diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2192781b..34550eaa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -106,16 +106,22 @@ message( STATUS "---- cmake_module_path: ${CMAKE_MODULE_PATH}" )
 
 include(CheckLanguage)
 
+include( SetupGit )
+include( SetupFeatures )
 include( SetupC99 )
 include( SetupCxx )
 include( SetupPython )
-include( SetupGit )
 
 # ------------------------------------------------------------------------------
 # Unit-testing:
 
 include( SetupUnitTesting )
 
+# ------------------------------------------------------------------------------
+# toml:
+
+include( SetupToml )
+
 # ------------------------------------------------------------------------------
 # MPFR4:
 
diff --git a/Settings.cmake.default b/Settings.cmake.default
index 2815d1c1..7d9d28c3 100644
--- a/Settings.cmake.default
+++ b/Settings.cmake.default
@@ -32,6 +32,20 @@ option( SIXTRACKL_BUILD_EXAMPLES         "Build sixtracklib examples"     OFF )
 option( SIXTRACKL_ENABLE_PROGRAMM_TESTS  "Enable programmatic unit-tests" OFF )
 option( SIXTRACKL_ENABLE_BENCHMARK_TESTS "Enable benchmark tests"         OFF )
 
+# ------------------------------------------------------------------------------
+# ---- SixTrackLib Features:
+
+# Track features: allowed values are enabled, disabled, or skip:
+
+set( SIXTRACKL_TRACK_BEAMBEAM4D             "enabled"  CACHE STRING "" )
+set( SIXTRACKL_TRACK_BEAMBEAM6D             "enabled"  CACHE STRING "" )
+set( SIXTRACKL_TRACK_SPACECHARGE            "enabled"  CACHE STRING "" )
+set( SIXTRACKL_TRACK_TRICUB                 "disabled" CACHE STRING "" )
+
+# Aperture check features: allowed values are always, never, conditional
+
+set( SIXTRACKL_APERTURE_CHECK_AT_DRIFT      "always"  CACHE STRING "" )
+
 # ------------------------------------------------------------------------------
 # CPU/System architecture settings:
 
@@ -47,24 +61,15 @@ set( SIXTRACKL_DEFAULT_C99_FLAGS
 set( SIXTRACKL_DEFAULT_CXX_FLAGS
      "-Wall -Werror -pedantic -ansi -fno-fast-math" )
 
-# ------------------------------------------------------------------------------
-# ---- SixTrackLib Features:
-
-option( SIXTRACKL_ENABLE_APERTURE_CHECK   "Enable xy - aperture check" ON )
-
-
 # ==============================================================================
 # ====  Detailed settings:
 
 # ------------------------------------------------------------------------------
 # ---- SixTrackLib detailed features settings:
 
-set( SIXTRACKL_APERTURE_X_LIMIT_VALUE "1.0"
-     CACHE STRING "Aperture check x limit" FORCE )
-
-set( SIXTRACKL_APERTURE_Y_LIMIT_VALUE "1.0"
-     CACHE STRING "Aperture check y limit" FORCE )
-
+set( SIXTRACKL_APERTURE_X_LIMIT_VALUE "1.0" CACHE STRING "" )
+set( SIXTRACKL_APERTURE_Y_LIMIT_VALUE "1.0" CACHE STRING "" )
+set( SIXTRACKL_APERTURE_CHECK_MIN_DRIFT_LENGTH "0.0" CACHE STRING "" )
 
 # ------------------------------------------------------------------------------
 # Installation detailed setings
@@ -117,6 +122,9 @@ endif()
 # OpenCL 1.x related detailed settings
 
 if( SIXTRACKL_ENABLE_OPENCL )
+    set( SIXTRACKL_OPENCL_DEFAULT_COMPILER_FLAGS "-w -Werror" CACHE STRING
+         "Default run-time compiler options for OpenCL" )
+
     set( SIXTRACKL_MIN_OPENCL_VERSION "110" CACHE STRING
         "Minimal expected OpenCL 1.x version" )
 
@@ -162,6 +170,5 @@ set( SIXTRACKL_CXX_NAMESPACE "sixtrack" CACHE STRING
 set( SIXTRACKL_C_NAMESPACE_PREFIX "st_" CACHE STRING
      "SixTrackLib C-Namespace prefix (default: st_)" )
 
-
 # ==============================================================================
 # end: Settings.cmake.default | Settings.cmake
diff --git a/cmake/SetupAutoVecSIMD.cmake b/cmake/SetupAutoVecSIMD.cmake
index 42b33a70..325de36c 100644
--- a/cmake/SetupAutoVecSIMD.cmake
+++ b/cmake/SetupAutoVecSIMD.cmake
@@ -8,13 +8,63 @@ if( NOT  SIXTRACKL_CMAKE_SETUP_AUTOVEC_SIMD_FINISHED )
     # and track its state:
 
     list( APPEND SIXTRACKLIB_SUPPORTED_MODULES "AUTOVECTORIZATION" )
+    set( SIXTRACKL_C_ENABLED_AUTOVEC_FLAGS )
+    set( SIXTRACKL_C_DISABLED_AUTOVEC_FLAGS )
+
+    if( CMAKE_C_COMPILER_ID STREQUAL "Clang" )
+        set( SIXTRACKL_C_DISABLED_AUTOVEC_FLAGS -fno-slp-vectorize )
+    elseif( CMAKE_C_COMPILER_ID STREQUAL "GNU" )
+        set( SIXTRACKL_C_ENABLED_AUTOVEC_FLAGS
+             -ftree-vectorize -ftree-vectorizer-verbose=6
+             -fopt-info-loop
+             -fno-fast-math
+             --param vect-max-version-for-alias-checks=150 )
+        set( SIXTRACKL_DEFAULT_C_NOAUTOVEC_FLAGS -fno-tree-vectorize )
+    endif()
+
+    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    set( SIXTRACKL_CXX_ENABLED_AUTOVEC_FLAGS )
+    set( SIXTRACKL_CXX_DISABLED_AUTOVEC_FLAGS )
+
+    if( SIXTRACKL_ENABLE_CXX )
+        if( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" )
+            set( SIXTRACKL_CXX_DISABLED_AUTOVEC_FLAGS -fno-slp-vectorize )
+        elseif( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" )
+            set( SIXTRACKL_CXX_ENABLED_AUTOVEC_FLAGS
+                 -ftree-vectorize -ftree-vectorizer-verbose=6
+                 -fopt-info-loop
+                 -fno-fast-math
+                 --param vect-max-version-for-alias-checks=150 )
+            set( SIXTRACKL_CXX_DISABLED_AUTOVEC_FLAGS -fno-tree-vectorize )
+        endif()
+    endif()
+
+    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    set( SIXTRACKL_C99_AUTOVEC_FLAGS )
+    set( SIXTRACKL_CXX_AUTOVEC_FLAGS )
 
     if( SIXTRACKL_ENABLE_AUTOVECTORIZATION )
         list( APPEND SIXTRACKLIB_SUPPORTED_MODULES_VALUES "1" )
+        set( SIXTRACKL_C99_AUTOVEC_FLAGS ${SIXTRACKL_C_ENABLED_AUTOVEC_FLAGS} )
+
+        if( SIXTRACKL_ENABLE_CXX )
+            set( SIXTRACKL_CXX_AUTOVEC_FLAGS
+               ${SIXTRACKL_CXX_ENABLED_AUTOVEC_FLAGS} )
+        endif()
     else()
         list( APPEND SIXTRACKLIB_SUPPORTED_MODULES_VALUES "0" )
+        set( SIXTRACKL_C99_AUTOVEC_FLAGS
+           ${SIXTRACKL_C_DISABLED_AUTOVEC_FLAGS} )
+
+        if( SIXTRACKL_ENABLE_C99 )
+            set( SIXTRACKL_C99_AUTOVEC_FLAGS
+               ${SIXTRACKL_C99_ENABLED_AUTOVEC_FLAGS} )
+        endif()
     endif()
 
+    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
     list( APPEND SIXTRACKLIB_SUPPORTED_MODULES "MANUAL_SIMD" )
 
diff --git a/cmake/SetupC99.cmake b/cmake/SetupC99.cmake
index f7201245..71da0e6c 100644
--- a/cmake/SetupC99.cmake
+++ b/cmake/SetupC99.cmake
@@ -6,15 +6,10 @@ if(  NOT SETUP_C99_FINISHED )
     # --------------------------------------------------------------------------
     # Prepare default c99 compiler flags
 
-    if( SIXTRACKL_DEFAULT_C99_FLAGS )
-        string( REPLACE " " ";" SIXTRL_C99_FLAGS
-                ${SIXTRACKL_DEFAULT_C99_FLAGS} )
-
-        if( SIXTRL_C99_FLAGS )
-            set( SIXTRACKLIB_C99_FLAGS
-               ${SIXTRACKLIB_C99_FLAGS} ${SIXTRL_C99_FLAGS} )
-        endif()
+    set( SIXTRACKLIB_C99_FLAGS )
 
+    if( SIXTRACKL_DEFAULT_C99_FLAGS )
+        string( REPLACE " " ";"
+                SIXTRACKLIB_C99_FLAGS ${SIXTRACKL_DEFAULT_C99_FLAGS} )
     endif()
-
 endif()
diff --git a/cmake/SetupCxx.cmake b/cmake/SetupCxx.cmake
index 1f226605..c22bf9de 100644
--- a/cmake/SetupCxx.cmake
+++ b/cmake/SetupCxx.cmake
@@ -13,19 +13,13 @@ if(  NOT SETUP_CXX_FINISHED )
     else()
         list( APPEND SIXTRACKLIB_SUPPORTED_BINDINGS_VALUES "0" )
     endif()
-    
+
     # --------------------------------------------------------------------------
     # Prepare default cxx compiler flags
-    
+
+    set( SIXTRACKLIB_CXX_FLAGS )
     if( SIXTRACKL_DEFAULT_CXX_FLAGS )
-        string( REPLACE " " ";" SIXTRL_CXX_FLAGS 
+        string( REPLACE " " ";" SIXTRACKLIB_CXX_FLAGS
                 ${SIXTRACKL_DEFAULT_CXX_FLAGS} )
-        
-        if( SIXTRL_CXX_FLAGS )
-            set( SIXTRACKLIB_CXX_FLAGS 
-               ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRL_CXX_FLAGS} )
-        endif()
-        
     endif()
-
 endif()
diff --git a/cmake/SetupFeatures.cmake b/cmake/SetupFeatures.cmake
new file mode 100644
index 00000000..c6fdc0bc
--- /dev/null
+++ b/cmake/SetupFeatures.cmake
@@ -0,0 +1,157 @@
+if(  NOT SETUP_SIXTRL_FEATURES_FINISHED )
+    set( SETUP_SIXTRL_FEATURES_FINISHED 1 )
+
+    # -------------------------------------------------------------------------
+    # Track features setup
+
+    set_property( CACHE SIXTRACKL_TRACK_BEAMBEAM4D
+                        SIXTRACKL_TRACK_BEAMBEAM6D
+                        SIXTRACKL_TRACK_SPACECHARGE
+                        SIXTRACKL_TRACK_TRICUB
+                  PROPERTY STRINGS enabled disabled skip )
+
+    set( SIXTRL_TRACK_MAP_ENABLED_VALUE  "2" )
+    set( SIXTRL_TRACK_MAP_SKIP_VALUE     "1" )
+    set( SIXTRL_TRACK_MAP_DISABLED_VALUE "0" )
+
+    set_property( CACHE SIXTRACKL_TRACK_BEAMBEAM4D PROPERTY HELPSTRING
+                  "Track over beam-beam 4D beam element" )
+
+    if( SIXTRACKL_TRACK_BEAMBEAM4D )
+        if( "${SIXTRACKL_TRACK_BEAMBEAM4D}" STREQUAL "skip" )
+            set( SIXTRL_TRACK_BEAMBEAM4D_FLAG "${SIXTRL_TRACK_MAP_SKIP_VALUE}" )
+            set( SIXTRL_TRACK_BEAMBEAM4D_FLAG_STR "skip" )
+        elseif( "${SIXTRACKL_TRACK_BEAMBEAM4D}" STREQUAL "disabled" )
+            set( SIXTRL_TRACK_BEAMBEAM4D_FLAG "${SIXTRL_TRACK_MAP_DISABLED_VALUE}" )
+            set( SIXTRL_TRACK_BEAMBEAM4D_FLAG_STR "disabled" )
+        else()
+            set( SIXTRL_TRACK_BEAMBEAM4D_FLAG "${SIXTRL_TRACK_MAP_ENABLED_VALUE}" )
+            set( SIXTRL_TRACK_BEAMBEAM4D_FLAG_STR "enabled" )
+        endif()
+    endif()
+
+    set_property( CACHE SIXTRACKL_TRACK_BEAMBEAM6D PROPERTY HELPSTRING
+                  "Track over beam-beam 6D beam element" )
+
+    if( SIXTRACKL_TRACK_BEAMBEAM6D )
+        if( "${SIXTRACKL_TRACK_BEAMBEAM6D}" STREQUAL "skip" )
+            set( SIXTRL_TRACK_BEAMBEAM6D_FLAG "${SIXTRL_TRACK_MAP_SKIP_VALUE}" )
+            set( SIXTRL_TRACK_BEAMBEAM6D_FLAG_STR "skip" )
+        elseif( "${SIXTRACKL_TRACK_BEAMBEAM6D}" STREQUAL "disabled" )
+            set( SIXTRL_TRACK_BEAMBEAM6D_FLAG "${SIXTRL_TRACK_MAP_DISABLED_VALUE}" )
+            set( SIXTRL_TRACK_BEAMBEAM6D_FLAG_STR "disabled" )
+        else()
+            set( SIXTRL_TRACK_BEAMBEAM6D_FLAG "${SIXTRL_TRACK_MAP_ENABLED_VALUE}" )
+            set( SIXTRL_TRACK_BEAMBEAM6D_FLAG_STR "enabled" )
+        endif()
+    endif()
+
+    set_property( CACHE SIXTRACKL_TRACK_SPACECHARGE PROPERTY HELPSTRING
+                  "Track over frozen space-charge beam element" )
+
+    if( SIXTRACKL_TRACK_SPACECHARGE )
+        if( "${SIXTRACKL_TRACK_SPACECHARGE}" STREQUAL "skip" )
+            set( SIXTRL_TRACK_SC_FLAG "${SIXTRL_TRACK_MAP_SKIP_VALUE}" )
+            set( SIXTRL_TRACK_SC_FLAG_STR "skip" )
+        elseif( "${SIXTRACKL_TRACK_SPACECHARGE}" STREQUAL "disabled" )
+            set( SIXTRL_TRACK_SC_FLAG "${SIXTRL_TRACK_MAP_DISABLED_VALUE}" )
+            set( SIXTRL_TRACK_SC_FLAG_STR "disabled" )
+        else()
+            set( SIXTRL_TRACK_SC_FLAG "${SIXTRL_TRACK_MAP_ENABLED_VALUE}" )
+            set( SIXTRL_TRACK_SC_FLAG_STR "enabled" )
+        endif()
+    endif()
+
+    set_property( CACHE SIXTRACKL_TRACK_TRICUB PROPERTY HELPSTRING
+                  "Track over tri-cub interpolation beam elements" )
+
+    if( SIXTRACKL_TRACK_TRICUB )
+        if( "${SIXTRACKL_TRACK_TRICUB}" STREQUAL "skip" )
+            set( SIXTRL_TRACK_TRICUB_FLAG "${SIXTRL_TRACK_MAP_SKIP_VALUE}" )
+            set( SIXTRL_TRACK_TRICUB_FLAG_STR "skip" )
+        elseif( "${SIXTRACKL_TRACK_TRICUB}" STREQUAL "disabled" )
+            set( SIXTRL_TRACK_TRICUB_FLAG "${SIXTRL_TRACK_MAP_DISABLED_VALUE}" )
+            set( SIXTRL_TRACK_TRICUB_FLAG_STR "disabled" )
+        else()
+            set( SIXTRL_TRACK_TRICUB_FLAG "${SIXTRL_TRACK_MAP_ENABLED_VALUE}" )
+            set( SIXTRL_TRACK_TRICUB_FLAG_STR "enabled" )
+        endif()
+    endif()
+
+    set( SIXTRL_TRACK_FEATURES_INSTALL_STR
+         "set( SIXTRL_TRACK_MAP_ENABLED_VALUE    \"${SIXTRL_TRACK_MAP_ENABLED_VALUE}\" )
+          set( SIXTRL_TRACK_MAP_SKIP_VALUE       \"${SIXTRL_TRACK_MAP_SKIP_VALUE}\" )
+          set( SIXTRL_TRACK_MAP_DISABLED_VALUE   \"${SIXTRL_TRACK_MAP_DISABLED_VALUE}\" )
+          set( SIXTRL_TRACK_BEAMBEAM4D_FLAG      \"${SIXTRL_TRACK_BEAMBEAM4D_FLAG}\" )
+          set( SIXTRL_TRACK_BEAMBEAM4D_FLAG_STR  \"${SIXTRL_TRACK_BEAMBEAM4D_FLAG_STR}\" )
+          set( SIXTRL_TRACK_BEAMBEAM6D_FLAG      \"${SIXTRL_TRACK_BEAMBEAM4D_FLAG}\" )
+          set( SIXTRL_TRACK_BEAMBEAM6D_FLAG_STR  \"${SIXTRL_TRACK_BEAMBEAM4D_FLAG_STR}\" )
+          set( SIXTRL_TRACK_SPACECHARGE_FLAG     \"${SIXTRL_TRACK_SPACECHARGE_FLAG}\" )
+          set( SIXTRL_TRACK_SPACECHARGE_FLAG_STR \"${SIXTRL_TRACK_SPACECHARGE_FLAG_STR}\" )
+          set( SIXTRL_TRACK_TRICUB_FLAG          \"${SIXTRL_TRACK_TRICUB_FLAG}\"
+          set( SIXTRL_TRACK_TRICUB_FLAG_STR      \"${SIXTRL_TRACK_TRICUB_FLAG_STR}\" )" )
+
+
+    # -------------------------------------------------------------------------
+    # Aperture check features:
+
+    set_property( CACHE SIXTRACKL_APERTURE_CHECK_AT_DRIFT PROPERTY HELPSTRING
+                  "Perform an x-y aperture check at Drift and DriftExact beam elements" )
+
+    set_property( CACHE SIXTRACKL_APERTURE_CHECK_AT_DRIFT
+                  PROPERTY STRINGS always conditional never )
+
+    set( SIXTRL_GLOBAL_APERATURE_CHECK_ALWAYS_VALUE        "2" )
+    set( SIXTRL_GLOBAL_APERATURE_CHECK_CONDITIONAL_VALUE   "1" )
+    set( SIXTRL_GLOBAL_APERATURE_CHECK_NEVER_VALUE         "0" )
+
+    if( SIXTRACKL_APERTURE_CHECK_AT_DRIFT )
+        if( "${SIXTRACKL_APERTURE_CHECK_AT_DRIFT}" STREQUAL "never" )
+            set( SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG
+                "${SIXTRL_GLOBAL_APERATURE_CHECK_NEVER_VALUE}" )
+            set( SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG_STR "never" )
+        elseif( "${SIXTRACKL_APERTURE_CHECK_AT_DRIFT}" STREQUAL "conditional" )
+            set( SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG
+                "${SIXTRL_GLOBAL_APERATURE_CHECK_CONDITIONAL_VALUE}" )
+            set( SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG_STR "conditional" )
+        else()
+            set( SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG
+                "${SIXTRL_GLOBAL_APERATURE_CHECK_ALWAYS_VALUE}" )
+            set( SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG_STR "always" )
+        endif()
+    endif()
+
+    set_property( CACHE SIXTRACKL_APERTURE_X_LIMIT_VALUE PROPERTY ADVANCED )
+    set_property( CACHE SIXTRACKL_APERTURE_X_LIMIT_VALUE PROPERTY HELPSTRING
+                  "Global aperture check limit for x [m]" )
+
+    set_property( CACHE SIXTRACKL_APERTURE_Y_LIMIT_VALUE PROPERTY ADVANCED )
+    set_property( CACHE SIXTRACKL_APERTURE_Y_LIMIT_VALUE PROPERTY HELPSTRING
+                  "Global aperture check limit for y [m]" )
+
+    set_property( CACHE SIXTRACKL_APERTURE_CHECK_MIN_DRIFT_LENGTH
+                  PROPERTY HELPSTRING
+                  "Perform conditional aperture checks for Drift and DriftExact elements with lengths larger than this [m]" )
+
+    set_property( CACHE SIXTRACKL_APERTURE_CHECK_MIN_DRIFT_LENGTH
+                  PROPERTY ADVANCED )
+
+    set( SIXTRL_APERTURE_CHECK_FEATURES_INSTALL_STR
+         "set( SIXTRL_GLOBAL_APERATURE_CHECK_ALWAYS_VALUE
+           \"${SIXTRL_GLOBAL_APERATURE_CHECK_ALWAYS_VALUE}\" )
+          set( SIXTRL_GLOBAL_APERATURE_CHECK_ALWAYS_VALUE_STR
+           \"${SIXTRL_GLOBAL_APERATURE_CHECK_ALWAYS_VALUE_STR}\" )
+          set( SIXTRL_GLOBAL_APERATURE_CHECK_CONDITIONAL_VALUE
+           \"${SIXTRL_GLOBAL_APERATURE_CHECK_CONDITIONAL_VALUE}\" )
+          set( SIXTRL_GLOBAL_APERATURE_CHECK_NEVER_VALUE
+           \"${SIXTRL_GLOBAL_APERATURE_CHECK_NEVER_VALUE}\" )
+          set( SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG
+           \"${SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG}\" )
+          set( SIXTRACKL_APERTURE_X_LIMIT_VALUE
+           \"${SIXTRACKL_APERTURE_X_LIMIT_VALUE}\" )
+          set( SIXTRACKL_APERTURE_Y_LIMIT_VALUE
+           \"${SIXTRACKL_APERTURE_Y_LIMIT_VALUE}\" )
+          set( SIXTRACKL_APERTURE_CHECK_MIN_DRIFT_LENGTH
+           \"${SIXTRACKL_APERTURE_CHECK_MIN_DRIFT_LENGTH}\" )" )
+
+endif()
diff --git a/cmake/SetupToml.cmake b/cmake/SetupToml.cmake
new file mode 100644
index 00000000..3eed0689
--- /dev/null
+++ b/cmake/SetupToml.cmake
@@ -0,0 +1,72 @@
+if(  NOT SETUP_TOML_FINISHED )
+    set( SETUP_TOML_FINISHED 1 )
+
+    message( STATUS "---- Processing cmake/SetupToml.cmake" )
+
+    if( NOT  SIXTRACKL_TOML_INCLUDE_DIRS )
+        set( SIXTRACKL_TOML_INCLUDE_DIRS )
+    endif()
+
+    include( SetupGit )
+
+    set( toml11_GIT_REPOSITORY https://github.com/ToruNiina/toml11.git )
+    set( toml11_GIT_BRANCH master )
+    set( toml11_EXT_DIR "${CMAKE_SOURCE_DIR}/external/toml11" )
+
+    Git_sync_with_repo( TARGET toml11
+        GIT_REPOSITORY ${toml11_GIT_REPOSITORY}
+        GIT_BRANCH ${toml11_GIT_BRANCH} )
+
+    if( NOT toml11_DIR  )
+        message( FATAL_ERROR "------ unable to fetch toml11 from git repository" )
+    endif()
+
+    if( ${toml11_SYNC} EQUAL 1 )
+        if( ${toml11_UPDATED} EQUAL 0 )
+            message( STATUS "------ toml11 already sync, no update for embedded library" )
+        elseif( ${toml11_UPDATED} EQUAL 1 )
+            message( STATUS "------ toml11 successfully cloned/pulled from ${toml11_GIT_REPOSITORY}/${toml11_GIT_BRANCH}" )
+            message( STATUS "------ attempting to update the embedded library at ${toml11_EXT_DIR} ..." )
+
+            set( toml11_TRANSFERED_ANY_FILES 0 )
+            if( EXISTS "${toml11_DIR}/LICENSE" )
+                configure_file( "${toml11_DIR}/LICENSE" "${toml11_EXT_DIR}/LICENSE" COPYONLY )
+                set( toml11_TRANSFERED_ANY_FILES 1 )
+            endif()
+
+            if( EXISTS "${toml11_DIR}/README.md" )
+                configure_file( "${toml11_DIR}/README.md"
+                                "${toml11_EXT_DIR}/toml11_README.md" COPYONLY )
+                set( toml11_TRANSFERED_ANY_FILES 1 )
+            endif()
+
+            if( EXISTS "${toml11_DIR}/toml.hpp" )
+                configure_file( "${toml11_DIR}/toml.hpp" "${toml11_EXT_DIR}/toml.hpp" COPYONLY )
+                set( toml11_TRANSFERED_ANY_FILES 1 )
+            endif()
+
+            file( GLOB toml11_IMPL_FILES "${toml11_DIR}/toml/*" )
+
+            if( toml11_IMPL_FILES )
+                foreach( PATH_TO_FILE IN LISTS toml11_IMPL_FILES )
+                    get_filename_component( FILE_NAME ${PATH_TO_FILE} NAME )
+                    configure_file( ${PATH_TO_FILE}
+                                    "${toml11_EXT_DIR}/toml/${FILE_NAME}" COPYONLY )
+                    set( toml11_TRANSFERED_ANY_FILES 1 )
+                endforeach()
+            endif()
+
+            if( ${toml11_TRANSFERED_ANY_FILES} EQUAL 1 )
+                message( STATUS "------ transfered updated files to ${toml11_EXT_DIR}" )
+            endif()
+        else()
+            message( FATAL_ERROR "------ internal error Git_sync_with_repo" )
+        endif()
+
+        set(  SIXTRACKL_TOML_INCLUDE_DIRS
+            ${SIXTRACKL_TOML_INCLUDE_DIRS} ${toml11_DIR} )
+    else()
+        message( WARNING "------ unable to sync toml11 with external repository ${toml11_GIT_REPOSITORY}/${toml11_GIT_BRANCH}" )
+        message( WARNING "------ rely on the contents of ${toml11_EXT_DIR}" )
+    endif()
+endif()
diff --git a/examples/c99/simple_drift_buffer.c b/examples/c99/simple_drift_buffer.c
index c1dec011..7c7f55d1 100644
--- a/examples/c99/simple_drift_buffer.c
+++ b/examples/c99/simple_drift_buffer.c
@@ -7,46 +7,46 @@
 
 int main( int argc, char* argv[] )
 {
-    typedef st_buffer_size_t  buf_size_t;
+    typedef NS(buffer_size_t)  buf_size_t;
 
     buf_size_t const NUM_BEAM_ELEMENTS = ( buf_size_t)25u;
     buf_size_t const DATA_CAPACITY     = ( buf_size_t )( 1u << 20u );
 
-    st_Buffer* eb = st_Buffer_new( DATA_CAPACITY );
+    NS(Buffer)* eb = NS(Buffer_new)( DATA_CAPACITY );
 
     buf_size_t ii = ( buf_size_t )0u;
     double length = ( double )10.0L;
 
-    st_Drift* copy_of_drift = 0; /* see below */
+    NS(Drift)* copy_of_drift = 0; /* see below */
 
-    /* add a new drift to the eb buffer using st_Drift_new function ->
+    /* add a new drift to the eb buffer using NS(Drift_new) function ->
      * the resulting drift will have default values, i.e. length == 0 */
 
-    st_Drift* drift = st_Drift_new( eb );
+    NS(Drift)* drift = NS(Drift_new)( eb );
     assert( drift != SIXTRL_NULLPTR );
 
-    st_Drift_set_length( drift, length );
+    NS(Drift_set_length)( drift, length );
 
     length += ( double )1.0L;
     ++ii;
 
-    /* add a new drift to the eb buffer using the st_Drift_add function ->
+    /* add a new drift to the eb buffer using the NS(Drift_add) function ->
      * the resulting drift will already have the provided length */
 
-    drift = st_Drift_add( eb, length );
+    drift = NS(Drift_add)( eb, length );
     assert( drift != SIXTRL_NULLPTR );
 
     length += ( double )1.0L;
     ++ii;
 
     /* add a new drift to the eb buffer which is an exact copy of an already
-     * existing st_Drift -> the two instances will have the exact same length */
+     * existing NS(Drift) -> the two instances will have the exact same length */
 
-    copy_of_drift = st_Drift_add_copy( eb, drift );
+    copy_of_drift = NS(Drift_add_copy)( eb, drift );
 
     assert( copy_of_drift != SIXTRL_NULLPTR );
     assert( copy_of_drift != drift  );
-    assert( memcmp( copy_of_drift, drift, sizeof( st_Drift ) ) == 0 );
+    assert( memcmp( copy_of_drift, drift, sizeof( NS(Drift) ) ) == 0 );
 
     #if defined( NDEBUG )
     ( void )copy_of_drift;
@@ -57,17 +57,17 @@ int main( int argc, char* argv[] )
 
     for( ; ii < NUM_BEAM_ELEMENTS ; ++ii, length += ( double )1.0L )
     {
-        drift = st_Drift_add( eb, length );
+        drift = NS(Drift_add)( eb, length );
         assert( drift != SIXTRL_NULLPTR );
     }
 
     /* print out all existing beam elements using the convenience
-     * st_BeamElement_print() function from testlib */
+     * NS(BeamElement_print)() function from testlib */
 
     for( ii = 0u ; ii < NUM_BEAM_ELEMENTS ; ++ii )
     {
         /* get the ii-th beam element object from the eb buffer */
-        st_Object* be_object = st_Buffer_get_object( eb, ii );
+        NS(Object)* be_object = NS(Buffer_get_object)( eb, ii );
         assert( be_object != SIXTRL_NULLPTR );
 
         /* We are about to modify the length of each drift ->
@@ -78,34 +78,33 @@ int main( int argc, char* argv[] )
                 ( int )ii );
 
         /* Print the be with the generic print helper function */
-        st_BeamElement_print_out( be_object );
+        NS(BeamElement_print_out)( be_object );
 
         /* We can get access to actual stored object if we know which type
          * it represents. In our case, that's easy - all stored objects are
          * drifts. But let's check that: */
 
-        if( st_Object_get_type_id( be_object ) == st_OBJECT_TYPE_DRIFT )
+        if( NS(Object_get_type_id)( be_object ) == NS(OBJECT_TYPE_DRIFT) )
         {
-            st_Drift* stored_drift =
-                ( st_Drift* )st_Object_get_begin_ptr( be_object );
+            NS(Drift)* stored_drift =
+                ( NS(Drift)* )NS(Object_get_begin_ptr)( be_object );
 
             /* We could now modify the length of the already stored Drift.
              * If you want to prevent accidentially doing that, use the
              * const interface */
 
-            st_Drift const* read_only_drift =
-                ( st_Drift const* )st_Object_get_const_begin_ptr( be_object );
+            NS(Drift) const* read_only_drift =
+                ( NS(Drift) const* )NS(Object_get_const_begin_ptr)( be_object );
 
             /* Modify the length via the rw pointer: */
-            double const new_length =
-                st_Drift_get_length( stored_drift ) + ( double )1.0L;
+            double const new_length = NS(Drift_length)( stored_drift ) + ( double )1;
 
-            st_Drift_set_length( stored_drift, new_length );
+            NS(Drift_set_length)( stored_drift, new_length );
 
             /* Since stored_drift and read_only_drift point to the same
              * location, read_only_drift yields the new length: */
 
-            if( fabs( st_Drift_get_length( read_only_drift ) - new_length ) >= 1e-12 )
+            if( fabs( NS(Drift_length)( read_only_drift ) - new_length ) >= 1e-12 )
             {
                 printf( "Error!" );
                 break;
@@ -116,14 +115,14 @@ int main( int argc, char* argv[] )
         printf( "after  changing the length of beam belement %d\r\n",
                 ( int )ii );
 
-        st_BeamElement_print_out( be_object );
+        NS(BeamElement_print_out)( be_object );
 
         printf( "\r\n" );
     }
 
     /* Cleaning up */
 
-    st_Buffer_delete( eb );
+    NS(Buffer_delete)( eb );
 
     return 0;
 }
diff --git a/examples/c99/track_io.c b/examples/c99/track_io.c
index cb15cb8e..2cdaaf1f 100644
--- a/examples/c99/track_io.c
+++ b/examples/c99/track_io.c
@@ -120,20 +120,13 @@ int main( int argc, char* argv[] )
 
     if( ( argc >= 8 ) && ( argv[ 7 ] != SIXTRL_NULLPTR ) )
     {
-        size_t const output_path_len = strlen( argv[ 7 ] );
+        size_t const output_path_len = strlen( argv[ 7 ] ) + ( size_t )2u;
+        path_output_particles = ( char* )calloc(
+            output_path_len, sizeof( char ) );
 
-        if( output_path_len > 0u )
+        if( path_output_particles != SIXTRL_NULLPTR )
         {
-            path_output_particles = ( char* )malloc(
-                sizeof( char ) * ( output_path_len + 1u ) );
-
-            if( path_output_particles != SIXTRL_NULLPTR )
-            {
-                memset(  path_output_particles, ( int )'\0',
-                         output_path_len );
-
-                strcpy( path_output_particles, argv[ 7 ] );
-            }
+            strcpy( path_output_particles, argv[ 7 ] );
         }
     }
 
diff --git a/examples/c99/track_io_opencl.c b/examples/c99/track_io_opencl.c
index 50f763d9..ce79cdb2 100644
--- a/examples/c99/track_io_opencl.c
+++ b/examples/c99/track_io_opencl.c
@@ -208,20 +208,13 @@ int main( int argc, char* argv[] )
 
     if( ( argc >= 9 ) && ( argv[ 8 ] != SIXTRL_NULLPTR ) )
     {
-        size_t const output_path_len = strlen( argv[ 8 ] );
+        size_t const output_path_len = strlen( argv[ 8 ] ) + ( size_t )2u;
+        path_output_particles = ( char* )calloc(
+            output_path_len, sizeof( char ) );
 
-        if( output_path_len > 0u )
+        if( path_output_particles != SIXTRL_NULLPTR )
         {
-            path_output_particles = ( char* )malloc(
-                sizeof( char ) * ( output_path_len + 1u ) );
-
-            if( path_output_particles != SIXTRL_NULLPTR )
-            {
-                memset(  path_output_particles, ( int )'\0',
-                         output_path_len );
-
-                strcpy( path_output_particles, argv[ 8 ] );
-            }
+            strcpy( path_output_particles, argv[ 8 ] );
         }
     }
 
diff --git a/examples/c99/track_lhc_no_bb_opencl.c b/examples/c99/track_lhc_no_bb_opencl.c
index 248f0bdc..b716e964 100644
--- a/examples/c99/track_lhc_no_bb_opencl.c
+++ b/examples/c99/track_lhc_no_bb_opencl.c
@@ -176,6 +176,7 @@ int main( int argc, char* argv[] )
     NS(ClContext_assign_particles_arg)( ctx, particles_arg );
     NS(ClContext_assign_particle_set_arg)( ctx, 0u, NUM_PARTICLES );
     NS(ClContext_assign_beam_elements_arg)( ctx, beam_elements_arg );
+    NS(ClContext_assign_slot_size_arg)( ctx, NS(Buffer_get_slot_size)( pb ) );
 
     NS(ClContext_track_until)( ctx, NUM_TURNS );
 
diff --git a/examples/cxx/track_lhc_no_bb_opencl.cpp b/examples/cxx/track_lhc_no_bb_opencl.cpp
index 02db3c91..f7ffcaae 100644
--- a/examples/cxx/track_lhc_no_bb_opencl.cpp
+++ b/examples/cxx/track_lhc_no_bb_opencl.cpp
@@ -142,6 +142,7 @@ int main( int argc, char* argv[] )
     ctx.assign_particles_arg( particles_arg );
     ctx.assign_particle_set_arg( 0u, NUM_PARTICLES );
     ctx.assign_beam_elements_arg( beam_elements_arg );
+    ctx.assign_slot_size_arg( pb.getSlotSize() );
 
     ctx.track_until( NUM_TURNS );
 
diff --git a/examples/python/opencl_cpu_particle_addr.py b/examples/python/opencl_cpu_particle_addr.py
new file mode 100644
index 00000000..945a1964
--- /dev/null
+++ b/examples/python/opencl_cpu_particle_addr.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import importlib
+from importlib import util
+import ctypes as ct
+import sixtracklib as st
+
+numpy_spec = util.find_spec('numpy')
+
+if numpy_spec is not None:
+    import numpy as np
+
+
+def np_array_from_st_addr(base_addr, count, dtype=np.dtype('<f8')):
+    typestr = dtype.str
+    assert typestr == '<f8' or typestr == '<i8'
+    if typestr == '<f8':
+        array_t = ct.c_double * count
+    elif typestr == '<i8':
+        array_t = ct.c_int64 * count
+    return np.frombuffer(array_t.from_address(base_addr), dtype=dtype)
+
+
+if __name__ == '__main__':
+    if not st.supports('opencl'):
+        raise SystemExit('Example requires opencl support in SixTrackLib')
+
+    if numpy_spec is None:
+        raise SystemExit('Example requires numpy installation')
+
+    beam = st.ParticlesSet()
+    p1_orig = beam.Particles(num_particles=16, p0c=6.5e12, q0=1.0)
+    p2_orig = beam.Particles(num_particles=256, p0c=1e9, q0=1.0)
+
+    lattice = st.Elements()
+    dr1 = lattice.Drift(length=0.5)
+    qp1 = lattice.Multipole(knl=[0.0, 0.01])
+    dr2 = lattice.Drift(length=1.0)
+    qp2 = lattice.Multipole(knl=[0.0, -0.01])
+    dr3 = lattice.Drift(length=0.5)
+
+    device_str = "opencl:1.0"
+    job = st.TrackJob(lattice, beam, device=device_str)
+
+    if not job.can_fetch_particle_addresses:
+        raise SystemExit(f'''
+            Example requires job for {device_str} to allow
+            fetching particle addresses''')
+
+    if not job.has_particle_addresses and job.can_fetch_particle_addresses:
+        job.fetch_particle_addresses()
+
+    ptr_p1_addr = job.get_particle_addresses(0)
+    ptr_p2_addr = job.get_particle_addresses(1)
+
+    # Printing the particle addresses
+    for label, ptr_p_addr in {'p1': ptr_p1_addr, 'p2': ptr_p2_addr}.items():
+        p_addr = ptr_p_addr.contents
+        print(f"""particle addresses for particle set {label}:\r\n
+          num_particles   = {p_addr.num_particles:8d}\r\n
+          x      begin at = {p_addr.x:16x} (alignment {p_addr.x%128 == 0})\r\n
+          y      begin at = {p_addr.y:16x} (alignment {p_addr.x%128 == 0})\r\n
+          px     begin at = {p_addr.px:16x} (alignment {p_addr.x%128 == 0})\r\n
+          py     begin at = {p_addr.py:16x} (alignment {p_addr.x%128 == 0})\r\n
+          zeta   begin at = {p_addr.zeta:16x} (alignment {p_addr.x%128 == 0})\r\n
+          delta  begin at = {p_addr.delta:16x} (alignment {p_addr.x%128 == 0})\r\n\r\n""")
+
+    # Creating np arrays from the addresses
+    p1_addr = ptr_p1_addr.contents
+    p1_npart = p1_addr.num_particles
+    p1_x = np_array_from_st_addr(p1_addr.x, count=p1_npart)
+    p1_px = np_array_from_st_addr(p1_addr.px, count=p1_npart)
+    p1_p0c = np_array_from_st_addr(p1_addr.p0c, count=p1_npart)
+    p1_state = np_array_from_st_addr(
+        p1_addr.state,
+        count=p1_npart,
+        dtype=np.dtype('<i8'))
+
+    # getting the p1 particle set from the job:
+    p1 = job.particles_buffer.get_object(0, cls=st.Particles)
+
+    # compare p1 on the host with the mapped arrays on the device side ->
+    # should be equal
+    assert np.array_equal(p1.x, p1_x)
+    assert np.array_equal(p1.px, p1_px)
+    assert np.array_equal(p1.p0c, p1_p0c)
+    assert np.array_equal(p1.state, p1_state)
+
+    # Update the content of the device side buffers:
+    p1_x[:] = np.random.uniform(-1e-5, +1e-5, p1_npart)
+    p1_px[:] = np.random.uniform(-1e-5, +1e-5, p1_npart)
+    p1_p0c[:] = np.ones(p1_npart) * 1e9
+    p1_state[:] = np.random.randint(0, 2, p1_npart)
+
+    # Verify that the host side p1 and the device side mapped arrays are
+    # no longer equal
+    assert not np.array_equal(p1.x, p1_x)
+    assert not np.array_equal(p1.px, p1_px)
+    assert not np.array_equal(p1.p0c, p1_p0c)
+    assert not np.array_equal(p1.state, p1_state)
+
+    # collect the particles -> this should update the host-side p1 with the
+    # data from the device
+    job.collect_particles()
+
+    # Print output:
+    print(f"""p1 after the update + collect_particles():\r\n
+        p1.x     : {p1.x} (from SixTrackLib) == \r\n
+        p1_x     : {p1_x} (mapped address) \r\n
+        p1.px    : {p1.px} (from SixTrackLib) \r\n
+        p1_px    : {p1_px} (mapped address) \r\n
+        p1.p0c   : {p1.p0c} (from SixTrackLib) \r\n
+        p1_p0c   : {p1_p0c} (mapped address) \r\n
+        p1.state : {p1.state} (from SixTrackLib) \r\n
+        p1_state : {p1_state} (mapped address) \r\n""")
+
+    # We expect, that the host side and the mapped device side arrays agree
+    # again:
+    assert np.array_equal(p1.x, p1_x)
+    assert np.array_equal(p1.px, p1_px)
+    assert np.array_equal(p1.p0c, p1_p0c)
+    assert np.array_equal(p1.state, p1_state)
diff --git a/examples/python/opencl_kernel_info.py b/examples/python/opencl_kernel_info.py
new file mode 100644
index 00000000..bd67b9fc
--- /dev/null
+++ b/examples/python/opencl_kernel_info.py
@@ -0,0 +1,36 @@
+import sixtracklib as st
+from sixtracklib.stcommon import st_ClContext_uses_optimized_tracking
+from sixtracklib.stcommon import st_ClContextBase_is_debug_mode_enabled
+from sixtracklib.stcommon import st_ARCH_ILLEGAL_KERNEL_ID
+
+if __name__ == '__main__':
+    lattice = st.Elements()
+    drift = lattice.Drift(length=1.0)
+
+    pset = st.Particles(num_particles=1000)
+
+    job = st.TrackJob(lattice, pset, device="opencl:0.0")
+    ctrl = job.controller
+
+    assert not st_ClContextBase_is_debug_mode_enabled( ctrl.pointer )
+    assert st_ClContext_uses_optimized_tracking( ctrl.pointer )
+
+    k_id = ctrl.find_kernel_by_name(
+        "st_Track_particles_until_turn_opt_pp_opencl" )
+
+    assert k_id != st_ARCH_ILLEGAL_KERNEL_ID.value
+    print( f""""
+          current workgroup size (0 == max) : {ctrl.kernel_workgroup_size( k_id )}
+          max workgroup size                : {ctrl.kernel_max_workgroup_size(k_id )}
+          preferred workgroup size multiple : {ctrl.kernel_preferred_workgroup_size_multiple(k_id)}
+          """ )
+
+    prog_id = ctrl.program_id_by_kernel_id( k_id )
+    used_compile_options = ctrl.program_compile_options( prog_id )
+    prog_compile_report  = ctrl.program_compile_report( prog_id )
+
+    print( f"""
+          used compile options               : {used_compile_options}
+          compile report / output            : {prog_compile_report}
+          """ )
+
diff --git a/examples/python/pycuda_particle_addr.py b/examples/python/pycuda_particle_addr.py
index 84a7d596..44dd9f53 100644
--- a/examples/python/pycuda_particle_addr.py
+++ b/examples/python/pycuda_particle_addr.py
@@ -6,7 +6,6 @@
 import ctypes as ct
 import sixtracklib as pyst
 from sixtracklib import stcommon as st
-import pdb
 
 pycuda_spec = util.find_spec('pycuda')
 numpy_spec = util.find_spec('numpy')
diff --git a/examples/python/spacecharge/line_density_profile.py b/examples/python/spacecharge/line_density_profile.py
new file mode 100644
index 00000000..df51151f
--- /dev/null
+++ b/examples/python/spacecharge/line_density_profile.py
@@ -0,0 +1,194 @@
+import sixtracklib as st
+import cobjects
+import numpy as np
+from cobjects import CBuffer
+
+
+def gaussian_dist(z, mu=0.0, sigma=1.0):
+    assert np.all(np.abs(sigma) > 0.0)
+    norm_z = (z - mu) / (np.sqrt(2.0) * sigma)
+    return 1.0 / np.sqrt(2 * np.pi * sigma) * np.exp(-norm_z * norm_z)
+
+
+if __name__ == "__main__":
+    # -------------------------------------------------------------------------
+    # A) Create buffer for storing the line density datasets:
+    interpol_buffer = CBuffer()
+
+    # Prepare two line density datasets from gaussian distributions:
+    # NOTE: We keep track on the indices of the datasets -> this will be used
+    #       later during assignment
+
+    # A.1) gaussian, sigma=1.0, 24 points, linear interpolation
+    lin_absc = np.linspace(-8.0, 8.0, num=24, dtype="float64")
+    sc_data0_idx = interpol_buffer.n_objects
+    sc_data0 = st.LineDensityProfileData(
+        cbuffer=interpol_buffer,
+        capacity=len(lin_absc),
+        z0=lin_absc[0],
+        dz=lin_absc[1] - lin_absc[0],
+        method="linear",
+    )
+
+    lin_values = gaussian_dist(lin_absc, mu=0.0, sigma=1.0)
+    sc_data0.values[:] = lin_values
+    sc_data0.prepare_interpolation()
+
+    # A.2) gaussian, sigma=2.0, 12 points, cubic spline interpolation
+    cub_absc = np.linspace(-8.0, 8.0, num=12, dtype="float64")
+    sc_data1_idx = interpol_buffer.n_objects
+    sc_data1 = st.LineDensityProfileData(
+        cbuffer=interpol_buffer,
+        capacity=len(cub_absc),
+        z0=cub_absc[0],
+        dz=cub_absc[1] - cub_absc[0],
+        method="cubic",
+    )
+
+    sc_data1.values[:] = gaussian_dist(cub_absc, mu=0.0, sigma=2.0)
+    sc_data1.prepare_interpolation()
+
+    # A.3) optional: demonstrate that interpolation works ->
+    # set plot_data = True!
+    plot_data = False
+
+    if plot_data:
+        from matplotlib import pyplot as plt
+
+        z_absc = np.linspace(-8.0, +8.0, num=512, dtype="float64")
+        y_exact1 = gaussian_dist(z_absc, mu=0.0, sigma=1.0)
+        sc_data0 = interpol_buffer.get_object(sc_data0_idx)
+        y_interp_lin = np.array([sc_data0.interpol(zz) for zz in z_absc])
+
+        y_exact2 = gaussian_dist(z_absc, mu=0.0, sigma=2.0)
+        sc_data1 = interpol_buffer.get_object(sc_data1_idx)
+        y_interp_cub = np.array([sc_data1.interpol(zz) for zz in z_absc])
+
+        plt.figure()
+        plt.subplot(211)
+        plt.plot(
+            lin_absc,
+            sc_data0.values,
+            "bo",
+            z_absc,
+            y_exact1,
+            "k",
+            z_absc,
+            y_interp_lin,
+            "b-",
+        )
+
+        plt.subplot(212)
+        plt.plot(
+            cub_absc,
+            sc_data0.values,
+            "ro",
+            z_absc,
+            y_exact2,
+            "k",
+            z_absc,
+            y_interp_cub,
+            "r-",
+        )
+        plt.show()
+
+    # -------------------------------------------------------------------------
+    # B) Init the particle set
+    beam = st.ParticlesSet()
+    particles = beam.Particles(num_particles=100, p0c=6.5e12)
+
+    # -------------------------------------------------------------------------
+    # C) Build the lattice. We add three interpolated space charge elements
+    #    and keep track of the indices at which they are available
+    lattice = st.Elements()
+
+    sc0_index = lattice.cbuffer.n_objects  # index of sc0 element
+    sc0 = lattice.SCInterpolatedProfile(
+        number_of_particles=particles.num_particles
+    )
+    dr0 = lattice.Drift(length=1.0)
+    q0 = lattice.Multipole(knl=[0.0, 0.1])
+
+    sc1_index = lattice.cbuffer.n_objects  # index of sc1 element
+    sc1 = lattice.SCInterpolatedProfile(
+        number_of_particles=particles.num_particles
+    )
+    dr1 = lattice.Drift(length=1.0)
+    q1 = lattice.Multipole(knl=[0.0, -0.1])
+
+    sc2_index = lattice.cbuffer.n_objects  # index of sc2 element
+    sc2 = lattice.SCInterpolatedProfile(
+        number_of_particles=particles.num_particles
+    )
+
+    # --------------------------------------------------------------------------
+    # D) Create the track-job
+    # Create the track-job
+    job = st.TrackJob(lattice, beam)
+    # job = st.TrackJob(lattice, beam, device="opencl:1.0")
+    # job = st.CudaTrackJob(lattice, beam)
+
+    # --------------------------------------------------------------------------
+    # E) Add the interpol_buffer to the track-job. This allows the track job
+    #    to push/pull this buffer like the other buffers via the returned id
+
+    interpol_buffer_id = job.add_stored_buffer(cbuffer=interpol_buffer)
+    print(f"interpol_buffer_id = {interpol_buffer_id}")
+
+    # --------------------------------------------------------------------------
+    # F) Create the assignments of the line profile datasets to the space
+    #    charge elements. Instead of doing it using the track-job API directly,
+    #    we use a convenience function which hides all the gritty details
+
+    # create first assignments:
+    # sc_data0 @ sc_data0_idx -> sc0 @ sc0_index
+    success = st.LineDensityProfileData_create_buffer_assignment(
+        job, sc0_index, interpol_buffer_id, sc_data0_idx
+    )
+    assert success
+
+    # create second assignments:
+    # sc_data1 @ sc_data1_idx -> sc1 @ sc1_index
+    success = st.LineDensityProfileData_create_buffer_assignment(
+        job, sc1_index, interpol_buffer_id, sc_data1_idx
+    )
+    assert success
+
+    # create third assignments:
+    # sc_data1 @ sc_data1_idx -> sc2 @ sc2_index
+    success = st.LineDensityProfileData_create_buffer_assignment(
+        job, sc2_index, interpol_buffer_id, sc_data1_idx
+    )
+    assert success
+
+    # --------------------------------------------------------------------------
+    # G) Perform the address assignments
+
+    job.commit_address_assignments()
+    job.assign_all_addresses()
+
+    # --------------------------------------------------------------------------
+    # F) Check whether the assignments actually worked
+
+    job.collect_beam_elements()
+    job.collect_stored_buffer(interpol_buffer_id)
+
+    sc0 = lattice.cbuffer.get_object(sc0_index)
+    sc1 = lattice.cbuffer.get_object(sc1_index)
+    sc2 = lattice.cbuffer.get_object(sc2_index)
+
+    if job.arch_str == "cpu":
+        print(
+            f"""
+        sc0.data_addr = {sc0.interpol_data_addr:#018x} <- sc_data0 @ {sc_data0._get_address():#018x}
+        sc1.data_addr = {sc1.interpol_data_addr:#018x} <- sc_data1 @ {sc_data1._get_address():#018x}
+        sc2.data_addr = {sc2.interpol_data_addr:#018x} <- sc_data1 @ {sc_data1._get_address():#018x}
+        """
+        )
+    else:
+        print(
+            f"""
+        sc0.data_addr = {sc0.interpol_data_addr:#018x}
+        sc1.data_addr = {sc1.interpol_data_addr:#018x}
+        sc2.data_addr = {sc2.interpol_data_addr:#018x}"""
+        )
diff --git a/examples/python/tricub/tricub_simple.py b/examples/python/tricub/tricub_simple.py
new file mode 100644
index 00000000..464e361a
--- /dev/null
+++ b/examples/python/tricub/tricub_simple.py
@@ -0,0 +1,104 @@
+import sixtracklib as st
+import cobjects
+from cobjects import CBuffer
+
+# ------------------------------------------------------------------------------
+# 1) Build the lattice and the particle set:
+# a) the lattice
+lattice = st.Elements()
+elem = lattice.Drift(length=1.0)
+elem = lattice.Multipole(knl=[0.0, 1.0])
+
+tc2_index = lattice.cbuffer.n_objects  # First TriCub element: index 2
+tc = st.TriCub(cbuffer=lattice.cbuffer)
+
+elem = lattice.Drift(length=2.0)
+elem = lattice.LimitRect(xmin=-1.0, xmax=1.0, ymin=-1.0, ymax=1.0)
+
+tc5_index = lattice.cbuffer.n_objects  # Second TriCub element: index 5
+tc = st.TriCub(cbuffer=lattice.cbuffer)
+
+elem = lattice.Drift(length=0.5)
+elem = lattice.LimitRect(xmin=-0.5, xmax=1.5, ymin=-1.5, ymax=0.5)
+
+tc8_index = lattice.cbuffer.n_objects  # Third TriCub element: index 8
+tc = st.TriCub(cbuffer=lattice.cbuffer)
+
+# b) the particle set
+particle_sets = st.ParticlesSet()
+particles = particle_sets.Particles(num_particles=100)
+
+# ------------------------------------------------------------------------------
+# 2) Create the track_job; currently only CPU is supported
+
+job = st.TrackJob(lattice, particle_sets)
+
+# ------------------------------------------------------------------------------
+# 3) Create the data buffer for the TriCubData instances and hand it over to
+#    the track_job for management:
+
+tricub_data_buffer = CBuffer()
+
+tc_data_0_index = tricub_data_buffer.n_objects
+tc_data_0 = st.TriCubData(cbuffer=tricub_data_buffer, nx=100, ny=100, nz=100)
+
+tc_data_1_index = tricub_data_buffer.n_objects
+tc_data_1 = st.TriCubData(cbuffer=tricub_data_buffer, nx=10, ny=16, nz=8)
+
+tricub_data_buffer_id = job.add_stored_buffer(cbuffer=tricub_data_buffer)
+
+# ------------------------------------------------------------------------------
+# 4) Create the mappings connecting the two TriCubData instances to the three
+#    TriCub beam elements
+#
+#    tc_data_0 -> tc2
+#    tc_data_1 -> tc5
+#    tc_data_0 -> tc8
+
+st.TriCub_buffer_create_assign_address_item(
+    job, tc2_index, tricub_data_buffer_id, tc_data_0_index)
+st.TriCub_buffer_create_assign_address_item(
+    job, tc5_index, tricub_data_buffer_id, tc_data_1_index)
+st.TriCub_buffer_create_assign_address_item(
+    job, tc8_index, tricub_data_buffer_id, tc_data_0_index)
+
+# commit the mappings:
+
+job.commit_address_assignments()
+
+# ------------------------------------------------------------------------------
+# 5) Perform the assignments
+
+job.assign_all_addresses()
+
+# ------------------------------------------------------------------------------
+# 6) Check whether the assignments actually worked
+
+job.collect_beam_elements()
+job.collect_stored_buffer(tricub_data_buffer_id)
+
+tc2 = job.beam_elements_buffer.get_object(tc2_index)
+tc5 = job.beam_elements_buffer.get_object(tc5_index)
+tc8 = job.beam_elements_buffer.get_object(tc8_index)
+
+tc2_data_addr = tc2.data_addr
+tc5_data_addr = tc5.data_addr
+tc8_data_addr = tc8.data_addr
+
+if job.arch_str == 'cpu':
+    tc_data_0_addr = tc_data_0._get_address()
+    tc_data_1_addr = tc_data_1._get_address()
+
+    print_str = f"""
+    tc2.data_addr = {tc2_data_addr:#018x} <- tc_data_0 @ {tc_data_0_addr:#018x}
+    tc5.data_addr = {tc5_data_addr:#018x} <- tc_data_1 @ {tc_data_1_addr:#018x}
+    tc8.data_addr = {tc8_data_addr:#018x} <- tc_data_0 @ {tc_data_0_addr:#018x}
+    """
+else:
+    print_str = f"""
+    tc2.data_addr = {tc2_data_addr:#018x}
+    tc5.data_addr = {tc5_data_addr:#018x}
+    tc8.data_addr = {tc8_data_addr:#018x}
+    """
+
+print(print_str)
diff --git a/external/.gitignore b/external/.gitignore
index 461e94bd..52734467 100644
--- a/external/.gitignore
+++ b/external/.gitignore
@@ -1,2 +1,3 @@
-CL/*
+toml11/
+CL/
 
diff --git a/external/CL/cl2.hpp b/external/CL/cl2.hpp
index dde00acc..7b23e1ab 100644
--- a/external/CL/cl2.hpp
+++ b/external/CL/cl2.hpp
@@ -1493,6 +1493,13 @@ CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUT
 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LOCAL_MEM_BANKS_AMD, cl_uint)
 #endif
 
+#ifdef CL_DEVICE_COMPUTE_UNITS_BITFIELD_ARM
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_UNITS_BITFIELD_ARM, cl_ulong)
+#endif
+#ifdef CL_DEVICE_JOB_SLOTS_ARM
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_JOB_SLOTS_ARM, cl_uint)
+#endif
+
 #ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
 CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, cl_uint)
 #endif
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
index f489c816..81166c35 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -1,9 +1,10 @@
-# =============================================================================
+# ============================================================================
 # external/CMakeLists.txt
 
 message( STATUS "---- processing external/CMakeLists.txt" )
 
+add_subdirectory( toml11 )
+
 if( SIXTRACKL_ENABLE_OPENCL )
     add_subdirectory( CL )
 endif()
-
diff --git a/external/toml11/CMakeLists.txt b/external/toml11/CMakeLists.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/external/toml11/README.md b/external/toml11/README.md
new file mode 100644
index 00000000..392755a1
--- /dev/null
+++ b/external/toml11/README.md
@@ -0,0 +1,9 @@
+# toml11 embedded into SixTrackLib
+This directory contains an embedded version of the
+[https://github.com/ToruNiina/toml11](toml11 library) for use within SixTrackLib.
+Copyright (C) 2017 Toru Niina. Please refer to the LICENSE file and the
+toml11_README.md files for further information about toml11.
+
+**Note**: We attempt to update the contents of this library from upstream
+every time cmake is run. This can be switched off by forcing offline builds
+via the settings file. Please refer to `cmake/SetupToml.cmake` for details.
diff --git a/external/toml11/toml.hpp b/external/toml11/toml.hpp
new file mode 100644
index 00000000..2182df16
--- /dev/null
+++ b/external/toml11/toml.hpp
@@ -0,0 +1,41 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Toru Niina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef TOML_FOR_MODERN_CPP
+#define TOML_FOR_MODERN_CPP
+
+#ifndef __cplusplus
+#    error "__cplusplus is not defined"
+#endif
+
+#if __cplusplus < 201103L && _MSC_VER < 1900
+#    error "toml11 requires C++11 or later."
+#endif
+
+#include "toml/parser.hpp"
+#include "toml/literal.hpp"
+#include "toml/serializer.hpp"
+#include "toml/get.hpp"
+
+#endif// TOML_FOR_MODERN_CPP
diff --git a/external/toml11/toml/combinator.hpp b/external/toml11/toml/combinator.hpp
new file mode 100644
index 00000000..1c6ce257
--- /dev/null
+++ b/external/toml11/toml/combinator.hpp
@@ -0,0 +1,333 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_COMBINATOR_HPP
+#define TOML11_COMBINATOR_HPP
+#include "traits.hpp"
+#include "result.hpp"
+#include "utility.hpp"
+#include "region.hpp"
+#include <type_traits>
+#include <iterator>
+#include <limits>
+#include <array>
+#include <iomanip>
+#include <cstdio>
+#include <cassert>
+#include <cctype>
+
+// they scans characters and returns region if it matches to the condition.
+// when they fail, it does not change the location.
+// in lexer.hpp, these are used.
+
+namespace toml
+{
+namespace detail
+{
+
+// to output character as an error message.
+inline std::string show_char(const char c)
+{
+    // It supress an error that occurs only in Debug mode of MSVC++ on Windows.
+    // I'm not completely sure but they check the value of char to be in the
+    // range [0, 256) and some of the COMPLETELY VALID utf-8 character sometimes
+    // has negative value (if char has sign). So here it re-interprets c as
+    // unsigned char through pointer. In general, converting pointer to a
+    // pointer that has different type cause UB, but `(signed|unsigned)?char`
+    // are one of the exceptions. Converting pointer only to char and std::byte
+    // (c++17) are valid.
+    if(std::isgraph(*reinterpret_cast<unsigned char const*>(std::addressof(c))))
+    {
+        return std::string(1, c);
+    }
+    else
+    {
+        std::array<char, 5> buf;
+        buf.fill('\0');
+        const auto r = std::snprintf(
+                buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
+        assert(r == static_cast<int>(buf.size()) - 1);
+        return std::string(buf.data());
+    }
+}
+
+template<char C>
+struct character
+{
+    static constexpr char target = C;
+
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        static_assert(std::is_same<char, typename Cont::value_type>::value,
+                      "internal error: container::value_type should be `char`.");
+
+        if(loc.iter() == loc.end()) {return none();}
+        const auto first = loc.iter();
+
+        const char c = *(loc.iter());
+        if(c != target)
+        {
+            return none();
+        }
+        loc.advance(); // update location
+
+        return ok(region<Cont>(loc, first, loc.iter()));
+    }
+};
+template<char C>
+constexpr char character<C>::target;
+
+// closed interval [Low, Up]. both Low and Up are included.
+template<char Low, char Up>
+struct in_range
+{
+    // assuming ascii part of UTF-8...
+    static_assert(Low <= Up, "lower bound should be less than upper bound.");
+
+    static constexpr char upper = Up;
+    static constexpr char lower = Low;
+
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        static_assert(std::is_same<char, typename Cont::value_type>::value,
+                      "internal error: container::value_type should be `char`.");
+
+        if(loc.iter() == loc.end()) {return none();}
+        const auto first = loc.iter();
+
+        const char c = *(loc.iter());
+        if(c < lower || upper < c)
+        {
+            return none();
+        }
+
+        loc.advance();
+        return ok(region<Cont>(loc, first, loc.iter()));
+    }
+};
+template<char L, char U> constexpr char in_range<L, U>::upper;
+template<char L, char U> constexpr char in_range<L, U>::lower;
+
+// keep iterator if `Combinator` matches. otherwise, increment `iter` by 1 char.
+// for detecting invalid characters, like control sequences in toml string.
+template<typename Combinator>
+struct exclude
+{
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        static_assert(std::is_same<char, typename Cont::value_type>::value,
+                      "internal error: container::value_type should be `char`.");
+
+        if(loc.iter() == loc.end()) {return none();}
+        auto first = loc.iter();
+
+        auto rslt = Combinator::invoke(loc);
+        if(rslt.is_ok())
+        {
+            loc.reset(first);
+            return none();
+        }
+        loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
+        return ok(region<Cont>(loc, first, loc.iter()));
+    }
+};
+
+// increment `iter`, if matches. otherwise, just return empty string.
+template<typename Combinator>
+struct maybe
+{
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        static_assert(std::is_same<char, typename Cont::value_type>::value,
+                      "internal error: container::value_type should be `char`.");
+
+        const auto rslt = Combinator::invoke(loc);
+        if(rslt.is_ok())
+        {
+            return rslt;
+        }
+        return ok(region<Cont>(loc));
+    }
+};
+
+template<typename ... Ts>
+struct sequence;
+
+template<typename Head, typename ... Tail>
+struct sequence<Head, Tail...>
+{
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        static_assert(std::is_same<char, typename Cont::value_type>::value,
+                      "internal error: container::value_type should be `char`.");
+
+        const auto first = loc.iter();
+        const auto rslt = Head::invoke(loc);
+        if(rslt.is_err())
+        {
+            loc.reset(first);
+            return none();
+        }
+        return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
+    }
+
+    // called from the above function only, recursively.
+    template<typename Cont, typename Iterator>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
+    {
+        const auto rslt = Head::invoke(loc);
+        if(rslt.is_err())
+        {
+            loc.reset(first);
+            return none();
+        }
+        reg += rslt.unwrap(); // concat regions
+        return sequence<Tail...>::invoke(loc, std::move(reg), first);
+    }
+};
+
+template<typename Head>
+struct sequence<Head>
+{
+    // would be called from sequence<T ...>::invoke only.
+    template<typename Cont, typename Iterator>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc, region<Cont> reg, Iterator first)
+    {
+        const auto rslt = Head::invoke(loc);
+        if(rslt.is_err())
+        {
+            loc.reset(first);
+            return none();
+        }
+        reg += rslt.unwrap(); // concat regions
+        return ok(reg);
+    }
+};
+
+template<typename ... Ts>
+struct either;
+
+template<typename Head, typename ... Tail>
+struct either<Head, Tail...>
+{
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        static_assert(std::is_same<char, typename Cont::value_type>::value,
+                      "internal error: container::value_type should be `char`.");
+
+        const auto rslt = Head::invoke(loc);
+        if(rslt.is_ok()) {return rslt;}
+        return either<Tail...>::invoke(loc);
+    }
+};
+template<typename Head>
+struct either<Head>
+{
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        static_assert(std::is_same<char, typename Cont::value_type>::value,
+                      "internal error: container::value_type should be `char`.");
+        return Head::invoke(loc);
+    }
+};
+
+template<typename T, typename N>
+struct repeat;
+
+template<std::size_t N> struct exactly{};
+template<std::size_t N> struct at_least{};
+struct unlimited{};
+
+template<typename T, std::size_t N>
+struct repeat<T, exactly<N>>
+{
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        region<Cont> retval(loc);
+        const auto first = loc.iter();
+        for(std::size_t i=0; i<N; ++i)
+        {
+            auto rslt = T::invoke(loc);
+            if(rslt.is_err())
+            {
+                loc.reset(first);
+                return none();
+            }
+            retval += rslt.unwrap();
+        }
+        return ok(std::move(retval));
+    }
+};
+
+template<typename T, std::size_t N>
+struct repeat<T, at_least<N>>
+{
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        region<Cont> retval(loc);
+
+        const auto first = loc.iter();
+        for(std::size_t i=0; i<N; ++i)
+        {
+            auto rslt = T::invoke(loc);
+            if(rslt.is_err())
+            {
+                loc.reset(first);
+                return none();
+            }
+            retval += rslt.unwrap();
+        }
+        while(true)
+        {
+            auto rslt = T::invoke(loc);
+            if(rslt.is_err())
+            {
+                return ok(std::move(retval));
+            }
+            retval += rslt.unwrap();
+        }
+    }
+};
+
+template<typename T>
+struct repeat<T, unlimited>
+{
+    template<typename Cont>
+    static result<region<Cont>, none_t>
+    invoke(location<Cont>& loc)
+    {
+        region<Cont> retval(loc);
+        while(true)
+        {
+            auto rslt = T::invoke(loc);
+            if(rslt.is_err())
+            {
+                return ok(std::move(retval));
+            }
+            retval += rslt.unwrap();
+        }
+    }
+};
+
+} // detail
+} // toml
+#endif// TOML11_COMBINATOR_HPP
diff --git a/external/toml11/toml/comments.hpp b/external/toml11/toml/comments.hpp
new file mode 100644
index 00000000..5d784402
--- /dev/null
+++ b/external/toml11/toml/comments.hpp
@@ -0,0 +1,416 @@
+//     Copyright Toru Niina 2019.
+// Distributed under the MIT License.
+#ifndef TOML11_COMMENTS_HPP
+#define TOML11_COMMENTS_HPP
+#include <type_traits>
+#include <utility>
+#include <iterator>
+#include <initializer_list>
+#include <vector>
+#include <string>
+
+// This file provides mainly two classes, `preserve_comments` and `discard_comments`.
+// Those two are a container that have the same interface as `std::vector<std::string>`
+// but bahaves in the opposite way. `preserve_comments` is just the same as
+// `std::vector<std::string>` and each `std::string` corresponds to a comment line.
+// Conversely, `discard_comments` discards all the strings and ignores everything
+// assigned in it. `discard_comments` is always empty and you will encounter an
+// error whenever you access to the element.
+namespace toml
+{
+struct discard_comments; // forward decl
+
+// use it in the following way
+//
+// const toml::basic_value<toml::preserve_comments> data =
+//     toml::parse<toml::preserve_comments>("example.toml");
+//
+// the interface is almost the same as std::vector<std::string>.
+struct preserve_comments
+{
+    // `container_type` is not provided in discard_comments.
+    // do not use this inner-type in a generic code.
+    using container_type         = std::vector<std::string>;
+
+    using size_type              = container_type::size_type;
+    using difference_type        = container_type::difference_type;
+    using value_type             = container_type::value_type;
+    using reference              = container_type::reference;
+    using const_reference        = container_type::const_reference;
+    using pointer                = container_type::pointer;
+    using const_pointer          = container_type::const_pointer;
+    using iterator               = container_type::iterator;
+    using const_iterator         = container_type::const_iterator;
+    using reverse_iterator       = container_type::reverse_iterator;
+    using const_reverse_iterator = container_type::const_reverse_iterator;
+
+    preserve_comments()  = default;
+    ~preserve_comments() = default;
+    preserve_comments(preserve_comments const&) = default;
+    preserve_comments(preserve_comments &&)     = default;
+    preserve_comments& operator=(preserve_comments const&) = default;
+    preserve_comments& operator=(preserve_comments &&)     = default;
+
+    explicit preserve_comments(const std::vector<std::string>& c): comments(c){}
+    explicit preserve_comments(std::vector<std::string>&& c)
+        : comments(std::move(c))
+    {}
+    preserve_comments& operator=(const std::vector<std::string>& c)
+    {
+        comments = c;
+        return *this;
+    }
+    preserve_comments& operator=(std::vector<std::string>&& c)
+    {
+        comments = std::move(c);
+        return *this;
+    }
+
+    explicit preserve_comments(const discard_comments&) {}
+
+    explicit preserve_comments(size_type n): comments(n) {}
+    preserve_comments(size_type n, const std::string& x): comments(n, x) {}
+    preserve_comments(std::initializer_list<std::string> x): comments(x) {}
+    template<typename InputIterator>
+    preserve_comments(InputIterator first, InputIterator last)
+        : comments(first, last)
+    {}
+
+    template<typename InputIterator>
+    void assign(InputIterator first, InputIterator last) {comments.assign(first, last);}
+    void assign(std::initializer_list<std::string> ini)  {comments.assign(ini);}
+    void assign(size_type n, const std::string& val)     {comments.assign(n, val);}
+
+    iterator insert(const_iterator p, const std::string& x)
+    {
+        return comments.insert(p, x);
+    }
+    iterator insert(const_iterator p, std::string&&      x)
+    {
+        return comments.insert(p, std::move(x));
+    }
+    iterator insert(const_iterator p, size_type n, const std::string& x)
+    {
+        return comments.insert(p, n, x);
+    }
+    template<typename InputIterator>
+    iterator insert(const_iterator p, InputIterator first, InputIterator last)
+    {
+        return comments.insert(p, first, last);
+    }
+    iterator insert(const_iterator p, std::initializer_list<std::string> ini)
+    {
+        return comments.insert(p, ini);
+    }
+
+    template<typename ... Ts>
+    iterator emplace(const_iterator p, Ts&& ... args)
+    {
+        return comments.emplace(p, std::forward<Ts>(args)...);
+    }
+
+    iterator erase(const_iterator pos) {return comments.erase(pos);}
+    iterator erase(const_iterator first, const_iterator last)
+    {
+        return comments.erase(first, last);
+    }
+
+    void swap(preserve_comments& other) {comments.swap(other.comments);}
+
+    void push_back(const std::string& v) {comments.push_back(v);}
+    void push_back(std::string&&      v) {comments.push_back(std::move(v));}
+    void pop_back()                      {comments.pop_back();}
+
+    template<typename ... Ts>
+    void emplace_back(Ts&& ... args) {comments.emplace_back(std::forward<Ts>(args)...);}
+
+    void clear() {comments.clear();}
+
+    size_type size()     const noexcept {return comments.size();}
+    size_type max_size() const noexcept {return comments.max_size();}
+    size_type capacity() const noexcept {return comments.capacity();}
+    bool      empty()    const noexcept {return comments.empty();}
+
+    void reserve(size_type n)                      {comments.reserve(n);}
+    void resize(size_type n)                       {comments.resize(n);}
+    void resize(size_type n, const std::string& c) {comments.resize(n, c);}
+    void shrink_to_fit()                           {comments.shrink_to_fit();}
+
+    reference       operator[](const size_type n)       noexcept {return comments[n];}
+    const_reference operator[](const size_type n) const noexcept {return comments[n];}
+    reference       at(const size_type n)       {return comments.at(n);}
+    const_reference at(const size_type n) const {return comments.at(n);}
+    reference       front()       noexcept {return comments.front();}
+    const_reference front() const noexcept {return comments.front();}
+    reference       back()        noexcept {return comments.back();}
+    const_reference back()  const noexcept {return comments.back();}
+
+    pointer         data()        noexcept {return comments.data();}
+    const_pointer   data()  const noexcept {return comments.data();}
+
+    iterator       begin()        noexcept {return comments.begin();}
+    iterator       end()          noexcept {return comments.end();}
+    const_iterator begin()  const noexcept {return comments.begin();}
+    const_iterator end()    const noexcept {return comments.end();}
+    const_iterator cbegin() const noexcept {return comments.cbegin();}
+    const_iterator cend()   const noexcept {return comments.cend();}
+
+    reverse_iterator       rbegin()        noexcept {return comments.rbegin();}
+    reverse_iterator       rend()          noexcept {return comments.rend();}
+    const_reverse_iterator rbegin()  const noexcept {return comments.rbegin();}
+    const_reverse_iterator rend()    const noexcept {return comments.rend();}
+    const_reverse_iterator crbegin() const noexcept {return comments.crbegin();}
+    const_reverse_iterator crend()   const noexcept {return comments.crend();}
+
+    friend bool operator==(const preserve_comments&, const preserve_comments&);
+    friend bool operator!=(const preserve_comments&, const preserve_comments&);
+    friend bool operator< (const preserve_comments&, const preserve_comments&);
+    friend bool operator<=(const preserve_comments&, const preserve_comments&);
+    friend bool operator> (const preserve_comments&, const preserve_comments&);
+    friend bool operator>=(const preserve_comments&, const preserve_comments&);
+
+    friend void swap(preserve_comments&, std::vector<std::string>&);
+    friend void swap(std::vector<std::string>&, preserve_comments&);
+
+  private:
+
+    container_type comments;
+};
+
+inline bool operator==(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments == rhs.comments;}
+inline bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments != rhs.comments;}
+inline bool operator< (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments <  rhs.comments;}
+inline bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments <= rhs.comments;}
+inline bool operator> (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments >  rhs.comments;}
+inline bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments >= rhs.comments;}
+
+inline void swap(preserve_comments& lhs, preserve_comments& rhs)
+{
+    lhs.swap(rhs);
+    return;
+}
+inline void swap(preserve_comments& lhs, std::vector<std::string>& rhs)
+{
+    lhs.comments.swap(rhs);
+    return;
+}
+inline void swap(std::vector<std::string>& lhs, preserve_comments& rhs)
+{
+    lhs.swap(rhs.comments);
+    return;
+}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const preserve_comments& com)
+{
+    for(const auto& c : com)
+    {
+        os << '#' << c << '\n';
+    }
+    return os;
+}
+
+namespace detail
+{
+
+// To provide the same interface with `preserve_comments`, `discard_comments`
+// should have an iterator. But it does not contain anything, so we need to
+// add an iterator that points nothing.
+//
+// It always points null, so DO NOT unwrap this iterator. It always crashes
+// your program.
+template<typename T, bool is_const>
+struct empty_iterator
+{
+    using value_type        = T;
+    using reference_type    = typename std::conditional<is_const, T const&, T&>::type;
+    using pointer_type      = typename std::conditional<is_const, T const*, T*>::type;
+    using difference_type   = std::ptrdiff_t;
+    using iterator_category = std::random_access_iterator_tag;
+
+    empty_iterator()  = default;
+    ~empty_iterator() = default;
+    empty_iterator(empty_iterator const&) = default;
+    empty_iterator(empty_iterator &&)     = default;
+    empty_iterator& operator=(empty_iterator const&) = default;
+    empty_iterator& operator=(empty_iterator &&)     = default;
+
+    // DO NOT call these operators.
+    reference_type operator*()  const noexcept {std::terminate();}
+    pointer_type   operator->() const noexcept {return nullptr;}
+    reference_type operator[](difference_type) const noexcept {return this->operator*();}
+
+    // These operators do nothing.
+    empty_iterator& operator++()    noexcept {return *this;}
+    empty_iterator  operator++(int) noexcept {return *this;}
+    empty_iterator& operator--()    noexcept {return *this;}
+    empty_iterator  operator--(int) noexcept {return *this;}
+
+    empty_iterator& operator+=(difference_type) noexcept {return *this;}
+    empty_iterator& operator-=(difference_type) noexcept {return *this;}
+
+    empty_iterator  operator+(difference_type) const noexcept {return *this;}
+    empty_iterator  operator-(difference_type) const noexcept {return *this;}
+};
+
+template<typename T, bool C>
+bool operator==(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
+template<typename T, bool C>
+bool operator!=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
+template<typename T, bool C>
+bool operator< (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
+template<typename T, bool C>
+bool operator<=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
+template<typename T, bool C>
+bool operator> (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
+template<typename T, bool C>
+bool operator>=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
+
+template<typename T, bool C>
+typename empty_iterator<T, C>::difference_type
+operator-(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return 0;}
+
+template<typename T, bool C>
+empty_iterator<T, C>
+operator+(typename empty_iterator<T, C>::difference_type, const empty_iterator<T, C>& rhs) noexcept {return rhs;}
+template<typename T, bool C>
+empty_iterator<T, C>
+operator+(const empty_iterator<T, C>& lhs, typename empty_iterator<T, C>::difference_type) noexcept {return lhs;}
+
+} // detail
+
+// The default comment type. It discards all the comments. It requires only one
+// byte to contain, so the memory footprint is smaller than preserve_comments.
+//
+// It just ignores `push_back`, `insert`, `erase`, and any other modifications.
+// IT always returns size() == 0, the iterator taken by `begin()` is always the
+// same as that of `end()`, and accessing through `operator[]` or iterators
+// always causes a segmentation fault. DO NOT access to the element of this.
+//
+// Why this is chose as the default type is because the last version (2.x.y)
+// does not contain any comments in a value. To minimize the impact on the
+// efficiency, this is choosed as a default.
+//
+// To reduce the memory footprint, later we can try empty base optimization (EBO).
+struct discard_comments
+{
+    using size_type              = std::size_t;
+    using difference_type        = std::ptrdiff_t;
+    using value_type             = std::string;
+    using reference              = std::string&;
+    using const_reference        = std::string const&;
+    using pointer                = std::string*;
+    using const_pointer          = std::string const*;
+    using iterator               = detail::empty_iterator<std::string, false>;
+    using const_iterator         = detail::empty_iterator<std::string, true>;
+    using reverse_iterator       = detail::empty_iterator<std::string, false>;
+    using const_reverse_iterator = detail::empty_iterator<std::string, true>;
+
+    discard_comments() = default;
+    ~discard_comments() = default;
+    discard_comments(discard_comments const&) = default;
+    discard_comments(discard_comments &&)     = default;
+    discard_comments& operator=(discard_comments const&) = default;
+    discard_comments& operator=(discard_comments &&)     = default;
+
+    explicit discard_comments(const std::vector<std::string>&) noexcept {}
+    explicit discard_comments(std::vector<std::string>&&)      noexcept {}
+    discard_comments& operator=(const std::vector<std::string>&) noexcept {return *this;}
+    discard_comments& operator=(std::vector<std::string>&&)      noexcept {return *this;}
+
+    explicit discard_comments(const preserve_comments&)        noexcept {}
+
+    explicit discard_comments(size_type) noexcept {}
+    discard_comments(size_type, const std::string&) noexcept {}
+    discard_comments(std::initializer_list<std::string>) noexcept {}
+    template<typename InputIterator>
+    discard_comments(InputIterator, InputIterator) noexcept {}
+
+    template<typename InputIterator>
+    void assign(InputIterator, InputIterator)       noexcept {}
+    void assign(std::initializer_list<std::string>) noexcept {}
+    void assign(size_type, const std::string&)      noexcept {}
+
+    iterator insert(const_iterator, const std::string&)                 {return iterator{};}
+    iterator insert(const_iterator, std::string&&)                      {return iterator{};}
+    iterator insert(const_iterator, size_type, const std::string&)      {return iterator{};}
+    template<typename InputIterator>
+    iterator insert(const_iterator, InputIterator, InputIterator)       {return iterator{};}
+    iterator insert(const_iterator, std::initializer_list<std::string>) {return iterator{};}
+
+    template<typename ... Ts>
+    iterator emplace(const_iterator, Ts&& ...)     {return iterator{};}
+    iterator erase(const_iterator)                 {return iterator{};}
+    iterator erase(const_iterator, const_iterator) {return iterator{};}
+
+    void swap(discard_comments&) {return;}
+
+    void push_back(const std::string&) {return;}
+    void push_back(std::string&&     ) {return;}
+    void pop_back()                    {return;}
+
+    template<typename ... Ts>
+    void emplace_back(Ts&& ...) {return;}
+
+    void clear() {return;}
+
+    size_type size()     const noexcept {return 0;}
+    size_type max_size() const noexcept {return 0;}
+    size_type capacity() const noexcept {return 0;}
+    bool      empty()    const noexcept {return true;}
+
+    void reserve(size_type)                    {return;}
+    void resize(size_type)                     {return;}
+    void resize(size_type, const std::string&) {return;}
+    void shrink_to_fit()                       {return;}
+
+    // DO NOT access to the element of this container. This container is always
+    // empty, so accessing through operator[], front/back, data causes address
+    // error.
+
+    reference       operator[](const size_type)       noexcept {return *data();}
+    const_reference operator[](const size_type) const noexcept {return *data();}
+    reference       at(const size_type)       {throw std::out_of_range("toml::discard_comment is always empty.");}
+    const_reference at(const size_type) const {throw std::out_of_range("toml::discard_comment is always empty.");}
+    reference       front()       noexcept {return *data();}
+    const_reference front() const noexcept {return *data();}
+    reference       back()        noexcept {return *data();}
+    const_reference back()  const noexcept {return *data();}
+
+    pointer         data()        noexcept {return nullptr;}
+    const_pointer   data()  const noexcept {return nullptr;}
+
+    iterator       begin()        noexcept {return iterator{};}
+    iterator       end()          noexcept {return iterator{};}
+    const_iterator begin()  const noexcept {return const_iterator{};}
+    const_iterator end()    const noexcept {return const_iterator{};}
+    const_iterator cbegin() const noexcept {return const_iterator{};}
+    const_iterator cend()   const noexcept {return const_iterator{};}
+
+    reverse_iterator       rbegin()        noexcept {return iterator{};}
+    reverse_iterator       rend()          noexcept {return iterator{};}
+    const_reverse_iterator rbegin()  const noexcept {return const_iterator{};}
+    const_reverse_iterator rend()    const noexcept {return const_iterator{};}
+    const_reverse_iterator crbegin() const noexcept {return const_iterator{};}
+    const_reverse_iterator crend()   const noexcept {return const_iterator{};}
+};
+
+inline bool operator==(const discard_comments&, const discard_comments&) noexcept {return true;}
+inline bool operator!=(const discard_comments&, const discard_comments&) noexcept {return false;}
+inline bool operator< (const discard_comments&, const discard_comments&) noexcept {return false;}
+inline bool operator<=(const discard_comments&, const discard_comments&) noexcept {return true;}
+inline bool operator> (const discard_comments&, const discard_comments&) noexcept {return false;}
+inline bool operator>=(const discard_comments&, const discard_comments&) noexcept {return true;}
+
+inline void swap(const discard_comments&, const discard_comments&) noexcept {return;}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const discard_comments&)
+{
+    return os;
+}
+
+} // toml11
+#endif// TOML11_COMMENTS_HPP
diff --git a/external/toml11/toml/datetime.hpp b/external/toml11/toml/datetime.hpp
new file mode 100644
index 00000000..dc523963
--- /dev/null
+++ b/external/toml11/toml/datetime.hpp
@@ -0,0 +1,559 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_DATETIME_HPP
+#define TOML11_DATETIME_HPP
+#include <chrono>
+#include <tuple>
+#include <array>
+#include <ostream>
+#include <iomanip>
+#include <cstdint>
+#include <cstdlib>
+#include <ctime>
+
+namespace toml
+{
+
+// To avoid non-threadsafe std::localtime. In C11 (not C++11!), localtime_s is
+// provided in the absolutely same purpose, but C++11 is actually not compatible
+// with C11. We need to dispatch the function depending on the OS.
+namespace detail
+{
+// TODO: find more sophisticated way to handle this
+#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE
+inline std::tm localtime_s(const std::time_t* src)
+{
+    std::tm dst;
+    const auto result = ::localtime_r(src, &dst);
+    if (!result) { throw std::runtime_error("localtime_r failed."); }
+    return dst;
+}
+#elif _MSC_VER
+inline std::tm localtime_s(const std::time_t* src)
+{
+    std::tm dst;
+    const auto result = ::localtime_s(&dst, src);
+    if (result) { throw std::runtime_error("localtime_s failed."); }
+    return dst;
+}
+#else
+inline std::tm localtime_s(const std::time_t* src)
+{
+    const auto result = std::localtime(src);
+    if (!result) { throw std::runtime_error("localtime failed."); }
+    return *result;
+}
+#endif
+} // detail
+
+enum class month_t : std::uint8_t
+{
+    Jan =  0,
+    Feb =  1,
+    Mar =  2,
+    Apr =  3,
+    May =  4,
+    Jun =  5,
+    Jul =  6,
+    Aug =  7,
+    Sep =  8,
+    Oct =  9,
+    Nov = 10,
+    Dec = 11
+};
+
+struct local_date
+{
+    std::int16_t year;   // A.D. (like, 2018)
+    std::uint8_t month;  // [0, 11]
+    std::uint8_t day;    // [1, 31]
+
+    local_date(int y, month_t m, int d)
+        : year (static_cast<std::int16_t>(y)),
+          month(static_cast<std::uint8_t>(m)),
+          day  (static_cast<std::uint8_t>(d))
+    {}
+
+    explicit local_date(const std::tm& t)
+        : year (static_cast<std::int16_t>(t.tm_year + 1900)),
+          month(static_cast<std::uint8_t>(t.tm_mon)),
+          day  (static_cast<std::uint8_t>(t.tm_mday))
+    {}
+
+    explicit local_date(const std::chrono::system_clock::time_point& tp)
+    {
+        const auto t    = std::chrono::system_clock::to_time_t(tp);
+        const auto time = detail::localtime_s(&t);
+        *this = local_date(time);
+    }
+
+    explicit local_date(const std::time_t t)
+        : local_date(std::chrono::system_clock::from_time_t(t))
+    {}
+
+    operator std::chrono::system_clock::time_point() const
+    {
+        // std::mktime returns date as local time zone. no conversion needed
+        std::tm t;
+        t.tm_sec   = 0;
+        t.tm_min   = 0;
+        t.tm_hour  = 0;
+        t.tm_mday  = static_cast<int>(this->day);
+        t.tm_mon   = static_cast<int>(this->month);
+        t.tm_year  = static_cast<int>(this->year) - 1900;
+        t.tm_wday  = 0; // the value will be ignored
+        t.tm_yday  = 0; // the value will be ignored
+        t.tm_isdst = -1;
+        return std::chrono::system_clock::from_time_t(std::mktime(&t));
+    }
+
+    operator std::time_t() const
+    {
+        return std::chrono::system_clock::to_time_t(
+                std::chrono::system_clock::time_point(*this));
+    }
+
+    local_date() = default;
+    ~local_date() = default;
+    local_date(local_date const&) = default;
+    local_date(local_date&&)      = default;
+    local_date& operator=(local_date const&) = default;
+    local_date& operator=(local_date&&)      = default;
+};
+
+inline bool operator==(const local_date& lhs, const local_date& rhs)
+{
+    return std::make_tuple(lhs.year, lhs.month, lhs.day) ==
+           std::make_tuple(rhs.year, rhs.month, rhs.day);
+}
+inline bool operator!=(const local_date& lhs, const local_date& rhs)
+{
+    return !(lhs == rhs);
+}
+inline bool operator< (const local_date& lhs, const local_date& rhs)
+{
+    return std::make_tuple(lhs.year, lhs.month, lhs.day) <
+           std::make_tuple(rhs.year, rhs.month, rhs.day);
+}
+inline bool operator<=(const local_date& lhs, const local_date& rhs)
+{
+    return (lhs < rhs) || (lhs == rhs);
+}
+inline bool operator> (const local_date& lhs, const local_date& rhs)
+{
+    return !(lhs <= rhs);
+}
+inline bool operator>=(const local_date& lhs, const local_date& rhs)
+{
+    return !(lhs < rhs);
+}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const local_date& date)
+{
+    os << std::setfill('0') << std::setw(4) << static_cast<int>(date.year     ) << '-';
+    os << std::setfill('0') << std::setw(2) << static_cast<int>(date.month + 1) << '-';
+    os << std::setfill('0') << std::setw(2) << static_cast<int>(date.day      );
+    return os;
+}
+
+struct local_time
+{
+    std::uint8_t  hour;        // [0, 23]
+    std::uint8_t  minute;      // [0, 59]
+    std::uint8_t  second;      // [0, 60]
+    std::uint16_t millisecond; // [0, 999]
+    std::uint16_t microsecond; // [0, 999]
+    std::uint16_t nanosecond;  // [0, 999]
+
+    local_time(int h, int m, int s,
+               int ms = 0, int us = 0, int ns = 0)
+        : hour  (static_cast<std::uint8_t>(h)),
+          minute(static_cast<std::uint8_t>(m)),
+          second(static_cast<std::uint8_t>(s)),
+          millisecond(static_cast<std::uint16_t>(ms)),
+          microsecond(static_cast<std::uint16_t>(us)),
+          nanosecond (static_cast<std::uint16_t>(ns))
+    {}
+
+    explicit local_time(const std::tm& t)
+        : hour  (static_cast<std::uint8_t>(t.tm_hour)),
+          minute(static_cast<std::uint8_t>(t.tm_min)),
+          second(static_cast<std::uint8_t>(t.tm_sec)),
+          millisecond(0), microsecond(0), nanosecond(0)
+    {}
+
+    template<typename Rep, typename Period>
+    explicit local_time(const std::chrono::duration<Rep, Period>& t)
+    {
+        const auto h = std::chrono::duration_cast<std::chrono::hours>(t);
+        this->hour = static_cast<std::uint8_t>(h.count());
+        const auto t2 = t - h;
+        const auto m = std::chrono::duration_cast<std::chrono::minutes>(t2);
+        this->minute = static_cast<std::uint8_t>(m.count());
+        const auto t3 = t2 - m;
+        const auto s = std::chrono::duration_cast<std::chrono::seconds>(t3);
+        this->second = static_cast<std::uint8_t>(s.count());
+        const auto t4 = t3 - s;
+        const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t4);
+        this->millisecond = static_cast<std::uint16_t>(ms.count());
+        const auto t5 = t4 - ms;
+        const auto us = std::chrono::duration_cast<std::chrono::microseconds>(t5);
+        this->microsecond = static_cast<std::uint16_t>(us.count());
+        const auto t6 = t5 - us;
+        const auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t6);
+        this->nanosecond = static_cast<std::uint16_t>(ns.count());
+    }
+
+    operator std::chrono::nanoseconds() const
+    {
+        return std::chrono::nanoseconds (this->nanosecond)  +
+               std::chrono::microseconds(this->microsecond) +
+               std::chrono::milliseconds(this->millisecond) +
+               std::chrono::seconds(this->second) +
+               std::chrono::minutes(this->minute) +
+               std::chrono::hours(this->hour);
+    }
+
+    local_time() = default;
+    ~local_time() = default;
+    local_time(local_time const&) = default;
+    local_time(local_time&&)      = default;
+    local_time& operator=(local_time const&) = default;
+    local_time& operator=(local_time&&)      = default;
+};
+
+inline bool operator==(const local_time& lhs, const local_time& rhs)
+{
+    return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) ==
+           std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond);
+}
+inline bool operator!=(const local_time& lhs, const local_time& rhs)
+{
+    return !(lhs == rhs);
+}
+inline bool operator< (const local_time& lhs, const local_time& rhs)
+{
+    return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) <
+           std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond);
+}
+inline bool operator<=(const local_time& lhs, const local_time& rhs)
+{
+    return (lhs < rhs) || (lhs == rhs);
+}
+inline bool operator> (const local_time& lhs, const local_time& rhs)
+{
+    return !(lhs <= rhs);
+}
+inline bool operator>=(const local_time& lhs, const local_time& rhs)
+{
+    return !(lhs < rhs);
+}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const local_time& time)
+{
+    os << std::setfill('0') << std::setw(2) << static_cast<int>(time.hour  ) << ':';
+    os << std::setfill('0') << std::setw(2) << static_cast<int>(time.minute) << ':';
+    os << std::setfill('0') << std::setw(2) << static_cast<int>(time.second);
+    if(time.millisecond != 0 || time.microsecond != 0 || time.nanosecond != 0)
+    {
+        os << '.';
+        os << std::setfill('0') << std::setw(3) << static_cast<int>(time.millisecond);
+        if(time.microsecond != 0 || time.nanosecond != 0)
+        {
+            os << std::setfill('0') << std::setw(3) << static_cast<int>(time.microsecond);
+            if(time.nanosecond != 0)
+            {
+                os << std::setfill('0') << std::setw(3) << static_cast<int>(time.nanosecond);
+            }
+        }
+    }
+    return os;
+}
+
+struct time_offset
+{
+    std::int8_t hour;   // [-12, 12]
+    std::int8_t minute; // [-59, 59]
+
+    time_offset(int h, int m)
+        : hour  (static_cast<std::int8_t>(h)),
+          minute(static_cast<std::int8_t>(m))
+    {}
+
+    operator std::chrono::minutes() const
+    {
+        return std::chrono::minutes(this->minute) +
+               std::chrono::hours(this->hour);
+    }
+
+    time_offset() = default;
+    ~time_offset() = default;
+    time_offset(time_offset const&) = default;
+    time_offset(time_offset&&)      = default;
+    time_offset& operator=(time_offset const&) = default;
+    time_offset& operator=(time_offset&&)      = default;
+};
+
+inline bool operator==(const time_offset& lhs, const time_offset& rhs)
+{
+    return std::make_tuple(lhs.hour, lhs.minute) ==
+           std::make_tuple(rhs.hour, rhs.minute);
+}
+inline bool operator!=(const time_offset& lhs, const time_offset& rhs)
+{
+    return !(lhs == rhs);
+}
+inline bool operator< (const time_offset& lhs, const time_offset& rhs)
+{
+    return std::make_tuple(lhs.hour, lhs.minute) <
+           std::make_tuple(rhs.hour, rhs.minute);
+}
+inline bool operator<=(const time_offset& lhs, const time_offset& rhs)
+{
+    return (lhs < rhs) || (lhs == rhs);
+}
+inline bool operator> (const time_offset& lhs, const time_offset& rhs)
+{
+    return !(lhs <= rhs);
+}
+inline bool operator>=(const time_offset& lhs, const time_offset& rhs)
+{
+    return !(lhs < rhs);
+}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const time_offset& offset)
+{
+    if(offset.hour == 0 && offset.minute == 0)
+    {
+        os << 'Z';
+        return os;
+    }
+    int minute = static_cast<int>(offset.hour) * 60 + offset.minute;
+    if(minute < 0){os << '-'; minute = std::abs(minute);} else {os << '+';}
+    os << std::setfill('0') << std::setw(2) << minute / 60 << ':';
+    os << std::setfill('0') << std::setw(2) << minute % 60;
+    return os;
+}
+
+struct local_datetime
+{
+    local_date date;
+    local_time time;
+
+    local_datetime(local_date d, local_time t): date(d), time(t) {}
+
+    explicit local_datetime(const std::tm& t): date(t), time(t){}
+
+    explicit local_datetime(const std::chrono::system_clock::time_point& tp)
+    {
+        const auto t = std::chrono::system_clock::to_time_t(tp);
+        std::tm ltime = detail::localtime_s(&t);
+
+        this->date = local_date(ltime);
+        this->time = local_time(ltime);
+
+        // std::tm lacks subsecond information, so diff between tp and tm
+        // can be used to get millisecond & microsecond information.
+        const auto t_diff = tp -
+            std::chrono::system_clock::from_time_t(std::mktime(&ltime));
+        this->time.millisecond = static_cast<std::uint16_t>(
+          std::chrono::duration_cast<std::chrono::milliseconds>(t_diff).count());
+        this->time.microsecond = static_cast<std::uint16_t>(
+          std::chrono::duration_cast<std::chrono::microseconds>(t_diff).count());
+        this->time.nanosecond = static_cast<std::uint16_t>(
+          std::chrono::duration_cast<std::chrono::nanoseconds >(t_diff).count());
+    }
+
+    explicit local_datetime(const std::time_t t)
+        : local_datetime(std::chrono::system_clock::from_time_t(t))
+    {}
+
+    operator std::chrono::system_clock::time_point() const
+    {
+        using internal_duration =
+            typename std::chrono::system_clock::time_point::duration;
+        // std::mktime returns date as local time zone. no conversion needed
+        auto dt = std::chrono::system_clock::time_point(this->date);
+        dt += std::chrono::duration_cast<internal_duration>(
+                   std::chrono::nanoseconds(this->time));
+        return dt;
+    }
+
+    operator std::time_t() const
+    {
+        return std::chrono::system_clock::to_time_t(
+                std::chrono::system_clock::time_point(*this));
+    }
+
+    local_datetime() = default;
+    ~local_datetime() = default;
+    local_datetime(local_datetime const&) = default;
+    local_datetime(local_datetime&&)      = default;
+    local_datetime& operator=(local_datetime const&) = default;
+    local_datetime& operator=(local_datetime&&)      = default;
+};
+
+inline bool operator==(const local_datetime& lhs, const local_datetime& rhs)
+{
+    return std::make_tuple(lhs.date, lhs.time) ==
+           std::make_tuple(rhs.date, rhs.time);
+}
+inline bool operator!=(const local_datetime& lhs, const local_datetime& rhs)
+{
+    return !(lhs == rhs);
+}
+inline bool operator< (const local_datetime& lhs, const local_datetime& rhs)
+{
+    return std::make_tuple(lhs.date, lhs.time) <
+           std::make_tuple(rhs.date, rhs.time);
+}
+inline bool operator<=(const local_datetime& lhs, const local_datetime& rhs)
+{
+    return (lhs < rhs) || (lhs == rhs);
+}
+inline bool operator> (const local_datetime& lhs, const local_datetime& rhs)
+{
+    return !(lhs <= rhs);
+}
+inline bool operator>=(const local_datetime& lhs, const local_datetime& rhs)
+{
+    return !(lhs < rhs);
+}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const local_datetime& dt)
+{
+    os << dt.date << 'T' << dt.time;
+    return os;
+}
+
+struct offset_datetime
+{
+    local_date  date;
+    local_time  time;
+    time_offset offset;
+
+    offset_datetime(local_date d, local_time t, time_offset o)
+        : date(d), time(t), offset(o)
+    {}
+    offset_datetime(const local_datetime& dt, time_offset o)
+        : date(dt.date), time(dt.time), offset(o)
+    {}
+    explicit offset_datetime(const local_datetime& ld)
+        : date(ld.date), time(ld.time), offset(get_local_offset())
+    {}
+    explicit offset_datetime(const std::chrono::system_clock::time_point& tp)
+        : offset_datetime(local_datetime(tp))
+    {}
+    explicit offset_datetime(const std::time_t& t)
+        : offset_datetime(local_datetime(t))
+    {}
+    explicit offset_datetime(const std::tm& t)
+        : offset_datetime(local_datetime(t))
+    {}
+
+    operator std::chrono::system_clock::time_point() const
+    {
+        // get date-time
+        using internal_duration =
+            typename std::chrono::system_clock::time_point::duration;
+        std::chrono::system_clock::time_point tp =
+            std::chrono::system_clock::time_point(this->date) +
+            std::chrono::duration_cast<internal_duration>(
+                   std::chrono::nanoseconds(this->time));
+
+        // get date-time in UTC. let's say we are in +09:00 (JPN).
+        // writing 12:00:00 in +09:00 means 03:00:00Z. to represent
+        // 12:00:00Z, first we need to add +09:00.
+        const auto ofs = get_local_offset();
+        tp += std::chrono::hours  (ofs.hour);
+        tp += std::chrono::minutes(ofs.minute);
+
+        // here, tp represents 12:00:00 in UTC but we have offset information.
+        // we need to subtract it. For example, let's say the input is
+        // 12:00:00-08:00. now we have tp = 12:00:00Z as a result of the above
+        // conversion. But the actual time we need to return is 20:00:00Z
+        // because of -08:00.
+        tp -= std::chrono::minutes(this->offset);
+        return tp;
+    }
+
+    operator std::time_t() const
+    {
+        return std::chrono::system_clock::to_time_t(
+                std::chrono::system_clock::time_point(*this));
+    }
+
+    offset_datetime() = default;
+    ~offset_datetime() = default;
+    offset_datetime(offset_datetime const&) = default;
+    offset_datetime(offset_datetime&&)      = default;
+    offset_datetime& operator=(offset_datetime const&) = default;
+    offset_datetime& operator=(offset_datetime&&)      = default;
+
+  private:
+
+    static time_offset get_local_offset()
+    {
+         // get current timezone
+        const auto tmp1 = std::time(nullptr);
+        const auto t    = detail::localtime_s(&tmp1);
+
+        std::array<char, 6> buf;
+        const auto result = std::strftime(buf.data(), 6, "%z", &t); // +hhmm\0
+        if(result != 5)
+        {
+            throw std::runtime_error("toml::offset_datetime: cannot obtain "
+                                     "timezone information of current env");
+        }
+        const int ofs = std::atoi(buf.data());
+        const int ofs_h = ofs / 100;
+        const int ofs_m = ofs - (ofs_h * 100);
+        return time_offset(ofs_h, ofs_m);
+    }
+};
+
+inline bool operator==(const offset_datetime& lhs, const offset_datetime& rhs)
+{
+    return std::make_tuple(lhs.date, lhs.time, lhs.offset) ==
+           std::make_tuple(rhs.date, rhs.time, rhs.offset);
+}
+inline bool operator!=(const offset_datetime& lhs, const offset_datetime& rhs)
+{
+    return !(lhs == rhs);
+}
+inline bool operator< (const offset_datetime& lhs, const offset_datetime& rhs)
+{
+    return std::make_tuple(lhs.date, lhs.time, lhs.offset) <
+           std::make_tuple(rhs.date, rhs.time, rhs.offset);
+}
+inline bool operator<=(const offset_datetime& lhs, const offset_datetime& rhs)
+{
+    return (lhs < rhs) || (lhs == rhs);
+}
+inline bool operator> (const offset_datetime& lhs, const offset_datetime& rhs)
+{
+    return !(lhs <= rhs);
+}
+inline bool operator>=(const offset_datetime& lhs, const offset_datetime& rhs)
+{
+    return !(lhs < rhs);
+}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const offset_datetime& dt)
+{
+    os << dt.date << 'T' << dt.time << dt.offset;
+    return os;
+}
+
+}//toml
+#endif// TOML11_DATETIME
diff --git a/external/toml11/toml/exception.hpp b/external/toml11/toml/exception.hpp
new file mode 100644
index 00000000..1b0005e6
--- /dev/null
+++ b/external/toml11/toml/exception.hpp
@@ -0,0 +1,64 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_EXCEPTION_HPP
+#define TOML11_EXCEPTION_HPP
+#include "source_location.hpp"
+#include <stdexcept>
+#include <string>
+
+namespace toml
+{
+
+struct exception : public std::exception
+{
+  public:
+    exception(const source_location& loc): loc_(loc) {}
+    virtual ~exception() noexcept override = default;
+    virtual const char* what() const noexcept override {return "";}
+    virtual source_location const& location() const noexcept {return loc_;}
+
+  protected:
+    source_location loc_;
+};
+
+struct syntax_error : public toml::exception
+{
+  public:
+    explicit syntax_error(const std::string& what_arg, const source_location& loc)
+        : exception(loc), what_(what_arg)
+    {}
+    virtual ~syntax_error() noexcept override = default;
+    virtual const char* what() const noexcept override {return what_.c_str();}
+
+  protected:
+    std::string what_;
+};
+
+struct type_error : public toml::exception
+{
+  public:
+    explicit type_error(const std::string& what_arg, const source_location& loc)
+        : exception(loc), what_(what_arg)
+    {}
+    virtual ~type_error() noexcept override = default;
+    virtual const char* what() const noexcept override {return what_.c_str();}
+
+  protected:
+    std::string what_;
+};
+
+struct internal_error : public toml::exception
+{
+  public:
+    explicit internal_error(const std::string& what_arg, const source_location& loc)
+        : exception(loc), what_(what_arg)
+    {}
+    virtual ~internal_error() noexcept override = default;
+    virtual const char* what() const noexcept override {return what_.c_str();}
+
+  protected:
+    std::string what_;
+};
+
+} // toml
+#endif // TOML_EXCEPTION
diff --git a/external/toml11/toml/from.hpp b/external/toml11/toml/from.hpp
new file mode 100644
index 00000000..8251973a
--- /dev/null
+++ b/external/toml11/toml/from.hpp
@@ -0,0 +1,20 @@
+//     Copyright Toru Niina 2019.
+// Distributed under the MIT License.
+#ifndef TOML11_FROM_HPP
+#define TOML11_FROM_HPP
+#include "traits.hpp"
+
+namespace toml
+{
+
+template<typename T>
+struct from;
+// {
+//     static T from_toml(const toml::value& v)
+//     {
+//         // User-defined conversions ...
+//     }
+// };
+
+} // toml
+#endif // TOML11_FROM_HPP
diff --git a/external/toml11/toml/get.hpp b/external/toml11/toml/get.hpp
new file mode 100644
index 00000000..2973e35e
--- /dev/null
+++ b/external/toml11/toml/get.hpp
@@ -0,0 +1,916 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_GET_HPP
+#define TOML11_GET_HPP
+#include "from.hpp"
+#include "result.hpp"
+#include "value.hpp"
+#include <algorithm>
+
+namespace toml
+{
+
+// ============================================================================
+// exact toml::* type
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> &
+get(basic_value<C, M, V>& v)
+{
+    return v.template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>();
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const&
+get(const basic_value<C, M, V>& v)
+{
+    return v.template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>();
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>
+get(basic_value<C, M, V>&& v)
+{
+    return T(std::move(v).template cast<detail::type_to_enum<T, basic_value<C, M, V>>::value>());
+}
+
+// ============================================================================
+// T == toml::value; identity transformation.
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T>&
+get(basic_value<C, M, V>& v)
+{
+    return v;
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T> const&
+get(const basic_value<C, M, V>& v)
+{
+    return v;
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<std::is_same<T, basic_value<C, M, V>>::value, T>
+get(basic_value<C, M, V>&& v)
+{
+    return basic_value<C, M, V>(std::move(v));
+}
+
+// ============================================================================
+// T == toml::basic_value<C2, M2, V2>; basic_value -> basic_value
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<detail::conjunction<detail::is_basic_value<T>,
+    detail::negation<std::is_same<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    return T(v);
+}
+
+// ============================================================================
+// integer convertible from toml::Integer
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<detail::conjunction<
+    std::is_integral<T>,                            // T is integral
+    detail::negation<std::is_same<T, bool>>,        // but not bool
+    detail::negation<                               // but not toml::integer
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    return static_cast<T>(v.as_integer());
+}
+
+// ============================================================================
+// floating point convertible from toml::Float
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<detail::conjunction<
+    std::is_floating_point<T>,                      // T is floating_point
+    detail::negation<                               // but not toml::floating
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    return static_cast<T>(v.as_floating());
+}
+
+// ============================================================================
+// std::string; toml uses its own toml::string, but it should be convertible to
+// std::string seamlessly
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
+get(basic_value<C, M, V>& v)
+{
+    return v.as_string().str;
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
+get(const basic_value<C, M, V>& v)
+{
+    return v.as_string().str;
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<std::is_same<T, std::string>::value, std::string>
+get(basic_value<C, M, V>&& v)
+{
+    return std::string(std::move(v.as_string().str));
+}
+
+// ============================================================================
+// std::string_view
+
+#if __cplusplus >= 201703L
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<std::is_same<T, std::string_view>::value, std::string_view>
+get(const basic_value<C, M, V>& v)
+{
+    return std::string_view(v.as_string().str);
+}
+#endif
+
+// ============================================================================
+// std::chrono::duration from toml::local_time.
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<detail::is_chrono_duration<T>::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    return std::chrono::duration_cast<T>(
+            std::chrono::nanoseconds(v.as_local_time()));
+}
+
+// ============================================================================
+// std::chrono::system_clock::time_point from toml::datetime variants
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+inline detail::enable_if_t<
+    std::is_same<std::chrono::system_clock::time_point, T>::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    switch(v.type())
+    {
+        case value_t::local_date:
+        {
+            return std::chrono::system_clock::time_point(v.as_local_date());
+        }
+        case value_t::local_datetime:
+        {
+            return std::chrono::system_clock::time_point(v.as_local_datetime());
+        }
+        case value_t::offset_datetime:
+        {
+            return std::chrono::system_clock::time_point(v.as_offset_datetime());
+        }
+        default:
+        {
+            throw type_error(detail::format_underline("[error] toml::value "
+                "bad_cast to std::chrono::system_clock::time_point", {
+                    {std::addressof(detail::get_region(v)),
+                     concat_to_string("the actual type is ", v.type())}
+                }), v.location());
+        }
+    }
+}
+
+// ============================================================================
+// forward declaration to use this recursively. ignore this and go ahead.
+
+// array-like type with resize(N) method
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::is_container<T>,      // T is container
+    detail::has_resize_method<T>, // T::resize(N) works
+    detail::negation<             // but not toml::array
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>&);
+
+// array-like type with resize(N) method
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::is_container<T>,                        // T is container
+    detail::negation<detail::has_resize_method<T>>, // no T::resize() exists
+    detail::negation<                               // not toml::array
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>&);
+
+// std::pair<T1, T2>
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_std_pair<T>::value, T>
+get(const basic_value<C, M, V>&);
+
+// std::tuple<T1, T2, ...>
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_std_tuple<T>::value, T>
+get(const basic_value<C, M, V>&);
+
+// map-like classes
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::is_map<T>, // T is map
+    detail::negation<  // but not toml::table
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>&);
+
+// T.from_toml(v)
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::negation<                         // not a toml::* type
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>,
+    detail::has_from_toml_method<T, C, M, V>, // but has from_toml(toml::value)
+    std::is_default_constructible<T>          // and default constructible
+    >::value, T>
+get(const basic_value<C, M, V>&);
+
+// toml::from<T>::from_toml(v)
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V,
+         std::size_t S = sizeof(::toml::from<T>)>
+T get(const basic_value<C, M, V>&);
+
+// ============================================================================
+// array-like types; most likely STL container, like std::vector, etc.
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::is_container<T>,      // T is container
+    detail::has_resize_method<T>, // T::resize(N) works
+    detail::negation<             // but not toml::array
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    using value_type = typename T::value_type;
+    const auto& ar = v.as_array();
+    T container;
+    container.resize(ar.size());
+    std::transform(ar.cbegin(), ar.cend(), container.begin(),
+                   [](const value& x){return ::toml::get<value_type>(x);});
+    return container;
+}
+
+// ============================================================================
+// array-like types; but does not have resize(); most likely std::array.
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::is_container<T>,                        // T is container
+    detail::negation<detail::has_resize_method<T>>, // no T::resize() exists
+    detail::negation<                              // but not toml::array
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    using value_type = typename T::value_type;
+    const auto& ar = v.as_array();
+
+    T container;
+    if(ar.size() != container.size())
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[erorr] toml::get specified container size is ", container.size(),
+            " but there are ", ar.size(), " elements in toml array."), {
+                {std::addressof(detail::get_region(v)), "here"}
+            }));
+    }
+    std::transform(ar.cbegin(), ar.cend(), container.begin(),
+                   [](const value& x){return ::toml::get<value_type>(x);});
+    return container;
+}
+
+// ============================================================================
+// std::pair.
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_std_pair<T>::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    using first_type  = typename T::first_type;
+    using second_type = typename T::second_type;
+
+    const auto& ar = v.as_array();
+    if(ar.size() != 2)
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[erorr] toml::get specified std::pair but there are ", ar.size(),
+            " elements in toml array."), {
+                {std::addressof(detail::get_region(v)), "here"}
+            }));
+    }
+    return std::make_pair(::toml::get<first_type >(ar.at(0)),
+                          ::toml::get<second_type>(ar.at(1)));
+}
+
+// ============================================================================
+// std::tuple.
+
+namespace detail
+{
+template<typename T, typename Array, std::size_t ... I>
+T get_tuple_impl(const Array& a, index_sequence<I...>)
+{
+    return std::make_tuple(
+        ::toml::get<typename std::tuple_element<I, T>::type>(a.at(I))...);
+}
+} // detail
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_std_tuple<T>::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    const auto& ar = v.as_array();
+    if(ar.size() != std::tuple_size<T>::value)
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[erorr] toml::get specified std::tuple with ",
+            std::tuple_size<T>::value, "elements, but there are ", ar.size(),
+            " elements in toml array."), {
+                {std::addressof(detail::get_region(v)), "here"}
+            }));
+    }
+    return detail::get_tuple_impl<T>(ar,
+            detail::make_index_sequence<std::tuple_size<T>::value>{});
+}
+
+// ============================================================================
+// map-like types; most likely STL map, like std::map or std::unordered_map.
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::is_map<T>, // T is map
+    detail::negation<  // but not toml::array
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>
+    >::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    using key_type    = typename T::key_type;
+    using mapped_type = typename T::mapped_type;
+    static_assert(std::is_convertible<std::string, key_type>::value,
+                  "toml::get only supports map type of which key_type is "
+                  "convertible from std::string.");
+    T map;
+    for(const auto& kv : v.as_table())
+    {
+        map[key_type(kv.first)] = ::toml::get<mapped_type>(kv.second);
+    }
+    return map;
+}
+
+// ============================================================================
+// user-defined, but compatible types.
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::negation<                         // not a toml::* type
+        detail::is_exact_toml_type<T, basic_value<C, M, V>>>,
+    detail::has_from_toml_method<T, C, M, V>, // but has from_toml(toml::value) memfn
+    std::is_default_constructible<T>          // and default constructible
+    >::value, T>
+get(const basic_value<C, M, V>& v)
+{
+    T ud;
+    ud.from_toml(v);
+    return ud;
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V,
+         std::size_t>
+T get(const basic_value<C, M, V>& v)
+{
+    return ::toml::from<T>::from_toml(v);
+}
+
+// ============================================================================
+// find
+
+// ----------------------------------------------------------------------------
+// these overloads do not require to set T. and returns value itself.
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V> const& find(const basic_value<C, M, V>& v, const key& ky)
+{
+    const auto& tab = v.as_table();
+    if(tab.count(ky) == 0)
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[error] key \"", ky, "\" not found"), {
+                {std::addressof(detail::get_region(v)), "in this table"}
+            }));
+    }
+    return tab.at(ky);
+}
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V>& find(basic_value<C, M, V>& v, const key& ky)
+{
+    auto& tab = v.as_table();
+    if(tab.count(ky) == 0)
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[error] key \"", ky, "\" not found"), {
+                {std::addressof(detail::get_region(v)), "in this table"}
+            }));
+    }
+    return tab.at(ky);
+}
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V> find(basic_value<C, M, V>&& v, const key& ky)
+{
+    typename basic_value<C, M, V>::table_type tab = std::move(v).as_table();
+    if(tab.count(ky) == 0)
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[error] key \"", ky, "\" not found"), {
+                {std::addressof(detail::get_region(v)), "in this table"}
+            }));
+    }
+    return basic_value<C, M, V>(std::move(tab.at(ky)));
+}
+
+// ----------------------------------------------------------------------------
+// find<T>(value, key);
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+decltype(::toml::get<T>(std::declval<basic_value<C, M, V> const&>()))
+find(const basic_value<C, M, V>& v, const key& ky)
+{
+    const auto& tab = v.as_table();
+    if(tab.count(ky) == 0)
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[error] key \"", ky, "\" not found"), {
+                {std::addressof(detail::get_region(v)), "in this table"}
+            }));
+    }
+    return ::toml::get<T>(tab.at(ky));
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
+find(basic_value<C, M, V>& v, const key& ky)
+{
+    auto& tab = v.as_table();
+    if(tab.count(ky) == 0)
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[error] key \"", ky, "\" not found"), {
+                {std::addressof(detail::get_region(v)), "in this table"}
+            }));
+    }
+    return ::toml::get<T>(tab.at(ky));
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
+find(basic_value<C, M, V>&& v, const key& ky)
+{
+    typename basic_value<C, M, V>::table_type tab = std::move(v).as_table();
+    if(tab.count(ky) == 0)
+    {
+        throw std::out_of_range(detail::format_underline(concat_to_string(
+            "[error] key \"", ky, "\" not found"), {
+                {std::addressof(detail::get_region(v)), "in this table"}
+            }));
+    }
+    return ::toml::get<T>(std::move(tab.at(ky)));
+}
+
+// --------------------------------------------------------------------------
+// toml::find(toml::value, toml::key, Ts&& ... keys)
+
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V,
+         typename ... Ts>
+const basic_value<C, M, V>&
+find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
+{
+    return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
+}
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V,
+         typename ... Ts>
+basic_value<C, M, V>&
+find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
+{
+    return ::toml::find(::toml::find(v, ky), std::forward<Ts>(keys)...);
+}
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V,
+         typename ... Ts>
+basic_value<C, M, V>
+find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
+{
+    return ::toml::find(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V,
+         typename ... Ts>
+decltype(::toml::get<T>(std::declval<const basic_value<C, M, V>&>()))
+find(const basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
+{
+    return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V,
+         typename ... Ts>
+decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&>()))
+find(basic_value<C, M, V>& v, const ::toml::key& ky, Ts&& ... keys)
+{
+    return ::toml::find<T>(::toml::find(v, ky), std::forward<Ts>(keys)...);
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V,
+         typename ... Ts>
+decltype(::toml::get<T>(std::declval<basic_value<C, M, V>&&>()))
+find(basic_value<C, M, V>&& v, const ::toml::key& ky, Ts&& ... keys)
+{
+    return ::toml::find<T>(::toml::find(std::move(v), ky), std::forward<Ts>(keys)...);
+}
+
+// ============================================================================
+// get_or(value, fallback)
+
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V> const&
+get_or(const basic_value<C, M, V>& v, const basic_value<C, M, V>&)
+{
+    return v;
+}
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V>&
+get_or(basic_value<C, M, V>& v, basic_value<C, M, V>&)
+{
+    return v;
+}
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V>
+get_or(basic_value<C, M, V>&& v, basic_value<C, M, V>&&)
+{
+    return v;
+}
+
+// ----------------------------------------------------------------------------
+// specialization for the exact toml types (return type becomes lvalue ref)
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<
+    detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const&
+get_or(const basic_value<C, M, V>& v, const T& opt)
+{
+    try
+    {
+        return get<detail::remove_cvref_t<T>>(v);
+    }
+    catch(...)
+    {
+        return opt;
+    }
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<
+    detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&
+get_or(basic_value<C, M, V>& v, T& opt)
+{
+    try
+    {
+        return get<detail::remove_cvref_t<T>>(v);
+    }
+    catch(...)
+    {
+        return opt;
+    }
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_exact_toml_type<detail::remove_cvref_t<T>,
+    basic_value<C, M, V>>::value, detail::remove_cvref_t<T>>
+get_or(basic_value<C, M, V>&& v, T&& opt)
+{
+    try
+    {
+        return get<detail::remove_cvref_t<T>>(std::move(v));
+    }
+    catch(...)
+    {
+        return detail::remove_cvref_t<T>(std::forward<T>(opt));
+    }
+}
+
+// ----------------------------------------------------------------------------
+// specialization for std::string (return type becomes lvalue ref)
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<std::is_same<detail::remove_cvref_t<T>, std::string>::value,
+    std::string> const&
+get_or(const basic_value<C, M, V>& v, const T& opt)
+{
+    try
+    {
+        return v.as_string().str;
+    }
+    catch(...)
+    {
+        return opt;
+    }
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
+get_or(basic_value<C, M, V>& v, T& opt)
+{
+    try
+    {
+        return v.as_string().str;
+    }
+    catch(...)
+    {
+        return opt;
+    }
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<
+    std::is_same<detail::remove_cvref_t<T>, std::string>::value, std::string>
+get_or(basic_value<C, M, V>&& v, T&& opt)
+{
+    try
+    {
+        return std::move(v.as_string().str);
+    }
+    catch(...)
+    {
+        return std::string(std::forward<T>(opt));
+    }
+}
+
+// ----------------------------------------------------------------------------
+// specialization for string literal
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::is_string_literal<
+    typename std::remove_reference<T>::type>::value, std::string>
+get_or(const basic_value<C, M, V>& v, T&& opt)
+{
+    try
+    {
+        return std::move(v.as_string().str);
+    }
+    catch(...)
+    {
+        return std::string(std::forward<T>(opt));
+    }
+}
+
+// ----------------------------------------------------------------------------
+// others (require type conversion and return type cannot be lvalue reference)
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    detail::negation<detail::is_exact_toml_type<detail::remove_cvref_t<T>,
+        basic_value<C, M, V>>>,
+    detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>,
+    detail::negation<detail::is_string_literal<
+        typename std::remove_reference<T>::type>>
+    >::value, detail::remove_cvref_t<T>>
+get_or(const basic_value<C, M, V>& v, T&& opt)
+{
+    try
+    {
+        return get<detail::remove_cvref_t<T>>(v);
+    }
+    catch(...)
+    {
+        return detail::remove_cvref_t<T>(std::forward<T>(opt));
+    }
+}
+
+// ===========================================================================
+// find_or(value, key, fallback)
+
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V> const&
+find_or(const basic_value<C, M, V>& v, const key& ky,
+        const basic_value<C, M, V>& opt)
+{
+    if(!v.is_table()) {return opt;}
+    const auto& tab = v.as_table();
+    if(tab.count(ky) == 0) {return opt;}
+    return tab.at(ky);
+}
+
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V>&
+find_or(basic_value<C, M, V>& v, const toml::key& ky, basic_value<C, M, V>& opt)
+{
+    if(!v.is_table()) {return opt;}
+    auto& tab = v.as_table();
+    if(tab.count(ky) == 0) {return opt;}
+    return tab.at(ky);
+}
+
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+basic_value<C, M, V>
+find_or(basic_value<C, M, V>&& v, const toml::key& ky, basic_value<C, M, V>&& opt)
+{
+    if(!v.is_table()) {return opt;}
+    auto tab = std::move(v).as_table();
+    if(tab.count(ky) == 0) {return opt;}
+    return basic_value<C, M, V>(std::move(tab.at(ky)));
+}
+
+// ---------------------------------------------------------------------------
+// exact types (return type can be a reference)
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<
+    detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T> const&
+find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt)
+{
+    if(!v.is_table()) {return opt;}
+    const auto& tab = v.as_table();
+    if(tab.count(ky) == 0) {return opt;}
+    return get_or(tab.at(ky), opt);
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<
+    detail::is_exact_toml_type<T, basic_value<C, M, V>>::value, T>&
+find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
+{
+    if(!v.is_table()) {return opt;}
+    auto& tab = v.as_table();
+    if(tab.count(ky) == 0) {return opt;}
+    return get_or(tab.at(ky), opt);
+}
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<
+    detail::is_exact_toml_type<T, basic_value<C, M, V>>::value,
+    detail::remove_cvref_t<T>>
+find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
+{
+    if(!v.is_table()) {return std::forward<T>(opt);}
+    auto tab = std::move(v).as_table();
+    if(tab.count(ky) == 0) {return std::forward<T>(opt);}
+    return get_or(std::move(tab.at(ky)), std::forward<T>(opt));
+}
+
+// ---------------------------------------------------------------------------
+// std::string (return type can be a reference)
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<std::is_same<T, std::string>::value, std::string> const&
+find_or(const basic_value<C, M, V>& v, const key& ky, const T& opt)
+{
+    if(!v.is_table()) {return opt;}
+    const auto& tab = v.as_table();
+    if(tab.count(ky) == 0) {return opt;}
+    return get_or(tab.at(ky), opt);
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<std::is_same<T, std::string>::value, std::string>&
+find_or(basic_value<C, M, V>& v, const toml::key& ky, T& opt)
+{
+    if(!v.is_table()) {return opt;}
+    auto& tab = v.as_table();
+    if(tab.count(ky) == 0) {return opt;}
+    return get_or(tab.at(ky), opt);
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<std::is_same<T, std::string>::value, std::string>
+find_or(basic_value<C, M, V>&& v, const toml::key& ky, T&& opt)
+{
+    if(!v.is_table()) {return std::forward<T>(opt);}
+    auto tab = std::move(v).as_table();
+    if(tab.count(ky) == 0) {return std::forward<T>(opt);}
+    return get_or(std::move(tab.at(ky)), std::forward<T>(opt));
+}
+
+// ---------------------------------------------------------------------------
+// string literal (deduced as std::string)
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<
+    detail::is_string_literal<typename std::remove_reference<T>::type>::value,
+    std::string>
+find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
+{
+    if(!v.is_table()) {return std::string(opt);}
+    const auto& tab = v.as_table();
+    if(tab.count(ky) == 0) {return std::string(opt);}
+    return get_or(tab.at(ky), std::forward<T>(opt));
+}
+
+// ---------------------------------------------------------------------------
+// others (require type conversion and return type cannot be lvalue reference)
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+detail::enable_if_t<detail::conjunction<
+    // T is not an exact toml type
+    detail::negation<detail::is_exact_toml_type<
+        detail::remove_cvref_t<T>, basic_value<C, M, V>>>,
+    // T is not std::string
+    detail::negation<std::is_same<std::string, detail::remove_cvref_t<T>>>,
+    // T is not a string literal
+    detail::negation<detail::is_string_literal<
+        typename std::remove_reference<T>::type>>
+    >::value, detail::remove_cvref_t<T>>
+find_or(const basic_value<C, M, V>& v, const toml::key& ky, T&& opt)
+{
+    if(!v.is_table()) {return std::forward<T>(opt);}
+    const auto& tab = v.as_table();
+    if(tab.count(ky) == 0) {return std::forward<T>(opt);}
+    return get_or(tab.at(ky), std::forward<T>(opt));
+}
+
+// ============================================================================
+// expect
+
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+result<T, std::string> expect(const basic_value<C, M, V>& v) noexcept
+{
+    try
+    {
+        return ok(get<T>(v));
+    }
+    catch(const std::exception& e)
+    {
+        return err(e.what());
+    }
+}
+template<typename T, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+result<T, std::string>
+expect(const basic_value<C, M, V>& v, const toml::key& k) noexcept
+{
+    try
+    {
+        return ok(find<T>(v, k));
+    }
+    catch(const std::exception& e)
+    {
+        return err(e.what());
+    }
+}
+
+} // toml
+#endif// TOML11_GET
diff --git a/external/toml11/toml/into.hpp b/external/toml11/toml/into.hpp
new file mode 100644
index 00000000..17f22488
--- /dev/null
+++ b/external/toml11/toml/into.hpp
@@ -0,0 +1,20 @@
+//     Copyright Toru Niina 2019.
+// Distributed under the MIT License.
+#ifndef TOML11_INTO_HPP
+#define TOML11_INTO_HPP
+#include "traits.hpp"
+
+namespace toml
+{
+
+template<typename T>
+struct into;
+// {
+//     static toml::value into_toml(const T& user_defined_type)
+//     {
+//         // User-defined conversions ...
+//     }
+// };
+
+} // toml
+#endif // TOML11_INTO_HPP
diff --git a/external/toml11/toml/lexer.hpp b/external/toml11/toml/lexer.hpp
new file mode 100644
index 00000000..978dc5f6
--- /dev/null
+++ b/external/toml11/toml/lexer.hpp
@@ -0,0 +1,248 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_LEXER_HPP
+#define TOML11_LEXER_HPP
+#include "combinator.hpp"
+#include <stdexcept>
+#include <istream>
+#include <sstream>
+#include <fstream>
+
+namespace toml
+{
+namespace detail
+{
+
+// these scans contents from current location in a container of char
+// and extract a region that matches their own pattern.
+// to see the implementation of each component, see combinator.hpp.
+
+using lex_wschar  = either<character<' '>, character<'\t'>>;
+using lex_ws      = repeat<lex_wschar, at_least<1>>;
+using lex_newline = either<character<'\n'>,
+                           sequence<character<'\r'>, character<'\n'>>>;
+using lex_lower   = in_range<'a', 'z'>;
+using lex_upper   = in_range<'A', 'Z'>;
+using lex_alpha   = either<lex_lower, lex_upper>;
+using lex_digit   = in_range<'0', '9'>;
+using lex_nonzero = in_range<'1', '9'>;
+using lex_oct_dig = in_range<'0', '7'>;
+using lex_bin_dig = in_range<'0', '1'>;
+using lex_hex_dig = either<lex_digit, in_range<'A', 'F'>, in_range<'a', 'f'>>;
+
+using lex_hex_prefix = sequence<character<'0'>, character<'x'>>;
+using lex_oct_prefix = sequence<character<'0'>, character<'o'>>;
+using lex_bin_prefix = sequence<character<'0'>, character<'b'>>;
+using lex_underscore = character<'_'>;
+using lex_plus       = character<'+'>;
+using lex_minus      = character<'-'>;
+using lex_sign       = either<lex_plus, lex_minus>;
+
+// digit | nonzero 1*(digit | _ digit)
+using lex_unsigned_dec_int = either<sequence<lex_nonzero, repeat<
+    either<lex_digit, sequence<lex_underscore, lex_digit>>, at_least<1>>>,
+    lex_digit>;
+// (+|-)? unsigned_dec_int
+using lex_dec_int = sequence<maybe<lex_sign>, lex_unsigned_dec_int>;
+
+// hex_prefix hex_dig *(hex_dig | _ hex_dig)
+using lex_hex_int = sequence<lex_hex_prefix, sequence<lex_hex_dig, repeat<
+    either<lex_hex_dig, sequence<lex_underscore, lex_hex_dig>>, unlimited>>>;
+// oct_prefix oct_dig *(oct_dig | _ oct_dig)
+using lex_oct_int = sequence<lex_oct_prefix, sequence<lex_oct_dig, repeat<
+    either<lex_oct_dig, sequence<lex_underscore, lex_oct_dig>>, unlimited>>>;
+// bin_prefix bin_dig *(bin_dig | _ bin_dig)
+using lex_bin_int = sequence<lex_bin_prefix, sequence<lex_bin_dig, repeat<
+    either<lex_bin_dig, sequence<lex_underscore, lex_bin_dig>>, unlimited>>>;
+
+// (dec_int | hex_int | oct_int | bin_int)
+using lex_integer = either<lex_bin_int, lex_oct_int, lex_hex_int, lex_dec_int>;
+
+// ===========================================================================
+
+using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
+using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
+using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
+
+using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
+    sequence<lex_underscore, lex_digit>>, unlimited>>;
+
+using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;
+
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+// use toml-lang/toml HEAD
+using lex_exponent_part   = sequence<either<character<'e'>, character<'E'>>,
+        maybe<lex_sign>, lex_zero_prefixable_int>;
+#else
+// strictly TOML v0.5.0
+using lex_exponent_part = sequence<either<character<'e'>, character<'E'>>,
+        lex_dec_int>;
+#endif
+
+using lex_float = either<lex_special_float,
+      sequence<lex_dec_int, either<lex_exponent_part,
+      sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;
+
+// ===========================================================================
+
+using lex_true = sequence<character<'t'>, character<'r'>,
+                          character<'u'>, character<'e'>>;
+using lex_false = sequence<character<'f'>, character<'a'>, character<'l'>,
+                           character<'s'>, character<'e'>>;
+using lex_boolean = either<lex_true, lex_false>;
+
+// ===========================================================================
+
+using lex_date_fullyear = repeat<lex_digit, exactly<4>>;
+using lex_date_month    = repeat<lex_digit, exactly<2>>;
+using lex_date_mday     = repeat<lex_digit, exactly<2>>;
+using lex_time_delim    = either<character<'T'>, character<'t'>, character<' '>>;
+using lex_time_hour     = repeat<lex_digit, exactly<2>>;
+using lex_time_minute   = repeat<lex_digit, exactly<2>>;
+using lex_time_second   = repeat<lex_digit, exactly<2>>;
+using lex_time_secfrac  = sequence<character<'.'>,
+                                   repeat<lex_digit, at_least<1>>>;
+
+using lex_time_numoffset = sequence<either<character<'+'>, character<'-'>>,
+                                    sequence<lex_time_hour, character<':'>,
+                                             lex_time_minute>>;
+using lex_time_offset = either<character<'Z'>, character<'z'>,
+                               lex_time_numoffset>;
+
+using lex_partial_time = sequence<lex_time_hour,   character<':'>,
+                                  lex_time_minute, character<':'>,
+                                  lex_time_second, maybe<lex_time_secfrac>>;
+using lex_full_date    = sequence<lex_date_fullyear, character<'-'>,
+                                  lex_date_month,    character<'-'>,
+                                  lex_date_mday>;
+using lex_full_time    = sequence<lex_partial_time, lex_time_offset>;
+
+using lex_offset_date_time = sequence<lex_full_date, lex_time_delim, lex_full_time>;
+using lex_local_date_time  = sequence<lex_full_date, lex_time_delim, lex_partial_time>;
+using lex_local_date       = lex_full_date;
+using lex_local_time       = lex_partial_time;
+
+// ===========================================================================
+
+using lex_quotation_mark  = character<'"'>;
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+using lex_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09 (tab)
+                                           in_range<0x0a, 0x1F>, // is allowed
+                                           character<0x22>, character<0x5C>,
+                                           character<0x7F>>>;
+#else
+using lex_basic_unescaped = exclude<either<in_range<0x00, 0x1F>,
+                                           character<0x22>, character<0x5C>,
+                                           character<0x7F>>>;
+
+#endif
+using lex_escape          = character<'\\'>;
+using lex_escape_unicode_short = sequence<character<'u'>,
+                                          repeat<lex_hex_dig, exactly<4>>>;
+using lex_escape_unicode_long  = sequence<character<'U'>,
+                                          repeat<lex_hex_dig, exactly<8>>>;
+using lex_escape_seq_char = either<character<'"'>, character<'\\'>,
+                                   character<'b'>, character<'f'>,
+                                   character<'n'>, character<'r'>,
+                                   character<'t'>,
+                                   lex_escape_unicode_short,
+                                   lex_escape_unicode_long
+                                   >;
+using lex_escaped      = sequence<lex_escape, lex_escape_seq_char>;
+using lex_basic_char   = either<lex_basic_unescaped, lex_escaped>;
+using lex_basic_string = sequence<lex_quotation_mark,
+                                  repeat<lex_basic_char, unlimited>,
+                                  lex_quotation_mark>;
+
+using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+using lex_ml_basic_unescaped    = exclude<either<in_range<0x00, 0x08>, // 0x09
+                                                 in_range<0x0a, 0x1F>, // is tab
+                                                 character<0x5C>,
+                                                 character<0x7F>,
+                                                 lex_ml_basic_string_delim>>;
+#else // TOML v0.5.0
+using lex_ml_basic_unescaped    = exclude<either<in_range<0x00,0x1F>,
+                                                 character<0x5C>,
+                                                 character<0x7F>,
+                                                 lex_ml_basic_string_delim>>;
+#endif
+
+using lex_ml_basic_escaped_newline = sequence<
+        lex_escape, maybe<lex_ws>, lex_newline,
+        repeat<either<lex_ws, lex_newline>, unlimited>>;
+
+using lex_ml_basic_char = either<lex_ml_basic_unescaped, lex_escaped>;
+using lex_ml_basic_body = repeat<either<lex_ml_basic_char, lex_newline,
+                                        lex_ml_basic_escaped_newline>,
+                                 unlimited>;
+using lex_ml_basic_string = sequence<lex_ml_basic_string_delim,
+                                     lex_ml_basic_body,
+                                     lex_ml_basic_string_delim>;
+
+using lex_literal_char = exclude<either<in_range<0x00, 0x08>,
+                                        in_range<0x10, 0x19>, character<0x27>>>;
+using lex_apostrophe = character<'\''>;
+using lex_literal_string = sequence<lex_apostrophe,
+                                    repeat<lex_literal_char, unlimited>,
+                                    lex_apostrophe>;
+
+using lex_ml_literal_string_delim = repeat<lex_apostrophe, exactly<3>>;
+
+using lex_ml_literal_char = exclude<either<in_range<0x00, 0x08>,
+                                           in_range<0x10, 0x1F>,
+                                           character<0x7F>,
+                                           lex_ml_literal_string_delim>>;
+using lex_ml_literal_body = repeat<either<lex_ml_literal_char, lex_newline>,
+                                   unlimited>;
+using lex_ml_literal_string = sequence<lex_ml_literal_string_delim,
+                                       lex_ml_literal_body,
+                                       lex_ml_literal_string_delim>;
+
+using lex_string = either<lex_ml_basic_string,   lex_basic_string,
+                          lex_ml_literal_string, lex_literal_string>;
+
+// ===========================================================================
+
+using lex_comment_start_symbol = character<'#'>;
+using lex_non_eol = either<character<'\t'>, exclude<in_range<0x00, 0x19>>>;
+using lex_comment = sequence<lex_comment_start_symbol,
+                             repeat<lex_non_eol, unlimited>>;
+
+using lex_dot_sep = sequence<maybe<lex_ws>, character<'.'>, maybe<lex_ws>>;
+
+using lex_unquoted_key = repeat<either<lex_alpha, lex_digit,
+                                       character<'-'>, character<'_'>>,
+                                at_least<1>>;
+using lex_quoted_key = either<lex_basic_string, lex_literal_string>;
+using lex_simple_key = either<lex_unquoted_key, lex_quoted_key>;
+using lex_dotted_key = sequence<lex_simple_key,
+                                repeat<sequence<lex_dot_sep, lex_simple_key>,
+                                       at_least<1>
+                                       >
+                                >;
+using lex_key = either<lex_dotted_key, lex_simple_key>;
+
+using lex_keyval_sep = sequence<maybe<lex_ws>,
+                                character<'='>,
+                                maybe<lex_ws>>;
+
+using lex_std_table_open  = character<'['>;
+using lex_std_table_close = character<']'>;
+using lex_std_table       = sequence<lex_std_table_open,
+                                     maybe<lex_ws>,
+                                     lex_key,
+                                     maybe<lex_ws>,
+                                     lex_std_table_close>;
+
+using lex_array_table_open  = sequence<lex_std_table_open,  lex_std_table_open>;
+using lex_array_table_close = sequence<lex_std_table_close, lex_std_table_close>;
+using lex_array_table       = sequence<lex_array_table_open,
+                                       maybe<lex_ws>,
+                                       lex_key,
+                                       maybe<lex_ws>,
+                                       lex_array_table_close>;
+
+} // detail
+} // toml
+#endif // TOML_LEXER_HPP
diff --git a/external/toml11/toml/literal.hpp b/external/toml11/toml/literal.hpp
new file mode 100644
index 00000000..14b68831
--- /dev/null
+++ b/external/toml11/toml/literal.hpp
@@ -0,0 +1,87 @@
+//     Copyright Toru Niina 2019.
+// Distributed under the MIT License.
+#ifndef TOML11_LITERAL_HPP
+#define TOML11_LITERAL_HPP
+#include "parser.hpp"
+
+namespace toml
+{
+inline namespace literals
+{
+inline namespace toml_literals
+{
+
+inline ::toml::value operator"" _toml(const char* str, std::size_t len)
+{
+    ::toml::detail::location<std::vector<char>>
+        loc(/* filename = */ std::string("TOML literal encoded in a C++ code"),
+            /* contents = */ std::vector<char>(str, str + len));
+
+    // if there are some comments or empty lines, skip them.
+    using skip_line = ::toml::detail::repeat<toml::detail::sequence<
+            ::toml::detail::maybe<::toml::detail::lex_ws>,
+            ::toml::detail::maybe<::toml::detail::lex_comment>,
+            ::toml::detail::lex_newline
+        >, ::toml::detail::at_least<1>>;
+    skip_line::invoke(loc);
+
+    // if there are some whitespaces before a value, skip them.
+    using skip_ws = ::toml::detail::repeat<
+        ::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
+    skip_ws::invoke(loc);
+
+    // to distinguish arrays and tables, first check it is a table or not.
+    //
+    // "[1,2,3]"_toml;   // this is an array
+    // "[table]"_toml;   // a table that has an empty table named "table" inside.
+    // "[[1,2,3]]"_toml; // this is an array of arrays
+    // "[[table]]"_toml; // this is a table that has an array of tables inside.
+    //
+    // "[[1]]"_toml;     // this can be both... (currently it becomes a table)
+    // "1 = [{}]"_toml;  // this is a table that has an array of table named 1.
+    // "[[1,]]"_toml;    // this is an array of arrays.
+    // "[[1],]"_toml;    // this also.
+
+    const auto the_front = loc.iter();
+
+    const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
+    loc.reset(the_front);
+
+    const bool is_aots_key  = ::toml::detail::lex_array_table::invoke(loc);
+    loc.reset(the_front);
+
+    // If it is neither a table-key or a array-of-table-key, it may be a value.
+    if(!is_table_key && !is_aots_key)
+    {
+        if(auto data = ::toml::detail::parse_value<::toml::value>(loc))
+        {
+            return data.unwrap();
+        }
+    }
+
+    // Note that still it can be a table, because the literal might be something
+    // like the following.
+    // ```cpp
+    // R"( // c++11 raw string literals
+    //   key = "value"
+    //   int = 42
+    // )"_toml;
+    // ```
+    // It is a valid toml file.
+    // It should be parsed as if we parse a file with this content.
+
+    if(auto data = ::toml::detail::parse_toml_file<::toml::value>(loc))
+    {
+        return data.unwrap();
+    }
+    else // none of them.
+    {
+        throw ::toml::syntax_error(data.unwrap_err(),
+                                   source_location(std::addressof(loc)));
+    }
+}
+
+} // toml_literals
+} // literals
+} // toml
+#endif//TOML11_LITERAL_HPP
diff --git a/external/toml11/toml/parser.hpp b/external/toml11/toml/parser.hpp
new file mode 100644
index 00000000..9fd7097b
--- /dev/null
+++ b/external/toml11/toml/parser.hpp
@@ -0,0 +1,2036 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_PARSER_HPP
+#define TOML11_PARSER_HPP
+#include "result.hpp"
+#include "region.hpp"
+#include "combinator.hpp"
+#include "lexer.hpp"
+#include "types.hpp"
+#include "value.hpp"
+#include <fstream>
+#include <sstream>
+#include <cstring>
+
+namespace toml
+{
+namespace detail
+{
+
+template<typename Container>
+result<std::pair<boolean, region<Container>>, std::string>
+parse_boolean(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_boolean::invoke(loc))
+    {
+        const auto reg = token.unwrap();
+        if     (reg.str() == "true")  {return ok(std::make_pair(true,  reg));}
+        else if(reg.str() == "false") {return ok(std::make_pair(false, reg));}
+        else // internal error.
+        {
+            throw internal_error(format_underline(
+                "[error] toml::parse_boolean: internal error",
+                {{std::addressof(reg), "invalid token"}}),
+                source_location(std::addressof(reg)));
+        }
+    }
+    loc.reset(first); //rollback
+    return err(format_underline("[error] toml::parse_boolean: ",
+               {{std::addressof(loc), "the next token is not a boolean"}}));
+}
+
+template<typename Container>
+result<std::pair<integer, region<Container>>, std::string>
+parse_binary_integer(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_bin_int::invoke(loc))
+    {
+        auto str = token.unwrap().str();
+        assert(str.size() > 2); // minimum -> 0b1
+        integer retval(0), base(1);
+        for(auto i(str.rbegin()), e(str.rend() - 2); i!=e; ++i)
+        {
+            if     (*i == '1'){retval += base; base *= 2;}
+            else if(*i == '0'){base *= 2;}
+            else if(*i == '_'){/* do nothing. */}
+            else // internal error.
+            {
+                throw internal_error(format_underline(
+                    "[error] toml::parse_integer: internal error",
+                    {{std::addressof(token.unwrap()), "invalid token"}}),
+                    source_location(std::addressof(loc)));
+            }
+        }
+        return ok(std::make_pair(retval, token.unwrap()));
+    }
+    loc.reset(first);
+    return err(format_underline("[error] toml::parse_binary_integer:",
+               {{std::addressof(loc), "the next token is not an integer"}}));
+}
+
+template<typename Container>
+result<std::pair<integer, region<Container>>, std::string>
+parse_octal_integer(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_oct_int::invoke(loc))
+    {
+        auto str = token.unwrap().str();
+        str.erase(std::remove(str.begin(), str.end(), '_'), str.end());
+        str.erase(str.begin()); str.erase(str.begin()); // remove `0o` prefix
+
+        std::istringstream iss(str);
+        integer retval(0);
+        iss >> std::oct >> retval;
+        return ok(std::make_pair(retval, token.unwrap()));
+    }
+    loc.reset(first);
+    return err(format_underline("[error] toml::parse_octal_integer:",
+               {{std::addressof(loc), "the next token is not an integer"}}));
+}
+
+template<typename Container>
+result<std::pair<integer, region<Container>>, std::string>
+parse_hexadecimal_integer(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_hex_int::invoke(loc))
+    {
+        auto str = token.unwrap().str();
+        str.erase(std::remove(str.begin(), str.end(), '_'), str.end());
+        str.erase(str.begin()); str.erase(str.begin()); // remove `0x` prefix
+
+        std::istringstream iss(str);
+        integer retval(0);
+        iss >> std::hex >> retval;
+        return ok(std::make_pair(retval, token.unwrap()));
+    }
+    loc.reset(first);
+    return err(format_underline("[error] toml::parse_hexadecimal_integer",
+               {{std::addressof(loc), "the next token is not an integer"}}));
+}
+
+template<typename Container>
+result<std::pair<integer, region<Container>>, std::string>
+parse_integer(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(first != loc.end() && *first == '0')
+    {
+        const auto second = std::next(first);
+        if(second == loc.end()) // the token is just zero.
+        {
+            return ok(std::make_pair(0, region<Container>(loc, first, second)));
+        }
+
+        if(*second == 'b') {return parse_binary_integer     (loc);} // 0b1100
+        if(*second == 'o') {return parse_octal_integer      (loc);} // 0o775
+        if(*second == 'x') {return parse_hexadecimal_integer(loc);} // 0xC0FFEE
+
+        if(std::isdigit(*second))
+        {
+            return err(format_underline("[error] toml::parse_integer: "
+                "leading zero in an Integer is not allowed.",
+                {{std::addressof(loc), "leading zero"}}));
+        }
+        else if(std::isalpha(*second))
+        {
+             return err(format_underline("[error] toml::parse_integer: "
+                "unknown integer prefix appeared.",
+                {{std::addressof(loc), "none of 0x, 0o, 0b"}}));
+        }
+    }
+
+    if(const auto token = lex_dec_int::invoke(loc))
+    {
+        auto str = token.unwrap().str();
+        str.erase(std::remove(str.begin(), str.end(), '_'), str.end());
+
+        std::istringstream iss(str);
+        integer retval(0);
+        iss >> retval;
+        return ok(std::make_pair(retval, token.unwrap()));
+    }
+    loc.reset(first);
+    return err(format_underline("[error] toml::parse_integer: ",
+               {{std::addressof(loc), "the next token is not an integer"}}));
+}
+
+template<typename Container>
+result<std::pair<floating, region<Container>>, std::string>
+parse_floating(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_float::invoke(loc))
+    {
+        auto str = token.unwrap().str();
+        if(str == "inf" || str == "+inf")
+        {
+            if(std::numeric_limits<floating>::has_infinity)
+            {
+                return ok(std::make_pair(
+                    std::numeric_limits<floating>::infinity(), token.unwrap()));
+            }
+            else
+            {
+                throw std::domain_error("toml::parse_floating: inf value found"
+                    " but the current environment does not support inf. Please"
+                    " make sure that the floating-point implementation conforms"
+                    " IEEE 754/ISO 60559 international standard.");
+            }
+        }
+        else if(str == "-inf")
+        {
+            if(std::numeric_limits<floating>::has_infinity)
+            {
+                return ok(std::make_pair(
+                    -std::numeric_limits<floating>::infinity(), token.unwrap()));
+            }
+            else
+            {
+                throw std::domain_error("toml::parse_floating: inf value found"
+                    " but the current environment does not support inf. Please"
+                    " make sure that the floating-point implementation conforms"
+                    " IEEE 754/ISO 60559 international standard.");
+            }
+        }
+        else if(str == "nan" || str == "+nan")
+        {
+            if(std::numeric_limits<floating>::has_quiet_NaN)
+            {
+                return ok(std::make_pair(
+                    std::numeric_limits<floating>::quiet_NaN(), token.unwrap()));
+            }
+            else if(std::numeric_limits<floating>::has_signaling_NaN)
+            {
+                return ok(std::make_pair(
+                    std::numeric_limits<floating>::signaling_NaN(), token.unwrap()));
+            }
+            else
+            {
+                throw std::domain_error("toml::parse_floating: NaN value found"
+                    " but the current environment does not support NaN. Please"
+                    " make sure that the floating-point implementation conforms"
+                    " IEEE 754/ISO 60559 international standard.");
+            }
+        }
+        else if(str == "-nan")
+        {
+            if(std::numeric_limits<floating>::has_quiet_NaN)
+            {
+                return ok(std::make_pair(
+                    -std::numeric_limits<floating>::quiet_NaN(), token.unwrap()));
+            }
+            else if(std::numeric_limits<floating>::has_signaling_NaN)
+            {
+                return ok(std::make_pair(
+                    -std::numeric_limits<floating>::signaling_NaN(), token.unwrap()));
+            }
+            else
+            {
+                throw std::domain_error("toml::parse_floating: NaN value found"
+                    " but the current environment does not support NaN. Please"
+                    " make sure that the floating-point implementation conforms"
+                    " IEEE 754/ISO 60559 international standard.");
+            }
+        }
+        str.erase(std::remove(str.begin(), str.end(), '_'), str.end());
+        std::istringstream iss(str);
+        floating v(0.0);
+        iss >> v;
+        return ok(std::make_pair(v, token.unwrap()));
+    }
+    loc.reset(first);
+    return err(format_underline("[error] toml::parse_floating: ",
+               {{std::addressof(loc), "the next token is not a float"}}));
+}
+
+template<typename Container, typename Container2>
+std::string read_utf8_codepoint(const region<Container>& reg,
+              /* for err msg */ const location<Container2>& loc)
+{
+    const auto str = reg.str().substr(1);
+    std::uint_least32_t codepoint;
+    std::istringstream iss(str);
+    iss >> std::hex >> codepoint;
+
+    const auto to_char = [](const int i) noexcept -> char {
+        const auto uc = static_cast<unsigned char>(i);
+        return *reinterpret_cast<const char*>(std::addressof(uc));
+    };
+
+    std::string character;
+    if(codepoint < 0x80) // U+0000 ... U+0079 ; just an ASCII.
+    {
+        character += static_cast<char>(codepoint);
+    }
+    else if(codepoint < 0x800) //U+0080 ... U+07FF
+    {
+        // 110yyyyx 10xxxxxx; 0x3f == 0b0011'1111
+        character += to_char(0xC0| codepoint >> 6);
+        character += to_char(0x80|(codepoint & 0x3F));
+    }
+    else if(codepoint < 0x10000) // U+0800...U+FFFF
+    {
+        if(0xD800 <= codepoint && codepoint <= 0xDFFF)
+        {
+            throw syntax_error(format_underline("[error] "
+                "toml::read_utf8_codepoint: codepoints in the range "
+                "[0xD800, 0xDFFF] are not valid UTF-8.", {{
+                    std::addressof(loc), "not a valid UTF-8 codepoint"
+                }}), source_location(std::addressof(loc)));
+        }
+        assert(codepoint < 0xD800 || 0xDFFF < codepoint);
+        // 1110yyyy 10yxxxxx 10xxxxxx
+        character += to_char(0xE0| codepoint >> 12);
+        character += to_char(0x80|(codepoint >> 6 & 0x3F));
+        character += to_char(0x80|(codepoint      & 0x3F));
+    }
+    else if(codepoint < 0x110000) // U+010000 ... U+10FFFF
+    {
+        // 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx
+        character += to_char(0xF0| codepoint >> 18);
+        character += to_char(0x80|(codepoint >> 12 & 0x3F));
+        character += to_char(0x80|(codepoint >> 6  & 0x3F));
+        character += to_char(0x80|(codepoint       & 0x3F));
+    }
+    else // out of UTF-8 region
+    {
+        throw syntax_error(format_underline("[error] toml::read_utf8_codepoint:"
+            " input codepoint is too large.",
+            {{std::addressof(loc), "should be in [0x00..0x10FFFF]"}}),
+            source_location(std::addressof(loc)));
+    }
+    return character;
+}
+
+template<typename Container>
+result<std::string, std::string> parse_escape_sequence(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(first == loc.end() || *first != '\\')
+    {
+        return err(format_underline("[error]: toml::parse_escape_sequence: ", {{
+            std::addressof(loc), "the next token is not a backslash \"\\\""}}));
+    }
+    loc.advance();
+    switch(*loc.iter())
+    {
+        case '\\':{loc.advance(); return ok(std::string("\\"));}
+        case '"' :{loc.advance(); return ok(std::string("\""));}
+        case 'b' :{loc.advance(); return ok(std::string("\b"));}
+        case 't' :{loc.advance(); return ok(std::string("\t"));}
+        case 'n' :{loc.advance(); return ok(std::string("\n"));}
+        case 'f' :{loc.advance(); return ok(std::string("\f"));}
+        case 'r' :{loc.advance(); return ok(std::string("\r"));}
+        case 'u' :
+        {
+            if(const auto token = lex_escape_unicode_short::invoke(loc))
+            {
+                return ok(read_utf8_codepoint(token.unwrap(), loc));
+            }
+            else
+            {
+                return err(format_underline("[error] parse_escape_sequence: "
+                           "invalid token found in UTF-8 codepoint uXXXX.",
+                           {{std::addressof(loc), "here"}}));
+            }
+        }
+        case 'U':
+        {
+            if(const auto token = lex_escape_unicode_long::invoke(loc))
+            {
+                return ok(read_utf8_codepoint(token.unwrap(), loc));
+            }
+            else
+            {
+                return err(format_underline("[error] parse_escape_sequence: "
+                           "invalid token found in UTF-8 codepoint Uxxxxxxxx",
+                           {{std::addressof(loc), "here"}}));
+            }
+        }
+    }
+
+    const auto msg = format_underline("[error] parse_escape_sequence: "
+           "unknown escape sequence appeared.", {{std::addressof(loc),
+           "escape sequence is one of \\, \", b, t, n, f, r, uxxxx, Uxxxxxxxx"}},
+           /* Hints = */{"if you want to write backslash as just one backslash, "
+           "use literal string like: regex    = '<\\i\\c*\\s*>'"});
+    loc.reset(first);
+    return err(msg);
+}
+
+template<typename Container>
+result<std::pair<toml::string, region<Container>>, std::string>
+parse_ml_basic_string(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_ml_basic_string::invoke(loc))
+    {
+        auto inner_loc = loc;
+        inner_loc.reset(first);
+
+        std::string retval;
+        retval.reserve(token.unwrap().size());
+
+        auto delim = lex_ml_basic_string_delim::invoke(inner_loc);
+        if(!delim)
+        {
+            throw internal_error(format_underline("[error] "
+                "parse_ml_basic_string: invalid token",
+                {{std::addressof(inner_loc), "should be \"\"\""}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        // immediate newline is ignored (if exists)
+        /* discard return value */ lex_newline::invoke(inner_loc);
+
+        delim = none();
+        while(!delim)
+        {
+            using lex_unescaped_seq = repeat<
+                either<lex_ml_basic_unescaped, lex_newline>, unlimited>;
+            if(auto unescaped = lex_unescaped_seq::invoke(inner_loc))
+            {
+                retval += unescaped.unwrap().str();
+            }
+            if(auto escaped = parse_escape_sequence(inner_loc))
+            {
+                retval += escaped.unwrap();
+            }
+            if(auto esc_nl = lex_ml_basic_escaped_newline::invoke(inner_loc))
+            {
+                // ignore newline after escape until next non-ws char
+            }
+            if(inner_loc.iter() == inner_loc.end())
+            {
+                throw internal_error(format_underline("[error] "
+                    "parse_ml_basic_string: unexpected end of region",
+                    {{std::addressof(inner_loc), "not sufficient token"}}),
+                    source_location(std::addressof(inner_loc)));
+            }
+            delim = lex_ml_basic_string_delim::invoke(inner_loc);
+        }
+        return ok(std::make_pair(toml::string(retval), token.unwrap()));
+    }
+    else
+    {
+        loc.reset(first);
+        return err(format_underline("[error] toml::parse_ml_basic_string: "
+                   "the next token is not a valid multiline string",
+                   {{std::addressof(loc), "here"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<toml::string, region<Container>>, std::string>
+parse_basic_string(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_basic_string::invoke(loc))
+    {
+        auto inner_loc = loc;
+        inner_loc.reset(first);
+
+        auto quot = lex_quotation_mark::invoke(inner_loc);
+        if(!quot)
+        {
+            throw internal_error(format_underline("[error] parse_basic_string: "
+                "invalid token", {{std::addressof(inner_loc), "should be \""}}),
+                source_location(std::addressof(inner_loc)));
+        }
+
+        std::string retval;
+        retval.reserve(token.unwrap().size());
+
+        quot = none();
+        while(!quot)
+        {
+            using lex_unescaped_seq = repeat<lex_basic_unescaped, unlimited>;
+            if(auto unescaped = lex_unescaped_seq::invoke(inner_loc))
+            {
+                retval += unescaped.unwrap().str();
+            }
+            if(auto escaped = parse_escape_sequence(inner_loc))
+            {
+                retval += escaped.unwrap();
+            }
+            if(inner_loc.iter() == inner_loc.end())
+            {
+                throw internal_error(format_underline("[error] "
+                    "parse_basic_string: unexpected end of region",
+                    {{std::addressof(inner_loc), "not sufficient token"}}),
+                    source_location(std::addressof(inner_loc)));
+            }
+            quot = lex_quotation_mark::invoke(inner_loc);
+        }
+        return ok(std::make_pair(toml::string(retval), token.unwrap()));
+    }
+    else
+    {
+        loc.reset(first); // rollback
+        return err(format_underline("[error] toml::parse_basic_string: "
+                   "the next token is not a valid string",
+                   {{std::addressof(loc), "here"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<toml::string, region<Container>>, std::string>
+parse_ml_literal_string(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_ml_literal_string::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+
+        const auto open = lex_ml_literal_string_delim::invoke(inner_loc);
+        if(!open)
+        {
+            throw internal_error(format_underline("[error] "
+                "parse_ml_literal_string: invalid token",
+                {{std::addressof(inner_loc), "should be '''"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        // immediate newline is ignored (if exists)
+        /* discard return value */ lex_newline::invoke(inner_loc);
+
+        const auto body = lex_ml_literal_body::invoke(inner_loc);
+
+        const auto close = lex_ml_literal_string_delim::invoke(inner_loc);
+        if(!close)
+        {
+            throw internal_error(format_underline("[error] "
+                "parse_ml_literal_string: invalid token",
+                {{std::addressof(inner_loc), "should be '''"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        return ok(std::make_pair(
+                  toml::string(body.unwrap().str(), toml::string_t::literal),
+                  token.unwrap()));
+    }
+    else
+    {
+        loc.reset(first); // rollback
+        return err(format_underline("[error] toml::parse_ml_literal_string: "
+                   "the next token is not a valid multiline literal string",
+                   {{std::addressof(loc), "here"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<toml::string, region<Container>>, std::string>
+parse_literal_string(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_literal_string::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+
+        const auto open = lex_apostrophe::invoke(inner_loc);
+        if(!open)
+        {
+            throw internal_error(format_underline("[error] "
+                "parse_literal_string: invalid token",
+                {{std::addressof(inner_loc), "should be '"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+
+        const auto body = repeat<lex_literal_char, unlimited>::invoke(inner_loc);
+
+        const auto close = lex_apostrophe::invoke(inner_loc);
+        if(!close)
+        {
+            throw internal_error(format_underline("[error] "
+                "parse_literal_string: invalid token",
+                {{std::addressof(inner_loc), "should be '"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        return ok(std::make_pair(
+                  toml::string(body.unwrap().str(), toml::string_t::literal),
+                  token.unwrap()));
+    }
+    else
+    {
+        loc.reset(first); // rollback
+        return err(format_underline("[error] toml::parse_literal_string: "
+                   "the next token is not a valid literal string",
+                   {{std::addressof(loc), "here"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<toml::string, region<Container>>, std::string>
+parse_string(location<Container>& loc)
+{
+    if(loc.iter() != loc.end() && *(loc.iter()) == '"')
+    {
+        if(loc.iter() + 1 != loc.end() && *(loc.iter() + 1) == '"' &&
+           loc.iter() + 2 != loc.end() && *(loc.iter() + 2) == '"')
+        {
+            return parse_ml_basic_string(loc);
+        }
+        else
+        {
+            return parse_basic_string(loc);
+        }
+    }
+    else if(loc.iter() != loc.end() && *(loc.iter()) == '\'')
+    {
+        if(loc.iter() + 1 != loc.end() && *(loc.iter() + 1) == '\'' &&
+           loc.iter() + 2 != loc.end() && *(loc.iter() + 2) == '\'')
+        {
+            return parse_ml_literal_string(loc);
+        }
+        else
+        {
+            return parse_literal_string(loc);
+        }
+    }
+    return err(format_underline("[error] toml::parse_string: ",
+                {{std::addressof(loc), "the next token is not a string"}}));
+}
+
+template<typename Container>
+result<std::pair<local_date, region<Container>>, std::string>
+parse_local_date(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_local_date::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+
+        const auto y = lex_date_fullyear::invoke(inner_loc);
+        if(!y || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-')
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_inner_local_date: invalid year format",
+                {{std::addressof(inner_loc), "should be `-`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        inner_loc.advance();
+        const auto m = lex_date_month::invoke(inner_loc);
+        if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != '-')
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_local_date: invalid month format",
+                {{std::addressof(inner_loc), "should be `-`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        inner_loc.advance();
+        const auto d = lex_date_mday::invoke(inner_loc);
+        if(!d)
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_local_date: invalid day format",
+                {{std::addressof(inner_loc), "here"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        return ok(std::make_pair(local_date(
+            static_cast<std::int16_t>(from_string<int>(y.unwrap().str(), 0)),
+            static_cast<month_t>(
+                static_cast<std::int8_t>(from_string<int>(m.unwrap().str(), 0)-1)),
+            static_cast<std::int8_t>(from_string<int>(d.unwrap().str(), 0))),
+            token.unwrap()));
+    }
+    else
+    {
+        loc.reset(first);
+        return err(format_underline("[error]: toml::parse_local_date: ",
+            {{std::addressof(loc), "the next token is not a local_date"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<local_time, region<Container>>, std::string>
+parse_local_time(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_local_time::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+
+        const auto h = lex_time_hour::invoke(inner_loc);
+        if(!h || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':')
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_local_time: invalid year format",
+                {{std::addressof(inner_loc), "should be `:`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        inner_loc.advance();
+        const auto m = lex_time_minute::invoke(inner_loc);
+        if(!m || inner_loc.iter() == inner_loc.end() || *inner_loc.iter() != ':')
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_local_time: invalid month format",
+                {{std::addressof(inner_loc), "should be `:`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        inner_loc.advance();
+        const auto s = lex_time_second::invoke(inner_loc);
+        if(!s)
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_local_time: invalid second format",
+                {{std::addressof(inner_loc), "here"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        local_time time(
+            from_string<int>(h.unwrap().str(), 0),
+            from_string<int>(m.unwrap().str(), 0),
+            from_string<int>(s.unwrap().str(), 0), 0, 0);
+
+        const auto before_secfrac = inner_loc.iter();
+        if(const auto secfrac = lex_time_secfrac::invoke(inner_loc))
+        {
+            auto sf = secfrac.unwrap().str();
+            sf.erase(sf.begin()); // sf.front() == '.'
+            switch(sf.size() % 3)
+            {
+                case 2:  sf += '0';  break;
+                case 1:  sf += "00"; break;
+                case 0:  break;
+                default: break;
+            }
+            if(sf.size() >= 6)
+            {
+                time.millisecond = from_string<std::uint16_t>(sf.substr(0, 3), 0u);
+                time.microsecond = from_string<std::uint16_t>(sf.substr(3, 3), 0u);
+            }
+            else if(sf.size() >= 3)
+            {
+                time.millisecond = from_string<std::uint16_t>(sf, 0u);
+                time.microsecond = 0u;
+            }
+        }
+        else
+        {
+            if(before_secfrac != inner_loc.iter())
+            {
+                throw internal_error(format_underline("[error]: "
+                    "toml::parse_local_time: invalid subsecond format",
+                    {{std::addressof(inner_loc), "here"}}),
+                source_location(std::addressof(inner_loc)));
+            }
+        }
+        return ok(std::make_pair(time, token.unwrap()));
+    }
+    else
+    {
+        loc.reset(first);
+        return err(format_underline("[error]: toml::parse_local_time: ",
+            {{std::addressof(loc), "the next token is not a local_time"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<local_datetime, region<Container>>, std::string>
+parse_local_datetime(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_local_date_time::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+        const auto date = parse_local_date(inner_loc);
+        if(!date || inner_loc.iter() == inner_loc.end())
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_local_datetime: invalid datetime format",
+                {{std::addressof(inner_loc), "date, not datetime"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        const char delim = *(inner_loc.iter());
+        if(delim != 'T' && delim != 't' && delim != ' ')
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_local_datetime: invalid datetime format",
+                {{std::addressof(inner_loc), "should be `T` or ` ` (space)"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        inner_loc.advance();
+        const auto time = parse_local_time(inner_loc);
+        if(!time)
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_local_datetime: invalid datetime format",
+                {{std::addressof(inner_loc), "invalid time fomrat"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        return ok(std::make_pair(
+            local_datetime(date.unwrap().first, time.unwrap().first),
+            token.unwrap()));
+    }
+    else
+    {
+        loc.reset(first);
+        return err(format_underline("[error]: toml::parse_local_datetime: ",
+            {{std::addressof(loc), "the next token is not a local_datetime"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<offset_datetime, region<Container>>, std::string>
+parse_offset_datetime(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    if(const auto token = lex_offset_date_time::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+        const auto datetime = parse_local_datetime(inner_loc);
+        if(!datetime || inner_loc.iter() == inner_loc.end())
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_offset_datetime: invalid datetime format",
+                {{std::addressof(inner_loc), "date, not datetime"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        time_offset offset(0, 0);
+        if(const auto ofs = lex_time_numoffset::invoke(inner_loc))
+        {
+            const auto str = ofs.unwrap().str();
+            if(str.front() == '+')
+            {
+                offset.hour   = static_cast<std::int8_t>(from_string<int>(str.substr(1,2), 0));
+                offset.minute = static_cast<std::int8_t>(from_string<int>(str.substr(4,2), 0));
+            }
+            else
+            {
+                offset.hour   = -static_cast<std::int8_t>(from_string<int>(str.substr(1,2), 0));
+                offset.minute = -static_cast<std::int8_t>(from_string<int>(str.substr(4,2), 0));
+            }
+        }
+        else if(*inner_loc.iter() != 'Z' && *inner_loc.iter() != 'z')
+        {
+            throw internal_error(format_underline("[error]: "
+                "toml::parse_offset_datetime: invalid datetime format",
+                {{std::addressof(inner_loc), "should be `Z` or `+HH:MM`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        return ok(std::make_pair(offset_datetime(datetime.unwrap().first, offset),
+                                 token.unwrap()));
+    }
+    else
+    {
+        loc.reset(first);
+        return err(format_underline("[error]: toml::parse_offset_datetime: ",
+            {{std::addressof(loc), "the next token is not a offset_datetime"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<key, region<Container>>, std::string>
+parse_simple_key(location<Container>& loc)
+{
+    if(const auto bstr = parse_basic_string(loc))
+    {
+        return ok(std::make_pair(bstr.unwrap().first.str, bstr.unwrap().second));
+    }
+    if(const auto lstr = parse_literal_string(loc))
+    {
+        return ok(std::make_pair(lstr.unwrap().first.str, lstr.unwrap().second));
+    }
+    if(const auto bare = lex_unquoted_key::invoke(loc))
+    {
+        const auto reg = bare.unwrap();
+        return ok(std::make_pair(reg.str(), reg));
+    }
+    return err(format_underline("[error] toml::parse_simple_key: ",
+            {{std::addressof(loc), "the next token is not a simple key"}}));
+}
+
+// dotted key become vector of keys
+template<typename Container>
+result<std::pair<std::vector<key>, region<Container>>, std::string>
+parse_key(location<Container>& loc)
+{
+    const auto first = loc.iter();
+    // dotted key -> foo.bar.baz whitespaces are allowed
+    if(const auto token = lex_dotted_key::invoke(loc))
+    {
+        const auto reg = token.unwrap();
+        location<std::string> inner_loc(loc.name(), reg.str());
+        std::vector<key> keys;
+
+        while(inner_loc.iter() != inner_loc.end())
+        {
+            lex_ws::invoke(inner_loc);
+            if(const auto k = parse_simple_key(inner_loc))
+            {
+                keys.push_back(k.unwrap().first);
+            }
+            else
+            {
+                throw internal_error(format_underline("[error] "
+                    "toml::detail::parse_key: dotted key contains invalid key",
+                    {{std::addressof(inner_loc), k.unwrap_err()}}),
+                    source_location(std::addressof(inner_loc)));
+            }
+
+            lex_ws::invoke(inner_loc);
+            if(inner_loc.iter() == inner_loc.end())
+            {
+                break;
+            }
+            else if(*inner_loc.iter() == '.')
+            {
+                inner_loc.advance(); // to skip `.`
+            }
+            else
+            {
+                throw internal_error(format_underline("[error] toml::parse_key: "
+                    "dotted key contains invalid key ",
+                    {{std::addressof(inner_loc), "should be `.`"}}),
+                    source_location(std::addressof(inner_loc)));
+            }
+        }
+        return ok(std::make_pair(keys, reg));
+    }
+    loc.reset(first);
+
+    // simple key -> foo
+    if(const auto smpl = parse_simple_key(loc))
+    {
+        return ok(std::make_pair(std::vector<key>(1, smpl.unwrap().first),
+                                 smpl.unwrap().second));
+    }
+    return err(format_underline("[error] toml::parse_key: ",
+                {{std::addressof(loc), "is not a valid key"}}));
+}
+
+// forward-decl to implement parse_array and parse_table
+template<typename Value, typename Container>
+result<Value, std::string> parse_value(location<Container>&);
+
+template<typename Value, typename Container>
+result<std::pair<typename Value::array_type, region<Container>>, std::string>
+parse_array(location<Container>& loc)
+{
+    using value_type = Value;
+    using array_type = typename value_type::array_type;
+
+    const auto first = loc.iter();
+    if(loc.iter() == loc.end())
+    {
+        return err("[error] toml::parse_array: input is empty");
+    }
+    if(*loc.iter() != '[')
+    {
+        return err("[error] toml::parse_array: token is not an array");
+    }
+    loc.advance();
+
+    using lex_ws_comment_newline = repeat<
+        either<lex_wschar, lex_newline, lex_comment>, unlimited>;
+
+    array_type retval;
+    while(loc.iter() != loc.end())
+    {
+        lex_ws_comment_newline::invoke(loc); // skip
+
+        if(loc.iter() != loc.end() && *loc.iter() == ']')
+        {
+            loc.advance(); // skip ']'
+            return ok(std::make_pair(retval,
+                      region<Container>(loc, first, loc.iter())));
+        }
+
+        if(auto val = parse_value<value_type>(loc))
+        {
+            if(!retval.empty() && retval.front().type() != val.as_ok().type())
+            {
+                auto array_start_loc = loc;
+                array_start_loc.reset(first);
+
+                throw syntax_error(format_underline("[error] toml::parse_array: "
+                    "type of elements should be the same each other.", {
+                        {std::addressof(array_start_loc), "array starts here"},
+                        {
+                            std::addressof(get_region(retval.front())),
+                            "value has type " + stringize(retval.front().type())
+                        },
+                        {
+                            std::addressof(get_region(val.unwrap())),
+                            "value has different type, " + stringize(val.unwrap().type())
+                        }
+                    }), source_location(std::addressof(loc)));
+            }
+            retval.push_back(std::move(val.unwrap()));
+        }
+        else
+        {
+            auto array_start_loc = loc;
+            array_start_loc.reset(first);
+
+            throw syntax_error(format_underline("[error] toml::parse_array: "
+                "value having invalid format appeared in an array", {
+                    {std::addressof(array_start_loc), "array starts here"},
+                    {std::addressof(loc), "it is not a valid value."}
+                }), source_location(std::addressof(loc)));
+        }
+
+        using lex_array_separator = sequence<maybe<lex_ws>, character<','>>;
+        const auto sp = lex_array_separator::invoke(loc);
+        if(!sp)
+        {
+            lex_ws_comment_newline::invoke(loc);
+            if(loc.iter() != loc.end() && *loc.iter() == ']')
+            {
+                loc.advance(); // skip ']'
+                return ok(std::make_pair(retval,
+                          region<Container>(loc, first, loc.iter())));
+            }
+            else
+            {
+                auto array_start_loc = loc;
+                array_start_loc.reset(first);
+
+                throw syntax_error(format_underline("[error] toml::parse_array:"
+                    " missing array separator `,` after a value", {
+                        {std::addressof(array_start_loc), "array starts here"},
+                        {std::addressof(loc),             "should be `,`"}
+                    }), source_location(std::addressof(loc)));
+            }
+        }
+    }
+    loc.reset(first);
+    throw syntax_error(format_underline("[error] toml::parse_array: "
+            "array did not closed by `]`",
+            {{std::addressof(loc), "should be closed"}}),
+            source_location(std::addressof(loc)));
+}
+
+template<typename Value, typename Container>
+result<std::pair<std::pair<std::vector<key>, region<Container>>, Value>, std::string>
+parse_key_value_pair(location<Container>& loc)
+{
+    using value_type = Value;
+
+    const auto first = loc.iter();
+    auto key_reg = parse_key(loc);
+    if(!key_reg)
+    {
+        std::string msg = std::move(key_reg.unwrap_err());
+        // if the next token is keyvalue-separator, it means that there are no
+        // key. then we need to show error as "empty key is not allowed".
+        if(const auto keyval_sep = lex_keyval_sep::invoke(loc))
+        {
+            loc.reset(first);
+            msg = format_underline("[error] toml::parse_key_value_pair: "
+                "empty key is not allowed.",
+                {{std::addressof(loc), "key expected before '='"}});
+        }
+        return err(std::move(msg));
+    }
+
+    const auto kvsp = lex_keyval_sep::invoke(loc);
+    if(!kvsp)
+    {
+        std::string msg;
+        // if the line contains '=' after the invalid sequence, possibly the
+        // error is in the key (like, invalid character in bare key).
+        const auto line_end = std::find(loc.iter(), loc.end(), '\n');
+        if(std::find(loc.iter(), line_end, '=') != line_end)
+        {
+            msg = format_underline("[error] toml::parse_key_value_pair: "
+                "invalid format for key",
+                {{std::addressof(loc), "invalid character in key"}},
+                {"Did you forget '.' to separate dotted-key?",
+                "Allowed characters for bare key are [0-9a-zA-Z_-]."});
+        }
+        else // if not, the error is lack of key-value separator.
+        {
+            msg = format_underline("[error] toml::parse_key_value_pair: "
+                "missing key-value separator `=`",
+                {{std::addressof(loc), "should be `=`"}});
+        }
+        loc.reset(first);
+        return err(std::move(msg));
+    }
+
+    const auto after_kvsp = loc.iter(); // err msg
+    auto val = parse_value<value_type>(loc);
+    if(!val)
+    {
+        std::string msg;
+        loc.reset(after_kvsp);
+        // check there is something not a comment/whitespace after `=`
+        if(sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>::invoke(loc))
+        {
+            loc.reset(after_kvsp);
+            msg = format_underline("[error] toml::parse_key_value_pair: "
+                    "missing value after key-value separator '='",
+                    {{std::addressof(loc), "expected value, but got nothing"}});
+        }
+        else // there is something not a comment/whitespace, so invalid format.
+        {
+            msg = std::move(val.unwrap_err());
+        }
+        loc.reset(first);
+        return err(msg);
+    }
+    return ok(std::make_pair(std::move(key_reg.unwrap()),
+                             std::move(val.unwrap())));
+}
+
+// for error messages.
+template<typename InputIterator>
+std::string format_dotted_keys(InputIterator first, const InputIterator last)
+{
+    static_assert(std::is_same<key,
+        typename std::iterator_traits<InputIterator>::value_type>::value,"");
+
+    std::string retval(*first++);
+    for(; first != last; ++first)
+    {
+        retval += '.';
+        retval += *first;
+    }
+    return retval;
+}
+
+// forward decl for is_valid_forward_table_definition
+template<typename Container>
+result<std::pair<std::vector<key>, region<Container>>, std::string>
+parse_table_key(location<Container>& loc);
+
+// The following toml file is allowed.
+// ```toml
+// [a.b.c]     # here, table `a` has element `b`.
+// foo = "bar"
+// [a]         # merge a = {baz = "qux"} to a = {b = {...}}
+// baz = "qux"
+// ```
+// But the following is not allowed.
+// ```toml
+// [a]
+// b.c.foo = "bar"
+// [a]             # error! the same table [a] defined!
+// baz = "qux"
+// ```
+// The following is neither allowed.
+// ```toml
+// a = { b.c.foo = "bar"}
+// [a]             # error! the same table [a] defined!
+// baz = "qux"
+// ```
+// Here, it parses region of `tab->at(k)` as a table key and check the depth
+// of the key. If the key region points deeper node, it would be allowed.
+// Otherwise, the key points the same node. It would be rejected.
+template<typename Value, typename Iterator>
+bool is_valid_forward_table_definition(const Value& fwd,
+        Iterator key_first, Iterator key_curr, Iterator key_last)
+{
+    location<std::string> def("internal", detail::get_region(fwd).str());
+    if(const auto tabkeys = parse_table_key(def))
+    {
+        // table keys always contains all the nodes from the root.
+        const auto& tks = tabkeys.unwrap().first;
+        if(std::size_t(std::distance(key_first, key_last)) == tks.size() &&
+           std::equal(tks.begin(), tks.end(), key_first))
+        {
+            // the keys are equivalent. it is not allowed.
+            return false;
+        }
+        // the keys are not equivalent. it is allowed.
+        return true;
+    }
+    if(const auto dotkeys = parse_key(def))
+    {
+        // consider the following case.
+        // [a]
+        // b.c = {d = 42}
+        // [a.b.c]
+        // e = 2.71
+        // this defines the table [a.b.c] twice. no?
+
+        // a dotted key starts from the node representing a table in which the
+        // dotted key belongs to.
+        const auto& dks = dotkeys.unwrap().first;
+        if(std::size_t(std::distance(key_curr, key_last)) == dks.size() &&
+           std::equal(dks.begin(), dks.end(), key_curr))
+        {
+            // the keys are equivalent. it is not allowed.
+            return false;
+        }
+        // the keys are not equivalent. it is allowed.
+        return true;
+    }
+    return false;
+}
+
+template<typename Value, typename InputIterator, typename Container>
+result<bool, std::string>
+insert_nested_key(typename Value::table_type& root, const Value& v,
+                  InputIterator iter, const InputIterator last,
+                  region<Container> key_reg,
+                  const bool is_array_of_table = false)
+{
+    static_assert(std::is_same<key,
+        typename std::iterator_traits<InputIterator>::value_type>::value,"");
+
+    using value_type = Value;
+    using table_type = typename value_type::table_type;
+    using array_type = typename value_type::array_type;
+
+    const auto first = iter;
+    assert(iter != last);
+
+    table_type* tab = std::addressof(root);
+    for(; iter != last; ++iter) // search recursively
+    {
+        const key& k = *iter;
+        if(std::next(iter) == last) // k is the last key
+        {
+            // XXX if the value is array-of-tables, there can be several
+            //     tables that are in the same array. in that case, we need to
+            //     find the last element and insert it to there.
+            if(is_array_of_table)
+            {
+                if(tab->count(k) == 1) // there is already an array of table
+                {
+                    if(tab->at(k).is_table())
+                    {
+                        // show special err msg for conflicting table
+                        throw syntax_error(format_underline(concat_to_string(
+                            "[error] toml::insert_value: array of table (\"",
+                            format_dotted_keys(first, last),
+                            "\") cannot be defined"), {
+                                {std::addressof(get_region(tab->at(k))),
+                                 "table already defined"},
+                                {std::addressof(get_region(v)),
+                                 "this conflicts with the previous table"}
+                            }), v.location());
+                    }
+                    else if(!(tab->at(k).is_array()))
+                    {
+                        throw syntax_error(format_underline(concat_to_string(
+                            "[error] toml::insert_value: array of table (\"",
+                            format_dotted_keys(first, last), "\") collides with"
+                            " existing value"), {
+                                {std::addressof(get_region(tab->at(k))),
+                                 concat_to_string("this ", tab->at(k).type(),
+                                                  " value already exists")},
+                                {std::addressof(get_region(v)),
+                                 "while inserting this array-of-tables"}
+                            }), v.location());
+                    }
+                    // the above if-else-if checks tab->at(k) is an array
+                    auto& a = tab->at(k).as_array();
+                    if(!(a.front().is_table()))
+                    {
+                        throw syntax_error(format_underline(concat_to_string(
+                            "[error] toml::insert_value: array of table (\"",
+                            format_dotted_keys(first, last), "\") collides with"
+                            " existing value"), {
+                                {std::addressof(get_region(tab->at(k))),
+                                 concat_to_string("this ", tab->at(k).type(),
+                                                  " value already exists")},
+                                {std::addressof(get_region(v)),
+                                 "while inserting this array-of-tables"}
+                            }), v.location());
+                    }
+                    // avoid conflicting array of table like the following.
+                    // ```toml
+                    // a = [{b = 42}] # define a as an array of *inline* tables
+                    // [[a]]          # a is an array of *multi-line* tables
+                    // b = 54
+                    // ```
+                    // Here, from the type information, these cannot be detected
+                    // bacause inline table is also a table.
+                    // But toml v0.5.0 explicitly says it is invalid. The above
+                    // array-of-tables has a static size and appending to the
+                    // array is invalid.
+                    // In this library, multi-line table value has a region
+                    // that points to the key of the table (e.g. [[a]]). By
+                    // comparing the first two letters in key, we can detect
+                    // the array-of-table is inline or multiline.
+                    if(detail::get_region(a.front()).str().substr(0,2) != "[[")
+                    {
+                        throw syntax_error(format_underline(concat_to_string(
+                            "[error] toml::insert_value: array of table (\"",
+                            format_dotted_keys(first, last), "\") collides with"
+                            " existing array-of-tables"), {
+                                {std::addressof(get_region(tab->at(k))),
+                                 concat_to_string("this ", tab->at(k).type(),
+                                                  " value has static size")},
+                                {std::addressof(get_region(v)),
+                                 "appending it to the statically sized array"}
+                            }), v.location());
+                    }
+                    a.push_back(v);
+                    return ok(true);
+                }
+                else // if not, we need to create the array of table
+                {
+                    value_type aot(array_type(1, v), key_reg);
+                    tab->insert(std::make_pair(k, aot));
+                    return ok(true);
+                }
+            } // end if(array of table)
+
+            if(tab->count(k) == 1)
+            {
+                if(tab->at(k).is_table() && v.is_table())
+                {
+                    if(!is_valid_forward_table_definition(
+                                tab->at(k), first, iter, last))
+                    {
+                        throw syntax_error(format_underline(concat_to_string(
+                            "[error] toml::insert_value: table (\"",
+                            format_dotted_keys(first, last),
+                            "\") already exists."), {
+                                {std::addressof(get_region(tab->at(k))),
+                                 "table already exists here"},
+                                {std::addressof(get_region(v)),
+                                 "table defined twice"}
+                            }), v.location());
+                    }
+                    // to allow the following toml file.
+                    // [a.b.c]
+                    // d = 42
+                    // [a]
+                    // e = 2.71
+                    auto& t = tab->at(k).as_table();
+                    for(const auto& kv : v.as_table())
+                    {
+                        t[kv.first] = kv.second;
+                    }
+                    detail::change_region(tab->at(k), key_reg);
+                    return ok(true);
+                }
+                else if(v.is_table()                     &&
+                        tab->at(k).is_array()            &&
+                        tab->at(k).as_array().size() > 0 &&
+                        tab->at(k).as_array().front().is_table())
+                {
+                    throw syntax_error(format_underline(concat_to_string(
+                        "[error] toml::insert_value: array of tables (\"",
+                        format_dotted_keys(first, last), "\") already exists."), {
+                            {std::addressof(get_region(tab->at(k))),
+                             "array of tables defined here"},
+                            {std::addressof(get_region(v)),
+                            "table conflicts with the previous array of table"}
+                        }), v.location());
+                }
+                else
+                {
+                    throw syntax_error(format_underline(concat_to_string(
+                        "[error] toml::insert_value: value (\"",
+                        format_dotted_keys(first, last), "\") already exists."), {
+                            {std::addressof(get_region(tab->at(k))),
+                             "value already exists here"},
+                            {std::addressof(get_region(v)),
+                             "value defined twice"}
+                        }), v.location());
+                }
+            }
+            tab->insert(std::make_pair(k, v));
+            return ok(true);
+        }
+        else
+        {
+            // if there is no corresponding value, insert it first.
+            // related: you don't need to write
+            // # [x]
+            // # [x.y]
+            // to write
+            // [x.y.z]
+            if(tab->count(k) == 0)
+            {
+                (*tab)[k] = value_type(table_type{}, key_reg);
+            }
+
+            // type checking...
+            if(tab->at(k).is_table())
+            {
+                tab = std::addressof((*tab)[k].as_table());
+            }
+            else if(tab->at(k).is_array()) // inserting to array-of-tables?
+            {
+                auto& a = (*tab)[k].as_array();
+                if(!a.back().is_table())
+                {
+                    throw syntax_error(format_underline(concat_to_string(
+                        "[error] toml::insert_value: target (",
+                        format_dotted_keys(first, std::next(iter)),
+                        ") is neither table nor an array of tables"), {
+                            {std::addressof(get_region(a.back())),
+                             concat_to_string("actual type is ", a.back().type())},
+                            {std::addressof(get_region(v)), "inserting this"}
+                        }), v.location());
+                }
+                tab = std::addressof(a.back().as_table());
+            }
+            else
+            {
+                throw syntax_error(format_underline(concat_to_string(
+                    "[error] toml::insert_value: target (",
+                    format_dotted_keys(first, std::next(iter)),
+                    ") is neither table nor an array of tables"), {
+                        {std::addressof(get_region(tab->at(k))),
+                         concat_to_string("actual type is ", tab->at(k).type())},
+                        {std::addressof(get_region(v)), "inserting this"}
+                    }), v.location());
+            }
+        }
+    }
+    return err(std::string("toml::detail::insert_nested_key: never reach here"));
+}
+
+template<typename Value, typename Container>
+result<std::pair<typename Value::table_type, region<Container>>, std::string>
+parse_inline_table(location<Container>& loc)
+{
+    using value_type = Value;
+    using table_type = typename value_type::table_type;
+
+    const auto first = loc.iter();
+    table_type retval;
+    if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
+    {
+        return err(format_underline("[error] toml::parse_inline_table: ",
+            {{std::addressof(loc), "the next token is not an inline table"}}));
+    }
+    loc.advance();
+    // it starts from "{". it should be formatted as inline-table
+    while(loc.iter() != loc.end())
+    {
+        maybe<lex_ws>::invoke(loc);
+        if(loc.iter() != loc.end() && *loc.iter() == '}')
+        {
+            loc.advance(); // skip `}`
+            return ok(std::make_pair(
+                        retval, region<Container>(loc, first, loc.iter())));
+        }
+
+        const auto kv_r = parse_key_value_pair<value_type>(loc);
+        if(!kv_r)
+        {
+            return err(kv_r.unwrap_err());
+        }
+        const auto&              kvpair  = kv_r.unwrap();
+        const std::vector<key>&  keys    = kvpair.first.first;
+        const region<Container>& key_reg = kvpair.first.second;
+        const value_type&        val     = kvpair.second;
+
+        const auto inserted =
+            insert_nested_key(retval, val, keys.begin(), keys.end(), key_reg);
+        if(!inserted)
+        {
+            throw internal_error("[error] toml::parse_inline_table: "
+                "failed to insert value into table: " + inserted.unwrap_err(),
+                source_location(std::addressof(loc)));
+        }
+
+        using lex_table_separator = sequence<maybe<lex_ws>, character<','>>;
+        const auto sp = lex_table_separator::invoke(loc);
+        if(!sp)
+        {
+            maybe<lex_ws>::invoke(loc);
+            if(loc.iter() != loc.end() && *loc.iter() == '}')
+            {
+                loc.advance(); // skip `}`
+                return ok(std::make_pair(
+                            retval, region<Container>(loc, first, loc.iter())));
+            }
+            else if(*loc.iter() == '#' || *loc.iter() == '\r' || *loc.iter() == '\n')
+            {
+                throw syntax_error(format_underline("[error] "
+                    "toml::parse_inline_table: missing curly brace `}`",
+                    {{std::addressof(loc), "should be `}`"}}),
+                    source_location(std::addressof(loc)));
+            }
+            else
+            {
+                throw syntax_error(format_underline("[error] "
+                    "toml::parse_inline_table: missing table separator `,` ",
+                    {{std::addressof(loc), "should be `,`"}}),
+                    source_location(std::addressof(loc)));
+            }
+        }
+    }
+    loc.reset(first);
+    throw syntax_error(format_underline("[error] toml::parse_inline_table: "
+            "inline table did not closed by `}`",
+            {{std::addressof(loc), "should be closed"}}),
+            source_location(std::addressof(loc)));
+}
+
+template<typename Container>
+result<value_t, std::string> guess_number_type(const location<Container>& l)
+{
+    // This function tries to find some (common) mistakes by checking characters
+    // that follows the last character of a value. But it is often difficult
+    // because some non-newline characters can appear after a value. E.g.
+    // spaces, tabs, commas (in an array or inline table), closing brackets
+    // (of an array or inline table), comment-sign (#). Since this function
+    // does not parse further, those characters are always allowed to be there.
+    location<Container> loc = l;
+
+    if(lex_offset_date_time::invoke(loc)) {return ok(value_t::offset_datetime);}
+    loc.reset(l.iter());
+
+    if(lex_local_date_time::invoke(loc))
+    {
+        // bad offset may appear after this.
+        if(loc.iter() != loc.end() && (*loc.iter() == '+' || *loc.iter() == '-'
+                    || *loc.iter() == 'Z' || *loc.iter() == 'z'))
+        {
+            return err(format_underline("[error] bad offset: should be [+-]HH:MM or Z",
+                        {{std::addressof(loc), "[+-]HH:MM or Z"}},
+                        {"pass: +09:00, -05:30", "fail: +9:00, -5:30"}));
+        }
+        return ok(value_t::local_datetime);
+    }
+    loc.reset(l.iter());
+
+    if(lex_local_date::invoke(loc))
+    {
+        // bad time may appear after this.
+        // A space is allowed as a delimiter between local time. But there are
+        // both cases in which a space becomes valid or invalid.
+        // - invalid: 2019-06-16 7:00:00
+        // - valid  : 2019-06-16 07:00:00
+        if(loc.iter() != loc.end())
+        {
+            const auto c = *loc.iter();
+            if(c == 'T' || c == 't')
+            {
+                return err(format_underline("[error] bad time: should be HH:MM:SS.subsec",
+                        {{std::addressof(loc), "HH:MM:SS.subsec"}},
+                        {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
+                         "fail: 1979-05-27T7:32:00, 1979-05-27 17:32"}));
+            }
+            if('0' <= c && c <= '9')
+            {
+                return err(format_underline("[error] bad time: missing T",
+                        {{std::addressof(loc), "T or space required here"}},
+                        {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
+                         "fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
+            }
+            if(c == ' ' && std::next(loc.iter()) != loc.end() &&
+                ('0' <= *std::next(loc.iter()) && *std::next(loc.iter())<= '9'))
+            {
+                loc.advance();
+                return err(format_underline("[error] bad time: should be HH:MM:SS.subsec",
+                        {{std::addressof(loc), "HH:MM:SS.subsec"}},
+                        {"pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999",
+                         "fail: 1979-05-27T7:32:00, 1979-05-27 7:32"}));
+            }
+        }
+        return ok(value_t::local_date);
+    }
+    loc.reset(l.iter());
+
+    if(lex_local_time::invoke(loc)) {return ok(value_t::local_time);}
+    loc.reset(l.iter());
+
+    if(lex_float::invoke(loc))
+    {
+        if(loc.iter() != loc.end() && *loc.iter() == '_')
+        {
+            return err(format_underline("[error] bad float: `_` should be surrounded by digits",
+                        {{std::addressof(loc), "here"}},
+                        {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
+                         "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
+        }
+        return ok(value_t::floating);
+    }
+    loc.reset(l.iter());
+
+    if(lex_integer::invoke(loc))
+    {
+        if(loc.iter() != loc.end())
+        {
+            const auto c = *loc.iter();
+            if(c == '_')
+            {
+                return err(format_underline("[error] bad integer: `_` should be surrounded by digits",
+                            {{std::addressof(loc), "here"}},
+                            {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
+                             "fail: 1__000, 0123"}));
+            }
+            if('0' <= c && c <= '9')
+            {
+                // leading zero. point '0'
+                loc.retrace();
+                return err(format_underline("[error] bad integer: leading zero",
+                            {{std::addressof(loc), "here"}},
+                            {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
+                             "fail: 1__000, 0123"}));
+            }
+            if(c == ':' || c == '-')
+            {
+                return err(format_underline("[error] bad datetime: invalid format",
+                            {{std::addressof(loc), "here"}},
+                            {"pass: 1979-05-27T07:32:00-07:00, 1979-05-27 07:32:00.999999Z",
+                             "fail: 1979-05-27T7:32:00-7:00, 1979-05-27 7:32-00:30"}));
+            }
+            if(c == '.' || c == 'e' || c == 'E')
+            {
+                return err(format_underline("[error] bad float: invalid format",
+                            {{std::addressof(loc), "here"}},
+                            {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
+                             "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
+            }
+        }
+        return ok(value_t::integer);
+    }
+    if(loc.iter() != loc.end() && *loc.iter() == '.')
+    {
+        return err(format_underline("[error] bad float: invalid format",
+                {{std::addressof(loc), "integer part required before this"}},
+                {"pass: +1.0, -2e-2, 3.141_592_653_589, inf, nan",
+                 "fail: .0, 1., _1.0, 1.0_, 1_.0, 1.0__0"}));
+    }
+    if(loc.iter() != loc.end() && *loc.iter() == '_')
+    {
+        return err(format_underline("[error] bad number: `_` should be surrounded by digits",
+                {{std::addressof(loc), "`_` is not surrounded by digits"}},
+                {"pass: -42, 1_000, 1_2_3_4_5, 0xC0FFEE, 0b0010, 0o755",
+                 "fail: 1__000, 0123"}));
+    }
+    return err(format_underline("[error] bad format: unknown value appeared",
+                {{std::addressof(loc), "here"}}));
+}
+
+template<typename Container>
+result<value_t, std::string> guess_value_type(const location<Container>& loc)
+{
+    switch(*loc.iter())
+    {
+        case '"' : {return ok(value_t::string);  }
+        case '\'': {return ok(value_t::string);  }
+        case 't' : {return ok(value_t::boolean); }
+        case 'f' : {return ok(value_t::boolean); }
+        case '[' : {return ok(value_t::array);   }
+        case '{' : {return ok(value_t::table);   }
+        case 'i' : {return ok(value_t::floating);} // inf.
+        case 'n' : {return ok(value_t::floating);} // nan.
+        default  : {return guess_number_type(loc);}
+    }
+}
+
+template<typename Value, typename Container>
+result<Value, std::string> parse_value(location<Container>& loc)
+{
+    using value_type = Value;
+
+    const auto first = loc.iter();
+    if(first == loc.end())
+    {
+        return err(format_underline("[error] toml::parse_value: input is empty",
+                   {{std::addressof(loc), ""}}));
+    }
+
+    const auto type = guess_value_type(loc);
+    if(!type)
+    {
+        return err(type.unwrap_err());
+    }
+    switch(type.unwrap())
+    {
+        case value_t::boolean        : {return parse_boolean(loc);        }
+        case value_t::integer        : {return parse_integer(loc);        }
+        case value_t::floating       : {return parse_floating(loc);       }
+        case value_t::string         : {return parse_string(loc);         }
+        case value_t::offset_datetime: {return parse_offset_datetime(loc);}
+        case value_t::local_datetime : {return parse_local_datetime(loc); }
+        case value_t::local_date     : {return parse_local_date(loc);     }
+        case value_t::local_time     : {return parse_local_time(loc);     }
+        case value_t::array          : {return parse_array<value_type>(loc);       }
+        case value_t::table          : {return parse_inline_table<value_type>(loc);}
+        default:
+        {
+            const auto msg = format_underline("[error] toml::parse_value: "
+                    "unknown token appeared", {{std::addressof(loc), "unknown"}});
+            loc.reset(first);
+            return err(msg);
+        }
+    }
+}
+
+template<typename Container>
+result<std::pair<std::vector<key>, region<Container>>, std::string>
+parse_table_key(location<Container>& loc)
+{
+    if(auto token = lex_std_table::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+
+        const auto open = lex_std_table_open::invoke(inner_loc);
+        if(!open || inner_loc.iter() == inner_loc.end())
+        {
+            throw internal_error(format_underline("[error] "
+                "toml::parse_table_key: no `[`",
+                {{std::addressof(inner_loc), "should be `[`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        // to skip [ a . b . c ]
+        //          ^----------- this whitespace
+        lex_ws::invoke(inner_loc);
+        const auto keys = parse_key(inner_loc);
+        if(!keys)
+        {
+            throw internal_error(format_underline("[error] "
+                "toml::parse_table_key: invalid key",
+                {{std::addressof(inner_loc), "not key"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        // to skip [ a . b . c ]
+        //                    ^-- this whitespace
+        lex_ws::invoke(inner_loc);
+        const auto close = lex_std_table_close::invoke(inner_loc);
+        if(!close)
+        {
+            throw internal_error(format_underline("[error] "
+                "toml::parse_table_key: no `]`",
+                {{std::addressof(inner_loc), "should be `]`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+
+        // after [table.key], newline or EOF(empty table) requried.
+        if(loc.iter() != loc.end())
+        {
+            using lex_newline_after_table_key =
+                sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>;
+            const auto nl = lex_newline_after_table_key::invoke(loc);
+            if(!nl)
+            {
+                throw syntax_error(format_underline("[error] "
+                    "toml::parse_table_key: newline required after [table.key]",
+                    {{std::addressof(loc), "expected newline"}}),
+                    source_location(std::addressof(loc)));
+            }
+        }
+        return ok(std::make_pair(keys.unwrap().first, token.unwrap()));
+    }
+    else
+    {
+        return err(format_underline("[error] toml::parse_table_key: "
+            "not a valid table key", {{std::addressof(loc), "here"}}));
+    }
+}
+
+template<typename Container>
+result<std::pair<std::vector<key>, region<Container>>, std::string>
+parse_array_table_key(location<Container>& loc)
+{
+    if(auto token = lex_array_table::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+
+        const auto open = lex_array_table_open::invoke(inner_loc);
+        if(!open || inner_loc.iter() == inner_loc.end())
+        {
+            throw internal_error(format_underline("[error] "
+                "toml::parse_array_table_key: no `[[`",
+                {{std::addressof(inner_loc), "should be `[[`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        lex_ws::invoke(inner_loc);
+        const auto keys = parse_key(inner_loc);
+        if(!keys)
+        {
+            throw internal_error(format_underline("[error] "
+                "toml::parse_array_table_key: invalid key",
+                {{std::addressof(inner_loc), "not a key"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+        lex_ws::invoke(inner_loc);
+        const auto close = lex_array_table_close::invoke(inner_loc);
+        if(!close)
+        {
+            throw internal_error(format_underline("[error] "
+                "toml::parse_table_key: no `]]`",
+                {{std::addressof(inner_loc), "should be `]]`"}}),
+                source_location(std::addressof(inner_loc)));
+        }
+
+        // after [[table.key]], newline or EOF(empty table) requried.
+        if(loc.iter() != loc.end())
+        {
+            using lex_newline_after_table_key =
+                sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>;
+            const auto nl = lex_newline_after_table_key::invoke(loc);
+            if(!nl)
+            {
+                throw syntax_error(format_underline("[error] toml::"
+                    "parse_array_table_key: newline required after [[table.key]]",
+                    {{std::addressof(loc), "expected newline"}}),
+                    source_location(std::addressof(loc)));
+            }
+        }
+        return ok(std::make_pair(keys.unwrap().first, token.unwrap()));
+    }
+    else
+    {
+        return err(format_underline("[error] toml::parse_array_table_key: "
+            "not a valid table key", {{std::addressof(loc), "here"}}));
+    }
+}
+
+// parse table body (key-value pairs until the iter hits the next [tablekey])
+template<typename Value, typename Container>
+result<typename Value::table_type, std::string>
+parse_ml_table(location<Container>& loc)
+{
+    using value_type = Value;
+    using table_type = typename value_type::table_type;
+
+    const auto first = loc.iter();
+    if(first == loc.end())
+    {
+        return ok(table_type{});
+    }
+
+    // XXX at lest one newline is needed.
+    using skip_line = repeat<
+        sequence<maybe<lex_ws>, maybe<lex_comment>, lex_newline>, at_least<1>>;
+    skip_line::invoke(loc);
+    lex_ws::invoke(loc);
+
+    table_type tab;
+    while(loc.iter() != loc.end())
+    {
+        lex_ws::invoke(loc);
+        const auto before = loc.iter();
+        if(const auto tmp = parse_array_table_key(loc)) // next table found
+        {
+            loc.reset(before);
+            return ok(tab);
+        }
+        if(const auto tmp = parse_table_key(loc)) // next table found
+        {
+            loc.reset(before);
+            return ok(tab);
+        }
+
+        if(const auto kv = parse_key_value_pair<value_type>(loc))
+        {
+            const auto&              kvpair  = kv.unwrap();
+            const std::vector<key>&  keys    = kvpair.first.first;
+            const region<Container>& key_reg = kvpair.first.second;
+            const value_type&        val     = kvpair.second;
+            const auto inserted =
+                insert_nested_key(tab, val, keys.begin(), keys.end(), key_reg);
+            if(!inserted)
+            {
+                return err(inserted.unwrap_err());
+            }
+        }
+        else
+        {
+            return err(kv.unwrap_err());
+        }
+
+        // comment lines are skipped by the above function call.
+        // However, since the `skip_line` requires at least 1 newline, it fails
+        // if the file ends with ws and/or comment without newline.
+        // `skip_line` matches `ws? + comment? + newline`, not `ws` or `comment`
+        // itself. To skip the last ws and/or comment, call lexers.
+        // It does not matter if these fails, so the return value is discarded.
+        lex_ws::invoke(loc);
+        lex_comment::invoke(loc);
+
+        // skip_line is (whitespace? comment? newline)_{1,}. multiple empty lines
+        // and comments after the last key-value pairs are allowed.
+        const auto newline = skip_line::invoke(loc);
+        if(!newline && loc.iter() != loc.end())
+        {
+            const auto before2 = loc.iter();
+            lex_ws::invoke(loc); // skip whitespace
+            const auto msg = format_underline("[error] toml::parse_table: "
+                "invalid line format", {{std::addressof(loc), concat_to_string(
+                "expected newline, but got '", show_char(*loc.iter()), "'.")}});
+            loc.reset(before2);
+            return err(msg);
+        }
+
+        // the skip_lines only matches with lines that includes newline.
+        // to skip the last line that includes comment and/or whitespace
+        // but no newline, call them one more time.
+        lex_ws::invoke(loc);
+        lex_comment::invoke(loc);
+    }
+    return ok(tab);
+}
+
+template<typename Value, typename Container>
+result<Value, std::string> parse_toml_file(location<Container>& loc)
+{
+    using value_type = Value;
+    using table_type = typename value_type::table_type;
+
+    const auto first = loc.iter();
+    if(first == loc.end())
+    {
+        return ok(value_type(table_type{} /*, empty file has no region ...*/));
+    }
+
+    // put the first line as a region of a file
+    // Here first != loc.end(), so taking std::next is okay
+    const region<Container> file(loc, first, std::next(loc.iter()));
+
+    // The first successive comments that are separated from the first value
+    // by an empty line are for a file itself.
+    // ```toml
+    // # this is a comment for a file.
+    //
+    // key = "the first value"
+    // ```
+    // ```toml
+    // # this is a comment for "the first value".
+    // key = "the first value"
+    // ```
+    std::vector<std::string> comments;
+    using lex_first_comments = sequence<
+        repeat<sequence<maybe<lex_ws>, lex_comment, lex_newline>, at_least<1>>,
+        sequence<maybe<lex_ws>, lex_newline>
+        >;
+    if(const auto token = lex_first_comments::invoke(loc))
+    {
+        location<std::string> inner_loc(loc.name(), token.unwrap().str());
+        while(inner_loc.iter() != inner_loc.end())
+        {
+            maybe<lex_ws>::invoke(inner_loc); // remove ws if exists
+            if(lex_newline::invoke(inner_loc))
+            {
+                assert(inner_loc.iter() == inner_loc.end());
+                break; // empty line found.
+            }
+            auto com = lex_comment::invoke(inner_loc).unwrap().str();
+            com.erase(com.begin()); // remove # sign
+            comments.push_back(std::move(com));
+            lex_newline::invoke(inner_loc);
+        }
+    }
+
+    table_type data;
+    // root object is also a table, but without [tablename]
+    if(auto tab = parse_ml_table<value_type>(loc))
+    {
+        data = std::move(tab.unwrap());
+    }
+    else // failed (empty table is regarded as success in parse_ml_table)
+    {
+        return err(tab.unwrap_err());
+    }
+    while(loc.iter() != loc.end())
+    {
+        // here, the region of [table] is regarded as the table-key because
+        // the table body is normally too big and it is not so informative
+        // if the first key-value pair of the table is shown in the error
+        // message.
+        if(const auto tabkey = parse_array_table_key(loc))
+        {
+            const auto tab = parse_ml_table<value_type>(loc);
+            if(!tab){return err(tab.unwrap_err());}
+
+            const auto& tk   = tabkey.unwrap();
+            const auto& keys = tk.first;
+            const auto& reg  = tk.second;
+
+            const auto inserted = insert_nested_key(data,
+                    value_type(tab.unwrap(), reg),
+                    keys.begin(), keys.end(), reg,
+                    /*is_array_of_table=*/ true);
+            if(!inserted) {return err(inserted.unwrap_err());}
+
+            continue;
+        }
+        if(const auto tabkey = parse_table_key(loc))
+        {
+            const auto tab = parse_ml_table<value_type>(loc);
+            if(!tab){return err(tab.unwrap_err());}
+
+            const auto& tk   = tabkey.unwrap();
+            const auto& keys = tk.first;
+            const auto& reg  = tk.second;
+
+            const auto inserted = insert_nested_key(data,
+                value_type(tab.unwrap(), reg), keys.begin(), keys.end(), reg);
+            if(!inserted) {return err(inserted.unwrap_err());}
+
+            continue;
+        }
+        return err(format_underline("[error]: toml::parse_toml_file: "
+            "unknown line appeared", {{std::addressof(loc), "unknown format"}}));
+    }
+
+    Value v(std::move(data), file);
+    v.comments() = comments;
+
+    return ok(std::move(v));
+}
+
+} // detail
+
+template<typename                     Comment = ::toml::discard_comments,
+         template<typename ...> class Table   = std::unordered_map,
+         template<typename ...> class Array   = std::vector>
+basic_value<Comment, Table, Array>
+parse(std::istream& is, const std::string& fname = "unknown file")
+{
+    using value_type = basic_value<Comment, Table, Array>;
+
+    const auto beg = is.tellg();
+    is.seekg(0, std::ios::end);
+    const auto end = is.tellg();
+    const auto fsize = end - beg;
+    is.seekg(beg);
+
+    // read whole file as a sequence of char
+    assert(fsize >= 0);
+    std::vector<char> letters(static_cast<std::size_t>(fsize));
+    is.read(letters.data(), fsize);
+
+    if(!letters.empty() && letters.back() == '\0')
+    {
+        letters.pop_back();
+    }
+
+    detail::location<std::vector<char>>
+        loc(std::move(fname), std::move(letters));
+
+    // skip BOM if exists.
+    // XXX component of BOM (like 0xEF) exceeds the representable range of
+    // signed char, so on some (actually, most) of the environment, these cannot
+    // be compared to char. However, since we are always out of luck, we need to
+    // check our chars are equivalent to BOM. To do this, first we need to
+    // convert char to unsigned char to guarantee the comparability.
+    if(loc.source()->size() >= 3)
+    {
+        std::array<unsigned char, 3> BOM;
+        std::memcpy(BOM.data(), loc.source()->data(), 3);
+        if(BOM[0] == 0xEF && BOM[1] == 0xBB && BOM[2] == 0xBF)
+        {
+            loc.advance(3); // BOM found. skip.
+        }
+    }
+
+    const auto data = detail::parse_toml_file<value_type>(loc);
+    if(!data)
+    {
+        throw syntax_error(data.unwrap_err(), source_location(std::addressof(loc)));
+    }
+    return data.unwrap();
+}
+
+template<typename                     Comment = ::toml::discard_comments,
+         template<typename ...> class Table   = std::unordered_map,
+         template<typename ...> class Array   = std::vector>
+basic_value<Comment, Table, Array> parse(const std::string& fname)
+{
+    std::ifstream ifs(fname.c_str(), std::ios_base::binary);
+    if(!ifs.good())
+    {
+        throw std::runtime_error("toml::parse: file open error -> " + fname);
+    }
+    return parse<Comment, Table, Array>(ifs, fname);
+}
+
+} // toml
+#endif// TOML11_PARSER_HPP
diff --git a/external/toml11/toml/region.hpp b/external/toml11/toml/region.hpp
new file mode 100644
index 00000000..de6d04ba
--- /dev/null
+++ b/external/toml11/toml/region.hpp
@@ -0,0 +1,492 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_REGION_HPP
+#define TOML11_REGION_HPP
+#include <memory>
+#include <vector>
+#include <algorithm>
+#include <initializer_list>
+#include <iterator>
+#include <iomanip>
+#include <cassert>
+
+namespace toml
+{
+namespace detail
+{
+
+// helper function to avoid std::string(0, 'c') or std::string(iter, iter)
+template<typename Iterator>
+std::string make_string(Iterator first, Iterator last)
+{
+    if(first == last) {return "";}
+    return std::string(first, last);
+}
+inline std::string make_string(std::size_t len, char c)
+{
+    if(len == 0) {return "";}
+    return std::string(len, c);
+}
+
+// region_base is a base class of location and region that are defined below.
+// it will be used to generate better error messages.
+struct region_base
+{
+    region_base() = default;
+    virtual ~region_base() = default;
+    region_base(const region_base&) = default;
+    region_base(region_base&&     ) = default;
+    region_base& operator=(const region_base&) = default;
+    region_base& operator=(region_base&&     ) = default;
+
+    virtual bool is_ok()           const noexcept {return false;}
+
+    virtual std::string str()      const {return std::string("unknown region");}
+    virtual std::string name()     const {return std::string("unknown file");}
+    virtual std::string line()     const {return std::string("unknown line");}
+    virtual std::string line_num() const {return std::string("?");}
+
+    // length of the region
+    virtual std::size_t size()     const noexcept {return 0;}
+    // number of characters in the line before the region
+    virtual std::size_t before()   const noexcept {return 0;}
+    // number of characters in the line after the region
+    virtual std::size_t after()    const noexcept {return 0;}
+
+    virtual std::vector<std::string> comments()const {return {};}
+    // ```toml
+    // # comment_before
+    // key = "value" # comment_inline
+    // ```
+};
+
+// location represents a position in a container, which contains a file content.
+// it can be considered as a region that contains only one character.
+//
+// it contains pointer to the file content and iterator that points the current
+// location.
+template<typename Container>
+struct location final : public region_base
+{
+    using const_iterator  = typename Container::const_iterator;
+    using difference_type = typename const_iterator::difference_type;
+    using source_ptr      = std::shared_ptr<const Container>;
+
+    static_assert(std::is_same<char, typename Container::value_type>::value,"");
+    static_assert(std::is_same<std::random_access_iterator_tag,
+        typename std::iterator_traits<const_iterator>::iterator_category>::value,
+        "container should be randomly accessible");
+
+    location(std::string name, Container cont)
+      : source_(std::make_shared<Container>(std::move(cont))), line_number_(1),
+        source_name_(std::move(name)), iter_(source_->cbegin())
+    {}
+    location(const location&) = default;
+    location(location&&)      = default;
+    location& operator=(const location&) = default;
+    location& operator=(location&&)      = default;
+    ~location() = default;
+
+    bool is_ok() const noexcept override {return static_cast<bool>(source_);}
+
+    // this const prohibits codes like `++(loc.iter())`.
+    const const_iterator iter()  const noexcept {return iter_;}
+
+    const_iterator begin() const noexcept {return source_->cbegin();}
+    const_iterator end()   const noexcept {return source_->cend();}
+
+    // XXX `location::line_num()` used to be implemented using `std::count` to
+    // count a number of '\n'. But with a long toml file (typically, 10k lines),
+    // it becomes intolerably slow because each time it generates error messages,
+    // it counts '\n' from thousands of characters. To workaround it, I decided
+    // to introduce `location::line_number_` member variable and synchronize it
+    // to the location changes the point to look. So an overload of `iter()`
+    // which returns mutable reference is removed and `advance()`, `retrace()`
+    // and `reset()` is added.
+    void advance(difference_type n = 1) noexcept
+    {
+        this->line_number_ += static_cast<std::size_t>(
+                std::count(this->iter_, std::next(this->iter_, n), '\n'));
+        this->iter_ += n;
+        return;
+    }
+    void retrace(difference_type n = 1) noexcept
+    {
+        this->line_number_ -= static_cast<std::size_t>(
+                std::count(std::prev(this->iter_, n), this->iter_, '\n'));
+        this->iter_ -= n;
+        return;
+    }
+    void reset(const_iterator rollback) noexcept
+    {
+        // since c++11, std::distance works in both ways for random-access
+        // iterators and returns a negative value if `first > last`.
+        if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
+        {
+            this->line_number_ -= static_cast<std::size_t>(
+                    std::count(rollback, this->iter_, '\n'));
+        }
+        else // iter < rollback [[unlikely]]
+        {
+            this->line_number_ += static_cast<std::size_t>(
+                    std::count(this->iter_, rollback, '\n'));
+        }
+        this->iter_ = rollback;
+        return;
+    }
+
+    std::string str()  const override {return make_string(1, *this->iter());}
+    std::string name() const override {return source_name_;}
+
+    std::string line_num() const override
+    {
+        return std::to_string(this->line_number_);
+    }
+
+    std::string line() const override
+    {
+        return make_string(this->line_begin(), this->line_end());
+    }
+
+    const_iterator line_begin() const noexcept
+    {
+        using reverse_iterator = std::reverse_iterator<const_iterator>;
+        return std::find(reverse_iterator(this->iter()),
+                         reverse_iterator(this->begin()), '\n').base();
+    }
+    const_iterator line_end() const noexcept
+    {
+        return std::find(this->iter(), this->end(), '\n');
+    }
+
+    // location is always points a character. so the size is 1.
+    std::size_t size() const noexcept override
+    {
+        return 1u;
+    }
+    std::size_t before() const noexcept override
+    {
+        const auto sz = std::distance(this->line_begin(), this->iter());
+        assert(sz >= 0);
+        return static_cast<std::size_t>(sz);
+    }
+    std::size_t after() const noexcept override
+    {
+        const auto sz = std::distance(this->iter(), this->line_end());
+        assert(sz >= 0);
+        return static_cast<std::size_t>(sz);
+    }
+
+    source_ptr const& source() const& noexcept {return source_;}
+    source_ptr&&      source() &&     noexcept {return std::move(source_);}
+
+  private:
+
+    source_ptr     source_;
+    std::size_t    line_number_;
+    std::string    source_name_;
+    const_iterator iter_;
+};
+
+// region represents a range in a container, which contains a file content.
+//
+// it contains pointer to the file content and iterator that points the first
+// and last location.
+template<typename Container>
+struct region final : public region_base
+{
+    using const_iterator = typename Container::const_iterator;
+    using source_ptr     = std::shared_ptr<const Container>;
+
+    static_assert(std::is_same<char, typename Container::value_type>::value,"");
+    static_assert(std::is_same<std::random_access_iterator_tag,
+        typename std::iterator_traits<const_iterator>::iterator_category>::value,
+        "container should be randomly accessible");
+
+    // delete default constructor. source_ never be null.
+    region() = delete;
+
+    region(const location<Container>& loc)
+      : source_(loc.source()), source_name_(loc.name()),
+        first_(loc.iter()), last_(loc.iter())
+    {}
+    region(location<Container>&& loc)
+      : source_(loc.source()), source_name_(loc.name()),
+        first_(loc.iter()), last_(loc.iter())
+    {}
+
+    region(const location<Container>& loc, const_iterator f, const_iterator l)
+      : source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
+    {}
+    region(location<Container>&& loc, const_iterator f, const_iterator l)
+      : source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
+    {}
+
+    region(const region&) = default;
+    region(region&&)      = default;
+    region& operator=(const region&) = default;
+    region& operator=(region&&)      = default;
+    ~region() = default;
+
+    region& operator+=(const region& other)
+    {
+        // different regions cannot be concatenated
+        assert(this->begin() == other.begin() && this->end() == other.end() &&
+               this->last_   == other.first_);
+
+        this->last_ = other.last_;
+        return *this;
+    }
+
+    bool is_ok() const noexcept override {return static_cast<bool>(source_);}
+
+    std::string str()  const override {return make_string(first_, last_);}
+    std::string line() const override
+    {
+        if(this->contain_newline())
+        {
+            return make_string(this->line_begin(),
+                    std::find(this->line_begin(), this->last(), '\n'));
+        }
+        return make_string(this->line_begin(), this->line_end());
+    }
+    std::string line_num() const override
+    {
+        return std::to_string(1 + std::count(this->begin(), this->first(), '\n'));
+    }
+
+    std::size_t size() const noexcept override
+    {
+        const auto sz = std::distance(first_, last_);
+        assert(sz >= 0);
+        return static_cast<std::size_t>(sz);
+    }
+    std::size_t before() const noexcept override
+    {
+        const auto sz = std::distance(this->line_begin(), this->first());
+        assert(sz >= 0);
+        return static_cast<std::size_t>(sz);
+    }
+    std::size_t after() const noexcept override
+    {
+        const auto sz = std::distance(this->last(), this->line_end());
+        assert(sz >= 0);
+        return static_cast<std::size_t>(sz);
+    }
+
+    bool contain_newline() const noexcept
+    {
+        return std::find(this->first(), this->last(), '\n') != this->last();
+    }
+
+    const_iterator line_begin() const noexcept
+    {
+        using reverse_iterator = std::reverse_iterator<const_iterator>;
+        return std::find(reverse_iterator(this->first()),
+                         reverse_iterator(this->begin()), '\n').base();
+    }
+    const_iterator line_end() const noexcept
+    {
+        return std::find(this->last(), this->end(), '\n');
+    }
+
+    const_iterator begin() const noexcept {return source_->cbegin();}
+    const_iterator end()   const noexcept {return source_->cend();}
+    const_iterator first() const noexcept {return first_;}
+    const_iterator last()  const noexcept {return last_;}
+
+    source_ptr const& source() const& noexcept {return source_;}
+    source_ptr&&      source() &&     noexcept {return std::move(source_);}
+
+    std::string name() const override {return source_name_;}
+
+    std::vector<std::string> comments() const override
+    {
+        // assuming the current region (`*this`) points a value.
+        // ```toml
+        // a = "value"
+        //     ^^^^^^^- this region
+        // ```
+        using rev_iter = std::reverse_iterator<const_iterator>;
+
+        std::vector<std::string> com{};
+        {
+            // find comments just before the current region.
+            // ```toml
+            // # this should be collected.
+            // # this also.
+            // a = value # not this.
+            // ```
+
+            // # this is a comment for `a`, not array elements.
+            // a = [1, 2, 3, 4, 5]
+            if(this->first() == std::find_if(this->line_begin(), this->first(),
+                [](const char c) noexcept -> bool {return c == '[' || c == '{';}))
+            {
+                auto iter = this->line_begin(); // points the first character
+                while(iter != this->begin())
+                {
+                    iter = std::prev(iter);
+
+                    // range [line_start, iter) represents the previous line
+                    const auto line_start   = std::find(
+                            rev_iter(iter), rev_iter(this->begin()), '\n').base();
+                    const auto comment_found = std::find(line_start, iter, '#');
+                    if(comment_found == iter)
+                    {
+                        break; // comment not found.
+                    }
+
+                    // exclude the following case.
+                    // > a = "foo" # comment // <-- this is not a comment for b but a.
+                    // > b = "current value"
+                    if(std::all_of(line_start, comment_found,
+                            [](const char c) noexcept -> bool {
+                                return c == ' ' || c == '\t';
+                            }))
+                    {
+                        // unwrap the first '#' by std::next.
+                        auto str = make_string(std::next(comment_found), iter);
+                        if(str.back() == '\r') {str.pop_back();}
+                        com.push_back(std::move(str));
+                    }
+                    else
+                    {
+                        break;
+                    }
+                    iter = line_start;
+                }
+            }
+        }
+
+        if(com.size() > 1)
+        {
+            std::reverse(com.begin(), com.end());
+        }
+
+        {
+            // find comments just after the current region.
+            // ```toml
+            // # not this.
+            // a = value # this one.
+            // a = [ # not this (technically difficult)
+            //
+            // ] # and this.
+            // ```
+            // The reason why it's difficult is that it requires parsing in the
+            // following case.
+            // ```toml
+            // a = [ 10 # this comment is for `10`. not for `a` but `a[0]`.
+            // # ...
+            // ] # this is apparently a comment for a.
+            //
+            // b = [
+            // 3.14 ] # there is no way to add a comment to `3.14` currently.
+            //
+            // c = [
+            //   3.14 # do this if you need a comment here.
+            // ]
+            // ```
+            const auto comment_found =
+                std::find(this->last(), this->line_end(), '#');
+            if(comment_found != this->line_end()) // '#' found
+            {
+                // table = {key = "value"} # what is this for?
+                // the above comment is not for "value", but {key="value"}.
+                if(comment_found == std::find_if(this->last(), comment_found,
+                    [](const char c) noexcept -> bool {
+                        return !(c == ' ' || c == '\t' || c == ',');
+                    }))
+                {
+                    // unwrap the first '#' by std::next.
+                    auto str = make_string(std::next(comment_found), this->line_end());
+                    if(str.back() == '\r') {str.pop_back();}
+                    com.push_back(std::move(str));
+                }
+            }
+        }
+        return com;
+    }
+
+  private:
+
+    source_ptr     source_;
+    std::string    source_name_;
+    const_iterator first_, last_;
+};
+
+// to show a better error message.
+inline std::string format_underline(const std::string& message,
+        const std::vector<std::pair<region_base const*, std::string>>& reg_com,
+        const std::vector<std::string>& helps = {})
+{
+    assert(!reg_com.empty());
+
+    const auto line_num_width = static_cast<int>(std::max_element(
+        reg_com.begin(), reg_com.end(),
+        [](std::pair<region_base const*, std::string> const& lhs,
+           std::pair<region_base const*, std::string> const& rhs)
+        {
+            return lhs.first->line_num().size() < rhs.first->line_num().size();
+        }
+    )->first->line_num().size());
+
+    std::ostringstream retval;
+    retval << message << '\n';
+
+    for(auto iter = reg_com.begin(); iter != reg_com.end(); ++iter)
+    {
+        // if the filenames are the same, print "..."
+        if(iter != reg_com.begin() &&
+           std::prev(iter)->first->name() == iter->first->name())
+        {
+            retval << "\n ...\n";
+        }
+        else // if filename differs, print " --> filename.toml"
+        {
+            if(iter != reg_com.begin()) {retval << '\n';}
+            retval << " --> " << iter->first->name() << '\n';
+        }
+        const region_base* const reg = iter->first;
+        const std::string&   comment = iter->second;
+
+        retval << ' ' << std::setw(line_num_width) << reg->line_num();
+        retval << " | " << reg->line() << '\n';
+        retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
+        retval << " | " << make_string(reg->before(), ' ');
+
+        if(reg->size() == 1)
+        {
+            // invalid
+            // ^------
+            retval << '^';
+            retval << make_string(reg->after(), '-');
+        }
+        else
+        {
+            // invalid
+            // ~~~~~~~
+            const auto underline_len = std::min(reg->size(), reg->line().size());
+            retval << make_string(underline_len, '~');
+        }
+        retval << ' ';
+        retval << comment;
+    }
+
+    if(!helps.empty())
+    {
+        retval << '\n';
+        retval << make_string(static_cast<std::size_t>(line_num_width + 1), ' ');
+        retval << " | ";
+        for(const auto help : helps)
+        {
+            retval << "\nHint: ";
+            retval << help;
+        }
+    }
+    return retval.str();
+}
+
+} // detail
+} // toml
+#endif// TOML11_REGION_H
diff --git a/external/toml11/toml/result.hpp b/external/toml11/toml/result.hpp
new file mode 100644
index 00000000..77cd46c6
--- /dev/null
+++ b/external/toml11/toml/result.hpp
@@ -0,0 +1,717 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_RESULT_HPP
+#define TOML11_RESULT_HPP
+#include "traits.hpp"
+#include <type_traits>
+#include <stdexcept>
+#include <utility>
+#include <new>
+#include <string>
+#include <sstream>
+#include <cassert>
+
+namespace toml
+{
+
+template<typename T>
+struct success
+{
+    using value_type = T;
+    value_type value;
+
+    explicit success(const value_type& v)
+        noexcept(std::is_nothrow_copy_constructible<value_type>::value)
+        : value(v)
+    {}
+    explicit success(value_type&& v)
+        noexcept(std::is_nothrow_move_constructible<value_type>::value)
+        : value(std::move(v))
+    {}
+
+    template<typename U>
+    explicit success(U&& v): value(std::forward<U>(v)) {}
+
+    template<typename U>
+    explicit success(const success<U>& v): value(v.value) {}
+    template<typename U>
+    explicit success(success<U>&& v): value(std::move(v.value)) {}
+
+    ~success() = default;
+    success(const success&) = default;
+    success(success&&)      = default;
+    success& operator=(const success&) = default;
+    success& operator=(success&&)      = default;
+};
+
+template<typename T>
+struct failure
+{
+    using value_type = T;
+    value_type value;
+
+    explicit failure(const value_type& v)
+        noexcept(std::is_nothrow_copy_constructible<value_type>::value)
+        : value(v)
+    {}
+    explicit failure(value_type&& v)
+        noexcept(std::is_nothrow_move_constructible<value_type>::value)
+        : value(std::move(v))
+    {}
+
+    template<typename U>
+    explicit failure(U&& v): value(std::forward<U>(v)) {}
+
+    template<typename U>
+    explicit failure(const failure<U>& v): value(v.value) {}
+    template<typename U>
+    explicit failure(failure<U>&& v): value(std::move(v.value)) {}
+
+    ~failure() = default;
+    failure(const failure&) = default;
+    failure(failure&&)      = default;
+    failure& operator=(const failure&) = default;
+    failure& operator=(failure&&)      = default;
+};
+
+template<typename T>
+success<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
+ok(T&& v)
+{
+    return success<
+        typename std::remove_cv<typename std::remove_reference<T>::type>::type
+        >(std::forward<T>(v));
+}
+template<typename T>
+failure<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
+err(T&& v)
+{
+    return failure<
+        typename std::remove_cv<typename std::remove_reference<T>::type>::type
+        >(std::forward<T>(v));
+}
+
+inline success<std::string> ok(const char* literal)
+{
+    return success<std::string>(std::string(literal));
+}
+inline failure<std::string> err(const char* literal)
+{
+    return failure<std::string>(std::string(literal));
+}
+
+
+template<typename T, typename E>
+struct result
+{
+    using value_type = T;
+    using error_type = E;
+    using success_type = success<value_type>;
+    using failure_type = failure<error_type>;
+
+    result(const success_type& s): is_ok_(true)
+    {
+        auto tmp = ::new(std::addressof(this->succ)) success_type(s);
+        assert(tmp == std::addressof(this->succ));
+        (void)tmp;
+    }
+    result(const failure_type& f): is_ok_(false)
+    {
+        auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
+        assert(tmp == std::addressof(this->fail));
+        (void)tmp;
+    }
+    result(success_type&& s): is_ok_(true)
+    {
+        auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
+        assert(tmp == std::addressof(this->succ));
+        (void)tmp;
+    }
+    result(failure_type&& f): is_ok_(false)
+    {
+        auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
+        assert(tmp == std::addressof(this->fail));
+        (void)tmp;
+    }
+
+    template<typename U>
+    result(const success<U>& s): is_ok_(true)
+    {
+        auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
+        assert(tmp == std::addressof(this->succ));
+        (void)tmp;
+    }
+    template<typename U>
+    result(const failure<U>& f): is_ok_(false)
+    {
+        auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
+        assert(tmp == std::addressof(this->fail));
+        (void)tmp;
+    }
+    template<typename U>
+    result(success<U>&& s): is_ok_(true)
+    {
+        auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
+        assert(tmp == std::addressof(this->succ));
+        (void)tmp;
+    }
+    template<typename U>
+    result(failure<U>&& f): is_ok_(false)
+    {
+        auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
+        assert(tmp == std::addressof(this->fail));
+        (void)tmp;
+    }
+
+    result& operator=(const success_type& s)
+    {
+        this->cleanup();
+        this->is_ok_ = true;
+        auto tmp = ::new(std::addressof(this->succ)) success_type(s);
+        assert(tmp == std::addressof(this->succ));
+        (void)tmp;
+        return *this;
+    }
+    result& operator=(const failure_type& f)
+    {
+        this->cleanup();
+        this->is_ok_ = false;
+        auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
+        assert(tmp == std::addressof(this->fail));
+        (void)tmp;
+        return *this;
+    }
+    result& operator=(success_type&& s)
+    {
+        this->cleanup();
+        this->is_ok_ = true;
+        auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
+        assert(tmp == std::addressof(this->succ));
+        (void)tmp;
+        return *this;
+    }
+    result& operator=(failure_type&& f)
+    {
+        this->cleanup();
+        this->is_ok_ = false;
+        auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
+        assert(tmp == std::addressof(this->fail));
+        (void)tmp;
+        return *this;
+    }
+
+    template<typename U>
+    result& operator=(const success<U>& s)
+    {
+        this->cleanup();
+        this->is_ok_ = true;
+        auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
+        assert(tmp == std::addressof(this->succ));
+        (void)tmp;
+        return *this;
+    }
+    template<typename U>
+    result& operator=(const failure<U>& f)
+    {
+        this->cleanup();
+        this->is_ok_ = false;
+        auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
+        assert(tmp == std::addressof(this->fail));
+        (void)tmp;
+        return *this;
+    }
+    template<typename U>
+    result& operator=(success<U>&& s)
+    {
+        this->cleanup();
+        this->is_ok_ = true;
+        auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
+        assert(tmp == std::addressof(this->succ));
+        (void)tmp;
+        return *this;
+    }
+    template<typename U>
+    result& operator=(failure<U>&& f)
+    {
+        this->cleanup();
+        this->is_ok_ = false;
+        auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
+        assert(tmp == std::addressof(this->fail));
+        (void)tmp;
+        return *this;
+    }
+
+    ~result() noexcept {this->cleanup();}
+
+    result(const result& other): is_ok_(other.is_ok())
+    {
+        if(other.is_ok())
+        {
+            auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
+            assert(tmp == std::addressof(this->succ));
+            (void)tmp;
+        }
+        else
+        {
+            auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
+            assert(tmp == std::addressof(this->fail));
+            (void)tmp;
+        }
+    }
+    result(result&& other): is_ok_(other.is_ok())
+    {
+        if(other.is_ok())
+        {
+            auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
+            assert(tmp == std::addressof(this->succ));
+            (void)tmp;
+        }
+        else
+        {
+            auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
+            assert(tmp == std::addressof(this->fail));
+            (void)tmp;
+        }
+    }
+
+    template<typename U, typename F>
+    result(const result<U, F>& other): is_ok_(other.is_ok())
+    {
+        if(other.is_ok())
+        {
+            auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
+            assert(tmp == std::addressof(this->succ));
+            (void)tmp;
+        }
+        else
+        {
+            auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
+            assert(tmp == std::addressof(this->fail));
+            (void)tmp;
+        }
+    }
+    template<typename U, typename F>
+    result(result<U, F>&& other): is_ok_(other.is_ok())
+    {
+        if(other.is_ok())
+        {
+            auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
+            assert(tmp == std::addressof(this->succ));
+            (void)tmp;
+        }
+        else
+        {
+            auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
+            assert(tmp == std::addressof(this->fail));
+            (void)tmp;
+        }
+    }
+
+    result& operator=(const result& other)
+    {
+        this->cleanup();
+        if(other.is_ok())
+        {
+            auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
+            assert(tmp == std::addressof(this->succ));
+            (void)tmp;
+        }
+        else
+        {
+            auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
+            assert(tmp == std::addressof(this->fail));
+            (void)tmp;
+        }
+        is_ok_ = other.is_ok();
+        return *this;
+    }
+    result& operator=(result&& other)
+    {
+        this->cleanup();
+        if(other.is_ok())
+        {
+            auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
+            assert(tmp == std::addressof(this->succ));
+            (void)tmp;
+        }
+        else
+        {
+            auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
+            assert(tmp == std::addressof(this->fail));
+            (void)tmp;
+        }
+        is_ok_ = other.is_ok();
+        return *this;
+    }
+
+    template<typename U, typename F>
+    result& operator=(const result<U, F>& other)
+    {
+        this->cleanup();
+        if(other.is_ok())
+        {
+            auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
+            assert(tmp == std::addressof(this->succ));
+            (void)tmp;
+        }
+        else
+        {
+            auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
+            assert(tmp == std::addressof(this->fail));
+            (void)tmp;
+        }
+        is_ok_ = other.is_ok();
+        return *this;
+    }
+    template<typename U, typename F>
+    result& operator=(result<U, F>&& other)
+    {
+        this->cleanup();
+        if(other.is_ok())
+        {
+            auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
+            assert(tmp == std::addressof(this->succ));
+            (void)tmp;
+        }
+        else
+        {
+            auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
+            assert(tmp == std::addressof(this->fail));
+            (void)tmp;
+        }
+        is_ok_ = other.is_ok();
+        return *this;
+    }
+
+    bool is_ok()  const noexcept {return is_ok_;}
+    bool is_err() const noexcept {return !is_ok_;}
+
+    operator bool() const noexcept {return is_ok_;}
+
+    value_type&       unwrap() &
+    {
+        if(is_err())
+        {
+            throw std::runtime_error("toml::result: bad unwrap: " +
+                                     format_error(this->as_err()));
+        }
+        return this->succ.value;
+    }
+    value_type const& unwrap() const&
+    {
+        if(is_err())
+        {
+            throw std::runtime_error("toml::result: bad unwrap: " +
+                                     format_error(this->as_err()));
+        }
+        return this->succ.value;
+    }
+    value_type&&      unwrap() &&
+    {
+        if(is_err())
+        {
+            throw std::runtime_error("toml::result: bad unwrap: " +
+                                     format_error(this->as_err()));
+        }
+        return std::move(this->succ.value);
+    }
+
+    value_type&       unwrap_or(value_type& opt) &
+    {
+        if(is_err()) {return opt;}
+        return this->succ.value;
+    }
+    value_type const& unwrap_or(value_type const& opt) const&
+    {
+        if(is_err()) {return opt;}
+        return this->succ.value;
+    }
+    value_type        unwrap_or(value_type opt) &&
+    {
+        if(is_err()) {return opt;}
+        return this->succ.value;
+    }
+
+    error_type&       unwrap_err() &
+    {
+        if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
+        return this->fail.value;
+    }
+    error_type const& unwrap_err() const&
+    {
+        if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
+        return this->fail.value;
+    }
+    error_type&&      unwrap_err() &&
+    {
+        if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
+        return std::move(this->fail.value);
+    }
+
+    value_type&       as_ok() &      noexcept {return this->succ.value;}
+    value_type const& as_ok() const& noexcept {return this->succ.value;}
+    value_type&&      as_ok() &&     noexcept {return std::move(this->succ.value);}
+
+    error_type&       as_err() &      noexcept {return this->fail.value;}
+    error_type const& as_err() const& noexcept {return this->fail.value;}
+    error_type&&      as_err() &&     noexcept {return std::move(this->fail.value);}
+
+
+    // prerequisities
+    // F: T -> U
+    // retval: result<U, E>
+    template<typename F>
+    result<detail::return_type_of_t<F, value_type&>, error_type>
+    map(F&& f) &
+    {
+        if(this->is_ok()){return ok(f(this->as_ok()));}
+        return err(this->as_err());
+    }
+    template<typename F>
+    result<detail::return_type_of_t<F, value_type const&>, error_type>
+    map(F&& f) const&
+    {
+        if(this->is_ok()){return ok(f(this->as_ok()));}
+        return err(this->as_err());
+    }
+    template<typename F>
+    result<detail::return_type_of_t<F, value_type &&>, error_type>
+    map(F&& f) &&
+    {
+        if(this->is_ok()){return ok(f(std::move(this->as_ok())));}
+        return err(std::move(this->as_err()));
+    }
+
+    // prerequisities
+    // F: E -> F
+    // retval: result<T, F>
+    template<typename F>
+    result<value_type, detail::return_type_of_t<F, error_type&>>
+    map_err(F&& f) &
+    {
+        if(this->is_err()){return err(f(this->as_err()));}
+        return ok(this->as_ok());
+    }
+    template<typename F>
+    result<value_type, detail::return_type_of_t<F, error_type const&>>
+    map_err(F&& f) const&
+    {
+        if(this->is_err()){return err(f(this->as_err()));}
+        return ok(this->as_ok());
+    }
+    template<typename F>
+    result<value_type, detail::return_type_of_t<F, error_type&&>>
+    map_err(F&& f) &&
+    {
+        if(this->is_err()){return err(f(std::move(this->as_err())));}
+        return ok(std::move(this->as_ok()));
+    }
+
+    // prerequisities
+    // F: T -> U
+    // retval: U
+    template<typename F, typename U>
+    detail::return_type_of_t<F, value_type&>
+    map_or_else(F&& f, U&& opt) &
+    {
+        if(this->is_err()){return std::forward<U>(opt);}
+        return f(this->as_ok());
+    }
+    template<typename F, typename U>
+    detail::return_type_of_t<F, value_type const&>
+    map_or_else(F&& f, U&& opt) const&
+    {
+        if(this->is_err()){return std::forward<U>(opt);}
+        return f(this->as_ok());
+    }
+    template<typename F, typename U>
+    detail::return_type_of_t<F, value_type&&>
+    map_or_else(F&& f, U&& opt) &&
+    {
+        if(this->is_err()){return std::forward<U>(opt);}
+        return f(std::move(this->as_ok()));
+    }
+
+    // prerequisities
+    // F: E -> U
+    // retval: U
+    template<typename F, typename U>
+    detail::return_type_of_t<F, error_type&>
+    map_err_or_else(F&& f, U&& opt) &
+    {
+        if(this->is_ok()){return std::forward<U>(opt);}
+        return f(this->as_err());
+    }
+    template<typename F, typename U>
+    detail::return_type_of_t<F, error_type const&>
+    map_err_or_else(F&& f, U&& opt) const&
+    {
+        if(this->is_ok()){return std::forward<U>(opt);}
+        return f(this->as_err());
+    }
+    template<typename F, typename U>
+    detail::return_type_of_t<F, error_type&&>
+    map_err_or_else(F&& f, U&& opt) &&
+    {
+        if(this->is_ok()){return std::forward<U>(opt);}
+        return f(std::move(this->as_err()));
+    }
+
+    // prerequisities:
+    // F: func T -> U
+    // toml::err(error_type) should be convertible to U.
+    // normally, type U is another result<S, F> and E is convertible to F
+    template<typename F>
+    detail::return_type_of_t<F, value_type&>
+    and_then(F&& f) &
+    {
+        if(this->is_ok()){return f(this->as_ok());}
+        return err(this->as_err());
+    }
+    template<typename F>
+    detail::return_type_of_t<F, value_type const&>
+    and_then(F&& f) const&
+    {
+        if(this->is_ok()){return f(this->as_ok());}
+        return err(this->as_err());
+    }
+    template<typename F>
+    detail::return_type_of_t<F, value_type&&>
+    and_then(F&& f) &&
+    {
+        if(this->is_ok()){return f(std::move(this->as_ok()));}
+        return err(std::move(this->as_err()));
+    }
+
+    // prerequisities:
+    // F: func E -> U
+    // toml::ok(value_type) should be convertible to U.
+    // normally, type U is another result<S, F> and T is convertible to S
+    template<typename F>
+    detail::return_type_of_t<F, error_type&>
+    or_else(F&& f) &
+    {
+        if(this->is_err()){return f(this->as_err());}
+        return ok(this->as_ok());
+    }
+    template<typename F>
+    detail::return_type_of_t<F, error_type const&>
+    or_else(F&& f) const&
+    {
+        if(this->is_err()){return f(this->as_err());}
+        return ok(this->as_ok());
+    }
+    template<typename F>
+    detail::return_type_of_t<F, error_type&&>
+    or_else(F&& f) &&
+    {
+        if(this->is_err()){return f(std::move(this->as_err()));}
+        return ok(std::move(this->as_ok()));
+    }
+
+    // if *this is error, returns *this. otherwise, returns other.
+    result and_other(const result& other) const&
+    {
+        return this->is_err() ? *this : other;
+    }
+    result and_other(result&& other) &&
+    {
+        return this->is_err() ? std::move(*this) : std::move(other);
+    }
+
+    // if *this is okay, returns *this. otherwise, returns other.
+    result or_other(const result& other) const&
+    {
+        return this->is_ok() ? *this : other;
+    }
+    result or_other(result&& other) &&
+    {
+        return this->is_ok() ? std::move(*this) : std::move(other);
+    }
+
+    void swap(result<T, E>& other)
+    {
+        result<T, E> tmp(std::move(*this));
+        *this = std::move(other);
+        other = std::move(tmp);
+        return ;
+    }
+
+  private:
+
+    static std::string format_error(std::exception const& excpt)
+    {
+        return std::string(excpt.what());
+    }
+    template<typename U, typename std::enable_if<!std::is_base_of<
+        std::exception, U>::value, std::nullptr_t>::type = nullptr>
+    static std::string format_error(U const& others)
+    {
+        std::ostringstream oss; oss << others;
+        return oss.str();
+    }
+
+    void cleanup() noexcept
+    {
+        if(this->is_ok_) {this->succ.~success_type();}
+        else             {this->fail.~failure_type();}
+        return;
+    }
+
+  private:
+
+    bool      is_ok_;
+    union
+    {
+        success_type succ;
+        failure_type fail;
+    };
+};
+
+template<typename T, typename E>
+void swap(result<T, E>& lhs, result<T, E>& rhs)
+{
+    lhs.swap(rhs);
+    return;
+}
+
+// this might be confusing because it eagerly evaluated, while in the other
+// cases operator && and || are short-circuited.
+//
+// template<typename T, typename E>
+// inline result<T, E>
+// operator&&(const result<T, E>& lhs, const result<T, E>& rhs) noexcept
+// {
+//     return lhs.is_ok() ? rhs : lhs;
+// }
+//
+// template<typename T, typename E>
+// inline result<T, E>
+// operator||(const result<T, E>& lhs, const result<T, E>& rhs) noexcept
+// {
+//     return lhs.is_ok() ? lhs : rhs;
+// }
+
+// ----------------------------------------------------------------------------
+// re-use result<T, E> as a optional<T> with none_t
+
+namespace detail
+{
+struct none_t {};
+inline bool operator==(const none_t&, const none_t&) noexcept {return true;}
+inline bool operator!=(const none_t&, const none_t&) noexcept {return false;}
+inline bool operator< (const none_t&, const none_t&) noexcept {return false;}
+inline bool operator<=(const none_t&, const none_t&) noexcept {return true;}
+inline bool operator> (const none_t&, const none_t&) noexcept {return false;}
+inline bool operator>=(const none_t&, const none_t&) noexcept {return true;}
+template<typename charT, typename traitsT>
+std::basic_ostream<charT, traitsT>&
+operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&)
+{
+    os << "none";
+    return os;
+}
+inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};}
+} // detail
+} // toml11
+#endif// TOML11_RESULT_H
diff --git a/external/toml11/toml/serializer.hpp b/external/toml11/toml/serializer.hpp
new file mode 100644
index 00000000..44fae974
--- /dev/null
+++ b/external/toml11/toml/serializer.hpp
@@ -0,0 +1,772 @@
+//     Copyright Toru Niina 2019.
+// Distributed under the MIT License.
+#ifndef TOML11_SERIALIZER_HPP
+#define TOML11_SERIALIZER_HPP
+#include "value.hpp"
+#include "lexer.hpp"
+#include <limits>
+#include <cstdio>
+
+namespace toml
+{
+
+// This function serialize a key. It checks a string is a bare key and
+// escapes special characters if the string is not compatible to a bare key.
+// ```cpp
+// std::string k("non.bare.key"); // the key itself includes `.`s.
+// std::string formatted = toml::format_key(k);
+// assert(formatted == "\"non.bare.key\"");
+// ```
+//
+// This function is exposed to make it easy to write a user-defined serializer.
+// Since toml restricts characters available in a bare key, generally a string
+// should be escaped. But checking whether a string needs to be surrounded by
+// a `"` and escaping some special character is boring.
+inline std::string format_key(const toml::key& key)
+{
+    detail::location<toml::key> loc(key, key);
+    detail::lex_unquoted_key::invoke(loc);
+    if(loc.iter() == loc.end())
+    {
+        return key; // all the tokens are consumed. the key is unquoted-key.
+    }
+    std::string token("\"");
+    for(const char c : key)
+    {
+        switch(c)
+        {
+            case '\\': {token += "\\\\"; break;}
+            case '\"': {token += "\\\""; break;}
+            case '\b': {token += "\\b";  break;}
+            case '\t': {token += "\\t";  break;}
+            case '\f': {token += "\\f";  break;}
+            case '\n': {token += "\\n";  break;}
+            case '\r': {token += "\\r";  break;}
+            default  : {token += c;      break;}
+        }
+    }
+    token += "\"";
+    return token;
+}
+
+template<typename Comment,
+         template<typename ...> class Table,
+         template<typename ...> class Array>
+struct serializer
+{
+    using value_type           = basic_value<Comment, Table, Array>;
+    using key_type             = typename value_type::key_type            ;
+    using comment_type         = typename value_type::comment_type        ;
+    using boolean_type         = typename value_type::boolean_type        ;
+    using integer_type         = typename value_type::integer_type        ;
+    using floating_type        = typename value_type::floating_type       ;
+    using string_type          = typename value_type::string_type         ;
+    using local_time_type      = typename value_type::local_time_type     ;
+    using local_date_type      = typename value_type::local_date_type     ;
+    using local_datetime_type  = typename value_type::local_datetime_type ;
+    using offset_datetime_type = typename value_type::offset_datetime_type;
+    using array_type           = typename value_type::array_type          ;
+    using table_type           = typename value_type::table_type          ;
+
+    serializer(const std::size_t w              = 80u,
+               const int         float_prec     = std::numeric_limits<toml::floating>::max_digits10,
+               const bool        can_be_inlined = false,
+               const bool        no_comment     = false,
+               std::vector<toml::key> ks        = {})
+        : can_be_inlined_(can_be_inlined), no_comment_(no_comment),
+          float_prec_(float_prec), width_(w), keys_(std::move(ks))
+    {}
+    ~serializer() = default;
+
+    std::string operator()(const boolean_type& b) const
+    {
+        return b ? "true" : "false";
+    }
+    std::string operator()(const integer_type i) const
+    {
+        return std::to_string(i);
+    }
+    std::string operator()(const floating_type f) const
+    {
+        const auto fmt = "%.*g";
+        const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f);
+        // +1 for null character(\0)
+        std::vector<char> buf(static_cast<std::size_t>(bsz + 1), '\0');
+        std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f);
+
+        std::string token(buf.begin(), std::prev(buf.end()));
+        if(token.back() == '.') // 1. => 1.0
+        {
+            token += '0';
+        }
+
+        const auto e = std::find_if(
+            token.cbegin(), token.cend(), [](const char c) noexcept -> bool {
+                return c == 'e' || c == 'E';
+            });
+        const auto has_exponent = (token.cend() != e);
+        const auto has_fraction = (token.cend() != std::find(
+            token.cbegin(), token.cend(), '.'));
+
+        if(!has_exponent && !has_fraction)
+        {
+            // the resulting value does not have any float specific part!
+            token += ".0";
+            return token;
+        }
+        if(!has_exponent)
+        {
+            return token; // there is no exponent part. just return it.
+        }
+#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
+        // Although currently it is not released yet, TOML will allow
+        // zero-prefix in an exponent part such as 1.234e+01.
+        // The following code removes the zero prefixes.
+        // If the feature is activated, the following codes can be skipped.
+        return token;
+#endif
+        // zero-prefix in an exponent is NOT allowed in TOML v0.5.0.
+        // remove it if it exists.
+        bool        sign_exists = false;
+        std::size_t zero_prefix = 0;
+        for(auto iter = std::next(e), iend = token.cend(); iter != iend; ++iter)
+        {
+            if(*iter == '+' || *iter == '-'){sign_exists = true; continue;}
+            if(*iter == '0'){zero_prefix += 1;}
+            else {break;}
+        }
+        if(zero_prefix != 0)
+        {
+            const auto offset = std::distance(token.cbegin(), e) +
+                               (sign_exists ? 2 : 1);
+            token.erase(static_cast<typename std::string::size_type>(offset),
+                        zero_prefix);
+        }
+        return token;
+    }
+    std::string operator()(const string_type& s) const
+    {
+        if(s.kind == string_t::basic)
+        {
+            if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
+            {
+                // if linefeed is contained, make it multiline-string.
+                const std::string open("\"\"\"\n");
+                const std::string close("\\\n\"\"\"");
+                return open + this->escape_ml_basic_string(s.str) + close;
+            }
+
+            // no linefeed. try to make it oneline-string.
+            std::string oneline = this->escape_basic_string(s.str);
+            if(oneline.size() + 2 < width_ || width_ < 2)
+            {
+                const std::string quote("\"");
+                return quote + oneline + quote;
+            }
+
+            // the line is too long compared to the specified width.
+            // split it into multiple lines.
+            std::string token("\"\"\"\n");
+            while(!oneline.empty())
+            {
+                if(oneline.size() < width_)
+                {
+                    token += oneline;
+                    oneline.clear();
+                }
+                else if(oneline.at(width_-2) == '\\')
+                {
+                    token += oneline.substr(0, width_-2);
+                    token += "\\\n";
+                    oneline.erase(0, width_-2);
+                }
+                else
+                {
+                    token += oneline.substr(0, width_-1);
+                    token += "\\\n";
+                    oneline.erase(0, width_-1);
+                }
+            }
+            return token + std::string("\\\n\"\"\"");
+        }
+        else // the string `s` is literal-string.
+        {
+            if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
+               std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
+            {
+                const std::string open("'''\n");
+                const std::string close("'''");
+                return open + s.str + close;
+            }
+            else
+            {
+                const std::string quote("'");
+                return quote + s.str + quote;
+            }
+        }
+    }
+
+    std::string operator()(const local_date_type& d) const
+    {
+        std::ostringstream oss;
+        oss << d;
+        return oss.str();
+    }
+    std::string operator()(const local_time_type& t) const
+    {
+        std::ostringstream oss;
+        oss << t;
+        return oss.str();
+    }
+    std::string operator()(const local_datetime_type& dt) const
+    {
+        std::ostringstream oss;
+        oss << dt;
+        return oss.str();
+    }
+    std::string operator()(const offset_datetime_type& odt) const
+    {
+        std::ostringstream oss;
+        oss << odt;
+        return oss.str();
+    }
+
+    std::string operator()(const array_type& v) const
+    {
+        if(!v.empty() && v.front().is_table())// v is an array of tables
+        {
+            // if it's not inlined, we need to add `[[table.key]]`.
+            // but if it can be inlined,
+            // ```
+            // table.key = [
+            //   {...},
+            //   # comment
+            //   {...},
+            // ]
+            // ```
+            if(this->can_be_inlined_)
+            {
+                std::string token;
+                if(!keys_.empty())
+                {
+                    token += this->serialize_key(keys_.back());
+                    token += " = ";
+                }
+                bool failed = false;
+                token += "[\n";
+                for(const auto& item : v)
+                {
+                    // if an element of the table has a comment, the table
+                    // cannot be inlined.
+                    if(this->has_comment_inside(item.as_table()))
+                    {
+                        failed = true;
+                        break;
+                    }
+                    if(!no_comment_)
+                    {
+                        for(const auto& c : item.comments())
+                        {
+                            token += '#';
+                            token += c;
+                            token += '\n';
+                        }
+                    }
+
+                    const auto t = this->make_inline_table(item.as_table());
+
+                    if(t.size() + 1 > width_ || // +1 for the last comma {...},
+                       std::find(t.cbegin(), t.cend(), '\n') != t.cend())
+                    {
+                        failed = true;
+                        break;
+                    }
+                    token += t;
+                    token += ",\n";
+                }
+                if(!failed)
+                {
+                    token += "]\n";
+                    return token;
+                }
+                // if failed, serialize them as [[array.of.tables]].
+            }
+
+            std::string token;
+            for(const auto& item : v)
+            {
+                if(!no_comment_)
+                {
+                    for(const auto& c : item.comments())
+                    {
+                        token += '#';
+                        token += c;
+                        token += '\n';
+                    }
+                }
+                token += "[[";
+                token += this->serialize_dotted_key(keys_);
+                token += "]]\n";
+                token += this->make_multiline_table(item.as_table());
+            }
+            return token;
+        }
+        if(v.empty())
+        {
+            return std::string("[]");
+        }
+
+        // not an array of tables. normal array.
+        // first, try to make it inline if none of the elements have a comment.
+        if(!this->has_comment_inside(v))
+        {
+            const auto inl = this->make_inline_array(v);
+            if(inl.size() < this->width_ &&
+               std::find(inl.cbegin(), inl.cend(), '\n') == inl.cend())
+            {
+                return inl;
+            }
+        }
+
+        // if the length exceeds this->width_, print multiline array.
+        // key = [
+        //   # ...
+        //   42,
+        //   ...
+        // ]
+        std::string token;
+        std::string current_line;
+        token += "[\n";
+        for(const auto& item : v)
+        {
+            if(!item.comments().empty() && !no_comment_)
+            {
+                // if comment exists, the element must be the only element in the line.
+                // e.g. the following is not allowed.
+                // ```toml
+                // array = [
+                // # comment for what?
+                // 1, 2, 3, 4, 5
+                // ]
+                // ```
+                if(!current_line.empty())
+                {
+                    if(current_line.back() != '\n')
+                    {
+                        current_line += '\n';
+                    }
+                    token += current_line;
+                    current_line.clear();
+                }
+                for(const auto& c : item.comments())
+                {
+                    token += '#';
+                    token += c;
+                    token += '\n';
+                }
+                token += toml::visit(*this, item);
+                if(token.back() == '\n') {token.pop_back();}
+                token += ",\n";
+                continue;
+            }
+            std::string next_elem;
+            next_elem += toml::visit(*this, item);
+
+            // comma before newline.
+            if(next_elem.back() == '\n') {next_elem.pop_back();}
+
+            // if current line does not exceeds the width limit, continue.
+            if(current_line.size() + next_elem.size() + 1 < this->width_)
+            {
+                current_line += next_elem;
+                current_line += ',';
+            }
+            else if(current_line.empty())
+            {
+                // if current line was empty, force put the next_elem because
+                // next_elem is not splittable
+                token += next_elem;
+                token += ",\n";
+                // current_line is kept empty
+            }
+            else // reset current_line
+            {
+                assert(current_line.back() == ',');
+                token += current_line;
+                token += '\n';
+                current_line = next_elem;
+                current_line += ',';
+            }
+        }
+        if(!current_line.empty())
+        {
+            if(current_line.back() != '\n') {current_line += '\n';}
+            token += current_line;
+        }
+        token += "]\n";
+        return token;
+    }
+
+    // templatize for any table-like container
+    std::string operator()(const table_type& v) const
+    {
+        // if an element has a comment, then it can't be inlined.
+        // table = {# how can we write a comment for this? key = "value"}
+        if(this->can_be_inlined_ && !(this->has_comment_inside(v)))
+        {
+            std::string token;
+            if(!this->keys_.empty())
+            {
+                token += this->serialize_key(this->keys_.back());
+                token += " = ";
+            }
+            token += this->make_inline_table(v);
+            if(token.size() < this->width_ &&
+               token.end() == std::find(token.begin(), token.end(), '\n'))
+            {
+                return token;
+            }
+        }
+
+        std::string token;
+        if(!keys_.empty())
+        {
+            token += '[';
+            token += this->serialize_dotted_key(keys_);
+            token += "]\n";
+        }
+        token += this->make_multiline_table(v);
+        return token;
+    }
+
+  private:
+
+    std::string serialize_key(const toml::key& key) const
+    {
+        return ::toml::format_key(key);
+    }
+
+    std::string serialize_dotted_key(const std::vector<toml::key>& keys) const
+    {
+        std::string token;
+        if(keys.empty()){return token;}
+
+        for(const auto& k : keys)
+        {
+            token += this->serialize_key(k);
+            token += '.';
+        }
+        token.erase(token.size() - 1, 1); // remove trailing `.`
+        return token;
+    }
+
+    std::string escape_basic_string(const std::string& s) const
+    {
+        //XXX assuming `s` is a valid utf-8 sequence.
+        std::string retval;
+        for(const char c : s)
+        {
+            switch(c)
+            {
+                case '\\': {retval += "\\\\"; break;}
+                case '\"': {retval += "\\\""; break;}
+                case '\b': {retval += "\\b";  break;}
+                case '\t': {retval += "\\t";  break;}
+                case '\f': {retval += "\\f";  break;}
+                case '\n': {retval += "\\n";  break;}
+                case '\r': {retval += "\\r";  break;}
+                default  : {retval += c;      break;}
+            }
+        }
+        return retval;
+    }
+
+    std::string escape_ml_basic_string(const std::string& s) const
+    {
+        std::string retval;
+        for(auto i=s.cbegin(), e=s.cend(); i!=e; ++i)
+        {
+            switch(*i)
+            {
+                case '\\': {retval += "\\\\"; break;}
+                case '\"': {retval += "\\\""; break;}
+                case '\b': {retval += "\\b";  break;}
+                case '\t': {retval += "\\t";  break;}
+                case '\f': {retval += "\\f";  break;}
+                case '\n': {retval += "\n";   break;}
+                case '\r':
+                {
+                    if(std::next(i) != e && *std::next(i) == '\n')
+                    {
+                        retval += "\r\n";
+                        ++i;
+                    }
+                    else
+                    {
+                        retval += "\\r";
+                    }
+                    break;
+                }
+                default: {retval += *i; break;}
+            }
+        }
+        return retval;
+    }
+
+    // if an element of a table or an array has a comment, it cannot be inlined.
+    bool has_comment_inside(const array_type& a) const noexcept
+    {
+        // if no_comment is set, comments would not be written.
+        if(this->no_comment_) {return false;}
+
+        for(const auto& v : a)
+        {
+            if(!v.comments().empty()) {return true;}
+        }
+        return false;
+    }
+    bool has_comment_inside(const table_type& t) const noexcept
+    {
+        // if no_comment is set, comments would not be written.
+        if(this->no_comment_) {return false;}
+
+        for(const auto& kv : t)
+        {
+            if(!kv.second.comments().empty()) {return true;}
+        }
+        return false;
+    }
+
+    std::string make_inline_array(const array_type& v) const
+    {
+        assert(!has_comment_inside(v));
+        std::string token;
+        token += '[';
+        bool is_first = true;
+        for(const auto& item : v)
+        {
+            if(is_first) {is_first = false;} else {token += ',';}
+            token += visit(serializer(std::numeric_limits<std::size_t>::max(),
+                                      this->float_prec_, true), item);
+        }
+        token += ']';
+        return token;
+    }
+
+    std::string make_inline_table(const table_type& v) const
+    {
+        assert(!has_comment_inside(v));
+        assert(this->can_be_inlined_);
+        std::string token;
+        token += '{';
+        bool is_first = true;
+        for(const auto& kv : v)
+        {
+            // in inline tables, trailing comma is not allowed (toml-lang #569).
+            if(is_first) {is_first = false;} else {token += ',';}
+            token += this->serialize_key(kv.first);
+            token += '=';
+            token += visit(serializer(std::numeric_limits<std::size_t>::max(),
+                                      this->float_prec_, true), kv.second);
+        }
+        token += '}';
+        return token;
+    }
+
+    std::string make_multiline_table(const table_type& v) const
+    {
+        std::string token;
+
+        // print non-table stuff first. because after printing [foo.bar], the
+        // remaining non-table values will be assigned into [foo.bar], not [foo]
+        for(const auto kv : v)
+        {
+            if(kv.second.is_table() || is_array_of_tables(kv.second))
+            {
+                continue;
+            }
+
+            if(!kv.second.comments().empty() && !no_comment_)
+            {
+                for(const auto& c : kv.second.comments())
+                {
+                    token += '#';
+                    token += c;
+                    token += '\n';
+                }
+            }
+            const auto key_and_sep    = this->serialize_key(kv.first) + " = ";
+            const auto residual_width = (this->width_ > key_and_sep.size()) ?
+                                        this->width_ - key_and_sep.size() : 0;
+            token += key_and_sep;
+            token += visit(serializer(residual_width, this->float_prec_, true),
+                           kv.second);
+            if(token.back() != '\n')
+            {
+                token += '\n';
+            }
+        }
+
+        // normal tables / array of tables
+
+        // after multiline table appeared, the other tables cannot be inline
+        // because the table would be assigned into the table.
+        // [foo]
+        // ...
+        // bar = {...} # <- bar will be a member of [foo].
+        bool multiline_table_printed = false;
+        for(const auto& kv : v)
+        {
+            if(!kv.second.is_table() && !is_array_of_tables(kv.second))
+            {
+                continue; // other stuff are already serialized. skip them.
+            }
+
+            std::vector<toml::key> ks(this->keys_);
+            ks.push_back(kv.first);
+
+            auto tmp = visit(serializer(this->width_, this->float_prec_,
+                !multiline_table_printed, this->no_comment_, ks),
+                kv.second);
+
+            if((!multiline_table_printed) &&
+               std::find(tmp.cbegin(), tmp.cend(), '\n') != tmp.cend())
+            {
+                multiline_table_printed = true;
+            }
+            else
+            {
+                // still inline tables only.
+                tmp += '\n';
+            }
+
+            if(!kv.second.comments().empty() && !no_comment_)
+            {
+                for(const auto& c : kv.second.comments())
+                {
+                    token += '#';
+                    token += c;
+                    token += '\n';
+                }
+            }
+            token += tmp;
+        }
+        return token;
+    }
+
+    bool is_array_of_tables(const value_type& v) const
+    {
+        if(!v.is_array()) {return false;}
+        const auto& a = v.as_array();
+        return !a.empty() && a.front().is_table();
+    }
+
+  private:
+
+    bool        can_be_inlined_;
+    bool        no_comment_;
+    int         float_prec_;
+    std::size_t width_;
+    std::vector<toml::key> keys_;
+};
+
+template<typename C,
+         template<typename ...> class M, template<typename ...> class V>
+std::string
+format(const basic_value<C, M, V>& v, std::size_t w = 80u,
+       int fprec = std::numeric_limits<toml::floating>::max_digits10,
+       bool no_comment = false, bool force_inline = false)
+{
+    // if value is a table, it is considered to be a root object.
+    // the root object can't be an inline table.
+    if(v.is_table())
+    {
+        std::ostringstream oss;
+        if(!v.comments().empty())
+        {
+            oss << v.comments();
+            oss << '\n'; // to split the file comment from the first element
+        }
+        oss << visit(serializer<C, M, V>(w, fprec, no_comment, false), v);
+        return oss.str();
+    }
+    return visit(serializer<C, M, V>(w, fprec, force_inline), v);
+}
+
+namespace detail
+{
+template<typename charT, typename traits>
+int comment_index(std::basic_ostream<charT, traits>&)
+{
+    static const int index = std::ios_base::xalloc();
+    return index;
+}
+} // detail
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+nocomment(std::basic_ostream<charT, traits>& os)
+{
+    // by default, it is zero. and by defalut, it shows comments.
+    os.iword(detail::comment_index(os)) = 1;
+    return os;
+}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+showcomment(std::basic_ostream<charT, traits>& os)
+{
+    // by default, it is zero. and by defalut, it shows comments.
+    os.iword(detail::comment_index(os)) = 0;
+    return os;
+}
+
+template<typename charT, typename traits, typename C,
+         template<typename ...> class M, template<typename ...> class V>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const basic_value<C, M, V>& v)
+{
+    // get status of std::setw().
+    const auto w     = static_cast<std::size_t>(os.width());
+    const int  fprec = static_cast<int>(os.precision());
+    os.width(0);
+
+    // by defualt, iword is initialized byl 0. And by default, toml11 outputs
+    // comments. So `0` means showcomment. 1 means nocommnet.
+    const bool no_comment = (1 == os.iword(detail::comment_index(os)));
+
+    if(!no_comment && v.is_table() && !v.comments().empty())
+    {
+        os << v.comments();
+        os << '\n'; // to split the file comment from the first element
+    }
+    // the root object can't be an inline table. so pass `false`.
+    os << visit(serializer<C, M, V>(w, fprec, false, no_comment), v);
+
+    // if v is a non-table value, and has only one comment, then
+    // put a comment just after a value. in the following way.
+    //
+    // ```toml
+    // key = "value" # comment.
+    // ```
+    //
+    // Since the top-level toml object is a table, one who want to put a
+    // non-table toml value must use this in a following way.
+    //
+    // ```cpp
+    // toml::value v;
+    // std::cout << "user-defined-key = " << v << std::endl;
+    // ```
+    //
+    // In this case, it is impossible to put comments before key-value pair.
+    // The only way to preserve comments is to put all of them after a value.
+    if(!no_comment && !v.is_table() && !v.comments().empty())
+    {
+        os << " #";
+        for(const auto& c : v.comments()) {os << c;}
+    }
+    return os;
+}
+
+} // toml
+#endif// TOML11_SERIALIZER_HPP
diff --git a/external/toml11/toml/source_location.hpp b/external/toml11/toml/source_location.hpp
new file mode 100644
index 00000000..f85c51ed
--- /dev/null
+++ b/external/toml11/toml/source_location.hpp
@@ -0,0 +1,86 @@
+//     Copyright Toru Niina 2019.
+// Distributed under the MIT License.
+#ifndef TOML11_SOURCE_LOCATION_HPP
+#define TOML11_SOURCE_LOCATION_HPP
+#include "region.hpp"
+#include <cstdint>
+
+namespace toml
+{
+
+// A struct to contain location in a toml file.
+// The interface imitates std::experimental::source_location,
+// but not completely the same.
+//
+// It would be constructed by toml::value. It can be used to generate
+// user-defined error messages.
+//
+// - std::uint_least32_t line() const noexcept
+//   - returns the line number where the region is on.
+// - std::uint_least32_t column() const noexcept
+//   - returns the column number where the region starts.
+// - std::uint_least32_t region() const noexcept
+//   - returns the size of the region.
+//
+// +-- line()       +-- region of interest (region() == 9)
+// v            .---+---.
+// 12 | value = "foo bar"
+//              ^
+//              +-- column()
+//
+// - std::string const& file_name() const noexcept;
+//   - name of the file.
+// - std::string const& line_str() const noexcept;
+//   - the whole line that contains the region of interest.
+//
+struct source_location
+{
+  public:
+
+    source_location()
+        : line_num_(0), column_num_(0), region_size_(0),
+          file_name_("unknown file"), line_str_("")
+    {}
+
+    explicit source_location(const detail::region_base* reg)
+        : line_num_(0), column_num_(0), region_size_(0),
+          file_name_("unknown file"), line_str_("")
+    {
+        if(reg)
+        {
+            if(reg->line_num() != detail::region_base().line_num())
+            {
+                line_num_ = static_cast<std::uint_least32_t>(
+                        std::stoul(reg->line_num()));
+            }
+            column_num_  = static_cast<std::uint_least32_t>(reg->before() + 1);
+            region_size_ = static_cast<std::uint_least32_t>(reg->size());
+            file_name_   = reg->name();
+            line_str_    = reg->line();
+        }
+    }
+
+    ~source_location() = default;
+    source_location(source_location const&) = default;
+    source_location(source_location &&)     = default;
+    source_location& operator=(source_location const&) = default;
+    source_location& operator=(source_location &&)     = default;
+
+    std::uint_least32_t line()      const noexcept {return line_num_;}
+    std::uint_least32_t column()    const noexcept {return column_num_;}
+    std::uint_least32_t region()    const noexcept {return region_size_;}
+
+    std::string const&  file_name() const noexcept {return file_name_;}
+    std::string const&  line_str()  const noexcept {return line_str_;}
+
+  private:
+
+    std::uint_least32_t line_num_;
+    std::uint_least32_t column_num_;
+    std::uint_least32_t region_size_;
+    std::string         file_name_;
+    std::string         line_str_;
+};
+
+} // toml
+#endif// TOML11_SOURCE_LOCATION_HPP
diff --git a/external/toml11/toml/storage.hpp b/external/toml11/toml/storage.hpp
new file mode 100644
index 00000000..30408f97
--- /dev/null
+++ b/external/toml11/toml/storage.hpp
@@ -0,0 +1,44 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_STORAGE_HPP
+#define TOML11_STORAGE_HPP
+#include "utility.hpp"
+
+namespace toml
+{
+namespace detail
+{
+
+// this contains pointer and deep-copy the content if copied.
+// to avoid recursive pointer.
+template<typename T>
+struct storage
+{
+    using value_type = T;
+
+    storage(value_type const& v): ptr(toml::make_unique<T>(v)) {}
+    storage(value_type&&      v): ptr(toml::make_unique<T>(std::move(v))) {}
+    ~storage() = default;
+
+    storage(const storage& rhs): ptr(toml::make_unique<T>(*rhs.ptr)) {}
+    storage& operator=(const storage& rhs)
+    {
+        this->ptr = toml::make_unique<T>(*rhs.ptr);
+        return *this;
+    }
+    storage(storage&&) = default;
+    storage& operator=(storage&&) = default;
+
+    bool is_ok() const noexcept {return static_cast<bool>(ptr);}
+
+    value_type&       value() &      noexcept {return *ptr;}
+    value_type const& value() const& noexcept {return *ptr;}
+    value_type&&      value() &&     noexcept {return std::move(*ptr);}
+
+  private:
+    std::unique_ptr<value_type> ptr;
+};
+
+} // detail
+} // toml
+#endif// TOML11_STORAGE_HPP
diff --git a/external/toml11/toml/string.hpp b/external/toml11/toml/string.hpp
new file mode 100644
index 00000000..0551ccdc
--- /dev/null
+++ b/external/toml11/toml/string.hpp
@@ -0,0 +1,222 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_STRING_HPP
+#define TOML11_STRING_HPP
+#include <algorithm>
+#include <string>
+#include <cstdint>
+#if __cplusplus >= 201703L
+#if __has_include(<string_view>)
+#include <string_view>
+#endif
+#endif
+
+namespace toml
+{
+
+enum class string_t : std::uint8_t
+{
+    basic   = 0,
+    literal = 1,
+};
+
+struct string
+{
+    string()  = default;
+    ~string() = default;
+    string(const string& s) = default;
+    string(string&& s)      = default;
+    string& operator=(const string& s) = default;
+    string& operator=(string&& s)      = default;
+
+    string(const std::string& s): kind(string_t::basic), str(s){}
+    string(const std::string& s, string_t k):   kind(k), str(s){}
+    string(const char* s):        kind(string_t::basic), str(s){}
+    string(const char* s,        string_t k):   kind(k), str(s){}
+
+    string(std::string&& s): kind(string_t::basic), str(std::move(s)){}
+    string(std::string&& s, string_t k):   kind(k), str(std::move(s)){}
+
+    string& operator=(const std::string& s)
+    {kind = string_t::basic; str = s; return *this;}
+    string& operator=(std::string&& s)
+    {kind = string_t::basic; str = std::move(s); return *this;}
+
+    operator std::string&       () &      noexcept {return str;}
+    operator std::string const& () const& noexcept {return str;}
+    operator std::string&&      () &&     noexcept {return std::move(str);}
+
+    string& operator+=(const char*        rhs) {str += rhs; return *this;}
+    string& operator+=(const char         rhs) {str += rhs; return *this;}
+    string& operator+=(const std::string& rhs) {str += rhs; return *this;}
+    string& operator+=(const string&      rhs) {str += rhs.str; return *this;}
+
+#if __cplusplus >= 201703L
+    explicit string(std::string_view s): kind(string_t::basic), str(s){}
+    string(std::string_view s, string_t k): kind(k), str(s){}
+
+    string& operator=(std::string_view s)
+    {kind = string_t::basic; str = s; return *this;}
+
+    explicit operator std::string_view() const noexcept
+    {return std::string_view(str);}
+
+    string& operator+=(const std::string_view& rhs) {str += rhs; return *this;}
+#endif
+
+    string_t    kind;
+    std::string str;
+};
+
+inline bool operator==(const string& lhs, const string& rhs)
+{
+    return lhs.kind == rhs.kind && lhs.str == rhs.str;
+}
+inline bool operator!=(const string& lhs, const string& rhs)
+{
+    return !(lhs == rhs);
+}
+inline bool operator<(const string& lhs, const string& rhs)
+{
+    return (lhs.kind == rhs.kind) ? (lhs.str < rhs.str) : (lhs.kind < rhs.kind);
+}
+inline bool operator>(const string& lhs, const string& rhs)
+{
+    return rhs < lhs;
+}
+inline bool operator<=(const string& lhs, const string& rhs)
+{
+    return !(rhs < lhs);
+}
+inline bool operator>=(const string& lhs, const string& rhs)
+{
+    return !(lhs < rhs);
+}
+
+inline bool
+operator==(const string& lhs, const std::string& rhs) {return lhs.str == rhs;}
+inline bool
+operator!=(const string& lhs, const std::string& rhs) {return lhs.str != rhs;}
+inline bool
+operator< (const string& lhs, const std::string& rhs) {return lhs.str <  rhs;}
+inline bool
+operator> (const string& lhs, const std::string& rhs) {return lhs.str >  rhs;}
+inline bool
+operator<=(const string& lhs, const std::string& rhs) {return lhs.str <= rhs;}
+inline bool
+operator>=(const string& lhs, const std::string& rhs) {return lhs.str >= rhs;}
+
+inline bool
+operator==(const std::string& lhs, const string& rhs) {return lhs == rhs.str;}
+inline bool
+operator!=(const std::string& lhs, const string& rhs) {return lhs != rhs.str;}
+inline bool
+operator< (const std::string& lhs, const string& rhs) {return lhs <  rhs.str;}
+inline bool
+operator> (const std::string& lhs, const string& rhs) {return lhs >  rhs.str;}
+inline bool
+operator<=(const std::string& lhs, const string& rhs) {return lhs <= rhs.str;}
+inline bool
+operator>=(const std::string& lhs, const string& rhs) {return lhs >= rhs.str;}
+
+inline bool
+operator==(const string& lhs, const char* rhs) {return lhs.str == std::string(rhs);}
+inline bool
+operator!=(const string& lhs, const char* rhs) {return lhs.str != std::string(rhs);}
+inline bool
+operator< (const string& lhs, const char* rhs) {return lhs.str <  std::string(rhs);}
+inline bool
+operator> (const string& lhs, const char* rhs) {return lhs.str >  std::string(rhs);}
+inline bool
+operator<=(const string& lhs, const char* rhs) {return lhs.str <= std::string(rhs);}
+inline bool
+operator>=(const string& lhs, const char* rhs) {return lhs.str >= std::string(rhs);}
+
+inline bool
+operator==(const char* lhs, const string& rhs) {return std::string(lhs) == rhs.str;}
+inline bool
+operator!=(const char* lhs, const string& rhs) {return std::string(lhs) != rhs.str;}
+inline bool
+operator< (const char* lhs, const string& rhs) {return std::string(lhs) <  rhs.str;}
+inline bool
+operator> (const char* lhs, const string& rhs) {return std::string(lhs) >  rhs.str;}
+inline bool
+operator<=(const char* lhs, const string& rhs) {return std::string(lhs) <= rhs.str;}
+inline bool
+operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.str;}
+
+template<typename charT, typename traits>
+std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, const string& s)
+{
+    if(s.kind == string_t::basic)
+    {
+        if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
+        {
+            // it contains newline. make it multiline string.
+            os << "\"\"\"\n";
+            for(auto i=s.str.cbegin(), e=s.str.cend(); i!=e; ++i)
+            {
+                switch(*i)
+                {
+                    case '\\': {os << "\\\\"; break;}
+                    case '\"': {os << "\\\""; break;}
+                    case '\b': {os << "\\b";  break;}
+                    case '\t': {os << "\\t";  break;}
+                    case '\f': {os << "\\f";  break;}
+                    case '\n': {os << '\n';   break;}
+                    case '\r':
+                    {
+                        // since it is a multiline string,
+                        // CRLF is not needed to be escaped.
+                        if(std::next(i) != e && *std::next(i) == '\n')
+                        {
+                            os << "\r\n";
+                            ++i;
+                        }
+                        else
+                        {
+                            os << "\\r";
+                        }
+                        break;
+                    }
+                    default: {os << *i; break;}
+                }
+            }
+            os << "\\\n\"\"\"";
+            return os;
+        }
+        // no newline. make it inline.
+        os << "\"";
+        for(const auto c : s.str)
+        {
+            switch(c)
+            {
+                case '\\': {os << "\\\\"; break;}
+                case '\"': {os << "\\\""; break;}
+                case '\b': {os << "\\b";  break;}
+                case '\t': {os << "\\t";  break;}
+                case '\f': {os << "\\f";  break;}
+                case '\n': {os << "\\n";  break;}
+                case '\r': {os << "\\r";  break;}
+                default  : {os << c;      break;}
+            }
+        }
+        os << "\"";
+        return os;
+    }
+    // the string `s` is literal-string.
+    if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
+       std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
+    {
+        // contains newline or single quote. make it multiline.
+        os << "'''\n" << s.str << "'''";
+        return os;
+    }
+    // normal literal string
+    os << '\'' << s.str << '\'';
+    return os;
+}
+
+} // toml
+#endif// TOML11_STRING_H
diff --git a/external/toml11/toml/traits.hpp b/external/toml11/toml/traits.hpp
new file mode 100644
index 00000000..c0c5ee98
--- /dev/null
+++ b/external/toml11/toml/traits.hpp
@@ -0,0 +1,258 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_TRAITS_HPP
+#define TOML11_TRAITS_HPP
+#include <type_traits>
+#include <utility>
+#include <chrono>
+#include <tuple>
+#include <string>
+#if __cplusplus >= 201703L
+#if __has_include(<string_view>)
+#include <string_view>
+#endif // has_include(<string_view>)
+#endif // cplusplus   >= C++17
+
+namespace toml
+{
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+class basic_value;
+
+namespace detail
+{
+// ---------------------------------------------------------------------------
+// check whether type T is a kind of container/map class
+
+struct has_iterator_impl
+{
+    template<typename T> static std::true_type  check(typename T::iterator*);
+    template<typename T> static std::false_type check(...);
+};
+struct has_value_type_impl
+{
+    template<typename T> static std::true_type  check(typename T::value_type*);
+    template<typename T> static std::false_type check(...);
+};
+struct has_key_type_impl
+{
+    template<typename T> static std::true_type  check(typename T::key_type*);
+    template<typename T> static std::false_type check(...);
+};
+struct has_mapped_type_impl
+{
+    template<typename T> static std::true_type  check(typename T::mapped_type*);
+    template<typename T> static std::false_type check(...);
+};
+struct has_resize_method_impl
+{
+    constexpr static std::size_t dummy=0;
+    template<typename T> static std::true_type  check(decltype(std::declval<T>().resize(dummy))*);
+    template<typename T> static std::false_type check(...);
+};
+
+struct is_comparable_impl
+{
+    template<typename T> static std::true_type  check(decltype(std::declval<T>() < std::declval<T>())*);
+    template<typename T> static std::false_type check(...);
+};
+
+struct has_from_toml_method_impl
+{
+    template<typename T, typename C,
+             template<typename ...> class Tb, template<typename ...> class A>
+    static std::true_type  check(
+        decltype(std::declval<T>().from_toml(
+                std::declval<::toml::basic_value<C, Tb, A>>()))*);
+
+    template<typename T, typename C,
+             template<typename ...> class Tb, template<typename ...> class A>
+    static std::false_type check(...);
+};
+struct has_into_toml_method_impl
+{
+    template<typename T>
+    static std::true_type  check(decltype(std::declval<T>().into_toml())*);
+    template<typename T>
+    static std::false_type check(...);
+};
+
+/// Intel C++ compiler can not use decltype in parent class declaration, here
+/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076
+#ifdef __INTEL_COMPILER
+#define decltype(...) std::enable_if<true, decltype(__VA_ARGS__)>::type
+#endif
+
+template<typename T>
+struct has_iterator    : decltype(has_iterator_impl::check<T>(nullptr)){};
+template<typename T>
+struct has_value_type  : decltype(has_value_type_impl::check<T>(nullptr)){};
+template<typename T>
+struct has_key_type    : decltype(has_key_type_impl::check<T>(nullptr)){};
+template<typename T>
+struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
+template<typename T>
+struct has_resize_method : decltype(has_resize_method_impl::check<T>(nullptr)){};
+template<typename T>
+struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){};
+
+template<typename T, typename C,
+         template<typename ...> class Tb, template<typename ...> class A>
+struct has_from_toml_method
+: decltype(has_from_toml_method_impl::check<T, C, Tb, A>(nullptr)){};
+
+template<typename T>
+struct has_into_toml_method
+: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
+
+#ifdef __INTEL_COMPILER
+#undef decltype(...)
+#endif
+
+// ---------------------------------------------------------------------------
+// C++17 and/or/not
+
+template<typename ...> struct conjunction : std::true_type{};
+template<typename T>   struct conjunction<T> : T{};
+template<typename T, typename ... Ts>
+struct conjunction<T, Ts...> :
+    std::conditional<static_cast<bool>(T::value), conjunction<Ts...>, T>::type
+{};
+
+template<typename ...> struct disjunction : std::false_type{};
+template<typename T>   struct disjunction<T> : T {};
+template<typename T, typename ... Ts>
+struct disjunction<T, Ts...> :
+    std::conditional<static_cast<bool>(T::value), T, disjunction<Ts...>>::type
+{};
+
+template<typename T>
+struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
+
+// ---------------------------------------------------------------------------
+// type checkers
+
+template<typename T> struct is_std_pair : std::false_type{};
+template<typename T1, typename T2>
+struct is_std_pair<std::pair<T1, T2>> : std::true_type{};
+
+template<typename T> struct is_std_tuple : std::false_type{};
+template<typename ... Ts>
+struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};
+
+template<typename T> struct is_chrono_duration: std::false_type{};
+template<typename Rep, typename Period>
+struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
+
+template<typename T>
+struct is_map : conjunction< // map satisfies all the following conditions
+    has_iterator<T>,         // has T::iterator
+    has_value_type<T>,       // has T::value_type
+    has_key_type<T>,         // has T::key_type
+    has_mapped_type<T>       // has T::mapped_type
+    >{};
+template<typename T> struct is_map<T&>                : is_map<T>{};
+template<typename T> struct is_map<T const&>          : is_map<T>{};
+template<typename T> struct is_map<T volatile&>       : is_map<T>{};
+template<typename T> struct is_map<T const volatile&> : is_map<T>{};
+
+template<typename T>
+struct is_container : conjunction<
+    negation<is_map<T>>,                         // not a map
+    negation<std::is_same<T, std::string>>,      // not a std::string
+#if __cplusplus >= 201703L
+    negation<std::is_same<T, std::string_view>>, // not a std::string_view
+#endif
+    has_iterator<T>,                             // has T::iterator
+    has_value_type<T>                            // has T::value_type
+    >{};
+template<typename T> struct is_container<T&>                : is_container<T>{};
+template<typename T> struct is_container<T const&>          : is_container<T>{};
+template<typename T> struct is_container<T volatile&>       : is_container<T>{};
+template<typename T> struct is_container<T const volatile&> : is_container<T>{};
+
+template<typename T>
+struct is_basic_value: std::false_type{};
+template<typename T> struct is_basic_value<T&>                : is_basic_value<T>{};
+template<typename T> struct is_basic_value<T const&>          : is_basic_value<T>{};
+template<typename T> struct is_basic_value<T volatile&>       : is_basic_value<T>{};
+template<typename T> struct is_basic_value<T const volatile&> : is_basic_value<T>{};
+template<typename C, template<typename ...> class M, template<typename ...> class V>
+struct is_basic_value<::toml::basic_value<C, M, V>>: std::true_type{};
+
+// ---------------------------------------------------------------------------
+// C++14 index_sequence
+
+template<std::size_t ... Ns> struct index_sequence{};
+
+template<typename IS, std::size_t N> struct push_back_index_sequence{};
+template<std::size_t N, std::size_t ... Ns>
+struct push_back_index_sequence<index_sequence<Ns...>, N>
+{
+    typedef index_sequence<Ns..., N> type;
+};
+
+template<std::size_t N>
+struct index_sequence_maker
+{
+    typedef typename push_back_index_sequence<
+        typename index_sequence_maker<N-1>::type, N>::type type;
+};
+template<>
+struct index_sequence_maker<0>
+{
+    typedef index_sequence<0> type;
+};
+template<std::size_t N>
+using make_index_sequence = typename index_sequence_maker<N-1>::type;
+
+// ---------------------------------------------------------------------------
+// C++14 enable_if_t
+template<bool B, typename T>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+// ---------------------------------------------------------------------------
+// return_type_of_t
+
+#if __cplusplus >= 201703L
+
+template<typename F, typename ... Args>
+using return_type_of_t = std::invoke_result_t<F, Args...>;
+
+#else
+// result_of is deprecated after C++17
+template<typename F, typename ... Args>
+using return_type_of_t = typename std::result_of<F(Args...)>::type;
+
+#endif
+
+// ---------------------------------------------------------------------------
+// is_string_literal
+//
+// to use this, pass `typename remove_reference<T>::type` to T.
+
+template<typename T>
+struct is_string_literal:
+disjunction<
+    std::is_same<const char*, T>,
+    conjunction<
+        std::is_array<T>,
+        std::is_same<const char, typename std::remove_extent<T>::type>
+        >
+    >{};
+
+// ---------------------------------------------------------------------------
+// C++20 remove_cvref_t
+
+template<typename T>
+struct remove_cvref
+{
+    using type = typename std::remove_cv<
+        typename std::remove_reference<T>::type>::type;
+};
+
+template<typename T>
+using remove_cvref_t = typename remove_cvref<T>::type;
+
+}// detail
+}//toml
+#endif // TOML_TRAITS
diff --git a/external/toml11/toml/types.hpp b/external/toml11/toml/types.hpp
new file mode 100644
index 00000000..b289d2d3
--- /dev/null
+++ b/external/toml11/toml/types.hpp
@@ -0,0 +1,149 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_TYPES_HPP
+#define TOML11_TYPES_HPP
+#include "datetime.hpp"
+#include "string.hpp"
+#include "traits.hpp"
+#include "comments.hpp"
+#include <vector>
+#include <unordered_map>
+
+namespace toml
+{
+
+template<typename Comment, // discard/preserve_comment
+         template<typename ...> class Table, // map-like class
+         template<typename ...> class Array> // vector-like class
+class basic_value;
+
+using character = char;
+using key = std::string;
+
+using boolean        = bool;
+using integer        = std::int64_t;
+using floating       = double; // "float" is a keyward, cannot use it here.
+// the following stuffs are structs defined here, so aliases are not needed.
+// - string
+// - offset_datetime
+// - offset_datetime
+// - local_datetime
+// - local_date
+// - local_time
+
+// default toml::value and default array/table. these are defined after defining
+// basic_value itself.
+// using value = basic_value<discard_comments, std::unordered_map, std::vector>;
+// using array = typename value::array_type;
+// using table = typename value::table_type;
+
+enum class value_t : std::uint8_t
+{
+    empty           =  0,
+    boolean         =  1,
+    integer         =  2,
+    floating        =  3,
+    string          =  4,
+    offset_datetime =  5,
+    local_datetime  =  6,
+    local_date      =  7,
+    local_time      =  8,
+    array           =  9,
+    table           = 10,
+};
+
+template<typename charT, typename traits>
+inline std::basic_ostream<charT, traits>&
+operator<<(std::basic_ostream<charT, traits>& os, value_t t)
+{
+    switch(t)
+    {
+        case value_t::boolean         : os << "boolean";         return os;
+        case value_t::integer         : os << "integer";         return os;
+        case value_t::floating        : os << "floating";        return os;
+        case value_t::string          : os << "string";          return os;
+        case value_t::offset_datetime : os << "offset_datetime"; return os;
+        case value_t::local_datetime  : os << "local_datetime";  return os;
+        case value_t::local_date      : os << "local_date";      return os;
+        case value_t::local_time      : os << "local_time";      return os;
+        case value_t::array           : os << "array";           return os;
+        case value_t::table           : os << "table";           return os;
+        case value_t::empty           : os << "empty";           return os;
+        default                       : os << "unknown";         return os;
+    }
+}
+
+template<typename charT = char,
+         typename traits = std::char_traits<charT>,
+         typename alloc = std::allocator<charT>>
+inline std::basic_string<charT, traits, alloc> stringize(value_t t)
+{
+    std::basic_ostringstream<charT, traits, alloc> oss;
+    oss << t;
+    return oss.str();
+}
+
+namespace detail
+{
+
+// helper to define a type that represents a value_t value.
+template<value_t V>
+using value_t_constant = std::integral_constant<value_t, V>;
+
+// meta-function that convertes from value_t to the exact toml type that corresponds to.
+// It takes toml::basic_value type because array and table types depend on it.
+template<value_t t, typename Value> struct enum_to_type                      {using type = void                      ;};
+template<typename Value> struct enum_to_type<value_t::empty          , Value>{using type = void                      ;};
+template<typename Value> struct enum_to_type<value_t::boolean        , Value>{using type = boolean                   ;};
+template<typename Value> struct enum_to_type<value_t::integer        , Value>{using type = integer                   ;};
+template<typename Value> struct enum_to_type<value_t::floating       , Value>{using type = floating                  ;};
+template<typename Value> struct enum_to_type<value_t::string         , Value>{using type = string                    ;};
+template<typename Value> struct enum_to_type<value_t::offset_datetime, Value>{using type = offset_datetime           ;};
+template<typename Value> struct enum_to_type<value_t::local_datetime , Value>{using type = local_datetime            ;};
+template<typename Value> struct enum_to_type<value_t::local_date     , Value>{using type = local_date                ;};
+template<typename Value> struct enum_to_type<value_t::local_time     , Value>{using type = local_time                ;};
+template<typename Value> struct enum_to_type<value_t::array          , Value>{using type = typename Value::array_type;};
+template<typename Value> struct enum_to_type<value_t::table          , Value>{using type = typename Value::table_type;};
+
+// meta-function that converts from an exact toml type to the enum that corresponds to.
+template<typename T, typename Value>
+struct type_to_enum : std::conditional<
+    std::is_same<T, typename Value::array_type>::value, // if T == array_type,
+    value_t_constant<value_t::array>,                   // then value_t::array
+    typename std::conditional<                          // else...
+        std::is_same<T, typename Value::table_type>::value, // if T == table_type
+        value_t_constant<value_t::table>,               // then value_t::table
+        value_t_constant<value_t::empty>                // else value_t::empty
+        >::type
+    >::type {};
+template<typename Value> struct type_to_enum<boolean        , Value>: value_t_constant<value_t::boolean        > {};
+template<typename Value> struct type_to_enum<integer        , Value>: value_t_constant<value_t::integer        > {};
+template<typename Value> struct type_to_enum<floating       , Value>: value_t_constant<value_t::floating       > {};
+template<typename Value> struct type_to_enum<string         , Value>: value_t_constant<value_t::string         > {};
+template<typename Value> struct type_to_enum<offset_datetime, Value>: value_t_constant<value_t::offset_datetime> {};
+template<typename Value> struct type_to_enum<local_datetime , Value>: value_t_constant<value_t::local_datetime > {};
+template<typename Value> struct type_to_enum<local_date     , Value>: value_t_constant<value_t::local_date     > {};
+template<typename Value> struct type_to_enum<local_time     , Value>: value_t_constant<value_t::local_time     > {};
+
+// meta-function that checks the type T is the same as one of the toml::* types.
+template<typename T, typename Value>
+struct is_exact_toml_type : disjunction<
+    std::is_same<T, boolean        >,
+    std::is_same<T, integer        >,
+    std::is_same<T, floating       >,
+    std::is_same<T, string         >,
+    std::is_same<T, offset_datetime>,
+    std::is_same<T, local_datetime >,
+    std::is_same<T, local_date     >,
+    std::is_same<T, local_time     >,
+    std::is_same<T, typename Value::array_type>,
+    std::is_same<T, typename Value::table_type>
+    >{};
+template<typename T, typename V> struct is_exact_toml_type<T&, V>               : is_exact_toml_type<T, V>{};
+template<typename T, typename V> struct is_exact_toml_type<T const&, V>         : is_exact_toml_type<T, V>{};
+template<typename T, typename V> struct is_exact_toml_type<T volatile&, V>      : is_exact_toml_type<T, V>{};
+template<typename T, typename V> struct is_exact_toml_type<T const volatile&, V>: is_exact_toml_type<T, V>{};
+
+} // detail
+} // toml
+#endif// TOML11_TYPES_H
diff --git a/external/toml11/toml/utility.hpp b/external/toml11/toml/utility.hpp
new file mode 100644
index 00000000..b6414e7f
--- /dev/null
+++ b/external/toml11/toml/utility.hpp
@@ -0,0 +1,89 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_UTILITY_HPP
+#define TOML11_UTILITY_HPP
+#include "traits.hpp"
+#include <utility>
+#include <memory>
+#include <sstream>
+
+#if __cplusplus >= 201402L
+#  define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]]
+#elif defined(__GNUC__)
+#  define TOML11_MARK_AS_DEPRECATED(msg) __attribute__((deprecated(msg)))
+#elif defined(_MSC_VER)
+#  define TOML11_MARK_AS_DEPRECATED(msg) __declspec(deprecated(msg))
+#else
+#  define TOML11_MARK_AS_DEPRECATED
+#endif
+
+namespace toml
+{
+
+template<typename T, typename ... Ts>
+inline std::unique_ptr<T> make_unique(Ts&& ... args)
+{
+    return std::unique_ptr<T>(new T(std::forward<Ts>(args)...));
+}
+
+namespace detail
+{
+
+template<typename T>
+inline void resize_impl(T& container, std::size_t N, std::true_type)
+{
+    container.resize(N);
+    return ;
+}
+
+template<typename T>
+inline void resize_impl(T& container, std::size_t N, std::false_type)
+{
+    if(container.size() >= N) {return;}
+
+    throw std::invalid_argument("not resizable type");
+}
+
+} // detail
+
+template<typename T>
+inline void resize(T& container, std::size_t N)
+{
+    if(container.size() == N) {return;}
+
+    return detail::resize_impl(container, N, detail::has_resize_method<T>());
+}
+
+namespace detail
+{
+inline std::string concat_to_string_impl(std::ostringstream& oss)
+{
+    return oss.str();
+}
+template<typename T, typename ... Ts>
+std::string concat_to_string_impl(std::ostringstream& oss, T&& head, Ts&& ... tail)
+{
+    oss << std::forward<T>(head);
+    return concat_to_string_impl(oss, std::forward<Ts>(tail) ... );
+}
+} // detail
+
+template<typename ... Ts>
+std::string concat_to_string(Ts&& ... args)
+{
+    std::ostringstream oss;
+    oss << std::boolalpha << std::fixed;
+    return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...);
+}
+
+template<typename T, typename U>
+T from_string(const std::string& str, U&& opt)
+{
+    T v(static_cast<T>(std::forward<U>(opt)));
+    std::istringstream iss(str);
+    iss >> v;
+    return v;
+}
+
+}// toml
+#endif // TOML11_UTILITY
diff --git a/external/toml11/toml/value.hpp b/external/toml11/toml/value.hpp
new file mode 100644
index 00000000..e2f5cf8c
--- /dev/null
+++ b/external/toml11/toml/value.hpp
@@ -0,0 +1,1955 @@
+//     Copyright Toru Niina 2017.
+// Distributed under the MIT License.
+#ifndef TOML11_VALUE_HPP
+#define TOML11_VALUE_HPP
+#include "traits.hpp"
+#include "into.hpp"
+#include "utility.hpp"
+#include "exception.hpp"
+#include "storage.hpp"
+#include "region.hpp"
+#include "types.hpp"
+#include "source_location.hpp"
+#include "comments.hpp"
+#include <cassert>
+
+namespace toml
+{
+
+namespace detail
+{
+
+// to show error messages. not recommended for users.
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+region_base const& get_region(const basic_value<C, T, A>&);
+template<typename Region,
+         typename C, template<typename ...> class T, template<typename ...> class A>
+void change_region(basic_value<C, T, A>&, Region&&);
+
+template<value_t Expected,
+         typename C, template<typename ...> class T, template<typename ...> class A>
+[[noreturn]] inline void
+throw_bad_cast(value_t actual, const ::toml::basic_value<C, T, A>& v)
+{
+    throw type_error(detail::format_underline(concat_to_string(
+        "[error] toml::value bad_cast to ", Expected), {
+            {std::addressof(get_region(v)),
+             concat_to_string("the actual type is ", actual)}
+        }), v.location());
+}
+
+// switch by `value_t` and call the corresponding `value::as_xxx()`. {{{
+template<value_t T>
+struct switch_cast {};
+template<>
+struct switch_cast<value_t::boolean>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::boolean& invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_boolean();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::boolean const& invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_boolean();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::boolean&& invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_boolean();
+    }
+};
+template<>
+struct switch_cast<value_t::integer>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::integer& invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_integer();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::integer const& invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_integer();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::integer&& invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_integer();
+    }
+};
+template<>
+struct switch_cast<value_t::floating>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::floating& invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_floating();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::floating const& invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_floating();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::floating&& invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_floating();
+    }
+};
+template<>
+struct switch_cast<value_t::string>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::string& invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_string();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::string const& invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_string();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::string&& invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_string();
+    }
+};
+template<>
+struct switch_cast<value_t::offset_datetime>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::offset_datetime& invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_offset_datetime();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::offset_datetime const& invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_offset_datetime();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::offset_datetime&& invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_offset_datetime();
+    }
+};
+template<>
+struct switch_cast<value_t::local_datetime>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_datetime& invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_local_datetime();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_datetime const& invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_local_datetime();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_datetime&& invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_local_datetime();
+    }
+};
+template<>
+struct switch_cast<value_t::local_date>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_date& invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_local_date();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_date const& invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_local_date();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_date&& invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_local_date();
+    }
+};
+template<>
+struct switch_cast<value_t::local_time>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_time& invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_local_time();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_time const& invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_local_time();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static ::toml::local_time&& invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_local_time();
+    }
+};
+template<>
+struct switch_cast<value_t::array>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static typename basic_value<C, T, A>::array_type&
+    invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_array();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static typename basic_value<C, T, A>::array_type const&
+    invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_array();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static typename basic_value<C, T, A>::array_type &&
+    invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_array();
+    }
+};
+template<>
+struct switch_cast<value_t::table>
+{
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static typename basic_value<C, T, A>::table_type&
+    invoke(basic_value<C, T, A>& v) noexcept
+    {
+        return v.as_table();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static typename basic_value<C, T, A>::table_type const&
+    invoke(basic_value<C, T, A> const& v) noexcept
+    {
+        return v.as_table();
+    }
+    template<typename C, template<typename ...> class T, template<typename ...> class A>
+    static typename basic_value<C, T, A>::table_type &&
+    invoke(basic_value<C, T, A>&& v) noexcept
+    {
+        return std::move(v).as_table();
+    }
+}; // }}}
+
+}// detail
+
+template<typename Comment, // discard/preserve_comment
+         template<typename ...> class Table = std::unordered_map,
+         template<typename ...> class Array = std::vector>
+class basic_value
+{
+    template<typename T, typename U>
+    static void assigner(T& dst, U&& v)
+    {
+        const auto tmp = ::new(std::addressof(dst)) T(std::forward<U>(v));
+        assert(tmp == std::addressof(dst));
+        (void)tmp;
+    }
+
+    using region_base = detail::region_base;
+
+    template<typename C, template<typename ...> class T,
+             template<typename ...> class A>
+    friend class basic_value;
+
+  public:
+
+    using comment_type         = Comment;
+    using key_type             = ::toml::key;
+    using value_type           = basic_value<comment_type, Table, Array>;
+    using boolean_type         = ::toml::boolean;
+    using integer_type         = ::toml::integer;
+    using floating_type        = ::toml::floating;
+    using string_type          = ::toml::string;
+    using local_time_type      = ::toml::local_time;
+    using local_date_type      = ::toml::local_date;
+    using local_datetime_type  = ::toml::local_datetime;
+    using offset_datetime_type = ::toml::offset_datetime;
+    using array_type           = Array<value_type>;
+    using table_type           = Table<key_type, value_type>;
+
+  public:
+
+    basic_value() noexcept
+        : type_(value_t::empty),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {}
+    ~basic_value() noexcept {this->cleanup();}
+
+    basic_value(const basic_value& v)
+        : type_(v.type()), region_info_(v.region_info_), comments_(v.comments_)
+    {
+        switch(v.type())
+        {
+            case value_t::boolean        : assigner(boolean_        , v.boolean_        ); break;
+            case value_t::integer        : assigner(integer_        , v.integer_        ); break;
+            case value_t::floating       : assigner(floating_       , v.floating_       ); break;
+            case value_t::string         : assigner(string_         , v.string_         ); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+            case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+            case value_t::local_date     : assigner(local_date_     , v.local_date_     ); break;
+            case value_t::local_time     : assigner(local_time_     , v.local_time_     ); break;
+            case value_t::array          : assigner(array_          , v.array_          ); break;
+            case value_t::table          : assigner(table_          , v.table_          ); break;
+            default: break;
+        }
+    }
+    basic_value(basic_value&& v)
+        : type_(v.type()), region_info_(std::move(v.region_info_)),
+          comments_(std::move(v.comments_))
+    {
+        switch(this->type_) // here this->type_ is already initialized
+        {
+            case value_t::boolean        : assigner(boolean_        , std::move(v.boolean_        )); break;
+            case value_t::integer        : assigner(integer_        , std::move(v.integer_        )); break;
+            case value_t::floating       : assigner(floating_       , std::move(v.floating_       )); break;
+            case value_t::string         : assigner(string_         , std::move(v.string_         )); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
+            case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
+            case value_t::local_date     : assigner(local_date_     , std::move(v.local_date_     )); break;
+            case value_t::local_time     : assigner(local_time_     , std::move(v.local_time_     )); break;
+            case value_t::array          : assigner(array_          , std::move(v.array_          )); break;
+            case value_t::table          : assigner(table_          , std::move(v.table_          )); break;
+            default: break;
+        }
+    }
+    basic_value& operator=(const basic_value& v)
+    {
+        this->cleanup();
+        this->region_info_ = v.region_info_;
+        this->comments_ = v.comments_;
+        this->type_ = v.type();
+        switch(this->type_)
+        {
+            case value_t::boolean        : assigner(boolean_        , v.boolean_        ); break;
+            case value_t::integer        : assigner(integer_        , v.integer_        ); break;
+            case value_t::floating       : assigner(floating_       , v.floating_       ); break;
+            case value_t::string         : assigner(string_         , v.string_         ); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+            case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+            case value_t::local_date     : assigner(local_date_     , v.local_date_     ); break;
+            case value_t::local_time     : assigner(local_time_     , v.local_time_     ); break;
+            case value_t::array          : assigner(array_          , v.array_          ); break;
+            case value_t::table          : assigner(table_          , v.table_          ); break;
+            default: break;
+        }
+        return *this;
+    }
+    basic_value& operator=(basic_value&& v)
+    {
+        this->cleanup();
+        this->region_info_ = std::move(v.region_info_);
+        this->comments_ = std::move(v.comments_);
+        this->type_ = v.type();
+        switch(this->type_)
+        {
+            case value_t::boolean        : assigner(boolean_        , std::move(v.boolean_        )); break;
+            case value_t::integer        : assigner(integer_        , std::move(v.integer_        )); break;
+            case value_t::floating       : assigner(floating_       , std::move(v.floating_       )); break;
+            case value_t::string         : assigner(string_         , std::move(v.string_         )); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
+            case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
+            case value_t::local_date     : assigner(local_date_     , std::move(v.local_date_     )); break;
+            case value_t::local_time     : assigner(local_time_     , std::move(v.local_time_     )); break;
+            case value_t::array          : assigner(array_          , std::move(v.array_          )); break;
+            case value_t::table          : assigner(table_          , std::move(v.table_          )); break;
+            default: break;
+        }
+        return *this;
+    }
+
+    // overwrite comments ----------------------------------------------------
+
+    basic_value(const basic_value& v, std::vector<std::string> comments)
+        : type_(v.type()), region_info_(v.region_info_),
+          comments_(std::move(comments))
+    {
+        switch(v.type())
+        {
+            case value_t::boolean        : assigner(boolean_        , v.boolean_        ); break;
+            case value_t::integer        : assigner(integer_        , v.integer_        ); break;
+            case value_t::floating       : assigner(floating_       , v.floating_       ); break;
+            case value_t::string         : assigner(string_         , v.string_         ); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+            case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+            case value_t::local_date     : assigner(local_date_     , v.local_date_     ); break;
+            case value_t::local_time     : assigner(local_time_     , v.local_time_     ); break;
+            case value_t::array          : assigner(array_          , v.array_          ); break;
+            case value_t::table          : assigner(table_          , v.table_          ); break;
+            default: break;
+        }
+    }
+
+    basic_value(basic_value&& v, std::vector<std::string> comments)
+        : type_(v.type()), region_info_(std::move(v.region_info_)),
+          comments_(std::move(comments))
+    {
+        switch(this->type_) // here this->type_ is already initialized
+        {
+            case value_t::boolean        : assigner(boolean_        , std::move(v.boolean_        )); break;
+            case value_t::integer        : assigner(integer_        , std::move(v.integer_        )); break;
+            case value_t::floating       : assigner(floating_       , std::move(v.floating_       )); break;
+            case value_t::string         : assigner(string_         , std::move(v.string_         )); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, std::move(v.offset_datetime_)); break;
+            case value_t::local_datetime : assigner(local_datetime_ , std::move(v.local_datetime_ )); break;
+            case value_t::local_date     : assigner(local_date_     , std::move(v.local_date_     )); break;
+            case value_t::local_time     : assigner(local_time_     , std::move(v.local_time_     )); break;
+            case value_t::array          : assigner(array_          , std::move(v.array_          )); break;
+            case value_t::table          : assigner(table_          , std::move(v.table_          )); break;
+            default: break;
+        }
+    }
+
+    // -----------------------------------------------------------------------
+    // conversion between different basic_values.
+    template<typename C,
+             template<typename ...> class T,
+             template<typename ...> class A>
+    basic_value(const basic_value<C, T, A>& v)
+        : type_(v.type()), region_info_(v.region_info_), comments_(v.comments())
+    {
+        switch(v.type())
+        {
+            case value_t::boolean        : assigner(boolean_        , v.boolean_        ); break;
+            case value_t::integer        : assigner(integer_        , v.integer_        ); break;
+            case value_t::floating       : assigner(floating_       , v.floating_       ); break;
+            case value_t::string         : assigner(string_         , v.string_         ); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+            case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+            case value_t::local_date     : assigner(local_date_     , v.local_date_     ); break;
+            case value_t::local_time     : assigner(local_time_     , v.local_time_     ); break;
+            case value_t::array          :
+            {
+                array_type tmp(v.as_array(std::nothrow).begin(),
+                               v.as_array(std::nothrow).end());
+                assigner(array_, std::move(tmp));
+                break;
+            }
+            case value_t::table          :
+            {
+                table_type tmp(v.as_table(std::nothrow).begin(),
+                               v.as_table(std::nothrow).end());
+                assigner(table_, std::move(tmp));
+                break;
+            }
+            default: break;
+        }
+    }
+    template<typename C,
+             template<typename ...> class T,
+             template<typename ...> class A>
+    basic_value(const basic_value<C, T, A>& v, std::vector<std::string> comments)
+        : type_(v.type()), region_info_(v.region_info_),
+          comments_(std::move(comments))
+    {
+        switch(v.type())
+        {
+            case value_t::boolean        : assigner(boolean_        , v.boolean_        ); break;
+            case value_t::integer        : assigner(integer_        , v.integer_        ); break;
+            case value_t::floating       : assigner(floating_       , v.floating_       ); break;
+            case value_t::string         : assigner(string_         , v.string_         ); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+            case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+            case value_t::local_date     : assigner(local_date_     , v.local_date_     ); break;
+            case value_t::local_time     : assigner(local_time_     , v.local_time_     ); break;
+            case value_t::array          :
+            {
+                array_type tmp(v.as_array(std::nothrow).begin(),
+                               v.as_array(std::nothrow).end());
+                assigner(array_, std::move(tmp));
+                break;
+            }
+            case value_t::table          :
+            {
+                table_type tmp(v.as_table(std::nothrow).begin(),
+                               v.as_table(std::nothrow).end());
+                assigner(table_, std::move(tmp));
+                break;
+            }
+            default: break;
+        }
+    }
+    template<typename C,
+             template<typename ...> class T,
+             template<typename ...> class A>
+    basic_value& operator=(const basic_value<C, T, A>& v)
+    {
+        this->region_info_ = v.region_info_;
+        this->comments_    = comment_type(v.comments());
+        this->type_        = v.type();
+        switch(v.type())
+        {
+            case value_t::boolean        : assigner(boolean_        , v.boolean_        ); break;
+            case value_t::integer        : assigner(integer_        , v.integer_        ); break;
+            case value_t::floating       : assigner(floating_       , v.floating_       ); break;
+            case value_t::string         : assigner(string_         , v.string_         ); break;
+            case value_t::offset_datetime: assigner(offset_datetime_, v.offset_datetime_); break;
+            case value_t::local_datetime : assigner(local_datetime_ , v.local_datetime_ ); break;
+            case value_t::local_date     : assigner(local_date_     , v.local_date_     ); break;
+            case value_t::local_time     : assigner(local_time_     , v.local_time_     ); break;
+            case value_t::array          :
+            {
+                array_type tmp(v.as_array(std::nothrow).begin(),
+                               v.as_array(std::nothrow).end());
+                assigner(array_, std::move(tmp));
+                break;
+            }
+            case value_t::table          :
+            {
+                table_type tmp(v.as_table(std::nothrow).begin(),
+                               v.as_table(std::nothrow).end());
+                assigner(table_, std::move(tmp));
+                break;
+            }
+            default: break;
+        }
+        return *this;
+    }
+
+    // boolean ==============================================================
+
+    basic_value(boolean b)
+        : type_(value_t::boolean),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->boolean_, b);
+    }
+    basic_value& operator=(boolean b)
+    {
+        this->cleanup();
+        this->type_ = value_t::boolean;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->boolean_, b);
+        return *this;
+    }
+    template<typename Container>
+    basic_value(boolean b, detail::region<Container> reg)
+        : type_(value_t::boolean),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->boolean_, b);
+    }
+    basic_value(boolean b, std::vector<std::string> comments)
+        : type_(value_t::boolean),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->boolean_, b);
+    }
+
+    // integer ==============================================================
+
+    template<typename T, typename std::enable_if<detail::conjunction<
+        std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
+        std::nullptr_t>::type = nullptr>
+    basic_value(T i)
+        : type_(value_t::integer),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->integer_, static_cast<integer>(i));
+    }
+
+    template<typename T, typename Container, typename std::enable_if<
+        detail::conjunction<
+            std::is_integral<T>,
+            detail::negation<std::is_same<T, boolean>>
+        >::value, std::nullptr_t>::type = nullptr>
+    basic_value(T i, detail::region<Container> reg)
+        : type_(value_t::integer),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->integer_, static_cast<integer>(i));
+    }
+
+    template<typename T, typename std::enable_if<detail::conjunction<
+        std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
+        std::nullptr_t>::type = nullptr>
+    basic_value& operator=(T i)
+    {
+        this->cleanup();
+        this->type_ = value_t::integer;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->integer_, static_cast<integer>(i));
+        return *this;
+    }
+
+    template<typename T, typename std::enable_if<detail::conjunction<
+        std::is_integral<T>, detail::negation<std::is_same<T, boolean>>>::value,
+        std::nullptr_t>::type = nullptr>
+    basic_value(T i, std::vector<std::string> comments)
+        : type_(value_t::integer),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->integer_, static_cast<integer>(i));
+    }
+
+    // floating =============================================================
+
+    template<typename T, typename std::enable_if<
+        std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
+    basic_value(T f)
+        : type_(value_t::floating),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->floating_, static_cast<floating>(f));
+    }
+
+    template<typename T, typename Container, typename std::enable_if<
+        std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
+    basic_value(T f, detail::region<Container> reg)
+        : type_(value_t::floating),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->floating_, static_cast<floating>(f));
+    }
+
+    template<typename T, typename std::enable_if<
+        std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
+    basic_value& operator=(T f)
+    {
+        this->cleanup();
+        this->type_ = value_t::floating;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->floating_, static_cast<floating>(f));
+        return *this;
+    }
+
+    template<typename T, typename std::enable_if<
+        std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
+    basic_value(T f, std::vector<std::string> comments)
+        : type_(value_t::floating),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->floating_, f);
+    }
+
+    // string ===============================================================
+
+    basic_value(toml::string s)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->string_, std::move(s));
+    }
+    template<typename Container>
+    basic_value(toml::string s, detail::region<Container> reg)
+        : type_(value_t::string),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->string_, std::move(s));
+    }
+    basic_value& operator=(toml::string s)
+    {
+        this->cleanup();
+        this->type_ = value_t::string ;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->string_, s);
+        return *this;
+    }
+    basic_value(toml::string s, std::vector<std::string> comments)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->string_, std::move(s));
+    }
+
+    basic_value(std::string s)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->string_, toml::string(std::move(s)));
+    }
+    basic_value& operator=(std::string s)
+    {
+        this->cleanup();
+        this->type_ = value_t::string ;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->string_, toml::string(std::move(s)));
+        return *this;
+    }
+    basic_value(std::string s, string_t kind)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->string_, toml::string(std::move(s), kind));
+    }
+    basic_value(std::string s, std::vector<std::string> comments)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->string_, toml::string(std::move(s)));
+    }
+    basic_value(std::string s, string_t kind, std::vector<std::string> comments)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->string_, toml::string(std::move(s), kind));
+    }
+
+    basic_value(const char* s)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->string_, toml::string(std::string(s)));
+    }
+    basic_value& operator=(const char* s)
+    {
+        this->cleanup();
+        this->type_ = value_t::string ;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->string_, toml::string(std::string(s)));
+        return *this;
+    }
+    basic_value(const char* s, string_t kind)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->string_, toml::string(std::string(s), kind));
+    }
+    basic_value(const char* s, std::vector<std::string> comments)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->string_, toml::string(std::string(s)));
+    }
+    basic_value(const char* s, string_t kind, std::vector<std::string> comments)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->string_, toml::string(std::string(s), kind));
+    }
+
+#if __cplusplus >= 201703L
+    basic_value(std::string_view s)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->string_, toml::string(s));
+    }
+    basic_value& operator=(std::string_view s)
+    {
+        this->cleanup();
+        this->type_ = value_t::string ;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->string_, toml::string(s));
+        return *this;
+    }
+    basic_value(std::string_view s, std::vector<std::string> comments)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->string_, toml::string(s));
+    }
+    basic_value(std::string_view s, string_t kind)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->string_, toml::string(s, kind));
+    }
+    basic_value(std::string_view s, string_t kind, std::vector<std::string> comments)
+        : type_(value_t::string),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->string_, toml::string(s, kind));
+    }
+#endif
+
+    // local date ===========================================================
+
+    basic_value(const local_date& ld)
+        : type_(value_t::local_date),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->local_date_, ld);
+    }
+    template<typename Container>
+    basic_value(const local_date& ld, detail::region<Container> reg)
+        : type_(value_t::local_date),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->local_date_, ld);
+    }
+    basic_value& operator=(const local_date& ld)
+    {
+        this->cleanup();
+        this->type_ = value_t::local_date;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->local_date_, ld);
+        return *this;
+    }
+    basic_value(const local_date& ld, std::vector<std::string> comments)
+        : type_(value_t::local_date),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->local_date_, ld);
+    }
+
+    // local time ===========================================================
+
+    basic_value(const local_time& lt)
+        : type_(value_t::local_time),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->local_time_, lt);
+    }
+    template<typename Container>
+    basic_value(const local_time& lt, detail::region<Container> reg)
+        : type_(value_t::local_time),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->local_time_, lt);
+    }
+    basic_value(const local_time& lt, std::vector<std::string> comments)
+        : type_(value_t::local_time),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->local_time_, lt);
+    }
+    basic_value& operator=(const local_time& lt)
+    {
+        this->cleanup();
+        this->type_ = value_t::local_time;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->local_time_, lt);
+        return *this;
+    }
+
+    template<typename Rep, typename Period>
+    basic_value(const std::chrono::duration<Rep, Period>& dur)
+        : type_(value_t::local_time),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->local_time_, local_time(dur));
+    }
+    template<typename Rep, typename Period>
+    basic_value(const std::chrono::duration<Rep, Period>& dur,
+                std::vector<std::string> comments)
+        : type_(value_t::local_time),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->local_time_, local_time(dur));
+    }
+    template<typename Rep, typename Period>
+    basic_value& operator=(const std::chrono::duration<Rep, Period>& dur)
+    {
+        this->cleanup();
+        this->type_ = value_t::local_time;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->local_time_, local_time(dur));
+        return *this;
+    }
+
+    // local datetime =======================================================
+
+    basic_value(const local_datetime& ldt)
+        : type_(value_t::local_datetime),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->local_datetime_, ldt);
+    }
+    template<typename Container>
+    basic_value(const local_datetime& ldt, detail::region<Container> reg)
+        : type_(value_t::local_datetime),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->local_datetime_, ldt);
+    }
+    basic_value(const local_datetime& ldt, std::vector<std::string> comments)
+        : type_(value_t::local_datetime),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->local_datetime_, ldt);
+    }
+    basic_value& operator=(const local_datetime& ldt)
+    {
+        this->cleanup();
+        this->type_ = value_t::local_datetime;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->local_datetime_, ldt);
+        return *this;
+    }
+
+    // offset datetime ======================================================
+
+    basic_value(const offset_datetime& odt)
+        : type_(value_t::offset_datetime),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->offset_datetime_, odt);
+    }
+    template<typename Container>
+    basic_value(const offset_datetime& odt, detail::region<Container> reg)
+        : type_(value_t::offset_datetime),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->offset_datetime_, odt);
+    }
+    basic_value(const offset_datetime& odt, std::vector<std::string> comments)
+        : type_(value_t::offset_datetime),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->offset_datetime_, odt);
+    }
+    basic_value& operator=(const offset_datetime& odt)
+    {
+        this->cleanup();
+        this->type_ = value_t::offset_datetime;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->offset_datetime_, odt);
+        return *this;
+    }
+    basic_value(const std::chrono::system_clock::time_point& tp)
+        : type_(value_t::offset_datetime),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->offset_datetime_, offset_datetime(tp));
+    }
+    basic_value(const std::chrono::system_clock::time_point& tp,
+                std::vector<std::string> comments)
+        : type_(value_t::offset_datetime),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->offset_datetime_, offset_datetime(tp));
+    }
+    basic_value& operator=(const std::chrono::system_clock::time_point& tp)
+    {
+        this->cleanup();
+        this->type_ = value_t::offset_datetime;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->offset_datetime_, offset_datetime(tp));
+        return *this;
+    }
+
+    // array ================================================================
+
+    basic_value(const array_type& ary)
+        : type_(value_t::array),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->array_, ary);
+    }
+    template<typename Container>
+    basic_value(const array_type& ary, detail::region<Container> reg)
+        : type_(value_t::array),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->array_, ary);
+    }
+    basic_value(const array_type& ary, std::vector<std::string> comments)
+        : type_(value_t::array),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->array_, ary);
+    }
+    basic_value& operator=(const array_type& ary)
+    {
+        this->cleanup();
+        this->type_ = value_t::array ;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->array_, ary);
+        return *this;
+    }
+
+    // array (initializer_list) ----------------------------------------------
+
+    template<typename T, typename std::enable_if<
+            std::is_convertible<T, value_type>::value,
+        std::nullptr_t>::type = nullptr>
+    basic_value(std::initializer_list<T> list)
+        : type_(value_t::array),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        array_type ary(list.begin(), list.end());
+        assigner(this->array_, std::move(ary));
+    }
+    template<typename T, typename std::enable_if<
+            std::is_convertible<T, value_type>::value,
+        std::nullptr_t>::type = nullptr>
+    basic_value(std::initializer_list<T> list, std::vector<std::string> comments)
+        : type_(value_t::array),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        array_type ary(list.begin(), list.end());
+        assigner(this->array_, std::move(ary));
+    }
+    template<typename T, typename std::enable_if<
+            std::is_convertible<T, value_type>::value,
+        std::nullptr_t>::type = nullptr>
+    basic_value& operator=(std::initializer_list<T> list)
+    {
+        this->cleanup();
+        this->type_ = value_t::array;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+
+        array_type ary(list.begin(), list.end());
+        assigner(this->array_, std::move(ary));
+        return *this;
+    }
+
+    // array (STL Containers) ------------------------------------------------
+
+    template<typename T, typename std::enable_if<detail::conjunction<
+            detail::negation<std::is_same<T, array_type>>,
+            detail::is_container<T>
+        >::value, std::nullptr_t>::type = nullptr>
+    basic_value(const T& list)
+        : type_(value_t::array),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        static_assert(std::is_convertible<typename T::value_type, value_type>::value,
+            "elements of a container should be convertible to toml::value");
+
+        array_type ary(list.size());
+        std::copy(list.begin(), list.end(), ary.begin());
+        assigner(this->array_, std::move(ary));
+    }
+    template<typename T, typename std::enable_if<detail::conjunction<
+            detail::negation<std::is_same<T, array_type>>,
+            detail::is_container<T>
+        >::value, std::nullptr_t>::type = nullptr>
+    basic_value(const T& list, std::vector<std::string> comments)
+        : type_(value_t::array),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        static_assert(std::is_convertible<typename T::value_type, value_type>::value,
+            "elements of a container should be convertible to toml::value");
+
+        array_type ary(list.size());
+        std::copy(list.begin(), list.end(), ary.begin());
+        assigner(this->array_, std::move(ary));
+    }
+    template<typename T, typename std::enable_if<detail::conjunction<
+            detail::negation<std::is_same<T, array_type>>,
+            detail::is_container<T>
+        >::value, std::nullptr_t>::type = nullptr>
+    basic_value& operator=(const T& list)
+    {
+        static_assert(std::is_convertible<typename T::value_type, value_type>::value,
+            "elements of a container should be convertible to toml::value");
+
+        this->cleanup();
+        this->type_ = value_t::array;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+
+        array_type ary(list.size());
+        std::copy(list.begin(), list.end(), ary.begin());
+        assigner(this->array_, std::move(ary));
+        return *this;
+    }
+
+    // table ================================================================
+
+    basic_value(const table_type& tab)
+        : type_(value_t::table),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        assigner(this->table_, tab);
+    }
+    template<typename Container>
+    basic_value(const table_type& tab, detail::region<Container> reg)
+        : type_(value_t::table),
+          region_info_(std::make_shared<detail::region<Container>>(std::move(reg))),
+          comments_(region_info_->comments())
+    {
+        assigner(this->table_, tab);
+    }
+    basic_value(const table_type& tab, std::vector<std::string> comments)
+        : type_(value_t::table),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        assigner(this->table_, tab);
+    }
+    basic_value& operator=(const table_type& tab)
+    {
+        this->cleanup();
+        this->type_ = value_t::table;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+        assigner(this->table_, tab);
+        return *this;
+    }
+
+    // initializer-list ------------------------------------------------------
+
+    basic_value(std::initializer_list<std::pair<key, basic_value>> list)
+        : type_(value_t::table),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        table_type tab;
+        for(const auto& elem : list) {tab[elem.first] = elem.second;}
+        assigner(this->table_, std::move(tab));
+    }
+
+    basic_value(std::initializer_list<std::pair<key, basic_value>> list,
+                std::vector<std::string> comments)
+        : type_(value_t::table),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        table_type tab;
+        for(const auto& elem : list) {tab[elem.first] = elem.second;}
+        assigner(this->table_, std::move(tab));
+    }
+    basic_value& operator=(std::initializer_list<std::pair<key, basic_value>> list)
+    {
+        this->cleanup();
+        this->type_ = value_t::table;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+
+        table_type tab;
+        for(const auto& elem : list) {tab[elem.first] = elem.second;}
+        assigner(this->table_, std::move(tab));
+        return *this;
+    }
+
+    // other table-like -----------------------------------------------------
+
+    template<typename Map, typename std::enable_if<detail::conjunction<
+            detail::negation<std::is_same<Map, table_type>>,
+            detail::is_map<Map>
+        >::value, std::nullptr_t>::type = nullptr>
+    basic_value(const Map& mp)
+        : type_(value_t::table),
+          region_info_(std::make_shared<region_base>(region_base{}))
+    {
+        table_type tab;
+        for(const auto& elem : mp) {tab[elem.first] = elem.second;}
+        assigner(this->table_, std::move(tab));
+    }
+    template<typename Map, typename std::enable_if<detail::conjunction<
+            detail::negation<std::is_same<Map, table_type>>,
+            detail::is_map<Map>
+        >::value, std::nullptr_t>::type = nullptr>
+    basic_value(const Map& mp, std::vector<std::string> comments)
+        : type_(value_t::table),
+          region_info_(std::make_shared<region_base>(region_base{})),
+          comments_(std::move(comments))
+    {
+        table_type tab;
+        for(const auto& elem : mp) {tab[elem.first] = elem.second;}
+        assigner(this->table_, std::move(tab));
+    }
+    template<typename Map, typename std::enable_if<detail::conjunction<
+            detail::negation<std::is_same<Map, table_type>>,
+            detail::is_map<Map>
+        >::value, std::nullptr_t>::type = nullptr>
+    basic_value& operator=(const Map& mp)
+    {
+        this->cleanup();
+        this->type_ = value_t::table;
+        this->region_info_ = std::make_shared<region_base>(region_base{});
+
+        table_type tab;
+        for(const auto& elem : mp) {tab[elem.first] = elem.second;}
+        assigner(this->table_, std::move(tab));
+        return *this;
+    }
+
+    // user-defined =========================================================
+
+    // convert using into_toml() method -------------------------------------
+
+    template<typename T, typename std::enable_if<
+        detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
+    basic_value(const T& ud): basic_value(ud.into_toml()) {}
+
+    template<typename T, typename std::enable_if<
+        detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
+    basic_value(const T& ud, std::vector<std::string> comments)
+        : basic_value(ud.into_toml(), std::move(comments))
+    {}
+    template<typename T, typename std::enable_if<
+        detail::has_into_toml_method<T>::value, std::nullptr_t>::type = nullptr>
+    basic_value& operator=(const T& ud)
+    {
+        *this = ud.into_toml();
+        return *this;
+    }
+
+    // convert using into<T> struct -----------------------------------------
+
+    template<typename T, std::size_t S = sizeof(::toml::into<T>)>
+    basic_value(const T& ud): basic_value(::toml::into<T>::into_toml(ud)) {}
+    template<typename T, std::size_t S = sizeof(::toml::into<T>)>
+    basic_value(const T& ud, std::vector<std::string> comments)
+        : basic_value(::toml::into<T>::into_toml(ud), std::move(comments))
+    {}
+    template<typename T, std::size_t S = sizeof(::toml::into<T>)>
+    basic_value& operator=(const T& ud)
+    {
+        *this = ::toml::into<T>::into_toml(ud);
+        return *this;
+    }
+
+    // for internal use ------------------------------------------------------
+
+    template<typename T, typename Container, typename std::enable_if<
+        detail::is_exact_toml_type<T, value_type>::value,
+        std::nullptr_t>::type = nullptr>
+    basic_value(std::pair<T, detail::region<Container>> parse_result)
+        : basic_value(std::move(parse_result.first), std::move(parse_result.second))
+    {}
+
+    // type checking and casting ============================================
+
+    template<typename T, typename std::enable_if<
+        detail::is_exact_toml_type<T, value_type>::value,
+        std::nullptr_t>::type = nullptr>
+    bool is() const noexcept
+    {
+        return detail::type_to_enum<T, value_type>::value == this->type_;
+    }
+    bool is(value_t t) const noexcept {return t == this->type_;}
+
+    bool is_uninitialized()   const noexcept {return this->is(value_t::empty          );}
+    bool is_boolean()         const noexcept {return this->is(value_t::boolean        );}
+    bool is_integer()         const noexcept {return this->is(value_t::integer        );}
+    bool is_floating()        const noexcept {return this->is(value_t::floating       );}
+    bool is_string()          const noexcept {return this->is(value_t::string         );}
+    bool is_offset_datetime() const noexcept {return this->is(value_t::offset_datetime);}
+    bool is_local_datetime()  const noexcept {return this->is(value_t::local_datetime );}
+    bool is_local_date()      const noexcept {return this->is(value_t::local_date     );}
+    bool is_local_time()      const noexcept {return this->is(value_t::local_time     );}
+    bool is_array()           const noexcept {return this->is(value_t::array          );}
+    bool is_table()           const noexcept {return this->is(value_t::table          );}
+
+    value_t type() const {return type_;}
+
+    template<value_t T>
+    typename detail::enum_to_type<T, value_type>::type&       cast() &
+    {
+        if(this->type_ != T)
+        {
+            detail::throw_bad_cast<T>(this->type_, *this);
+        }
+        return detail::switch_cast<T>::invoke(*this);
+    }
+    template<value_t T>
+    typename detail::enum_to_type<T, value_type>::type const& cast() const&
+    {
+        if(this->type_ != T)
+        {
+            detail::throw_bad_cast<T>(this->type_, *this);
+        }
+        return detail::switch_cast<T>::invoke(*this);
+    }
+    template<value_t T>
+    typename detail::enum_to_type<T, value_type>::type&&      cast() &&
+    {
+        if(this->type_ != T)
+        {
+            detail::throw_bad_cast<T>(this->type_, *this);
+        }
+        return detail::switch_cast<T>::invoke(std::move(*this));
+    }
+
+    // ------------------------------------------------------------------------
+    // nothrow version
+
+    boolean         const& as_boolean        (const std::nothrow_t&) const& noexcept {return this->boolean_;}
+    integer         const& as_integer        (const std::nothrow_t&) const& noexcept {return this->integer_;}
+    floating        const& as_floating       (const std::nothrow_t&) const& noexcept {return this->floating_;}
+    string          const& as_string         (const std::nothrow_t&) const& noexcept {return this->string_;}
+    offset_datetime const& as_offset_datetime(const std::nothrow_t&) const& noexcept {return this->offset_datetime_;}
+    local_datetime  const& as_local_datetime (const std::nothrow_t&) const& noexcept {return this->local_datetime_;}
+    local_date      const& as_local_date     (const std::nothrow_t&) const& noexcept {return this->local_date_;}
+    local_time      const& as_local_time     (const std::nothrow_t&) const& noexcept {return this->local_time_;}
+    array_type      const& as_array          (const std::nothrow_t&) const& noexcept {return this->array_.value();}
+    table_type      const& as_table          (const std::nothrow_t&) const& noexcept {return this->table_.value();}
+
+    boolean        & as_boolean        (const std::nothrow_t&) & noexcept {return this->boolean_;}
+    integer        & as_integer        (const std::nothrow_t&) & noexcept {return this->integer_;}
+    floating       & as_floating       (const std::nothrow_t&) & noexcept {return this->floating_;}
+    string         & as_string         (const std::nothrow_t&) & noexcept {return this->string_;}
+    offset_datetime& as_offset_datetime(const std::nothrow_t&) & noexcept {return this->offset_datetime_;}
+    local_datetime & as_local_datetime (const std::nothrow_t&) & noexcept {return this->local_datetime_;}
+    local_date     & as_local_date     (const std::nothrow_t&) & noexcept {return this->local_date_;}
+    local_time     & as_local_time     (const std::nothrow_t&) & noexcept {return this->local_time_;}
+    array_type     & as_array          (const std::nothrow_t&) & noexcept {return this->array_.value();}
+    table_type     & as_table          (const std::nothrow_t&) & noexcept {return this->table_.value();}
+
+    boolean        && as_boolean        (const std::nothrow_t&) && noexcept {return std::move(this->boolean_);}
+    integer        && as_integer        (const std::nothrow_t&) && noexcept {return std::move(this->integer_);}
+    floating       && as_floating       (const std::nothrow_t&) && noexcept {return std::move(this->floating_);}
+    string         && as_string         (const std::nothrow_t&) && noexcept {return std::move(this->string_);}
+    offset_datetime&& as_offset_datetime(const std::nothrow_t&) && noexcept {return std::move(this->offset_datetime_);}
+    local_datetime && as_local_datetime (const std::nothrow_t&) && noexcept {return std::move(this->local_datetime_);}
+    local_date     && as_local_date     (const std::nothrow_t&) && noexcept {return std::move(this->local_date_);}
+    local_time     && as_local_time     (const std::nothrow_t&) && noexcept {return std::move(this->local_time_);}
+    array_type     && as_array          (const std::nothrow_t&) && noexcept {return std::move(this->array_.value());}
+    table_type     && as_table          (const std::nothrow_t&) && noexcept {return std::move(this->table_.value());}
+
+    // ========================================================================
+    // throw version
+    // ------------------------------------------------------------------------
+    // const reference
+
+    boolean const& as_boolean() const&
+    {
+        if(this->type_ != value_t::boolean)
+        {
+            detail::throw_bad_cast<value_t::boolean>(this->type_, *this);
+        }
+        return this->boolean_;
+    }
+    integer const& as_integer() const&
+    {
+        if(this->type_ != value_t::integer)
+        {
+            detail::throw_bad_cast<value_t::integer>(this->type_, *this);
+        }
+        return this->integer_;
+    }
+    floating const& as_floating() const&
+    {
+        if(this->type_ != value_t::floating)
+        {
+            detail::throw_bad_cast<value_t::floating>(this->type_, *this);
+        }
+        return this->floating_;
+    }
+    string const& as_string() const&
+    {
+        if(this->type_ != value_t::string)
+        {
+            detail::throw_bad_cast<value_t::string>(this->type_, *this);
+        }
+        return this->string_;
+    }
+    offset_datetime const& as_offset_datetime() const&
+    {
+        if(this->type_ != value_t::offset_datetime)
+        {
+            detail::throw_bad_cast<value_t::offset_datetime>(this->type_, *this);
+        }
+        return this->offset_datetime_;
+    }
+    local_datetime const& as_local_datetime() const&
+    {
+        if(this->type_ != value_t::local_datetime)
+        {
+            detail::throw_bad_cast<value_t::local_datetime>(this->type_, *this);
+        }
+        return this->local_datetime_;
+    }
+    local_date const& as_local_date() const&
+    {
+        if(this->type_ != value_t::local_date)
+        {
+            detail::throw_bad_cast<value_t::local_date>(this->type_, *this);
+        }
+        return this->local_date_;
+    }
+    local_time const& as_local_time() const&
+    {
+        if(this->type_ != value_t::local_time)
+        {
+            detail::throw_bad_cast<value_t::local_time>(this->type_, *this);
+        }
+        return this->local_time_;
+    }
+    array_type const& as_array() const&
+    {
+        if(this->type_ != value_t::array)
+        {
+            detail::throw_bad_cast<value_t::array>(this->type_, *this);
+        }
+        return this->array_.value();
+    }
+    table_type const& as_table() const&
+    {
+        if(this->type_ != value_t::table)
+        {
+            detail::throw_bad_cast<value_t::table>(this->type_, *this);
+        }
+        return this->table_.value();
+    }
+
+    // ------------------------------------------------------------------------
+    // nonconst reference
+
+    boolean & as_boolean() &
+    {
+        if(this->type_ != value_t::boolean)
+        {
+            detail::throw_bad_cast<value_t::boolean>(this->type_, *this);
+        }
+        return this->boolean_;
+    }
+    integer & as_integer() &
+    {
+        if(this->type_ != value_t::integer)
+        {
+            detail::throw_bad_cast<value_t::integer>(this->type_, *this);
+        }
+        return this->integer_;
+    }
+    floating & as_floating() &
+    {
+        if(this->type_ != value_t::floating)
+        {
+            detail::throw_bad_cast<value_t::floating>(this->type_, *this);
+        }
+        return this->floating_;
+    }
+    string & as_string() &
+    {
+        if(this->type_ != value_t::string)
+        {
+            detail::throw_bad_cast<value_t::string>(this->type_, *this);
+        }
+        return this->string_;
+    }
+    offset_datetime & as_offset_datetime() &
+    {
+        if(this->type_ != value_t::offset_datetime)
+        {
+            detail::throw_bad_cast<value_t::offset_datetime>(this->type_, *this);
+        }
+        return this->offset_datetime_;
+    }
+    local_datetime & as_local_datetime() &
+    {
+        if(this->type_ != value_t::local_datetime)
+        {
+            detail::throw_bad_cast<value_t::local_datetime>(this->type_, *this);
+        }
+        return this->local_datetime_;
+    }
+    local_date & as_local_date() &
+    {
+        if(this->type_ != value_t::local_date)
+        {
+            detail::throw_bad_cast<value_t::local_date>(this->type_, *this);
+        }
+        return this->local_date_;
+    }
+    local_time & as_local_time() &
+    {
+        if(this->type_ != value_t::local_time)
+        {
+            detail::throw_bad_cast<value_t::local_time>(this->type_, *this);
+        }
+        return this->local_time_;
+    }
+    array_type & as_array() &
+    {
+        if(this->type_ != value_t::array)
+        {
+            detail::throw_bad_cast<value_t::array>(this->type_, *this);
+        }
+        return this->array_.value();
+    }
+    table_type & as_table() &
+    {
+        if(this->type_ != value_t::table)
+        {
+            detail::throw_bad_cast<value_t::table>(this->type_, *this);
+        }
+        return this->table_.value();
+    }
+
+    // ------------------------------------------------------------------------
+    // rvalue reference
+
+    boolean && as_boolean() &&
+    {
+        if(this->type_ != value_t::boolean)
+        {
+            detail::throw_bad_cast<value_t::boolean>(this->type_, *this);
+        }
+        return std::move(this->boolean_);
+    }
+    integer && as_integer() &&
+    {
+        if(this->type_ != value_t::integer)
+        {
+            detail::throw_bad_cast<value_t::integer>(this->type_, *this);
+        }
+        return std::move(this->integer_);
+    }
+    floating && as_floating() &&
+    {
+        if(this->type_ != value_t::floating)
+        {
+            detail::throw_bad_cast<value_t::floating>(this->type_, *this);
+        }
+        return std::move(this->floating_);
+    }
+    string && as_string() &&
+    {
+        if(this->type_ != value_t::string)
+        {
+            detail::throw_bad_cast<value_t::string>(this->type_, *this);
+        }
+        return std::move(this->string_);
+    }
+    offset_datetime && as_offset_datetime() &&
+    {
+        if(this->type_ != value_t::offset_datetime)
+        {
+            detail::throw_bad_cast<value_t::offset_datetime>(this->type_, *this);
+        }
+        return std::move(this->offset_datetime_);
+    }
+    local_datetime && as_local_datetime() &&
+    {
+        if(this->type_ != value_t::local_datetime)
+        {
+            detail::throw_bad_cast<value_t::local_datetime>(this->type_, *this);
+        }
+        return std::move(this->local_datetime_);
+    }
+    local_date && as_local_date() &&
+    {
+        if(this->type_ != value_t::local_date)
+        {
+            detail::throw_bad_cast<value_t::local_date>(this->type_, *this);
+        }
+        return std::move(this->local_date_);
+    }
+    local_time && as_local_time() &&
+    {
+        if(this->type_ != value_t::local_time)
+        {
+            detail::throw_bad_cast<value_t::local_time>(this->type_, *this);
+        }
+        return std::move(this->local_time_);
+    }
+    array_type && as_array() &&
+    {
+        if(this->type_ != value_t::array)
+        {
+            detail::throw_bad_cast<value_t::array>(this->type_, *this);
+        }
+        return std::move(this->array_.value());
+    }
+    table_type && as_table() &&
+    {
+        if(this->type_ != value_t::table)
+        {
+            detail::throw_bad_cast<value_t::table>(this->type_, *this);
+        }
+        return std::move(this->table_.value());
+    }
+
+    // accessors =============================================================
+    //
+    // may throw type_error or out_of_range
+    //
+    value_type&       at(const key& k)
+    {
+        return this->as_table().at(k);
+    }
+    value_type const& at(const key& k) const
+    {
+        return this->as_table().at(k);
+    }
+
+    value_type&       at(const std::size_t idx)
+    {
+        return this->as_array().at(idx);
+    }
+    value_type const& at(const std::size_t idx) const
+    {
+        return this->as_array().at(idx);
+    }
+
+    source_location location() const
+    {
+        return source_location(this->region_info_.get());
+    }
+
+    comment_type const& comments() const noexcept {return this->comments_;}
+    comment_type&       comments()       noexcept {return this->comments_;}
+
+  private:
+
+    void cleanup() noexcept
+    {
+        switch(this->type_)
+        {
+            case value_t::string  : {string_.~string();       return;}
+            case value_t::array   : {array_.~array_storage(); return;}
+            case value_t::table   : {table_.~table_storage(); return;}
+            default              : return;
+        }
+    }
+
+    // for error messages
+    template<typename C,
+             template<typename ...> class T, template<typename ...> class A>
+    friend region_base const& detail::get_region(const basic_value<C, T, A>&);
+
+    template<typename Region, typename C,
+             template<typename ...> class T, template<typename ...> class A>
+    friend void detail::change_region(basic_value<C, T, A>&, Region&&);
+
+  private:
+
+    using array_storage = detail::storage<array_type>;
+    using table_storage = detail::storage<table_type>;
+
+    value_t type_;
+    union
+    {
+        boolean         boolean_;
+        integer         integer_;
+        floating        floating_;
+        string          string_;
+        offset_datetime offset_datetime_;
+        local_datetime  local_datetime_;
+        local_date      local_date_;
+        local_time      local_time_;
+        array_storage   array_;
+        table_storage   table_;
+    };
+    std::shared_ptr<region_base> region_info_;
+    comment_type                 comments_;
+};
+
+// default toml::value and default array/table.
+using value = basic_value<discard_comments, std::unordered_map, std::vector>;
+using array = typename value::array_type;
+using table = typename value::table_type;
+
+namespace detail
+{
+template<typename C,
+         template<typename ...> class T, template<typename ...> class A>
+inline region_base const& get_region(const basic_value<C, T, A>& v)
+{
+    return *(v.region_info_);
+}
+
+template<typename Region, typename C,
+         template<typename ...> class T, template<typename ...> class A>
+void change_region(basic_value<C, T, A>& v, Region&& reg)
+{
+    using region_type = typename std::remove_reference<
+        typename std::remove_cv<Region>::type
+        >::type;
+
+    std::shared_ptr<region_base> new_reg =
+        std::make_shared<region_type>(std::forward<region_type>(reg));
+    v.region_info_ = new_reg;
+    return;
+}
+}// detail
+
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+inline bool
+operator==(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+{
+    if(lhs.type()     != rhs.type())     {return false;}
+    if(lhs.comments() != rhs.comments()) {return false;}
+
+    switch(lhs.type())
+    {
+        case value_t::boolean  :
+        {
+            return lhs.as_boolean() == rhs.as_boolean();
+        }
+        case value_t::integer  :
+        {
+            return lhs.as_integer() == rhs.as_integer();
+        }
+        case value_t::floating :
+        {
+            return lhs.as_floating() == rhs.as_floating();
+        }
+        case value_t::string   :
+        {
+            return lhs.as_string() == rhs.as_string();
+        }
+        case value_t::offset_datetime:
+        {
+            return lhs.as_offset_datetime() == rhs.as_offset_datetime();
+        }
+        case value_t::local_datetime:
+        {
+            return lhs.as_local_datetime() == rhs.as_local_datetime();
+        }
+        case value_t::local_date:
+        {
+            return lhs.as_local_date() == rhs.as_local_date();
+        }
+        case value_t::local_time:
+        {
+            return lhs.as_local_time() == rhs.as_local_time();
+        }
+        case value_t::array    :
+        {
+            return lhs.as_array() == rhs.as_array();
+        }
+        case value_t::table    :
+        {
+            return lhs.as_table() == rhs.as_table();
+        }
+        case value_t::empty    : {return true; }
+        default:                 {return false;}
+    }
+}
+
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+inline bool operator!=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+{
+    return !(lhs == rhs);
+}
+
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+typename std::enable_if<detail::conjunction<
+    detail::is_comparable<typename basic_value<C, T, A>::array_type>,
+    detail::is_comparable<typename basic_value<C, T, A>::table_type>
+    >::value, bool>::type
+operator<(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+{
+    if(lhs.type() != rhs.type()){return (lhs.type() < rhs.type());}
+    switch(lhs.type())
+    {
+        case value_t::boolean  :
+        {
+            return lhs.as_boolean() <  rhs.as_boolean() ||
+                  (lhs.as_boolean() == rhs.as_boolean() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::integer  :
+        {
+            return lhs.as_integer() <  rhs.as_integer() ||
+                  (lhs.as_integer() == rhs.as_integer() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::floating :
+        {
+            return lhs.as_floating() <  rhs.as_floating() ||
+                  (lhs.as_floating() == rhs.as_floating() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::string   :
+        {
+            return lhs.as_string() <  rhs.as_string() ||
+                  (lhs.as_string() == rhs.as_string() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::offset_datetime:
+        {
+            return lhs.as_offset_datetime() <  rhs.as_offset_datetime() ||
+                  (lhs.as_offset_datetime() == rhs.as_offset_datetime() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::local_datetime:
+        {
+            return lhs.as_local_datetime() <  rhs.as_local_datetime() ||
+                  (lhs.as_local_datetime() == rhs.as_local_datetime() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::local_date:
+        {
+            return lhs.as_local_date() <  rhs.as_local_date() ||
+                  (lhs.as_local_date() == rhs.as_local_date() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::local_time:
+        {
+            return lhs.as_local_time() <  rhs.as_local_time() ||
+                  (lhs.as_local_time() == rhs.as_local_time() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::array    :
+        {
+            return lhs.as_array() <  rhs.as_array() ||
+                  (lhs.as_array() == rhs.as_array() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::table    :
+        {
+            return lhs.as_table() <  rhs.as_table() ||
+                  (lhs.as_table() == rhs.as_table() &&
+                   lhs.comments() < rhs.comments());
+        }
+        case value_t::empty    :
+        {
+            return lhs.comments() < rhs.comments();
+        }
+        default:
+        {
+            return lhs.comments() < rhs.comments();
+        }
+    }
+}
+
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+typename std::enable_if<detail::conjunction<
+    detail::is_comparable<typename basic_value<C, T, A>::array_type>,
+    detail::is_comparable<typename basic_value<C, T, A>::table_type>
+    >::value, bool>::type
+operator<=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+{
+    return (lhs < rhs) || (lhs == rhs);
+}
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+typename std::enable_if<detail::conjunction<
+    detail::is_comparable<typename basic_value<C, T, A>::array_type>,
+    detail::is_comparable<typename basic_value<C, T, A>::table_type>
+    >::value, bool>::type
+operator>(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+{
+    return !(lhs <= rhs);
+}
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+typename std::enable_if<detail::conjunction<
+    detail::is_comparable<typename basic_value<C, T, A>::array_type>,
+    detail::is_comparable<typename basic_value<C, T, A>::table_type>
+    >::value, bool>::type
+operator>=(const basic_value<C, T, A>& lhs, const basic_value<C, T, A>& rhs)
+{
+    return !(lhs < rhs);
+}
+
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+inline std::string format_error(const std::string& err_msg,
+        const basic_value<C, T, A>& v, const std::string& comment,
+        std::vector<std::string> hints = {})
+{
+    return detail::format_underline(err_msg,
+        std::vector<std::pair<detail::region_base const*, std::string>>{
+            {std::addressof(detail::get_region(v)), comment}
+        }, std::move(hints));
+}
+
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+inline std::string format_error(const std::string& err_msg,
+        const toml::basic_value<C, T, A>& v1, const std::string& comment1,
+        const toml::basic_value<C, T, A>& v2, const std::string& comment2,
+        std::vector<std::string> hints = {})
+{
+    return detail::format_underline(err_msg,
+        std::vector<std::pair<detail::region_base const*, std::string>>{
+            {std::addressof(detail::get_region(v1)), comment1},
+            {std::addressof(detail::get_region(v2)), comment2}
+        }, std::move(hints));
+}
+
+template<typename C, template<typename ...> class T, template<typename ...> class A>
+inline std::string format_error(const std::string& err_msg,
+        const toml::basic_value<C, T, A>& v1, const std::string& comment1,
+        const toml::basic_value<C, T, A>& v2, const std::string& comment2,
+        const toml::basic_value<C, T, A>& v3, const std::string& comment3,
+        std::vector<std::string> hints = {})
+{
+    return detail::format_underline(err_msg,
+        std::vector<std::pair<detail::region_base const*, std::string>>{
+            {std::addressof(detail::get_region(v1)), comment1},
+            {std::addressof(detail::get_region(v2)), comment2},
+            {std::addressof(detail::get_region(v3)), comment3}
+        }, std::move(hints));
+}
+
+template<typename Visitor, typename C,
+         template<typename ...> class T, template<typename ...> class A>
+detail::return_type_of_t<Visitor, const toml::boolean&>
+visit(Visitor&& visitor, const toml::basic_value<C, T, A>& v)
+{
+    switch(v.type())
+    {
+        case value_t::boolean        : {return visitor(v.as_boolean        ());}
+        case value_t::integer        : {return visitor(v.as_integer        ());}
+        case value_t::floating       : {return visitor(v.as_floating       ());}
+        case value_t::string         : {return visitor(v.as_string         ());}
+        case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
+        case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
+        case value_t::local_date     : {return visitor(v.as_local_date     ());}
+        case value_t::local_time     : {return visitor(v.as_local_time     ());}
+        case value_t::array          : {return visitor(v.as_array          ());}
+        case value_t::table          : {return visitor(v.as_table          ());}
+        case value_t::empty          : break;
+        default: break;
+    }
+    throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
+            "does not have any valid basic_value.", v, "here"));
+}
+
+template<typename Visitor, typename C,
+         template<typename ...> class T, template<typename ...> class A>
+detail::return_type_of_t<Visitor, toml::boolean&>
+visit(Visitor&& visitor, toml::basic_value<C, T, A>& v)
+{
+    switch(v.type())
+    {
+        case value_t::boolean        : {return visitor(v.as_boolean        ());}
+        case value_t::integer        : {return visitor(v.as_integer        ());}
+        case value_t::floating       : {return visitor(v.as_floating       ());}
+        case value_t::string         : {return visitor(v.as_string         ());}
+        case value_t::offset_datetime: {return visitor(v.as_offset_datetime());}
+        case value_t::local_datetime : {return visitor(v.as_local_datetime ());}
+        case value_t::local_date     : {return visitor(v.as_local_date     ());}
+        case value_t::local_time     : {return visitor(v.as_local_time     ());}
+        case value_t::array          : {return visitor(v.as_array          ());}
+        case value_t::table          : {return visitor(v.as_table          ());}
+        case value_t::empty          : break;
+        default: break;
+    }
+    throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
+            "does not have any valid basic_value.", v, "here"));
+}
+
+template<typename Visitor, typename C,
+         template<typename ...> class T, template<typename ...> class A>
+detail::return_type_of_t<Visitor, toml::boolean&&>
+visit(Visitor&& visitor, toml::basic_value<C, T, A>&& v)
+{
+    switch(v.type())
+    {
+        case value_t::boolean        : {return visitor(std::move(v.as_boolean        ()));}
+        case value_t::integer        : {return visitor(std::move(v.as_integer        ()));}
+        case value_t::floating       : {return visitor(std::move(v.as_floating       ()));}
+        case value_t::string         : {return visitor(std::move(v.as_string         ()));}
+        case value_t::offset_datetime: {return visitor(std::move(v.as_offset_datetime()));}
+        case value_t::local_datetime : {return visitor(std::move(v.as_local_datetime ()));}
+        case value_t::local_date     : {return visitor(std::move(v.as_local_date     ()));}
+        case value_t::local_time     : {return visitor(std::move(v.as_local_time     ()));}
+        case value_t::array          : {return visitor(std::move(v.as_array          ()));}
+        case value_t::table          : {return visitor(std::move(v.as_table          ()));}
+        case value_t::empty          : break;
+        default: break;
+    }
+    throw std::runtime_error(format_error("[error] toml::visit: toml::basic_value "
+            "does not have any valid basic_value.", v, "here"));
+}
+
+}// toml
+#endif// TOML11_VALUE
diff --git a/external/toml11/toml11_README.md b/external/toml11/toml11_README.md
new file mode 100644
index 00000000..077a2f03
--- /dev/null
+++ b/external/toml11/toml11_README.md
@@ -0,0 +1,1540 @@
+toml11
+======
+
+[![Build Status on TravisCI](https://travis-ci.org/ToruNiina/toml11.svg?branch=master)](https://travis-ci.org/ToruNiina/toml11)
+[![Build status on Appveyor](https://ci.appveyor.com/api/projects/status/m2n08a926asvg5mg/branch/master?svg=true)](https://ci.appveyor.com/project/ToruNiina/toml11/branch/master)
+[![Build status on CircleCI](https://circleci.com/gh/ToruNiina/toml11/tree/master.svg?style=svg)](https://circleci.com/gh/ToruNiina/toml11/tree/master)
+[![Version](https://img.shields.io/github/release/ToruNiina/toml11.svg?style=flat)](https://github.com/ToruNiina/toml11/releases)
+[![License](https://img.shields.io/github/license/ToruNiina/toml11.svg?style=flat)](LICENSE)
+[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1209136.svg)](https://doi.org/10.5281/zenodo.1209136)
+
+toml11 is a C++11 header-only toml parser/encoder depending only on C++ standard library.
+
+compatible to the latest version of
+[TOML v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md)
+after version 2.0.0.
+
+It passes [the language agnostic test suite for TOML parsers by BurntSushi](https://github.com/BurntSushi/toml-test).
+Not only the test suite itself, a TOML reader/encoder also runs on [CircleCI](https://circleci.com/gh/ToruNiina/toml11).
+You can see the error messages about invalid files and serialization results of valid files at
+[CircleCI](https://circleci.com/gh/ToruNiina/toml11).
+
+## Example
+
+```cpp
+#include <toml.hpp>
+#include <iostream>
+
+int main()
+{
+    const auto data = toml::parse("example.toml");
+
+    // title = "an example toml file"
+    std::string title = toml::find<std::string>(data, "title");
+    std::cout << "the title is " << title << std::endl;
+
+    // nums = [1, 2, 3, 4, 5]
+    std::vector<int> nums  = toml::find<std::vector<int>>(data, "nums");
+    std::cout << "the length of `nums` is" << nums.size() << std::endl;
+
+    return 0;
+}
+```
+
+## Table of Contents
+
+- [Integration](#integration)
+- [Decoding a toml file](#decoding-a-toml-file)
+  - [In the case of syntax error](#in-the-case-of-syntax-error)
+  - [Invalid UTF-8 Codepoints](#invalid-utf-8-codepoints)
+- [Finding a toml value](#finding-a-toml-value)
+  - [Finding a value in a table](#finding-a-value-in-a-table)
+  - [In case of error](#in-case-of-error)
+  - [Dotted keys](#dotted-keys)
+- [Casting a toml value](#casting-a-toml-value)
+- [Checking value type](#checking-value-type)
+- [More about conversion](#more-about-conversion)
+  - [Converting an array](#converting-an-array)
+  - [Converting a table](#converting-a-table)
+  - [Getting an array of tables](#getting-an-array-of-tables)
+  - [Cost of conversion](#cost-of-conversion)
+  - [Converting datetime and its variants](#converting-datetime-and-its-variants)
+- [Getting with a fallback](#getting-with-a-fallback)
+- [Expecting conversion](#expecting-conversion)
+- [Visiting a toml::value](#visiting-a-tomlvalue)
+- [Constructing a toml::value](#constructing-a-tomlvalue)
+- [Preserving Comments](#preserving-comments)
+- [Customizing containers](#customizing-containers)
+- [TOML literal](#toml-literal)
+- [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types)
+- [Formatting user-defined error messages](#formatting-user-defined-error-messages)
+- [Obtaining location information](#obtaining-location-information)
+- [Exceptions](#exceptions)
+- [Serializing TOML data](#serializing-toml-data)
+- [Underlying types](#underlying-types)
+- [Unreleased TOML features](#unreleased-toml-features)
+- [Breaking Changes from v2](#breaking-changes-from-v2)
+- [Running Tests](#running-tests)
+- [Contributors](#contributors)
+- [Licensing Terms](#licensing-terms)
+
+## Integration
+
+Just include the file after adding it to the include path.
+
+```cpp
+#include <toml11/toml.hpp> // that's all! now you can use it.
+#include <iostream>
+
+int main()
+{
+    const auto data  = toml::parse("example.toml");
+    const auto title = toml::find<std::string>(data, "title");
+    std::cout << "the title is " << title << std::endl;
+    return 0;
+}
+```
+
+The convenient way is to add this repository as a git-submodule or to install
+it in your system by CMake.
+
+## Decoding a toml file
+
+To parse a toml file, the only thing you have to do is
+to pass a filename to the `toml::parse` function.
+
+```cpp
+const std::string fname("sample.toml");
+const toml::value data = toml::parse(fname);
+```
+
+If it encounters an error while opening a file, it will throw `std::runtime_error`.
+
+You can also pass a `std::istream` to the  `toml::parse` function.
+To show a filename in an error message, however, it is recommended to pass the
+filename with the stream.
+
+```cpp
+std::ifstream ifs("sample.toml", std::ios_base::binary);
+assert(ifs.good());
+const auto data = toml::parse(ifs, /*optional -> */ "sample.toml");
+```
+
+**Note**: When you are **on Windows, open a file in binary mode**.
+If a file is opened in text-mode, CRLF ("\r\n") will automatically be
+converted to LF ("\n") and this causes inconsistency between file size
+and the contents that would be read. This causes weird error.
+
+### In the case of syntax error
+
+If there is a syntax error in a toml file, `toml::parse` will throw
+`toml::syntax_error` that inherits `std::exception`.
+
+toml11 has clean and informative error messages inspired by Rust and
+it looks like the following.
+
+```console
+terminate called after throwing an instance of 'toml::syntax_error'
+  what():  [error] toml::parse_table: invalid line format # error description
+ --> example.toml                                         # file name
+ 3 | a = 42 = true                                        # line num and content
+   |        ^------ expected newline, but got '='.        # error reason
+```
+
+If you (mistakenly) duplicate tables and got an error, it is helpful to see
+where they are. toml11 shows both at the same time like the following.
+
+```console
+terminate called after throwing an instance of 'toml::syntax_error'
+  what():  [error] toml::insert_value: table ("table") already exists.
+ --> duplicate-table.toml
+ 1 | [table]
+   | ~~~~~~~ table already exists here
+ ...
+ 3 | [table]
+   | ~~~~~~~ table defined twice
+```
+
+When toml11 encounters a malformed value, it tries to detect what type it is.
+Then it shows hints to fix the format. An error message while reading one of
+the malformed files in [the language agnostic test suite](https://github.com/BurntSushi/toml-test).
+is shown below.
+
+```console
+what(): [error] bad time: should be HH:MM:SS.subsec
+ --> ./datetime-malformed-no-secs.toml
+ 1 | no-secs = 1987-07-05T17:45Z
+   |                     ^------- HH:MM:SS.subsec
+   | 
+Hint: pass: 1979-05-27T07:32:00, 1979-05-27 07:32:00.999999
+Hint: fail: 1979-05-27T7:32:00, 1979-05-27 17:32
+```
+
+You can find other examples in a job named `output_result` on
+[CircleCI](https://circleci.com/gh/ToruNiina/toml11).
+
+Since the error message generation is generally a difficult task, the current
+status is not ideal. If you encounter a weird error message, please let us know
+and contribute to improve the quality!
+
+### Invalid UTF-8 codepoints
+
+It throws `syntax_error` if a value of an escape sequence
+representing unicode character is not a valid UTF-8 codepoint.
+
+```console
+  what():  [error] toml::read_utf8_codepoint: input codepoint is too large.
+ --> utf8.toml
+ 1 | exceeds_unicode = "\U0011FFFF example"
+   |                              ^--------- should be in [0x00..0x10FFFF]
+```
+
+## Finding a toml value
+
+After parsing successfully, you can obtain the values from the result of
+`toml::parse` using `toml::find` function.
+
+```toml
+# sample.toml
+answer  = 42
+pi      = 3.14
+numbers = [1,2,3]
+time    = 1979-05-27T07:32:00Z
+```
+
+``` cpp
+const auto data      = toml::parse("sample.toml");
+const auto answer    = toml::find<std::int64_t    >(data, "answer");
+const auto pi        = toml::find<double          >(data, "pi");
+const auto numbers   = toml::find<std::vector<int>>(data, "numbers");
+const auto timepoint = toml::find<std::chrono::system_clock::time_point>(data, "time");
+```
+
+By default, `toml::find` returns a `toml::value`.
+
+```cpp
+const toml::value& answer = toml::find(data, "answer");
+```
+
+When you pass an exact TOML type that does not require type conversion,
+`toml::find` returns a reference without copying the value.
+
+```cpp
+const auto  data   = toml::parse("sample.toml");
+const auto& answer = toml::find<toml::integer>(data, "answer");
+```
+
+If the specified type requires conversion, you can't take a reference to the value.
+See also [underlying types](#underlying-types).
+
+**NOTE**: For some technical reason, automatic conversion between `integer` and
+`floating` is not supported. If you want to get a floating value even if a value
+has integer value, you need to convert it manually after obtaining a value,
+like the followings.
+
+```cpp
+const auto vx = toml::find(data, "x");
+double x = vx.is_floating() ? vx.as_floating(std::nothrow) :
+           static_cast<double>(vx.as_integer()); // it throws if vx is neither
+                                                 // floating nor integer.
+```
+
+### Finding a value in a table
+
+There are several way to get a value defined in a table.
+First, you can get a table as a normal value and find a value from the table.
+
+```toml
+[fruit]
+name = "apple"
+[fruit.physical]
+color = "red"
+shape = "round"
+```
+
+``` cpp
+const auto  data  = toml::parse("fruit.toml");
+const auto& fruit = toml::find(data, "fruit");
+const auto  name  = toml::find<std::string>(fruit, "apple");
+
+const auto& physical = toml::find(fruit, "physical");
+const auto  color    = toml::find<std::string>(fruit, "color");
+const auto  shape    = toml::find<std::string>(fruit, "shape");
+```
+
+Here, variable `fruit` is a `toml::value` and can be used as the first argument
+of `toml::find`.
+
+Second, you can pass as many arguments as the number of subtables to `toml::find`.
+
+```cpp
+const auto data  = toml::parse("fruit.toml");
+const auto color = toml::find<std::string>(data, "fruit", "physical", "color");
+const auto shape = toml::find<std::string>(data, "fruit", "physical", "shape");
+```
+
+### In case of error
+
+If the value does not exist, `toml::find` throws an error with the location of
+the table.
+
+```console
+terminate called after throwing an instance of 'std::out_of_range'
+  what():  [error] key "answer" not found
+ --> example.toml
+ 6 | [tab]
+   | ~~~~~ in this table
+```
+
+**Note**: It is recommended to find a table as `toml::value` because it has much information
+compared to `toml::table`, which is an alias of
+`std::unordered_map<std::string, toml::value>`. Since `toml::table` does not have
+any information about toml file, such as where the table was defined in the file.
+
+----
+
+If the specified type differs from the actual value contained, it throws
+`toml::type_error` that inherits `std::exception`.
+
+Similar to the case of syntax error, toml11 also displays clean error messages.
+The error message when you choose `int` to get `string` value would be like this.
+
+```console
+terminate called after throwing an instance of 'toml::type_error'
+  what():  [error] toml::value bad_cast to integer
+ --> example.toml
+ 3 | title = "TOML Example"
+   |         ~~~~~~~~~~~~~~ the actual type is string
+```
+
+**NOTE**: In order to show this kind of error message, all the toml values have
+a pointer to represent its range in a file. The entire contents of a file is
+shared by `toml::value`s and remains on the heap memory. It is recommended to
+destruct all the `toml::value` classes after configuring your application
+if you have a large TOML file compared to the memory resource.
+
+### Dotted keys
+
+TOML v0.5.0 has a new feature named "dotted keys".
+You can chain keys to represent the structure of the data.
+
+```toml
+physical.color = "orange"
+physical.shape = "round"
+```
+
+This is equivalent to the following.
+
+```toml
+[physical]
+color = "orange"
+shape = "round"
+```
+
+You can get both of the above tables with the same c++ code.
+
+```cpp
+const auto physical = toml::find(data, "physical");
+const auto color    = toml::find<std::string>(physical, "color");
+```
+
+The following code does not work for the above toml file.
+
+```cpp
+// XXX this does not work!
+const auto color = toml::find<std::string>(data, "physical.color");
+```
+
+The above code works with the following toml file.
+
+```toml
+"physical.color" = "orange"
+# equivalent to {"physical.color": "orange"},
+# NOT {"physical": {"color": "orange"}}.
+```
+
+
+## Casting a toml value
+
+### `toml::get`
+
+`toml::parse` returns `toml::value`. `toml::value` is a union type that can
+contain one of the following types.
+
+- `toml::boolean` (`bool`)
+- `toml::integer` (`std::int64_t`)
+- `toml::floating` (`double`)
+- `toml::string` (a type convertible to std::string)
+- `toml::local_date`
+- `toml::local_time`
+- `toml::local_datetime`
+- `toml::offset_datetime`
+- `toml::array` (by default, `std::vector<toml::value>`)
+  - It depends. See [customizing containers](#customizing-containers) for detail.
+- `toml::table` (by default, `std::unordered_map<toml::key, toml::value>`)
+  - It depends. See [customizing containers](#customizing-containers) for detail.
+
+To get a value inside, you can use `toml::get<T>()`. The usage is the same as
+`toml::find<T>` (actually, `toml::find` internally uses `toml::get` after casting
+a value to `toml::table`).
+
+``` cpp
+const toml::value  data    = toml::parse("sample.toml");
+const toml::value  answer_ = toml::get<toml::table >(data).at("answer");
+const std::int64_t answer  = toml::get<std::int64_t>(answer_);
+```
+
+When you pass an exact TOML type that does not require type conversion,
+`toml::get` returns a reference through which you can modify the content
+(if the `toml::value` is `const`, it returns `const` reference).
+
+```cpp
+toml::value   data    = toml::parse("sample.toml");
+toml::value   answer_ = toml::get<toml::table >(data).at("answer");
+toml::integer& answer = toml::get<toml::integer>(answer_);
+answer = 6 * 9; // write to data.answer. now `answer_` contains 54.
+```
+
+If the specified type requires conversion, you can't take a reference to the value.
+See also [underlying types](#underlying-types).
+
+It also throws a `toml::type_error` if the type differs.
+
+### `as_xxx`
+
+You can also use a member function to cast a value.
+
+```cpp
+const std::int64_t answer = data.as_table().at("answer").as_integer();
+```
+
+It also throws a `toml::type_error` if the type differs. If you are sure that
+the value `v` contains a value of the specified type, you can suppress checking
+by passing `std::nothrow`.
+
+```cpp
+const auto& answer = data.as_table().at("answer");
+if(answer.is_integer() && answer.as_integer(std::nothrow) == 42)
+{
+    std::cout << "value is 42" << std::endl;
+}
+```
+
+If `std::nothrow` is passed, the functions are marked as noexcept.
+
+The full list of the functions is below.
+
+```cpp
+namespace toml {
+class value {
+    // ...
+    const boolean&         as_boolean()         const&;
+    const integer&         as_integer()         const&;
+    const floating&        as_floating()        const&;
+    const string&          as_string()          const&;
+    const offset_datetime& as_offset_datetime() const&;
+    const local_datetime&  as_local_datetime()  const&;
+    const local_date&      as_local_date()      const&;
+    const local_time&      as_local_time()      const&;
+    const array&           as_array()           const&;
+    const table&           as_table()           const&;
+    // --------------------------------------------------------
+    // non-const version
+    boolean&               as_boolean()         &;
+    // ditto...
+    // --------------------------------------------------------
+    // rvalue version
+    boolean&&              as_boolean()         &&;
+    // ditto...
+
+    // --------------------------------------------------------
+    // noexcept versions ...
+    const boolean&         as_boolean(const std::nothrow_t&) const& noexcept;
+    boolean&               as_boolean(const std::nothrow_t&) &      noexcept;
+    boolean&&              as_boolean(const std::nothrow_t&) &&     noexcept;
+    // ditto...
+};
+} // toml
+```
+
+### `at()`
+
+You can access to the element of a table and an array by `toml::basic_value::at`.
+
+```cpp
+const toml::value v{1,2,3,4,5};
+std::cout << v.at(2).as_integer() << std::endl; // 3
+
+const toml::value v{{"foo", 42}, {"bar", 3.14}};
+std::cout << v.at("foo").as_integer() << std::endl; // 42
+```
+
+If an invalid key (integer for a table, string for an array), it throws
+`toml::type_error` for the conversion. If the provided key is out-of-range,
+it throws `std::out_of_range`.
+
+Note that, although `std::string` has `at()` member function, `toml::value::at`
+throws if the contained type is a string. Because `std::string` does not
+contain `toml::value`.
+
+## Checking value type
+
+You can check the type of a value by `is_xxx` function.
+
+```cpp
+const toml::value v = /* ... */;
+if(v.is_integer())
+{
+    std::cout << "value is an integer" << std::endl;
+}
+```
+
+The complete list of the functions is below.
+
+```cpp
+namespace toml {
+class value {
+    // ...
+    bool is_boolean()         const noexcept;
+    bool is_integer()         const noexcept;
+    bool is_floating()        const noexcept;
+    bool is_string()          const noexcept;
+    bool is_offset_datetime() const noexcept;
+    bool is_local_datetime()  const noexcept;
+    bool is_local_date()      const noexcept;
+    bool is_local_time()      const noexcept;
+    bool is_array()           const noexcept;
+    bool is_table()           const noexcept;
+    bool is_uninitialized()   const noexcept;
+    // ...
+};
+} // toml
+```
+
+Also, you can get `enum class value_t` from `toml::value::type()`.
+
+```cpp
+switch(data.at("something").type())
+{
+    case toml::value_t::integer:  /*do some stuff*/ ; break;
+    case toml::value_t::floating: /*do some stuff*/ ; break;
+    case toml::value_t::string :  /*do some stuff*/ ; break;
+    default : throw std::runtime_error(
+        "unexpected type : " + toml::stringize(data.at("something").type()));
+}
+```
+
+The complete list of the `enum`s can be found in the section
+[underlying types](#underlying-types).
+
+The `enum`s can be used as a parameter of `toml::value::is` function like the following.
+
+```cpp
+toml::value v = /* ... */;
+if(v.is(toml::value_t::boolean)) // ...
+```
+
+## More about conversion
+
+Since `toml::find` internally uses `toml::get`, all the following examples work
+with both `toml::get` and `toml::find`.
+
+### Converting an array
+
+You can get any kind of `container` class from a `toml::array`
+except for `map`-like classes.
+
+``` cpp
+// # sample.toml
+// numbers = [1,2,3]
+
+const auto numbers = toml::find(data, "numbers");
+
+const auto vc  = toml::get<std::vector<int>  >(numbers);
+const auto ls  = toml::get<std::list<int>    >(numbers);
+const auto dq  = toml::get<std::deque<int>   >(numbers);
+const auto ar  = toml::get<std::array<int, 3>>(numbers);
+// if the size of data.at("numbers") is larger than that of std::array,
+// it will throw toml::type_error because std::array is not resizable.
+```
+
+Surprisingly, you can convert `toml::array` into `std::pair` and `std::tuple`.
+
+```cpp
+// numbers = [1,2,3]
+const auto tp = toml::get<std::tuple<short, int, unsigned int>>(numbers);
+```
+
+This functionality is helpful when you have a toml file like the following.
+
+```toml
+array_of_arrays = [[1, 2, 3], ["foo", "bar", "baz"]] # toml allows this
+```
+
+What is the corresponding C++ type?
+Obviously, it is a `std::pair` of `std::vector`s.
+
+```cpp
+const auto array_of_arrays = toml::find(data, "array_of_arrays");
+const auto aofa = toml::get<
+    std::pair<std::vector<int>, std::vector<std::string>>
+    >(array_of_arrays);
+```
+
+If you don't know the type of the elements, you can use `toml::array`,
+which is a `std::vector` of `toml::value`, instead.
+
+```cpp
+const auto a_of_a = toml::get<toml::array>(array_of_arrays);
+const auto first  = toml::get<std::vector<int>>(a_of_a.at(0));
+```
+
+You can change the implementation of `toml::array` with `std::deque` or some
+other array-like container. See [Customizing containers](#customizing-containers)
+for detail.
+
+### Converting a table
+
+When all the values of the table have the same type, toml11 allows you to
+convert a `toml::table` to a `map` that contains the convertible type.
+
+```toml
+[tab]
+key1 = "foo" # all the values are
+key2 = "bar" # toml String
+```
+
+```cpp
+const auto data = toml::parse("sample.toml");
+const auto tab = toml::find<std::map<std::string, std::string>>(data, "tab");
+std::cout << tab["key1"] << std::endl; // foo
+std::cout << tab["key2"] << std::endl; // bar
+```
+
+But since `toml::table` is just an alias of `std::unordered_map<toml::key, toml::value>`,
+normally you don't need to convert it because it has all the functionalities that
+`std::unordered_map` has (e.g. `operator[]`, `count`, and `find`). In most cases
+`toml::table` is sufficient.
+
+```cpp
+toml::table tab = toml::get<toml::table>(data);
+if(data.count("title") != 0)
+{
+    data["title"] = std::string("TOML example");
+}
+```
+
+You can change the implementation of `toml::table` with `std::map` or some
+other map-like container. See [Customizing containers](#customizing-containers)
+for detail.
+
+### Getting an array of tables
+
+An array of tables is just an array of tables.
+You can get it in completely the same way as the other arrays and tables.
+
+```toml
+# sample.toml
+array_of_inline_tables = [{key = "value1"}, {key = "value2"}, {key = "value3"}]
+
+[[array_of_tables]]
+key = "value4"
+[[array_of_tables]]
+key = "value5"
+[[array_of_tables]]
+key = "value6"
+```
+
+```cpp
+const auto data = toml::parse("sample.toml");
+const auto aot1 = toml::find<std::vector<toml::table>>(data, "array_of_inline_tables");
+const auto aot2 = toml::find<std::vector<toml::table>>(data, "array_of_tables");
+```
+
+### Cost of conversion
+
+Although conversion through `toml::(get|find)` is convenient, it has additional
+copy-cost because it copies data contained in `toml::value` to the
+user-specified type. Of course in some cases this overhead is not ignorable.
+
+```cpp
+// the following code constructs a std::vector.
+// it requires heap allocation for vector and element conversion.
+const auto array = toml::find<std::vector<int>>(data, "foo");
+```
+
+By passing the exact types, `toml::get` returns reference that has no overhead.
+
+``` cpp
+const auto& tab     = toml::find<toml::table>(data, "tab");
+const auto& numbers = toml::find<toml::array>(data, "numbers");
+```
+
+Also, `as_xxx` are zero-overhead because they always return a reference.
+
+``` cpp
+const auto& tab     = toml::find(data, "tab"    ).as_table();
+const auto& numbers = toml::find(data, "numbers").as_array();
+```
+
+In this case you need to call `toml::get` each time you access to
+the element of `toml::array` because `toml::array` is an array of `toml::value`.
+
+```cpp
+const auto& num0 = toml::get<toml::integer>(numbers.at(0));
+const auto& num1 = toml::get<toml::integer>(numbers.at(1));
+const auto& num2 = toml::get<toml::integer>(numbers.at(2));
+```
+
+### Converting datetime and its variants
+
+TOML v0.5.0 has 4 different datetime objects, `local_date`, `local_time`,
+`local_datetime`, and `offset_datetime`.
+
+Since `local_date`, `local_datetime`, and `offset_datetime` represent a time
+point, you can convert them to `std::chrono::system_clock::time_point`.
+
+Contrary, `local_time` does not represents a time point because they lack a
+date information, but it can be converted to `std::chrono::duration` that
+represents a duration from the beginning of the day, `00:00:00.000`.
+
+```toml
+date = 2018-12-23
+time = 12:30:00
+l_dt = 2018-12-23T12:30:00
+o_dt = 2018-12-23T12:30:00+09:30
+```
+
+```cpp
+const auto data = toml::parse("sample.toml");
+
+const auto date = toml::get<std::chrono::system_clock::time_point>(data.at("date"));
+const auto l_dt = toml::get<std::chrono::system_clock::time_point>(data.at("l_dt"));
+const auto o_dt = toml::get<std::chrono::system_clock::time_point>(data.at("o_dt"));
+
+const auto time = toml::get<std::chrono::minutes>(data.at("time")); // 12 * 60 + 30 min
+```
+
+toml11 defines its own datetime classes.
+You can see the definitions in [toml/datetime.hpp](toml/datetime.hpp).
+
+## Getting with a fallback
+
+`toml::find_or` returns a default value if the value is not found or has a
+different type.
+
+```cpp
+const auto data = toml::parse("example.toml");
+const auto num  = toml::find_or(data, "num", 42);
+```
+
+Also, `toml::get_or` returns a default value if `toml::get<T>` failed.
+
+```cpp
+toml::value v("foo"); // v contains String
+const int value = toml::get_or(v, 42); // conversion fails. it returns 42.
+```
+
+These functions automatically deduce what type you want to get
+from the default value you passed.
+
+To get a reference through this function, take care about the default value.
+
+```cpp
+toml::value v("foo"); // v contains String
+toml::integer& i = toml::get_or(v, 42); // does not work because binding `42`
+                                        // to `integer&` is invalid
+toml::integer opt = 42;
+toml::integer& i = toml::get_or(v, opt); // this works.
+```
+
+## Expecting conversion
+
+By using `toml::expect`, you will get your expected value or an error message
+without throwing `toml::type_error`.
+
+```cpp
+const auto value = toml::expect<std::string>(data.at("title"));
+if(value.is_ok()) {
+    std::cout << value.unwrap() << std::endl;
+} else {
+    std::cout << value.unwrap_err() << std::endl;
+}
+```
+
+Also, you can pass a function object to modify the expected value.
+
+```cpp
+const auto value = toml::expect<int>(data.at("number"))
+    .map(// function that receives expected type (here, int)
+    [](const int number) -> double {
+        return number * 1.5 + 1.0;
+    }).unwrap_or(/*default value =*/ 3.14);
+```
+
+## Visiting a toml::value
+
+toml11 provides `toml::visit` to apply a function to `toml::value` in the
+same way as `std::variant`.
+
+```cpp
+const toml::value v(3.14);
+toml::visit([](const auto& val) -> void {
+        std::cout << val << std::endl;
+    }, v);
+```
+
+The function object that would be passed to `toml::visit` must be able to
+recieve all the possible TOML types. Also, the result types should be the same
+each other.
+
+## Constructing a toml::value
+
+`toml::value` can be constructed in various ways.
+
+```cpp
+toml::value v(true);     // boolean
+toml::value v(42);       // integer
+toml::value v(3.14);     // floating
+toml::value v("foobar"); // string
+toml::value v(toml::local_date(2019, toml::month_t::Apr, 1)); // date
+toml::value v{1, 2, 3, 4, 5};                                 // array
+toml::value v{{"foo", 42}, {"bar", 3.14}, {"baz", "qux"}};    // table
+```
+
+When constructing a string, you can choose to use either literal or basic string.
+By default, it will be a basic string.
+
+```cpp
+toml::value v("foobar", toml::string_t::basic  );
+toml::value v("foobar", toml::string_t::literal);
+```
+
+Datetime objects can be constructed from `std::tm` and
+`std::chrono::system_clock::time_point`. But you need to specify what type
+you use to avoid ambiguity.
+
+```cpp
+const auto now = std::chrono::system_clock::now();
+toml::value v(toml::local_date(now));
+toml::value v(toml::local_datetime(now));
+toml::value v(toml::offset_datetime(now));
+```
+
+Since local time is not equivalent to a time point, because it lacks date
+information, it will be constructed from `std::chrono::duration`.
+
+```cpp
+toml::value v(toml::local_time(std::chrono::hours(10)));
+```
+
+You can construct an array object not only from `initializer_list`, but also
+from STL containers.
+
+```cpp
+std::vector<int> vec{1,2,3,4,5};
+toml::value v = vec;
+```
+
+All the elements of `initializer_list` should be convertible into `toml::value`.
+
+## Preserving comments
+
+After toml11 v3, you can choose whether comments are preserved or not.
+
+```cpp
+const auto data1 = toml::parse<toml::discard_comments >("example.toml");
+const auto data2 = toml::parse<toml::preserve_comments>("example.toml");
+```
+
+Comments related to a value can be obtained by `toml::value::comments()`.
+The return value has the same interface as `std::vector<std::string>`.
+
+```cpp
+const auto& com = v.comments();
+for(const auto& c : com)
+{
+    std::cout << c << std::endl;
+}
+```
+
+Comments just before and just after (within the same line) a value are kept in a value.
+
+```toml
+# this is a comment for v1.
+v1 = "foo"
+
+v2 = "bar" # this is a comment for v2.
+# Note that this comment is NOT a comment for v2.
+
+# this comment is not related to any value
+# because there are empty lines between v3.
+# this comment will be ignored even if you set `preserve_comments`.
+
+# this is a comment for v3
+# this is also a comment for v3.
+v3 = "baz" # ditto.
+```
+
+Each comment line becomes one element of a `std::vector`.
+
+Hash signs will be removed, but spaces after hash sign will not be removed.
+
+```cpp
+v1.comments().at(0) == " this is a comment for v1."s;
+
+v2.comments().at(1) == " this is a comment for v1."s;
+
+v3.comments().at(0) == " this is a comment for v3."s;
+v3.comments().at(1) == " this is also a comment for v3."s;
+v3.comments().at(2) == " ditto."s;
+```
+
+Note that a comment just after an opening brace of an array will not be a
+comment for the array.
+
+```toml
+# this is a comment for a.
+a = [ # this is not a comment for a. this will be ignored.
+  1, 2, 3,
+  # this is a comment for `42`.
+  42, # this is also a comment for `42`.
+  5
+] # this is a comment for a.
+```
+
+You can also append and modify comments.
+The interfaces are the same as `std::vector<std::string>`.
+
+```cpp
+toml::basic_value<toml::preserve_comments> v(42);
+v.comments().push_back(" add this comment.");
+// # add this comment.
+// i = 42
+```
+
+Also, you can pass a `std::vector<std::string>` when constructing a
+`toml::basic_value<toml::preserve_comments>`.
+
+```cpp
+std::vector<std::string> comments{"comment 1", "comment 2"};
+const toml::basic_value<toml::preserve_comments> v1(42, std::move(comments));
+const toml::basic_value<toml::preserve_comments> v2(42, {"comment 1", "comment 2"});
+```
+
+When `toml::discard_comments` is chosen, comments will not be contained in a value.
+`value::comments()` will always be kept empty.
+All the modification on comments would be ignored.
+All the element access in a `discard_comments` causes the same error as accessing
+an element of an empty `std::vector`.
+
+The comments will also be serialized. If comments exist, those comments will be
+added just before the values.
+
+__NOTE__: Result types from `toml::parse(...)` and
+`toml::parse<toml::preserve_comments>(...)` are different.
+
+## Customizing containers
+
+Actually, `toml::basic_value` has 3 template arguments.
+
+```cpp
+template<typename Comment, // discard/preserve_comment
+         template<typename ...> class Table = std::unordered_map,
+         template<typename ...> class Array = std::vector>
+class basic_value;
+```
+
+This enables you to change the containers used inside. E.g. you can use
+`std::map` to contain a table object instead of `std::unordered_map`.
+And also can use `std::deque` as a array object instead of `std::vector`.
+
+You can set these parameters while calling `toml::parse` function.
+
+```cpp
+const auto data = toml::parse<
+    toml::preserve_comments, std::map, std::deque
+    >("example.toml");
+```
+
+Needless to say, the result types from `toml::parse(...)` and
+`toml::parse<Com, Map, Cont>(...)` are different (unless you specify the same
+types as default).
+
+Note that, since `toml::table` and `toml::array` is an alias for a table and an
+array of a default `toml::value`, so it is different from the types actually
+contained in a `toml::basic_value` when you customize containers.
+To get the actual type in a generic way, use
+`typename toml::basic_type<C, T, A>::table_type` and
+`typename toml::basic_type<C, T, A>::array_type`.
+
+## TOML literal
+
+toml11 supports `"..."_toml` literal.
+It accept both a bare value and a file content.
+
+```cpp
+using namespace toml::literals::toml_literals;
+
+// `_toml` can convert a bare value without key
+const toml::value v = u8"0xDEADBEEF"_toml;
+// v is an Integer value containing 0xDEADBEEF.
+
+// raw string literal (`R"(...)"` is useful for this purpose)
+const toml::value t = u8R"(
+    title = "this is TOML literal"
+    [table]
+    key = "value"
+)"_toml;
+// the literal will be parsed and the result will be contained in t
+```
+
+The literal function is defined in the same way as the standard library literals
+such as `std::literals::string_literals::operator""s`.
+
+```cpp
+namespace toml
+{
+inline namespace literals
+{
+inline namespace toml_literals
+{
+toml::value operator"" _toml(const char* str, std::size_t len);
+} // toml_literals
+} // literals
+} // toml
+```
+
+Access to the operator can be gained with `using namespace toml::literals;`,
+`using namespace toml::toml_literals`, and `using namespace toml::literals::toml_literals`.
+
+Note that a key that is composed only of digits is allowed in TOML.
+And, unlike the file parser, toml-literal allows a bare value without a key.
+Thus it is difficult to distinguish arrays having integers and definitions of
+tables that are named as digits.
+Currently, literal `[1]` becomes a table named "1".
+To ensure a literal to be considered as an array with one element, you need to
+add a comma after the first element (like `[1,]`).
+
+```cpp
+"[1,2,3]"_toml;   // This is an array
+"[table]"_toml;   // This is a table that has an empty table named "table" inside.
+"[[1,2,3]]"_toml; // This is an array of arrays
+"[[table]]"_toml; // This is a table that has an array of tables inside.
+
+"[[1]]"_toml;     // This literal is ambiguous.
+                  // Currently, it becomes a table that has array of table "1".
+"1 = [{}]"_toml;  // This is a table that has an array of table named 1.
+"[[1,]]"_toml;    // This is an array of arrays.
+"[[1],]"_toml;    // ditto.
+```
+
+NOTE: `_toml` literal returns a `toml::value`  that does not have comments.
+
+## Conversion between toml value and arbitrary types
+
+You can also use `toml::get` and other related functions with the types
+you defined after you implement a way to convert it.
+
+```cpp
+namespace ext
+{
+struct foo
+{
+    int         a;
+    double      b;
+    std::string c;
+};
+} // ext
+
+const auto data = toml::parse("example.toml");
+
+// to do this
+const foo f = toml::find<ext::foo>(data, "foo");
+```
+
+There are 2 ways to use `toml::get` with the types that you defined.
+
+The first one is to implement `from_toml(const toml::value&)` member function.
+
+```cpp
+namespace ext
+{
+struct foo
+{
+    int         a;
+    double      b;
+    std::string c;
+
+    void from_toml(const toml::value& v)
+    {
+        this->a = toml::find<int        >(v, "a");
+        this->b = toml::find<double     >(v, "b");
+        this->c = toml::find<std::string>(v, "c");
+        return;
+    }
+};
+} // ext
+```
+
+In this way, because `toml::get` first constructs `foo` without arguments,
+the type should be default-constructible.
+
+The second is to implement specialization of `toml::from` for your type.
+
+```cpp
+namespace ext
+{
+struct foo
+{
+    int         a;
+    double      b;
+    std::string c;
+};
+} // ext
+
+namespace toml
+{
+template<>
+struct from<ext::foo>
+{
+    static ext::foo from_toml(const value& v)
+    {
+        ext::foo f;
+        f.a = find<int        >(v, "a");
+        f.b = find<double     >(v, "b");
+        f.c = find<std::string>(v, "c");
+        return f;
+    }
+};
+} // toml
+```
+
+In this way, since the conversion function is defined outside of the class,
+you can add conversion between `toml::value` and classes defined in another library.
+
+Note that you cannot implement both of the functions because the overload
+resolution of `toml::get` will be ambiguous.
+
+If you want to convert any versions of `toml::basic_value`,
+you need to templatize the conversion function as follows.
+
+```cpp
+struct foo
+{
+    template<typename C, template<typename ...> class M, template<typename ...> class A>
+    void from_toml(const toml::basic_value<C, M, A>& v)
+    {
+        this->a = toml::find<int        >(v, "a");
+        this->b = toml::find<double     >(v, "b");
+        this->c = toml::find<std::string>(v, "c");
+        return;
+    }
+};
+// or
+namespace toml
+{
+template<>
+struct from<ext::foo>
+{
+    template<typename C, template<typename ...> class M, template<typename ...> class A>
+    static ext::foo from_toml(const basic_value<C, M, A>& v)
+    {
+        ext::foo f;
+        f.a = find<int        >(v, "a");
+        f.b = find<double     >(v, "b");
+        f.c = find<std::string>(v, "c");
+        return f;
+    }
+};
+} // toml
+```
+
+----
+
+The opposite direction is also supported in a similar way. You can directly
+pass your type to `toml::value`'s constructor by introducing `into_toml` or
+`toml::into<T>`.
+
+```cpp
+namespace ext
+{
+struct foo
+{
+    int         a;
+    double      b;
+    std::string c;
+
+    toml::table into_toml() const // you need to mark it const.
+    {
+        return toml::table{{"a", this->a}, {"b", this->b}, {"c", this->c}};
+    }
+};
+} // ext
+
+ext::foo    f{42, 3.14, "foobar"};
+toml::value v(f);
+```
+
+The definition of `toml::into<T>` is similar to `toml::from<T>`.
+
+```cpp
+namespace ext
+{
+struct foo
+{
+    int         a;
+    double      b;
+    std::string c;
+};
+} // ext
+
+namespace toml
+{
+template<>
+struct into<ext::foo>
+{
+    static toml::table into_toml(const ext::foo& f)
+    {
+        return toml::table{{"a", f.a}, {"b", f.b}, {"c", f.c}};
+    }
+};
+} // toml
+
+ext::foo    f{42, 3.14, "foobar"};
+toml::value v(f);
+```
+
+Any type that can be converted to `toml::value`, e.g. `int`, `toml::table` and
+`toml::array` are okay to return from `into_toml`.
+
+## Formatting user-defined error messages
+
+When you encounter an error after you read the toml value, you may want to
+show the error with the value.
+
+toml11 provides you a function that formats user-defined error message with
+related values. With a code like the following,
+
+```cpp
+const auto value = toml::find<int>(data, "num");
+if(value < 0)
+{
+    std::cerr << toml::format_error("[error] value should be positive",
+                                    data.at("num"), "positive number required")
+              << std::endl;
+}
+```
+
+you will get an error message like this.
+
+```console
+[error] value should be positive
+ --> example.toml
+ 3 | num = -42
+   |       ~~~ positive number required
+```
+
+When you pass two values to `toml::format_error`,
+
+```cpp
+const auto min = toml::find<int>(range, "min");
+const auto max = toml::find<int>(range, "max");
+if(max < min)
+{
+    std::cerr << toml::format_error("[error] max should be larger than min",
+                                    data.at("min"), "minimum number here",
+                                    data.at("max"), "maximum number here");
+              << std::endl;
+}
+```
+
+you will get an error message like this.
+
+```console
+[error] max should be larger than min
+ --> example.toml
+ 3 | min = 54
+   |       ~~ minimum number here
+ ...
+ 4 | max = 42
+   |       ~~ maximum number here
+```
+
+## Obtaining location information
+
+You can also format error messages in your own way by using `source_location`.
+
+```cpp
+struct source_location
+{
+    std::uint_least32_t line()      const noexcept;
+    std::uint_least32_t column()    const noexcept;
+    std::uint_least32_t region()    const noexcept;
+    std::string const&  file_name() const noexcept;
+    std::string const&  line_str()  const noexcept;
+};
+// +-- line()       +--- length of the region (here, region() == 9)
+// v            .---+---.
+// 12 | value = "foo bar" <- line_str() returns the line itself.
+//              ^-------- column() points here
+```
+
+You can get this by
+```cpp
+const toml::value           v   = /*...*/;
+const toml::source_location loc = v.location();
+```
+
+## Exceptions
+
+All the exceptions thrown by toml11 inherits `toml::exception` that inherits
+`std::exception`.
+
+```cpp
+namespace toml {
+struct exception      : public std::exception  {/**/};
+struct syntax_error   : public toml::exception {/**/};
+struct type_error     : public toml::exception {/**/};
+struct internal_error : public toml::exception {/**/};
+} // toml
+```
+
+`toml::exception` has `toml::exception::location()` member function that returns
+`toml::source_location`, in addition to `what()`.
+
+```cpp
+namespace toml {
+struct exception : public std::exception
+{
+    // ...
+    source_location const& location() const noexcept;
+};
+} // toml
+```
+
+It represents where the error occurs.
+
+## Serializing TOML data
+
+toml11 enables you to serialize data into toml format.
+
+```cpp
+const toml::value data{{"foo", 42}, {"bar", "baz"}};
+std::cout << data << std::endl;
+// bar = "baz"
+// foo = 42
+```
+
+toml11 automatically makes a small table and small array inline.
+You can specify the width to make them inline by `std::setw` for streams.
+
+```cpp
+const toml::value data{
+    {"qux",    {{"foo", 42}, {"bar", "baz"}}},
+    {"quux",   {"small", "array", "of", "strings"}},
+    {"foobar", {"this", "array", "of", "strings", "is", "too", "long",
+                "to", "print", "into", "single", "line", "isn't", "it?"}},
+};
+
+// the threshold becomes 80.
+std::cout << std::setw(80) << data << std::endl;
+// foobar = [
+// "this","array","of","strings","is","too","long","to","print","into",
+// "single","line","isn't","it?",
+// ]
+// quux = ["small","array","of","strings"]
+// qux = {bar="baz",foo=42}
+
+
+// the width is 0. nothing become inline.
+std::cout << std::setw(0) << data << std::endl;
+// foobar = [
+// "this",
+// ... (snip)
+// "it?",
+// ]
+// quux = [
+// "small",
+// "array",
+// "of",
+// "strings",
+// ]
+// [qux]
+// bar = "baz"
+// foo = 42
+```
+
+It is recommended to set width before printing data. Some I/O functions changes
+width to 0, and it makes all the stuff (including `toml::array`) multiline.
+The resulting files becomes too long.
+
+To control the precision of floating point numbers, you need to pass
+`std::setprecision` to stream.
+
+```cpp
+const toml::value data{
+    {"pi", 3.141592653589793},
+    {"e",  2.718281828459045}
+};
+std::cout << std::setprecision(17) << data << std::endl;
+// e = 2.7182818284590451
+// pi = 3.1415926535897931
+std::cout << std::setprecision( 7) << data << std::endl;
+// e = 2.718282
+// pi = 3.141593
+```
+
+There is another way to format toml values, `toml::format()`.
+It returns `std::string` that represents a value.
+
+```cpp
+const toml::value v{{"a", 42}};
+const std::string fmt = toml::format(v);
+// a = 42
+```
+
+Note that since `toml::format` formats a value, the resulting string may lack
+the key value.
+
+```cpp
+const toml::value v{3.14};
+const std::string fmt = toml::format(v);
+// 3.14
+```
+
+To control the width and precision, `toml::format` receives optional second and
+third arguments to set them. By default, the witdh is 80 and the precision is
+`std::numeric_limits<double>::max_digit10`.
+
+```cpp
+const auto serial = toml::format(data, /*width = */ 0, /*prec = */ 17);
+```
+
+When you pass a comment-preserving-value, the comment will also be serialized.
+An array or a table containing a value that has a comment would not be inlined.
+
+## Underlying types
+
+The toml types (can be used as `toml::*` in this library) and corresponding `enum` names are listed in the table below.
+
+| TOML type      | underlying c++ type                | enum class                       |
+| -------------- | ---------------------------------- | -------------------------------- |
+| Boolean        | `bool`                             | `toml::value_t::boolean`         |
+| Integer        | `std::int64_t`                     | `toml::value_t::integer`         |
+| Float          | `double`                           | `toml::value_t::floating`        |
+| String         | `toml::string`                     | `toml::value_t::string`          |
+| LocalDate      | `toml::local_date`                 | `toml::value_t::local_date`      |
+| LocalTime      | `toml::local_time`                 | `toml::value_t::local_time`      |
+| LocalDatetime  | `toml::local_datetime`             | `toml::value_t::local_datetime`  |
+| OffsetDatetime | `toml::offset_datetime`            | `toml::value_t::offset_datetime` |
+| Array          | `array-like<toml::value>`          | `toml::value_t::array`           |
+| Table          | `map-like<toml::key, toml::value>` | `toml::value_t::table`           |
+
+`array-like` and `map-like` are the STL containers that works like a `std::vector` and
+`std::unordered_map`, respectively. By default, `std::vector` and `std::unordered_map`
+are used. See [Customizing containers](#customizing-containers) for detail.
+
+`toml::string` is effectively the same as `std::string` but has an additional
+flag that represents a kind of a string, `string_t::basic` and `string_t::literal`.
+Although `std::string` is not an exact toml type, still you can get a reference
+that points to internal `std::string` by using `toml::get<std::string>()` for convenience.
+The most important difference between `std::string` and `toml::string` is that
+`toml::string` will be formatted as a TOML string when outputed with `ostream`.
+This feature is introduced to make it easy to write a custom serializer.
+
+`Datetime` variants are `struct` that are defined in this library.
+Because `std::chrono::system_clock::time_point` is a __time point__,
+not capable of representing a Local Time independent from a specific day.
+
+It is recommended to get `datetime`s as `std::chrono` classes through `toml::get`.
+
+## Unreleased TOML features
+
+There are some unreleased features in toml-lang/toml:master.
+Currently, the following features are available after defining
+`TOML11_USE_UNRELEASED_TOML_FEATURES` macro flag.
+
+- Leading zeroes in exponent parts of floats are permitted.
+  - e.g. `1.0e+01`, `5e+05`
+- Allow raw tab characters in basic strings and multi-line basic strings.
+
+## Breaking Changes from v2
+
+Although toml11 is relatively new library (it's three years old now), it had
+some confusing and inconvenient user-interfaces because of historical reasons.
+
+Between v2 and v3, those interfaces are rearranged.
+
+- `toml::parse` now returns a `toml::value`, not `toml::table`.
+- `toml::value` is now an alias of `toml::basic_value<discard_comment, std::vector, std::unordered_map>`.
+  - See [Customizing containers](#customizing-containers) for detail.
+- The elements of `toml::value_t` are renamed as `snake_case`.
+  - See [Underlying types](#underlying-types) for detail.
+- Supports for the CamelCaseNames are dropped.
+  - See [Underlying types](#underlying-types) for detail.
+- `(is|as)_float` has been removed to make the function names consistent with others.
+  - Since `float` is a keyword, toml11 named a float type as `toml::floating`.
+  - Also a `value_t` corresponds to `toml::floating` is named `value_t::floating`.
+  - So `(is|as)_floating` is introduced and `is_float` has been removed.
+  - See [Casting a toml::value](#casting-a-tomlvalue) and [Checking value type](#checking-value-type) for detail.
+- An overload of `toml::find` for `toml::table` has been dropped. Use `toml::value` version instead.
+  - Because type conversion between a table and a value causes ambiguity while overload resolution
+  - Since `toml::parse` now returns a `toml::value`, this feature becomes less important.
+  - Also because `toml::table` is a normal STL container, implementing utility function is easy.
+  - See [Finding a toml::value](#finding-a-toml-value) for detail.
+- An overload of `operator<<` and `toml::format` for `toml::table`s are dropped.
+  - Use `toml::value` instead.
+  - See [Serializing TOML data](#serializing-toml-data) for detail.
+- Interface around comments.
+  - See [Preserving Comments](#preserving-comments) for detail.
+- An ancient `from_toml/into_toml` has been removed. Use arbitrary type conversion support.
+  - See [Conversion between toml value and arbitrary types](#conversion-between-toml-value-and-arbitrary-types) for detail.
+
+Such a big change will not happen in the coming years.
+
+## Running Tests
+
+To run test codes, you need to clone toml-lang/toml repository under `build/` directory
+because some of the test codes read a file in the repository.
+
+```sh
+$ mkdir build
+$ cd build
+$ git clone https://github.com/toml-lang/toml.git
+$ cmake ..
+$ make
+$ make test
+```
+
+To run the language agnostic test suite, you need to compile
+`tests/check_toml_test.cpp` and pass it to the tester.
+
+## Contributors
+
+I appreciate the help of the contributors who introduced the great feature to this library.
+
+- Guillaume Fraux (@Luthaf)
+  - Windows support and CI on Appvayor
+  - Intel Compiler support
+- Quentin Khan (@xaxousis)
+  - Found & Fixed a bug around ODR
+  - Improved error messages for invaild keys to show the location where the parser fails
+- Petr Beneš (@wbenny)
+  - Fixed warnings on MSVC
+- Ivan Shynkarenka (@chronoxor)
+  - Fixed Visual Studio 2019 warnings
+- @khoitd1997
+  - Fixed warnings while type conversion
+- @KerstinKeller
+  - Added installation script to CMake
+- J.C. Moyer (@jcmoyer)
+  - Fixed an example code in the documentation
+
+## Licensing terms
+
+This product is licensed under the terms of the [MIT License](LICENSE).
+
+- Copyright (c) 2017-2019 Toru Niina
+
+All rights reserved.
diff --git a/python/sixtracklib/CMakeLists.txt b/python/sixtracklib/CMakeLists.txt
index a795715f..d7fbe7a1 100644
--- a/python/sixtracklib/CMakeLists.txt
+++ b/python/sixtracklib/CMakeLists.txt
@@ -33,18 +33,8 @@ set( SIXTRL_PY_INSTALL_PATH
      "${CMAKE_INSTALL_PREFIX}/python/sixtracklib/config.py" )
 
 install( CODE
-    "set( PYTHON_SIXTRACKLIB_SHARED_LIB  ${PYTHON_SIXTRACKLIB_SHARED_LIB}  )
-     set( PYTHON_SIXTRACKLIB_MODULES_STR ${PYTHON_SIXTRACKLIB_MODULES_STR} )
-     set( PYTHON_SIXTRL_C99_NAMESPACE_STR ${PYTHON_SIXTRL_C99_NAMESPACE_STR} )
-     set( PYTHON_SIXTRL_CXX_NAMESPACE_STR ${PYTHON_SIXTRL_CXX_NAMESPACE_STR} )
-     set( PYTHON_SIXTRL_C99_NAMESPACE_PREFIX_STR
-          ${PYTHON_SIXTRL_C99_NAMESPACE_PREFIX_STR} )
-     set( PYTHON_SIXTRL_CXX_NAMESPACE_PREFIX_STR
-          ${PYTHON_SIXTRL_CXX_NAMESPACE_PREFIX_STR} )
-     set( PYTHON_SIXTRL_ENABLE_APERTURE_CHECK
-         ${PYTHON_SIXTRL_ENABLE_APERATURE_CHECK} )
-     set( PYTHON_SIXTRL_APERTURE_X_LIMIT ${PYTHON_SIXTRL_APERTURE_X_LIMIT} )
-     set( PYTHON_SIXTRL_APERTURE_Y_LIMIT ${PYTHON_SIXTRL_APERTURE_Y_LIMIT} )
+    "${SIXTRL_TRACK_FEATURES_INSTALL_STR}
+     ${SIXTRL_APERTURE_CHECK_FEATURES_INSTALL_STR}
 
      message( STATUS \"Generating: ${SIXTRL_PY_INSTALL_PATH}\" )
      configure_file( \"${SIXTRL_PY_IN_FILE}\" \"${SIXTRL_PY_INSTALL_PATH}\"
diff --git a/python/sixtracklib/__init__.py b/python/sixtracklib/__init__.py
index 0ab9fe3d..51178d15 100644
--- a/python/sixtracklib/__init__.py
+++ b/python/sixtracklib/__init__.py
@@ -1,11 +1,35 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-from .particles import *
+from .particles import (
+    Particles,
+    makeCopy,
+    calcParticlesDifference,
+    compareParticlesDifference,
+    ParticlesSet,
+    ParticlesAddr,
+)
 from .beam_elements import *
-from .buffer import Buffer
-from .control import NodeId, NodeInfoBase, ControllerBase, NodeControllerBase, \
-    ArgumentBase
+from .buffer import Buffer, get_cbuffer_from_obj, AssignAddressItem
+from .control import (
+    NodeId,
+    NodeInfoBase,
+    ControllerBase,
+    NodeControllerBase,
+    ArgumentBase,
+)
 from .cuda import CudaArgument, CudaController, CudaNodeInfo, CudaTrackJob
+from .opencl import ClNodeId, ClController, ClArgument
 from .trackjob import TrackJob
 from .config_helper import supports
+
+from .sc_line_density import (
+    LineDensityProfileData,
+    LineDensityProfileData_create_buffer_assignment,
+)
+
+from .tricub import (
+    TriCub,
+    TriCubData,
+    TriCub_buffer_create_assign_address_item,
+)
diff --git a/python/sixtracklib/beam_elements.py b/python/sixtracklib/beam_elements.py
index fd3fe463..7a5a6c08 100644
--- a/python/sixtracklib/beam_elements.py
+++ b/python/sixtracklib/beam_elements.py
@@ -7,95 +7,67 @@
 
 import numpy as np
 from scipy.special import factorial
+from scipy.special import gamma as tgamma
 from scipy.constants import e as qe
 from cobjects import CBuffer, CObject, CField
 from .mad_helper import madseq_to_generator
 
+from .stcommon import (
+    st_BeamBeam4D_type_id,
+    st_BeamBeam4D_data_addr_offset,
+    st_BeamBeam6D_type_id,
+    st_BeamBeam6D_data_addr_offset,
+    st_BeamMonitor_type_id,
+    st_Cavity_type_id,
+    st_DipoleEedge_type_id,
+    st_Drift_type_id,
+    st_DriftExact_type_id,
+    st_LimitRect_type_id,
+    st_LimitEllipse_type_id,
+    st_LimitRectEllipse_type_id,
+    st_Multipole_type_id,
+    st_RFMultipole_type_id,
+    st_SCCoasting_type_id,
+    Math_q_gauss_cq,
+    st_SCQGaussProfile_type_id,
+    st_LineDensityProfileData_type_id,
+    st_NullSCInterpolatedProfile,
+    st_SCInterpolatedProfile_type_id,
+    st_SCInterpolatedProfile_interpol_data_addr_offset,
+    st_SRotation_type_id,
+    st_XYShift_type_id,
+)
+
 
 class Drift(CObject):
-    _typeid = 2
-    length = CField(0, 'real', default=0.0, alignment=8)
+    _typeid = st_Drift_type_id()
+    length = CField(0, "real", default=0.0)
 
 
 class DriftExact(CObject):
-    _typeid = 3
-    length = CField(0, 'real', default=0.0, alignment=8)
-
-
-class BeamMonitor(CObject):
-    _typeid = 10
-    num_stores = CField(0, 'int64', default=0, alignment=8)
-    start = CField(1, 'int64', default=0, alignment=8)
-    skip = CField(2, 'int64', default=1, alignment=8)
-    out_address = CField(3, 'uint64', default=0, alignment=8)
-    max_particle_id = CField(4, 'int64', default=0, alignment=8)
-    min_particle_id = CField(5, 'int64', default=0, alignment=8)
-    is_rolling = CField(6, 'int64', default=0, alignment=8)
-    is_turn_ordered = CField(7, 'int64', default=1, alignment=8)
-
-
-def append_beam_monitors_to_lattice(
-        beam_elements_buffer, until_turn_elem_by_elem, until_turn_turn_by_turn,
-        until_turn, skip_turns=1, min_particle_id=0, max_particle_id=0,
-        initial_at_turn=0):
-    num_beam_monitors_added = 0
-    start_turn_by_turn = max(initial_at_turn, until_turn_elem_by_elem)
-
-    if until_turn_turn_by_turn > start_turn_by_turn:
-        bm_turn_by_turn = BeamMonitor(
-            start=start_turn_by_turn,
-            num_stores=(
-                until_turn_turn_by_turn -
-                start_turn_by_turn),
-            skip=1,
-            out_address=0,
-            min_particle_id=min_particle_id,
-            max_particle_id=max_particle_id,
-            is_rolling=False,
-            is_turn_ordered=True,
-            cbuffer=beam_elements_buffer)
-        num_beam_monitors_added += 1
-
-    start_output_turn = max(start_turn_by_turn, until_turn_turn_by_turn)
-
-    if until_turn > start_output_turn:
-        if skip_turns <= 0:
-            skip_turns = 1
-
-        num_stores = until_turn - start_output_turn
-        remainder = num_stores % skip_turns
-        num_stores = num_stores // skip_turns
-
-        if remainder > 0:
-            num_stores += 1
-
-        bm_output = BeamMonitor(
-            start=start_output_turn,
-            num_stores=num_stores,
-            skip=skip_turns,
-            out_address=0,
-            min_particle_id=min_particle_id,
-            max_particle_id=max_particle_id,
-            is_rolling=True,
-            is_turn_ordered=True,
-            cbuffer=beam_elements_buffer)
-        num_beam_monitors_added += 1
-
-    return num_beam_monitors_added
+    _typeid = st_DriftExact_type_id()
+    length = CField(0, "real", default=0.0)
 
 
 class Multipole(CObject):
-    _typeid = 4
-    order = CField(0, 'int64', default=0, const=True, alignment=8)
-    length = CField(1, 'real', default=0.0, alignment=8)
-    hxl = CField(2, 'real', default=0.0, alignment=8)
-    hyl = CField(3, 'real', default=0.0, alignment=8)
-    bal = CField(4, 'real', default=0.0, alignment=8, pointer=True,
-                    length='2 * order + 2')
+    _typeid = st_Multipole_type_id()
+    order = CField(0, "int64", default=0, const=True)
+    length = CField(1, "real", default=0.0)
+    hxl = CField(2, "real", default=0.0)
+    hyl = CField(3, "real", default=0.0)
+    bal = CField(
+        4,
+        "real",
+        default=0.0,
+        alignment=8,
+        pointer=True,
+        length="2 * order + 2",
+    )
 
     def __init__(self, order=None, knl=None, ksl=None, bal=None, **kwargs):
-        if bal is None and \
-                (knl is not None or ksl is not None or order is not None):
+        if bal is None and (
+            knl is not None or ksl is not None or order is not None
+        ):
             if knl is None:
                 knl = []
             if ksl is None:
@@ -104,21 +76,21 @@ def __init__(self, order=None, knl=None, ksl=None, bal=None, **kwargs):
                 order = 0
 
             n = max((order + 1), max(len(knl), len(ksl)))
-            assert(n > 0)
+            assert n > 0
 
             _knl = np.array(knl)
             nknl = np.zeros(n, dtype=_knl.dtype)
-            nknl[:len(knl)] = knl
+            nknl[: len(knl)] = knl
             knl = nknl
-            del(_knl)
-            assert(len(knl) == n)
+            del _knl
+            assert len(knl) == n
 
             _ksl = np.array(ksl)
             nksl = np.zeros(n, dtype=_ksl.dtype)
-            nksl[:len(ksl)] = ksl
+            nksl[: len(ksl)] = ksl
             ksl = nksl
-            del(_ksl)
-            assert(len(ksl) == n)
+            del _ksl
+            assert len(ksl) == n
 
             order = n - 1
             bal = np.zeros(2 * order + 2)
@@ -157,29 +129,32 @@ def set_ksl(self, value, order):
 
 
 class RFMultipole(CObject):
-    _typeid = 256  # This is subject to change
-    order = CField(0, 'int64', default=0, const=True, alignment=8)
-    voltage = CField(1, 'real', default=0.0, alignment=8)
-    frequency = CField(2, 'real', default=0.0, alignment=8)
-    lag = CField(3, 'real', default=0.0, alignment=8)
-    bal = CField(4, 'real', pointer=True, length='2*order+2',
-                    default=0.0, alignment=8)
-    phase = CField(5, 'real', pointer=True, length='2*order+2',
-                    default=0.0, alignment=8)
+    _typeid = st_RFMultipole_type_id()
+    order = CField(0, "int64", default=0, const=True)
+    voltage = CField(1, "real", default=0.0)
+    frequency = CField(2, "real", default=0.0)
+    lag = CField(3, "real", default=0.0)
+    bal = CField(4, "real", pointer=True, length="2*order+2", default=0.0)
+    phase = CField(5, "real", pointer=True, length="2*order+2", default=0.0)
 
     def __init__(
-            self,
-            order=None,
-            knl=None,
-            ksl=None,
-            pn=None,
-            ps=None,
-            bal=None,
-            p=None,
-            **kwargs):
-        if bal is None and \
-                (knl is not None or ksl is not None or
-                 pn is not None or ps is not None or order is not None):
+        self,
+        order=None,
+        knl=None,
+        ksl=None,
+        pn=None,
+        ps=None,
+        bal=None,
+        p=None,
+        **kwargs
+    ):
+        if bal is None and (
+            knl is not None
+            or ksl is not None
+            or pn is not None
+            or ps is not None
+            or order is not None
+        ):
             if knl is None:
                 knl = []
             if ksl is None:
@@ -192,35 +167,35 @@ def __init__(
                 order = 0
 
             n = max((order + 1), max(len(knl), len(ksl), len(pn), len(ps)))
-            assert(n > 0)
+            assert n > 0
 
             _knl = np.array(knl)
             nknl = np.zeros(n, dtype=_knl.dtype)
-            nknl[:len(knl)] = knl
+            nknl[: len(knl)] = knl
             knl = nknl
-            del(_knl)
-            assert(len(knl) == n)
+            del _knl
+            assert len(knl) == n
 
             _ksl = np.array(ksl)
             nksl = np.zeros(n, dtype=_ksl.dtype)
-            nksl[:len(ksl)] = ksl
+            nksl[: len(ksl)] = ksl
             ksl = nksl
-            del(_ksl)
-            assert(len(ksl) == n)
+            del _ksl
+            assert len(ksl) == n
 
             _pn = np.array(pn)
             npn = np.zeros(n, dtype=_pn.dtype)
-            npn[:len(pn)] = pn
+            npn[: len(pn)] = pn
             pn = npn
-            del(_pn)
-            assert(len(pn) == n)
+            del _pn
+            assert len(pn) == n
 
             _ps = np.array(ps)
             nps = np.zeros(n, dtype=_ps.dtype)
-            nps[:len(ps)] = ps
+            nps[: len(ps)] = ps
             ps = nps
-            del(_ps)
-            assert(len(ps) == n)
+            del _ps
+            assert len(ps) == n
 
             order = n - 1
             bal = np.zeros(2 * order + 2)
@@ -238,8 +213,16 @@ def __init__(
             kwargs["phase"] = p
             kwargs["order"] = order
 
-        elif bal is not None and bal and len(bal) > 2 and ((len(bal) % 2) == 0)\
-                and p is not None and p and len(p) > 2 and ((len(p) % 2) == 0):
+        elif (
+            bal is not None
+            and bal
+            and len(bal) > 2
+            and ((len(bal) % 2) == 0)
+            and p is not None
+            and p
+            and len(p) > 2
+            and ((len(p) % 2) == 0)
+        ):
             kwargs["bal"] = bal
             kwargs["phase"] = p
             kwargs["order"] = (len(bal) - 2) / 2
@@ -284,22 +267,22 @@ def set_ps(self, value, order):
 
 
 class Cavity(CObject):
-    _typeid = 5
-    voltage = CField(0, 'real', default=0.0, alignment=8)
-    frequency = CField(1, 'real', default=0.0, alignment=8)
-    lag = CField(2, 'real', default=0.0, alignment=8)
+    _typeid = st_Cavity_type_id()
+    voltage = CField(0, "real", default=0.0)
+    frequency = CField(1, "real", default=0.0)
+    lag = CField(2, "real", default=0.0)
 
 
 class XYShift(CObject):
-    _typeid = 6
-    dx = CField(0, 'real', default=0.0, alignment=8)
-    dy = CField(1, 'real', default=0.0, alignment=8)
+    _typeid = st_XYShift_type_id()
+    dx = CField(0, "real", default=0.0)
+    dy = CField(1, "real", default=0.0)
 
 
 class SRotation(CObject):
-    _typeid = 7
-    cos_z = CField(0, 'real', default=1.0, alignment=8)
-    sin_z = CField(1, 'real', default=0.0, alignment=8)
+    _typeid = st_SRotation_type_id()
+    cos_z = CField(0, "real", default=1.0)
+    sin_z = CField(1, "real", default=0.0)
 
     def __init__(self, angle=0, **nargs):
         anglerad = angle / 180 * np.pi
@@ -316,141 +299,91 @@ def angle_deg(self):
         return self.angle * (180.0 / np.pi)
 
 
-class BeamBeam4D(CObject):
-    _typeid = 8
-    size = CField(0, 'uint64', const=True, default=0)
-    data = CField(1, 'float64', default=0.0,
-                  length='size', pointer=True)
-
-    def __init__(self, **kwargs):
-        if 'x_bb' in kwargs:
-            slots = (
-                'charge',
-                'sigma_x',
-                'sigma_y',
-                'beta_r',
-                'min_sigma_diff',
-                'x_bb',
-                'y_bb',
-                'd_px',
-                'd_py',
-                'enabled')
-
-            data = [qe] + [kwargs[ss] for ss in slots]
-            super().__init__(size=len(data), data=data, **kwargs)
-        else:
-            super().__init__(**kwargs)
-
+class BeamMonitor(CObject):
+    _typeid = st_BeamMonitor_type_id()
+    num_stores = CField(0, "int64", default=0)
+    start = CField(1, "int64", default=0)
+    skip = CField(2, "int64", default=1)
+    out_address = CField(3, "uint64", default=0)
+    max_particle_id = CField(4, "int64", default=0)
+    min_particle_id = CField(5, "int64", default=0)
+    is_rolling = CField(6, "int64", default=0)
+    is_turn_ordered = CField(7, "int64", default=1)
 
-class SpaceChargeCoasting(CObject):
-    _typeid = 13
-    size = CField(0, 'uint64', const=True, default=0)
-    data = CField(1, 'float64', default=0.0,
-                  length='size', pointer=True)
-
-    def __init__(self, **kwargs):
-        if 'sigma_x' in kwargs:
-            slots = (
-                'line_density',
-                'sigma_x',
-                'sigma_y',
-                'length',
-                'x_co',
-                'y_co',
-                'min_sigma_diff',
-                'enabled')
-
-            data = [kwargs[ss] for ss in slots]
-            super().__init__(size=len(data), data=data, **kwargs)
-        else:
-            super().__init__(**kwargs)
 
+def append_beam_monitors_to_lattice(
+    beam_elements_buffer,
+    until_turn_elem_by_elem,
+    until_turn_turn_by_turn,
+    until_turn,
+    skip_turns=1,
+    min_particle_id=0,
+    max_particle_id=0,
+    initial_at_turn=0,
+):
+    num_beam_monitors_added = 0
+    start_turn_by_turn = max(initial_at_turn, until_turn_elem_by_elem)
 
-class SpaceChargeBunched(CObject):
-    _typeid = 14
-    size = CField(0, 'uint64', const=True, default=0)
-    data = CField(1, 'float64', default=0.0,
-                  length='size', pointer=True)
+    if until_turn_turn_by_turn > start_turn_by_turn:
+        bm_turn_by_turn = BeamMonitor(
+            start=start_turn_by_turn,
+            num_stores=(until_turn_turn_by_turn - start_turn_by_turn),
+            skip=1,
+            out_address=0,
+            min_particle_id=min_particle_id,
+            max_particle_id=max_particle_id,
+            is_rolling=False,
+            is_turn_ordered=True,
+            cbuffer=beam_elements_buffer,
+        )
+        num_beam_monitors_added += 1
 
-    def __init__(self, **kwargs):
-        if 'sigma_x' in kwargs:
-            slots = (
-                'number_of_particles',
-                'bunchlength_rms',
-                'sigma_x',
-                'sigma_y',
-                'length',
-                'x_co',
-                'y_co',
-                'min_sigma_diff',
-                'enabled')
-
-            data = [kwargs[ss] for ss in slots]
-            super().__init__(size=len(data), data=data, **kwargs)
-        else:
-            super().__init__(**kwargs)
+    start_output_turn = max(start_turn_by_turn, until_turn_turn_by_turn)
 
+    if until_turn > start_output_turn:
+        if skip_turns <= 0:
+            skip_turns = 1
 
-class BeamBeam6D(CObject):
-    _typeid = 9
-    size = CField(0, 'uint64', const=True, default=0)
-    data = CField(1, 'float64', default=0.0,
-                  length='size', pointer=True)
+        num_stores = until_turn - start_output_turn
+        remainder = num_stores % skip_turns
+        num_stores = num_stores // skip_turns
 
-    def __init__(self, **kwargs):
-        if 'x_bb_co' in kwargs:
+        if remainder > 0:
+            num_stores += 1
 
-            import pysixtrack
-            params = kwargs
+        bm_output = BeamMonitor(
+            start=start_output_turn,
+            num_stores=num_stores,
+            skip=skip_turns,
+            out_address=0,
+            min_particle_id=min_particle_id,
+            max_particle_id=max_particle_id,
+            is_rolling=True,
+            is_turn_ordered=True,
+            cbuffer=beam_elements_buffer,
+        )
+        num_beam_monitors_added += 1
 
-            data = pysixtrack.BB6Ddata.BB6D_init(
-                q_part=qe,
-                phi=params['phi'],
-                alpha=params['alpha'],
-                delta_x=params['x_bb_co'],
-                delta_y=params['y_bb_co'],
-                N_part_per_slice=params['charge_slices'],
-                z_slices=params['zeta_slices'],
-                Sig_11_0=params['sigma_11'],
-                Sig_12_0=params['sigma_12'],
-                Sig_13_0=params['sigma_13'],
-                Sig_14_0=params['sigma_14'],
-                Sig_22_0=params['sigma_22'],
-                Sig_23_0=params['sigma_23'],
-                Sig_24_0=params['sigma_24'],
-                Sig_33_0=params['sigma_33'],
-                Sig_34_0=params['sigma_34'],
-                Sig_44_0=params['sigma_44'],
-                x_CO=params['x_co'],
-                px_CO=params['px_co'],
-                y_CO=params['y_co'],
-                py_CO=params['py_co'],
-                sigma_CO=params['zeta_co'],
-                delta_CO=params['delta_co'],
-                min_sigma_diff=params['min_sigma_diff'],
-                threshold_singular=params['threshold_singular'],
-                Dx_sub=params['d_x'],
-                Dpx_sub=params['d_px'],
-                Dy_sub=params['d_y'],
-                Dpy_sub=params['d_py'],
-                Dsigma_sub=params['d_zeta'],
-                Ddelta_sub=params['d_delta'],
-                enabled=params['enabled']
-            ).tobuffer()
-            super().__init__(size=len(data), data=data, **kwargs)
-        else:
-            super().__init__(**kwargs)
+    return num_beam_monitors_added
 
 
 class LimitRect(CObject):
-    _typeid = 11
-    min_x = CField(0, 'float64', default=-1.0, alignment=8)
-    max_x = CField(1, 'float64', default=+1.0, alignment=8)
-    min_y = CField(2, 'float64', default=-1.0, alignment=8)
-    max_y = CField(3, 'float64', default=+1.0, alignment=8)
-
-    def __init__(self, min_x=None, max_x=None, min_y=None, max_y=None,
-                 min_coord=-1.0, max_coord=1.0, **kwargs):
+    _typeid = st_LimitRect_type_id()
+    min_x = CField(0, "float64", default=-1.0)
+    max_x = CField(1, "float64", default=+1.0)
+    min_y = CField(2, "float64", default=-1.0)
+    max_y = CField(3, "float64", default=+1.0)
+
+    def __init__(
+        self,
+        min_x=None,
+        max_x=None,
+        min_y=None,
+        max_y=None,
+        min_coord=-1.0,
+        max_coord=1.0,
+        **kwargs
+    ):
         if min_x is None and min_coord is not None:
             min_x = min_coord
         if min_y is None and min_coord is not None:
@@ -483,34 +416,34 @@ def __init__(self, min_x=None, max_x=None, min_y=None, max_y=None,
             delta_y = max_y - min_y
 
         if delta_x * delta_y > 0.0:
-            super().__init__(min_x=min_x, max_x=max_x,
-                             min_y=min_y, max_y=max_y, **kwargs)
+            super().__init__(
+                min_x=min_x, max_x=max_x, min_y=min_y, max_y=max_y, **kwargs
+            )
         else:
             raise ValueError(
-                "min_x, max_x, min_y, max_y have to delimit " +
-                "a non-vanishing rectangle; values = [{0},{1},{2},{3}]".format(
-                    min_x,
-                    max_x,
-                    min_y,
-                    max_x))
+                "min_x, max_x, min_y, max_y have to delimit "
+                + "a non-vanishing rectangle; values = [{0},{1},{2},{3}]".format(
+                    min_x, max_x, min_y, max_x
+                )
+            )
 
 
 class LimitEllipse(CObject):
-    _typeid = 12
-    a_squ = CField(0, 'float64', default=+1.0, alignment=8)
-    b_squ = CField(1, 'float64', default=+1.0, alignment=8)
-    a_b_squ = CField(2, 'float64', alignment=8)
+    _typeid = st_LimitEllipse_type_id()
+    a_squ = CField(0, "float64", default=+1.0)
+    b_squ = CField(1, "float64", default=+1.0)
+    a_b_squ = CField(2, "float64")
 
     def __init__(self, a_squ=None, b_squ=None, **kwargs):
-        if a_squ is None and 'a' in kwargs:
-            a = kwargs.get('a')
+        if a_squ is None and "a" in kwargs:
+            a = kwargs.get("a")
             if a is not None and a > 0.0:
                 a_squ = a * a
         if a_squ is None:
             a_squ = 1.0
 
-        if b_squ is None and 'b' in kwargs:
-            b = kwargs.get('b')
+        if b_squ is None and "b" in kwargs:
+            b = kwargs.get("b")
             if b is not None and b > 0.0:
                 b_squ = b * b
         if b_squ is None:
@@ -518,8 +451,9 @@ def __init__(self, a_squ=None, b_squ=None, **kwargs):
 
         if a_squ > 0.0 and b_squ > 0.0:
             a_b_squ = a_squ * b_squ
-            super().__init__(a_squ=a_squ, b_squ=b_squ, a_b_squ=a_squ * b_squ,
-                             **kwargs)
+            super().__init__(
+                a_squ=a_squ, b_squ=b_squ, a_b_squ=a_squ * b_squ, **kwargs
+            )
         else:
             raise ValueError("a_squ and b_squ have to be positive definite")
 
@@ -533,34 +467,160 @@ def set_half_axes_squ(self, a_squ, b_squ):
         return self
 
 
+class BeamBeam4D(CObject):
+    _typeid = st_BeamBeam4D_type_id()
+    size = CField(0, "uint64", const=True, default=0)
+    data = CField(1, "float64", default=0.0, length="size", pointer=True)
+
+    def __init__(self, **kwargs):
+        if "x_bb" in kwargs:
+            slots = (
+                "charge",
+                "sigma_x",
+                "sigma_y",
+                "beta_r",
+                "min_sigma_diff",
+                "x_bb",
+                "y_bb",
+                "d_px",
+                "d_py",
+                "enabled",
+            )
+
+            data = [qe] + [kwargs[ss] for ss in slots]
+            super().__init__(size=len(data), data=data, **kwargs)
+        else:
+            super().__init__(**kwargs)
+
+
+class BeamBeam6D(CObject):
+    _typeid = st_BeamBeam6D_type_id()
+    size = CField(0, "uint64", const=True, default=0)
+    data = CField(1, "float64", default=0.0, length="size", pointer=True)
+
+    def __init__(self, **kwargs):
+        if "x_bb_co" in kwargs:
+            import pysixtrack
+
+            params = kwargs
+
+            data = pysixtrack.BB6Ddata.BB6D_init(
+                q_part=qe,
+                phi=params["phi"],
+                alpha=params["alpha"],
+                delta_x=params["x_bb_co"],
+                delta_y=params["y_bb_co"],
+                N_part_per_slice=params["charge_slices"],
+                z_slices=params["zeta_slices"],
+                Sig_11_0=params["sigma_11"],
+                Sig_12_0=params["sigma_12"],
+                Sig_13_0=params["sigma_13"],
+                Sig_14_0=params["sigma_14"],
+                Sig_22_0=params["sigma_22"],
+                Sig_23_0=params["sigma_23"],
+                Sig_24_0=params["sigma_24"],
+                Sig_33_0=params["sigma_33"],
+                Sig_34_0=params["sigma_34"],
+                Sig_44_0=params["sigma_44"],
+                x_CO=params["x_co"],
+                px_CO=params["px_co"],
+                y_CO=params["y_co"],
+                py_CO=params["py_co"],
+                sigma_CO=params["zeta_co"],
+                delta_CO=params["delta_co"],
+                min_sigma_diff=params["min_sigma_diff"],
+                threshold_singular=params["threshold_singular"],
+                Dx_sub=params["d_x"],
+                Dpx_sub=params["d_px"],
+                Dy_sub=params["d_y"],
+                Dpy_sub=params["d_py"],
+                Dsigma_sub=params["d_zeta"],
+                Ddelta_sub=params["d_delta"],
+                enabled=params["enabled"],
+            ).tobuffer()
+            super().__init__(size=len(data), data=data, **kwargs)
+        else:
+            super().__init__(**kwargs)
+
+
+class SCCoasting(CObject):
+    _typeid = st_SCCoasting_type_id()
+    number_of_particles = CField(0, "float64", default=0.0)
+    circumference = CField(1, "float64", default=1.0)
+    sigma_x = CField(2, "float64", default=1.0)
+    sigma_y = CField(3, "float64", default=1.0)
+    length = CField(4, "float64", default=0.0)
+    x_co = CField(5, "float64", default=0.0)
+    y_co = CField(6, "float64", default=0.0)
+    min_sigma_diff = CField(7, "float64", default=1e-10)
+    enabled = CField(8, "uint64", default=1)
+
+    def __init__(self, **kwargs):
+        super().__init__(**kwargs)
+
+
+class SCQGaussProfile(CObject):
+    _typeid = st_SCQGaussProfile_type_id()
+    number_of_particles = CField(0, "float64", default=0.0)
+    bunchlength_rms = CField(1, "float64", default=1.0)
+    sigma_x = CField(2, "float64", default=1.0)
+    sigma_y = CField(3, "float64", default=1.0)
+    length = CField(4, "float64", default=0.0)
+    x_co = CField(5, "float64", default=0.0)
+    y_co = CField(6, "float64", default=0.0)
+    min_sigma_diff = CField(7, "float64", default=1e-10)
+    q_param = CField(8, "float64", default=1.0)
+    cq = CField(9, "float64", default=Math_q_gauss_cq(1.0))
+    enabled = CField(10, "uint64", default=1)
+
+    def __init__(self, **kwargs):
+        q = kwargs.get("q_param", 1.0)
+        kwargs["cq"] = Math_q_gauss_cq(q)
+        kwargs["q_param"] = q
+        super().__init__(**kwargs)
+
+
+class SCInterpolatedProfile(CObject):
+    _typeid = st_SCInterpolatedProfile_type_id()
+    number_of_particles = CField(0, "float64", default=0.0)
+    sigma_x = CField(1, "float64", default=1.0)
+    sigma_y = CField(2, "float64", default=1.0)
+    length = CField(3, "float64", default=0.0)
+    x_co = CField(4, "float64", default=0.0)
+    y_co = CField(5, "float64", default=0.0)
+    interpol_data_addr = CField(6, "uint64", default=0)
+    line_density_prof_fallback = CField(7, "float64", default=1.0)
+    min_sigma_diff = CField(8, "float64", default=1e-10)
+    enabled = CField(9, "uint64", default=1)
+
+    def __init__(self, **kwargs):
+        super().__init__(**kwargs)
+
+
 class LimitRectEllipse(CObject):
-    _typeid = 16
-    max_x = CField(0, 'float64', default=+1.0, alignment=8)
-    max_y = CField(1, 'float64', default=+1.0, alignment=8)
-    a_squ = CField(2, 'float64', default=+1.0, alignment=8)
-    b_squ = CField(3, 'float64', default=+1.0, alignment=8)
-    a_b_squ = CField(4, 'float64', alignment=8)
+    _typeid = st_LimitRectEllipse_type_id()
+    max_x = CField(0, "float64", default=+1.0)
+    max_y = CField(1, "float64", default=+1.0)
+    a_squ = CField(2, "float64", default=+1.0)
+    b_squ = CField(3, "float64", default=+1.0)
+    a_b_squ = CField(4, "float64")
 
     def __init__(
-            self,
-            max_x=None,
-            max_y=None,
-            a_squ=None,
-            b_squ=None,
-            **kwargs):
+        self, max_x=None, max_y=None, a_squ=None, b_squ=None, **kwargs
+    ):
         if max_x is None:
             max_x = 1.0
         if max_y is None:
             max_y = 1.0
-        if a_squ is None and 'a' in kwargs:
-            a = kwargs.get('a')
+        if a_squ is None and "a" in kwargs:
+            a = kwargs.get("a")
             if a is not None and a > 0.0:
                 a_squ = a * a
         if a_squ is None:
             a_squ = 1.0
 
-        if b_squ is None and 'b' in kwargs:
-            b = kwargs.get('b')
+        if b_squ is None and "b" in kwargs:
+            b = kwargs.get("b")
             if b is not None and b > 0.0:
                 b_squ = b * b
         if b_squ is None:
@@ -575,8 +635,14 @@ def __init__(
         if a_squ < 0.0 or b_squ < 0.0:
             raise ValueError("a_squ and b_squ have to be positive definite")
 
-        super().__init__(max_x=max_x, max_y=max_y, a_squ=a_squ, b_squ=b_squ,
-                         a_b_squ=a_squ * b_squ, **kwargs)
+        super().__init__(
+            max_x=max_x,
+            max_y=max_y,
+            a_squ=a_squ,
+            b_squ=b_squ,
+            a_b_squ=a_squ * b_squ,
+            **kwargs
+        )
 
     def set_half_axes(self, a, b):
         return self.set_half_axes_squ(a * a, b * b)
@@ -589,12 +655,20 @@ def set_half_axes_squ(self, a_squ, b_squ):
 
 
 class DipoleEdge(CObject):
-    _typeid = 24
-    r21 = CField(0, 'float64', default=0.0, alignment=8)
-    r43 = CField(1, 'float64', default=0.0, alignment=8)
+    _typeid = st_DipoleEedge_type_id()
+    r21 = CField(0, "float64", default=0.0)
+    r43 = CField(1, "float64", default=0.0)
 
-    def __init__(self, r21=None, r43=None,
-                 h=None, e1=None, hgap=None, fint=None, **kwargs):
+    def __init__(
+        self,
+        r21=None,
+        r43=None,
+        h=None,
+        e1=None,
+        hgap=None,
+        fint=None,
+        **kwargs
+    ):
         if r21 is None and r43 is None:
             ZERO = np.float64(0.0)
             if hgap is None:
@@ -613,8 +687,7 @@ def __init__(self, r21=None, r43=None,
 
             corr = np.float64(2.0) * h * hgap * fint
             r21 = h * np.tan(e1)
-            temp = corr / np.cos(e1) * (np.float64(1) +
-                                        np.sin(e1) * np.sin(e1))
+            temp = corr / np.cos(e1) * (np.float64(1) + np.sin(e1) * np.sin(e1))
 
             # again, the argument to the tan calculation should be limited
             assert not np.isclose(np.absolute(np.cos(e1 - temp)), ZERO)
@@ -625,33 +698,46 @@ def __init__(self, r21=None, r43=None,
         else:
             raise ValueError(
                 "DipoleEdge needs either coefficiants r21 and r43"
-                " or suitable values for h, e1, hgap, and fint provided")
+                " or suitable values for h, e1, hgap, and fint provided"
+            )
 
 
 class Elements(object):
-    element_types = {'Cavity': Cavity,
-                     'Drift': Drift,
-                     'DriftExact': DriftExact,
-                     'Multipole': Multipole,
-                     'RFMultipole': RFMultipole,
-                     'SRotation': SRotation,
-                     'XYShift': XYShift,
-                     'BeamBeam6D': BeamBeam6D,
-                     'BeamBeam4D': BeamBeam4D,
-                     'SpaceChargeCoasting': SpaceChargeCoasting,
-                     'SpaceChargeBunched': SpaceChargeBunched,
-                     'LimitRect': LimitRect,
-                     'LimitEllipse': LimitEllipse,
-                     'LimitRectEllipse': LimitRectEllipse,
-                     'DipoleEdge': DipoleEdge,
-                     #                     'Line': Line,
-                     'BeamMonitor': BeamMonitor,
-                     }
+    element_types = {
+        "Cavity": Cavity,
+        "Drift": Drift,
+        "DriftExact": DriftExact,
+        "Multipole": Multipole,
+        "RFMultipole": RFMultipole,
+        "SRotation": SRotation,
+        "XYShift": XYShift,
+        "BeamMonitor": BeamMonitor,
+        "LimitRect": LimitRect,
+        "LimitEllipse": LimitEllipse,
+        "LimitRectEllipse": LimitRectEllipse,
+        "BeamBeam4D": BeamBeam4D,
+        "BeamBeam6D": BeamBeam6D,
+        "SCCoasting": SCCoasting,
+        "SCQGaussProfile": SCQGaussProfile,
+        "SCInterpolatedProfile": SCInterpolatedProfile,
+        "LimitRect": LimitRect,
+        "LimitEllipse": LimitEllipse,
+        "LimitRectEllipse": LimitRectEllipse,
+        "DipoleEdge": DipoleEdge,
+        #                     'Line': Line,
+        # 'Solenoid': Solenoid,
+        # 'Wire': Wire,
+    }
+
+    @staticmethod
+    def add_element_type(cls, cls_name):
+        Elements.element_types.update({cls_name: cls})
 
     def _mk_fun(self, buff, cls):
         def fun(*args, **nargs):
             # print(cls.__name__,nargs)
             return cls(cbuffer=buff, **nargs)
+
         return fun
 
     @classmethod
@@ -702,8 +788,8 @@ def from_mad(cls, seq, exact_drift=False):
         # temporary
         self = cls()
         for label, element_name, element in madseq_to_generator(seq):
-            if exact_drift and element_name == 'Drift':
-                element_name = 'DriftExact'
+            if exact_drift and element_name == "Drift":
+                element_name = "DriftExact"
             getattr(self, element_name)(**element._asdict())
         return self
 
diff --git a/python/sixtracklib/buffer.py b/python/sixtracklib/buffer.py
index b9bcfeba..47c3c1fb 100644
--- a/python/sixtracklib/buffer.py
+++ b/python/sixtracklib/buffer.py
@@ -2,70 +2,203 @@
 # -*- coding: utf-8 -*-
 
 import cobjects
-from cobjects import CBuffer
+from cobjects import CBuffer, CObject, CField
 
 import ctypes as ct
 
-from .stcommon import st_Buffer, st_Null, st_NullChar, st_NullUChar, \
-    st_ARCH_STATUS_GENERAL_FAILURE, st_ARCH_STATUS_SUCCESS, st_arch_status_t, \
-    st_buffer_size_t, st_arch_size_t, st_uchar_p, st_buffer_addr_t, \
-    st_Buffer, st_Buffer_p, st_NullBuffer, st_Buffer_preset, \
-    st_Buffer_new, st_Buffer_new_on_memory, st_Buffer_new_on_data, \
-    st_Buffer_new_from_file, st_Buffer_init_from_data, st_Buffer_get_slot_size,\
-    st_Buffer_get_num_of_objects, st_Buffer_get_size, st_Buffer_get_capacity, \
-    st_Buffer_new_mapped_on_cbuffer, st_Buffer_get_header_size, \
-    st_Buffer_get_data_begin_addr, st_Buffer_get_data_end_addr, \
-    st_Buffer_get_objects_begin_addr, st_Buffer_get_objects_end_addr, \
-    st_Buffer_get_num_of_slots, st_Buffer_get_max_num_of_slots, \
-    st_Buffer_get_num_of_objects, st_Buffer_get_max_num_of_objects, \
-    st_Buffer_get_num_of_dataptrs, st_Buffer_get_max_num_of_dataptrs, \
-    st_Buffer_get_num_of_garbage_ranges, st_Buffer_get_max_num_of_garbage_ranges, \
-    st_Buffer_read_from_file, st_Buffer_write_to_file, \
-    st_Buffer_write_to_file_normalized_addr, st_Buffer_reset, \
-    st_Buffer_reset_detailed, st_Buffer_reserve, st_Buffer_reserve_capacity, \
-    st_Buffer_needs_remapping, st_Buffer_remap, st_Buffer_refresh, \
-    st_Buffer_clear, st_Buffer_free, st_Buffer_delete
+from .stcommon import (
+    st_Buffer,
+    st_Null,
+    st_NullChar,
+    st_NullUChar,
+    st_ARCH_STATUS_GENERAL_FAILURE,
+    st_ARCH_STATUS_SUCCESS,
+    st_arch_status_t,
+    st_BUFFER_DEFAULT_DATASTORE_FLAGS,
+    st_buffer_flags_t,
+    st_buffer_size_t,
+    st_arch_size_t,
+    st_uchar_p,
+    st_buffer_addr_t,
+    st_Buffer,
+    st_Buffer_p,
+    st_NullBuffer,
+    st_Buffer_preset,
+    st_Buffer_new,
+    st_Buffer_new_on_memory,
+    st_Buffer_new_on_data,
+    st_Buffer_new_from_file,
+    st_Buffer_init_from_data,
+    st_Buffer_new_detailed,
+    st_Buffer_new_mapped_on_cbuffer,
+    st_Buffer_get_slot_size,
+    st_Buffer_get_num_of_objects,
+    st_Buffer_get_size,
+    st_Buffer_get_capacity,
+    st_Buffer_get_header_size,
+    st_Buffer_get_data_begin_addr,
+    st_Buffer_get_data_end_addr,
+    st_Buffer_get_objects_begin_addr,
+    st_Buffer_get_objects_end_addr,
+    st_Buffer_get_num_of_slots,
+    st_Buffer_get_max_num_of_slots,
+    st_Buffer_get_num_of_objects,
+    st_Buffer_get_max_num_of_objects,
+    st_Buffer_get_num_of_dataptrs,
+    st_Buffer_get_max_num_of_dataptrs,
+    st_Buffer_get_num_of_garbage_ranges,
+    st_Buffer_get_max_num_of_garbage_ranges,
+    st_Buffer_read_from_file,
+    st_Buffer_write_to_file,
+    st_Buffer_write_to_file_normalized_addr,
+    st_Buffer_reset,
+    st_Buffer_reset_detailed,
+    st_Buffer_reserve,
+    st_Buffer_reserve_capacity,
+    st_Buffer_needs_remapping,
+    st_Buffer_remap,
+    st_Buffer_refresh,
+    st_Buffer_clear,
+    st_Buffer_free,
+    st_Buffer_delete,
+    st_AssignAddressItem_p,
+    st_NullAssignAddressItem,
+)
+
+
+class AssignAddressItem(CObject):
+    _typeid = 513
+    dest_buffer_id = CField(0, "uint64", default=0, alignment=8)
+    src_buffer_id = CField(1, "uint64", default=0, alignment=8)
+    dest_elem_type_id = CField(2, "uint64", default=0, alignment=8)
+    src_elem_type_id = CField(3, "uint64", default=0, alignment=8)
+    dest_elem_index = CField(4, "uint64", default=1, alignment=8)
+    src_elem_index = CField(5, "uint64", default=1, alignment=8)
+    dest_pointer_offset = CField(6, "uint64", default=0, alignment=8)
+    src_pointer_offset = CField(7, "uint64", default=0, alignment=8)
+
+
+def get_cbuffer_from_obj(obj):
+    if obj is not None:
+        if isinstance(obj, CBuffer):
+            return obj
+        elif isinstance(obj, CObject):
+            return obj._buffer
+        elif hasattr(obj, "cbuffer"):
+            return obj.cbuffer
+    return None
 
 
 class Buffer(object):
-    def __init__(self, size=0, ptr_data=st_NullUChar, path_to_file=None,
-                 cbuffer=None, ptr_ext_buffer=st_NullBuffer, orig=None,
-                 owns_ptr=True, slot_size=8):
+    def __init__(
+        self,
+        cbuffer=None,
+        ptr_ext_buffer=st_NullBuffer,
+        owns_pointer=None,
+        owns_buffer=None,
+        ptr_data=st_NullUChar,
+        path_to_file=None,
+        size=0,
+        num_objects=None,
+        num_slots=None,
+        num_dataptrs=None,
+        num_garbage_ranges=None,
+        buffer_flags=None,
+        slot_size=8,
+    ):
         self._ptr_st_buffer = st_NullBuffer
         self._last_status = st_ARCH_STATUS_SUCCESS.value
-        self._on_del = "delete"
-
-        if ptr_ext_buffer is not None and ptr_ext_buffer != st_NullBuffer:
+        self._owns_buffer = True
+        self._owns_pointer = True
+        self._cbuffer = get_cbuffer_from_obj(cbuffer)
+
+        if self._cbuffer is not None:
+            self._ptr_st_buffer = st_Buffer_new_mapped_on_cbuffer(
+                self._cbuffer
+            )
+            self._owns_buffer = False
+            if self._ptr_st_buffer == st_NullBuffer:
+                self._cbuffer = None
+        elif ptr_ext_buffer is not None and ptr_ext_buffer != st_NullBuffer:
             self._ptr_st_buffer = ptr_ext_buffer
-            if owns_ptr is None or not(owns_ptr is True):
-                self._on_del = None
-        elif cbuffer is not None and isinstance(cbuffer, CBuffer):
-            self._ptr_st_buffer = st_Buffer_new_mapped_on_cbuffer(cbuffer)
+            if owns_pointer is None or not (owns_pointer is True):
+                self._owns_pointer = False
+            if owns_buffer is None or not (owns_buffer is True):
+                self._owns_buffer = False
         elif path_to_file is not None and path_to_file != "":
-            _path_to_file = ct.c_char_p(path_to_file.encode('utf-8'))
+            _path_to_file = ct.c_char_p(path_to_file.encode("utf-8"))
             self._ptr_st_buffer = st_Buffer_new_from_file(_path_to_file)
-        elif ptr_data is not None and ptr_data != st_NullUChar and \
-                slot_size is not None and slot_size > 0:
+        elif (
+            ptr_data is not None
+            and ptr_data != st_NullUChar
+            and slot_size is not None
+            and slot_size > 0
+        ):
             self._ptr_st_buffer = st_Buffer_new_on_data(
-                ptr_data, st_buffer_size_t(slot_size))
+                ptr_data, st_buffer_size_t(slot_size)
+            )
+            if not (owns_buffer is None) or not (owns_buffer is True):
+                self._owns_buffer = False
         elif size is not None and size >= 0:
             self._ptr_st_buffer = st_Buffer_new(st_buffer_size_t(size))
+        elif (
+            not (num_objects is None)
+            and not (num_slots is None)
+            and not (num_dataptrs is None)
+        ):
+            if num_garbage_ranges is None:
+                num_garbage_ranges = 0
+            if buffer_flags is None:
+                buffer_flags = st_BUFFER_DEFAULT_DATASTORE_FLAGS.value
+            self._ptr_st_buffer = st_Buffer_new_detailed(
+                st_buffer_size_t(num_objects),
+                st_buffer_size_t(num_slots),
+                st_buffer_size_t(num_dataptrs),
+                st_buffer_size_t(num_garbage_ranges),
+                st_buffer_flags_t(buffer_flags),
+            )
         else:
             self._ptr_st_buffer = st_Buffer_new(st_buffer_size_t(0))
 
     def __del__(self):
-        if self._ptr_st_buffer != st_NullBuffer and self._on_del is not None:
-            if self._on_del == "delete":
+        if self._ptr_st_buffer != st_NullBuffer:
+            if self._owns_buffer and self._owns_pointer:
                 st_Buffer_delete(self._ptr_st_buffer)
-                self._ptr_st_buffer = st_NullBuffer
-            elif self._on_del == "free":
+            elif self._owns_buffer:
                 st_Buffer_free(self._ptr_st_buffer)
+                self._ptr_st_buffer = st_NullBuffer
+            elif self._owns_pointer:
                 st_Buffer_preset(self._ptr_st_buffer)
+                st_Buffer_delete(self._ptr_st_buffer)
+            self._ptr_st_buffer = st_NullBuffer
+
+    @classmethod
+    def from_cbuffer(cls, obj, owns_buffer=False, owns_pointer=True, **kwargs):
+        cbuffer = get_cbuffer_from_obj(obj)
+        if cbuffer is None:
+            raise ValueError(f"Unable to obtain cbuffer for {obj}")
+        return cls(
+            cbuffer=cbuffer,
+            owns_buffer=owns_buffer,
+            owns_pointer=owns_pointer,
+            **kwargs,
+        )
 
     @property
     def pointer(self):
         return self._ptr_st_buffer
 
+    @property
+    def maps_to_cbuffer(self):
+        return (
+            not (self._cbuffer is None)
+            and self._ptr_st_buffer != st_NullBuffer
+        )
+
+    @property
+    def cbuffer(self):
+        return self._cbuffer
+
     @property
     def last_status(self):
         return self._last_status.value
@@ -74,6 +207,18 @@ def last_status(self):
     def last_status_success(self):
         return self._last_status == st_ARCH_STATUS_SUCCESS.value
 
+    @property
+    def owns_buffer(self):
+        return self._owns_buffer
+
+    @property
+    def owns_pointer(self):
+        return self._owns_pointer
+
+    @property
+    def is_owner(self):
+        return self._owns_buffer and self._owns_pointer
+
     @property
     def slot_size(self):
         return st_Buffer_get_slot_size(self._ptr_st_buffer)
@@ -136,50 +281,61 @@ def data_end_addr(self):
 
     @property
     def ptr_data_begin(self):
-        return ct.cast(st_Buffer_get_data_begin_addr(
-            self._ptr_st_buffer), st_uchar_p)
+        return ct.cast(
+            st_Buffer_get_data_begin_addr(self._ptr_st_buffer), st_uchar_p
+        )
 
     @property
     def ptr_data_end(self):
-        return ct.cast(st_Buffer_get_data_end_addr(
-            self._ptr_st_buffer), st_uchar_p)
+        return ct.cast(
+            st_Buffer_get_data_end_addr(self._ptr_st_buffer), st_uchar_p
+        )
 
     def clear(self, clear_data=False):
         self._last_status = st_Buffer_clear(
-            self._ptr_st_buffer, ct.c_bool(clear_data is True))
+            self._ptr_st_buffer, ct.c_bool(clear_data is True)
+        )
         if self._last_status != st_ARCH_STATUS_SUCCESS.value:
-            raise RuntimeError("unsuccessful clear op; status:{0}".format(
-                self._last_status))
+            raise RuntimeError(
+                "unsuccessful clear op; status:{0}".format(self._last_status)
+            )
         return self
 
     def refresh(self):
         self._last_status = st_Buffer_refresh(self._ptr_st_buffer)
         if self._last_status != st_ARCH_STATUS_SUCCESS.value:
-            raise RuntimeError("unsuccessful refresh op; status:{0}".format(
-                self._last_status))
+            raise RuntimeError(
+                "unsuccessful refresh op; status:{0}".format(self._last_status)
+            )
         return self
 
     def remap(self):
         self._last_status = st_Buffer_remap(self._ptr_st_buffer)
         if self._last_status != st_ARCH_STATUS_SUCCESS.value:
-            raise RuntimeError("unsuccessful reamp op; status:{0}".format(
-                self._last_status))
+            raise RuntimeError(
+                "unsuccessful reamp op; status:{0}".format(self._last_status)
+            )
         return self
 
     def write_to_file(self, path_to_file, normalized_base_addr=None):
         if path_to_file is not None and path_to_file != "":
-            _path_to_file = ct.c_char_p(path_to_file.encode('utf-8'))
+            _path_to_file = ct.c_char_p(path_to_file.encode("utf-8"))
             if normalized_base_addr is not None and normalized_base_addr > 0:
                 self._last_status = st_Buffer_write_to_file_normalized_addr(
-                    self._ptr_st_buffer, _path_to_file, st_buffer_addr_t(
-                        normalized_base_addr))
+                    self._ptr_st_buffer,
+                    _path_to_file,
+                    st_buffer_addr_t(normalized_base_addr),
+                )
             else:
                 self._last_status = st_Buffer_write_to_file(
-                    self._ptr_st_buffer, _path_to_file)
+                    self._ptr_st_buffer, _path_to_file
+                )
 
             if self._last_status != st_ARCH_STATUS_SUCCESS.value:
-                raise RuntimeError("unsuccessful write_to_file op; " +
-                                   "status:{0}".format(self._last_status))
+                raise RuntimeError(
+                    "unsuccessful write_to_file op; "
+                    + "status:{0}".format(self._last_status)
+                )
         else:
             self._last_status = st_ARCH_STATUS_GENERAL_FAILURE
             raise RuntimeError("illegal path supplied")
@@ -189,41 +345,62 @@ def write_to_file(self, path_to_file, normalized_base_addr=None):
     def read_from_file(self, path_to_file):
         if path_to_file is not None and path_to_file != "":
             self._last_status = st_Buffer_read_from_file(
-                self._ptr_st_buffer, ct.c_char_p(
-                    path_to_file.encode('utf-8')))
+                self._ptr_st_buffer, ct.c_char_p(path_to_file.encode("utf-8"))
+            )
             if self._last_status != st_ARCH_STATUS_SUCCESS.value:
-                raise RuntimeError("unsuccessful read_from_file op; " +
-                                   "status:{0}".format(self._last_status))
+                raise RuntimeError(
+                    "unsuccessful read_from_file op; "
+                    + "status:{0}".format(self._last_status)
+                )
         return self
 
     def reserve_capacity(self, capacity):
         if capacity is not None and capacity >= 0:
             self._last_status = st_Buffer_reserve_capacity(
-                self._ptr_st_buffer, st_buffer_size_t(capacity))
+                self._ptr_st_buffer, st_buffer_size_t(capacity)
+            )
             if self._last_status != st_ARCH_STATUS_SUCCESS.value:
-                raise RuntimeError("unsuccessful reserve capacity op; " +
-                                   "status:{0}".format(self._last_status))
+                raise RuntimeError(
+                    "unsuccessful reserve capacity op; "
+                    + "status:{0}".format(self._last_status)
+                )
         return self
 
-    def reserve(self, max_num_objects, max_num_slots, max_num_dataptrs,
-                max_num_garbage_ranges):
+    def reserve(
+        self,
+        max_num_objects,
+        max_num_slots,
+        max_num_dataptrs,
+        max_num_garbage_ranges,
+    ):
         self._last_status = st_Buffer_reserve(
             self._ptr_st_buffer,
             max_num_objects,
             max_num_slots,
             max_num_dataptrs,
-            max_num_garbage_ranges)
+            max_num_garbage_ranges,
+        )
 
         if self._last_status != st_ARCH_STATUS_SUCCESS.value:
-            raise RuntimeError("unsuccessful reserve op; status:{0}".format(
-                self._last_status))
+            raise RuntimeError(
+                "unsuccessful reserve op; status:{0}".format(self._last_status)
+            )
 
         return self
 
-    def reset(self, max_num_objects=None, max_num_slots=None,
-              max_num_dataptrs=None, max_num_garbage_ranges=None):
-        if max_num_slots is None and max_num_objects is None and \
-                max_num_dataptrs is None and max_num_garbage_ranges is None:
+    def reset(
+        self,
+        max_num_objects=None,
+        max_num_slots=None,
+        max_num_dataptrs=None,
+        max_num_garbage_ranges=None,
+    ):
+        if (
+            max_num_slots is None
+            and max_num_objects is None
+            and max_num_dataptrs is None
+            and max_num_garbage_ranges is None
+        ):
             self._last_status = st_Buffer_reset(self._ptr_st_buffer)
         else:
             if max_num_objects is None:
@@ -236,14 +413,17 @@ def reset(self, max_num_objects=None, max_num_slots=None,
                 max_num_garbage_ranges = self.max_num_garbage_ranges
 
             self._last_status = st_Buffer_reset_detailed(
-                self._ptr_st_buffer, st_buffer_size_t(max_num_objects),
+                self._ptr_st_buffer,
+                st_buffer_size_t(max_num_objects),
                 st_buffer_size_t(max_num_slots),
                 st_buffer_size_t(max_num_dataptrs),
-                st_buffer_size_t(max_num_garbage_ranges))
+                st_buffer_size_t(max_num_garbage_ranges),
+            )
 
         if self._last_status != st_ARCH_STATUS_SUCCESS.value:
-            raise RuntimeError("unsuccessful reset op; status:{0}".format(
-                self._last_status))
+            raise RuntimeError(
+                "unsuccessful reset op; status:{0}".format(self._last_status)
+            )
         return self
 
 
diff --git a/python/sixtracklib/config.py.template b/python/sixtracklib/config.py.template
index 2a469d8d..8083ba2d 100644
--- a/python/sixtracklib/config.py.template
+++ b/python/sixtracklib/config.py.template
@@ -8,6 +8,42 @@ import os
 SHARED_LIB = os.path.join( os.path.dirname( os.path.realpath( __file__ ) ),
                            "@PYTHON_SIXTRACKLIB_SHARED_LIB@" )
 
+# -----------------------------------------------------------------------------
+# ------                 List of enabled / disabled modules              ------
+# -----------------------------------------------------------------------------
+@PYTHON_SIXTRACKLIB_MODULES_STR@
+
+# -----------------------------------------------------------------------------
+# ------  Enable / disable / skip tracking over specific beam elements   ------
+# -----------------------------------------------------------------------------
+
+# "enabled" : Unconditionally enable tracking of beam-elements
+# "skip"    : Ignore beam-elements of this type and silently "skip" it
+# "disable" : Like "skip", but generate error if encountered during tracking
+
+TRACK_BEAMBEAM4D  = "@SIXTRL_TRACK_BEAMBEAM4D_FLAG_STR@"
+TRACK_BEAMBEAM6D  = "@SIXTRL_TRACK_BEAMBEAM6D_FLAG_STR@"
+TRACK_SPACECHARGE = "@SIXTRL_TRACK_SC_FLAG_STR@"
+TRACK_TRICUB      = "@SIXTRL_TRACK_TRICUB_FLAG_STR@"
+
+# -----------------------------------------------------------------------------
+# ------                     Global aperture check                       ------
+# -----------------------------------------------------------------------------
+
+# "always"     : Perform aperture check with at Drifts, DriftExacts
+#"conditional" : Perform if beam element meets certain conditions
+#"never"       : No global check, only at Limit* beam-elements (if any)
+
+APERTURE_CHECK_AT_DRIFT = "@SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG_STR@"
+APERTURE_CHECK_MIN_DRIFT_LENGTH = @SIXTRACKL_APERTURE_CHECK_MIN_DRIFT_LENGTH@ # [m]
+
+APERTURE_X_LIMIT = @SIXTRACKL_APERTURE_X_LIMIT_VALUE@ # [m]
+APERTURE_Y_LIMIT = @SIXTRACKL_APERTURE_Y_LIMIT_VALUE@ # [m]
+
+# -----------------------------------------------------------------------------
+# ------              Namespace and Namespace - Prefix Settings          ------
+# -----------------------------------------------------------------------------
+
 # Namespace constants for C99
 C99_NAMESPACE_STR = "@PYTHON_SIXTRL_C99_NAMESPACE_STR@"
 C99_NAMESPACE_PREFIX_STR = "@PYTHON_SIXTRL_C99_NAMESPACE_PREFIX_STR@"
@@ -16,12 +52,4 @@ C99_NAMESPACE_PREFIX_STR = "@PYTHON_SIXTRL_C99_NAMESPACE_PREFIX_STR@"
 CXX_NAMESPACE_STR = "@PYTHON_SIXTRL_CXX_NAMESPACE_STR@"
 CXX_NAMESPACE_PREFIX_STR = "@PYTHON_SIXTRL_CXX_NAMESPACE_PREFIX_STR@"
 
-# Config options
-ENABLE_APERATURE_CHECK = @PYTHON_SIXTRL_ENABLE_APERTURE_CHECK@
-APERTURE_X_LIMIT = @PYTHON_SIXTRL_APERTURE_X_LIMIT@
-APERTURE_Y_LIMIT = @PYTHON_SIXTRL_APERTURE_Y_LIMIT@
-
-# List of modules for sixtracklib:
-@PYTHON_SIXTRACKLIB_MODULES_STR@
-
 # end: config.py
diff --git a/python/sixtracklib/control.py b/python/sixtracklib/control.py
index 26c073a7..c0c6f7a5 100644
--- a/python/sixtracklib/control.py
+++ b/python/sixtracklib/control.py
@@ -1,125 +1,204 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-from .stcommon import st_Controller_delete, st_Controller_clear, \
-    st_Controller_get_arch_id, st_Controller_uses_nodes, \
-    st_Controller_has_arch_string, st_Controller_get_arch_string, \
-    st_Controller_has_config_string, st_Controller_get_config_string, \
-    st_Controller_send_detailed, st_Controller_send_buffer, \
-    st_Controller_receive_detailed, st_Controller_receive_buffer, \
-    st_Controller_is_cobjects_buffer_arg_remapped, \
-    st_Controller_remap_cobjects_buffer_arg, st_Controller_is_ready_to_send, \
-    st_Controller_is_ready_to_remap, st_Controller_is_ready_to_run_kernel, \
-    st_Controller_is_ready_to_receive, st_Controller_is_in_debug_mode, \
-    st_Controller_enable_debug_mode, st_Controller_disable_debug_mode, \
-    st_Controller_get_num_of_kernels, st_Controller_get_kernel_work_items_dim, \
-    st_Controller_get_kernel_work_groups_dim, st_Controller_kernel_has_name, \
-    st_Controller_get_num_of_kernel_arguments, st_Controller_has_kernel_id, \
-    st_Controller_get_kernel_name_string, st_Controller_has_kernel_by_name, \
-    st_Controller_get_ptr_kernel_config_base, \
-    st_Controller_get_ptr_kernel_config_base_by_name, \
-    st_Controller_has_remap_cobject_buffer_kernel, \
-    st_Controller_get_remap_cobject_buffer_kernel_id, \
-    st_Controller_set_remap_cobject_buffer_kernel_id, \
-    st_Controller_has_remap_cobject_buffer_debug_kernel, \
-    st_Controller_get_remap_cobject_buffer_debug_kernel_id, \
-    st_Controller_set_remap_cobject_buffer_debug_kernel_id, \
-    st_Controller_get_num_available_nodes, \
-    st_Controller_get_available_node_indices, \
-    st_Controller_is_node_available_by_index, \
-    st_Controller_get_ptr_node_id_by_index, \
-    st_Controller_get_ptr_node_info_base_by_index, \
-    st_Controller_get_min_available_node_index, \
-    st_Controller_get_max_available_node_index, \
-    st_Controller_has_default_node, st_Controller_get_default_node_id, \
-    st_Controller_get_default_node_index, \
-    st_Controller_get_default_node_info_base, \
-    st_Controller_has_selected_node, \
-    st_Controller_get_ptr_selected_node_id, \
-    st_Controller_get_selected_node_index, \
-    st_Controller_get_ptr_selected_node_info_base, \
-    st_Controller_can_change_selected_node, \
-    st_Controller_can_directly_change_selected_node, \
-    st_Controller_can_unselect_node, st_Controller_is_default_node_id, \
-    st_Controller_is_default_node, st_Controller_is_default_node_index, \
-    st_Controller_is_default_platform_id_and_device_id, \
-    st_Controller_get_ptr_node_info_base, \
-    st_Controller_get_ptr_node_info_base_by_node_id, \
-    st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id, \
-    st_Controller_get_node_index_by_node_id, st_Controller_get_node_index, \
-    st_Controller_get_node_index_by_platform_id_and_device_id, \
-    st_Controller_is_node_available_by_node_id, \
-    st_Controller_is_node_available, \
-    st_Controller_is_node_available_by_platform_id_and_device_id, \
-    st_Controller_select_node_by_index, st_Controller_select_node_by_node_id, \
-    st_Controller_select_node, \
-    st_Controller_select_node_by_plaform_id_and_device_id, \
-    st_Controller_change_selected_node, st_Controller_unselect_node, \
-    st_Controller_unselect_node_by_index, \
-    st_Controller_unselect_node_by_node_id, \
-    st_Controller_unselect_node_by_platform_id_and_device_id
-
-
-
-from .stcommon import st_Argument_delete, \
-    st_Argument_get_arch_id, st_Argument_has_arch_string, \
-    st_Argument_get_arch_string, st_Argument_send_again, \
-    st_Argument_send_buffer, st_Argument_send_buffer_without_remap, \
-    st_Argument_send_raw_argument, \
-    st_Argument_receive_again, st_Argument_receive_buffer, \
-    st_Argument_receive_buffer_without_remap, \
-    st_Argument_receive_raw_argument, st_Argument_remap_cobjects_buffer, \
-    st_Argument_uses_cobjects_buffer, st_Argument_get_cobjects_buffer, \
-    st_Argument_get_cobjects_buffer_slot_size, \
-    st_Argument_uses_raw_argument, st_Argument_get_const_ptr_raw_argument, \
-    st_Argument_get_ptr_raw_argument, st_Argument_get_size, \
-    st_Argument_get_capacity, st_Argument_has_argument_buffer, \
-    st_Argument_requires_argument_buffer, \
-    st_Argument_get_ptr_base_controller
-from .stcommon import \
-    st_NodeInfoBase_p, st_NullNodeInfoBase, st_NodeInfo_delete, \
-    st_NodeInfo_get_ptr_const_node_id, st_NodeInfo_get_platform_id, \
-    st_NodeInfo_get_device_id, st_NodeInfo_has_node_index, \
-    st_NodeInfo_get_node_index, st_NodeInfo_is_default_node, \
-    st_NodeInfo_is_selected_node, st_NodeInfo_get_arch_id, \
-    st_NodeInfo_has_arch_string, st_NodeInfo_get_arch_string, \
-    st_NodeInfo_has_platform_name, st_NodeInfo_get_platform_name, \
-    st_NodeInfo_has_device_name, st_NodeInfo_get_device_name, \
-    st_NodeInfo_has_description, st_NodeInfo_get_description, \
-    st_NodeInfo_print_out, st_NodeInfo_get_required_output_str_length, \
-    _st_NodeInfo_convert_to_string
+from .stcommon import (
+    st_Controller_delete,
+    st_Controller_clear,
+    st_Controller_get_arch_id,
+    st_Controller_uses_nodes,
+    st_Controller_has_arch_string,
+    st_Controller_get_arch_string,
+    st_Controller_has_config_string,
+    st_Controller_get_config_string,
+    st_Controller_send_detailed,
+    st_Controller_send_buffer,
+    st_Controller_receive_detailed,
+    st_Controller_receive_buffer,
+    st_Controller_is_cobjects_buffer_arg_remapped,
+    st_Controller_remap_cobjects_buffer_arg,
+    st_Controller_is_ready_to_send,
+    st_Controller_is_ready_to_remap,
+    st_Controller_is_ready_to_run_kernel,
+    st_Controller_is_ready_to_receive,
+    st_Controller_is_in_debug_mode,
+    st_Controller_enable_debug_mode,
+    st_Controller_disable_debug_mode,
+    st_Controller_get_num_of_kernels,
+    st_Controller_get_kernel_work_items_dim,
+    st_Controller_get_kernel_work_groups_dim,
+    st_Controller_kernel_has_name,
+    st_Controller_get_num_of_kernel_arguments,
+    st_Controller_has_kernel_id,
+    st_Controller_get_kernel_name_string,
+    st_Controller_has_kernel_by_name,
+    st_Controller_get_ptr_kernel_config_base,
+    st_Controller_get_ptr_kernel_config_base_by_name,
+    st_Controller_has_remap_cobject_buffer_kernel,
+    st_Controller_get_remap_cobject_buffer_kernel_id,
+    st_Controller_set_remap_cobject_buffer_kernel_id,
+    st_Controller_has_remap_cobject_buffer_debug_kernel,
+    st_Controller_get_remap_cobject_buffer_debug_kernel_id,
+    st_Controller_set_remap_cobject_buffer_debug_kernel_id,
+    st_Controller_get_num_available_nodes,
+    st_Controller_get_available_node_indices,
+    st_Controller_is_node_available_by_index,
+    st_Controller_get_ptr_node_id_by_index,
+    st_Controller_get_ptr_node_info_base_by_index,
+    st_Controller_get_min_available_node_index,
+    st_Controller_get_max_available_node_index,
+    st_Controller_has_default_node,
+    st_Controller_get_default_node_id,
+    st_Controller_get_default_node_index,
+    st_Controller_get_default_node_info_base,
+    st_Controller_has_selected_node,
+    st_Controller_get_ptr_selected_node_id,
+    st_Controller_get_selected_node_index,
+    st_Controller_get_ptr_selected_node_info_base,
+    st_Controller_can_change_selected_node,
+    st_Controller_can_directly_change_selected_node,
+    st_Controller_can_unselect_node,
+    st_Controller_is_default_node_id,
+    st_Controller_is_default_node,
+    st_Controller_is_default_node_index,
+    st_Controller_is_default_platform_id_and_device_id,
+    st_Controller_get_ptr_node_info_base,
+    st_Controller_get_ptr_node_info_base_by_node_id,
+    st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id,
+    st_Controller_get_node_index_by_node_id,
+    st_Controller_get_node_index,
+    st_Controller_get_node_index_by_platform_id_and_device_id,
+    st_Controller_is_node_available_by_node_id,
+    st_Controller_is_node_available,
+    st_Controller_is_node_available_by_platform_id_and_device_id,
+    st_Controller_select_node_by_index,
+    st_Controller_select_node_by_node_id,
+    st_Controller_select_node,
+    st_Controller_select_node_by_plaform_id_and_device_id,
+    st_Controller_change_selected_node,
+    st_Controller_unselect_node,
+    st_Controller_unselect_node_by_index,
+    st_Controller_unselect_node_by_node_id,
+    st_Controller_unselect_node_by_platform_id_and_device_id,
+)
+
+from .stcommon import (
+    st_Argument_delete,
+    st_Argument_get_arch_id,
+    st_Argument_has_arch_string,
+    st_Argument_get_arch_string,
+    st_Argument_send_again,
+    st_Argument_send_buffer,
+    st_Argument_send_buffer_without_remap,
+    st_Argument_send_raw_argument,
+    st_Argument_receive_again,
+    st_Argument_receive_buffer,
+    st_Argument_receive_buffer_without_remap,
+    st_Argument_receive_raw_argument,
+    st_Argument_remap_cobjects_buffer,
+    st_Argument_uses_cobjects_buffer,
+    st_Argument_get_cobjects_buffer,
+    st_Argument_get_cobjects_buffer_slot_size,
+    st_Argument_uses_raw_argument,
+    st_Argument_get_const_ptr_raw_argument,
+    st_Argument_get_ptr_raw_argument,
+    st_Argument_get_size,
+    st_Argument_get_capacity,
+    st_Argument_has_argument_buffer,
+    st_Argument_requires_argument_buffer,
+    st_Argument_get_ptr_base_controller,
+)
+from .stcommon import (
+    st_NodeInfoBase_p,
+    st_NullNodeInfoBase,
+    st_NodeInfo_delete,
+    st_NodeInfo_get_ptr_const_node_id,
+    st_NodeInfo_get_platform_id,
+    st_NodeInfo_get_device_id,
+    st_NodeInfo_has_node_index,
+    st_NodeInfo_get_node_index,
+    st_NodeInfo_is_default_node,
+    st_NodeInfo_is_selected_node,
+    st_NodeInfo_get_arch_id,
+    st_NodeInfo_has_arch_string,
+    st_NodeInfo_get_arch_string,
+    st_NodeInfo_has_platform_name,
+    st_NodeInfo_get_platform_name,
+    st_NodeInfo_has_device_name,
+    st_NodeInfo_get_device_name,
+    st_NodeInfo_has_description,
+    st_NodeInfo_get_description,
+    st_NodeInfo_print_out,
+    st_NodeInfo_get_required_output_str_length,
+    _st_NodeInfo_convert_to_string,
+)
 import ctypes as ct
 import cobjects
 from cobjects import CBuffer
 from .buffer import Buffer
 
-from .stcommon import st_Null, st_NullChar, st_Buffer_p, st_NullBuffer, \
-    st_ARCH_STATUS_GENERAL_FAILURE, st_ARCH_STATUS_SUCCESS, \
-    st_NODE_UNDEFINED_INDEX, st_NODE_ILLEGAL_PLATFORM_ID, \
-    st_NODE_ILLEGAL_DEVICE_ID, st_node_platform_id_t, st_node_device_id_t, \
-    st_kernel_id_t, st_node_index_t, st_arch_status_t, st_buffer_size_t, \
-    st_arch_size_t, st_NodeId_p, st_NullNodeId, \
-    st_ArgumentBase_p, st_NullArgumentBase, \
-    st_ControllerBase_p, st_NullControllerBase
-
-from .stcommon import st_NodeId_create, st_NodeId_new, \
-    st_NodeId_new_from_string, st_NodeId_new_detailed, st_NodeId_delete, \
-    st_NodeId_is_valid, st_NodeId_get_platform_id, st_NodeId_get_device_id, \
-    st_NodeId_has_node_index, st_NodeId_get_node_index, _st_NodeId_to_string
+from .stcommon import (
+    string_to_encoded_ctypes_str,
+    ctypes_str_to_decoded_string,
+    st_Null,
+    st_NullChar,
+    st_Buffer_p,
+    st_NullBuffer,
+    st_ARCH_STATUS_GENERAL_FAILURE,
+    st_ARCH_STATUS_SUCCESS,
+    st_NODE_UNDEFINED_INDEX,
+    st_NODE_ILLEGAL_PLATFORM_ID,
+    st_NODE_ILLEGAL_DEVICE_ID,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+    st_kernel_id_t,
+    st_node_index_t,
+    st_arch_status_t,
+    st_buffer_size_t,
+    st_arch_size_t,
+    st_NodeId_p,
+    st_NullNodeId,
+    st_ArgumentBase_p,
+    st_NullArgumentBase,
+    st_ControllerBase_p,
+    st_NullControllerBase,
+)
+
+from .stcommon import (
+    st_NodeId_create,
+    st_NodeId_new,
+    st_NodeId_new_from_string,
+    st_NodeId_new_detailed,
+    st_NodeId_delete,
+    st_NodeId_is_valid,
+    st_NodeId_get_platform_id,
+    st_NodeId_get_device_id,
+    st_NodeId_has_node_index,
+    st_NodeId_get_node_index,
+    _st_NodeId_to_string,
+)
 
 
 def raise_error_if_status_not_success(
-        status, msg=None, cls=RuntimeError, prev=None):
-    if (prev is None or prev != status) and \
-            status != st_ARCH_STATUS_SUCCESS.value:
+    status, msg=None, cls=RuntimeError, prev=None
+):
+    if (
+        prev is None or prev != status
+    ) and status != st_ARCH_STATUS_SUCCESS.value:
         if msg is None:
             msg = "an error occured; status:{0}".format(status)
         raise cls(msg)
 
 
 class NodeId(object):
-    def __init__(self, node_id_str=None, platform_id=None, device_id=None,
-                 node_index=None, ext_ptr_node_id=st_NullNodeId, orig=None):
+    def __init__(
+        self,
+        node_id_str=None,
+        platform_id=None,
+        device_id=None,
+        node_index=None,
+        ext_ptr_node_id=st_NullNodeId,
+        orig=None,
+    ):
         self._ptr_node_id = st_NullNodeId
         self._owns_ptr = True
 
@@ -127,29 +206,35 @@ def __init__(self, node_id_str=None, platform_id=None, device_id=None,
             self._ptr_node_id = ext_ptr_node_id
             self._owns_ptr = False
         elif node_id_str is not None:
-            node_id_str = node_id_str.strip().encode('utf-8')
-            _node_id_str = ct.c_char_p(node_id_str)
-            self._ptr_node_id = st_NodeId_new_from_string(_node_id_str)
-            del _node_id_str
-        elif platform_id is not None and \
-                platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value and \
-                device_id is not None and \
-                device_id != st_NODE_ILLEGAL_DEVICE_ID.value:
+            self._ptr_node_id = st_NodeId_new_from_string(
+                string_to_encoded_ctypes_str(node_id_str)
+            )
+        elif (
+            platform_id is not None
+            and platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value
+            and device_id is not None
+            and device_id != st_NODE_ILLEGAL_DEVICE_ID.value
+        ):
             if node_index is None:
                 self._ptr_node_id = st_NodeId_new(
                     st_node_platform_id_t(platform_id),
-                    st_node_device_id_t(device_id))
-            elif node_index is not None and \
-                    node_index != st_NODE_UNDEFINED_INDEX.value:
+                    st_node_device_id_t(device_id),
+                )
+            elif (
+                node_index is not None
+                and node_index != st_NODE_UNDEFINED_INDEX.value
+            ):
                 self._ptr_node_id = st_NodeId_new_detailed(
                     st_node_platform_id_t(platform_id),
                     st_node_device_id_t(device_id),
-                    st_node_index_t(node_index))
+                    st_node_index_t(node_index),
+                )
         elif orig is not None and isinstance(orig, NodeId):
             self._ptr_node_id = st_NodeId_new_detailed(
                 st_node_platform_id_t(orig.platform_id),
                 st_node_device_id_t(orig.device_id),
-                st_node_index_t(orig.node_index))
+                st_node_index_t(orig.node_index),
+            )
 
         if self._ptr_node_id == st_NullNodeId:
             raise ValueError("Unable to create NodeId object")
@@ -162,17 +247,18 @@ def __del__(self):
 
     @staticmethod
     def to_string(node_id):
+        node_id_str = None
         if isinstance(node_id, NodeId):
             _ptr_node_id = node_id.pointer
         else:
             _ptr_node_id = node_id
-
-        _max_str_len = ct.c_uint64(64)
-        _int_str = ct.create_string_buffer(_max_str_len.value)
-        _status = _st_NodeId_to_string(_ptr_node_id, _int_str, _max_str_len)
-        node_id_str = None
+        _max_str_len = 64
+        _int_str = ct.create_string_buffer(_max_str_len)
+        _status = _st_NodeId_to_string(
+            _ptr_node_id, _int_str, st_arch_size_t(_max_str_len)
+        )
         if _status == st_ARCH_STATUS_SUCCESS.value:
-            node_id_str = bytes(_int_str.value).decode('utf-8')
+            node_id_str = ctypes_str_to_decoded_string(_int_str)
         return node_id_str
 
     @property
@@ -181,8 +267,9 @@ def pointer(self):
 
     @property
     def is_valid(self):
-        return self._ptr_node_id != st_NullNodeId and \
-            st_NodeId_is_valid(self._ptr_node_id)
+        return self._ptr_node_id != st_NullNodeId and st_NodeId_is_valid(
+            self._ptr_node_id
+        )
 
     @property
     def platform_id(self):
@@ -238,14 +325,16 @@ def to_string(node_info):
             _ptr_node_info = node_info
         str_repr = None
         if _ptr_node_info != st_NullNodeInfoBase:
-            _requ_str_capacity = 1 + \
-                st_NodeInfo_get_required_output_str_length(_ptr_node_info)
+            _requ_str_capacity = (
+                1 + st_NodeInfo_get_required_output_str_length(_ptr_node_info)
+            )
             _max_str_capacity = ct.c_uint64(_requ_str_capacity)
             _temp_str = ct.create_string_buffer(_requ_str_capacity)
             _status = _st_NodeInfo_convert_to_string(
-                _ptr_node_info, _max_str_capacity, _temp_str)
+                _ptr_node_info, _max_str_capacity, _temp_str
+            )
             if _status == st_ARCH_STATUS_SUCCESS.value:
-                str_repr = bytes(_temp_str.value).decode('utf-8')
+                str_repr = ctypes_str_to_decoded_string(_temp_str)
         return str_repr
 
     @property
@@ -268,14 +357,18 @@ def arch_id(self):
     def arch_str(self):
         arch_str = None
         if st_NodeInfo_has_arch_string(self._ptr_node_info):
-            arch_str = bytes(st_NodeInfo_get_arch_string(
-                self._ptr_node_info)).decode('utf-8')
+            arch_str = ctypes_str_to_decoded_string(
+                st_NodeInfo_get_arch_string(self._ptr_node_info)
+            )
         return arch_str
 
     @property
     def node_id(self):
-        return NodeId(ext_ptr_node_id=st_NodeInfo_get_ptr_const_node_id(
-            self._ptr_node_info))
+        return NodeId(
+            ext_ptr_node_id=st_NodeInfo_get_ptr_const_node_id(
+                self._ptr_node_info
+            )
+        )
 
     @property
     def platform_id(self):
@@ -299,12 +392,9 @@ def has_platform_name(self):
 
     @property
     def platform_name(self):
-        temp_cstr = st_NodeInfo_get_platform_name(self._ptr_node_info)
-        if temp_cstr != st_NullChar:
-            platform_name = bytes(temp_cstr).decode('utf-8')
-        else:
-            platform_name = ""
-        return platform_name
+        return ctypes_str_to_decoded_string(
+            st_NodeInfo_get_platform_name(self._ptr_node_info)
+        )
 
     @property
     def has_device_name(self):
@@ -312,12 +402,9 @@ def has_device_name(self):
 
     @property
     def device_name(self):
-        temp_cstr = st_NodeInfo_get_device_name(self._ptr_node_info)
-        if temp_cstr != st_NullChar:
-            device_name = bytes(temp_cstr).decode('utf-8')
-        else:
-            device_name = ""
-        return device_name
+        return ctypes_str_to_decoded_string(
+            st_NodeInfo_get_device_name(self._ptr_node_info)
+        )
 
     @property
     def has_description(self):
@@ -325,12 +412,9 @@ def has_description(self):
 
     @property
     def description(self):
-        temp_cstr = st_NodeInfo_get_description(self._ptr_node_info)
-        if temp_cstr != st_NullChar:
-            description = bytes(temp_cstr).decode('utf-8')
-        else:
-            description = ""
-        return description
+        return ctypes_str_to_decoded_string(
+            st_NodeInfo_get_description(self._ptr_node_info)
+        )
 
     @property
     def is_selected(self):
@@ -341,9 +425,8 @@ def is_default(self):
         return st_NodeInfo_is_default_node(self._ptr_node_info)
 
     def required_out_string_capacity(self):
-        requ_str_capacity = st_NodeInfo_get_required_output_str_length(
-            self._ptr_node_info) + 1
-        return requ_str_capacity
+        cap = st_NodeInfo_get_required_output_str_length(self._ptr_node_info)
+        return cap + 1
 
     def __str__(self):
         return NodeInfoBase.to_string(self.pointer)
@@ -377,8 +460,9 @@ def arch_id(self):
     def arch_str(self):
         arch_str = None
         if st_Argument_has_arch_string(self._ptr_argument):
-            arch_str = bytes(st_Argument_get_arch_string(
-                self._ptr_argument)).decode('utf-8')
+            arch_str = ctypes_str_to_decoded_string(
+                st_Argument_get_arch_string(self._ptr_argument)
+            )
         return arch_str
 
     @property
@@ -387,10 +471,10 @@ def uses_buffer(self):
 
     @property
     def ptr_buffer(self):
-        ptr_buffer = st_NullBuffer
         if st_Argument_uses_cobjects_buffer(self._ptr_argument):
-            ptr_buffer = st_Argument_get_cobjects_buffer(self._ptr_argument)
-        return ptr_buffer
+            return st_Argument_get_cobjects_buffer(self._ptr_argument)
+        else:
+            return st_NullBuffer
 
     @property
     def buffer_slot_size(self):
@@ -422,9 +506,8 @@ def requires_argument_buffer(self):
 
     @property
     def controller(self):
-        return ControllerBase(
-            ptr_controller=st_Argument_get_ptr_base_controller(
-                self._ptr_argument), owns_ptr=False)
+        _ptr_ctrl = st_Argument_get_ptr_base_controller(self._ptr_argument)
+        return ControllerBase(ptr_controller=_ptr_ctrl, owns_ptr=False)
 
     @property
     def last_status(self):
@@ -434,8 +517,13 @@ def last_status(self):
     def last_status_success(self):
         return self._last_status == st_ARCH_STATUS_SUCCESS.value
 
-    def send(self, buffer=st_NullBuffer, remap_buffer=True,
-             ptr_raw_arg_begin=st_Null, raw_arg_size=None):
+    def send(
+        self,
+        buffer=st_NullBuffer,
+        remap_buffer=True,
+        ptr_raw_arg_begin=st_Null,
+        raw_arg_size=None,
+    ):
         ptr_buffer = st_NullBuffer
         if buffer is not None and buffer is not st_NullBuffer:
             if isinstance(buffer, Buffer):
@@ -446,22 +534,25 @@ def send(self, buffer=st_NullBuffer, remap_buffer=True,
         if ptr_buffer != st_NullBuffer:
             if remap_buffer:
                 self._last_status = st_Argument_send_buffer(
-                    self._ptr_argument, ptr_buffer)
+                    self._ptr_argument, ptr_buffer
+                )
             else:
                 self._last_status = st_Argument_send_buffer_without_remap(
-                    self._ptr_argument, ptr_buffer)
+                    self._ptr_argument, ptr_buffer
+                )
         elif raw_arg_size is not None:
             if ptr_raw_arg_begin == st_Null:
                 ptr_raw_arg_begin = self.ptr_raw_argument
             self._last_status = st_Argument_send_raw_argument(
-                self._ptr_argument, ptr_raw_arg_begin, raw_arg_size)
+                self._ptr_argument, ptr_raw_arg_begin, raw_arg_size
+            )
         else:
             self._last_status = st_Argument_send_again(self._ptr_argument)
 
         raise_error_if_status_not_success(
             self._last_status,
-            "unsuccessful send op; status:{0}".format(
-                self._last_status))
+            f"unsuccessful send op; status:{self._last_status}",
+        )
 
         return self
 
@@ -472,11 +563,17 @@ def send_buffer_without_remap(self, buffer):
         return self.send(buffer=buffer, remap_buffer=False)
 
     def send_raw_argument(self, ptr_raw_arg_begin, raw_arg_size):
-        return self.send(ptr_raw_arg_begin=ptr_raw_arg_begin,
-                         raw_arg_size=raw_arg_size)
-
-    def receive(self, buffer=st_NullBuffer, remap_buffer=True,
-                ptr_raw_arg_begin=st_Null, raw_arg_capacity=None):
+        return self.send(
+            ptr_raw_arg_begin=ptr_raw_arg_begin, raw_arg_size=raw_arg_size
+        )
+
+    def receive(
+        self,
+        buffer=st_NullBuffer,
+        remap_buffer=True,
+        ptr_raw_arg_begin=st_Null,
+        raw_arg_capacity=None,
+    ):
         ptr_buffer = st_NullBuffer
         if buffer is not None and buffer is not st_NullBuffer:
             if isinstance(buffer, Buffer):
@@ -490,24 +587,27 @@ def receive(self, buffer=st_NullBuffer, remap_buffer=True,
         if ptr_buffer != st_NullBuffer:
             if remap_buffer:
                 self._last_status = st_Argument_receive_buffer(
-                    self._ptr_argument, ptr_buffer)
+                    self._ptr_argument, ptr_buffer
+                )
             else:
                 self._last_status = st_Argument_receive_buffer_without_remap(
-                    self._ptr_argument, ptr_buffer)
+                    self._ptr_argument, ptr_buffer
+                )
         elif raw_arg_capacity is not None:
             if ptr_raw_arg_begin is st_Null:
                 ptr_raw_arg_begin = st_Argument_get_ptr_raw_argument(
-                    self._ptr_argument)
+                    self._ptr_argument
+                )
             self._last_status = st_Argument_receive_raw_argument(
-                self._ptr_argument, ptr_raw_arg_begin, raw_arg_capacity)
+                self._ptr_argument, ptr_raw_arg_begin, raw_arg_capacity
+            )
         else:
-            self._last_status = st_Argument_receive_again(
-                self._ptr_argument)
+            self._last_status = st_Argument_receive_again(self._ptr_argument)
 
         raise_error_if_status_not_success(
             self._last_status,
-            "unsuccessful receive op; status:{0}".format(
-                self._last_status))
+            f"unsuccessful receive op; status:{self._last_status}",
+        )
 
         return self
 
@@ -518,8 +618,10 @@ def receive_buffer_without_remap(self, buffer):
         return self.receive(buffer=buffer, remap_buffer=False)
 
     def receive_raw_argument(self, ptr_raw_arg_begin, raw_arg_capacity):
-        return self.receive(ptr_raw_arg_begin=ptr_raw_arg_begin,
-                            raw_arg_capacity=raw_arg_capacity)
+        return self.receive(
+            ptr_raw_arg_begin=ptr_raw_arg_begin,
+            raw_arg_capacity=raw_arg_capacity,
+        )
 
 
 class ControllerBase(object):
@@ -562,16 +664,18 @@ def arch_id(self):
     def arch_str(self):
         arch_str = None
         if st_Controller_has_arch_string(self._ptr_ctrl):
-            arch_str = bytes(st_Controller_get_arch_string(
-                self._ptr_ctrl)).decode('utf-8')
+            arch_str = ctypes_str_to_decoded_string(
+                st_Controller_get_arch_string(self._ptr_ctrl)
+            )
         return arch_str
 
     @property
     def config_str(self):
         conf_str = None
         if st_Controller_has_config_string(self._ptr_ctrl):
-            conf_str = bytes(st_Controller_get_config_string(
-                self._ptr_ctrl)).decode('utf-8')
+            conf_str = ctypes_str_to_decoded_string(
+                st_Controller_get_config_string(self._ptr_ctrl)
+            )
         return conf_str
 
     @property
@@ -594,19 +698,23 @@ def ready_to_remap(self):
     def has_remap_kernel(self):
         if not st_Controller_is_in_debug_mode(self._ptr_ctrl):
             return st_Controller_has_remap_cobject_buffer_kernel(
-                self._ptr_ctrl)
+                self._ptr_ctrl
+            )
         else:
             return st_Controller_has_remap_cobject_buffer_debug_kernel(
-                self._ptr_ctrl)
+                self._ptr_ctrl
+            )
 
     @property
     def remap_kernel_id(self):
         if not st_Controller_is_in_debug_mode(self._ptr_ctrl):
             return st_Controller_get_remap_cobject_buffer_kernel_id(
-                self._ptr_ctrl)
+                self._ptr_ctrl
+            )
         else:
             return st_Controller_get_remap_cobject_buffer_debug_kernel_id(
-                self._ptr_ctrl)
+                self._ptr_ctrl
+            )
 
     @property
     def in_debug_mode(self):
@@ -626,47 +734,58 @@ def disable_debug_mode(self):
 
     def has_kernel(self, kernel_id):
         return st_Controller_has_kernel_id(
-            self._ptr_ctrl, st_kernel_id_t(kernel_id))
+            self._ptr_ctrl, st_kernel_id_t(kernel_id)
+        )
 
-    def has_kernel_by_name(self, kernel_name_str):
-        kernel_name_str = kernel_name_str.encode('utf-8')
+    def has_kernel_by_name(self, kernel_name):
         return st_Controller_has_kernel_by_name(
-            self._ptr_ctrl, ct.c_char_p(kernel_name_str))
+            self._ptr_ctrl, string_to_encoded_ctypes_str(kernel_name)
+        )
 
     def num_kernel_arguments(self, kernel_id):
         return st_Controller_get_num_of_kernel_arguments(
-            self._ptr_ctrl, st_kernel_id_t(kernel_id))
+            self._ptr_ctrl, st_kernel_id_t(kernel_id)
+        )
 
     def kernel_name(self, kernel_id):
-        _kernel_name = None
-        _kernel_name_cstr = st_NullChar
+        kernel_name = None
         _kernel_id = st_kernel_id_t(kernel_id)
         if st_Controller_kernel_has_name(self._ptr_ctrl, _kernel_id):
-            _kernel_name_cstr = st_Controller_get_kernel_name_string(
-                self._ptr_ctrl, _kernel_id)
-        if _kernel_name_cstr != st_NullChar:
-            _kernel_name = bytes(_kernel_name_cstr.value).decode('utf-8')
-        return _kernel_name
+            kernel_name = ctypes_str_to_decoded_string(
+                st_Controller_get_kernel_name_string(
+                    self._ptr_ctrl, _kernel_id
+                )
+            )
+        return kernel_name
 
     # TODO: Implement missing KernelConfig* methods as soon as all API details
     #       concerning KernelCOnfig are settled!!
 
-    def send(self, ptr_argument, ptr_buffer=st_NullBuffer,
-             ptr_raw_arg_begin=st_Null, raw_arg_size=None):
+    def send(
+        self,
+        ptr_argument,
+        ptr_buffer=st_NullBuffer,
+        ptr_raw_arg_begin=st_Null,
+        raw_arg_size=None,
+    ):
         if ptr_buffer != st_NullBuffer:
             self._last_status = st_Controller_send_buffer(
-                self._ptr_ctrl, ptr_argument, ptr_buffer)
+                self._ptr_ctrl, ptr_argument, ptr_buffer
+            )
         elif ptr_raw_arg_begin != st_Null and raw_arg_size is not None:
             self._last_status = st_Controller_send_detailed(
-                self._ptr_ctrl, ptr_argument, ptr_raw_arg_begin,
-                st_arch_size_t(raw_arg_size))
+                self._ptr_ctrl,
+                ptr_argument,
+                ptr_raw_arg_begin,
+                st_arch_size_t(raw_arg_size),
+            )
         else:
             self._last_status = st_ARCH_STATUS_GENERAL_FAILURE.value
 
         raise_error_if_status_not_success(
             self._last_status,
-            "unsuccessful send op; status:{0}".format(
-                self._last_status))
+            "unsuccessful send op; status:{0}".format(self._last_status),
+        )
 
         return self
 
@@ -674,37 +793,54 @@ def send_buffer(self, ptr_argument, ptr_buffer):
         return self.send(ptr_argument, ptr_buffer=ptr_buffer)
 
     def send_detailed(self, ptr_argument, ptr_raw_arg_begin, raw_arg_size):
-        return self.send(ptr_argument,
-                         ptr_raw_arg_begin, raw_arg_size=raw_arg_size)
-
-    def receive(self, ptr_argument=st_NullArgumentBase,
-                ptr_buffer=st_NullBuffer,
-                ptr_raw_arg_begin=st_Null, raw_arg_capacity=None):
+        return self.send(
+            ptr_argument, ptr_raw_arg_begin, raw_arg_size=raw_arg_size
+        )
+
+    def receive(
+        self,
+        ptr_argument=st_NullArgumentBase,
+        ptr_buffer=st_NullBuffer,
+        ptr_raw_arg_begin=st_Null,
+        raw_arg_capacity=None,
+    ):
         self._last_status = st_ARCH_STATUS_GENERAL_FAILURE.value
         if ptr_argument != st_NullArgumentBase:
             prev_last_status = self._last_status
             if ptr_buffer != st_NullBuffer:
                 self._last_status = st_Controller_receive_buffer(
-                    self._ptr_ctrl, ptr_buffer, ptr_argument)
+                    self._ptr_ctrl, ptr_buffer, ptr_argument
+                )
             elif ptr_raw_arg_begin != st_Null and raw_arg_capacity is not None:
                 self._last_status = st_Controller_send_detailed(
-                    self._ptr_ctrl, ptr_raw_arg_begin, st_arch_size_t(raw_arg_capacity), ptr_argument)
+                    self._ptr_ctrl,
+                    ptr_raw_arg_begin,
+                    st_arch_size_t(raw_arg_capacity),
+                    ptr_argument,
+                )
 
             raise_error_if_status_not_success(
-                self._last_status, msg="unsuccessful receive op; status:{0}".format(
-                    self._last_status), cls=RuntimeError, prev=prev_last_status)
+                self._last_status,
+                msg="unsuccessful receive op; status:{0}".format(
+                    self._last_status
+                ),
+                cls=RuntimeError,
+                prev=prev_last_status,
+            )
 
         return self
 
     def receive_buffer(self, ptr_buffer, ptr_argument):
         return self.receive(ptr_argument=ptr_argument, ptr_buffer=ptr_buffer)
 
-    def receive_detailed(self, ptr_raw_arg_begin, raw_arg_capacity,
-                         ptr_argument):
+    def receive_detailed(
+        self, ptr_raw_arg_begin, raw_arg_capacity, ptr_argument
+    ):
         return self.receive(
             ptr_argument=ptr_argument,
             ptr_raw_arg_begin=ptr_raw_arg_begin,
-            raw_arg_capacity=raw_arg_capacity)
+            raw_arg_capacity=raw_arg_capacity,
+        )
 
     def buffer_arg_needs_remapping(self, argument):
         needs_remapping = False
@@ -713,10 +849,14 @@ def buffer_arg_needs_remapping(self, argument):
             ptr_argument = argument.pointer
         else:
             ptr_argument = argument
-        if ptr_argument is not None and ptr_argument != st_NullArgumentBase and \
-                st_Argument_uses_cobjects_buffer(ptr_argument):
+        if (
+            ptr_argument is not None
+            and ptr_argument != st_NullArgumentBase
+            and st_Argument_uses_cobjects_buffer(ptr_argument)
+        ):
             needs_remapping = not st_Controller_is_cobjects_buffer_arg_remapped(
-                self._ptr_ctrl, ptr_argument)
+                self._ptr_ctrl, ptr_argument
+            )
         else:
             raise ValueError("illegal argument supplied")
         return needs_remapping
@@ -730,12 +870,13 @@ def remap_buffer_arg(self, argument):
 
         if ptr_argument is not None and ptr_argument != st_NullArgumentBase:
             self._last_status = st_Controller_remap_cobjects_buffer_arg(
-                self._ptr_ctrl, ptr_argument)
+                self._ptr_ctrl, ptr_argument
+            )
 
             raise_error_if_status_not_success(
                 self._last_status,
-                "unsuccesful mapping op; status:{0}".format(
-                    self._last_status))
+                "unsuccesful mapping op; status:{0}".format(self._last_status),
+            )
         else:
             raise RuntimeError("illegal argument supplied")
 
@@ -757,8 +898,11 @@ def num_available_nodes(ctrl=None):
         elif ctrl is not None:
             _ptr_ctrl = ctrl
 
-        return _ptr_ctrl != st_NullControllerBase \
-            and st_Controller_get_num_available_nodes(_ptr_ctrl) or 0
+        return (
+            _ptr_ctrl != st_NullControllerBase
+            and st_Controller_get_num_available_nodes(_ptr_ctrl)
+            or 0
+        )
 
     @staticmethod
     def available_node_indices(ctrl=None):
@@ -776,11 +920,13 @@ def available_node_indices(ctrl=None):
                 _temp_node_indices_t = st_node_index_t * int(av_num_nodes)
                 _temp_node_indices = _temp_node_indices_t()
                 _status = st_Controller_get_available_node_indices(
-                    _ptr_ctrl, st_arch_size_t(av_num_nodes), _temp_node_indices)
+                    _ptr_ctrl, st_arch_size_t(av_num_nodes), _temp_node_indices
+                )
                 if _status == st_ARCH_STATUS_SUCCESS.value:
                     for idx in _temp_node_indices:
                         if st_Controller_is_node_available_by_index(
-                                _ptr_ctrl, idx):
+                            _ptr_ctrl, idx
+                        ):
                             _node_indices.add(idx)
 
         return list(_node_indices)
@@ -788,10 +934,9 @@ def available_node_indices(ctrl=None):
     @staticmethod
     def available_node_ids(ctrl=None):
         _node_ids = []
-        available_node_indices = \
-            NodeControllerBase.available_node_indices(ctrl)
+        avail_indices = NodeControllerBase.available_node_indices(ctrl)
 
-        if available_node_indices and len(available_node_indices) > 0:
+        if avail_indices and len(avail_indices) > 0:
             _ptr_ctrl = st_NullControllerBase
             if ctrl is not None and isinstance(ctrl, NodeControllerBase):
                 _ptr_ctrl = ctrl.pointer
@@ -799,10 +944,11 @@ def available_node_ids(ctrl=None):
                 _ptr_ctrl = ctrl
 
             if _ptr_ctrl != st_NullControllerBase:
-                for idx in available_node_indices:
+                for idx in avail_indices:
                     _ptr_node = st_Controller_get_ptr_node_id_by_index(
-                        _ptr_ctrl, st_node_index_t(idx))
-                    if _ptr_node != st_NullNodeId:
+                        _ptr_ctrl, st_node_index_t(idx)
+                    )
+                    if _ptr_node is not st_NullNodeId:
                         _node_ids.append(NodeId(ext_ptr_node_id=_ptr_node))
 
         return _node_ids
@@ -810,45 +956,44 @@ def available_node_ids(ctrl=None):
     @staticmethod
     def available_node_id_strs(ctrl=None):
         _node_id_strs = []
-        available_node_indices = \
-            NodeControllerBase.available_node_indices(ctrl)
-
-        if available_node_indices and len(available_node_indices) > 0:
+        avail_indices = NodeControllerBase.available_node_indices(ctrl)
+        if avail_indices and len(avail_indices) > 0:
             _ptr_ctrl = st_NullControllerBase
             if ctrl is not None and isinstance(ctrl, NodeControllerBase):
                 _ptr_ctrl = ctrl.pointer
             elif ctrl is not None:
                 _ptr_ctrl = ctrl
-
-            if _ptr_ctrl != st_NullControllerBase:
-                for idx in available_node_indices:
+            if _ptr_ctrl is not st_NullControllerBase:
+                for idx in avail_indices:
                     _ptr_node = st_Controller_get_ptr_node_id_by_index(
-                        _ptr_ctrl, st_node_index_t(idx))
+                        _ptr_ctrl, st_node_index_t(idx)
+                    )
                     if _ptr_node != st_NullNodeId:
                         _node_id_strs.append(NodeId.to_string(_ptr_node))
-
         return _node_id_strs
 
     @staticmethod
     def available_node_infos(ctrl=None):
         _node_infos = []
-        available_node_indices = \
-            NodeControllerBase.available_node_indices(ctrl)
-
-        if available_node_indices and len(available_node_indices) > 0:
+        avail_indices = NodeControllerBase.available_node_indices(ctrl)
+        if avail_indices and len(avail_indices) > 0:
             _ptr_ctrl = st_NullControllerBase
             if ctrl is not None and isinstance(ctrl, NodeControllerBase):
                 _ptr_ctrl = ctrl.pointer
             elif ctrl is not None:
                 _ptr_ctrl = ctrl
 
-            if _ptr_ctrl != st_NullControllerBase:
-                for idx in available_node_indices:
+            if _ptr_ctrl is not st_NullControllerBase:
+                for idx in avail_indices:
                     _ptr_info = st_Controller_get_ptr_node_info_base_by_index(
-                        _ptr_ctrl, st_node_index_t(idx))
+                        _ptr_ctrl, st_node_index_t(idx)
+                    )
                     if _ptr_info != st_NullNodeInfoBase:
-                        _node_infos.append(NodeInfoBase(
-                            ptr_node_info=_ptr_info, owns_ptr=False))
+                        _node_infos.append(
+                            NodeInfoBase(
+                                ptr_node_info=_ptr_info, owns_ptr=False
+                            )
+                        )
 
         return _node_infos
 
@@ -870,13 +1015,15 @@ def has_default_node(self):
 
     @property
     def default_node_id(self):
-        return NodeId(ext_ptr_node_id=st_Controller_get_default_node_id(
-            self._ptr_ctrl))
+        return NodeId(
+            ext_ptr_node_id=st_Controller_get_default_node_id(self._ptr_ctrl)
+        )
 
     @property
     def default_node_id_str(self):
         return NodeId.to_string(
-            st_Controller_get_default_node_id(self._ptr_ctrl))
+            st_Controller_get_default_node_id(self._ptr_ctrl)
+        )
 
     @property
     def default_node_index(self):
@@ -886,8 +1033,10 @@ def default_node_index(self):
     def default_node_info(self):
         return NodeInfoBase(
             ptr_node_info=st_Controller_get_default_node_info_base(
-                self._ptr_ctrl),
-            owns_ptr=False)
+                self._ptr_ctrl
+            ),
+            owns_ptr=False,
+        )
 
     @property
     def has_selected_node(self):
@@ -895,13 +1044,17 @@ def has_selected_node(self):
 
     @property
     def selected_node_id(self):
-        return NodeId(ext_ptr_node_id=st_Controller_get_ptr_selected_node_id(
-            self._ptr_ctrl))
+        return NodeId(
+            ext_ptr_node_id=st_Controller_get_ptr_selected_node_id(
+                self._ptr_ctrl
+            )
+        )
 
     @property
     def selected_node_id_str(self):
-        return NodeId.to_string(st_Controller_get_ptr_selected_node_id(
-            self._ptr_ctrl))
+        return NodeId.to_string(
+            st_Controller_get_ptr_selected_node_id(self._ptr_ctrl)
+        )
 
     @property
     def selected_node_index(self):
@@ -911,7 +1064,10 @@ def selected_node_index(self):
     def selected_node_info(self):
         return NodeInfoBase(
             ptr_node_info=st_Controller_get_ptr_selected_node_info_base(
-                self._ptr_ctrl), owns_ptr=False)
+                self._ptr_ctrl
+            ),
+            owns_ptr=False,
+        )
 
     @property
     def can_change_node(self):
@@ -928,35 +1084,44 @@ def can_unselect_node(self):
     # -------------------------------------------------------------------------
 
     def is_default_node_check(
-            self,
-            node_id=st_NullNodeId,
-            node_id_str=None,
-            node_index=None,
-            platform_id=None,
-            device_id=None):
+        self,
+        node_id=st_NullNodeId,
+        node_id_str=None,
+        node_index=None,
+        platform_id=None,
+        device_id=None,
+    ):
         _is_default_node = False
         if node_id is not None and isinstance(node_id, NodeId):
             _is_default_node = st_Controller_is_default_node_id(
-                self._ptr_ctrl, node_id.pointer)
+                self._ptr_ctrl, node_id.pointer
+            )
         elif node_id is not None and node_id != st_NullNodeId:
             _is_default_node = st_Controller_is_default_node_id(
-                self._ptr_ctrl, node_id)
+                self._ptr_ctrl, node_id
+            )
         elif node_id_str is not None:
-            node_id_str = node_id_str.encode('utf-8')
             _is_default_node = st_Controller_is_default_node(
-                self._ptr_ctrl, ct.c_char_p(node_id_str))
-        elif node_index is not None and \
-                node_index != st_NODE_UNDEFINED_INDEX.value:
+                self._ptr_ctrl, string_to_encoded_ctypes_str(node_id_str)
+            )
+        elif (
+            node_index is not None
+            and node_index != st_NODE_UNDEFINED_INDEX.value
+        ):
             _is_default_node = st_Controller_is_default_node_index(
-                self._ptr_ctrl, st_node_index_t(node_index))
-        elif platform_id is not None and \
-                platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value and \
-                device_id is not None and \
-                device_id != st_NODE_ILLEGAL_DEVICE_ID.value:
-            _is_default_node = \
-                st_Controller_is_default_platform_id_and_device_id(
-                    self._ptr_ctrl, st_node_platform_id_t(platform_id),
-                    st_node_device_id_t(device_id))
+                self._ptr_ctrl, st_node_index_t(node_index)
+            )
+        elif (
+            platform_id is not None
+            and platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value
+            and device_id is not None
+            and device_id != st_NODE_ILLEGAL_DEVICE_ID.value
+        ):
+            _is_default_node = st_Controller_is_default_platform_id_and_device_id(
+                self._ptr_ctrl,
+                st_node_platform_id_t(platform_id),
+                st_node_device_id_t(device_id),
+            )
         return _is_default_node
 
     def is_default_node(self, node_id_str):
@@ -986,41 +1151,57 @@ def get_available_node_infos(self):
         return NodeControllerBase.available_node_infos(self.pointer)
 
     def __str__(self):
-        return '\r\n'.join(
-            [str(info) for info in self.get_available_node_infos()])
+        return "\r\n".join(
+            [str(info) for info in self.get_available_node_infos()]
+        )
 
     # -------------------------------------------------------------------------
 
-    def get_node_info_disp(self, node_id=st_NullNodeId, node_id_str=None,
-                           node_index=None, platform_id=None, device_id=None):
+    def get_node_info_disp(
+        self,
+        node_id=st_NullNodeId,
+        node_id_str=None,
+        node_index=None,
+        platform_id=None,
+        device_id=None,
+    ):
         node_info_base = None
         _ptr_node_info = st_NullNodeInfoBase
         if node_id_str is not None:
-            node_id_str = node_id_str.encode('utf-8')
             _ptr_node_info = st_Controller_get_ptr_node_info_base(
-                self._ptr_ctrl, ct.c_char_p(node_id_str))
+                self._ptr_ctrl, string_to_encoded_ctypes_str(node_id_str)
+            )
         elif node_id is not None and isinstance(node_id, NodeId):
             _ptr_node_info = st_Controller_get_ptr_node_info_base_by_node_id(
-                self._ptr_ctrl, node_id.pointer)
+                self._ptr_ctrl, node_id.pointer
+            )
         elif node_id is not None and node_id != st_NullNodeId:
             _ptr_node_info = st_Controller_get_ptr_node_info_base_by_node_id(
-                self._ptr_ctrl, node_id)
-        elif node_index is not None and \
-                node_index != st_NODE_UNDEFINED_INDEX.value:
+                self._ptr_ctrl, node_id
+            )
+        elif (
+            node_index is not None
+            and node_index != st_NODE_UNDEFINED_INDEX.value
+        ):
             _ptr_node_info = st_Controller_get_ptr_node_info_base_by_index(
-                self._ptr_ctrl, st_node_index_t(node_index))
-        elif platform_id is not None and \
-                platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value and \
-                device_id is not None and \
-                device_id != st_NODE_ILLEGAL_DEVICE_ID.value:
-            _ptr_node_info = \
-                st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id(
-                    self._ptr_ctrl, st_node_platform_id_t(platform_id),
-                    st_node_device_id_t(device_id))
+                self._ptr_ctrl, st_node_index_t(node_index)
+            )
+        elif (
+            platform_id is not None
+            and platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value
+            and device_id is not None
+            and device_id != st_NODE_ILLEGAL_DEVICE_ID.value
+        ):
+            _ptr_node_info = st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id(
+                self._ptr_ctrl,
+                st_node_platform_id_t(platform_id),
+                st_node_device_id_t(device_id),
+            )
 
         if _ptr_node_info != st_NullNodeInfoBase:
             node_info_base = NodeInfoBase(
-                ptr_node_info=_ptr_node_info, owns_ptr=False)
+                ptr_node_info=_ptr_node_info, owns_ptr=False
+            )
         return node_info_base
 
     def get_node_info(self, node_id_str):
@@ -1038,43 +1219,63 @@ def get_node_info_by_platform_id_and_device_id(self, pid, dev_id):
     # -------------------------------------------------------------------------
 
     def is_selected_node_check(
-            self,
-            node_id_str=None,
-            node_id=st_NullNodeId,
-            node_index=None,
-            platform_id=None,
-            device_id=None):
+        self,
+        node_id_str=None,
+        node_id=st_NullNodeId,
+        node_index=None,
+        platform_id=None,
+        device_id=None,
+    ):
         _is_selected_node = False
         _selected_node_index = st_Controller_get_selected_node_index(
-            self._ptr_ctrl)
-
-        if st_Controller_has_selected_node(self._ptr_ctrl) and \
-           _selected_node_index != st_NODE_UNDEFINED_INDEX.value:
-            if node_index is not None and \
-                    node_index != st_NODE_UNDEFINED_INDEX.value:
+            self._ptr_ctrl
+        )
+
+        if (
+            st_Controller_has_selected_node(self._ptr_ctrl)
+            and _selected_node_index != st_NODE_UNDEFINED_INDEX.value
+        ):
+            if (
+                node_index is not None
+                and node_index != st_NODE_UNDEFINED_INDEX.value
+            ):
                 is_selected_node = bool(node_index == _selected_node_index)
             elif node_id is not None and isinstance(node_id, NodeId):
                 _is_selected_node = bool(
-                    _selected_node_index == st_Controller_get_node_index_by_node_id(
-                        self._ptr_ctrl, node_id.pointer))
+                    _selected_node_index
+                    == st_Controller_get_node_index_by_node_id(
+                        self._ptr_ctrl, node_id.pointer
+                    )
+                )
             elif node_id is not None and node_id != st_NullNodeId:
                 _is_selected_node = bool(
-                    _selected_node_index == st_Controller_get_node_index_by_node_id(
-                        self._ptr_ctrl, node_id))
+                    _selected_node_index
+                    == st_Controller_get_node_index_by_node_id(
+                        self._ptr_ctrl, node_id
+                    )
+                )
             elif node_id_str is not None:
-                node_id_str = node_id_str.encode('utf-8')
                 _is_selected_node = bool(
-                    _selected_node_index == st_Controller_get_node_index(
-                        self._ptr_ctrl, ct.c_char_p(node_id_str)))
-            elif platform_id is not None and \
-                    platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value and \
-                    device_id is not None and \
-                    device_id != st_NODE_ILLEGAL_DEVICE_ID.value:
+                    _selected_node_index
+                    == st_Controller_get_node_index(
+                        self._ptr_ctrl,
+                        string_to_encoded_ctypes_str(node_id_str),
+                    )
+                )
+            elif (
+                platform_id is not None
+                and platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value
+                and device_id is not None
+                and device_id != st_NODE_ILLEGAL_DEVICE_ID.value
+            ):
                 _is_selected_node = bool(
-                    _selected_node_index == st_Controller_get_node_index_by_platform_id_and_device_id(
+                    _selected_node_index
+                    == st_Controller_get_node_index_by_platform_id_and_device_id(
                         self._ptr_ctrl,
                         st_node_platform_id_t(platform_id),
-                        st_node_device_id_t(device_id)))
+                        st_node_device_id_t(device_id),
+                    )
+                )
 
         return _is_selected_node
 
@@ -1093,35 +1294,44 @@ def are_selected_node_platform_id_and_device_id(self, pid, dev_id):
     # -------------------------------------------------------------------------
 
     def is_node_available_check(
-            self,
-            node_id_str=None,
-            node_id=st_NullNodeId,
-            node_index=None,
-            platform_id=None,
-            device_id=None):
+        self,
+        node_id_str=None,
+        node_id=st_NullNodeId,
+        node_index=None,
+        platform_id=None,
+        device_id=None,
+    ):
         _is_available = False
-        if node_index is not None and \
-                node_index != st_NODE_UNDEFINED_INDEX.value:
+        if (
+            node_index is not None
+            and node_index != st_NODE_UNDEFINED_INDEX.value
+        ):
             _is_available = st_Controller_is_node_available_by_index(
-                self._ptr_ctrl, st_node_index_t(node_index))
+                self._ptr_ctrl, st_node_index_t(node_index)
+            )
         elif node_id is not None and isinstance(node_id, NodeId):
             _is_available = st_Controller_is_node_available_by_node_id(
-                self._ptr_ctrl, node_id.pointer)
+                self._ptr_ctrl, node_id.pointer
+            )
         elif node_id is not None and node_id != st_NullNodeId:
             _is_available = st_Controller_is_node_available_by_node_id(
-                self._ptr_ctrl, node_id)
+                self._ptr_ctrl, node_id
+            )
         elif node_id_str is not None:
-            node_id_str = node_id_str.encode('utf-8')
             _is_available = st_Controller_is_node_available(
-                self._ptr_ctrl, ct.c_char_p(node_id_str))
-        elif platform_id is not None and \
-                platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value and \
-                device_id is not None and \
-                device_id != st_NODE_ILLEGAL_DEVICE_ID.value:
-            _is_available = \
-                st_Controller_is_node_available_by_platform_id_and_device_id(
-                    self._ptr_ctrl, st_node_platform_id_t(platform_id),
-                    st_node_device_id_t(device_id))
+                self._ptr_ctrl, string_to_encoded_ctypes_str(node_id_str)
+            )
+        elif (
+            platform_id is not None
+            and platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value
+            and device_id is not None
+            and device_id != st_NODE_ILLEGAL_DEVICE_ID.value
+        ):
+            _is_available = st_Controller_is_node_available_by_platform_id_and_device_id(
+                self._ptr_ctrl,
+                st_node_platform_id_t(platform_id),
+                st_node_device_id_t(device_id),
+            )
 
         return _is_available
 
@@ -1139,38 +1349,54 @@ def are_platform_id_and_device_id_available(self, pid, dev_id):
 
     # ------------------------------------------------------------------------
 
-    def select_node_disp(self, node_id_str=None, node_id=st_NullNodeId,
-                         node_index=None, platform_id=None, device_id=None):
+    def select_node_disp(
+        self,
+        node_id_str=None,
+        node_id=st_NullNodeId,
+        node_index=None,
+        platform_id=None,
+        device_id=None,
+    ):
         prev_last_status = self._last_status
-        if node_index is not None and \
-                node_index != st_NODE_UNDEFINED_INDEX.value:
+        if (
+            node_index is not None
+            and node_index != st_NODE_UNDEFINED_INDEX.value
+        ):
             self._last_status = st_Controller_select_node_by_index(
-                self._ptr_ctrl, st_node_index_t(node_index))
+                self._ptr_ctrl, st_node_index_t(node_index)
+            )
         elif node_id is not None and isinstance(node_id, NodeId):
             self._last_status = st_Controller_select_node_by_node_id(
-                self._ptr_ctrl, node_id.pointer)
+                self._ptr_ctrl, node_id.pointer
+            )
         elif node_id is not None and node_id != st_NullNodeId:
             self._last_status = st_Controller_select_node_by_node_id(
-                self._ptr_ctrl, node_id)
+                self._ptr_ctrl, node_id
+            )
         elif node_id_str is not None:
-            node_id_str = node_id_str.encode('utf-8')
             self._last_status = st_Controller_select_node(
-                self._ptr_ctrl, ct.c_char_p(node_id_str))
-        elif platform_id is not None and \
-                platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value and \
-                device_id is not None and \
-                device_id != st_NODE_ILLEGAL_DEVICE_ID.value:
-            self._last_status = \
-                st_Controller_select_node_by_plaform_id_and_device_id(
-                    self._ptr_ctrl, st_node_platform_id_t(platform_id),
-                    st_node_device_id_t(device_id))
+                self._ptr_ctrl, string_to_encoded_ctypes_str(node_id_str)
+            )
+        elif (
+            platform_id is not None
+            and platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value
+            and device_id is not None
+            and device_id != st_NODE_ILLEGAL_DEVICE_ID.value
+        ):
+            self._last_status = st_Controller_select_node_by_plaform_id_and_device_id(
+                self._ptr_ctrl,
+                st_node_platform_id_t(platform_id),
+                st_node_device_id_t(device_id),
+            )
 
         raise_error_if_status_not_success(
             self._last_status,
             msg="unsuccessful select node op; status:{0}".format(
-                self._last_status),
+                self._last_status
+            ),
             cls=RuntimeError,
-            prev=prev_last_status)
+            prev=prev_last_status,
+        )
 
         return self
 
@@ -1190,49 +1416,69 @@ def select_node_by_platform_id_and_device_id(self, pid, dev_id):
 
     def change_selected_node(self, current_node_index, new_selected_index):
         self._last_status = st_Controller_change_selected_node(
-            self._ptr_ctrl, st_node_index_t(current_node_index),
-            st_node_index_t(new_selected_index))
+            self._ptr_ctrl,
+            st_node_index_t(current_node_index),
+            st_node_index_t(new_selected_index),
+        )
 
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful change selected node op; status:{0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
 
         return self
 
     # ------------------------------------------------------------------------
 
-    def unselect_node_disp(self, node_id_str=None, node_id=st_NullNodeId,
-                           node_index=None, platform_id=None, device_id=None):
+    def unselect_node_disp(
+        self,
+        node_id_str=None,
+        node_id=st_NullNodeId,
+        node_index=None,
+        platform_id=None,
+        device_id=None,
+    ):
         prev_last_status = self._last_status
-        if node_index is not None and \
-                node_index != st_NODE_UNDEFINED_INDEX.value:
+        if (
+            node_index is not None
+            and node_index != st_NODE_UNDEFINED_INDEX.value
+        ):
             self._last_status = st_Controller_unselect_node_by_index(
-                self._ptr_ctrl, st_node_index_t(node_index))
+                self._ptr_ctrl, st_node_index_t(node_index)
+            )
         elif node_id is not None and isinstance(node_id, NodeId):
             self._last_status = st_Controller_unselect_node_by_node_id(
-                self._ptr_ctrl, node_id.pointer)
+                self._ptr_ctrl, node_id.pointer
+            )
         elif node_id is not None and node_id != st_NullNodeId:
             self._last_status = st_Controller_unselect_node_by_node_id(
-                self._ptr_ctrl, node_id)
+                self._ptr_ctrl, node_id
+            )
         elif node_id_str is not None:
-            node_id_str = node_id_str.encode('utf-8')
             self._last_status = st_Controller_unselect_node(
-                self._ptr_ctrl, ct.c_char_p(node_id_str))
-        elif platform_id is not None and \
-                platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value and \
-                device_id is not None and \
-                device_id != st_NODE_ILLEGAL_DEVICE_ID.value:
-            self._last_status = \
-                st_Controller_unselect_node_by_platform_id_and_device_id(
-                    self._ptr_ctrl, st_node_platform_id_t(platform_id),
-                    st_node_device_id_t(device_id))
+                self._ptr_ctrl, string_to_encoded_ctypes_str(node_id_str)
+            )
+        elif (
+            platform_id is not None
+            and platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value
+            and device_id is not None
+            and device_id != st_NODE_ILLEGAL_DEVICE_ID.value
+        ):
+            self._last_status = st_Controller_unselect_node_by_platform_id_and_device_id(
+                self._ptr_ctrl,
+                st_node_platform_id_t(platform_id),
+                st_node_device_id_t(device_id),
+            )
         raise_error_if_status_not_success(
             self._last_status,
             msg="unsuccessful unselect node op; status:{0}".format(
-                self._last_status),
+                self._last_status
+            ),
             cls=RuntimeError,
-            prev=prev_last_status)
+            prev=prev_last_status,
+        )
 
         return self
 
diff --git a/python/sixtracklib/cuda.py b/python/sixtracklib/cuda.py
index 14a8a51e..2556a0ad 100644
--- a/python/sixtracklib/cuda.py
+++ b/python/sixtracklib/cuda.py
@@ -9,28 +9,59 @@
 from .control import NodeId, NodeInfoBase, ArgumentBase, NodeControllerBase
 from .control import raise_error_if_status_not_success
 
-if SIXTRACKLIB_MODULES.get('cuda', False):
-    from .stcommon import st_Null, st_node_platform_id_t, st_node_device_id_t, \
-        st_node_index_t, st_arch_status_t, st_arch_size_t, st_buffer_size_t, \
-        st_ctrl_size_t, st_ctrl_status_t, st_NullBuffer, \
-        st_NullChar, st_ARCH_STATUS_GENERAL_FAILURE, st_ARCH_STATUS_SUCCESS, \
-        st_NODE_UNDEFINED_INDEX, st_NODE_ILLEGAL_PLATFORM_ID, \
-        st_NODE_ILLEGAL_DEVICE_ID, st_NullNodeId
-
-    from .stcommon import st_CudaNodeInfo_p, st_NullCudaNodeInfo, \
-        st_cuda_dev_index_t, st_CudaNodeInfo_new, st_CudaNodeInfo_new_detailed,\
-        st_CudaNodeInfo_get_cuda_device_index, \
-        st_CudaNodeInfo_get_pci_bus_id_str, st_CudaNodeInfo_get_warp_size, \
-        st_CudaNodeInfo_get_compute_capability, \
-        st_CudaNodeInfo_get_num_multiprocessors, \
-        st_CudaNodeInfo_get_max_threads_per_block, \
-        st_CudaNodeInfo_get_max_threads_per_multiprocessor
+if SIXTRACKLIB_MODULES.get("cuda", False):
+    from .stcommon import (
+        string_to_encoded_ctypes_str,
+        ctypes_str_to_decoded_string,
+        st_Null,
+        st_node_platform_id_t,
+        st_node_device_id_t,
+        st_node_index_t,
+        st_arch_status_t,
+        st_arch_size_t,
+        st_buffer_size_t,
+        st_ctrl_size_t,
+        st_ctrl_status_t,
+        st_NullBuffer,
+        st_NullChar,
+        st_ARCH_STATUS_GENERAL_FAILURE,
+        st_ARCH_STATUS_SUCCESS,
+        st_NODE_UNDEFINED_INDEX,
+        st_NODE_ILLEGAL_PLATFORM_ID,
+        st_NODE_ILLEGAL_DEVICE_ID,
+        st_NullNodeId,
+    )
+
+    from .stcommon import (
+        st_CudaNodeInfo_p,
+        st_NullCudaNodeInfo,
+        st_cuda_dev_index_t,
+        st_CudaNodeInfo_new,
+        st_CudaNodeInfo_new_detailed,
+        st_NodeId_create,
+        st_NodeId_delete,
+        st_CudaNodeInfo_get_cuda_device_index,
+        st_CudaNodeInfo_get_pci_bus_id_str,
+        st_CudaNodeInfo_get_warp_size,
+        st_CudaNodeInfo_get_compute_capability,
+        st_CudaNodeInfo_get_num_multiprocessors,
+        st_CudaNodeInfo_get_max_threads_per_block,
+        st_CudaNodeInfo_get_max_threads_per_multiprocessor,
+    )
 
     class CudaNodeInfo(NodeInfoBase):
-        def __init__(self, ptr_node_info=st_NullCudaNodeInfo, owns_ptr=False,
-                     cuda_dev_index=None, platform_id=None,
-                     device_id=None, node_index=None, is_default_node=False,
-                     is_selected_node=False, **kwargs):
+        def __init__(
+            self,
+            ptr_node_info=st_NullCudaNodeInfo,
+            owns_ptr=False,
+            cuda_dev_index=None,
+            platform_id=None,
+            device_id=None,
+            node_index=None,
+            is_default_node=False,
+            is_selected_node=False,
+            **kwargs
+        ):
             _ptr_node_info = ptr_node_info
             if _ptr_node_info == st_NullCudaNodeInfo:
                 if cuda_dev_index is not None and cuda_dev_index > 0:
@@ -47,13 +78,15 @@ def __init__(self, ptr_node_info=st_NullCudaNodeInfo, owns_ptr=False,
                         st_node_device_id_t(device_id),
                         st_node_index_t(node_index),
                         ct.c_bool(is_default_node),
-                        ct.c_bool(is_selected_node))
+                        ct.c_bool(is_selected_node),
+                    )
 
                     owns_ptr = bool(_ptr_node_info != st_NullCudaNodeInfo)
 
             if _ptr_node_info != st_NullCudaNodeInfo:
                 super().__init__(
-                    ptr_node_info=_ptr_node_info, owns_ptr=owns_ptr, **kwargs)
+                    ptr_node_info=_ptr_node_info, owns_ptr=owns_ptr, **kwargs
+                )
 
         def __del__(self):
             super().__del__()
@@ -64,13 +97,9 @@ def cuda_device_index(self):
 
         @property
         def pci_bus_id(self):
-            _pci_bus_id_str = None
-            _ptr_bus_id_cstr = st_CudaNodeInfo_get_pci_bus_id_str(
-                self._ptr_node_info)
-            if _ptr_bus_id_cstr != st_NullChar:
-                _pci_bus_id_str = bytes(
-                    _ptr_bus_id_cstr.value).decode('utf-8')
-            return _pci_bus_id_str
+            return ctypes_str_to_decoded_string(
+                st_CudaNodeInfo_get_pci_bus_id_str(self._ptr_node_info)
+            )
 
         @property
         def warp_size(self):
@@ -78,78 +107,231 @@ def warp_size(self):
 
         @property
         def compute_capability(self):
-            return st_CudaNodeInfo_get_compute_capability(
-                self._ptr_node_info)
+            return st_CudaNodeInfo_get_compute_capability(self._ptr_node_info)
 
         @property
         def num_multiprocessors(self):
-            return st_CudaNodeInfo_get_num_multiprocessors(
-                self._ptr_node_info)
+            return st_CudaNodeInfo_get_num_multiprocessors(self._ptr_node_info)
 
         @property
         def max_threads_per_block(self):
             return st_CudaNodeInfo_get_max_threads_per_block(
-                self._ptr_node_info)
+                self._ptr_node_info
+            )
 
         @property
         def max_threads_per_multiprocessor(self):
             st_CudaNodeInfo_get_max_threads_per_multiprocessor(
-                self._ptr_node_info)
-
-    from .stcommon import st_CudaController_p, st_NullCudaController, \
-        st_ControllerBase_p, st_NullControllerBase, \
-        st_CudaController_create, st_CudaController_new, \
-        st_CudaController_new_from_node_id, \
-        st_CudaController_new_from_platform_id_and_device_id, \
-        st_CudaController_new_from_node_index, \
-        st_CudaController_new_from_cuda_device_index, \
-        st_CudaController_select_node_by_cuda_device_index, \
-        st_CudaController_select_node_by_cuda_pci_bus_id, \
-        st_CudaController_is_managed_cobject_buffer_remapped, \
-        st_CudaController_remap_managed_cobject_buffer, \
-        st_CudaController_send_memory, st_CudaController_receive_memory, \
-        st_CudaController_get_ptr_node_info_by_index, \
-        st_CudaController_get_ptr_node_info_by_node_id, \
-        st_CudaController_get_ptr_node_info, \
-        st_CudaController_get_ptr_node_info_by_platform_id_and_device_id, \
-        st_CudaController_get_ptr_node_info_by_cuda_dev_index, \
-        st_CudaController_get_ptr_node_info_by_pci_bus_id
+                self._ptr_node_info
+            )
+
+    from .stcommon import (
+        st_node_id_str_fmt_t,
+        st_CudaController_p,
+        st_NullCudaController,
+        st_ControllerBase_p,
+        st_NullControllerBase,
+        st_CudaController_create,
+        st_CudaController_new,
+        st_CudaController_new_from_node_id,
+        st_CudaController_new_from_platform_id_and_device_id,
+        st_CudaController_new_from_node_index,
+        st_CudaController_new_from_cuda_device_index,
+        st_CudaController_select_node_by_cuda_device_index,
+        st_CudaController_select_node_by_cuda_pci_bus_id,
+        st_CudaController_is_managed_cobject_buffer_remapped,
+        st_CudaController_remap_managed_cobject_buffer,
+        st_CudaController_send_memory,
+        st_CudaController_receive_memory,
+        st_CudaController_get_ptr_node_info_by_index,
+        st_CudaController_get_ptr_node_info_by_node_id,
+        st_CudaController_get_ptr_node_info,
+        st_CudaController_get_ptr_node_info_by_platform_id_and_device_id,
+        st_CudaController_get_ptr_node_info_by_cuda_dev_index,
+        st_CudaController_get_ptr_node_info_by_pci_bus_id,
+        st_Cuda_get_num_all_nodes,
+        st_Cuda_print_all_nodes,
+        st_Cuda_num_available_nodes,
+        st_Cuda_num_available_nodes_detailed,
+        st_Cuda_print_available_nodes_detailed,
+        st_Cuda_get_available_nodes_detailed,
+        st_Cuda_get_available_node_id_strs,
+        st_Cuda_get_available_node_id_strs_detailed,
+        st_NodeId_p,
+        st_NullNodeId,
+        st_NodeId_get_platform_id,
+        st_NodeId_get_device_id,
+        st_NodeId_has_node_index,
+        st_NodeId_get_node_index,
+        st_NODE_ID_STR_FORMAT_ARCHSTR,
+    )
 
     class CudaController(NodeControllerBase):
-        def __init__(self, config_str=None, node_id=None,
-                     node_index=None, platform_id=None, device_id=None,
-                     cuda_dev_index=None, **kwargs):
-
-            if "ptr_controller" not in kwargs or \
-                    kwargs["ptr_controller"] == st_NullControllerBase:
+        @staticmethod
+        def NUM_ALL_NODES():
+            return st_Cuda_get_num_all_nodes()
+
+        @staticmethod
+        def PRINT_ALL_NODES():
+            st_Cuda_print_all_nodes()
+
+        @staticmethod
+        def NUM_AVAILABLE_NODES(filter_str=None, env_var_name=None):
+            return st_Cuda_num_available_nodes_detailed(
+                string_to_encoded_ctypes_str(filter_str),
+                string_to_encoded_ctypes_str(env_var_name),
+            )
+
+        @staticmethod
+        def PRINT_AVAILABLE_NODES(filter_str=None, env_var_name=None):
+            st_Cuda_print_available_nodes_detailed(
+                string_to_encoded_ctypes_str(filter_str),
+                string_to_encoded_ctypes_str(env_var_name),
+            )
+
+        @staticmethod
+        def GET_AVAILABLE_NODES(
+            filter_str=None, env_var_name=None, skip_first_num_nodes=0
+        ):
+            nodes = []
+            _filter_str = string_to_encoded_ctypes_str(filter_str)
+            _env_var_name = string_to_encoded_ctypes_str(env_var_name)
+            _num_avail_nodes = st_Cuda_num_available_nodes_detailed(
+                _filter_str, _env_var_name
+            )
+
+            if _num_avail_nodes > 0:
+                node_ids_array_t = st_NodeId_p * _num_avail_nodes
+                _node_ids = node_ids_array_t()
+                for ii in range(0, _num_avail_nodes):
+                    _node_ids[ii] = ct.cast(st_NodeId_create, st_NodeId_p)
+
+                _num_nodes = st_Cuda_get_available_nodes_detailed(
+                    _node_ids,
+                    st_arch_size_t(_num_avail_nodes),
+                    st_arch_size_t(skip_first_num_nodes),
+                    _filter_str,
+                    _env_var_name,
+                )
+
+                for ii in range(0, _num_nodes):
+                    platform_id = st_NodeId_get_platform_id(
+                        ct.byref(_node_ids[ii])
+                    )
+                    device_id = st_NodeId_get_platform_id(
+                        ct.byref(_node_ids[ii])
+                    )
+                    node_index = st_NodeId_get_node_index(
+                        ct.byref(_node_ids[ii])
+                    )
+                    nodes.append(
+                        NodeId(
+                            platform_id=platform_id,
+                            device_id=device_id,
+                            node_index=node_index,
+                        )
+                    )
+
+                for ii in range(0, _num_avail_nodes):
+                    st_NodeId_delete(_node_ids[ii])
+                    _node_ids[ii] = st_NullNodeId
+
+            return nodes
+
+        @staticmethod
+        def GET_AVAILABLE_NODE_ID_STRS(
+            filter_str=None,
+            env_var_name=None,
+            skip_first_num_nodes=0,
+            node_id_str_fmt=st_NODE_ID_STR_FORMAT_ARCHSTR.value,
+        ):
+            node_id_strs = []
+            _filter_str = string_to_encoded_ctypes_str(filter_str)
+            _env_var_name = string_to_encoded_ctypes_str(env_var_name)
+            _num_avail_nodes = st_Cuda_num_available_nodes_detailed(
+                _filter_str, _env_var_name
+            )
+
+            if _num_avail_nodes > 0:
+                _node_id_str_capacity = 64
+                node_id_str_buffer = [
+                    ct.create_string_buffer(_node_id_str_capacity)
+                ]
+
+                node_id_str_array_t = ct.c_char_p * _num_avail_nodes
+                _tmp_node_id_strs = node_id_str_array_t()
+
+                for ii in range(0, _num_avail_nodes):
+                    _tmp_node_id_strs[ii] = ct.cast(
+                        node_id_str_buffer[ii], ct.c_char_p
+                    )
+
+                _num_node_id_strs = st_Cuda_get_available_node_id_strs_detailed(
+                    _tmp_node_id_strs,
+                    st_arch_size_t(_num_avail_nodes),
+                    st_arch_size_t(_node_id_str_capacity),
+                    st_node_id_str_fmt_t(node_id_str_fmt),
+                    st_arch_size_t(skip_first_num_nodes),
+                    _filter_str,
+                    _env_var_name,
+                )
+
+                node_id_strs = [
+                    ctypes_str_to_decoded_string(_tmp_node_id_strs[ii])
+                    for ii in range(0, _num_node_id_strs)
+                ]
+            return node_id_strs
+
+        # *********************************************************************
+
+        def __init__(
+            self,
+            config_str=None,
+            node_id=None,
+            node_index=None,
+            platform_id=None,
+            device_id=None,
+            cuda_dev_index=None,
+            **kwargs
+        ):
+
+            if (
+                "ptr_controller" not in kwargs
+                or kwargs["ptr_controller"] == st_NullControllerBase
+            ):
                 _ptr_ctrl = st_NullCudaController
-
-                if config_str is None or config_str == st_NullChar:
-                    config_str = ''
-                config_str = config_str.encode('utf-8')
-                _config_str = ct.c_char_p(config_str)
+                _config_str = string_to_encoded_ctypes_str(config_str)
 
                 if node_id is not None and isinstance(node_id, NodeId):
                     _ptr_ctrl = st_CudaController_new_from_node_id(
-                        node_id.pointer, _config_str)
+                        node_id.pointer, _config_str
+                    )
                 elif node_id is not None and node_id != st_NullNodeId:
                     _ptr_ctrl = st_CudaController_new_from_node_id(
-                        node_id, _config_str)
-                elif node_index is not None and \
-                        node_index != st_NODE_UNDEFINED_INDEX.value:
+                        node_id, _config_str
+                    )
+                elif (
+                    node_index is not None
+                    and node_index != st_NODE_UNDEFINED_INDEX.value
+                ):
                     _ptr_ctrl = st_CudaController_new_from_node_index(
-                        st_node_index_t(node_index), _config_str)
+                        st_node_index_t(node_index), _config_str
+                    )
                 elif cuda_dev_index is not None and cuda_dev_index >= 0:
                     _ptr_ctrl = st_CudaController_new_from_cuda_device_index(
-                        st_cuda_dev_index_t(cuda_dev_index), _config_str)
-                elif platform_id is not None and \
-                        platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value and \
-                        device_id is not None and \
-                        device_id != st_NODE_ILLEGAL_DEVICE_ID:
-                    _ptr_ctrl = \
-                        st_CudaController_new_from_platform_id_and_device_id(
-                            st_node_platform_id_t(platform_id),
-                            st_node_device_id_t(device_id), _config_str)
+                        st_cuda_dev_index_t(cuda_dev_index), _config_str
+                    )
+                elif (
+                    platform_id is not None
+                    and platform_id != st_NODE_ILLEGAL_PLATFORM_ID.value
+                    and device_id is not None
+                    and device_id != st_NODE_ILLEGAL_DEVICE_ID
+                ):
+                    _ptr_ctrl = st_CudaController_new_from_platform_id_and_device_id(
+                        st_node_platform_id_t(platform_id),
+                        st_node_device_id_t(device_id),
+                        _config_str,
+                    )
                 else:
                     _ptr_ctrl = st_CudaController_new(_config_str)
 
@@ -162,89 +344,117 @@ def __del__(self):
             super().__del__()
 
         def select_node_by_cuda_device_id(self, cuda_dev_index):
-            self._last_status = \
-                st_CudaController_select_node_by_cuda_device_index(
-                    self._ptr_ctrl, st_cuda_dev_index_t(cuda_dev_index))
+            self._last_status = st_CudaController_select_node_by_cuda_device_index(
+                self._ptr_ctrl, st_cuda_dev_index_t(cuda_dev_index)
+            )
 
             raise_error_if_status_not_success(
                 self._last_status,
-                "unsuccessful select node by cuda_dev_index op; " +
-                "cuda_dev_index:{0}, status:{0}".format(
-                    cuda_dev_index,
-                    self._last_status))
+                "unsuccessful select node by cuda_dev_index op; "
+                + "cuda_dev_index:{0}, status:{0}".format(
+                    cuda_dev_index, self._last_status
+                ),
+            )
 
             return self
 
         def select_node_by_pci_bus_id(self, pci_bus_id):
-            pci_bus_id = pci_bus_id.encode('utf-8')
-            self._last_status = \
-                st_CudaController_select_node_by_cuda_pci_bus_id(
-                    self._ptr_ctrl, ct.c_char_p(pci_bus_id))
+            self._last_status = st_CudaController_select_node_by_cuda_pci_bus_id(
+                self._ptr_ctrl, string_to_encoded_ctypes_str(pci_bus_id)
+            )
 
             raise_error_if_status_not_success(
                 self._last_status,
-                "unsuccessful select node by pci bus id op; " +
-                "pci_bus_id:{0}, status:{0}".format(
-                    pci_bus_id,
-                    self._last_status))
+                "unsuccessful select node by pci bus id op; "
+                + "pci_bus_id:{0}, status:{0}".format(
+                    pci_bus_id, self._last_status
+                ),
+            )
 
             return self
 
         def managed_cobject_buffer_needs_remapping(
-                self, ptr_argument, slot_size):
+            self, ptr_argument, slot_size
+        ):
             return not st_CudaController_is_managed_cobject_buffer_remapped(
-                self._ptr_ctrl, ptr_argument, st_buffer_size_t(slot_size))
+                self._ptr_ctrl, ptr_argument, st_buffer_size_t(slot_size)
+            )
 
         def remap_managed_cobject_buffer(self, ptr_argument, slot_size):
             self._last_status = st_CudaController_remap_managed_cobject_buffer(
-                self._ptr_ctrl, ptr_argument, st_buffer_size_t(slot_size))
+                self._ptr_ctrl, ptr_argument, st_buffer_size_t(slot_size)
+            )
 
             raise_error_if_status_not_success(
                 self._last_status,
                 "unsuccessful remap managed cobject buffer op; status:{0}".format(
-                    self._last_status))
+                    self._last_status
+                ),
+            )
 
             return self
 
         def send_memory(self, ptr_argument, ptr_mem_begin, mem_size):
             self._last_status = st_CudaController_send_memory(
-                self._ptr_ctrl, ptr_argument, ptr_mem_begin,
-                st_arch_size_t(mem_size))
+                self._ptr_ctrl,
+                ptr_argument,
+                ptr_mem_begin,
+                st_arch_size_t(mem_size),
+            )
 
             raise_error_if_status_not_success(
                 self._last_status,
                 "unsuccessful send memory op; status:{0}".format(
-                    self._last_status))
+                    self._last_status
+                ),
+            )
 
             return self
 
         def receive_memory(self, ptr_mem_begin, ptr_argument, mem_capacity):
             self._last_status = st_CudaController_receive_memory(
-                self._ptr_ctrl, ptr_mem_begin, ptr_argument,
-                st_arch_size_t(mem_capacity))
+                self._ptr_ctrl,
+                ptr_mem_begin,
+                ptr_argument,
+                st_arch_size_t(mem_capacity),
+            )
 
             raise_error_if_status_not_success(
                 self._last_status,
                 "unsuccessful receive memory op; status:{0}".format(
-                    self._last_status))
+                    self._last_status
+                ),
+            )
 
             return self
 
-    from .stcommon import st_CudaArgument_p, st_NullCudaArgument, \
-        st_CudaArgument_new, st_CudaArgument_new_from_buffer, \
-        st_CudaArgument_new_from_raw_argument, st_CudaArgument_new_from_size, \
-        st_Argument_has_cuda_arg_buffer, st_CudaArgument_get_cuda_arg_buffer, \
-        st_CudaArgument_get_const_cuda_arg_buffer, \
-        st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin, \
-        st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin, \
-        st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin, \
-        st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin, \
-        st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin, \
-        st_CudaArgument_get_cuda_arg_buffer_as_const_elem_by_elem_config_begin
+    from .stcommon import (
+        st_CudaArgument_p,
+        st_NullCudaArgument,
+        st_CudaArgument_new,
+        st_CudaArgument_new_from_buffer,
+        st_CudaArgument_new_from_raw_argument,
+        st_CudaArgument_new_from_size,
+        st_Argument_has_cuda_arg_buffer,
+        st_CudaArgument_get_cuda_arg_buffer,
+        st_CudaArgument_get_const_cuda_arg_buffer,
+        st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin,
+        st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin,
+        st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin,
+        st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin,
+        st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin,
+        st_CudaArgument_get_cuda_arg_buffer_as_const_elem_by_elem_config_begin,
+    )
 
     class CudaArgument(ArgumentBase):
-        def __init__(self, buffer=None, ctrl=None,
-                     ptr_raw_arg_begin=None, raw_arg_size=None, **kwargs):
+        def __init__(
+            self,
+            buffer=None,
+            ctrl=None,
+            ptr_raw_arg_begin=None,
+            raw_arg_size=None,
+            **kwargs
+        ):
             ptr_cuda_ctrl = st_NullCudaController
             if ctrl is not None and isinstance(ctrl, CudaController):
                 ptr_cuda_ctrl = ctrl.pointer
@@ -252,10 +462,14 @@ def __init__(self, buffer=None, ctrl=None,
                 ptr_cuda_ctrl = ctrl
 
             if ptr_cuda_ctrl == st_NullCudaController:
-                raise ValueError("creating CudaArgument requires a " +
-                                 "CudaController instance")
-            if "ptr_argument" not in kwargs or \
-                    kwargs["ptr_argument"] == st_NullCudaArgument:
+                raise ValueError(
+                    "creating CudaArgument requires a "
+                    + "CudaController instance"
+                )
+            if (
+                "ptr_argument" not in kwargs
+                or kwargs["ptr_argument"] == st_NullCudaArgument
+            ):
                 _ptr_arg = st_NullCudaArgument
                 owns_ptr = True
                 ptr_buffer = st_NullBuffer
@@ -265,16 +479,21 @@ def __init__(self, buffer=None, ctrl=None,
                     ptr_buffer = buffer
                 if ptr_buffer is not None and ptr_buffer != st_NullBuffer:
                     _ptr_arg = st_CudaArgument_new_from_buffer(
-                        ptr_buffer, ptr_cuda_ctrl)
+                        ptr_buffer, ptr_cuda_ctrl
+                    )
                 elif raw_arg_size is not None and raw_arg_size > 0:
                     _raw_arg_size = st_ctrl_size_t(raw_arg_size)
-                    if ptr_raw_arg_begin is not None and \
-                            ptr_raw_arg_begin != st_Null:
+                    if (
+                        ptr_raw_arg_begin is not None
+                        and ptr_raw_arg_begin != st_Null
+                    ):
                         _ptr_arg = st_CudaArgument_new_from_raw_argument(
-                            ptr_raw_arg_begin, _raw_arg_size, ptr_cuda_ctrl)
+                            ptr_raw_arg_begin, _raw_arg_size, ptr_cuda_ctrl
+                        )
                     else:
                         _ptr_arg = st_CudaArgument_new_from_size(
-                            _raw_arg_size, ptr_cuda_ctrl)
+                            _raw_arg_size, ptr_cuda_ctrl
+                        )
                 else:
                     _ptr_arg = st_CudaArgument_new(ptr_cuda_ctrl)
 
@@ -295,83 +514,106 @@ def has_cuda_arg_buffer(self):
         @property
         def cuda_arg_buffer(self):
             _cuda_arg_buffer = st_CudaArgument_get_cuda_arg_buffer(
-                self._ptr_argument)
+                self._ptr_argument
+            )
             return _cuda_arg_buffer
 
         def get_as_buffer_begin(self):
             return st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin(
-                self._ptr_argument)
+                self._ptr_argument
+            )
 
         def get_as_ptr_debugging_register(self):
             return st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin(
-                self._ptr_argument)
+                self._ptr_argument
+            )
 
         def get_as_ptr_elem_by_elem_config(self):
             return st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin(
-                self._ptr_argument)
+                self._ptr_argument
+            )
 
     from .buffer import Buffer
     from .trackjob import TrackJobBaseNew
-    from .stcommon import st_CudaTrackJob_p, st_NullCudaTrackJob, \
-        st_CudaTrackJob_create, st_CudaTrackJob_new_from_config_str, \
-        st_CudaTrackJob_new, st_CudaTrackJob_new_with_output, \
-        st_CudaTrackJob_new_detailed, st_CudaTrackJob_has_controller, \
-        st_CudaTrackJob_get_ptr_controller, st_CudaTrackJob_has_particles_arg, \
-        st_CudaTrackJob_get_ptr_particles_arg, \
-        st_CudaTrackJob_has_beam_elements_arg, \
-        st_CudaTrackJob_get_ptr_beam_elements_arg, \
-        st_CudaTrackJob_has_output_arg, st_CudaTrackJob_get_ptr_output_arg, \
-        st_CudaTrackJob_has_elem_by_elem_config_arg, \
-        st_CudaTrackJob_get_ptr_elem_by_elem_config_arg, \
-        st_CudaTrackJob_has_debug_register_arg, \
-        st_CudaTrackJob_get_ptr_debug_register_arg, \
-        st_CudaTrackJob_has_particles_addr_arg, \
-        st_CudaTrackJob_get_ptr_particles_addr_arg, \
-        st_Controller_select_node
+    from .stcommon import (
+        st_CudaTrackJob_p,
+        st_NullCudaTrackJob,
+        st_CudaTrackJob_create,
+        st_CudaTrackJob_new_from_config_str,
+        st_CudaTrackJob_new,
+        st_CudaTrackJob_new_with_output,
+        st_CudaTrackJob_new_detailed,
+        st_CudaTrackJob_has_controller,
+        st_CudaTrackJob_get_ptr_controller,
+        st_CudaTrackJob_has_particles_arg,
+        st_CudaTrackJob_get_ptr_particles_arg,
+        st_CudaTrackJob_has_beam_elements_arg,
+        st_CudaTrackJob_get_ptr_beam_elements_arg,
+        st_CudaTrackJob_has_output_arg,
+        st_CudaTrackJob_get_ptr_output_arg,
+        st_CudaTrackJob_has_elem_by_elem_config_arg,
+        st_CudaTrackJob_get_ptr_elem_by_elem_config_arg,
+        st_CudaTrackJob_has_debug_register_arg,
+        st_CudaTrackJob_get_ptr_debug_register_arg,
+        st_CudaTrackJob_has_particles_addr_arg,
+        st_CudaTrackJob_get_ptr_particles_addr_arg,
+        st_Controller_select_node,
+        st_CudaTrackJob_default_threads_per_block,
+        st_CudaTrackJob_default_track_threads_per_block,
+    )
 
     class CudaTrackJob(TrackJobBaseNew):
-        def __init__(self, beam_elements_buffer, particles_buffer,
-                     particle_set_index=0, until_turn_elem_by_elem=0,
-                     output_buffer=None, node_id_str=None, config_str=None):
+        def __init__(
+            self,
+            beam_elements_buffer,
+            particles_buffer,
+            particle_set_index=0,
+            until_turn_elem_by_elem=0,
+            output_buffer=None,
+            node_id_str=None,
+            config_str=None,
+        ):
             _ptr_track_job = st_NullCudaTrackJob
 
             if config_str is not None and config_str != "":
-                _config_str = ct.c_char_p(config_str.encode('utf-8'))
                 _ptr_track_job = st_CudaTrackJob_new_from_config_str(
-                    _config_str)
+                    string_to_encoded_ctypes_str(config_str)
+                )
             else:
                 _ptr_track_job = st_CudaTrackJob_create()
 
-            if _ptr_track_job == st_NullCudaTrackJob:
+            if _ptr_track_job is st_NullCudaTrackJob:
                 raise RuntimeError("Error while creating CudaTrackJob")
 
             _last_status = st_ARCH_STATUS_SUCCESS.value
 
-            _ptr_cuda_ctrl = \
-                st_CudaTrackJob_get_ptr_controller(_ptr_track_job)
+            _ptr_cuda_ctrl = st_CudaTrackJob_get_ptr_controller(_ptr_track_job)
 
-            if not st_CudaTrackJob_has_controller(_ptr_track_job) or \
-                    _ptr_cuda_ctrl is None or \
-                    _ptr_cuda_ctrl == st_NullCudaController:
+            if (
+                not st_CudaTrackJob_has_controller(_ptr_track_job)
+                or _ptr_cuda_ctrl is None
+                or _ptr_cuda_ctrl == st_NullCudaController
+            ):
                 raise RuntimeError("CudaTrackJob requires CudaController")
 
             if node_id_str is not None and node_id_str != "":
-                _node_id_str = ct.c_char_p(node_id_str.encode('utf-8'))
                 _last_status = st_Controller_select_node(
-                    _ptr_cuda_ctrl, _node_id_str)
+                    _ptr_cuda_ctrl, string_to_encoded_ctypes_str(node_id_str)
+                )
                 raise_error_if_status_not_success(
                     _last_status,
-                    "Error selection of node by node_id_str {0} " +
-                    "status:{1}".format(
-                        node_id_str,
-                        _last_status))
+                    "Error selection of node by node_id_str {0} "
+                    + "status:{1}".format(node_id_str, _last_status),
+                )
 
             if _last_status == st_ARCH_STATUS_SUCCESS.value:
                 super().__init__(ptr_track_job=_ptr_track_job, owns_ptr=True)
 
-            if self._ptr_track_job is None or \
-                    self._ptr_track_job == st_NullCudaTrackJob or \
-                    self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            if (
+                self._ptr_track_job is None
+                or self._ptr_track_job == st_NullCudaTrackJob
+                or self._last_status != st_ARCH_STATUS_SUCCESS.value
+            ):
                 raise RuntimeError("Error during creation of TrackJobBase")
 
             super()._reset_detailed(
@@ -379,7 +621,8 @@ def __init__(self, beam_elements_buffer, particles_buffer,
                 particles_buffer,
                 particle_set_index,
                 until_turn_elem_by_elem,
-                output_buffer)
+                output_buffer,
+            )
 
             if self._last_status != st_ARCH_STATUS_SUCCESS.value:
                 raise RuntimeError("Error during resetting TrackJobBase")
@@ -394,7 +637,8 @@ def has_particles_arg(self):
         @property
         def particles_arg(self):
             _ptr_argument = st_CudaTrackJob_get_ptr_particles_arg(
-                self._ptr_track_job)
+                self._ptr_track_job
+            )
             return CudaArgument(ptr_argument=_ptr_argument, owns_ptr=False)
 
         @property
@@ -404,7 +648,8 @@ def has_beam_elements_arg(self):
         @property
         def beam_elements_arg(self):
             _ptr_argument = st_CudaTrackJob_get_ptr_beam_elements_arg(
-                self._ptr_track_job)
+                self._ptr_track_job
+            )
             return CudaArgument(ptr_argument=_ptr_argument, owns_ptr=False)
 
         @property
@@ -414,7 +659,8 @@ def has_output_arg(self):
         @property
         def output_arg(self):
             _ptr_argument = st_CudaTrackJob_get_ptr_output_arg(
-                self._ptr_track_job)
+                self._ptr_track_job
+            )
             return CudaArgument(ptr_argument=_ptr_argument, owns_ptr=False)
 
         @property
@@ -424,7 +670,8 @@ def has_particles_addr_arg(self):
         @property
         def particles_addr_arg(self):
             _ptr_argument = st_CudaTrackJob_get_ptr_particles_addr_arg(
-                self._ptr_track_job)
+                self._ptr_track_job
+            )
             return CudaArgument(ptr_argument=_ptr_argument, owns_ptr=False)
 
         @property
@@ -434,7 +681,8 @@ def has_debug_register_arg(self):
         @property
         def particles_arg(self):
             _ptr_argument = st_CudaTrackJob_get_ptr_debug_register_arg(
-                self._ptr_track_job)
+                self._ptr_track_job
+            )
             return CudaArgument(ptr_argument=_ptr_argument, owns_ptr=False)
 
         @property
@@ -444,18 +692,64 @@ def has_controller(self):
         @property
         def controller(self):
             _ptr_cuda_ctrl = st_CudaTrackJob_get_ptr_controller(
-                self._ptr_track_job)
+                self._ptr_track_job
+            )
             return CudaController(
-                ptr_controller=_ptr_cuda_ctrl,
-                owns_ptr=False)
+                ptr_controller=_ptr_cuda_ctrl, owns_ptr=False
+            )
+
+        @property
+        def default_threads_per_block(self):
+            return st_CudaTrackJob_default_threads_per_block(
+                self._ptr_track_job)
+
+        @property
+        def default_track_threads_per_block(self):
+            return st_CudaTrackJob_default_track_threads_per_block(
+                self._ptr_track_job)
 
 
 else:
+
     class CudaNodeInfo(object):
         pass
 
     class CudaController(object):
-        pass
+        @staticmethod
+        def NUM_ALL_NODES():
+            raise RuntimeError("Cuda module disabled, no nodes present")
+            return 0
+
+        @staticmethod
+        def PRINT_ALL_NODES():
+            raise RuntimeError("Cuda module disabled, no nodes to print")
+            st_Cuda_print_all_nodes()
+
+        @staticmethod
+        def NUM_AVAILABLE_NODES(filter_str=None, env_var_name=None):
+            raise RuntimeError("Cuda module disabled, no nodes available")
+            return 0
+
+        @staticmethod
+        def PRINT_AVAILABLE_NODES(filter_str=None, env_var_name=None):
+            raise RuntimeError("Cuda module disabled, no nodes to print")
+
+        @staticmethod
+        def GET_AVAILABLE_NODES(
+            filter_str=None, env_var_name=None, skip_first_num_nodes=0
+        ):
+            raise RuntimeError("Cuda module disabled, no nodes available")
+            return []
+
+        @staticmethod
+        def GET_AVAILABLE_NODE_ID_STRS(
+            filter_str=None,
+            env_var_name=None,
+            skip_first_num_nodes=0,
+            node_id_str_fmt=None,
+        ):
+            raise RuntimeError("Cuda module disabled, no nodes available")
+            return []
 
     class CudaArgument(object):
         pass
diff --git a/python/sixtracklib/mad_helper.py b/python/sixtracklib/mad_helper.py
index f74d12d5..8a821885 100644
--- a/python/sixtracklib/mad_helper.py
+++ b/python/sixtracklib/mad_helper.py
@@ -2,47 +2,47 @@
 
 
 classes = dict(
-    Drift=namedtuple('Drift', 'length'),
-    Multipole=namedtuple('Multipole', 'knl ksl hxl hyl length'),
-    Cavity=namedtuple('Cavity', 'voltage frequency lag'),
-    XYShift=namedtuple('XYShift', 'dx dy'),
-    SRotation=namedtuple('SRotation', 'angle'),
-    Line=namedtuple('Line', 'elems'),
+    Drift=namedtuple("Drift", "length"),
+    Multipole=namedtuple("Multipole", "knl ksl hxl hyl length"),
+    Cavity=namedtuple("Cavity", "voltage frequency lag"),
+    XYShift=namedtuple("XYShift", "dx dy"),
+    SRotation=namedtuple("SRotation", "angle"),
+    Line=namedtuple("Line", "elems"),
 )
 
 
 def dispatch(el, classes):
-    Drift = classes['Drift']
-    Multipole = classes['Multipole']
-    Cavity = classes['Cavity']
+    Drift = classes["Drift"]
+    Multipole = classes["Multipole"]
+    Cavity = classes["Cavity"]
 
     key = el.base_type.name
-    if key == 'multipole':
-        knl = el.knl if hasattr(el, 'knl') else [0]
-        ksl = el.ksl if hasattr(el, 'ksl') else [0]
-        el = Multipole(
-            knl=knl,
-            ksl=ksl,
-            hxl=knl[0],
-            hyl=0,
-            length=el.lrad)
-    elif key in ['marker', 'hmonitor', 'vmonitor', 'instrument',
-                 'monitor', 'rcollimator']:
+    if key == "multipole":
+        knl = el.knl if hasattr(el, "knl") else [0]
+        ksl = el.ksl if hasattr(el, "ksl") else [0]
+        el = Multipole(knl=knl, ksl=ksl, hxl=knl[0], hyl=0, length=el.lrad)
+    elif key in [
+        "marker",
+        "hmonitor",
+        "vmonitor",
+        "instrument",
+        "monitor",
+        "rcollimator",
+    ]:
         el = Drift(length=0)
-    elif key == 'hkicker':
-        el = Multipole(knl=[-el.kick], ksl=[],
-                       length=el.lrad, hxl=0, hyl=0)
-    elif key == 'vkicker':
-        el = Multipole(knl=[], ksl=[el.kick],
-                       length=el.lrad, hxl=0, hyl=0)
-    elif key == 'rfcavity':
-        el = Cavity(voltage=el.volt * 1e6,
-                    frequency=el.freq * 1e6, lag=el.lag * 360)
+    elif key == "hkicker":
+        el = Multipole(knl=[-el.kick], ksl=[], length=el.lrad, hxl=0, hyl=0)
+    elif key == "vkicker":
+        el = Multipole(knl=[], ksl=[el.kick], length=el.lrad, hxl=0, hyl=0)
+    elif key == "rfcavity":
+        el = Cavity(
+            voltage=el.volt * 1e6, frequency=el.freq * 1e6, lag=el.lag * 360
+        )
     return el
 
 
 def madseq_to_generator(seq, convert=classes):
-    Drift = convert['Drift']
+    Drift = convert["Drift"]
     oldpos = 0
     poss = seq.element_positions()
     names = seq.element_names()
diff --git a/python/sixtracklib/opencl.py b/python/sixtracklib/opencl.py
new file mode 100644
index 00000000..a49fb233
--- /dev/null
+++ b/python/sixtracklib/opencl.py
@@ -0,0 +1,1055 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import ctypes as ct
+from cobjects import CBuffer, CObject
+from .particles import ParticlesSet
+from .buffer import Buffer
+from .config import SIXTRACKLIB_MODULES
+from .control import raise_error_if_status_not_success
+
+if SIXTRACKLIB_MODULES.get("opencl", False):
+    from .stcommon import (
+        string_to_encoded_ctypes_str,
+        ctypes_str_to_decoded_string,
+        st_ClContextBase_p,
+        st_NullClContextBase,
+        st_NullBuffer,
+        st_Buffer_p,
+        st_Null,
+        st_NullChar,
+        st_ARCH_ILLEGAL_PROGRAM_ID,
+        st_ARCH_ILLEGAL_KERNEL_ID,
+        st_ARCH_STATUS_GENERAL_FAILURE,
+        st_ARCH_STATUS_SUCCESS,
+        st_ARCHITECTURE_OPENCL,
+        st_NODE_ID_STR_FORMAT_ARCHSTR,
+        st_NODE_ID_STR_FORMAT_NOARCH,
+        st_node_id_str_fmt_t,
+        st_arch_id_t,
+        st_arch_program_id_t,
+        st_arch_kernel_id_t,
+        st_arch_status_t,
+        st_arch_size_t,
+        st_node_platform_id_t,
+        st_node_device_id_t,
+        st_ClNodeId,
+        st_ClNodeId_p,
+        st_NullClNodeId,
+        st_ClNodeInfo_p,
+        st_NullClNodeInfo,
+        st_ComputeNodeId_create,
+        st_ComputeNodeId_delete,
+        st_ComputeNodeId_get_platform_id,
+        st_ComputeNodeId_get_device_id,
+        st_ComputeNodeId_set_platform_id,
+        st_ComputeNodeId_set_device_id,
+        st_ComputeNodeId_is_valid,
+        st_ComputeNodeId_compare,
+        st_ComputeNodeId_are_equal,
+        st_ComputeNodeId_from_string,
+        st_ComputeNodeId_from_string_with_format,
+        st_ComputeNodeId_to_string,
+        st_ComputeNodeId_to_string_with_format,
+        st_ComputeNodeInfo_preset,
+        st_ComputeNodeInfo_print_out,
+        st_ComputeNodeInfo_free,
+        st_ComputeNodeInfo_delete,
+        st_ComputeNodeInfo_reserve,
+        st_ComputeNodeInfo_make,
+        st_ComputeNodeInfo_is_valid,
+        st_ComputeNodeInfo_get_id,
+        st_ComputeNodeInfo_get_platform_id,
+        st_ComputeNodeInfo_get_device_id,
+        st_ComputeNodeInfo_get_arch,
+        st_ComputeNodeInfo_get_platform,
+        st_ComputeNodeInfo_get_name,
+        st_ComputeNodeInfo_get_description,
+        st_ClContext_create,
+        st_ClContextBase_set_default_compile_options,
+        st_ClContextBase_default_compile_options,
+        st_ClContextBase_num_feature_flags,
+        st_ClContextBase_has_feature_flag,
+        st_ClContextBase_feature_flag,
+        st_ClContextBase_set_feature_flag,
+        st_ClContextBase_feature_flag_repr_required_capacity,
+        st_ClContextBase_feature_flag_repr_as_cstr,
+        st_ClContextBase_reinit_default_programs,
+        st_ClContextBase_delete,
+        st_ClContextBase_has_selected_node,
+        st_ClContextBase_get_selected_node_id,
+        st_ClContextBase_get_selected_node_info,
+        st_ClContextBase_get_selected_node_index,
+        st_ClContextBase_get_selected_node_id_str,
+        st_ClContextBase_select_node_by_node_id,
+        st_ClContextBase_select_node_by_index,
+        st_ClContextBase_select_node,
+        st_ClContextBase_get_num_available_programs,
+        st_ClContextBase_print_nodes_info,
+        st_ClContextBase_add_program_file,
+        st_ClContextBase_compile_program,
+        st_ClContextBase_get_num_available_kernels,
+        st_ClContextBase_enable_kernel,
+        st_ClContextBase_find_kernel_id_by_name,
+        st_ClContextBase_get_kernel_local_mem_size,
+        st_ClContextBase_get_kernel_num_args,
+        st_ClContextBase_get_kernel_work_group_size,
+        st_ClContextBase_get_kernel_max_work_group_size,
+        st_ClContextBase_set_kernel_work_group_size,
+        st_ClContextBase_get_kernel_preferred_work_group_size_multiple,
+        st_ClContextBase_get_ptr_kernel_argument,
+        st_ClContextBase_get_kernel_argument_type,
+        st_ClContextBase_reset_single_kernel_argument,
+        st_ClContextBase_reset_kernel_arguments,
+        st_ClContextBase_assign_kernel_argument,
+        st_ClContextBase_assign_kernel_argument_value,
+        st_ClContextBase_assign_kernel_argument_raw_ptr,
+        st_ClContextBase_calculate_kernel_num_work_items,
+        st_ClContextBase_run_kernel,
+        st_ClContextBase_run_kernel_wgsize,
+        st_ClContextBase_get_kernel_exec_counter,
+        st_ClContextBase_get_last_exec_time,
+        st_ClContextBase_get_min_exec_time,
+        st_ClContextBase_get_max_exec_time,
+        st_ClContextBase_get_avg_exec_time,
+        st_ClContextBase_get_last_exec_work_group_size,
+        st_ClContextBase_get_last_exec_num_work_items,
+        st_ClContextBase_reset_kernel_exec_timing,
+        st_ClContextBase_get_program_id_by_kernel_id,
+        st_ClContextBase_get_required_program_compile_options_capacity,
+        st_ClContextBase_get_program_compile_options,
+        st_ClContextBase_get_required_program_path_capacity,
+        st_ClContextBase_get_program_path_to_file,
+        st_ClContextBase_get_required_program_source_code_capacity,
+        st_ClContextBase_get_program_source_code,
+        st_ClContextBase_has_program_file_path,
+        st_ClContextBase_get_required_program_compile_report_capacity,
+        st_ClContextBase_get_program_compile_report,
+        st_ClContextBase_is_program_compiled,
+        st_ClContextBase_has_remapping_program,
+        st_ClContextBase_remapping_program_id,
+        st_ClContextBase_has_remapping_kernel,
+        st_ClContextBase_remapping_kernel_id,
+        st_ClContextBase_set_remapping_kernel_id,
+        st_ClContextBase_is_debug_mode_enabled,
+        st_ClContextBase_enable_debug_mode,
+        st_ClContextBase_disable_debug_mode,
+        st_ClArgument_p,
+        st_NullClArgument,
+        st_ClArgument_new_from_buffer,
+        st_ClArgument_delete,
+        st_ClArgument_write,
+        st_ClArgument_read,
+        st_ClArgument_write_memory,
+        st_ClArgument_read_memory,
+        st_ClArgument_get_argument_size,
+        st_ClArgument_uses_cobj_buffer,
+        st_ClArgument_get_ptr_cobj_buffer,
+        st_ClArgument_get_ptr_to_context,
+        st_ClArgument_attach_to_context,
+        st_OpenCL_get_num_all_nodes,
+        st_OpenCL_get_all_nodes,
+        st_OpenCL_print_all_nodes,
+        st_OpenCL_num_available_nodes,
+        st_OpenCL_num_available_nodes_detailed,
+        st_OpenCL_get_available_nodes_detailed,
+        st_OpenCL_print_available_nodes_detailed,
+    )
+
+    class ClNodeId(object):
+        @staticmethod
+        def PTR_TO_STRING(
+            ptr_node_id,
+            arch_id=st_ARCHITECTURE_OPENCL.value,
+            format=st_NODE_ID_STR_FORMAT_ARCHSTR.value,
+            node_id_cstr=None,
+            capacity=64,
+        ):
+            node_id_str = None
+            if capacity is None or capacity <= 0:
+                capacity = 64
+            if node_id_cstr is None:
+                node_id_cstr = ct.create_string_buffer(capacity)
+
+            status = st_ComputeNodeId_to_string_with_format(
+                ptr_node_id,
+                node_id_cstr,
+                st_arch_size_t(capacity),
+                st_arch_id_t(arch_id),
+                st_node_id_str_fmt_t(format),
+            )
+
+            if status == st_ARCH_STATUS_SUCCESS.value:
+                node_id_str = ctypes_str_to_decoded_string(node_id_cstr.value)
+            else:
+                raise RuntimeError(
+                    "Unable to create node_id_str from pointer to ClNodeId"
+                )
+            return node_id_str
+
+        def __init__(
+            self,
+            ext_ptr_node_id=st_NullClNodeId,
+            owns_ptr=True,
+            node_id_str=None,
+            node_id_str_fmt=st_NODE_ID_STR_FORMAT_NOARCH.value,
+            platform_id=None,
+            device_id=None,
+        ):
+            self._arch_id = st_ARCHITECTURE_OPENCL.value
+            self._ptr_node_id = st_NullClNodeId
+            self._owns_node = True
+            self._last_status = st_ARCH_STATUS_SUCCESS.value
+
+            if ext_ptr_node_id != st_NullClNodeId:
+                self._ptr_node_id = ext_ptr_node_id
+                self._owns_node = owns_ptr
+            else:
+                self._ptr_node_id = st_ComputeNodeId_create()
+                _temp_arch_id = st_ARCHITECTURE_OPENCL
+
+                if not (node_id_str is None):
+                    self._last_status = st_ComputeNodeId_from_string_with_format(
+                        self._ptr_node_id,
+                        string_to_encoded_ctypes_str(node_id_str),
+                        st_node_id_str_fmt_t(node_id_str_fmt),
+                        ct.byref(_temp_arch_id),
+                    )
+                    if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+                        error_msg = f"""
+                        "Unable to initialize a ClNodeId from node_id_str=\"
+                        {node_id_str}, format={node_id_str_fmt}"""
+                        raise ValueError(error_msg)
+                elif not (platform_id is None) and not (device_id is None):
+                    st_ComputeNodeId_set_platform_id(
+                        self._ptr_node_id, st_node_platform_id_t(platform_id)
+                    )
+                    st_ComputeNodeId_set_device_id(
+                        self._ptr_node_id, st_node_device_id_t(device_id)
+                    )
+
+        def __del__(self):
+            if self._owns_node and self._ptr_node_id != st_NullClNodeId:
+                st_ComputeNodeId_delete(self._ptr_node_id)
+                self._ptr_node_id = st_NullClNodeId
+
+        @property
+        def last_status(self):
+            return self._last_status
+
+        @property
+        def pointer(self):
+            return self._ptr_node_id
+
+        @property
+        def owns_node(self):
+            return self._owns_node
+
+        @property
+        def arch_id(self):
+            return self._arch_id
+
+        @property
+        def platform_id(self):
+            return st_ComputeNodeId_get_platform_id(self._ptr_node_id)
+
+        @property
+        def device_id(self):
+            return st_ComputeNodeId_get_device_id(self._ptr_node_id)
+
+        def set_platform_id(self, platform_id):
+            if self._owns_node:
+                st_ComputeNodeId_set_platform_id(
+                    self._ptr_node_id, st_node_platform_id_t(platform_id)
+                )
+            else:
+                raise RuntimeError(
+                    "Can't update ClNodeId via a non-owning obj"
+                )
+            return self
+
+        def set_device_id(self, device_id):
+            if self._owns_node:
+                st_ComputeNodeId_set_device_id(
+                    self._ptr_node_id, st_node_device_id_t(device_id)
+                )
+            else:
+                raise RuntimeError(
+                    "Can't update ClNodeId via a non-owning obj"
+                )
+            return self
+
+        def to_string(self, format=st_NODE_ID_STR_FORMAT_ARCHSTR.value):
+            return ClNodeId.PTR_TO_STRING(
+                self._ptr_node_id, arch_id=self.arch_id, format=format
+            )
+
+        def __repr__(self):
+            a_id = self.arch_id
+            p_id = self.platform_id
+            d_id = self.device_id
+            msg = f"<ClNodeId:arch_id={a_id},platform_id={p_id},device_id={d_id}>\r\n"
+            return msg
+
+        def __str__(self):
+            return self.to_string(format=st_NODE_ID_STR_FORMAT_ARCHSTR.value)
+
+    class ClController(object):
+        @staticmethod
+        def NUM_ALL_NODES():
+            return st_OpenCL_get_num_all_nodes()
+
+        @staticmethod
+        def PRINT_ALL_NODES():
+            st_OpenCL_print_all_nodes()
+
+        @staticmethod
+        def NUM_AVAILABLE_NODES(filter_str=None, env_var_name=None):
+            return st_OpenCL_num_available_nodes_detailed(
+                string_to_encoded_ctypes_str(filter_str),
+                string_to_encoded_ctypes_str(env_var_name),
+            )
+
+        @staticmethod
+        def PRINT_AVAILABLE_NODES(filter_str=None, env_var_name=None):
+            st_OpenCL_print_available_nodes_detailed(
+                string_to_encoded_ctypes_str(filter_str),
+                string_to_encoded_ctypes_str(env_var_name),
+            )
+
+        @staticmethod
+        def GET_AVAILABLE_NODES(
+            filter_str=None, env_var_name=None, skip_first_num_nodes=0
+        ):
+            _filter_str = string_to_encoded_ctypes_str(filter_str)
+            _env_var_name = string_to_encoded_ctypes_str(env_var_name)
+            _num_avail_nodes = ClController.NUM_AVAILABLE_NODES(
+                filter_str=_filter_str, env_var_name=_env_var_name
+            )
+            nodes = []
+            if _num_avail_nodes > 0:
+                node_ids_array_t = st_ClNodeId * _num_avail_nodes
+                _node_ids = node_ids_array_t()
+                _num_nodes = st_OpenCL_get_available_nodes_detailed(
+                    _node_ids,
+                    st_arch_size_t(_num_avail_nodes),
+                    st_arch_size_t(skip_first_num_nodes),
+                    _filter_str,
+                    _env_var_name,
+                )
+
+                for ii in range(0, _num_nodes):
+                    platform_id = st_ComputeNodeId_get_platform_id(
+                        ct.byref(_node_ids[ii])
+                    )
+                    device_id = st_ComputeNodeId_get_device_id(
+                        ct.byref(_node_ids[ii])
+                    )
+                    nodes.append(
+                        ClNodeId(
+                            platform_id=platform_id,
+                            device_id=device_id,
+                            owns_ptr=True,
+                        )
+                    )
+            return nodes
+
+        @staticmethod
+        def GET_AVAILABLE_NODE_ID_STRS(
+            filter_str=None,
+            env_var_name=None,
+            skip_first_num_nodes=0,
+            node_id_str_fmt=st_NODE_ID_STR_FORMAT_ARCHSTR.value,
+        ):
+            node_id_strs = []
+            _filter_str = string_to_encoded_ctypes_str(filter_str)
+            _env_var_name = string_to_encoded_ctypes_str(env_var_name)
+            _num_avail_nodes = st_OpenCL_num_available_nodes_detailed(
+                _filter_str, _env_var_name
+            )
+
+            if _num_avail_nodes > skip_first_num_nodes:
+                _num_nodes = _num_avail_nodes - skip_first_num_nodes
+                node_id_array_t = st_ClNodeId * _num_nodes
+                _tmp_node_ids = node_id_array_t()
+
+                _num_retrieved_nodes = st_OpenCL_get_available_nodes_detailed(
+                    _tmp_node_ids,
+                    st_arch_size_t(_num_nodes),
+                    st_arch_size_t(skip_first_num_nodes),
+                    _filter_str,
+                    _env_var_name,
+                )
+
+                if _num_retrieved_nodes > 0:
+                    assert _num_nodes >= _num_retrieved_nodes
+                    _node_id_cstr_cap = 64
+                    _node_id_cstr = ct.create_string_buffer(_node_id_cstr_cap)
+
+                    for ii in range(0, _num_retrieved_nodes):
+                        tmp_node_id_str = ClNodeId.PTR_TO_STRING(
+                            ct.byref(_tmp_node_ids[ii]),
+                            arch_id=st_ARCHITECTURE_OPENCL.value,
+                            format=node_id_str_fmt,
+                            node_id_cstr=_node_id_cstr,
+                            capacity=_node_id_cstr_cap,
+                        )
+                        node_id_strs.append(tmp_node_id_str)
+
+            assert len(node_id_strs) <= _num_avail_nodes
+            return node_id_strs
+
+        def __init__(
+            self,
+            config_str=None,
+            device_id=None,
+            ext_ptr_ctrl=st_NullClContextBase,
+            owns_ptr=True,
+        ):
+            self._ptr_ctrl = st_NullClContextBase
+            self._owns_ctrl = True
+            self._last_status = st_ARCH_STATUS_SUCCESS.value
+
+            if ext_ptr_ctrl != st_NullClContextBase:
+                self._ptr_ctrl = ext_ptr_ctrl
+                self._owns_ctrl = owns_ptr
+            else:
+                self._ptr_ctrl = st_ClContext_create()
+
+            if self._ptr_ctrl is st_NullClContextBase:
+                raise RuntimeError("ClController needs a valid ptr")
+
+            if device_id is not None:
+                device_id = device_id.strip()
+                if device_id.startswith("opencl:"):
+                    device_id = device_id[7:]
+                elif ":" in device_id:
+                    device_id = None
+
+            if device_id is not None and len(device_id) > 0:
+                st_ClContextBase_select_node(
+                    self._ptr_ctrl, string_to_encoded_ctypes_str(device_id)
+                )
+
+        def __del__(self):
+            if self._owns_ctrl and self._ptr_ctrl != st_NullClContextBase:
+                st_ClContextBase_delete(self._ptr_ctrl)
+            self._ptr_ctrl = st_NullClContextBase
+
+        @property
+        def last_status(self):
+            return self.last_status
+
+        @property
+        def pointer(self):
+            return self._ptr_ctrl
+
+        @property
+        def owns_controller(self):
+            return self._owns_ctrl
+
+        @property
+        def has_selected_node(self):
+            return st_ClContextBase_has_selected_node(self._ptr_ctrl)
+
+        @property
+        def selected_node_platform_id(self):
+            platform_id = None
+            _info = st_ClContextBase_get_selected_node_info(self._ptr_ctrl)
+            if _info is not st_NullClNodeInfo:
+                platform_id = st_ComputeNodeInfo_get_platform_id(_info)
+            return platform_id
+
+        @property
+        def selected_node_device_id(self):
+            device_id = None
+            _info = st_ClContextBase_get_selected_node_info(self._ptr_ctrl)
+            if _info is not st_NullClNodeInfo:
+                device_id = st_ComputeNodeInfo_get_device_id(_info)
+            return device_id
+
+        @property
+        def selected_node_id_str(self):
+            node_id_str = None
+            _info = st_ClContextBase_get_selected_node_info(self._ptr_ctrl)
+            if _info is not st_NullClNodeInfo:
+                platform_id = st_ComputeNodeInfo_get_platform_id(_info)
+                device_id = st_ComputeNodeInfo_get_device_id(_info)
+                node_id_str = f"opencl:{platform_id}.{device_id}"
+            return node_id_str
+
+        @property
+        def selected_node_platform(self):
+            node_platform_str = None
+            _info = st_ClContextBase_get_selected_node_info(self._ptr_ctrl)
+            if _info is not st_NullClNodeInfo:
+                node_platform_str = ctypes_str_to_decoded_string(
+                    st_ComputeNodeInfo_get_platform(_info)
+                )
+            return node_platform_str
+
+        @property
+        def selected_node_name(self):
+            node_name = None
+            _info = st_ClContextBase_get_selected_node_info(self._ptr_ctrl)
+            if _info is not st_NullClNodeInfo:
+                node_name = ctypes_str_to_decoded_string(
+                    st_ComputeNodeInfo_get_name(_info)
+                )
+            return node_name
+
+        @property
+        def selected_node_description(self):
+            description = None
+            _info = st_ClContextBase_get_selected_node_info(self._ptr_ctrl)
+            if _info is not st_NullClNodeInfo:
+                description = ctypes_str_to_decoded_string(
+                    st_ComputeNodeInfo_get_description(_info)
+                )
+            return description
+
+        def add_program_file(
+            self, path_to_program, compile_defs, compile=True
+        ):
+            program_id = st_ARCH_ILLEGAL_PROGRAM_ID
+            if self._ptr_ctrl is not st_NullClContextBase:
+                program_id = st_ClContextBase_add_program_file(
+                    self._ptr_ctrl,
+                    string_to_encoded_ctypes_str(path_to_program),
+                    string_to_encoded_ctypes_str(compile_defs),
+                )
+                if compile:
+                    if not self.compile_program(program_id):
+                        raise RuntimeError("Error while compiling program")
+            return program_id
+
+        def compile_program(self, program_id):
+            success = False
+            if (
+                self._ptr_ctrl is not st_NullClContextBase
+                and program_id is not st_ARCH_ILLEGAL_PROGRAM_ID.value
+            ):
+                success = st_ClContextBase_compile_program(
+                    self._ptr_ctrl, st_arch_program_id_t(program_id)
+                )
+            return success
+
+        def is_program_compiled(self, program_id):
+            return (
+                self._ptr_ctrl is not st_NullClContextBase
+                and program_id is not st_ARCH_ILLEGAL_PROGRAM_ID.value
+                and st_ClContextBase_is_program_compiled(
+                    self._ptr_ctrl, st_arch_program_id_t(program_id)
+                )
+            )
+
+        def enable_kernel(self, program_id, kernel_name):
+            kernel_id = st_ARCH_ILLEGAL_KERNEL_ID.value
+            if (
+                self._ptr_ctrl is not st_NullClContextBase
+                and program_id is not st_ARCH_ILLEGAL_PROGRAM_ID.value
+            ):
+                kernel_id = st_ClContextBase_enable_kernel(
+                    self._ptr_ctrl,
+                    string_to_encoded_ctypes_str(kernel_name),
+                    st_arch_program_id_t(program_id),
+                )
+            return kernel_id
+
+        def find_kernel_by_name(self, kernel_name):
+            kernel_id = st_ARCH_ILLEGAL_KERNEL_ID.value
+            if self._ptr_ctrl is not st_NullClContextBase:
+                kernel_id = st_ClContextBase_find_kernel_id_by_name(
+                    self._ptr_ctrl, string_to_encoded_ctypes_str(kernel_name)
+                )
+            return kernel_id
+
+        def program_id_by_kernel_id(self, kernel_id):
+            program_id = st_ARCH_ILLEGAL_PROGRAM_ID.value
+            if self._ptr_ctrl is not st_NullClContextBase and self.has_kernel(
+                kernel_id
+            ):
+                program_id = st_ClContextBase_get_program_id_by_kernel_id(
+                    self._ptr_ctrl, st_arch_kernel_id_t(kernel_id)
+                )
+            return program_id
+
+        def program_compile_report(self, program_id):
+            report = ""
+            if (
+                self._ptr_ctrl is not st_NullClContextBase
+                and program_id != st_ARCH_ILLEGAL_PROGRAM_ID.value
+            ):
+                report = ctypes_str_to_decoded_string(
+                    st_ClContextBase_get_program_compile_report(
+                        self._ptr_ctrl, st_arch_program_id_t(program_id)
+                    )
+                )
+            return report
+
+        def program_compile_options(self, program_id):
+            options = ""
+            if (
+                self._ptr_ctrl is not st_NullClContextBase
+                and program_id != st_ARCH_ILLEGAL_PROGRAM_ID.value
+            ):
+                options = ctypes_str_to_decoded_string(
+                    st_ClContextBase_get_program_compile_options(
+                        self._ptr_ctrl, st_arch_program_id_t(program_id)
+                    )
+                )
+            return options
+
+        def program_source_code(self, program_id):
+            src_code = ""
+            if (
+                self._ptr_ctrl is not st_NullClContextBase
+                and program_id != st_ARCH_ILLEGAL_PROGRAM_ID.value
+            ):
+                src_code = ctypes_str_to_decoded_string(
+                    st_ClContextBase_get_program_source_code(
+                        self._ptr_ctrl, st_arch_program_id_t(program_id)
+                    )
+                )
+            return src_code
+
+        def has_program_file_path(self, program_id):
+            return (
+                self._ptr_ctrl is not st_NullClContextBase
+                and program_id != st_ARCH_ILLEGAL_PROGRAM_ID.value
+                and st_ClContextBase_has_program_file_path(
+                    self._ptr_ctrl, st_arch_program_id_t(program_id)
+                )
+            )
+
+        def program_path_to_file(self, program_id):
+            path_to_program = ""
+            if (
+                self._ptr_ctrl is not st_NullClContextBase
+                and program_id != st_ARCH_ILLEGAL_PROGRAM_ID.value
+            ):
+                path_to_program = ctypes_str_to_decoded_string(
+                    st_ClContextBase_get_program_path_to_file(
+                        self._ptr_ctrl, st_arch_program_id_t(program_id)
+                    )
+                )
+            return path_to_program
+
+        def set_kernel_arg(self, kernel_id, arg_index, arg):
+            if (
+                kernel_id != st_ARCH_ILLEGAL_KERNEL_ID.value
+                and self._ptr_ctrl != st_NullClContextBase
+            ):
+                if isinstance(arg, ClArgument):
+                    st_ClContextBase_assign_kernel_argument(
+                        self._ptr_ctrl,
+                        st_arch_kernel_id_t(kernel_id),
+                        st_arch_size_t(arg_index),
+                        arg.ptr_argument,
+                    )
+                elif isinstance(arg, type(st_ClArgument_p)):
+                    st_ClContextBase_assign_kernel_argument(
+                        self._ptr_ctrl,
+                        st_arch_kernel_id_t(kernel_id),
+                        st_arch_size_t(arg_index),
+                        arg,
+                    )
+                else:
+                    raise ValueError(
+                        "arg expected to be an instance of ClArgument"
+                    )
+            return self
+
+        def set_kernel_arg_value(self, kernel_id, arg_index, val_p, val_size):
+            if (
+                kernel_id != st_ARCH_ILLEGAL_KERNEL_ID.value
+                and isinstance(val_p, type(ct.c_void_p))
+                and val_size > 0
+            ):
+                st_ClContextBase_assign_kernel_argument_value(
+                    self._ptr_ctrl,
+                    st_arch_kernel_id_t(kernel_id),
+                    st_arch_size_t(arg_index),
+                    val_p,
+                    st_arch_size_t(val_size),
+                )
+            return self
+
+        def reset_kernel_args(self, kernel_id, arg_index=None):
+            _kernel_id = st_arch_kernel_id_t(kernel_id)
+            status = st_ARCH_STATUS_GENERAL_FAILURE
+            if arg_index is not None:
+                st_ClContextBase_reset_single_kernel_argument(
+                    self._ptr_ctrl, _kernel_id, st_arch_size_t(arg_index)
+                )
+                status = st_ARCH_STATUS_SUCCESS.value
+            else:
+                st_ClContextBase_reset_kernel_arguments(
+                    self._ptr_ctrl, _kernel_id
+                )
+                status = st_ARCH_STATUS_SUCCESS.value
+            self._last_status = status
+            return self
+
+        def has_kernel(self, kernel_id):
+            return (
+                kernel_id != st_ARCH_ILLEGAL_KERNEL_ID.value
+                and kernel_id
+                < st_ClContextBase_get_num_available_kernels(self._ptr_ctrl)
+            )
+
+        def kernel_local_mem_size(self, kernel_id):
+            return st_ClContextBase_get_kernel_local_mem_size(
+                self._ptr_ctrl, st_arch_kernel_id_t(kernel_id)
+            )
+
+        def num_kernel_args(self, kernel_id):
+            return st_ClContextBase_get_kernel_num_args(
+                self._ptr_ctrl, st_arch_kernel_id_t(kernel_id)
+            )
+
+        def kernel_workgroup_size(self, kernel_id):
+            return st_ClContextBase_get_kernel_work_group_size(
+                self._ptr_ctrl, st_arch_kernel_id_t(kernel_id)
+            )
+
+        def kernel_max_workgroup_size(self, kernel_id):
+            return st_ClContextBase_get_kernel_max_work_group_size(
+                self._ptr_ctrl, st_arch_kernel_id_t(kernel_id)
+            )
+
+        def kernel_preferred_workgroup_size_multiple(self, kernel_id):
+            return st_ClContextBase_get_kernel_preferred_work_group_size_multiple(
+                self._ptr_ctrl, st_arch_kernel_id_t(kernel_id)
+            )
+
+        def argument_of_kernel(self, kernel_id, arg_index):
+            _ptr_arg = st_ClContextBase_get_ptr_kernel_argument(
+                self._ptr_ctrl,
+                st_arch_kernel_id_t(kernel_id),
+                st_arch_size_t(arg_index),
+            )
+            if _ptr_arg != st_NullClArgument:
+                return ClArgument(ext_ptr_arg=_ptr_arg, owns_ptr=False)
+            else:
+                error_msg = f"""
+                "unable to retrieve ClArgument of kernel id={kernel_id},
+                argument idx = {arg_index}
+                """
+                raise ValueError(error_msg)
+                self._last_status = st_ARCH_STATUS_GENERAL_FAILURE.value
+
+        def argument_type_of_kernel(self, kernel_id, arg_index):
+            return st_ClContextBase_get_kernel_argument_type(
+                self._ptr_ctrl,
+                st_arch_kernel_id_t(kernel_id),
+                st_arch_size_t(arg_index),
+            )
+
+        def set_kernel_workgroup_size(self, kernel_id, wgsize):
+            ret = st_ClContextBase_set_kernel_work_group_size(
+                self._ptr_ctrl,
+                st_arch_kernel_id_t(kernel_id),
+                st_arch_kernel_id_t(wgsize),
+            )
+            if not ret:
+                self._last_status = st_ARCH_STATUS_GENERAL_FAILURE.value
+                error_msg = f"""
+                unable to set workgroup size to {wgsize}
+                for kernel id={kernel_id}
+                """
+                raise RuntimeError(error_msg)
+            return self
+
+        def run_kernel(self, kernel_id, num_work_items, work_group_size=None):
+            _kernel_id = st_arch_kernel_id_t(kernel_id)
+            _num_work_items = st_arch_size_t(num_work_items)
+            ret = False
+            if work_group_size is None:
+                ret = st_ClContextBase_run_kernel(
+                    self._ptr_ctrl, _kernel_id, _num_work_items
+                )
+            else:
+                ret = st_ClContextBase_run_kernel_wgsize(
+                    self._ptr_ctrl,
+                    _kernel_id,
+                    _num_work_items,
+                    st_arch_size_t(work_group_size),
+                )
+            if ret:
+                self._last_status = st_ARCH_STATUS_SUCCESS.value
+            else:
+                self._last_status = st_ARCH_STATUS_GENERAL_FAILURE.value
+                error_msg = f"Unable to run OpenCL kernel id={kernel_id}"
+                raise RuntimeError(error_msg)
+            return self
+
+        def num_feature_flags(self):
+            num_feature_flags = 0
+            if self._ptr_ctrl is not st_NullClContextBase:
+                num_feature_flags = st_ClContextBase_num_feature_flags(
+                    self._ptr_ctrl
+                )
+            return num_feature_flags
+
+        def has_feature_flag(self, feature_flag_key):
+            return (
+                self._ptr_ctrl is not st_NullClContextBase
+                and st_ClContextBase_has_feature_flag(
+                    self._ptr_ctrl,
+                    string_to_encoded_ctypes_str(feature_flag_key),
+                )
+            )
+
+        def feature_flag(self, feature_flag_key):
+            feature = None
+            if self._ptr_ctrl is not st_NullClContextBase:
+                feature = ctypes_str_to_decoded_string(
+                    st_ClContextBase_feature_flag(
+                        self._ptr_ctrl,
+                        string_to_encoded_ctypes_str(feature_flag_key),
+                    )
+                )
+            return feature
+
+        def feature_flag_repr(self, feature_flag_key, prefix="-D", sep="="):
+            feature_repr = None
+            _key = string_to_encoded_ctypes_str(feature_flag_key)
+            _prefix = string_to_encoded_ctypes_str(prefix)
+            _sep = string_to_encoded_ctypes_str(sep)
+            if self._ptr_ctrl is not st_NullClContextBase:
+                _requ_capacity = st_ClContextBase_feature_flag_repr_required_capacity(
+                    self._ptr_ctrl, _key, _prefix, _sep,
+                )
+                if _requ_capacity > 0:
+                    _temp_buffer = ct.create_string_buffer(_requ_capacity)
+                    ret = st_ClContextBase_feature_flag_repr_as_cstr(
+                        self._ptr_ctrl,
+                        _temp_buffer,
+                        st_arch_size_t(_requ_capacity),
+                        _key,
+                        _prefix,
+                        _sep,
+                    )
+                    if ret == st_ARCH_STATUS_SUCCESS.value:
+                        feature_repr = ctypes_str_to_decoded_string(
+                            _temp_buffer
+                        )
+            return feature_repr
+
+        def set_feature_flag(self, feature_flag_key, feature_flag_value):
+            if self._ptr_ctrl is not st_NullClContextBase:
+                st_ClContextBase_set_feature_flag(
+                    self._ptr_ctrl,
+                    string_to_encoded_ctypes_str(feature_flag_key),
+                    string_to_encoded_ctypes_str(feature_flag_value),
+                )
+
+        def default_compile_options(self):
+            options = None
+            if self._ptr_ctrl is not st_NullClContextBase:
+                options = ctypes_str_to_decoded_string(
+                    st_ClContextBase_default_compile_options(self._ptr_ctrl)
+                )
+            return options
+
+        def set_default_compile_options(self, new_compile_options):
+            if self._ptr_ctrl is not st_NullClContextBase:
+                st_ClContextBase_set_default_compile_options(
+                    self._ptr_ctrl,
+                    string_to_encoded_ctypes_str(new_compile_options),
+                )
+
+    # -------------------------------------------------------------------------
+
+    class ClArgument(object):
+        def __init__(
+            self,
+            buffer=None,
+            ctrl=None,
+            ext_ptr_arg=st_NullClArgument,
+            owns_ptr=True,
+        ):
+            self._ptr_arg = st_NullClArgument
+            self._owns_arg = True
+            self._last_status = st_ARCH_STATUS_SUCCESS
+
+        def __del__(self):
+            if self._owns_arg and self._ptr_arg != st_NullClArgument:
+                st_ClArgument_delete(self._ptr_arg)
+            self._ptr_arg = st_NullClArgument
+
+        @property
+        def pointer(self):
+            return self._ptr_arg
+
+        @property
+        def owns_argument(self):
+            return self._owns_arg
+
+        @property
+        def controller(self):
+            _ptr_ctrl = st_ClArgument_get_ptr_to_context(self._ptr_arg)
+            return ClController(ext_ptr_ctrl=_ptr_ctrl, owns_ptr=False)
+
+        @property
+        def uses_buffer(self):
+            return st_ClArgument_uses_cobj_buffer(self._ptr_arg)
+
+        @property
+        def ptr_buffer(self):
+            _ptr_buffer = st_NullBuffer
+            if st_ClArgument_uses_cobj_buffer(self._ptr_arg):
+                _ptr_buffer = st_ClArgument_get_ptr_cobj_buffer(self._ptr_arg)
+            if _ptr_buffer is st_NullBuffer:
+                raise RuntimeError("Unable to retrieve buffer from argument")
+            return Buffer(ptr_ext_buffer=_ptr_buffer, owns_ptr=False)
+
+        @property
+        def size(self):
+            return st_ClArgument_get_argument_size(self._ptr_arg)
+
+        @property
+        def capacity(self):
+            return st_ClArgument_get_argument_size(self._ptr_arg)
+
+        def send(
+            self,
+            buffer=st_NullBuffer,
+            remap_buffer=True,
+            ptr_raw_arg_begin=st_Null,
+            raw_arg_size=None,
+        ):
+            status = st_ARCH_STATUS_GENERAL_FAILURE.value
+            ptr_buffer = st_NullBuffer
+            if buffer is not None and buffer is not st_NullBuffer:
+                if isinstance(buffer, Buffer):
+                    ptr_buffer = buffer.pointer
+                else:
+                    ptr_buffer = buffer
+
+            if ptr_buffer is not st_NullBuffer:
+                if remap_buffer:
+                    if st_ClArgument_write(self._ptr_argument, ptr_buffer):
+                        status = st_ARCH_STATUS_SUCCESS.value
+                else:
+                    raise ValueError(
+                        "sending with remap_buffer=False not yet implemented"
+                    )
+            elif raw_arg_size is not None:
+                raise ValueError(
+                    "sending raw-memory based ClArguments not yet implemented"
+                )
+
+            self._last_status = status
+            raise_error_if_status_not_success(
+                self._last_status,
+                "unsuccessful send op; status:{0}".format(status),
+            )
+
+            return self
+
+        def send_buffer(self, buffer):
+            return self.send(buffer=buffer, remap_buffer=True)
+
+        def send_buffer_without_remap(self, buffer):
+            return self.send(buffer=buffer, remap_buffer=False)
+
+        def send_raw_argument(self, ptr_raw_arg_begin, raw_arg_size):
+            return self.send(
+                ptr_raw_arg_begin=ptr_raw_arg_begin, raw_arg_size=raw_arg_size
+            )
+
+    def receive(
+        self,
+        buffer=st_NullBuffer,
+        remap_buffer=True,
+        ptr_raw_arg_begin=st_Null,
+        raw_arg_capacity=None,
+    ):
+        ptr_buffer = st_NullBuffer
+        status = st_ARCH_STATUS_GENERAL_FAILURE.value
+        if buffer is not None and buffer is not st_NullBuffer:
+            if isinstance(buffer, Buffer):
+                ptr_buffer = buffer.pointer
+            elif isinstance(buffer, CBuffer):
+                _buffer = Buffer(cbuffer=buffer)
+                ptr_buffer = _buffer.pointer
+            else:
+                ptr_buffer = buffer
+
+        if ptr_buffer != st_NullBuffer:
+            if remap_buffer:
+                status = st_ClArgument_read(self._ptr_arg, ptr_buffer)
+            else:
+                raise RuntimeError(
+                    "receiving with remap_buffer=False not yet implemented"
+                )
+        elif raw_arg_capacity is not None:
+            raise RuntimeError(
+                "receiving raw-memory based ClArguments not yet implemented"
+            )
+
+        raise_error_if_status_not_success(
+            status, "unsuccessful receive op; status:{0}".format(status)
+        )
+        self._last_status = status
+
+        return self
+
+    def receive_buffer(self, buffer):
+        return self.receive(buffer=buffer, remap_buffer=True)
+
+    def receive_buffer_without_remap(self, buffer):
+        return self.receive(buffer=buffer, remap_buffer=False)
+
+    def receive_raw_argument(self, ptr_raw_arg_begin, raw_arg_capacity):
+        return self.receive(
+            ptr_raw_arg_begin=ptr_raw_arg_begin,
+            raw_arg_capacity=raw_arg_capacity,
+        )
+
+
+else:
+
+    class ClNodeId(object):
+        pass
+
+    class ClController(object):
+        @staticmethod
+        def NUM_ALL_NODES():
+            raise RuntimeError("OpenCL module disabled, no nodes present")
+            return 0
+
+        @staticmethod
+        def PRINT_ALL_NODES():
+            raise RuntimeError("OpenCL module disabled, no nodes to print")
+
+        @staticmethod
+        def NUM_AVAILABLE_NODES(filter_str=None, env_var_name=None):
+            raise RuntimeError("OpenCL module disabled, no nodes available")
+            return 0
+
+        @staticmethod
+        def PRINT_AVAILABLE_NODES(filter_str=None, env_var_name=None):
+            raise RuntimeError("OpenCL module disabled, no nodes to print")
+
+        @staticmethod
+        def GET_AVAILABLE_NODES(
+            filter_str=None, env_var_name=None, skip_first_num_nodes=0
+        ):
+            raise RuntimeError("OpenCL module disabled, no nodes available")
+            return []
+
+        @staticmethod
+        def GET_AVAILABLE_NODE_ID_STRS(
+            filter_str=None,
+            env_var_name=None,
+            skip_first_num_nodes=0,
+            node_id_str_fmt=None,
+        ):
+            raise RuntimeError("OpenCL module disabled, no nodes available")
+            return []
+
+    class ClArgument(object):
+        pass
diff --git a/python/sixtracklib/particles.py b/python/sixtracklib/particles.py
index 5926b1b6..7311949c 100644
--- a/python/sixtracklib/particles.py
+++ b/python/sixtracklib/particles.py
@@ -6,78 +6,210 @@ class Particles(CObject):
     pmass = 938.2720813e6
 
     def _set_p0c(self):
-        energy0 = np.sqrt(self.p0c**2 + self.mass0**2)
+        energy0 = np.sqrt(self.p0c ** 2 + self.mass0 ** 2)
         self.beta0 = self.p0c / energy0
         self.gamma0 = energy0 / self.mass0
 
     def _set_delta(self):
-        rep = np.sqrt(self.delta**2 + 2 * self.delta + 1 / self.beta0**2)
+        rep = np.sqrt(self.delta ** 2 + 2 * self.delta + 1 / self.beta0 ** 2)
         irpp = 1 + self.delta
         self.rpp = 1 / irpp
         beta = irpp / rep
         self.rvv = beta / self.beta0
-        self.psigma = np.sqrt(self.delta**2 + 2 * self.delta +
-                              1 / self.beta0**2) / self.beta0 - 1 / self.beta0**2
+        self.psigma = (
+            np.sqrt(self.delta ** 2 + 2 * self.delta + 1 / self.beta0 ** 2)
+            / self.beta0
+            - 1 / self.beta0 ** 2
+        )
 
     _typeid = 1
-    num_particles = CField(0, 'int64', const=True)
-    q0 = CField(1, 'real', length='num_particles',
-                default=0.0, pointer=True, alignment=8)
-    mass0 = CField(2, 'real', length='num_particles',
-                   default=pmass, pointer=True, alignment=8)
-    beta0 = CField(3, 'real', length='num_particles',
-                   default=1.0, pointer=True, alignment=8)
-    gamma0 = CField(4, 'real', length='num_particles',
-                    default=1.0, pointer=True, alignment=8)
-    p0c = CField(5, 'real', length='num_particles',
-                 default=1.0, pointer=True, alignment=8, setter=_set_p0c)
-    s = CField(6, 'real', length='num_particles',
-               default=0.0, pointer=True, alignment=8)
-    x = CField(7, 'real', length='num_particles',
-               default=0.0, pointer=True, alignment=8)
-    y = CField(8, 'real', length='num_particles',
-               default=0.0, pointer=True, alignment=8)
-    px = CField(9, 'real', length='num_particles',
-                default=0.0, pointer=True, alignment=8)
-    py = CField(10, 'real', length='num_particles',
-                default=0.0, pointer=True, alignment=8)
-    zeta = CField(11, 'real', length='num_particles',
-                  default=0.0, pointer=True, alignment=8)
-    psigma = CField(12, 'real', length='num_particles',
-                    default=0.0, pointer=True, alignment=8)
-    delta = CField(13, 'real', length='num_particles',
-                   default=0.0, pointer=True, alignment=8, setter=_set_delta)
-    rpp = CField(14, 'real', length='num_particles',
-                 default=1.0, pointer=True, alignment=8)
-    rvv = CField(15, 'real', length='num_particles',
-                 default=1.0, pointer=True, alignment=8)
-    chi = CField(16, 'real', length='num_particles',
-                 default=1.0, pointer=True, alignment=8)
-    charge_ratio = CField(17, 'real', length='num_particles',
-                          default=1.0, pointer=True, alignment=8)
-    particle_id = CField(18, 'int64', length='num_particles',
-                         default=0, pointer=True, alignment=8)
-    at_element = CField(19, 'int64', length='num_particles',
-                        default=0, pointer=True, alignment=8)
-    at_turn = CField(20, 'int64', length='num_particles',
-                     default=0, pointer=True, alignment=8)
-    state = CField(21, 'int64', length='num_particles',
-                   default=1, pointer=True, alignment=8)
+    num_particles = CField(0, "int64", const=True, alignment=8)
+    q0 = CField(
+        1,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+    )
+    mass0 = CField(
+        2,
+        "real",
+        length="num_particles",
+        default=pmass,
+        pointer=True,
+        alignment=8,
+    )
+    beta0 = CField(
+        3,
+        "real",
+        length="num_particles",
+        default=1.0,
+        pointer=True,
+        alignment=8,
+    )
+    gamma0 = CField(
+        4,
+        "real",
+        length="num_particles",
+        default=1.0,
+        pointer=True,
+        alignment=8,
+    )
+    p0c = CField(
+        5,
+        "real",
+        length="num_particles",
+        default=1.0,
+        pointer=True,
+        alignment=8,
+        setter=_set_p0c,
+    )
+    s = CField(
+        6,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+    )
+    x = CField(
+        7,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+    )
+    y = CField(
+        8,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+    )
+    px = CField(
+        9,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+    )
+    py = CField(
+        10,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+    )
+    zeta = CField(
+        11,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+    )
+    psigma = CField(
+        12,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+    )
+    delta = CField(
+        13,
+        "real",
+        length="num_particles",
+        default=0.0,
+        pointer=True,
+        alignment=8,
+        setter=_set_delta,
+    )
+    rpp = CField(
+        14,
+        "real",
+        length="num_particles",
+        default=1.0,
+        pointer=True,
+        alignment=8,
+    )
+    rvv = CField(
+        15,
+        "real",
+        length="num_particles",
+        default=1.0,
+        pointer=True,
+        alignment=8,
+    )
+    chi = CField(
+        16,
+        "real",
+        length="num_particles",
+        default=1.0,
+        pointer=True,
+        alignment=8,
+    )
+    charge_ratio = CField(
+        17,
+        "real",
+        length="num_particles",
+        default=1.0,
+        pointer=True,
+        alignment=8,
+    )
+    particle_id = CField(
+        18,
+        "int64",
+        length="num_particles",
+        default=0,
+        pointer=True,
+        alignment=8,
+    )
+    at_element = CField(
+        19,
+        "int64",
+        length="num_particles",
+        default=0,
+        pointer=True,
+        alignment=8,
+    )
+    at_turn = CField(
+        20,
+        "int64",
+        length="num_particles",
+        default=0,
+        pointer=True,
+        alignment=8,
+    )
+    state = CField(
+        21,
+        "int64",
+        length="num_particles",
+        default=1,
+        pointer=True,
+        alignment=8,
+    )
 
     @classmethod
-    def from_ref(cls, num_particles=1, mass0=pmass,
-                 p0c=1e9, q0=1):
-        return cls(num_particles=num_particles,
-                   particle_id=np.arange(num_particles),
-                   ).set_reference(mass0=mass0, p0c=p0c, q0=q0)
+    def from_ref(cls, num_particles=1, mass0=pmass, p0c=1e9, q0=1):
+        return cls(
+            num_particles=num_particles, particle_id=np.arange(num_particles),
+        ).set_reference(mass0=mass0, p0c=p0c, q0=q0)
 
     sigma = property(lambda self: (self.beta0 / self.beta) * self.zeta)
     beta = property(lambda p: (1 + p.delta) / (1 / p.beta0 + p.ptau))
 
     @property
     def ptau(self):
-        return np.sqrt(self.delta**2 + 2 * self.delta +
-                       1 / self.beta0**2) - 1 / self.beta0
+        return (
+            np.sqrt(self.delta ** 2 + 2 * self.delta + 1 / self.beta0 ** 2)
+            - 1 / self.beta0
+        )
 
     def set_reference(self, p0c=7e12, mass0=pmass, q0=1):
         self.q0 = q0
@@ -86,7 +218,7 @@ def set_reference(self, p0c=7e12, mass0=pmass, q0=1):
         return self
 
     def from_pysixtrack(self, inp, particle_index):
-        assert(particle_index < self.num_particles)
+        assert particle_index < self.num_particles
         self.q0[particle_index] = inp.q0
         self.mass0[particle_index] = inp.mass0
         self.beta0[particle_index] = inp.beta0
@@ -104,15 +236,16 @@ def from_pysixtrack(self, inp, particle_index):
         self.rvv[particle_index] = inp.rvv
         self.chi[particle_index] = inp.chi
         self.charge_ratio[particle_index] = inp.qratio
-        self.particle_id[particle_index] = \
+        self.particle_id[particle_index] = (
             inp.partid is not None and inp.partid or particle_index
+        )
         self.at_element[particle_index] = inp.elemid
         self.at_turn[particle_index] = inp.turn
         self.state[particle_index] = inp.state
         return
 
     def to_pysixtrack(self, other, particle_index):
-        assert(particle_index < self.num_particles)
+        assert particle_index < self.num_particles
         other._update_coordinates = False
         other.q0 = self.q0[particle_index]
         other.mass0 = self.mass0[particle_index]
@@ -162,17 +295,38 @@ def makeCopy(orig, cbuffer=None):
         particle_id=orig.particle_id,
         at_element=orig.at_element,
         at_turn=orig.at_turn,
-        state=orig.state)
+        state=orig.state,
+    )
 
     return p
 
 
 def calcParticlesDifference(lhs, rhs, cbuffer=None):
-    assert(lhs.num_particles == rhs.num_particles)
+    assert lhs.num_particles == rhs.num_particles
     diff = Particles(num_particles=lhs.num_particles, cbuffer=cbuffer)
-    keys = ['q0', 'mass0', 'beta0', 'gamma0', 'p0c', 's', 'x', 'y', 'px', 'py',
-            'zeta', 'psigma', 'delta', 'rpp', 'rvv', 'chi', 'charge_ratio',
-            'particle_id', 'at_element', 'at_turn', 'state']
+    keys = [
+        "q0",
+        "mass0",
+        "beta0",
+        "gamma0",
+        "p0c",
+        "s",
+        "x",
+        "y",
+        "px",
+        "py",
+        "zeta",
+        "psigma",
+        "delta",
+        "rpp",
+        "rvv",
+        "chi",
+        "charge_ratio",
+        "particle_id",
+        "at_element",
+        "at_turn",
+        "state",
+    ]
 
     for k in keys:
         try:
@@ -190,8 +344,24 @@ def compareParticlesDifference(lhs, rhs, abs_treshold=None):
         num_particles = lhs.num_particles
 
         real_keys = [
-            'q0', 'mass0', 'beta0', 'gamma0', 'p0c', 's', 'x', 'y', 'px', 'py',
-            'zeta', 'psigma', 'delta', 'rpp', 'rvv', 'chi', 'charge_ratio']
+            "q0",
+            "mass0",
+            "beta0",
+            "gamma0",
+            "p0c",
+            "s",
+            "x",
+            "y",
+            "px",
+            "py",
+            "zeta",
+            "psigma",
+            "delta",
+            "rpp",
+            "rvv",
+            "chi",
+            "charge_ratio",
+        ]
 
         cmp_result = 0
 
@@ -221,7 +391,7 @@ def compareParticlesDifference(lhs, rhs, abs_treshold=None):
                 break
 
         if cmp_result == 0:
-            int_keys = ['particle_id', 'at_element', 'at_turn', 'state']
+            int_keys = ["particle_id", "at_element", "at_turn", "state"]
 
             for k in int_keys:
                 lhs_arg = getattr(lhs, k)
@@ -245,7 +415,7 @@ def compareParticlesDifference(lhs, rhs, abs_treshold=None):
 
 
 class ParticlesSet(object):
-    element_types = {'Particles': Particles}
+    element_types = {"Particles": Particles}
 
     @property
     def particles(self):
@@ -274,6 +444,7 @@ def fromSixDump101(cls, input_folder, st_dump_file, **kwargs):
 
         import sixtracktools
         import pysixtrack
+
         six = sixtracktools.SixInput(input_folder)
         line, rest, iconv = six.expand_struct(convert=pysixtrack.element_types)
 
@@ -283,10 +454,10 @@ def fromSixDump101(cls, input_folder, st_dump_file, **kwargs):
         num_belem = int(len(line))
         num_dumps = int(len(sixdump.particles))
 
-        assert(num_iconv > 0)
-        assert(num_belem > iconv[num_iconv - 1])
-        assert(num_dumps >= num_iconv)
-        assert((num_dumps % num_iconv) == 0)
+        assert num_iconv > 0
+        assert num_belem > iconv[num_iconv - 1]
+        assert num_dumps >= num_iconv
+        assert (num_dumps % num_iconv) == 0
 
         num_particles = int(num_dumps / num_iconv)
 
@@ -294,18 +465,19 @@ def fromSixDump101(cls, input_folder, st_dump_file, **kwargs):
 
         for ii in range(num_iconv):
             elem_id = iconv[ii]
-            assert(elem_id < num_belem)
+            assert elem_id < num_belem
 
             p = self.Particles(num_particles=num_particles)
 
-            assert(p.num_particles == num_particles)
-            assert(len(p.q0) == num_particles)
+            assert p.num_particles == num_particles
+            assert len(p.q0) == num_particles
 
             for jj in range(num_particles):
                 kk = num_particles * ii + jj
-                assert(kk < num_dumps)
+                assert kk < num_dumps
                 p.from_pysixtrack(
-                    pysixtrack.Particles(**sixdump[kk].get_minimal_beam()), jj)
+                    pysixtrack.Particles(**sixdump[kk].get_minimal_beam()), jj
+                )
                 p.state[jj] = 1
                 p.at_element[jj] = elem_id
 
@@ -313,3 +485,29 @@ def fromSixDump101(cls, input_folder, st_dump_file, **kwargs):
 
     def to_file(self, filename):
         self.cbuffer.tofile(filename)
+
+
+class ParticlesAddr(CObject):
+    _typeid = 512
+    num_particles = CField(0, "int64", default=0, alignment=8)
+    q0 = CField(1, "uint64", default=0, alignment=8)
+    mass0 = CField(2, "uint64", default=0, alignment=8)
+    beta0 = CField(3, "uint64", default=0, alignment=8)
+    gamma0 = CField(4, "uint64", default=0, alignment=8)
+    p0c = CField(5, "uint64", default=0, alignment=8)
+    s = CField(6, "uint64", default=0, alignment=8)
+    x = CField(7, "uint64", default=0, alignment=8)
+    y = CField(8, "uint64", default=0, alignment=8)
+    px = CField(9, "uint64", default=0, alignment=8)
+    py = CField(10, "uint64", default=0, alignment=8)
+    zeta = CField(11, "uint64", default=0, alignment=8)
+    psigma = CField(12, "uint64", default=0, alignment=8)
+    delta = CField(13, "uint64", default=0, alignment=8)
+    rpp = CField(14, "uint64", default=0, alignment=8)
+    rvv = CField(15, "uint64", default=0, alignment=8)
+    chi = CField(16, "uint64", default=0, alignment=8)
+    charge_ratio = CField(17, "uint64", default=0, alignment=8)
+    particle_id = CField(18, "uint64", default=0, alignment=8)
+    at_element = CField(19, "uint64", default=0, alignment=8)
+    at_turn = CField(20, "uint64", default=0, alignment=8)
+    state = CField(21, "uint64", default=0, alignment=8)
diff --git a/python/sixtracklib/pysixtrack_helper.py b/python/sixtracklib/pysixtrack_helper.py
index 33f1a278..21d963cc 100644
--- a/python/sixtracklib/pysixtrack_helper.py
+++ b/python/sixtracklib/pysixtrack_helper.py
@@ -1,24 +1,43 @@
 import importlib
 from importlib import util
 
-if importlib.util.find_spec('pysixtrack') is not None:
+if importlib.util.find_spec("pysixtrack") is not None:
     from pysixtrack import elements as pysixelem
     import numpy as np
     from cobjects import CBuffer, CObject, CField
-    from .beam_elements import \
-        Drift, DriftExact, Multipole, Cavity, XYShift, SRotation, \
-        BeamBeam4D, BeamMonitor
+    from .beam_elements import (
+        Drift,
+        DriftExact,
+        Multipole,
+        Cavity,
+        XYShift,
+        SRotation,
+        BeamBeam4D,
+        BeamMonitor,
+    )
 
     class BeamElementConverter(object):
         _type_id_to_elem_map = {
-            2: Drift, 3: DriftExact, 4: Multipole, 5: Cavity, 6: XYShift,
-            7: SRotation, 8: BeamBeam4D,  # 9:BeamBeam6D,
-            10: BeamMonitor}
+            2: Drift,
+            3: DriftExact,
+            4: Multipole,
+            5: Cavity,
+            6: XYShift,
+            7: SRotation,
+            8: BeamBeam4D,  # 9:BeamBeam6D,
+            10: BeamMonitor,
+        }
 
         _pysixtrack_to_type_id_map = {
-            'Drift': 2, 'DriftExact': 3, 'Multipole': 4, 'Cavity': 5,
-            'XYShift': 6, 'SRotation': 7, 'BeamBeam4D': 8,  # 'BeamBeam6D': 9,
-            'BeamMonitor': 10, }
+            "Drift": 2,
+            "DriftExact": 3,
+            "Multipole": 4,
+            "Cavity": 5,
+            "XYShift": 6,
+            "SRotation": 7,
+            "BeamBeam4D": 8,  # 'BeamBeam6D': 9,
+            "BeamMonitor": 10,
+        }
 
         @staticmethod
         def get_elemtype(type_id):
@@ -26,8 +45,10 @@ def get_elemtype(type_id):
 
         @classmethod
         def get_typeid(cls):
-            inv_map = {v: k for k, v in
-                       BeamElementConverter._type_id_to_elem_map.items()}
+            inv_map = {
+                v: k
+                for k, v in BeamElementConverter._type_id_to_elem_map.items()
+            }
             return inv_map.get(cls, None)
 
         @staticmethod
@@ -39,9 +60,13 @@ def to_pysixtrack(elem):
             except AttributeError:
                 type_id = None
 
-            cls = type_id is not None and \
-                BeamElementConverter._type_id_to_elem_map.get(
-                    type_id, None) or None
+            cls = (
+                type_id is not None
+                and BeamElementConverter._type_id_to_elem_map.get(
+                    type_id, None
+                )
+                or None
+            )
 
             if cls is not None:
                 if type_id == 2:
@@ -50,34 +75,48 @@ def to_pysixtrack(elem):
                     pysixtrack_elem = pysixelem.DriftExact(length=elem.length)
                 elif type_id == 4:
                     pysixtrack_elem = pysixelem.Multipole(
-                        knl=elem.knl, ksl=elem.ksl,
-                        hxl=elem.hxl, hyl=elem.hyl, length=elem.length)
+                        knl=elem.knl,
+                        ksl=elem.ksl,
+                        hxl=elem.hxl,
+                        hyl=elem.hyl,
+                        length=elem.length,
+                    )
                 elif type_id == 5:
                     pysixtrack_elem = pysixelem.Cavity(
-                        voltage=elem.voltage, frequency=elem.frequency,
-                        lag=elem.lag)
+                        voltage=elem.voltage,
+                        frequency=elem.frequency,
+                        lag=elem.lag,
+                    )
                 elif type_id == 6:
                     pysixtrack_elem = pysixelem.XYShift(dx=elem.dx, dy=elem.dy)
                 elif type_id == 7:
                     pysixtrack_elem = pysixelem.SRotation(angle=elem.angle_deg)
                 elif type_id == 8:
                     pysixtrack_elem = pysixelem.BeamBeam4D(
-                        q_part=elem.q_part, N_part=elem.N_part,
-                        sigma_x=elem.sigma_x, sigma_y=elem.sigma_y,
+                        q_part=elem.q_part,
+                        N_part=elem.N_part,
+                        sigma_x=elem.sigma_x,
+                        sigma_y=elem.sigma_y,
                         beta_s=elem.beta_s,
                         min_sigma_diff=elem.min_sigma_diff,
-                        Delta_x=elem.Delta_x, Delta_y=elem.Delta_y,
-                        Dpx_sub=elem.Dpx_sub, Dpy_sub=elem.Dpy_sub,
-                        enabled=elem.enabled)
+                        Delta_x=elem.Delta_x,
+                        Delta_y=elem.Delta_y,
+                        Dpx_sub=elem.Dpx_sub,
+                        Dpy_sub=elem.Dpy_sub,
+                        enabled=elem.enabled,
+                    )
                 # elif type_id == 9:
-                    #pysixtrack_elem = pysixelem.BeamBeam6D()
+                # pysixtrack_elem = pysixelem.BeamBeam6D()
                 elif type_id == 10:
                     pysixtrack_elem = pysixelem.BeamMonitor(
-                        num_stores=elem.num_stores, start=elem.start,
-                        skip=elem.skip, max_particle_id=elem.max_particle_id,
+                        num_stores=elem.num_stores,
+                        start=elem.start,
+                        skip=elem.skip,
+                        max_particle_id=elem.max_particle_id,
                         min_particle_id=elem.min_particle_id,
                         is_rolling=elem.is_rolling,
-                        is_turn_ordered=elem.is_turn_ordered,)
+                        is_turn_ordered=elem.is_turn_ordered,
+                    )
 
             return pysixtrack_elem
 
@@ -87,12 +126,16 @@ def from_pysixtrack(elem, cbuffer=None):
 
             if elem_type in BeamElementConverter._pysixtrack_to_type_id_map:
                 type_id = BeamElementConverter._pysixtrack_to_type_id_map[
-                    elem_type]
+                    elem_type
+                ]
                 if type_id in BeamElementConverter._type_id_to_elem_map:
                     cls = BeamElementConverter._type_id_to_elem_map[type_id]
                     return cls(cbuffer=cbuffer, **elem.as_dict())
 
             return None
+
+
 else:
+
     class BeamElementConverter(object):
         pass
diff --git a/python/sixtracklib/sc_line_density.py b/python/sixtracklib/sc_line_density.py
new file mode 100644
index 00000000..965c9ce9
--- /dev/null
+++ b/python/sixtracklib/sc_line_density.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import numpy as np
+import ctypes as ct
+from cobjects import CBuffer, CObject, CField
+
+from .trackjob import TrackJob
+from .cuda import CudaTrackJob
+from .beam_elements import Elements, SCInterpolatedProfile
+from .buffer import AssignAddressItem, get_cbuffer_from_obj, Buffer
+from .stcommon import (
+    st_ARCH_STATUS_SUCCESS,
+    st_ARCH_ILLEGAL_BUFFER_ID,
+    st_ARCH_BEAM_ELEMENTS_BUFFER_ID,
+    st_LineDensityProfileData_p,
+    st_LineDensityProfileData_type_id,
+    st_NullLineDensityProfileData,
+    st_NullSCInterpolatedProfile,
+    st_SCInterpolatedProfile_type_id,
+    st_SCInterpolatedProfile_interpol_data_addr_offset,
+    st_LineDensityProfileData_values_offset,
+    st_LineDensityProfileData_derivatives_offset,
+    st_LineDensityProfileData_prepare_interpolation,
+    st_LineDensityProfileData_interpolate_value,
+    st_LineDensityProfileData_interpolate_1st_derivative,
+    st_LineDensityProfileData_interpolate_2nd_derivative,
+)
+
+
+class LineDensityProfileData(CObject):
+    _typeid = st_LineDensityProfileData_type_id()
+
+    INTERPOL_LINEAR = 0
+    INTERPOL_CUBIC = 1
+    INTERPOL_NONE = 255
+
+    method = CField(0, "uint64", default=0)
+    capacity = CField(1, "int64", const=True, default=2)
+    values = CField(2, "real", default=0.0, pointer=True, length="capacity")
+    derivatives = CField(
+        3, "real", default=0.0, pointer=True, length="capacity"
+    )
+    z0 = CField(4, "real", default=0.0)
+    dz = CField(5, "real", default=1.0)
+    num_values = CField(6, "int64", default=0)
+
+    def __init__(self, method=None, capacity=None, num_values=None, **kwargs):
+        if method is not None and isinstance(method, str):
+            method_str = method.lower().strip()
+            if method_str == "linear":
+                method = self.INTERPOL_LINEAR
+            elif method_str == "cubic":
+                method = self.INTERPOL_CUBIC
+            else:
+                method = self.INTERPOL_NONE
+            kwargs["method"] = method
+
+        if capacity is not None or num_values is not None:
+            if capacity is None:
+                capacity = 1
+            if num_values is None:
+                num_values = capacity
+            if num_values > capacity:
+                capacity = num_values
+
+            kwargs["capacity"] = capacity
+            kwargs["num_values"] = num_values
+
+        super().__init__(**kwargs)
+
+    @staticmethod
+    def ptr_offset():
+        return 0
+
+    @property
+    def values_offset(self):
+        _ptr = ct.cast(int(self._get_address()), st_LineDensityProfileData_p)
+        return st_LineDensityProfileData_values_offset(_ptr)
+
+    @property
+    def derivatives_offset(self):
+        _ptr = ct.cast(int(self._get_address()), st_LineDensityProfileData_p)
+        return st_LineDensityProfileData_derivatives_offset(_ptr)
+
+    def prepare_interpolation(self):
+        _ptr = ct.cast(int(self._get_address()), st_LineDensityProfileData_p)
+        if (
+            st_ARCH_STATUS_SUCCESS.value
+            != st_LineDensityProfileData_prepare_interpolation(_ptr)
+        ):
+            raise RuntimeError(
+                "unable to calculate derivaties for interpolation"
+            )
+
+    def interpol(self, z):
+        _ptr = ct.cast(int(self._get_address()), st_LineDensityProfileData_p)
+        return st_LineDensityProfileData_interpolate_value(_ptr, ct.c_double(z))
+
+    def interpol_1st_deriv(self, z):
+        _ptr = ct.cast(int(self._get_address()), st_LineDensityProfileData_p)
+        return st_LineDensityProfileData_interpolate_1st_derivative(
+            _ptr, ct.c_double(z)
+        )
+
+    def interpol_2nd_deriv(self, z):
+        _ptr = ct.cast(int(self._get_address()), st_LineDensityProfileData_p)
+        return st_LineDensityProfileData_interpolate_2nd_derivative(
+            _ptr, ct.c_double(z)
+        )
+
+
+def LineDensityProfileData_create_buffer_assignment(
+    track_job, be_sc_index, interpol_buffer_id, lp_data_index
+):
+    assert isinstance(track_job, TrackJob) or isinstance(
+        track_job, CudaTrackJob
+    )
+    assert interpol_buffer_id != st_ARCH_ILLEGAL_BUFFER_ID.value
+    assert track_job.min_stored_buffer_id <= interpol_buffer_id
+    assert track_job.max_stored_buffer_id >= interpol_buffer_id
+    assert (
+        track_job.stored_buffer(interpol_buffer_id).num_objects > lp_data_index
+    )
+
+    dest_buffer_id = st_ARCH_BEAM_ELEMENTS_BUFFER_ID.value
+    src_buffer_id = interpol_buffer_id
+
+    prev_num_assign_items = track_job.num_assign_items(
+        dest_buffer_id=dest_buffer_id, src_buffer_id=src_buffer_id
+    )
+
+    _ptr_item = track_job.add_assign_address_item(
+        dest_elem_type_id=st_SCInterpolatedProfile_type_id(),
+        dest_buffer_id=dest_buffer_id,
+        dest_elem_index=be_sc_index,
+        dest_pointer_offset=st_SCInterpolatedProfile_interpol_data_addr_offset(
+            st_NullSCInterpolatedProfile
+        ),
+        src_elem_type_id=st_LineDensityProfileData_type_id(),
+        src_buffer_id=src_buffer_id,
+        src_elem_index=lp_data_index,
+        src_pointer_offset=LineDensityProfileData.ptr_offset(),
+    )
+
+    return bool(
+        prev_num_assign_items
+        < track_job.num_assign_items(
+            dest_buffer_id=dest_buffer_id, src_buffer_id=src_buffer_id
+        )
+    )
diff --git a/python/sixtracklib/stcommon.py b/python/sixtracklib/stcommon.py
index 99913c8b..87d8fe8a 100644
--- a/python/sixtracklib/stcommon.py
+++ b/python/sixtracklib/stcommon.py
@@ -7,20 +7,62 @@
 
 sixtracklib = ct.CDLL(stconf.SHARED_LIB)
 
-# C-API Types
+# Low-level C-API Types:
 
 st_Null = ct.cast(0, ct.c_void_p)
 st_NullChar = ct.cast(0, ct.c_char_p)
+st_char_pp = ct.POINTER(ct.c_char_p)
 
-st_Context_p = ct.c_void_p
 st_uint64_p = ct.POINTER(ct.c_uint64)
 st_uchar_p = ct.POINTER(ct.c_ubyte)
 st_const_uchar_p = ct.POINTER(ct.c_ubyte)
 
-st_NullUChar = ct.cast(0, st_uchar_p)
-
 st_double_p = ct.POINTER(ct.c_double)
 st_int64_p = ct.POINTER(ct.c_int64)
+
+st_NullUChar = ct.cast(0, st_uchar_p)
+
+# Helper functions for handling strings between Python and CTypes / C99:
+
+
+def string_to_encoded_ctypes_str(s, encoding="utf-8", strip=True):
+    if s is not None:
+        if strip:
+            s = s.strip()
+        _temp_str = s.encode(encoding)
+        return ct.c_char_p(_temp_str)
+    else:
+        return None
+
+
+def ctypes_str_to_decoded_string(bstr, encoding="utf-8", strip=True):
+    _bstr_bytes = None
+    if bstr is not None:
+        if isinstance(bstr, ct.Array):
+            _bstr_bytes = bytes(bstr.value)
+        elif isinstance(bstr, bytes):
+            _bstr_bytes = bstr
+        else:
+            raise RuntimeError(
+                f"""
+                Illegal type for parameter bstr {type(bstr)}, required
+                ctypes.Array or bytes
+                """
+            )
+    if _bstr_bytes is not None:
+        if b"\0" in _bstr_bytes:
+            _bstr_bytes = _bstr_bytes.split(b"\0", 1)[0]
+        if strip:
+            _bstr_bytes = _bstr_bytes.strip()
+        return _bstr_bytes.decode(encoding)
+    else:
+        return b"".decode(encoding)
+
+
+# SixTrackLib C-API Types:
+
+st_Context_p = ct.c_void_p
+
 st_buffer_size_t = ct.c_uint64
 st_buffer_size_p = ct.POINTER(st_buffer_size_t)
 
@@ -31,20 +73,55 @@
 st_ARCH_STATUS_SUCCESS = st_arch_status_t(0)
 st_ARCH_STATUS_GENERAL_FAILURE = st_arch_status_t(-1)
 
+st_arch_id_t = ct.c_uint64
+st_arch_id_p = ct.POINTER(st_arch_id_t)
+
+st_ARCHITECTURE_ILLEGAL = st_arch_id_t(0x000003FF)
+st_ARCHITECTURE_NONE = st_arch_id_t(0)
+st_ARCHITECTURE_CPU = st_arch_id_t(1)
+st_ARCHITECTURE_OPENCL = st_arch_id_t(2)
+st_ARCHITECTURE_CUDA = st_arch_id_t(3)
+
+st_node_id_str_fmt_t = ct.c_uint16
+
+st_NODE_ID_STR_FORMAT_NOARCH = st_node_id_str_fmt_t(0)
+st_NODE_ID_STR_FORMAT_ARCHID = st_node_id_str_fmt_t(1)
+st_NODE_ID_STR_FORMAT_ARCHSTR = st_node_id_str_fmt_t(2)
+st_NODE_ID_STR_FORMAT_DEFAULT = st_node_id_str_fmt_t(0)
+st_NODE_ID_STR_FORMAT_ILLEGAL = st_node_id_str_fmt_t(0xFFFF)
+
 # ------------------------------------------------------------------------------
 # st_Buffer C-API functions
 
+st_buffer_flags_t = ct.c_uint64
+
+st_BUFFER_DEFAULT_CAPACITY = st_buffer_size_t(256)
+st_BUFFER_DEFAULT_DATASTORE_FLAGS = st_buffer_flags_t(0x00010000)
+
+st_ARCH_ILLEGAL_BUFFER_ID = st_arch_size_t(0)
+st_ARCH_PARTICLES_BUFFER_ID = st_arch_status_t(1)
+st_ARCH_BEAM_ELEMENTS_BUFFER_ID = st_arch_status_t(2)
+st_ARCH_OUTPUT_BUFFER_ID = st_arch_status_t(3)
+st_ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID = st_arch_status_t(4)
+st_ARCH_PARTICLE_ADDR_BUFFER_ID = st_arch_status_t(5)
+st_ARCH_MIN_USER_DEFINED_BUFFER_ID = st_arch_status_t(1024)
+st_ARCH_EXTERNAL_BUFFER_ID = st_arch_status_t(1024)
+st_ARCH_MAX_USER_DEFINED_BUFFER_ID = st_arch_status_t(0xFFFFFFFFFFFFFFFE)
+
 
 class st_Buffer(ct.Structure):
-    _fields_ = [("data_addr", ct.c_uint64),
-                ("data_size", ct.c_uint64),
-                ("header_size", ct.c_uint64),
-                ("data_capacity", ct.c_uint64),
-                ("slot_length", ct.c_uint64),
-                ("object_addr", ct.c_uint64),
-                ("num_objects", ct.c_uint64),
-                ("datastore_flags", ct.c_uint64),
-                ("datastore_addr", ct.c_uint64)]
+    _pack_ = 8
+    _fields_ = [
+        ("data_addr", ct.c_uint64),
+        ("data_size", ct.c_uint64),
+        ("header_size", ct.c_uint64),
+        ("data_capacity", ct.c_uint64),
+        ("slot_length", ct.c_uint64),
+        ("object_addr", ct.c_uint64),
+        ("num_objects", ct.c_uint64),
+        ("datastore_flags", ct.c_uint64),
+        ("datastore_addr", ct.c_uint64),
+    ]
 
 
 st_Buffer_p = ct.POINTER(st_Buffer)
@@ -81,7 +158,8 @@ class st_Buffer(ct.Structure):
     st_buffer_size_t,
     st_buffer_size_t,
     st_buffer_size_t,
-    ct.c_uint64]
+    st_buffer_flags_t,
+]
 st_Buffer_new_detailed.restype = st_Buffer_p
 
 st_Buffer_init_from_data = sixtracklib.st_Buffer_init_from_data_ext
@@ -89,11 +167,11 @@ class st_Buffer(ct.Structure):
 st_Buffer_init_from_data.restypes = ct.c_int32
 
 st_Buffer_get_slot_size = sixtracklib.st_Buffer_get_slot_size_ext
-st_Buffer_get_slot_size.argtypes = [st_Buffer_p, ]
+st_Buffer_get_slot_size.argtypes = [st_Buffer_p]
 st_Buffer_get_slot_size.restype = ct.c_uint64
 
 st_Buffer_get_num_of_objects = sixtracklib.st_Buffer_get_num_of_objects_ext
-st_Buffer_get_num_of_objects.argtypes = [st_Buffer_p, ]
+st_Buffer_get_num_of_objects.argtypes = [st_Buffer_p]
 st_Buffer_get_num_of_objects.restype = ct.c_uint64
 
 st_Buffer_get_size = sixtracklib.st_Buffer_get_size_ext
@@ -116,8 +194,9 @@ class st_Buffer(ct.Structure):
 st_Buffer_get_data_end_addr.argtypes = [st_Buffer_p]
 st_Buffer_get_data_end_addr.restype = st_buffer_addr_t
 
-st_Buffer_get_objects_begin_addr = \
+st_Buffer_get_objects_begin_addr = (
     sixtracklib.st_Buffer_get_objects_begin_addr_ext
+)
 st_Buffer_get_objects_begin_addr.argtypes = [st_Buffer_p]
 st_Buffer_get_objects_begin_addr.restype = st_buffer_addr_t
 
@@ -137,8 +216,9 @@ class st_Buffer(ct.Structure):
 st_Buffer_get_num_of_objects.argtypes = [st_Buffer_p]
 st_Buffer_get_num_of_objects.restype = st_buffer_size_t
 
-st_Buffer_get_max_num_of_objects = \
+st_Buffer_get_max_num_of_objects = (
     sixtracklib.st_Buffer_get_max_num_of_objects_ext
+)
 st_Buffer_get_max_num_of_objects.argtypes = [st_Buffer_p]
 st_Buffer_get_max_num_of_objects.restype = st_buffer_size_t
 
@@ -146,18 +226,21 @@ class st_Buffer(ct.Structure):
 st_Buffer_get_num_of_dataptrs.argtypes = [st_Buffer_p]
 st_Buffer_get_num_of_dataptrs.restype = st_buffer_size_t
 
-st_Buffer_get_max_num_of_dataptrs = \
+st_Buffer_get_max_num_of_dataptrs = (
     sixtracklib.st_Buffer_get_max_num_of_dataptrs_ext
+)
 st_Buffer_get_max_num_of_dataptrs.argtypes = [st_Buffer_p]
 st_Buffer_get_max_num_of_dataptrs.restype = st_buffer_size_t
 
-st_Buffer_get_num_of_garbage_ranges = \
+st_Buffer_get_num_of_garbage_ranges = (
     sixtracklib.st_Buffer_get_num_of_garbage_ranges_ext
+)
 st_Buffer_get_num_of_garbage_ranges.argtypes = [st_Buffer_p]
 st_Buffer_get_num_of_garbage_ranges.restype = st_buffer_size_t
 
-st_Buffer_get_max_num_of_garbage_ranges = \
+st_Buffer_get_max_num_of_garbage_ranges = (
     sixtracklib.st_Buffer_get_max_num_of_garbage_ranges_ext
+)
 st_Buffer_get_max_num_of_garbage_ranges.argtypes = [st_Buffer_p]
 st_Buffer_get_max_num_of_garbage_ranges.restype = st_buffer_size_t
 
@@ -169,10 +252,14 @@ class st_Buffer(ct.Structure):
 st_Buffer_write_to_file.argtypes = [st_Buffer_p, ct.c_char_p]
 st_Buffer_write_to_file.restype = ct.c_bool
 
-st_Buffer_write_to_file_normalized_addr = \
+st_Buffer_write_to_file_normalized_addr = (
     sixtracklib.st_Buffer_write_to_file_normalized_addr
+)
 st_Buffer_write_to_file_normalized_addr.argtypes = [
-    st_Buffer_p, ct.c_char_p, st_buffer_addr_t]
+    st_Buffer_p,
+    ct.c_char_p,
+    st_buffer_addr_t,
+]
 st_Buffer_write_to_file_normalized_addr.restype = ct.c_bool
 
 st_Buffer_reset = sixtracklib.st_Buffer_reset_ext
@@ -185,7 +272,8 @@ class st_Buffer(ct.Structure):
     st_buffer_size_t,
     st_buffer_size_t,
     st_buffer_size_t,
-    st_buffer_size_t]
+    st_buffer_size_t,
+]
 st_Buffer_reset_detailed.restype = st_arch_status_t
 
 st_Buffer_reserve = sixtracklib.st_Buffer_reserve_ext
@@ -194,7 +282,8 @@ class st_Buffer(ct.Structure):
     st_buffer_size_t,
     st_buffer_size_t,
     st_buffer_size_t,
-    st_buffer_size_t]
+    st_buffer_size_t,
+]
 st_Buffer_reserve.restype = st_arch_status_t
 
 st_Buffer_reserve_capacity = sixtracklib.st_Buffer_reserve_capacity_ext
@@ -234,35 +323,223 @@ def st_Buffer_new_mapped_on_cbuffer(cbuffer):
     size = ct.c_uint64(cbuffer.size)
     return st_Buffer_new_on_data(ptr_data, size)
 
+
+# ------------------------------------------------------------------------------
+# AssignAddressItem C-API functions
+
+
+st_object_type_id_t = ct.c_uint64
+
+
+class st_AssignAddressItem(ct.Structure):
+    _pack_ = 8
+    _fields_ = [
+        ("dest_elem_type_id", st_object_type_id_t),
+        ("dest_buffer_id", st_buffer_size_t),
+        ("dest_elem_index", st_buffer_size_t),
+        ("dest_pointer_offset", st_buffer_size_t),
+        ("src_elem_type_id", st_object_type_id_t),
+        ("src_buffer_id", st_buffer_size_t),
+        ("src_elem_index", st_buffer_size_t),
+        ("src_pointer_offset", st_buffer_size_t),
+    ]
+
+
+st_AssignAddressItem_p = ct.POINTER(st_AssignAddressItem)
+st_NullAssignAddressItem = ct.cast(0, st_AssignAddressItem_p)
+
+st_AssignAddressItem_perform_assignment = (
+    sixtracklib.st_AssignAddressItem_perform_assignment
+)
+st_AssignAddressItem_perform_assignment.argtypes = [
+    st_AssignAddressItem_p,
+    st_Buffer_p,
+    st_Buffer_p,
+]
+st_AssignAddressItem_perform_assignment.restype = st_arch_status_t
+
+st_AssignAddressItem_assign_fixed_addr = (
+    sixtracklib.st_AssignAddressItem_assign_fixed_addr
+)
+st_AssignAddressItem_assign_fixed_addr.argtypes = [
+    st_AssignAddressItem_p,
+    st_Buffer_p,
+    ct.c_uint64,
+]
+st_AssignAddressItem_assign_fixed_addr.restype = st_arch_status_t
+
+st_AssignAddressItem_remap_assignment = (
+    sixtracklib.st_AssignAddressItem_remap_assignment
+)
+st_AssignAddressItem_remap_assignment.argtypes = [
+    st_AssignAddressItem_p,
+    st_Buffer_p,
+    ct.c_int64,
+]
+st_AssignAddressItem_remap_assignment.restype = st_arch_status_t
+
+st_AssignAddressItem_dest_pointer_from_buffer = (
+    sixtracklib.st_AssignAddressItem_dest_pointer_from_buffer
+)
+st_AssignAddressItem_dest_pointer_from_buffer.argtypes = [
+    st_AssignAddressItem_p,
+    st_Buffer_p,
+]
+st_AssignAddressItem_dest_pointer_from_buffer.restype = st_uint64_p
+
+st_AssignAddressItem_src_pointer_addr_from_buffer = (
+    sixtracklib.st_AssignAddressItem_src_pointer_addr_from_buffer
+)
+st_AssignAddressItem_src_pointer_addr_from_buffer.argtypes = [
+    st_AssignAddressItem_p,
+    st_Buffer_p,
+]
+st_AssignAddressItem_src_pointer_addr_from_buffer.restype = ct.c_uint64
+
+st_AssignAddressItem_from_buffer = sixtracklib.st_AssignAddressItem_from_buffer
+st_AssignAddressItem_from_buffer.argtypes = [
+    st_AssignAddressItem_p,
+    st_Buffer_p,
+    st_buffer_size_t,
+]
+st_AssignAddressItem_from_buffer.restype = st_AssignAddressItem_p
+
+st_AssignAddressItem_can_be_added = (
+    sixtracklib.st_AssignAddressItem_can_be_added
+)
+st_AssignAddressItem_can_be_added.restype = ct.c_bool
+st_AssignAddressItem_can_be_added.argtypes = [
+    st_Buffer_p,
+    st_buffer_size_p,
+    st_buffer_size_p,
+    st_buffer_size_p,
+]
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+st_AssignAddressItem_compare_less = (
+    sixtracklib.st_AssignAddressItem_compare_less_ext
+)
+st_AssignAddressItem_compare_less.argtypes = [
+    st_AssignAddressItem_p,
+    st_AssignAddressItem_p,
+]
+st_AssignAddressItem_compare_less.restype = ct.c_bool
+
+st_AssignAddressItem_are_equal = sixtracklib.st_AssignAddressItem_are_equal_ext
+st_AssignAddressItem_are_equal.argtypes = [
+    st_AssignAddressItem_p,
+    st_AssignAddressItem_p,
+]
+st_AssignAddressItem_are_equal.restype = ct.c_bool
+
+st_AssignAddressItem_are_not_equal = (
+    sixtracklib.st_AssignAddressItem_are_not_equal_ext
+)
+st_AssignAddressItem_are_not_equal.argtypes = [
+    st_AssignAddressItem_p,
+    st_AssignAddressItem_p,
+]
+st_AssignAddressItem_are_not_equal.restype = ct.c_bool
+
+st_AssignAddressItem_dest_src_are_equal = (
+    sixtracklib.st_AssignAddressItem_dest_src_are_equal_ext
+)
+st_AssignAddressItem_dest_src_are_equal.argtypes = [
+    st_AssignAddressItem_p,
+    st_AssignAddressItem_p,
+]
+st_AssignAddressItem_dest_src_are_equal.restype = ct.c_bool
+
+st_AssignAddressItem_dest_src_are_not_equal = (
+    sixtracklib.st_AssignAddressItem_dest_src_are_not_equal_ext
+)
+st_AssignAddressItem_dest_src_are_not_equal.argtypes = [
+    st_AssignAddressItem_p,
+    st_AssignAddressItem_p,
+]
+st_AssignAddressItem_dest_src_are_not_equal.restype = ct.c_bool
+
+st_AssignAddressItem_new = sixtracklib.st_AssignAddressItem_new
+st_AssignAddressItem_new.argtypes = [st_Buffer_p]
+st_AssignAddressItem_new.restype = st_AssignAddressItem_p
+
+st_AssignAddressItem_add = sixtracklib.st_AssignAddressItem_add
+st_AssignAddressItem_add.argtypes = [
+    st_Buffer_p,
+    ct.c_uint64,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    ct.c_uint64,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_AssignAddressItem_add.restype = st_AssignAddressItem_p
+
+st_AssignAddressItem_add_copy = sixtracklib.st_AssignAddressItem_add_copy
+st_AssignAddressItem_add_copy.argtypes = [st_Buffer_p, st_AssignAddressItem_p]
+st_AssignAddressItem_add_copy.restype = st_AssignAddressItem_p
+
 # ------------------------------------------------------------------------------
 # st_Particles C-API functions
 
 
 class st_Particles(ct.Structure):
-    _fields_ = [("num_particles", ct.c_int64), ("q0", st_double_p),
-                ("mass0", st_double_p), ("beta0", st_double_p),
-                ("gamma0", st_double_p), ("p0C", st_double_p),
-                ("s", st_double_p), ("x", st_double_p), ("y", st_double_p),
-                ("px", st_double_p), ("py", st_double_p), ("zeta", st_double_p),
-                ("psigma", st_double_p), ("delta", st_double_p),
-                ("rpp", st_double_p), ("rvv", st_double_p), ("chi", st_double_p),
-                ("charge_ratio", st_double_p), ("particle_id", st_int64_p),
-                ("at_element", st_int64_p), ("at_turn", st_int64_p),
-                ("state", st_int64_p)]
+    _pack_ = 8
+    _fields_ = [
+        ("num_particles", ct.c_int64),
+        ("q0", st_double_p),
+        ("mass0", st_double_p),
+        ("beta0", st_double_p),
+        ("gamma0", st_double_p),
+        ("p0C", st_double_p),
+        ("s", st_double_p),
+        ("x", st_double_p),
+        ("y", st_double_p),
+        ("px", st_double_p),
+        ("py", st_double_p),
+        ("zeta", st_double_p),
+        ("psigma", st_double_p),
+        ("delta", st_double_p),
+        ("rpp", st_double_p),
+        ("rvv", st_double_p),
+        ("chi", st_double_p),
+        ("charge_ratio", st_double_p),
+        ("particle_id", st_int64_p),
+        ("at_element", st_int64_p),
+        ("at_turn", st_int64_p),
+        ("state", st_int64_p),
+    ]
 
 
 class st_ParticlesAddr(ct.Structure):
-    _fields_ = [("num_particles", ct.c_int64), ("q0", ct.c_uint64),
-                ("mass0", ct.c_uint64), ("beta0", ct.c_uint64),
-                ("gamma0", ct.c_uint64), ("p0C", ct.c_uint64),
-                ("s", ct.c_uint64), ("x", ct.c_uint64), ("y", ct.c_uint64),
-                ("px", ct.c_uint64), ("py", ct.c_uint64), ("zeta", ct.c_uint64),
-                ("psigma", ct.c_uint64), ("delta", ct.c_uint64),
-                ("rpp", ct.c_uint64), ("rvv", ct.c_uint64), ("chi", ct.c_uint64),
-                ("charge_ratio", ct.c_uint64), ("particle_id", ct.c_uint64),
-                ("at_element", ct.c_uint64), ("at_turn", ct.c_uint64),
-                ("state", ct.c_uint64)]
-
+    _pack_ = 8
+    _fields_ = [
+        ("num_particles", ct.c_int64),
+        ("q0", ct.c_uint64),
+        ("mass0", ct.c_uint64),
+        ("beta0", ct.c_uint64),
+        ("gamma0", ct.c_uint64),
+        ("p0c", ct.c_uint64),
+        ("s", ct.c_uint64),
+        ("x", ct.c_uint64),
+        ("y", ct.c_uint64),
+        ("px", ct.c_uint64),
+        ("py", ct.c_uint64),
+        ("zeta", ct.c_uint64),
+        ("psigma", ct.c_uint64),
+        ("delta", ct.c_uint64),
+        ("rpp", ct.c_uint64),
+        ("rvv", ct.c_uint64),
+        ("chi", ct.c_uint64),
+        ("charge_ratio", ct.c_uint64),
+        ("particle_id", ct.c_uint64),
+        ("at_element", ct.c_uint64),
+        ("at_turn", ct.c_uint64),
+        ("state", ct.c_uint64),
+    ]
 
 st_Particles_p = ct.POINTER(st_Particles)
 st_NullParticles = ct.cast(0, st_Particles_p)
@@ -282,16 +559,20 @@ def st_Particles_cbuffer_get_particles(cbuffer, obj_index):
 st_Particles_preset.argtypes = [st_Particles_p]
 st_Particles_preset.restype = st_Particles_p
 
-st_Particles_get_num_of_particles = \
+st_Particles_get_num_of_particles = (
     sixtracklib.st_Particles_get_num_of_particles_ext
+)
 st_Particles_get_num_of_particles.argtypes = [st_Particles_p]
 st_Particles_get_num_of_particles.restype = st_particle_num_elem_t
 
 st_Particles_copy_single = sixtracklib.st_Particles_copy_single_ext
 st_Particles_copy_single.restype = ct.c_bool
 st_Particles_copy_single.argtypes = [
-    st_Particles_p, st_particle_num_elem_t,
-    st_Particles_p, st_particle_num_elem_t]
+    st_Particles_p,
+    st_particle_num_elem_t,
+    st_Particles_p,
+    st_particle_num_elem_t,
+]
 
 st_Particles_copy_range = sixtracklib.st_Particles_copy_range_ext
 st_Particles_copy_range.restype = ct.c_bool
@@ -300,65 +581,90 @@ def st_Particles_cbuffer_get_particles(cbuffer, obj_index):
     st_Particles_p,
     st_particle_num_elem_t,
     st_particle_num_elem_t,
-    st_particle_num_elem_t]
+    st_particle_num_elem_t,
+]
 
 st_Particles_copy = sixtracklib.st_Particles_copy_ext
 st_Particles_copy.argtypes = [st_Particles_p, st_Particles_p]
 st_Particles_copy.restype = ct.c_bool
 
-st_Particles_calculate_difference = \
+st_Particles_calculate_difference = (
     sixtracklib.st_Particles_calculate_difference_ext
+)
 st_Particles_calculate_difference.restype = None
 st_Particles_calculate_difference.argtypes = [
-    st_Particles_p, st_Particles_p, st_Particles_p]
+    st_Particles_p,
+    st_Particles_p,
+    st_Particles_p,
+]
 
-st_Particles_buffer_get_total_num_of_particles = \
+st_Particles_buffer_get_total_num_of_particles = (
     sixtracklib.st_Particles_buffer_get_total_num_of_particles_ext
+)
 st_Particles_buffer_get_total_num_of_particles.restype = st_particle_num_elem_t
 st_Particles_buffer_get_total_num_of_particles.argtypes = [st_Buffer_p]
 
-st_Particles_buffer_get_num_of_particle_blocks = \
+st_Particles_buffer_get_num_of_particle_blocks = (
     sixtracklib.st_Particles_buffer_get_num_of_particle_blocks_ext
+)
 st_Particles_buffer_get_num_of_particle_blocks.restype = st_buffer_size_t
 st_Particles_buffer_get_num_of_particle_blocks.argtypes = [st_Buffer_p]
 
-st_Particles_buffer_get_particles = \
+st_Particles_buffer_get_particles = (
     sixtracklib.st_Particles_buffer_get_particles_ext
+)
 st_Particles_buffer_get_particles.restype = st_Particles_p
 st_Particles_buffer_get_particles.argtypes = [st_Buffer_p, st_buffer_size_t]
 
-st_Particles_buffers_have_same_structure = \
+st_Particles_buffers_have_same_structure = (
     sixtracklib.st_Particles_buffers_have_same_structure_ext
+)
 st_Particles_buffers_have_same_structure.restype = ct.c_bool
 st_Particles_buffers_have_same_structure.argtypes = [
-    st_Particles_p, st_Particles_p]
+    st_Particles_p,
+    st_Particles_p,
+]
 
-st_Particles_buffers_calculate_difference = \
+st_Particles_buffers_calculate_difference = (
     sixtracklib.st_Particles_buffers_calculate_difference_ext
+)
 st_Particles_buffers_calculate_difference.restype = None
 st_Particles_buffers_calculate_difference.argtypes = [
-    st_Buffer_p, st_Buffer_p, st_Buffer_p]
+    st_Buffer_p,
+    st_Buffer_p,
+    st_Buffer_p,
+]
 
-st_Particles_buffer_clear_particles = \
+st_Particles_buffer_clear_particles = (
     sixtracklib.st_Particles_buffer_clear_particles_ext
+)
 st_Particles_buffer_clear_particles.restype = None
 st_Particles_buffer_clear_particles.argtypes = [st_Buffer_p]
 
-st_Particles_get_required_num_slots = \
+st_Particles_get_required_num_slots = (
     sixtracklib.st_Particles_get_required_num_slots_ext
+)
 st_Particles_get_required_num_slots.restype = st_buffer_size_t
 st_Particles_get_required_num_slots.argtypes = [st_Buffer_p, st_buffer_size_t]
 
-st_Particles_get_required_num_dataptrs = \
+st_Particles_get_required_num_dataptrs = (
     sixtracklib.st_Particles_get_required_num_dataptrs_ext
+)
 st_Particles_get_required_num_dataptrs.restype = st_buffer_size_t
 st_Particles_get_required_num_dataptrs.argtypes = [
-    st_Buffer_p, st_buffer_size_t]
+    st_Buffer_p,
+    st_buffer_size_t,
+]
 
 st_Particles_can_be_added = sixtracklib.st_Particles_can_be_added_ext
 st_Particles_can_be_added.restype = ct.c_bool
 st_Particles_can_be_added.argtypes = [
-    st_Buffer_p, st_buffer_size_t, st_uint64_p, st_uint64_p, st_uint64_p]
+    st_Buffer_p,
+    st_buffer_size_t,
+    st_uint64_p,
+    st_uint64_p,
+    st_uint64_p,
+]
 
 st_Particles_new = sixtracklib.st_Particles_new_ext
 st_Particles_new.argtypes = [st_Buffer_p, st_particle_num_elem_t]
@@ -389,7 +695,8 @@ def st_Particles_cbuffer_get_particles(cbuffer, obj_index):
     st_int64_p,
     st_int64_p,
     st_int64_p,
-    st_int64_p]
+    st_int64_p,
+]
 
 st_Particles_add_copy = sixtracklib.st_Particles_add_copy_ext
 st_Particles_add_copy.restype = st_Particles_p
@@ -399,20 +706,27 @@ def st_Particles_cbuffer_get_particles(cbuffer, obj_index):
 st_ParticlesAddr_preset.argtypes = [st_ParticlesAddr_p]
 st_ParticlesAddr_preset.restype = st_ParticlesAddr_p
 
-st_ParticlesAddr_assign_from_particles = \
+st_ParticlesAddr_assign_from_particles = (
     sixtracklib.st_ParticlesAddr_assign_from_particles_ext
+)
 st_ParticlesAddr_assign_from_particles.argtypes = [
-    st_ParticlesAddr_p, st_Particles_p]
+    st_ParticlesAddr_p,
+    st_Particles_p,
+]
 st_ParticlesAddr_assign_from_particles.restype = None
 
-st_ParticlesAddr_assign_to_particles = \
+st_ParticlesAddr_assign_to_particles = (
     sixtracklib.st_ParticlesAddr_assign_to_particles_ext
+)
 st_ParticlesAddr_assign_to_particles.argtypes = [
-    st_ParticlesAddr_p, st_Particles_p]
+    st_ParticlesAddr_p,
+    st_Particles_p,
+]
 st_ParticlesAddr_assign_to_particles.restype = None
 
-st_ParticlesAddr_remap_addresses = \
+st_ParticlesAddr_remap_addresses = (
     sixtracklib.st_ParticlesAddr_remap_addresses_ext
+)
 st_ParticlesAddr_remap_addresses.argtypes = [st_ParticlesAddr_p, ct.c_int64]
 st_ParticlesAddr_remap_addresses.restype = None
 
@@ -433,18 +747,21 @@ def st_Particles_cbuffer_get_particles(cbuffer, obj_index):
 
 
 class st_ElemByElemConfig(ct.Structure):
-    _fields_ = [("order", st_elem_by_elem_order_int_t),
-                ("num_particles_to_store", st_particle_num_elem_t),
-                ("num_elements_to_store", st_particle_num_elem_t),
-                ("num_turns_to_store", st_particle_num_elem_t),
-                ("min_particle_id", st_particle_index_t),
-                ("min_element_id", st_particle_index_t),
-                ("min_turn", st_particle_index_t),
-                ("max_particle_id", st_particle_index_t),
-                ("max_element_id", st_particle_index_t),
-                ("max_turn", st_particle_index_t),
-                ("is_rolling", st_elem_by_elem_flag_t),
-                ("out_store_addr", st_elem_by_elem_out_addr_t)]
+    _pack_ = 8
+    _fields_ = [
+        ("order", st_elem_by_elem_order_int_t),
+        ("num_particles_to_store", st_particle_num_elem_t),
+        ("num_elements_to_store", st_particle_num_elem_t),
+        ("num_turns_to_store", st_particle_num_elem_t),
+        ("min_particle_id", st_particle_index_t),
+        ("min_element_id", st_particle_index_t),
+        ("min_turn", st_particle_index_t),
+        ("max_particle_id", st_particle_index_t),
+        ("max_element_id", st_particle_index_t),
+        ("max_turn", st_particle_index_t),
+        ("is_rolling", st_elem_by_elem_flag_t),
+        ("out_store_addr", st_elem_by_elem_out_addr_t),
+    ]
 
 
 st_ElemByElemConfig_p = ct.POINTER(st_ElemByElemConfig)
@@ -459,62 +776,71 @@ class st_ElemByElemConfig(ct.Structure):
 st_ElemByElemConfig_delete.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_delete.restype = None
 
-st_ElemByElemConfig_is_active = \
-    sixtracklib.st_ElemByElemConfig_is_active_ext
+st_ElemByElemConfig_is_active = sixtracklib.st_ElemByElemConfig_is_active_ext
 st_ElemByElemConfig_is_active.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_is_active.restype = ct.c_bool
 
-st_ElemByElemConfig_get_out_store_num_particles = \
+st_ElemByElemConfig_get_out_store_num_particles = (
     sixtracklib.st_ElemByElemConfig_get_out_store_num_particles_ext
+)
 st_ElemByElemConfig_get_out_store_num_particles.argtypes = [
-    st_ElemByElemConfig_p]
-st_ElemByElemConfig_get_out_store_num_particles.restype = \
-    st_particle_num_elem_t
+    st_ElemByElemConfig_p
+]
+st_ElemByElemConfig_get_out_store_num_particles.restype = st_particle_num_elem_t
 
-st_ElemByElemConfig_get_num_particles_to_store = \
+st_ElemByElemConfig_get_num_particles_to_store = (
     sixtracklib.st_ElemByElemConfig_get_num_particles_to_store_ext
+)
 st_ElemByElemConfig_get_num_particles_to_store.argtypes = [
-    st_ElemByElemConfig_p]
+    st_ElemByElemConfig_p
+]
 st_ElemByElemConfig_get_num_particles_to_store.restype = st_particle_num_elem_t
 
-st_ElemByElemConfig_get_num_turns_to_store = \
+st_ElemByElemConfig_get_num_turns_to_store = (
     sixtracklib.st_ElemByElemConfig_get_num_turns_to_store_ext
+)
 st_ElemByElemConfig_get_num_turns_to_store.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_num_turns_to_store.restype = st_particle_num_elem_t
 
-st_ElemByElemConfig_get_num_elements_to_store = \
+st_ElemByElemConfig_get_num_elements_to_store = (
     sixtracklib.st_ElemByElemConfig_get_num_elements_to_store_ext
-st_ElemByElemConfig_get_num_elements_to_store.argtypes = [
-    st_ElemByElemConfig_p]
+)
+st_ElemByElemConfig_get_num_elements_to_store.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_num_elements_to_store.restype = st_particle_num_elem_t
 
-st_ElemByElemConfig_get_min_particle_id = \
+st_ElemByElemConfig_get_min_particle_id = (
     sixtracklib.st_ElemByElemConfig_get_min_particle_id_ext
+)
 st_ElemByElemConfig_get_min_particle_id.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_min_particle_id.restype = st_particle_index_t
 
-st_ElemByElemConfig_get_max_particle_id = \
+st_ElemByElemConfig_get_max_particle_id = (
     sixtracklib.st_ElemByElemConfig_get_max_particle_id_ext
+)
 st_ElemByElemConfig_get_max_particle_id.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_max_particle_id.restype = st_particle_index_t
 
-st_ElemByElemConfig_get_min_element_id = \
+st_ElemByElemConfig_get_min_element_id = (
     sixtracklib.st_ElemByElemConfig_get_min_element_id_ext
+)
 st_ElemByElemConfig_get_min_element_id.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_min_element_id.restype = st_particle_index_t
 
-st_ElemByElemConfig_get_max_element_id = \
+st_ElemByElemConfig_get_max_element_id = (
     sixtracklib.st_ElemByElemConfig_get_max_element_id_ext
+)
 st_ElemByElemConfig_get_max_element_id.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_max_element_id.restype = st_particle_index_t
 
-st_ElemByElemConfig_get_min_turn = \
+st_ElemByElemConfig_get_min_turn = (
     sixtracklib.st_ElemByElemConfig_get_min_turn_ext
+)
 st_ElemByElemConfig_get_min_turn.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_min_turn.restype = st_particle_index_t
 
-st_ElemByElemConfig_get_max_turn = \
+st_ElemByElemConfig_get_max_turn = (
     sixtracklib.st_ElemByElemConfig_get_max_turn_ext
+)
 st_ElemByElemConfig_get_max_turn.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_max_turn.restype = st_particle_index_t
 
@@ -526,47 +852,68 @@ class st_ElemByElemConfig(ct.Structure):
 st_ElemByElemConfig_get_order.argtypes = [st_ElemByElemConfig_p]
 st_ElemByElemConfig_get_order.restype = st_elem_by_elem_order_int_t
 
-st_ElemByElemConfig_get_output_store_address = \
+st_ElemByElemConfig_get_output_store_address = (
     sixtracklib.st_ElemByElemConfig_get_output_store_address_ext
-st_ElemByElemConfig_get_output_store_address.argtypes = [
-    st_ElemByElemConfig_p]
-st_ElemByElemConfig_get_output_store_address.restype = \
+)
+st_ElemByElemConfig_get_output_store_address.argtypes = [st_ElemByElemConfig_p]
+st_ElemByElemConfig_get_output_store_address.restype = (
     st_elem_by_elem_out_addr_t
+)
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_ElemByElemConfig_get_particles_store_index_details = \
+st_ElemByElemConfig_get_particles_store_index_details = (
     sixtracklib.st_ElemByElemConfig_get_particles_store_index_details_ext
+)
 st_ElemByElemConfig_get_particles_store_index_details.argtypes = [
-    st_ElemByElemConfig_p, st_particle_index_t, st_particle_index_t,
-    st_particle_index_t]
-st_ElemByElemConfig_get_particles_store_index_details.restype = \
+    st_ElemByElemConfig_p,
+    st_particle_index_t,
+    st_particle_index_t,
+    st_particle_index_t,
+]
+st_ElemByElemConfig_get_particles_store_index_details.restype = (
     st_particle_num_elem_t
+)
 
-st_ElemByElemConfig_get_particles_store_index = \
+st_ElemByElemConfig_get_particles_store_index = (
     sixtracklib.st_ElemByElemConfig_get_particles_store_index_ext
+)
 st_ElemByElemConfig_get_particles_store_index.argtypes = [
-    st_ElemByElemConfig_p, st_Particles_p, st_particle_num_elem_t]
+    st_ElemByElemConfig_p,
+    st_Particles_p,
+    st_particle_num_elem_t,
+]
 st_ElemByElemConfig_get_particles_store_index.restype = st_particle_num_elem_t
 
-st_ElemByElemConfig_get_particle_id_from_store_index = \
+st_ElemByElemConfig_get_particle_id_from_store_index = (
     sixtracklib.st_ElemByElemConfig_get_particle_id_from_store_index_ext
+)
 st_ElemByElemConfig_get_particle_id_from_store_index.argtypes = [
-    st_ElemByElemConfig_p, st_particle_num_elem_t]
-st_ElemByElemConfig_get_particle_id_from_store_index.restype = \
+    st_ElemByElemConfig_p,
+    st_particle_num_elem_t,
+]
+st_ElemByElemConfig_get_particle_id_from_store_index.restype = (
     st_particle_num_elem_t
+)
 
-st_ElemByElemConfig_get_at_element_id_from_store_index = \
+st_ElemByElemConfig_get_at_element_id_from_store_index = (
     sixtracklib.st_ElemByElemConfig_get_at_element_id_from_store_index_ext
+)
 st_ElemByElemConfig_get_at_element_id_from_store_index.argtypes = [
-    st_ElemByElemConfig_p, st_particle_num_elem_t]
-st_ElemByElemConfig_get_at_element_id_from_store_index.restype = \
+    st_ElemByElemConfig_p,
+    st_particle_num_elem_t,
+]
+st_ElemByElemConfig_get_at_element_id_from_store_index.restype = (
     st_particle_num_elem_t
+)
 
-st_ElemByElemConfig_get_at_turn_from_store_index = \
+st_ElemByElemConfig_get_at_turn_from_store_index = (
     sixtracklib.st_ElemByElemConfig_get_at_turn_from_store_index_ext
+)
 st_ElemByElemConfig_get_at_turn_from_store_index.argtypes = [
-    st_ElemByElemConfig_p, st_particle_num_elem_t]
+    st_ElemByElemConfig_p,
+    st_particle_num_elem_t,
+]
 st_ElemByElemConfig_get_at_turn_from_store_index.restype = st_particle_index_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -577,11 +924,13 @@ class st_ElemByElemConfig(ct.Structure):
     st_Particles_p,
     st_Buffer_p,
     st_particle_index_t,
-    st_particle_index_t]
+    st_particle_index_t,
+]
 st_ElemByElemConfig_init.restype = st_arch_status_t
 
-st_ElemByElemConfig_init_on_particle_sets = \
+st_ElemByElemConfig_init_on_particle_sets = (
     sixtracklib.st_ElemByElemConfig_init_on_particle_sets
+)
 st_ElemByElemConfig_init_on_particle_sets.argtypes = [
     st_ElemByElemConfig_p,
     st_Buffer_p,
@@ -589,11 +938,13 @@ class st_ElemByElemConfig(ct.Structure):
     st_buffer_size_p,
     st_Buffer_p,
     st_particle_index_t,
-    st_particle_index_t]
+    st_particle_index_t,
+]
 st_ElemByElemConfig_init_on_particle_sets.restype = st_arch_status_t
 
-st_ElemByElemConfig_init_detailed = \
+st_ElemByElemConfig_init_detailed = (
     sixtracklib.st_ElemByElemConfig_init_detailed_ext
+)
 st_ElemByElemConfig_init_detailed.argtypes = [
     st_ElemByElemConfig_p,
     st_elem_by_elem_order_int_t,
@@ -603,31 +954,37 @@ class st_ElemByElemConfig(ct.Structure):
     st_particle_index_t,
     st_particle_index_t,
     st_particle_index_t,
-    ct.c_bool]
+    ct.c_bool,
+]
 st_ElemByElemConfig_init_detailed.restype = st_arch_status_t
 
-st_ElemByElemConfig_assign_output_buffer = \
+st_ElemByElemConfig_assign_output_buffer = (
     sixtracklib.st_ElemByElemConfig_assign_output_buffer
+)
 st_ElemByElemConfig_assign_output_buffer.restype = st_arch_status_t
 st_ElemByElemConfig_assign_output_buffer.argtypes = [
-    st_ElemByElemConfig_p, st_Buffer_p, st_buffer_size_t]
+    st_ElemByElemConfig_p,
+    st_Buffer_p,
+    st_buffer_size_t,
+]
 
 
 def st_ElemByElemConfig_assign_output_cbuffer(
-        elem_by_elem_config,
-        output_buffer,
-        out_buffer_offset_index):
+    elem_by_elem_config, output_buffer, out_buffer_offset_index
+):
     ptr_output_buffer = st_Buffer_new_mapped_on_cbuffer(output_buffer)
 
     out_buffer_offset_index_arg = st_buffer_size_t(out_buffer_offset_index)
 
     ret = st_ElemByElemConfig_assign_output_buffer(
-        elem_by_elem_config, ptr_output_buffer, out_buffer_offset_index_arg)
+        elem_by_elem_config, ptr_output_buffer, out_buffer_offset_index_arg
+    )
 
     st_Buffer_delete(ptr_output_buffer)
     ptr_output_buffer = st_NullBuffer
     return ret
 
+
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 
@@ -641,42 +998,64 @@ def st_ElemByElemConfig_assign_output_cbuffer(
 
 st_ElemByElemConfig_set_order = sixtracklib.st_ElemByElemConfig_set_order_ext
 st_ElemByElemConfig_set_order.argtypes = [
-    st_ElemByElemConfig_p, st_elem_by_elem_order_int_t]
+    st_ElemByElemConfig_p,
+    st_elem_by_elem_order_int_t,
+]
 st_ElemByElemConfig_set_order.restype = None
 
-st_ElemByElemConfig_set_is_rolling = \
+st_ElemByElemConfig_set_is_rolling = (
     sixtracklib.st_ElemByElemConfig_set_is_rolling_ext
+)
 st_ElemByElemConfig_set_is_rolling.argtypes = [
-    st_ElemByElemConfig_p, ct.c_bool]
+    st_ElemByElemConfig_p,
+    ct.c_bool,
+]
 st_ElemByElemConfig_set_is_rolling.restype = None
 
-st_ElemByElemConfig_set_output_store_address = \
+st_ElemByElemConfig_set_output_store_address = (
     sixtracklib.st_ElemByElemConfig_set_output_store_address_ext
+)
 st_ElemByElemConfig_set_output_store_address.argtypes = [
-    st_ElemByElemConfig_p, st_elem_by_elem_out_addr_t]
+    st_ElemByElemConfig_p,
+    st_elem_by_elem_out_addr_t,
+]
 st_ElemByElemConfig_set_output_store_address.restype = None
 
 # -----------------------------------------------------------------------------
 # BeamMonitor objects
 
-st_BeamMonitor_insert_end_of_turn_monitors = \
+st_BeamMonitor_type_id = sixtracklib.st_BeamMonitor_type_id_ext
+st_BeamMonitor_type_id.argtypes = None
+st_BeamMonitor_type_id.restype = st_object_type_id_t
+
+st_BeamMonitor_insert_end_of_turn_monitors = (
     sixtracklib.st_BeamMonitor_insert_end_of_turn_monitors_at_pos
+)
 st_BeamMonitor_insert_end_of_turn_monitors.restype = ct.c_int32
 st_BeamMonitor_insert_end_of_turn_monitors.argtypes = [
-    st_Buffer_p, ct.c_int64, ct.c_int64, ct.c_int64, ct.c_int64, ct.c_uint64, ]
+    st_Buffer_p,
+    ct.c_int64,
+    ct.c_int64,
+    ct.c_int64,
+    ct.c_int64,
+    ct.c_uint64,
+]
 
-st_BeamMonitor_assign_output_buffer = \
+st_BeamMonitor_assign_output_buffer = (
     sixtracklib.st_BeamMonitor_assign_output_buffer
+)
 st_BeamMonitor_assign_output_buffer.restype = ct.c_int32
 st_BeamMonitor_assign_output_buffer.argtypes = [
-    st_Buffer_p, st_Buffer_p, ct.c_int64, ct.c_uint64]
+    st_Buffer_p,
+    st_Buffer_p,
+    ct.c_int64,
+    ct.c_uint64,
+]
 
 
 def st_BeamMonitor_assign_output_cbuffer(
-        beam_elements_buffer,
-        output_buffer,
-        min_turn_id,
-        until_turn_elem_by_elem):
+    beam_elements_buffer, output_buffer, min_turn_id, until_turn_elem_by_elem
+):
     ptr_belem_buffer = st_Buffer_new_mapped_on_cbuffer(beam_elements_buffer)
     ptr_output_buffer = st_Buffer_new_mapped_on_cbuffer(output_buffer)
 
@@ -684,8 +1063,11 @@ def st_BeamMonitor_assign_output_cbuffer(
     until_turn_elem_by_elem = ct.c_uint64(until_turn_elem_by_elem)
 
     ret = st_BeamMonitor_assign_output_buffer(
-        ptr_belem_buffer, ptr_output_buffer,
-        min_turn_id, until_turn_elem_by_elem)
+        ptr_belem_buffer,
+        ptr_output_buffer,
+        min_turn_id,
+        until_turn_elem_by_elem,
+    )
 
     st_Buffer_delete(ptr_belem_buffer)
     st_Buffer_delete(ptr_output_buffer)
@@ -693,49 +1075,61 @@ def st_BeamMonitor_assign_output_cbuffer(
     return ret
 
 
-st_BeamMonitor_assign_output_buffer_from_offset = \
+st_BeamMonitor_assign_output_buffer_from_offset = (
     sixtracklib.st_BeamMonitor_assign_output_buffer_from_offset
+)
 st_BeamMonitor_assign_output_buffer_from_offset.restype = ct.c_int32
 st_BeamMonitor_assign_output_buffer_from_offset.argtypes = [
-    st_Buffer_p, st_Buffer_p, ct.c_int64, ct.c_uint64]
+    st_Buffer_p,
+    st_Buffer_p,
+    ct.c_int64,
+    ct.c_uint64,
+]
 
 # -----------------------------------------------------------------------------
 # OutputBuffer bindings
 
 st_out_buffer_flags_t = ct.c_int32
 
-st_OutputBuffer_requires_output_buffer = \
+st_OutputBuffer_requires_output_buffer = (
     sixtracklib.st_OutputBuffer_requires_output_buffer_ext
+)
 st_OutputBuffer_requires_output_buffer.restype = ct.c_bool
 st_OutputBuffer_requires_output_buffer.argtypes = [ct.c_int32]
 
-st_OutputBuffer_requires_beam_monitor_output = \
+st_OutputBuffer_requires_beam_monitor_output = (
     sixtracklib.st_OutputBuffer_requires_beam_monitor_output_ext
+)
 st_OutputBuffer_requires_beam_monitor_output.restype = ct.c_bool
 st_OutputBuffer_requires_beam_monitor_output.argtypes = [ct.c_int32]
 
-st_OutputBuffer_requires_elem_by_elem_output = \
+st_OutputBuffer_requires_elem_by_elem_output = (
     sixtracklib.st_OutputBuffer_requires_elem_by_elem_output_ext
+)
 st_OutputBuffer_requires_elem_by_elem_output.restype = ct.c_bool
 st_OutputBuffer_requires_elem_by_elem_output.argtypes = [ct.c_int32]
 
-st_OutputBuffer_required_for_tracking = \
+st_OutputBuffer_required_for_tracking = (
     sixtracklib.st_OutputBuffer_required_for_tracking
+)
 st_OutputBuffer_required_for_tracking.restype = ct.c_int32
 st_OutputBuffer_required_for_tracking.argtypes = [
     st_Particles_p,
     st_Buffer_p,
-    ct.c_uint64]
+    ct.c_uint64,
+]
 
-st_OutputBuffer_required_for_tracking_of_particle_sets = \
+st_OutputBuffer_required_for_tracking_of_particle_sets = (
     sixtracklib.st_OutputBuffer_required_for_tracking_of_particle_sets
+)
 st_OutputBuffer_required_for_tracking_of_particle_sets.restype = ct.c_int32
 st_OutputBuffer_required_for_tracking_of_particle_sets.argtypes = [
     st_Buffer_p,
     ct.c_uint64,
     st_uint64_p,
     st_Buffer_p,
-    ct.c_uint64]
+    ct.c_uint64,
+]
 
 st_OutputBuffer_prepare = sixtracklib.st_OutputBuffer_prepare
 st_OutputBuffer_prepare.restype = ct.c_int32
@@ -746,10 +1140,12 @@ def st_BeamMonitor_assign_output_cbuffer(
     ct.c_uint64,
     st_uint64_p,
     st_uint64_p,
-    st_int64_p]
+    st_int64_p,
+]
 
-st_OutputBuffer_prepare_for_particle_sets = \
+st_OutputBuffer_prepare_for_particle_sets = (
     sixtracklib.st_OutputBuffer_prepare_for_particle_sets
+)
 st_OutputBuffer_prepare_for_particle_sets.restype = ct.c_int32
 st_OutputBuffer_prepare_for_particle_sets.argtypes = [
     st_Buffer_p,
@@ -760,11 +1156,13 @@ def st_BeamMonitor_assign_output_cbuffer(
     ct.c_uint64,
     st_uint64_p,
     st_uint64_p,
-    st_uint64_p]
+    st_uint64_p,
+]
 
 
-st_OutputBuffer_calculate_output_buffer_params = \
+st_OutputBuffer_calculate_output_buffer_params = (
     sixtracklib.st_OutputBuffer_calculate_output_buffer_params
+)
 st_OutputBuffer_calculate_output_buffer_params.restype = ct.c_int32
 st_OutputBuffer_calculate_output_buffer_params.argtypes = [
     st_Buffer_p,
@@ -774,29 +1172,42 @@ def st_BeamMonitor_assign_output_cbuffer(
     st_uint64_p,
     st_uint64_p,
     st_uint64_p,
-    ct.c_uint64]
+    ct.c_uint64,
+]
 
 
-st_OutputBuffer_calculate_output_buffer_params_for_particles_sets = \
+st_OutputBuffer_calculate_output_buffer_params_for_particles_sets = (
     sixtracklib.st_OutputBuffer_calculate_output_buffer_params_for_particles_sets
+)
 st_OutputBuffer_calculate_output_buffer_params_for_particles_sets.argtypes = [
-    st_Buffer_p, st_Buffer_p, ct.c_uint64, st_uint64_p, ct.c_uint64,
-    st_uint64_p, st_uint64_p, st_uint64_p, st_uint64_p, ct.c_uint64]
+    st_Buffer_p,
+    st_Buffer_p,
+    ct.c_uint64,
+    st_uint64_p,
+    ct.c_uint64,
+    st_uint64_p,
+    st_uint64_p,
+    st_uint64_p,
+    st_uint64_p,
+    ct.c_uint64,
+]
 st_OutputBuffer_calculate_output_buffer_params.restype = ct.c_int32
 
 
 def st_OutputBuffer_create_output_cbuffer(
-        beam_elements_buffer,
-        particles_buffer,
-        num_particle_sets=1,
-        indices=None,
-        until_turn_elem_by_elem=0):
+    beam_elements_buffer,
+    particles_buffer,
+    num_particle_sets=1,
+    indices=None,
+    until_turn_elem_by_elem=0,
+):
 
     ptr_particles_buffer = st_Buffer_new_mapped_on_cbuffer(particles_buffer)
     particles = st_Particles_buffer_get_particles(ptr_particles_buffer, 0)
 
-    ptr_beam_elements_buffer = \
-        st_Buffer_new_mapped_on_cbuffer(beam_elements_buffer)
+    ptr_beam_elements_buffer = st_Buffer_new_mapped_on_cbuffer(
+        beam_elements_buffer
+    )
 
     num_objects = ct.c_uint64(0)
     num_slots = ct.c_uint64(0)
@@ -806,23 +1217,35 @@ def st_OutputBuffer_create_output_cbuffer(
     until_turn_elem_by_elem = ct.c_uint64(until_turn_elem_by_elem)
 
     ret = st_OutputBuffer_calculate_output_buffer_params(
-        ptr_beam_elements_buffer, particles,
-        until_turn_elem_by_elem, ct.byref(num_objects),
-        ct.byref(num_slots), ct.byref(num_dataptrs),
-        ct.byref(num_garbage), slot_size)
+        ptr_beam_elements_buffer,
+        particles,
+        until_turn_elem_by_elem,
+        ct.byref(num_objects),
+        ct.byref(num_slots),
+        ct.byref(num_dataptrs),
+        ct.byref(num_garbage),
+        slot_size,
+    )
 
     output_buffer = None
     elem_by_elem_output_offset = -1
     beam_monitor_output_offset = -1
     min_turn_id = -1
 
-    if ret == 0 and num_objects.value > 0 and num_slots.value > 0 and \
-            num_dataptrs.value > 0 and num_garbage.value >= 0:
+    if (
+        ret == 0
+        and num_objects.value > 0
+        and num_slots.value > 0
+        and num_dataptrs.value > 0
+        and num_garbage.value >= 0
+    ):
         if output_buffer is None:
-            output_buffer = CBuffer(max_slots=num_slots.value,
-                                    max_objects=num_objects.value,
-                                    max_pointers=num_dataptrs.value,
-                                    max_garbage=num_garbage.value)
+            output_buffer = CBuffer(
+                max_slots=num_slots.value,
+                max_objects=num_objects.value,
+                max_pointers=num_dataptrs.value,
+                max_garbage=num_garbage.value,
+            )
 
         ptr_out_buffer_view = st_Buffer_new_mapped_on_cbuffer(output_buffer)
 
@@ -838,20 +1261,37 @@ def st_OutputBuffer_create_output_cbuffer(
                 until_turn_elem_by_elem,
                 ct.byref(elem_by_elem_output_offset),
                 ct.byref(beam_monitor_output_offset),
-                ct.byref(min_turn_id))
+                ct.byref(min_turn_id),
+            )
 
         st_Buffer_delete(ptr_out_buffer_view)
 
     st_Buffer_delete(ptr_beam_elements_buffer)
     st_Buffer_delete(ptr_particles_buffer)
 
-    return (output_buffer, elem_by_elem_output_offset.value,
-            beam_monitor_output_offset.value, min_turn_id.value)
+    return (
+        output_buffer,
+        elem_by_elem_output_offset.value,
+        beam_monitor_output_offset.value,
+        min_turn_id.value,
+    )
+
 
 # -----------------------------------------------------------------------------
 # TrackJob objects
 
 
+class st_TrackJobDestSrcBufferIds(ct.Structure):
+    _pack_ = 8
+    _fields_ = [
+        ("dest_buffer_id", st_buffer_size_t),
+        ("src_buffer_id", st_buffer_size_t),
+    ]
+
+
+st_TrackJobDestSrcBufferIds_p = ct.POINTER(st_TrackJobDestSrcBufferIds)
+st_NullTrackJobDestSrcBufferIds = ct.cast(0, st_TrackJobDestSrcBufferIds_p)
+
 st_TrackJob_p = ct.c_void_p
 st_NullTrackJob = ct.cast(0, st_TrackJob_p)
 
@@ -871,19 +1311,35 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJob_reset_with_output = sixtracklib.st_TrackJob_reset_with_output
 st_TrackJob_reset_with_output.restype = ct.c_bool
 st_TrackJob_reset_with_output.argtypes = [
-    st_TrackJob_p, st_Buffer, st_Buffer, st_Buffer, ct.c_uint64]
+    st_TrackJob_p,
+    st_Buffer,
+    st_Buffer,
+    st_Buffer,
+    ct.c_uint64,
+]
 
 st_TrackJob_reset_detailed = sixtracklib.st_TrackJob_reset_detailed
 st_TrackJob_reset_detailed.restype = ct.c_bool
 st_TrackJob_reset_detailed.argtypes = [
-    st_TrackJob_p, st_Buffer, ct.c_uint64, st_uint64_p, st_Buffer,
-    st_Buffer, ct.c_uint64]
+    st_TrackJob_p,
+    st_Buffer,
+    ct.c_uint64,
+    st_uint64_p,
+    st_Buffer,
+    st_Buffer,
+    ct.c_uint64,
+]
 
 
 st_TrackJob_new_with_output = sixtracklib.st_TrackJob_new_with_output
 st_TrackJob_new_with_output.argtypes = [
-    ct.c_char_p, st_Buffer_p, st_Buffer_p, st_Buffer_p,
-    ct.c_uint64, ct.c_char_p]
+    ct.c_char_p,
+    st_Buffer_p,
+    st_Buffer_p,
+    st_Buffer_p,
+    ct.c_uint64,
+    ct.c_char_p,
+]
 st_TrackJob_new_with_output.restype = st_TrackJob_p
 
 
@@ -908,7 +1364,8 @@ def st_OutputBuffer_create_output_cbuffer(
     st_TrackJob_p,
     ct.c_uint64,
     ct.c_uint64,
-    ct.c_bool]
+    ct.c_bool,
+]
 
 
 st_TrackJob_collect = sixtracklib.st_TrackJob_collect
@@ -923,7 +1380,9 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJob_collect_particles.argtypes = [st_TrackJob_p]
 st_TrackJob_collect_particles.restype = None
 
-st_TrackJob_collect_beam_elements = sixtracklib.st_TrackJob_collect_beam_elements
+st_TrackJob_collect_beam_elements = (
+    sixtracklib.st_TrackJob_collect_beam_elements
+)
 st_TrackJob_collect_beam_elements.argtypes = [st_TrackJob_p]
 st_TrackJob_collect_beam_elements.restype = None
 
@@ -931,6 +1390,11 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJob_collect_output.argtypes = [st_TrackJob_p]
 st_TrackJob_collect_output.restype = None
 
+st_TrackJob_collect_particles_addresses = \
+    sixtracklib.st_TrackJob_collect_particles_addresses
+st_TrackJob_collect_particles_addresses.argtypes = [st_TrackJob_p]
+st_TrackJob_collect_particles_addresses.restype = None
+
 st_TrackJob_requires_collecting = sixtracklib.st_TrackJob_requires_collecting
 st_TrackJob_requires_collecting.argtypes = [st_TrackJob_p]
 st_TrackJob_requires_collecting.restype = ct.c_bool
@@ -951,15 +1415,53 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJob_push_output.argtypes = [st_TrackJob_p]
 st_TrackJob_push_output.restype = None
 
-st_TrackJob_can_fetch_particle_addresses = \
-    sixtracklib.st_TrackJob_can_fetch_particle_addresses
-st_TrackJob_can_fetch_particle_addresses.argtypes = [st_TrackJob_p]
-st_TrackJob_can_fetch_particle_addresses.restype = ct.c_bool
-
-st_TrackJob_has_particle_addresses = \
-    sixtracklib.st_TrackJob_has_particle_addresses
-st_TrackJob_has_particle_addresses.argtypes = [st_TrackJob_p]
-st_TrackJob_has_particle_addresses.restype = ct.c_bool
+st_TrackJob_push_particles_addresses = \
+    sixtracklib.st_TrackJob_push_particles_addresses
+st_TrackJob_push_particles_addresses.argtypes = [st_TrackJob_p]
+st_TrackJob_push_particles_addresses.restype = None
+
+st_TrackJob_particle_addresses = sixtracklib.st_TrackJob_particle_addresses
+st_TrackJob_particle_addresses.argtypes = [st_TrackJob_p,st_buffer_size_t]
+st_TrackJob_particle_addresses.restype = st_ParticlesAddr_p
+
+st_TrackJob_can_fetch_particles_addr = \
+    sixtracklib.st_TrackJob_can_fetch_particles_addr
+st_TrackJob_can_fetch_particles_addr.argtypes = [st_TrackJob_p]
+st_TrackJob_can_fetch_particles_addr.restype = ct.c_bool
+
+st_TrackJob_has_particles_addr = \
+    sixtracklib.st_TrackJob_has_particles_addr
+st_TrackJob_has_particles_addr.argtypes = [st_TrackJob_p]
+st_TrackJob_has_particles_addr.restype = ct.c_bool
+
+st_TrackJob_fetch_particle_addresses = \
+    sixtracklib.st_TrackJob_fetch_particle_addresses
+st_TrackJob_fetch_particle_addresses.argtypes = [st_TrackJob_p]
+st_TrackJob_fetch_particle_addresses.restype  = st_arch_status_t
+
+st_TrackJob_clear_particle_addresses = \
+    sixtracklib.st_TrackJob_clear_particle_addresses
+st_TrackJob_clear_particle_addresses.argtypes = [st_TrackJob_p, st_arch_size_t]
+st_TrackJob_clear_particle_addresses.restype  = st_arch_status_t
+
+st_TrackJob_clear_all_particle_addresses = \
+    sixtracklib.st_TrackJob_clear_all_particle_addresses
+st_TrackJob_clear_all_particle_addresses.argtypes = [st_TrackJob_p]
+st_TrackJob_clear_all_particle_addresses.restype = st_arch_status_t
+
+st_TrackJob_particle_addresses = sixtracklib.st_TrackJob_particle_addresses
+st_TrackJob_particle_addresses.argtypes = [ st_TrackJob_p, st_arch_size_t]
+st_TrackJob_particle_addresses.restype = st_ParticlesAddr_p
+
+st_TrackJob_get_particles_addr_buffer = \
+    sixtracklib.st_TrackJob_get_particles_addr_buffer
+st_TrackJob_get_particles_addr_buffer.argtypes = [st_TrackJob_p]
+st_TrackJob_get_particles_addr_buffer.restype = st_Buffer_p
+
+st_TrackJob_get_const_particles_addr_buffer = \
+    sixtracklib.st_TrackJob_get_const_particles_addr_buffer
+st_TrackJob_get_const_particles_addr_buffer.argtypes = [st_TrackJob_p]
+st_TrackJob_get_const_particles_addr_buffer.restype = st_Buffer_p
 
 st_TrackJob_get_type_id = sixtracklib.st_TrackJob_get_type_id
 st_TrackJob_get_type_id.argtypes = [st_TrackJob_p]
@@ -986,39 +1488,372 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJob_get_output_buffer.restype = st_Buffer_p
 
 
-st_TrackJob_has_elem_by_elem_output = \
+st_TrackJob_has_elem_by_elem_output = (
     sixtracklib.st_TrackJob_has_elem_by_elem_output
+)
 st_TrackJob_has_elem_by_elem_output.argtypes = [st_TrackJob_p]
 st_TrackJob_has_elem_by_elem_output.restype = ct.c_bool
 
 
-st_TrackJob_get_elem_by_elem_output_buffer_offset = \
+st_TrackJob_get_elem_by_elem_output_buffer_offset = (
     sixtracklib.st_TrackJob_get_elem_by_elem_output_buffer_offset
+)
 st_TrackJob_get_elem_by_elem_output_buffer_offset.argtypes = [st_TrackJob_p]
 st_TrackJob_get_elem_by_elem_output_buffer_offset.restype = ct.c_uint64
 
 
-st_TrackJob_has_beam_monitor_output = \
+st_TrackJob_has_beam_monitor_output = (
     sixtracklib.st_TrackJob_has_beam_monitor_output
+)
 st_TrackJob_has_beam_monitor_output.argtypes = [st_TrackJob_p]
 st_TrackJob_has_beam_monitor_output.restype = ct.c_bool
 
 
-st_TrackJob_get_num_beam_monitors = \
+st_TrackJob_get_num_beam_monitors = (
     sixtracklib.st_TrackJob_get_num_beam_monitors
+)
 st_TrackJob_get_num_beam_monitors.argtypes = [st_TrackJob_p]
 st_TrackJob_get_num_beam_monitors.restype = ct.c_uint64
 
 
-st_TrackJob_get_beam_monitor_output_buffer_offset = \
+st_TrackJob_get_beam_monitor_output_buffer_offset = (
     sixtracklib.st_TrackJob_get_beam_monitor_output_buffer_offset
+)
 st_TrackJob_get_beam_monitor_output_buffer_offset.argtypes = [st_TrackJob_p]
 st_TrackJob_get_beam_monitor_output_buffer_offset.restype = ct.c_uint64
 
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+st_TrackJob_can_fetch_particles_addr = (
+    sixtracklib.st_TrackJob_can_fetch_particles_addr
+)
+st_TrackJob_can_fetch_particles_addr.argtypes = [st_TrackJob_p]
+st_TrackJob_can_fetch_particles_addr.restype = ct.c_bool
+
+st_TrackJob_has_particles_addr = sixtracklib.st_TrackJob_has_particles_addr
+st_TrackJob_has_particles_addr.argtypes = [st_TrackJob_p]
+st_TrackJob_has_particles_addr.restype = ct.c_bool
+
+st_TrackJob_fetch_particles_addr = sixtracklib.st_TrackJob_fetch_particles_addr
+st_TrackJob_fetch_particles_addr.argtypes = [st_TrackJob_p]
+st_TrackJob_fetch_particles_addr.restype = st_arch_status_t
+
+st_TrackJob_clear_particles_addr = sixtracklib.st_TrackJob_clear_particles_addr
+st_TrackJob_clear_particles_addr.argtypes = [st_TrackJob_p, st_buffer_size_t]
+st_TrackJob_clear_particles_addr.restype = st_arch_status_t
+
+st_TrackJob_clear_all_particles_addr = (
+    sixtracklib.st_TrackJob_clear_all_particles_addr
+)
+st_TrackJob_clear_all_particles_addr.argtypes = [st_TrackJob_p]
+st_TrackJob_clear_all_particles_addr.restype = st_arch_status_t
+
+st_TrackJob_particles_addr = sixtracklib.st_TrackJob_particles_addr
+st_TrackJob_particles_addr.argtypes = [st_TrackJob_p, st_buffer_size_t]
+st_TrackJob_particles_addr.restype = st_ParticlesAddr_p
+
+st_TrackJob_particles_addr_buffer = (
+    sixtracklib.st_TrackJob_particles_addr_buffer
+)
+st_TrackJob_particles_addr_buffer.argtypes = [st_TrackJob_p]
+st_TrackJob_particles_addr_buffer.restype = st_Buffer_p
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+st_TrackJob_stored_buffers_capacity = (
+    sixtracklib.st_TrackJob_stored_buffers_capacity
+)
+st_TrackJob_stored_buffers_capacity.argtypes = [st_TrackJob_p]
+st_TrackJob_stored_buffers_capacity.restype = st_arch_size_t
+
+st_TrackJob_reserve_stored_buffers_capacity = (
+    sixtracklib.st_TrackJob_reserve_stored_buffers_capacity
+)
+st_TrackJob_reserve_stored_buffers_capacity.argtypes = [st_TrackJob_p]
+st_TrackJob_reserve_stored_buffers_capacity.restype = st_arch_status_t
+
+st_TrackJob_has_stored_buffers = sixtracklib.st_TrackJob_has_stored_buffers
+st_TrackJob_has_stored_buffers.argtypes = [st_TrackJob_p]
+st_TrackJob_has_stored_buffers.restype = ct.c_bool
+
+st_TrackJob_num_stored_buffers = sixtracklib.st_TrackJob_num_stored_buffers
+st_TrackJob_num_stored_buffers.argtypes = [st_TrackJob_p]
+st_TrackJob_num_stored_buffers.restype = st_arch_size_t
+
+st_TrackJob_min_stored_buffer_id = sixtracklib.st_TrackJob_min_stored_buffer_id
+st_TrackJob_min_stored_buffer_id.argtypes = [st_TrackJob_p]
+st_TrackJob_min_stored_buffer_id.restype = st_arch_size_t
+
+st_TrackJob_max_stored_buffer_id = sixtracklib.st_TrackJob_max_stored_buffer_id
+st_TrackJob_max_stored_buffer_id.argtypes = [st_TrackJob_p]
+st_TrackJob_max_stored_buffer_id.restype = st_arch_size_t
+
+st_TrackJob_create_stored_buffer = sixtracklib.st_TrackJob_create_stored_buffer
+st_TrackJob_create_stored_buffer.argtypes = [st_TrackJob_p, st_buffer_size_t]
+st_TrackJob_create_stored_buffer.restype = st_arch_size_t
+
+st_TrackJob_add_stored_buffer = sixtracklib.st_TrackJob_add_stored_buffer
+st_TrackJob_add_stored_buffer.argtypes = [
+    st_TrackJob_p,
+    st_Buffer_p,
+    ct.c_bool,
+    ct.c_bool,
+]
+st_TrackJob_add_stored_buffer.restype = st_arch_size_t
+
+st_TrackJob_owns_stored_buffer = sixtracklib.st_TrackJob_owns_stored_buffer
+st_TrackJob_owns_stored_buffer.argtypes = [st_TrackJob_p, st_arch_size_t]
+st_TrackJob_owns_stored_buffer.restype = ct.c_bool
+
+st_TrackJob_remove_stored_buffer = sixtracklib.st_TrackJob_remove_stored_buffer
+st_TrackJob_remove_stored_buffer.argtypes = [st_TrackJob_p, st_arch_size_t]
+st_TrackJob_remove_stored_buffer.restype = st_arch_status_t
+
+st_TrackJob_stored_buffer = sixtracklib.st_TrackJob_stored_buffer
+st_TrackJob_stored_buffer.argtypes = [st_TrackJob_p, st_arch_size_t]
+st_TrackJob_stored_buffer.restype = st_Buffer_p
+
+st_TrackJob_const_stored_buffer = sixtracklib.st_TrackJob_const_stored_buffer
+st_TrackJob_const_stored_buffer.argtypes = [st_TrackJob_p, st_arch_size_t]
+st_TrackJob_const_stored_buffer.restype = st_Buffer_p
+
+st_TrackJob_push_stored_buffer = sixtracklib.st_TrackJob_push_stored_buffer
+st_TrackJob_push_stored_buffer.argtypes = [st_TrackJob_p, st_arch_size_t]
+st_TrackJob_push_stored_buffer.restype = st_arch_status_t
+
+st_TrackJob_collect_stored_buffer = (
+    sixtracklib.st_TrackJob_collect_stored_buffer
+)
+st_TrackJob_collect_stored_buffer.argtypes = [st_TrackJob_p, st_arch_size_t]
+st_TrackJob_collect_stored_buffer.restype = st_arch_status_t
+
+# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+st_TrackJob_add_assign_address_item = (
+    sixtracklib.st_TrackJob_add_assign_address_item
+)
+st_TrackJob_add_assign_address_item.argtypes = [
+    st_TrackJob_p,
+    st_AssignAddressItem_p,
+]
+st_TrackJob_add_assign_address_item.restype = st_AssignAddressItem_p
+
+st_TrackJob_add_assign_address_item_detailed = (
+    sixtracklib.st_TrackJob_add_assign_address_item_detailed
+)
+st_TrackJob_add_assign_address_item_detailed.argtypes = [
+    st_TrackJob_p,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_add_assign_address_item_detailed.restype = st_AssignAddressItem_p
+
+# st_TrackJob_remove_assign_address_item = sixtracklib.st_TrackJob_remove_assign_address_item
+# st_TrackJob_remove_assign_address_item.argtypes = [ st_TrackJob_p, st_AssignAddressItem_p ]
+# st_TrackJob_remove_assign_address_item.restype = st_arch_status_t
+
+# st_TrackJob_remove_assign_address_item_by_key_and_index = sixtracklib.st_TrackJob_remove_assign_address_item_by_key_and_index
+# st_TrackJob_remove_assign_address_item_by_key_and_index.argtypes = [
+# st_TrackJob_p, st_TrackJobDestSrcBufferIds_p, st_buffer_size_t ]
+# st_TrackJob_remove_assign_address_item_by_key_and_index.restype = st_arch_status_t
+
+st_TrackJob_has_assign_address_item = (
+    sixtracklib.st_TrackJob_has_assign_address_item
+)
+st_TrackJob_has_assign_address_item.argtypes = [
+    st_TrackJob_p,
+    st_AssignAddressItem_p,
+]
+st_TrackJob_has_assign_address_item.restype = ct.c_bool
+
+st_TrackJob_has_assign_item_by_index = (
+    sixtracklib.st_TrackJob_has_assign_item_by_index
+)
+st_TrackJob_has_assign_item_by_index.argtypes = [
+    st_TrackJob_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_has_assign_item_by_index.restype = ct.c_bool
+
+st_TrackJob_has_assign_address_item_detailed = (
+    sixtracklib.st_TrackJob_has_assign_address_item_detailed
+)
+st_TrackJob_has_assign_address_item_detailed.argtypes = [
+    st_TrackJob_p,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_has_assign_address_item_detailed.restype = ct.c_bool
+
+
+st_TrackJob_index_of_assign_address_item_detailed = (
+    sixtracklib.st_TrackJob_index_of_assign_address_item_detailed
+)
+st_TrackJob_index_of_assign_address_item_detailed.argtypes = [
+    st_TrackJob_p,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_index_of_assign_address_item_detailed.restype = st_buffer_size_t
+
+st_TrackJob_index_of_assign_address_item = (
+    sixtracklib.st_TrackJob_index_of_assign_address_item
+)
+st_TrackJob_index_of_assign_address_item.argtypes = [
+    st_TrackJob_p,
+    st_AssignAddressItem_p,
+]
+st_TrackJob_index_of_assign_address_item.restype = st_buffer_size_t
+
+st_TrackJob_has_assign_items = sixtracklib.st_TrackJob_has_assign_items
+st_TrackJob_has_assign_items.argtypes = [
+    st_TrackJob_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_has_assign_items.restype = ct.c_bool
+
+st_TrackJob_num_assign_items = sixtracklib.st_TrackJob_num_assign_items
+st_TrackJob_num_assign_items.argtypes = [
+    st_TrackJob_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_num_assign_items.restype = st_buffer_size_t
+
+st_TrackJob_total_num_assign_items = (
+    sixtracklib.st_TrackJob_total_num_assign_items
+)
+st_TrackJob_total_num_assign_items.argtypes = [st_TrackJob_p]
+st_TrackJob_total_num_assign_items.restype = st_buffer_size_t
+
+st_TrackJob_ptr_assign_address_item = (
+    sixtracklib.st_TrackJob_ptr_assign_address_item
+)
+st_TrackJob_ptr_assign_address_item.argtypes = [
+    st_TrackJob_p,
+    st_AssignAddressItem_p,
+]
+st_TrackJob_ptr_assign_address_item.restype = st_AssignAddressItem_p
+
+st_TrackJob_ptr_assign_address_item_by_index = (
+    sixtracklib.st_TrackJob_ptr_assign_address_item_by_index
+)
+st_TrackJob_ptr_assign_address_item_by_index.argtypes = [
+    st_TrackJob_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_ptr_assign_address_item_by_index.restype = st_AssignAddressItem_p
+
+st_TrackJob_ptr_assign_address_item_detailed = (
+    sixtracklib.st_TrackJob_ptr_assign_address_item_detailed
+)
+st_TrackJob_ptr_assign_address_item_detailed.argtypes = [
+    st_TrackJob_p,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_ptr_assign_address_item_detailed.restype = st_AssignAddressItem_p
+
+st_TrackJob_num_distinct_available_assign_address_items_dest_src_pairs = (
+    sixtracklib.st_TrackJob_num_distinct_available_assign_address_items_dest_src_pairs
+)
+st_TrackJob_num_distinct_available_assign_address_items_dest_src_pairs.argtypes = [
+    st_TrackJob_p
+]
+st_TrackJob_num_distinct_available_assign_address_items_dest_src_pairs.restype = (
+    st_buffer_size_t
+)
+
+st_TrackJob_available_assign_address_items_dest_src_pairs = (
+    sixtracklib.st_TrackJob_available_assign_address_items_dest_src_pairs
+)
+st_TrackJob_available_assign_address_items_dest_src_pairs.argtypes = [
+    st_TrackJob_p,
+    st_buffer_size_t,
+    st_TrackJobDestSrcBufferIds_p,
+]
+st_TrackJob_available_assign_address_items_dest_src_pairs.restype = (
+    st_buffer_size_t
+)
+
+st_TrackJob_buffer_by_buffer_id = sixtracklib.st_TrackJob_buffer_by_buffer_id
+st_TrackJob_buffer_by_buffer_id.argtypes = [st_TrackJob_p, st_buffer_size_t]
+st_TrackJob_buffer_by_buffer_id.restype = st_Buffer_p
+
+st_TrackJob_const_buffer_by_buffer_id = (
+    sixtracklib.st_TrackJob_const_buffer_by_buffer_id
+)
+st_TrackJob_const_buffer_by_buffer_id.argtypes = [
+    st_TrackJob_p,
+    st_buffer_size_t,
+]
+st_TrackJob_const_buffer_by_buffer_id.restype = st_Buffer_p
+
+st_TrackJob_is_buffer_by_buffer_id = (
+    sixtracklib.st_TrackJob_is_buffer_by_buffer_id
+)
+st_TrackJob_is_buffer_by_buffer_id.argtypes = [st_TrackJob_p, st_buffer_size_t]
+st_TrackJob_is_buffer_by_buffer_id.restype = ct.c_bool
+
+st_TrackJob_is_raw_memory_by_buffer_id = (
+    sixtracklib.st_TrackJob_is_raw_memory_by_buffer_id
+)
+st_TrackJob_is_raw_memory_by_buffer_id.argtypes = [
+    st_TrackJob_p,
+    st_buffer_size_t,
+]
+st_TrackJob_is_raw_memory_by_buffer_id.restype = ct.c_bool
+
+st_TrackJob_commit_address_assignments = (
+    sixtracklib.st_TrackJob_commit_address_assignments
+)
+st_TrackJob_commit_address_assignments.argtypes = [st_TrackJob_p]
+st_TrackJob_commit_address_assignments.restype = st_arch_status_t
+
+st_TrackJob_assign_all_addresses = sixtracklib.st_TrackJob_assign_all_addresses
+st_TrackJob_assign_all_addresses.argtypes = [st_TrackJob_p]
+st_TrackJob_assign_all_addresses.restype = st_arch_status_t
+
+st_TrackJob_assign_addresses = sixtracklib.st_TrackJob_assign_addresses
+st_TrackJob_assign_addresses.argtypes = [
+    st_TrackJob_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJob_assign_addresses.restype = st_arch_status_t
+
 # ==============================================================================
 # sixtracklib/control, sixtracklib/track API:
 
-st_arch_id_t = ct.c_uint64
 st_node_platform_id_t = ct.c_int64
 st_node_device_id_t = ct.c_int64
 st_node_index_t = ct.c_uint32
@@ -1043,7 +1878,10 @@ def st_OutputBuffer_create_output_cbuffer(
 
 st_NodeId_new_detailed = sixtracklib.st_NodeId_new_detailed
 st_NodeId_new_detailed.argtypes = [
-    st_node_platform_id_t, st_node_device_id_t, st_node_index_t]
+    st_node_platform_id_t,
+    st_node_device_id_t,
+    st_node_index_t,
+]
 st_NodeId_new_detailed.restype = st_NodeId_p
 
 st_NodeId_delete = sixtracklib.st_NodeId_delete
@@ -1081,7 +1919,11 @@ def st_OutputBuffer_create_output_cbuffer(
 
 st_NodeId_reset = sixtracklib.st_NodeId_reset
 st_NodeId_reset.argtypes = [
-    st_NodeId_p, st_node_platform_id_t, st_node_device_id_t, st_node_index_t]
+    st_NodeId_p,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+    st_node_index_t,
+]
 
 _st_NodeId_to_string = sixtracklib.st_NodeId_to_string
 _st_NodeId_to_string.argtypes = [st_NodeId_p, ct.c_char_p, st_buffer_size_t]
@@ -1109,8 +1951,9 @@ def st_OutputBuffer_create_output_cbuffer(
 st_NodeInfo_delete.argtypes = [st_NodeInfoBase_p]
 st_NodeInfo_delete.restype = None
 
-st_NodeInfo_get_ptr_const_node_id = \
+st_NodeInfo_get_ptr_const_node_id = (
     sixtracklib.st_NodeInfo_get_ptr_const_node_id
+)
 st_NodeInfo_get_ptr_const_node_id.argtypes = [st_NodeInfoBase_p]
 st_NodeInfo_get_ptr_const_node_id.restype = st_NodeId_p
 
@@ -1178,14 +2021,18 @@ def st_OutputBuffer_create_output_cbuffer(
 st_NodeInfo_print_out.argtypes = [st_NodeInfoBase_p]
 st_NodeInfo_print_out.restype = None
 
-st_NodeInfo_get_required_output_str_length = \
+st_NodeInfo_get_required_output_str_length = (
     sixtracklib.st_NodeInfo_get_required_output_str_length
+)
 st_NodeInfo_get_required_output_str_length.argtypes = [st_NodeInfoBase_p]
 st_NodeInfo_get_required_output_str_length.restype = st_arch_size_t
 
 _st_NodeInfo_convert_to_string = sixtracklib.st_NodeInfo_convert_to_string
 _st_NodeInfo_convert_to_string.argtypes = [
-    st_NodeInfoBase_p, st_arch_size_t, ct.c_char_p]
+    st_NodeInfoBase_p,
+    st_arch_size_t,
+    ct.c_char_p,
+]
 _st_NodeInfo_convert_to_string.restype = st_arch_status_t
 
 # -----------------------------------------------------------------------------
@@ -1213,8 +2060,9 @@ def st_OutputBuffer_create_output_cbuffer(
 st_KernelConfig_has_arch_string.argtypes = [st_KernelConfigBase_p]
 st_KernelConfig_has_arch_string.restype = ct.c_bool
 
-_st_KernelConfig_get_ptr_arch_string = \
+_st_KernelConfig_get_ptr_arch_string = (
     sixtracklib.st_KernelConfig_get_ptr_arch_string
+)
 _st_KernelConfig_get_ptr_arch_string.argtypes = [st_KernelConfigBase_p]
 _st_KernelConfig_get_ptr_arch_string.restype = ct.c_char_p
 
@@ -1232,159 +2080,235 @@ def st_OutputBuffer_create_output_cbuffer(
 st_KernelConfig_has_name.argtypes = [st_KernelConfigBase_p]
 st_KernelConfig_has_name.restype = ct.c_bool
 
-_st_KernelConfig_get_ptr_name_string = \
+_st_KernelConfig_get_ptr_name_string = (
     sixtracklib.st_KernelConfig_get_ptr_name_string
+)
 _st_KernelConfig_get_ptr_name_string.argtypes = [st_KernelConfigBase_p]
 _st_KernelConfig_get_ptr_name_string.restype = ct.c_char_p
 
-st_KernelConfig_get_num_arguments = \
+st_KernelConfig_get_num_arguments = (
     sixtracklib.st_KernelConfig_get_num_arguments
+)
 st_KernelConfig_get_num_arguments.argtypes = [st_KernelConfigBase_p]
 st_KernelConfig_get_num_arguments.restype = st_ctrl_size_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_KernelConfig_get_work_items_dim = \
+st_KernelConfig_get_work_items_dim = (
     sixtracklib.st_KernelConfig_get_work_items_dim
+)
 st_KernelConfig_get_work_items_dim.argtypes = [st_KernelConfigBase_p]
 st_KernelConfig_get_work_items_dim.restype = st_ctrl_size_t
 
-st_KernelConfig_get_num_work_items_by_dim = \
+st_KernelConfig_get_num_work_items_by_dim = (
     sixtracklib.st_KernelConfig_get_num_work_items_by_dim
+)
 st_KernelConfig_get_num_work_items_by_dim.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+]
 st_KernelConfig_get_num_work_items_by_dim.restype = st_ctrl_size_t
 
-st_KernelConfig_get_total_num_work_items = \
+st_KernelConfig_get_total_num_work_items = (
     sixtracklib.st_KernelConfig_get_total_num_work_items
+)
 st_KernelConfig_get_total_num_work_items.argtypes = [st_KernelConfigBase_p]
 st_KernelConfig_get_total_num_work_items.restype = st_ctrl_size_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_KernelConfig_set_num_work_items_1d = \
+st_KernelConfig_set_num_work_items_1d = (
     sixtracklib.st_KernelConfig_set_num_work_items_1d
+)
 st_KernelConfig_set_num_work_items_1d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_num_work_items_1d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_num_work_items_2d = \
+st_KernelConfig_set_num_work_items_2d = (
     sixtracklib.st_KernelConfig_set_num_work_items_2d
+)
 st_KernelConfig_set_num_work_items_2d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_num_work_items_2d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_num_work_items_3d = \
+st_KernelConfig_set_num_work_items_3d = (
     sixtracklib.st_KernelConfig_set_num_work_items_3d
+)
 st_KernelConfig_set_num_work_items_3d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_num_work_items_3d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_num_work_items = \
+st_KernelConfig_set_num_work_items = (
     sixtracklib.st_KernelConfig_set_num_work_items
+)
 st_KernelConfig_set_num_work_items.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t_p]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t_p,
+]
 st_KernelConfig_set_num_work_items.restype = st_ctrl_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_KernelConfig_get_work_item_offset_by_dim = \
+st_KernelConfig_get_work_item_offset_by_dim = (
     sixtracklib.st_KernelConfig_get_work_item_offset_by_dim
-st_KernelConfig_get_work_item_offset_by_dim.argtypes = [
-    st_KernelConfigBase_p]
+)
+st_KernelConfig_get_work_item_offset_by_dim.argtypes = [st_KernelConfigBase_p]
 st_KernelConfig_get_work_item_offset_by_dim.restype = st_ctrl_size_t
 
-st_KernelConfig_set_work_item_offset_1d = \
+st_KernelConfig_set_work_item_offset_1d = (
     sixtracklib.st_KernelConfig_set_work_item_offset_1d
+)
 st_KernelConfig_set_work_item_offset_1d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_work_item_offset_1d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_work_item_offset_2d = \
+st_KernelConfig_set_work_item_offset_2d = (
     sixtracklib.st_KernelConfig_set_work_item_offset_2d
+)
 st_KernelConfig_set_work_item_offset_2d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_work_item_offset_2d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_work_item_offset_3d = \
+st_KernelConfig_set_work_item_offset_3d = (
     sixtracklib.st_KernelConfig_set_work_item_offset_3d
+)
 st_KernelConfig_set_work_item_offset_3d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_work_item_offset_3d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_work_item_offset = \
+st_KernelConfig_set_work_item_offset = (
     sixtracklib.st_KernelConfig_set_work_item_offset
+)
 st_KernelConfig_set_work_item_offset.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t_p]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t_p,
+]
 st_KernelConfig_set_work_item_offset.restype = st_ctrl_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_KernelConfig_get_work_group_size_by_dim = \
+st_KernelConfig_get_work_group_size_by_dim = (
     sixtracklib.st_KernelConfig_get_work_group_size_by_dim
+)
 st_KernelConfig_get_work_group_size_by_dim.argtypes = [st_KernelConfigBase_p]
 st_KernelConfig_get_work_group_size_by_dim.restype = st_ctrl_size_t
 
-st_KernelConfig_get_work_groups_dim = \
+st_KernelConfig_get_work_groups_dim = (
     sixtracklib.st_KernelConfig_get_work_groups_dim
+)
 st_KernelConfig_get_work_groups_dim.argtypes = [st_KernelConfigBase_p]
 st_KernelConfig_get_work_groups_dim.restype = st_ctrl_size_t
 
-st_KernelConfig_set_work_group_sizes_1d = \
+st_KernelConfig_set_work_group_sizes_1d = (
     sixtracklib.st_KernelConfig_set_work_group_sizes_1d
+)
 st_KernelConfig_set_work_group_sizes_1d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_work_group_sizes_1d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_work_group_sizes_2d = \
+st_KernelConfig_set_work_group_sizes_2d = (
     sixtracklib.st_KernelConfig_set_work_group_sizes_2d
+)
 st_KernelConfig_set_work_group_sizes_2d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_work_group_sizes_2d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_work_group_sizes_3d = \
+st_KernelConfig_set_work_group_sizes_3d = (
     sixtracklib.st_KernelConfig_set_work_group_sizes_3d
+)
 st_KernelConfig_set_work_group_sizes_3d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_work_group_sizes_3d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_work_group_sizes = \
+st_KernelConfig_set_work_group_sizes = (
     sixtracklib.st_KernelConfig_set_work_group_sizes
+)
 st_KernelConfig_set_work_group_sizes.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t_p]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t_p,
+]
 st_KernelConfig_set_work_group_sizes.restype = st_ctrl_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_KernelConfig_get_preferred_work_group_multiple_by_dim = \
+st_KernelConfig_get_preferred_work_group_multiple_by_dim = (
     sixtracklib.st_KernelConfig_get_preferred_work_group_multiple_by_dim
+)
 st_KernelConfig_get_preferred_work_group_multiple_by_dim.argtypes = [
-    st_KernelConfigBase_p]
-st_KernelConfig_get_preferred_work_group_multiple_by_dim.restype = \
+    st_KernelConfigBase_p
+]
+st_KernelConfig_get_preferred_work_group_multiple_by_dim.restype = (
     st_ctrl_size_t
+)
 
-st_KernelConfig_set_preferred_work_group_multiple_1d = \
+st_KernelConfig_set_preferred_work_group_multiple_1d = (
     sixtracklib.st_KernelConfig_set_preferred_work_group_multiple_1d
+)
 st_KernelConfig_set_preferred_work_group_multiple_1d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_preferred_work_group_multiple_1d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_preferred_work_group_multiple_2d = \
+st_KernelConfig_set_preferred_work_group_multiple_2d = (
     sixtracklib.st_KernelConfig_set_preferred_work_group_multiple_2d
+)
 st_KernelConfig_set_preferred_work_group_multiple_2d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_preferred_work_group_multiple_2d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_preferred_work_group_multiple_3d = \
+st_KernelConfig_set_preferred_work_group_multiple_3d = (
     sixtracklib.st_KernelConfig_set_preferred_work_group_multiple_3d
+)
 st_KernelConfig_set_preferred_work_group_multiple_3d.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_set_preferred_work_group_multiple_3d.restype = st_ctrl_status_t
 
-st_KernelConfig_set_preferred_work_group_multiple = \
+st_KernelConfig_set_preferred_work_group_multiple = (
     sixtracklib.st_KernelConfig_set_preferred_work_group_multiple
+)
 st_KernelConfig_set_preferred_work_group_multiple.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t_p]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t_p,
+]
 st_KernelConfig_set_preferred_work_group_multiple.restype = st_ctrl_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1395,7 +2319,10 @@ def st_OutputBuffer_create_output_cbuffer(
 
 st_KernelConfig_reset = sixtracklib.st_KernelConfig_reset
 st_KernelConfig_reset.argtypes = [
-    st_KernelConfigBase_p, st_ctrl_size_t, st_ctrl_size_t]
+    st_KernelConfigBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t,
+]
 st_KernelConfig_reset.restype = None
 
 st_KernelConfig_needs_update = sixtracklib.st_KernelConfig_needs_update
@@ -1462,12 +2389,16 @@ def st_OutputBuffer_create_output_cbuffer(
     st_ControllerBase_p,
     st_ArgumentBase_p,
     ct.c_void_p,
-    st_arch_size_t]
+    st_arch_size_t,
+]
 st_Controller_send_detailed.restype = st_arch_status_t
 
 st_Controller_send_buffer = sixtracklib.st_Controller_send_buffer
-st_Controller_send_buffer.argtypes = [st_ControllerBase_p,
-                                      st_ArgumentBase_p, st_Buffer_p]
+st_Controller_send_buffer.argtypes = [
+    st_ControllerBase_p,
+    st_ArgumentBase_p,
+    st_Buffer_p,
+]
 st_Controller_send_buffer.restype = st_arch_status_t
 
 st_Controller_receive_detailed = sixtracklib.st_Controller_receive_detailed
@@ -1475,30 +2406,41 @@ def st_OutputBuffer_create_output_cbuffer(
     st_ControllerBase_p,
     ct.c_void_p,
     st_arch_size_t,
-    st_ArgumentBase_p]
+    st_ArgumentBase_p,
+]
 st_Controller_receive_detailed.restype = st_arch_status_t
 
 st_Controller_receive_buffer = sixtracklib.st_Controller_receive_buffer
-st_Controller_receive_buffer.argtypes = [st_ControllerBase_p, st_Buffer_p,
-                                         st_ArgumentBase_p]
+st_Controller_receive_buffer.argtypes = [
+    st_ControllerBase_p,
+    st_Buffer_p,
+    st_ArgumentBase_p,
+]
 st_Controller_receive_buffer.restype = st_arch_status_t
 
-st_Controller_is_cobjects_buffer_arg_remapped = \
+st_Controller_is_cobjects_buffer_arg_remapped = (
     sixtracklib.st_Controller_is_cobjects_buffer_arg_remapped
-st_Controller_is_cobjects_buffer_arg_remapped.argtypes = [st_ControllerBase_p,
-                                                          st_ArgumentBase_p]
+)
+st_Controller_is_cobjects_buffer_arg_remapped.argtypes = [
+    st_ControllerBase_p,
+    st_ArgumentBase_p,
+]
 st_Controller_is_cobjects_buffer_arg_remapped.restype = ct.c_bool
 
-st_Controller_remap_cobjects_buffer_arg = \
+st_Controller_remap_cobjects_buffer_arg = (
     sixtracklib.st_Controller_remap_cobjects_buffer_arg
-st_Controller_remap_cobjects_buffer_arg.argtypes = [st_ControllerBase_p,
-                                                    st_ArgumentBase_p]
+)
+st_Controller_remap_cobjects_buffer_arg.argtypes = [
+    st_ControllerBase_p,
+    st_ArgumentBase_p,
+]
 st_Controller_remap_cobjects_buffer_arg.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_is_ready_to_run_kernel = \
+st_Controller_is_ready_to_run_kernel = (
     sixtracklib.st_Controller_is_ready_to_run_kernel
+)
 st_Controller_is_ready_to_run_kernel.argtypes = [st_ControllerBase_p]
 st_Controller_is_ready_to_run_kernel.restype = ct.c_bool
 
@@ -1510,13 +2452,13 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Controller_is_ready_to_send.argtypes = [st_ControllerBase_p]
 st_Controller_is_ready_to_send.restype = ct.c_bool
 
-st_Controller_is_ready_to_receive = \
+st_Controller_is_ready_to_receive = (
     sixtracklib.st_Controller_is_ready_to_receive
+)
 st_Controller_is_ready_to_receive.argtypes = [st_ControllerBase_p]
 st_Controller_is_ready_to_receive.restype = ct.c_bool
 
-st_Controller_is_in_debug_mode = \
-    sixtracklib.st_Controller_is_in_debug_mode
+st_Controller_is_in_debug_mode = sixtracklib.st_Controller_is_in_debug_mode
 st_Controller_is_in_debug_mode.argtypes = [st_ControllerBase_p]
 st_Controller_is_in_debug_mode.restype = ct.c_bool
 
@@ -1534,108 +2476,137 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Controller_get_num_of_kernels.argtypes = [st_ControllerBase_p]
 st_Controller_get_num_of_kernels.restype = st_arch_size_t
 
-st_Controller_get_kernel_work_items_dim = \
+st_Controller_get_kernel_work_items_dim = (
     sixtracklib.st_Controller_get_kernel_work_items_dim
-st_Controller_get_kernel_work_items_dim.argtypes = [st_ControllerBase_p,
-                                                    st_kernel_id_t]
+)
+st_Controller_get_kernel_work_items_dim.argtypes = [
+    st_ControllerBase_p,
+    st_kernel_id_t,
+]
 st_Controller_get_kernel_work_items_dim.restype = st_arch_size_t
 
-st_Controller_get_kernel_work_groups_dim = \
-    sixtracklib. st_Controller_get_kernel_work_groups_dim
-st_Controller_get_kernel_work_groups_dim.argtypes = [st_ControllerBase_p,
-                                                     st_kernel_id_t]
+st_Controller_get_kernel_work_groups_dim = (
+    sixtracklib.st_Controller_get_kernel_work_groups_dim
+)
+st_Controller_get_kernel_work_groups_dim.argtypes = [
+    st_ControllerBase_p,
+    st_kernel_id_t,
+]
 st_Controller_get_kernel_work_groups_dim.restype = st_arch_size_t
 
-st_Controller_get_num_of_kernel_arguments = \
+st_Controller_get_num_of_kernel_arguments = (
     sixtracklib.st_Controller_get_num_of_kernel_arguments
-st_Controller_get_num_of_kernel_arguments.argtypes = [st_ControllerBase_p,
-                                                      st_kernel_id_t]
+)
+st_Controller_get_num_of_kernel_arguments.argtypes = [
+    st_ControllerBase_p,
+    st_kernel_id_t,
+]
 st_Controller_get_num_of_kernel_arguments.restype = st_arch_size_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 st_Controller_kernel_has_name = sixtracklib.st_Controller_kernel_has_name
-st_Controller_kernel_has_name.argtypes = [st_ControllerBase_p,
-                                          st_kernel_id_t]
+st_Controller_kernel_has_name.argtypes = [st_ControllerBase_p, st_kernel_id_t]
 st_Controller_kernel_has_name.restype = ct.c_bool
 
-st_Controller_get_kernel_name_string = \
+st_Controller_get_kernel_name_string = (
     sixtracklib.st_Controller_get_kernel_name_string
-st_Controller_get_kernel_name_string.argtypes = [st_ControllerBase_p,
-                                                 st_kernel_id_t]
+)
+st_Controller_get_kernel_name_string.argtypes = [
+    st_ControllerBase_p,
+    st_kernel_id_t,
+]
 st_Controller_get_kernel_name_string.restype = ct.c_char_p
 
 st_Controller_has_kernel_id = sixtracklib.st_Controller_has_kernel_id
-st_Controller_has_kernel_id.argtypes = [st_ControllerBase_p,
-                                        st_kernel_id_t]
+st_Controller_has_kernel_id.argtypes = [st_ControllerBase_p, st_kernel_id_t]
 st_Controller_has_kernel_id.restype = ct.c_bool
 
 st_Controller_has_kernel_by_name = sixtracklib.st_Controller_has_kernel_by_name
-st_Controller_has_kernel_by_name.argtypes = [st_ControllerBase_p,
-                                             ct.c_char_p]
+st_Controller_has_kernel_by_name.argtypes = [st_ControllerBase_p, ct.c_char_p]
 st_Controller_has_kernel_by_name.restype = ct.c_bool
 
-st_Controller_get_ptr_kernel_config_base = \
+st_Controller_get_ptr_kernel_config_base = (
     sixtracklib.st_Controller_get_ptr_kernel_config_base
-st_Controller_get_ptr_kernel_config_base.argtypes = [st_ControllerBase_p,
-                                                     st_kernel_id_t]
+)
+st_Controller_get_ptr_kernel_config_base.argtypes = [
+    st_ControllerBase_p,
+    st_kernel_id_t,
+]
 st_Controller_get_ptr_kernel_config_base.restype = st_KernelConfigBase_p
 
-st_Controller_get_ptr_kernel_config_base_by_name = \
+st_Controller_get_ptr_kernel_config_base_by_name = (
     sixtracklib.st_Controller_get_ptr_kernel_config_base_by_name
+)
 st_Controller_get_ptr_kernel_config_base_by_name.argtypes = [
-    st_ControllerBase_p, ct.c_char_p]
+    st_ControllerBase_p,
+    ct.c_char_p,
+]
 st_Controller_get_ptr_kernel_config_base_by_name.restype = st_KernelConfigBase_p
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_has_remap_cobject_buffer_kernel = \
+st_Controller_has_remap_cobject_buffer_kernel = (
     sixtracklib.st_Controller_has_remap_cobject_buffer_kernel
+)
 st_Controller_has_remap_cobject_buffer_kernel.argtypes = [st_ControllerBase_p]
 st_Controller_has_remap_cobject_buffer_kernel.restype = ct.c_bool
 
-st_Controller_get_remap_cobject_buffer_kernel_id = \
+st_Controller_get_remap_cobject_buffer_kernel_id = (
     sixtracklib.st_Controller_get_remap_cobject_buffer_kernel_id
+)
 st_Controller_get_remap_cobject_buffer_kernel_id.argtypes = [
-    st_ControllerBase_p]
+    st_ControllerBase_p
+]
 st_Controller_get_remap_cobject_buffer_kernel_id.restype = st_kernel_id_t
 
 
-st_Controller_set_remap_cobject_buffer_kernel_id = \
+st_Controller_set_remap_cobject_buffer_kernel_id = (
     sixtracklib.st_Controller_set_remap_cobject_buffer_kernel_id
+)
 st_Controller_set_remap_cobject_buffer_kernel_id.argtypes = [
-    st_ControllerBase_p, st_kernel_id_t]
+    st_ControllerBase_p,
+    st_kernel_id_t,
+]
 st_Controller_set_remap_cobject_buffer_kernel_id.restype = None
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_has_remap_cobject_buffer_debug_kernel = \
+st_Controller_has_remap_cobject_buffer_debug_kernel = (
     sixtracklib.st_Controller_has_remap_cobject_buffer_debug_kernel
+)
 st_Controller_has_remap_cobject_buffer_debug_kernel.argtypes = [
-    st_ControllerBase_p]
+    st_ControllerBase_p
+]
 st_Controller_has_remap_cobject_buffer_debug_kernel.restype = ct.c_bool
 
-st_Controller_get_remap_cobject_buffer_debug_kernel_id = \
+st_Controller_get_remap_cobject_buffer_debug_kernel_id = (
     sixtracklib.st_Controller_get_remap_cobject_buffer_debug_kernel_id
+)
 st_Controller_get_remap_cobject_buffer_debug_kernel_id.argtypes = [
-    st_ControllerBase_p]
+    st_ControllerBase_p
+]
 st_Controller_get_remap_cobject_buffer_debug_kernel_id.restype = st_kernel_id_t
 
-st_Controller_set_remap_cobject_buffer_debug_kernel_id = \
+st_Controller_set_remap_cobject_buffer_debug_kernel_id = (
     sixtracklib.st_Controller_set_remap_cobject_buffer_debug_kernel_id
+)
 st_Controller_set_remap_cobject_buffer_debug_kernel_id.argtypes = [
-    st_ControllerBase_p, st_kernel_id_t]
+    st_ControllerBase_p,
+    st_kernel_id_t,
+]
 st_Controller_set_remap_cobject_buffer_debug_kernel_id.restype = None
 
 # ------------------------------------------------------------------------------
 # NS(NodeControllerBase):
 
-st_NODE_UNDEFINED_INDEX = st_node_index_t(int('0xFFFFFFFF', 16))
+st_NODE_UNDEFINED_INDEX = st_node_index_t(int("0xFFFFFFFF", 16))
 st_NODE_ILLEGAL_PLATFORM_ID = st_node_platform_id_t(-1)
 st_NODE_ILLEGAL_DEVICE_ID = st_node_device_id_t(-1)
 
-st_Controller_get_num_available_nodes = \
+st_Controller_get_num_available_nodes = (
     sixtracklib.st_Controller_get_num_available_nodes
+)
 st_Controller_get_num_available_nodes.argtypes = [st_ControllerBase_p]
 st_Controller_get_num_available_nodes.restype = st_node_index_t
 
@@ -1645,38 +2616,47 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Controller_has_default_node.argtypes = [st_ControllerBase_p]
 st_Controller_has_default_node.restype = ct.c_bool
 
-st_Controller_get_default_node_index = \
+st_Controller_get_default_node_index = (
     sixtracklib.st_Controller_get_default_node_index
+)
 st_Controller_get_default_node_index.argtypes = [st_ControllerBase_p]
 st_Controller_get_default_node_index.restype = st_node_index_t
 
-st_Controller_get_default_node_id = \
+st_Controller_get_default_node_id = (
     sixtracklib.st_Controller_get_default_node_id
+)
 st_Controller_get_default_node_id.argtypes = [st_ControllerBase_p]
 st_Controller_get_default_node_id.restype = st_NodeId_p
 
-st_Controller_get_default_node_info_base = \
+st_Controller_get_default_node_info_base = (
     sixtracklib.st_Controller_get_default_node_info_base
+)
 st_Controller_get_default_node_info_base.argtypes = [st_ControllerBase_p]
 st_Controller_get_default_node_info_base.restype = st_NodeInfoBase_p
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_is_default_node_index = \
+st_Controller_is_default_node_index = (
     sixtracklib.st_Controller_is_default_node_index
+)
 st_Controller_is_default_node_index.argtypes = [
-    st_ControllerBase_p, st_node_index_t]
+    st_ControllerBase_p,
+    st_node_index_t,
+]
 st_Controller_is_default_node_index.restype = ct.c_bool
 
-st_Controller_is_default_node_id = \
-    sixtracklib.st_Controller_is_default_node_id
+st_Controller_is_default_node_id = sixtracklib.st_Controller_is_default_node_id
 st_Controller_is_default_node_id.argtypes = [st_ControllerBase_p, st_NodeId_p]
 st_Controller_is_default_node_id.restype = ct.c_bool
 
-st_Controller_is_default_platform_id_and_device_id = \
+st_Controller_is_default_platform_id_and_device_id = (
     sixtracklib.st_Controller_is_default_platform_id_and_device_id
+)
 st_Controller_is_default_platform_id_and_device_id.argtypes = [
-    st_ControllerBase_p, st_node_platform_id_t, st_node_device_id_t]
+    st_ControllerBase_p,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+]
 st_Controller_is_default_platform_id_and_device_id.restype = ct.c_bool
 
 st_Controller_is_default_node = sixtracklib.st_Controller_is_default_node
@@ -1685,80 +2665,114 @@ def st_OutputBuffer_create_output_cbuffer(
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_is_node_available_by_index = \
+st_Controller_is_node_available_by_index = (
     sixtracklib.st_Controller_is_node_available_by_index
+)
 st_Controller_is_node_available_by_index.argtypes = [
-    st_ControllerBase_p, st_node_index_t]
+    st_ControllerBase_p,
+    st_node_index_t,
+]
 st_Controller_is_node_available_by_index.restype = ct.c_bool
 
-st_Controller_is_node_available_by_node_id = \
+st_Controller_is_node_available_by_node_id = (
     sixtracklib.st_Controller_is_node_available_by_node_id
+)
 st_Controller_is_node_available_by_node_id.argtypes = [
-    st_ControllerBase_p, st_NodeId_p]
+    st_ControllerBase_p,
+    st_NodeId_p,
+]
 st_Controller_is_node_available_by_node_id.restype = ct.c_bool
 
-st_Controller_is_node_available_by_platform_id_and_device_id = \
+st_Controller_is_node_available_by_platform_id_and_device_id = (
     sixtracklib.st_Controller_is_node_available_by_platform_id_and_device_id
+)
 st_Controller_is_node_available_by_platform_id_and_device_id.argtypes = [
-    st_ControllerBase_p, st_node_platform_id_t, st_node_device_id_t]
+    st_ControllerBase_p,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+]
 st_Controller_is_node_available_by_platform_id_and_device_id.restype = ct.c_bool
 
-st_Controller_is_node_available = \
-    sixtracklib.st_Controller_is_node_available
+st_Controller_is_node_available = sixtracklib.st_Controller_is_node_available
 st_Controller_is_node_available.argtypes = [st_ControllerBase_p, ct.c_char_p]
 st_Controller_is_node_available.restype = ct.c_bool
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_get_min_available_node_index = \
+st_Controller_get_min_available_node_index = (
     sixtracklib.st_Controller_get_min_available_node_index
+)
 st_Controller_get_min_available_node_index.argtypes = [st_ControllerBase_p]
 st_Controller_get_min_available_node_index.restype = st_node_index_t
 
-st_Controller_get_max_available_node_index = \
+st_Controller_get_max_available_node_index = (
     sixtracklib.st_Controller_get_max_available_node_index
+)
 st_Controller_get_max_available_node_index.argtypes = [st_ControllerBase_p]
 st_Controller_get_max_available_node_index.restype = st_node_index_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_get_available_node_indices = \
+st_Controller_get_available_node_indices = (
     sixtracklib.st_Controller_get_available_node_indices
+)
 st_Controller_get_available_node_indices.argtypes = [
-    st_ControllerBase_p, st_ctrl_size_t, st_ctrl_size_t_p]
+    st_ControllerBase_p,
+    st_ctrl_size_t,
+    st_ctrl_size_t_p,
+]
 st_Controller_get_available_node_indices.restype = st_ctrl_size_t
 
-st_Controller_get_available_node_ids = \
+st_Controller_get_available_node_ids = (
     sixtracklib.st_Controller_get_available_node_ids
+)
 st_Controller_get_available_node_ids.argtypes = [
-    st_ControllerBase_p, st_ctrl_size_t, st_NodeId_p]
+    st_ControllerBase_p,
+    st_ctrl_size_t,
+    st_NodeId_p,
+]
 st_Controller_get_available_node_ids.restype = st_ctrl_size_t
 
-st_Controller_get_available_base_node_infos = \
+st_Controller_get_available_base_node_infos = (
     sixtracklib.st_Controller_get_available_base_node_infos
+)
 st_Controller_get_available_base_node_infos.argtypes = [
-    st_ControllerBase_p, st_ctrl_size_t, ct.POINTER(st_NodeInfoBase_p)]
+    st_ControllerBase_p,
+    st_ctrl_size_t,
+    ct.POINTER(st_NodeInfoBase_p),
+]
 st_Controller_get_available_base_node_infos.restype = st_ctrl_size_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_get_node_index_by_node_id = \
+st_Controller_get_node_index_by_node_id = (
     sixtracklib.st_Controller_get_node_index_by_node_id
+)
 st_Controller_get_node_index_by_node_id.argtypes = [
-    st_ControllerBase_p, st_NodeId_p]
+    st_ControllerBase_p,
+    st_NodeId_p,
+]
 st_Controller_get_node_index_by_node_id.restype = st_node_index_t
 
-st_Controller_get_node_index_by_platform_id_and_device_id =  \
+st_Controller_get_node_index_by_platform_id_and_device_id = (
     sixtracklib.st_Controller_get_node_index_by_platform_id_and_device_id
+)
 st_Controller_get_node_index_by_platform_id_and_device_id.argtypes = [
-    st_ControllerBase_p, st_node_platform_id_t, st_node_device_id_t]
-st_Controller_get_node_index_by_platform_id_and_device_id.restype = \
+    st_ControllerBase_p,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+]
+st_Controller_get_node_index_by_platform_id_and_device_id.restype = (
     st_node_index_t
+)
 
-st_Controller_get_node_index_by_node_info = \
+st_Controller_get_node_index_by_node_info = (
     sixtracklib.st_Controller_get_node_index_by_node_info
+)
 st_Controller_get_node_index_by_node_info.argtypes = [
-    st_ControllerBase_p, st_NodeInfoBase_p]
+    st_ControllerBase_p,
+    st_NodeInfoBase_p,
+]
 st_Controller_get_node_index_by_node_info.restype = st_node_index_t
 
 st_Controller_get_node_index = sixtracklib.st_Controller_get_node_index
@@ -1767,16 +2781,23 @@ def st_OutputBuffer_create_output_cbuffer(
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_get_ptr_node_id_by_index = \
+st_Controller_get_ptr_node_id_by_index = (
     sixtracklib.st_Controller_get_ptr_node_id_by_index
+)
 st_Controller_get_ptr_node_id_by_index.argtypes = [
-    st_ControllerBase_p, st_node_index_t]
+    st_ControllerBase_p,
+    st_node_index_t,
+]
 st_Controller_get_ptr_node_id_by_index.restype = st_NodeId_p
 
-st_Controller_get_ptr_node_id_by_platform_id_and_device_id = \
+st_Controller_get_ptr_node_id_by_platform_id_and_device_id = (
     sixtracklib.st_Controller_get_ptr_node_id_by_platform_id_and_device_id
+)
 st_Controller_get_ptr_node_id_by_platform_id_and_device_id.argtypes = [
-    st_ControllerBase_p, st_node_platform_id_t, st_node_device_id_t]
+    st_ControllerBase_p,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+]
 st_Controller_get_ptr_node_id_by_platform_id_and_device_id.restype = st_NodeId_p
 
 st_Controller_get_ptr_node_id = sixtracklib.st_Controller_get_ptr_node_id
@@ -1785,29 +2806,43 @@ def st_OutputBuffer_create_output_cbuffer(
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_get_ptr_node_info_base_by_index = \
+st_Controller_get_ptr_node_info_base_by_index = (
     sixtracklib.st_Controller_get_ptr_node_info_base_by_index
+)
 st_Controller_get_ptr_node_info_base_by_index.argtypes = [
-    st_ControllerBase_p, st_node_index_t]
+    st_ControllerBase_p,
+    st_node_index_t,
+]
 st_Controller_get_ptr_node_info_base_by_index.restype = st_NodeInfoBase_p
 
-st_Controller_get_ptr_node_info_base_by_node_id = \
+st_Controller_get_ptr_node_info_base_by_node_id = (
     sixtracklib.st_Controller_get_ptr_node_info_base_by_node_id
+)
 st_Controller_get_ptr_node_info_base_by_node_id.argtypes = [
-    st_ControllerBase_p, st_NodeId_p]
+    st_ControllerBase_p,
+    st_NodeId_p,
+]
 st_Controller_get_ptr_node_info_base_by_node_id.restype = st_NodeInfoBase_p
 
-st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id = \
+st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id = (
     sixtracklib.st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id
+)
 st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id.argtypes = [
-    st_ControllerBase_p, st_node_platform_id_t, st_node_device_id_t]
-st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id.restype = \
+    st_ControllerBase_p,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+]
+st_Controller_get_ptr_node_info_base_by_platform_id_and_device_id.restype = (
     st_NodeInfoBase_p
+)
 
-st_Controller_get_ptr_node_info_base = \
+st_Controller_get_ptr_node_info_base = (
     sixtracklib.st_Controller_get_ptr_node_info_base
+)
 st_Controller_get_ptr_node_info_base.argtypes = [
-    st_ControllerBase_p, ct.c_char_p]
+    st_ControllerBase_p,
+    ct.c_char_p,
+]
 st_Controller_get_ptr_node_info_base.restype = st_NodeInfoBase_p
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1816,30 +2851,38 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Controller_has_selected_node.argtypes = [st_ControllerBase_p]
 st_Controller_has_selected_node.restype = ct.c_bool
 
-st_Controller_get_selected_node_index = \
+st_Controller_get_selected_node_index = (
     sixtracklib.st_Controller_get_selected_node_index
+)
 st_Controller_get_selected_node_index.argtypes = [st_ControllerBase_p]
 st_Controller_get_selected_node_index.restype = st_node_index_t
 
-st_Controller_get_ptr_selected_node_id = \
+st_Controller_get_ptr_selected_node_id = (
     sixtracklib.st_Controller_get_ptr_selected_node_id
+)
 st_Controller_get_ptr_selected_node_id.argtypes = [st_ControllerBase_p]
 st_Controller_get_ptr_selected_node_id.restype = st_NodeId_p
 
-st_Controller_get_ptr_selected_node_info_base = \
+st_Controller_get_ptr_selected_node_info_base = (
     sixtracklib.st_Controller_get_ptr_selected_node_info_base
+)
 st_Controller_get_ptr_selected_node_info_base.argtypes = [st_ControllerBase_p]
 st_Controller_get_ptr_selected_node_info_base.restype = st_NodeInfoBase_p
 
-st_Controller_get_selected_node_id_str = \
+st_Controller_get_selected_node_id_str = (
     sixtracklib.st_Controller_get_selected_node_id_str
+)
 st_Controller_get_selected_node_id_str.argtypes = [st_ControllerBase_p]
 st_Controller_get_selected_node_id_str.restype = ct.c_char_p
 
-_st_Controller_copy_selected_node_id_str = \
+_st_Controller_copy_selected_node_id_str = (
     sixtracklib.st_Controller_copy_selected_node_id_str
+)
 _st_Controller_copy_selected_node_id_str.argtypes = [
-    st_ControllerBase_p, ct.c_char_p, st_arch_size_t]
+    st_ControllerBase_p,
+    ct.c_char_p,
+    st_arch_size_t,
+]
 _st_Controller_copy_selected_node_id_str.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1848,43 +2891,56 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Controller_select_node.argtypes = [st_ControllerBase_p, ct.c_char_p]
 st_Controller_select_node.restype = st_arch_status_t
 
-st_Controller_select_node_by_node_id = \
+st_Controller_select_node_by_node_id = (
     sixtracklib.st_Controller_select_node_by_node_id
+)
 st_Controller_select_node_by_node_id.argtypes = [
-    st_ControllerBase_p, st_NodeId_p]
+    st_ControllerBase_p,
+    st_NodeId_p,
+]
 st_Controller_select_node_by_node_id.rstype = st_arch_status_t
 
-st_Controller_select_node_by_plaform_id_and_device_id = \
+st_Controller_select_node_by_plaform_id_and_device_id = (
     sixtracklib.st_Controller_select_node_by_plaform_id_and_device_id
+)
 st_Controller_select_node_by_plaform_id_and_device_id.argtypes = [
-    st_ControllerBase_p, st_node_platform_id_t, st_node_device_id_t]
-st_Controller_select_node_by_plaform_id_and_device_id.restype = \
-    st_arch_status_t
+    st_ControllerBase_p,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+]
+st_Controller_select_node_by_plaform_id_and_device_id.restype = st_arch_status_t
 
-st_Controller_select_node_by_index = \
+st_Controller_select_node_by_index = (
     sixtracklib.st_Controller_select_node_by_index
+)
 st_Controller_select_node_by_index.argtypes = [
-    st_ControllerBase_p, st_node_index_t]
+    st_ControllerBase_p,
+    st_node_index_t,
+]
 st_Controller_select_node_by_index.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_can_change_selected_node = \
+st_Controller_can_change_selected_node = (
     sixtracklib.st_Controller_can_change_selected_node
-st_Controller_can_change_selected_node.argtypes = [
-    st_ControllerBase_p]
+)
+st_Controller_can_change_selected_node.argtypes = [st_ControllerBase_p]
 st_Controller_can_change_selected_node.restype = ct.c_bool
 
-st_Controller_can_directly_change_selected_node = \
+st_Controller_can_directly_change_selected_node = (
     sixtracklib.st_Controller_can_directly_change_selected_node
-st_Controller_can_directly_change_selected_node.argtypes = [
-    st_ControllerBase_p]
+)
+st_Controller_can_directly_change_selected_node.argtypes = [st_ControllerBase_p]
 st_Controller_can_directly_change_selected_node.restype = ct.c_bool
 
-st_Controller_change_selected_node = \
+st_Controller_change_selected_node = (
     sixtracklib.st_Controller_change_selected_node
+)
 st_Controller_change_selected_node.argtypes = [
-    st_ControllerBase_p, st_node_index_t, st_node_index_t]
+    st_ControllerBase_p,
+    st_node_index_t,
+    st_node_index_t,
+]
 st_Controller_change_selected_node.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1897,43 +2953,62 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Controller_unselect_node.argtypes = [st_ControllerBase_p]
 st_Controller_unselect_node.restype = st_arch_status_t
 
-st_Controller_unselect_node_by_index = \
+st_Controller_unselect_node_by_index = (
     sixtracklib.st_Controller_unselect_node_by_index
+)
 st_Controller_unselect_node_by_index.argtypes = [
-    st_ControllerBase_p, st_node_index_t]
+    st_ControllerBase_p,
+    st_node_index_t,
+]
 st_Controller_unselect_node_by_index.restype = st_arch_status_t
 
-st_Controller_unselect_node_by_node_id = \
+st_Controller_unselect_node_by_node_id = (
     sixtracklib.st_Controller_unselect_node_by_node_id
+)
 st_Controller_unselect_node_by_node_id.argtypes = [
-    st_ControllerBase_p, st_NodeId_p]
+    st_ControllerBase_p,
+    st_NodeId_p,
+]
 st_Controller_unselect_node_by_node_id.restype = st_arch_status_t
 
-st_Controller_unselect_node_by_platform_id_and_device_id = \
+st_Controller_unselect_node_by_platform_id_and_device_id = (
     sixtracklib.st_Controller_unselect_node_by_platform_id_and_device_id
+)
 st_Controller_unselect_node_by_platform_id_and_device_id.argtypes = [
-    st_ControllerBase_p, st_node_platform_id_t, st_node_device_id_t]
-st_Controller_unselect_node_by_platform_id_and_device_id.restype = \
+    st_ControllerBase_p,
+    st_node_platform_id_t,
+    st_node_device_id_t,
+]
+st_Controller_unselect_node_by_platform_id_and_device_id.restype = (
     st_arch_status_t
+)
 
-st_Controller_unselect_node_by_node_id_str = \
+st_Controller_unselect_node_by_node_id_str = (
     sixtracklib.st_Controller_unselect_node_by_node_id_str
+)
 st_Controller_unselect_node_by_node_id_str.argtypes = [
-    st_ControllerBase_p, ct.c_char_p]
+    st_ControllerBase_p,
+    ct.c_char_p,
+]
 st_Controller_unselect_node_by_node_id_str.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Controller_print_out_available_nodes_info = \
+st_Controller_print_out_available_nodes_info = (
     sixtracklib.st_Controller_print_out_available_nodes_info
-st_Controller_print_out_available_nodes_info.argtypes = [
-    st_ControllerBase_p]
+)
+st_Controller_print_out_available_nodes_info.argtypes = [st_ControllerBase_p]
 st_Controller_print_out_available_nodes_info.restype = None
 
-st_Controller_store_available_nodes_info_to_string = \
+st_Controller_store_available_nodes_info_to_string = (
     sixtracklib.st_Controller_store_available_nodes_info_to_string
+)
 st_Controller_store_available_nodes_info_to_string.argtypes = [
-    st_ControllerBase_p, ct.c_char_p, st_arch_size_t, st_arch_size_t_p]
+    st_ControllerBase_p,
+    ct.c_char_p,
+    st_arch_size_t,
+    st_arch_size_t_p,
+]
 st_Controller_store_available_nodes_info_to_string.restype = None
 
 # -----------------------------------------------------------------------------
@@ -1965,15 +3040,21 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Argument_send_buffer.argtypes = [st_ArgumentBase_p, st_Buffer_p]
 st_Argument_send_buffer.restype = st_arch_status_t
 
-st_Argument_send_buffer_without_remap = \
+st_Argument_send_buffer_without_remap = (
     sixtracklib.st_Argument_send_buffer_without_remap
+)
 st_Argument_send_buffer_without_remap.argtypes = [
-    st_ArgumentBase_p, st_Buffer_p]
+    st_ArgumentBase_p,
+    st_Buffer_p,
+]
 st_Argument_send_buffer_without_remap.restype = st_arch_status_t
 
 st_Argument_send_raw_argument = sixtracklib.st_Argument_send_raw_argument
 st_Argument_send_raw_argument.argtypes = [
-    st_ArgumentBase_p, ct.c_void_p, st_arch_size_t]
+    st_ArgumentBase_p,
+    ct.c_void_p,
+    st_arch_size_t,
+]
 st_Argument_send_raw_argument.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1986,33 +3067,40 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Argument_receive_buffer.argtypes = [st_ArgumentBase_p, st_Buffer_p]
 st_Argument_receive_buffer.restype = st_arch_status_t
 
-st_Argument_receive_buffer_without_remap = \
+st_Argument_receive_buffer_without_remap = (
     sixtracklib.st_Argument_receive_buffer_without_remap
+)
 st_Argument_receive_buffer_without_remap.argtypes = [
-    st_ArgumentBase_p, st_Buffer_p]
+    st_ArgumentBase_p,
+    st_Buffer_p,
+]
 st_Argument_receive_buffer_without_remap.restype = st_arch_status_t
 
 st_Argument_receive_raw_argument = sixtracklib.st_Argument_receive_raw_argument
 st_Argument_receive_raw_argument.argtypes = [
-    st_ArgumentBase_p, ct.c_void_p, st_arch_size_t]
+    st_ArgumentBase_p,
+    ct.c_void_p,
+    st_arch_size_t,
+]
 st_Argument_receive_raw_argument.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Argument_remap_cobjects_buffer = \
+st_Argument_remap_cobjects_buffer = (
     sixtracklib.st_Argument_remap_cobjects_buffer
+)
 st_Argument_remap_cobjects_buffer.argtypes = [st_ArgumentBase_p]
 st_Argument_remap_cobjects_buffer.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Argument_uses_cobjects_buffer = \
-    sixtracklib.st_Argument_uses_cobjects_buffer
+st_Argument_uses_cobjects_buffer = sixtracklib.st_Argument_uses_cobjects_buffer
 st_Argument_uses_cobjects_buffer.argtypes = [st_ArgumentBase_p]
 st_Argument_uses_cobjects_buffer.restype = ct.c_bool
 
-st_Argument_get_const_cobjects_buffer = \
+st_Argument_get_const_cobjects_buffer = (
     sixtracklib.st_Argument_get_const_cobjects_buffer
+)
 st_Argument_get_const_cobjects_buffer.argtypes = [st_ArgumentBase_p]
 st_Argument_get_const_cobjects_buffer.restype = st_Buffer_p
 
@@ -2020,8 +3108,9 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Argument_get_cobjects_buffer.argtypes = [st_ArgumentBase_p]
 st_Argument_get_cobjects_buffer.restype = st_Buffer_p
 
-st_Argument_get_cobjects_buffer_slot_size = \
+st_Argument_get_cobjects_buffer_slot_size = (
     sixtracklib.st_Argument_get_cobjects_buffer_slot_size
+)
 st_Argument_get_cobjects_buffer_slot_size.argtypes = [st_ArgumentBase_p]
 st_Argument_get_cobjects_buffer_slot_size.restype = st_buffer_size_t
 
@@ -2030,13 +3119,13 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Argument_uses_raw_argument.argtypes = [st_ArgumentBase_p]
 st_Argument_uses_raw_argument.restype = ct.c_bool
 
-st_Argument_get_const_ptr_raw_argument = \
+st_Argument_get_const_ptr_raw_argument = (
     sixtracklib.st_Argument_get_const_ptr_raw_argument
+)
 st_Argument_get_const_ptr_raw_argument.argtypes = [st_ArgumentBase_p]
 st_Argument_get_const_ptr_raw_argument.restype = ct.c_void_p
 
-st_Argument_get_ptr_raw_argument = \
-    sixtracklib.st_Argument_get_ptr_raw_argument
+st_Argument_get_ptr_raw_argument = sixtracklib.st_Argument_get_ptr_raw_argument
 st_Argument_get_ptr_raw_argument.argtypes = [st_ArgumentBase_p]
 st_Argument_get_ptr_raw_argument.restype = ct.c_void_p
 
@@ -2054,20 +3143,23 @@ def st_OutputBuffer_create_output_cbuffer(
 st_Argument_has_argument_buffer.argtypes = [st_ArgumentBase_p]
 st_Argument_has_argument_buffer.restype = ct.c_bool
 
-st_Argument_requires_argument_buffer = \
+st_Argument_requires_argument_buffer = (
     sixtracklib.st_Argument_has_argument_buffer
+)
 st_Argument_has_argument_buffer.argtypes = [st_ArgumentBase_p]
 st_Argument_has_argument_buffer.restype = ct.c_bool
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_Argument_get_ptr_base_controller = \
+st_Argument_get_ptr_base_controller = (
     sixtracklib.st_Argument_get_ptr_base_controller
+)
 st_Argument_get_ptr_base_controller.argtypes = [st_ArgumentBase_p]
 st_Argument_get_ptr_base_controller.restype = st_ControllerBase_p
 
-st_Argument_get_const_ptr_base_controller = \
+st_Argument_get_const_ptr_base_controller = (
     sixtracklib.st_Argument_get_const_ptr_base_controller
+)
 st_Argument_get_const_ptr_base_controller.argtypes = [st_ArgumentBase_p]
 st_Argument_get_const_ptr_base_controller.restype = st_ControllerBase_p
 
@@ -2091,7 +3183,11 @@ def st_OutputBuffer_create_output_cbuffer(
 
 st_TrackJobNew_new = sixtracklib.st_TrackJobNew_new
 st_TrackJobNew_new.argtypes = [
-    ct.c_char_p, st_Buffer_p, st_Buffer_p, ct.c_char_p]
+    ct.c_char_p,
+    st_Buffer_p,
+    st_Buffer_p,
+    ct.c_char_p,
+]
 st_TrackJobNew_new.restype = st_TrackJobBaseNew_p
 
 st_TrackJobNew_new_with_output = sixtracklib.st_TrackJobNew_new_with_output
@@ -2101,7 +3197,8 @@ def st_OutputBuffer_create_output_cbuffer(
     st_Buffer_p,
     st_Buffer_p,
     st_buffer_size_t,
-    ct.c_char_p]
+    ct.c_char_p,
+]
 st_TrackJobNew_new_with_output.restype = st_TrackJobBaseNew_p
 
 st_TrackJobNew_new_detailed = sixtracklib.st_TrackJobNew_new_detailed
@@ -2113,7 +3210,8 @@ def st_OutputBuffer_create_output_cbuffer(
     st_Buffer_p,
     st_Buffer_p,
     st_buffer_size_t,
-    ct.c_char_p]
+    ct.c_char_p,
+]
 st_TrackJobNew_new_detailed.restype = st_TrackJobBaseNew_p
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2126,15 +3224,22 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJobNew_track_until.argtypes = [st_TrackJobBaseNew_p, st_buffer_size_t]
 st_TrackJobNew_track_until.restype = st_track_status_t
 
-st_TrackJobNew_track_elem_by_elem = \
+st_TrackJobNew_track_elem_by_elem = (
     sixtracklib.st_TrackJobNew_track_elem_by_elem
+)
 st_TrackJobNew_track_elem_by_elem.argtypes = [
-    st_TrackJobBaseNew_p, st_buffer_size_t]
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
 st_TrackJobNew_track_elem_by_elem.restype = st_track_status_t
 
 st_TrackJobNew_track_line = sixtracklib.st_TrackJobNew_track_line
 st_TrackJobNew_track_line.argtypes = [
-    st_TrackJobBaseNew_p, st_buffer_size_t, st_buffer_size_t, ct.c_bool]
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    ct.c_bool,
+]
 st_TrackJobNew_track_line.restype = st_track_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2145,15 +3250,18 @@ def st_OutputBuffer_create_output_cbuffer(
 
 st_TrackJobNew_collect_detailed = sixtracklib.st_TrackJobNew_collect_detailed
 st_TrackJobNew_collect_detailed.argtypes = [
-    st_TrackJobBaseNew_p, st_track_job_collect_flag_t]
+    st_TrackJobBaseNew_p,
+    st_track_job_collect_flag_t,
+]
 st_TrackJobNew_collect_detailed.restype = st_track_job_collect_flag_t
 
 st_TrackJobNew_collect_particles = sixtracklib.st_TrackJobNew_collect_particles
 st_TrackJobNew_collect_particles.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_collect_particles.restype = st_arch_status_t
 
-st_TrackJobNew_collect_beam_elements = \
+st_TrackJobNew_collect_beam_elements = (
     sixtracklib.st_TrackJobNew_collect_beam_elements
+)
 st_TrackJobNew_collect_beam_elements.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_collect_beam_elements.restype = st_arch_status_t
 
@@ -2161,58 +3269,69 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJobNew_collect_output.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_collect_output.restype = st_arch_status_t
 
-st_TrackJobNew_collect_debug_flag = \
+st_TrackJobNew_collect_debug_flag = (
     sixtracklib.st_TrackJobNew_collect_debug_flag
+)
 st_TrackJobNew_collect_debug_flag.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_collect_debug_flag.restype = st_arch_status_t
 
-st_TrackJobNew_collect_particles_addresses = \
+st_TrackJobNew_collect_particles_addresses = (
     sixtracklib.st_TrackJobNew_collect_particles_addresses
+)
 st_TrackJobNew_collect_particles_addresses.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_collect_particles_addresses.restype = st_arch_status_t
 
-st_TrackJobNew_enable_collect_particles = \
+st_TrackJobNew_enable_collect_particles = (
     sixtracklib.st_TrackJobNew_enable_collect_particles
+)
 st_TrackJobNew_enable_collect_particles.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_enable_collect_particles.restype = None
 
-st_TrackJobNew_disable_collect_particles = \
+st_TrackJobNew_disable_collect_particles = (
     sixtracklib.st_TrackJobNew_disable_collect_particles
+)
 st_TrackJobNew_disable_collect_particles.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_disable_collect_particles.restype = None
 
-st_TrackJobNew_is_collecting_particles = \
+st_TrackJobNew_is_collecting_particles = (
     sixtracklib.st_TrackJobNew_is_collecting_particles
+)
 st_TrackJobNew_is_collecting_particles.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_is_collecting_particles.restype = ct.c_bool
 
-st_TrackJobNew_enable_collect_beam_elements = \
+st_TrackJobNew_enable_collect_beam_elements = (
     sixtracklib.st_TrackJobNew_enable_collect_beam_elements
+)
 st_TrackJobNew_enable_collect_beam_elements.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_enable_collect_beam_elements.restype = None
 
-st_TrackJobNew_disable_collect_beam_elements = \
+st_TrackJobNew_disable_collect_beam_elements = (
     sixtracklib.st_TrackJobNew_disable_collect_beam_elements
+)
 st_TrackJobNew_disable_collect_beam_elements.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_disable_collect_beam_elements.restype = None
 
-st_TrackJobNew_is_collecting_beam_elements = \
+st_TrackJobNew_is_collecting_beam_elements = (
     sixtracklib.st_TrackJobNew_is_collecting_beam_elements
+)
 st_TrackJobNew_is_collecting_beam_elements.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_is_collecting_beam_elements.restype = ct.c_bool
 
-st_TrackJobNew_enable_collect_output = \
+st_TrackJobNew_enable_collect_output = (
     sixtracklib.st_TrackJobNew_enable_collect_output
+)
 st_TrackJobNew_enable_collect_output.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_enable_collect_output.restype = None
 
-st_TrackJobNew_disable_collect_output = \
+st_TrackJobNew_disable_collect_output = (
     sixtracklib.st_TrackJobNew_disable_collect_output
+)
 st_TrackJobNew_disable_collect_output.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_disable_collect_output.restype = None
 
-st_TrackJobNew_is_collecting_output = \
+st_TrackJobNew_is_collecting_output = (
     sixtracklib.st_TrackJobNew_is_collecting_output
+)
 st_TrackJobNew_is_collecting_output.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_is_collecting_output.restype = ct.c_bool
 
@@ -2222,11 +3341,14 @@ def st_OutputBuffer_create_output_cbuffer(
 
 st_TrackJobNew_set_collect_flags = sixtracklib.st_TrackJobNew_set_collect_flags
 st_TrackJobNew_set_collect_flags.argtypes = [
-    st_TrackJobBaseNew_p, st_track_job_collect_flag_t]
+    st_TrackJobBaseNew_p,
+    st_track_job_collect_flag_t,
+]
 st_TrackJobNew_set_collect_flags.restype = None
 
-st_TrackJobNew_requires_collecting = \
+st_TrackJobNew_requires_collecting = (
     sixtracklib.st_TrackJobNew_requires_collecting
+)
 st_TrackJobNew_requires_collecting.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_requires_collecting.restype = ct.c_bool
 
@@ -2240,8 +3362,9 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJobNew_push_particles.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_push_particles.restype = st_arch_status_t
 
-st_TrackJobNew_push_beam_elements = \
+st_TrackJobNew_push_beam_elements = (
     sixtracklib.st_TrackJobNew_push_beam_elements
+)
 st_TrackJobNew_push_beam_elements.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_push_beam_elements.restype = st_arch_status_t
 
@@ -2251,42 +3374,54 @@ def st_OutputBuffer_create_output_cbuffer(
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_TrackJobNew_can_fetch_particle_addresses = \
+st_TrackJobNew_can_fetch_particle_addresses = (
     sixtracklib.st_TrackJobNew_can_fetch_particle_addresses
+)
 st_TrackJobNew_can_fetch_particle_addresses.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_can_fetch_particle_addresses.restype = ct.c_bool
 
-st_TrackJobNew_has_particle_addresses = \
+st_TrackJobNew_has_particle_addresses = (
     sixtracklib.st_TrackJobNew_has_particle_addresses
+)
 st_TrackJobNew_has_particle_addresses.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_has_particle_addresses.restype = ct.c_bool
 
-st_TrackJobNew_fetch_particle_addresses = \
+st_TrackJobNew_fetch_particle_addresses = (
     sixtracklib.st_TrackJobNew_fetch_particle_addresses
+)
 st_TrackJobNew_fetch_particle_addresses.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_fetch_particle_addresses.restype = st_arch_status_t
 
-st_TrackJobNew_clear_particle_addresses = \
+st_TrackJobNew_clear_particle_addresses = (
     sixtracklib.st_TrackJobNew_clear_particle_addresses
-st_TrackJobNew_clear_particle_addresses.argtypes = [st_TrackJobBaseNew_p,
-                                                    st_buffer_size_t]
+)
+st_TrackJobNew_clear_particle_addresses.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
 st_TrackJobNew_clear_particle_addresses.restype = st_arch_status_t
 
-st_TrackJobNew_clear_all_particle_addresses = \
+st_TrackJobNew_clear_all_particle_addresses = (
     sixtracklib.st_TrackJobNew_clear_all_particle_addresses
+)
 st_TrackJobNew_clear_all_particle_addresses.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_clear_all_particle_addresses.restype = st_arch_status_t
 
-st_TrackJobNew_get_particle_addresses = \
+st_TrackJobNew_get_particle_addresses = (
     sixtracklib.st_TrackJobNew_get_particle_addresses
+)
 st_TrackJobNew_get_particle_addresses.argtypes = [
-    st_TrackJobBaseNew_p, st_buffer_size_t]
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
 st_TrackJobNew_get_particle_addresses.restype = st_ParticlesAddr_p
 
-st_TrackJobNew_get_ptr_particle_addresses_buffer = \
+st_TrackJobNew_get_ptr_particle_addresses_buffer = (
     sixtracklib.st_TrackJobNew_get_ptr_particle_addresses_buffer
+)
 st_TrackJobNew_get_ptr_particle_addresses_buffer.argtypes = [
-    st_TrackJobBaseNew_p]
+    st_TrackJobBaseNew_p
+]
 st_TrackJobNew_get_ptr_particle_addresses_buffer.restype = st_Buffer_p
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2299,8 +3434,9 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJobNew_enable_debug_mode.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_enable_debug_mode.restype = st_arch_status_t
 
-st_TrackJobNew_disable_debug_mode = \
+st_TrackJobNew_disable_debug_mode = (
     sixtracklib.st_TrackJobNew_disable_debug_mode
+)
 st_TrackJobNew_disable_debug_mode.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_disable_debug_mode.restype = st_arch_status_t
 
@@ -2312,13 +3448,22 @@ def st_OutputBuffer_create_output_cbuffer(
 
 st_TrackJobNew_reset = sixtracklib.st_TrackJobNew_reset
 st_TrackJobNew_reset.argtypes = [
-    st_TrackJobBaseNew_p, st_Buffer_p, st_Buffer_p, st_Buffer_p]
+    st_TrackJobBaseNew_p,
+    st_Buffer_p,
+    st_Buffer_p,
+    st_Buffer_p,
+]
 st_TrackJobNew_reset.restype = st_arch_status_t
 
 st_TrackJobNew_reset_particle_set = sixtracklib.st_TrackJobNew_reset
 st_TrackJobNew_reset_particle_set.argtypes = [
-    st_TrackJobBaseNew_p, st_Buffer_p, st_buffer_size_t, st_buffer_size_p,
-    st_Buffer_p, st_Buffer_p]
+    st_TrackJobBaseNew_p,
+    st_Buffer_p,
+    st_buffer_size_t,
+    st_buffer_size_p,
+    st_Buffer_p,
+    st_Buffer_p,
+]
 st_TrackJobNew_reset_particle_set.restype = st_arch_status_t
 
 st_TrackJobNew_reset_with_output = sixtracklib.st_TrackJobNew_reset_with_output
@@ -2327,7 +3472,8 @@ def st_OutputBuffer_create_output_cbuffer(
     st_Buffer_p,
     st_Buffer_p,
     st_Buffer_p,
-    st_buffer_size_t]
+    st_buffer_size_t,
+]
 st_TrackJobNew_reset_with_output.restype = st_arch_status_t
 
 st_TrackJobNew_reset_detailed = sixtracklib.st_TrackJobNew_reset_detailed
@@ -2338,19 +3484,26 @@ def st_OutputBuffer_create_output_cbuffer(
     st_buffer_size_p,
     st_Buffer_p,
     st_Buffer_p,
-    st_buffer_size_t]
+    st_buffer_size_t,
+]
 st_TrackJobNew_reset_detailed.restype = st_arch_status_t
 
-st_TrackJobNew_select_particle_set = \
+st_TrackJobNew_select_particle_set = (
     sixtracklib.st_TrackJobNew_select_particle_set
+)
 st_TrackJobNew_select_particle_set.argtypes = [
-    st_TrackJobBaseNew_p, st_buffer_size_t]
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
 st_TrackJobNew_select_particle_set.restype = st_arch_status_t
 
-st_TrackJobNew_assign_output_buffer = \
+st_TrackJobNew_assign_output_buffer = (
     sixtracklib.st_TrackJobNew_assign_output_buffer
-st_TrackJobNew_assign_output_buffer.argtypes = [st_TrackJobBaseNew_p,
-                                                st_Buffer_p]
+)
+st_TrackJobNew_assign_output_buffer.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_Buffer_p,
+]
 st_TrackJobNew_assign_output_buffer.restype = st_arch_status_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2377,83 +3530,100 @@ def st_OutputBuffer_create_output_cbuffer(
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_TrackJobNew_get_num_particle_sets = \
+st_TrackJobNew_get_num_particle_sets = (
     sixtracklib.st_TrackJobNew_get_num_particle_sets
+)
 st_TrackJobNew_get_num_particle_sets.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_num_particle_sets.restype = st_buffer_size_t
 
-st_TrackJobNew_get_particle_set_indices_begin = \
+st_TrackJobNew_get_particle_set_indices_begin = (
     sixtracklib.st_TrackJobNew_get_particle_set_indices_begin
+)
 st_TrackJobNew_get_particle_set_indices_begin.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_particle_set_indices_begin.restype = st_buffer_size_p
 
-st_TrackJobNew_get_particle_set_indices_end = \
+st_TrackJobNew_get_particle_set_indices_end = (
     sixtracklib.st_TrackJobNew_get_particle_set_indices_end
+)
 st_TrackJobNew_get_particle_set_indices_end.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_particle_set_indices_end.restype = st_buffer_size_p
 
-st_TrackJobNew_get_particle_set_index = \
+st_TrackJobNew_get_particle_set_index = (
     sixtracklib.st_TrackJobNew_get_particle_set_index
+)
 st_TrackJobNew_get_particle_set_index.argtypes = [
-    st_TrackJobBaseNew_p, st_buffer_size_t]
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
 st_TrackJobNew_get_particle_set_index.restype = st_buffer_size_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_TrackJobNew_get_total_num_of_particles = \
+st_TrackJobNew_get_total_num_of_particles = (
     sixtracklib.st_TrackJobNew_get_total_num_of_particles
+)
 st_TrackJobNew_get_total_num_of_particles.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_total_num_of_particles.restype = st_buffer_size_t
 
-st_TrackJobNew_get_min_particle_id = \
+st_TrackJobNew_get_min_particle_id = (
     sixtracklib.st_TrackJobNew_get_min_particle_id
+)
 st_TrackJobNew_get_min_particle_id.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_min_particle_id.restype = st_particle_index_t
 
-st_TrackJobNew_get_max_particle_id = \
+st_TrackJobNew_get_max_particle_id = (
     sixtracklib.st_TrackJobNew_get_max_particle_id
+)
 st_TrackJobNew_get_max_particle_id.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_max_particle_id.restype = st_particle_index_t
 
-st_TrackJobNew_get_min_element_id = \
+st_TrackJobNew_get_min_element_id = (
     sixtracklib.st_TrackJobNew_get_min_element_id
+)
 st_TrackJobNew_get_min_element_id.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_min_element_id.restype = st_particle_index_t
 
-st_TrackJobNew_get_max_element_id = \
+st_TrackJobNew_get_max_element_id = (
     sixtracklib.st_TrackJobNew_get_max_element_id
+)
 st_TrackJobNew_get_max_element_id.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_max_element_id.restype = st_particle_index_t
 
-st_TrackJobNew_get_min_initial_turn_id = \
+st_TrackJobNew_get_min_initial_turn_id = (
     sixtracklib.st_TrackJobNew_get_min_initial_turn_id
+)
 st_TrackJobNew_get_min_initial_turn_id.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_min_initial_turn_id.restype = st_particle_index_t
 
-st_TrackJobNew_get_max_initial_turn_id = \
+st_TrackJobNew_get_max_initial_turn_id = (
     sixtracklib.st_TrackJobNew_get_max_initial_turn_id
+)
 st_TrackJobNew_get_max_initial_turn_id.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_max_initial_turn_id.restype = st_particle_index_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_TrackJobNew_get_particles_buffer = \
+st_TrackJobNew_get_particles_buffer = (
     sixtracklib.st_TrackJobNew_get_particles_buffer
+)
 st_TrackJobNew_get_particles_buffer.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_particles_buffer.restype = st_Buffer_p
 
-st_TrackJobNew_get_const_particles_buffer = \
+st_TrackJobNew_get_const_particles_buffer = (
     sixtracklib.st_TrackJobNew_get_const_particles_buffer
+)
 st_TrackJobNew_get_const_particles_buffer.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_const_particles_buffer.restype = st_Buffer_p
 
-st_TrackJobNew_get_beam_elements_buffer = \
+st_TrackJobNew_get_beam_elements_buffer = (
     sixtracklib.st_TrackJobNew_get_beam_elements_buffer
+)
 st_TrackJobNew_get_beam_elements_buffer.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_beam_elements_buffer.restype = st_Buffer_p
 
-st_TrackJobNew_get_const_beam_elements_buffer = \
+st_TrackJobNew_get_const_beam_elements_buffer = (
     sixtracklib.st_TrackJobNew_get_const_beam_elements_buffer
+)
 st_TrackJobNew_get_const_beam_elements_buffer.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_const_beam_elements_buffer.restype = st_Buffer_p
 
@@ -2463,123 +3633,151 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJobNew_has_output_buffer.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_has_output_buffer.restype = ct.c_bool
 
-st_TrackJobNew_owns_output_buffer = \
+st_TrackJobNew_owns_output_buffer = (
     sixtracklib.st_TrackJobNew_owns_output_buffer
+)
 st_TrackJobNew_owns_output_buffer.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_owns_output_buffer.restype = ct.c_bool
 
-st_TrackJobNew_has_elem_by_elem_output = \
+st_TrackJobNew_has_elem_by_elem_output = (
     sixtracklib.st_TrackJobNew_has_elem_by_elem_output
+)
 st_TrackJobNew_has_elem_by_elem_output.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_has_elem_by_elem_output.restype = ct.c_bool
 
-st_TrackJobNew_has_beam_monitor_output = \
+st_TrackJobNew_has_beam_monitor_output = (
     sixtracklib.st_TrackJobNew_has_beam_monitor_output
+)
 st_TrackJobNew_has_beam_monitor_output.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_has_beam_monitor_output.restype = ct.c_bool
 
-st_TrackJobNew_get_beam_monitor_output_buffer_offset = \
+st_TrackJobNew_get_beam_monitor_output_buffer_offset = (
     sixtracklib.st_TrackJobNew_get_beam_monitor_output_buffer_offset
+)
 st_TrackJobNew_get_beam_monitor_output_buffer_offset.argtypes = [
-    st_TrackJobBaseNew_p]
+    st_TrackJobBaseNew_p
+]
 st_TrackJobNew_get_beam_monitor_output_buffer_offset.restype = st_buffer_size_t
 
-st_TrackJobNew_get_elem_by_elem_output_buffer_offset = \
+st_TrackJobNew_get_elem_by_elem_output_buffer_offset = (
     sixtracklib.st_TrackJobNew_get_elem_by_elem_output_buffer_offset
+)
 st_TrackJobNew_get_elem_by_elem_output_buffer_offset.argtypes = [
-    st_TrackJobBaseNew_p]
+    st_TrackJobBaseNew_p
+]
 st_TrackJobNew_get_elem_by_elem_output_buffer_offset.restype = st_buffer_size_t
 
-st_TrackJobNew_get_num_elem_by_elem_turns = \
+st_TrackJobNew_get_num_elem_by_elem_turns = (
     sixtracklib.st_TrackJobNew_get_num_elem_by_elem_turns
+)
 st_TrackJobNew_get_num_elem_by_elem_turns.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_num_elem_by_elem_turns.restype = st_buffer_size_t
 
-st_TrackJobNew_get_output_buffer = \
-    sixtracklib.st_TrackJobNew_get_output_buffer
+st_TrackJobNew_get_output_buffer = sixtracklib.st_TrackJobNew_get_output_buffer
 st_TrackJobNew_get_output_buffer.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_output_buffer.restype = st_Buffer_p
 
-st_TrackJobNew_get_const_output_buffer = \
+st_TrackJobNew_get_const_output_buffer = (
     sixtracklib.st_TrackJobNew_get_const_output_buffer
+)
 st_TrackJobNew_get_const_output_buffer.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_const_output_buffer.restype = st_Buffer_p
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_TrackJobNew_has_beam_monitors = \
-    sixtracklib.st_TrackJobNew_has_beam_monitors
+st_TrackJobNew_has_beam_monitors = sixtracklib.st_TrackJobNew_has_beam_monitors
 st_TrackJobNew_has_beam_monitors.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_has_beam_monitors.restype = ct.c_bool
 
-st_TrackJobNew_get_num_beam_monitors = \
+st_TrackJobNew_get_num_beam_monitors = (
     sixtracklib.st_TrackJobNew_get_num_beam_monitors
+)
 st_TrackJobNew_get_num_beam_monitors.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_num_beam_monitors.restype = st_buffer_size_t
 
-st_TrackJobNew_get_beam_monitor_indices_begin = \
+st_TrackJobNew_get_beam_monitor_indices_begin = (
     sixtracklib.st_TrackJobNew_get_beam_monitor_indices_begin
+)
 st_TrackJobNew_get_beam_monitor_indices_begin.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_beam_monitor_indices_begin.restype = st_buffer_size_p
 
-st_TrackJobNew_get_beam_monitor_indices_end = \
+st_TrackJobNew_get_beam_monitor_indices_end = (
     sixtracklib.st_TrackJobNew_get_beam_monitor_indices_end
+)
 st_TrackJobNew_get_beam_monitor_indices_end.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_beam_monitor_indices_end.restype = st_buffer_size_p
 
-st_TrackJobNew_get_beam_monitor_index = \
+st_TrackJobNew_get_beam_monitor_index = (
     sixtracklib.st_TrackJobNew_get_beam_monitor_index
+)
 st_TrackJobNew_get_beam_monitor_index.argtypes = [
-    st_TrackJobBaseNew_p, st_buffer_size_t]
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
 st_TrackJobNew_get_beam_monitor_index.restype = st_buffer_size_t
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-st_TrackJobNew_has_elem_by_elem_config = \
+st_TrackJobNew_has_elem_by_elem_config = (
     sixtracklib.st_TrackJobNew_has_elem_by_elem_config
+)
 st_TrackJobNew_has_elem_by_elem_config.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_has_elem_by_elem_config.restype = ct.c_bool
 
-st_TrackJobNew_get_elem_by_elem_config = \
+st_TrackJobNew_get_elem_by_elem_config = (
     sixtracklib.st_TrackJobNew_get_elem_by_elem_config
+)
 st_TrackJobNew_get_elem_by_elem_config.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_get_elem_by_elem_config.restype = st_ElemByElemConfig_p
 
-st_TrackJobNew_is_elem_by_elem_config_rolling = \
+st_TrackJobNew_is_elem_by_elem_config_rolling = (
     sixtracklib.st_TrackJobNew_is_elem_by_elem_config_rolling
+)
 st_TrackJobNew_is_elem_by_elem_config_rolling.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_is_elem_by_elem_config_rolling.restype = ct.c_bool
 
-st_TrackJobNew_get_default_elem_by_elem_config_rolling_flag = \
+st_TrackJobNew_get_default_elem_by_elem_config_rolling_flag = (
     sixtracklib.st_TrackJobNew_get_default_elem_by_elem_config_rolling_flag
+)
 st_TrackJobNew_get_default_elem_by_elem_config_rolling_flag.argtypes = [
-    st_TrackJobBaseNew_p]
+    st_TrackJobBaseNew_p
+]
 st_TrackJobNew_get_default_elem_by_elem_config_rolling_flag.restype = ct.c_bool
 
-st_TrackJobNew_set_default_elem_by_elem_config_rolling_flag = \
+st_TrackJobNew_set_default_elem_by_elem_config_rolling_flag = (
     sixtracklib.st_TrackJobNew_set_default_elem_by_elem_config_rolling_flag
+)
 st_TrackJobNew_set_default_elem_by_elem_config_rolling_flag.argtypes = [
-    st_TrackJobBaseNew_p, ct.c_bool]
+    st_TrackJobBaseNew_p,
+    ct.c_bool,
+]
 st_TrackJobNew_set_default_elem_by_elem_config_rolling_flag.restype = None
 
-st_TrackJobNew_get_elem_by_elem_config_order = \
+st_TrackJobNew_get_elem_by_elem_config_order = (
     sixtracklib.st_TrackJobNew_get_elem_by_elem_config_order
-st_TrackJobNew_get_elem_by_elem_config_order.argtypes = [
-    st_TrackJobBaseNew_p]
-st_TrackJobNew_get_elem_by_elem_config_order.restype = \
+)
+st_TrackJobNew_get_elem_by_elem_config_order.argtypes = [st_TrackJobBaseNew_p]
+st_TrackJobNew_get_elem_by_elem_config_order.restype = (
     st_elem_by_elem_order_int_t
+)
 
-st_TrackJobNew_get_default_elem_by_elem_config_order = \
+st_TrackJobNew_get_default_elem_by_elem_config_order = (
     sixtracklib.st_TrackJobNew_get_default_elem_by_elem_config_order
+)
 st_TrackJobNew_get_default_elem_by_elem_config_order.argtypes = [
-    st_TrackJobBaseNew_p]
-st_TrackJobNew_get_default_elem_by_elem_config_order.restype = \
+    st_TrackJobBaseNew_p
+]
+st_TrackJobNew_get_default_elem_by_elem_config_order.restype = (
     st_elem_by_elem_order_int_t
+)
 
-st_TrackJobNew_set_default_elem_by_elem_config_order = \
+st_TrackJobNew_set_default_elem_by_elem_config_order = (
     sixtracklib.st_TrackJobNew_set_default_elem_by_elem_config_order
+)
 st_TrackJobNew_set_default_elem_by_elem_config_order.argtypes = [
-    st_TrackJobBaseNew_p, st_elem_by_elem_order_int_t]
+    st_TrackJobBaseNew_p,
+    st_elem_by_elem_order_int_t,
+]
 st_TrackJobNew_set_default_elem_by_elem_config_order.restype = None
 
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2592,10 +3790,380 @@ def st_OutputBuffer_create_output_cbuffer(
 st_TrackJobNew_uses_arguments.argtypes = [st_TrackJobBaseNew_p]
 st_TrackJobNew_uses_arguments.restype = ct.c_bool
 
+# -----------------------------------------------------------------------------
+
+st_TrackJobNew_add_assign_address_item = (
+    sixtracklib.st_TrackJobNew_add_assign_address_item
+)
+st_TrackJobNew_add_assign_address_item.restype = st_AssignAddressItem_p
+st_TrackJobNew_add_assign_address_item.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_AssignAddressItem_p,
+]
+
+st_TrackJobNew_add_assign_address_item_detailed = (
+    sixtracklib.st_TrackJobNew_add_assign_address_item_detailed
+)
+st_TrackJobNew_add_assign_address_item_detailed.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+st_TrackJobNew_add_assign_address_item_detailed.restype = st_AssignAddressItem_p
+
+st_TrackJobNew_remove_assign_address_item = (
+    sixtracklib.st_TrackJobNew_remove_assign_address_item
+)
+st_TrackJobNew_remove_assign_address_item.restype = st_arch_status_t
+st_TrackJobNew_remove_assign_address_item.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_AssignAddressItem_p,
+]
+
+st_TrackJobNew_remove_assign_address_item_by_key_and_index = (
+    sixtracklib.st_TrackJobNew_remove_assign_address_item_by_key_and_index
+)
+st_TrackJobNew_remove_assign_address_item_by_key_and_index.restype = (
+    st_arch_status_t
+)
+st_TrackJobNew_remove_assign_address_item_by_key_and_index.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_TrackJobDestSrcBufferIds_p,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_has_assign_address_item = (
+    sixtracklib.st_TrackJobNew_has_assign_address_item
+)
+st_TrackJobNew_has_assign_address_item.restype = ct.c_bool
+st_TrackJobNew_has_assign_address_item.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_AssignAddressItem_p,
+]
+
+st_TrackJobNew_has_assign_item_by_index = (
+    sixtracklib.st_TrackJobNew_has_assign_item_by_index
+)
+st_TrackJobNew_has_assign_item_by_index.restype = ct.c_bool
+st_TrackJobNew_has_assign_item_by_index.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_has_assign_address_item_detailed = (
+    sixtracklib.st_TrackJobNew_has_assign_address_item_detailed
+)
+st_TrackJobNew_has_assign_address_item_detailed.restype = ct.c_bool
+st_TrackJobNew_has_assign_address_item_detailed.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_index_of_assign_address_item_detailed = (
+    sixtracklib.st_TrackJobNew_index_of_assign_address_item_detailed
+)
+st_TrackJobNew_index_of_assign_address_item_detailed.restype = st_buffer_size_t
+st_TrackJobNew_index_of_assign_address_item_detailed.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_index_of_assign_address_item = (
+    sixtracklib.st_TrackJobNew_index_of_assign_address_item
+)
+st_TrackJobNew_index_of_assign_address_item.restype = st_buffer_size_t
+st_TrackJobNew_index_of_assign_address_item.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_AssignAddressItem_p,
+]
+
+st_TrackJobNew_has_assign_items = sixtracklib.st_TrackJobNew_has_assign_items
+st_TrackJobNew_has_assign_items.restype = ct.c_bool
+st_TrackJobNew_has_assign_items.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_num_assign_items = sixtracklib.st_TrackJobNew_num_assign_items
+st_TrackJobNew_num_assign_items.restype = st_buffer_size_t
+st_TrackJobNew_num_assign_items.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_total_num_assign_items = (
+    sixtracklib.st_TrackJobNew_total_num_assign_items
+)
+st_TrackJobNew_total_num_assign_items.restype = st_buffer_size_t
+st_TrackJobNew_total_num_assign_items.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_ptr_assign_address_item = (
+    sixtracklib.st_TrackJobNew_ptr_assign_address_item
+)
+st_TrackJobNew_ptr_assign_address_item.restype = st_AssignAddressItem_p
+st_TrackJobNew_ptr_assign_address_item.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_AssignAddressItem_p,
+]
+
+st_TrackJobNew_ptr_assign_address_item_detailed = (
+    sixtracklib.st_TrackJobNew_ptr_assign_address_item_detailed
+)
+st_TrackJobNew_ptr_assign_address_item_detailed.restype = st_AssignAddressItem_p
+st_TrackJobNew_ptr_assign_address_item_detailed.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_object_type_id_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_ptr_assign_address_item_by_index = (
+    sixtracklib.st_TrackJobNew_ptr_assign_address_item_by_index
+)
+st_TrackJobNew_ptr_assign_address_item_by_index.restype = st_AssignAddressItem_p
+st_TrackJobNew_ptr_assign_address_item_by_index.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_num_distinct_available_assign_address_items_dest_src_pairs = (
+    sixtracklib.st_TrackJobNew_num_distinct_available_assign_address_items_dest_src_pairs
+)
+st_TrackJobNew_num_distinct_available_assign_address_items_dest_src_pairs.restype = (
+    st_buffer_size_t
+)
+st_TrackJobNew_num_distinct_available_assign_address_items_dest_src_pairs.argtypes = [
+    st_TrackJobBaseNew_p
+]
+
+st_TrackJobNew_available_assign_address_items_dest_src_pairs = (
+    sixtracklib.st_TrackJobNew_available_assign_address_items_dest_src_pairs
+)
+st_TrackJobNew_available_assign_address_items_dest_src_pairs.restype = (
+    st_buffer_size_t
+)
+st_TrackJobNew_available_assign_address_items_dest_src_pairs.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+    st_TrackJobDestSrcBufferIds_p,
+]
+
+st_TrackJobNew_buffer_by_buffer_id = (
+    sixtracklib.st_TrackJobNew_buffer_by_buffer_id
+)
+st_TrackJobNew_buffer_by_buffer_id.restype = st_Buffer_p
+st_TrackJobNew_buffer_by_buffer_id.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_const_buffer_by_buffer_id = (
+    sixtracklib.st_TrackJobNew_const_buffer_by_buffer_id
+)
+st_TrackJobNew_const_buffer_by_buffer_id.restype = st_Buffer_p
+st_TrackJobNew_const_buffer_by_buffer_id.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_is_buffer_by_buffer_id = (
+    sixtracklib.st_TrackJobNew_is_buffer_by_buffer_id
+)
+st_TrackJobNew_is_buffer_by_buffer_id.restype = ct.c_bool
+st_TrackJobNew_is_buffer_by_buffer_id.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_is_raw_memory_by_buffer_id = (
+    sixtracklib.st_TrackJobNew_is_raw_memory_by_buffer_id
+)
+st_TrackJobNew_is_raw_memory_by_buffer_id.restype = ct.c_bool
+st_TrackJobNew_is_raw_memory_by_buffer_id.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_assign_item_dest_src_begin = (
+    sixtracklib.st_TrackJobNew_assign_item_dest_src_begin
+)
+st_TrackJobNew_assign_item_dest_src_begin.restype = (
+    st_TrackJobDestSrcBufferIds_p
+)
+st_TrackJobNew_assign_item_dest_src_begin.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_assign_item_dest_src_end = (
+    sixtracklib.st_TrackJobNew_assign_item_dest_src_end
+)
+st_TrackJobNew_assign_item_dest_src_end.restype = st_TrackJobDestSrcBufferIds_p
+st_TrackJobNew_assign_item_dest_src_end.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_commit_address_assignments = (
+    sixtracklib.st_TrackJobNew_commit_address_assignments
+)
+st_TrackJobNew_commit_address_assignments.restype = st_arch_status_t
+st_TrackJobNew_commit_address_assignments.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_assign_all_addresses = (
+    sixtracklib.st_TrackJobNew_assign_all_addresses
+)
+st_TrackJobNew_assign_all_addresses.restype = st_arch_status_t
+st_TrackJobNew_assign_all_addresses.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_assign_addresses = sixtracklib.st_TrackJobNew_assign_addresses
+st_TrackJobNew_assign_addresses.restype = st_arch_status_t
+st_TrackJobNew_assign_addresses.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+    st_buffer_size_t,
+]
+
+# -----------------------------------------------------------------------------
+
+st_TrackJobNew_stored_buffers_capacity = (
+    sixtracklib.st_TrackJobNew_stored_buffers_capacity
+)
+st_TrackJobNew_stored_buffers_capacity.restype = st_arch_size_t
+st_TrackJobNew_stored_buffers_capacity.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_reserve_stored_buffers_capacity = (
+    sixtracklib.st_TrackJobNew_reserve_stored_buffers_capacity
+)
+st_TrackJobNew_reserve_stored_buffers_capacity.restype = st_arch_status_t
+st_TrackJobNew_reserve_stored_buffers_capacity.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_arch_size_t,
+]
+
+st_TrackJobNew_has_stored_buffers = (
+    sixtracklib.st_TrackJobNew_has_stored_buffers
+)
+st_TrackJobNew_has_stored_buffers.restype = ct.c_bool
+st_TrackJobNew_has_stored_buffers.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_has_stored_buffers = (
+    sixtracklib.st_TrackJobNew_has_stored_buffers
+)
+st_TrackJobNew_has_stored_buffers.restype = ct.c_bool
+st_TrackJobNew_has_stored_buffers.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_num_stored_buffers = (
+    sixtracklib.st_TrackJobNew_num_stored_buffers
+)
+st_TrackJobNew_num_stored_buffers.restype = st_arch_size_t
+st_TrackJobNew_num_stored_buffers.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_min_stored_buffer_id = (
+    sixtracklib.st_TrackJobNew_min_stored_buffer_id
+)
+st_TrackJobNew_min_stored_buffer_id.restype = st_arch_size_t
+st_TrackJobNew_min_stored_buffer_id.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_max_stored_buffer_id = (
+    sixtracklib.st_TrackJobNew_max_stored_buffer_id
+)
+st_TrackJobNew_max_stored_buffer_id.restype = st_arch_size_t
+st_TrackJobNew_max_stored_buffer_id.argtypes = [st_TrackJobBaseNew_p]
+
+st_TrackJobNew_create_stored_buffer = (
+    sixtracklib.st_TrackJobNew_create_stored_buffer
+)
+st_TrackJobNew_create_stored_buffer.restype = st_arch_size_t
+st_TrackJobNew_create_stored_buffer.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_buffer_size_t,
+]
+
+st_TrackJobNew_add_stored_buffer = sixtracklib.st_TrackJobNew_add_stored_buffer
+st_TrackJobNew_add_stored_buffer.restype = st_arch_size_t
+st_TrackJobNew_add_stored_buffer.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_Buffer_p,
+    ct.c_bool,
+    ct.c_bool,
+]
+
+st_TrackJobNew_owns_stored_buffer = (
+    sixtracklib.st_TrackJobNew_owns_stored_buffer
+)
+st_TrackJobNew_owns_stored_buffer.restype = ct.c_bool
+st_TrackJobNew_owns_stored_buffer.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_arch_size_t,
+]
+
+st_TrackJobNew_remove_stored_buffer = (
+    sixtracklib.st_TrackJobNew_remove_stored_buffer
+)
+st_TrackJobNew_remove_stored_buffer.restype = st_arch_status_t
+st_TrackJobNew_remove_stored_buffer.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_arch_size_t,
+]
+
+st_TrackJobNew_stored_buffer = sixtracklib.st_TrackJobNew_stored_buffer
+st_TrackJobNew_stored_buffer.restype = st_Buffer_p
+st_TrackJobNew_stored_buffer.argtypes = [st_TrackJobBaseNew_p, st_arch_size_t]
+
+st_TrackJobNew_const_stored_buffer = (
+    sixtracklib.st_TrackJobNew_const_stored_buffer
+)
+st_TrackJobNew_const_stored_buffer.restype = st_Buffer_p
+st_TrackJobNew_const_stored_buffer.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_arch_size_t,
+]
+
+st_TrackJobNew_push_stored_buffer = (
+    sixtracklib.st_TrackJobNew_push_stored_buffer
+)
+st_TrackJobNew_push_stored_buffer.restype = st_arch_size_t
+st_TrackJobNew_push_stored_buffer.argtypes = [
+    st_TrackJobBaseNew_p,
+    st_arch_size_t,
+]
+
+st_TrackJobNew_collect_stored_buffer = (
+    sixtracklib.st_TrackJobNew_collect_stored_buffer
+)
+st_TrackJobNew_collect_stored_buffer.restype = st_arch_status_t
+st_TrackJobNew_collect_stored_buffer.argtypes = [st_TrackJobBaseNew_p]
+
 # ==============================================================================
 # Cuda-Context methods
 
-if SIXTRACKLIB_MODULES.get('cuda', False):
+if SIXTRACKLIB_MODULES.get("cuda", False):
     # --------------------------------------------------------------------------
     # NS(CudaNodeInfo):
 
@@ -2615,18 +4183,21 @@ def st_OutputBuffer_create_output_cbuffer(
         st_node_device_id_t,
         st_node_index_t,
         ct.c_bool,
-        ct.c_bool]
+        ct.c_bool,
+    ]
     st_CudaNodeInfo_new_detailed.restype = st_CudaNodeInfo_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaNodeInfo_get_cuda_device_index = \
+    st_CudaNodeInfo_get_cuda_device_index = (
         sixtracklib.st_CudaNodeInfo_get_cuda_device_index
+    )
     st_CudaNodeInfo_get_cuda_device_index.argtypes = [st_CudaNodeInfo_p]
     st_CudaNodeInfo_get_cuda_device_index.restype = st_cuda_dev_index_t
 
-    st_CudaNodeInfo_get_pci_bus_id_str = \
+    st_CudaNodeInfo_get_pci_bus_id_str = (
         sixtracklib.st_CudaNodeInfo_get_pci_bus_id_str
+    )
     st_CudaNodeInfo_get_pci_bus_id_str.argtypes = [st_CudaNodeInfo_p]
     st_CudaNodeInfo_get_pci_bus_id_str.restype = ct.c_char_p
 
@@ -2636,25 +4207,30 @@ def st_OutputBuffer_create_output_cbuffer(
     st_CudaNodeInfo_get_warp_size.argtypes = [st_CudaNodeInfo_p]
     st_CudaNodeInfo_get_warp_size.restype = st_arch_size_t
 
-    st_CudaNodeInfo_get_compute_capability = \
+    st_CudaNodeInfo_get_compute_capability = (
         sixtracklib.st_CudaNodeInfo_get_compute_capability
+    )
     st_CudaNodeInfo_get_compute_capability.argtypes = [st_CudaNodeInfo_p]
     st_CudaNodeInfo_get_compute_capability.restype = st_arch_size_t
 
-    st_CudaNodeInfo_get_num_multiprocessors = \
+    st_CudaNodeInfo_get_num_multiprocessors = (
         sixtracklib.st_CudaNodeInfo_get_num_multiprocessors
+    )
     st_CudaNodeInfo_get_num_multiprocessors.argtypes = [st_CudaNodeInfo_p]
     st_CudaNodeInfo_get_num_multiprocessors.restype = st_arch_size_t
 
-    st_CudaNodeInfo_get_max_threads_per_block = \
+    st_CudaNodeInfo_get_max_threads_per_block = (
         sixtracklib.st_CudaNodeInfo_get_max_threads_per_block
+    )
     st_CudaNodeInfo_get_max_threads_per_block.argtypes = [st_CudaNodeInfo_p]
     st_CudaNodeInfo_get_max_threads_per_block.restype = st_arch_size_t
 
-    st_CudaNodeInfo_get_max_threads_per_multiprocessor = \
+    st_CudaNodeInfo_get_max_threads_per_multiprocessor = (
         sixtracklib.st_CudaNodeInfo_get_max_threads_per_multiprocessor
+    )
     st_CudaNodeInfo_get_max_threads_per_multiprocessor.argtypes = [
-        st_CudaNodeInfo_p]
+        st_CudaNodeInfo_p
+    ]
     st_CudaNodeInfo_get_max_threads_per_multiprocessor.restype = st_arch_size_t
 
     # --------------------------------------------------------------------------
@@ -2666,6 +4242,87 @@ def st_OutputBuffer_create_output_cbuffer(
     # --------------------------------------------------------------------------
     # NS(CudaController):
 
+    st_Cuda_get_num_all_nodes = sixtracklib.st_Cuda_get_num_all_nodes
+    st_Cuda_get_num_all_nodes.argtypes = None
+    st_Cuda_get_num_all_nodes.restype = st_arch_size_t
+
+    st_Cuda_get_all_nodes = sixtracklib.st_Cuda_get_all_nodes
+    st_Cuda_get_all_nodes.argtypes = [st_NodeId_p, st_arch_size_t]
+    st_Cuda_get_all_nodes.restype = st_arch_size_t
+
+    st_Cuda_print_all_nodes = sixtracklib.st_Cuda_print_all_nodes
+    st_Cuda_print_all_nodes.argtypes = None
+    st_Cuda_print_all_nodes.restype = None
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_Cuda_num_available_nodes = sixtracklib.st_Cuda_num_available_nodes
+    st_Cuda_num_available_nodes.argtypes = [ct.c_char_p]
+    st_Cuda_num_available_nodes.restype = st_arch_size_t
+
+    st_Cuda_num_available_nodes_detailed = (
+        sixtracklib.st_Cuda_num_available_nodes_detailed
+    )
+    st_Cuda_num_available_nodes_detailed.argtypes = [ct.c_char_p, ct.c_char_p]
+    st_Cuda_num_available_nodes_detailed.restype = st_arch_size_t
+
+    st_Cuda_get_available_nodes = sixtracklib.st_Cuda_get_available_nodes
+    st_Cuda_get_available_nodes.argtypes = [st_NodeId_p, st_arch_size_t]
+    st_Cuda_get_available_nodes.restype = st_arch_size_t
+
+    st_Cuda_get_available_nodes_detailed = (
+        sixtracklib.st_Cuda_get_available_nodes_detailed
+    )
+    st_Cuda_get_available_nodes_detailed.argtypes = [
+        st_NodeId_p,
+        st_arch_size_t,
+        st_arch_size_t,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_Cuda_get_available_nodes_detailed.restpye = st_arch_size_t
+
+    st_Cuda_print_available_nodes = sixtracklib.st_Cuda_print_available_nodes
+    st_Cuda_print_available_nodes.argtypes = None
+    st_Cuda_print_available_nodes.restype = None
+
+    st_Cuda_print_available_nodes_detailed = (
+        sixtracklib.st_Cuda_print_available_nodes_detailed
+    )
+    st_Cuda_print_available_nodes_detailed.argtypes = [
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_Cuda_print_available_nodes_detailed.restype = None
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_Cuda_get_available_node_id_strs = (
+        sixtracklib.st_Cuda_get_available_node_id_strs
+    )
+    st_Cuda_get_available_node_id_strs.argtypes = [
+        st_char_pp,
+        st_arch_size_t,
+        st_arch_size_t,
+    ]
+    st_Cuda_get_available_node_id_strs.restype = st_arch_size_t
+
+    st_Cuda_get_available_node_id_strs_detailed = (
+        sixtracklib.st_Cuda_get_available_node_id_strs_detailed
+    )
+    st_Cuda_get_available_node_id_strs_detailed.argtypes = [
+        st_char_pp,
+        st_arch_size_t,
+        st_arch_size_t,
+        st_node_id_str_fmt_t,
+        st_arch_size_t,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_Cuda_get_available_node_id_strs_detailed.restype = st_arch_size_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
     st_CudaArgBuffer_p = ct.c_void_p
     st_NullCudaArgBuffer = ct.cast(0, st_CudaArgBuffer_p)
 
@@ -2683,127 +4340,188 @@ def st_OutputBuffer_create_output_cbuffer(
     st_CudaController_new.argtypes = [ct.c_char_p]
     st_CudaController_new.restype = st_CudaController_p
 
-    st_CudaController_new_from_node_id = \
+    st_CudaController_new_from_node_id = (
         sixtracklib.st_CudaController_new_from_node_id
+    )
     st_CudaController_new_from_node_id.argtypes = [st_NodeId_p]
     st_CudaController_new_from_node_id.restype = st_CudaController_p
 
-    st_CudaController_new_from_node_index = \
+    st_CudaController_new_from_node_index = (
         sixtracklib.st_CudaController_new_from_node_index
+    )
     st_CudaController_new_from_node_index.argtypes = [st_node_index_t]
     st_CudaController_new_from_node_index.restype = st_CudaController_p
 
-    st_CudaController_new_from_platform_id_and_device_id = \
+    st_CudaController_new_from_platform_id_and_device_id = (
         sixtracklib.st_CudaController_new_from_platform_id_and_device_id
+    )
     st_CudaController_new_from_platform_id_and_device_id.argtypes = [
-        st_node_platform_id_t, st_node_device_id_t]
-    st_CudaController_new_from_platform_id_and_device_id.restype = \
+        st_node_platform_id_t,
+        st_node_device_id_t,
+    ]
+    st_CudaController_new_from_platform_id_and_device_id.restype = (
         st_CudaController_p
+    )
 
-    st_CudaController_new_from_cuda_device_index = \
+    st_CudaController_new_from_cuda_device_index = (
         sixtracklib.st_CudaController_new_from_cuda_device_index
+    )
     st_CudaController_new_from_cuda_device_index.argtypes = [
-        st_cuda_dev_index_t]
+        st_cuda_dev_index_t
+    ]
     st_CudaController_new_from_cuda_device_index.restype = st_CudaController_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaController_select_node_by_cuda_device_index = \
+    st_CudaController_select_node_by_cuda_device_index = (
         sixtracklib.st_CudaController_select_node_by_cuda_device_index
+    )
     st_CudaController_select_node_by_cuda_device_index.argtypes = [
-        st_CudaController_p, st_cuda_dev_index_t]
-    st_CudaController_select_node_by_cuda_device_index.restype = \
+        st_CudaController_p,
+        st_cuda_dev_index_t,
+    ]
+    st_CudaController_select_node_by_cuda_device_index.restype = (
         st_arch_status_t
+    )
 
-    st_CudaController_select_node_by_cuda_pci_bus_id = \
+    st_CudaController_select_node_by_cuda_pci_bus_id = (
         sixtracklib.st_CudaController_select_node_by_cuda_pci_bus_id
+    )
     st_CudaController_select_node_by_cuda_pci_bus_id.argtypes = [
-        st_CudaController_p, ct.c_char_p]
-    st_CudaController_select_node_by_cuda_pci_bus_id.restype = \
-        st_arch_status_t
+        st_CudaController_p,
+        ct.c_char_p,
+    ]
+    st_CudaController_select_node_by_cuda_pci_bus_id.restype = st_arch_status_t
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaController_get_ptr_node_info_by_index = \
+    st_CudaController_get_ptr_node_info_by_index = (
         sixtracklib.st_CudaController_get_ptr_node_info_by_index
+    )
     st_CudaController_get_ptr_node_info_by_index.argtypes = [
-        st_CudaController_p, st_ctrl_size_t]
+        st_CudaController_p,
+        st_ctrl_size_t,
+    ]
     st_CudaController_get_ptr_node_info_by_index.restype = st_CudaNodeInfo_p
 
-    st_CudaController_get_ptr_node_info_by_platform_id_and_device_id = \
+    st_CudaController_get_ptr_node_info_by_platform_id_and_device_id = (
         sixtracklib.st_CudaController_get_ptr_node_info_by_platform_id_and_device_id
+    )
     st_CudaController_get_ptr_node_info_by_platform_id_and_device_id.argtypes = [
-        st_CudaController_p, st_node_platform_id_t, st_node_device_id_t]
-    st_CudaController_get_ptr_node_info_by_platform_id_and_device_id.restype = \
+        st_CudaController_p,
+        st_node_platform_id_t,
+        st_node_device_id_t,
+    ]
+    st_CudaController_get_ptr_node_info_by_platform_id_and_device_id.restype = (
         st_CudaNodeInfo_p
+    )
 
-    st_CudaController_get_ptr_node_info_by_node_id = \
+    st_CudaController_get_ptr_node_info_by_node_id = (
         sixtracklib.st_CudaController_get_ptr_node_info_by_node_id
+    )
     st_CudaController_get_ptr_node_info_by_node_id.argtypes = [
-        st_CudaController_p, st_NodeId_p]
+        st_CudaController_p,
+        st_NodeId_p,
+    ]
     st_CudaController_get_ptr_node_info_by_node_id.restype = st_CudaNodeInfo_p
 
-    st_CudaController_get_ptr_node_info = \
+    st_CudaController_get_ptr_node_info = (
         sixtracklib.st_CudaController_get_ptr_node_info
+    )
     st_CudaController_get_ptr_node_info.argtypes = [
-        st_CudaController_p, ct.c_char_p]
+        st_CudaController_p,
+        ct.c_char_p,
+    ]
     st_CudaController_get_ptr_node_info.restype = st_CudaNodeInfo_p
 
-    st_CudaController_get_ptr_node_info_by_cuda_dev_index = \
+    st_CudaController_get_ptr_node_info_by_cuda_dev_index = (
         sixtracklib.st_CudaController_get_ptr_node_info_by_cuda_dev_index
+    )
     st_CudaController_get_ptr_node_info_by_cuda_dev_index.argtypes = [
-        st_CudaController_p, st_cuda_dev_index_t]
-    st_CudaController_get_ptr_node_info_by_cuda_dev_index.restype = \
+        st_CudaController_p,
+        st_cuda_dev_index_t,
+    ]
+    st_CudaController_get_ptr_node_info_by_cuda_dev_index.restype = (
         st_CudaNodeInfo_p
+    )
 
-    st_CudaController_get_ptr_node_info_by_pci_bus_id = \
+    st_CudaController_get_ptr_node_info_by_pci_bus_id = (
         sixtracklib.st_CudaController_get_ptr_node_info_by_pci_bus_id
+    )
     st_CudaController_get_ptr_node_info_by_pci_bus_id.argtypes = [
-        st_CudaController_p, ct.c_char_p]
-    st_CudaController_get_ptr_node_info_by_pci_bus_id.restype = \
+        st_CudaController_p,
+        ct.c_char_p,
+    ]
+    st_CudaController_get_ptr_node_info_by_pci_bus_id.restype = (
         st_CudaNodeInfo_p
+    )
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaController_add_kernel_config = \
+    st_CudaController_add_kernel_config = (
         sixtracklib.st_CudaController_add_kernel_config
+    )
     st_CudaController_add_kernel_config.argtypes = [
-        st_CudaController_p, st_CudaKernelConfig_p]
+        st_CudaController_p,
+        st_CudaKernelConfig_p,
+    ]
     st_CudaController_add_kernel_config.restype = st_kernel_id_t
 
-    st_CudaController_add_kernel_config_detailed = \
+    st_CudaController_add_kernel_config_detailed = (
         sixtracklib.st_CudaController_add_kernel_config_detailed
+    )
     st_CudaController_add_kernel_config_detailed.argtypes = [
-        st_CudaController_p, ct.c_char_p, st_ctrl_size_t, st_ctrl_size_t,
-        st_ctrl_size_t, st_ctrl_size_t, ct.c_char_p]
+        st_CudaController_p,
+        ct.c_char_p,
+        st_ctrl_size_t,
+        st_ctrl_size_t,
+        st_ctrl_size_t,
+        st_ctrl_size_t,
+        ct.c_char_p,
+    ]
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaController_get_ptr_kernel_config = \
+    st_CudaController_get_ptr_kernel_config = (
         sixtracklib.st_CudaController_get_ptr_kernel_config
+    )
     st_CudaController_get_ptr_kernel_config.argtypes = [
-        st_CudaController_p, st_kernel_id_t]
+        st_CudaController_p,
+        st_kernel_id_t,
+    ]
     st_CudaController_get_ptr_kernel_config.restype = st_CudaKernelConfig_p
 
-    st_CudaController_get_ptr_kernel_config_by_kernel_name = \
+    st_CudaController_get_ptr_kernel_config_by_kernel_name = (
         sixtracklib.st_CudaController_get_ptr_kernel_config_by_kernel_name
+    )
     st_CudaController_get_ptr_kernel_config_by_kernel_name.argtypes = [
-        st_CudaController_p, ct.c_char_p]
-    st_CudaController_get_ptr_kernel_config_by_kernel_name.restype = \
+        st_CudaController_p,
+        ct.c_char_p,
+    ]
+    st_CudaController_get_ptr_kernel_config_by_kernel_name.restype = (
         st_CudaKernelConfig_p
+    )
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaController_is_managed_cobject_buffer_remapped = \
+    st_CudaController_is_managed_cobject_buffer_remapped = (
         sixtracklib.st_CudaController_is_managed_cobject_buffer_remapped
+    )
     st_CudaController_is_managed_cobject_buffer_remapped.argtypes = [
-        st_CudaController_p, st_CudaArgBuffer_p, st_arch_size_t]
+        st_CudaController_p,
+        st_CudaArgBuffer_p,
+        st_arch_size_t,
+    ]
     st_CudaController_is_managed_cobject_buffer_remapped.restype = ct.c_bool
 
-    st_CudaController_remap_managed_cobject_buffer = \
+    st_CudaController_remap_managed_cobject_buffer = (
         sixtracklib.st_CudaController_remap_managed_cobject_buffer
+    )
     st_CudaController_remap_managed_cobject_buffer.argtypes = [
-        st_CudaController_p, st_CudaArgBuffer_p, st_arch_size_t]
+        st_CudaController_p,
+        st_CudaArgBuffer_p,
+        st_arch_size_t,
+    ]
     st_CudaController_remap_managed_cobject_buffer.restype = st_arch_status_t
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2813,13 +4531,19 @@ def st_OutputBuffer_create_output_cbuffer(
         st_CudaController_p,
         st_CudaArgument_p,
         ct.c_void_p,
-        st_arch_size_t]
+        st_arch_size_t,
+    ]
     st_CudaController_send_memory.restype = st_arch_status_t
 
-    st_CudaController_receive_memory = \
+    st_CudaController_receive_memory = (
         sixtracklib.st_CudaController_receive_memory
+    )
     st_CudaController_receive_memory.argtypes = [
-        st_CudaController_p, ct.c_void_p, st_CudaArgument_p, st_arch_size_t]
+        st_CudaController_p,
+        ct.c_void_p,
+        st_CudaArgument_p,
+        st_arch_size_t,
+    ]
     st_CudaController_receive_memory.restype = st_arch_status_t
 
     # --------------------------------------------------------------------------
@@ -2832,89 +4556,118 @@ def st_OutputBuffer_create_output_cbuffer(
     st_CudaArgument_new.argtypes = [st_CudaController_p]
     st_CudaArgument_new.restype = st_CudaArgument_p
 
-    st_CudaArgument_new_from_buffer = \
+    st_CudaArgument_new_from_buffer = (
         sixtracklib.st_CudaArgument_new_from_buffer
+    )
     st_CudaArgument_new_from_buffer.argtypes = [
-        st_Buffer_p, st_CudaController_p]
+        st_Buffer_p,
+        st_CudaController_p,
+    ]
     st_CudaArgument_new_from_buffer.restype = st_CudaArgument_p
 
-    st_CudaArgument_new_from_raw_argument = \
+    st_CudaArgument_new_from_raw_argument = (
         sixtracklib.st_CudaArgument_new_from_raw_argument
+    )
     st_CudaArgument_new_from_raw_argument.argtypes = [
-        ct.c_void_p, st_ctrl_size_t, st_CudaController_p]
+        ct.c_void_p,
+        st_ctrl_size_t,
+        st_CudaController_p,
+    ]
     st_CudaArgument_new_from_raw_argument.restype = st_CudaArgument_p
 
-    st_CudaArgument_new_from_size = \
-        sixtracklib.st_CudaArgument_new_from_size
+    st_CudaArgument_new_from_size = sixtracklib.st_CudaArgument_new_from_size
     st_CudaArgument_new_from_size.argtypes = [
-        st_ctrl_size_t, st_CudaController_p]
+        st_ctrl_size_t,
+        st_CudaController_p,
+    ]
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_Argument_has_cuda_arg_buffer = \
+    st_Argument_has_cuda_arg_buffer = (
         sixtracklib.st_Argument_has_cuda_arg_buffer
+    )
     st_Argument_has_cuda_arg_buffer.argtypes = [st_ArgumentBase_p]
     st_Argument_has_cuda_arg_buffer.restype = ct.c_bool
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaArgument_get_cuda_arg_buffer = \
+    st_CudaArgument_get_cuda_arg_buffer = (
         sixtracklib.st_CudaArgument_get_cuda_arg_buffer
+    )
     st_CudaArgument_get_cuda_arg_buffer.argtypes = [st_CudaArgument_p]
     st_CudaArgument_get_cuda_arg_buffer.restype = st_CudaArgBuffer_p
 
-    st_CudaArgument_get_const_cuda_arg_buffer = \
+    st_CudaArgument_get_const_cuda_arg_buffer = (
         sixtracklib.st_CudaArgument_get_const_cuda_arg_buffer
+    )
     st_CudaArgument_get_const_cuda_arg_buffer.argtypes = [st_CudaArgument_p]
     st_CudaArgument_get_const_cuda_arg_buffer.restype = st_CudaArgBuffer_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin = \
+    st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin = (
         sixtracklib.st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin
+    )
     st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin.argtypes = [
-        st_CudaArgument_p]
-    st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin.restype = \
+        st_CudaArgument_p
+    ]
+    st_CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin.restype = (
         st_uchar_p
+    )
 
-    st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin = \
+    st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin = (
         sixtracklib.st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin
-    st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin.argtypes \
-        = [st_CudaArgument_p]
-    st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin.restype \
-        = st_const_uchar_p
+    )
+    st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin.argtypes = [
+        st_CudaArgument_p
+    ]
+    st_CudaArgument_get_cuda_arg_buffer_as_const_cobject_buffer_begin.restype = (
+        st_const_uchar_p
+    )
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin = \
+    st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin = (
         sixtracklib.st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin
+    )
     st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin.argtypes = [
-        st_CudaArgument_p]
-    st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin.restype = \
+        st_CudaArgument_p
+    ]
+    st_CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin.restype = (
         st_arch_debugging_p
+    )
 
-    st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin = \
+    st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin = (
         sixtracklib.st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin
-    st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin.argtypes \
-        = [st_CudaArgument_p]
-    st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin.restype \
-        = st_arch_debugging_p
+    )
+    st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin.argtypes = [
+        st_CudaArgument_p
+    ]
+    st_CudaArgument_get_cuda_arg_buffer_as_const_debugging_register_begin.restype = (
+        st_arch_debugging_p
+    )
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin = \
+    st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin = (
         sixtracklib.st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin
+    )
     st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin.argtypes = [
-        st_CudaArgument_p]
-    st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin.restype = \
+        st_CudaArgument_p
+    ]
+    st_CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin.restype = (
         st_ElemByElemConfig_p
+    )
 
-    st_CudaArgument_get_cuda_arg_buffer_as_const_elem_by_elem_config_begin = \
+    st_CudaArgument_get_cuda_arg_buffer_as_const_elem_by_elem_config_begin = (
         sixtracklib.st_CudaArgument_get_cuda_arg_buffer_as_const_elem_by_elem_config_begin
+    )
     st_CudaArgument_get_cuda_arg_buffer_as_const_elem_by_elem_config_begin.argtypes = [
-        st_CudaArgument_p]
-    st_CudaArgument_get_cuda_arg_buffer_as_const_elem_by_elem_config_begin.restype = \
+        st_CudaArgument_p
+    ]
+    st_CudaArgument_get_cuda_arg_buffer_as_const_elem_by_elem_config_begin.restype = (
         st_ElemByElemConfig_p
+    )
 
     # ==========================================================================
     # NS(CudaTrackJob):
@@ -2922,21 +4675,28 @@ def st_OutputBuffer_create_output_cbuffer(
     st_CudaTrackJob_p = ct.c_void_p
     st_NullCudaTrackJob = ct.cast(0, st_CudaTrackJob_p)
 
-    st_CudaTrackJob_get_num_available_nodes = \
+    st_CudaTrackJob_get_num_available_nodes = (
         sixtracklib.st_CudaTrackJob_get_num_available_nodes
+    )
     st_CudaTrackJob_get_num_available_nodes.argtypes = None
     st_CudaTrackJob_get_num_available_nodes.restype = st_ctrl_size_t
 
-    _st_CudaTrackJob_get_available_node_ids_list = \
+    _st_CudaTrackJob_get_available_node_ids_list = (
         sixtracklib.st_CudaTrackJob_get_available_node_ids_list
+    )
     _st_CudaTrackJob_get_available_node_ids_list.argtypes = [
-        st_ctrl_size_t, st_NodeId_p]
+        st_ctrl_size_t,
+        st_NodeId_p,
+    ]
     _st_CudaTrackJob_get_available_node_ids_list.restype = st_ctrl_size_t
 
-    st_CudaTrackJob_get_available_node_indices_list = \
+    st_CudaTrackJob_get_available_node_indices_list = (
         sixtracklib.st_CudaTrackJob_get_available_node_indices_list
+    )
     st_CudaTrackJob_get_available_node_indices_list.argtypes = [
-        st_ctrl_size_t, st_node_index_p]
+        st_ctrl_size_t,
+        st_node_index_p,
+    ]
     st_CudaTrackJob_get_available_node_indices_list.restype = st_ctrl_size_t
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2945,8 +4705,9 @@ def st_OutputBuffer_create_output_cbuffer(
     st_CudaTrackJob_create.argtypes = None
     st_CudaTrackJob_create.restype = st_CudaTrackJob_p
 
-    st_CudaTrackJob_new_from_config_str = \
+    st_CudaTrackJob_new_from_config_str = (
         sixtracklib.st_CudaTrackJob_new_from_config_str
+    )
     st_CudaTrackJob_new_from_config_str.argtypes = [ct.c_char_p]
     st_CudaTrackJob_new_from_config_str.restype = st_CudaTrackJob_p
 
@@ -2954,10 +4715,16 @@ def st_OutputBuffer_create_output_cbuffer(
     st_CudaTrackJob_new.argtypes = [ct.c_char_p, st_Buffer_p, st_Buffer_p]
     st_CudaTrackJob_new.restype = st_CudaTrackJob_p
 
-    st_CudaTrackJob_new_with_output = \
+    st_CudaTrackJob_new_with_output = (
         sixtracklib.st_CudaTrackJob_new_with_output
+    )
     st_CudaTrackJob_new_with_output.argtypes = [
-        ct.c_char_p, st_Buffer_p, st_Buffer_p, st_Buffer_p, st_buffer_size_t]
+        ct.c_char_p,
+        st_Buffer_p,
+        st_Buffer_p,
+        st_Buffer_p,
+        st_buffer_size_t,
+    ]
     st_CudaTrackJob_new_with_output.restype = st_CudaTrackJob_p
 
     st_CudaTrackJob_new_detailed = sixtracklib.st_CudaTrackJob_new_detailed
@@ -2969,7 +4736,8 @@ def st_OutputBuffer_create_output_cbuffer(
         st_Buffer_p,
         st_Buffer_p,
         st_buffer_size_t,
-        ct.c_char_p]
+        ct.c_char_p,
+    ]
     st_CudaTrackJob_new_detailed.restype = st_CudaTrackJob_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2978,65 +4746,75 @@ def st_OutputBuffer_create_output_cbuffer(
     st_CudaTrackJob_has_controller.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_has_controller.restype = ct.c_bool
 
-    st_CudaTrackJob_get_ptr_controller = \
+    st_CudaTrackJob_get_ptr_controller = (
         sixtracklib.st_CudaTrackJob_get_ptr_controller
+    )
     st_CudaTrackJob_get_ptr_controller.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_controller.restype = st_CudaController_p
 
-    st_CudaTrackJob_get_ptr_const_controller = \
+    st_CudaTrackJob_get_ptr_const_controller = (
         sixtracklib.st_CudaTrackJob_get_ptr_const_controller
+    )
     st_CudaTrackJob_get_ptr_const_controller.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_const_controller.restype = st_CudaController_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaTrackJob_has_particles_arg = \
+    st_CudaTrackJob_has_particles_arg = (
         sixtracklib.st_CudaTrackJob_has_particles_arg
+    )
     st_CudaTrackJob_has_particles_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_has_particles_arg.restype = ct.c_bool
 
-    st_CudaTrackJob_get_ptr_particles_arg = \
+    st_CudaTrackJob_get_ptr_particles_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_particles_arg
+    )
     st_CudaTrackJob_get_ptr_particles_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_particles_arg.restype = st_CudaArgument_p
 
-    st_CudaTrackJob_get_ptr_const_particles_arg = \
+    st_CudaTrackJob_get_ptr_const_particles_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_const_particles_arg
+    )
     st_CudaTrackJob_get_ptr_const_particles_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_const_particles_arg.restype = st_CudaArgument_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaTrackJob_has_beam_elements_arg = \
+    st_CudaTrackJob_has_beam_elements_arg = (
         sixtracklib.st_CudaTrackJob_has_beam_elements_arg
+    )
     st_CudaTrackJob_has_beam_elements_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_has_beam_elements_arg.restype = ct.c_bool
 
-    st_CudaTrackJob_get_ptr_beam_elements_arg = \
+    st_CudaTrackJob_get_ptr_beam_elements_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_beam_elements_arg
+    )
     st_CudaTrackJob_get_ptr_beam_elements_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_beam_elements_arg.restype = st_CudaArgument_p
 
-    st_CudaTrackJob_get_ptr_const_beam_elements_arg = \
+    st_CudaTrackJob_get_ptr_const_beam_elements_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_const_beam_elements_arg
+    )
     st_CudaTrackJob_get_ptr_const_beam_elements_arg.argtypes = [
-        st_CudaTrackJob_p]
+        st_CudaTrackJob_p
+    ]
     st_CudaTrackJob_get_ptr_const_beam_elements_arg.restype = st_CudaArgument_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaTrackJob_has_output_arg = \
-        sixtracklib.st_CudaTrackJob_has_output_arg
+    st_CudaTrackJob_has_output_arg = sixtracklib.st_CudaTrackJob_has_output_arg
     st_CudaTrackJob_has_output_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_has_output_arg.restype = ct.c_bool
 
-    st_CudaTrackJob_get_ptr_output_arg = \
+    st_CudaTrackJob_get_ptr_output_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_output_arg
+    )
     st_CudaTrackJob_get_ptr_output_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_output_arg.restype = st_CudaArgument_p
 
-    st_CudaTrackJob_get_ptr_const_output_arg = \
+    st_CudaTrackJob_get_ptr_const_output_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_const_output_arg
+    )
     st_CudaTrackJob_get_ptr_const_output_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_const_output_arg.restype = st_CudaArgument_p
 
@@ -3044,140 +4822,1998 @@ def st_OutputBuffer_create_output_cbuffer(
 
     # st_CudaTrackJob_has_particles_arg = \
     # sixtracklib.st_CudaTrackJob_has_particles_arg
-    #st_CudaTrackJob_has_particles_arg.argtypes = [ st_CudaTrackJob_p ]
-    #st_CudaTrackJob_has_particles_arg.restype = ct.c_bool
+    # st_CudaTrackJob_has_particles_arg.argtypes = [ st_CudaTrackJob_p ]
+    # st_CudaTrackJob_has_particles_arg.restype = ct.c_bool
 
     # st_CudaTrackJob_get_ptr_particles_arg = \
     # sixtracklib.st_CudaTrackJob_get_ptr_particles_arg
-    #st_CudaTrackJob_get_ptr_particles_arg.argtypes = [ st_CudaTrackJob_p ]
-    #st_CudaTrackJob_get_ptr_particles_arg.restype = st_CudaArgument_p
+    # st_CudaTrackJob_get_ptr_particles_arg.argtypes = [ st_CudaTrackJob_p ]
+    # st_CudaTrackJob_get_ptr_particles_arg.restype = st_CudaArgument_p
 
     # st_CudaTrackJob_get_ptr_const_particles_arg = \
     # sixtracklib.st_CudaTrackJob_get_ptr_const_particles_arg
-    #st_CudaTrackJob_get_ptr_const_particles_arg.argtypes = [ st_CudaTrackJob_p ]
-    #st_CudaTrackJob_get_ptr_const_particles_arg.restype = st_CudaArgument_p
+    # st_CudaTrackJob_get_ptr_const_particles_arg.argtypes = [ st_CudaTrackJob_p ]
+    # st_CudaTrackJob_get_ptr_const_particles_arg.restype = st_CudaArgument_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaTrackJob_has_elem_by_elem_config_arg = \
+    st_CudaTrackJob_has_elem_by_elem_config_arg = (
         sixtracklib.st_CudaTrackJob_has_elem_by_elem_config_arg
-    st_CudaTrackJob_has_elem_by_elem_config_arg.argtypes = [
-        st_CudaTrackJob_p]
+    )
+    st_CudaTrackJob_has_elem_by_elem_config_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_has_elem_by_elem_config_arg.restype = ct.c_bool
 
-    st_CudaTrackJob_get_ptr_elem_by_elem_config_arg = \
+    st_CudaTrackJob_get_ptr_elem_by_elem_config_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_elem_by_elem_config_arg
+    )
     st_CudaTrackJob_get_ptr_elem_by_elem_config_arg.argtypes = [
-        st_CudaTrackJob_p]
+        st_CudaTrackJob_p
+    ]
     st_CudaTrackJob_get_ptr_elem_by_elem_config_arg.restype = st_CudaArgument_p
 
-    st_CudaTrackJob_get_ptr_const_elem_by_elem_config_arg = \
+    st_CudaTrackJob_get_ptr_const_elem_by_elem_config_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_const_elem_by_elem_config_arg
+    )
     st_CudaTrackJob_get_ptr_const_elem_by_elem_config_arg.argtypes = [
-        st_CudaTrackJob_p]
-    st_CudaTrackJob_get_ptr_const_elem_by_elem_config_arg.restype = \
+        st_CudaTrackJob_p
+    ]
+    st_CudaTrackJob_get_ptr_const_elem_by_elem_config_arg.restype = (
         st_CudaArgument_p
+    )
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaTrackJob_has_debug_register_arg = \
+    st_CudaTrackJob_has_debug_register_arg = (
         sixtracklib.st_CudaTrackJob_has_debug_register_arg
+    )
     st_CudaTrackJob_has_debug_register_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_has_debug_register_arg.restype = ct.c_bool
 
-    st_CudaTrackJob_get_ptr_debug_register_arg = \
+    st_CudaTrackJob_get_ptr_debug_register_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_debug_register_arg
+    )
     st_CudaTrackJob_get_ptr_debug_register_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_debug_register_arg.restype = st_CudaArgument_p
 
-    st_CudaTrackJob_get_ptr_const_debug_register_arg = \
+    st_CudaTrackJob_get_ptr_const_debug_register_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_const_debug_register_arg
+    )
     st_CudaTrackJob_get_ptr_const_debug_register_arg.argtypes = [
-        st_CudaTrackJob_p]
-    st_CudaTrackJob_get_ptr_const_debug_register_arg.restype = \
-        st_CudaArgument_p
+        st_CudaTrackJob_p
+    ]
+    st_CudaTrackJob_get_ptr_const_debug_register_arg.restype = st_CudaArgument_p
 
     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-    st_CudaTrackJob_has_particles_addr_arg = \
+    st_CudaTrackJob_has_particles_addr_arg = (
         sixtracklib.st_CudaTrackJob_has_particles_addr_arg
+    )
     st_CudaTrackJob_has_particles_addr_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_has_particles_addr_arg.restype = ct.c_bool
 
-    st_CudaTrackJob_get_ptr_particles_addr_arg = \
+    st_CudaTrackJob_get_ptr_particles_addr_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_particles_addr_arg
+    )
     st_CudaTrackJob_get_ptr_particles_addr_arg.argtypes = [st_CudaTrackJob_p]
     st_CudaTrackJob_get_ptr_particles_addr_arg.restype = st_CudaArgument_p
 
-    st_CudaTrackJob_get_ptr_const_particles_addr_arg = \
+    st_CudaTrackJob_get_ptr_const_particles_addr_arg = (
         sixtracklib.st_CudaTrackJob_get_ptr_const_particles_addr_arg
+    )
     st_CudaTrackJob_get_ptr_const_particles_addr_arg.argtypes = [
+        st_CudaTrackJob_p
+    ]
+    st_CudaTrackJob_get_ptr_const_particles_addr_arg.restype = st_CudaArgument_p
+
+    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+    st_CudaTrackJob_default_threads_per_block = \
+        sixtracklib.st_CudaTrackJob_default_threads_per_block
+    st_CudaTrackJob_default_threads_per_block.argtypes = [st_CudaTrackJob_p]
+    st_CudaTrackJob_default_threads_per_block.restype = st_arch_size_t
+
+    st_CudaTrackJob_default_track_threads_per_block = \
+        sixtracklib.st_CudaTrackJob_default_track_threads_per_block
+    st_CudaTrackJob_default_track_threads_per_block.argtypes = [
         st_CudaTrackJob_p]
-    st_CudaTrackJob_get_ptr_const_particles_addr_arg.restype = \
-        st_CudaArgument_p
+    st_CudaTrackJob_default_track_threads_per_block.restype = st_arch_size_t
 
 # -----------------------------------------------------------------------------
 # Cl-Context methods
 
-if SIXTRACKLIB_MODULES.get('opencl', False):
+if SIXTRACKLIB_MODULES.get("opencl", False):
+    st_ClArgument_p = ct.c_void_p
+    st_NullClArgument = ct.cast(0, st_ClArgument_p)
+
+    st_ClContextBase_p = ct.c_void_p
+    st_NullClContextBase = ct.cast(0, st_ClContextBase_p)
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    class st_ClNodeId(ct.Structure):
+        _fields_ = [("platform_id", ct.c_int64), ("device_id", ct.c_int64)]
+
+    st_cl_node_id_t = st_ClNodeId
+    st_ClNodeId_p = ct.POINTER(st_ClNodeId)
+    st_NullClNodeId = ct.cast(0, st_ClNodeId_p)
+
+    st_ComputeNodeId_create = sixtracklib.st_ComputeNodeId_create
+    st_ComputeNodeId_create.argtypes = None
+    st_ComputeNodeId_create.restype = st_ClNodeId_p
+
+    st_ComputeNodeId_delete = sixtracklib.st_ComputeNodeId_delete
+    st_ComputeNodeId_delete.argtypes = [st_ClNodeId_p]
+    st_ComputeNodeId_delete.restype = None
+
+    st_ComputeNodeId_get_platform_id = (
+        sixtracklib.st_ComputeNodeId_get_platform_id_ext
+    )
+    st_ComputeNodeId_get_platform_id.argtypes = [st_ClNodeId_p]
+    st_ComputeNodeId_get_platform_id.restype = st_node_platform_id_t
+
+    st_ComputeNodeId_get_device_id = (
+        sixtracklib.st_ComputeNodeId_get_device_id_ext
+    )
+    st_ComputeNodeId_get_device_id.argtypes = [st_ClNodeId_p]
+    st_ComputeNodeId_get_device_id.restype = st_node_device_id_t
+
+    st_ComputeNodeId_set_platform_id = (
+        sixtracklib.st_ComputeNodeId_set_platform_id_ext
+    )
+    st_ComputeNodeId_set_platform_id.argtypes = [
+        st_ClNodeId_p,
+        st_node_platform_id_t,
+    ]
+    st_ComputeNodeId_set_platform_id.restype = None
+
+    st_ComputeNodeId_set_device_id = (
+        sixtracklib.st_ComputeNodeId_set_device_id_ext
+    )
+    st_ComputeNodeId_set_device_id.argtypes = [
+        st_ClNodeId_p,
+        st_node_device_id_t,
+    ]
+    st_ComputeNodeId_set_device_id.restype = None
+
+    st_ComputeNodeId_is_valid = sixtracklib.st_ComputeNodeId_is_valid_ext
+    st_ComputeNodeId_is_valid.argtypes = [st_ClNodeId_p]
+    st_ComputeNodeId_is_valid.restype = ct.c_bool
+
+    st_ComputeNodeId_compare = sixtracklib.st_ComputeNodeId_compare_ext
+    st_ComputeNodeId_compare.argtypes = [st_ClNodeId_p, st_ClNodeId_p]
+    st_ComputeNodeId_compare.restype = ct.c_int
+
+    st_ComputeNodeId_are_equal = sixtracklib.st_ComputeNodeId_are_equal_ext
+    st_ComputeNodeId_are_equal.argtypes = [st_ClNodeId_p, st_ClNodeId_p]
+    st_ComputeNodeId_are_equal.restype = ct.c_bool
+
+    st_ComputeNodeId_to_string = sixtracklib.st_ComputeNodeId_to_string
+    st_ComputeNodeId_to_string.argtypes = [
+        st_ClNodeId_p,
+        ct.c_char_p,
+        st_arch_size_t,
+    ]
+    st_ComputeNodeId_to_string.restype = st_arch_status_t
+
+    st_ComputeNodeId_from_string = sixtracklib.st_ComputeNodeId_from_string
+    st_ComputeNodeId_from_string.argtypes = [st_ClNodeId_p, ct.c_char_p]
+    st_ComputeNodeId_from_string.restype = st_arch_status_t
+
+    st_ComputeNodeId_to_string_with_format = (
+        sixtracklib.st_ComputeNodeId_to_string_with_format
+    )
+    st_ComputeNodeId_to_string_with_format.argtypes = [
+        st_NodeId_p,
+        ct.c_char_p,
+        st_arch_size_t,
+        st_arch_id_t,
+        st_node_id_str_fmt_t,
+    ]
+    st_ComputeNodeId_to_string_with_format.restype = st_arch_status_t
+
+    st_ComputeNodeId_from_string_with_format = (
+        sixtracklib.st_ComputeNodeId_from_string_with_format
+    )
+    st_ComputeNodeId_from_string_with_format.argtypes = [
+        st_ClNodeId_p,
+        ct.c_char_p,
+        st_node_id_str_fmt_t,
+        st_arch_id_p,
+    ]
+    st_ComputeNodeId_from_string_with_format.restype = st_arch_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    class st_ClNodeInfo(ct.Structure):
+        _pack_ = 8
+        _fields_ = [
+            ("id", st_ClNodeId),
+            ("arch", ct.c_char_p),
+            ("platform", ct.c_char_p),
+            ("name", ct.c_char_p),
+            ("description", ct.c_char_p),
+        ]
+
+    st_cl_node_info_t = st_ClNodeInfo
+    st_ClNodeInfo_p = ct.POINTER(st_ClNodeInfo)
+    st_NullClNodeInfo = ct.cast(0, st_ClNodeInfo_p)
+
+    st_ComputeNodeInfo_preset = sixtracklib.st_ComputeNodeInfo_preset_ext
+    st_ComputeNodeInfo_preset.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_preset.restype = st_ClNodeInfo_p
+
+    st_ComputeNodeInfo_print_out = sixtracklib.st_ComputeNodeInfo_print_out
+    st_ComputeNodeInfo_print_out.argtypes = [st_ClNodeInfo_p, st_ClNodeId_p]
+    st_ComputeNodeInfo_print_out.restype = None
+
+    st_ComputeNodeInfo_free = sixtracklib.st_ComputeNodeInfo_free
+    st_ComputeNodeInfo_free.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_free.restype = None
+
+    st_ComputeNodeInfo_delete = sixtracklib.st_ComputeNodeInfo_delete
+    st_ComputeNodeInfo_delete.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_delete.restype = None
+
+    st_ComputeNodeInfo_reserve = sixtracklib.st_ComputeNodeInfo_reserve
+    st_ComputeNodeInfo_reserve.argtypes = [
+        st_ClNodeInfo_p,
+        st_arch_size_t,
+        st_arch_size_t,
+        st_arch_size_t,
+        st_arch_size_t,
+    ]
+    st_ComputeNodeInfo_reserve.restype = st_ClNodeInfo_p
+
+    st_ComputeNodeInfo_make = sixtracklib.st_ComputeNodeInfo_make
+    st_ComputeNodeInfo_make.argtypes = [
+        st_ClNodeInfo_p,
+        st_ClNodeId,
+        ct.c_char_p,
+        ct.c_char_p,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_ComputeNodeInfo_make.restype = ct.c_int
+
+    st_ComputeNodeInfo_is_valid = sixtracklib.st_ComputeNodeInfo_is_valid_ext
+    st_ComputeNodeInfo_is_valid.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_is_valid.restype = ct.c_bool
+
+    st_ComputeNodeInfo_get_id = sixtracklib.st_ComputeNodeInfo_get_id_ext
+    st_ComputeNodeInfo_get_id.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_get_id.restype = st_ClNodeId
+
+    st_ComputeNodeInfo_get_platform_id = (
+        sixtracklib.st_ComputeNodeInfo_get_platform_id_ext
+    )
+    st_ComputeNodeInfo_get_platform_id.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_get_platform_id.restype = st_node_platform_id_t
+
+    st_ComputeNodeInfo_get_device_id = (
+        sixtracklib.st_ComputeNodeInfo_get_device_id_ext
+    )
+    st_ComputeNodeInfo_get_device_id.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_get_device_id.restype = st_node_device_id_t
+
+    st_ComputeNodeInfo_get_arch = sixtracklib.st_ComputeNodeInfo_get_arch_ext
+    st_ComputeNodeInfo_get_arch.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_get_arch.restype = ct.c_char_p
+
+    st_ComputeNodeInfo_get_platform = (
+        sixtracklib.st_ComputeNodeInfo_get_platform_ext
+    )
+    st_ComputeNodeInfo_get_platform.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_get_platform.restype = ct.c_char_p
+
+    st_ComputeNodeInfo_get_name = sixtracklib.st_ComputeNodeInfo_get_name_ext
+    st_ComputeNodeInfo_get_name.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_get_name.restype = ct.c_char_p
+
+    st_ComputeNodeInfo_get_description = (
+        sixtracklib.st_ComputeNodeInfo_get_description_ext
+    )
+    st_ComputeNodeInfo_get_description.argtypes = [st_ClNodeInfo_p]
+    st_ComputeNodeInfo_get_description.restype = ct.c_char_p
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_OpenCL_get_num_all_nodes = sixtracklib.st_OpenCL_get_num_all_nodes
+    st_OpenCL_get_num_all_nodes.argtypes = None
+    st_OpenCL_get_num_all_nodes.restype = st_arch_size_t
+
+    st_OpenCL_get_all_nodes = sixtracklib.st_OpenCL_get_all_nodes
+    st_OpenCL_get_all_nodes.argtypes = [st_ClNodeInfo_p, st_arch_size_t]
+    st_OpenCL_get_all_nodes.restype = st_arch_size_t
 
     st_OpenCL_print_all_nodes = sixtracklib.st_OpenCL_print_all_nodes
     st_OpenCL_print_all_nodes.argtypes = None
     st_OpenCL_print_all_nodes.restype = None
 
-    st_OpenCL_print_available_nodes = \
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_OpenCL_num_available_nodes = sixtracklib.st_OpenCL_num_available_nodes
+    st_OpenCL_num_available_nodes.argtypes = [ct.c_char_p]
+    st_OpenCL_num_available_nodes.restype = st_arch_size_t
+
+    st_OpenCL_num_available_nodes_detailed = (
+        sixtracklib.st_OpenCL_num_available_nodes_detailed
+    )
+    st_OpenCL_num_available_nodes_detailed.argtypes = [
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_OpenCL_num_available_nodes_detailed.restype = st_arch_size_t
+
+    st_OpenCL_get_available_nodes = sixtracklib.st_OpenCL_get_available_nodes
+    st_OpenCL_get_available_nodes.argtypes = [st_ClNodeId_p, st_arch_size_t]
+    st_OpenCL_get_available_nodes.restype = st_arch_size_t
+
+    st_OpenCL_get_available_nodes_detailed = (
+        sixtracklib.st_OpenCL_get_available_nodes_detailed
+    )
+    st_OpenCL_get_available_nodes_detailed.argtypes = [
+        st_ClNodeId_p,
+        st_arch_size_t,
+        st_arch_size_t,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_OpenCL_get_available_nodes_detailed.restype = st_arch_size_t
+
+    st_OpenCL_print_available_nodes = (
         sixtracklib.st_OpenCL_print_available_nodes
+    )
     st_OpenCL_print_available_nodes.argtypes = None
     st_OpenCL_print_available_nodes.restype = None
 
-    st_OpenCL_get_all_nodes_required_str_capacity = \
+    st_OpenCL_print_available_nodes_detailed = (
+        sixtracklib.st_OpenCL_print_available_nodes_detailed
+    )
+    st_OpenCL_print_available_nodes_detailed.argtypes = [
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_OpenCL_print_available_nodes_detailed.restype = None
+
+    # --------------------------------------------------------------------------
+
+    st_ClArgument_new = sixtracklib.st_ClArgument_new
+    st_ClArgument_new.argtypes = [st_ClContextBase_p]
+    st_ClArgument_new.restype = st_ClArgument_p
+
+    st_ClArgument_new_from_buffer = sixtracklib.st_ClArgument_new_from_buffer
+    st_ClArgument_new_from_buffer.argtypes = [st_Buffer_p, st_ClContextBase_p]
+    st_ClArgument_new_from_buffer.restype = st_ClArgument_p
+
+    st_ClArgument_new_from_size = sixtracklib.st_ClArgument_new_from_size
+    st_ClArgument_new_from_size.argtypes = [st_arch_size_t, st_ClContextBase_p]
+    st_ClArgument_new_from_size.restype = st_ClArgument_p
+
+    st_ClArgument_new_from_memory = sixtracklib.st_ClArgument_new_from_memory
+    st_ClArgument_new_from_memory.argtypes = [
+        ct.c_void_p,
+        st_arch_size_t,
+        st_ClContextBase_p,
+    ]
+    st_ClArgument_new_from_memory.restype = st_ClArgument_p
+
+    st_ClArgument_delete = sixtracklib.st_ClArgument_delete
+    st_ClArgument_delete.argtypes = [st_ClArgument_p]
+    st_ClArgument_delete.restype = None
+
+    st_ClArgument_write = sixtracklib.st_ClArgument_write
+    st_ClArgument_write.argtypes = [st_ClArgument_p, st_Buffer_p]
+    st_ClArgument_write.restype = ct.c_bool
+
+    st_ClArgument_write_memory = sixtracklib.st_ClArgument_write_memory
+    st_ClArgument_write_memory.argtypes = [
+        st_ClArgument_p,
+        ct.c_void_p,
+        st_arch_size_t,
+    ]
+    st_ClArgument_write_memory.restype = ct.c_bool
+
+    st_ClArgument_read = sixtracklib.st_ClArgument_write
+    st_ClArgument_read.argtypes = [st_ClArgument_p, st_Buffer_p]
+    st_ClArgument_read.restype = ct.c_bool
+
+    st_ClArgument_read_memory = sixtracklib.st_ClArgument_read_memory
+    st_ClArgument_read_memory.argtypes = [
+        st_ClArgument_p,
+        ct.c_void_p,
+        st_arch_size_t,
+    ]
+    st_ClArgument_read_memory.restype = ct.c_bool
+
+    st_ClArgument_get_argument_size = (
+        sixtracklib.st_ClArgument_get_argument_size
+    )
+    st_ClArgument_get_argument_size.argtypes = [st_ClArgument_p]
+    st_ClArgument_get_argument_size.restype = st_arch_size_t
+
+    st_ClArgument_update_region = sixtracklib.st_ClArgument_update_region
+    st_ClArgument_update_region.argtypes = [
+        st_ClArgument_p,
+        st_arch_size_t,
+        st_arch_size_t,
+        ct.c_void_p,
+    ]
+    st_ClArgument_update_region.restype = st_arch_status_t
+
+    st_ClArgument_update_regions = sixtracklib.st_ClArgument_update_regions
+    st_ClArgument_update_regions.argtypes = [
+        st_ClArgument_p,
+        st_arch_size_t,
+        st_arch_size_t_p,
+        st_arch_size_t_p,
+        ct.POINTER(ct.c_void_p),
+    ]
+    st_ClArgument_update_regions.restype = st_arch_status_t
+
+    st_ClArgument_uses_cobj_buffer = sixtracklib.st_ClArgument_uses_cobj_buffer
+    st_ClArgument_uses_cobj_buffer.argtypes = [st_ClArgument_p]
+    st_ClArgument_uses_cobj_buffer.restype = ct.c_bool
+
+    st_ClArgument_get_ptr_cobj_buffer = (
+        sixtracklib.st_ClArgument_get_ptr_cobj_buffer
+    )
+    st_ClArgument_get_ptr_cobj_buffer.argtypes = [st_ClArgument_p]
+    st_ClArgument_get_ptr_cobj_buffer.restype = st_Buffer_p
+
+    st_ClArgument_get_ptr_to_context = (
+        sixtracklib.st_ClArgument_get_ptr_to_context
+    )
+    st_ClArgument_get_ptr_to_context.argtypes = [st_ClArgument_p]
+    st_ClArgument_get_ptr_to_context.restype = st_ClContextBase_p
+
+    st_ClArgument_attach_to_context = (
+        sixtracklib.st_ClArgument_attach_to_context
+    )
+    st_ClArgument_attach_to_context.argtypes = [
+        st_ClArgument_p,
+        st_ClContextBase_p,
+    ]
+    st_ClArgument_attach_to_context.restype = ct.c_bool
+
+    # --------------------------------------------------------------------------
+
+    st_arch_program_id_t = ct.c_uint32
+    st_arch_kernel_id_t = ct.c_uint32
+    st_ARCH_ILLEGAL_KERNEL_ID = st_arch_kernel_id_t(0xFFFFFFFF)
+    st_ARCH_ILLEGAL_PROGRAM_ID = st_arch_program_id_t(0xFFFFFFFF)
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_kernel_arg_type_t = ct.c_uint32
+    st_KERNEL_ARG_TYPE_NONE = st_kernel_arg_type_t(0x00000000)
+    st_KERNEL_ARG_TYPE_VALUE = st_kernel_arg_type_t(0x00000001)
+    st_KERNEL_ARG_TYPE_RAW_PTR = st_kernel_arg_type_t(0x00000002)
+    st_KERNEL_ARG_TYPE_CL_ARGUMENT = st_kernel_arg_type_t(0x00000010)
+    st_KERNEL_ARG_TYPE_CL_BUFFER = st_kernel_arg_type_t(0x00000020)
+    st_KERNEL_ARG_TYPE_NONE = st_kernel_arg_type_t(0xFFFFFFFF)
+
+    st_ClContextBase_new = sixtracklib.st_ClContextBase_new
+    st_ClContextBase_new.argtypes = None
+    st_ClContextBase_new.restype = st_ClContextBase_p
+
+    st_ClContextBase_set_default_compile_options = (
+        sixtracklib.st_ClContextBase_set_default_compile_options
+    )
+    st_ClContextBase_set_default_compile_options.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_set_default_compile_options.restype = None
+
+    st_ClContextBase_default_compile_options = (
+        sixtracklib.st_ClContextBase_default_compile_options
+    )
+    st_ClContextBase_default_compile_options.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_default_compile_options.restype = ct.c_char_p
+
+    st_ClContextBase_new_on_selected_node_id_str = (
+        sixtracklib.st_ClContextBase_new_on_selected_node_id_str
+    )
+    st_ClContextBase_new_on_selected_node_id_str.argtypes = [ct.c_char_p]
+    st_ClContextBase_new_on_selected_node_id_str.restype = st_ClContextBase_p
+
+    st_ClContextBase_new_on_selected_node_id = (
+        sixtracklib.st_ClContextBase_new_on_selected_node_id
+    )
+    st_ClContextBase_new_on_selected_node_id.argtypes = [st_ClNodeId_p]
+    st_ClContextBase_new_on_selected_node_id.restype = st_ClContextBase_p
+
+    st_ClContextBase_delete = sixtracklib.st_ClContextBase_delete
+    st_ClContextBase_delete.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_delete.restype = None
+
+    st_ClContextBase_clear = sixtracklib.st_ClContextBase_clear
+    st_ClContextBase_clear.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_clear.restyp = None
+
+    st_ClContextBase_reinit_default_programs = (
+        sixtracklib.st_ClContextBase_reinit_default_programs
+    )
+    st_ClContextBase_reinit_default_programs.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_reinit_default_programs.restype = st_arch_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContextBase_get_num_available_nodes = (
+        sixtracklib.st_ClContextBase_get_num_available_nodes
+    )
+    st_ClContextBase_get_num_available_nodes.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_get_num_available_nodes.restype = st_arch_size_t
+
+    st_ClContextBase_get_available_node_info_by_index = (
+        sixtracklib.st_ClContextBase_get_available_node_info_by_index
+    )
+    st_ClContextBase_get_available_node_info_by_index.argtypes = [
+        st_ClContextBase_p,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_get_available_node_info_by_index.restype = st_ClNodeInfo_p
+
+    st_ClContextBase_is_available_node_amd_platform = (
+        sixtracklib.st_ClContextBase_is_available_node_amd_platform
+    )
+    st_ClContextBase_is_available_node_amd_platform.argtypes = [
+        st_ClContextBase_p,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_is_available_node_amd_platform.restype = ct.c_bool
+
+    st_ClContextBase_get_default_node_info = (
+        sixtracklib.st_ClContextBase_get_default_node_info
+    )
+    st_ClContextBase_get_default_node_info.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_get_default_node_info.restype = st_ClNodeInfo_p
+
+    st_ClContextBase_get_default_node_id = (
+        sixtracklib.st_ClContextBase_get_default_node_id
+    )
+    st_ClContextBase_get_default_node_id.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_get_default_node_id.restype = st_ClNodeId
+
+    st_ClContextBase_get_available_node_info_by_node_id = (
+        sixtracklib.st_ClContextBase_get_available_node_info_by_node_id
+    )
+    st_ClContextBase_get_available_node_info_by_node_id.argtypes = [
+        st_ClContextBase_p,
+        st_ClNodeId_p,
+    ]
+    st_ClContextBase_get_available_node_info_by_node_id.restype = (
+        st_ClNodeInfo_p
+    )
+
+    st_ClContextBase_is_node_id_str_available = (
+        sixtracklib.st_ClContextBase_is_node_id_str_available
+    )
+    st_ClContextBase_is_node_id_str_available.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_is_node_id_str_available.restype = ct.c_bool
+
+    st_ClContextBase_is_node_id_available = (
+        sixtracklib.st_ClContextBase_is_node_id_available
+    )
+    st_ClContextBase_is_node_id_available.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_is_node_id_available.restype = ct.c_bool
+
+    st_ClContextBase_is_node_index_available = (
+        sixtracklib.st_ClContextBase_is_node_index_available
+    )
+    st_ClContextBase_is_node_index_available.argtypes = [
+        st_ClContextBase_p,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_is_node_index_available.restype = ct.c_bool
+
+    st_ClContextBase_is_platform_device_tuple_available = (
+        sixtracklib.st_ClContextBase_is_platform_device_tuple_available
+    )
+    st_ClContextBase_is_platform_device_tuple_available.argtypes = [
+        st_ClContextBase_p,
+        st_node_platform_id_t,
+        st_node_device_id_t,
+    ]
+    st_ClContextBase_is_platform_device_tuple_available.restype = ct.c_bool
+
+    st_ClContextBase_is_node_id_default_node = (
+        sixtracklib.st_ClContextBase_is_node_id_default_node
+    )
+    st_ClContextBase_is_node_id_default_node.argtypes = [
+        st_ClContextBase_p,
+        st_ClNodeId_p,
+    ]
+    st_ClContextBase_is_node_id_default_node.restype = ct.c_bool
+
+    st_ClContextBase_is_node_id_str_default_node = (
+        sixtracklib.st_ClContextBase_is_node_id_str_default_node
+    )
+    st_ClContextBase_is_node_id_str_default_node.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_is_node_id_str_default_node.restype = ct.c_bool
+
+    st_ClContextBase_is_platform_device_tuple_default_node = (
+        sixtracklib.st_ClContextBase_is_platform_device_tuple_default_node
+    )
+    st_ClContextBase_is_platform_device_tuple_default_node.argtypes = [
+        st_ClContextBase_p,
+        st_node_platform_id_t,
+        st_node_device_id_t,
+    ]
+    st_ClContextBase_is_platform_device_tuple_default_node.restype = ct.c_bool
+
+    st_ClContextBase_is_node_index_default_node = (
+        sixtracklib.st_ClContextBase_is_node_index_default_node
+    )
+    st_ClContextBase_is_node_index_default_node.argtypes = [
+        st_ClContextBase_p,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_is_node_index_default_node.restype = ct.c_bool
+
+    st_ClContextBase_has_selected_node = (
+        sixtracklib.st_ClContextBase_has_selected_node
+    )
+    st_ClContextBase_has_selected_node.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_has_selected_node.restype = ct.c_bool
+
+    st_ClContextBase_get_selected_node_info = (
+        sixtracklib.st_ClContextBase_get_selected_node_info
+    )
+    st_ClContextBase_get_selected_node_info.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_get_selected_node_info.restype = st_ClNodeInfo_p
+
+    st_ClContextBase_get_selected_node_id = (
+        sixtracklib.st_ClContextBase_get_selected_node_id
+    )
+    st_ClContextBase_get_selected_node_id.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_get_selected_node_id.restype = st_ClNodeId_p
+
+    st_ClContextBase_get_selected_node_index = (
+        sixtracklib.st_ClContextBase_get_selected_node_index
+    )
+    st_ClContextBase_get_selected_node_index.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_get_selected_node_index.restype = st_arch_size_t
+
+    st_ClContextBase_get_selected_node_id_str = (
+        sixtracklib.st_ClContextBase_get_selected_node_id_str
+    )
+    st_ClContextBase_get_selected_node_id_str.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_get_selected_node_id_str.restype = ct.c_bool
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContextBase_select_node_by_node_id = (
+        sixtracklib.st_ClContextBase_select_node_by_node_id
+    )
+    st_ClContextBase_select_node_by_node_id.argtypes = [
+        st_ClContextBase_p,
+        st_ClNodeId_p,
+    ]
+    st_ClContextBase_select_node_by_node_id.restype = ct.c_bool
+
+    st_ClContextBase_select_node_by_index = (
+        sixtracklib.st_ClContextBase_select_node_by_index
+    )
+    st_ClContextBase_select_node_by_index.argtypes = [
+        st_ClContextBase_p,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_select_node_by_index.restype = ct.c_bool
+
+    st_OpenCL_get_all_nodes_required_str_capacity = (
         sixtracklib.st_OpenCL_get_all_nodes_required_str_capacity
+    )
     st_OpenCL_get_all_nodes_required_str_capacity.argtypes = None
     st_OpenCL_get_all_nodes_required_str_capacity.restype = st_arch_size_t
 
-    st_OpenCL_get_all_nodes_as_string = \
+    st_OpenCL_get_all_nodes_as_string = (
         sixtracklib.st_OpenCL_get_all_nodes_as_string
+    )
     st_OpenCL_get_all_nodes_as_string.argtypes = [ct.c_char_p, st_arch_size_t]
+    st_OpenCL_get_all_nodes_as_string.restype = st_arch_status_t
 
-    st_OpenCL_get_available_nodes_required_str_capacity = \
+    st_OpenCL_get_available_nodes_required_str_capacity = (
         sixtracklib.st_OpenCL_get_available_nodes_required_str_capacity
+    )
     st_OpenCL_get_available_nodes_required_str_capacity.argtypes = [
-        ct.c_char_p, ct.c_char_p]
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
     st_OpenCL_get_available_nodes_required_str_capacity.restype = st_arch_size_t
 
-    st_OpenCL_get_available_nodes_as_string = \
+    st_OpenCL_get_available_nodes_as_string = (
         sixtracklib.st_OpenCL_get_available_nodes_as_string
+    )
     st_OpenCL_get_available_nodes_as_string.argtypes = [
-        ct.c_char_p, st_arch_size_t, ct.c_char_p, ct.c_char_p]
+        ct.c_char_p,
+        st_arch_size_t,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
     st_OpenCL_get_available_nodes_as_string.restype = st_arch_status_t
 
     st_ClContext_create = sixtracklib.st_ClContext_create
     st_ClContext_create.restype = st_Context_p
 
     st_ClContextBase_select_node = sixtracklib.st_ClContextBase_select_node
-    st_ClContextBase_select_node.argtypes = [st_Context_p, ct.c_char_p]
+    st_ClContextBase_select_node.argtypes = [st_ClContextBase_p, ct.c_char_p]
     st_ClContextBase_select_node.restype = None
 
-    st_ClContextBase_print_nodes_info = \
+    st_ClContextBase_get_num_available_programs = (
+        sixtracklib.st_ClContextBase_get_num_available_programs
+    )
+    st_ClContextBase_get_num_available_programs.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_get_num_available_programs.restype = st_arch_size_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContextBase_print_nodes_info = (
         sixtracklib.st_ClContextBase_print_nodes_info
-    st_ClContextBase_print_nodes_info.argtypes = [st_Context_p]
+    )
+    st_ClContextBase_print_nodes_info.argtypes = [st_ClContextBase_p]
     st_ClContextBase_print_nodes_info.restype = None
 
-    st_ClContextBase_delete = sixtracklib.st_ClContextBase_delete
-    st_ClContextBase_delete.argtypes = [st_Context_p]
-    st_ClContextBase_delete.restype = None
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContextBase_add_program_file = (
+        sixtracklib.st_ClContextBase_add_program_file
+    )
+    st_ClContextBase_add_program_file.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_add_program_file.restype = st_arch_program_id_t
+
+    st_ClContextBase_compile_program = (
+        sixtracklib.st_ClContextBase_compile_program
+    )
+    st_ClContextBase_compile_program.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_compile_program.restype = ct.c_bool
+
+    st_ClContextBase_get_required_program_source_code_capacity = (
+        sixtracklib.st_ClContextBase_get_required_program_source_code_capacity
+    )
+    st_ClContextBase_get_required_program_source_code_capacity.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_get_required_program_source_code_capacity.restype = (
+        st_arch_size_t
+    )
+
+    st_ClContextBase_get_program_source_code = (
+        sixtracklib.st_ClContextBase_get_program_source_code
+    )
+    st_ClContextBase_get_program_source_code.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_get_program_source_code.restype = ct.c_char_p
+
+    st_ClContextBase_has_program_file_path = (
+        sixtracklib.st_ClContextBase_has_program_file_path
+    )
+    st_ClContextBase_has_program_file_path.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_has_program_file_path.restype = ct.c_bool
+
+    st_ClContextBase_get_required_program_path_capacity = (
+        sixtracklib.st_ClContextBase_get_required_program_path_capacity
+    )
+    st_ClContextBase_get_required_program_path_capacity.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_get_required_program_path_capacity.restype = st_arch_size_t
+
+    st_ClContextBase_get_program_path_to_file = (
+        sixtracklib.st_ClContextBase_get_program_path_to_file
+    )
+    st_ClContextBase_get_program_path_to_file.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_get_program_path_to_file.restype = ct.c_char_p
+
+    st_ClContextBase_get_required_program_compile_options_capacity = (
+        sixtracklib.st_ClContextBase_get_required_program_compile_options_capacity
+    )
+    st_ClContextBase_get_required_program_compile_options_capacity.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_get_required_program_compile_options_capacity.restype = (
+        st_arch_size_t
+    )
+
+    st_ClContextBase_get_program_compile_options = (
+        sixtracklib.st_ClContextBase_get_program_compile_options
+    )
+    st_ClContextBase_get_program_compile_options.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_get_program_compile_options.restype = ct.c_char_p
+
+    st_ClContextBase_get_required_program_compile_report_capacity = (
+        sixtracklib.st_ClContextBase_get_required_program_compile_report_capacity
+    )
+    st_ClContextBase_get_required_program_compile_report_capacity.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_get_required_program_compile_report_capacity.restype = (
+        st_arch_size_t
+    )
+
+    st_ClContextBase_get_program_compile_report = (
+        sixtracklib.st_ClContextBase_get_program_compile_report
+    )
+    st_ClContextBase_get_program_compile_report.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_get_program_compile_report.restype = ct.c_char_p
+
+    st_ClContextBase_is_program_compiled = (
+        sixtracklib.st_ClContextBase_is_program_compiled
+    )
+    st_ClContextBase_is_program_compiled.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_is_program_compiled.restype = ct.c_bool
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContextBase_get_num_available_kernels = (
+        sixtracklib.st_ClContextBase_get_num_available_kernels
+    )
+    st_ClContextBase_get_num_available_kernels.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_get_num_available_kernels.restype = st_arch_size_t
+
+    st_ClContextBase_enable_kernel = sixtracklib.st_ClContextBase_enable_kernel
+    st_ClContextBase_enable_kernel.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_enable_kernel.restype = st_arch_kernel_id_t
+
+    st_ClContextBase_find_kernel_id_by_name = (
+        sixtracklib.st_ClContextBase_find_kernel_id_by_name
+    )
+    st_ClContextBase_find_kernel_id_by_name.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_find_kernel_id_by_name.restype = st_arch_kernel_id_t
+
+    st_ClContextBase_get_kernel_function_name = (
+        sixtracklib.st_ClContextBase_get_kernel_function_name
+    )
+    st_ClContextBase_get_kernel_function_name.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_kernel_function_name.restype = ct.c_char_p
+
+    st_ClContextBase_get_kernel_local_mem_size = (
+        sixtracklib.st_ClContextBase_get_kernel_local_mem_size
+    )
+    st_ClContextBase_get_kernel_local_mem_size.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_kernel_local_mem_size.restype = st_arch_size_t
+
+    st_ClContextBase_get_kernel_num_args = (
+        sixtracklib.st_ClContextBase_get_kernel_num_args
+    )
+    st_ClContextBase_get_kernel_num_args.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_kernel_num_args.restype = st_arch_size_t
+
+    st_ClContextBase_get_kernel_work_group_size = (
+        sixtracklib.st_ClContextBase_get_kernel_work_group_size
+    )
+    st_ClContextBase_get_kernel_work_group_size.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+
+    st_ClContextBase_get_kernel_max_work_group_size = (
+        sixtracklib.st_ClContextBase_get_kernel_max_work_group_size
+    )
+    st_ClContextBase_get_kernel_max_work_group_size.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_kernel_max_work_group_size.restype = st_arch_size_t
+
+    st_ClContextBase_set_kernel_work_group_size = (
+        sixtracklib.st_ClContextBase_set_kernel_work_group_size
+    )
+    st_ClContextBase_set_kernel_work_group_size.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_set_kernel_work_group_size.restype = ct.c_bool
+
+    st_ClContextBase_get_kernel_preferred_work_group_size_multiple = (
+        sixtracklib.st_ClContextBase_get_kernel_preferred_work_group_size_multiple
+    )
+    st_ClContextBase_get_kernel_preferred_work_group_size_multiple.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_kernel_preferred_work_group_size_multiple.restype = (
+        st_arch_size_t
+    )
+
+    st_ClContextBase_get_ptr_kernel_argument = (
+        sixtracklib.st_ClContextBase_get_ptr_kernel_argument
+    )
+    st_ClContextBase_get_ptr_kernel_argument.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_get_ptr_kernel_argument.restype = st_ClArgument_p
+
+    st_ClContextBase_get_kernel_argument_type = (
+        sixtracklib.st_ClContextBase_get_kernel_argument_type
+    )
+    st_ClContextBase_get_kernel_argument_type.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_get_kernel_argument_type.restype = st_kernel_arg_type_t
+
+    st_ClContextBase_reset_single_kernel_argument = (
+        sixtracklib.st_ClContextBase_reset_single_kernel_argument
+    )
+    st_ClContextBase_reset_single_kernel_argument.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_reset_single_kernel_argument.restype = None
+
+    st_ClContextBase_reset_kernel_arguments = (
+        sixtracklib.st_ClContextBase_reset_kernel_arguments
+    )
+    st_ClContextBase_reset_kernel_arguments.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_reset_kernel_arguments.restype = None
+
+    st_ClContextBase_assign_kernel_argument = (
+        sixtracklib.st_ClContextBase_assign_kernel_argument
+    )
+    st_ClContextBase_assign_kernel_argument.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+        st_ClArgument_p,
+    ]
+    st_ClContextBase_assign_kernel_argument.restype = None
+
+    st_ClContextBase_assign_kernel_argument_value = (
+        sixtracklib.st_ClContextBase_assign_kernel_argument_value
+    )
+    st_ClContextBase_assign_kernel_argument_value.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+        ct.c_void_p,
+        st_arch_size_t,
+    ]
+
+    st_ClContextBase_assign_kernel_argument_raw_ptr = (
+        sixtracklib.st_ClContextBase_assign_kernel_argument_raw_ptr
+    )
+    st_ClContextBase_assign_kernel_argument_raw_ptr.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+        st_arch_size_t,
+        ct.c_void_p,
+    ]
+    st_ClContextBase_assign_kernel_argument_raw_ptr.restype = None
+
+    st_ClContextBase_calculate_kernel_num_work_items = (
+        sixtracklib.st_ClContextBase_calculate_kernel_num_work_items
+    )
+    st_ClContextBase_calculate_kernel_num_work_items.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_calculate_kernel_num_work_items.restype = st_arch_size_t
+
+    st_ClContextBase_run_kernel = sixtracklib.st_ClContextBase_run_kernel
+    st_ClContextBase_run_kernel.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_run_kernel.restype = ct.c_bool
+
+    st_ClContextBase_run_kernel_wgsize = (
+        sixtracklib.st_ClContextBase_run_kernel_wgsize
+    )
+    st_ClContextBase_run_kernel_wgsize.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+        st_arch_size_t,
+        st_arch_size_t,
+    ]
+    st_ClContextBase_run_kernel_wgsize.restype = ct.c_bool
+
+    st_ClContextBase_get_kernel_exec_counter = (
+        sixtracklib.st_ClContextBase_get_kernel_exec_counter
+    )
+    st_ClContextBase_get_kernel_exec_counter.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_kernel_exec_counter.restype = st_arch_size_t
+
+    st_ClContextBase_get_last_exec_time = (
+        sixtracklib.st_ClContextBase_get_last_exec_time
+    )
+    st_ClContextBase_get_last_exec_time.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_last_exec_time.restype = ct.c_double
+
+    st_ClContextBase_get_min_exec_time = (
+        sixtracklib.st_ClContextBase_get_min_exec_time
+    )
+    st_ClContextBase_get_min_exec_time.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_min_exec_time.restype = ct.c_double
+
+    st_ClContextBase_get_max_exec_time = (
+        sixtracklib.st_ClContextBase_get_max_exec_time
+    )
+    st_ClContextBase_get_max_exec_time.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_max_exec_time.restype = ct.c_double
+
+    st_ClContextBase_get_avg_exec_time = (
+        sixtracklib.st_ClContextBase_get_avg_exec_time
+    )
+    st_ClContextBase_get_avg_exec_time.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_avg_exec_time.restype = ct.c_double
+
+    st_ClContextBase_get_last_exec_work_group_size = (
+        sixtracklib.st_ClContextBase_get_last_exec_work_group_size
+    )
+    st_ClContextBase_get_last_exec_work_group_size.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_last_exec_work_group_size.restype = st_arch_size_t
+
+    st_ClContextBase_get_last_exec_num_work_items = (
+        sixtracklib.st_ClContextBase_get_last_exec_num_work_items
+    )
+    st_ClContextBase_get_last_exec_num_work_items.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_last_exec_num_work_items.restype = st_arch_size_t
+
+    st_ClContextBase_reset_kernel_exec_timing = (
+        sixtracklib.st_ClContextBase_reset_kernel_exec_timing
+    )
+    st_ClContextBase_reset_kernel_exec_timing.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_reset_kernel_exec_timing.restype = None
+
+    st_ClContextBase_get_program_id_by_kernel_id = (
+        sixtracklib.st_ClContextBase_get_program_id_by_kernel_id
+    )
+    st_ClContextBase_get_program_id_by_kernel_id.argtypes = [
+        st_ClContextBase_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContextBase_get_program_id_by_kernel_id.restype = st_arch_program_id_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContextBase_has_remapping_program = (
+        sixtracklib.st_ClContextBase_has_remapping_program
+    )
+    st_ClContextBase_has_remapping_program.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_has_remapping_program.restype = ct.c_bool
+
+    st_ClContextBase_remapping_program_id = (
+        sixtracklib.st_ClContextBase_remapping_program_id
+    )
+    st_ClContextBase_remapping_program_id.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_remapping_program_id.restype = st_arch_program_id_t
+
+    st_ClContextBase_has_remapping_kernel = (
+        sixtracklib.st_ClContextBase_has_remapping_kernel
+    )
+    st_ClContextBase_has_remapping_kernel.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_has_remapping_kernel.restype = ct.c_bool
+
+    st_ClContextBase_remapping_kernel_id = (
+        sixtracklib.st_ClContextBase_remapping_kernel_id
+    )
+    st_ClContextBase_remapping_kernel_id.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_remapping_kernel_id.restype = st_arch_kernel_id_t
+
+    st_ClContextBase_set_remapping_kernel_id = (
+        sixtracklib.st_ClContextBase_set_remapping_kernel_id
+    )
+    st_ClContextBase_set_remapping_kernel_id.argtypes = [
+        st_ClContextBase_p,
+        st_arch_program_id_t,
+    ]
+    st_ClContextBase_set_remapping_kernel_id.restype = st_arch_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContextBase_is_debug_mode_enabled = (
+        sixtracklib.st_ClContextBase_is_debug_mode_enabled
+    )
+    st_ClContextBase_is_debug_mode_enabled.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_is_debug_mode_enabled.restype = ct.c_bool
+
+    st_ClContextBase_enable_debug_mode = (
+        sixtracklib.st_ClContextBase_enable_debug_mode
+    )
+    st_ClContextBase_enable_debug_mode.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_enable_debug_mode.restype = None
+
+    st_ClContextBase_disable_debug_mode = (
+        sixtracklib.st_ClContextBase_disable_debug_mode
+    )
+    st_ClContextBase_disable_debug_mode.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_disable_debug_mode.restype = None
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+    st_ClContextBase_num_feature_flags = (
+        sixtracklib.st_ClContextBase_num_feature_flags
+    )
+    st_ClContextBase_num_feature_flags.argtypes = [st_ClContextBase_p]
+    st_ClContextBase_num_feature_flags.restype = st_arch_size_t
+
+    st_ClContextBase_has_feature_flag = (
+        sixtracklib.st_ClContextBase_has_feature_flag
+    )
+    st_ClContextBase_has_feature_flag.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_has_feature_flag.restype = ct.c_bool
+
+    st_ClContextBase_feature_flag = sixtracklib.st_ClContextBase_feature_flag
+    st_ClContextBase_feature_flag.argtypes = [st_ClContextBase_p, ct.c_char_p]
+    st_ClContextBase_feature_flag.restype = ct.c_char_p
+
+    st_ClContextBase_set_feature_flag = (
+        sixtracklib.st_ClContextBase_set_feature_flag
+    )
+    st_ClContextBase_set_feature_flag.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_set_feature_flag.restype = None
+
+    st_ClContextBase_feature_flag_repr_required_capacity = (
+        sixtracklib.st_ClContextBase_feature_flag_repr_required_capacity
+    )
+    st_ClContextBase_feature_flag_repr_required_capacity.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_feature_flag_repr_required_capacity.restype = (
+        st_arch_size_t
+    )
+
+    st_ClContextBase_feature_flag_repr_as_cstr = (
+        sixtracklib.st_ClContextBase_feature_flag_repr_as_cstr
+    )
+    st_ClContextBase_feature_flag_repr_as_cstr.argtypes = [
+        st_ClContextBase_p,
+        ct.c_char_p,
+        st_arch_size_t,
+        ct.c_char_p,
+        ct.c_char_p,
+        ct.c_char_p,
+    ]
+    st_ClContextBase_feature_flag_repr_as_cstr.restype = st_arch_status_t
+
+    # --------------------------------------------------------------------------
+    st_context_num_turns_t = ct.c_int64
+    st_ClContext_p = ct.c_void_p
+    st_NullClContext = ct.cast(0, st_ClContext_p)
+
+    st_ClContext_new = sixtracklib.st_ClContext_new
+    st_ClContext_new.argtypes = [ct.c_char_p]
+    st_ClContext_new.restype = st_ClContext_p
+
+    st_ClContext_clear = sixtracklib.st_ClContext_clear
+    st_ClContext_clear.argtypes = [st_ClContext_p]
+    st_ClContext_clear.restype = None
+
+    st_ClContext_delete = sixtracklib.st_ClContext_delete
+    st_ClContext_delete.argtypes = [st_ClContext_p]
+    st_ClContext_delete.restype = None
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_assign_particles_arg = (
+        sixtracklib.st_ClContext_assign_particles_arg
+    )
+    st_ClContext_assign_particles_arg.argtypes = [
+        st_ClContext_p,
+        st_ClArgument_p,
+    ]
+    st_ClContext_assign_particles_arg.restype = st_arch_status_t
+
+    st_ClContext_assign_particle_set_arg = (
+        sixtracklib.st_ClContext_assign_particle_set_arg
+    )
+    st_ClContext_assign_particle_set_arg.argtypes = [
+        st_ClContext_p,
+        st_buffer_size_t,
+        st_buffer_size_t,
+    ]
+    st_ClContext_assign_particle_set_arg.restype = st_arch_status_t
+
+    st_ClContext_assign_beam_elements_arg = (
+        sixtracklib.st_ClContext_assign_beam_elements_arg
+    )
+    st_ClContext_assign_beam_elements_arg.argtypes = [
+        st_ClContext_p,
+        st_ClArgument_p,
+    ]
+    st_ClContext_assign_beam_elements_arg.restype = st_arch_status_t
+
+    st_ClContext_assign_output_buffer_arg = (
+        sixtracklib.st_ClContext_assign_output_buffer_arg
+    )
+    st_ClContext_assign_output_buffer_arg.argtypes = [
+        st_ClContext_p,
+        st_ClArgument_p,
+    ]
+    st_ClContext_assign_output_buffer_arg.restype = st_arch_status_t
+
+    # st_arch_status_t st_ClContext_assign_elem_by_elem_config_arg(
+    # st_ClContext* SIXTRL_RESTRICT ctx, cl_mem elem_by_elem_config_arg  );
+
+    st_ClContext_assign_slot_size_arg = (
+        sixtracklib.st_ClContext_assign_slot_size_arg
+    )
+    st_ClContext_assign_slot_size_arg.argtypes = [
+        st_ClContext_p,
+        st_buffer_size_t,
+    ]
+    st_ClContext_assign_slot_size_arg.restype = st_arch_status_t
+
+    # st_arch_status_t st_ClContext_assign_status_flags_arg(
+    # st_ClContext* SIXTRL_RESTRICT ctx, cl_mem status_flags_arg );
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_has_track_until_kernel = (
+        sixtracklib.st_ClContext_has_track_until_kernel
+    )
+    st_ClContext_has_track_until_kernel.argtypes = [st_ClContext_p]
+    st_ClContext_has_track_until_kernel.restype = ct.c_bool
+
+    st_ClContext_track_until_kernel_id = (
+        sixtracklib.st_ClContext_track_until_kernel_id
+    )
+    st_ClContext_track_until_kernel_id.argtypes = [st_ClContext_p]
+    st_ClContext_track_until_kernel_id.restype = st_arch_kernel_id_t
+
+    st_ClContext_set_track_until_kernel_id = (
+        sixtracklib.st_ClContext_set_track_until_kernel_id
+    )
+    st_ClContext_set_track_until_kernel_id.argtypes = [
+        st_ClContext_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContext_set_track_until_kernel_id.restype = st_arch_status_t
+
+    st_ClContext_track_until = sixtracklib.st_ClContext_track_until
+    st_ClContext_track_until.argtypes = [
+        st_ClContext_p,
+        st_context_num_turns_t,
+    ]
+    st_ClContext_track_until.restype = st_track_status_t
+
+    st_ClContext_track_until_for_particle_set = (
+        sixtracklib.st_ClContext_track_until_for_particle_set
+    )
+    st_ClContext_track_until_for_particle_set.argtypes = [
+        st_ClContext_p,
+        st_context_num_turns_t,
+        st_buffer_size_t,
+        st_buffer_size_t,
+        ct.c_bool,
+    ]
+    st_ClContext_track_until_for_particle_set.restype = st_track_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_has_track_line_kernel = (
+        sixtracklib.st_ClContext_has_track_line_kernel
+    )
+    st_ClContext_has_track_line_kernel.argtypes = [st_ClContext_p]
+    st_ClContext_has_track_line_kernel.restype = ct.c_bool
+
+    st_ClContext_track_line_kernel_id = (
+        sixtracklib.st_ClContext_track_line_kernel_id
+    )
+    st_ClContext_track_line_kernel_id.argtypes = [st_ClContext_p]
+    st_ClContext_track_line_kernel_id.restype = st_arch_kernel_id_t
+
+    st_ClContext_set_track_line_kernel_id = (
+        sixtracklib.st_ClContext_set_track_line_kernel_id
+    )
+    st_ClContext_set_track_line_kernel_id.argtypes = [
+        st_ClContext_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContext_set_track_line_kernel_id.restype = st_arch_status_t
+
+    st_ClContext_track_line = sixtracklib.st_ClContext_track_line
+    st_ClContext_track_line.argtypes = [
+        st_ClContext_p,
+        st_buffer_size_t,
+        st_buffer_size_t,
+        ct.c_bool,
+    ]
+    st_ClContext_track_line.restype = st_track_status_t
+
+    st_ClContext_track_line_for_particle_set = (
+        sixtracklib.st_ClContext_track_line_for_particle_set
+    )
+    st_ClContext_track_line_for_particle_set.argtypes = [
+        st_ClContext_p,
+        st_buffer_size_t,
+        st_buffer_size_t,
+        ct.c_bool,
+        st_buffer_size_t,
+        st_buffer_size_t,
+        ct.c_bool,
+    ]
+    st_ClContext_track_line_for_particle_set.restype = st_track_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_has_track_elem_by_elem_kernel = (
+        sixtracklib.st_ClContext_has_track_elem_by_elem_kernel
+    )
+    st_ClContext_has_track_elem_by_elem_kernel.argtypes = [st_ClContext_p]
+    st_ClContext_has_track_elem_by_elem_kernel.restype = ct.c_bool
+
+    st_ClContext_track_elem_by_elem_kernel_id = (
+        sixtracklib.st_ClContext_track_elem_by_elem_kernel_id
+    )
+    st_ClContext_track_elem_by_elem_kernel_id.argtypes = [st_ClContext_p]
+    st_ClContext_track_elem_by_elem_kernel_id.restype = st_arch_kernel_id_t
+
+    st_ClContext_set_track_elem_by_elem_kernel_id = (
+        sixtracklib.st_ClContext_set_track_elem_by_elem_kernel_id
+    )
+    st_ClContext_set_track_elem_by_elem_kernel_id.argtypes = [
+        st_ClContext_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContext_set_track_elem_by_elem_kernel_id.restype = st_arch_status_t
+
+    st_ClContext_track_elem_by_elem = (
+        sixtracklib.st_ClContext_track_elem_by_elem
+    )
+    st_ClContext_track_elem_by_elem.argtypes = [
+        st_ClContext_p,
+        st_buffer_size_t,
+    ]
+    st_ClContext_track_elem_by_elem.restype = st_track_status_t
+
+    st_ClContext_track_elem_by_elem_for_particle_set = (
+        sixtracklib.st_ClContext_track_elem_by_elem_for_particle_set
+    )
+    st_ClContext_track_elem_by_elem_for_particle_set.argtypes = [
+        st_ClContext_p,
+        st_context_num_turns_t,
+        st_buffer_size_t,
+        st_buffer_size_t,
+        ct.c_bool,
+    ]
+    st_ClContext_track_elem_by_elem_for_particle_set.restype = st_track_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_has_assign_beam_monitor_output_kernel = (
+        sixtracklib.st_ClContext_has_assign_beam_monitor_output_kernel
+    )
+    st_ClContext_has_assign_beam_monitor_output_kernel.argtypes = [
+        st_ClContext_p
+    ]
+    st_ClContext_has_assign_beam_monitor_output_kernel.restype = ct.c_bool
+
+    st_ClContext_assign_beam_monitor_output_kernel_id = (
+        sixtracklib.st_ClContext_assign_beam_monitor_output_kernel_id
+    )
+    st_ClContext_assign_beam_monitor_output_kernel_id.argtypes = [
+        st_ClContext_p
+    ]
+    st_ClContext_assign_beam_monitor_output_kernel_id.restype = (
+        st_arch_kernel_id_t
+    )
+
+    st_ClContext_set_assign_beam_monitor_output_kernel_id = (
+        sixtracklib.st_ClContext_set_assign_beam_monitor_output_kernel_id
+    )
+    st_ClContext_set_assign_beam_monitor_output_kernel_id.argtypes = [
+        st_ClContext_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContext_set_assign_beam_monitor_output_kernel_id.restype = (
+        st_arch_status_t
+    )
+
+    st_ClContext_assign_beam_monitor_output = (
+        sixtracklib.st_ClContext_assign_beam_monitor_output
+    )
+    st_ClContext_assign_beam_monitor_output.argtypes = [
+        st_ClContext_p,
+        st_particle_index_t,
+        st_buffer_size_t,
+    ]
+    st_ClContext_assign_beam_monitor_output.restype = st_arch_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_has_assign_elem_by_elem_output_kernel = (
+        sixtracklib.st_ClContext_has_assign_elem_by_elem_output_kernel
+    )
+    st_ClContext_has_assign_elem_by_elem_output_kernel.argtypes = [
+        st_ClContext_p
+    ]
+    st_ClContext_has_assign_elem_by_elem_output_kernel.restype = ct.c_bool
+
+    st_ClContext_assign_elem_by_elem_output_kernel_id = (
+        sixtracklib.st_ClContext_assign_elem_by_elem_output_kernel_id
+    )
+    st_ClContext_assign_elem_by_elem_output_kernel_id.argtypes = [
+        st_ClContext_p
+    ]
+    st_ClContext_assign_elem_by_elem_output_kernel_id.restype = ct.c_bool
+
+    st_ClContext_set_assign_elem_by_elem_output_kernel_id = (
+        sixtracklib.st_ClContext_set_assign_elem_by_elem_output_kernel_id
+    )
+    st_ClContext_set_assign_elem_by_elem_output_kernel_id.argtypes = [
+        st_ClContext_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContext_set_assign_elem_by_elem_output_kernel_id.restype = (
+        st_arch_status_t
+    )
+
+    st_ClContext_assign_elem_by_elem_output = (
+        sixtracklib.st_ClContext_assign_elem_by_elem_output
+    )
+    st_ClContext_assign_elem_by_elem_output.argtypes = [
+        st_ClContext_p,
+        st_buffer_size_t,
+    ]
+    st_ClContext_assign_elem_by_elem_output.restype = st_arch_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_has_clear_beam_monitor_output_kernel = (
+        sixtracklib.st_ClContext_has_clear_beam_monitor_output_kernel
+    )
+    st_ClContext_has_clear_beam_monitor_output_kernel.argtypes = [
+        st_ClContext_p
+    ]
+    st_ClContext_has_clear_beam_monitor_output_kernel.restype = ct.c_bool
+
+    st_ClContext_clear_beam_monitor_output_kernel_id = (
+        sixtracklib.st_ClContext_clear_beam_monitor_output_kernel_id
+    )
+    st_ClContext_clear_beam_monitor_output_kernel_id.argtypes = [st_ClContext_p]
+    st_ClContext_clear_beam_monitor_output_kernel_id.restype = (
+        st_arch_kernel_id_t
+    )
+
+    st_ClContext_set_clear_beam_monitor_output_kernel_id = (
+        sixtracklib.st_ClContext_set_clear_beam_monitor_output_kernel_id
+    )
+    st_ClContext_set_clear_beam_monitor_output_kernel_id.argtypes = [
+        st_ClContext_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContext_set_clear_beam_monitor_output_kernel_id.restype = (
+        st_arch_status_t
+    )
+
+    st_ClContext_clear_beam_monitor_output = (
+        sixtracklib.st_ClContext_clear_beam_monitor_output
+    )
+    st_ClContext_clear_beam_monitor_output.argtypes = [st_ClContext_p]
+    st_ClContext_clear_beam_monitor_output.restype = st_arch_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_has_assign_addresses_kernel = (
+        sixtracklib.st_ClContext_has_assign_addresses_kernel
+    )
+    st_ClContext_has_assign_addresses_kernel.argtypes = [st_ClContext_p]
+    st_ClContext_has_assign_addresses_kernel.restype = ct.c_bool
+
+    st_ClContext_assign_addresses_kernel_id = (
+        sixtracklib.st_ClContext_assign_addresses_kernel_id
+    )
+    st_ClContext_assign_addresses_kernel_id.argtypes = [st_ClContext_p]
+    st_ClContext_assign_addresses_kernel_id.restype = st_arch_kernel_id_t
+
+    st_ClContext_set_assign_addresses_kernel_id = (
+        sixtracklib.st_ClContext_set_assign_addresses_kernel_id
+    )
+    st_ClContext_set_assign_addresses_kernel_id.argtypes = [
+        st_ClContext_p,
+        st_arch_kernel_id_t,
+    ]
+    st_ClContext_set_assign_addresses_kernel_id.restype = st_arch_status_t
+
+    st_ClContext_assign_addresses = sixtracklib.st_ClContext_assign_addresses
+    st_ClContext_assign_addresses.argtypes = [
+        st_ClContext_p,
+        st_Buffer_p,
+        st_Buffer_p,
+        st_Buffer_p,
+    ]
+    st_ClContext_assign_addresses.restype = st_arch_status_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_selected_particle_set = (
+        sixtracklib.st_ClContext_selected_particle_set
+    )
+    st_ClContext_selected_particle_set.argtypes = [st_ClContext_p]
+    st_ClContext_selected_particle_set.restype = st_buffer_size_t
+
+    st_ClContext_num_particles_in_selected_set = (
+        sixtracklib.st_ClContext_num_particles_in_selected_set
+    )
+    st_ClContext_num_particles_in_selected_set.argtypes = [st_ClContext_p]
+    st_ClContext_num_particles_in_selected_set.restype = st_buffer_size_t
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_uses_optimized_tracking = (
+        sixtracklib.st_ClContext_uses_optimized_tracking
+    )
+    st_ClContext_uses_optimized_tracking.argtypes = [st_ClContext_p]
+    st_ClContext_uses_optimized_tracking.restype = ct.c_bool
+
+    st_ClContext_enable_optimized_tracking = (
+        sixtracklib.st_ClContext_enable_optimized_tracking
+    )
+    st_ClContext_enable_optimized_tracking.argtypes = [st_ClContext_p]
+    st_ClContext_enable_optimized_tracking.restype = None
+
+    st_ClContext_disable_optimized_tracking = (
+        sixtracklib.st_ClContext_disable_optimized_tracking
+    )
+    st_ClContext_disable_optimized_tracking.argtypes = [st_ClContext_p]
+    st_ClContext_disable_optimized_tracking.restype = None
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_ClContext_is_beam_beam_tracking_enabled = (
+        sixtracklib.st_ClContext_is_beam_beam_tracking_enabled
+    )
+    st_ClContext_is_beam_beam_tracking_enabled.argtypes = [st_ClContext_p]
+    st_ClContext_is_beam_beam_tracking_enabled.restype = ct.c_bool
+
+    st_ClContext_disable_beam_beam_tracking = (
+        sixtracklib.st_ClContext_disable_beam_beam_tracking
+    )
+    st_ClContext_disable_beam_beam_tracking.argtypes = [st_ClContext_p]
+    st_ClContext_disable_beam_beam_tracking.restype = None
+
+    st_ClContext_enable_beam_beam_tracking = (
+        sixtracklib.st_ClContext_enable_beam_beam_tracking
+    )
+    st_ClContext_enable_beam_beam_tracking.argtypes = [st_ClContext_p]
+    st_ClContext_enable_beam_beam_tracking.restype = None
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    st_TrackJobCl_p = ct.c_void_p
+    st_NullTrackJobCl = ct.cast(0, st_TrackJobCl_p)
+    st_TrackJobCl_get_context = sixtracklib.st_TrackJobCl_get_context
+    st_TrackJobCl_get_context.argtypes = [st_TrackJobCl_p]
+    st_TrackJobCl_get_context.restype = st_ClContext_p
+
+    st_TrackJobCl_const_argument_by_buffer_id = (
+        sixtracklib.st_TrackJobCl_const_argument_by_buffer_id
+    )
+    st_TrackJobCl_const_argument_by_buffer_id.argtypes = [
+        st_TrackJobCl_p,
+        st_buffer_size_t,
+    ]
+    st_TrackJobCl_const_argument_by_buffer_id.restype = st_ClArgument_p
+
+    st_TrackJobCl_argument_by_buffer_id = (
+        sixtracklib.st_TrackJobCl_argument_by_buffer_id
+    )
+    st_TrackJobCl_argument_by_buffer_id.argtypes = [
+        st_TrackJobCl_p,
+        st_buffer_size_t,
+    ]
+    st_TrackJobCl_argument_by_buffer_id.restype = st_ClArgument_p
+
+    st_TrackJobCl_const_stored_buffer_argument = (
+        sixtracklib.st_TrackJobCl_const_stored_buffer_argument
+    )
+    st_TrackJobCl_const_stored_buffer_argument.argtypes = [
+        st_TrackJobCl_p,
+        st_buffer_size_t,
+    ]
+    st_TrackJobCl_const_stored_buffer_argument.restype = st_ClArgument_p
+
+    st_TrackJobCl_stored_buffer_argument = (
+        sixtracklib.st_TrackJobCl_stored_buffer_argument
+    )
+    st_TrackJobCl_stored_buffer_argument.argtypes = [
+        st_TrackJobCl_p,
+        st_buffer_size_t,
+    ]
+    st_TrackJobCl_stored_buffer_argument.restype = st_ClArgument_p
+
+    st_TrackJobCl_p = ct.c_void_p
+    st_NullTrackJobCl = ct.cast( 0, st_TrackJobCl_p )
+
+    st_TrackJobCl_get_opencl_context_addr = \
+        sixtracklib.st_TrackJobCl_get_opencl_context_addr
+    st_TrackJobCl_get_opencl_context_addr.argtypes = [st_TrackJobCl_p]
+    st_TrackJobCl_get_opencl_context_addr.restype  = ct.c_uint64
+
+    st_TrackJobCl_get_opencl_queue_addr = \
+        sixtracklib.st_TrackJobCl_get_opencl_queue_addr
+    st_TrackJobCl_get_opencl_queue_addr.argtypes = [st_TrackJobCl_p]
+    st_TrackJobCl_get_opencl_queue_addr.restype  = ct.c_uint64
+
+
 
 # ------------------------------------------------------------------------------
 # Stand-alone tracking functions (CPU only)
 
-st_Track_all_particles_until_turn = \
+st_Track_all_particles_until_turn = (
     sixtracklib.st_Track_all_particles_until_turn
+)
 st_Track_all_particles_until_turn.restype = st_track_status_t
 st_Track_all_particles_until_turn.argtypes = [
-    st_Particles_p, st_Buffer_p, st_particle_index_t]
+    st_Particles_p,
+    st_Buffer_p,
+    st_particle_index_t,
+]
 
-st_Track_all_particles_element_by_element_until_turn = \
+st_Track_all_particles_element_by_element_until_turn = (
     sixtracklib.st_Track_all_particles_element_by_element_until_turn
+)
 st_Track_all_particles_element_by_element_until_turn.restype = st_track_status_t
 st_Track_all_particles_element_by_element_until_turn.argtypes = [
-    st_Particles_p, st_ElemByElemConfig_p, st_Buffer_p, ct.c_int64]
+    st_Particles_p,
+    st_ElemByElemConfig_p,
+    st_Buffer_p,
+    ct.c_int64,
+]
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Q-Gaussian methods:
+
+st_Math_q_gauss_min_support = sixtracklib.st_Math_q_gauss_min_support_ext
+st_Math_q_gauss_min_support.argtypes = [ct.c_double, ct.c_double]
+st_Math_q_gauss_min_support.restype = ct.c_double
+
+st_Math_q_gauss_max_support = sixtracklib.st_Math_q_gauss_max_support_ext
+st_Math_q_gauss_max_support.argtypes = [ct.c_double, ct.c_double]
+st_Math_q_gauss_max_support.restype = ct.c_double
+
+st_Math_q_gauss_cq = sixtracklib.st_Math_q_gauss_cq_ext
+st_Math_q_gauss_cq.argtypes = [ct.c_double]
+st_Math_q_gauss_cq.restype = ct.c_double
+
+st_Math_q_gauss_sqrt_beta_from_gauss_sigma = (
+    sixtracklib.st_Math_q_gauss_sqrt_beta_from_gauss_sigma_ext
+)
+st_Math_q_gauss_sqrt_beta_from_gauss_sigma.argtypes = [ct.c_double]
+st_Math_q_gauss_sqrt_beta_from_gauss_sigma.restype = ct.c_double
+
+st_Math_q_gauss_exp_q = sixtracklib.st_Math_q_gauss_exp_q_ext
+st_Math_q_gauss_exp_q.argtypes = [ct.c_double, ct.c_double]
+st_Math_q_gauss_exp_q.restype = ct.c_double
+
+st_Math_q_gauss = sixtracklib.st_Math_q_gauss_ext
+st_Math_q_gauss.restype = ct.c_double
+st_Math_q_gauss.argtypes = [ct.c_double, ct.c_double, ct.c_double, ct.c_double]
+
+st_Math_q_gauss_shifted = sixtracklib.st_Math_q_gauss_shifted_ext
+st_Math_q_gauss_shifted.restype = ct.c_double
+st_Math_q_gauss_shifted.argtypes = [
+    ct.c_double,
+    ct.c_double,
+    ct.c_double,
+    ct.c_double,
+    ct.c_double,
+]
+
+
+def Math_q_gauss_cq(q):
+    assert q < float(3)
+    return st_Math_q_gauss_cq(ct.c_double(q))
+
+def Math_sqrt_beta_from_gauss_sigma(sigma):
+    assert sigma > 0
+    return st_Math_q_gauss_sqrt_beta_from_gauss_sigma(ct.c_double(sigma))
+
+def Math_q_gauss(x, q, sqrt_beta, mu=None):
+    assert q < float(3)
+    assert sqrt_beta > float(0)
+    q_arg = ct.c_double(q)
+    cq = st_Math_q_gauss_cq(q_arg)
+    if mu is None:
+        return st_Math_q_gauss(
+            ct.c_double(x), q_arg, ct.c_double(sqrt_beta), ct.c_double(cq)
+        )
+    else:
+        return st_Math_q_gauss_shifted(
+            ct.c_double(x),
+            q_arg,
+            ct.c_double(sqrt_beta),
+            ct.c_double(cq),
+            ct.c_double(mu),
+        )
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# TriCub related methods:
+
+st_TriCubData_p = ct.c_void_p
+st_NullTriCubData = ct.cast(0, st_TriCubData_p)
+
+st_TriCubData_type_id = sixtracklib.st_TriCubData_type_id_ext
+st_TriCubData_type_id.argtypes = [st_TriCubData_p]
+st_TriCubData_type_id.restype = st_object_type_id_t
+
+st_TriCubData_ptr_offset = sixtracklib.st_TriCubData_ptr_offset_ext
+st_TriCubData_ptr_offset.argtypes = [st_TriCubData_p]
+st_TriCubData_ptr_offset.restype = st_arch_size_t
+
+st_TriCub_p = ct.c_void_p
+st_NullTriCub = ct.cast(0, st_TriCubData_p)
+
+st_TriCub_type_id = sixtracklib.st_TriCub_type_id_ext
+st_TriCub_type_id.argtypes = [st_TriCub_p]
+st_TriCub_type_id.restype = st_object_type_id_t
+
+st_TriCub_data_addr_offset = sixtracklib.st_TriCub_data_addr_offset_ext
+st_TriCub_data_addr_offset.argtypes = [st_TriCub_p]
+st_TriCub_data_addr_offset.restype = st_arch_size_t
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Drift, multipole, rf multipole, cavity, xyshift, srotation, limit*
+
+st_Cavity_type_id = sixtracklib.st_Cavity_type_id_ext
+st_Cavity_type_id.argtypes = None
+st_Cavity_type_id.restype = st_object_type_id_t
+
+st_DipoleEedge_type_id = sixtracklib.st_DipoleEdge_type_id_ext
+st_DipoleEedge_type_id.argtypes = None
+st_DipoleEedge_type_id.restype = st_object_type_id_t
+
+st_Drift_type_id = sixtracklib.st_Drift_type_id_ext
+st_Drift_type_id.argtypes = None
+st_Drift_type_id.restype = st_object_type_id_t
+
+st_DriftExact_type_id = sixtracklib.st_DriftExact_type_id_ext
+st_DriftExact_type_id.argtypes = None
+st_DriftExact_type_id.restype = st_object_type_id_t
+
+st_LimitRect_type_id = sixtracklib.st_LimitRect_type_id_ext
+st_LimitRect_type_id.argtypes = None
+st_LimitRect_type_id.restype = st_object_type_id_t
+
+st_LimitEllipse_type_id = sixtracklib.st_LimitEllipse_type_id_ext
+st_LimitEllipse_type_id.argtypes = None
+st_LimitEllipse_type_id.restype = st_object_type_id_t
+
+st_LimitRectEllipse_type_id = sixtracklib.st_LimitRectEllipse_type_id_ext
+st_LimitRectEllipse_type_id.argtypes = None
+st_LimitRectEllipse_type_id.restype = st_object_type_id_t
+
+st_Multipole_type_id = sixtracklib.st_Multipole_type_id_ext
+st_Multipole_type_id.argtypes = None
+st_Multipole_type_id.restype = st_object_type_id_t
+
+st_RFMultipole_type_id = sixtracklib.st_RFMultipole_type_id_ext
+st_RFMultipole_type_id.argtypes = None
+st_RFMultipole_type_id.restype = st_object_type_id_t
+
+st_SRotation_type_id = sixtracklib.st_SRotation_type_id_ext
+st_SRotation_type_id.argtypes = None
+st_SRotation_type_id.restype = st_object_type_id_t
+
+st_XYShift_type_id = sixtracklib.st_XYShift_type_id_ext
+st_XYShift_type_id.argtypes = None
+st_XYShift_type_id.restype = st_object_type_id_t
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# SC related methods:
+
+st_BeamBeam4D_p = ct.c_void_p
+st_NullBeamBeam4D = ct.cast(0, st_BeamBeam4D_p)
+
+st_BeamBeam4D_type_id = sixtracklib.st_BeamBeam4D_type_id_ext
+st_BeamBeam4D_type_id.argtypes = None
+st_BeamBeam4D_type_id.restype = st_object_type_id_t
+
+st_BeamBeam4D_data_addr_offset = sixtracklib.st_BeamBeam4D_data_addr_offset_ext
+st_BeamBeam4D_data_addr_offset.argtypes = [
+    st_BeamBeam4D_p,
+]
+st_BeamBeam4D_data_addr_offset.restype = st_buffer_size_t
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+st_BeamBeam6D_p = ct.c_void_p
+st_NullBeamBeam6D = ct.cast(0, st_BeamBeam6D_p)
+
+st_BeamBeam6D_type_id = sixtracklib.st_BeamBeam6D_type_id_ext
+st_BeamBeam6D_type_id.argtypes = None
+st_BeamBeam6D_type_id.restype = st_object_type_id_t
+
+st_BeamBeam6D_data_addr_offset = sixtracklib.st_BeamBeam6D_data_addr_offset_ext
+st_BeamBeam6D_data_addr_offset.argtypes = [
+    st_BeamBeam6D_p,
+]
+st_BeamBeam6D_data_addr_offset.restype = st_buffer_size_t
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+st_SCCoasting_p = ct.c_void_p
+st_NullSCCoasting = ct.cast(0, st_SCCoasting_p)
+
+st_SCCoasting_type_id = sixtracklib.st_SCCoasting_type_id_ext
+st_SCCoasting_type_id.argtypes = None
+st_SCCoasting_type_id.restype = st_object_type_id_t
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+st_SCQGaussProfile_p = ct.c_void_p
+st_NullSCQGaussProfile = ct.cast(0, st_SCQGaussProfile_p)
+
+st_SCQGaussProfile_type_id = sixtracklib.st_SCQGaussProfile_type_id_ext
+st_SCQGaussProfile_type_id.argtypes = None
+st_SCQGaussProfile_type_id.restype = st_object_type_id_t
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+st_LineDensityProfileData_p = ct.c_void_p
+st_NullLineDensityProfileData = ct.cast(0, st_LineDensityProfileData_p)
+
+st_LineDensityProfileData_type_id = (
+    sixtracklib.st_LineDensityProfileData_type_id_ext
+)
+st_LineDensityProfileData_type_id.argtypes = None
+st_LineDensityProfileData_type_id.restype = st_object_type_id_t
+
+st_LineDensityProfileData_values_offset = (
+    sixtracklib.st_LineDensityProfileData_values_offset_ext
+)
+st_LineDensityProfileData_values_offset.argtypes = [st_LineDensityProfileData_p]
+st_LineDensityProfileData_values_offset.restype = st_buffer_size_t
+
+st_LineDensityProfileData_derivatives_offset = (
+    sixtracklib.st_LineDensityProfileData_derivatives_offset_ext
+)
+st_LineDensityProfileData_derivatives_offset.argtypes = [
+    st_LineDensityProfileData_p
+]
+st_LineDensityProfileData_derivatives_offset.restype = st_buffer_size_t
+
+st_LineDensityProfileData_prepare_interpolation = (
+    sixtracklib.st_LineDensityProfileData_prepare_interpolation_ext
+)
+st_LineDensityProfileData_prepare_interpolation.argtypes = [
+    st_LineDensityProfileData_p
+]
+st_LineDensityProfileData_prepare_interpolation.restype = st_arch_status_t
+
+st_LineDensityProfileData_interpolate_value = (
+    sixtracklib.st_LineDensityProfileData_interpolate_value_ext
+)
+st_LineDensityProfileData_interpolate_value.argtypes = [
+    st_LineDensityProfileData_p,
+    ct.c_double,
+]
+st_LineDensityProfileData_interpolate_value.restype = ct.c_double
+
+st_LineDensityProfileData_interpolate_1st_derivative = (
+    sixtracklib.st_LineDensityProfileData_interpolate_1st_derivative_ext
+)
+st_LineDensityProfileData_interpolate_1st_derivative.argtypes = [
+    st_LineDensityProfileData_p,
+    ct.c_double,
+]
+st_LineDensityProfileData_interpolate_1st_derivative.restype = ct.c_double
+
+st_LineDensityProfileData_interpolate_2nd_derivative = (
+    sixtracklib.st_LineDensityProfileData_interpolate_1st_derivative_ext
+)
+st_LineDensityProfileData_interpolate_2nd_derivative.argtypes = [
+    st_LineDensityProfileData_p,
+    ct.c_double,
+]
+st_LineDensityProfileData_interpolate_2nd_derivative.restype = ct.c_double
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+st_SCInterpolatedProfile_p = ct.c_void_p
+st_NullSCInterpolatedProfile = ct.cast(0, st_SCInterpolatedProfile_p)
+
+st_SCInterpolatedProfile_type_id = (
+    sixtracklib.st_SCInterpolatedProfile_type_id_ext
+)
+st_SCInterpolatedProfile_type_id.argtypes = None
+st_SCInterpolatedProfile_type_id.restype = st_object_type_id_t
+
+st_SCInterpolatedProfile_interpol_data_addr_offset = (
+    sixtracklib.st_SCInterpolatedProfile_interpol_data_addr_offset_ext
+)
+st_SCInterpolatedProfile_interpol_data_addr_offset.argtypes = [
+    st_SCInterpolatedProfile_p,
+]
+st_SCInterpolatedProfile_interpol_data_addr_offset.restype = st_object_type_id_t
diff --git a/python/sixtracklib/trackjob.py b/python/sixtracklib/trackjob.py
index 0eef4b2f..bd57047a 100644
--- a/python/sixtracklib/trackjob.py
+++ b/python/sixtracklib/trackjob.py
@@ -4,6 +4,7 @@
 import ctypes as ct
 import cobjects
 from cobjects import CBuffer, CObject
+from .config import SIXTRACKLIB_MODULES
 import warnings
 
 from . import stcommon as st
@@ -11,84 +12,139 @@
 from .particles import ParticlesSet
 from .control import raise_error_if_status_not_success
 from .control import ControllerBase, NodeControllerBase, ArgumentBase
-from .buffer import Buffer
+from .buffer import Buffer, get_cbuffer_from_obj, AssignAddressItem
 from .particles import ParticlesSet
 from .beam_elements import Elements
-
-from .stcommon import st_TrackJobBaseNew_p, st_NullTrackJobBaseNew, \
-    st_ARCH_STATUS_SUCCESS, st_ARCH_STATUS_GENERAL_FAILURE, \
-    st_TRACK_SUCCESS, st_TRACK_STATUS_GENERAL_FAILURE, \
-    st_Particles_p, st_NullParticles, st_ParticlesAddr, st_NullParticlesAddr, \
-    st_track_status_t, st_track_job_collect_flag_t, st_track_job_clear_flag_t,\
-    st_out_buffer_flags_t, st_track_job_size_t, \
-    st_TrackJobNew_delete, st_TrackJobNew_track_until, \
-    st_buffer_size_t, st_NullBuffer, st_Buffer_is_particles_buffer, \
-    st_Particles_buffer_get_num_of_particle_blocks, \
-    st_Particles_buffer_get_particles, st_Particles_get_num_of_particles, \
-    st_OutputBuffer_required_for_tracking, \
-    st_OutputBuffer_requires_output_buffer, \
-    st_OutputBuffer_calculate_output_buffer_params, \
-    st_TrackJobNew_track_elem_by_elem, st_TrackJobNew_track_line, \
-    st_TrackJobNew_collect, st_TrackJobNew_collect_detailed, \
-    st_TrackJobNew_collect_particles, st_TrackJobNew_collect_beam_elements, \
-    st_TrackJobNew_collect_output, st_TrackJobNew_collect_debug_flag, \
-    st_TrackJobNew_collect_particles_addresses, \
-    st_TrackJobNew_enable_collect_particles, \
-    st_TrackJobNew_disable_collect_particles, \
-    st_TrackJobNew_is_collecting_particles, \
-    st_TrackJobNew_enable_collect_beam_elements, \
-    st_TrackJobNew_disable_collect_beam_elements, \
-    st_TrackJobNew_is_collecting_beam_elements, \
-    st_TrackJobNew_enable_collect_output, st_TrackJobNew_disable_collect_output, \
-    st_TrackJobNew_is_collecting_output, st_TrackJobNew_get_collect_flags, \
-    st_TrackJobNew_set_collect_flags, st_TrackJobNew_requires_collecting, \
-    st_TrackJobNew_push, st_TrackJobNew_push_particles, \
-    st_TrackJobNew_push_beam_elements, st_TrackJobNew_push_output, \
-    st_TrackJobNew_can_fetch_particle_addresses, \
-    st_TrackJobNew_has_particle_addresses, \
-    st_TrackJobNew_fetch_particle_addresses, \
-    st_TrackJobNew_clear_particle_addresses, \
-    st_TrackJobNew_clear_all_particle_addresses, \
-    st_TrackJobNew_get_particle_addresses, \
-    st_TrackJobNew_get_ptr_particle_addresses_buffer, \
-    st_TrackJobNew_is_in_debug_mode, \
-    st_TrackJobNew_enable_debug_mode, \
-    st_TrackJobNew_disable_debug_mode, \
-    st_TrackJobNew_clear, st_TrackJobNew_reset, \
-    st_TrackJobNew_reset_particle_set, st_TrackJobNew_reset_with_output, \
-    st_TrackJobNew_reset_detailed, st_TrackJobNew_select_particle_set, \
-    st_TrackJobNew_assign_output_buffer, st_TrackJobNew_get_arch_id, \
-    st_TrackJobNew_has_arch_string, st_TrackJobNew_get_arch_string, \
-    st_TrackJobNew_has_config_str, st_TrackJobNew_get_config_str, \
-    st_TrackJobNew_get_num_particle_sets, \
-    st_TrackJobNew_get_particle_set_indices_begin, \
-    st_TrackJobNew_get_particle_set_indices_end, \
-    st_TrackJobNew_get_particle_set_index, \
-    st_TrackJobNew_get_total_num_of_particles, \
-    st_TrackJobNew_get_min_particle_id, st_TrackJobNew_get_max_particle_id,\
-    st_TrackJobNew_get_min_element_id, st_TrackJobNew_get_max_element_id, \
-    st_TrackJobNew_get_min_initial_turn_id, \
-    st_TrackJobNew_get_max_initial_turn_id, \
-    st_TrackJobNew_get_particles_buffer, st_TrackJobNew_get_beam_elements_buffer, \
-    st_TrackJobNew_has_output_buffer, st_TrackJobNew_owns_output_buffer, \
-    st_TrackJobNew_has_elem_by_elem_output, \
-    st_TrackJobNew_has_beam_monitor_output, \
-    st_TrackJobNew_get_beam_monitor_output_buffer_offset, \
-    st_TrackJobNew_get_elem_by_elem_output_buffer_offset, \
-    st_TrackJobNew_get_num_elem_by_elem_turns, st_TrackJobNew_get_output_buffer,\
-    st_TrackJobNew_has_beam_monitors, st_TrackJobNew_get_num_beam_monitors, \
-    st_TrackJobNew_get_beam_monitor_indices_begin, \
-    st_TrackJobNew_get_beam_monitor_indices_end, \
-    st_TrackJobNew_get_beam_monitor_index, \
-    st_TrackJobNew_has_elem_by_elem_config, \
-    st_TrackJobNew_get_elem_by_elem_config, \
-    st_TrackJobNew_is_elem_by_elem_config_rolling, \
-    st_TrackJobNew_get_default_elem_by_elem_config_rolling_flag, \
-    st_TrackJobNew_set_default_elem_by_elem_config_rolling_flag, \
-    st_TrackJobNew_get_elem_by_elem_config_order, \
-    st_TrackJobNew_get_default_elem_by_elem_config_order, \
-    st_TrackJobNew_set_default_elem_by_elem_config_order, \
-    st_TrackJobNew_uses_controller, st_TrackJobNew_uses_arguments
+from .opencl import ClController
+
+from .stcommon import (
+    string_to_encoded_ctypes_str,
+    ctypes_str_to_decoded_string,
+    st_TrackJobBaseNew_p,
+    st_NullTrackJobBaseNew,
+    st_ARCH_STATUS_SUCCESS,
+    st_ARCH_STATUS_GENERAL_FAILURE,
+    st_TRACK_SUCCESS,
+    st_TRACK_STATUS_GENERAL_FAILURE,
+    st_buffer_flags_t,
+    st_arch_size_t,
+    st_object_type_id_t,
+    st_BUFFER_DEFAULT_CAPACITY,
+    st_BUFFER_DEFAULT_DATASTORE_FLAGS,
+    st_Particles_p,
+    st_NullParticles,
+    st_ParticlesAddr,
+    st_NullParticlesAddr,
+    st_track_status_t,
+    st_track_job_collect_flag_t,
+    st_track_job_clear_flag_t,
+    st_out_buffer_flags_t,
+    st_track_job_size_t,
+    st_NullTrackJob,
+    st_TrackJobNew_delete,
+    st_TrackJobNew_track_until,
+    st_buffer_size_t,
+    st_NullBuffer,
+    st_Buffer_is_particles_buffer,
+    st_Particles_buffer_get_num_of_particle_blocks,
+    st_Particles_buffer_get_particles,
+    st_Particles_get_num_of_particles,
+    st_OutputBuffer_required_for_tracking,
+    st_OutputBuffer_requires_output_buffer,
+    st_OutputBuffer_calculate_output_buffer_params,
+    st_TrackJob_get_type_str,
+    st_TrackJobNew_track_elem_by_elem,
+    st_TrackJobNew_track_line,
+    st_TrackJobNew_collect,
+    st_TrackJobNew_collect_detailed,
+    st_TrackJobNew_collect_particles,
+    st_TrackJobNew_collect_beam_elements,
+    st_TrackJobNew_collect_output,
+    st_TrackJobNew_collect_debug_flag,
+    st_TrackJobNew_collect_particles_addresses,
+    st_TrackJobNew_enable_collect_particles,
+    st_TrackJobNew_disable_collect_particles,
+    st_TrackJobNew_is_collecting_particles,
+    st_TrackJobNew_enable_collect_beam_elements,
+    st_TrackJobNew_disable_collect_beam_elements,
+    st_TrackJobNew_is_collecting_beam_elements,
+    st_TrackJobNew_enable_collect_output,
+    st_TrackJobNew_disable_collect_output,
+    st_TrackJobNew_is_collecting_output,
+    st_TrackJobNew_get_collect_flags,
+    st_TrackJobNew_set_collect_flags,
+    st_TrackJobNew_requires_collecting,
+    st_TrackJobNew_push,
+    st_TrackJobNew_push_particles,
+    st_TrackJobNew_push_beam_elements,
+    st_TrackJobNew_push_output,
+    st_TrackJobNew_can_fetch_particle_addresses,
+    st_TrackJobNew_has_particle_addresses,
+    st_TrackJobNew_fetch_particle_addresses,
+    st_TrackJobNew_clear_particle_addresses,
+    st_TrackJobNew_clear_all_particle_addresses,
+    st_TrackJobNew_get_particle_addresses,
+    st_TrackJobNew_get_ptr_particle_addresses_buffer,
+    st_TrackJobNew_is_in_debug_mode,
+    st_TrackJobNew_enable_debug_mode,
+    st_TrackJobNew_disable_debug_mode,
+    st_TrackJobNew_clear,
+    st_TrackJobNew_reset,
+    st_TrackJobNew_reset_particle_set,
+    st_TrackJobNew_reset_with_output,
+    st_TrackJobNew_reset_detailed,
+    st_TrackJobNew_select_particle_set,
+    st_TrackJobNew_assign_output_buffer,
+    st_TrackJobNew_get_arch_id,
+    st_TrackJobNew_has_arch_string,
+    st_TrackJobNew_get_arch_string,
+    st_TrackJobNew_has_config_str,
+    st_TrackJobNew_get_config_str,
+    st_TrackJobNew_get_num_particle_sets,
+    st_TrackJobNew_get_particle_set_indices_begin,
+    st_TrackJobNew_get_particle_set_indices_end,
+    st_TrackJobNew_get_particle_set_index,
+    st_TrackJobNew_get_total_num_of_particles,
+    st_TrackJobNew_get_min_particle_id,
+    st_TrackJobNew_get_max_particle_id,
+    st_TrackJobNew_get_min_element_id,
+    st_TrackJobNew_get_max_element_id,
+    st_TrackJobNew_get_min_initial_turn_id,
+    st_TrackJobNew_get_max_initial_turn_id,
+    st_TrackJobNew_get_particles_buffer,
+    st_TrackJobNew_get_beam_elements_buffer,
+    st_TrackJobNew_has_output_buffer,
+    st_TrackJobNew_owns_output_buffer,
+    st_TrackJobNew_has_elem_by_elem_output,
+    st_TrackJobNew_has_beam_monitor_output,
+    st_TrackJobNew_get_beam_monitor_output_buffer_offset,
+    st_TrackJobNew_get_elem_by_elem_output_buffer_offset,
+    st_TrackJobNew_get_num_elem_by_elem_turns,
+    st_TrackJobNew_get_output_buffer,
+    st_TrackJobNew_has_beam_monitors,
+    st_TrackJobNew_get_num_beam_monitors,
+    st_TrackJobNew_get_beam_monitor_indices_begin,
+    st_TrackJobNew_get_beam_monitor_indices_end,
+    st_TrackJobNew_get_beam_monitor_index,
+    st_TrackJobNew_has_elem_by_elem_config,
+    st_TrackJobNew_get_elem_by_elem_config,
+    st_TrackJobNew_is_elem_by_elem_config_rolling,
+    st_TrackJobNew_get_default_elem_by_elem_config_rolling_flag,
+    st_TrackJobNew_set_default_elem_by_elem_config_rolling_flag,
+    st_TrackJobNew_get_elem_by_elem_config_order,
+    st_TrackJobNew_get_default_elem_by_elem_config_order,
+    st_TrackJobNew_set_default_elem_by_elem_config_order,
+    st_TrackJobNew_uses_controller,
+    st_TrackJobNew_uses_arguments,
+)
+
+if stconf.SIXTRACKLIB_MODULES.get("opencl", False):
+    from .stcommon import (
+        st_OpenCL_get_available_nodes_required_str_capacity,
+        st_OpenCL_get_all_nodes_required_str_capacity,
+        st_OpenCL_get_available_nodes_as_string,
+        st_OpenCL_get_all_nodes_as_string,
+    )
 
 
 class TrackJobBaseNew(object):
@@ -109,30 +165,40 @@ def __init__(self, ptr_track_job=None, owns_ptr=True):
         self._ptr_c_particles_buffer = st_NullBuffer
         self._ptr_c_beam_elements_buffer = st_NullBuffer
         self._ptr_c_output_buffer = st_NullBuffer
+        self._stored_buffers = {}
 
-        if ptr_track_job is not None and ptr_track_job != st_NullTrackJobBaseNew:
+        if (
+            ptr_track_job is not None
+            and ptr_track_job != st_NullTrackJobBaseNew
+        ):
             self._ptr_track_job = ptr_track_job
             self._owns_ptr = owns_ptr
 
     def __del__(self):
-        if self._ptr_track_job is not None and \
-                self._ptr_track_job != st_NullTrackJobBaseNew and \
-                self._owns_ptr:
+        if (
+            self._ptr_track_job is not None
+            and self._ptr_track_job != st_NullTrackJobBaseNew
+            and self._owns_ptr
+        ):
             st_TrackJobNew_delete(self._ptr_track_job)
             self._ptr_track_job = st_NullTrackJobBaseNew
             self._owns_ptr = False
 
     def _reset_detailed(
-            self,
-            beam_elements_buffer,
-            particles_buffer,
-            particle_set_index=0,
-            until_turn_elem_by_elem=0,
-            output_buffer=None):
-        if self._ptr_track_job is None or \
-                self._ptr_track_job == st_NullTrackJobBaseNew:
-            raise ValueError("TrackJob has to be initialized before " +
-                             "calling reset")
+        self,
+        beam_elements_buffer,
+        particles_buffer,
+        particle_set_index=0,
+        until_turn_elem_by_elem=0,
+        output_buffer=None,
+    ):
+        if (
+            self._ptr_track_job is None
+            or self._ptr_track_job == st_NullTrackJobBaseNew
+        ):
+            raise ValueError(
+                "TrackJob has to be initialized before " + "calling reset"
+            )
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         _particles_buffer = None
         _internal_particles_buffer = None
@@ -155,26 +221,36 @@ def _reset_detailed(
                 _internal_particles_buffer = particles_buffer
                 _ptr_c_particles_buffer = particles_buffer.pointer
 
-        if _internal_particles_buffer is None or \
-                _ptr_c_particles_buffer == st_NullBuffer:
+        if (
+            _internal_particles_buffer is None
+            or _ptr_c_particles_buffer == st_NullBuffer
+        ):
             raise ValueError("Issues with input particles buffer")
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         slot_size = _internal_particles_buffer.slot_size
         _slot_size = st_buffer_size_t(slot_size)
         particles = st_NullParticles
 
-        if st_Particles_buffer_get_num_of_particle_blocks(
-                _ptr_c_particles_buffer) > particle_set_index:
+        if (
+            st_Particles_buffer_get_num_of_particle_blocks(
+                _ptr_c_particles_buffer
+            )
+            > particle_set_index
+        ):
             _pset_index = st_buffer_size_t(particle_set_index)
             particles = st_Particles_buffer_get_particles(
-                _ptr_c_particles_buffer, _pset_index)
+                _ptr_c_particles_buffer, _pset_index
+            )
         else:
             raise ValueError(
-                "Input particle buffer has {0} blocks, " +
-                "inconsistent with particle set index {1}".format(
+                "Input particle buffer has {0} blocks, "
+                + "inconsistent with particle set index {1}".format(
                     st_Particles_buffer_get_num_of_particle_blocks(
-                        _ptr_c_particles_buffer),
-                    particle_set_index))
+                        _ptr_c_particles_buffer
+                    ),
+                    particle_set_index,
+                )
+            )
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         _beam_elem_buffer = None
         _internal_beam_elements_buffer = None
@@ -184,27 +260,35 @@ def _reset_detailed(
             if isinstance(beam_elements_buffer, CBuffer):
                 _beam_elements_buffer = beam_elements_buffer
                 _internal_beam_elements_buffer = Buffer(
-                    cbuffer=beam_elements_buffer)
-                _ptr_c_beam_elements_buffer = \
+                    cbuffer=beam_elements_buffer
+                )
+                _ptr_c_beam_elements_buffer = (
                     _internal_beam_elements_buffer.pointer
+                )
             elif isinstance(beam_elements_buffer, CObject):
                 _beam_elements_buffer = beam_elements_buffer._buffer
                 _internal_beam_elements_buffer = Buffer(
-                    cbuffer=_beam_elements_buffer)
-                _ptr_c_beam_elements_buffer = \
+                    cbuffer=_beam_elements_buffer
+                )
+                _ptr_c_beam_elements_buffer = (
                     _internal_beam_elements_buffer.pointer
+                )
             elif isinstance(beam_elements_buffer, Elements):
                 _beam_elements_buffer = beam_elements_buffer.cbuffer
                 _internal_beam_elements_buffer = Buffer(
-                    cbuffer=_beam_elements_buffer)
-                _ptr_c_beam_elements_buffer = \
+                    cbuffer=_beam_elements_buffer
+                )
+                _ptr_c_beam_elements_buffer = (
                     _internal_beam_elements_buffer.pointer
+                )
             elif isinstance(beam_elements_buffer, Buffer):
                 _internal_beam_elements_buffer = beam_elements_buffer
                 _ptr_c_beam_elements_buffer = beam_elements_buffer.pointer
 
-        if _internal_beam_elements_buffer is None or \
-                _ptr_c_beam_elements_buffer == st_NullBuffer:
+        if (
+            _internal_beam_elements_buffer is None
+            or _ptr_c_beam_elements_buffer == st_NullBuffer
+        ):
             raise ValueError("Issues with input beam elements buffer")
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         _output_buffer = None
@@ -224,12 +308,14 @@ def _reset_detailed(
         _until_turn_elem_by_elem = st_buffer_size_t(until_turn_elem_by_elem)
 
         out_buffer_flags = st_OutputBuffer_required_for_tracking(
-            particles, _ptr_c_beam_elements_buffer, _until_turn_elem_by_elem)
+            particles, _ptr_c_beam_elements_buffer, _until_turn_elem_by_elem
+        )
 
         _out_buffer_flags = st_out_buffer_flags_t(out_buffer_flags)
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-        needs_output_buffer = \
-            st_OutputBuffer_requires_output_buffer(_out_buffer_flags)
+        needs_output_buffer = st_OutputBuffer_requires_output_buffer(
+            _out_buffer_flags
+        )
 
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         if needs_output_buffer:
@@ -239,35 +325,48 @@ def _reset_detailed(
             num_garbage = st_buffer_size_t(0)
 
             ret = st.st_OutputBuffer_calculate_output_buffer_params(
-                _ptr_c_beam_elements_buffer, particles,
-                _until_turn_elem_by_elem, ct.byref(num_objects),
-                ct.byref(num_slots), ct.byref(num_dataptrs),
-                ct.byref(num_garbage), _slot_size)
+                _ptr_c_beam_elements_buffer,
+                particles,
+                _until_turn_elem_by_elem,
+                ct.byref(num_objects),
+                ct.byref(num_slots),
+                ct.byref(num_dataptrs),
+                ct.byref(num_garbage),
+                _slot_size,
+            )
 
             if ret != 0:
                 raise RuntimeError("Error pre-calculating out buffer params")
 
-            if num_objects.value > 0 and num_slots.value > 0 and \
-                    num_dataptrs.value > 0 and num_garbage.value >= 0:
-                if _output_buffer is None and \
-                        _internal_output_buffer is None:
+            if (
+                num_objects.value > 0
+                and num_slots.value > 0
+                and num_dataptrs.value > 0
+                and num_garbage.value >= 0
+            ):
+                if _output_buffer is None and _internal_output_buffer is None:
                     _output_buffer = CBuffer(
                         max_slots=num_slots.value,
                         max_objects=num_objects.value,
                         max_pointers=num_dataptrs.value,
-                        max_garbage=num_garbage.value)
-                    _internal_output_buffer = Buffer(
-                        cbuffer=_output_buffer)
+                        max_garbage=num_garbage.value,
+                    )
+                    _internal_output_buffer = Buffer(cbuffer=_output_buffer)
                 elif _output_buffer is not None:
                     _output_buffer.reallocate(
                         max_slots=num_slots.value,
                         max_objects=num_objects.value,
                         max_pointers=num_dataptrs.value,
-                        max_garbage=num_garbage.value)
+                        max_garbage=num_garbage.value,
+                    )
                     _internal_output_buffer = Buffer(cbuffer=_output_buffer)
                 elif _internal_output_buffer is not None:
                     _internal_output_buffer.reserve(
-                        num_objects.value, num_slots.value, num_dataptrs.value, num_garbage.value)
+                        num_objects.value,
+                        num_slots.value,
+                        num_dataptrs.value,
+                        num_garbage.value,
+                    )
                 else:
                     raise ValueError("No valid output buffer available")
 
@@ -280,19 +379,28 @@ def _reset_detailed(
             _ptr_c_output_buffer = _internal_output_buffer.pointer
 
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-        if (needs_output_buffer and
-            (_ptr_c_output_buffer == st_NullBuffer or
-             _internal_output_buffer is None)) or \
-           ((_output_buffer is not None or
-               _internal_output_buffer is not None) and
-                _ptr_c_output_buffer == st_NullBuffer):
+        if (
+            needs_output_buffer
+            and (
+                _ptr_c_output_buffer == st_NullBuffer
+                or _internal_output_buffer is None
+            )
+        ) or (
+            (_output_buffer is not None or _internal_output_buffer is not None)
+            and _ptr_c_output_buffer == st_NullBuffer
+        ):
             raise RuntimeError("Unable to provide output buffer")
 
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         self._last_status = st_TrackJobNew_reset_detailed(
-            self._ptr_track_job, _ptr_c_particles_buffer, st_buffer_size_t(1),
-            ct.byref(_pset_index), _ptr_c_beam_elements_buffer,
-            _ptr_c_output_buffer, _until_turn_elem_by_elem)
+            self._ptr_track_job,
+            _ptr_c_particles_buffer,
+            st_buffer_size_t(1),
+            ct.byref(_pset_index),
+            _ptr_c_beam_elements_buffer,
+            _ptr_c_output_buffer,
+            _until_turn_elem_by_elem,
+        )
 
         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         if self._last_status == st_ARCH_STATUS_SUCCESS.value:
@@ -304,17 +412,19 @@ def _reset_detailed(
             self._ptr_c_beam_elements_buffer = _ptr_c_beam_elements_buffer
             self._ptr_c_output_buffer = _ptr_c_output_buffer
 
-            del(self._internal_particles_buffer)
-            del(self._internal_beam_elements_buffer)
-            del(self._internal_output_buffer)
+            del self._internal_particles_buffer
+            del self._internal_beam_elements_buffer
+            del self._internal_output_buffer
 
-            self._internal_beam_elements_buffer = _internal_beam_elements_buffer
+            self._internal_beam_elements_buffer = (
+                _internal_beam_elements_buffer
+            )
             self._internal_particles_buffer = _internal_particles_buffer
             self._internal_output_buffer = _internal_output_buffer
 
-            del(self._particles_buffer)
-            del(self._beam_elements_buffer)
-            del(self._output_buffer)
+            del self._particles_buffer
+            del self._beam_elements_buffer
+            del self._output_buffer
 
             self._particles_buffer = _particles_buffer
             self._beam_elements_buffer = beam_elements_buffer
@@ -350,8 +460,9 @@ def arch_id(self):
     def arch_str(self):
         arch_str = None
         if st_TrackJobNew_has_arch_string(self._ptr_track_job):
-            arch_str = bytes(st_TrackJobNew_get_arch_string(
-                self._ptr_track_job)).decode('utf-8')
+            arch_str = ctypes_str_to_decoded_string(
+                st_TrackJobNew_get_arch_string(self._ptr_track_job)
+            )
         return arch_str
 
     @property
@@ -388,8 +499,7 @@ def collecting_flags(self):
 
     @property
     def can_fetch_particle_addresses(self):
-        return st_TrackJobNew_can_fetch_particle_addresses(
-            self._ptr_track_job)
+        return st_TrackJobNew_can_fetch_particle_addresses(self._ptr_track_job)
 
     @property
     def has_particle_addresses(self):
@@ -434,17 +544,20 @@ def has_beam_monitor_output(self):
     @property
     def beam_monitor_output_buffer_offset(self):
         return st_TrackJobNew_get_beam_monitor_output_buffer_offset(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
 
     @property
     def elem_by_elem_output_buffer_offset(self):
         return st_TrackJobNew_get_elem_by_elem_output_buffer_offset(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
 
     @property
     def num_elem_by_elem_turn(self):
         return st_TrackJobNew_get_elem_by_elem_output_buffer_offset(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
 
     @property
     def has_elem_by_elem_config(self):
@@ -466,37 +579,58 @@ def particles_buffer(self):
     def beam_elements_buffer(self):
         return self._beam_elements_buffer
 
+    @property
+    def has_stored_buffers(self):
+        return st.st_TrackJobNew_has_stored_buffers( self._ptr_track_job )
+
+    @property
+    def num_stored_buffers(self):
+        return st.st_TrackJobNew_num_stored_buffers( self._ptr_track_job )
+
+    @property
+    def min_stored_buffer_id(self):
+        return st.st_TrackJobNew_min_stored_buffer_id( self._ptr_track_job )
+
+    @property
+    def max_stored_buffer_id(self):
+        return st.st_TrackJobNew_max_stored_buffer_id( self._ptr_track_job )
+
     # -------------------------------------------------------------------------
 
     def track_until(self, until_turn):
         self._last_track_status = st_TrackJobNew_track_until(
-            self._ptr_track_job, st_buffer_size_t(until_turn))
+            self._ptr_track_job, st_buffer_size_t(until_turn)
+        )
         if self._last_track_status != st_TRACK_SUCCESS.value:
             raise RuntimeError(
                 "Error occuriung during track_until(); "
-                "track status:{0}".format(
-                    self._last_track_status))
+                "track status:{0}".format(self._last_track_status)
+            )
         return self
 
     def track_elem_by_elem(self, until_turn):
         self._last_track_status = st_TrackJobNew_track_elem_by_elem(
-            self._ptr_track_job, st_buffer_size_t(until_turn))
+            self._ptr_track_job, st_buffer_size_t(until_turn)
+        )
         if self._last_track_status != st_TRACK_SUCCESS.value:
             raise RuntimeError(
                 "Error occuriung during track_elem_by_elem(); "
-                "track status:{0}".format(
-                    self._last_track_status))
+                "track status:{0}".format(self._last_track_status)
+            )
         return self
 
     def track_line(self, be_begin_idx, be_end_idx, finish_turn=False):
         self._last_track_status = st_TrackJobNew_track_line(
-            self._ptr_track_job, st_buffer_size_t(be_begin_idx),
-            st_buffer_size_t(be_end_idx), ct.c_bool(finish_turn))
+            self._ptr_track_job,
+            st_buffer_size_t(be_begin_idx),
+            st_buffer_size_t(be_end_idx),
+            ct.c_bool(finish_turn),
+        )
         if self._last_track_status != st_TRACK_SUCCESS.value:
             raise RuntimeError(
                 "Error occuriung during track_line(); "
-                "track status:{0}".format(
-                    self._last_track_status))
+                "track status:{0}".format(self._last_track_status)
+            )
         return self
 
     # -------------------------------------------------------------------------
@@ -504,14 +638,18 @@ def track_line(self, be_begin_idx, be_end_idx, finish_turn=False):
     def collect(self, collect_flags=None):
         if collect_flags is None:
             collect_flags = st_TrackJobNew_get_collect_flags(
-                self._ptr_track_job)
+                self._ptr_track_job
+            )
         if collect_flags > 0:
             collected_flags = st_TrackJobNew_collect(self._ptr_track_job)
         return self
 
     def collectParticles(self):
-        warnings.warn("collectParticles() is depreciated;" +
-                      "use collect_particles instead", DeprecationWarning)
+        warnings.warn(
+            "collectParticles() is depreciated;"
+            + "use collect_particles instead",
+            DeprecationWarning,
+        )
         self.collect_particles(self)
 
     def collect_particles(self):
@@ -519,70 +657,90 @@ def collect_particles(self):
         assert self._internal_particles_buffer.pointer != st_NullBuffer
 
         self._last_status = st_TrackJobNew_collect_particles(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful particles collection op; status:{0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     def collectBeamElements(self):
-        warnings.warn("collectBeamElements() is depreciated; " +
-                      "use collect_beam_elements() instead", DeprecationWarning)
+        warnings.warn(
+            "collectBeamElements() is depreciated; "
+            + "use collect_beam_elements() instead",
+            DeprecationWarning,
+        )
         self.collect_beam_elements()
 
     def collect_beam_elements(self):
         self._last_status = st_TrackJobNew_collect_beam_elements(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful beam-elements collection op; status:{0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     def collectOutput(self):
-        warnings.warn("collectOutput() is depreciated; " +
-                      "use collect_output instead", DeprecationWarning)
+        warnings.warn(
+            "collectOutput() is depreciated; " + "use collect_output instead",
+            DeprecationWarning,
+        )
         self.collect_output()
 
     def collect_output(self):
-        self._last_status = st_TrackJobNew_collect_output(
-            self._ptr_track_job)
+        self._last_status = st_TrackJobNew_collect_output(self._ptr_track_job)
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful output collection op; status:{0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     def collectParticlesAddresses(self):
         warnings.warn(
-            "collectParticleAddresses() is depreciated;" +
-            " use collect_particle_addresses() instead",
-            DeprecationWarning)
+            "collectParticleAddresses() is depreciated;"
+            + " use collect_particle_addresses() instead",
+            DeprecationWarning,
+        )
         self.collect_particle_addresses()
 
     def collect_particle_addresses(self):
         self._last_status = st_TrackJobNew_collect_particles_addresses(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
-            "unsuccessful particles addresses collection op; " +
-            "status:{0}".format(
-                self._last_status))
+            "unsuccessful particles addresses collection op; "
+            + "status:{0}".format(self._last_status),
+        )
         return self
 
     def collectDebugFlag(self):
-        warnings.warn("collectDebugFlag() is depreciated; " +
-                      "use collect_debug_flag() instead", DeprecationWarning)
+        warnings.warn(
+            "collectDebugFlag() is depreciated; "
+            + "use collect_debug_flag() instead",
+            DeprecationWarning,
+        )
         self.collect_debug_flag()
 
     def collect_debug_flag(self):
         self._last_status = st_TrackJobNew_collect_debug_flag(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful debug flag collection op; status:{0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     # -------------------------------------------------------------------------
@@ -592,159 +750,549 @@ def push_particles(self):
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful particles push op; status: {0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     def push_beam_elements(self):
         self._last_status = st_TrackJobNew_push_beam_elements(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful beam elements push op; status: {0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     def _push_output(self):
-        self._last_status = st_TrackJobNew_push_output(
-            self._ptr_track_job)
+        self._last_status = st_TrackJobNew_push_output(self._ptr_track_job)
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful output push op; status: {0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     # -------------------------------------------------------------------------
 
     def enable_debug_mode(self):
         self._last_status = st_TrackJobNew_enable_debug_mode(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful enable debug mode op; status:{0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     def disable_debug_mode(self):
         self._last_status = st_TrackJobNew_disable_debug_mode(
-            self._ptr_track_job)
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
             "unsuccessful disable debug mode op; status:{0}".format(
-                self._last_status))
+                self._last_status
+            ),
+        )
         return self
 
     # -------------------------------------------------------------------------
 
     def fetch_particle_addresses(self):
-        self._last_status = st_TrackJobNew_fetch_particle_addresses(
-            self._ptr_track_job)
+        self._last_status = st.st_TrackJobNew_fetch_particle_addresses(
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
-            "unsuccessful fetching particle addresses op; " +
-            "status:{0}".format(
-                self._last_status))
+            "unsuccessful fetching particle addresses op; "
+            + "status:{0}".format(self._last_status),
+        )
         return self
 
     def clear_particle_addresses(self, particle_set_index=0):
-        self._last_status = st_TrackJobNew_clear_particle_addresses(
-            self._ptr_track_job, st_buffer_size_t(particle_set_index))
+        self._last_status = st.st_TrackJobNew_clear_particle_addresses(
+            self._ptr_track_job, st_buffer_size_t(particle_set_index)
+        )
         raise_error_if_status_not_success(
             self._last_status,
-            "unsuccessful clearing of particle addresses op; " +
-            "particle_set_index={0}, status:{1}".format(
-                particle_set_index,
-                self._last_status))
+            "unsuccessful clearing of particle addresses op; "
+            + "particle_set_index={0}, status:{1}".format(
+                particle_set_index, self._last_status
+            ),
+        )
         return self
 
     def clear_all_particle_addresses(self):
-        self._last_status = st_TrackJobNew_clear_all_particle_addresses(
-            self._ptr_track_job)
+        self._last_status = st.st_TrackJobNew_clear_all_particle_addresses(
+            self._ptr_track_job
+        )
         raise_error_if_status_not_success(
             self._last_status,
-            "unsuccessful clearing all particle addresses op; " +
-            "status:{0}".format(
-                self._last_status))
+            "unsuccessful clearing all particle addresses op; "
+            + "status:{0}".format(self._last_status),
+        )
         return self
 
     def get_particle_addresses(self, particle_set_index=0):
-        return st_TrackJobNew_get_particle_addresses(
-            self._ptr_track_job, st_buffer_size_t(particle_set_index))
+        return st.st_TrackJobNew_get_particle_addresses(
+            self._ptr_track_job, st_buffer_size_t(particle_set_index)
+        )
+
+    # -------------------------------------------------------------------------
+
+    def add_stored_buffer(
+        self,
+        cbuffer=None,
+        size=None,
+        ptr_c_buffer=None,
+        take_ownership=False,
+        delete_ptr_after_move=False,
+    ):
+        _st_buffer = None
+        buffer_id = st.st_ARCH_ILLEGAL_BUFFER_ID.value
+        if not (cbuffer is None):
+            _st_buffer = Buffer.from_cbuffer(cbuffer)
+        elif not (size is None) and size > 0:
+            _st_buffer = Buffer(size=size)
+        elif not (ptr_c_buffer is None) and ptr_c_buffer != st_NullBuffer:
+            owns_buffer = take_ownership
+            owns_pointer = take_ownership and delete_ptr_after_move
+            _st_buffer = Buffer(
+                ptr_ext_buffer=ptr_c_buffer,
+                owns_buffer=owns_buffer,
+                owns_pointer=owns_pointer,
+            )
+        if not (_st_buffer is None) and _st_buffer.pointer != st_NullBuffer:
+            buffer_id = st.st_TrackJobNew_add_stored_buffer(
+                self._ptr_track_job,
+                _st_buffer.pointer,
+                ct.c_bool(False),
+                ct.c_bool(False)
+            )
+            if buffer_id != st.st_ARCH_ILLEGAL_BUFFER_ID.value:
+                assert buffer_id not in self._stored_buffers
+                self._stored_buffers[buffer_id] = _st_buffer
+        return buffer_id
+
+    def remove_stored_buffer(self, buffer_id):
+        return st.st_TrackJobNew_remove_stored_buffer(
+            self._ptr_track_job, st_arch_size_t(buffer_id)
+        )
+
+    def owns_stored_buffer(self, buffer_id):
+        return st.st_TrackJobNew_owns_stored_buffer(
+            self._ptr_track_job, st_arch_size_t(buffer_id)
+        )
+
+    @property
+    def stored_buffer_is_cbuffer(self, buffer_id):
+        return (
+            buffer_id in self._stored_buffers
+            and self._stored_buffers[buffer_id].maps_to_cbuffer
+        )
+
+    def stored_buffer_cbuffer(self, buffer_id):
+        if not self.stored_buffer_is_cbuffer:
+            raise RuntimeError(
+                f"Unable to retrieve CBuffer for buffer_id={buffer_id}"
+            )
+        return self._stored_buffers[buffer_id].cbuffer
+
+    def ptr_stored_buffer(self, buffer_id):
+        return st.st_TrackJobNew_stored_buffer(
+            self._ptr_track_job, st_arch_size_t(buffer_id)
+        )
+
+    def stored_buffer(self, buffer_id):
+        return self._stored_buffers.get(buffer_id, None)
+
+    def push_stored_buffer(self, buffer_id):
+        self._last_status = st.st_TrackJobNew_push_stored_buffer(
+            self._ptr_track_job, st_buffer_size_t(buffer_id)
+        )
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError(f"Unable to push stored buffer {buffer_id}")
+        return self
+
+    def collect_stored_buffer(self, buffer_id):
+        self._last_status = st.st_TrackJobNew_collect_stored_buffer(
+            self._ptr_track_job, st_buffer_size_t(buffer_id)
+        )
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError(f"Unable to collect stored buffer {buffer_id}")
+        return self
+
+    # -------------------------------------------------------------------------
+
+    @property
+    def total_num_assign_items(self):
+        return st.st_TrackJobNew_total_num_assign_items(self._ptr_track_job)
+
+    def ptr_assign_address_item(
+        self,
+        item=None,
+        dest_elem_type_id=None,
+        dest_buffer_id=None,
+        dest_elem_index=None,
+        dest_pointer_offset=None,
+        src_elem_type_id=None,
+        src_buffer_id=None,
+        src_elem_index=None,
+        src_pointer_offset=None,
+        index=None,
+    ):
+        _ptr_found = st.st_NullAssignAddressItem
+        if not (item is None):
+            if isinstance(item, AssignAddressItem):
+                # TODO: Figure out a way to do this without relying on
+                #      internal API for cobjects
+                _ptr_found = st.st_TrackJobNew_ptr_assign_address_item(
+                    self._ptr_track_job,
+                    ct.cast(item._get_address(), st.st_AssignAddressItem_p),
+                )
+            elif item != st.st_NullAssignAddressItem:
+                _ptr_found = st.st_TrackJobNew_ptr_assign_address_item(
+                    self._ptr_track_job, item
+                )
+        elif not (dest_buffer_id is None) and not (src_buffer_id is None):
+            if not (index is None) and index >= 0:
+                _ptr_found = st.st_TrackJobNew_ptr_assign_address_item_by_index(
+                    self._ptr_track_job,
+                    st_buffer_size_t(dest_buffer_id),
+                    st_buffer_size_t(src_buffer_id),
+                    st_buffer_size_t(index),
+                )
+            elif (
+                not (dest_elem_type_id is None)
+                and not (dest_elem_index is None)
+                and not (dest_pointer_offset is None)
+                and not (src_elem_type_id is None)
+                and not (src_elem_index is None)
+                and not (src_pointer_offset is None)
+            ):
+                _ptr_found = st.st_TrackJobNew_ptr_assign_address_item_detailed(
+                    self._ptr_track_job,
+                    st_object_type_id_t(dest_elem_type_id),
+                    st_buffer_size_t(dest_buffer_id),
+                    st_buffer_size_t(dest_elem_index),
+                    st_buffer_size_t(dest_pointer_offset),
+                    st_object_type_id_t(src_elem_type_id),
+                    st_buffer_size_t(src_buffer_id),
+                    st_buffer_size_t(src_elem_index),
+                    st_buffer_size_t(src_pointer_offset),
+                )
+        return _ptr_found
+
+    def has_assign_items(self, dest_buffer_id, src_buffer_id):
+        return st.st_TrackJobNew_has_assign_items(
+            self._ptr_track_job,
+            st_buffer_size_t(dest_buffer_id),
+            st_buffer_size_t(src_buffer_id),
+        )
+
+    def num_assign_items(self, dest_buffer_id, src_buffer_id):
+        return st.st_TrackJobNew_num_assign_items(
+            self._ptr_track_job,
+            st_buffer_size_t(dest_buffer_id),
+            st_buffer_size_t(src_buffer_id),
+        )
+
+    def has_assign_item(
+        self,
+        item=None,
+        dest_buffer_id=None,
+        src_buffer_id=None,
+        index=None,
+        dest_elem_type_id=None,
+        dest_elem_index=None,
+        dest_pointer_offset=None,
+        src_elem_type_id=None,
+        src_elem_index=None,
+        src_pointer_offset=None,
+    ):
+        has_item = False
+        if not (item is None):
+            if isinstance(item, AssignAddressItem):
+                # TODO: Figure out a way to do this without relying on
+                #      internal API for cobjects
+                has_item = st.st_TrackJobNew_has_assign_address_item(
+                    self._ptr_track_job,
+                    ct.cast(item._get_address(), st.st_AssignAddressItem_p),
+                )
+            elif item != st.st_NullAssignAddressItem:
+                has_item = st.st_TrackJobNew_has_assign_address_item(
+                    self._ptr_track_job, item
+                )
+        elif not (dest_buffer_id is None) and not (src_buffer_id is None):
+            if not (index is None) and index >= 0:
+                has_item = st.st_TrackJobNew_has_assign_item_by_index(
+                    self._ptr_track_job,
+                    st_buffer_size_t(dest_buffer_id),
+                    st_buffer_size_t(src_buffer_id),
+                    st_buffer_size_t(index),
+                )
+            elif (
+                not (dest_elem_type_id is None)
+                and not (dest_elem_index is None)
+                and not (dest_pointer_offset is None)
+                and not (src_elem_type_id is None)
+                and not (src_elem_index is None)
+                and not (src_pointer_offset is None)
+            ):
+                has_item = st.st_TrackJobNew_has_assign_address_item_detailed(
+                    self._ptr_track_job,
+                    st_object_type_id_t(dest_elem_type_id),
+                    st_buffer_size_t(dest_buffer_id),
+                    st_buffer_size_t(dest_elem_index),
+                    st_buffer_size_t(dest_pointer_offset),
+                    st_object_type_id_t(src_elem_type_id),
+                    st_buffer_size_t(src_buffer_id),
+                    st_buffer_size_t(src_elem_index),
+                    st_buffer_size_t(src_pointer_offset),
+                )
+        return has_item
+
+    def index_of_assign_address_item(
+        self,
+        item=None,
+        dest_buffer_id=None,
+        src_buffer_id=None,
+        dest_elem_type_id=None,
+        dest_elem_index=None,
+        dest_pointer_offset=None,
+        src_elem_type_id=None,
+        src_elem_index=None,
+        src_pointer_offset=None,
+    ):
+        index_of_item = None
+        if not (item is None):
+            if isinstance(item, AssignAddressItem):
+                # TODO: Figure out a way to do this without relying on
+                #      internal API for cobjects
+                index_of_item = st.st_TrackJobNew_index_of_assign_address_item(
+                    self._ptr_track_job,
+                    ct.cast(item._get_address(), st.st_AssignAddressItem_p),
+                )
+            elif item != st.st_NullAssignAddressItem:
+                index_of_item = st.st_TrackJobNew_index_of_assign_address_item(
+                    self._ptr_track_job, item
+                )
+        elif (
+            not (dest_buffer_id is None)
+            and not (src_buffer_id is None)
+            and not (dest_elem_type_id is None)
+            and not (dest_elem_index is None)
+            and not (dest_pointer_offset is None)
+            and not (src_elem_type_id is None)
+            and not (src_elem_index is None)
+            and not (src_pointer_offset is None)
+        ):
+            index_of_item = st.st_TrackJobNew_index_of_assign_address_item_detailed(
+                self._ptr_track_job,
+                st_object_type_id_t(dest_elem_type_id),
+                st_buffer_size_t(dest_buffer_id),
+                st_buffer_size_t(dest_elem_index),
+                st_buffer_size_t(dest_pointer_offset),
+                st_object_type_id_t(src_elem_type_id),
+                st_buffer_size_t(src_buffer_id),
+                st_buffer_size_t(src_elem_index),
+                st_buffer_size_t(src_pointer_offset),
+            )
+        return index_of_item
+
+    def add_assign_address_item(
+        self,
+        item=None,
+        dest_elem_type_id=None,
+        dest_buffer_id=None,
+        dest_elem_index=None,
+        dest_pointer_offset=None,
+        src_elem_type_id=None,
+        src_buffer_id=None,
+        src_elem_index=None,
+        src_pointer_offset=None,
+    ):
+        ptr_added_item = st.st_NullAssignAddressItem
+        if not (item is None):
+            if isinstance(item, AssignAddressItem):
+                # TODO: Figure out a way to do this without relying on
+                #      internal API for cobjects
+                _ptr_item = ct.cast(
+                    item._get_address(), st.st_AssignAddressItem_p
+                )
+
+                ptr_added_item = st.st_TrackJobNew_add_assign_address_item(
+                    self._ptr_track_job, _ptr_item
+                )
+            elif item != st.st_NullAssignAddressItem:
+                ptr_added_item = st.st_TrackJobNew_add_assign_address_item(
+                    self._ptr_track_job, item
+                )
+        elif (
+            not (dest_elem_type_id is None)
+            and not (dest_buffer_id is None)
+            and not (dest_elem_index is None)
+            and not (dest_pointer_offset is None)
+            and not (src_elem_type_id is None)
+            and not (src_buffer_id is None)
+            and not (src_elem_index is None)
+            and not (src_pointer_offset is None)
+        ):
+            ptr_added_item = st.st_TrackJobNew_add_assign_address_item_detailed(
+                self._ptr_track_job,
+                st.st_object_type_id_t(dest_elem_type_id),
+                st_buffer_size_t(dest_buffer_id),
+                st_buffer_size_t(dest_elem_index),
+                st_buffer_size_t(dest_pointer_offset),
+                st.st_object_type_id_t(src_elem_type_id),
+                st_buffer_size_t(src_buffer_id),
+                st_buffer_size_t(src_elem_index),
+                st_buffer_size_t(src_pointer_offset),
+            )
+
+        if ptr_added_item == st.st_NullAssignAddressItem:
+            raise ValueError(
+                "unable to add AssignAddressItem given by these parameters"
+            )
+        return ptr_added_item
+
+    def commit_address_assignments(self):
+        self._last_status = st.st_TrackJobNew_commit_address_assignments(
+            self._ptr_track_job
+        )
+
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError("Unable to commit address assignment items")
+
+        return self
+
+    def assign_all_addresses(self):
+        self._last_status = st.st_TrackJobNew_assign_all_addresses(
+            self._ptr_track_job
+        )
+
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError(
+                "Unable to perform assignment of all address items"
+            )
+
+        return self
+
+    def assign_addresses(self, dest_buffer_id, src_buffer_id):
+        if dest_buffer_id is None and src_buffer_id is None:
+            self._last_status = st.st_TrackJobNew_assign_all_addresses(
+                self._ptr_track_job
+            )
+        elif not (dest_buffer_id is None) and not (src_buffer_id is None):
+            self._last_status = st.st_TrackJobNew_assign_addresses(
+                self._ptr_track_job,
+                st_buffer_size_t(dest_buffer_id),
+                st_buffer_size_t(src_buffer_id),
+            )
+        else:
+            raise ValueError(
+                "inconsistent dest_buffer_id and src_buffer_id parameters"
+            )
+            self._last_status = st_ARCH_STATUS_GENERAL_FAILURE.value
 
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError("Unable to perform assignment of address items")
+        return self
 
-def _get_buffer(obj):
-    if isinstance(obj, CBuffer):
-        return obj
-    elif isinstance(obj, CObject):
-        return obj._buffer
-    elif hasattr(obj, 'cbuffer'):
-        return obj.cbuffer
-    else:
-        raise ValueError("Object {obj} is not or has not a CBuffer")
+# *****************************************************************************
+# *****************************************************************************
 
 
 class TrackJob(object):
+    @staticmethod
+    def num_all_nodes(arch_str=None):
+        if (
+            not (arch_str is None)
+            and arch_str == "opencl"
+            and stconf.SIXTRACKLIB_MODULES.get("opencl", False)
+        ):
+            return st.st_OpenCL_get_num_all_nodes()
+        else:
+            return 0
+
+    @staticmethod
+    def num_available_nodes(arch_str=None, env_var_name=None, filter_str=None):
+        if (
+            not (arch_str is None)
+            and arch_str == "opencl"
+            and stconf.SIXTRACKLIB_MODULES.get("opencl", False)
+        ):
+            return st.st_OpenCL_num_available_nodes_detailed(
+                string_to_encoded_ctypes_str(filter_str),
+                string_to_encoded_ctypes_str(env_var_name),
+            )
+        else:
+            return 0
+
     @staticmethod
     def enabled_archs():
-        enabled_archs = [arch_str for arch_str, flag in
-                         stconf.SIXTRACKLIB_MODULES.items() if flag]
-        if 'cpu' not in stconf.SIXTRACKLIB_MODULES:
+        enabled_archs = [
+            arch_str for arch_str, flag in SIXTRACKLIB_MODULES.items() if flag
+        ]
+        if "cpu" not in SIXTRACKLIB_MODULES:
             enabled_archs.append("cpu")
         return enabled_archs
 
     @staticmethod
     def print_nodes(arch_str, all=False, filter_str=None, env_var_name=None):
         arch_str = arch_str.strip().lower()
-        if not(filter_str is None):
-            _filter_str_bytes = filter_str.strip().encode('utf-8')
-            _filter_str = ct.c_char_p(_filter_str_bytes)
-        else:
-            _filter_str = None
-
-        if not(env_var_name is None):
-            _env_var_name_bytes = env_var_name.strip().encode('utf-8')
-            _env_var_name = ct.c_char_p(_env_var_name_bytes)
-        else:
-            _env_var_name = None
+        _filter_str = string_to_encoded_ctypes_str(filter_str)
+        _env_var_name = string_to_encoded_ctypes_str(env_var_name)
 
         if stconf.SIXTRACKLIB_MODULES.get(arch_str, False):
             if arch_str == "opencl":
                 if not all:
-                    capacity = \
-                        st.st_OpenCL_get_available_nodes_required_str_capacity(
-                            _filter_str, _env_var_name)
+                    cap = st_OpenCL_get_available_nodes_required_str_capacity(
+                        _filter_str, _env_var_name
+                    )
                 else:
-                    capacity = \
-                        st.st_OpenCL_get_all_nodes_required_str_capacity()
+                    cap = st_OpenCL_get_all_nodes_required_str_capacity()
 
-                _nodes_str = ct.create_string_buffer(capacity)
+                if cap > 0:
+                    _nodes_str = ct.create_string_buffer(cap)
+                    cap = st_arch_size_t(cap)
 
-                if not all:
-                    _status = st.st_OpenCL_get_available_nodes_as_string(
-                        _nodes_str, st.st_arch_size_t(capacity),
-                        _filter_str, _env_var_name)
-                else:
-                    _status = st.st_OpenCL_get_all_nodes_as_string(
-                        _nodes_str, st.st_arch_size_t(capacity))
+                    if not all:
+                        _status = st_OpenCL_get_available_nodes_as_string(
+                            _nodes_str, cap, _filter_str, _env_var_name
+                        )
+                    else:
+                        _status = st_OpenCL_get_all_nodes_as_string(
+                            _nodes_str, cap
+                        )
 
-                if _status == st.st_ARCH_STATUS_SUCCESS.value and capacity > 0:
-                    print(bytes(_nodes_str).decode('utf-8'))
-                else:
-                    raise RuntimeError("unable to print opencl nodes")
+                    if _status == st_ARCH_STATUS_SUCCESS.value:
+                        print(ctypes_str_to_decoded_string(_nodes_str))
+                    else:
+                        raise RuntimeError("unable to print opencl nodes")
             else:
-                print("nodes not available for architecture {0}".format(
-                    arch_str))
+                print(f"nodes not available for architecture {arch_str}")
         else:
-            print("architecture {0} is not enabled/known".format(arch_str))
-
-    def __init__(self,
-                 beam_elements_buffer,
-                 particles_buffer,
-                 until_turn_elem_by_elem=0,
-                 arch='cpu',
-                 device_id=None,
-                 device=None,
-                 output_buffer=None,
-                 config_str=None):
+            print(f"architecture {arc_str} is not enabled/known")
+
+    def __init__(
+        self,
+        beam_elements_buffer,
+        particles_buffer,
+        until_turn_elem_by_elem=0,
+        arch="cpu",
+        device_id=None,
+        device=None,
+        output_buffer=None,
+        config_str=None,
+    ):
         self.ptr_st_track_job = st.st_NullTrackJob
         self._particles_buffer = None
         self._ptr_c_particles_buffer = st.st_NullBuffer
@@ -752,37 +1300,48 @@ def __init__(self,
         self._ptr_c_beam_elements_buffer = st.st_NullBuffer
         self._output_buffer = None
         self._ptr_c_output_buffer = st.st_NullBuffer
+        self._arch = None
+        self._stored_buffers = {}
+        self._last_status = st_ARCH_STATUS_SUCCESS.value
+        self._last_track_status = st_TRACK_SUCCESS.value
 
         base_addr_t = ct.POINTER(ct.c_ubyte)
         success = False
 
         if particles_buffer is not None:
-            particles_buffer = _get_buffer(particles_buffer)
+            particles_buffer = get_cbuffer_from_obj(particles_buffer)
             self._particles_buffer = particles_buffer
-            self._ptr_c_particles_buffer = \
-                st.st_Buffer_new_mapped_on_cbuffer(particles_buffer)
+            self._ptr_c_particles_buffer = st.st_Buffer_new_mapped_on_cbuffer(
+                particles_buffer
+            )
             if self._ptr_c_particles_buffer == st.st_NullBuffer:
                 raise ValueError("Issues with input particles buffer")
 
         if beam_elements_buffer is not None:
-            beam_elements_buffer = _get_buffer(beam_elements_buffer)
+            beam_elements_buffer = get_cbuffer_from_obj(beam_elements_buffer)
             self._beam_elements_buffer = beam_elements_buffer
-            self._ptr_c_beam_elements_buffer = \
-                st.st_Buffer_new_mapped_on_cbuffer(beam_elements_buffer)
+            self._ptr_c_beam_elements_buffer = st.st_Buffer_new_mapped_on_cbuffer(
+                beam_elements_buffer
+            )
             if self._ptr_c_beam_elements_buffer == st.st_NullBuffer:
                 raise ValueError("Issues with input beam elements buffer")
 
         particles = st.st_Particles_buffer_get_particles(
-            self._ptr_c_particles_buffer, 0)
+            self._ptr_c_particles_buffer, 0
+        )
 
         if particles == st.st_NullParticles:
             raise ValueError("Required particle sets not available")
 
         until_turn_elem_by_elem = ct.c_uint64(until_turn_elem_by_elem)
         out_buffer_flags = st.st_OutputBuffer_required_for_tracking(
-            particles, self._ptr_c_beam_elements_buffer, until_turn_elem_by_elem)
+            particles,
+            self._ptr_c_beam_elements_buffer,
+            until_turn_elem_by_elem,
+        )
         needs_output_buffer = st.st_OutputBuffer_requires_output_buffer(
-            ct.c_int32(out_buffer_flags))
+            ct.c_int32(out_buffer_flags)
+        )
 
         if needs_output_buffer:
             num_objects = ct.c_uint64(0)
@@ -790,58 +1349,77 @@ def __init__(self,
             num_dataptrs = ct.c_uint64(0)
             num_garbage = ct.c_uint64(0)
             slot_size = st.st_Buffer_get_slot_size(
-                self._ptr_c_particles_buffer)
+                self._ptr_c_particles_buffer
+            )
 
             ret = st.st_OutputBuffer_calculate_output_buffer_params(
-                self._ptr_c_beam_elements_buffer, particles,
-                until_turn_elem_by_elem, ct.byref(num_objects),
-                ct.byref(num_slots), ct.byref(num_dataptrs),
-                ct.byref(num_garbage), slot_size)
+                self._ptr_c_beam_elements_buffer,
+                particles,
+                until_turn_elem_by_elem,
+                ct.byref(num_objects),
+                ct.byref(num_slots),
+                ct.byref(num_dataptrs),
+                ct.byref(num_garbage),
+                slot_size,
+            )
 
             if ret == 0:
-                if num_objects.value > 0 and num_slots.value > 0 and \
-                        num_dataptrs.value > 0 and num_garbage.value >= 0:
+                if (
+                    num_objects.value > 0
+                    and num_slots.value > 0
+                    and num_dataptrs.value > 0
+                    and num_garbage.value >= 0
+                ):
                     if output_buffer is None:
                         output_buffer = CBuffer(
                             max_slots=num_slots.value,
                             max_objects=num_objects.value,
                             max_pointers=num_dataptrs.value,
-                            max_garbage=num_garbage.value)
+                            max_garbage=num_garbage.value,
+                        )
                     else:
                         output_buffer.reallocate(
                             max_slots=num_slots.value,
                             max_objects=num_objects.value,
                             max_pointers=num_dataptrs.value,
-                            max_garbage=num_garbage.value)
+                            max_garbage=num_garbage.value,
+                        )
 
                     if output_buffer is None:
                         raise ValueError("Could not provide output buffer")
 
                 self._output_buffer = output_buffer
-                self._ptr_c_output_buffer = \
-                    st.st_Buffer_new_mapped_on_cbuffer(output_buffer)
+                self._ptr_c_output_buffer = st.st_Buffer_new_mapped_on_cbuffer(
+                    output_buffer
+                )
                 if self._ptr_c_output_buffer == st.st_NullBuffer:
                     raise ValueError("Unable to map (optional) output buffer")
             else:
                 raise ValueError("Error pre-calculating out buffer params")
         elif output_buffer is not None:
             self._output_buffer = output_buffer
-            self._ptr_c_output_buffer = \
-                st.st_Buffer_new_mapped_on_cbuffer(self._output_buffer)
+            self._ptr_c_output_buffer = st.st_Buffer_new_mapped_on_cbuffer(
+                self._output_buffer
+            )
             if self._ptr_c_output_buffer == st.st_NullBuffer:
                 raise ValueError("Unable to map (optional) output buffer")
 
-        assert((needs_output_buffer and
-                self._ptr_c_output_buffer != st.st_NullBuffer) or
-               (not needs_output_buffer))
+        assert (
+            needs_output_buffer
+            and self._ptr_c_output_buffer != st.st_NullBuffer
+        ) or (not needs_output_buffer)
 
         if device is not None:
-            arch, device_id = device.split(':')
+            arch, device_id = device.split(":")
 
         arch = arch.strip().lower()
-        if not(stconf.SIXTRACKLIB_MODULES.get(arch, False) is not False or
-               arch == 'cpu'):
-            raise ValueError("Unknown architecture {0}".format(arch, ))
+        if not (
+            stconf.SIXTRACKLIB_MODULES.get(arch, False) is not False
+            or arch == "cpu"
+        ):
+            raise ValueError("Unknown architecture {0}".format(arch,))
+
+        self._arch = arch
 
         if device_id is not None:
             if config_str is None:
@@ -851,27 +1429,34 @@ def __init__(self,
         else:
             config_str = ""
 
-        arch = arch.encode('utf-8')
-        config_str = config_str.encode('utf-8')
+        _arch = string_to_encoded_ctypes_str(arch)
+        _config_str = string_to_encoded_ctypes_str(config_str)
 
         self.ptr_st_track_job = st.st_TrackJob_new_with_output(
-            ct.c_char_p(arch), self._ptr_c_particles_buffer,
-            self._ptr_c_beam_elements_buffer, self._ptr_c_output_buffer,
-            until_turn_elem_by_elem, ct.c_char_p(config_str))
+            _arch,
+            self._ptr_c_particles_buffer,
+            self._ptr_c_beam_elements_buffer,
+            self._ptr_c_output_buffer,
+            until_turn_elem_by_elem,
+            _config_str,
+        )
 
         if self.ptr_st_track_job == st.st_NullTrackJob:
-            raise ValueError('unable to construct TrackJob from arguments')
+            raise ValueError("unable to construct TrackJob from arguments")
 
     def __del__(self):
         if self.ptr_st_track_job != st.st_NullTrackJob:
             job_owns_output_buffer = st.st_TrackJob_owns_output_buffer(
-                self.ptr_st_track_job)
+                self.ptr_st_track_job
+            )
 
             st.st_TrackJob_delete(self.ptr_st_track_job)
             self.ptr_st_track_job = st.st_NullTrackJob
 
-            if job_owns_output_buffer and \
-                    self._ptr_c_output_buffer != st.st_NullBuffer:
+            if (
+                job_owns_output_buffer
+                and self._ptr_c_output_buffer != st.st_NullBuffer
+            ):
                 self._ptr_c_output_buffer = st.st_NullBuffer
 
         if self._ptr_c_particles_buffer != st.st_NullBuffer:
@@ -886,6 +1471,30 @@ def __del__(self):
             st.st_Buffer_delete(self._ptr_c_output_buffer)
             self._ptr_c_output_buffer = st.st_NullBuffer
 
+        if len(self._stored_buffers) > 0:
+            stored_buffer_ids = [ ii for ii in self._stored_buffers.keys() ]
+            for buffer_id in stored_buffer_ids:
+                if self._stored_buffers.get( buffer_id ) is None or \
+                   isinstance( self._stored_buffers[ buffer_id ], Buffer ) or \
+                   isinstance( self._stored_buffers[ buffer_id ], CBuffer ) or \
+                   isinstance( self._stored_buffers[ buffer_id ], CObject ):
+                    self._stored_buffers.pop( buffer_id )
+            if len( self._stored_buffers ) > 0:
+                raise RuntimeWarning(
+                    f"remaining stored buffers at destruction of trackjob: {self._stored_buffers.keys()}" )
+
+    @property
+    def last_status(self):
+        return self._last_status
+
+    @property
+    def last_track_status(self):
+        return self._last_track_status
+
+    @property
+    def arch(self):
+        return self._arch
+
     @property
     def output_buffer(self):
         return self._output_buffer
@@ -903,24 +1512,45 @@ def beam_elements_buffer(self):
         return self._beam_elements_buffer
 
     def track(self, until_turn):
-        warnings.warn("track(until_turn) is depreciated; " +
-                      "use track_until(until_turn) instead", DeprecationWarning)
+        warnings.warn(
+            "track(until_turn) is depreciated; "
+            + "use track_until(until_turn) instead",
+            DeprecationWarning,
+        )
         return self.track_until(until_turn)
 
     def track_until(self, until_turn):
-        return st.st_TrackJob_track_until(
-            self.ptr_st_track_job, ct.c_uint64(until_turn))
+        self._last_track_status = st.st_TrackJob_track_until(
+            self.ptr_st_track_job, ct.c_uint64(until_turn)
+        )
+        if self._last_track_status != st.st_TRACK_SUCCESS.value:
+            raise RuntimeError(
+                f"Error during performing track_until({until_turn})"
+            )
+        return self
 
     def track_elem_by_elem(self, until_turn):
-        return st.st_TrackJob_track_elem_by_elem(
-            self.ptr_st_track_job, ct.c_uint64(until_turn))
+        self._last_track_status = st.st_TrackJob_track_elem_by_elem(
+            self.ptr_st_track_job, ct.c_uint64(until_turn)
+        )
+        if self._last_track_status != st.st_TRACK_SUCCESS.value:
+            raise RuntimeError(
+                f"Error during performing track_elem_by_elem({until_turn})"
+            )
+        return self
 
     def track_line(self, begin_idx, end_idx, finish_turn=False):
-        return st.st_TrackJob_track_line(
+        self._last_track_status = st.st_TrackJob_track_line(
             self.ptr_st_track_job,
             ct.c_uint64(begin_idx),
             ct.c_uint64(end_idx),
-            ct.c_bool(finish_turn))
+            ct.c_bool(finish_turn),
+        )
+        if self._last_track_status != st.st_TRACK_SUCCESS.value:
+            raise RuntimeError(
+                f"Error during performing track_line({until_turn})"
+            )
+        return self
 
     def collect(self):
         st.st_TrackJob_collect(self.ptr_st_track_job)
@@ -954,19 +1584,48 @@ def _push_output(self):
 
     @property
     def can_fetch_particle_addresses(self):
-        return st.st_TrackJob_can_fetch_particle_addresses(
-            self.ptr_st_track_job)
+        return st.st_TrackJob_can_fetch_particles_addr(self.ptr_st_track_job)
 
     @property
     def has_particle_addresses(self):
-        return st.st_TrackJob_has_particle_addresses(self.ptr_st_track_job)
+        return st.st_TrackJob_has_particles_addr(self.ptr_st_track_job)
+
+    def fetch_particle_addresses(self):
+        last_status = st.st_TrackJob_fetch_particle_addresses(
+            self.ptr_st_track_job )
+        raise_error_if_status_not_success( last_status,
+            "unsuccessful fetching particle addresses op; " +
+            "status:{0}".format( last_status) )
+        return self
+
+    def clear_particle_addresses(self, particle_set_index=0):
+        last_status = st.st_TrackJob_clear_particle_addresses(
+            self.ptr_st_track_job, st_buffer_size_t(particle_set_index))
+        raise_error_if_status_not_success( last_status,
+            "unsuccessful clearing of particle addresses op; " +
+            "particle_set_index={0}, status:{1}".format(
+                particle_set_index, last_status))
+        return self
+
+    def clear_all_particle_addresses(self):
+        last_status = st.st_TrackJob_clear_all_particle_addresses(
+            self.ptr_st_track_job)
+        raise_error_if_status_not_success( last_status,
+            "unsuccessful clearing all particle addresses op; " +
+            "status:{0}".format(last_status))
+        return self
+
+    def get_particle_addresses(self, particle_set_index=0):
+        return st.st_TrackJob_particle_addresses(
+            self.ptr_st_track_job, st_buffer_size_t(particle_set_index))
 
     def type(self):
         return st.st_TrackJob_get_type_id(self.ptr_st_track_job)
 
     def type_str(self):
-        str = st.st_TrackJob_get_type_str(self.ptr_st_track_job)
-        return str.decode('utf-8')
+        return ctypes_str_to_decoded_string(
+            st_TrackJob_get_type_str(self.ptr_st_track_job)
+        )
 
     @property
     def arch_id(self):
@@ -974,8 +1633,9 @@ def arch_id(self):
 
     @property
     def arch_str(self):
-        str = st.st_TrackJob_get_type_str(self.ptr_st_track_job)
-        return str.decode('utf-8')
+        return ctypes_str_to_decoded_string(
+            st_TrackJob_get_type_str(self.ptr_st_track_job)
+        )
 
     @property
     def num_beam_monitors(self):
@@ -992,40 +1652,425 @@ def has_beam_monitor_output(self):
     @property
     def elem_by_elem_output_offset(self):
         return st.st_TrackJob_get_elem_by_elem_output_buffer_offset(
-            self.ptr_st_track_job)
+            self.ptr_st_track_job
+        )
 
     @property
     def beam_monitor_output_offset(self):
         return st.st_TrackJob_get_beam_monitor_output_buffer_offset(
-            self.ptr_st_track_job)
+            self.ptr_st_track_job
+        )
 
     @property
     def has_output_buffer(self):
-        return st.st_TrackJob_has_output_buffer(self.ptr_st_track_job) and \
-            bool(self._output_buffer is not None)
+        return st.st_TrackJob_has_output_buffer(
+            self.ptr_st_track_job
+        ) and bool(self._output_buffer is not None)
+
+    @property
+    def allows_add_program(self):
+        return self.arch_str() == "opencl"
+
+    @property
+    def allows_enable_kernel(self):
+        return self.arch_str() == "opencl"
+
+    @property
+    def has_stored_buffers(self):
+        return st.st_TrackJob_has_stored_buffers(self.ptr_st_track_job)
+
+    @property
+    def num_stored_buffers(self):
+        return st.st_TrackJob_num_stored_buffers(self.ptr_st_track_job)
+
+    @property
+    def min_stored_buffer_id(self):
+        return st.st_TrackJob_min_stored_buffer_id(self.ptr_st_track_job)
+
+    @property
+    def max_stored_buffer_id(self):
+        return st.st_TrackJob_max_stored_buffer_id(self.ptr_st_track_job)
+
+    @property
+    def controller(self):
+        if self.arch_str == "opencl" and SIXTRACKLIB_MODULES.get(
+            self.arch_str, False
+        ):
+            if self.ptr_st_track_job == st_NullTrackJob:
+                raise RuntimeError("TrackJob is not initialized yet")
+            return ClController(
+                ext_ptr_ctrl=st.st_TrackJobCl_get_context(
+                    self.ptr_st_track_job
+                ),
+                owns_ptr=False,
+            )
+        else:
+            raise RuntimeError(
+                "TrackJob has no controller for this architecture"
+            )
+        return None
+
+    def add_program(self, path_to_program_file, compile_options):
+        if not self.allows_add_program:
+            raise RuntimeError("Can not add a program to this TrackJob")
+        success = False
+        program_id = st.st_ARCH_ILLEGAL_PROGRAM_ID.value
+
+        if self.arch_str == "opencl" and SIXTRACKLIB_MODULES.get(
+            self.arch_str, False
+        ):
+            _controller = st.st_TrackJobCl_get_context(self.ptr_st_track_job)
+            program_id = st.st_ClContextBase_add_program_file(
+                _controller,
+                string_to_encoded_ctypes_str(path_to_program_file),
+                string_to_encoded_ctypes_str(compile_options),
+            )
+
+            if program_id != st.st_ARCH_ILLEGAL_PROGRAM_ID.value:
+                success = st.st_ClContextBase_compile_program(
+                    _controller, ct.c_uint32(program_id)
+                )
+                if not (success):
+                    program_id = st.st_ARCH_ILLEGAL_PROGRAM_ID.value
+            else:
+                raise RuntimeError("Unable to load program")
+
+        if program_id == st.st_ARCH_ILLEGAL_PROGRAM_ID.value:
+            raise RuntimeError("Unable to compile program")
+        return program_id
+
+    def enable_kernel(self, program_id, kernel_name):
+        if not self.allows_enable_kernel:
+            raise RuntimeError("Can not enable a kernel at this TrackJob")
+
+        if program_id == st.st_ARCH_ILLEGAL_PROGRAM_ID.value:
+            raise ValueError("Illegal program_id provided")
+
+        kernel_id = st.st_ARCH_ILLEGAL_KERNEL_ID.value
+
+        if self.arch_str == "opencl" and SIXTRACKLIB_MODULES.get(
+            self.arch_str, False
+        ):
+            _controller = st.st_TrackJobCl_get_context(self.ptr_st_track_job)
+            kernel_id = st.st_ClContextBase_enable_kernel(
+                _controller,
+                string_to_encoded_ctypes_str(kernel_name),
+                program_id,
+            )
+
+        if kernel_id == st.st_ARCH_ILLEGAL_KERNEL_ID.value:
+            raise RuntimeError("Unable to enable kernel")
+        return kernel_id
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    @property
+    def total_num_assign_items(self):
+        return st.st_TrackJob_total_num_assign_items(self.ptr_st_track_job)
+
+    def ptr_assign_address_item(
+        self,
+        item=None,
+        dest_elem_type_id=None,
+        dest_buffer_id=None,
+        dest_elem_index=None,
+        dest_pointer_offset=None,
+        src_elem_type_id=None,
+        src_buffer_id=None,
+        src_elem_index=None,
+        src_pointer_offset=None,
+        index=None,
+    ):
+        _ptr_found = st.st_NullAssignAddressItem
+        if not (item is None):
+            if isinstance(item, AssignAddressItem):
+                # TODO: Figure out a way to do this without relying on
+                #      internal API for cobjects
+                _ptr_found = st.st_TrackJob_ptr_assign_address_item(
+                    self.ptr_st_track_job,
+                    ct.cast(item._get_address(), st.st_AssignAddressItem_p),
+                )
+            elif item != st.st_NullAssignAddressItem:
+                _ptr_found = st.st_TrackJob_ptr_assign_address_item(
+                    self.ptr_st_track_job, item
+                )
+        elif not (dest_buffer_id is None) and not (src_buffer_id is None):
+            if not (index is None) and index >= 0:
+                _ptr_found = st.st_TrackJob_ptr_assign_address_item_by_index(
+                    self.ptr_st_track_job,
+                    st_buffer_size_t(dest_buffer_id),
+                    st_buffer_size_t(src_buffer_id),
+                    st_buffer_size_t(index),
+                )
+            elif (
+                not (dest_elem_type_id is None)
+                and not (dest_elem_index is None)
+                and not (dest_pointer_offset is None)
+                and not (src_elem_type_id is None)
+                and not (src_elem_index is None)
+                and not (src_pointer_offset is None)
+            ):
+                _ptr_found = st.st_TrackJob_ptr_assign_address_item_detailed(
+                    self.ptr_st_track_job,
+                    st_object_type_id_t(dest_elem_type_id),
+                    st_buffer_size_t(dest_buffer_id),
+                    st_buffer_size_t(dest_elem_index),
+                    st_buffer_size_t(dest_pointer_offset),
+                    st_object_type_id_t(src_elem_type_id),
+                    st_buffer_size_t(src_buffer_id),
+                    st_buffer_size_t(src_elem_index),
+                    st_buffer_size_t(src_pointer_offset),
+                )
+        return _ptr_found
+
+    def has_assign_items(self, dest_buffer_id, src_buffer_id):
+        return st.st_TrackJob_has_assign_items(
+            self.ptr_st_track_job,
+            st_buffer_size_t(dest_buffer_id),
+            st_buffer_size_t(src_buffer_id),
+        )
+
+    def num_assign_items(self, dest_buffer_id, src_buffer_id):
+        return st.st_TrackJob_num_assign_items(
+            self.ptr_st_track_job,
+            st_buffer_size_t(dest_buffer_id),
+            st_buffer_size_t(src_buffer_id),
+        )
+
+    def has_assign_item(
+        self,
+        item=None,
+        dest_buffer_id=None,
+        src_buffer_id=None,
+        index=None,
+        dest_elem_type_id=None,
+        dest_elem_index=None,
+        dest_pointer_offset=None,
+        src_elem_type_id=None,
+        src_elem_index=None,
+        src_pointer_offset=None,
+    ):
+        has_item = False
+        if not (item is None):
+            if isinstance(item, AssignAddressItem):
+                # TODO: Figure out a way to do this without relying on
+                #      internal API for cobjects
+                has_item = st.st_TrackJob_has_assign_address_item(
+                    self.ptr_st_track_job,
+                    ct.cast(item._get_address(), st.st_AssignAddressItem_p),
+                )
+            elif item != st.st_NullAssignAddressItem:
+                has_item = st.st_TrackJob_has_assign_address_item(
+                    self.ptr_st_track_job, item
+                )
+        elif not (dest_buffer_id is None) and not (src_buffer_id is None):
+            if not (index is None) and index >= 0:
+                has_item = st.st_TrackJob_has_assign_item_by_index(
+                    self.ptr_st_track_job,
+                    st_buffer_size_t(dest_buffer_id),
+                    st_buffer_size_t(src_buffer_id),
+                    st_buffer_size_t(index),
+                )
+            elif (
+                not (dest_elem_type_id is None)
+                and not (dest_elem_index is None)
+                and not (dest_pointer_offset is None)
+                and not (src_elem_type_id is None)
+                and not (src_elem_index is None)
+                and not (src_pointer_offset is None)
+            ):
+                has_item = st.st_TrackJob_has_assign_address_item_detailed(
+                    self.ptr_st_track_job,
+                    st_object_type_id_t(dest_elem_type_id),
+                    st_buffer_size_t(dest_buffer_id),
+                    st_buffer_size_t(dest_elem_index),
+                    st_buffer_size_t(dest_pointer_offset),
+                    st_object_type_id_t(src_elem_type_id),
+                    st_buffer_size_t(src_buffer_id),
+                    st_buffer_size_t(src_elem_index),
+                    st_buffer_size_t(src_pointer_offset),
+                )
+        return has_item
+
+    def index_of_assign_address_item(
+        self,
+        item=None,
+        dest_buffer_id=None,
+        src_buffer_id=None,
+        dest_elem_type_id=None,
+        dest_elem_index=None,
+        dest_pointer_offset=None,
+        src_elem_type_id=None,
+        src_elem_index=None,
+        src_pointer_offset=None,
+    ):
+        index_of_item = None
+        if not (item is None):
+            if isinstance(item, AssignAddressItem):
+                # TODO: Figure out a way to do this without relying on
+                #      internal API for cobjects
+                index_of_item = st.st_TrackJob_index_of_assign_address_item(
+                    self.ptr_st_track_job,
+                    ct.cast(item._get_address(), st.st_AssignAddressItem_p),
+                )
+            elif item != st.st_NullAssignAddressItem:
+                index_of_item = st.st_TrackJob_index_of_assign_address_item(
+                    self.ptr_st_track_job, item
+                )
+        elif (
+            not (dest_buffer_id is None)
+            and not (src_buffer_id is None)
+            and not (dest_elem_type_id is None)
+            and not (dest_elem_index is None)
+            and not (dest_pointer_offset is None)
+            and not (src_elem_type_id is None)
+            and not (src_elem_index is None)
+            and not (src_pointer_offset is None)
+        ):
+            index_of_item = st.st_TrackJob_index_of_assign_address_item_detailed(
+                self.ptr_st_track_job,
+                st_object_type_id_t(dest_elem_type_id),
+                st_buffer_size_t(dest_buffer_id),
+                st_buffer_size_t(dest_elem_index),
+                st_buffer_size_t(dest_pointer_offset),
+                st_object_type_id_t(src_elem_type_id),
+                st_buffer_size_t(src_buffer_id),
+                st_buffer_size_t(src_elem_index),
+                st_buffer_size_t(src_pointer_offset),
+            )
+        return index_of_item
+
+    def add_assign_address_item(
+        self,
+        item=None,
+        dest_elem_type_id=None,
+        dest_buffer_id=None,
+        dest_elem_index=None,
+        dest_pointer_offset=None,
+        src_elem_type_id=None,
+        src_buffer_id=None,
+        src_elem_index=None,
+        src_pointer_offset=None,
+    ):
+        ptr_added_item = st.st_NullAssignAddressItem
+        if not (item is None):
+            if isinstance(item, AssignAddressItem):
+                # TODO: Figure out a way to do this without relying on
+                #      internal API for cobjects
+                _ptr_item = ct.cast(
+                    item._get_address(), st.st_AssignAddressItem_p
+                )
+
+                ptr_added_item = st.st_TrackJob_add_assign_address_item(
+                    self.ptr_st_track_job, _ptr_item
+                )
+            elif item != st.st_NullAssignAddressItem:
+                ptr_added_item = st.st_TrackJob_add_assign_address_item(
+                    self.ptr_st_track_job, item
+                )
+        elif (
+            not (dest_elem_type_id is None)
+            and not (dest_buffer_id is None)
+            and not (dest_elem_index is None)
+            and not (dest_pointer_offset is None)
+            and not (src_elem_type_id is None)
+            and not (src_buffer_id is None)
+            and not (src_elem_index is None)
+            and not (src_pointer_offset is None)
+        ):
+            ptr_added_item = st.st_TrackJob_add_assign_address_item_detailed(
+                self.ptr_st_track_job,
+                st.st_object_type_id_t(dest_elem_type_id),
+                st_buffer_size_t(dest_buffer_id),
+                st_buffer_size_t(dest_elem_index),
+                st_buffer_size_t(dest_pointer_offset),
+                st.st_object_type_id_t(src_elem_type_id),
+                st_buffer_size_t(src_buffer_id),
+                st_buffer_size_t(src_elem_index),
+                st_buffer_size_t(src_pointer_offset),
+            )
+
+        if ptr_added_item == st.st_NullAssignAddressItem:
+            raise ValueError(
+                "unable to add AssignAddressItem given by these parameters"
+            )
+        return ptr_added_item
+
+    def commit_address_assignments(self):
+        self._last_status = st.st_TrackJob_commit_address_assignments(
+            self.ptr_st_track_job
+        )
+
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError("Unable to commit address assignment items")
+
+        return self
+
+    def assign_all_addresses(self):
+        self._last_status = st.st_TrackJob_assign_all_addresses(
+            self.ptr_st_track_job
+        )
+
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError(
+                "Unable to perform assignment of all address items"
+            )
+
+        return self
+
+    def assign_addresses(self, dest_buffer_id, src_buffer_id):
+        if dest_buffer_id is None and src_buffer_id is None:
+            self._last_status = st.st_TrackJob_assign_all_addresses(
+                self.ptr_st_track_job
+            )
+        elif not (dest_buffer_id is None) and not (src_buffer_id is None):
+            self._last_status = st.st_TrackJob_assign_addresses(
+                self.ptr_st_track_job,
+                st_buffer_size_t(dest_buffer_id),
+                st_buffer_size_t(src_buffer_id),
+            )
+        else:
+            raise ValueError(
+                "inconsistent dest_buffer_id and src_buffer_id parameters"
+            )
+            self._last_status = st_ARCH_STATUS_GENERAL_FAILURE.value
 
-    def reset(self, beam_elements_buffer, particles_buffer,
-              until_turn_elem_by_elem=0, output_buffer=None):
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError("Unable to perform assignment of address items")
+        return self
+
+    # --------------------------------------------------------------------------
+
+    def reset(
+        self,
+        beam_elements_buffer,
+        particles_buffer,
+        until_turn_elem_by_elem=0,
+        output_buffer=None,
+    ):
         _new_ptr_c_particles_buffer = st.st_NullBuffer
         _new_ptr_c_beam_elements_buffer = st.st_NullBuffer
         _new_ptr_c_output_buffer = st.st_NullBuffer
 
         if particles_buffer is not None:
-            particles_buffer = _get_buffer(particles_buffer)
-            _new_ptr_c_particles_buffer = \
-                st.st_Buffer_new_mapped_on_cbuffer(particles_buffer)
+            particles_buffer = get_cbuffer_from_obj(particles_buffer)
+            _new_ptr_c_particles_buffer = st.st_Buffer_new_mapped_on_cbuffer(
+                particles_buffer
+            )
             if _new_ptr_c_particles_buffer == st.st_NullBuffer:
                 raise ValueError("Issues with input particles buffer")
 
         if beam_elements_buffer is not None:
-            beam_elements_buffer = _get_buffer(beam_elements_buffer)
-            _new_ptr_c_beam_elements_buffer = \
-                st.st_Buffer_new_mapped_on_cbuffer(beam_elements_buffer)
+            beam_elements_buffer = get_cbuffer_from_obj(beam_elements_buffer)
+            _new_ptr_c_beam_elements_buffer = st.st_Buffer_new_mapped_on_cbuffer(
+                beam_elements_buffer
+            )
             if _new_ptr_c_beam_elements_buffer == st.st_NullBuffer:
                 raise ValueError("Issues with input beam elements buffer")
 
         particles = st.st_Particles_buffer_get_particles(
-            _new_ptr_c_particles_buffer, 0)
+            _new_ptr_c_particles_buffer, 0
+        )
 
         if particles == st.st_NullParticles:
             raise ValueError("Required particle sets not available")
@@ -1033,10 +2078,12 @@ def reset(self, beam_elements_buffer, particles_buffer,
         until_turn_elem_by_elem = ct.c_uint64(until_turn_elem_by_elem)
 
         out_buffer_flags = st.st_OutputBuffer_required_for_tracking(
-            particles, _new_ptr_c_beam_elements_buffer, until_turn_elem_by_elem)
+            particles, _new_ptr_c_beam_elements_buffer, until_turn_elem_by_elem
+        )
 
         needs_output_buffer = st.st_OutputBuffer_requires_output_buffer(
-            ct.c_int32(out_buffer_flags))
+            ct.c_int32(out_buffer_flags)
+        )
 
         if needs_output_buffer:
             num_objects = ct.c_uint64(0)
@@ -1046,52 +2093,68 @@ def reset(self, beam_elements_buffer, particles_buffer,
             slot_size = st.st_Buffer_get_slot_size(_new_ptr_c_particles_buffer)
 
             ret = st.st_OutputBuffer_calculate_output_buffer_params(
-                _new_ptr_c_beam_elements_buffer, particles,
-                until_turn_elem_by_elem, ct.byref(num_objects),
-                ct.byref(num_slots), ct.byref(num_dataptrs),
-                ct.byref(num_garbage), slot_size)
+                _new_ptr_c_beam_elements_buffer,
+                particles,
+                until_turn_elem_by_elem,
+                ct.byref(num_objects),
+                ct.byref(num_slots),
+                ct.byref(num_dataptrs),
+                ct.byref(num_garbage),
+                slot_size,
+            )
 
             if ret == 0:
-                if num_objects.value > 0 and num_slots.value > 0 and \
-                        num_dataptrs.value > 0 and num_garbage.value >= 0:
+                if (
+                    num_objects.value > 0
+                    and num_slots.value > 0
+                    and num_dataptrs.value > 0
+                    and num_garbage.value >= 0
+                ):
                     if output_buffer is None:
                         output_buffer = CBuffer(
                             max_slots=num_slots.value,
                             max_objects=num_objects.value,
                             max_pointers=num_dataptrs.value,
-                            max_garbage=num_garbage.value)
+                            max_garbage=num_garbage.value,
+                        )
                     else:
                         output_buffer.reallocate(
                             max_slots=num_slots.value,
                             max_objects=num_objects.value,
                             max_pointers=num_dataptrs.value,
-                            max_garbage=num_garbage.value)
+                            max_garbage=num_garbage.value,
+                        )
 
                     if output_buffer is None:
                         raise ValueError("Could not provide output buffer")
 
-                _new_ptr_c_output_buffer = \
-                    st.st_Buffer_new_mapped_on_cbuffer(output_buffer)
+                _new_ptr_c_output_buffer = st.st_Buffer_new_mapped_on_cbuffer(
+                    output_buffer
+                )
                 if _new_ptr_c_output_buffer == st.st_NullBuffer:
                     raise ValueError("Unable to map (optional) output buffer")
             else:
                 raise ValueError("Error pre-calculating out buffer params")
         elif output_buffer is not None:
-            _new_ptr_c_output_buffer = \
-                st.st_Buffer_new_mapped_on_cbuffer(output_buffer)
+            _new_ptr_c_output_buffer = st.st_Buffer_new_mapped_on_cbuffer(
+                output_buffer
+            )
             if _new_ptr_c_output_buffer == st.st_NullBuffer:
                 raise ValueError("Unable to map (optional) output buffer")
 
-        if self.ptr_st_track_job != st.st_NullTrackJob and \
-                _new_ptr_c_particles_buffer != st_NullBuffer and \
-                _new_ptr_c_beam_elements_buffer != st_NullBuffer:
+        if (
+            self.ptr_st_track_job != st.st_NullTrackJob
+            and _new_ptr_c_particles_buffer != st_NullBuffer
+            and _new_ptr_c_beam_elements_buffer != st_NullBuffer
+        ):
 
             if st.st_TrackJob_reset_with_output(
-                    self.ptr_st_track_job,
-                    _new_ptr_c_particles_buffer,
-                    _new_ptr_c_beam_elements_buffer,
-                    _new_ptr_c_output_buffer,
-                    until_turn_elem_by_elem):
+                self.ptr_st_track_job,
+                _new_ptr_c_particles_buffer,
+                _new_ptr_c_beam_elements_buffer,
+                _new_ptr_c_output_buffer,
+                until_turn_elem_by_elem,
+            ):
 
                 if self._ptr_c_particles_buffer != st.st_NullBuffer:
                     st.st_Buffer_delete(self._ptr_c_particles_buffer)
@@ -1101,7 +2164,9 @@ def reset(self, beam_elements_buffer, particles_buffer,
                 if self._ptr_c_beam_elements_buffer != st.st_NullBuffer:
                     st.st_Buffer_delete(self._ptr_c_beam_elements_buffer)
                     self._beam_elements_buffer = beam_elements_buffer
-                    self._ptr_c_beam_elements_buffer = _new_ptr_c_beam_elements_buffer
+                    self._ptr_c_beam_elements_buffer = (
+                        _new_ptr_c_beam_elements_buffer
+                    )
 
                 if self._output_buffer is not None:
                     del self._output_buffer
@@ -1121,4 +2186,123 @@ def reset(self, beam_elements_buffer, particles_buffer,
 
         return self
 
-# end: python/sixtracklib/trackjob.py
+    @property
+    def opencl_context_addr(self):
+        return 0 if self._arch != "opencl" else \
+            st.st_TrackJobCl_get_opencl_context_addr( self.ptr_st_track_job )
+
+    @property
+    def opencl_queue_addr(self):
+        return 0 if self._arch != "opencl" else \
+            st.st_TrackJobCl_get_opencl_queue_addr( self.ptr_st_track_job )
+    # -------------------------------------------------------------------------
+
+    def add_stored_buffer(
+        self,
+        cbuffer=None,
+        size=None,
+        ptr_c_buffer=None,
+        take_ownership=False,
+        delete_ptr_after_move=False,
+    ):
+        _st_buffer = None
+        buffer_id = st.st_ARCH_ILLEGAL_BUFFER_ID.value
+        if not (cbuffer is None):
+            _st_buffer = Buffer.from_cbuffer(cbuffer)
+        elif not (size is None) and size > 0:
+            _st_buffer = Buffer(size=size)
+        elif not (ptr_c_buffer is None) and ptr_c_buffer != st_NullBuffer:
+            owns_buffer = take_ownership
+            owns_pointer = take_ownership and delete_ptr_after_move
+            _st_buffer = Buffer(
+                ptr_ext_buffer=ptr_c_buffer,
+                owns_buffer=owns_buffer,
+                owns_pointer=owns_pointer,
+            )
+        if not (_st_buffer is None) and _st_buffer.pointer != st_NullBuffer:
+            buffer_id = st.st_TrackJob_add_stored_buffer(
+                self.ptr_st_track_job,
+                _st_buffer.pointer,
+                ct.c_bool(False),
+                ct.c_bool(False),
+            )
+            if buffer_id != st.st_ARCH_ILLEGAL_BUFFER_ID.value:
+                assert buffer_id not in self._stored_buffers
+                self._stored_buffers[buffer_id] = _st_buffer
+        return buffer_id
+
+    def remove_stored_buffer(self, buffer_id):
+        return st.st_TrackJob_remove_stored_buffer(
+            self.ptr_st_track_job, st_arch_size_t(buffer_id)
+        )
+
+    def owns_stored_buffer(self, buffer_id):
+        return st.st_TrackJob_owns_stored_buffer(
+            self.ptr_st_track_job, st_arch_size_t(buffer_id)
+        )
+
+    @property
+    def stored_buffer_is_cbuffer(self, buffer_id):
+        return (
+            buffer_id in self._stored_buffers
+            and self._stored_buffers[buffer_id].maps_to_cbuffer
+        )
+
+    def stored_buffer_cbuffer(self, buffer_id):
+        if not self.stored_buffer_is_cbuffer:
+            raise RuntimeError(
+                f"Unable to retrieve CBuffer for buffer_id={buffer_id}"
+            )
+        return self._stored_buffers[buffer_id].cbuffer
+
+    def ptr_stored_buffer(self, buffer_id):
+        return st.st_TrackJob_stored_buffer(
+            self.ptr_st_track_job, st_arch_size_t(buffer_id)
+        )
+
+    def stored_buffer(self, buffer_id):
+        return self._stored_buffers.get(buffer_id, None)
+
+    def push_stored_buffer(self, buffer_id):
+        self._last_status = st.st_TrackJob_push_stored_buffer(
+            self.ptr_st_track_job, st_buffer_size_t(buffer_id)
+        )
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError(f"Unable to push stored buffer {buffer_id}")
+        return self
+
+    def collect_stored_buffer(self, buffer_id):
+        self._last_status = st.st_TrackJob_collect_stored_buffer(
+            self.ptr_st_track_job, st_buffer_size_t(buffer_id)
+        )
+        if self._last_status != st_ARCH_STATUS_SUCCESS.value:
+            raise RuntimeError(f"Unable to collect stored buffer {buffer_id}")
+        return self
+
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    def argument_by_buffer_id(self, buffer_id):
+        ptr_arg = st.st_NullClArgument.value
+        if self.arch_str == "opencl":
+            ptr_arg = st.st_TrackJobCl_argument_by_buffer_id(
+                self.ptr_st_track_job, st_buffer_size_t(buffer_id)
+            )
+        else:
+            arch_str = self.arch_str
+            raise RuntimeError(
+                f"unable to get argument for buffer on arch {arch_str}"
+            )
+        return ptr_arg
+
+    def stored_buffer_argument(self, buffer_id):
+        ptr_arg = st.st_NullClArgument.value
+        if self.arch_str == "opencl":
+            ptr_arg = st.st_TrackJobCl_stored_buffer_argument(
+                self.ptr_st_track_job, st_buffer_size_t(buffer_id)
+            )
+        else:
+            arch_str = self.arch_str
+            raise RuntimeError(
+                f"unable to get argument for stored buffer on arch {arch_str}"
+            )
+        return ptr_arg
diff --git a/python/sixtracklib/tricub.py b/python/sixtracklib/tricub.py
new file mode 100644
index 00000000..b73b4021
--- /dev/null
+++ b/python/sixtracklib/tricub.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import numpy as np
+from cobjects import CBuffer, CObject, CField
+
+from .trackjob import TrackJob
+from .beam_elements import Elements
+from .buffer import AssignAddressItem, get_cbuffer_from_obj, Buffer
+from .stcommon import (
+    st_ARCH_ILLEGAL_BUFFER_ID,
+    st_ARCH_BEAM_ELEMENTS_BUFFER_ID,
+    st_NullTriCubData,
+    st_TriCubData_type_id,
+    st_TriCubData_ptr_offset,
+    st_NullTriCub,
+    st_TriCub_type_id,
+    st_TriCub_data_addr_offset,
+)
+
+class TriCubData(CObject):
+    _typeid = st_TriCubData_type_id(st_NullTriCubData)
+    x0 = CField(0, "real", default=0.0, alignment=8)
+    dx = CField(1, "real", default=0.0, alignment=8)
+    nx = CField(2, "int64", default=0, alignment=8, const=True)
+    y0 = CField(3, "real", default=0.0, alignment=8)
+    dy = CField(4, "real", default=0.0, alignment=8)
+    ny = CField(5, "int64", default=0, alignment=8, const=True)
+    z0 = CField(6, "real", default=0.0, alignment=8)
+    dz = CField(7, "real", default=0.0, alignment=8)
+    nz = CField(8, "int64", default=0, alignment=8, const=True)
+    mirror_x = CField(9, "int64", default=0.0, alignment=8)
+    mirror_y = CField(10, "int64", default=0.0, alignment=8)
+    mirror_z = CField(11, "int64", default=0.0, alignment=8)
+    table_addr = CField(
+        12,
+        "real",
+        default=0,
+        pointer=True,
+        length="nx * ny * nz * 8",
+        alignment=8,
+    )
+
+    def __init__(self, nx=0, ny=0, nz=0, **kwargs):
+        super().__init__(nx=nx, ny=ny, nz=nz, **kwargs)
+
+    @staticmethod
+    def ptr_offset():
+        return 0
+
+class TriCub(CObject):
+    _typeid = st_TriCub_type_id(st_NullTriCub)
+    x_shift = CField(0, "real", default=0.0, alignment=8)
+    y_shift = CField(1, "real", default=0.0, alignment=8)
+    tau_shift = CField(2, "real", default=0.0, alignment=8)
+    dipolar_kick_px = CField(3, "real", default=0.0, alignment=8)
+    dipolar_kick_py = CField(4, "real", default=0.0, alignment=8)
+    dipolar_kick_ptau = CField(5, "real", default=0.0, alignment=8)
+    length = CField(6, "real", default=0.0, alignment=8)
+    data_addr = CField(7, "uint64", default=0, alignment=8)
+
+    @staticmethod
+    def data_addr_offset():
+        return st_TriCub_data_addr_offset(st_NullTriCub)
+
+
+def TriCub_buffer_create_assign_address_item(
+    track_job, be_tricub_index, tricub_data_buffer_id, tricub_data_index
+):
+    assert isinstance(track_job, TrackJob)
+    assert tricub_data_buffer_id != st_ARCH_ILLEGAL_BUFFER_ID.value
+    assert track_job.min_stored_buffer_id <= tricub_data_buffer_id
+    assert track_job.max_stored_buffer_id >= tricub_data_buffer_id
+    assert (
+        track_job.stored_buffer(tricub_data_buffer_id).num_objects
+        > tricub_data_index
+    )
+
+    dest_buffer_id = st_ARCH_BEAM_ELEMENTS_BUFFER_ID.value
+    src_buffer_id = tricub_data_buffer_id
+
+    prev_num_assign_items = track_job.num_assign_items(
+        dest_buffer_id=dest_buffer_id, src_buffer_id=src_buffer_id
+    )
+
+    _ptr_item = track_job.add_assign_address_item(
+        dest_elem_type_id=TriCub._typeid,
+        dest_buffer_id=dest_buffer_id,
+        dest_elem_index=be_tricub_index,
+        dest_pointer_offset=TriCub.data_addr_offset(),
+        src_elem_type_id=TriCubData._typeid,
+        src_buffer_id=src_buffer_id,
+        src_elem_index=tricub_data_index,
+        src_pointer_offset=TriCubData.ptr_offset(),
+    )
+
+    if prev_num_assign_items < track_job.num_assign_items(
+        dest_buffer_id=dest_buffer_id, src_buffer_id=src_buffer_id
+    ):
+        return True
+
+    return False
diff --git a/python/sixtracklib_test/generic_obj.py b/python/sixtracklib_test/generic_obj.py
index 28bb718f..5b59202f 100644
--- a/python/sixtracklib_test/generic_obj.py
+++ b/python/sixtracklib_test/generic_obj.py
@@ -7,16 +7,18 @@
 
 class GenericObj(CObject):
     _typeid = 99999
-    type_id = CField(0, 'int64', default=_typeid, alignment=8)
-    a = CField(1, 'int32', default=0, alignment=8)
-    b = CField(2, 'real', default=0.0, alignment=8)
-    c = CField(3, 'real', length=4, default=0.0, alignment=8)
-    num_d = CField(4, 'uint64', const=True, default=0, alignment=8)
-    d = CField(5, 'uint8', default=0, pointer=True,
-               length='num_d', alignment=8)
-    num_e = CField(6, 'uint64', const=True, default=0, alignment=8)
-    e = CField(7, 'real', default=0.0, pointer=True,
-               length='num_e', alignment=8)
+    type_id = CField(0, "int64", default=_typeid, alignment=8)
+    a = CField(1, "int32", default=0, alignment=8)
+    b = CField(2, "real", default=0.0, alignment=8)
+    c = CField(3, "real", length=4, default=0.0, alignment=8)
+    num_d = CField(4, "uint64", const=True, default=0, alignment=8)
+    d = CField(
+        5, "uint8", default=0, pointer=True, length="num_d", alignment=8
+    )
+    num_e = CField(6, "uint64", const=True, default=0, alignment=8)
+    e = CField(
+        7, "real", default=0.0, pointer=True, length="num_e", alignment=8
+    )
 
     def __init__(self, num_d=0, num_e=0, d=None, e=None, **kwargs):
         in_d_len = d is not None and d and len(d) or 0
@@ -24,11 +26,11 @@ def __init__(self, num_d=0, num_e=0, d=None, e=None, **kwargs):
 
         d_len = max(num_d, in_d_len)
 
-        if d is None or not(d and len(d) > 0):
-            d = np.zeros(d_len, dtype=np.dtype('uint8'))
+        if d is None or not (d and len(d) > 0):
+            d = np.zeros(d_len, dtype=np.dtype("uint8"))
         elif d and len(d) > 0:
-            _d = np.zeros(d_len, dtype=np.dtype('uint8'))
-            _d[:len(d)] = d
+            _d = np.zeros(d_len, dtype=np.dtype("uint8"))
+            _d[: len(d)] = d
             d = _d
 
         if d is not None and len(d) == d_len:
@@ -36,11 +38,11 @@ def __init__(self, num_d=0, num_e=0, d=None, e=None, **kwargs):
 
         e_len = max(num_e, in_e_len)
 
-        if e is None or not(e and len(e) > 0):
-            e = np.zeros(e_len, dtype=np.dtype('float64'))
+        if e is None or not (e and len(e) > 0):
+            e = np.zeros(e_len, dtype=np.dtype("float64"))
         elif e and len(e) > 0:
-            _e = np.zeros(e_len, dtype=np.dtype('float64'))
-            _e[:len(e)] = e
+            _e = np.zeros(e_len, dtype=np.dtype("float64"))
+            _e[: len(e)] = e
             e = _e
 
         if e is not None and len(e) == e_len:
diff --git a/python/sixtracklib_test/stcommon.py b/python/sixtracklib_test/stcommon.py
index 48781d83..1e5bbaf0 100644
--- a/python/sixtracklib_test/stcommon.py
+++ b/python/sixtracklib_test/stcommon.py
@@ -4,30 +4,30 @@
 import ctypes as ct
 from . import config as stconf
 from sixtracklib.particles import Particles as st_Particles
-import sixtracklib.stcommon as pyst
+import sixtracklib.stcommon as stcom
 
 testlib = ct.CDLL(stconf.SHARED_LIB)
 
 # C-API Types
 
-st_Null = pyst.st_Null
-st_NullChar = pyst.st_NullChar
+st_Null = stcom.st_Null
+st_NullChar = stcom.st_NullChar
 
-st_uint64_p = pyst.st_uint64_p
-st_uchar_p = pyst.st_uchar_p
+st_uint64_p = stcom.st_uint64_p
+st_uchar_p = stcom.st_uchar_p
 
-st_double_p = pyst.st_double_p
-st_int64_p = pyst.st_int64_p
+st_double_p = stcom.st_double_p
+st_int64_p = stcom.st_int64_p
 
-st_Buffer = pyst.st_Buffer
-st_Buffer_p = pyst.st_Buffer_p
+st_Buffer = stcom.st_Buffer
+st_Buffer_p = stcom.st_Buffer_p
 
 # -----------------------------------------------------------------------------
 # Particles realted functions and definitions
 
-st_Particles = pyst.st_Particles
-st_Particles_p = pyst.st_Particles_p
-st_NullParticles = pyst.st_NullParticles
+st_Particles = stcom.st_Particles
+st_Particles_p = stcom.st_Particles_p
+st_NullParticles = stcom.st_NullParticles
 
 
 st_Particles_realistic_init = testlib.st_Particles_realistic_init
@@ -55,18 +55,21 @@
 st_Particles_compare_real_values.argtypes = [st_Particles_p, st_Particles_p]
 
 
-st_Particles_compare_real_values_with_treshold = \
+st_Particles_compare_real_values_with_treshold = (
     testlib.st_Particles_compare_real_values_with_treshold_ext
+)
 st_Particles_compare_real_values_with_treshold.restype = ct.c_int32
 st_Particles_compare_real_values_with_treshold.argtypes = [
-    st_Particles_p, st_Particles_p]
+    st_Particles_p,
+    st_Particles_p,
+]
 
 
-st_Particles_compare_integer_values = \
+st_Particles_compare_integer_values = (
     testlib.st_Particles_compare_integer_values_ext
+)
 st_Particles_compare_integer_values.restype = ct.c_int32
-st_Particles_compare_integer_values.argtypes = [
-    st_Particles_p, st_Particles_p]
+st_Particles_compare_integer_values.argtypes = [st_Particles_p, st_Particles_p]
 
 
 st_Particles_compare_values = testlib.st_Particles_compare_values_ext
@@ -74,11 +77,15 @@
 st_Particles_compare_values.restypes = ct.c_int32
 
 
-st_Particles_compare_values_with_treshold = \
+st_Particles_compare_values_with_treshold = (
     testlib.st_Particles_compare_values_with_treshold_ext
+)
 st_Particles_compare_values_with_treshold.restype = ct.c_int32
 st_Particles_compare_values_with_treshold.argtypes = [
-    st_Particles_p, st_Particles_p, ct.c_double]
+    st_Particles_p,
+    st_Particles_p,
+    ct.c_double,
+]
 
 
 st_Particles_print_out_single = testlib.st_Particles_print_out_single_ext
@@ -91,29 +98,36 @@
 st_Particles_print_out.argtypes = [st_Particles_p]
 
 
-st_Particles_buffers_map_to_same_memory = \
+st_Particles_buffers_map_to_same_memory = (
     testlib.st_Particles_buffers_map_to_same_memory
+)
 st_Particles_buffers_map_to_same_memory.restype = ct.c_bool
 st_Particles_buffers_map_to_same_memory.argtypes = [st_Buffer_p, st_Buffer_p]
 
 
-st_Particles_buffer_have_same_structure = \
+st_Particles_buffer_have_same_structure = (
     testlib.st_Particles_buffer_have_same_structure
+)
 st_Particles_buffer_have_same_structure.restype = ct.c_bool
 st_Particles_buffer_have_same_structure.argtypes = [st_Buffer_p, st_Buffer_p]
 
 
-st_Particles_buffers_compare_values = \
+st_Particles_buffers_compare_values = (
     testlib.st_Particles_buffers_compare_values
+)
 st_Particles_buffers_compare_values.restype = ct.c_int32
 st_Particles_buffers_compare_values.argtypes = [st_Buffer_p, st_Buffer_p]
 
 
-st_Particles_buffers_compare_values_with_treshold = \
+st_Particles_buffers_compare_values_with_treshold = (
     testlib.st_Particles_buffers_compare_values_with_treshold
+)
 st_Particles_buffers_compare_values.restype = ct.c_int32
 st_Particles_buffers_compare_values.argtypes = [
-    st_Buffer_p, st_Buffer_p, ct.c_double]
+    st_Buffer_p,
+    st_Buffer_p,
+    ct.c_double,
+]
 
 
 st_Particles_buffer_print_out = testlib.st_Particles_buffer_print_out
@@ -123,15 +137,29 @@
 # -----------------------------------------------------------------------------
 # ParticlesAddr realted functions and definitions
 
-st_ParticlesAddr = pyst.st_ParticlesAddr
-st_ParticlesAddr_p = pyst.st_ParticlesAddr_p
-st_NullParticlesAddr = pyst.st_NullParticlesAddr
+st_ParticlesAddr = stcom.st_ParticlesAddr
+st_ParticlesAddr_p = stcom.st_ParticlesAddr_p
+st_NullParticlesAddr = stcom.st_NullParticlesAddr
 
-st_buffer_size_t = pyst.st_buffer_size_t
+st_buffer_size_t = stcom.st_buffer_size_t
 
-st_TestParticlesAddr_are_addresses_consistent_with_particle = \
+st_TestParticlesAddr_are_addresses_consistent_with_particle = (
     testlib.st_TestParticlesAddr_are_addresses_consistent_with_particle
+)
 st_TestParticlesAddr_are_addresses_consistent_with_particle.argtypes = [
-    st_ParticlesAddr_p, st_Particles_p, st_buffer_size_t]
-st_TestParticlesAddr_are_addresses_consistent_with_particle.restype = \
-    ct.c_bool
+    st_ParticlesAddr_p,
+    st_Particles_p,
+    st_buffer_size_t,
+]
+st_TestParticlesAddr_are_addresses_consistent_with_particle.restype = ct.c_bool
+
+# -------------------------------------------------------------------------------
+# AssignAddressItem:
+
+st_AssignAddressItem = stcom.st_AssignAddressItem
+st_AssignAddressItem_p = stcom.st_AssignAddressItem_p
+st_NullAssignAddressItem = stcom.st_NullAssignAddressItem
+
+st_AssignAddressItem_print_out = testlib.st_AssignAddressItem_print_out_ext
+st_AssignAddressItem_print_out.argtypes = [st_AssignAddressItem_p]
+st_AssignAddressItem_print_out.restype = None
diff --git a/python/sixtracklib_test/testdata.py b/python/sixtracklib_test/testdata.py
index bbead7c4..cc277a14 100644
--- a/python/sixtracklib_test/testdata.py
+++ b/python/sixtracklib_test/testdata.py
@@ -9,12 +9,23 @@
 import pysixtrack as pysix
 from pysixtrack.particles import Particles as pysix_Particle
 
-from pysixtrack.elements import Drift, DriftExact, Multipole, XYShift, \
-    SRotation, Cavity, RFMultipole, BeamBeam4D, BeamBeam6D, BeamMonitor
-
-
-def line_from_beam_elem_buffer_pysixtrack(beam_elements_buffer,
-                                          skip_unknown=False):
+from pysixtrack.elements import (
+    Drift,
+    DriftExact,
+    Multipole,
+    XYShift,
+    SRotation,
+    Cavity,
+    RFMultipole,
+    BeamBeam4D,
+    BeamBeam6D,
+    BeamMonitor,
+)
+
+
+def line_from_beam_elem_buffer_pysixtrack(
+    beam_elements_buffer, skip_unknown=False
+):
     line = []
     num_elements = beam_elements_buffer.n_objects
     for ii in range(num_elements):
@@ -31,18 +42,19 @@ def line_from_beam_elem_buffer_pysixtrack(beam_elements_buffer,
 
 
 def track_particle_pysixtrack(
-        particle,
-        line,
-        until_turn_elem_by_elem,
-        until_turn_turn_by_turn,
-        until_turn=0,
-        skip_turns=1):
+    particle,
+    line,
+    until_turn_elem_by_elem,
+    until_turn_turn_by_turn,
+    until_turn=0,
+    skip_turns=1,
+):
     output_elem_by_elem = []
     output_turn_by_turn = []
     output_turns = []
 
-    while(particle.turn < until_turn_elem_by_elem):
-        assert(particle.elemid == 0)
+    while particle.turn < until_turn_elem_by_elem:
+        assert particle.elemid == 0
         for elem in line:
             output_elem_by_elem.append(particle.copy())
             elem.track(particle)
@@ -50,8 +62,8 @@ def track_particle_pysixtrack(
         particle.turn += 1
         particle.elemid = 0
 
-    while(particle.turn < until_turn_turn_by_turn):
-        assert(particle.elemid == 0)
+    while particle.turn < until_turn_turn_by_turn:
+        assert particle.elemid == 0
         for elem in line:
             elem.track(particle)
             particle.elemid += 1
@@ -60,8 +72,8 @@ def track_particle_pysixtrack(
         particle.elemid = 0
 
     out_turns_tracked = 0
-    while(particle.turn < until_turn):
-        assert(particle.elemid == 0)
+    while particle.turn < until_turn:
+        assert particle.elemid == 0
         for elem in line:
             elem.track(particle)
             particle.elemid += 1
@@ -76,13 +88,14 @@ def track_particle_pysixtrack(
 
 
 def track_particles_pysixtrack(
-        input_particles,
-        line,
-        until_turn_elem_by_elem,
-        until_turn_turn_by_turn,
-        until_turn=0,
-        skip_turns=1,
-        output_buffer=None):
+    input_particles,
+    line,
+    until_turn_elem_by_elem,
+    until_turn_turn_by_turn,
+    until_turn=0,
+    skip_turns=1,
+    output_buffer=None,
+):
 
     num_particles = input_particles.num_particles
     num_beam_elements = len(line)
@@ -99,7 +112,7 @@ def track_particles_pysixtrack(
         if max_particle_id < input_particles.particle_id[ii]:
             max_particle_id = input_particles.particle_id[ii]
 
-    nn = (max_particle_id - min_particle_id + 1)
+    nn = max_particle_id - min_particle_id + 1
     num_particles_per_turn = nn * num_beam_elements
 
     if output_buffer is None:
@@ -107,28 +120,32 @@ def track_particles_pysixtrack(
 
     if initial_at_turn < until_turn_elem_by_elem:
         num_particles_to_store = num_particles_per_turn * (
-            until_turn_elem_by_elem - initial_at_turn)
+            until_turn_elem_by_elem - initial_at_turn
+        )
 
-        out = st_Particles(num_particles=num_particles_to_store,
-                           cbuffer=output_buffer)
+        out = st_Particles(
+            num_particles=num_particles_to_store, cbuffer=output_buffer
+        )
 
         for ii in range(num_particles):
             particle = pysix_Particle()
             input_particles.to_pysixtrack(particle, ii)
 
-            assert(particle.partid >= min_particle_id)
-            assert(particle.partid <= max_particle_id)
-            assert(particle.turn >= initial_at_turn)
-            assert(particle.turn < until_turn_elem_by_elem)
+            assert particle.partid >= min_particle_id
+            assert particle.partid <= max_particle_id
+            assert particle.turn >= initial_at_turn
+            assert particle.turn < until_turn_elem_by_elem
             delta_part_id = particle.partid - min_particle_id
 
             while particle.turn < until_turn_elem_by_elem:
-                assert(particle.elemid == 0)
-                offset = num_beam_elements * nn * (
-                    particle.turn - initial_at_turn)
+                assert particle.elemid == 0
+                offset = (
+                    num_beam_elements * nn * (particle.turn - initial_at_turn)
+                )
                 for elem in line:
                     out.from_pysixtrack(
-                        particle, offset + particle.elemid * nn + delta_part_id)
+                        particle, offset + particle.elemid * nn + delta_part_id
+                    )
                     elem.track(particle)
                     particle.elemid += 1
                 particle.turn += 1
@@ -140,27 +157,29 @@ def track_particles_pysixtrack(
     if start_turn_by_turn < until_turn_turn_by_turn:
         max_num_turns_to_store = until_turn_turn_by_turn - start_turn_by_turn
         num_particles_to_store = nn * max_num_turns_to_store
-        out = st_Particles(num_particles=num_particles_to_store,
-                           cbuffer=output_buffer)
+        out = st_Particles(
+            num_particles=num_particles_to_store, cbuffer=output_buffer
+        )
 
         for ii in range(num_particles):
             particle = pysix_Particle()
             input_particles.to_pysixtrack(particle, ii)
 
-            assert(particle.partid >= min_particle_id)
-            assert(particle.partid <= max_particle_id)
-            assert(particle.turn >= start_turn_by_turn)
+            assert particle.partid >= min_particle_id
+            assert particle.partid <= max_particle_id
+            assert particle.turn >= start_turn_by_turn
             delta_part_id = particle.partid - min_particle_id
             turns_tracked = particle.turn - start_turn_by_turn
 
             while particle.turn < until_turn_turn_by_turn:
-                assert(particle.elemid == 0)
+                assert particle.elemid == 0
                 for elem in line:
                     elem.track(particle)
                     particle.elemid += 1
 
-                out.from_pysixtrack(particle,
-                                    nn * turns_tracked + delta_part_id)
+                out.from_pysixtrack(
+                    particle, nn * turns_tracked + delta_part_id
+                )
                 turns_tracked += 1
                 particle.turn += 1
                 particle.elemid = 0
@@ -181,21 +200,22 @@ def track_particles_pysixtrack(
             max_num_turns_to_store += 1
 
         num_particles_to_store = int(nn * max_num_turns_to_store)
-        out = st_Particles(num_particles=num_particles_to_store,
-                           cbuffer=output_buffer)
+        out = st_Particles(
+            num_particles=num_particles_to_store, cbuffer=output_buffer
+        )
 
         for ii in range(num_particles):
             particle = pysix_Particle()
             input_particles.to_pysixtrack(particle, ii)
 
-            assert(particle.partid >= min_particle_id)
-            assert(particle.partid <= max_particle_id)
-            assert(particle.turn >= start_out_turns_turn)
+            assert particle.partid >= min_particle_id
+            assert particle.partid <= max_particle_id
+            assert particle.turn >= start_out_turns_turn
             delta_part_id = particle.partid - min_particle_id
             turns_tracked = particle.turn - start_turn_by_turn
 
             while particle.turn < until_turn:
-                assert(particle.elemid == 0)
+                assert particle.elemid == 0
                 for elem in line:
                     elem.track(particle)
                     particle.elemid += 1
@@ -214,4 +234,5 @@ def track_particles_pysixtrack(
 
     return output_buffer
 
+
 # end: sixtracklib/python/sixtracklib_test
diff --git a/sixtracklib/CMakeLists.txt b/sixtracklib/CMakeLists.txt
index d35b4baa..a10a9662 100644
--- a/sixtracklib/CMakeLists.txt
+++ b/sixtracklib/CMakeLists.txt
@@ -94,8 +94,13 @@ set_target_properties( sixtrack PROPERTIES
     LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
     DEBUG_POSTFIX d C_STANDARD_REQUIRED ON )
 
+if( TARGET sixtrack_cuda_device )
+    set_target_properties( sixtrack PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS ON )
+endif()
+
 target_compile_options( sixtrack PRIVATE
-    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # provide a copy of the library to the python module if it is defined!
diff --git a/sixtracklib/common/CMakeLists.txt b/sixtracklib/common/CMakeLists.txt
index 289b3159..8f96795f 100644
--- a/sixtracklib/common/CMakeLists.txt
+++ b/sixtracklib/common/CMakeLists.txt
@@ -30,6 +30,7 @@ add_subdirectory( be_xyshift     )
 add_subdirectory( be_monitor     )
 add_subdirectory( be_limit       )
 add_subdirectory( be_dipedge     )
+add_subdirectory( be_tricub      )
 add_subdirectory( output         )
 add_subdirectory( particles      )
 add_subdirectory( track          )
diff --git a/sixtracklib/common/be_beamfields/CMakeLists.txt b/sixtracklib/common/be_beamfields/CMakeLists.txt
index ba3c3856..a3c011a8 100644
--- a/sixtracklib/common/be_beamfields/CMakeLists.txt
+++ b/sixtracklib/common/be_beamfields/CMakeLists.txt
@@ -1,45 +1,33 @@
-set( SIXTRL_COMMON_BE_BEAMFIELDS_SOURCES
-    be_beamfields.c
-)
+set( SIXTRL_COMMON_BE_BEAMFIELDS_SOURCES be_beamfields.c )
 
 set( SIXTRL_COMMON_BE_BEAMFIELDS_HEADERS
-     be_beamfields.h
-     track.h
-     faddeeva_cern.h
-     gauss_fields.h
-)
+     be_beamfields.h track.h faddeeva_cern.h gauss_fields.h )
 
 add_library( sixtrack_common_be_beamfields OBJECT
     ${SIXTRL_COMMON_BE_BEAMFIELDS_HEADERS}
-    ${SIXTRL_COMMON_BE_BEAMFIELDS_SOURCES}
-)
-
+    ${SIXTRL_COMMON_BE_BEAMFIELDS_SOURCES} )
 
 target_include_directories( sixtrack_common_be_beamfields PRIVATE
-    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
-    $<INSTALL_INTERFACE:include> )
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
 set_target_properties( sixtrack_common_be_beamfields PROPERTIES
     LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
     C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_be_beamfields PRIVATE
-                        -Wall -Werror -pedantic -ansi
-                        ${SIXTRACKLIB_CPU_FLAGS} )
+        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_be_beamfields as a module for sixtracklib:
 
-set(  SIXTRACKL_LIBRARY_MODULES
-    ${SIXTRACKL_LIBRARY_MODULES}
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
     $<TARGET_OBJECTS:sixtrack_common_be_beamfields> CACHE INTERNAL "" FORCE )
 
 # ------------------------------------------------------------------------------
 # install :
 
-set( SIXTRACKLIB_COMMON_BE_BEAMFIELDS_C99_INSTALL_PATH
-     include/sixtracklib/common/be_beamfields )
-
-install( FILES ${SIXTRL_COMMON_BE_BEAMFIELDS_HEADERS}
-         DESTINATION ${SIXTRACKLIB_COMMON_BE_BEAMFIELDS_C99_INSTALL_PATH} )
-
+if( SIXTRL_COMMON_BE_BEAMFIELDS_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_BEAMFIELDS_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/be_beamfields" )
+endif()
diff --git a/sixtracklib/common/be_beamfields/be_beamfields.c b/sixtracklib/common/be_beamfields/be_beamfields.c
index f25777ae..b15a0c1b 100644
--- a/sixtracklib/common/be_beamfields/be_beamfields.c
+++ b/sixtracklib/common/be_beamfields/be_beamfields.c
@@ -11,6 +11,7 @@
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
+    #include "sixtracklib/common/internal/math_interpol.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
     #include "sixtracklib/common/be_beamfields/gauss_fields.h"
@@ -20,25 +21,104 @@
 /* ************************************************************************* */
 /* BeamBeam4D: */
 
-NS(buffer_size_t) NS(BeamBeam4D_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const beam_beam )
+NS(object_type_id_t) NS(BeamBeam4D_type_id_ext)( void ) SIXTRL_NOEXCEPT
 {
-    return NS(BeamBeam4D_get_required_num_dataptrs_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        beam_beam, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(BeamBeam4D_type_id)();
 }
 
-NS(buffer_size_t)
-NS(BeamBeam4D_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const beam_beam )
+NS(buffer_size_t) NS(BeamBeam4D_data_addr_offset_ext)( SIXTRL_BE_ARGPTR_DEC
+    const NS(BeamBeam4D) *const SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamBeam4D_data_addr_offset)( bb_elem );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(BeamBeam4D_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BeamBeam4D_get_required_num_slots_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        beam_beam, NS(Buffer_get_slot_size)( buffer ) );
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( elem != SIXTRL_NULLPTR ) && ( offsets != SIXTRL_NULLPTR ) &&
+        ( max_num_offsets >= ( NS(buffer_size_t) )1 ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) )
+    {
+        offsets[ 0 ] = offsetof( NS(BeamBeam4D), data_addr );
+        SIXTRL_ASSERT( offsets[ 0 ] % slot_size == ( NS(buffer_size_t) )0u );
+
+        if( max_num_offsets > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_offsets ; ++ii )
+                    offsets[ ii ] = ( NS(buffer_size_t) )0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
+NS(arch_status_t) NS(BeamBeam4D_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( elem != SIXTRL_NULLPTR ) && ( sizes != SIXTRL_NULLPTR ) &&
+        ( max_num_sizes >= ( NS(buffer_size_t) )1 ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) )
+    {
+        sizes[ 0 ] = sizeof( SIXTRL_REAL_T );
+        if( max_num_sizes > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_sizes ; ++ii )
+                sizes[ ii ] = ( NS(buffer_size_t) )0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(BeamBeam4D_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( elem != SIXTRL_NULLPTR ) && ( counts != SIXTRL_NULLPTR ) &&
+        ( max_num_counts >= ( NS(buffer_size_t) )1 ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) )
+    {
+        counts[ 0 ] = NS(BeamBeam4D_data_size)( elem );
+        if( max_num_counts > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_counts ; ++ii )
+                counts[ ii ] = ( NS(buffer_size_t) )0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
 bool NS(BeamBeam4D_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     NS(buffer_size_t) const data_size,
@@ -47,420 +127,1673 @@ bool NS(BeamBeam4D_can_be_added)(
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs )
 {
     typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(BeamBeam4D) elem_t;
 
-    buf_size_t const sizes[]  = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[] = { data_size };
-    buf_size_t num_dataptrs   = ( buf_size_t )0u;
+    bool can_be_added = false;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    NS(BeamBeam4D) temp;
+    NS(BeamBeam4D_preset)( &temp );
+    status = NS(BeamBeam4D_set_data_size)( &temp, data_size );
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ];
+
+        status = NS(BeamBeam4D_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            status = NS(BeamBeam4D_attributes_counts)(
+                &counts[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            buf_size_t const ndataptrs = NS(BeamBeam4D_num_dataptrs)( &temp );
+            if( ndataptrs == ( buf_size_t )1 )
+            {
+                can_be_added = NS(Buffer_can_add_object)( buffer, sizeof(
+                    NS(BeamBeam4D) ), ndataptrs, &sizes[ 0 ], &counts[ 0 ],
+                        ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
+            }
+        }
+    }
+
+    return can_be_added;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const data_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
 
-    elem_t temp_obj;
-    NS(BeamBeam4D_preset)( &temp_obj );
-    NS(BeamBeam4D_set_data_size)( &temp_obj, data_size );
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* added_elem = SIXTRL_NULLPTR;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ] = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1 ]   = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ]  = { ( buf_size_t )0 };
+
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+    NS(BeamBeam4D) temp;
+    NS(BeamBeam4D_preset)( &temp );
+    status = NS(BeamBeam4D_set_data_size)( &temp, data_size );
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam4D_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam4D_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam4D_attributes_counts)(
+            &counts[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        buf_size_t const ndataptrs = NS(BeamBeam4D_num_dataptrs)( &temp );
+        if( ndataptrs == ( buf_size_t )1 )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* )( uintptr_t
+                )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                    &temp, sizeof( NS(BeamBeam4D) ), NS(BeamBeam4D_type_id)(),
+                        ndataptrs, &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
 
-    num_dataptrs = NS(BeamBeam4D_get_required_num_dataptrs)( buffer, &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const  data_size,
+    NS(buffer_addr_t) data_addr )
+{
+    typedef NS(buffer_size_t) buf_size_t;
 
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ),
-        num_dataptrs, &sizes[ 0 ], &counts[ 0 ], ptr_requ_objects,
-            ptr_requ_slots, ptr_requ_dataptrs );
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* added_elem = SIXTRL_NULLPTR;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ] = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1 ]   = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ]  = { ( buf_size_t )0 };
+
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    NS(BeamBeam4D) temp;
+    NS(BeamBeam4D_preset)( &temp );
+    status  = NS(BeamBeam4D_set_data_size)( &temp, data_size );
+    status |= NS(BeamBeam4D_set_data_addr)( &temp, data_addr );
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam4D_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam4D_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam4D_attributes_counts)(
+            &counts[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        buf_size_t const ndataptrs = NS(BeamBeam4D_num_dataptrs)( &temp );
+        if( ndataptrs == ( buf_size_t )1 )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* )( uintptr_t
+                )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                    &temp, sizeof( NS(BeamBeam4D) ), NS(BeamBeam4D_type_id)(),
+                        ndataptrs, &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_new)(
+SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const data_size )
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT orig )
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(BeamBeam4D) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* added_elem = SIXTRL_NULLPTR;
+
+    SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ] = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1 ]   = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ]  = { ( buf_size_t )0 };
+
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    NS(arch_status_t) status = NS(BeamBeam4D_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, orig, slot_size );
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam4D_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )1u, orig, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam4D_attributes_counts)(
+            &counts[ 0 ], ( buf_size_t )1u, orig, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        buf_size_t const ndataptrs = NS(BeamBeam4D_num_dataptrs)( orig );
+
+        if( ndataptrs == ( buf_size_t )1 )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* )( uintptr_t
+                )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+                    sizeof( NS(BeamBeam4D) ), NS(BeamBeam4D_type_id)(),
+                        ndataptrs, &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
 
-    buf_size_t const offsets[] = { offsetof( elem_t, data ) };
-    buf_size_t const sizes[]   = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[]  = { data_size };
-    buf_size_t num_dataptrs    = ( buf_size_t )0u;
+/* ************************************************************************* */
+/* NS(BeamBeam6D) */
 
-    elem_t temp_obj;
-    NS(BeamBeam4D_preset)( &temp_obj );
-    NS(BeamBeam4D_set_data_size)( &temp_obj, data_size );
+NS(object_type_id_t) NS(BeamBeam6D_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamBeam6D_type_id)();
+}
 
-    num_dataptrs = NS(BeamBeam4D_get_required_num_dataptrs)( buffer, &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+NS(buffer_size_t) NS(BeamBeam6D_data_addr_offset_ext)( SIXTRL_BE_ARGPTR_DEC
+    const NS(BeamBeam6D) *const SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamBeam6D_data_addr_offset)( bb_elem );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(BeamBeam6D_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( elem != SIXTRL_NULLPTR ) && ( offsets != SIXTRL_NULLPTR ) &&
+        ( max_num_offsets >= ( NS(buffer_size_t) )1 ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) )
+    {
+        offsets[ 0 ] = offsetof( NS(BeamBeam6D), data_addr );
+        SIXTRL_ASSERT( offsets[ 0 ] % slot_size == ( NS(buffer_size_t) )0u );
+
+        if( max_num_offsets > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_offsets ; ++ii )
+                    offsets[ ii ] = ( NS(buffer_size_t) )0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_BEAM_BEAM_4D), num_dataptrs,
-                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+NS(arch_status_t) NS(BeamBeam6D_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( elem != SIXTRL_NULLPTR ) && ( sizes != SIXTRL_NULLPTR ) &&
+        ( max_num_sizes >= ( NS(buffer_size_t) )1 ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) )
+    {
+        sizes[ 0 ] = sizeof( SIXTRL_REAL_T );
+
+        if( max_num_sizes > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_sizes ; ++ii )
+                sizes[ ii ] = ( NS(buffer_size_t) )0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(BeamBeam6D_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( elem != SIXTRL_NULLPTR ) && ( counts != SIXTRL_NULLPTR ) &&
+        ( max_num_counts >= ( NS(buffer_size_t) )1 ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) )
+    {
+        counts[ 0 ] = NS(BeamBeam6D_data_size)( elem );
+        if( max_num_counts > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_counts ; ++ii )
+                counts[ ii ] = ( NS(buffer_size_t) )0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(BeamBeam6D_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const data_size,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs )
+{
+    typedef NS(buffer_size_t)  buf_size_t;
+
+    bool can_be_added = false;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    NS(BeamBeam6D) temp;
+    NS(BeamBeam6D_preset)( &temp );
+    status = NS(BeamBeam6D_set_data_size)( &temp, data_size );
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ];
+
+        status = NS(BeamBeam6D_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            status = NS(BeamBeam6D_attributes_counts)(
+                &counts[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            buf_size_t const ndataptrs = NS(BeamBeam6D_num_dataptrs)( &temp );
+
+            if( ndataptrs == ( buf_size_t )1 )
+            {
+                can_be_added = NS(Buffer_can_add_object)( buffer, sizeof(
+                    NS(BeamBeam6D) ), ndataptrs, &sizes[ 0 ], &counts[ 0 ],
+                        ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
+            }
+        }
+    }
+
+    return can_be_added;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* NS(BeamBeam6D_new)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const  data_size,
-    NS(beambeam4d_real_ptr_t) SIXTRL_RESTRICT input_data )
+    NS(buffer_size_t) const data_size )
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(BeamBeam4D) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
 
-    buf_size_t const offsets[] = { offsetof( elem_t, data ) };
-    buf_size_t const sizes[]   = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[]  = { data_size };
-    buf_size_t num_dataptrs    = ( buf_size_t )0u;
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* added_elem = SIXTRL_NULLPTR;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ] = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1 ]   = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ]  = { ( buf_size_t )0 };
+
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    NS(BeamBeam6D) temp;
+    NS(BeamBeam6D_preset)( &temp );
+    status = NS(BeamBeam6D_set_data_size)( &temp, data_size );
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam6D_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam6D_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam6D_attributes_counts)(
+            &counts[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        buf_size_t const ndataptrs = NS(BeamBeam6D_num_dataptrs)( &temp );
+        if( ndataptrs == ( buf_size_t )1 )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* )( uintptr_t
+                )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                    &temp, sizeof( NS(BeamBeam6D) ), NS(BeamBeam6D_type_id)(),
+                        ndataptrs, &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
 
-    elem_t temp_obj;
-    NS(BeamBeam4D_preset)( &temp_obj );
-    NS(BeamBeam4D_set_data_size)( &temp_obj, data_size );
-    NS(BeamBeam4D_assign_data_ptr)( &temp_obj, input_data );
-    num_dataptrs = NS(BeamBeam4D_get_required_num_dataptrs)(
-        buffer, SIXTRL_NULLPTR );
+SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* NS(BeamBeam6D_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const data_size,
+    NS(buffer_addr_t) const data_addr )
+{
+    typedef NS(buffer_size_t) buf_size_t;
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_BEAM_BEAM_4D), num_dataptrs,
-                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* added_elem = SIXTRL_NULLPTR;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ] = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1 ]   = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ]  = { ( buf_size_t )0 };
+
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    NS(BeamBeam6D) temp;
+    NS(BeamBeam6D_preset)( &temp );
+    status  = NS(BeamBeam6D_set_data_size)( &temp, data_size );
+    status |= NS(BeamBeam6D_set_data_addr)( &temp, data_addr );
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam6D_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam6D_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam6D_attributes_counts)(
+            &counts[ 0 ], ( buf_size_t )1u, &temp, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        buf_size_t const ndataptrs = NS(BeamBeam6D_num_dataptrs)( &temp );
+        if( ndataptrs == ( buf_size_t )1 )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* )( uintptr_t
+                )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                    &temp, sizeof( NS(BeamBeam6D) ), NS(BeamBeam6D_type_id)(),
+                        ndataptrs, &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_add_copy)(
+SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* NS(BeamBeam6D_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT orig )
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT orig )
 {
-    return NS(BeamBeam4D_add)( buffer, NS(BeamBeam4D_get_data_size)( orig ),
-        NS(BeamBeam4D_get_data)( ( NS(BeamBeam4D)* )orig ) );
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* added_elem = SIXTRL_NULLPTR;
+
+    SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ] = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1 ]   = { ( buf_size_t )0 };
+    SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ]  = { ( buf_size_t )0 };
+
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    NS(arch_status_t) status = NS(BeamBeam6D_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, orig, slot_size );
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam6D_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )1u, orig, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        status = NS(BeamBeam6D_attributes_counts)(
+            &counts[ 0 ], ( buf_size_t )1u, orig, slot_size );
+    }
+
+    if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+    {
+        buf_size_t const ndataptrs = NS(BeamBeam6D_num_dataptrs)( orig );
+        if( ndataptrs == ( buf_size_t )1 )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* )( uintptr_t
+                )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+                    sizeof( NS(BeamBeam6D) ), NS(BeamBeam6D_type_id)(),
+                        ndataptrs, &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
 }
 
 /* ************************************************************************* */
-/* SpaceChargeCoasting: */
+/* SCCoasting: */
+
+NS(object_type_id_t) NS(SCCoasting_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_SC_COASTING);
+}
 
+/* ------------------------------------------------------------------------- */
 
-NS(buffer_size_t) NS(SpaceChargeCoasting_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const beam_beam )
+SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) const*
+NS(SCCoasting_const_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    return NS(SpaceChargeCoasting_get_required_num_dataptrs_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        beam_beam, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(SCCoasting_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
 }
 
-NS(buffer_size_t)
-NS(SpaceChargeCoasting_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const beam_beam )
+SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    return NS(SpaceChargeCoasting_get_required_num_slots_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        beam_beam, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(SCCoasting_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
+}
+
+NS(arch_status_t) NS(SCCoasting_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(SCCoasting_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(SCCoasting_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ( buf_size_t )0 ) &&
+        ( max_num_counts > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-bool NS(SpaceChargeCoasting_can_be_added)(
+/* ------------------------------------------------------------------------- */
+
+bool NS(SCCoasting_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const data_size,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs )
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(SpaceChargeCoasting) elem_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    bool can_be_added = false;
 
-    buf_size_t const sizes[]  = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[] = { data_size };
-    buf_size_t num_dataptrs   = ( buf_size_t )0u;
+    buf_size_t num_dataptrs = ( buf_size_t )0u;
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) sc_elem;
+    NS(arch_status_t) status = NS(SCCoasting_clear)( &sc_elem );
+    num_dataptrs = NS(SCCoasting_num_dataptrs)( &sc_elem );
 
-    elem_t temp_obj;
-    NS(SpaceChargeCoasting_preset)( &temp_obj );
-    NS(SpaceChargeCoasting_set_data_size)( &temp_obj, data_size );
+    can_be_added = (
+        ( num_dataptrs == ( buf_size_t )0u ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( NS(Buffer_can_add_object)( buffer, sizeof( NS(SCCoasting) ),
+            num_dataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, ptr_requ_objects,
+                ptr_requ_slots, ptr_requ_dataptrs ) ) );
 
-    num_dataptrs = NS(SpaceChargeCoasting_get_required_num_dataptrs)(
-        buffer, &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+    return can_be_added;
+}
 
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ),
-        num_dataptrs, &sizes[ 0 ], &counts[ 0 ], ptr_requ_objects,
-            ptr_requ_slots, ptr_requ_dataptrs );
+SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* NS(SCCoasting_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) num_dataptrs = ( NS(buffer_size_t) )0u;
+
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) sc_elem;
+    NS(arch_status_t) status = NS(SCCoasting_clear)( &sc_elem );
+    num_dataptrs = NS(SCCoasting_num_dataptrs)( &sc_elem );
+
+    if( ( num_dataptrs == ( NS(buffer_size_t) )0u ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( buffer != SIXTRL_NULLPTR ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* )(
+            uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                &sc_elem, sizeof( sc_elem ), NS(SCCoasting_type_id)(),
+                    num_dataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeCoasting)* NS(SpaceChargeCoasting_new)(
+SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* NS(SCCoasting_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const data_size )
+    SIXTRL_REAL_T const number_of_particles, SIXTRL_REAL_T const circumference,
+    SIXTRL_REAL_T const sigma_x, SIXTRL_REAL_T const sigma_y,
+    SIXTRL_REAL_T const length, SIXTRL_REAL_T const x_co,
+    SIXTRL_REAL_T const y_co, SIXTRL_REAL_T const min_sigma_diff,
+    bool const enabled )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) num_dataptrs = ( NS(buffer_size_t) )0u;
+
+    NS(SCCoasting) sc_elem;
+    NS(arch_status_t) status = NS(SCCoasting_clear)( &sc_elem );
+    status |= NS(SCCoasting_set_number_of_particles)(
+        &sc_elem, number_of_particles );
+
+    status |= NS(SCCoasting_set_circumference)(
+        &sc_elem, circumference );
+
+    status |= NS(SCCoasting_set_sigma_x)( &sc_elem, sigma_x );
+    status |= NS(SCCoasting_set_sigma_y)( &sc_elem, sigma_y );
+    status |= NS(SCCoasting_set_length)( &sc_elem, length );
+    status |= NS(SCCoasting_set_x_co)( &sc_elem, x_co );
+    status |= NS(SCCoasting_set_y_co)( &sc_elem, y_co );
+    status |= NS(SCCoasting_set_min_sigma_diff)(
+        &sc_elem, min_sigma_diff );
+
+    status |= NS(SCCoasting_set_enabled)( &sc_elem, enabled );
+
+    num_dataptrs = NS(SCCoasting_num_dataptrs)( &sc_elem );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( num_dataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* )(
+            uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                &sc_elem, sizeof( sc_elem ), NS(SCCoasting_type_id)(),
+                    num_dataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* NS(SCCoasting_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT orig ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* added_elem = SIXTRL_NULLPTR;
+
+    NS(buffer_size_t) const num_dataptrs =
+        NS(SCCoasting_num_dataptrs)( orig );
+
+    if( ( orig != SIXTRL_NULLPTR ) && ( buffer != SIXTRL_NULLPTR ) &&
+        ( num_dataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* )(
+            uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                orig, sizeof( NS(SCCoasting) ),
+                    NS(SCCoasting_type_id)(), num_dataptrs,
+                        SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+/* *************************************************************************  */
+/* NS(SCQGaussProfile): */
+
+NS(object_type_id_t)
+NS(SCQGaussProfile_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF);
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile) const*
+NS(SCQGaussProfile_const_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(SCQGaussProfile_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(SCQGaussProfile_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
+}
+
+NS(arch_status_t) NS(SCQGaussProfile_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(SpaceChargeCoasting) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
 
-    buf_size_t const offsets[] = { offsetof( elem_t, data ) };
-    buf_size_t const sizes[]   = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[]  = { data_size };
-    buf_size_t num_dataptrs    = ( buf_size_t )0u;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
 
-    elem_t temp_obj;
-    NS(SpaceChargeCoasting_preset)( &temp_obj );
-    NS(SpaceChargeCoasting_set_data_size)( &temp_obj, data_size );
+NS(arch_status_t) NS(SCQGaussProfile_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    num_dataptrs = NS(SpaceChargeCoasting_get_required_num_dataptrs)( buffer, &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_SPACE_CHARGE_COASTING), num_dataptrs,
-                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeCoasting)* NS(SpaceChargeCoasting_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const  data_size,
-    NS(beambeam4d_real_ptr_t) SIXTRL_RESTRICT input_data )
+NS(arch_status_t) NS(SCQGaussProfile_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(SpaceChargeCoasting) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    buf_size_t const offsets[] = { offsetof( elem_t, data ) };
-    buf_size_t const sizes[]   = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[]  = { data_size };
-    buf_size_t num_dataptrs    = ( buf_size_t )0u;
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_counts > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
 
-    elem_t temp_obj;
-    NS(SpaceChargeCoasting_preset)( &temp_obj );
-    NS(SpaceChargeCoasting_set_data_size)( &temp_obj, data_size );
-    NS(SpaceChargeCoasting_assign_data_ptr)( &temp_obj, input_data );
-    num_dataptrs = NS(SpaceChargeCoasting_get_required_num_dataptrs)(
-        buffer, SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+/* ------------------------------------------------------------------------- */
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_SPACE_CHARGE_COASTING), num_dataptrs,
-                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+bool NS(SCQGaussProfile_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    bool can_be_added = false;
+
+    buf_size_t ndataptrs = ( buf_size_t )0u;
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile) sc_elem;
+    NS(arch_status_t) const status =
+        NS(SCQGaussProfile_clear)( &sc_elem );
+    ndataptrs = NS(SCQGaussProfile_num_dataptrs)( &sc_elem );
+
+    can_be_added = ( ( ndataptrs == ( buf_size_t )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( NS(Buffer_can_add_object)( buffer,
+            sizeof( NS(SCQGaussProfile) ), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, ptr_requ_objects,
+                    ptr_requ_slots, ptr_requ_dataptrs ) ) );
+
+    return can_be_added;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        added_elem = SIXTRL_NULLPTR;
+
+    NS(buffer_size_t) ndataptrs = ( NS(buffer_size_t) )0u;
+
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile) sc_elem;
+    NS(arch_status_t) const status =
+        NS(SCQGaussProfile_clear)( &sc_elem );
+
+    ndataptrs = NS(SCQGaussProfile_num_dataptrs)( &sc_elem );
+
+    if( ( ndataptrs == ( NS(buffer_size_t) )0u ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* )(
+        uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+            &sc_elem, sizeof( NS(SCQGaussProfile) ),
+                NS(SCQGaussProfile_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeCoasting)* NS(SpaceChargeCoasting_add_copy)(
+SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT orig )
+    SIXTRL_REAL_T const number_of_particles, SIXTRL_REAL_T const bunchlength_rms,
+    SIXTRL_REAL_T const sigma_x, SIXTRL_REAL_T const sigma_y,
+    SIXTRL_REAL_T const length,
+    SIXTRL_REAL_T const x_co, SIXTRL_REAL_T const y_co,
+    SIXTRL_REAL_T const min_sigma_diff,
+    SIXTRL_REAL_T const q_param, bool const enabled )
 {
-    return NS(SpaceChargeCoasting_add)( buffer,
-            NS(SpaceChargeCoasting_get_data_size)( orig ),
-            NS(SpaceChargeCoasting_get_data)(
-                ( NS(SpaceChargeCoasting)* )orig ) );
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        added_elem = SIXTRL_NULLPTR;
+
+    NS(buffer_size_t) num_dataptrs = ( NS(buffer_size_t) )0u;
+
+    NS(SCQGaussProfile) sc_elem;
+    NS(arch_status_t) status =
+        NS(SCQGaussProfile_clear)( &sc_elem );
+
+    status |= NS(SCQGaussProfile_set_number_of_particles)(
+        &sc_elem, number_of_particles );
+
+    status |= NS(SCQGaussProfile_set_bunchlength_rms)(
+        &sc_elem, bunchlength_rms );
+
+    status |= NS(SCQGaussProfile_set_sigma_x)( &sc_elem, sigma_x );
+    status |= NS(SCQGaussProfile_set_sigma_y)( &sc_elem, sigma_y );
+    status |= NS(SCQGaussProfile_set_length)( &sc_elem, length );
+    status |= NS(SCQGaussProfile_set_x_co)( &sc_elem, x_co );
+    status |= NS(SCQGaussProfile_set_y_co)( &sc_elem, y_co );
+
+    status |= NS(SCQGaussProfile_set_min_sigma_diff)(
+        &sc_elem, min_sigma_diff );
+
+    status |= NS(SCQGaussProfile_set_q_param)( &sc_elem, q_param );
+    status |= NS(SCQGaussProfile_set_enabled)( &sc_elem, enabled );
+
+    num_dataptrs = NS(SCQGaussProfile_num_dataptrs)( &sc_elem );
+    SIXTRL_ASSERT( num_dataptrs == ( NS(buffer_size_t) )0u );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( num_dataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* )(
+            uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                &sc_elem, sizeof( sc_elem ),
+                    NS(SCQGaussProfile_type_id)(), num_dataptrs,
+                        SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT orig ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        added_elem = SIXTRL_NULLPTR;
+
+    NS(buffer_size_t) const num_dataptrs =
+        NS(SCQGaussProfile_num_dataptrs)( orig );
+
+    if( ( orig != SIXTRL_NULLPTR ) && ( buffer != SIXTRL_NULLPTR ) &&
+        ( num_dataptrs == ( NS(buffer_size_t) )0 ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* )(
+            uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+                orig, sizeof( NS(SCQGaussProfile) ),
+                    NS(SCQGaussProfile_type_id)(), num_dataptrs,
+                        SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
 /* ************************************************************************* */
-/* SpaceChargeBunched: */
+/* NS(LineDensityProfileData) */
 
-NS(buffer_size_t) NS(SpaceChargeBunched_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const beam_beam )
+NS(object_type_id_t) NS(LineDensityProfileData_type_id_ext)(
+    void ) SIXTRL_NOEXCEPT
 {
-    return NS(SpaceChargeBunched_get_required_num_dataptrs_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        beam_beam, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(LineDensityProfileData_type_id)();
 }
 
-NS(buffer_size_t)
-NS(SpaceChargeBunched_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const beam_beam )
+NS(buffer_size_t) NS(LineDensityProfileData_values_offset_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
 {
-    return NS(SpaceChargeBunched_get_required_num_slots_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        beam_beam, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(LineDensityProfileData_values_offset)( data );
 }
 
-bool NS(SpaceChargeBunched_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const data_size,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs )
+NS(buffer_size_t) NS(LineDensityProfileData_derivatives_offset_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(SpaceChargeBunched) elem_t;
+    return NS(LineDensityProfileData_derivatives_offset)( data );
+}
 
-    buf_size_t const sizes[]  = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[] = { data_size };
-    buf_size_t num_dataptrs   = ( buf_size_t )0u;
+NS(arch_status_t) NS(LineDensityProfileData_prepare_interpolation_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    NS(math_abscissa_idx_t) const num_values =
+        NS(LineDensityProfileData_num_values)( data );
+
+    if( ( data != SIXTRL_NULLPTR ) &&
+        ( num_values > ( NS(math_abscissa_idx_t) )1 ) )
+    {
+        NS(math_interpol_t) const interpol_method =
+            NS(LineDensityProfileData_method)( data );
+
+        if( interpol_method == NS(MATH_INTERPOL_LINEAR) )
+        {
+            status = NS(LineDensityProfileData_prepare_interpolation)(
+                data, SIXTRL_NULLPTR );
+        }
+        else if( interpol_method == NS(MATH_INTERPOL_CUBIC) )
+        {
+            SIXTRL_REAL_T* temp_data = ( SIXTRL_REAL_T* )malloc(
+                sizeof( SIXTRL_REAL_T ) * num_values * 6u );
+
+            status = NS(LineDensityProfileData_prepare_interpolation)(
+                data, temp_data );
+
+            free( temp_data );
+        }
+    }
+
+    return status;
+}
 
-    elem_t temp_obj;
-    NS(SpaceChargeBunched_preset)( &temp_obj );
-    NS(SpaceChargeBunched_set_data_size)( &temp_obj, data_size );
+SIXTRL_REAL_T NS(LineDensityProfileData_z0_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_z0)( data );
+}
 
-    num_dataptrs = NS(SpaceChargeBunched_get_required_num_dataptrs)(
-        buffer, &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+SIXTRL_REAL_T NS(LineDensityProfileData_dz_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(LineDensityProfileData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_dz)( data );
+}
 
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ),
-        num_dataptrs, &sizes[ 0 ], &counts[ 0 ], ptr_requ_objects,
-            ptr_requ_slots, ptr_requ_dataptrs );
+SIXTRL_REAL_T NS(LineDensityProfileData_z_min_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_z_min)( data );
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeBunched)* NS(SpaceChargeBunched_new)(
+SIXTRL_REAL_T NS(LineDensityProfileData_z_max_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(LineDensityProfileData) *const SIXTRL_RESTRICT
+        data ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_z_max)( data );
+}
+
+NS(math_abscissa_idx_t) NS(LineDensityProfileData_find_idx_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_find_idx)( data, z );
+}
+
+
+SIXTRL_REAL_T NS(LineDensityProfileData_interpolate_value_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_interpolate_value)( data, z );
+}
+
+SIXTRL_REAL_T NS(LineDensityProfileData_interpolate_1st_derivative_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_interpolate_1st_derivative)( data, z );
+}
+
+SIXTRL_REAL_T NS(LineDensityProfileData_interpolate_2nd_derivative_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_interpolate_2nd_derivative)( data, z );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(LineDensityProfileData_set_z0_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z0 ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_set_z0)( data, z0 );
+}
+
+NS(arch_status_t) NS(LineDensityProfileData_set_dz_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const dz ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_set_dz)( data, dz );
+}
+
+NS(arch_status_t) NS(LineDensityProfileData_set_values_addr_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const values_addr ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_set_values_addr)( data, values_addr );
+}
+
+NS(arch_status_t) NS(LineDensityProfileData_set_derivatives_addr_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const derivatives_addr ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_set_derivatives_addr)( data, derivatives_addr );
+}
+
+NS(arch_status_t) NS(LineDensityProfileData_set_method_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(math_interpol_t) const method ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_set_method)( data, method );
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData) const*
+NS(LineDensityProfileData_const_from_buffer_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_from_buffer_ext)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const data_size )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS(arch_status_t) NS(LineDensityProfileData_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(SpaceChargeBunched) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( data != SIXTRL_NULLPTR ) &&
+        ( slot_size > ZERO ) && ( max_num_offsets >= ( buf_size_t )2u ) )
+    {
+        offsets[ 0 ] = ( buf_size_t )offsetof(
+            NS(LineDensityProfileData), values_addr );
 
-    buf_size_t const offsets[] = { offsetof( elem_t, data ) };
-    buf_size_t const sizes[]   = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[]  = { data_size };
-    buf_size_t num_dataptrs    = ( buf_size_t )0u;
+        offsets[ 1 ] = ( buf_size_t )offsetof(
+            NS(LineDensityProfileData), derivatives_addr );
 
-    elem_t temp_obj;
-    NS(SpaceChargeBunched_preset)( &temp_obj );
-    NS(SpaceChargeBunched_set_data_size)( &temp_obj, data_size );
+        SIXTRL_ASSERT( offsets[ 0 ] % slot_size == ( buf_size_t )0 );
+        SIXTRL_ASSERT( offsets[ 0 ] % slot_size == ( buf_size_t )0 );
 
-    num_dataptrs = NS(SpaceChargeBunched_get_required_num_dataptrs)(
-        buffer, &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+        if( max_num_offsets > ( buf_size_t )2u )
+        {
+            SIXTRACKLIB_SET_VALUES(
+                buf_size_t, &offsets[ 2 ], max_num_offsets - 2u, ZERO );
+        }
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED), num_dataptrs,
-                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        status = NS(ARCH_STATUS_SUCCESS);
+    }
+
+    return status;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeBunched)* NS(SpaceChargeBunched_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const  data_size,
-    NS(beambeam4d_real_ptr_t) SIXTRL_RESTRICT input_data )
+NS(arch_status_t) NS(LineDensityProfileData_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(SpaceChargeBunched) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( data != SIXTRL_NULLPTR ) &&
+        ( slot_size > ZERO ) && ( max_num_sizes >= ( buf_size_t )2u ) )
+    {
+        sizes[ 0 ] = sizeof( SIXTRL_REAL_T );
+        sizes[ 1 ] = sizeof( SIXTRL_REAL_T );
 
-    buf_size_t const offsets[] = { offsetof( elem_t, data ) };
-    buf_size_t const sizes[]   = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[]  = { data_size };
-    buf_size_t num_dataptrs    = ( buf_size_t )0u;
+        if( max_num_sizes > ( buf_size_t )2u )
+        {
+            SIXTRACKLIB_SET_VALUES(
+                buf_size_t, &sizes[ 2 ], max_num_sizes - 2u, ZERO );
+        }
 
-    elem_t temp_obj;
-    NS(SpaceChargeBunched_preset)( &temp_obj );
-    NS(SpaceChargeBunched_set_data_size)( &temp_obj, data_size );
-    NS(SpaceChargeBunched_assign_data_ptr)( &temp_obj, input_data );
-    num_dataptrs = NS(SpaceChargeBunched_get_required_num_dataptrs)(
-        buffer, SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+        status = NS(ARCH_STATUS_SUCCESS);
+    }
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED), num_dataptrs,
-                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+    return status;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeBunched)* NS(SpaceChargeBunched_add_copy)(
+NS(arch_status_t) NS(LineDensityProfileData_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( data != SIXTRL_NULLPTR ) &&
+        ( max_num_counts >= ( buf_size_t )2u ) &&
+        ( slot_size > ( NS(buffer_size_t) )0u ) &&
+        ( NS(LineDensityProfileData_capacity)( data ) >=
+          ( NS(math_abscissa_idx_t) )0u ) )
+    {
+        counts[ 0 ] = ( buf_size_t )NS(LineDensityProfileData_capacity)( data );
+        counts[ 1 ] = ( buf_size_t )NS(LineDensityProfileData_capacity)( data );
+        status = NS(ARCH_STATUS_SUCCESS);
+
+        if( max_num_counts > ( buf_size_t )2u )
+        {
+            SIXTRACKLIB_SET_VALUES(
+                buf_size_t, &counts[ 2 ], max_num_counts - 2u, ZERO );
+        }
+    }
+
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+bool NS(LineDensityProfileData_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(math_abscissa_idx_t) const capacity,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    bool can_be_added = false;
+
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+    buf_size_t ndataptrs = ( buf_size_t )0u;
+
+    NS(LineDensityProfileData) data;
+    NS(arch_status_t) status = NS(LineDensityProfileData_clear)( &data );
+    status |= NS(LineDensityProfileData_set_capacity)( &data, capacity );
+    status |= NS(LineDensityProfileData_set_num_values)( &data, capacity );
+    ndataptrs = NS(LineDensityProfileData_num_dataptrs)( &data );
+
+    if( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( ndataptrs == ( buf_size_t )2u ) && ( slot_size > ( buf_size_t )0 ) &&
+        ( buffer != SIXTRL_NULLPTR ) &&
+        ( capacity > ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        NS(buffer_size_t) sizes[ 2 ];
+        NS(buffer_size_t) counts[ 2 ];
+
+        status = NS(LineDensityProfileData_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )2u, &data, slot_size );
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            status = NS(LineDensityProfileData_attributes_counts)(
+                &counts[ 0 ], ( buf_size_t )2u, &data, slot_size );
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            can_be_added = NS(Buffer_can_add_object)( buffer, sizeof(
+                NS(LineDensityProfileData) ), ndataptrs, SIXTRL_NULLPTR,
+                    SIXTRL_NULLPTR, ptr_requ_objects, ptr_requ_slots,
+                        ptr_requ_dataptrs );
+        }
+    }
+
+    return can_be_added;
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_new)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT orig )
+    NS(math_abscissa_idx_t) const capacity )
 {
-    return NS(SpaceChargeBunched_add)( buffer,
-       NS(SpaceChargeBunched_get_data_size)( orig ),
-       NS(SpaceChargeBunched_get_data)( ( NS(SpaceChargeBunched)* )orig ) );
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        added_elem = SIXTRL_NULLPTR;
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( capacity > ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 2u ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 2u ];
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 2u ];
+
+        buf_size_t num_dataptrs = ( buf_size_t )0u;
+
+        NS(LineDensityProfileData) data;
+        NS(arch_status_t) status = NS(LineDensityProfileData_clear)( &data );
+        status |= NS(LineDensityProfileData_set_capacity)( &data, capacity );
+        status |= NS(LineDensityProfileData_set_num_values)( &data, capacity );
+        num_dataptrs = NS(LineDensityProfileData_num_dataptrs)( &data );
+
+        if( ( num_dataptrs == ( buf_size_t )2u ) &&
+            ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+            ( slot_size > ( buf_size_t )0 ) && ( buffer != SIXTRL_NULLPTR ) )
+        {
+            status = NS(LineDensityProfileData_attributes_offsets)(
+                &offsets[ 0 ], ( buf_size_t )2u, &data, slot_size );
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(LineDensityProfileData_attributes_sizes)(
+                    &sizes[ 0 ], ( buf_size_t )2u, &data, slot_size );
+            }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(LineDensityProfileData_attributes_counts)(
+                    &counts[ 0 ], ( buf_size_t )2u, &data, slot_size );
+            }
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+                )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, &data, sizeof( data ),
+                        NS(LineDensityProfileData_type_id)(), num_dataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(LineDensityProfileData)* NS(LineDensityProfileData_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(math_interpol_t) const method, NS(math_abscissa_idx_t) num_values,
+    NS(buffer_addr_t) const values_addr,
+    NS(buffer_addr_t) const derivatives_addr,
+    SIXTRL_REAL_T const z0, SIXTRL_REAL_T const dz,
+    NS(math_abscissa_idx_t) capacity )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        added_elem = SIXTRL_NULLPTR;
+
+    if( num_values < ( NS(math_abscissa_idx_t) )0 )
+    {
+        num_values = ( NS(math_abscissa_idx_t) )0;
+    }
+
+    if( ( capacity < num_values ) &&
+        ( num_values > ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        capacity = num_values;
+    }
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( capacity > ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 2u ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 2u ];
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 2u ];
+
+        buf_size_t num_dataptrs = ( buf_size_t )0u;
+
+        NS(LineDensityProfileData) data;
+        NS(arch_status_t) status = NS(LineDensityProfileData_clear)( &data );
+        status |= NS(LineDensityProfileData_set_capacity)( &data, capacity );
+        status |= NS(LineDensityProfileData_set_num_values)( &data, num_values );
+        status |= NS(LineDensityProfileData_set_method)( &data, method );
+        status |= NS(LineDensityProfileData_set_values_addr)( &data, values_addr );
+        status |= NS(LineDensityProfileData_set_z0)( &data, z0 );
+        status |= NS(LineDensityProfileData_set_z0)( &data, dz );
+        status |= NS(LineDensityProfileData_set_derivatives_addr)(
+                        &data, derivatives_addr );
+        num_dataptrs = NS(LineDensityProfileData_num_dataptrs)( &data );
+
+        if( ( num_dataptrs == ( buf_size_t )2u ) &&
+            ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+        {
+            status = NS(LineDensityProfileData_attributes_offsets)(
+                &offsets[ 0 ], ( buf_size_t )2u, &data, slot_size );
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(LineDensityProfileData_attributes_sizes)(
+                    &sizes[ 0 ], ( buf_size_t )2u, &data, slot_size );
+            }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(LineDensityProfileData_attributes_counts)(
+                    &counts[ 0 ], ( buf_size_t )2u, &data, slot_size );
+            }
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+                )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, &data, sizeof( data ),
+                        NS(LineDensityProfileData_type_id)(), num_dataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        added_elem = SIXTRL_NULLPTR;
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( data != SIXTRL_NULLPTR ) )
+    {
+        buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+        NS(arch_status_t) status = ( NS(arch_status_t)
+            )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 2u ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 2u ];
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 2u ];
+
+        buf_size_t num_dataptrs = ( buf_size_t )0u;
+        num_dataptrs = NS(LineDensityProfileData_num_dataptrs)( data );
+
+        if( num_dataptrs == ( buf_size_t )2u )
+        {
+            status = NS(LineDensityProfileData_attributes_offsets)(
+                &offsets[ 0 ], ( buf_size_t )2u, data, slot_size );
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(LineDensityProfileData_attributes_sizes)(
+                    &sizes[ 0 ], ( buf_size_t )2u, data, slot_size );
+            }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(LineDensityProfileData_attributes_counts)(
+                    &counts[ 0 ], ( buf_size_t )2u, data, slot_size );
+            }
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+                )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, data, sizeof( NS(LineDensityProfileData) ),
+                        NS(LineDensityProfileData_type_id)(), num_dataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
 }
 
 /* ************************************************************************* */
-/* BeamBeam6D: */
+/* NS(SCInterpolatedProfile): */
 
-NS(buffer_size_t) NS(BeamBeam6D_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const beam_beam )
+NS(object_type_id_t) NS(SCInterpolatedProfile_type_id_ext)(
+    void ) SIXTRL_NOEXCEPT
 {
-    return NS(BeamBeam6D_get_required_num_dataptrs_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        beam_beam, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(SCInterpolatedProfile_type_id)();
 }
 
 NS(buffer_size_t)
-NS(BeamBeam6D_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const beam_beam )
+NS(SCInterpolatedProfile_interpol_data_addr_offset_ext)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
 {
-    return NS(BeamBeam6D_get_required_num_slots_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        beam_beam, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(SCInterpolatedProfile_interpol_data_addr_offset)(
+        sc_elem );
 }
 
-bool NS(BeamBeam6D_can_be_added)(
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile) const*
+NS(SCInterpolatedProfile_const_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(SCInterpolatedProfile_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile)* NS(SCInterpolatedProfile_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(SCInterpolatedProfile_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
+}
+
+NS(arch_status_t) NS(SCInterpolatedProfile_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets, SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(SCInterpolatedProfile) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+
+    if( ( offsets_begin != SIXTRL_NULLPTR ) && ( data != SIXTRL_NULLPTR ) &&
+        ( slot_size > ZERO ) )
+    {
+        status = NS(ARCH_STATUS_SUCCESS);
+
+        if( max_num_offsets > ZERO )
+        {
+            SIXTRACKLIB_SET_VALUES(
+                buf_size_t, offsets_begin, max_num_offsets, ZERO );
+        }
+    }
+
+    return status;
+}
+
+NS(arch_status_t) NS(SCInterpolatedProfile_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+
+    if( ( sizes_begin != SIXTRL_NULLPTR ) && ( data != SIXTRL_NULLPTR ) &&
+        ( slot_size > ZERO ) )
+    {
+        status = NS(ARCH_STATUS_SUCCESS);
+
+        if( max_num_sizes > ZERO )
+        {
+            SIXTRACKLIB_SET_VALUES(
+                buf_size_t, sizes_begin, max_num_sizes, ZERO );
+        }
+    }
+
+    return status;
+}
+
+NS(arch_status_t) NS(SCInterpolatedProfile_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCInterpolatedProfile)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+
+    if( ( counts_begin != SIXTRL_NULLPTR ) && ( data != SIXTRL_NULLPTR ) &&
+        ( slot_size > ( NS(buffer_size_t) )0u ) )
+    {
+        status = NS(ARCH_STATUS_SUCCESS);
+
+        if( max_num_counts > ZERO )
+        {
+            SIXTRACKLIB_SET_VALUES(
+                buf_size_t, counts_begin, max_num_counts, ZERO );
+        }
+    }
+
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+bool NS(SCInterpolatedProfile_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const data_size,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs )
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(BeamBeam6D) elem_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    bool can_be_added = false;
 
-    buf_size_t const sizes[]  = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[] = { data_size };
-    buf_size_t num_dataptrs   = ( buf_size_t )0u;
+    buf_size_t num_dataptrs = ( buf_size_t )0u;
+    NS(SCInterpolatedProfile) sc_elem;
+    NS(SCInterpolatedProfile_preset)( &sc_elem );
 
-    elem_t temp_obj;
-    NS(BeamBeam6D_preset)( &temp_obj );
-    NS(BeamBeam6D_set_data_size)( &temp_obj, data_size );
+    num_dataptrs = NS(SCInterpolatedProfile_num_dataptrs)( &sc_elem );
+    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
 
-    num_dataptrs = NS(BeamBeam6D_get_required_num_dataptrs)( buffer, &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+    can_be_added = NS(Buffer_can_add_object)( buffer, sizeof(
+        NS(SCInterpolatedProfile) ), num_dataptrs, SIXTRL_NULLPTR,
+            SIXTRL_NULLPTR, ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
 
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ),
-        num_dataptrs, &sizes[ 0 ], &counts[ 0 ], ptr_requ_objects,
-            ptr_requ_slots, ptr_requ_dataptrs );
+    return can_be_added;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam6D)* NS(BeamBeam6D_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const data_size )
+SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile)* NS(SCInterpolatedProfile_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(BeamBeam6D) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        added_elem = SIXTRL_NULLPTR;
 
-    buf_size_t const offsets[] = { offsetof( elem_t, data ) };
-    buf_size_t const sizes[]   = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[]  = { data_size };
-    buf_size_t num_dataptrs    = ( buf_size_t )0u;
+    buf_size_t num_dataptrs = ( buf_size_t )0u;
 
-    elem_t temp_obj;
-    NS(BeamBeam6D_preset)( &temp_obj );
-    NS(BeamBeam6D_set_data_size)( &temp_obj, data_size );
+    NS(SCInterpolatedProfile) sc_elem;
+    NS(SCInterpolatedProfile_preset)( &sc_elem );
 
-    num_dataptrs = NS(BeamBeam6D_get_required_num_dataptrs)( buffer, &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+    num_dataptrs = NS(SCInterpolatedProfile_num_dataptrs)(
+        &sc_elem );
+    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_BEAM_BEAM_6D), num_dataptrs,
-                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+    added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+            &sc_elem, sizeof( sc_elem ),
+                NS(SCInterpolatedProfile_type_id)(), num_dataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam6D)* NS(BeamBeam6D_add)(
+SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile)* NS(SCInterpolatedProfile_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const  data_size,
-    NS(beambeam4d_real_ptr_t) SIXTRL_RESTRICT input_data )
+    SIXTRL_REAL_T const number_of_particles,
+    SIXTRL_REAL_T const sigma_x, SIXTRL_REAL_T const sigma_y,
+    SIXTRL_REAL_T const length, SIXTRL_REAL_T const x_co,
+    SIXTRL_REAL_T const y_co,
+    SIXTRL_REAL_T const line_density_prof_fallback,
+    NS(buffer_addr_t) const interpol_data_addr,
+    SIXTRL_REAL_T const min_sigma_diff, bool const enabled )
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(BeamBeam6D) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        added_elem = SIXTRL_NULLPTR;
+
+    buf_size_t num_dataptrs = ( buf_size_t )0u;
+
+    NS(SCInterpolatedProfile) sc_elem;
+    NS(SCInterpolatedProfile_preset)( &sc_elem );
+    NS(SCInterpolatedProfile_set_number_of_particles)(
+        &sc_elem, number_of_particles );
+
+    NS(SCInterpolatedProfile_set_sigma_x)( &sc_elem, sigma_x );
+    NS(SCInterpolatedProfile_set_sigma_y)( &sc_elem, sigma_y );
+    NS(SCInterpolatedProfile_set_length)( &sc_elem, length );
+    NS(SCInterpolatedProfile_set_x_co)( &sc_elem, x_co );
+    NS(SCInterpolatedProfile_set_y_co)( &sc_elem, y_co );
+    NS(SCInterpolatedProfile_set_enabled)( &sc_elem, enabled );
 
-    buf_size_t const offsets[] = { offsetof( elem_t, data ) };
-    buf_size_t const sizes[]   = { sizeof( SIXTRL_REAL_T ) };
-    buf_size_t const counts[]  = { data_size };
-    buf_size_t num_dataptrs    = ( buf_size_t )0u;
+    NS(SCInterpolatedProfile_set_interpol_data_addr)(
+        &sc_elem, interpol_data_addr );
 
-    elem_t temp_obj;
-    NS(BeamBeam6D_preset)( &temp_obj );
-    NS(BeamBeam6D_set_data_size)( &temp_obj, data_size );
-    NS(BeamBeam6D_assign_data_ptr)( &temp_obj, input_data );
-    num_dataptrs = NS(BeamBeam6D_get_required_num_dataptrs)(
-        buffer, SIXTRL_NULLPTR );
+    NS(SCInterpolatedProfile_set_line_density_prof_fallback)(
+        &sc_elem, line_density_prof_fallback );
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_BEAM_BEAM_6D), num_dataptrs,
-                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+    NS(SCInterpolatedProfile_set_min_sigma_diff)(
+        &sc_elem, min_sigma_diff );
+
+    num_dataptrs = NS(SCInterpolatedProfile_num_dataptrs)( &sc_elem );
+    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
+
+    added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+        &sc_elem, sizeof( sc_elem ), NS(SCInterpolatedProfile_type_id)(),
+            num_dataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam6D)* NS(BeamBeam6D_add_copy)(
+SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile)* NS(SCInterpolatedProfile_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT orig )
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
 {
-    return NS(BeamBeam6D_add)( buffer,
-        NS(BeamBeam6D_get_data_size)( orig ),
-        NS(BeamBeam6D_get_data)( ( NS(BeamBeam6D)* )orig ) );
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        added_elem = SIXTRL_NULLPTR;
+
+    buf_size_t num_dataptrs =
+        NS(SCInterpolatedProfile_num_dataptrs)( sc_elem );
+    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
+
+    added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer,
+        sc_elem, sizeof( NS(SCInterpolatedProfile) ),
+            NS(SCInterpolatedProfile_type_id)(), num_dataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+
+    return added_elem;
 }
 
 /* end: sixtracklib/common/be_beamfields/be_beamfields.c */
diff --git a/sixtracklib/common/be_beamfields/be_beamfields.h b/sixtracklib/common/be_beamfields/be_beamfields.h
index b02f6a68..e9868b04 100644
--- a/sixtracklib/common/be_beamfields/be_beamfields.h
+++ b/sixtracklib/common/be_beamfields/be_beamfields.h
@@ -12,6 +12,8 @@
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #include "sixtracklib/common/internal/math_interpol.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
     #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
@@ -31,14 +33,10 @@ extern "C" {
 /* ************************************************************************* */
 /* BeamBeam4D: */
 
-typedef SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* NS(beambeam4d_real_ptr_t);
-typedef SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const*
-        NS(beambeam4d_real_const_ptr_t);
-
 typedef struct NS(BeamBeam4D)
 {
-    SIXTRL_UINT64_T  size SIXTRL_ALIGN( 8 );
-    NS(beambeam4d_real_ptr_t) SIXTRL_RESTRICT data SIXTRL_ALIGN( 8 );
+    SIXTRL_UINT64_T   data_size SIXTRL_ALIGN( 8 );
+    NS(buffer_addr_t) data_addr SIXTRL_ALIGN( 8 );
 }
 NS(BeamBeam4D);
 
@@ -57,306 +55,134 @@ typedef struct
     SIXTRL_REAL_T enabled           SIXTRL_ALIGN( 8 );
 }NS(BB4D_data);
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(BeamBeam4D_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(BeamBeam4D_type_id)(
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(BeamBeam4D_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamBeam4D_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT elem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN  SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamBeam4D_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
 NS(BeamBeam4D_preset)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam );
 
 SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam4D_clear)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam );
 
-#if !defined( _GPUCODE )
-
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(BeamBeam4D_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const beam_beam );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(BeamBeam4D_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const beam_beam );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(BeamBeam4D_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const data_size,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam4D)*
-NS(BeamBeam4D_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const data_size );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam4D)*
-NS(BeamBeam4D_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const  data_size,
-    NS(beambeam4d_real_ptr_t) SIXTRL_RESTRICT input_data );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam4D)*
-NS(BeamBeam4D_add_copy)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT orig );
-
-#endif /* !defined( _GPUCODE ) */
-
-SIXTRL_STATIC SIXTRL_FN NS(beambeam4d_real_const_ptr_t)
-NS(BeamBeam4D_get_const_data)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN NS(beambeam4d_real_ptr_t) NS(BeamBeam4D_get_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN SIXTRL_UINT64_T NS(BeamBeam4D_get_data_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT beam_beam );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(BeamBeam4D_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam4D_set_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ptr_data );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamBeam4D_set_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT bb_elem,
+    NS(buffer_addr_t) const data_addr ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam4D_set_data_size)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const data_size );
 
-SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam4D_assign_data_ptr)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ptr_data );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(BB4D_data) const*
+NS(BeamBeam4D_const_data)( SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+    SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam4D_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT source );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(BB4D_data)*
+NS(BeamBeam4D_data)( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+    SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
 
-/* ************************************************************************* */
-/* SpaceChargeCoasting: */
 
-typedef SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* NS(sc_coasting_real_ptr_t);
-typedef SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const*
-        NS(sc_coasting_real_const_ptr_t);
+SIXTRL_STATIC SIXTRL_FN NS(arch_size_t) NS(BeamBeam4D_data_size)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
 
-typedef struct NS(SpaceChargeCoasting)
-{
-    SIXTRL_UINT64_T size SIXTRL_ALIGN( 8 );
-    NS(sc_coasting_real_ptr_t) SIXTRL_RESTRICT data SIXTRL_ALIGN( 8 );
-}
-NS(SpaceChargeCoasting);
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamBeam4D_set_data_size)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT bb_elem,
+    NS(arch_size_t) const data_size ) SIXTRL_NOEXCEPT;
 
-typedef struct
-{
-    SIXTRL_REAL_T line_density        SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T sigma_x             SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T sigma_y             SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T length              SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T x_co                SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T y_co                SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T min_sigma_diff      SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T enabled             SIXTRL_ALIGN( 8 );
-}NS(SpaceChargeCoasting_data);
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const*
+NS(BeamBeam4D_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT obj_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(SpaceChargeCoasting_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+NS(BeamBeam4D_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT obj_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(SpaceChargeCoasting_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN  SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)*
-NS(SpaceChargeCoasting_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT beam_beam );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const*
+NS(BeamBeam4D_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeCoasting_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT beam_beam );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+NS(BeamBeam4D_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(SpaceChargeCoasting_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const beam_beam );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(SpaceChargeCoasting_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const beam_beam );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(SpaceChargeCoasting_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const data_size,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeCoasting)*
-NS(SpaceChargeCoasting_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const data_size );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeCoasting)*
-NS(SpaceChargeCoasting_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const  data_size,
-    NS(sc_coasting_real_ptr_t) SIXTRL_RESTRICT input_data );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const*
+NS(BeamBeam4D_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer) const* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeCoasting)*
-NS(SpaceChargeCoasting_add_copy)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+NS(BeamBeam4D_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT orig );
-
-#endif /* !defined( _GPUCODE ) */
-
-SIXTRL_STATIC SIXTRL_FN NS(sc_coasting_real_const_ptr_t)
-NS(SpaceChargeCoasting_get_const_data)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN NS(sc_coasting_real_ptr_t) NS(SpaceChargeCoasting_get_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN SIXTRL_UINT64_T NS(SpaceChargeCoasting_get_data_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeCoasting_set_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ptr_data );
-
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeCoasting_set_data_size)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const data_size );
-
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeCoasting_assign_data_ptr)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ptr_data );
-
-SIXTRL_STATIC SIXTRL_FN int NS(SpaceChargeCoasting_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT source );
-
-/* ************************************************************************* */
-/* SpaceChargeBunched: */
-
-typedef SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* NS(sc_bunched_real_ptr_t);
-typedef SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const*
-        NS(sc_bunched_real_const_ptr_t);
-
-typedef struct NS(SpaceChargeBunched)
-{
-    SIXTRL_UINT64_T size SIXTRL_ALIGN( 8 );
-    NS(sc_bunched_real_ptr_t) SIXTRL_RESTRICT data SIXTRL_ALIGN( 8 );
-}
-NS(SpaceChargeBunched);
-
-typedef struct
-{
-    SIXTRL_REAL_T number_of_particles SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T bunchlength_rms     SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T sigma_x             SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T sigma_y             SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T length              SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T x_co                SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T y_co                SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T min_sigma_diff      SIXTRL_ALIGN( 8 );
-    SIXTRL_REAL_T enabled             SIXTRL_ALIGN( 8 );
-}NS(SpaceChargeBunched_data);
-
-
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(SpaceChargeBunched_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(SpaceChargeBunched_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN  SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)*
-NS(SpaceChargeBunched_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT beam_beam );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamBeam4D_data_addr_offset)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT elem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeBunched_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT beam_beam );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-#if !defined( _GPUCODE )
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(BeamBeam4D_type_id_ext)( void ) SIXTRL_NOEXCEPT;
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(SpaceChargeBunched_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const beam_beam );
+NS(BeamBeam4D_data_addr_offset_ext)( SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D)
+    *const SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(SpaceChargeBunched_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const beam_beam );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(SpaceChargeBunched_can_be_added)(
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(BeamBeam4D_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     NS(buffer_size_t) const data_size,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeBunched)*
-NS(SpaceChargeBunched_new)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+NS(BeamBeam4D_new)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const data_size );
+    NS(buffer_size_t) const data_size );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeBunched)*
-NS(SpaceChargeBunched_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+NS(BeamBeam4D_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const  data_size,
-    NS(sc_bunched_real_ptr_t) SIXTRL_RESTRICT input_data );
+    NS(buffer_size_t) const  data_size,
+    NS(buffer_addr_t) const bb4d_data_addr );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SpaceChargeBunched)*
-NS(SpaceChargeBunched_add_copy)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+NS(BeamBeam4D_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT orig );
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT orig );
 
 #endif /* !defined( _GPUCODE ) */
 
-SIXTRL_STATIC SIXTRL_FN NS(sc_bunched_real_const_ptr_t)
-NS(SpaceChargeBunched_get_const_data)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN NS(sc_bunched_real_ptr_t) NS(SpaceChargeBunched_get_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN SIXTRL_UINT64_T NS(SpaceChargeBunched_get_data_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeBunched_set_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ptr_data );
-
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeBunched_set_data_size)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const data_size );
-
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeBunched_assign_data_ptr)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ptr_data );
-
-SIXTRL_STATIC SIXTRL_FN int NS(SpaceChargeBunched_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT source );
+SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam4D_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT destination,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT source );
 
 /* ************************************************************************* */
 /* BeamBeam6D: */
@@ -367,8 +193,8 @@ typedef SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const*
 
 typedef struct NS(BeamBeam6D)
 {
-    SIXTRL_UINT64_T                           size      SIXTRL_ALIGN( 8 );
-    NS(beambeam6d_real_ptr_t) SIXTRL_RESTRICT data      SIXTRL_ALIGN( 8 );
+    SIXTRL_UINT64_T    data_size    SIXTRL_ALIGN( 8 );
+    NS(buffer_addr_t)  data_addr    SIXTRL_ALIGN( 8 );
 }
 NS(BeamBeam6D);
 
@@ -424,17 +250,16 @@ typedef struct{
 }NS(BB6D_data);
 
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(BeamBeam6D_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(BeamBeam6D_type_id)(
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(BeamBeam6D_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamBeam6D_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+        SIXTRL_RESTRICT elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamBeam6D_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
 NS(BeamBeam6D_preset)(
@@ -443,69 +268,119 @@ NS(BeamBeam6D_preset)(
 SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam6D_clear)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam );
 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(BeamBeam6D_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+        SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamBeam6D_set_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT bb_elem,
+    NS(buffer_addr_t) const data_addr ) SIXTRL_NOEXCEPT;
+
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(BB6D_data) const*
+NS(BeamBeam6D_const_data)( SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+    SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(BB6D_data)*
+NS(BeamBeam6D_data)( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+    SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
+
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_size_t) NS(BeamBeam6D_data_size)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+        SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamBeam6D_set_data_size)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT bb_elem,
+    NS(arch_size_t) const data_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const*
+NS(BeamBeam6D_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT obj_index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+NS(BeamBeam6D_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT obj_index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const*
+NS(BeamBeam6D_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+NS(BeamBeam6D_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
 #if !defined( _GPUCODE )
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(BeamBeam6D_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const beam_beam );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const*
+NS(BeamBeam6D_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer) const* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+NS(BeamBeam6D_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamBeam6D_data_addr_offset)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+        SIXTRL_RESTRICT elem ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(BeamBeam6D_type_id_ext)( void ) SIXTRL_NOEXCEPT;
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(BeamBeam6D_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const beam_beam );
+NS(BeamBeam6D_data_addr_offset_ext)( SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D)
+    *const SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(BeamBeam6D_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     NS(buffer_size_t) const data_size,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam6D)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
 NS(BeamBeam6D_new)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_UINT64_T const data_size );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam6D)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
 NS(BeamBeam6D_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_UINT64_T const  data_size,
-    NS(beambeam6d_real_ptr_t) SIXTRL_RESTRICT input_data );
+    NS(buffer_size_t) const  data_size,
+    NS(buffer_addr_t) const bb4d_data_addr );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BeamBeam6D)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
 NS(BeamBeam6D_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT orig );
 
 #endif /* !defined( _GPUCODE ) */
 
-SIXTRL_STATIC SIXTRL_FN NS(beambeam6d_real_const_ptr_t)
-NS(BeamBeam6D_get_const_data)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN NS(beambeam6d_real_ptr_t) NS(BeamBeam6D_get_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN SIXTRL_UINT64_T NS(BeamBeam6D_get_data_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT beam_beam );
-
-SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam6D_set_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ptr_data );
-
-SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam6D_set_data_size)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const data_size );
-
-SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam6D_assign_data_ptr)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ptr_data );
-
 SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam6D_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT destination,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT source );
 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
 SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam6D_boost)(
     SIXTRL_BE_DATAPTR_DEC NS(BB6D_boost_data)* data,
     SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT x_star,
@@ -537,631 +412,1688 @@ SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam6D_propagate_Sigma_matrix)(
         SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT dS_costheta_ptr,
         SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT dS_sintheta_ptr);
 
-#if !defined(  _GPUCODE ) && defined( __cplusplus )
+/* ************************************************************************* */
+/* SCCoasting: */
+
+typedef struct NS(SCCoasting)
+{
+    SIXTRL_REAL_T   number_of_particles     SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   circumference           SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   sigma_x                 SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   sigma_y                 SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   length                  SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   x_co                    SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   y_co                    SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   min_sigma_diff          SIXTRL_ALIGN( 8 );
+    SIXTRL_UINT64_T enabled                 SIXTRL_ALIGN( 8 );
 }
-#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+NS(SCCoasting);
 
-/* ========================================================================= */
-/* =====             Implementation of inline functions                ===== */
-/* ========================================================================= */
+/* ------------------------------------------------------------------------- */
 
-#if !defined( SIXTRL_NO_INCLUDES )
-    #if !defined( _GPUCODE ) || defined( __CUDACC__ )
-    #include "sixtracklib/common/buffer.h"
-    #endif /* !defined( _GPUCODE ) || defined( __CUDACC__ ) */
-#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_preset)( SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+    SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-#if !defined( _GPUCODE ) && defined( __cplusplus )
-extern "C" {
-#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCCoasting_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-/* ************************************************************************* */
-/* BeamBeam4D: */
+/* ------------------------------------------------------------------------- */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(BeamBeam4D_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size )
-{
-    typedef NS(buffer_size_t) buf_size_t;
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t)
+    NS(SCCoasting_type_id)( void ) SIXTRL_NOEXCEPT;
 
-    buf_size_t num_dataptrs = ( buf_size_t )0u;
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(SCCoasting_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-    if( ( buffer != SIXTRL_NULLPTR ) && ( slot_size > ( buf_size_t )0u ) &&
-        ( beam_beam != SIXTRL_NULLPTR ) &&
-        ( NS(BeamBeam4D_get_data_size)( beam_beam ) > ( buf_size_t )0u ) )
-    {
-        num_dataptrs = ( buf_size_t )1u;
-    }
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(SCCoasting_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT sc_elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-    return num_dataptrs;
-}
+/* ------------------------------------------------------------------------- */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(BeamBeam4D_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size )
-{
-    typedef NS(buffer_size_t) buf_size_t;
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCCoasting_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-    buf_size_t num_slots = ( buf_size_t )0u;
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCCoasting_circumference)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-    if( ( buffer != SIXTRL_NULLPTR ) && ( slot_size > ( buf_size_t )0u ) &&
-        ( beam_beam != SIXTRL_NULLPTR ) &&
-        ( NS(BeamBeam4D_get_data_size)( beam_beam ) > ( buf_size_t )0u ) )
-    {
-        num_slots = NS(ManagedBuffer_get_slot_based_length)(
-            NS(BeamBeam4D_get_data_size)( beam_beam ) * sizeof( SIXTRL_REAL_T ),
-                slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCCoasting_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-        num_slots /= slot_size;
-    }
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCCoasting_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-    return num_slots;
-}
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCCoasting_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam )
-{
-    if( beam_beam != SIXTRL_NULLPTR )
-    {
-        beam_beam->size = ( SIXTRL_UINT64_T )0u;
-        beam_beam->data   = SIXTRL_NULLPTR;
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCCoasting_x_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-        NS(BeamBeam4D_clear)( beam_beam );
-    }
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCCoasting_y_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-    return beam_beam;
-}
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCCoasting_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE void NS(BeamBeam4D_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam )
-{
-    typedef NS(buffer_size_t ) buf_size_t;
+SIXTRL_STATIC SIXTRL_FN bool NS(SCCoasting_enabled)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
 
-    buf_size_t const data_size = NS(BeamBeam4D_get_data_size)( beam_beam );
-    NS(beambeam4d_real_ptr_t) ptr_data = NS(BeamBeam4D_get_data)( beam_beam );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    if( ( data_size > ( NS(buffer_size_t) )0u ) &&
-        ( ptr_data != SIXTRL_NULLPTR ) )
-    {
-        SIXTRL_REAL_T const Z = ( SIXTRL_REAL_T )0;
-        SIXTRACKLIB_SET_VALUES( SIXTRL_REAL_T, ptr_data, data_size, Z );
-    }
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCCoasting_set_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const number_of_particles ) SIXTRL_NOEXCEPT;
 
-    return;
-}
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCCoasting_set_circumference)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const circumference ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE NS(beambeam4d_real_const_ptr_t)
-NS(BeamBeam4D_get_const_data)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT beam_beam )
-{
-    SIXTRL_ASSERT( beam_beam != SIXTRL_NULLPTR );
-    return beam_beam->data;
-}
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCCoasting_set_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const sigma_x ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE NS(beambeam4d_real_ptr_t) NS(BeamBeam4D_get_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam )
-{
-    return ( NS(beambeam4d_real_ptr_t) )NS(BeamBeam4D_get_const_data)( beam_beam );
-}
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCCoasting_set_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const sigma_y ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE SIXTRL_UINT64_T NS(BeamBeam4D_get_data_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT beam_beam )
-{
-    SIXTRL_ASSERT( beam_beam != SIXTRL_NULLPTR );
-    return beam_beam->size;
-}
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCCoasting_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const length ) SIXTRL_NOEXCEPT;
 
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCCoasting_set_x_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const x_co ) SIXTRL_NOEXCEPT;
 
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCCoasting_set_y_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const y_co ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE void NS(BeamBeam4D_set_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ptr_data )
-{
-    typedef SIXTRL_REAL_T real_t;
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCCoasting_set_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const min_sigma_diff ) SIXTRL_NOEXCEPT;
 
-    NS(buffer_size_t) const size =
-        NS(BeamBeam4D_get_data_size)( beam_beam );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCCoasting_set_enabled)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT belem,
+    bool const is_enabled ) SIXTRL_NOEXCEPT;
 
-    NS(beambeam4d_real_ptr_t) ptr_dest_data =
-        NS(BeamBeam4D_get_data)( beam_beam );
+/* ------------------------------------------------------------------------- */
 
-    SIXTRL_ASSERT( ptr_dest_data != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ptr_data      != SIXTRL_NULLPTR );
-    SIXTRACKLIB_COPY_VALUES( real_t, ptr_dest_data, ptr_data, size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) const*
+NS(SCCoasting_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    const NS(Object) *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT;
 
-    return;
-}
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE void NS(BeamBeam4D_set_data_size)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const data_size )
-{
-    SIXTRL_ASSERT( beam_beam != SIXTRL_NULLPTR );
-    beam_beam->size = data_size;
-    return;
-}
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) const*
+NS(SCCoasting_const_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC
+        unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE void NS(BeamBeam4D_assign_data_ptr)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ptr_data )
-{
-    SIXTRL_ASSERT( beam_beam != SIXTRL_NULLPTR );
-    beam_beam->data = ptr_data;
-    return;
-}
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC
+        unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE int NS(BeamBeam4D_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT source )
-{
-    int success = -1;
+#if !defined( _GPUCODE )
 
-    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) &&
-        ( destination != source ) &&
-        ( NS(BeamBeam4D_get_const_data)( destination ) != SIXTRL_NULLPTR ) &&
-        ( NS(BeamBeam4D_get_const_data)( source      ) != SIXTRL_NULLPTR ) &&
-        ( NS(BeamBeam4D_get_data_size)( destination ) ==
-          NS(BeamBeam4D_get_data_size)( source ) ) )
-    {
-        SIXTRL_ASSERT( NS(BeamBeam4D_get_const_data)( destination ) !=
-                       NS(BeamBeam4D_get_const_data)( source ) );
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(SCCoasting_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) const*
+NS(SCCoasting_const_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCCoasting_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCCoasting_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCCoasting_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(SCCoasting_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-        SIXTRACKLIB_COPY_VALUES( SIXTRL_REAL_T,
-            NS(BeamBeam4D_get_data)( destination ),
-            NS(BeamBeam4D_get_const_data)( source ),
-            NS(BeamBeam4D_get_data_size)( source ) );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer );
 
-        success = 0;
-    }
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_REAL_T const number_of_particles, SIXTRL_REAL_T const circumference,
+    SIXTRL_REAL_T const sigma_x, SIXTRL_REAL_T const sigma_y,
+    SIXTRL_REAL_T const length, SIXTRL_REAL_T const x_co,
+    SIXTRL_REAL_T const y_co, SIXTRL_REAL_T const min_sigma_diff,
+    bool const enabled );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-    return success;
-}
+#endif /* !defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCCoasting_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
 
 /* ************************************************************************* */
-/* SpaceChargeBunched: */
+/* NS(SCQGaussProfile): */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(SpaceChargeBunched_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT sc,
-    NS(buffer_size_t) const slot_size )
+typedef struct NS(SCQGaussProfile)
 {
-    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_REAL_T   number_of_particles   SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   bunchlength_rms       SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   sigma_x               SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   sigma_y               SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   length                SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   x_co                  SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   y_co                  SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   min_sigma_diff        SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   q_param               SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T   cq                    SIXTRL_ALIGN( 8 );
+    SIXTRL_UINT64_T enabled               SIXTRL_ALIGN( 8 );
+}
+NS(SCQGaussProfile);
 
-    buf_size_t num_dataptrs = ( buf_size_t )0u;
+/* ------------------------------------------------------------------------- */
 
-    if( ( slot_size > ( buf_size_t )0u ) && ( buffer != SIXTRL_NULLPTR ) &&
-        ( sc != SIXTRL_NULLPTR ) &&
-        ( NS(SpaceChargeBunched_get_data_size)( sc ) > ( buf_size_t )0u ) )
-    {
-        num_dataptrs = ( buf_size_t )1u;
-    }
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_preset)( SIXTRL_BE_ARGPTR_DEC
+    NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-    return num_dataptrs;
-}
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCQGaussProfile_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(SpaceChargeBunched_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT sc,
-    NS(buffer_size_t) const slot_size )
-{
-    typedef NS(buffer_size_t) buf_size_t;
+/* ------------------------------------------------------------------------- */
 
-    buf_size_t num_slots = ( buf_size_t )0u;
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t)
+NS(SCQGaussProfile_type_id)( void ) SIXTRL_NOEXCEPT;
 
-    if( ( slot_size > ( buf_size_t )0u ) && ( buffer != SIXTRL_NULLPTR ) &&
-        ( sc != SIXTRL_NULLPTR ) &&
-        ( NS(SpaceChargeBunched_get_data_size)( sc ) > ( buf_size_t )0u ) )
-    {
-        num_slots = NS(ManagedBuffer_get_slot_based_length)(
-            NS(SpaceChargeBunched_get_data_size)( sc ) * sizeof( SIXTRL_REAL_T ),
-                slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(SCQGaussProfile_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-        num_slots /= slot_size;
-    }
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(SCQGaussProfile_num_slots)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCQGaussProfile) *const SIXTRL_RESTRICT sc_elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCQGaussProfile_number_of_particles)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCQGaussProfile_bunchlength_rms)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCQGaussProfile_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCQGaussProfile_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCQGaussProfile_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCQGaussProfile_x_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCQGaussProfile_y_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCQGaussProfile_min_sigma_diff)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCQGaussProfile_q_param)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCQGaussProfile_cq)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(SCQGaussProfile_enabled)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT belem ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const number_of_particles ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_bunchlength_rms)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const circumference ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const sigma_x ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const sigma_y ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const length ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_x_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const x_co ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_y_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const y_co ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const min_sigma_diff ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_q_param)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    SIXTRL_REAL_T const q_param ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCQGaussProfile_set_enabled)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT belem,
+    bool const is_enabled ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCQGaussProfile) const*
+NS(SCQGaussProfile_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC
+    NS(SCQGaussProfile) const*
+NS(SCQGaussProfile_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC
+        unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-    return num_slots;
-}
+#if !defined( _GPUCODE )
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)*
-NS(SpaceChargeBunched_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT sc )
-{
-    if( sc != SIXTRL_NULLPTR )
-    {
-        sc->size = ( SIXTRL_UINT64_T )0u;
-        sc->data   = SIXTRL_NULLPTR;
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(SCQGaussProfile_type_id_ext)( void ) SIXTRL_NOEXCEPT;
 
-        NS(SpaceChargeBunched_clear)( sc );
-    }
+/* ------------------------------------------------------------------------- */
 
-    return sc;
-}
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCQGaussProfile) const*
+NS(SCQGaussProfile_const_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE void NS(SpaceChargeBunched_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT sc )
-{
-    typedef NS(buffer_size_t ) buf_size_t;
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCQGaussProfile)* NS(SCQGaussProfile_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCQGaussProfile_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCQGaussProfile_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCQGaussProfile_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(SCQGaussProfile_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-    buf_size_t const data_size = NS(SpaceChargeBunched_get_data_size)( sc );
-    NS(sc_bunched_real_ptr_t) ptr_data = NS(SpaceChargeBunched_get_data)( sc );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCQGaussProfile)* NS(SCQGaussProfile_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
 
-    if( ( data_size > ( NS(buffer_size_t) )0u ) &&
-        ( ptr_data != SIXTRL_NULLPTR ) )
-    {
-        SIXTRL_REAL_T const Z = ( SIXTRL_REAL_T )0;
-        SIXTRACKLIB_SET_VALUES( SIXTRL_REAL_T, ptr_data, data_size, Z );
-    }
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCQGaussProfile)* NS(SCQGaussProfile_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_REAL_T const number_of_particles,
+    SIXTRL_REAL_T const bunchlength_rms,
+    SIXTRL_REAL_T const sigma_x, SIXTRL_REAL_T const sigma_y,
+    SIXTRL_REAL_T const length,
+    SIXTRL_REAL_T const x_co, SIXTRL_REAL_T const y_co,
+    SIXTRL_REAL_T const min_sigma_diff,
+    SIXTRL_REAL_T const q_param, bool const enabled );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCQGaussProfile)* NS(SCQGaussProfile_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-    return;
-}
+#endif /* !defined( _GPUCODE ) */
 
-SIXTRL_INLINE NS(sc_bunched_real_const_ptr_t)
-NS(SpaceChargeBunched_get_const_data)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT sc )
-{
-    SIXTRL_ASSERT( sc != SIXTRL_NULLPTR );
-    return sc->data;
-}
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCQGaussProfile_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE NS(sc_bunched_real_ptr_t)
-NS(SpaceChargeBunched_get_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT sc )
-{
-    return ( NS(sc_bunched_real_ptr_t) )NS(SpaceChargeBunched_get_const_data)( sc );
-}
+/* ************************************************************************* */
+/* NS(SCInterpolatedProfile): */
 
-SIXTRL_INLINE SIXTRL_UINT64_T NS(SpaceChargeBunched_get_data_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT sc )
+typedef struct NS(LineDensityProfileData)
 {
-    SIXTRL_ASSERT( sc != SIXTRL_NULLPTR );
-    return sc->size;
+    NS(math_interpol_int_t) method           SIXTRL_ALIGN( 8 );
+    NS(math_abscissa_idx_t) capacity         SIXTRL_ALIGN( 8 );
+    NS(buffer_addr_t)       values_addr      SIXTRL_ALIGN( 8 );
+    NS(buffer_addr_t)       derivatives_addr SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T           z0               SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T           dz               SIXTRL_ALIGN( 8 );
+    NS(math_abscissa_idx_t) num_values       SIXTRL_ALIGN( 8 );
 }
+NS(LineDensityProfileData);
 
+/* ------------------------------------------------------------------------- */
 
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_preset)( SIXTRL_BE_ARGPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE void NS(SpaceChargeBunched_set_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT sc,
-    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ptr_data )
-{
-    typedef SIXTRL_REAL_T real_t;
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LineDensityProfileData_clear)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-    NS(buffer_size_t) const size =
-        NS(SpaceChargeBunched_get_data_size)( sc );
+/* ------------------------------------------------------------------------- */
 
-    NS(sc_bunched_real_ptr_t) ptr_dest_data =
-        NS(SpaceChargeBunched_get_data)( sc );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t)
+    NS(LineDensityProfileData_type_id)( void ) SIXTRL_NOEXCEPT;
 
-    SIXTRL_ASSERT( ptr_dest_data != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ptr_data      != SIXTRL_NULLPTR );
-    SIXTRACKLIB_COPY_VALUES( real_t, ptr_dest_data, ptr_data, size );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(LineDensityProfileData_num_dataptrs)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-    return;
-}
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(LineDensityProfileData_num_slots)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(LineDensityProfileData) *const SIXTRL_RESTRICT sc_elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
 
-SIXTRL_INLINE void NS(SpaceChargeBunched_set_data_size)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT sc,
-    NS(buffer_size_t) const data_size )
-{
-    SIXTRL_ASSERT( sc != SIXTRL_NULLPTR );
-    sc->size = data_size;
-    return;
-}
+SIXTRL_STATIC SIXTRL_FN NS(math_interpol_t) NS(LineDensityProfileData_method)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE void NS(SpaceChargeBunched_assign_data_ptr)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT sc,
-    SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ptr_data )
-{
-    SIXTRL_ASSERT( sc != SIXTRL_NULLPTR );
-    sc->data = ptr_data;
-    return;
-}
+SIXTRL_STATIC SIXTRL_FN NS(math_abscissa_idx_t)
+NS(LineDensityProfileData_num_values)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE int NS(SpaceChargeBunched_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeBunched)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT source )
-{
-    int success = -1;
+SIXTRL_STATIC SIXTRL_FN NS(math_abscissa_idx_t)
+NS(LineDensityProfileData_capacity)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(LineDensityProfileData_values_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(LineDensityProfileData_derivatives_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
 
-    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) &&
-        ( destination != source ) &&
-        ( NS(SpaceChargeBunched_get_const_data)( destination ) != SIXTRL_NULLPTR ) &&
-        ( NS(SpaceChargeBunched_get_const_data)( source      ) != SIXTRL_NULLPTR ) &&
-        ( NS(SpaceChargeBunched_get_data_size)( destination ) ==
-          NS(SpaceChargeBunched_get_data_size)( source ) ) )
-    {
-        SIXTRL_ASSERT( NS(SpaceChargeBunched_get_const_data)( destination ) !=
-                       NS(SpaceChargeBunched_get_const_data)( source ) );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const*
+NS(LineDensityProfileData_const_values_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const*
+NS(LineDensityProfileData_const_values_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+NS(LineDensityProfileData_values_begin)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+NS(LineDensityProfileData_values_end)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(LineDensityProfileData_value_at_idx)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data,
+    NS(math_abscissa_idx_t) const idx ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const*
+NS(LineDensityProfileData_const_derivatives_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const*
+NS(LineDensityProfileData_const_derivatives_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+NS(LineDensityProfileData_derivatives_begin)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+NS(LineDensityProfileData_derivatives_end)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(LineDensityProfileData_derivatives_at_idx)( SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(LineDensityProfileData) *const SIXTRL_RESTRICT data,
+    NS(math_abscissa_idx_t) const idx ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(LineDensityProfileData_z0)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(LineDensityProfileData_dz)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(LineDensityProfileData_z_min)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(LineDensityProfileData_z_max)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(math_abscissa_idx_t)
+NS(LineDensityProfileData_find_idx)( SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(LineDensityProfileData) *const SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(LineDensityProfileData_interpolate_value)( SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(LineDensityProfileData) *const SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(LineDensityProfileData_interpolate_1st_derivative)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(LineDensityProfileData_interpolate_2nd_derivative)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LineDensityProfileData_prepare_interpolation)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_ARGPTR_DEC SIXTRL_REAL_T*
+        SIXTRL_RESTRICT temp_data ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-        SIXTRACKLIB_COPY_VALUES( SIXTRL_REAL_T,
-            NS(SpaceChargeBunched_get_data)( destination ),
-            NS(SpaceChargeBunched_get_const_data)( source ),
-            NS(SpaceChargeBunched_get_data_size)( source ) );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_num_values)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_capacity)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(math_abscissa_idx_t) const capacity ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_z0)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z0 ) SIXTRL_NOEXCEPT;
 
-        success = 0;
-    }
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_dz)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z0 ) SIXTRL_NOEXCEPT;
 
-    return success;
-}
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_values_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const values_addr ) SIXTRL_NOEXCEPT;
 
-/* ************************************************************************* */
-/* SpaceChargeCoasting: */
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_derivatives_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const derivatives_addr ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_method)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(math_interpol_t) const method ) SIXTRL_NOEXCEPT;
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(SpaceChargeCoasting_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT sc,
-    NS(buffer_size_t) const slot_size )
-{
-    typedef NS(buffer_size_t) buf_size_t;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    buf_size_t num_dataptrs = ( buf_size_t )0u;
+#if !defined( _GPUCODE )
 
-    if( ( slot_size > ( buf_size_t )0u ) &&
-        ( sc != SIXTRL_NULLPTR ) &&
-        ( NS(SpaceChargeCoasting_get_data_size)( sc ) > ( buf_size_t )0u ) )
-    {
-        num_dataptrs = ( buf_size_t )1u;
-    }
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(LineDensityProfileData_values_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
 
-    ( void )buffer;
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(LineDensityProfileData_derivatives_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
 
-    return num_dataptrs;
-}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(SpaceChargeCoasting_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT sc,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(LineDensityProfileData_values_offset_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(LineDensityProfileData_derivatives_offset_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_prepare_interpolation_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(LineDensityProfileData_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(LineDensityProfileData_z0_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(LineDensityProfileData_dz_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(LineDensityProfileData_z_min_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(LineDensityProfileData_z_max_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(math_abscissa_idx_t)
+NS(LineDensityProfileData_find_idx_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(LineDensityProfileData) *const SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T
+NS(LineDensityProfileData_interpolate_value_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+        const NS(LineDensityProfileData) *const SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T
+NS(LineDensityProfileData_interpolate_1st_derivative_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T
+NS(LineDensityProfileData_interpolate_2nd_derivative_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_z0_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z0 ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_dz_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z0 ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_values_addr_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+        NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const values_addr ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_derivatives_addr_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data, NS(buffer_addr_t) const
+        derivatives_addr ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_set_method_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(math_interpol_t) const method ) SIXTRL_NOEXCEPT;
+
+#endif /* Host */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LineDensityProfileData) const*
+NS(LineDensityProfileData_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LineDensityProfileData) const*
+NS(LineDensityProfileData_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC
+        unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(LineDensityProfileData) const* NS(LineDensityProfileData_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LineDensityProfileData_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(LineDensityProfileData_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(math_abscissa_idx_t) const capacity,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(LineDensityProfileData)* NS(LineDensityProfileData_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(math_abscissa_idx_t) const capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(LineDensityProfileData)* NS(LineDensityProfileData_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(math_interpol_t) const method, NS(math_abscissa_idx_t) num_values,
+    NS(buffer_addr_t) const values_addr,
+    NS(buffer_addr_t) const derivatives_addr,
+    SIXTRL_REAL_T const z0, SIXTRL_REAL_T const dz,
+    NS(math_abscissa_idx_t) capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(LineDensityProfileData)* NS(LineDensityProfileData_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+#endif /* !defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LineDensityProfileData_copy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
+
+/* ************************************************************************* */
+
+typedef struct NS(SCInterpolatedProfile)
 {
-    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_REAL_T     number_of_particles        SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T     sigma_x                    SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T     sigma_y                    SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T     length                     SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T     x_co                       SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T     y_co                       SIXTRL_ALIGN( 8 );
+    NS(buffer_addr_t) interpol_data_addr         SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T     line_density_prof_fallback SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T     min_sigma_diff             SIXTRL_ALIGN( 8 );
+    SIXTRL_UINT64_T   enabled                    SIXTRL_ALIGN( 8 );
+}
+NS(SCInterpolatedProfile);
 
-    buf_size_t num_slots = ( buf_size_t )0u;
+/* ------------------------------------------------------------------------- */
 
-    if( ( slot_size > ( buf_size_t )0u ) && ( sc != SIXTRL_NULLPTR ) &&
-        ( NS(SpaceChargeCoasting_get_data_size)( sc ) > ( buf_size_t )0u ) )
-    {
-        num_slots = NS(ManagedBuffer_get_slot_based_length)(
-            NS(SpaceChargeCoasting_get_data_size)( sc ) * sizeof( SIXTRL_REAL_T ),
-                slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+NS(SCInterpolatedProfile_preset)( SIXTRL_BE_ARGPTR_DEC
+    NS(SCInterpolatedProfile)* SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
-        num_slots /= slot_size;
-    }
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_clear)( SIXTRL_BE_ARGPTR_DEC
+    NS(SCInterpolatedProfile)* SIXTRL_RESTRICT
+        sc_elem ) SIXTRL_NOEXCEPT;
 
-    ( void )buffer;
+/* ------------------------------------------------------------------------- */
 
-    return num_slots;
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t)
+NS(SCInterpolatedProfile_type_id)( void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(SCInterpolatedProfile_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(SCInterpolatedProfile_num_slots)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCInterpolatedProfile) *const SIXTRL_RESTRICT sc_elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(SCInterpolatedProfile_interpol_data_addr_offset)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN bool
+NS(SCInterpolatedProfile_has_interpol_data)( SIXTRL_BE_ARGPTR_DEC
+    const NS(SCInterpolatedProfile) *const SIXTRL_RESTRICT
+        sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(SCInterpolatedProfile_interpol_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(LineDensityProfileData) const*
+NS(SCInterpolatedProfile_const_line_density_profile_data)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(SCInterpolatedProfile_line_density_profile_data)( SIXTRL_BE_ARGPTR_DEC
+    NS(SCInterpolatedProfile)* SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_number_of_particles)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_line_density_prof_fallback)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_sigma_x)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_sigma_y)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_length)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCInterpolatedProfile_x_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SCInterpolatedProfile_y_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_min_sigma_diff)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(SCInterpolatedProfile_enabled)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_interpol_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    NS(buffer_addr_t) const interpol_data_addr ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const number_of_particles ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_line_density_prof_fallback)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const line_density_prof_fallback ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const sigma_x ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const sigma_y ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const length ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_x_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const x_co ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_y_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const y_co ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const min_sigma_diff ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_set_enabled)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, bool const is_enabled ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_line_density_profile)( SIXTRL_BE_ARGPTR_DEC
+    NS(SCInterpolatedProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_line_density_profile_1st_derivative)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(SCInterpolatedProfile_line_density_profile_2nd_derivative)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_prepare_interpolation)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_ARGPTR_DEC SIXTRL_REAL_T*
+            SIXTRL_RESTRICT temp_data ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN
+SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile) const*
+NS(SCInterpolatedProfile_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const
+        SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN
+SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+NS(SCInterpolatedProfile_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+        SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT;
+
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile) const*
+NS(SCInterpolatedProfile_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+NS(SCInterpolatedProfile_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+    NS(SCInterpolatedProfile_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(SCInterpolatedProfile_interpol_data_addr_offset_ext)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile) const*
+NS(SCInterpolatedProfile_const_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC
+        const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile)* NS(SCInterpolatedProfile_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(SCInterpolatedProfile_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile)
+        *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(SCInterpolatedProfile_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile)* NS(SCInterpolatedProfile_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile)* NS(SCInterpolatedProfile_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_REAL_T const number_of_particles,
+    SIXTRL_REAL_T const sigma_x, SIXTRL_REAL_T const sigma_y,
+    SIXTRL_REAL_T const length, SIXTRL_REAL_T const x_co,
+    SIXTRL_REAL_T const y_co,
+    SIXTRL_REAL_T const line_density_prof_fallback_value,
+    NS(buffer_addr_t) const interpol_data_addr,
+    SIXTRL_REAL_T const min_sigma_diff, bool const enabled );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC
+NS(SCInterpolatedProfile)* NS(SCInterpolatedProfile_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
+
+#endif /* !defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SCInterpolatedProfile_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)* SIXTRL_RESTRICT dest,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* ========================================================================= */
+/* =====             Implementation of inline functions                ===== */
+/* ========================================================================= */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #if !defined( _GPUCODE ) || defined( __CUDACC__ )
+    #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) || defined( __CUDACC__ ) */
+
+    #include "sixtracklib/common/internal/math_qgauss.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* ************************************************************************* */
+/* BeamBeam4D: */
+
+SIXTRL_INLINE NS(object_type_id_t)
+    NS(BeamBeam4D_type_id)( void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_BEAM_BEAM_4D);
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)*
-NS(SpaceChargeCoasting_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT sc )
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamBeam4D_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( elem ) ) SIXTRL_NOEXCEPT
 {
-    if( sc != SIXTRL_NULLPTR )
+    return ( NS(buffer_size_t) )1u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamBeam4D_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) st_size_t;
+    st_size_t num_slots = ( st_size_t )0u;
+
+    if( ( elem != SIXTRL_NULLPTR ) && ( slot_size > ( st_size_t )0 ) )
     {
-        sc->size = ( SIXTRL_UINT64_T )0u;
-        sc->data   = SIXTRL_NULLPTR;
+        st_size_t num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(BeamBeam4D) ), slot_size );
 
-        NS(SpaceChargeCoasting_clear)( sc );
+        st_size_t const stored_data_size =
+            NS(BeamBeam4D_data_size)( elem ) * sizeof( SIXTRL_REAL_T );
+
+        SIXTRL_ASSERT( stored_data_size >=
+            NS(ManagedBuffer_get_slot_based_length)( sizeof(
+                NS(BB4D_data) ), slot_size ) );
+
+        SIXTRL_ASSERT( ( stored_data_size % slot_size ) == ( st_size_t )0 );
+        num_bytes += stored_data_size;
+        num_slots  = num_bytes / slot_size;
+
+        if( num_slots * slot_size < num_bytes ) ++num_slots;
     }
 
-    return sc;
+    return num_slots;
 }
 
-SIXTRL_INLINE void NS(SpaceChargeCoasting_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT sc )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT bb_elem )
 {
-    typedef NS(buffer_size_t ) buf_size_t;
+    if( bb_elem != SIXTRL_NULLPTR ) NS(BeamBeam4D_clear)( bb_elem );
+    return bb_elem;
+}
 
-    buf_size_t const data_size = NS(SpaceChargeCoasting_get_data_size)( sc );
-    NS(sc_coasting_real_ptr_t) ptr_data = NS(SpaceChargeCoasting_get_data)( sc );
+SIXTRL_INLINE void NS(BeamBeam4D_clear)( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+    SIXTRL_RESTRICT bb_elem )
+{
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    NS(arch_status_t) status = NS(BeamBeam4D_set_data_addr)(
+        bb_elem, ( NS(buffer_addr_t) )0 );
 
-    if( ( data_size > ( NS(buffer_size_t) )0u ) &&
-        ( ptr_data != SIXTRL_NULLPTR ) )
-    {
-        SIXTRL_REAL_T const Z = ( SIXTRL_REAL_T )0;
-        SIXTRACKLIB_SET_VALUES( SIXTRL_REAL_T, ptr_data, data_size, Z );
-    }
+    status |= NS(BeamBeam4D_set_data_size)(
+        bb_elem, ( NS(buffer_size_t) )0 );
 
-    return;
+    SIXTRL_ASSERT( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS );
 }
 
-SIXTRL_INLINE NS(sc_coasting_real_const_ptr_t)
-NS(SpaceChargeCoasting_get_const_data)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT sc )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(BeamBeam4D_data_addr)( SIXTRL_BE_ARGPTR_DEC
+    const NS(BeamBeam4D) *const SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( sc != SIXTRL_NULLPTR );
-    return sc->data;
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    return bb_elem->data_addr;
 }
 
-SIXTRL_INLINE NS(sc_coasting_real_ptr_t)
-NS(SpaceChargeCoasting_get_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT sc )
+SIXTRL_INLINE NS(arch_status_t) NS(BeamBeam4D_set_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT bb_elem,
+    NS(buffer_addr_t) const data_addr ) SIXTRL_NOEXCEPT
 {
-    return ( NS(sc_coasting_real_ptr_t) )NS(SpaceChargeCoasting_get_const_data)( sc );
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    bb_elem->data_addr = data_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE SIXTRL_UINT64_T NS(SpaceChargeCoasting_get_data_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT sc )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(BB4D_data) const*
+NS(BeamBeam4D_const_data)( SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+    SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( sc != SIXTRL_NULLPTR );
-    return sc->size;
+    return ( SIXTRL_BE_DATAPTR_DEC NS(BB4D_data) const* )( uintptr_t
+        )NS(BeamBeam4D_data_addr)( bb_elem );
 }
 
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(BB4D_data)* NS(BeamBeam4D_data)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+        SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_DATAPTR_DEC NS(BB4D_data)* )( uintptr_t
+        )NS(BeamBeam4D_data_addr)( bb_elem );
+}
 
+SIXTRL_INLINE NS(arch_size_t) NS(BeamBeam4D_data_size)( SIXTRL_BE_ARGPTR_DEC
+    const NS(BeamBeam4D) *const SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    return bb_elem->data_size;
+}
 
-SIXTRL_INLINE void NS(SpaceChargeCoasting_set_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT sc,
-    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ptr_data )
+SIXTRL_INLINE NS(arch_status_t) NS(BeamBeam4D_set_data_size)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT bb_elem,
+    NS(arch_size_t) const data_size ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_REAL_T real_t;
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    NS(buffer_size_t) min_bb4_data_size =
+        NS(ManagedBuffer_get_slot_based_length)( sizeof( NS(BB4D_data) ),
+            ( NS(buffer_size_t) )8u );
+    min_bb4_data_size /= sizeof( SIXTRL_REAL_T );
 
-    NS(buffer_size_t) const size =
-        NS(SpaceChargeCoasting_get_data_size)( sc );
 
-    NS(sc_coasting_real_ptr_t) ptr_dest_data =
-        NS(SpaceChargeCoasting_get_data)( sc );
+    if( ( bb_elem != SIXTRL_NULLPTR ) &&
+        ( ( data_size == ( NS(buffer_size_t) )0 ) ||
+          ( data_size >= min_bb4_data_size ) ) )
+    {
+        bb_elem->data_size = data_size;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
 
-    SIXTRL_ASSERT( ptr_dest_data != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ptr_data      != SIXTRL_NULLPTR );
-    SIXTRACKLIB_COPY_VALUES( real_t, ptr_dest_data, ptr_data, size );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    return;
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const*
+NS(BeamBeam4D_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+     return (
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_BEAM_BEAM_4D) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(BeamBeam4D) ) ) )
+        ? ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const* )( uintptr_t
+            )NS(Object_get_begin_addr)( obj )
+        : SIXTRL_NULLPTR;
 }
 
-SIXTRL_INLINE void NS(SpaceChargeCoasting_set_data_size)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT sc,
-    NS(buffer_size_t) const data_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+NS(BeamBeam4D_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT obj_index ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( sc != SIXTRL_NULLPTR );
-    sc->size = data_size;
-    return;
+    return ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+        )NS(BeamBeam4D_const_from_obj_index)( obj_index );
 }
 
-SIXTRL_INLINE void NS(SpaceChargeCoasting_assign_data_ptr)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT sc,
-    SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ptr_data )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const*
+NS(BeamBeam4D_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( sc != SIXTRL_NULLPTR );
-    sc->data = ptr_data;
-    return;
+    return NS(BeamBeam4D_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
 }
 
-SIXTRL_INLINE int NS(SpaceChargeCoasting_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(SpaceChargeCoasting)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT source )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+NS(BeamBeam4D_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    int success = -1;
+    return NS(BeamBeam4D_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
 
-    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) &&
-        ( destination != source ) &&
-        ( NS(SpaceChargeCoasting_get_const_data)( destination ) != SIXTRL_NULLPTR ) &&
-        ( NS(SpaceChargeCoasting_get_const_data)( source      ) != SIXTRL_NULLPTR ) &&
-        ( NS(SpaceChargeCoasting_get_data_size)( destination ) ==
-          NS(SpaceChargeCoasting_get_data_size)( source ) ) )
-    {
-        SIXTRL_ASSERT( NS(SpaceChargeCoasting_get_const_data)( destination ) !=
-                       NS(SpaceChargeCoasting_get_const_data)( source ) );
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const*
+NS(BeamBeam4D_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer) const* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamBeam4D_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* NS(BeamBeam4D_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamBeam4D_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamBeam4D_data_addr_offset)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( elem ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )offsetof( NS(BeamBeam4D), data_addr );
+}
+
+#endif /* _GPUCODE */
+
+SIXTRL_INLINE NS(arch_status_t) NS(BeamBeam4D_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* SIXTRL_RESTRICT destination,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT source )
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-        SIXTRACKLIB_COPY_VALUES( SIXTRL_REAL_T,
-            NS(SpaceChargeCoasting_get_data)( destination ),
-            NS(SpaceChargeCoasting_get_const_data)( source ),
-            NS(SpaceChargeCoasting_get_data_size)( source ) );
+    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) )
+    {
+        if( destination != source )
+        {
+            SIXTRL_BE_DATAPTR_DEC NS(BB4D_data)* dst_data =
+                NS(BeamBeam4D_data)( destination );
+
+            SIXTRL_BE_DATAPTR_DEC NS(BB4D_data) const* src_data =
+                NS(BeamBeam4D_const_data)( source );
+
+            if( ( dst_data != SIXTRL_NULLPTR ) &&
+                ( src_data != SIXTRL_NULLPTR ) &&
+                ( NS(BeamBeam4D_data_size)( destination ) >=
+                  NS(BeamBeam4D_data_size)( source ) ) &&
+                ( dst_data != src_data ) )
+            {
+                *dst_data = *src_data;
+                status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+            }
 
-        success = 0;
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(BeamBeam4D_set_data_size)( destination,
+                    NS(BeamBeam4D_data_size)( source ) );
+            }
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+        }
     }
 
-    return success;
+    return status;
 }
 
 /* ************************************************************************* */
 /* BeamBeam6D: */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(BeamBeam6D_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(object_type_id_t)
+    NS(BeamBeam6D_type_id)( void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_BEAM_BEAM_4D);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamBeam6D_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( elem ) ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
+    return ( NS(buffer_size_t) )1u;
+}
 
-    buf_size_t num_dataptrs = ( buf_size_t )0u;
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamBeam6D_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT elem,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) st_size_t;
+    st_size_t num_slots = ( st_size_t )0u;
 
-    if( ( slot_size > ( buf_size_t )0u ) && ( beam_beam != SIXTRL_NULLPTR ) &&
-        ( NS(BeamBeam6D_get_data_size)( beam_beam ) > ( buf_size_t )0u ) )
+    if( ( elem != SIXTRL_NULLPTR ) && ( slot_size > ( st_size_t )0 ) )
     {
-        num_dataptrs = ( buf_size_t )1u;
+        st_size_t num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(BeamBeam6D) ), slot_size );
+
+        st_size_t const stored_data_size =
+            NS(BeamBeam6D_data_size)( elem ) * sizeof( SIXTRL_REAL_T );
+
+        SIXTRL_ASSERT( stored_data_size >=
+            NS(ManagedBuffer_get_slot_based_length)( sizeof(
+                NS(BB6D_data) ), slot_size ) );
+
+        SIXTRL_ASSERT( ( stored_data_size % slot_size ) == ( st_size_t )0 );
+        num_bytes += stored_data_size;
+        num_slots  = num_bytes / slot_size;
+
+        if( num_slots * slot_size < num_bytes ) ++num_slots;
     }
 
-    ( void )buffer;
+    return num_slots;
+}
 
-    return num_dataptrs;
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* NS(BeamBeam6D_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT bb_elem )
+{
+    if( bb_elem != SIXTRL_NULLPTR ) NS(BeamBeam6D_clear)( bb_elem );
+    return bb_elem;
 }
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(BeamBeam6D_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE void NS(BeamBeam6D_clear)( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+    SIXTRL_RESTRICT bb_elem )
 {
-    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    NS(arch_status_t) status = NS(BeamBeam6D_set_data_addr)(
+        bb_elem, ( NS(buffer_addr_t) )0 );
 
-    buf_size_t num_slots = ( buf_size_t )0u;
+    status |= NS(BeamBeam6D_set_data_size)(
+        bb_elem, ( NS(buffer_size_t) )0 );
 
-    if( ( slot_size > ( buf_size_t )0u ) && ( beam_beam != SIXTRL_NULLPTR ) &&
-        ( NS(BeamBeam6D_get_data_size)( beam_beam ) > ( buf_size_t )0u ) )
-    {
-        num_slots = NS(ManagedBuffer_get_slot_based_length)(
-            NS(BeamBeam6D_get_data_size)( beam_beam ) * sizeof( SIXTRL_REAL_T ),
-                slot_size );
+    SIXTRL_ASSERT( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS );
+}
 
-        num_slots /= slot_size;
-    }
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    ( void )buffer;
+SIXTRL_INLINE NS(buffer_addr_t) NS(BeamBeam6D_data_addr)( SIXTRL_BE_ARGPTR_DEC
+    const NS(BeamBeam6D) *const SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    return bb_elem->data_addr;
+}
 
-    return num_slots;
+SIXTRL_INLINE NS(arch_status_t) NS(BeamBeam6D_set_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT bb_elem,
+    NS(buffer_addr_t) const data_addr ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    bb_elem->data_addr = data_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
-NS(BeamBeam6D_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(BB6D_data) const*
+NS(BeamBeam6D_const_data)( SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+    SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
 {
-    if( beam_beam != SIXTRL_NULLPTR )
-    {
-        beam_beam->size = ( NS(buffer_size_t) )0u;
-        beam_beam->data = SIXTRL_NULLPTR;
-    }
+    return ( SIXTRL_BE_DATAPTR_DEC NS(BB6D_data) const* )( uintptr_t
+        )NS(BeamBeam6D_data_addr)( bb_elem );
+}
 
-    return beam_beam;
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(BB6D_data)* NS(BeamBeam6D_data)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+        SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_DATAPTR_DEC NS(BB6D_data)* )( uintptr_t
+        )NS(BeamBeam6D_data_addr)( bb_elem );
+}
+
+SIXTRL_INLINE NS(arch_size_t) NS(BeamBeam6D_data_size)( SIXTRL_BE_ARGPTR_DEC
+    const NS(BeamBeam6D) *const SIXTRL_RESTRICT bb_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    return bb_elem->data_size;
 }
 
-SIXTRL_INLINE void NS(BeamBeam6D_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam )
+SIXTRL_INLINE NS(arch_status_t) NS(BeamBeam6D_set_data_size)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT bb_elem,
+    NS(arch_size_t) const data_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t ) buf_size_t;
+    SIXTRL_ASSERT( bb_elem != SIXTRL_NULLPTR );
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    buf_size_t const data_size = NS(BeamBeam6D_get_data_size)( beam_beam );
-    NS(beambeam6d_real_ptr_t) ptr_data = NS(BeamBeam6D_get_data)( beam_beam );
+    NS(buffer_size_t) min_bb4_data_size =
+        NS(ManagedBuffer_get_slot_based_length)( sizeof( NS(BB6D_data) ),
+            ( NS(buffer_size_t) )8u );
+    min_bb4_data_size /= sizeof( SIXTRL_REAL_T );
 
-    if( ( data_size > ( NS(buffer_size_t) )0u ) &&
-        ( ptr_data != SIXTRL_NULLPTR ) )
+
+    if( ( bb_elem != SIXTRL_NULLPTR ) &&
+        ( ( data_size == ( NS(buffer_size_t) )0 ) ||
+          ( data_size >= min_bb4_data_size ) ) )
     {
-        SIXTRL_STATIC_VAR SIXTRL_REAL_T const ZERO = ( SIXTRL_REAL_T )0u;
-        SIXTRACKLIB_SET_VALUES( SIXTRL_REAL_T, ptr_data, data_size, ZERO );
+        bb_elem->data_size = data_size;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return;
+    return status;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const*
+NS(BeamBeam6D_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+     return (
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_BEAM_BEAM_6D) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(BeamBeam6D) ) ) )
+        ? ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const* )( uintptr_t
+            )NS(Object_get_begin_addr)( obj )
+        : SIXTRL_NULLPTR;
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+NS(BeamBeam6D_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT obj_index ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+        )NS(BeamBeam6D_const_from_obj_index)( obj_index );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const*
+NS(BeamBeam6D_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamBeam6D_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+NS(BeamBeam6D_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamBeam6D_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const*
+NS(BeamBeam6D_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer) const* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamBeam6D_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
 }
 
-SIXTRL_INLINE NS(beambeam6d_real_const_ptr_t)
-NS(BeamBeam6D_get_const_data)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT beam_beam )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* NS(BeamBeam6D_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( beam_beam != SIXTRL_NULLPTR );
-    return beam_beam->data;
+    return NS(BeamBeam6D_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
 }
 
-SIXTRL_INLINE NS(beambeam6d_real_ptr_t)
-NS(BeamBeam6D_get_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamBeam6D_data_addr_offset)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( elem ) ) SIXTRL_NOEXCEPT
 {
-    return ( NS(beambeam6d_real_ptr_t) )NS(BeamBeam6D_get_const_data)( beam_beam );
+    return ( NS(buffer_size_t) )offsetof( NS(BeamBeam6D), data_addr );
 }
 
-SIXTRL_INLINE SIXTRL_UINT64_T NS(BeamBeam6D_get_data_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT beam_beam )
+#endif /* !defined( _GPUCODE ) */
+
+SIXTRL_INLINE NS(arch_status_t) NS(BeamBeam6D_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT destination,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT source )
 {
-    SIXTRL_ASSERT( beam_beam != SIXTRL_NULLPTR );
-    return beam_beam->size;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) )
+    {
+        if( destination != source )
+        {
+            SIXTRL_BE_DATAPTR_DEC NS(BB6D_data)* dst_data =
+                NS(BeamBeam6D_data)( destination );
+
+            SIXTRL_BE_DATAPTR_DEC NS(BB6D_data) const* src_data =
+                NS(BeamBeam6D_const_data)( source );
+
+            if( ( dst_data != SIXTRL_NULLPTR ) &&
+                ( src_data != SIXTRL_NULLPTR ) &&
+                ( NS(BeamBeam6D_data_size)( destination ) >=
+                  NS(BeamBeam6D_data_size)( source ) ) &&
+                ( dst_data != src_data ) )
+            {
+                *dst_data = *src_data;
+                status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+            }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(BeamBeam6D_set_data_size)( destination,
+                    NS(BeamBeam6D_data_size)( source ) );
+            }
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+        }
+    }
+
+    return status;
 }
 
+/* ------------------------------------------------------------------------- */
+
 #if !defined(mysign)
 	#define mysign(a) (((a) >= 0) - ((a) < 0))
 #endif
@@ -1452,70 +2384,1803 @@ SIXTRL_INLINE void NS(BeamBeam6D_propagate_Sigma_matrix)(
 
 }
 
-SIXTRL_INLINE void NS(BeamBeam6D_set_data)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ptr_data )
+/* ************************************************************************* */
+/* SCCoasting: */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_preset)( SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+    SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    if( sc_elem != SIXTRL_NULLPTR ) NS(SCCoasting_clear)( sc_elem );
+    return sc_elem;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
 {
     typedef SIXTRL_REAL_T real_t;
 
-    NS(buffer_size_t) const size =
-        NS(BeamBeam6D_get_data_size)( beam_beam );
+    NS(arch_status_t) status = NS(SCCoasting_set_number_of_particles)(
+        sc_elem, ( real_t )0 );
+    status |= NS(SCCoasting_set_circumference)( sc_elem, ( real_t )1 );
+    status |= NS(SCCoasting_set_sigma_x)( sc_elem, ( real_t )1 );
+    status |= NS(SCCoasting_set_sigma_y)( sc_elem, ( real_t )1 );
+    status |= NS(SCCoasting_set_length)( sc_elem, ( real_t )0 );
+    status |= NS(SCCoasting_set_x_co)( sc_elem, ( real_t )0 );
+    status |= NS(SCCoasting_set_y_co)( sc_elem, ( real_t )0 );
+    status |= NS(SCCoasting_set_min_sigma_diff)(
+        sc_elem, ( real_t )1e-10 );
+    status |= NS(SCCoasting_set_enabled)( sc_elem, true );
+
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(object_type_id_t) NS(SCCoasting_type_id)(
+    void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_SC_COASTING);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(SCCoasting_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(SCCoasting_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
 
-    NS(beambeam6d_real_ptr_t) ptr_dest_data =
-        NS(BeamBeam6D_get_data)( beam_beam );
+    if( num_slots > ( NS(buffer_size_t) )0u )
+    {
+        NS(buffer_size_t) const required_size =
+            NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(SCCoasting) ), slot_size );
 
-    SIXTRL_ASSERT( ptr_dest_data != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ptr_data      != SIXTRL_NULLPTR );
-    SIXTRACKLIB_COPY_VALUES( real_t, ptr_dest_data, ptr_data, size );
+        num_slots = required_size / slot_size;
+        if( num_slots * slot_size < required_size ) ++num_slots;
+    }
 
-    return;
+    return num_slots;
 }
 
-SIXTRL_INLINE void NS(BeamBeam6D_set_data_size)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam,
-    NS(buffer_size_t) const data_size )
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCCoasting_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( beam_beam != SIXTRL_NULLPTR );
-    beam_beam->size = data_size;
-    return;
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->number_of_particles;
 }
 
-SIXTRL_INLINE void NS(BeamBeam6D_assign_data_ptr)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT beam_beam,
-    SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ptr_data )
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCCoasting_circumference)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( beam_beam != SIXTRL_NULLPTR );
-    beam_beam->data = ptr_data;
-    return;
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->circumference;
 }
 
-SIXTRL_INLINE int NS(BeamBeam6D_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT source )
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCCoasting_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->sigma_x;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCCoasting_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
 {
-    int success = -1;
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->sigma_y;
+}
 
-    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) &&
-        ( destination != source ) &&
-        ( NS(BeamBeam6D_get_const_data)( destination ) != SIXTRL_NULLPTR ) &&
-        ( NS(BeamBeam6D_get_const_data)( source      ) != SIXTRL_NULLPTR ) &&
-        ( NS(BeamBeam6D_get_data_size)( destination ) ==
-          NS(BeamBeam6D_get_data_size)( source ) ) )
-    {
-        SIXTRL_ASSERT( NS(BeamBeam6D_get_const_data)( destination ) !=
-                       NS(BeamBeam6D_get_const_data)( source ) );
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCCoasting_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->length;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCCoasting_x_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->x_co;
+}
 
-        SIXTRACKLIB_COPY_VALUES( SIXTRL_REAL_T,
-            NS(BeamBeam6D_get_data)( destination ),
-            NS(BeamBeam6D_get_const_data)( source ),
-            NS(BeamBeam6D_get_data_size)( source ) );
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCCoasting_y_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->y_co;
+}
 
-        success = 0;
-    }
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCCoasting_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->min_sigma_diff;
+}
 
-    return success;
+SIXTRL_INLINE bool NS(SCCoasting_enabled)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return ( sc_elem->enabled == ( SIXTRL_UINT64_T )1 );
 }
 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const number_of_particles ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->number_of_particles = number_of_particles;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_circumference)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const circumference ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->circumference = circumference;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const sigma_x ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->sigma_x = sigma_x;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const sigma_y ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->sigma_y = sigma_y;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const length ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->length = length;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_x_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const x_co ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->x_co = x_co;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_y_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const y_co ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->y_co = y_co;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const min_sigma_diff ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->min_sigma_diff = min_sigma_diff;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_set_enabled)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT sc_elem,
+    bool const is_enabled ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->enabled = ( is_enabled )
+        ? ( SIXTRL_UINT64_T )1 : ( SIXTRL_UINT64_T )0;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) const*
+NS(SCCoasting_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    const NS(Object) *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return (
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_SC_COASTING) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(SCCoasting) ) ) )
+        ? ( SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) const* )( uintptr_t
+            )NS(Object_get_begin_addr)( obj )
+        : SIXTRL_NULLPTR;
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+        )NS(SCCoasting_const_from_obj_index)( obj );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) const*
+NS(SCCoasting_const_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC
+        unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(SCCoasting_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)*
+NS(SCCoasting_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC
+        unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+   return NS(SCCoasting_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCCoasting_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCCoasting)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( (  dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
+    {
+        if( dest != src )
+        {
+            status = NS(SCCoasting_set_number_of_particles)( dest,
+                NS(SCCoasting_number_of_particles)( src ) );
+
+            status |= NS(SCCoasting_set_circumference)( dest,
+                NS(SCCoasting_circumference)( src ) );
+
+            status |= NS(SCCoasting_set_sigma_x)( dest,
+                NS(SCCoasting_sigma_x)( src ) );
+
+            status |= NS(SCCoasting_set_sigma_y)( dest,
+                NS(SCCoasting_sigma_y)( src ) );
+
+            status |= NS(SCCoasting_set_length)( dest,
+                NS(SCCoasting_length)( src ) );
+
+            status |= NS(SCCoasting_set_x_co)( dest,
+                NS(SCCoasting_x_co)( src ) );
+
+            status |= NS(SCCoasting_set_y_co)( dest,
+                NS(SCCoasting_y_co)( src ) );
+
+            status |= NS(SCCoasting_set_min_sigma_diff)( dest,
+                NS(SCCoasting_min_sigma_diff)( src ) );
+
+            status |= NS(SCCoasting_set_enabled)( dest,
+                NS(SCCoasting_enabled)( src ) );
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+/* ************************************************************************* */
+/* SCQGaussProfile: */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_preset)( SIXTRL_BE_ARGPTR_DEC
+    NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    if( sc_elem != SIXTRL_NULLPTR )
+    {
+        NS(SCQGaussProfile_clear)( sc_elem );
+    }
+
+    return sc_elem;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_REAL_T real_t;
+    NS(arch_status_t) status =
+        NS(SCQGaussProfile_set_number_of_particles)(
+            sc_elem, ( real_t )0 );
+
+    status |= NS(SCQGaussProfile_set_bunchlength_rms)(
+        sc_elem, ( real_t )1 );
+
+    status |= NS(SCQGaussProfile_set_sigma_x)(
+        sc_elem, ( real_t )1 );
+
+    status |= NS(SCQGaussProfile_set_sigma_y)(
+        sc_elem, ( real_t )1 );
+
+    status |= NS(SCQGaussProfile_set_length)(
+        sc_elem, ( real_t )0 );
+
+    status |= NS(SCQGaussProfile_set_x_co)( sc_elem, ( real_t )0 );
+    status |= NS(SCQGaussProfile_set_y_co)( sc_elem, ( real_t )0 );
+    status |= NS(SCQGaussProfile_set_q_param)(
+        sc_elem, ( real_t )1 );
+
+    status |= NS(SCQGaussProfile_set_enabled)( sc_elem, true );
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(object_type_id_t) NS(SCQGaussProfile_type_id)(
+    void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(SCQGaussProfile_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(SCQGaussProfile_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    if( slot_size > ( NS(buffer_size_t) )0u )
+    {
+        NS(buffer_size_t) const extent =
+            NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(SCQGaussProfile) ), slot_size );
+        num_slots = ( extent / slot_size );
+        if( ( num_slots * slot_size ) < extent ) ++num_slots;
+        SIXTRL_ASSERT( ( num_slots * slot_size ) >= extent );
+    }
+
+    return num_slots;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->number_of_particles;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_bunchlength_rms)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->bunchlength_rms;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->sigma_x;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->sigma_y;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->length;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_x_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->x_co;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_y_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->y_co;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_q_param)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->q_param;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_cq)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->cq;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCQGaussProfile_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->min_sigma_diff;
+}
+
+SIXTRL_INLINE bool NS(SCQGaussProfile_enabled)( SIXTRL_BE_ARGPTR_DEC
+    const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return ( sc_elem->enabled == ( SIXTRL_UINT64_T )1 );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(SCQGaussProfile_set_number_of_particles)( SIXTRL_BE_ARGPTR_DEC
+        NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const number_of_particles ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->number_of_particles = number_of_particles;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(SCQGaussProfile_set_bunchlength_rms)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const bunchlength_rms ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->bunchlength_rms = bunchlength_rms;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_set_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const sigma_x ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->sigma_x = sigma_x;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_set_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const sigma_y ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->sigma_y = sigma_y;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const length ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->length = length;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_set_x_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const x_co ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->x_co = x_co;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_set_y_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const y_co ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->y_co = y_co;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_set_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const min_sigma_diff ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->min_sigma_diff = min_sigma_diff;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_set_q_param)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const q_param ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( sc_elem != SIXTRL_NULLPTR ) && ( q_param < ( SIXTRL_REAL_T )3 ) )
+    {
+        sc_elem->q_param = q_param;
+        sc_elem->cq = NS(Math_q_gauss_cq)( q_param );
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_set_enabled)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        SIXTRL_RESTRICT sc_elem, bool const is_enabled ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->enabled = ( is_enabled )
+        ? ( SIXTRL_UINT64_T )1 : ( SIXTRL_UINT64_T )0;
+        return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile) const*
+NS(SCQGaussProfile_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const
+        SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return ( ( NS(Object_get_type_id)( obj ) ==
+               NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF) ) &&
+             ( NS(Object_get_size)( obj ) >=
+               sizeof( NS(SCQGaussProfile) ) ) )
+             ? ( SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile) const* )(
+                 uintptr_t )NS(Object_get_begin_addr)( obj )
+             : SIXTRL_NULLPTR;
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+        )NS(SCQGaussProfile_const_from_obj_index)( obj );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile) const*
+NS(SCQGaussProfile_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(SCQGaussProfile_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)*
+NS(SCQGaussProfile_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC
+        unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(SCQGaussProfile_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCQGaussProfile_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( (  dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
+    {
+        if( dest != src )
+        {
+            status = NS(SCQGaussProfile_set_number_of_particles)( dest,
+                NS(SCQGaussProfile_number_of_particles)( src ) );
+
+            status |= NS(SCQGaussProfile_set_bunchlength_rms)( dest,
+                NS(SCQGaussProfile_bunchlength_rms)( src ) );
+
+            status |= NS(SCQGaussProfile_set_sigma_x)( dest,
+                NS(SCQGaussProfile_sigma_x)( src ) );
+
+            status |= NS(SCQGaussProfile_set_sigma_y)( dest,
+                NS(SCQGaussProfile_sigma_y)( src ) );
+
+            status |= NS(SCQGaussProfile_set_length)( dest,
+                NS(SCQGaussProfile_length)( src ) );
+
+            status |= NS(SCQGaussProfile_set_x_co)( dest,
+                NS(SCQGaussProfile_x_co)( src ) );
+
+            status |= NS(SCQGaussProfile_set_y_co)( dest,
+                NS(SCQGaussProfile_y_co)( src ) );
+
+            status |= NS(SCQGaussProfile_set_min_sigma_diff)( dest,
+                NS(SCQGaussProfile_min_sigma_diff)( src ) );
+
+            status |= NS(SCQGaussProfile_set_q_param)( dest,
+                NS(SCQGaussProfile_q_param)( src ) );
+
+            status |= NS(SCQGaussProfile_set_enabled)( dest,
+                NS(SCQGaussProfile_enabled)( src ) );
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+/* ************************************************************************* */
+/* SCInterpolatedProfile: */
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_preset)( SIXTRL_BE_ARGPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    if( data != SIXTRL_NULLPTR ) NS(LineDensityProfileData_clear)( data );
+    return data;
+}
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(LineDensityProfileData_clear)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_REAL_T real_t;
+    typedef NS(math_abscissa_idx_t) absc_t;
+    typedef NS(buffer_addr_t) addr_t;
+
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    status = NS(LineDensityProfileData_set_method)(
+        data, NS(MATH_INTERPOL_NONE) );
+
+    status |= NS(LineDensityProfileData_set_capacity)( data, ( absc_t )2 );
+    status |= NS(LineDensityProfileData_set_values_addr)( data, ( addr_t )0 );
+    status |= NS(LineDensityProfileData_set_derivatives_addr)( data, ( addr_t )0 );
+    status |= NS(LineDensityProfileData_set_z0)( data, ( real_t )0 );
+    status |= NS(LineDensityProfileData_set_dz)( data, ( real_t )1 );
+    status |= NS(LineDensityProfileData_set_num_values)( data, ( absc_t )0 );
+
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(object_type_id_t) NS(LineDensityProfileData_type_id)(
+    void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_LINE_DENSITY_PROF_DATA);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(LineDensityProfileData_num_dataptrs)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( data ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )2u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(LineDensityProfileData_num_slots)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) st_size_t;
+    typedef NS(math_abscissa_idx_t) absc_t;
+
+    st_size_t num_slots = ( st_size_t )0u;
+    if( slot_size > ( st_size_t )0u )
+    {
+        st_size_t required_size = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(LineDensityProfileData) ), slot_size );
+
+        SIXTRL_ASSERT( NS(LineDensityProfileData_num_dataptrs)( data ) ==
+            ( st_size_t )2u );
+
+        if( ( data != SIXTRL_NULLPTR ) && ( data->capacity > ( absc_t )0 ) )
+        {
+            st_size_t const capacity = ( st_size_t
+                )NS(LineDensityProfileData_capacity)( data );
+
+            st_size_t const field_size =
+            NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( SIXTRL_REAL_T ) * capacity, slot_size );
+
+            required_size += ( st_size_t )2 * field_size;
+        }
+
+        num_slots = required_size / slot_size;
+
+        if( ( num_slots * slot_size ) < required_size ) ++num_slots;
+    }
+
+    return num_slots;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(math_interpol_t) NS(LineDensityProfileData_method)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    typedef NS(math_interpol_t) method_t;
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+
+    SIXTRL_ASSERT(
+        ( ( method_t )data->method == NS(MATH_INTERPOL_NONE) ) ||
+        ( ( method_t )data->method == NS(MATH_INTERPOL_LINEAR) ) ||
+        ( ( method_t )data->method == NS(MATH_INTERPOL_CUBIC) ) );
+
+    return ( method_t )data->method;
+}
+
+SIXTRL_INLINE NS(math_abscissa_idx_t) NS(LineDensityProfileData_num_values)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->num_values;
+}
+
+SIXTRL_INLINE NS(math_abscissa_idx_t) NS(LineDensityProfileData_capacity)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->capacity;
+}
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(LineDensityProfileData_values_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->values_addr;
+}
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(LineDensityProfileData_derivatives_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->derivatives_addr;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const*
+NS(LineDensityProfileData_const_values_begin)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(LineDensityProfileData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return ( SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+        )NS(LineDensityProfileData_values_addr)( data );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const*
+NS(LineDensityProfileData_const_values_end)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(LineDensityProfileData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* ptr_end =
+        NS(LineDensityProfileData_const_values_begin)( data );
+
+    NS(math_abscissa_idx_t) const num_values =
+        NS(LineDensityProfileData_num_values)( data );
+
+    if( ( ptr_end != SIXTRL_NULLPTR ) &&
+        ( num_values >= ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        ptr_end = ptr_end + num_values;
+    }
+
+    return ptr_end;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+NS(LineDensityProfileData_values_begin)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return ( SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* )( uintptr_t
+        )NS(LineDensityProfileData_values_addr)( data );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+NS(LineDensityProfileData_values_end)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+        )NS(LineDensityProfileData_const_values_end)( data );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(LineDensityProfileData_value_at_idx)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data,
+    NS(math_abscissa_idx_t) const idx ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* ptr_begin =
+        NS(LineDensityProfileData_const_values_begin)( data );
+
+    SIXTRL_ASSERT( ptr_begin != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( idx < NS(LineDensityProfileData_num_values)( data ) );
+
+    return ptr_begin[ idx ];
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const*
+NS(LineDensityProfileData_const_derivatives_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return ( SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+        )NS(LineDensityProfileData_derivatives_addr)( data );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const*
+NS(LineDensityProfileData_const_derivatives_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* ptr_end =
+        NS(LineDensityProfileData_const_derivatives_begin)( data );
+
+    NS(math_abscissa_idx_t) const num_values =
+        NS(LineDensityProfileData_num_values)( data );
+
+    if( ( ptr_end != SIXTRL_NULLPTR ) &&
+        ( num_values >= ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        ptr_end = ptr_end + num_values;
+    }
+
+    return ptr_end;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+NS(LineDensityProfileData_derivatives_begin)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+        )NS(LineDensityProfileData_const_derivatives_begin)( data );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+NS(LineDensityProfileData_derivatives_end)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(LineDensityProfileData)* SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+        )NS(LineDensityProfileData_const_derivatives_end)( data );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(LineDensityProfileData_derivatives_at_idx)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data,
+    NS(math_abscissa_idx_t) const idx ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_ARGPTR_DEC SIXTRL_REAL_T const* ptr_begin =
+        NS(LineDensityProfileData_const_derivatives_begin)( data );
+
+    SIXTRL_ASSERT( ptr_begin != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( idx < NS(LineDensityProfileData_num_values)( data ) );
+
+    return ptr_begin[ idx ];
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(LineDensityProfileData_z0)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->z0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(LineDensityProfileData_dz)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->dz;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(LineDensityProfileData_z_min)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->z0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(LineDensityProfileData_z_max)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+            SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( data->dz > ( SIXTRL_REAL_T )0 );
+    SIXTRL_ASSERT( data->num_values > ( NS(math_abscissa_idx_t) )0 );
+    return data->z0 + data->dz * data->num_values;
+}
+
+SIXTRL_INLINE NS(math_abscissa_idx_t) NS(LineDensityProfileData_find_idx)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( z >= NS(LineDensityProfileData_z_min)( data ) );
+    SIXTRL_ASSERT( z <= NS(LineDensityProfileData_z_max)( data ) );
+    SIXTRL_ASSERT( NS(LineDensityProfileData_values_addr)( data ) !=
+                   ( NS(buffer_addr_t) )0 );
+    SIXTRL_ASSERT( NS(LineDensityProfileData_derivatives_addr)( data ) !=
+                   ( NS(buffer_addr_t) )0 );
+
+    return NS(Math_abscissa_index_equ)(
+        z, data->z0, data->dz, data->num_values );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(LineDensityProfileData_interpolate_value)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T result = ( SIXTRL_REAL_T )0;
+
+    SIXTRL_ASSERT( NS(LineDensityProfileData_values_addr)( data ) !=
+                   ( NS(buffer_addr_t) )0 );
+
+    SIXTRL_ASSERT( NS(LineDensityProfileData_derivatives_addr)( data ) !=
+                   ( NS(buffer_addr_t) )0 );
+
+    if( ( z <= NS(LineDensityProfileData_z_max)( data ) ) &&
+        ( z >= NS(LineDensityProfileData_z_min)( data ) ) )
+    {
+        result = NS(Math_interpol_y_equ)( z,
+            NS(LineDensityProfileData_z0)( data ),
+            NS(LineDensityProfileData_dz)( data ),
+            NS(LineDensityProfileData_const_values_begin)( data ),
+            NS(LineDensityProfileData_const_derivatives_begin)( data ),
+            NS(LineDensityProfileData_num_values)( data ),
+            NS(LineDensityProfileData_method)( data ) );
+    }
+
+    return result;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T
+NS(LineDensityProfileData_interpolate_1st_derivative)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T result = ( SIXTRL_REAL_T )0;
+
+    SIXTRL_ASSERT( NS(LineDensityProfileData_values_addr)( data ) !=
+                   ( NS(buffer_addr_t) )0 );
+
+    SIXTRL_ASSERT( NS(LineDensityProfileData_derivatives_addr)( data ) !=
+                   ( NS(buffer_addr_t) )0 );
+
+    if( ( z <= NS(LineDensityProfileData_z_max)( data ) ) &&
+        ( z >= NS(LineDensityProfileData_z_min)( data ) ) )
+    {
+        result = NS(Math_interpol_yp_equ)( z,
+            NS(LineDensityProfileData_z0)( data ),
+            NS(LineDensityProfileData_dz)( data ),
+            NS(LineDensityProfileData_const_values_begin)( data ),
+            NS(LineDensityProfileData_const_derivatives_begin)( data ),
+            NS(LineDensityProfileData_num_values)( data ),
+            NS(LineDensityProfileData_method)( data ) );
+    }
+
+    return result;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T
+NS(LineDensityProfileData_interpolate_2nd_derivative)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT data, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T result = ( SIXTRL_REAL_T )0;
+
+    SIXTRL_ASSERT( NS(LineDensityProfileData_values_addr)( data ) !=
+                   ( NS(buffer_addr_t) )0 );
+
+    SIXTRL_ASSERT( NS(LineDensityProfileData_derivatives_addr)( data ) !=
+                   ( NS(buffer_addr_t) )0 );
+
+    if( ( z <= NS(LineDensityProfileData_z_max)( data ) ) &&
+        ( z >= NS(LineDensityProfileData_z_min)( data ) ) )
+    {
+        result = NS(Math_interpol_ypp_equ)( z,
+            NS(LineDensityProfileData_z0)( data ),
+            NS(LineDensityProfileData_dz)( data ),
+            NS(LineDensityProfileData_const_values_begin)( data ),
+            NS(LineDensityProfileData_const_derivatives_begin)( data ),
+            NS(LineDensityProfileData_num_values)( data ),
+            NS(LineDensityProfileData_method)( data ) );
+    }
+
+    return result;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(LineDensityProfileData_prepare_interpolation)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_ARGPTR_DEC SIXTRL_REAL_T*
+        SIXTRL_RESTRICT temp_data ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_addr_t) addr_t;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_DEBUGGING_GENERAL_FAILURE;
+
+    if( ( data != SIXTRL_NULLPTR ) &&
+        ( NS(LineDensityProfileData_values_addr)( data ) != ( addr_t )0 ) &&
+        ( NS(LineDensityProfileData_derivatives_addr)( data ) != ( addr_t )0 ) &&
+        ( NS(LineDensityProfileData_num_values)( data ) >
+          ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        status = NS(Math_interpol_prepare_equ)(
+            NS(LineDensityProfileData_derivatives_begin)( data ), temp_data,
+            NS(LineDensityProfileData_const_values_begin)( data ),
+            NS(LineDensityProfileData_z0)( data ),
+            NS(LineDensityProfileData_dz)( data ),
+            NS(LineDensityProfileData_num_values)( data ),
+            NS(LineDensityProfileData_method)( data ) );
+    }
+
+    return status;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(LineDensityProfileData_set_z0)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const z0 ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->z0 = z0;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(LineDensityProfileData_set_dz)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    SIXTRL_REAL_T const dz ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( dz >= ( SIXTRL_REAL_T )0 );
+    data->dz = dz;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(LineDensityProfileData_set_num_values)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->num_values = num_values;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(LineDensityProfileData_set_capacity)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(math_abscissa_idx_t) const capacity ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->capacity = capacity;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(LineDensityProfileData_set_values_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const values_addr ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->values_addr = values_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(LineDensityProfileData_set_derivatives_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const derivatives_addr ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->derivatives_addr = derivatives_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(LineDensityProfileData_set_method)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT data,
+    NS(math_interpol_t) const method ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->method = ( NS(math_interpol_int_t) )method;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LineDensityProfileData) const*
+NS(LineDensityProfileData_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    const NS(Object) *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return ( ( NS(Object_get_type_id)( obj ) ==
+               NS(OBJECT_TYPE_LINE_DENSITY_PROF_DATA) ) &&
+             ( NS(Object_get_size)( obj ) >=
+               sizeof( NS(LineDensityProfileData) ) ) )
+        ? ( SIXTRL_BE_ARGPTR_DEC NS(LineDensityProfileData) const* )( uintptr_t
+            )NS(Object_get_begin_addr)( obj )
+        : SIXTRL_NULLPTR;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        )NS(LineDensityProfileData_const_from_obj_index)( obj );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LineDensityProfileData) const*
+NS(LineDensityProfileData_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size) );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(LineDensityProfileData_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC
+        unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(LineDensityProfileData_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size) );
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(LineDensityProfileData_copy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) &&
+        ( NS(LineDensityProfileData_capacity)( dest ) >=
+          NS(LineDensityProfileData_num_values)( src ) ) &&
+        ( ( ( NS(LineDensityProfileData_values_addr)( dest ) !=
+              NS(LineDensityProfileData_values_addr)( src ) ) &&
+            ( NS(LineDensityProfileData_values_addr)( dest ) !=
+              ( NS(buffer_addr_t) )0 ) &&
+            ( NS(LineDensityProfileData_values_addr)( src ) !=
+              ( NS(buffer_addr_t) )0 ) &&
+            ( NS(LineDensityProfileData_derivatives_addr)( dest ) !=
+              NS(LineDensityProfileData_derivatives_addr)( src ) ) &&
+            ( NS(LineDensityProfileData_derivatives_addr)( dest ) !=
+              ( NS(buffer_addr_t) )0 ) &&
+            ( NS(LineDensityProfileData_derivatives_addr)( src ) !=
+              ( NS(buffer_addr_t) )0 ) ) ||
+          ( dest == src ) ) )
+    {
+        if( dest != src )
+        {
+            typedef NS(math_abscissa_idx_t) absc_t;
+            absc_t ii = ( absc_t )0;
+            absc_t const num_values =
+                NS(LineDensityProfileData_num_values)( src );
+
+            SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* src_values =
+                NS(LineDensityProfileData_const_values_begin)( src );
+
+            SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* dest_values =
+                NS(LineDensityProfileData_values_begin)( dest );
+
+            SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* src_derivatives =
+                NS(LineDensityProfileData_const_derivatives_begin)( src );
+
+            SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* dest_derivatives =
+                NS(LineDensityProfileData_derivatives_begin)( dest );
+
+            NS(LineDensityProfileData_set_method)( dest,
+                NS(LineDensityProfileData_method)( src ) );
+
+            NS(LineDensityProfileData_set_num_values)( dest, num_values );
+
+            NS(LineDensityProfileData_set_z0)( dest,
+                NS(LineDensityProfileData_z0)( src ) );
+
+            NS(LineDensityProfileData_set_dz)( dest,
+                NS(LineDensityProfileData_dz)( src ) );
+
+            SIXTRL_ASSERT( src_values  != SIXTRL_NULLPTR );
+            SIXTRL_ASSERT( dest_values != SIXTRL_NULLPTR );
+            SIXTRL_ASSERT( dest_values != src_values );
+
+            SIXTRL_ASSERT( src_derivatives  != SIXTRL_NULLPTR );
+            SIXTRL_ASSERT( dest_derivatives != SIXTRL_NULLPTR );
+            SIXTRL_ASSERT( dest_derivatives != src_derivatives );
+
+            for( ; ii < num_values ; ++ii )
+            {
+                dest_values[ ii ] = src_values[ ii ];
+                dest_derivatives[ ii ] = src_derivatives[ ii ];
+            }
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE NS(buffer_size_t) NS(LineDensityProfileData_values_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( data ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )offsetof(
+        NS(LineDensityProfileData), values_addr );
+}
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(LineDensityProfileData_derivatives_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( data ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )offsetof(
+        NS(LineDensityProfileData), derivatives_addr );
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+/* ************************************************************************* */
+/* NS(SCInterpolatedProfile) */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+NS(SCInterpolatedProfile_preset)( SIXTRL_BE_ARGPTR_DEC
+    NS(SCInterpolatedProfile)* SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    if( sc_elem != SIXTRL_NULLPTR )
+    {
+        NS(SCInterpolatedProfile_clear)( sc_elem );
+    }
+
+    return sc_elem;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_REAL_T real_t;
+
+    NS(arch_status_t) status =
+        NS(SCInterpolatedProfile_set_number_of_particles)(
+            sc_elem, ( real_t )0 );
+
+    status |= NS(SCInterpolatedProfile_set_sigma_x)(
+        sc_elem, ( real_t )1 );
+
+    status |= NS(SCInterpolatedProfile_set_sigma_y)(
+        sc_elem, ( real_t )1 );
+
+    status |= NS(SCInterpolatedProfile_set_length)(
+        sc_elem, ( real_t )0 );
+
+    status |= NS(SCInterpolatedProfile_set_x_co)(
+        sc_elem, ( real_t )0 );
+
+    status |= NS(SCInterpolatedProfile_set_y_co)(
+        sc_elem, ( real_t )0 );
+
+    status |= NS(SCInterpolatedProfile_set_interpol_data_addr)(
+        sc_elem, ( NS(buffer_addr_t) )0 );
+
+    status |= NS(SCInterpolatedProfile_set_line_density_prof_fallback)(
+        sc_elem, ( real_t )1 );
+
+    status |= NS(SCInterpolatedProfile_set_min_sigma_diff)(
+        sc_elem, ( real_t )1e-10 );
+
+    status |= NS(SCInterpolatedProfile_set_enabled)( sc_elem, true );
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(object_type_id_t)
+    NS(SCInterpolatedProfile_type_id)() SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_SC_INTERPOLATED_PROF);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(SCInterpolatedProfile_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(SCInterpolatedProfile_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+
+    if( num_slots > ( NS(buffer_size_t) )0u )
+    {
+        NS(buffer_size_t) const required_size =
+            NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(SCInterpolatedProfile) ), slot_size );
+
+        num_slots = required_size / slot_size;
+        if( num_slots * slot_size < required_size ) ++num_slots;
+    }
+
+    return num_slots;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE bool NS(SCInterpolatedProfile_has_interpol_data)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData) const* interpol_data =
+        NS(SCInterpolatedProfile_const_line_density_profile_data)(
+            sc_elem );
+
+    return ( ( interpol_data != SIXTRL_NULLPTR ) &&
+             ( NS(LineDensityProfileData_method)( interpol_data ) !=
+               NS(MATH_INTERPOL_NONE) ) &&
+             ( NS(LineDensityProfileData_num_values)( interpol_data ) >=
+              ( NS(math_abscissa_idx_t) )0 ) &&
+             ( NS(LineDensityProfileData_const_values_begin)(
+                 interpol_data ) != SIXTRL_NULLPTR ) &&
+             ( NS(LineDensityProfileData_const_derivatives_begin)(
+                 interpol_data ) != SIXTRL_NULLPTR ) );
+}
+
+SIXTRL_INLINE NS(buffer_addr_t)
+NS(SCInterpolatedProfile_interpol_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->interpol_data_addr;
+}
+
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(LineDensityProfileData) const*
+NS(SCInterpolatedProfile_const_line_density_profile_data)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData) const*
+        )( uintptr_t )sc_elem->interpol_data_addr;
+}
+
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(LineDensityProfileData)*
+NS(SCInterpolatedProfile_line_density_profile_data)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)* SIXTRL_RESTRICT
+        sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)*
+        )( uintptr_t )sc_elem->interpol_data_addr;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCInterpolatedProfile_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->number_of_particles;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T
+NS(SCInterpolatedProfile_line_density_prof_fallback)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->line_density_prof_fallback;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCInterpolatedProfile_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->sigma_x;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCInterpolatedProfile_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->sigma_y;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCInterpolatedProfile_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->length;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCInterpolatedProfile_x_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->x_co;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCInterpolatedProfile_y_co)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->y_co;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(SCInterpolatedProfile_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return sc_elem->min_sigma_diff;
+}
+
+SIXTRL_INLINE bool NS(SCInterpolatedProfile_enabled)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    return ( sc_elem->enabled == ( SIXTRL_UINT64_T )1 );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(SCInterpolatedProfile_set_interpol_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    NS(buffer_addr_t) const interpol_data_addr ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->interpol_data_addr = interpol_data_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_set_number_of_particles)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const number_of_particles ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->number_of_particles = number_of_particles;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_set_sigma_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const sigma_x ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->sigma_x = sigma_x;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_set_sigma_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const sigma_y ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->sigma_y = sigma_y;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const length ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->length = length;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_set_x_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const x_co ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->x_co = x_co;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_set_y_co)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const y_co ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->y_co = y_co;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(SCInterpolatedProfile_set_line_density_prof_fallback)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const line_density_prof_fallback ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->line_density_prof_fallback = line_density_prof_fallback;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(SCInterpolatedProfile_set_min_sigma_diff)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const min_sigma_diff ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->min_sigma_diff = min_sigma_diff;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_set_enabled)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, bool const is_enabled ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sc_elem != SIXTRL_NULLPTR );
+    sc_elem->enabled = ( is_enabled )
+        ? ( SIXTRL_UINT64_T )1 : ( SIXTRL_UINT64_T )0;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_REAL_T
+NS(SCInterpolatedProfile_line_density_profile)( SIXTRL_BE_ARGPTR_DEC
+    NS(SCInterpolatedProfile)* SIXTRL_RESTRICT sc_elem,
+    SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData) const* interpol_data =
+        NS(SCInterpolatedProfile_const_line_density_profile_data)(
+            sc_elem );
+
+    SIXTRL_ASSERT( interpol_data != SIXTRL_NULLPTR );
+    return NS(LineDensityProfileData_interpolate_value)( interpol_data, z );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T
+NS(SCInterpolatedProfile_line_density_profile_1st_derivative)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData) const* interpol_data =
+        NS(SCInterpolatedProfile_const_line_density_profile_data)(
+            sc_elem );
+
+    SIXTRL_ASSERT( interpol_data != SIXTRL_NULLPTR );
+    return NS(LineDensityProfileData_interpolate_1st_derivative)(
+        interpol_data, z );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T
+NS(SCInterpolatedProfile_line_density_profile_2nd_derivative)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_REAL_T const z ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData) const* interpol_data =
+        NS(SCInterpolatedProfile_const_line_density_profile_data)(
+            sc_elem );
+
+    SIXTRL_ASSERT( interpol_data != SIXTRL_NULLPTR );
+    return NS(LineDensityProfileData_interpolate_2nd_derivative)(
+        interpol_data, z );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(SCInterpolatedProfile_prepare_interpolation)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT sc_elem, SIXTRL_ARGPTR_DEC SIXTRL_REAL_T*
+            SIXTRL_RESTRICT temp_data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData)* interpol_data =
+        NS(SCInterpolatedProfile_line_density_profile_data)( sc_elem );
+
+    SIXTRL_ASSERT( interpol_data != SIXTRL_NULLPTR );
+    return NS(LineDensityProfileData_prepare_interpolation)(
+        interpol_data, temp_data );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile) const*
+NS(SCInterpolatedProfile_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const
+        SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return ( ( NS(Object_get_type_id)( obj ) ==
+               NS(OBJECT_TYPE_SC_INTERPOLATED_PROF) ) &&
+             ( NS(Object_get_size)( obj ) >= sizeof(
+               NS(SCInterpolatedProfile) ) ) )
+        ? ( SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile) const* )(
+            uintptr_t )NS(Object_get_begin_addr)( obj )
+        : SIXTRL_NULLPTR;
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+NS(SCInterpolatedProfile_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+        SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        )NS(SCInterpolatedProfile_const_from_obj_index)( obj );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile) const*
+NS(SCInterpolatedProfile_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(SCInterpolatedProfile_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+NS(SCInterpolatedProfile_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(SCInterpolatedProfile_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(SCInterpolatedProfile_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)*
+        SIXTRL_RESTRICT dest,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
+    {
+        if( dest != src )
+        {
+            NS(SCInterpolatedProfile_set_number_of_particles)( dest,
+                NS(SCInterpolatedProfile_number_of_particles)( src ) );
+
+            NS(SCInterpolatedProfile_set_sigma_x)( dest,
+                NS(SCInterpolatedProfile_sigma_x)( src ) );
+
+            NS(SCInterpolatedProfile_set_sigma_y)( dest,
+                NS(SCInterpolatedProfile_sigma_y)( src ) );
+
+            NS(SCInterpolatedProfile_set_length)( dest,
+                NS(SCInterpolatedProfile_length)( src ) );
+
+            NS(SCInterpolatedProfile_set_x_co)( dest,
+                NS(SCInterpolatedProfile_x_co)( src ) );
+
+            NS(SCInterpolatedProfile_set_y_co)( dest,
+                NS(SCInterpolatedProfile_y_co)( src ) );
+
+            NS(SCInterpolatedProfile_set_interpol_data_addr)( dest,
+                NS(SCInterpolatedProfile_interpol_data_addr)( src ) );
+
+            NS(SCInterpolatedProfile_set_line_density_prof_fallback)(
+                dest, NS(SCInterpolatedProfile_line_density_prof_fallback)(
+                    src ) );
+
+            NS(SCInterpolatedProfile_set_min_sigma_diff)( dest,
+                NS(SCInterpolatedProfile_min_sigma_diff)( src ) );
+
+            NS(SCInterpolatedProfile_set_enabled)( dest,
+                NS(SCInterpolatedProfile_enabled)( src ) );
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(SCInterpolatedProfile_interpol_data_addr_offset)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( sc_elem ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )offsetof(
+        NS(SCInterpolatedProfile), interpol_data_addr );
+}
+
+#endif /* _GPUCODE */
+
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
diff --git a/sixtracklib/common/be_beamfields/faddeeva_cern.h b/sixtracklib/common/be_beamfields/faddeeva_cern.h
index 849fe477..60b3ba60 100644
--- a/sixtracklib/common/be_beamfields/faddeeva_cern.h
+++ b/sixtracklib/common/be_beamfields/faddeeva_cern.h
@@ -41,81 +41,82 @@ SIXTRL_FN SIXTRL_STATIC void cerrf(
 extern "C" {
 #endif /* !defined( __cplusplus ) && !defined( _GPUCODE ) */
 
+/* From: be_beamfields/faddeeva_cern.h */
 SIXTRL_INLINE void cerrf( SIXTRL_REAL_T in_real, SIXTRL_REAL_T in_imag,
     SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT out_real,
     SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT out_imag )
 {
-	/**
-	this function calculates the SIXTRL_REAL_T precision complex error function based on the
-	algorithm of the FORTRAN function written at CERN by K. Koelbig, Program C335, 1970.
-	See also M. Bassetti and G.A. Erskine, "Closed expression for the electric field of a
-	two-dimensional Gaussian charge density", CERN-ISR-TH/80-06;
-	*/
+    /* This function calculates the SIXTRL_REAL_T precision complex error fnct.
+    based on the algorithm of the FORTRAN function written at CERN by K. Koelbig
+    Program C335, 1970. See also M. Bassetti and G.A. Erskine, "Closed
+    expression for the electric field of a two-dimensional Gaussian charge
+    density", CERN-ISR-TH/80-06; */
 
-	int n, nc, nu;
-	SIXTRL_REAL_T a_constant = 1.12837916709551;
-	SIXTRL_REAL_T xLim = 5.33;
-	SIXTRL_REAL_T yLim = 4.29;
-	SIXTRL_REAL_T h, q, Saux, Sx, Sy, Tn, Tx, Ty, Wx, Wy, xh, xl, x, yh, y;
-	SIXTRL_REAL_T Rx [33];
-	SIXTRL_REAL_T Ry [33];
+    int n, nc, nu;
+    SIXTRL_REAL_T a_constant = 1.12837916709551;
+    SIXTRL_REAL_T xLim = 5.33;
+    SIXTRL_REAL_T yLim = 4.29;
+    SIXTRL_REAL_T h, q, Saux, Sx, Sy, Tn, Tx, Ty, Wx, Wy, xh, xl, x, yh, y;
+    SIXTRL_REAL_T Rx [33];
+    SIXTRL_REAL_T Ry [33];
 
-	x = fabs(in_real);
-	y = fabs(in_imag);
+    x = fabs(in_real);
+    y = fabs(in_imag);
 
-	if (y < yLim && x < xLim){
-		q = (1.0 - y / yLim) * sqrt(1.0 - (x / xLim) * (x / xLim));
-		h  = 1.0 / (3.2 * q);
-		nc = 7 + (int) (23.0 * q);
-		xl = pow(h, (SIXTRL_REAL_T) (1 - nc));
-		xh = y + 0.5 / h;
-		yh = x;
-		nu = 10 + (int) (21.0 * q);
-		Rx[nu] = 0.;
-		Ry[nu] = 0.;
-		for (n = nu; n > 0; n--){
-			Tx = xh + n * Rx[n];
-			Ty = yh - n * Ry[n];
-			Tn = Tx*Tx + Ty*Ty;
-			Rx[n-1] = 0.5 * Tx / Tn;
-			Ry[n-1] = 0.5 * Ty / Tn;
-			}
-		Sx = 0.;
-		Sy = 0.;
-		for (n = nc; n>0; n--){
-			Saux = Sx + xl;
-			Sx = Rx[n-1] * Saux - Ry[n-1] * Sy;
-			Sy = Rx[n-1] * Sy + Ry[n-1] * Saux;
-			xl = h * xl;
-		};
-		Wx = a_constant * Sx;
-		Wy = a_constant * Sy;
-	}
-	else{
-		xh = y;
-		yh = x;
-		Rx[0] = 0.;
-		Ry[0] = 0.;
-		for (n = 9; n>0; n--){
-			Tx = xh + n * Rx[0];
-			Ty = yh - n * Ry[0];
-			Tn = Tx * Tx + Ty * Ty;
-			Rx[0] = 0.5 * Tx / Tn;
-			Ry[0] = 0.5 * Ty / Tn;
-		};
-		Wx = a_constant * Rx[0];
-		Wy = a_constant * Ry[0];
-	}
-	if (y == 0.) {Wx = exp(-x * x);}
-	if (in_imag < 0.){
-		Wx =   2.0 * exp(y * y - x * x) * cos(2.0 * x * y) - Wx;
-		Wy = - 2.0 * exp(y * y - x * x) * sin(2.0 * x * y) - Wy;
-		if (in_real > 0.) {Wy = -Wy;}
-	}
-	else if (in_real < 0.) {Wy = -Wy;}
+    if (y < yLim && x < xLim){
+        q = (1.0 - y / yLim) * sqrt(1.0 - (x / xLim) * (x / xLim));
+        h  = 1.0 / (3.2 * q);
+        nc = 7 + (int) (23.0 * q);
+        xl = pow(h, (SIXTRL_REAL_T) (1 - nc));
+        xh = y + 0.5 / h;
+        yh = x;
+        nu = 10 + (int) (21.0 * q);
+        Rx[nu] = 0.;
+        Ry[nu] = 0.;
+        for (n = nu; n > 0; n--){
+            Tx = xh + n * Rx[n];
+            Ty = yh - n * Ry[n];
+            Tn = Tx*Tx + Ty*Ty;
+            Rx[n-1] = 0.5 * Tx / Tn;
+            Ry[n-1] = 0.5 * Ty / Tn;
+            }
+        /* .... */
+        Sx = 0.;
+        Sy = 0.;
+        for (n = nc; n>0; n--){
+            Saux = Sx + xl;
+            Sx = Rx[n-1] * Saux - Ry[n-1] * Sy;
+            Sy = Rx[n-1] * Sy + Ry[n-1] * Saux;
+            xl = h * xl;
+        };
+        Wx = a_constant * Sx;
+        Wy = a_constant * Sy;
+    }
+    else{
+        xh = y;
+        yh = x;
+        Rx[0] = 0.;
+        Ry[0] = 0.;
+        for (n = 9; n>0; n--){
+            Tx = xh + n * Rx[0];
+            Ty = yh - n * Ry[0];
+            Tn = Tx * Tx + Ty * Ty;
+            Rx[0] = 0.5 * Tx / Tn;
+            Ry[0] = 0.5 * Ty / Tn;
+        };
+        Wx = a_constant * Rx[0];
+        Wy = a_constant * Ry[0];
+    }
+    if (y == 0.) {Wx = exp(-x * x);}
+    if (in_imag < 0.){
+        Wx =   2.0 * exp(y * y - x * x) * cos(2.0 * x * y) - Wx;
+        Wy = - 2.0 * exp(y * y - x * x) * sin(2.0 * x * y) - Wy;
+        if (in_real > 0.) {Wy = -Wy;}
+    }
+    else if (in_real < 0.) {Wy = -Wy;}
 
-	*out_real = Wx;
-	*out_imag = Wy;
+    *out_real = Wx;
+    *out_imag = Wy;
 }
 
 #if defined( __cplusplus ) && !defined( _GPUCODE )
diff --git a/sixtracklib/common/be_beamfields/track.h b/sixtracklib/common/be_beamfields/track.h
index 131a0b22..fdf141ad 100644
--- a/sixtracklib/common/be_beamfields/track.h
+++ b/sixtracklib/common/be_beamfields/track.h
@@ -5,6 +5,9 @@
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/track/definitions.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
+    #include "sixtracklib/common/internal/math_constants.h"
+    #include "sixtracklib/common/internal/math_functions.h"
+    #include "sixtracklib/common/internal/physics_constants.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/particles.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
@@ -14,35 +17,45 @@ extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
 struct NS(BeamBeam4D);
-struct NS(SpaceChargeCoasting);
-struct NS(SpaceChargeBunched);
+struct NS(SCCoasting);
+struct NS(SCQGaussProfile);
+struct NS(SCInterpolatedProfile);
 struct NS(BeamBeam6D);
 
 SIXTRL_STATIC SIXTRL_FN NS(track_status_t)
 NS(Track_particle_beam_beam_4d)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
-    NS(particle_num_elements_t) const particle_index,
+    NS(particle_num_elements_t) const ii,
     SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam4D) *const SIXTRL_RESTRICT bb );
 
+SIXTRL_STATIC SIXTRL_FN NS(track_status_t)
+NS(Track_particle_beam_beam_6d)(
+    SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
+    NS(particle_num_elements_t)  const ii,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam6D) *const SIXTRL_RESTRICT bb );
+
+/* ------------------------------------------------------------------------- */
+
 SIXTRL_STATIC SIXTRL_FN NS(track_status_t)
 NS(Track_particle_space_charge_coasting)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
-    NS(particle_num_elements_t) const particle_index,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(SpaceChargeCoasting) *const
-        SIXTRL_RESTRICT sc );
+    NS(particle_num_elements_t) const ii,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(SCCoasting) *const
+        SIXTRL_RESTRICT sc_elem )  SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN NS(track_status_t)
-NS(Track_particle_space_charge_bunched)(
+NS(Track_particle_space_charge_qgaussian_profile)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
-    NS(particle_num_elements_t) const particle_index,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(SpaceChargeBunched) *const
-        SIXTRL_RESTRICT sc );
+    NS(particle_num_elements_t) const ii,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN NS(track_status_t)
-NS(Track_particle_beam_beam_6d)(
+NS(Track_particle_space_charge_interpolated_profile)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
-    NS(particle_num_elements_t)  const particle_index,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam6D) *const SIXTRL_RESTRICT bb );
+    NS(particle_num_elements_t) const ii,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
@@ -63,6 +76,7 @@ NS(Track_particle_beam_beam_6d)(
     #include "sixtracklib/common/constants.h"
     #include "sixtracklib/common/particles.h"
     #include "sixtracklib/common/be_beamfields/be_beamfields.h"
+    #include "sixtracklib/common/internal/math_qgauss.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined( _GPUCODE ) && defined( __cplusplus )
@@ -73,14 +87,14 @@ extern "C" {
 /* BeamBeam4D: */
 
 SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_beam_4d)(
-    SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
-    NS(particle_num_elements_t) const particle_index,
+    SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT p,
+    NS(particle_num_elements_t) const ii,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT bb )
 {
     typedef SIXTRL_REAL_T real_t;
     typedef SIXTRL_BE_DATAPTR_DEC NS(BB4D_data)* data_ptr_t;
 
-    data_ptr_t bb4ddata = ( data_ptr_t )NS(BeamBeam4D_get_const_data)( bb );
+    data_ptr_t bb4ddata = ( data_ptr_t )NS(BeamBeam4D_const_data)( bb );
 
     /*
     // Test data transfer
@@ -96,25 +110,25 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_beam_4d)(
     printf("4D: Dpy_sub = %e\n",bb4ddata->Dpy_sub);
     printf("4D: enabled = %ld\n",bb4ddata->enabled); */
 
-    SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, particle_index )
-        == ( NS(particle_index_t) )1 );
+    SIXTRL_ASSERT( NS(Particles_get_state_value)( p, ii )
+        == ( NS(particle_num_elements_t) )1 );
 
     if (bb4ddata->enabled > 0.) {
 
-        real_t px = NS(Particles_get_px_value)( particles, particle_index );
-        real_t py = NS(Particles_get_py_value)( particles, particle_index );
+        real_t px = NS(Particles_get_px_value)( p, ii );
+        real_t py = NS(Particles_get_py_value)( p, ii );
 
         real_t qratio = 1.;// To be generalized for multi-ion!
-        real_t charge = qratio*NS(Particles_get_q0_value)( particles, particle_index )*SIXTRL_QELEM;
+        real_t charge = qratio*NS(Particles_get_q0_value)( p, ii )*SIXTRL_QELEM;
 
-        real_t x = NS(Particles_get_x_value)( particles, particle_index ) - bb4ddata->Delta_x;
-        real_t y = NS(Particles_get_y_value)( particles, particle_index ) - bb4ddata->Delta_y;
+        real_t x = NS(Particles_get_x_value)( p, ii ) - bb4ddata->Delta_x;
+        real_t y = NS(Particles_get_y_value)( p, ii ) - bb4ddata->Delta_y;
 
-        real_t chi = NS(Particles_get_chi_value)( particles, particle_index );
+        real_t chi = NS(Particles_get_chi_value)( p, ii );
 
-        real_t beta = NS(Particles_get_beta0_value)( particles, particle_index ) \
-                        /NS(Particles_get_rvv_value)( particles, particle_index );
-        real_t p0c = NS(Particles_get_p0c_value)( particles, particle_index )*SIXTRL_QELEM;
+        real_t beta = NS(Particles_get_beta0_value)( p, ii ) \
+                        /NS(Particles_get_rvv_value)( p, ii );
+        real_t p0c = NS(Particles_get_p0c_value)( p, ii )*SIXTRL_QELEM;
 
         real_t Ex, Ey, Gx, Gy;
         NS(get_Ex_Ey_Gx_Gy_gauss)(x, y, bb4ddata->sigma_x, bb4ddata->sigma_y,
@@ -127,152 +141,199 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_beam_4d)(
         px += (fact_kick*Ex - bb4ddata->Dpx_sub);
         py += (fact_kick*Ey - bb4ddata->Dpy_sub);
 
-        NS(Particles_set_px_value)( particles, particle_index, px );
-        NS(Particles_set_py_value)( particles, particle_index, py );
+        NS(Particles_set_px_value)( p, ii, px );
+        NS(Particles_set_py_value)( p, ii, py );
     }
 
     return SIXTRL_TRACK_SUCCESS;
 }
 
 /* ************************************************************************* */
-/* SpaceChargeCoasting: */
+/* NS(SCCoasting): */
 
 SIXTRL_INLINE NS(track_status_t) NS(Track_particle_space_charge_coasting)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
-    NS(particle_num_elements_t) const particle_index,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT sc )
+    NS(particle_num_elements_t) const ii,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
 {
-     typedef SIXTRL_REAL_T real_t;
-     typedef SIXTRL_BE_DATAPTR_DEC NS(SpaceChargeCoasting_data)* data_ptr_t;
+    typedef SIXTRL_REAL_T real_t;
 
+    SIXTRL_ARGPTR_DEC real_t Ex;
+    SIXTRL_ARGPTR_DEC real_t Ey;
+    SIXTRL_ARGPTR_DEC real_t Gx;
+    SIXTRL_ARGPTR_DEC real_t Gy;
+
+    real_t const charge = NS(PhysConst_charge0_si)() *
+        NS(Particles_get_q0_value)( particles, ii );
+
+    real_t const beta0 = NS(Particles_get_beta0_value)( particles, ii );
+    real_t const pc0   = NS(Particles_get_p0c_value)( particles, ii ) *
+                         NS(PhysConst_charge0_si)();
+
+    real_t fact_kick =
+        NS(SCCoasting_number_of_particles)( sc_elem ) *
+        NS(SCCoasting_length)( sc_elem ) *
+        NS(Particles_get_chi_value)( particles, ii ) *
+        NS(Particles_get_charge_ratio_value)( particles, ii ) *
+        charge * charge * ( ( real_t )1 - beta0 * beta0 );
+
+    fact_kick /= NS(SCCoasting_circumference)( sc_elem ) *
+                 pc0 * beta0 * NS(Particles_get_rvv_value)( particles, ii );
+
+    NS(get_Ex_Ey_Gx_Gy_gauss)(
+        NS(Particles_get_x_value)( particles, ii ) -
+            NS(SCCoasting_x_co)( sc_elem ),
+        NS(Particles_get_y_value)( particles, ii ) -
+            NS(SCCoasting_y_co)( sc_elem ),
+        NS(SCCoasting_sigma_x)( sc_elem ),
+        NS(SCCoasting_sigma_y)( sc_elem ),
+        NS(SCCoasting_min_sigma_diff)( sc_elem ),
+        ( int )1, &Ex, &Ey, &Gx, &Gy );
+
+    NS(Particles_add_to_px_value)( particles, ii, fact_kick * Ex );
+    NS(Particles_add_to_py_value)( particles, ii, fact_kick * Ey );
+
+    return ( NS(track_status_t) )SIXTRL_TRACK_SUCCESS;
+}
 
-    data_ptr_t scdata = ( data_ptr_t )NS(SpaceChargeCoasting_get_const_data)( sc );
+/* ************************************************************************* */
+/* NS(SCQGaussProfile) */
 
-    /*
-    // Test data transfer
-    printf("SCC: line_density = %e\n",scdata->line_density);
-    printf("SCC: sigma_x = %e\n",scdata->sigma_x);
-    printf("SCC: sigma_y = %e\n",scdata->sigma_y);
-    printf("SCC: length = %e\n",scdata->length);
-    printf("SCC: x_co = %e\n",scdata->x_co);
-    printf("SCC: y_co = %e\n",scdata->y_co);
-    printf("SCC: min_sigma_diff = %e\n",scdata->min_sigma_diff);
-    printf("SCC: enabled = %e\n",scdata->enabled);
-    */
+SIXTRL_INLINE NS(track_status_t)
+NS(Track_particle_space_charge_qgaussian_profile)( SIXTRL_PARTICLE_ARGPTR_DEC
+        NS(Particles)* SIXTRL_RESTRICT p, NS(particle_num_elements_t) const ii,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_REAL_T real_t;
 
-    SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, particle_index )
-        == ( NS(particle_index_t) )1 );
+    SIXTRL_ARGPTR_DEC real_t Ex;
+    SIXTRL_ARGPTR_DEC real_t Ey;
+    SIXTRL_ARGPTR_DEC real_t Gx;
+    SIXTRL_ARGPTR_DEC real_t Gy;
 
-    if (scdata->enabled > 0.) {
+    real_t const charge = NS(PhysConst_charge0_si)() *
+        NS(Particles_get_q0_value)( p, ii );
 
-        real_t px = NS(Particles_get_px_value)( particles, particle_index );
-        real_t py = NS(Particles_get_py_value)( particles, particle_index );
+    real_t const beta0 = NS(Particles_get_beta0_value)( p, ii );
+    real_t const beta  = beta0 * NS(Particles_get_rvv_value)( p, ii );
+    real_t const pc0   = NS(Particles_get_p0c_value)( p, ii ) *
+                         NS(PhysConst_charge0_si)();
 
-        real_t qratio = 1.;// To be generalized for multi-ion!
-        real_t charge =
-	   qratio*NS(Particles_get_q0_value)( particles, particle_index )*SIXTRL_QELEM;
+    real_t const z = NS(Particles_get_zeta_value)( p, ii ) /
+                     NS(Particles_get_rvv_value)( p, ii );
 
-        real_t x = NS(Particles_get_x_value)( particles, particle_index )
-	       	- scdata->x_co;
-        real_t y = NS(Particles_get_y_value)( particles, particle_index )
-		- scdata->y_co;
+    real_t const bunchlength_rms =
+        NS(SCQGaussProfile_bunchlength_rms)( sc_elem );
 
-	real_t chi = NS(Particles_get_chi_value)( particles, particle_index );
+    real_t fact_kick =
+        NS(Particles_get_chi_value)( p, ii ) *
+        NS(Particles_get_charge_ratio_value)( p, ii ) *
+        NS(SCQGaussProfile_length)( sc_elem ) *
+        charge * charge * ( ( real_t )1 - beta0 * beta );
 
-        real_t beta0 = NS(Particles_get_beta0_value)( particles, particle_index );
-        real_t beta = beta0 / NS(Particles_get_rvv_value)( particles, particle_index );
-        real_t p0c = NS(Particles_get_p0c_value)( particles, particle_index )
-		*SIXTRL_QELEM;
+    SIXTRL_ASSERT( NS(Type_comp_all_more)(
+        NS(Particles_get_rvv_value)( p, ii ), ( real_t )0 ) );
 
-        real_t Ex, Ey, Gx, Gy;
-        NS(get_Ex_Ey_Gx_Gy_gauss)(x, y, scdata->sigma_x, scdata->sigma_y,
-                scdata->min_sigma_diff, 1,
-                &Ex, &Ey, &Gx, &Gy);
+    SIXTRL_ASSERT( NS(Type_comp_all_more)(
+        NS(Particles_get_beta0_value)( p, ii ), ( real_t )0 ) );
 
-	real_t fact_kick = chi * charge * charge * (1. - beta0 * beta) / (p0c * beta)
-		* scdata->line_density * scdata->length;
-        px += (fact_kick*Ex);
-        py += (fact_kick*Ey);
+    SIXTRL_ASSERT( NS(Type_comp_all_less_or_equal)(
+        NS(Particles_get_beta0_value)( p, ii ), ( real_t )1 ) );
 
-        NS(Particles_set_px_value)( particles, particle_index, px );
-        NS(Particles_set_py_value)( particles, particle_index, py );
-    }
+    fact_kick *=
+        NS(SCQGaussProfile_number_of_particles)( sc_elem );
 
-    return SIXTRL_TRACK_SUCCESS;
+    fact_kick *= NS(Math_q_gauss)( z,
+        NS(SCQGaussProfile_q_param)( sc_elem ),
+        NS(Math_q_gauss_sqrt_beta_from_gauss_sigma)( bunchlength_rms ),
+        NS(SCQGaussProfile_cq)( sc_elem ) );
+
+    fact_kick /= pc0 * beta;
+    NS(get_Ex_Ey_Gx_Gy_gauss)(
+            NS(Particles_get_x_value)( p, ii ) -
+                NS(SCQGaussProfile_x_co)( sc_elem ),
+            NS(Particles_get_y_value)( p, ii ) -
+                NS(SCQGaussProfile_y_co)( sc_elem ),
+            NS(SCQGaussProfile_sigma_x)( sc_elem ),
+            NS(SCQGaussProfile_sigma_y)( sc_elem ),
+            NS(SCQGaussProfile_min_sigma_diff)( sc_elem ),
+            ( int )1, &Ex, &Ey, &Gx, &Gy );
+
+    NS(Particles_add_to_px_value)( p, ii, fact_kick * Ex );
+    NS(Particles_add_to_py_value)( p, ii, fact_kick * Ey );
 
+    return ( NS(track_status_t) )SIXTRL_TRACK_SUCCESS;
 }
 
 /* ************************************************************************* */
-/* SpaceChargeBunched: */
+/* NS(SCInterpolatedProfile) */
 
-SIXTRL_INLINE NS(track_status_t) NS(Track_particle_space_charge_bunched)(
+SIXTRL_INLINE NS(track_status_t)
+NS(Track_particle_space_charge_interpolated_profile)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
-    NS(particle_num_elements_t) const particle_index,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT sc )
+    NS(particle_num_elements_t) const ii,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT sc_elem ) SIXTRL_NOEXCEPT
 {
-     typedef SIXTRL_REAL_T real_t;
-     typedef SIXTRL_BE_DATAPTR_DEC NS(SpaceChargeBunched_data)* data_ptr_t;
-
-
-    data_ptr_t scdata = ( data_ptr_t )NS(SpaceChargeBunched_get_const_data)( sc );
-
-    /*
-    // Test data transfer
-    printf("SCB: number_of_particles = %e\n",scdata->number_of_particles);
-    printf("SCB: bunchlength_rms = %e\n",scdata->bunchlength_rms);
-    printf("SCB: sigma_x = %e\n",scdata->sigma_x);
-    printf("SCB: sigma_y = %e\n",scdata->sigma_y);
-    printf("SCB: length = %e\n",scdata->length);
-    printf("SCB: x_co = %e\n",scdata->x_co);
-    printf("SCB: y_co = %e\n",scdata->y_co);
-    printf("SCB: min_sigma_diff = %e\n",scdata->min_sigma_diff);
-    printf("SCB: enabled = %e\n",scdata->enabled);
-    */
-
-    SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, particle_index )
-        == ( NS(particle_index_t) )1 );
-
-    if (scdata->enabled > 0.) {
-
-        real_t px = NS(Particles_get_px_value)( particles, particle_index );
-        real_t py = NS(Particles_get_py_value)( particles, particle_index );
-
-        real_t qratio = 1.;// To be generalized for multi-ion!
-        real_t charge =
-	   qratio*NS(Particles_get_q0_value)( particles, particle_index )*SIXTRL_QELEM;
-
-        real_t x = NS(Particles_get_x_value)( particles, particle_index )
-	       	- scdata->x_co;
-        real_t y = NS(Particles_get_y_value)( particles, particle_index )
-		- scdata->y_co;
-        real_t zeta = NS(Particles_get_zeta_value)( particles, particle_index );
-
-	real_t chi = NS(Particles_get_chi_value)( particles, particle_index );
+    typedef SIXTRL_REAL_T real_t;
 
-        real_t beta0 = NS(Particles_get_beta0_value)( particles, particle_index );
-        real_t beta = beta0 / NS(Particles_get_rvv_value)( particles, particle_index );
-        real_t p0c = NS(Particles_get_p0c_value)( particles, particle_index )
-		*SIXTRL_QELEM;
+    SIXTRL_ARGPTR_DEC real_t Ex;
+    SIXTRL_ARGPTR_DEC real_t Ey;
+    SIXTRL_ARGPTR_DEC real_t Gx;
+    SIXTRL_ARGPTR_DEC real_t Gy;
+
+    real_t const charge = NS(PhysConst_charge0_si)() *
+        NS(Particles_get_q0_value)( particles, ii );
+
+    real_t const beta0 = NS(Particles_get_beta0_value)( particles, ii );
+    real_t const beta  = beta0 * NS(Particles_get_rvv_value)( particles, ii );
+    real_t const pc0   = NS(Particles_get_p0c_value)( particles, ii ) *
+                         NS(PhysConst_charge0_si)();
+
+    real_t fact_kick =
+        NS(Particles_get_chi_value)( particles, ii ) *
+        NS(Particles_get_charge_ratio_value)( particles, ii ) *
+        NS(SCInterpolatedProfile_length)( sc_elem ) *
+        NS(SCInterpolatedProfile_number_of_particles)( sc_elem ) *
+        charge * charge * ( ( real_t )1 - beta0 * beta );
+
+    SIXTRL_BUFFER_DATAPTR_DEC NS(LineDensityProfileData) const* interpol =
+        NS(SCInterpolatedProfile_const_line_density_profile_data)(
+            sc_elem );
+
+    if( ( interpol != SIXTRL_NULLPTR ) &&
+        ( NS(LineDensityProfileData_method)( interpol ) !=
+          NS(MATH_INTERPOL_NONE) ) &&
+        ( NS(LineDensityProfileData_num_values)( interpol ) >
+          ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        fact_kick *= NS(LineDensityProfileData_interpolate_value)(
+            interpol, NS(Particles_get_zeta_value)( particles, ii ) );
+    }
+    else
+    {
+        fact_kick *=
+        NS(SCInterpolatedProfile_line_density_prof_fallback)( sc_elem );
+    }
 
-        real_t Ex, Ey, Gx, Gy;
-        NS(get_Ex_Ey_Gx_Gy_gauss)(x, y, scdata->sigma_x, scdata->sigma_y,
-                scdata->min_sigma_diff, 1,
-                &Ex, &Ey, &Gx, &Gy);
+    fact_kick /= ( pc0 * beta );
 
-	real_t fact_kick = chi * charge * charge * (1. - beta0 * beta) / (p0c * beta)
-		* scdata->length * scdata->number_of_particles
-		/ (scdata -> bunchlength_rms * sqrt(2*SIXTRL_PI))
-		* exp(-0.5*(zeta /scdata->bunchlength_rms)
-				*(zeta /scdata->bunchlength_rms));
-        px += (fact_kick*Ex);
-        py += (fact_kick*Ey);
+    NS(get_Ex_Ey_Gx_Gy_gauss)(
+            NS(Particles_get_x_value)( particles, ii ) -
+                NS(SCInterpolatedProfile_x_co)( sc_elem ),
+            NS(Particles_get_y_value)( particles, ii ) -
+                NS(SCInterpolatedProfile_y_co)( sc_elem ),
+            NS(SCInterpolatedProfile_sigma_x)( sc_elem ),
+            NS(SCInterpolatedProfile_sigma_y)( sc_elem ),
+            NS(SCInterpolatedProfile_min_sigma_diff)( sc_elem ),
+            ( int )1, &Ex, &Ey, &Gx, &Gy );
 
-        NS(Particles_set_px_value)( particles, particle_index, px );
-        NS(Particles_set_py_value)( particles, particle_index, py );
-    }
-
-    return SIXTRL_TRACK_SUCCESS;
+    NS(Particles_add_to_px_value)( particles, ii, fact_kick * Ex );
+    NS(Particles_add_to_py_value)( particles, ii, fact_kick * Ey );
 
+    return ( NS(track_status_t) )SIXTRL_TRACK_SUCCESS;
 }
 
 /* ************************************************************************* */
@@ -280,7 +341,7 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_space_charge_bunched)(
 
 SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_beam_6d)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
-    NS(particle_num_elements_t)  const particle_index,
+    NS(particle_num_elements_t)  const ii,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT bb )
 {
     typedef SIXTRL_REAL_T real_t;
@@ -289,10 +350,10 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_beam_6d)(
     int i_slice;
 
     // Start Gianni's part
-    data_ptr_t bb6ddata = ( data_ptr_t )NS(BeamBeam6D_get_const_data)( bb );
+    data_ptr_t bb6ddata = ( data_ptr_t )NS(BeamBeam6D_const_data)( bb );
 
-    SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, particle_index )
-        == ( NS(particle_index_t) )1 );
+    SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, ii )
+        == ( NS(particle_num_elements_t) )1 );
 
     if (bb6ddata->enabled > 0.) {
 
@@ -321,15 +382,15 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_beam_6d)(
         printf("sigma_slices_star[1]=%e\n",sigma_slices_star[1]);
         */
 
-        real_t x = NS(Particles_get_x_value)( particles, particle_index );
-        real_t px = NS(Particles_get_px_value)( particles, particle_index );
-        real_t y = NS(Particles_get_y_value)( particles, particle_index );
-        real_t py = NS(Particles_get_py_value)( particles, particle_index );
-        real_t zeta = NS(Particles_get_zeta_value)( particles, particle_index );
-        real_t delta = NS(Particles_get_delta_value)( particles, particle_index );
+        real_t x = NS(Particles_get_x_value)( particles, ii );
+        real_t px = NS(Particles_get_px_value)( particles, ii );
+        real_t y = NS(Particles_get_y_value)( particles, ii );
+        real_t py = NS(Particles_get_py_value)( particles, ii );
+        real_t zeta = NS(Particles_get_zeta_value)( particles, ii );
+        real_t delta = NS(Particles_get_delta_value)( particles, ii );
 
-        real_t q0 = SIXTRL_QELEM*NS(Particles_get_q0_value)( particles, particle_index );
-        real_t p0c = NS(Particles_get_p0c_value)( particles, particle_index ); // eV
+        real_t q0 = SIXTRL_QELEM*NS(Particles_get_q0_value)( particles, ii );
+        real_t p0c = NS(Particles_get_p0c_value)( particles, ii ); // eV
 
         real_t P0 = p0c/SIXTRL_C_LIGHT*SIXTRL_QELEM;
 
@@ -434,12 +495,12 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_beam_6d)(
         delta = delta_star + bb6ddata->delta_CO                    - bb6ddata->Ddelta_sub;
 
 
-        NS(Particles_set_x_value)( particles, particle_index, x );
-        NS(Particles_set_px_value)( particles, particle_index, px );
-        NS(Particles_set_y_value)( particles, particle_index, y );
-        NS(Particles_set_py_value)( particles, particle_index, py );
-        NS(Particles_set_zeta_value)( particles, particle_index, zeta );
-        NS(Particles_update_delta_value)( particles, particle_index, delta );
+        NS(Particles_set_x_value)( particles, ii, x );
+        NS(Particles_set_px_value)( particles, ii, px );
+        NS(Particles_set_y_value)( particles, ii, y );
+        NS(Particles_set_py_value)( particles, ii, py );
+        NS(Particles_set_zeta_value)( particles, ii, zeta );
+        NS(Particles_update_delta_value)( particles, ii, delta );
     }
 
     return SIXTRL_TRACK_SUCCESS;
@@ -448,8 +509,4 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_beam_6d)(
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
-
 #endif /* SIXTRACKLIB_COMMON_BE_BEAMFIELDS_TRACK_BEAMFIELDS_H__ */
-
-/* end: sixtracklib/common/be_beamfields/track.h */
diff --git a/sixtracklib/common/be_cavity/CMakeLists.txt b/sixtracklib/common/be_cavity/CMakeLists.txt
index 89d8a1bc..90ec0ccc 100644
--- a/sixtracklib/common/be_cavity/CMakeLists.txt
+++ b/sixtracklib/common/be_cavity/CMakeLists.txt
@@ -1,49 +1,38 @@
-set( SIXTRACKLIB_COMMON_BE_CAVITY_C99_HEADERS
-     be_cavity.h
-)
+set( SIXTRL_COMMON_BE_CAVITY_C99_HEADERS be_cavity.h track.h )
+set( SIXTRL_COMMON_BE_CAVITY_C99_SOURCES be_cavity.c )
+set( SIXTRL_COMMON_BE_CAVITY_CXX_HEADERS be_cavity.hpp )
 
-set( SIXTRACKLIB_COMMON_BE_CAVITY_CXX_HEADERS
-     be_cavity.hpp
-)
+add_library( sixtrack_common_be_cavity OBJECT
+    ${SIXTRL_COMMON_BE_CAVITY_C99_HEADERS}
+    ${SIXTRL_COMMON_BE_CAVITY_C99_SOURCES} )
 
-if( SIXTRACKLIB_COMMON_BE_CAVITY_C99_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_cavity/\\1" LOCAL_C99_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_CAVITY_C99_HEADERS}" )
+target_include_directories( sixtrack_common_be_cavity PRIVATE
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-    set(  SIXTRACKLIB_COMMON_C99_HEADERS
-        ${SIXTRACKLIB_COMMON_C99_HEADERS}
-        ${LOCAL_C99_HEADERS} PARENT_SCOPE )
-endif()
+set_target_properties( sixtrack_common_be_cavity PROPERTIES
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
+    C_STANDARD_REQUIRED ON )
 
-if( SIXTRACKLIB_COMMON_BE_CAVITY_CXX_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_cavity/\\1" LOCAL_CXX_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_CAVITY_CXX_HEADERS}" )
+target_compile_options( sixtrack_common_be_cavity PRIVATE
+        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
-    set(  SIXTRACKLIB_COMMON_CXX_HEADERS
-        ${SIXTRACKLIB_COMMON_CXX_HEADERS}
-        ${LOCAL_CXX_HEADERS} PARENT_SCOPE )
-endif()
+# ------------------------------------------------------------------------------
+# pass on sixtrack_common_be_beambeam as a module for sixtracklib:
+
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_common_be_cavity> CACHE INTERNAL "" FORCE )
 
 # ----------------------------------------------------------------------------
 # install :
 
-if( SIXTRACKLIB_COMMON_BE_CAVITY_C99_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_CAVITY_C99_INSTALL_PATH
-         include/sixtracklib/common/be_cavity )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_CAVITY_C99_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_CAVITY_C99_INSTALL_PATH} )
+if( SIXTRL_COMMON_BE_CAVITY_C99_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_CAVITY_C99_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/be_cavity" )
 endif()
 
+if( SIXTRACKL_ENABLE_CXX AND SIXTRL_COMMON_BE_CAVITY_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_CAVITY_CXX_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/be_cavity" )
+ endif()
 
-if( SIXTRACKLIB_COMMON_BE_CAVITY_CXX_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_CAVITY_CXX_INSTALL_PATH
-         include/sixtracklib/common/be_cavity )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_CAVITY_CXX_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_CAVITY_CXX_INSTALL_PATH} )
-endif()
-
-#end: sixtracklib/common/be_cavity/CMakeLists.txt
diff --git a/sixtracklib/common/be_cavity/be_cavity.c b/sixtracklib/common/be_cavity/be_cavity.c
new file mode 100644
index 00000000..170b20f2
--- /dev/null
+++ b/sixtracklib/common/be_cavity/be_cavity.c
@@ -0,0 +1,158 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/be_cavity/be_cavity.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+
+NS(object_type_id_t) NS(Cavity_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(Cavity_type_id)();
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(Cavity_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( cavity ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(Cavity_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( cavity ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(Cavity_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( cavity ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_counts > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(Cavity_can_be_added)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    NS(Cavity) temp;
+    NS(arch_status_t) const status = NS(Cavity_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(Cavity_num_dataptrs)( &temp );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof( NS(Cavity) ),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects,
+                    requ_slots, requ_dataptrs ) ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(Cavity)* added_elem = SIXTRL_NULLPTR;
+
+    NS(Cavity) temp;
+    NS(arch_status_t) const status = NS(Cavity_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(Cavity_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(Cavity)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(Cavity) ), NS(Cavity_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_REAL_T  const voltage,
+    SIXTRL_REAL_T  const frequency,
+    SIXTRL_REAL_T  const lag )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(Cavity)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) ndataptrs = ( NS(buffer_size_t) )0;
+
+    NS(Cavity) temp;
+    NS(arch_status_t) status = NS(Cavity_set_voltage)( &temp, voltage );
+    status |= NS(Cavity_set_frequency)( &temp, frequency );
+    status |= NS(Cavity_set_lag)( &temp, lag );
+    ndataptrs = NS(Cavity_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(Cavity)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(Cavity) ), NS(Cavity_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(Cavity)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(Cavity_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(Cavity)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(Cavity) ), NS(Cavity_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
diff --git a/sixtracklib/common/be_cavity/be_cavity.h b/sixtracklib/common/be_cavity/be_cavity.h
index 088e980d..3b4dc561 100644
--- a/sixtracklib/common/be_cavity/be_cavity.h
+++ b/sixtracklib/common/be_cavity/be_cavity.h
@@ -9,10 +9,13 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
-    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -31,100 +34,129 @@ NS(Cavity);
 
 /* ------------------------------------------------------------------------- */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(Cavity_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(Cavity) *const SIXTRL_RESTRICT cavity );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(Cavity_type_id)(
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(Cavity_get_num_slots)(
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(Cavity_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC  const NS(Cavity) *const
+        SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(Cavity_num_slots)(
     SIXTRL_BE_ARGPTR_DEC  const NS(Cavity) *const SIXTRL_RESTRICT cavity,
-    NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_preset)(
-    SIXTRL_BE_ARGPTR_DEC  NS(Cavity)* SIXTRL_RESTRICT cavity );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_preset)(
+    SIXTRL_BE_ARGPTR_DEC  NS(Cavity)* SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_REAL_T NS(Cavity_get_voltage)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Cavity_voltage)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const
+        SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_REAL_T NS(Cavity_get_frequency)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(Cavity) *const SIXTRL_RESTRICT cavity );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Cavity_frequency)(
+    SIXTRL_BE_ARGPTR_DEC  const NS(Cavity) *const
+        SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_REAL_T NS(Cavity_get_lag)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(Cavity) *const SIXTRL_RESTRICT cavity );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Cavity_lag)(
+    SIXTRL_BE_ARGPTR_DEC  const NS(Cavity) *const
+        SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(Cavity_set_voltage)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Cavity_set_voltage)(
     SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity,
-    SIXTRL_REAL_T const voltage );
+    SIXTRL_REAL_T const voltage ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(Cavity_set_frequency)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Cavity_set_frequency)(
     SIXTRL_BE_ARGPTR_DEC  NS(Cavity)* SIXTRL_RESTRICT cavity,
-    SIXTRL_REAL_T const frequency );
+    SIXTRL_REAL_T const frequency ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(Cavity_set_lag)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Cavity_set_lag)(
     SIXTRL_BE_ARGPTR_DEC  NS(Cavity)* SIXTRL_RESTRICT cavity,
-    SIXTRL_REAL_T const lag );
+    SIXTRL_REAL_T const lag ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(Cavity_clear)(
-    SIXTRL_BE_ARGPTR_DEC  NS(Cavity)* SIXTRL_RESTRICT cavity );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Cavity_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(Cavity_copy)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Cavity_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT source );
-
-SIXTRL_FN SIXTRL_STATIC int NS(Cavity_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT rhs );
-
-SIXTRL_FN SIXTRL_STATIC int NS(Cavity_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const
+        SIXTRL_RESTRICT source ) SIXTRL_NOEXCEPT;
 
 /* ------------------------------------------------------------------------- */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity) const*
-NS(BufferIndex_get_const_cavity)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity) const*
+NS(Cavity_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)*
-NS(BufferIndex_get_cavity)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity)*
+NS(Cavity_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity) const*
-NS(BeamElements_managed_buffer_get_const_cavity)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity) const*
+NS(Cavity_const_from_manged_buffer)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
     NS(buffer_size_t) const be_index,
-    NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)*
-NS(BeamElements_managed_buffer_get_cavity)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity)*
+NS(Cavity_from_manged_buffer)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const be_index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity) const*
-NS(BeamElements_buffer_get_const_cavity)(
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity) const*
+NS(Cavity_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const be_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)*
-NS(BeamElements_buffer_get_cavity)(
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity)*
+NS(Cavity_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const be_index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(Cavity_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(Cavity_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(Cavity_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t) NS(Cavity_type_id_ext)(
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC bool NS(Cavity_can_be_added)(
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(Cavity_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)* NS(Cavity_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity)*
+NS(Cavity_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)* NS(Cavity_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity)*
+NS(Cavity_add)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_REAL_T  const voltage, SIXTRL_REAL_T  const frequency,
     SIXTRL_REAL_T  const lag );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Cavity)*
 NS(Cavity_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity );
@@ -140,6 +172,7 @@ NS(Cavity_add_copy)(
 /* ************************************************************************* */
 
 #if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer.h"
     #if !defined( _GPUCODE )
         #include "sixtracklib/common/buffer.h"
     #endif /* !defined( _GPUCODE ) */
@@ -149,401 +182,187 @@ NS(Cavity_add_copy)(
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
+SIXTRL_INLINE NS(object_type_id_t) NS(Cavity_type_id)( void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_CAVITY);
+}
 
-SIXTRL_INLINE NS(buffer_size_t) NS(Cavity_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity )
+SIXTRL_INLINE NS(buffer_size_t) NS(Cavity_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC
+    const NS(Cavity) *const SIXTRL_RESTRICT
+        SIXTRL_UNUSED( cavity ) ) SIXTRL_NOEXCEPT
 {
     return ( NS(buffer_size_t) )0u;
 }
 
-SIXTRL_INLINE NS(buffer_size_t) NS(Cavity_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(Cavity) *const SIXTRL_RESTRICT cavity,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(buffer_size_t) NS(Cavity_num_slots)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Cavity) *const SIXTRL_RESTRICT SIXTRL_UNUSED( cavity ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(Cavity)        beam_element_t;
-
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
-
-    ( void )cavity;
-
-    buf_size_t extent = NS(ManagedBuffer_get_slot_based_length)(
-        sizeof( beam_element_t ), slot_size );
-
-    SIXTRL_ASSERT( ( slot_size == ZERO ) || ( ( extent % slot_size ) == ZERO ) );
-    return ( slot_size > ZERO ) ? ( extent / slot_size ) : ( ZERO );
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0;
+    NS(buffer_size_t) const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+        sizeof( NS(Cavity) ), slot_size );
+
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
+    return num_slots;
 }
 
 SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity )
+    SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT
 {
-    NS(Cavity_clear)( cavity );
+    if( cavity != SIXTRL_NULLPTR ) NS(Cavity_clear)( cavity );
     return cavity;
 }
 
-SIXTRL_INLINE SIXTRL_REAL_T NS(Cavity_get_voltage)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity )
+SIXTRL_INLINE NS(arch_status_t) NS(Cavity_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = NS(Cavity_set_voltage)(
+        cavity, ( SIXTRL_REAL_T )0 );
+
+    status |= NS(Cavity_set_frequency)( cavity, ( SIXTRL_REAL_T )0 );
+    status |= NS(Cavity_set_lag)( cavity, ( SIXTRL_REAL_T )0 );
+    return status;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Cavity_voltage)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Cavity) *const SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( cavity != SIXTRL_NULLPTR );
     return cavity->voltage;
 }
 
-SIXTRL_INLINE SIXTRL_REAL_T NS(Cavity_get_frequency)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity )
+SIXTRL_INLINE SIXTRL_REAL_T NS(Cavity_frequency)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Cavity) *const SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( cavity != SIXTRL_NULLPTR );
     return cavity->frequency;
 }
 
-SIXTRL_INLINE SIXTRL_REAL_T NS(Cavity_get_lag)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity )
+SIXTRL_INLINE SIXTRL_REAL_T NS(Cavity_lag)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Cavity) *const SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( cavity != SIXTRL_NULLPTR );
     return cavity->lag;
 }
 
-SIXTRL_INLINE void NS(Cavity_set_voltage)(
+SIXTRL_INLINE NS(arch_status_t) NS(Cavity_set_voltage)(
     SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity,
-    SIXTRL_REAL_T const voltage )
+    SIXTRL_REAL_T const voltage ) SIXTRL_NOEXCEPT
 {
-    if( cavity != SIXTRL_NULLPTR ) cavity->voltage = voltage;
-    return;
+    SIXTRL_ASSERT( cavity != SIXTRL_NULLPTR );
+    cavity->voltage = voltage;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(Cavity_set_frequency)(
+SIXTRL_INLINE NS(arch_status_t) NS(Cavity_set_frequency)(
     SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity,
-    SIXTRL_REAL_T const frequency )
+    SIXTRL_REAL_T const frequency ) SIXTRL_NOEXCEPT
 {
-    if( cavity != SIXTRL_NULLPTR ) cavity->frequency = frequency;
-    return;
+    SIXTRL_ASSERT( cavity != SIXTRL_NULLPTR );
+    cavity->frequency = frequency;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(Cavity_set_lag)(
+SIXTRL_INLINE NS(arch_status_t) NS(Cavity_set_lag)(
     SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity,
-    SIXTRL_REAL_T const lag )
-{
-    if( cavity != SIXTRL_NULLPTR ) cavity->lag = lag;
-    return;
-}
-
-SIXTRL_INLINE void NS(Cavity_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT cavity )
+    SIXTRL_REAL_T const lag ) SIXTRL_NOEXCEPT
 {
-    NS(Cavity_set_voltage)(   cavity, ( SIXTRL_REAL_T )0 );
-    NS(Cavity_set_frequency)( cavity, ( SIXTRL_REAL_T )0 );
-    NS(Cavity_set_lag)(       cavity, ( SIXTRL_REAL_T )0 );
-
-    return;
+    SIXTRL_ASSERT( cavity != SIXTRL_NULLPTR );
+    cavity->lag = lag;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE int NS(Cavity_copy)(
+SIXTRL_INLINE NS(arch_status_t) NS(Cavity_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(Cavity)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT source )
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const
+        SIXTRL_RESTRICT source ) SIXTRL_NOEXCEPT
 {
-    int success = -1;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
     if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) )
     {
-        NS(Cavity_set_voltage)(
-            destination, NS(Cavity_get_voltage)( source ) );
-
-        NS(Cavity_set_frequency)(
-            destination, NS(Cavity_get_frequency)( source ) );
-
-        NS(Cavity_set_lag)( destination, NS(Cavity_get_lag)( source ) );
-
-        success = 0;
-    }
-
-    return success;
-}
-
-SIXTRL_INLINE int NS(Cavity_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT rhs )
-{
-    int compare_value = -1;
-
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
-    {
-        compare_value = 0;
-
-        if( NS(Cavity_get_voltage)( lhs ) >
-            NS(Cavity_get_voltage)( rhs ) )
-        {
-            compare_value = +1;
-        }
-        else if( NS(Cavity_get_voltage)( lhs ) <
-                 NS(Cavity_get_voltage)( rhs ) )
-        {
-            compare_value = -1;
-        }
-
-        if( compare_value == 0 )
-        {
-            if( NS(Cavity_get_frequency)( lhs ) >
-                NS(Cavity_get_frequency)( rhs ) )
-            {
-                compare_value = +1;
-            }
-            else if( NS(Cavity_get_frequency)( lhs ) <
-                     NS(Cavity_get_frequency)( rhs ) )
-            {
-                compare_value = -1;
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            if( NS(Cavity_get_lag)( lhs ) > NS(Cavity_get_lag)( rhs ) )
-            {
-                compare_value = +1;
-            }
-            else if( NS(Cavity_get_lag)( lhs ) < NS(Cavity_get_lag)( rhs ) )
-            {
-                compare_value = -1;
-            }
-        }
-    }
-    else if( lhs != SIXTRL_NULLPTR )
-    {
-        compare_value = +1;
-    }
-
-    return compare_value;
-}
-
-SIXTRL_INLINE int NS(Cavity_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
-{
-    typedef SIXTRL_REAL_T       real_t;
-
-    SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0.0;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 
-    int compare_value = -1;
-
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) &&
-        ( treshold >= ZERO ) )
-    {
-        compare_value = 0;
-
-        if( compare_value == 0 )
+        if( destination != source )
         {
-            real_t const diff =
-                NS(Cavity_get_voltage)( lhs ) - NS(Cavity_get_voltage)( rhs );
-
-            real_t const abs_diff = ( diff >= ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
+            status |= NS(Cavity_set_voltage)( destination,
+                NS(Cavity_voltage)( source ) );
 
-        if( compare_value == 0 )
-        {
-            real_t const diff = NS(Cavity_get_frequency)( lhs ) -
-                                NS(Cavity_get_frequency)( rhs );
-
-            real_t const abs_diff = ( diff >= ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
+            status |= NS(Cavity_set_frequency)( destination,
+                NS(Cavity_frequency)( source ) );
 
-        if( compare_value == 0 )
-        {
-            real_t const diff =
-                NS(Cavity_get_lag)( lhs ) - NS(Cavity_get_lag)( rhs );
-
-            real_t const abs_diff = ( diff >= ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
+            status |= NS(Cavity_set_lag)( destination,
+                NS(Cavity_lag)( source ) );
         }
     }
-    else if( ( lhs != SIXTRL_NULLPTR ) && ( treshold >= ZERO ) )
-    {
-        compare_value = +1;
-    }
 
-    return compare_value;
+    return status;
 }
 
 /* ------------------------------------------------------------------------- */
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity) const*
-NS(BufferIndex_get_const_cavity)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Cavity) const*
+NS(Cavity_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
 {
-    typedef NS(Cavity) beam_element_t;
-    typedef SIXTRL_BUFFER_OBJ_DATAPTR_DEC beam_element_t const* ptr_to_be_t;
-    ptr_to_be_t ptr_to_be = SIXTRL_NULLPTR;
-
-    if( ( index_obj != SIXTRL_NULLPTR ) &&
-        ( NS(Object_get_type_id)( index_obj ) == NS(OBJECT_TYPE_CAVITY) ) &&
-        ( NS(Object_get_size)( index_obj ) >= sizeof( beam_element_t ) ) )
+    SIXTRL_BE_ARGPTR_DEC NS(Cavity) const* elem = SIXTRL_NULLPTR;
+    if( ( obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_CAVITY) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(Cavity) ) ) )
     {
-        ptr_to_be = ( ptr_to_be_t )( uintptr_t
-            )NS(Object_get_begin_addr)( index_obj );
+        elem = ( SIXTRL_BE_ARGPTR_DEC NS(Cavity) const* )(
+            uintptr_t )NS(Object_get_begin_addr)( obj );
     }
 
-    return ptr_to_be;
+    return elem;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)*
-NS(BufferIndex_get_cavity)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* obj ) SIXTRL_NOEXCEPT
 {
     return ( SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)*
-        )NS(BufferIndex_get_const_cavity)( index_obj );
+        )NS(Cavity_const_from_obj_index)( obj );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity) const*
-NS(BeamElements_managed_buffer_get_const_cavity)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Cavity) const*
+NS(Cavity_const_from_manged_buffer)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+    NS(buffer_size_t) const be_index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_const_cavity)(
+    return NS(Cavity_const_from_obj_index)(
         NS(ManagedBuffer_get_const_object)( pbuffer, be_index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)*
-NS(BeamElements_managed_buffer_get_cavity)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_from_manged_buffer)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+    NS(buffer_size_t) const be_index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_cavity)(
+    return NS(Cavity_from_obj_index)(
         NS(ManagedBuffer_get_object)( pbuffer, be_index, slot_size ) );
 }
 
 #if !defined( _GPUCODE )
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity) const*
-NS(BeamElements_buffer_get_const_cavity)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Cavity) const*
+NS(Cavity_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+    NS(buffer_size_t) const be_index ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_const_cavity)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(Cavity_const_from_obj_index)( NS(Buffer_get_const_object)(
+        buffer, be_index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)*
-NS(BeamElements_buffer_get_cavity)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Cavity)* NS(Cavity_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+    NS(buffer_size_t) const be_index ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_cavity)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
-}
-
-SIXTRL_INLINE bool NS(Cavity_can_be_added)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs )
-{
-    typedef NS(buffer_size_t) buf_size_t;
-
-    buf_size_t const num_dataptrs =
-        NS(Cavity_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes  = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts = SIXTRL_NULLPTR;
-
-    return NS(Buffer_can_add_object)( buffer, sizeof( NS(Cavity) ),
-        num_dataptrs, sizes, counts, requ_objects, requ_slots, requ_dataptrs );
-}
-
-SIXTRL_INLINE SIXTRL_ARGPTR_DEC NS(Cavity)* NS(Cavity_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
-{
-    typedef NS(buffer_size_t)                       buf_size_t;
-    typedef SIXTRL_REAL_T                           real_t;
-    typedef NS(Cavity)                              elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC   elem_t*     ptr_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(Cavity_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.voltage   = ( real_t )0.0;
-    temp_obj.frequency = ( real_t )0.0;
-    temp_obj.lag       = ( real_t )0.0;
-
-    return ( ptr_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( temp_obj ),
-        NS(OBJECT_TYPE_CAVITY), num_dataptrs, offsets, sizes, counts ) );
-}
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)* NS(Cavity_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_REAL_T  const voltage,
-    SIXTRL_REAL_T  const frequency,
-    SIXTRL_REAL_T  const lag )
-{
-    typedef NS(buffer_size_t)                       buf_size_t;
-    typedef NS(Cavity)                              elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC   elem_t*     ptr_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(Cavity_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.voltage   = voltage;
-    temp_obj.frequency = frequency;
-    temp_obj.lag       = lag;
-
-    return ( ptr_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( temp_obj ),
-            NS(OBJECT_TYPE_CAVITY), num_dataptrs, offsets, sizes, counts ) );
-}
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)* NS(Cavity_add_copy)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity )
-{
-    return NS(Cavity_add)( buffer, NS(Cavity_get_voltage)( cavity ),
-        NS(Cavity_get_frequency)( cavity ), NS(Cavity_get_lag)( cavity ) );
-
+    return NS(Cavity_from_obj_index)(
+        NS(Buffer_get_object)( buffer, be_index ) );
 }
 
 #endif /* !defined( _GPUCODE ) */
@@ -551,7 +370,4 @@ SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Cavity)* NS(Cavity_add_copy)(
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRACKLIB_COMMON_BE_CAVITY_BEAM_ELEMENT_CAVITY_H__ */
-
-/*end: sixtracklib/common/be_cavity/be_cavity.h */
diff --git a/sixtracklib/common/be_cavity/be_cavity.hpp b/sixtracklib/common/be_cavity/be_cavity.hpp
index 9e7bf5de..947ab0f1 100644
--- a/sixtracklib/common/be_cavity/be_cavity.hpp
+++ b/sixtracklib/common/be_cavity/be_cavity.hpp
@@ -505,19 +505,19 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE TCavity< SIXTRL_REAL_T >::value_type
     TCavity< SIXTRL_REAL_T >::getVoltage() const SIXTRL_NOEXCEPT
     {
-        return ::NS(Cavity_get_voltage)( this->getCApiPtr() );
+        return ::NS(Cavity_voltage)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE TCavity< SIXTRL_REAL_T >::value_type
     TCavity< SIXTRL_REAL_T >::getFrequency() const SIXTRL_NOEXCEPT
     {
-        return ::NS(Cavity_get_frequency)( this->getCApiPtr() );
+        return ::NS(Cavity_frequency)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE TCavity< SIXTRL_REAL_T >::value_type
     TCavity< SIXTRL_REAL_T >::getLag() const SIXTRL_NOEXCEPT
     {
-        return ::NS(Cavity_get_lag)( this->getCApiPtr() );
+        return ::NS(Cavity_lag)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE void TCavity< SIXTRL_REAL_T >::preset() SIXTRL_NOEXCEPT
diff --git a/sixtracklib/common/be_cavity/track.h b/sixtracklib/common/be_cavity/track.h
index 858a96f2..642208ad 100644
--- a/sixtracklib/common/be_cavity/track.h
+++ b/sixtracklib/common/be_cavity/track.h
@@ -53,10 +53,10 @@ SIXTRL_INLINE int NS(Track_particle_cavity)(
     real_t         rvv    = NS(Particles_get_rvv_value)(          particles, index );
     real_t const   tau    = zeta / ( beta0 * rvv );
 
-    real_t const   phase  = DEG2RAD  * NS(Cavity_get_lag)( cavity ) -
-                            K_FACTOR * NS(Cavity_get_frequency)( cavity ) * tau;
+    real_t const   phase  = DEG2RAD  * NS(Cavity_lag)( cavity ) -
+                            K_FACTOR * NS(Cavity_frequency)( cavity ) * tau;
 
-    real_t const energy   = q * NS(Cavity_get_voltage)( cavity ) * sin( phase );
+    real_t const energy   = q * NS(Cavity_voltage)( cavity ) * sin( phase );
 
     SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, index ) ==
                    ( NS(particle_index_t) )1 );
diff --git a/sixtracklib/common/be_dipedge/CMakeLists.txt b/sixtracklib/common/be_dipedge/CMakeLists.txt
index 037a7858..b995e1a4 100644
--- a/sixtracklib/common/be_dipedge/CMakeLists.txt
+++ b/sixtracklib/common/be_dipedge/CMakeLists.txt
@@ -1,23 +1,14 @@
 # =============================================================================
 # end: sixtracklib/common/be_dipedge/CMakeLitst.txt
 
-set( SIXTRL_COMMON_BE_DIPEDGE_CXX_HEADERS 
-     be_dipedge.hpp
-)
-
-set( SIXTRL_COMMON_BE_DIPEDGE_C99_HEADERS 
-     be_dipedge.h
-     track.h
-)
-set( SIXTRL_COMMON_BE_DIPEDGE_C99_SOURCES 
-     be_dipedge.c
-)
+set( SIXTRL_COMMON_BE_DIPEDGE_CXX_HEADERS be_dipedge.hpp )
+set( SIXTRL_COMMON_BE_DIPEDGE_C99_HEADERS be_dipedge.h track.h )
+set( SIXTRL_COMMON_BE_DIPEDGE_C99_SOURCES be_dipedge.c )
 
 add_library( sixtrack_common_be_dipedge OBJECT
     ${SIXTRL_COMMON_BE_DIPEDGE_C99_HEADERS}
     ${SIXTRL_COMMON_BE_DIPEDGE_CXX_HEADERS}
-    ${SIXTRL_COMMON_BE_DIPEDGE_C99_SOURCES}
-)
+    ${SIXTRL_COMMON_BE_DIPEDGE_C99_SOURCES} )
 
 target_include_directories( sixtrack_common_be_dipedge PRIVATE
     $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
@@ -27,7 +18,8 @@ set_target_properties( sixtrack_common_be_dipedge PROPERTIES
     C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_be_dipedge PRIVATE
-    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_be_beambeam as a module for sixtracklib:
diff --git a/sixtracklib/common/be_dipedge/be_dipedge.c b/sixtracklib/common/be_dipedge/be_dipedge.c
index 18fa6820..c4638bf0 100644
--- a/sixtracklib/common/be_dipedge/be_dipedge.c
+++ b/sixtracklib/common/be_dipedge/be_dipedge.c
@@ -1,6 +1,5 @@
 #include "sixtracklib/common/be_dipedge/be_dipedge.h"
 
-
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <stdbool.h>
     #include <stdint.h>
@@ -17,117 +16,147 @@
     #include "sixtracklib/common/buffer.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
-NS(buffer_size_t) NS(DipoleEdge_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge )
-{
-    return NS(DipoleEdge_get_required_num_dataptrs_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ), dipedge,
-        NS(Buffer_get_slot_size)( buffer ) );
-}
-
-NS(buffer_size_t) NS(DipoleEdge_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC  const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge )
+NS(object_type_id_t) NS(DipoleEdge_type_id_ext)( void ) SIXTRL_NOEXCEPT
 {
-    return NS(DipoleEdge_get_required_num_slots_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ), dipedge,
-        NS(Buffer_get_slot_size)( buffer ) );
+    return NS(DipoleEdge_type_id)();
 }
 
-bool NS(DipoleEdge_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs )
+NS(arch_status_t) NS(DipoleEdge_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dipedge ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(DipoleEdge) elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(DipoleEdge_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
-
-    SIXTRL_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
+    if( ( offsets != SIXTRL_NULLPTR ) &&
+        ( max_num_offsets > ZERO ) && ( slot_size > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
 
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ),
-        num_dataptrs, sizes, counts, requ_objects, requ_slots, requ_dataptrs );
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+NS(arch_status_t) NS(DipoleEdge_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dipedge ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(DipoleEdge) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    buf_size_t const num_dataptrs =
-        NS(DipoleEdge_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
+    if( ( sizes != SIXTRL_NULLPTR ) &&
+        ( max_num_sizes > ZERO ) && ( slot_size > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
 
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-
-    NS(DipoleEdge_preset)( &temp_obj );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_DIPEDGE), num_dataptrs, offsets, sizes, counts ) );
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(dipedge_real_t) const r21, NS(dipedge_real_t) const r43 )
+NS(arch_status_t) NS(DipoleEdge_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dipedge ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(DipoleEdge) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    buf_size_t const num_dataptrs =
-        NS(DipoleEdge_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
+    if( ( counts != SIXTRL_NULLPTR ) &&
+        ( max_num_counts > ZERO ) && ( slot_size > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
 
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
 
-    elem_t temp_obj;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    NS(DipoleEdge_set_r21)( &temp_obj, r21 );
-    NS(DipoleEdge_set_r43)( &temp_obj, r43 );
+bool NS(DipoleEdge_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t)  buf_size_t;
+    buf_size_t const ndataptrs = NS(DipoleEdge_num_dataptrs)( SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ndataptrs == ( buf_size_t )0u );
 
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
+    return NS(Buffer_can_add_object)( buffer, sizeof( NS(DipoleEdge) ),
+        ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects, requ_slots,
+            requ_dataptrs );
+}
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_DIPEDGE), num_dataptrs, offsets, sizes, counts ) );
+SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* added_elem = SIXTRL_NULLPTR;
+
+    NS(DipoleEdge) temp;
+    NS(arch_status_t) status = NS(DipoleEdge_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(DipoleEdge_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) )
+    {
+        added_elem = (SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+            sizeof( NS(DipoleEdge) ), NS(DipoleEdge_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_add_copy)(
+SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge )
+    NS(dipedge_real_t) const r21, NS(dipedge_real_t) const r43 )
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(DipoleEdge) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(DipoleEdge_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    SIXTRL_ASSERT( dipedge != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, dipedge, sizeof( elem_t ),
-            NS(OBJECT_TYPE_DIPEDGE), num_dataptrs, offsets, sizes, counts ) );
+    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) ndataptrs = ( NS(buffer_size_t) )0;
+
+    NS(DipoleEdge) temp;
+    NS(arch_status_t) status = NS(DipoleEdge_set_r21)( &temp, r21 );
+    status |= NS(DipoleEdge_set_r43)( &temp, r43 );
+    ndataptrs = NS(DipoleEdge_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( status == NS(ARCH_STATUS_SUCCESS) ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) )
+    {
+        added_elem = (SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+            sizeof( NS(DipoleEdge) ), NS(DipoleEdge_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
-/* end: sixtracklib/common/be_dipedge/be_dipedge.c */
+SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(DipoleEdge_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) )
+    {
+        added_elem = (SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(DipoleEdge) ), NS(DipoleEdge_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
diff --git a/sixtracklib/common/be_dipedge/be_dipedge.h b/sixtracklib/common/be_dipedge/be_dipedge.h
index ec08bd8f..35e8a68f 100644
--- a/sixtracklib/common/be_dipedge/be_dipedge.h
+++ b/sixtracklib/common/be_dipedge/be_dipedge.h
@@ -10,13 +10,14 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/constants.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
-    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTGRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -32,82 +33,144 @@ typedef struct NS(DipoleEdge)
 }
 NS(DipoleEdge);
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(DipoleEdge_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge,
-    NS(buffer_size_t) const slot_size );
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(DipoleEdge_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge,
-    NS(buffer_size_t) const slot_size );
+/* ------------------------------------------------------------------------- */
 
 SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
-NS(DipoleEdge_preset)( SIXTRL_BE_ARGPTR_DEC
-    NS(DipoleEdge)* SIXTRL_RESTRICT dipedge );
+NS(DipoleEdge_preset)( SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+    SIXTRL_RESTRICT dipedge ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(DipoleEdge_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dipedge );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(DipoleEdge_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT
+        dipedge ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN NS(dipedge_real_t) NS(DipoleEdge_get_r21)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(DipoleEdge_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const
+        SIXTRL_RESTRICT dipedge ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(dipedge_real_t) NS(DipoleEdge_get_r43)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(DipoleEdge_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(DipoleEdge_type_id)(
+    void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(dipedge_real_t) NS(DipoleEdge_r21)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT
+        dipedge ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(dipedge_real_t) NS(DipoleEdge_r43)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT
+        dipedge ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(DipoleEdge_set_r21)(
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(DipoleEdge_set_r21)(
     SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dipedge,
-    NS(dipedge_real_t) const r21  );
+    NS(dipedge_real_t) const r21 ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(DipoleEdge_set_r43)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(DipoleEdge_set_r43)(
     SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dipedge,
-    NS(dipedge_real_t) const r43 );
+    NS(dipedge_real_t) const r43 ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(DipoleEdge_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT source );
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const
+        SIXTRL_RESTRICT source ) SIXTRL_NOEXCEPT;
+
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const*
+NS(DipoleEdge_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+NS(DipoleEdge_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const*
+NS(DipoleEdge_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+NS(DipoleEdge_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(DipoleEdge_get_required_num_dataptrs)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const*
+NS(DipoleEdge_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(DipoleEdge_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC  const NS(DipoleEdge) *const SIXTRL_RESTRICT  );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+NS(DipoleEdge_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(DipoleEdge_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(DipoleEdge_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(DipoleEdge_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(DipoleEdge_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(DipoleEdge_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objs,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN
-SIXTRL_BUFFER_DATAPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+NS(DipoleEdge_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN
-SIXTRL_BUFFER_DATAPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+NS(DipoleEdge_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(dipedge_real_t) const r21, NS(dipedge_real_t) const r43 );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(DipoleEdge)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
 NS(DipoleEdge_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge );
 
-#endif /* !defined( _GPUCODE )*/
+#endif /* !defined( _GPUCODE ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
@@ -117,130 +180,196 @@ NS(DipoleEdge_add_copy)(
 /*        Implementation of inline functions for NS(DipoleEdge)                   */
 /* ========================================================================= */
 
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #if !defined( _GPUCODE )
+    #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(DipoleEdge_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+        SIXTRL_RESTRICT dipedge ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( buffer != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0u );
-
-    ( void )buffer;
-    ( void )dipedge;
-    ( void )slot_size;
-
-    return ( NS(buffer_size_t) )0u;
+    if( dipedge != SIXTRL_NULLPTR ) NS(DipoleEdge_clear)( dipedge );
+    return dipedge;
 }
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(DipoleEdge_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(arch_status_t) NS(DipoleEdge_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+        SIXTRL_RESTRICT dipedge ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( buffer != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0u );
+    NS(arch_status_t) status = NS(DipoleEdge_set_r21)(
+        dipedge, ( NS(dipedge_real_t) )0 );
+    status |= NS(DipoleEdge_set_r43)( dipedge, ( NS(dipedge_real_t) )1 );
+    return status;
+}
 
-    ( void )buffer;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    return ( dipedge != SIXTRL_NULLPTR )
-        ? NS(ManagedBuffer_get_slot_based_length)(
-            sizeof( *dipedge ), slot_size )
-        : ( NS(buffer_size_t) )0u;
+SIXTRL_INLINE NS(buffer_size_t) NS(DipoleEdge_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dipedge ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0u;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dipedge )
+SIXTRL_INLINE NS(buffer_size_t) NS(DipoleEdge_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    if( dipedge != SIXTRL_NULLPTR )
-    {
-        NS(DipoleEdge_clear)( dipedge );
-    }
-
-    return dipedge;
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    NS(buffer_size_t) const num_bytes =
+        NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(DipoleEdge) ), slot_size );
+
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
+    return num_slots;
 }
 
-SIXTRL_INLINE void NS(DipoleEdge_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dipedge )
+SIXTRL_INLINE NS(object_type_id_t) NS(DipoleEdge_type_id)(
+    void ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_STATIC_VAR NS(dipedge_real_t) const ZERO = ( NS(dipedge_real_t) )0;
-    SIXTRL_STATIC_VAR NS(dipedge_real_t) const ONE  = ( NS(dipedge_real_t) )1;
-
-    NS(DipoleEdge_set_r21)( dipedge, ZERO );
-    NS(DipoleEdge_set_r43)( dipedge, ONE );
-
-    return;
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_DIPEDGE);
 }
 
-/* ------------------------------------------------------------------------- */
-
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE NS(dipedge_real_t) NS(DipoleEdge_get_r21)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge )
+SIXTRL_INLINE NS(dipedge_real_t) NS(DipoleEdge_r21)( SIXTRL_BE_ARGPTR_DEC const
+    NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( dipedge != SIXTRL_NULLPTR );
     return dipedge->r21;
 }
 
-SIXTRL_INLINE NS(dipedge_real_t) NS(DipoleEdge_get_r43)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge )
+SIXTRL_INLINE NS(dipedge_real_t) NS(DipoleEdge_r43)( SIXTRL_BE_ARGPTR_DEC const
+    NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( dipedge != SIXTRL_NULLPTR );
     return dipedge->r43;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE void NS(DipoleEdge_set_r21)(
+SIXTRL_INLINE NS(arch_status_t) NS(DipoleEdge_set_r21)(
     SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dipedge,
-    NS(dipedge_real_t) const r21  )
+    NS(dipedge_real_t) const r21 ) SIXTRL_NOEXCEPT
 {
-    if( dipedge != SIXTRL_NULLPTR )
-    {
-        dipedge->r21 = r21;
-    }
+    SIXTRL_ASSERT( dipedge != SIXTRL_NULLPTR );
+    dipedge->r21 = r21;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(DipoleEdge_set_r43)(
+SIXTRL_INLINE NS(arch_status_t) NS(DipoleEdge_set_r43)(
     SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dipedge,
-    NS(dipedge_real_t) const r43 )
+    NS(dipedge_real_t) const r43 ) SIXTRL_NOEXCEPT
 {
-    if( dipedge != SIXTRL_NULLPTR )
-    {
-        dipedge->r43 = r43;
-    }
+    SIXTRL_ASSERT( dipedge != SIXTRL_NULLPTR );
+    dipedge->r43 = r43;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_INLINE NS(arch_status_t) NS(DipoleEdge_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dest,
-    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT source )
+    SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* SIXTRL_RESTRICT dst,
+    SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT src
+) SIXTRL_NOEXCEPT
 {
-    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    if( ( dest != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) )
+    if( ( dst != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
     {
-        if( dest != source )
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+
+        if( dst != src )
         {
-            NS(DipoleEdge_set_r21)( dest, NS(DipoleEdge_get_r21)( source ) );
-            NS(DipoleEdge_set_r43)( dest, NS(DipoleEdge_get_r43)( source ) );
+            status  = NS(DipoleEdge_set_r21)( dst, NS(DipoleEdge_r21)( src ) );
+            status |= NS(DipoleEdge_set_r43)( dst, NS(DipoleEdge_r43)( src ) );
         }
-
-        status = SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
     return status;
 }
 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const*
+NS(DipoleEdge_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const* ptr_dipedge_t;
+    ptr_dipedge_t elem = SIXTRL_NULLPTR;
+
+    if( ( index_obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( index_obj ) == NS(OBJECT_TYPE_DIPEDGE) ) &&
+        ( NS(Object_get_size)( index_obj ) >= sizeof( NS(DipoleEdge) ) ) )
+    {
+        elem = ( ptr_dipedge_t )( uintptr_t )NS(Object_get_begin_addr)(
+            index_obj );
+    }
+
+    return elem;
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT index_obj
+) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+        )NS(DipoleEdge_const_from_obj_index)( index_obj );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const*
+NS(DipoleEdge_const_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC unsigned char
+        const* SIXTRL_RESTRICT buffer_begin, NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(DipoleEdge_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)* NS(DipoleEdge_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(DipoleEdge_from_obj_index)( NS(ManagedBuffer_get_object)(
+        buffer_begin, index, slot_size ) );
+}
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const*
+NS(DipoleEdge_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(DipoleEdge_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge)*
+NS(DipoleEdge_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer, NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(DipoleEdge_from_obj_index)( NS(Buffer_get_object)(
+        buffer, index ) );
+}
+
+#endif /* !defined( _GPUCODE ) */
+
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRL_COMMON_BE_DIPEDGE_BE_DIPEDGE_C99_H__ */
-/*end: sixtracklib/common/be_/be_.h */
diff --git a/sixtracklib/common/be_dipedge/be_dipedge.hpp b/sixtracklib/common/be_dipedge/be_dipedge.hpp
index d6215e61..f458d9f2 100644
--- a/sixtracklib/common/be_dipedge/be_dipedge.hpp
+++ b/sixtracklib/common/be_dipedge/be_dipedge.hpp
@@ -19,7 +19,7 @@
 namespace SIXTRL_CXX_NAMESPACE
 {
     typedef ::NS(dipedge_real_t) dipedge_real_t;
-    
+
     template< typename T >
     struct TDipoleEdge
     {
@@ -30,16 +30,16 @@ namespace SIXTRL_CXX_NAMESPACE
         using size_type       = ::NS(buffer_size_t);
         using buffer_t        = Buffer;
         using c_buffer_t      = buffer_t::c_api_t;
-        
+
         SIXTRL_FN TDipoleEdge() = default;
 
         SIXTRL_FN TDipoleEdge( TDipoleEdge< T > const& other ) = default;
         SIXTRL_FN TDipoleEdge( TDipoleEdge< T >&& other ) = default;
 
-        SIXTRL_FN TDipoleEdge< T >& 
+        SIXTRL_FN TDipoleEdge< T >&
         operator=( TDipoleEdge< T > const& other ) = default;
-        
-        SIXTRL_FN TDipoleEdge< T >& 
+
+        SIXTRL_FN TDipoleEdge< T >&
         operator=( TDipoleEdge< T >&& other ) = default;
 
         SIXTRL_FN ~TDipoleEdge() = default;
@@ -64,34 +64,34 @@ namespace SIXTRL_CXX_NAMESPACE
             SIXTRL_ARGPTR_DEC size_type* SIXTRL_RESTRICT
                 ptr_requ_dataptrs = nullptr ) SIXTRL_NOEXCEPT;
 
-        /* - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - -  */                
+        /* - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - -  */
 
         SIXTRL_STATIC SIXTRL_FN SIXTRL_ARGPTR_DEC TDipoleEdge< T >*
         CreateNewOnBuffer( buffer_t& SIXTRL_RESTRICT_REF buffer );
 
         SIXTRL_STATIC SIXTRL_FN SIXTRL_ARGPTR_DEC TDipoleEdge< T >*
         CreateNewOnBuffer( c_buffer_t& SIXTRL_RESTRICT_REF buffer );
-        
+
         /* - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - -  */
 
         SIXTRL_STATIC SIXTRL_FN SIXTRL_ARGPTR_DEC TDipoleEdge< T >* AddToBuffer(
             buffer_t& SIXTRL_RESTRICT_REF buffer,
-            const_reference SIXTRL_RESTRICT_REF r21, 
+            const_reference SIXTRL_RESTRICT_REF r21,
             const_reference SIXTRL_RESTRICT_REF r43 );
 
         SIXTRL_STATIC SIXTRL_FN SIXTRL_ARGPTR_DEC TDipoleEdge< T >* AddToBuffer(
             c_buffer_t& SIXTRL_RESTRICT_REF buffer,
-            const_reference SIXTRL_RESTRICT_REF r21, 
+            const_reference SIXTRL_RESTRICT_REF r21,
             const_reference SIXTRL_RESTRICT_REF r43 );
-        
-        /* - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - -  */                
+
+        /* - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - -  */
 
         SIXTRL_STATIC SIXTRL_FN SIXTRL_ARGPTR_DEC TDipoleEdge< T >*
-        AddCopyToBuffer( buffer_t& SIXTRL_RESTRICT_REF buffer, 
+        AddCopyToBuffer( buffer_t& SIXTRL_RESTRICT_REF buffer,
             TDipoleEdge< T > const& SIXTRL_RESTRICT_REF dipedge );
 
         SIXTRL_STATIC SIXTRL_FN SIXTRL_ARGPTR_DEC TDipoleEdge< T >*
-        AddCopyToBuffer( c_buffer_t& SIXTRL_RESTRICT_REF buffer, 
+        AddCopyToBuffer( c_buffer_t& SIXTRL_RESTRICT_REF buffer,
             TDipoleEdge< T > const& SIXTRL_RESTRICT_REF dipedge );
 
         /* ---------------------------------------------------------------- */
@@ -102,27 +102,27 @@ namespace SIXTRL_CXX_NAMESPACE
             buffer_t const& SIXTRL_RESTRICT_REF buffer ) SIXTRL_NOEXCEPT;
 
         SIXTRL_STATIC SIXTRL_FN size_type RequiredNumDataPtrs(
-            SIXTRL_BUFFER_ARGPTR_DEC const c_buffer_t *const 
+            SIXTRL_BUFFER_ARGPTR_DEC const c_buffer_t *const
                 SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT;
-            
+
         /* ----------------------------------------------------------------- */
-            
+
         SIXTRL_FN void preset() SIXTRL_NOEXCEPT;
         SIXTRL_FN void clear()  SIXTRL_NOEXCEPT;
-        
+
         SIXTRL_FN const_reference getR21() const SIXTRL_NOEXCEPT;
         SIXTRL_FN const_reference getR43() const SIXTRL_NOEXCEPT;
-        
+
         /* ----------------------------------------------------------------- */
-        
-        SIXTRL_FN void setR21( 
+
+        SIXTRL_FN void setR21(
             const_reference SIXTRL_RESTRICT_REF r21 ) SIXTRL_NOEXCEPT;
-            
-        SIXTRL_FN void setR43( 
+
+        SIXTRL_FN void setR43(
             const_reference SIXTRL_RESTRICT_REF r43 ) SIXTRL_NOEXCEPT;
-            
+
         /* ----------------------------------------------------------------- */
-         
+
         value_type r21  SIXTRL_ALIGN( 8 );
         value_type r43  SIXTRL_ALIGN( 8 );
     };
@@ -150,7 +150,7 @@ namespace SIXTRL_CXX_NAMESPACE
         typename TDipoleEdge< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
         typename TDipoleEdge< T >::const_reference SIXTRL_RESTRICT_REF r21,
         typename TDipoleEdge< T >::const_reference SIXTRL_RESTRICT_REF r43 );
-    
+
     template< typename T >
     SIXTRL_ARGPTR_DEC TDipoleEdge< T >* TDipoleEdge_add(
         typename TDipoleEdge< T >::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
@@ -171,7 +171,7 @@ namespace SIXTRL_CXX_NAMESPACE
      * ====  Specialization TDipoleEdge< NS(dipedge_real_t) > :
      * ===================================================================== */
 
-    template<> struct TDipoleEdge< ::NS(dipedge_real_t) > : 
+    template<> struct TDipoleEdge< ::NS(dipedge_real_t) > :
         public ::NS(DipoleEdge)
     {
         using value_type = ::NS(dipedge_real_t);
@@ -180,14 +180,14 @@ namespace SIXTRL_CXX_NAMESPACE
         using buffer_t   = Buffer;
         using c_buffer_t = buffer_t::c_api_t;
         using c_api_t    = ::NS(DipoleEdge);
-        
+
         /* ---------------------------------------------------------------- */
 
         SIXTRL_FN TDipoleEdge() = default;
 
-        SIXTRL_FN TDipoleEdge( 
+        SIXTRL_FN TDipoleEdge(
             TDipoleEdge< value_type > const& other ) = default;
-            
+
         SIXTRL_FN TDipoleEdge( TDipoleEdge< value_type >&& other ) = default;
 
         SIXTRL_FN TDipoleEdge< value_type >& operator=(
@@ -230,7 +230,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
         SIXTRL_STATIC SIXTRL_FN
         SIXTRL_ARGPTR_DEC TDipoleEdge< ::NS(dipedge_real_t) >* AddToBuffer(
-            buffer_t& SIXTRL_RESTRICT_REF buffer, 
+            buffer_t& SIXTRL_RESTRICT_REF buffer,
             value_type const r21, value_type const r43 );
 
         SIXTRL_STATIC SIXTRL_FN
@@ -247,7 +247,7 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_ARGPTR_DEC TDipoleEdge< ::NS(dipedge_real_t) >* AddCopyToBuffer(
             c_buffer_t& SIXTRL_RESTRICT_REF buffer,
             TDipoleEdge< ::NS(dipedge_real_t) > const& SIXTRL_RESTRICT_REF );
-        
+
         /* ----------------------------------------------------------------- */
 
         SIXTRL_ARGPTR_DEC c_api_t const* getCApiPtr() const SIXTRL_NOEXCEPT;
@@ -263,30 +263,30 @@ namespace SIXTRL_CXX_NAMESPACE
                 SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT;
 
         SIXTRL_FN type_id_t getTypeId() const SIXTRL_NOEXCEPT;
-        
+
         /* ----------------------------------------------------------------- */
-        
+
         SIXTRL_FN void preset() SIXTRL_NOEXCEPT;
         SIXTRL_FN void clear() SIXTRL_NOEXCEPT;
 
         SIXTRL_FN value_type getR21() const SIXTRL_NOEXCEPT;
         SIXTRL_FN value_type getR43() const SIXTRL_NOEXCEPT;
-        
+
         /* ----------------------------------------------------------------- */
-        
-        SIXTRL_FN void setR21( value_type const r21 ) SIXTRL_NOEXCEPT;            
+
+        SIXTRL_FN void setR21( value_type const r21 ) SIXTRL_NOEXCEPT;
         SIXTRL_FN void setR43( value_type const r43 ) SIXTRL_NOEXCEPT;
     };
 
     using DipoleEdge = TDipoleEdge< ::NS(dipedge_real_t) >;
 
-    SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge_new(   
+    SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge_new(
         DipoleEdge::buffer_t& SIXTRL_RESTRICT_REF buffer );
 
     SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge_new(
         DipoleEdge::c_buffer_t& SIXTRL_RESTRICT_REF buffer );
 
-    SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge_add( 
+    SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge_add(
         DipoleEdge::buffer_t& SIXTRL_RESTRICT_REF buffer,
         DipoleEdge::value_type const r21, DipoleEdge::value_type const r43 );
 
@@ -294,7 +294,7 @@ namespace SIXTRL_CXX_NAMESPACE
         DipoleEdge::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
         DipoleEdge::value_type const r21, DipoleEdge::value_type const r43 );
 
-    SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge_add_copy( 
+    SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge_add_copy(
         DipoleEdge::buffer_t& SIXTRL_RESTRICT_REF buffer,
         SIXTRL_CXX_NAMESPACE::DipoleEdge const& SIXTRL_RESTRICT_REF dipedge );
 
@@ -400,7 +400,7 @@ namespace SIXTRL_CXX_NAMESPACE
             *buffer.getCApiPtr(), r21, r43 );
     }
 
-    template< typename T > SIXTRL_INLINE SIXTRL_ARGPTR_DEC TDipoleEdge< T >* 
+    template< typename T > SIXTRL_INLINE SIXTRL_ARGPTR_DEC TDipoleEdge< T >*
     TDipoleEdge< T >::AddToBuffer(
         typename TDipoleEdge< T >::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
         typename TDipoleEdge< T >::const_reference SIXTRL_RESTRICT_REF r21,
@@ -428,7 +428,7 @@ namespace SIXTRL_CXX_NAMESPACE
             ::NS(Buffer_add_object)( &buffer, &temp, sizeof( _this_t ),
                 temp.getTypeId(), num_dataptrs, offsets, sizes, counts ) ) );
     }
-    
+
     template< typename T >SIXTRL_INLINE SIXTRL_ARGPTR_DEC TDipoleEdge< T >*
     TDipoleEdge< T >::AddCopyToBuffer(
         typename TDipoleEdge< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
@@ -436,7 +436,7 @@ namespace SIXTRL_CXX_NAMESPACE
     {
         return TDipoleEdge< T >::AddCopyToBuffer( *buffer.getCApiPtr(), orig );
     }
-    
+
     template< typename T >SIXTRL_INLINE SIXTRL_ARGPTR_DEC TDipoleEdge< T >*
     TDipoleEdge< T >::AddCopyToBuffer(
         typename TDipoleEdge< T >::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
@@ -475,61 +475,56 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TDipoleEdge< T >::size_type 
-    TDipoleEdge< T >::RequiredNumDataPtrs( typename TDipoleEdge< T >::buffer_t 
-        const& SIXTRL_RESTRICT_REF buffer ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TDipoleEdge< T >::size_type
+    TDipoleEdge< T >::RequiredNumDataPtrs( typename TDipoleEdge< T >::buffer_t
+        const& SIXTRL_RESTRICT_REF SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(DipoleEdge_get_required_num_dataptrs)( 
-            buffer.getCApiPtr(), nullptr );
+        return ::NS(DipoleEdge_num_dataptrs)( nullptr );
     }
-    
-    template< typename T > 
+
+    template< typename T >
     SIXTRL_INLINE typename TDipoleEdge< T >::size_type
-    TDipoleEdge< T >::RequiredNumDataPtrs( const 
-        typename TDipoleEdge< T >::c_buffer_t *const SIXTRL_RESTRICT 
-            buffer ) SIXTRL_NOEXCEPT
+    TDipoleEdge< T >::RequiredNumDataPtrs( const
+        typename TDipoleEdge< T >::c_buffer_t *const SIXTRL_RESTRICT
+            SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(DipoleEdge_get_required_num_dataptrs)( buffer, nullptr );
+        return ::NS(DipoleEdge_num_dataptrs)( nullptr );
     }
-    
+
     template< typename T > void TDipoleEdge< T >::preset() SIXTRL_NOEXCEPT
     {
-        this->setB( TDipoleEdge< T >::DEFAULT_B );
         this->clear();
     }
-     
+
     template< typename T > void TDipoleEdge< T >::clear() SIXTRL_NOEXCEPT
-    {   
-        using _this_t = TDipoleEdge< T >;
-        
-        this->setInvRho( _this_t::DEFAULT_INV_RHO );
-        this->setRotAngleDeg( _this_t::DEFAULT_ROT_ANGLE_DEG );        
-        this->setTiltAngleDeg( _this_t::DEFAULT_TILT_ANGLE_DEG );
-    }
-    
-    template< typename T > typename TDipoleEdge< T >::const_reference 
+    {
+        this->setR21( T{0} );
+        this->setR43( T{1} );
+    }
+
+    template< typename T > typename TDipoleEdge< T >::const_reference
     TDipoleEdge< T >::getR21() const SIXTRL_NOEXCEPT
     {
         return this->r21;
     }
-    
-    template< typename T > typename TDipoleEdge< T >::const_reference  
+
+    template< typename T > typename TDipoleEdge< T >::const_reference
     TDipoleEdge< T >::getR43() const SIXTRL_NOEXCEPT
     {
         return this->r43;
     }
-    
+
     /* ----------------------------------------------------------------- */
-    
-    template< typename T > void TDipoleEdge< T >::setR21( 
-        typename TDipoleEdge< T >::const_reference 
+
+    template< typename T > void TDipoleEdge< T >::setR21(
+        typename TDipoleEdge< T >::const_reference
             SIXTRL_RESTRICT_REF r21 ) SIXTRL_NOEXCEPT
     {
         this->r21 = r21;
     }
-    
-    template< typename T > void TDipoleEdge< T >::setR43( 
-        typename TDipoleEdge< T >::const_reference 
+
+    template< typename T > void TDipoleEdge< T >::setR43(
+        typename TDipoleEdge< T >::const_reference
             SIXTRL_RESTRICT_REF r43 ) SIXTRL_NOEXCEPT
     {
         this->r43 = r43;
@@ -591,27 +586,27 @@ namespace SIXTRL_CXX_NAMESPACE
      * ====  Specialization TDipoleEdge< ::NS(dipedge_real_t) > :
      * ===================================================================== */
 
-    SIXTRL_INLINE bool DipoleEdge::CanAddToBuffer( 
+    SIXTRL_INLINE bool DipoleEdge::CanAddToBuffer(
         DipoleEdge::buffer_t& SIXTRL_RESTRICT_REF buffer,
         SIXTRL_ARGPTR_DEC DipoleEdge::size_type* SIXTRL_RESTRICT req_objects,
         SIXTRL_ARGPTR_DEC DipoleEdge::size_type* SIXTRL_RESTRICT req_slots,
-        SIXTRL_ARGPTR_DEC DipoleEdge::size_type* SIXTRL_RESTRICT req_dataptrs 
+        SIXTRL_ARGPTR_DEC DipoleEdge::size_type* SIXTRL_RESTRICT req_dataptrs
     ) SIXTRL_NOEXCEPT
     {
-        return ::NS(DipoleEdge_can_be_added)( 
+        return ::NS(DipoleEdge_can_be_added)(
             buffer.getCApiPtr(), req_objects, req_slots, req_dataptrs );
     }
 
 
     SIXTRL_INLINE bool DipoleEdge::CanAddToBuffer(
-        SIXTRL_BUFFER_ARGPTR_DEC DipoleEdge::c_buffer_t* 
+        SIXTRL_BUFFER_ARGPTR_DEC DipoleEdge::c_buffer_t*
             SIXTRL_RESTRICT ptr_buffer,
         SIXTRL_ARGPTR_DEC DipoleEdge::size_type* SIXTRL_RESTRICT req_objects,
         SIXTRL_ARGPTR_DEC DipoleEdge::size_type* SIXTRL_RESTRICT req_slots,
-        SIXTRL_ARGPTR_DEC DipoleEdge::size_type* SIXTRL_RESTRICT req_dataptrs 
+        SIXTRL_ARGPTR_DEC DipoleEdge::size_type* SIXTRL_RESTRICT req_dataptrs
     ) SIXTRL_NOEXCEPT
     {
-        return ::NS(DipoleEdge_can_be_added)( 
+        return ::NS(DipoleEdge_can_be_added)(
             ptr_buffer, req_objects, req_slots, req_dataptrs );
     }
 
@@ -644,16 +639,16 @@ namespace SIXTRL_CXX_NAMESPACE
         return static_cast< SIXTRL_ARGPTR_DEC DipoleEdge* >(
             ::NS(DipoleEdge_add)( &buffer, r21, r43 ) );
     }
-    
+
     SIXTRL_INLINE SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge::AddCopyToBuffer(
         DipoleEdge::buffer_t& SIXTRL_RESTRICT_REF buffer,
         DipoleEdge const& SIXTRL_RESTRICT_REF orig )
     {
         return static_cast< SIXTRL_ARGPTR_DEC DipoleEdge* >(
-            ::NS(DipoleEdge_add_copy)( 
+            ::NS(DipoleEdge_add_copy)(
                 buffer.getCApiPtr(), orig.getCApiPtr() ) );
     }
-    
+
     SIXTRL_INLINE SIXTRL_ARGPTR_DEC DipoleEdge* DipoleEdge::AddCopyToBuffer(
         DipoleEdge::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
         DipoleEdge const& SIXTRL_RESTRICT_REF orig )
@@ -666,8 +661,8 @@ namespace SIXTRL_CXX_NAMESPACE
 
     SIXTRL_ARGPTR_DEC DipoleEdge::c_api_t const*
     DipoleEdge::getCApiPtr() const SIXTRL_NOEXCEPT
-    {        
-        return reinterpret_cast< 
+    {
+        return reinterpret_cast<
             SIXTRL_ARGPTR_DEC DipoleEdge::c_api_t const* >( this );
     }
 
@@ -686,66 +681,64 @@ namespace SIXTRL_CXX_NAMESPACE
         return SIXTRL_CXX_NAMESPACE::OBJECT_TYPE_DIPEDGE;
     }
 
-    
-    DipoleEdge::size_type DipoleEdge::RequiredNumDataPtrs( DipoleEdge::buffer_t 
-        const& SIXTRL_RESTRICT_REF buffer ) SIXTRL_NOEXCEPT
+
+    DipoleEdge::size_type DipoleEdge::RequiredNumDataPtrs( DipoleEdge::buffer_t
+        const& SIXTRL_RESTRICT_REF SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(DipoleEdge_get_required_num_dataptrs)( 
-            buffer.getCApiPtr(), nullptr );
+        return ::NS(DipoleEdge_num_dataptrs)( nullptr );
     }
 
-    
+
     DipoleEdge::size_type DipoleEdge::RequiredNumDataPtrs(
         SIXTRL_BUFFER_ARGPTR_DEC const DipoleEdge::c_buffer_t *const
-                SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+                SIXTRL_RESTRICT SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(DipoleEdge_get_required_num_dataptrs)( 
-            ptr_buffer, nullptr );
+        return ::NS(DipoleEdge_num_dataptrs)( nullptr );
     }
-    
-    void DipoleEdge::preset() SIXTRL_NOEXCEPT 
+
+    void DipoleEdge::preset() SIXTRL_NOEXCEPT
     {
         ::NS(DipoleEdge_preset)( this->getCApiPtr() );
     }
-    
-    void DipoleEdge::clear() SIXTRL_NOEXCEPT 
+
+    void DipoleEdge::clear() SIXTRL_NOEXCEPT
     {
         ::NS(DipoleEdge_clear)( this->getCApiPtr() );
     }
 
     DipoleEdge::value_type DipoleEdge::getR21() const SIXTRL_NOEXCEPT
     {
-        return ::NS(DipoleEdge_get_r21)( this->getCApiPtr() );
+        return ::NS(DipoleEdge_r21)( this->getCApiPtr() );
     }
-    
+
     DipoleEdge::value_type DipoleEdge::getR43() const SIXTRL_NOEXCEPT
     {
-        return ::NS(DipoleEdge_get_r43)( this->getCApiPtr() );
+        return ::NS(DipoleEdge_r43)( this->getCApiPtr() );
     }
-    
+
     /* ----------------------------------------------------------------- */
-    
-     void DipoleEdge::setR21( 
+
+     void DipoleEdge::setR21(
          DipoleEdge::value_type const r21 ) SIXTRL_NOEXCEPT
     {
         ::NS(DipoleEdge_set_r21)( this->getCApiPtr(), r21 );
     }
-        
-     void DipoleEdge::setR43( 
+
+     void DipoleEdge::setR43(
         DipoleEdge::value_type const r43 ) SIXTRL_NOEXCEPT
     {
         ::NS(DipoleEdge_set_r43)( this->getCApiPtr(), r43 );
     }
-        
+
     /* --------------------------------------------------------------------- */
-    
-    SIXTRL_INLINE SIXTRL_ARGPTR_DEC DipoleEdge* 
+
+    SIXTRL_INLINE SIXTRL_ARGPTR_DEC DipoleEdge*
     DipoleEdge_new( DipoleEdge::buffer_t& SIXTRL_RESTRICT_REF buffer )
     {
         return DipoleEdge::CreateNewOnBuffer( buffer );
     }
 
-    SIXTRL_INLINE SIXTRL_ARGPTR_DEC DipoleEdge* 
+    SIXTRL_INLINE SIXTRL_ARGPTR_DEC DipoleEdge*
     DipoleEdge_new( DipoleEdge::c_buffer_t& SIXTRL_RESTRICT_REF buffer )
     {
         return DipoleEdge::CreateNewOnBuffer( buffer );
diff --git a/sixtracklib/common/be_dipedge/track.h b/sixtracklib/common/be_dipedge/track.h
index f3f8ebc3..b71c1a8d 100644
--- a/sixtracklib/common/be_dipedge/track.h
+++ b/sixtracklib/common/be_dipedge/track.h
@@ -40,11 +40,11 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_dipedge)(
     SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge )
 {
     NS(Particles_add_to_px_value)( particles, particle_idx,
-       NS(DipoleEdge_get_r21)( dipedge ) * 
+       NS(DipoleEdge_r21)( dipedge ) *
        NS(Particles_get_x_value)( particles, particle_idx ) );
-    
+
     NS(Particles_add_to_py_value)( particles, particle_idx,
-       NS(DipoleEdge_get_r43)( dipedge ) * 
+       NS(DipoleEdge_r43)( dipedge ) *
        NS(Particles_get_y_value)( particles, particle_idx ) );
 
     return SIXTRL_TRACK_SUCCESS;
diff --git a/sixtracklib/common/be_drift/CMakeLists.txt b/sixtracklib/common/be_drift/CMakeLists.txt
index 06e86707..6bd9cbbf 100644
--- a/sixtracklib/common/be_drift/CMakeLists.txt
+++ b/sixtracklib/common/be_drift/CMakeLists.txt
@@ -1,49 +1,37 @@
-set( SIXTRACKLIB_COMMON_BE_DRIFT_C99_HEADERS
-     be_drift.h
-)
+set( SIXTRL_COMMON_BE_DRIFT_C99_HEADERS be_drift.h track.h )
+set( SIXTRL_COMMON_BE_DRIFT_C99_SOURCES be_drift.c )
+set( SIXTRL_COMMON_BE_DRIFT_CXX_HEADERS be_drift.hpp )
 
-set( SIXTRACKLIB_COMMON_BE_DRIFT_CXX_HEADERS
-     be_drift.hpp
-)
+add_library( sixtrack_common_be_drift OBJECT
+    ${SIXTRL_COMMON_BE_DRIFT_C99_HEADERS}
+    ${SIXTRL_COMMON_BE_DRIFT_C99_SOURCES} )
 
-if( SIXTRACKLIB_COMMON_BE_DRIFT_C99_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_drift/\\1" LOCAL_C99_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_DRIFT_C99_HEADERS}" )
+target_include_directories( sixtrack_common_be_drift PRIVATE
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-    set(  SIXTRACKLIB_COMMON_C99_HEADERS
-        ${SIXTRACKLIB_COMMON_C99_HEADERS}
-        ${LOCAL_C99_HEADERS} PARENT_SCOPE )
-endif()
+set_target_properties( sixtrack_common_be_drift PROPERTIES
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
+    C_STANDARD_REQUIRED ON )
 
-if( SIXTRACKLIB_COMMON_BE_DRIFT_CXX_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_drift/\\1" LOCAL_CXX_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_DRIFT_CXX_HEADERS}" )
+target_compile_options( sixtrack_common_be_drift PRIVATE
+        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
-    set(  SIXTRACKLIB_COMMON_CXX_HEADERS
-        ${SIXTRACKLIB_COMMON_CXX_HEADERS}
-        ${LOCAL_CXX_HEADERS} PARENT_SCOPE )
-endif()
+# ------------------------------------------------------------------------------
+# pass on sixtrack_common_be_beambeam as a module for sixtracklib:
+
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_common_be_drift> CACHE INTERNAL "" FORCE )
 
 # ----------------------------------------------------------------------------
 # install :
 
-if( SIXTRACKLIB_COMMON_BE_DRIFT_C99_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_DRIFT_C99_INSTALL_PATH
-         include/sixtracklib/common/be_drift )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_DRIFT_C99_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_DRIFT_C99_INSTALL_PATH} )
-endif()
-
-
-if( SIXTRACKLIB_COMMON_BE_DRIFT_CXX_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_DRIFT_CXX_INSTALL_PATH
-         include/sixtracklib/common/be_drift )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_DRIFT_CXX_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_DRIFT_CXX_INSTALL_PATH} )
+if( SIXTRL_COMMON_BE_DRIFT_C99_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_DRIFT_C99_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/be_drift" )
 endif()
 
-#end: sixtracklib/common/be_drift/CMakeLists.txt
+if( SIXTRACKL_ENABLE_CXX AND SIXTRL_COMMON_BE_DRIFT_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_DRIFT_CXX_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/be_drift" )
+ endif()
diff --git a/sixtracklib/common/be_drift/be_drift.c b/sixtracklib/common/be_drift/be_drift.c
new file mode 100644
index 00000000..80354419
--- /dev/null
+++ b/sixtracklib/common/be_drift/be_drift.c
@@ -0,0 +1,308 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/be_drift/be_drift.h"
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #if !defined( _GPUCODE )
+    #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+NS(object_type_id_t) NS(Drift_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(Drift_type_id)();
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(Drift_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( drift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(Drift_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( drift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(Drift_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( drift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_counts > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(Drift_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    NS(Drift) temp;
+    NS(arch_status_t) const status = NS(Drift_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(Drift_num_dataptrs)( &temp );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof( NS(Drift) ),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects,
+                    requ_slots, requ_dataptrs ) ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(Drift)* added_elem = SIXTRL_NULLPTR;
+
+    NS(Drift) temp;
+    NS(arch_status_t) const status = NS(Drift_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(Drift_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(Drift)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(Drift) ), NS(Drift_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_add)(
+    SIXTRL_BE_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(drift_real_t) const length )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(Drift)* added_elem = SIXTRL_NULLPTR;
+
+    NS(Drift) temp;
+    NS(arch_status_t) status = NS(Drift_set_length)( &temp, length );
+    NS(buffer_size_t) const ndataptrs = NS(Drift_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(Drift)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(Drift) ), NS(Drift_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(Drift)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(Drift_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(Drift)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(Drift) ), NS(Drift_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+/* ------------------------------------------------------------------------- */
+
+NS(object_type_id_t) NS(DriftExact_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(DriftExact_type_id)();
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(DriftExact_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( drift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) &&
+        ( max_num_offsets > ZERO ) && ( slot_size > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(DriftExact_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( drift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) &&
+        ( max_num_sizes > ZERO ) && ( slot_size > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(DriftExact_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( drift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( counts != SIXTRL_NULLPTR ) &&
+        ( max_num_counts > ZERO ) && ( slot_size > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(DriftExact_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    NS(DriftExact) temp;
+    NS(arch_status_t) const status = NS(DriftExact_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(DriftExact_num_dataptrs)( &temp );
+    SIXTRL_ASSERT( ndataptrs == ( NS(buffer_size_t) )0u );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof( NS(DriftExact) ),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects,
+                    requ_slots, requ_dataptrs ) ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* NS(DriftExact_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* added_elem = SIXTRL_NULLPTR;
+
+    NS(DriftExact) temp;
+    NS(arch_status_t) const status = NS(DriftExact_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(DriftExact_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(DriftExact) ), NS(DriftExact_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* NS(DriftExact_add)(
+    SIXTRL_BE_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(drift_real_t) const length )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* added_elem = SIXTRL_NULLPTR;
+
+    NS(DriftExact) temp;
+    NS(arch_status_t) status = NS(DriftExact_set_length)( &temp, length );
+    NS(buffer_size_t) const ndataptrs = NS(DriftExact_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(DriftExact) ), NS(DriftExact_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* NS(DriftExact_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(DriftExact_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(DriftExact) ), NS(DriftExact_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
diff --git a/sixtracklib/common/be_drift/be_drift.h b/sixtracklib/common/be_drift/be_drift.h
index eec319f2..790b00e2 100644
--- a/sixtracklib/common/be_drift/be_drift.h
+++ b/sixtracklib/common/be_drift/be_drift.h
@@ -9,10 +9,12 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -31,86 +33,122 @@ NS(Drift);
 
 /* ------------------------------------------------------------------------- */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(Drift_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Drift_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(Drift_get_num_slots)(
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(Drift_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const
+        SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(Drift_num_slots)(
     SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift,
-    NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(Drift_type_id)(
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(drift_real_t) NS(Drift_get_length)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(drift_real_t) NS(Drift_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const
+        SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(Drift_set_length)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Drift_set_length)(
     SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift,
-    NS(drift_real_t) const length );
+    NS(drift_real_t) const length ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(Drift_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC int NS(Drift_copy)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Drift_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT source );
-
-SIXTRL_FN SIXTRL_STATIC int NS(Drift_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT rhs );
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const
+        SIXTRL_RESTRICT source ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(Drift_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT rhs,
-    NS(drift_real_t) const treshold );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-/* ------------------------------------------------------------------------- */
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Drift) const*
+NS(Drift_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Drift) const*
-NS(BufferIndex_get_const_drift)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Drift)*
+NS(Drift_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)*
-NS(BufferIndex_get_drift)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Drift) const*
-NS(BeamElements_managed_buffer_get_const_drift)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Drift) const*
+NS(Drift_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)*
-NS(BeamElements_managed_buffer_get_drift)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Drift)*
+NS(Drift_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(Drift) const*
-NS(BeamElements_buffer_get_const_drift)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Drift) const*
+NS(Drift_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)*
-NS(BeamElements_buffer_get_drift)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(Drift_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(Drift_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC bool NS(Drift_can_be_added)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(Drift_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(Drift_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(Drift_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objs,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)* NS(Drift_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Drift)*
+NS(Drift_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)* NS(Drift_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(drift_real_t) const length );
 
-SIXTRL_FN SIXTRL_STATIC
-SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)* NS(Drift_add_copy)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift );
 
@@ -126,97 +164,128 @@ NS(DriftExact);
 
 /* ------------------------------------------------------------------------- */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(DriftExact_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+NS(DriftExact_preset)( SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+    SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(DriftExact_get_num_slots)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(DriftExact_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+        SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(DriftExact_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const
+        SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(DriftExact_num_slots)(
     SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift,
-    NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
-NS(DriftExact_preset)( SIXTRL_BE_ARGPTR_DEC
-    NS(DriftExact)* SIXTRL_RESTRICT drift );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(DriftExact_type_id)(
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(drift_real_t) NS(DriftExact_get_length)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC void NS(DriftExact_set_length)(
-    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT drift,
-    NS(drift_real_t) const length );
+SIXTRL_STATIC SIXTRL_FN NS(drift_real_t) NS(DriftExact_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const
+        SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(DriftExact_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT drift );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(DriftExact_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT drift,
+    NS(drift_real_t) const length ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(DriftExact_copy)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(DriftExact_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT source );
-
-SIXTRL_FN SIXTRL_STATIC int NS(DriftExact_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT rhs );
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const
+        SIXTRL_RESTRICT source ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(DriftExact_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT rhs,
-    NS(drift_real_t) const treshold );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const*
+NS(DriftExact_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact) const*
-NS(BufferIndex_get_const_drift_exact)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+NS(DriftExact_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(BufferIndex_get_drift_exact)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact) const*
-NS(BeamElements_managed_buffer_get_const_drift_exact)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const*
+NS(DriftExact_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(BeamElements_managed_buffer_get_drift_exact)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+NS(DriftExact_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC unsigned char*
+        SIXTRL_RESTRICT buffer_begin, NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact) const*
-NS(BeamElements_buffer_get_const_drift_exact)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const*
+NS(DriftExact_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(BeamElements_buffer_get_drift_exact)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+NS(DriftExact_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+        SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(DriftExact_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(DriftExact_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(DriftExact_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(DriftExact_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC bool NS(DriftExact_can_be_added)(
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(DriftExact_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objs,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(DriftExact_new)( SIXTRL_BUFFER_ARGPTR_DEC
-    NS(Buffer)* SIXTRL_RESTRICT buffer );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+NS(DriftExact_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(DriftExact_add)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
-    SIXTRL_RESTRICT buffer, NS(drift_real_t) const length );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+NS(DriftExact_add)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(drift_real_t) const length );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
 NS(DriftExact_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift );
 
-
 #endif /* !defined( _GPUCODE ) */
-
-/* ========================================================================= */
-
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
@@ -227,6 +296,7 @@ NS(DriftExact_add_copy)(
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
     #if !defined( _GPUCODE )
     #include "sixtracklib/common/buffer.h"
     #endif /* !defined( _GPUCODE ) */
@@ -236,588 +306,282 @@ NS(DriftExact_add_copy)(
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_INLINE NS(buffer_size_t) NS(Drift_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT
 {
-    ( void )drift;
-    return ( NS(buffer_size_t) )0u;
+    if( drift != SIXTRL_NULLPTR ) NS(Drift_clear)( drift );
+    return drift;
 }
 
-SIXTRL_INLINE NS(buffer_size_t) NS(Drift_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(arch_status_t) NS(Drift_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(Drift)         beam_element_t;
+    SIXTRL_ASSERT( drift != SIXTRL_NULLPTR );
+    return NS(Drift_set_length)( drift, ( NS(drift_real_t) )0 );
+}
 
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    ( void )drift;
+SIXTRL_INLINE NS(buffer_size_t) NS(Drift_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC
+    const NS(Drift) *const SIXTRL_RESTRICT SIXTRL_UNUSED( drift )
+) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0u;
+}
 
-    buf_size_t extent = NS(ManagedBuffer_get_slot_based_length)(
-        sizeof( beam_element_t ), slot_size );
+SIXTRL_INLINE NS(buffer_size_t) NS(Drift_num_slots)( SIXTRL_BE_ARGPTR_DEC const
+        NS(Drift) *const SIXTRL_RESTRICT SIXTRL_UNUSED( drift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    NS(buffer_size_t) const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(Drift) ), slot_size );
 
-    SIXTRL_ASSERT( ( slot_size == ZERO ) || ( ( extent % slot_size ) == ZERO ) );
-    return ( slot_size > ZERO ) ? ( extent / slot_size ) : ( ZERO );
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
+    return num_slots;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift )
+SIXTRL_INLINE NS(object_type_id_t) NS(Drift_type_id)(
+    void ) SIXTRL_NOEXCEPT
 {
-    NS(Drift_clear)( drift );
-    return drift;
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_DRIFT);
 }
 
-SIXTRL_INLINE  NS(drift_real_t) NS(Drift_get_length)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(drift_real_t) NS(Drift_length)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Drift) *const SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( drift != SIXTRL_NULLPTR );
     return drift->length;
 }
 
-SIXTRL_INLINE void NS(Drift_set_length)(
+SIXTRL_INLINE NS(arch_status_t) NS(Drift_set_length)(
     SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift,
-    NS(drift_real_t) const length )
-{
-    if( drift != SIXTRL_NULLPTR ) drift->length = length;
-    return;
-}
-
-SIXTRL_INLINE void NS(Drift_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT drift )
+    NS(drift_real_t) const length ) SIXTRL_NOEXCEPT
 {
-    NS(Drift_set_length)( drift, 0.0 );
-    return;
+    SIXTRL_ASSERT( drift != SIXTRL_NULLPTR );
+    drift->length = length;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE int NS(Drift_copy)(
+SIXTRL_INLINE NS(arch_status_t) NS(Drift_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(Drift)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT source )
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT source
+) SIXTRL_NOEXCEPT
 {
-    int success = -1;
-
-    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) )
-    {
-        NS(Drift_set_length)( destination, NS(Drift_get_length)( source ) );
-        success = 0;
-    }
-
-    return success;
-}
-
-SIXTRL_INLINE int NS(Drift_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT rhs )
-{
-    int compare_value = -1;
-
-    if( ( lhs != SIXTRL_NULLPTR ) &&
-        ( rhs != SIXTRL_NULLPTR ) )
-    {
-        if( NS(Drift_get_length)( lhs ) > NS(Drift_get_length)( rhs ) )
-        {
-            compare_value = +1;
-        }
-        else if( NS(Drift_get_length)( lhs ) < NS(Drift_get_length)( rhs ) )
-        {
-            compare_value = -1;
-        }
-        else
-        {
-            compare_value = 0;
-        }
-    }
-    else if( rhs != SIXTRL_NULLPTR )
-    {
-        compare_value = +1;
-    }
-
-    return compare_value;
+    return NS(Drift_set_length)( destination, NS(Drift_length)( source ) );
 }
 
-SIXTRL_INLINE int NS(Drift_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT rhs,
-    NS(drift_real_t) const treshold )
-{
-    int compare_value = -1;
-
-    if( ( lhs != SIXTRL_NULLPTR ) &&
-        ( rhs != SIXTRL_NULLPTR ) )
-    {
-        SIXTRL_ASSERT( treshold >= ( NS(drift_real_t) )0.0 );
-
-        NS(drift_real_t) const diff =
-            NS(Drift_get_length)( lhs ) - NS(Drift_get_length)( rhs );
-
-        NS(drift_real_t) const abs_diff =
-            ( diff > ( NS(drift_real_t) )0.0 ) ? diff : -diff;
-
-        if( abs_diff < treshold )
-        {
-            compare_value = 0;
-        }
-        else if( diff > ( NS(drift_real_t) )0.0 )
-        {
-            compare_value = +1;
-        }
-        else
-        {
-            compare_value = -1;
-        }
-    }
-    else if( rhs != SIXTRL_NULLPTR )
-    {
-        compare_value = +1;
-    }
-
-    return compare_value;
-}
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift) const*
-NS(BufferIndex_get_const_drift)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Drift) const*
+NS(Drift_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT
 {
-    typedef NS(Drift) beam_element_t;
-    typedef SIXTRL_BUFFER_OBJ_DATAPTR_DEC beam_element_t const* ptr_to_be_t;
-    ptr_to_be_t ptr_to_be = SIXTRL_NULLPTR;
+    typedef SIXTRL_BE_ARGPTR_DEC NS(Drift) const* ptr_drift_t;
+    ptr_drift_t elem = SIXTRL_NULLPTR;
 
     if( ( index_obj != SIXTRL_NULLPTR ) &&
         ( NS(Object_get_type_id)( index_obj ) == NS(OBJECT_TYPE_DRIFT) ) &&
-        ( NS(Object_get_size)( index_obj ) >= sizeof( beam_element_t ) ) )
+        ( NS(Object_get_size)( index_obj ) >= sizeof( NS(Drift) ) ) )
     {
-        ptr_to_be = ( ptr_to_be_t )( uintptr_t
-            )NS(Object_get_begin_addr)( index_obj );
+        elem = ( ptr_drift_t )( uintptr_t )NS(Object_get_begin_addr)(
+            index_obj );
     }
 
-    return ptr_to_be;
+    return elem;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)*
-NS(BufferIndex_get_drift)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT index_obj
+) SIXTRL_NOEXCEPT
 {
-    return ( SIXTRL_BUFFER_OBJ_DATAPTR_DEC NS(Drift)*
-        )NS(BufferIndex_get_const_drift)( index_obj );
+    return ( SIXTRL_BE_ARGPTR_DEC NS(Drift)*
+        )NS(Drift_const_from_obj_index)( index_obj );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift) const*
-NS(BeamElements_managed_buffer_get_const_drift)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Drift) const*
+NS(Drift_const_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC unsigned char
+        const* SIXTRL_RESTRICT buffer_begin, NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_const_drift)(
-        NS(ManagedBuffer_get_const_object)( pbuffer, be_index, slot_size ) );
+    return NS(Drift_const_from_obj_index)( NS(ManagedBuffer_get_const_object)(
+        buffer_begin, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)*
-NS(BeamElements_managed_buffer_get_drift)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size
+) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_drift)( NS(ManagedBuffer_get_object)(
-        pbuffer, be_index, slot_size ) );
+    return NS(Drift_from_obj_index)( NS(ManagedBuffer_get_object)(
+        buffer_begin, index, slot_size ) );
 }
 
 #if !defined( _GPUCODE )
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift) const*
-NS(BeamElements_buffer_get_const_drift)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Drift) const* NS(Drift_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_const_drift)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(Drift_const_from_obj_index)( NS(Buffer_get_const_object)(
+        buffer, index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)*
-NS(BeamElements_buffer_get_drift)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Drift)* NS(Drift_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_drift)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
-}
-
-SIXTRL_INLINE  bool NS(Drift_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs )
-{
-    typedef NS(Drift)           elem_t;
-    typedef NS(buffer_size_t)   buf_size_t;
-
-    buf_size_t const num_dataptrs = NS(Drift_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ), num_dataptrs,
-        sizes, counts, requ_objects, requ_slots, requ_dataptrs );
+    return NS(Drift_from_obj_index)( NS(Buffer_get_object)(
+        buffer, index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)* NS(Drift_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
-{
-    typedef NS(Drift)                            elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t*    ptr_to_elem_t;
-    typedef NS(buffer_size_t)                    buf_size_t;
-
-    buf_size_t const num_dataptrs = NS(Drift_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.length = ( NS(drift_real_t) )0.0;
-
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
+#endif /* !defined( _GPUCODE ) */
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_DRIFT), num_dataptrs, offsets, sizes, counts ) );
-}
+/* ------------------------------------------------------------------------- */
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)* NS(Drift_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC  NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(drift_real_t) const length )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* NS(DriftExact_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT
 {
-    typedef NS(Drift)                            elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t*    ptr_to_elem_t;
-    typedef NS(buffer_size_t)                    buf_size_t;
-
-    buf_size_t const num_dataptrs = NS(Drift_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.length = length;
-
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_DRIFT), num_dataptrs, offsets, sizes, counts ) );
+    if( drift != SIXTRL_NULLPTR ) NS(DriftExact_clear)( drift );
+    return drift;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(Drift)* NS(Drift_add_copy)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift )
+SIXTRL_INLINE NS(arch_status_t) NS(DriftExact_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT
 {
-    return NS(Drift_add)( buffer, NS(Drift_get_length)( drift ) );
+    SIXTRL_ASSERT( drift != SIXTRL_NULLPTR );
+    return NS(DriftExact_set_length)( drift, ( NS(drift_real_t) )0 );
 }
 
-#endif /* !defined( _GPUCODE ) */
-
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE NS(buffer_size_t) NS(DriftExact_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(DriftExact) *const SIXTRL_RESTRICT drift )
+SIXTRL_INLINE NS(buffer_size_t) NS(DriftExact_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC
+    const NS(DriftExact) *const SIXTRL_RESTRICT SIXTRL_UNUSED( drift )
+) SIXTRL_NOEXCEPT
 {
-    ( void )drift;
     return ( NS(buffer_size_t) )0u;
 }
 
-SIXTRL_INLINE NS(buffer_size_t) NS(DriftExact_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(buffer_size_t) NS(DriftExact_num_slots)( SIXTRL_BE_ARGPTR_DEC
+        const NS(DriftExact) *const SIXTRL_RESTRICT SIXTRL_UNUSED( drift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(DriftExact)    beam_element_t;
-
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    NS(buffer_size_t) const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(DriftExact) ), slot_size );
 
-    ( void )drift;
-
-    buf_size_t extent = NS(ManagedBuffer_get_slot_based_length)(
-        sizeof( beam_element_t ), slot_size );
-
-    SIXTRL_ASSERT( ( slot_size == ZERO ) || ( ( extent % slot_size ) == ZERO ) );
-    return ( slot_size > ZERO ) ? ( extent / slot_size ) : ( ZERO );
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
+    return num_slots;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* NS(DriftExact_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT drift )
+SIXTRL_INLINE NS(object_type_id_t) NS(DriftExact_type_id)(
+    void ) SIXTRL_NOEXCEPT
 {
-    NS(DriftExact_clear)( drift );
-    return drift;
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_DRIFT_EXACT);
 }
 
-SIXTRL_INLINE  NS(drift_real_t) NS(DriftExact_get_length)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(drift_real_t) NS(DriftExact_length)( SIXTRL_BE_ARGPTR_DEC const
+    NS(DriftExact) *const SIXTRL_RESTRICT drift ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( drift != SIXTRL_NULLPTR );
     return drift->length;
 }
 
-SIXTRL_INLINE void NS(DriftExact_set_length)(
+SIXTRL_INLINE NS(arch_status_t) NS(DriftExact_set_length)(
     SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT drift,
-    NS(drift_real_t) const length )
+    NS(drift_real_t) const length ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( drift != SIXTRL_NULLPTR );
     drift->length = length;
-    return;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(DriftExact_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT drift )
-{
-    NS(DriftExact_set_length)( drift, 0.0 );
-    return;
-}
-
-
 SIXTRL_INLINE int NS(DriftExact_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT source )
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT source
+) SIXTRL_NOEXCEPT
 {
-    int success = -1;
-
-    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) )
-    {
-        NS(DriftExact_set_length)( destination,
-                                   NS(DriftExact_get_length)( source ) );
-        success = 0;
-    }
-
-    return success;
+    return NS(DriftExact_set_length)(
+        destination, NS(DriftExact_length)( source ) );
 }
 
-SIXTRL_INLINE int NS(DriftExact_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT rhs )
-{
-    int compare_value = -1;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    if( ( lhs != SIXTRL_NULLPTR ) &&
-        ( rhs != SIXTRL_NULLPTR ) )
-    {
-        if( NS(DriftExact_get_length)( lhs ) >
-            NS(DriftExact_get_length)( rhs ) )
-        {
-            compare_value = +1;
-        }
-        else if( NS(DriftExact_get_length)( lhs ) <
-                 NS(DriftExact_get_length)( rhs ) )
-        {
-            compare_value = -1;
-        }
-        else
-        {
-            compare_value = 0;
-        }
-    }
-    else if( rhs != SIXTRL_NULLPTR )
-    {
-        compare_value = +1;
-    }
-
-    return compare_value;
-}
-
-SIXTRL_INLINE int NS(DriftExact_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT rhs,
-    NS(drift_real_t) const treshold )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const*
+NS(DriftExact_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT
 {
-    int compare_value = -1;
-
-    typedef NS(drift_real_t) real_t;
-
-    SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0.0;
-
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) &&
-        ( treshold > ZERO ) )
-    {
-        SIXTRL_ASSERT( treshold >= ZERO );
-
-        NS(drift_real_t) const diff =
-            NS(DriftExact_get_length)( lhs ) - NS(DriftExact_get_length)( rhs );
-
-        NS(drift_real_t) const abs_diff = ( diff > ZERO ) ? diff : -diff;
-
-        if( abs_diff < treshold )
-        {
-            compare_value = 0;
-        }
-        else if( diff > ZERO )
-        {
-            compare_value = +1;
-        }
-        else
-        {
-            compare_value = -1;
-        }
-    }
-    else if( ( rhs != SIXTRL_NULLPTR ) && ( treshold > ZERO ) )
-    {
-        compare_value = +1;
-    }
-
-    return compare_value;
-}
-
-/* ------------------------------------------------------------------------- */
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact) const*
-NS(BufferIndex_get_const_drift_exact)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj )
-{
-    typedef NS(DriftExact) beam_element_t;
-    typedef SIXTRL_BUFFER_OBJ_DATAPTR_DEC beam_element_t const* ptr_to_be_t;
-    ptr_to_be_t ptr_to_be = SIXTRL_NULLPTR;
+    typedef SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const* ptr_elem_t;
+    ptr_elem_t elem = SIXTRL_NULLPTR;
 
     if( ( index_obj != SIXTRL_NULLPTR ) &&
-        ( NS(Object_get_type_id)( index_obj ) == NS(OBJECT_TYPE_DRIFT_EXACT) ) &&
-        ( NS(Object_get_size)( index_obj ) >= sizeof( beam_element_t ) ) )
+        ( NS(Object_get_type_id)( index_obj ) ==
+          NS(OBJECT_TYPE_DRIFT_EXACT) ) &&
+        ( NS(Object_get_size)( index_obj ) >= sizeof( NS(DriftExact) ) ) )
     {
-        ptr_to_be = ( ptr_to_be_t )( uintptr_t
-            )NS(Object_get_begin_addr)( index_obj );
+        elem = ( ptr_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
+            index_obj );
     }
 
-    return ptr_to_be;
+    return elem;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(BufferIndex_get_drift_exact)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* NS(DriftExact_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT index_obj
+) SIXTRL_NOEXCEPT
 {
-    return ( SIXTRL_BUFFER_OBJ_DATAPTR_DEC NS(DriftExact)*
-        )NS(BufferIndex_get_const_drift_exact)( index_obj );
+    return ( SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+        )NS(DriftExact_const_from_obj_index)( index_obj );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact) const*
-NS(BeamElements_managed_buffer_get_const_drift_exact)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index,
-    NS(buffer_size_t) const slot_size )
-{
-    return NS(BufferIndex_get_const_drift_exact)(
-        NS(ManagedBuffer_get_const_object)( pbuffer, be_index, slot_size ) );
-}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(BeamElements_managed_buffer_get_drift_exact)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const*
+NS(DriftExact_const_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC unsigned char
+        const* SIXTRL_RESTRICT buffer_begin, NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_drift_exact)( NS(ManagedBuffer_get_object)(
-        pbuffer, be_index, slot_size ) );
+    return NS(DriftExact_const_from_obj_index)( NS(ManagedBuffer_get_const_object)(
+        buffer_begin, index, slot_size ) );
 }
 
-#if !defined( _GPUCODE )
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact) const*
-NS(BeamElements_buffer_get_const_drift_exact)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DriftExact)*
+NS(DriftExact_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size
+) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_const_drift_exact)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(DriftExact_from_obj_index)( NS(ManagedBuffer_get_object)(
+        buffer_begin, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(BeamElements_buffer_get_drift_exact)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
-{
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_drift_exact)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
-}
+#if !defined( _GPUCODE )
 
-SIXTRL_INLINE  bool NS(DriftExact_can_be_added)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const*
+NS(DriftExact_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs )
-{
-    typedef NS(buffer_size_t) buf_size_t;
-
-    buf_size_t const num_dataptrs =
-        NS(DriftExact_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes  = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts = SIXTRL_NULLPTR;
-
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-
-    return NS(Buffer_can_add_object)( buffer, sizeof( NS(DriftExact) ),
-        num_dataptrs, sizes, counts, requ_objects, requ_slots, requ_dataptrs );
-}
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(DriftExact_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
-    SIXTRL_RESTRICT buffer )
-{
-    typedef NS(DriftExact)                      elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t*   ptr_to_elem_t;
-    typedef NS(buffer_size_t)                   buf_size_t;
-
-    buf_size_t const num_dataptrs =
-        NS(DriftExact_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.length = ( NS(drift_real_t) )0.0;
-
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, NS(DriftExact_preset)( &temp_obj ),
-            sizeof( elem_t ), NS(OBJECT_TYPE_DRIFT_EXACT), num_dataptrs,
-                offsets, sizes, counts ) );
-}
-
-SIXTRL_INLINE  SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)*
-NS(DriftExact_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(drift_real_t) const length )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef NS(DriftExact)                      elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t*   ptr_to_elem_t;
-    typedef NS(buffer_size_t)                   buf_size_t;
-
-    buf_size_t const num_dataptrs =
-        NS(DriftExact_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.length = length;
-
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_DRIFT_EXACT), num_dataptrs, offsets, sizes, counts ) );
+    return NS(DriftExact_const_from_obj_index)( NS(Buffer_get_const_object)(
+        buffer, index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)* NS(DriftExact_add_copy)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* NS(DriftExact_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    return NS(DriftExact_add)( buffer, NS(DriftExact_get_length)( drift ) );
+    return NS(DriftExact_from_obj_index)( NS(Buffer_get_object)(
+        buffer, index ) );
 }
 
 #endif /* !defined( _GPUCODE ) */
@@ -825,7 +589,4 @@ SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(DriftExact)* NS(DriftExact_add_copy)(
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRACKLIB_COMMON_BE_DRIFT_BEAM_ELEMENT_DRIFT_H__ */
-
-/* end: sixtracklib/common/be_drift/be_drift.h */
diff --git a/sixtracklib/common/be_drift/be_drift.hpp b/sixtracklib/common/be_drift/be_drift.hpp
index 6b376d2a..b334f194 100644
--- a/sixtracklib/common/be_drift/be_drift.hpp
+++ b/sixtracklib/common/be_drift/be_drift.hpp
@@ -1016,7 +1016,7 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE TDrift< NS(drift_real_t) >::value_type
     TDrift< NS(drift_real_t) >::getLength() const SIXTRL_NOEXCEPT
     {
-        return ::NS(Drift_get_length)( this->getCApiPtr() );
+        return ::NS(Drift_length)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE void TDrift< NS(drift_real_t) >::setLength(
@@ -1239,7 +1239,7 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE TDriftExact< NS(drift_real_t) >::value_type
     TDriftExact< NS(drift_real_t) >::getLength() const SIXTRL_NOEXCEPT
     {
-        return ::NS(DriftExact_get_length)( this->getCApiPtr() );
+        return ::NS(DriftExact_length)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE void TDriftExact< NS(drift_real_t) >::setLength(
diff --git a/sixtracklib/common/be_drift/track.h b/sixtracklib/common/be_drift/track.h
index 964fe41a..3a77ffb6 100644
--- a/sixtracklib/common/be_drift/track.h
+++ b/sixtracklib/common/be_drift/track.h
@@ -52,7 +52,7 @@ SIXTRL_INLINE int NS(Track_particle_drift)(
     real_t const rpp    = NS(Particles_get_rpp_value)( p, ii );
     real_t const xp     = NS(Particles_get_px_value )( p, ii ) * rpp;
     real_t const yp     = NS(Particles_get_py_value )( p, ii ) * rpp;
-    real_t const length = NS(Drift_get_length)( drift );
+    real_t const length = NS(Drift_length)( drift );
     real_t const dzeta  = NS(Particles_get_rvv_value)( p, ii ) -
                           ( ( real_t )1 + ( xp*xp + yp*yp ) / ( real_t )2 );
 
@@ -75,7 +75,7 @@ SIXTRL_INLINE int NS(Track_particle_drift_exact)(
 {
     typedef NS(particle_real_t) real_t;
 
-    real_t const length = NS(DriftExact_get_length)( drift );
+    real_t const length = NS(DriftExact_length)( drift );
     real_t const px     = NS(Particles_get_px_value)( p, ii );
     real_t const py     = NS(Particles_get_py_value)( p, ii );
     real_t const opd    = NS(Particles_get_delta_value)( p, ii ) + ( real_t )1;
diff --git a/sixtracklib/common/be_limit/CMakeLists.txt b/sixtracklib/common/be_limit/CMakeLists.txt
index 8e547a59..f7eec3f6 100644
--- a/sixtracklib/common/be_limit/CMakeLists.txt
+++ b/sixtracklib/common/be_limit/CMakeLists.txt
@@ -1,28 +1,15 @@
 # =============================================================================
 # end: sixtracklib/common/be_limit/CMakeLitst.txt
 
-set( SIXTRL_COMMON_BE_LIMIT_CXX_HEADERS
-     be_limit_rect.hpp
-     be_limit_ellipse.hpp
-)
-
 set( SIXTRL_COMMON_BE_LIMIT_C99_HEADERS
-     be_limit_rect.h
-     be_limit_ellipse.h
-     be_limit_rect_ellipse.h
-     track.h
-)
+     be_limit_rect.h be_limit_ellipse.h be_limit_rect_ellipse.h track.h )
+
 set( SIXTRL_COMMON_BE_LIMIT_C99_SOURCES
-     be_limit_rect.c
-     be_limit_ellipse.c
-     be_limit_rect_ellipse.c
-)
+     be_limit_rect.c be_limit_ellipse.c be_limit_rect_ellipse.c )
 
 add_library( sixtrack_common_be_limit OBJECT
     ${SIXTRL_COMMON_BE_LIMIT_C99_HEADERS}
-    ${SIXTRL_COMMON_BE_LIMIT_C99_SOURCES}
-    ${SIXTRL_COMMON_BE_LIMIT_CXX_HEADERS}
-)
+    ${SIXTRL_COMMON_BE_LIMIT_C99_SOURCES} )
 
 target_include_directories( sixtrack_common_be_limit PRIVATE
     $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
@@ -32,13 +19,36 @@ set_target_properties( sixtrack_common_be_limit PROPERTIES
     C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_be_limit PRIVATE
-    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
+
+
+
+set( SIXTRL_COMMON_BE_LIMIT_CXX_HEADERS be_limit_rect.hpp be_limit_ellipse.hpp )
+set( SIXTRL_COMMON_BE_LIMIT_CXX_SOURCES be_limit.cpp )
+
+add_library( sixtrack_common_be_limit_cxx OBJECT
+    ${SIXTRL_COMMON_BE_LIMIT_C99_HEADERS}
+    ${SIXTRL_COMMON_BE_LIMIT_CXX_HEADERS}
+    ${SIXTRL_COMMON_BE_LIMIT_CXX_SOURCES} )
+
+target_include_directories( sixtrack_common_be_limit_cxx PRIVATE
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
+
+set_target_properties( sixtrack_common_be_limit_cxx PROPERTIES
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON
+    CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON )
+
+target_compile_options( sixtrack_common_be_limit_cxx PRIVATE
+    ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_CXX_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_be_beambeam as a module for sixtracklib:
 
-set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
-    $<TARGET_OBJECTS:sixtrack_common_be_limit> CACHE INTERNAL "" FORCE )
+set( SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_common_be_limit>
+    $<TARGET_OBJECTS:sixtrack_common_be_limit_cxx> CACHE INTERNAL "" FORCE )
 
 # ==============================================================================
 # Installation:
diff --git a/sixtracklib/common/be_limit/be_limit.cpp b/sixtracklib/common/be_limit/be_limit.cpp
new file mode 100644
index 00000000..08ea53cc
--- /dev/null
+++ b/sixtracklib/common/be_limit/be_limit.cpp
@@ -0,0 +1,33 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/be_limit/be_limit_rect.hpp"
+    #include "sixtracklib/common/be_limit/be_limit_ellipse.hpp"
+#endif/* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus )
+namespace SIXTRL_CXX_NAMESPACE
+{
+    constexpr TLimitRect< ::NS(particle_real_t) >::value_type
+        TLimitRect< ::NS(particle_real_t) >::DEFAULT_MIN_X;
+
+    constexpr TLimitRect< ::NS(particle_real_t) >::value_type
+        TLimitRect< ::NS(particle_real_t) >::DEFAULT_MAX_X;
+
+    constexpr TLimitRect< ::NS(particle_real_t) >::value_type
+        TLimitRect< ::NS(particle_real_t) >::DEFAULT_MIN_Y;
+
+    constexpr TLimitRect< ::NS(particle_real_t) >::value_type
+        TLimitRect< ::NS(particle_real_t) >::DEFAULT_MAX_Y;
+
+    /* --------------------------------------------------------------------- */
+
+    constexpr TLimitEllipse< ::NS(particle_real_t) >::value_type
+        TLimitEllipse< ::NS(particle_real_t) >::DEFAULT_X_HALF_AXIS;
+
+    constexpr TLimitEllipse< ::NS(particle_real_t) >::value_type
+        TLimitEllipse< ::NS(particle_real_t) >::DEFAULT_Y_HALF_AXIS;
+
+    /* --------------------------------------------------------------------- */
+
+
+}
+#endif /* C++ */
diff --git a/sixtracklib/common/be_limit/be_limit_ellipse.c b/sixtracklib/common/be_limit/be_limit_ellipse.c
index 00fd6172..09a28890 100644
--- a/sixtracklib/common/be_limit/be_limit_ellipse.c
+++ b/sixtracklib/common/be_limit/be_limit_ellipse.c
@@ -22,104 +22,156 @@
 
 #if !defined( _GPUCODE )
 
-NS(buffer_size_t) NS(LimitEllipse_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit )
+NS(object_type_id_t) NS(LimitEllipse_type_id_ext)( void ) SIXTRL_NOEXCEPT
 {
-    return NS(LimitEllipse_get_required_num_dataptrs_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ), limit, 
-        NS(Buffer_get_slot_size)( buffer ) );
+    return NS(LimitEllipse_type_id)();
 }
 
-NS(buffer_size_t) NS(LimitEllipse_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC  const NS(LimitEllipse) *const SIXTRL_RESTRICT limit)
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(LimitEllipse_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(LimitEllipse_get_required_num_slots_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ), limit, 
-        NS(Buffer_get_slot_size)( buffer ) );
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-bool NS(LimitEllipse_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT req_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT req_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT req_dataptrs )
+NS(arch_status_t) NS(LimitEllipse_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(LimitEllipse_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(LimitEllipse) elem_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    buf_size_t const num_dataptrs =
-        NS(LimitEllipse_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_counts > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
 
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes  = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts = SIXTRL_NULLPTR;
-    
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ),
-        num_dataptrs, sizes, counts, req_objects, req_slots, req_dataptrs );
+bool NS(LimitEllipse_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    NS(LimitEllipse) temp;
+    NS(arch_status_t) const status = NS(LimitEllipse_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(LimitEllipse_num_dataptrs)( &temp );
+    SIXTRL_ASSERT( ndataptrs == ( NS(buffer_size_t) )0u );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof( NS(LimitEllipse) ),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects,
+                    requ_slots, requ_dataptrs ) ) );
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_new)(
+SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_new)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(LimitEllipse) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(LimitEllipse_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-    
-    elem_t temp_obj;
-    NS(LimitEllipse_preset)( &temp_obj );
-
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-    
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-        NS(OBJECT_TYPE_LIMIT_ELLIPSE), num_dataptrs, offsets, sizes, counts ) );
+    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* added_elem = SIXTRL_NULLPTR;
+
+    NS(LimitEllipse) temp;
+    NS(arch_status_t) const status = NS(LimitEllipse_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(LimitEllipse_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(LimitEllipse) ), NS(LimitEllipse_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(particle_real_t) const x_semi_axis, 
+SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_add)(
+    SIXTRL_BE_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(particle_real_t) const x_semi_axis,
     NS(particle_real_t) const y_semi_axis )
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(LimitEllipse) elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(LimitEllipse_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-    
-    NS(LimitEllipse_set_half_axes)( &temp_obj, x_semi_axis, y_semi_axis );
-    
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_LIMIT_ELLIPSE), num_dataptrs, offsets, 
-                sizes, counts ) );
+    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* added_elem = SIXTRL_NULLPTR;
+
+    NS(LimitEllipse) temp;
+    NS(arch_status_t) status = NS(LimitEllipse_set_half_axes)(
+        &temp, x_semi_axis, y_semi_axis );
+    NS(buffer_size_t) const ndataptrs = NS(LimitEllipse_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(LimitEllipse) ), NS(LimitEllipse_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_add_copy)(
+SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit )
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT orig )
 {
-    return NS(LimitEllipse_add)( buffer, 
-        NS(LimitEllipse_get_x_half_axis)( limit ),
-        NS(LimitEllipse_get_y_half_axis)( limit ) );
+    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(LimitEllipse_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(LimitEllipse) ), NS(LimitEllipse_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
 #endif /* !defined( _GPUCODE )*/
diff --git a/sixtracklib/common/be_limit/be_limit_ellipse.h b/sixtracklib/common/be_limit/be_limit_ellipse.h
index 7c621c6f..21f1651d 100644
--- a/sixtracklib/common/be_limit/be_limit_ellipse.h
+++ b/sixtracklib/common/be_limit/be_limit_ellipse.h
@@ -10,13 +10,15 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/particles/definitions.h"
     #include "sixtracklib/common/be_limit/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
+    #include "sixtracklib/common/internal/math_functions.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
-    #include "sixtracklib/common/control/definitions.h"
-    #include "sixtracklib/common/particles.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -31,122 +33,153 @@ typedef struct NS(LimitEllipse)
 }
 NS(LimitEllipse);
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(LimitEllipse_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit,
-    NS(buffer_size_t) const slot_size );
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_preset)( SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+    SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(LimitEllipse_clear)( SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+    SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(LimitEllipse_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
+NS(LimitEllipse_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse)
+    *const SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(LimitEllipse_num_slots)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit,
-    NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
-NS(LimitEllipse_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(LimitEllipse_type_id)(
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitEllipse_get_x_half_axis)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN NS(particle_real_t)
-NS(LimitEllipse_get_x_half_axis_squ)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit );
+SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitEllipse_x_half_axis)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitEllipse_get_y_half_axis)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit );
+SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitEllipse_x_half_axis_squ)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(particle_real_t)
-NS(LimitEllipse_get_y_half_axis_squ)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit );
+SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitEllipse_y_half_axis)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitEllipse_y_half_axis_squ)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN NS(particle_real_t)
-NS(LimitEllipse_get_half_axes_product_squ)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit );
+NS(LimitEllipse_half_axes_product_squ)( SIXTRL_BE_ARGPTR_DEC const
+    NS(LimitEllipse) *const SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitEllipse_set_half_axes)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitEllipse_set_half_axes)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const x_half_axis,
-    NS(particle_real_t) const y_half_axis );
+    NS(particle_real_t) const y_half_axis ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitEllipse_set_half_axes_squ)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitEllipse_set_half_axes_squ)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const x_half_axis_squ,
-    NS(particle_real_t) const y_half_axis_squ );
-
-
-SIXTRL_STATIC SIXTRL_FN void NS(LimitEllipse_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit );
+    NS(particle_real_t) const y_half_axis_squ ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitEllipse_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT destination,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
-        SIXTRL_RESTRICT source );
+        SIXTRL_RESTRICT source ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse) const*
-NS(BufferIndex_get_const_limit_ellipse)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const*
+NS(LimitEllipse_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)*
-NS(BufferIndex_get_limit_ellipse)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse) const*
-NS(BeamElements_managed_buffer_get_const_limit_ellipse)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const*
+NS(LimitEllipse_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)*
-NS(BeamElements_managed_buffer_get_limit_ellipse)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse) const*
-NS(BeamElements_buffer_get_const_limit_ellipse)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const*
+NS(LimitEllipse_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)*
-NS(BeamElements_buffer_get_limit_ellipse)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer, NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(LimitEllipse_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(LimitEllipse_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC  const NS(LimitEllipse) *const SIXTRL_RESTRICT limit);
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LimitEllipse_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LimitEllipse_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LimitEllipse_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(LimitEllipse_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(LimitEllipse_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT req_objects,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT req_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT req_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT req_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(particle_real_t) const x_semi_axis,
     NS(particle_real_t) const y_semi_axis );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
 NS(LimitEllipse_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit );
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT orig );
 
 #endif /* !defined( _GPUCODE )*/
 
@@ -158,237 +191,228 @@ NS(LimitEllipse_add_copy)(
 /*        Implementation of inline functions for NS(LimitEllipse)               */
 /* ========================================================================= */
 
-#if !defined( _GPUCODE )
-    #if !defined( SIXTRL_NO_INCLUDES )
-        #include "sixtracklib/common/buffer.h"
-    #endif /* !defined( SIXTRL_NO_INCLUDES ) */
-#endif /* !defined( _GPUCODE ) */
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #if !defined( _GPUCODE )
+    #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(LimitEllipse_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( buffer != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0u );
-
-    ( void )buffer;
-    ( void )limit;
-    ( void )slot_size;
-
-    return ( NS(buffer_size_t) )0u;
+    if( limit != SIXTRL_NULLPTR ) NS(LimitEllipse_clear)( limit );
+    return limit;
 }
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(LimitEllipse_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitEllipse_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( buffer != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0u );
+    return NS(LimitEllipse_set_half_axes)( limit,
+        ( NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_X_HALF_AXIS,
+        ( NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_Y_HALF_AXIS );
+}
 
-    ( void )buffer;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    return ( limit != SIXTRL_NULLPTR )
-        ? NS(ManagedBuffer_get_slot_based_length)(
-            sizeof( *limit ), slot_size )
-        : ( NS(buffer_size_t) )0u;
+SIXTRL_INLINE NS(buffer_size_t) NS(LimitEllipse_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC
+    const NS(LimitEllipse) *const SIXTRL_RESTRICT SIXTRL_UNUSED( limit )
+) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0u;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* NS(LimitEllipse_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit )
+SIXTRL_INLINE NS(buffer_size_t) NS(LimitEllipse_num_slots)( SIXTRL_BE_ARGPTR_DEC const
+        NS(LimitEllipse) *const SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR )
-    {
-        NS(LimitEllipse_clear)( limit );
-    }
-
-    return limit;
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    NS(buffer_size_t) const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(LimitEllipse) ), slot_size );
+
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
+    return num_slots;
 }
 
+SIXTRL_INLINE NS(object_type_id_t) NS(LimitEllipse_type_id)(
+    void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_LIMIT_ELLIPSE);
+}
 
-SIXTRL_INLINE NS(particle_real_t) NS(LimitEllipse_get_x_half_axis)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit )
+SIXTRL_INLINE NS(particle_real_t) NS(LimitEllipse_x_half_axis)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    return sqrt( NS(LimitEllipse_get_x_half_axis_squ)( limit ) );
+    return NS(sqrt)( NS(LimitEllipse_x_half_axis_squ)( limit ) );
 }
 
-SIXTRL_INLINE NS(particle_real_t)
-NS(LimitEllipse_get_x_half_axis_squ)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit )
+SIXTRL_INLINE NS(particle_real_t) NS(LimitEllipse_x_half_axis_squ)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
     return limit->a_squ;
 }
 
-SIXTRL_INLINE NS(particle_real_t) NS(LimitEllipse_get_y_half_axis)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit )
+SIXTRL_INLINE NS(particle_real_t) NS(LimitEllipse_y_half_axis)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    return sqrt( NS(LimitEllipse_get_y_half_axis_squ)( limit ) );
+    return NS(sqrt)( NS(LimitEllipse_y_half_axis_squ)( limit ) );
 }
 
-SIXTRL_INLINE NS(particle_real_t)
-NS(LimitEllipse_get_y_half_axis_squ)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit )
+SIXTRL_INLINE NS(particle_real_t) NS(LimitEllipse_y_half_axis_squ)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
     return limit->b_squ;
 }
 
-SIXTRL_INLINE NS(particle_real_t)
-NS(LimitEllipse_get_half_axes_product_squ)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit )
+SIXTRL_INLINE NS(particle_real_t) NS(LimitEllipse_half_axes_product_squ)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
     return limit->a_b_squ;
 }
 
 
-SIXTRL_INLINE void NS(LimitEllipse_set_half_axes)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitEllipse_set_half_axes)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const x_half_axis,
-    NS(particle_real_t) const y_half_axis )
+    NS(particle_real_t) const y_half_axis ) SIXTRL_NOEXCEPT
 {
-    NS(LimitEllipse_set_half_axes_squ)( limit,
+    return NS(LimitEllipse_set_half_axes_squ)( limit,
         x_half_axis * x_half_axis, y_half_axis * y_half_axis );
 }
 
-SIXTRL_INLINE void NS(LimitEllipse_set_half_axes_squ)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitEllipse_set_half_axes_squ)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const x_half_axis_squ,
-    NS(particle_real_t) const y_half_axis_squ )
+    NS(particle_real_t) const y_half_axis_squ ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR )
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( limit != SIXTRL_NULLPTR ) &&
+        ( x_half_axis_squ >= ( NS(particle_real_t) )0 ) &&
+        ( y_half_axis_squ >= ( NS(particle_real_t) )0 ) )
     {
         limit->a_squ   = x_half_axis_squ;
         limit->b_squ   = y_half_axis_squ;
         limit->a_b_squ = x_half_axis_squ * y_half_axis_squ;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
-}
 
-
-SIXTRL_INLINE void NS(LimitEllipse_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT limit )
-{
-    SIXTRL_STATIC_VAR NS(particle_real_t) const ONE_HALF =
-        ( NS(particle_real_t) )0.5;
-
-    NS(particle_real_t) const x_half_axis =
-        ONE_HALF * ( SIXTRL_LIMIT_DEFAULT_MAX_X - SIXTRL_LIMIT_DEFAULT_MIN_X );
-
-    NS(particle_real_t) const y_half_axis =
-        ONE_HALF * ( SIXTRL_LIMIT_DEFAULT_MAX_Y - SIXTRL_LIMIT_DEFAULT_MIN_Y );
-
-    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
-
-    NS(LimitEllipse_set_half_axes)( limit, x_half_axis, y_half_axis );
+    return status;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_INLINE NS(arch_status_t) NS(LimitEllipse_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT source )
+    SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)* SIXTRL_RESTRICT dst,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
 {
-    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    if( ( destination != SIXTRL_NULLPTR ) &&
-        ( source != SIXTRL_NULLPTR ) && ( destination != source ) )
+    if( ( dst != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
     {
-        if( destination != source )
+        if( dst != src )
         {
-            destination->a_squ    = source->a_squ;
-            destination->b_squ    = source->b_squ;
-            destination->a_b_squ  = source->a_b_squ;
+            status = NS(LimitEllipse_set_half_axes_squ)( dst,
+                NS(LimitEllipse_x_half_axis_squ)( src ),
+                NS(LimitEllipse_y_half_axis_squ)( src ) );
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
         }
-
-        status = SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
     return status;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse) const*
-NS(BufferIndex_get_const_limit_ellipse)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const*
+NS(LimitEllipse_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
 {
-    typedef NS(LimitEllipse) beam_element_t;
-    typedef SIXTRL_BUFFER_OBJ_DATAPTR_DEC beam_element_t const* ptr_to_be_t;
-    ptr_to_be_t ptr_to_be = SIXTRL_NULLPTR;
+    typedef SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const* ptr_elem_t;
+    ptr_elem_t elem = SIXTRL_NULLPTR;
 
-    if( ( index_obj != SIXTRL_NULLPTR ) &&
-        ( NS(Object_get_type_id)( index_obj ) == NS(OBJECT_TYPE_LIMIT_ELLIPSE) ) &&
-        ( NS(Object_get_size)( index_obj ) >= sizeof( beam_element_t ) ) )
+    if( ( obj != SIXTRL_NULLPTR ) && ( NS(Object_get_type_id)( obj ) ==
+          NS(OBJECT_TYPE_LIMIT_ELLIPSE) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(LimitEllipse) ) ) )
     {
-        ptr_to_be = ( ptr_to_be_t )( uintptr_t
-            )NS(Object_get_begin_addr)( index_obj );
+        elem = ( ptr_elem_t )( uintptr_t )NS(Object_get_begin_addr)( obj );
     }
 
-    return ptr_to_be;
+    return elem;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)*
-NS(BufferIndex_get_limit_ellipse)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
 {
-    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)*
-        )NS(BufferIndex_get_const_limit_ellipse)( index_obj );
+    return ( SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+        )NS(LimitEllipse_const_from_obj_index)( obj );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse) const*
-NS(BeamElements_managed_buffer_get_const_limit_ellipse)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const*
+NS(LimitEllipse_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_const_limit_ellipse)(
-        NS(ManagedBuffer_get_const_object)( pbuffer, be_index, slot_size ) );
+    return NS(LimitEllipse_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)*
-NS(BeamElements_managed_buffer_get_limit_ellipse)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_limit_ellipse)(
-        NS(ManagedBuffer_get_object)( pbuffer, be_index, slot_size ) );
+    return NS(LimitEllipse_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
 }
 
 #if !defined( _GPUCODE )
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse) const*
-NS(BeamElements_buffer_get_const_limit_ellipse)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const*
+NS(LimitEllipse_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_const_limit_ellipse)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(LimitEllipse_const_from_obj_index)( NS(Buffer_get_const_object)(
+        buffer, index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitEllipse)*
-NS(BeamElements_buffer_get_limit_ellipse)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse)*
+NS(LimitEllipse_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer, NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_limit_ellipse)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(LimitEllipse_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
 }
-
 #endif /* !defined( _GPUCODE ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRL_COMMON_BE_LIMIT_ELLIPSE_C99_H__ */
-/*end: sixtracklib/common/be_/be_.h */
diff --git a/sixtracklib/common/be_limit/be_limit_ellipse.hpp b/sixtracklib/common/be_limit/be_limit_ellipse.hpp
index 9b46a081..36f71cdb 100644
--- a/sixtracklib/common/be_limit/be_limit_ellipse.hpp
+++ b/sixtracklib/common/be_limit/be_limit_ellipse.hpp
@@ -15,6 +15,7 @@
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/buffer.hpp"
     #include "sixtracklib/common/be_limit/be_limit_ellipse.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 namespace SIXTRL_CXX_NAMESPACE
@@ -32,17 +33,11 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* ----------------------------------------------------------------- */
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MAX_X =
-             value_type{ SIXTRL_LIMIT_DEFAULT_MAX_X };
+        static constexpr value_type DEFAULT_X_HALF_AXIS =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_X_HALF_AXIS );
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MIN_X =
-            value_type{ SIXTRL_LIMIT_DEFAULT_MIN_X };
-
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MAX_Y =
-            value_type{ SIXTRL_LIMIT_DEFAULT_MAX_Y };
-
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MIN_Y =
-            value_type{ SIXTRL_LIMIT_DEFAULT_MIN_Y };
+        static constexpr value_type DEFAULT_Y_HALF_AXIS =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_Y_HALF_AXIS );
 
         /* ----------------------------------------------------------------- */
 
@@ -136,8 +131,8 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* ----------------------------------------------------------------- */
 
-        SIXTRL_FN void setHalfAxes( 
-            const_reference x_half_axis, 
+        SIXTRL_FN void setHalfAxes(
+            const_reference x_half_axis,
             const_reference y_half_axis ) SIXTRL_NOEXCEPT;
 
         SIXTRL_FN void setHalfAxesSqu(
@@ -151,6 +146,14 @@ namespace SIXTRL_CXX_NAMESPACE
         value_type  a_b_squ;
     };
 
+    template< typename T > constexpr typename TLimitEllipse< T >::value_type
+        TLimitEllipse< T >::DEFAULT_X_HALF_AXIS;
+
+    template< typename T > constexpr typename TLimitEllipse< T >::value_type
+        TLimitEllipse< T >::DEFAULT_Y_HALF_AXIS;
+
+    /* --------------------------------------------------------------------- */
+
     template< typename T > struct ObjectTypeTraits<
         SIXTRL_CXX_NAMESPACE::TLimitEllipse< T > >
     {
@@ -209,17 +212,11 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* ----------------------------------------------------------------- */
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MAX_X =
-            SIXTRL_CXX_NAMESPACE::LIMIT_DEFAULT_MAX_X;
-
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MIN_X =
-            SIXTRL_CXX_NAMESPACE::LIMIT_DEFAULT_MIN_X;
+        static constexpr value_type DEFAULT_X_HALF_AXIS =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_X_HALF_AXIS );
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MAX_Y =
-            SIXTRL_CXX_NAMESPACE::LIMIT_DEFAULT_MAX_Y;
-
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MIN_Y =
-            SIXTRL_CXX_NAMESPACE::LIMIT_DEFAULT_MIN_Y;
+        static constexpr value_type DEFAULT_Y_HALF_AXIS =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_Y_HALF_AXIS );
 
         /* ----------------------------------------------------------------- */
 
@@ -349,7 +346,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
     SIXTRL_ARGPTR_DEC LimitEllipse* LimitEllipse_add(
         LimitEllipse::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
-        LimitEllipse::value_type const x_haxis, 
+        LimitEllipse::value_type const x_haxis,
         LimitEllipse::value_type const y_haxis );
 
     SIXTRL_ARGPTR_DEC LimitEllipse* LimitEllipse_add_copy(
@@ -367,7 +364,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
 namespace SIXTRL_CXX_NAMESPACE
 {
-    template< typename T > typename TLimitEllipse< T >::value_type 
+    template< typename T > typename TLimitEllipse< T >::value_type
     TLimitEllipse< T >::getXHalfAxis() const SIXTRL_NOEXCEPT
     {
         return std::sqrt( this->a_squ );
@@ -477,17 +474,17 @@ namespace SIXTRL_CXX_NAMESPACE
     template< typename T > SIXTRL_INLINE SIXTRL_ARGPTR_DEC TLimitEllipse< T >*
     TLimitEllipse< T >::AddToBuffer(
         typename TLimitEllipse< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        typename TLimitEllipse< T >::const_reference x_half_axis, 
+        typename TLimitEllipse< T >::const_reference x_half_axis,
         typename TLimitEllipse< T >::const_reference y_half_axis )
     {
-        return TLimitEllipse< T >::AddToBuffer( 
+        return TLimitEllipse< T >::AddToBuffer(
             *buffer.getCApiPtr(), x_half_axis, y_half_axis );
     }
 
     template< typename T > SIXTRL_INLINE SIXTRL_ARGPTR_DEC TLimitEllipse< T >*
     TLimitEllipse< T >::AddToBuffer(
         typename TLimitEllipse< T >::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
-        typename TLimitEllipse< T >::const_reference x_half_axis, 
+        typename TLimitEllipse< T >::const_reference x_half_axis,
         typename TLimitEllipse< T >::const_reference y_half_axis )
     {
         using _this_t = SIXTRL_CXX_NAMESPACE::TLimitEllipse< T >;
@@ -566,20 +563,18 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE typename TLimitEllipse< T >::size_type
     TLimitEllipse< T >::RequiredNumDataPtrs(
         typename TLimitEllipse< T >::buffer_t const& SIXTRL_RESTRICT_REF
-            buffer ) SIXTRL_NOEXCEPT
+            SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_required_num_dataptrs)(
-            buffer.getCApiPtr(), nullptr );
+        return ::NS(LimitEllipse_num_dataptrs)( nullptr );
     }
 
     template< typename T >
     SIXTRL_INLINE typename TLimitEllipse< T >::size_type
     TLimitEllipse< T >::RequiredNumDataPtrs(
         SIXTRL_BUFFER_ARGPTR_DEC const c_buffer_t *const SIXTRL_RESTRICT
-            ptr_buffer ) SIXTRL_NOEXCEPT
+            SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_required_num_dataptrs)(
-            ptr_buffer, nullptr );
+        return ::NS(LimitEllipse_num_dataptrs)( nullptr );
     }
 
     /* --------------------------------------------------------------------- */
@@ -587,16 +582,9 @@ namespace SIXTRL_CXX_NAMESPACE
     template< typename T >
     void TLimitEllipse< T >::preset() SIXTRL_NOEXCEPT
     {
-        using _this_t = TLimitEllipse< T >;
-        using  real_t = typename _this_t::value_type;
-
-        real_t const x_half_axis = real_t{ 0.5 } * (
-            _this_t::DEFAULT_MAX_X - _this_t::DEFAULT_MIN_X );
-
-        real_t const y_half_axis = real_t{ 0.5 } * (
-            _this_t::DEFAULT_MAX_Y - _this_t::DEFAULT_MIN_Y );
-        
-        this->setHalfAxes( x_half_axis, y_half_axis );
+        using this_t = TLimitEllipse< T >;
+        this->setHalfAxes( this_t::DEFAULT_X_HALF_AXIS,
+                           this_t::DEFAULT_Y_HALF_AXIS );
     }
 
     template< typename T >
@@ -608,9 +596,9 @@ namespace SIXTRL_CXX_NAMESPACE
     /* --------------------------------------------------------------------- */
 
     template< typename T >
-    void TLimitEllipse< T >::setHalfAxes( 
-        typename TLimitEllipse< T >::const_reference x_half_axis, 
-        typename TLimitEllipse< T >::const_reference y_half_axis 
+    void TLimitEllipse< T >::setHalfAxes(
+        typename TLimitEllipse< T >::const_reference x_half_axis,
+        typename TLimitEllipse< T >::const_reference y_half_axis
     ) SIXTRL_NOEXCEPT
     {
         this->setHalfAxesSqu( x_half_axis * x_half_axis,
@@ -624,10 +612,10 @@ namespace SIXTRL_CXX_NAMESPACE
         ) SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( x_half_axis_squ >=
-                       typename TLimitEllipse< T >::real_t{ 0 } );
+                       typename TLimitEllipse< T >::value_type{ 0 } );
 
         SIXTRL_ASSERT( y_half_axis_squ >=
-                       typename TLimitEllipse< T >::real_t{ 0 } );
+                       typename TLimitEllipse< T >::value_type{ 0 } );
 
         this->a_squ = x_half_axis_squ;
         this->b_squ = y_half_axis_squ;
@@ -640,31 +628,30 @@ namespace SIXTRL_CXX_NAMESPACE
 
     LimitEllipse::value_type LimitEllipse::getXHalfAxis() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_x_half_axis)( this->getCApiPtr() );
+        return ::NS(LimitEllipse_x_half_axis)( this->getCApiPtr() );
     }
 
     LimitEllipse::value_type LimitEllipse::getYHalfAxis() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_y_half_axis)( this->getCApiPtr() );
+        return ::NS(LimitEllipse_y_half_axis)( this->getCApiPtr() );
     }
 
     LimitEllipse::value_type
     LimitEllipse::getXHalfAxisSqu() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_x_half_axis_squ)( this->getCApiPtr() );
+        return ::NS(LimitEllipse_x_half_axis_squ)( this->getCApiPtr() );
     }
 
     LimitEllipse::value_type
     LimitEllipse::getYHalfAxisSqu() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_y_half_axis_squ)( this->getCApiPtr() );
+        return ::NS(LimitEllipse_y_half_axis_squ)( this->getCApiPtr() );
     }
 
     LimitEllipse::value_type
     LimitEllipse::getHalfAxesProductSqu() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_half_axes_product_squ)(
-            this->getCApiPtr() );
+        return ::NS(LimitEllipse_half_axes_product_squ)( this->getCApiPtr() );
     }
 
     /* --------------------------------------------------------------------- */
@@ -712,18 +699,18 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE SIXTRL_ARGPTR_DEC LimitEllipse*
     LimitEllipse::AddToBuffer(
         LimitEllipse::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        LimitEllipse::value_type const x_half_axis, 
+        LimitEllipse::value_type const x_half_axis,
         LimitEllipse::value_type const y_half_axis )
     {
         return static_cast< SIXTRL_ARGPTR_DEC LimitEllipse* >(
-            ::NS(LimitEllipse_add)( 
+            ::NS(LimitEllipse_add)(
                 buffer.getCApiPtr(), x_half_axis, y_half_axis ) );
     }
 
     SIXTRL_INLINE SIXTRL_ARGPTR_DEC LimitEllipse*
     LimitEllipse::AddToBuffer(
         LimitEllipse::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
-        LimitEllipse::value_type const x_half_axis, 
+        LimitEllipse::value_type const x_half_axis,
         LimitEllipse::value_type const y_half_axis )
     {
         return static_cast< SIXTRL_ARGPTR_DEC LimitEllipse* >(
@@ -774,18 +761,16 @@ namespace SIXTRL_CXX_NAMESPACE
 
     SIXTRL_INLINE LimitEllipse::size_type LimitEllipse::RequiredNumDataPtrs(
         LimitEllipse::buffer_t const& SIXTRL_RESTRICT_REF
-            buffer ) SIXTRL_NOEXCEPT
+            SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_required_num_dataptrs)(
-            buffer.getCApiPtr(), nullptr );
+        return ::NS(LimitEllipse_num_dataptrs)( nullptr );
     }
 
     SIXTRL_INLINE LimitEllipse::size_type LimitEllipse::RequiredNumDataPtrs(
         SIXTRL_BUFFER_ARGPTR_DEC const LimitEllipse::c_buffer_t *const
-            SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+            SIXTRL_RESTRICT SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitEllipse_get_required_num_dataptrs)(
-            ptr_buffer, nullptr );
+        return ::NS(LimitEllipse_num_dataptrs)( nullptr );
     }
 
     /* --------------------------------------------------------------------- */
@@ -801,8 +786,8 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     /* --------------------------------------------------------------------- */
-    
-    void LimitEllipse::setHalfAxes( 
+
+    void LimitEllipse::setHalfAxes(
         LimitEllipse::value_type const x_half_axis,
         LimitEllipse::value_type const y_half_axis ) SIXTRL_NOEXCEPT
     {
@@ -837,16 +822,16 @@ namespace SIXTRL_CXX_NAMESPACE
         LimitEllipse::value_type const x_half_axis,
         LimitEllipse::value_type const y_half_axis )
     {
-        return LimitEllipse::AddToBuffer( 
+        return LimitEllipse::AddToBuffer(
             *buffer.getCApiPtr(), x_half_axis, y_half_axis );
     }
 
     SIXTRL_INLINE SIXTRL_ARGPTR_DEC LimitEllipse* LimitEllipse_add(
         LimitEllipse::c_buffer_t& SIXTRL_RESTRICT_REF buffer,
-        LimitEllipse::value_type const x_half_axis, 
+        LimitEllipse::value_type const x_half_axis,
         LimitEllipse::value_type const y_half_axis )
     {
-        return LimitEllipse::AddToBuffer( 
+        return LimitEllipse::AddToBuffer(
             buffer, x_half_axis, y_half_axis );
     }
 
@@ -866,7 +851,4 @@ namespace SIXTRL_CXX_NAMESPACE
 }
 
 #endif /* !defined( _GPUCODE ) */
-
 #endif /* defined( SIXTRACKLIB_COMMON_BE_LIMIT_ELLIPSE_CXX_HPP__ ) */
-
-/* end: sixtracklib/common/be_limit/be_limit_ellipse.hpp */
diff --git a/sixtracklib/common/be_limit/be_limit_rect.c b/sixtracklib/common/be_limit/be_limit_rect.c
index 816b4558..c4fecaca 100644
--- a/sixtracklib/common/be_limit/be_limit_rect.c
+++ b/sixtracklib/common/be_limit/be_limit_rect.c
@@ -8,109 +8,165 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/be_limit/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
-    #include "sixtracklib/common/control/definitions.h"
-    #include "sixtracklib/common/particles.h"
-    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
-
-NS(buffer_size_t) NS(LimitRect_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit )
+NS(object_type_id_t) NS(LimitRect_type_id_ext)( void ) SIXTRL_NOEXCEPT
 {
-    return NS(LimitRect_get_required_num_dataptrs_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ), limit,
-        NS(Buffer_get_slot_size)( buffer ) );
+    return NS(LimitRect_type_id)();
 }
 
-NS(buffer_size_t) NS(LimitRect_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC  const NS(LimitRect) *const SIXTRL_RESTRICT limit )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(LimitRect_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(LimitRect_get_required_num_slots_on_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ), limit,
-        NS(Buffer_get_slot_size)( buffer ) );
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-bool NS(LimitRect_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs )
+NS(arch_status_t) NS(LimitRect_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(LimitRect) elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(LimitRect_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes  = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts = SIXTRL_NULLPTR;
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
 
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ),
-        num_dataptrs, sizes, counts, requ_objects, requ_slots, requ_dataptrs );
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)* NS(LimitRect_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+NS(arch_status_t) NS(LimitRect_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)   buf_size_t;
-    typedef NS(LimitRect)           elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    buf_size_t const num_dataptrs =
-        NS(LimitRect_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_counts > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
 
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
 
-    elem_t temp_obj;
-    NS(LimitRect_preset)( &temp_obj );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-        NS(OBJECT_TYPE_LIMIT_RECT), num_dataptrs, offsets, sizes, counts ) );
+bool NS(LimitRect_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    NS(LimitRect) temp;
+    NS(arch_status_t) const status = NS(LimitRect_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(LimitRect_num_dataptrs)( &temp );
+    SIXTRL_ASSERT( ndataptrs == ( NS(buffer_size_t) )0u );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof( NS(LimitRect) ),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects,
+                    requ_slots, requ_dataptrs ) ) );
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)* NS(LimitRect_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* NS(LimitRect_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* added_elem = SIXTRL_NULLPTR;
+
+    NS(LimitRect) temp;
+    NS(arch_status_t) const status = NS(LimitRect_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(LimitRect_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(LimitRect) ), NS(LimitRect_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* NS(LimitRect_add)(
+    SIXTRL_BE_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(particle_real_t) const min_x, NS(particle_real_t) const max_x,
     NS(particle_real_t) const min_y, NS(particle_real_t) const max_y )
 {
-    typedef NS(buffer_size_t)   buf_size_t;
-    typedef NS(LimitRect)           elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(LimitRect_get_required_num_dataptrs)( buffer, SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    NS(LimitRect_set_min_x)( &temp_obj, min_x );
-    NS(LimitRect_set_max_x)( &temp_obj, max_x );
-    NS(LimitRect_set_min_y)( &temp_obj, min_y );
-    NS(LimitRect_set_max_y)( &temp_obj, max_y );
-    
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-        NS(OBJECT_TYPE_LIMIT_RECT), num_dataptrs, offsets, sizes, counts ) );
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) ndataptrs = ( NS(buffer_size_t) )0u;
+
+    NS(LimitRect) temp;
+    NS(arch_status_t) status = NS(LimitRect_set_min_x)( &temp, min_x );
+    status |= NS(LimitRect_set_max_x)( &temp, max_x );
+    status |= NS(LimitRect_set_min_y)( &temp, min_y );
+    status |= NS(LimitRect_set_max_y)( &temp, max_y );
+    ndataptrs = NS(LimitRect_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(LimitRect) ), NS(LimitRect_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)* NS(LimitRect_add_copy)(
+SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* NS(LimitRect_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit )
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT orig )
 {
-    return NS(LimitRect_add)( buffer, 
-        NS(LimitRect_get_min_x)( limit ), NS(LimitRect_get_max_x)( limit ),
-        NS(LimitRect_get_min_y)( limit ), NS(LimitRect_get_max_y)( limit ) );
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(LimitRect_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(LimitRect) ), NS(LimitRect_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
-
-/* end: sixtracklib/common/be_limit/be_limit.c */
diff --git a/sixtracklib/common/be_limit/be_limit_rect.h b/sixtracklib/common/be_limit/be_limit_rect.h
index 856c3516..d8d15326 100644
--- a/sixtracklib/common/be_limit/be_limit_rect.h
+++ b/sixtracklib/common/be_limit/be_limit_rect.h
@@ -9,13 +9,14 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/particles/definitions.h"
     #include "sixtracklib/common/be_limit/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
-    #include "sixtracklib/common/control/definitions.h"
-    #include "sixtracklib/common/particles.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -32,108 +33,139 @@ typedef struct NS(LimitRect)
 }
 NS(LimitRect);
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(LimitRect_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit,
-    NS(buffer_size_t) const slot_size );
-
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
-NS(LimitRect_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit,
-    NS(buffer_size_t) const slot_size );
+/* ------------------------------------------------------------------------- */
 
 SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
-NS(LimitRect_preset)( SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT );
+NS(LimitRect_preset)( SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
+    SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRect_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRect_get_min_x)(
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(LimitRect_num_dataptrs)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
-        SIXTRL_RESTRICT limit_rect );
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRect_get_max_x)(
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(LimitRect_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(LimitRect_type_id)(
+    void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRect_min_x)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
-        SIXTRL_RESTRICT limit_rect );
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRect_get_min_y)(
+SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRect_max_x)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
-        SIXTRL_RESTRICT limit_rect );
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRect_get_max_y)(
+SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRect_min_y)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
-        SIXTRL_RESTRICT limit_rect );
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRect_set_x_limit)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const x_limit );
+SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRect_max_y)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRect_set_y_limit)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const y_limit );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRect_set_x_limit)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const x_limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRect_set_min_x)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const min_x );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRect_set_y_limit)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const y_limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRect_set_max_x)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const max_x );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRect_set_min_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const min_x ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRect_set_min_y)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const min_y );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRect_set_max_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const max_x ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRect_set_max_y)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const max_y );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRect_set_min_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const min_y ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRect_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRect_set_max_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const max_y ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRect_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT source );
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT dst,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect) const*
-NS(BufferIndex_get_const_limit_rect)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const*
+NS(LimitRect_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
+NS(LimitRect_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)*
-NS(BufferIndex_get_limit_rect)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect) const*
-NS(BeamElements_managed_buffer_get_const_limit_rect)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const*
+NS(LimitRect_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)*
-NS(BeamElements_managed_buffer_get_limit_rect)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
+NS(LimitRect_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect) const*
-NS(BeamElements_buffer_get_const_limit_rect)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const*
+NS(LimitRect_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)*
-NS(BeamElements_buffer_get_limit_rect)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* NS(LimitRect_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(LimitRect_get_required_num_dataptrs)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT  );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
-NS(LimitRect_get_required_num_slots)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC  const NS(LimitRect) *const SIXTRL_RESTRICT  );
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LimitRect_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LimitRect_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(LimitRect_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(LimitRect_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(LimitRect_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
@@ -141,17 +173,17 @@ SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(LimitRect_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT req_slots,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT req_dataptrs );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)* NS(LimitRect_new)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
+NS(LimitRect_new)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN
-SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)* NS(LimitRect_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
+NS(LimitRect_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(particle_real_t) const min_x, NS(particle_real_t) const max_x,
     NS(particle_real_t) const min_y, NS(particle_real_t) const max_y );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
 NS(LimitRect_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit );
@@ -166,250 +198,266 @@ NS(LimitRect_add_copy)(
 /*        Implementation of inline functions for NS(LimitRect)               */
 /* ========================================================================= */
 
-#if !defined( _GPUCODE )
-    #if !defined( SIXTRL_NO_INCLUDES )
-        #include "sixtracklib/common/buffer.h"
-    #endif /* !defined( SIXTRL_NO_INCLUDES ) */
-#endif /* !defined( _GPUCODE ) */
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #if !defined( _GPUCODE )
+    #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(LimitRect_get_required_num_dataptrs_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* NS(LimitRect_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( buffer != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0u );
-
-    ( void )buffer;
-    ( void )limit;
-    ( void )slot_size;
-
-    return ( NS(buffer_size_t) )0u;
+    if( limit != SIXTRL_NULLPTR ) NS(LimitRect_clear)( limit );
+    return limit;
 }
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(LimitRect_get_required_num_slots_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRect_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( buffer != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0u );
+    NS(arch_status_t) status = NS(LimitRect_set_min_x)(
+        limit, ( NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_MIN_X );
+
+    status |= NS(LimitRect_set_max_x)(
+        limit, ( NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_MAX_X );
 
-    ( void )buffer;
+    status |= NS(LimitRect_set_min_y)(
+        limit, ( NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_MIN_Y );
 
-    return ( limit != SIXTRL_NULLPTR )
-        ? NS(ManagedBuffer_get_slot_based_length)( sizeof( *limit ), slot_size )
-        : ( NS(buffer_size_t) )0u;
+    status |= NS(LimitRect_set_max_y)(
+        limit, ( NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_MAX_Y );
+
+    return status;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* NS(LimitRect_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(buffer_size_t) NS(LimitRect_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC
+    const NS(LimitRect) *const SIXTRL_RESTRICT SIXTRL_UNUSED( limit )
+) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR )
+    return ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(LimitRect_num_slots)( SIXTRL_BE_ARGPTR_DEC
+    const NS(LimitRect) *const SIXTRL_RESTRICT limit,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+
+    if( ( limit != SIXTRL_NULLPTR ) && ( slot_size > ( NS(buffer_size_t) )0u ) )
     {
-        NS(LimitRect_set_min_x)( limit, SIXTRL_LIMIT_DEFAULT_MIN_X );
-        NS(LimitRect_set_max_x)( limit, SIXTRL_LIMIT_DEFAULT_MAX_X );
+        NS(buffer_size_t) const requ_bytes =
+            NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(LimitRect) ), slot_size );
 
-        NS(LimitRect_set_min_y)( limit, SIXTRL_LIMIT_DEFAULT_MIN_Y );
-        NS(LimitRect_set_max_y)( limit, SIXTRL_LIMIT_DEFAULT_MAX_Y );
+        num_slots = requ_bytes / slot_size;
+        if( num_slots * slot_size < requ_bytes ) ++num_slots;
     }
 
-    return limit;
+    return num_slots;
 }
 
-SIXTRL_INLINE  NS(particle_real_t) NS(LimitRect_get_min_x)( SIXTRL_BE_ARGPTR_DEC
-    const NS(LimitRect) *const SIXTRL_RESTRICT limit_rect )
+SIXTRL_INLINE NS(object_type_id_t) NS(LimitRect_type_id)(
+    void ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( limit_rect != SIXTRL_NULLPTR );
-    return limit_rect->min_x;
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_LIMIT_RECT);
 }
 
-SIXTRL_INLINE NS(particle_real_t) NS(LimitRect_get_max_x)( SIXTRL_BE_ARGPTR_DEC
-    const NS(LimitRect) *const SIXTRL_RESTRICT limit_rect )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE  NS(particle_real_t) NS(LimitRect_min_x)( SIXTRL_BE_ARGPTR_DEC
+    const NS(LimitRect) *const SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( limit_rect != SIXTRL_NULLPTR );
-    return limit_rect->max_x;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    return limit->min_x;
 }
 
-SIXTRL_INLINE NS(particle_real_t) NS(LimitRect_get_min_y)( SIXTRL_BE_ARGPTR_DEC
-    const NS(LimitRect) *const SIXTRL_RESTRICT limit_rect )
+SIXTRL_INLINE NS(particle_real_t) NS(LimitRect_max_x)( SIXTRL_BE_ARGPTR_DEC
+    const NS(LimitRect) *const SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( limit_rect != SIXTRL_NULLPTR );
-    return limit_rect->min_y;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    return limit->max_x;
 }
 
-SIXTRL_INLINE NS(particle_real_t) NS(LimitRect_get_max_y)( SIXTRL_BE_ARGPTR_DEC
-    const NS(LimitRect) *const SIXTRL_RESTRICT limit_rect )
+SIXTRL_INLINE NS(particle_real_t) NS(LimitRect_min_y)( SIXTRL_BE_ARGPTR_DEC
+    const NS(LimitRect) *const SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( limit_rect != SIXTRL_NULLPTR );
-    return limit_rect->max_y;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    return limit->min_y;
 }
 
-SIXTRL_INLINE void NS(LimitRect_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit )
+SIXTRL_INLINE NS(particle_real_t) NS(LimitRect_max_y)( SIXTRL_BE_ARGPTR_DEC
+    const NS(LimitRect) *const SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    NS(LimitRect_preset)( limit );
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    return limit->max_y;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE void NS(LimitRect_set_x_limit)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const x_limit )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRect_set_x_limit)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const x_limit ) SIXTRL_NOEXCEPT
 {
-    if( limit_rect != SIXTRL_NULLPTR )
-    {
-        limit_rect->min_x = -x_limit;
-        limit_rect->max_x =  x_limit;
-    }
+    NS(arch_status_t) status = NS(LimitRect_set_min_x)( limit, -x_limit );
+    status |= NS(LimitRect_set_max_x)( limit, +x_limit );
+
+    SIXTRL_ASSERT( x_limit >= ( NS(particle_real_t) )0 );
+    return status;
 }
 
-SIXTRL_INLINE void NS(LimitRect_set_y_limit)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const y_limit )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRect_set_y_limit)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const y_limit ) SIXTRL_NOEXCEPT
 {
-    if( limit_rect != SIXTRL_NULLPTR )
-    {
-        limit_rect->min_y = -y_limit;
-        limit_rect->max_y =  y_limit;
-    }
+    NS(arch_status_t) status = NS(LimitRect_set_min_y)( limit, -y_limit );
+    status |= NS(LimitRect_set_max_y)( limit, +y_limit );
+
+    SIXTRL_ASSERT( y_limit >= ( NS(particle_real_t) )0 );
+    return status;
 }
 
-SIXTRL_INLINE void NS(LimitRect_set_min_x)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const min_x )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRect_set_min_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const min_x ) SIXTRL_NOEXCEPT
 {
-    if( limit_rect != SIXTRL_NULLPTR ) limit_rect->min_x = min_x;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->min_x = min_x;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRect_set_max_x)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const max_x )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRect_set_max_x)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const max_x ) SIXTRL_NOEXCEPT
 {
-    if( limit_rect != SIXTRL_NULLPTR ) limit_rect->max_x = max_x;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->max_x = max_x;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRect_set_min_y)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const min_y )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRect_set_min_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const min_y ) SIXTRL_NOEXCEPT
 {
-    if( limit_rect != SIXTRL_NULLPTR ) limit_rect->min_y = min_y;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->min_y = min_y;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRect_set_max_y)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit_rect,
-    NS(particle_real_t) const max_y )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRect_set_max_y)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT limit,
+    NS(particle_real_t) const max_y ) SIXTRL_NOEXCEPT
 {
-    if( limit_rect != SIXTRL_NULLPTR ) limit_rect->max_y = max_y;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->max_y = max_y;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_INLINE NS(arch_status_t) NS(LimitRect_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT source )
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* SIXTRL_RESTRICT dst,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
 {
-    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    if( ( destination != SIXTRL_NULLPTR ) &&
-        ( source != SIXTRL_NULLPTR ) && ( destination != source ) )
+    if( ( dst != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
     {
-        if( destination != source )
+        if( dst != src )
         {
-            destination->min_x = source->min_x;
-            destination->max_x = source->max_x;
-
-            destination->min_y = source->min_y;
-            destination->max_y = source->max_y;
+            status  = NS(LimitRect_set_min_x)( dst, NS(LimitRect_min_x)( src ) );
+            status |= NS(LimitRect_set_max_x)( dst, NS(LimitRect_max_x)( src ) );
+            status |= NS(LimitRect_set_min_y)( dst, NS(LimitRect_min_y)( src ) );
+            status |= NS(LimitRect_set_max_y)( dst, NS(LimitRect_max_y)( src ) );
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
         }
-
-        status = SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
     return status;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect) const*
-NS(BufferIndex_get_const_limit_rect)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const*
+NS(LimitRect_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT
 {
-    typedef NS(LimitRect) beam_element_t;
-    typedef SIXTRL_BUFFER_OBJ_DATAPTR_DEC beam_element_t const* ptr_to_be_t;
-    ptr_to_be_t ptr_to_be = SIXTRL_NULLPTR;
+    typedef SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const* ptr_limit_t;
+    ptr_limit_t elem = SIXTRL_NULLPTR;
 
     if( ( index_obj != SIXTRL_NULLPTR ) &&
         ( NS(Object_get_type_id)( index_obj ) == NS(OBJECT_TYPE_LIMIT_RECT) ) &&
-        ( NS(Object_get_size)( index_obj ) >= sizeof( beam_element_t ) ) )
+        ( NS(Object_get_size)( index_obj ) >= sizeof( NS(LimitRect) ) ) )
     {
-        ptr_to_be = ( ptr_to_be_t )( uintptr_t
-            )NS(Object_get_begin_addr)( index_obj );
+        elem = ( ptr_limit_t )( uintptr_t )NS(Object_get_begin_addr)(
+            index_obj );
     }
 
-    return ptr_to_be;
+    return elem;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)*
-NS(BufferIndex_get_limit_rect)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* NS(LimitRect_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT index_obj
+) SIXTRL_NOEXCEPT
 {
-    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)*
-        )NS(BufferIndex_get_const_limit_rect)( index_obj );
+    return ( SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
+        )NS(LimitRect_const_from_obj_index)( index_obj );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect) const*
-NS(BeamElements_managed_buffer_get_const_limit_rect)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const*
+NS(LimitRect_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_const_limit_rect)(
-        NS(ManagedBuffer_get_const_object)( pbuffer, be_index, slot_size ) );
+    return NS(LimitRect_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)*
-NS(BeamElements_managed_buffer_get_limit_rect)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRect)*
+NS(LimitRect_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_limit_rect)(
-        NS(ManagedBuffer_get_object)( pbuffer, be_index, slot_size ) );
+    return NS(LimitRect_from_obj_index)( NS(ManagedBuffer_get_object)(
+        buffer_begin, index, slot_size ) );
 }
 
 #if !defined( _GPUCODE )
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect) const*
-NS(BeamElements_buffer_get_const_limit_rect)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const*
+NS(LimitRect_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_const_limit_rect)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(LimitRect_const_from_obj_index)( NS(Buffer_get_const_object)(
+        buffer, index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRect)*
-NS(BeamElements_buffer_get_limit_rect)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRect)* NS(LimitRect_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_limit_rect)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(LimitRect_from_obj_index)( NS(Buffer_get_object)(
+        buffer, index ) );
 }
 
 #endif /* !defined( _GPUCODE ) */
-
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRL_COMMON_BE_LIMIT_RECT_C99_H__ */
-/*end: sixtracklib/common/be_/be_.h */
diff --git a/sixtracklib/common/be_limit/be_limit_rect.hpp b/sixtracklib/common/be_limit/be_limit_rect.hpp
index e6899c39..9b3c65ef 100644
--- a/sixtracklib/common/be_limit/be_limit_rect.hpp
+++ b/sixtracklib/common/be_limit/be_limit_rect.hpp
@@ -31,21 +31,20 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* ----------------------------------------------------------------- */
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MAX_X =
-             value_type{ SIXTRL_LIMIT_DEFAULT_MAX_X };
+        static constexpr value_type  DEFAULT_MIN_X =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_MIN_X );
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MIN_X =
-            value_type{ SIXTRL_LIMIT_DEFAULT_MIN_X };
+        static constexpr value_type  DEFAULT_MAX_X =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_MAX_X );
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MAX_Y =
-            value_type{ SIXTRL_LIMIT_DEFAULT_MAX_Y };
+        static constexpr value_type  DEFAULT_MIN_Y =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_MIN_Y );
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MIN_Y =
-            value_type{ SIXTRL_LIMIT_DEFAULT_MIN_Y };
+        static constexpr value_type  DEFAULT_MAX_Y =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_MAX_Y );
 
         /* ----------------------------------------------------------------- */
 
-
         SIXTRL_FN TLimitRect() = default;
 
         SIXTRL_FN TLimitRect( TLimitRect< T > const& other ) = default;
@@ -194,7 +193,7 @@ namespace SIXTRL_CXX_NAMESPACE
      * ====  Specialization TLimitRect< NS(particle_real_t) > :
      * ===================================================================== */
 
-    template<> struct TLimitRect< NS(particle_real_t) > :
+    template<> struct TLimitRect< ::NS(particle_real_t) > :
         public ::NS(LimitRect)
     {
         using value_type = ::NS(particle_real_t);
@@ -204,17 +203,17 @@ namespace SIXTRL_CXX_NAMESPACE
         using c_buffer_t = buffer_t::c_api_t;
         using c_api_t    = ::NS(LimitRect);
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MAX_X =
-             SIXTRL_CXX_NAMESPACE::LIMIT_DEFAULT_MAX_X;
+        static constexpr value_type  DEFAULT_MAX_X =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_MAX_X );
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type  DEFAULT_MIN_X =
-            SIXTRL_CXX_NAMESPACE::LIMIT_DEFAULT_MIN_X;
+        static constexpr value_type  DEFAULT_MIN_X =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_MIN_X );
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type DEFAULT_MAX_Y =
-            SIXTRL_CXX_NAMESPACE::LIMIT_DEFAULT_MAX_Y;
+        static constexpr value_type  DEFAULT_MIN_Y =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_MIN_Y );
 
-        static SIXTRL_CONSTEXPR_OR_CONST value_type DEFAULT_MIN_Y =
-            SIXTRL_CXX_NAMESPACE::LIMIT_DEFAULT_MIN_Y;
+        static constexpr value_type  DEFAULT_MAX_Y =
+            static_cast< value_type >( SIXTRL_LIMIT_DEFAULT_MAX_Y );
 
         /* ---------------------------------------------------------------- */
 
@@ -522,19 +521,18 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE typename TLimitRect< T >::size_type
     TLimitRect< T >::RequiredNumDataPtrs(
         typename TLimitRect< T >::buffer_t const&
-            SIXTRL_RESTRICT_REF buffer ) SIXTRL_NOEXCEPT
+            SIXTRL_RESTRICT_REF SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitRect_get_required_num_dataptrs)(
-            buffer.getCApiPtr(), nullptr );
+        return ::NS(LimitRect_num_dataptrs)( nullptr );
     }
 
     template< typename T >
     SIXTRL_INLINE typename TLimitRect< T >::size_type
     TLimitRect< T >::RequiredNumDataPtrs( SIXTRL_BUFFER_ARGPTR_DEC const
         typename TLimitRect< T >::c_buffer_t *const
-            SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+            SIXTRL_RESTRICT SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitRect_get_required_num_dataptrs)( ptr_buffer, nullptr );
+        return ::NS(LimitRect_num_dataptrs)( nullptr );
     }
 
     /* --------------------------------------------------------------------- */
@@ -788,18 +786,17 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     LimitRect::size_type LimitRect::RequiredNumDataPtrs(
-        LimitRect::buffer_t const& SIXTRL_RESTRICT_REF buffer ) SIXTRL_NOEXCEPT
+        LimitRect::buffer_t const& SIXTRL_RESTRICT_REF SIXTRL_UNUSED( buffer )
+            ) SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitRect_get_required_num_dataptrs)(
-            buffer.getCApiPtr(), nullptr );
+        return ::NS(LimitRect_num_dataptrs)( nullptr );
     }
 
     LimitRect::size_type LimitRect::RequiredNumDataPtrs(
         SIXTRL_BUFFER_ARGPTR_DEC const LimitRect::c_buffer_t *const
-            SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+            SIXTRL_RESTRICT SIXTRL_UNUSED( buffer ) ) SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitRect_get_required_num_dataptrs)(
-            ptr_buffer, nullptr );
+        return ::NS(LimitRect_num_dataptrs)( nullptr );
     }
 
     /* --------------------------------------------------------------------- */
@@ -818,22 +815,22 @@ namespace SIXTRL_CXX_NAMESPACE
 
     LimitRect::value_type LimitRect::getMinX() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitRect_get_min_x)( this->getCApiPtr() );
+        return ::NS(LimitRect_min_x)( this->getCApiPtr() );
     }
 
     LimitRect::value_type LimitRect::getMaxX() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitRect_get_max_x)( this->getCApiPtr() );
+        return ::NS(LimitRect_max_x)( this->getCApiPtr() );
     }
 
     LimitRect::value_type LimitRect::getMinY() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitRect_get_min_y)( this->getCApiPtr() );
+        return ::NS(LimitRect_min_y)( this->getCApiPtr() );
     }
 
     LimitRect::value_type LimitRect::getMaxY() const SIXTRL_NOEXCEPT
     {
-        return ::NS(LimitRect_get_max_y)( this->getCApiPtr() );
+        return ::NS(LimitRect_max_y)( this->getCApiPtr() );
     }
 
     /* --------------------------------------------------------------------- */
@@ -927,7 +924,4 @@ namespace SIXTRL_CXX_NAMESPACE
 }
 
 #endif /* __cplusplus */
-
 #endif /* SIXTRACKLIB_COMMON_BE_LIMIT_RECT_CXX_HPP__ */
-
-/* end: sixtracklib/common/be_limit/be_limit.hpp */
diff --git a/sixtracklib/common/be_limit/be_limit_rect_ellipse.c b/sixtracklib/common/be_limit/be_limit_rect_ellipse.c
index 5e941d2c..a926c411 100644
--- a/sixtracklib/common/be_limit/be_limit_rect_ellipse.c
+++ b/sixtracklib/common/be_limit/be_limit_rect_ellipse.c
@@ -10,200 +10,174 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/be_limit/definitions.h"
+    #include "sixtracklib/common/particles/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/control/definitions.h"
-    #include "sixtracklib/common/particles.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
     #include "sixtracklib/common/buffer.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
-SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse) const*
-NS(LimitRectEllipse_const_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC const
-    NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
-{
-    return NS(LimitRectEllipse_const_from_obj_index)(
-        NS(Buffer_get_const_object)( buffer, index ) );
-}
-
-SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
-NS(LimitRectEllipse_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
-    SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+NS(object_type_id_t) NS(LimitRectEllipse_type_id_ext)( void ) SIXTRL_NOEXCEPT
 {
-    return NS(LimitRectEllipse_from_obj_index)(
-        NS(Buffer_get_object)( buffer, index ) );
+    return NS(LimitRectEllipse_type_id)();
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 NS(arch_status_t) NS(LimitRectEllipse_attributes_offsets)(
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
     NS(buffer_size_t) const max_num_offsets,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
-        SIXTRL_RESTRICT limit,
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
     NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
     SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
-    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
 
-    if( ( offsets_begin != SIXTRL_NULLPTR ) && ( limit != SIXTRL_NULLPTR ) &&
-        ( slot_size > ZERO ) )
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ( buf_size_t )0u ) )
     {
-        status = NS(ARCH_STATUS_SUCCESS);
-
-        if( max_num_offsets > ZERO )
-        {
-            SIXTRACKLIB_SET_VALUES(
-                buf_size_t, offsets_begin, max_num_offsets, ZERO );
-        }
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
     }
 
-    return status;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
 NS(arch_status_t) NS(LimitRectEllipse_attributes_sizes)(
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
     NS(buffer_size_t) const max_num_sizes,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
-        SIXTRL_RESTRICT limit,
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
     NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
     SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
-    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
 
-    if( ( sizes_begin != SIXTRL_NULLPTR ) && ( limit != SIXTRL_NULLPTR ) &&
-        ( slot_size > ZERO ) )
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ( buf_size_t )0u ) )
     {
-        status = NS(ARCH_STATUS_SUCCESS);
-
-        if( max_num_sizes > ZERO )
-        {
-            SIXTRACKLIB_SET_VALUES(
-                buf_size_t, sizes_begin, max_num_sizes, ZERO );
-        }
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
     }
 
-    return status;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
 NS(arch_status_t) NS(LimitRectEllipse_attributes_counts)(
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
     NS(buffer_size_t) const max_num_counts,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
-        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
     SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
-    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
 
-    if( ( counts_begin != SIXTRL_NULLPTR ) && ( limit != SIXTRL_NULLPTR ) )
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_counts > ( buf_size_t )0u ) )
     {
-        status = NS(ARCH_STATUS_SUCCESS);
-
-        if( max_num_counts > ZERO )
-        {
-            SIXTRACKLIB_SET_VALUES(
-                buf_size_t, counts_begin, max_num_counts, ZERO );
-        }
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
     }
 
-    return status;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 bool NS(LimitRectEllipse_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_num_objs,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_num_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_num_dataptrs
-) SIXTRL_NOEXCEPT
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    bool can_be_added = false;
-
-    buf_size_t num_dataptrs = ( buf_size_t )0u;
-    NS(LimitRectEllipse) limit;
-    NS(LimitRectEllipse_preset)( &limit );
-
-    num_dataptrs = NS(LimitRectEllipse_num_dataptrs)( &limit );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )0u );
-
-    can_be_added = NS(Buffer_can_add_object)( buffer,
-        sizeof( NS(LimitRectEllipse) ), num_dataptrs,
-            SIXTRL_NULLPTR, SIXTRL_NULLPTR, ptr_requ_num_objs,
-                ptr_requ_num_slots, ptr_requ_num_dataptrs );
-
-    return can_be_added;
+    NS(LimitRectEllipse) temp;
+    NS(arch_status_t) const status = NS(LimitRectEllipse_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs =
+        NS(LimitRectEllipse_num_dataptrs)( &temp );
+    SIXTRL_ASSERT( ndataptrs == ( NS(buffer_size_t) )0u );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof(
+                   NS(LimitRectEllipse) ), ndataptrs, SIXTRL_NULLPTR,
+               SIXTRL_NULLPTR, requ_objects, requ_slots, requ_dataptrs ) ) );
 }
 
-SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
-NS(LimitRectEllipse_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
-    SIXTRL_RESTRICT buffer )
+SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* NS(LimitRectEllipse_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRectEllipse)* ptr_limit = SIXTRL_NULLPTR;
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* added_elem = SIXTRL_NULLPTR;
 
-    buf_size_t num_dataptrs = ( buf_size_t )0u;
+    NS(LimitRectEllipse) temp;
+    NS(arch_status_t) const status = NS(LimitRectEllipse_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(LimitRectEllipse_num_dataptrs)( &temp );
 
-    NS(LimitRectEllipse) limit;
-    NS(LimitRectEllipse_preset)( &limit );
-
-    num_dataptrs = NS(LimitRectEllipse_num_dataptrs)( &limit );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
-
-    ptr_limit = ( SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRectEllipse)* )(
-        uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
-            buffer, &limit, sizeof( limit ), NS(LimitRectEllipse_type_id)(
-                &limit ), num_dataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
-                    SIXTRL_NULLPTR ) );
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(LimitRectEllipse) ), NS(LimitRectEllipse_type_id)(),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
 
-    return ptr_limit;
+    return added_elem;
 }
 
 SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* NS(LimitRectEllipse_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(particle_real_t) const max_x, NS(particle_real_t) const max_y,
     NS(particle_real_t) const a_squ, NS(particle_real_t) const b_squ )
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRectEllipse)* ptr_limit = SIXTRL_NULLPTR;
-
-    buf_size_t num_dataptrs = ( buf_size_t )0u;
-    NS(LimitRectEllipse) limit;
-    NS(LimitRectEllipse_preset)( &limit );
-    NS(LimitRectEllipse_set_max_x)( &limit, max_x );
-    NS(LimitRectEllipse_set_max_y)( &limit, max_y );
-    NS(LimitRectEllipse_set_a_squ)( &limit, a_squ );
-    NS(LimitRectEllipse_set_b_squ)( &limit, b_squ );
-    NS(LimitRectEllipse_set_a_squ_b_squ)( &limit, a_squ * b_squ );
-
-    num_dataptrs = NS(LimitRectEllipse_num_dataptrs)( &limit );
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
-
-    ptr_limit = ( SIXTRL_BUFFER_DATAPTR_DEC NS(LimitRectEllipse)* )(
-        uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
-            buffer, &limit, sizeof( limit ),
-                NS(LimitRectEllipse_type_id)( &limit ), num_dataptrs,
-                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
-
-    return ptr_limit;
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) ndataptrs = ( NS(buffer_size_t) )0;
+
+    NS(LimitRectEllipse) temp;
+    NS(arch_status_t) status = NS(LimitRectEllipse_set_max_x)( &temp, max_x );
+    status |= NS(LimitRectEllipse_set_max_y)( &temp, max_y );
+    status |= NS(LimitRectEllipse_set_a_squ)( &temp, a_squ );
+    status |= NS(LimitRectEllipse_set_b_squ)( &temp, b_squ );
+    status |= NS(LimitRectEllipse_set_a_squ_b_squ)( &temp, a_squ * b_squ );
+    ndataptrs = NS(LimitRectEllipse_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( max_x >= ( NS(particle_real_t) )0 ) &&
+        ( max_y >= ( NS(particle_real_t) )0 ) &&
+        ( a_squ >= ( NS(particle_real_t) )0 ) &&
+        ( b_squ >= ( NS(particle_real_t) )0 ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(LimitRectEllipse) ), NS(LimitRectEllipse_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
 
-SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
-NS(LimitRectEllipse_add_copy)(
+SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* NS(LimitRectEllipse_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
-        SIXTRL_RESTRICT orig )
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT orig )
 {
-    return NS(LimitRectEllipse_add)( buffer,
-        NS(LimitRectEllipse_max_x)( orig ), NS(LimitRectEllipse_max_y)( orig ),
-        NS(LimitRectEllipse_a_squ)( orig ),
-        NS(LimitRectEllipse_b_squ)( orig ) );
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(LimitRectEllipse_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(LimitRectEllipse) ), NS(LimitRectEllipse_type_id)(),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
 }
diff --git a/sixtracklib/common/be_limit/be_limit_rect_ellipse.h b/sixtracklib/common/be_limit/be_limit_rect_ellipse.h
index 3c45d07a..1d7dbf98 100644
--- a/sixtracklib/common/be_limit/be_limit_rect_ellipse.h
+++ b/sixtracklib/common/be_limit/be_limit_rect_ellipse.h
@@ -9,16 +9,14 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/particles/definitions.h"
     #include "sixtracklib/common/be_limit/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
-    #include "sixtracklib/common/control/definitions.h"
-    #include "sixtracklib/common/particles.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
-    #if !defined( _GPUCODE )
-        #include "sixtracklib/common/buffer.h"
-    #endif /* !defined( _GPUCODE ) */
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -35,26 +33,27 @@ typedef struct NS(LimitRectEllipse)
 }
 NS(LimitRectEllipse);
 
+
 /* ------------------------------------------------------------------------- */
 
 SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
-NS(LimitRectEllipse_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit );
+NS(LimitRectEllipse_preset)( SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
+    SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(LimitRectEllipse_type_id)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
-        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(LimitRectEllipse_num_dataptrs)(
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(LimitRectEllipse_num_dataptrs)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
         SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(LimitRectEllipse_num_slots)(
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(LimitRectEllipse_num_slots)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT l,
     NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
@@ -90,31 +89,31 @@ SIXTRL_STATIC SIXTRL_FN NS(particle_real_t) NS(LimitRectEllipse_b)(
 
 /* ------------------------------------------------------------------------- */
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_set_max_x)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_set_max_x)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT l,
     NS(particle_real_t) const max_x ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_set_max_y)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_set_max_y)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT l,
     NS(particle_real_t) const max_y ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_set_a_squ)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_set_a_squ)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT l,
     NS(particle_real_t) const a_squ ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_set_b_squ)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_set_b_squ)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT l,
     NS(particle_real_t) const b_squ ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_set_a_squ_b_squ)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_set_a_squ_b_squ)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT l,
     NS(particle_real_t) const a_squ_b_squ ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_set_a)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_set_a)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT l,
     NS(particle_real_t) const a ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_set_b)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_set_b)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT l,
     NS(particle_real_t) const b ) SIXTRL_NOEXCEPT;
 
@@ -140,10 +139,9 @@ NS(LimitRectEllipse_from_managed_buffer)(
     NS(buffer_size_t) const index,
     NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
-NS(LimitRectEllipse_copy)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(LimitRectEllipse_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT dest,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
         SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
@@ -160,7 +158,7 @@ NS(LimitRectEllipse_from_buffer)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
         SIXTRL_RESTRICT buffer,
     NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(LimitRectEllipse_attributes_offsets)(
@@ -181,9 +179,10 @@ NS(LimitRectEllipse_attributes_counts)(
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
     NS(buffer_size_t) const max_num_counts,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
-        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT;
+        SIXTRL_RESTRICT limit,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(LimitRectEllipse_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
@@ -209,7 +208,6 @@ NS(LimitRectEllipse_add_copy)(
         SIXTRL_RESTRICT orig );
 
 #endif /* !defined( _GPUCODE ) */
-
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
@@ -226,77 +224,80 @@ NS(LimitRectEllipse_add_copy)(
     #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
 
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #if !defined( _GPUCODE )
+    #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
 SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
-NS(LimitRectEllipse_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit )
+NS(LimitRectEllipse_preset)( SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
+    SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR )
-    {
-        NS(LimitRectEllipse_clear)( limit );
-    }
-
+    if( limit != SIXTRL_NULLPTR ) NS(LimitRectEllipse_clear)( limit );
     return limit;
 }
 
-SIXTRL_INLINE void NS(LimitRectEllipse_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit )
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)*
+        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    NS(arch_status_t) status = NS(LimitRectEllipse_set_max_x)(
+        limit, ( NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_MAX_X );
 
-    limit->max_x = ( NS(particle_real_t) )1.0;
-    limit->max_y = ( NS(particle_real_t) )1.0;
+    status |= NS(LimitRectEllipse_set_max_y)(
+        limit, ( NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_MAX_Y );
 
-    limit->a_squ = ( NS(particle_real_t) )1.0;
-    limit->b_squ = ( NS(particle_real_t) )1.0;
+    status |= NS(LimitRectEllipse_set_a)(
+        limit, ( NS(particle_real_t) )SIXTRL_APERTURE_X_LIMIT );
 
-    limit->a_squ_b_squ = limit->a_squ * limit->b_squ;
-}
+    status |= NS(LimitRectEllipse_set_b)(
+        limit, ( NS(particle_real_t) )SIXTRL_APERTURE_Y_LIMIT );
 
-/* ------------------------------------------------------------------------- */
+    status |= NS(LimitRectEllipse_set_a_squ_b_squ)( limit,
+        NS(LimitRectEllipse_a_squ)( limit ) *
+        NS(LimitRectEllipse_b_squ)( limit ) );
 
-SIXTRL_INLINE NS(object_type_id_t) NS(LimitRectEllipse_type_id)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
-        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
-{
-    ( void )limit;
-    return NS(OBJECT_TYPE_LIMIT_RECT_ELLIPSE);
+    return status;
 }
 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE NS(object_type_id_t) NS(LimitRectEllipse_num_dataptrs)(
+SIXTRL_INLINE NS(buffer_size_t) NS(LimitRectEllipse_num_dataptrs)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
-        SIXTRL_RESTRICT limit ) SIXTRL_NOEXCEPT
+        SIXTRL_RESTRICT SIXTRL_UNUSED( limit ) ) SIXTRL_NOEXCEPT
 {
-    ( void )limit;
     return ( NS(buffer_size_t) )0u;
 }
 
-SIXTRL_INLINE NS(object_type_id_t) NS(LimitRectEllipse_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT limit,
+SIXTRL_INLINE NS(buffer_size_t) NS(LimitRectEllipse_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT
+        SIXTRL_UNUSED( limit ),
     NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    NS(buffer_size_t) const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(LimitRectEllipse) ), slot_size );
 
-    if( slot_size > ( NS(buffer_size_t) )0u )
-    {
-        NS(buffer_size_t) const extent =
-            NS(ManagedBuffer_get_slot_based_length)(
-                sizeof( NS(LimitRectEllipse) ), slot_size );
-
-        num_slots = ( extent / slot_size );
-        if( ( num_slots * slot_size ) < extent ) ++num_slots;
-        SIXTRL_ASSERT( ( num_slots * slot_size ) >= extent );
-    }
-
-    ( void )limit;
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
     return num_slots;
 }
 
-/* ------------------------------------------------------------------------- */
+SIXTRL_INLINE NS(object_type_id_t) NS(LimitRectEllipse_type_id)(
+    void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_LIMIT_RECT_ELLIPSE);
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_INLINE NS(particle_real_t) NS(LimitRectEllipse_max_x)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
@@ -347,7 +348,7 @@ SIXTRL_INLINE NS(particle_real_t) NS(LimitRectEllipse_a)(
     #endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
 
     SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( limit->a_squ >= ( NS(particle_real_t) )0.0 );
+    SIXTRL_ASSERT( limit->a_squ >= ( NS(particle_real_t) )0 );
     return sqrt( limit->a_squ );
 }
 
@@ -360,62 +361,76 @@ SIXTRL_INLINE NS(particle_real_t) NS(LimitRectEllipse_b)(
     #endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
 
     SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( limit->b_squ >= ( NS(particle_real_t) )0.0 );
+    SIXTRL_ASSERT( limit->b_squ >= ( NS(particle_real_t) )0 );
     return sqrt( limit->b_squ );
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE void NS(LimitRectEllipse_set_max_x)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_set_max_x)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const max_x ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR ) limit->max_x = max_x;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->max_x = max_x;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRectEllipse_set_max_y)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_set_max_y)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const max_y ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR ) limit->max_y = max_y;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->max_y = max_y;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRectEllipse_set_a_squ)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_set_a_squ)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const a_squ ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR ) limit->a_squ = a_squ;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->a_squ = a_squ;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRectEllipse_set_b_squ)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_set_b_squ)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const b_squ ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR ) limit->b_squ = b_squ;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->b_squ = b_squ;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRectEllipse_set_a_squ_b_squ)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_set_a_squ_b_squ)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const a_squ_b_squ ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR ) limit->a_squ_b_squ = a_squ_b_squ;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->a_squ_b_squ = a_squ_b_squ;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRectEllipse_set_a)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_set_a)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const a ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR ) limit->a_squ = a * a;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->a_squ = a * a;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(LimitRectEllipse_set_b)(
+SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_set_b)(
     SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT limit,
     NS(particle_real_t) const b ) SIXTRL_NOEXCEPT
 {
-    if( limit != SIXTRL_NULLPTR ) limit->b_squ = b * b;
+    SIXTRL_ASSERT( limit != SIXTRL_NULLPTR );
+    limit->b_squ = b * b;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse) const*
 NS(LimitRectEllipse_const_from_obj_index)(
@@ -457,32 +472,42 @@ NS(LimitRectEllipse_from_managed_buffer)(
         NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_INLINE NS(arch_status_t) NS(LimitRectEllipse_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT dest,
+    SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse)* SIXTRL_RESTRICT dst,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
         SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
 {
-    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    if( ( dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
+    if( ( dst != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
     {
-        if( dest != src )
+        if( dst != src )
         {
-            *dest = *src;
-        }
+            status  = NS(LimitRectEllipse_set_max_x)( dst,
+                        NS(LimitRectEllipse_max_x)( src ) );
+
+            status |= NS(LimitRectEllipse_set_max_y)( dst,
+                        NS(LimitRectEllipse_max_y)( src ) );
 
-        status = SIXTRL_ARCH_STATUS_SUCCESS;
+            status |= NS(LimitRectEllipse_set_a_squ)( dst,
+                        NS(LimitRectEllipse_a_squ)( src ) );
+
+            status |= NS(LimitRectEllipse_set_b_squ)( dst,
+                        NS(LimitRectEllipse_b_squ)( src ) );
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+        }
     }
 
     return status;
 }
 
-
-
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRACKLIB_COMMON_BE_LIMIT_BE_LIMIT_RECT_ELLIPSE_C99_H__ */
diff --git a/sixtracklib/common/be_limit/definitions.h b/sixtracklib/common/be_limit/definitions.h
index bc023d94..1625a727 100644
--- a/sixtracklib/common/be_limit/definitions.h
+++ b/sixtracklib/common/be_limit/definitions.h
@@ -33,6 +33,14 @@ extern "C" {
     #define SIXTRL_LIMIT_DEFAULT_MIN_Y -SIXTRL_APERTURE_Y_LIMIT
 #endif /* !defined( SIXTRL_LIMIT_DEFAULT_MIN_Y ) */
 
+#if !defined( SIXTRL_LIMIT_DEFAULT_X_HALF_AXIS )
+    #define SIXTRL_LIMIT_DEFAULT_X_HALF_AXIS SIXTRL_APERTURE_X_LIMIT
+#endif /* !defined( SIXTRL_LIMIT_DEFAULT_X_HALF_AXIS ) */
+
+#if !defined( SIXTRL_LIMIT_DEFAULT_Y_HALF_AXIS )
+    #define SIXTRL_LIMIT_DEFAULT_Y_HALF_AXIS SIXTRL_APERTURE_Y_LIMIT
+#endif /* !defined( SIXTRL_LIMIT_DEFAULT_Y_HALF_AXIS ) */
+
 #if !defined( _GPUCODE )
 
 SIXTRL_STATIC_VAR NS(particle_real_t) const NS(LIMIT_DEFAULT_MIN_X) = (
@@ -47,19 +55,20 @@ SIXTRL_STATIC_VAR NS(particle_real_t) const NS(LIMIT_DEFAULT_MIN_Y) = (
 SIXTRL_STATIC_VAR NS(particle_real_t) const NS(LIMIT_DEFAULT_MAX_Y) = (
     NS(particle_real_t) )SIXTRL_LIMIT_DEFAULT_MAX_Y;
 
-
 SIXTRL_STATIC_VAR NS(particle_real_t) const NS(LIMIT_DEFAULT_X_HALF_AXIS) =
-    ( NS(particle_real_t) )( 0.5 * (
-        SIXTRL_LIMIT_DEFAULT_MAX_X - SIXTRL_LIMIT_DEFAULT_MIN_X ) );
+    ( NS(particle_real_t) )( SIXTRL_LIMIT_DEFAULT_X_HALF_AXIS );
 
 SIXTRL_STATIC_VAR NS(particle_real_t) const NS(LIMIT_DEFAULT_Y_HALF_AXIS) =
-    ( NS(particle_real_t) )( 0.5 * (
-        SIXTRL_LIMIT_DEFAULT_MAX_Y - SIXTRL_LIMIT_DEFAULT_MIN_Y ) );
+    ( NS(particle_real_t) )( SIXTRL_LIMIT_DEFAULT_Y_HALF_AXIS );
 
 #endif /* !defined( _GPUCODE ) */
 
-#if defined( __cplusplus ) && !defined( _GPUCODE )
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
 
+#if defined( __cplusplus ) && !defined( _GPUCODE )
 namespace SIXTRL_CXX_NAMESPACE
 {
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST NS(particle_real_t)
@@ -78,21 +87,14 @@ namespace SIXTRL_CXX_NAMESPACE
         LIMIT_DEFAULT_MIN_Y = static_cast< NS(particle_real_t) >(
             SIXTRL_LIMIT_DEFAULT_MIN_Y );
 
-
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST NS(particle_real_t)
-        LIMIT_DEFAULT_X_HALF_AXIS = static_cast< NS(particle_real_t) >( 0.5 *
-            ( SIXTRL_LIMIT_DEFAULT_MAX_X - SIXTRL_LIMIT_DEFAULT_MIN_X ) );
+        LIMIT_DEFAULT_X_HALF_AXIS = static_cast< NS(particle_real_t) >(
+            SIXTRL_LIMIT_DEFAULT_X_HALF_AXIS );
 
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST NS(particle_real_t)
-        LIMIT_DEFAULT_Y_HALF_AXIS = static_cast< NS(particle_real_t) >( 0.5 *
-            ( SIXTRL_LIMIT_DEFAULT_MAX_Y - SIXTRL_LIMIT_DEFAULT_MIN_Y ) );
+        LIMIT_DEFAULT_Y_HALF_AXIS = static_cast< NS(particle_real_t) >(
+            SIXTRL_LIMIT_DEFAULT_Y_HALF_AXIS );
 }
-
 #endif /* C++, host */
 
-#if !defined(  _GPUCODE ) && defined( __cplusplus )
-}
-#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRACKLIB_COMMON_BE_LIMIT_DEFINTIONS_C99_H__ */
-/* end: sixtracklib/common/be_limit/definitions.h */
diff --git a/sixtracklib/common/be_limit/track.h b/sixtracklib/common/be_limit/track.h
index 3c70bac8..a52be7bc 100644
--- a/sixtracklib/common/be_limit/track.h
+++ b/sixtracklib/common/be_limit/track.h
@@ -60,17 +60,17 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_limit_global)(
 
     SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0;
 
-    #if defined( SIXTRL_APERTURE_X_LIMIT ) && defined( SIXTRL_APERTURE_Y_LIMIT )
-
+    #if defined( SIXTRL_APERTURE_X_LIMIT )
     SIXTRL_STATIC_VAR real_t const X_LIMIT = ( real_t )SIXTRL_APERTURE_X_LIMIT;
-    SIXTRL_STATIC_VAR real_t const Y_LIMIT = ( real_t )SIXTRL_APERTURE_Y_LIMIT;
-
-    #else /* SIXTRL_APERTURE_X_LIMIT && SIXTRL_APERTURE_Y_LIMIT  */
-
+    #else /* defined( SIXTRL_APERTURE_X_LIMIT )  */
     SIXTRL_STATIC_VAR real_t const X_LIMIT = ( real_t )1.0;
-    SIXTRL_STATIC_VAR real_t const Y_LIMIT = ( real_t )1.0;
+    #endif /* defined( SIXTRL_APERTURE_X_LIMIT ) */
 
-    #endif /* SIXTRL_APERTURE_X_LIMIT && SIXTRL_APERTURE_Y_LIMIT  */
+    #if defined( SIXTRL_APERTURE_Y_LIMIT )
+    SIXTRL_STATIC_VAR real_t const Y_LIMIT = ( real_t )SIXTRL_APERTURE_Y_LIMIT;
+    #else /* defined( SIXTRL_APERTURE_Y_LIMIT ) */
+    SIXTRL_STATIC_VAR real_t const Y_LIMIT = ( real_t )1.0;
+    #endif /* defined( SIXTRL_APERTURE_Y_LIMIT ) */
 
     index_t state = NS(Particles_get_state_value)( p, idx );
 
@@ -99,10 +99,10 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_limit_rect)(
     real_t const y = NS(Particles_get_y_value)( particles, particle_idx );
 
     index_t const new_state = ( index_t )(
-        ( x >= NS(LimitRect_get_min_x)( limit ) ) &&
-        ( x <= NS(LimitRect_get_max_x)( limit ) ) &&
-        ( y >= NS(LimitRect_get_min_y)( limit ) ) &&
-        ( y <= NS(LimitRect_get_max_y)( limit ) ) );
+        ( x >= NS(LimitRect_min_x)( limit ) ) &&
+        ( x <= NS(LimitRect_max_x)( limit ) ) &&
+        ( y >= NS(LimitRect_min_y)( limit ) ) &&
+        ( y <= NS(LimitRect_max_y)( limit ) ) );
 
     NS(Particles_update_state_value_if_not_already_lost)(
         particles, particle_idx, new_state );
@@ -122,16 +122,16 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_limit_ellipse)(
         particles, particle_idx );
 
     temp *= temp; /* temp = x² */
-    temp *= NS(LimitEllipse_get_y_half_axis_squ)( limit ); /* temp = x² * b² */
+    temp *= NS(LimitEllipse_y_half_axis_squ)( limit ); /* temp = x² * b² */
 
     y_squ *= y_squ; /* y_squ = y² */
-    y_squ *= NS(LimitEllipse_get_x_half_axis_squ)( limit ); /*y_squ = y² * a²*/
+    y_squ *= NS(LimitEllipse_x_half_axis_squ)( limit ); /*y_squ = y² * a²*/
 
     temp += y_squ; /* temp = x² * b² + y² * a² */
 
     NS(Particles_update_state_value_if_not_already_lost)( particles,
         particle_idx, ( NS(particle_index_t) )( temp <=
-            NS(LimitEllipse_get_half_axes_product_squ)( limit ) ) );
+            NS(LimitEllipse_half_axes_product_squ)( limit ) ) );
 
     return SIXTRL_TRACK_SUCCESS;
 }
diff --git a/sixtracklib/common/be_monitor/CMakeLists.txt b/sixtracklib/common/be_monitor/CMakeLists.txt
index 8c466fbc..06aa71c6 100644
--- a/sixtracklib/common/be_monitor/CMakeLists.txt
+++ b/sixtracklib/common/be_monitor/CMakeLists.txt
@@ -20,7 +20,8 @@ set_target_properties( sixtrack_common_be_monitor PROPERTIES LINKER_LANGUAGE C
     POSITION_INDEPENDENT_CODE ON C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_be_monitor PRIVATE
-    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_be_beambeam as a module for sixtracklib:
diff --git a/sixtracklib/common/be_monitor/be_monitor.c b/sixtracklib/common/be_monitor/be_monitor.c
index c18e4080..c261f314 100644
--- a/sixtracklib/common/be_monitor/be_monitor.c
+++ b/sixtracklib/common/be_monitor/be_monitor.c
@@ -13,52 +13,302 @@
     #include "sixtracklib/common/internal/objects_type_id.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
-int NS(BeamMonitor_insert_end_of_turn_monitors_at_pos)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT belements,
-    NS(be_monitor_turn_t) const turn_by_turn_start,
-    NS(be_monitor_turn_t) const num_turn_by_turn_turns,
-    NS(be_monitor_turn_t) const target_num_turns,
-    NS(be_monitor_turn_t) const skip_turns,
-    NS(buffer_size_t) const insert_at_index )
+NS(arch_status_t) NS(BeamMonitor_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( monitor ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    if( insert_at_index == ( NS(buffer_size_t) )0u )
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ( buf_size_t )0u ) )
     {
-        return NS(BeamMonitor_insert_end_of_turn_monitors)(
-            belements, turn_by_turn_start, num_turn_by_turn_turns,
-            target_num_turns, skip_turns, SIXTRL_NULLPTR );
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
     }
-    else if( insert_at_index <= NS(Buffer_get_num_of_objects)( belements ) )
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(BeamMonitor_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( monitor ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ( buf_size_t )0u ) )
     {
-        SIXTRL_BUFFER_ARGPTR_DEC NS(Object)* prev_node =
-            NS(Buffer_get_objects_begin)( belements );
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
 
-        SIXTRL_ASSERT( prev_node != SIXTRL_NULLPTR );
-        prev_node = prev_node + insert_at_index;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
 
-        return NS(BeamMonitor_insert_end_of_turn_monitors)(
-            belements, turn_by_turn_start, num_turn_by_turn_turns,
-            target_num_turns, skip_turns, prev_node );
+NS(arch_status_t) NS(BeamMonitor_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( monitor ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_counts > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
     }
 
-    return -1;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-int NS(BeamMonitor_insert_end_of_turn_monitors)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT belements,
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(object_type_id_t) NS(BeamMonitor_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_type_id)();
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(BeamMonitor_are_present_in_obj_index_range_ext)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_are_present_in_obj_index_range)( obj_begin, obj_end );
+}
+
+bool NS(BeamMonitor_are_present_in_managed_buffer_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_are_present_in_managed_buffer)(
+        buffer_begin, slot_size );
+}
+
+bool NS(BeamMonitor_are_present_in_buffer_ext)( SIXTRL_BUFFER_ARGPTR_DEC
+    const NS(Buffer) *const SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT
+{
+   return NS(BeamMonitor_are_present_in_buffer)( buffer );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(buffer_size_t) NS(BeamMonitor_num_monitors_in_obj_index_range_ext)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_num_monitors_in_obj_index_range)(
+        obj_begin, obj_end );
+}
+
+NS(buffer_size_t) NS(BeamMonitor_num_monitors_in_managed_buffer_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_num_monitors_in_managed_buffer)(
+        buffer_begin, slot_size );
+}
+
+NS(buffer_size_t) NS(BeamMonitor_num_monitors_in_buffer_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT
+        buffer ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_num_monitors_in_buffer)( buffer );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(buffer_size_t) NS(BeamMonitor_monitor_indices_from_obj_index_range_ext)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end,
+    NS(buffer_size_t) const start_index ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_monitor_indices_from_obj_index_range)(
+        indices_begin, max_num_of_indices, obj_begin, obj_end, start_index );
+}
+
+NS(buffer_size_t) NS(BeamMonitor_monitor_indices_from_managed_buffer_ext)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_monitor_indices_from_managed_buffer)( indices_begin,
+        max_num_of_indices, buffer_begin, slot_size );
+}
+
+NS(buffer_size_t) NS(BeamMonitor_monitor_indices_from_buffer_ext)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer
+) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_monitor_indices_from_buffer)(
+        indices_begin, max_num_of_indices, buffer );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(BeamMonitor_reset_ext)( SIXTRL_BE_ARGPTR_DEC
+    NS(BeamMonitor)* SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_reset)( monitor );
+}
+
+NS(arch_status_t) NS(BeamMonitor_reset_all_in_obj_index_range_ext)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_reset_all_in_obj_index_range)( obj_begin, obj_end );
+}
+
+NS(arch_status_t) NS(BeamMonitor_reset_all_in_managed_buffer_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_reset_all_in_managed_buffer)(
+        buffer_begin, slot_size );
+}
+
+NS(arch_status_t) NS(BeamMonitor_reset_all_in_buffer_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+        SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_reset_all_in_buffer)( buffer );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(BeamMonitor_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    NS(BeamMonitor) temp;
+    NS(arch_status_t) const status = NS(BeamMonitor_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(BeamMonitor_num_dataptrs)( &temp );
+    SIXTRL_ASSERT( ndataptrs == ( NS(buffer_size_t) )0u );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof( NS(BeamMonitor) ),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects,
+                    requ_slots, requ_dataptrs ) ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* NS(BeamMonitor_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* added_elem = SIXTRL_NULLPTR;
+
+    NS(BeamMonitor) temp;
+    NS(arch_status_t) const status = NS(BeamMonitor_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(BeamMonitor_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(BeamMonitor) ), NS(BeamMonitor_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* NS(BeamMonitor_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(be_monitor_turn_t) const num_stores, NS(be_monitor_turn_t) const start,
+    NS(be_monitor_turn_t) const skip,  NS(be_monitor_addr_t) const out_address,
+    NS(be_monitor_index_t) const min_particle_id,
+    NS(be_monitor_index_t) const max_particle_id,
+    bool const is_rolling, bool const is_turn_ordered )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) ndataptrs = ( NS(buffer_size_t) )0;
+
+    NS(BeamMonitor) temp;
+    NS(arch_status_t) status =
+        NS(BeamMonitor_set_num_stores)( &temp, num_stores );
+    status |= NS(BeamMonitor_set_start)( &temp, start );
+    status |= NS(BeamMonitor_set_skip)( &temp, skip );
+    status |= NS(BeamMonitor_set_out_address)( &temp, out_address );
+    status |= NS(BeamMonitor_set_min_particle_id)( &temp, min_particle_id );
+    status |= NS(BeamMonitor_set_max_particle_id)( &temp, max_particle_id );
+    status |= NS(BeamMonitor_set_is_rolling)( &temp, is_rolling );
+    status |= NS(BeamMonitor_set_is_turn_ordered)( &temp, is_turn_ordered );
+    ndataptrs = NS(BeamMonitor_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(BeamMonitor) ), NS(BeamMonitor_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* NS(BeamMonitor_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(BeamMonitor_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(BeamMonitor) ), NS(BeamMonitor_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(BeamMonitor_insert_end_of_turn_monitors)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(be_monitor_turn_t) const turn_by_turn_start,
     NS(be_monitor_turn_t) const num_turn_by_turn_turns,
     NS(be_monitor_turn_t) const target_num_turns,
     NS(be_monitor_turn_t) const skip_turns,
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT prev_node )
 {
-    typedef SIXTRL_BUFFER_ARGPTR_DEC NS(Object)*        ptr_obj_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*  ptr_beam_monitor_t;
-    typedef NS(be_monitor_turn_t)                       nturn_t;
+    typedef SIXTRL_BUFFER_ARGPTR_DEC NS(Object)* ptr_obj_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)* ptr_beam_monitor_t;
+    typedef NS(be_monitor_turn_t) nturn_t;
 
-    int success = -1;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    ptr_obj_t idx_begin = NS(Buffer_get_objects_begin)( belements );
-    ptr_obj_t idx_end   = NS(Buffer_get_objects_end)( belements );
+    ptr_obj_t idx_begin = NS(Buffer_get_objects_begin)( buffer );
+    ptr_obj_t idx_end   = NS(Buffer_get_objects_end)( buffer );
 
     SIXTRL_STATIC_VAR nturn_t const ONE_TURN = ( nturn_t )1u;
     SIXTRL_STATIC_VAR nturn_t const ZERO     = ( nturn_t )0u;
@@ -68,13 +318,10 @@ int NS(BeamMonitor_insert_end_of_turn_monitors)(
      * is to add the beam monitors to the end.
      * Thus, if the prev_node != idx_end, we can currently not perform the
      * action and return false immediately. */
-    if( prev_node != idx_end )
-    {
-        return success;
-    }
+    if( prev_node != idx_end ) return status;
 
-    if( ( belements != SIXTRL_NULLPTR ) &&
-        ( idx_begin != SIXTRL_NULLPTR ) && ( idx_end != SIXTRL_NULLPTR ) &&
+    if( ( buffer  != SIXTRL_NULLPTR ) && ( idx_begin != SIXTRL_NULLPTR ) &&
+        ( idx_end != SIXTRL_NULLPTR ) &&
         ( ( intptr_t )( idx_end - idx_begin ) >= ( intptr_t )0 ) &&
         ( ( prev_node == SIXTRL_NULLPTR ) ||
           ( ( ( intptr_t )( prev_node - idx_begin ) >= ( intptr_t )0 ) &&
@@ -83,7 +330,7 @@ int NS(BeamMonitor_insert_end_of_turn_monitors)(
         nturn_t const output_turn_start =
             turn_by_turn_start + num_turn_by_turn_turns;
 
-        success = 0;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 
         if( num_turn_by_turn_turns > ZERO )
         {
@@ -96,7 +343,7 @@ int NS(BeamMonitor_insert_end_of_turn_monitors)(
              */
             SIXTRL_ASSERT( prev_node == idx_end );
 
-            ptr_beam_monitor_t mon = NS(BeamMonitor_new)( belements );
+            ptr_beam_monitor_t mon = NS(BeamMonitor_new)( buffer );
             if( mon != SIXTRL_NULLPTR )
             {
                 NS(BeamMonitor_set_num_stores)( mon, num_turn_by_turn_turns );
@@ -104,13 +351,14 @@ int NS(BeamMonitor_insert_end_of_turn_monitors)(
                 NS(BeamMonitor_set_skip)( mon, ONE_TURN );
                 NS(BeamMonitor_set_is_rolling)( mon, false );
 
-                idx_begin = NS(Buffer_get_objects_begin)( belements );
-                idx_end   = NS(Buffer_get_objects_end)( belements );
+                idx_begin = NS(Buffer_get_objects_begin)( buffer );
+                idx_end   = NS(Buffer_get_objects_end)( buffer );
                 prev_node = idx_begin + ( offset + ( uintptr_t )1u );
             }
             else
             {
-                success = -1;
+                status = ( NS(arch_status_t)
+                    )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
             }
         }
 
@@ -123,17 +371,13 @@ int NS(BeamMonitor_insert_end_of_turn_monitors)(
              */
             SIXTRL_ASSERT( prev_node == idx_end );
 
-            ptr_beam_monitor_t mon = NS(BeamMonitor_new)( belements );
+            ptr_beam_monitor_t mon = NS(BeamMonitor_new)( buffer );
             if( mon != SIXTRL_NULLPTR )
             {
                 nturn_t skip = skip_turns;
                 nturn_t num_stores = target_num_turns - output_turn_start;
 
-                if( skip < ONE_TURN )
-                {
-                    skip = ONE_TURN;
-                }
-
+                if( skip < ONE_TURN ) skip = ONE_TURN;
                 if( skip > ONE_TURN )
                 {
                     nturn_t const remainder = num_stores % skip;
@@ -149,12 +393,44 @@ int NS(BeamMonitor_insert_end_of_turn_monitors)(
             }
             else
             {
-                success = -1;
+                status = ( NS(arch_status_t)
+                    )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
             }
         }
     }
 
-    return success;
+    return status;
 }
 
-/* end: sixtracklib/common/be_monitor/be_monitor.c */
+NS(arch_status_t) NS(BeamMonitor_insert_end_of_turn_monitors_at_pos)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT belements,
+    NS(be_monitor_turn_t) const turn_by_turn_start,
+    NS(be_monitor_turn_t) const num_turn_by_turn_turns,
+    NS(be_monitor_turn_t) const target_num_turns,
+    NS(be_monitor_turn_t) const skip_turns,
+    NS(buffer_size_t) const insert_at_index )
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( insert_at_index == ( NS(buffer_size_t) )0u )
+    {
+        status = NS(BeamMonitor_insert_end_of_turn_monitors)(
+            belements, turn_by_turn_start, num_turn_by_turn_turns,
+            target_num_turns, skip_turns, SIXTRL_NULLPTR );
+    }
+    else if( insert_at_index <= NS(Buffer_get_num_of_objects)( belements ) )
+    {
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Object)* prev_node =
+            NS(Buffer_get_objects_begin)( belements );
+
+        SIXTRL_ASSERT( prev_node != SIXTRL_NULLPTR );
+        prev_node = prev_node + insert_at_index;
+
+        status = NS(BeamMonitor_insert_end_of_turn_monitors)(
+            belements, turn_by_turn_start, num_turn_by_turn_turns,
+            target_num_turns, skip_turns, prev_node );
+    }
+
+    return status;
+}
diff --git a/sixtracklib/common/be_monitor/be_monitor.h b/sixtracklib/common/be_monitor/be_monitor.h
index fb0c37de..2a74cee0 100644
--- a/sixtracklib/common/be_monitor/be_monitor.h
+++ b/sixtracklib/common/be_monitor/be_monitor.h
@@ -10,7 +10,9 @@
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/particles/definitions.h"
     #include "sixtracklib/common/control/debug_register.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/buffer_object_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
@@ -44,207 +46,376 @@ typedef struct NS(BeamMonitor)
 NS(BeamMonitor);
 
 /* ------------------------------------------------------------------------- */
-/* Helper functions: */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(BeamMonitor_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+NS(BeamMonitor_preset)( SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+    SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(BeamMonitor_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT
+        monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
-NS(BeamMonitor_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor);
-
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_clear)(
-    SIXTRL_BE_ARGPTR_DEC  NS(BeamMonitor)* SIXTRL_RESTRICT monitor );
-
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_clear_all_line_obj)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* be_begin,
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* be_end );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC NS(arch_status_t) NS(BeamMonitor_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT source );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamMonitor_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(BeamMonitor_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT rhs );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamMonitor_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(BeamMonitor_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(BeamMonitor_type_id)(
+    void ) SIXTRL_NOEXCEPT;
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* getter accessor functions: */
-
-SIXTRL_FN SIXTRL_STATIC NS(be_monitor_turn_t)
-NS(BeamMonitor_get_num_stores)( SIXTRL_BE_ARGPTR_DEC const
-    NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
 
-SIXTRL_FN SIXTRL_STATIC NS(be_monitor_turn_t)
-NS(BeamMonitor_get_start)( SIXTRL_BE_ARGPTR_DEC const
-    NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN NS(be_monitor_turn_t) NS(BeamMonitor_num_stores)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(be_monitor_turn_t)
-NS(BeamMonitor_get_skip)( SIXTRL_BE_ARGPTR_DEC const
-    NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN NS(be_monitor_turn_t) NS(BeamMonitor_start)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC bool NS(BeamMonitor_is_rolling)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN NS(be_monitor_turn_t) NS(BeamMonitor_skip)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC bool NS(BeamMonitor_is_turn_ordered)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN bool NS(BeamMonitor_is_rolling)( SIXTRL_BE_ARGPTR_DEC
+    const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC bool NS(BeamMonitor_is_particle_ordered)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN bool NS(BeamMonitor_is_turn_ordered)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(be_monitor_addr_t)
-NS(BeamMonitor_get_out_address)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN bool NS(BeamMonitor_is_particle_ordered)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(be_monitor_index_t)
-NS(BeamMonitor_get_min_particle_id)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN NS(be_monitor_addr_t) NS(BeamMonitor_out_address)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(be_monitor_index_t)
-NS(BeamMonitor_get_max_particle_id)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN NS(be_monitor_index_t) NS(BeamMonitor_min_particle_id)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t)
-NS(BeamMonitor_get_stored_num_particles)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+SIXTRL_STATIC SIXTRL_FN NS(be_monitor_index_t) NS(BeamMonitor_max_particle_id)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* accessor functions for retrieving already dumped data */
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BeamMonitor_stored_num_particles)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC bool NS(BeamMonitor_has_turn_stored)(
+SIXTRL_STATIC SIXTRL_FN bool NS(BeamMonitor_has_turn_stored)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor,
     NS(be_monitor_turn_t) const turn_id,
-    NS(be_monitor_turn_t) const max_num_turns );
+    NS(be_monitor_turn_t) const max_num_turns ) SIXTRL_NOEXCEPT;
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* setter accessor functions: */
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_num_stores)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_set_num_stores)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_turn_t) const num_stores );
+    NS(be_monitor_turn_t) const num_stores ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_start)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_set_start)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_turn_t) const start );
+    NS(be_monitor_turn_t) const start )SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_skip)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_set_skip)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_turn_t) const skip );
+    NS(be_monitor_turn_t) const skip ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_is_rolling)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_set_is_rolling)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    bool const is_rolling );
+    bool const is_rolling ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_is_turn_ordered)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_set_is_turn_ordered)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    bool const is_turn_ordered );
+    bool const is_turn_ordered ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_is_particle_ordered)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(BeamMonitor_set_is_particle_ordered)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    bool const is_particle_ordered );
+    bool const is_particle_ordered ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_out_address)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_set_out_address)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_addr_t) const out_address );
+    NS(be_monitor_addr_t) const out_address ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_min_particle_id)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_set_min_particle_id)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_index_t) const min_particle_id );
+    NS(be_monitor_index_t) const min_particle_id ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_set_max_particle_id)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_set_max_particle_id)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_index_t) const min_particle_id );
+    NS(be_monitor_index_t) const min_particle_id ) SIXTRL_NOEXCEPT;
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Buffer management functions: */
 
-SIXTRL_FN SIXTRL_STATIC NS(arch_status_t)
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT destination,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT source ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
 NS(BeamMonitor_get_beam_monitor_indices_from_managed_buffer)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
     NS(buffer_size_t) const max_num_of_indices,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_be_monitors,
-    NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(arch_status_t)
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
 NS(BeamMonitor_get_beam_monitor_indices_from_index_range)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* index_begin,
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* index_end,
     NS(buffer_size_t) const start_index,
     NS(buffer_size_t) const max_num_of_indices,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_be_monitors );
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_num_be_monitors )SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor) const*
-NS(BufferIndex_get_const_beam_monitor)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const*
+NS(BeamMonitor_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-NS(BufferIndex_get_beam_monitor)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+NS(BeamMonitor_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor) const*
-NS(BeamElements_managed_buffer_get_const_beam_monitor)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const*
+NS(BeamMonitor_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-NS(BeamElements_managed_buffer_get_beam_monitor)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+NS(BeamMonitor_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN bool NS(BeamMonitor_are_present_in_obj_index_range)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(BeamMonitor_are_present_in_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BeamMonitor_num_monitors_in_obj_index_range)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BeamMonitor_num_monitors_in_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BeamMonitor_monitor_indices_from_obj_index_range)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end,
+    NS(buffer_size_t) const start_index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BeamMonitor_monitor_indices_from_managed_buffer)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(BeamMonitor_reset)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(BeamMonitor_reset_all_in_obj_index_range)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(BeamMonitor_reset_all_in_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor) const*
-NS(BeamElements_buffer_get_const_beam_monitor)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const*
+NS(BeamMonitor_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-NS(BeamElements_buffer_get_beam_monitor)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+NS(BeamMonitor_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC bool
-NS(BeamMonitor_are_present_in_buffer)( SIXTRL_BUFFER_ARGPTR_DEC const
-        NS(Buffer) *const SIXTRL_RESTRICT belements_buffer );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t)
-NS(BeamMonitor_get_num_of_beam_monitor_objects)( SIXTRL_BUFFER_ARGPTR_DEC const
-        NS(Buffer) *const SIXTRL_RESTRICT belements_buffer );
+SIXTRL_STATIC SIXTRL_FN bool NS(BeamMonitor_are_present_in_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const
+        SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(arch_status_t)
-NS(BeamMonitor_get_beam_monitor_indices_from_buffer)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BeamMonitor_num_monitors_in_buffer)( SIXTRL_BUFFER_ARGPTR_DEC const
+    NS(Buffer) *const SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BeamMonitor_monitor_indices_from_buffer)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(BeamMonitor_reset_all_in_buffer)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(BeamMonitor_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(BeamMonitor_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(BeamMonitor_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(BeamMonitor_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool
+NS(BeamMonitor_are_present_in_obj_index_range_ext)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool
+NS(BeamMonitor_are_present_in_managed_buffer_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(BeamMonitor_are_present_in_buffer_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const
+        SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BeamMonitor_num_monitors_in_obj_index_range_ext)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BeamMonitor_num_monitors_in_managed_buffer_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BeamMonitor_num_monitors_in_buffer_ext)( SIXTRL_BUFFER_ARGPTR_DEC const
+    NS(Buffer) *const SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BeamMonitor_monitor_indices_from_obj_index_range_ext)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
     NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end,
+    NS(buffer_size_t) const start_index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BeamMonitor_monitor_indices_from_managed_buffer_ext)(
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_be_monitors );
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BeamMonitor_monitor_indices_from_buffer_ext)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer
+) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_clear_all)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT belements_buffer );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(BeamMonitor_reset_ext)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(BeamMonitor_reset_all_in_obj_index_range_ext)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj_begin,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(BeamMonitor_reset_all_in_managed_buffer_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC bool NS(BeamMonitor_can_be_added)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(BeamMonitor_reset_all_in_buffer_ext)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(BeamMonitor_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-NS(BeamMonitor_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+NS(BeamMonitor_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
 NS(BeamMonitor_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(be_monitor_turn_t) const num_stores, NS(be_monitor_turn_t) const start,
@@ -253,10 +424,13 @@ NS(BeamMonitor_add)(
     NS(be_monitor_index_t) const max_particle_id,
     bool const is_rolling, bool const is_turn_ordered );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
 NS(BeamMonitor_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor );
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(BeamMonitor_insert_end_of_turn_monitors)(
@@ -278,23 +452,6 @@ NS(BeamMonitor_insert_end_of_turn_monitors_at_pos)(
 
 #endif /* !defined( _GPUCODE ) */
 
-/* ------------------------------------------------------------------------- */
-
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t)
-NS(BeamMonitor_get_num_of_beam_monitor_objects_from_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT
-        blements_buffer, NS(buffer_size_t) const slot_size );
-
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_clear_all_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT
-        beam_elements_buffer, NS(buffer_size_t) const slot_size );
-
-SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_clear_all_on_managed_buffer_debug)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT
-        beam_elements_buffer,
-    NS(buffer_size_t) const slot_size,
-    SIXTRL_ARGPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags );
-
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
@@ -313,407 +470,168 @@ SIXTRL_FN SIXTRL_STATIC void NS(BeamMonitor_clear_all_on_managed_buffer_debug)(
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Helper functions: */
-
-SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* NS(BeamMonitor_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT
+        monitor ) SIXTRL_NOEXCEPT
 {
-    return ( NS(buffer_size_t) )0u;
-}
-
-SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor,
-    NS(buffer_size_t) const slot_size )
-{
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(BeamMonitor)   beam_element_t;
-
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
-
-    ( void )monitor;
-
-    buf_size_t extent = NS(ManagedBuffer_get_slot_based_length)(
-        sizeof( beam_element_t ), slot_size );
-
-    SIXTRL_ASSERT( ( slot_size == ZERO ) || ( ( extent % slot_size ) == ZERO ) );
-    return ( slot_size > ZERO ) ? ( extent / slot_size ) : ( ZERO );
-}
-
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
-NS(BeamMonitor_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor)
-{
-    if( monitor != SIXTRL_NULLPTR )
-    {
-        NS(BeamMonitor_set_num_stores)( monitor, 0u );
-        NS(BeamMonitor_set_start)( monitor, 0u );
-        NS(BeamMonitor_set_skip)(  monitor, 1u );
-        NS(BeamMonitor_set_is_rolling)( monitor, false );
-        NS(BeamMonitor_set_is_turn_ordered)( monitor, true );
-        NS(BeamMonitor_clear)( monitor );
-    }
-
+    if( monitor != SIXTRL_NULLPTR ) NS(BeamMonitor_clear)( monitor );
     return monitor;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_clear)(
-    SIXTRL_BE_ARGPTR_DEC  NS(BeamMonitor)* SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_clear)( SIXTRL_BE_ARGPTR_DEC
+    NS(BeamMonitor)* SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
-    NS(BeamMonitor_set_out_address)( monitor, ( NS(buffer_addr_t) )0 );
-    NS(BeamMonitor_set_min_particle_id)( monitor, ( NS(be_monitor_index_t) )0 );
-    NS(BeamMonitor_set_max_particle_id)( monitor, ( NS(be_monitor_index_t) )0 );
-
-    return;
-}
-
-SIXTRL_INLINE void NS(BeamMonitor_clear_all_line_obj)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* be_it,
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* be_end )
-{
-    SIXTRL_ASSERT( be_it  != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( be_end != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ( ( ( uintptr_t )be_it ) <= ( ( uintptr_t )be_end ) ) );
-
-    for( ; be_it != be_end ; ++be_it )
-    {
-        if( NS(Object_get_type_id)( be_it ) == NS(OBJECT_TYPE_BEAM_MONITOR) )
-        {
-            SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* beam_monitor =
-                ( SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* )( uintptr_t
-                    )NS(Object_get_begin_addr)( be_it );
+    NS(arch_status_t) status = NS(BeamMonitor_set_num_stores)( monitor, 0 );
+    status |= NS(BeamMonitor_set_start)( monitor, 0 );
+    status |= NS(BeamMonitor_set_skip)( monitor, 1 );
+    status |= NS(BeamMonitor_set_is_rolling)( monitor, false );
+    status |= NS(BeamMonitor_set_is_turn_ordered)( monitor, true );
 
-            SIXTRL_ASSERT( NS(Object_get_size)( be_it ) >=
-                           sizeof( NS(BeamMonitor ) ) );
+    status |= NS(BeamMonitor_set_out_address)(
+        monitor, ( NS(be_monitor_addr_t) )0 );
 
-            SIXTRL_ASSERT( beam_monitor != SIXTRL_NULLPTR );
+    status |= NS(BeamMonitor_set_min_particle_id)(
+        monitor, ( NS(be_monitor_index_t) )-1 );
 
-            NS(BeamMonitor_clear)( beam_monitor );
-        }
-    }
+    status |= NS(BeamMonitor_set_max_particle_id)(
+        monitor, ( NS(be_monitor_index_t) )-1 );
 
-    return;
+    return status;
 }
 
-SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT source )
-{
-    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
-
-    if( ( destination != SIXTRL_NULLPTR ) &&
-        ( source != SIXTRL_NULLPTR ) )
-    {
-        NS(BeamMonitor_set_num_stores)(destination,
-             NS(BeamMonitor_get_num_stores)( source ) );
-
-        NS(BeamMonitor_set_start)(destination,
-             NS(BeamMonitor_get_start)( source ) );
-
-        NS(BeamMonitor_set_skip)( destination,
-             NS(BeamMonitor_get_skip)(  source ) );
-
-        NS(BeamMonitor_set_out_address)( destination,
-            NS(BeamMonitor_get_out_address)( source ) );
-
-        NS(BeamMonitor_set_is_rolling)( destination,
-             NS(BeamMonitor_is_rolling)( source ) );
-
-        NS(BeamMonitor_set_is_turn_ordered)( destination,
-            NS(BeamMonitor_is_turn_ordered)( source ) );
-
-        NS(BeamMonitor_set_min_particle_id)( destination,
-            NS(BeamMonitor_get_min_particle_id)( source ) );
-
-        NS(BeamMonitor_set_max_particle_id)( destination,
-            NS(BeamMonitor_get_max_particle_id)( source ) );
-
-        status = SIXTRL_ARCH_STATUS_SUCCESS;
-    }
-
-    return status;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( monitor ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0u;
 }
 
-SIXTRL_INLINE int NS(BeamMonitor_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT rhs )
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT
+        SIXTRL_UNUSED( monitor ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(be_monitor_turn_t)   nturn_t;
-    typedef NS(be_monitor_index_t)  index_t;
-    typedef NS(be_monitor_addr_t)   addr_t;
-
-    int compare_value = -1;
-
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
-    {
-        if( NS(BeamMonitor_get_num_stores)( lhs ) ==
-            NS(BeamMonitor_get_num_stores)( rhs ) )
-        {
-            compare_value = 0;
-        }
-        else if( NS(BeamMonitor_get_num_stores)( lhs ) >
-                 NS(BeamMonitor_get_num_stores)( rhs ) )
-        {
-            compare_value = +1;
-        }
-        else if( NS(BeamMonitor_get_num_stores)( lhs ) <
-                 NS(BeamMonitor_get_num_stores)( rhs ) )
-        {
-            compare_value = -1;
-        }
-
-        if( compare_value == 0 )
-        {
-            nturn_t const lhs_value = NS(BeamMonitor_get_start)( lhs );
-            nturn_t const rhs_value = NS(BeamMonitor_get_start)( rhs );
-
-            if( lhs_value != rhs_value )
-            {
-                if( lhs_value > rhs_value )
-                {
-                    compare_value = +1;
-                }
-                else if( lhs_value < rhs_value )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            nturn_t const lhs_value = NS(BeamMonitor_get_skip)( lhs );
-            nturn_t const rhs_value = NS(BeamMonitor_get_skip)( rhs );
-
-            if( lhs_value != rhs_value )
-            {
-                if( lhs_value > rhs_value )
-                {
-                    compare_value = +1;
-                }
-                else if( lhs_value < rhs_value )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            addr_t const lhs_addr = NS(BeamMonitor_get_out_address)( lhs );
-            addr_t const rhs_addr = NS(BeamMonitor_get_out_address)( rhs );
-
-            if( lhs_addr != rhs_addr )
-            {
-                if( lhs_addr > rhs_addr )
-                {
-                    compare_value = +1;
-                }
-                else if( lhs_addr < rhs_addr )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            index_t const lhs_value = NS(BeamMonitor_get_min_particle_id)( lhs );
-            index_t const rhs_value = NS(BeamMonitor_get_min_particle_id)( rhs );
-
-            if( lhs_value != rhs_value )
-            {
-                if( lhs_value > rhs_value )
-                {
-                    compare_value = +1;
-                }
-                else if( lhs_value < rhs_value )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            index_t const lhs_value = NS(BeamMonitor_get_max_particle_id)( lhs );
-            index_t const rhs_value = NS(BeamMonitor_get_max_particle_id)( rhs );
-
-            if( lhs_value != rhs_value )
-            {
-                if( lhs_value > rhs_value )
-                {
-                    compare_value = +1;
-                }
-                else if( lhs_value < rhs_value )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            if( lhs->is_rolling != rhs->is_rolling )
-            {
-                if( lhs->is_rolling > rhs->is_rolling )
-                {
-                    compare_value = +1;
-                }
-                else if( lhs->is_rolling < rhs->is_rolling )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            if( lhs->is_turn_ordered != rhs->is_turn_ordered )
-            {
-                if( lhs->is_turn_ordered > rhs->is_turn_ordered )
-                {
-                    compare_value = +1;
-                }
-                else if( lhs->is_turn_ordered < rhs->is_turn_ordered )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-    }
-    else if( lhs != SIXTRL_NULLPTR )
-    {
-        compare_value = +1;
-    }
-
-    return compare_value;
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    NS(buffer_size_t) const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(BeamMonitor) ), slot_size );
+
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
+    return num_slots;
 }
 
-SIXTRL_INLINE int NS(BeamMonitor_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
+SIXTRL_INLINE NS(object_type_id_t)
+    NS(BeamMonitor_type_id)( void ) SIXTRL_NOEXCEPT
 {
-    ( void )treshold;
-    return NS(BeamMonitor_compare_values)( lhs, rhs );
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_BEAM_MONITOR);
 }
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* getter accessor functions: */
 
-SIXTRL_INLINE NS(be_monitor_turn_t)
-NS(BeamMonitor_get_num_stores)( SIXTRL_BE_ARGPTR_DEC const
-    NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE NS(be_monitor_turn_t) NS(BeamMonitor_num_stores)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
     return monitor->num_stores;
 }
 
-SIXTRL_INLINE NS(be_monitor_turn_t)
-NS(BeamMonitor_get_start)( SIXTRL_BE_ARGPTR_DEC const
-    NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE NS(be_monitor_turn_t) NS(BeamMonitor_start)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
     return monitor->start;
 }
 
-SIXTRL_INLINE NS(be_monitor_turn_t)
-NS(BeamMonitor_get_skip)( SIXTRL_BE_ARGPTR_DEC const
-    NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE NS(be_monitor_turn_t) NS(BeamMonitor_skip)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
     return monitor->skip;
 }
 
-SIXTRL_INLINE bool NS(BeamMonitor_is_rolling)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE bool NS(BeamMonitor_is_rolling)( SIXTRL_BE_ARGPTR_DEC const
+    NS(BeamMonitor) *const SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
-    return ( monitor->is_rolling == 1 );
+    return ( monitor->is_rolling == ( NS(be_monitor_flag_t) )1 );
 }
 
-SIXTRL_INLINE bool NS(BeamMonitor_is_turn_ordered)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE bool NS(BeamMonitor_is_turn_ordered)( SIXTRL_BE_ARGPTR_DEC const
+    NS(BeamMonitor) *const SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
-    return ( monitor->is_turn_ordered == 1 );
+    return ( monitor->is_turn_ordered == ( NS(be_monitor_flag_t) )1 );
 }
 
-SIXTRL_INLINE bool NS(BeamMonitor_is_particle_ordered)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE bool NS(BeamMonitor_is_particle_ordered)( SIXTRL_BE_ARGPTR_DEC
+    const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     return !NS(BeamMonitor_is_turn_ordered)( monitor );
 }
 
-SIXTRL_INLINE NS(be_monitor_addr_t)
-NS(BeamMonitor_get_out_address)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE NS(be_monitor_addr_t) NS(BeamMonitor_out_address)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
     return monitor->out_address;
 }
 
-SIXTRL_INLINE NS(be_monitor_index_t)
-NS(BeamMonitor_get_min_particle_id)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE NS(be_monitor_index_t) NS(BeamMonitor_min_particle_id)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
     return monitor->min_particle_id;
 }
 
-SIXTRL_INLINE NS(be_monitor_index_t)
-NS(BeamMonitor_get_max_particle_id)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE NS(be_monitor_index_t) NS(BeamMonitor_max_particle_id)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( monitor->max_particle_id >= monitor->min_particle_id );
     return monitor->max_particle_id;
 }
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(BeamMonitor_get_stored_num_particles)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_stored_num_particles)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)       size_t;
-    typedef NS(be_monitor_index_t)  index_t;
+    typedef NS(buffer_size_t) size_t;
+    typedef NS(be_monitor_index_t) index_t;
 
     size_t required_num_particles = ( size_t )0u;
-
-    index_t const min_particle_id =
-        NS(BeamMonitor_get_min_particle_id)( monitor );
-
-    index_t const max_particle_id =
-        NS(BeamMonitor_get_max_particle_id)( monitor );
+    index_t const min_particle_id = NS(BeamMonitor_min_particle_id)( monitor );
+    index_t const max_particle_id = NS(BeamMonitor_max_particle_id)( monitor );
 
     if( ( min_particle_id >= ( index_t )0u ) &&
         ( max_particle_id >= min_particle_id ) )
     {
         required_num_particles = ( size_t )(
             max_particle_id - min_particle_id + ( size_t )1u );
-
-        required_num_particles *= NS(BeamMonitor_get_num_stores)( monitor );
+        required_num_particles *= NS(BeamMonitor_num_stores)( monitor );
     }
 
     return required_num_particles;
 }
 
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* accessor functions for retrieving already dumped data */
-
 SIXTRL_INLINE bool NS(BeamMonitor_has_turn_stored)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor,
     NS(be_monitor_turn_t) const turn_id,
-    NS(be_monitor_turn_t) const max_num_turns )
+    NS(be_monitor_turn_t) const max_num_turns ) SIXTRL_NOEXCEPT
 {
     bool is_stored = false;
-
     typedef NS(be_monitor_turn_t) nturn_t;
 
-    nturn_t const num_stores = NS(BeamMonitor_get_num_stores)( monitor );
-    nturn_t const start_turn = NS(BeamMonitor_get_start)( monitor );
-    nturn_t const skip_turns = NS(BeamMonitor_get_skip)( monitor );
+    nturn_t const num_stores = NS(BeamMonitor_num_stores)( monitor );
+    nturn_t const start_turn = NS(BeamMonitor_start)( monitor );
+    nturn_t const skip_turns = NS(BeamMonitor_skip)( monitor );
 
     if( ( monitor != SIXTRL_NULLPTR ) && ( start_turn >= ( nturn_t )0u ) &&
         ( start_turn <= turn_id ) && ( num_stores > ( nturn_t )0u ) &&
@@ -755,86 +673,139 @@ SIXTRL_INLINE bool NS(BeamMonitor_has_turn_stored)(
 }
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* setter accessor functions: */
 
-SIXTRL_INLINE void NS(BeamMonitor_set_num_stores)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_num_stores)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_turn_t) const num_stores )
+    NS(be_monitor_turn_t) const num_stores ) SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR ) monitor->num_stores = num_stores;
-    return;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->num_stores = num_stores;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_set_start)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_start)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_turn_t) const start )
+    NS(be_monitor_turn_t) const start )SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR ) monitor->start = start;
-    return;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->start = start;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_set_skip)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_skip)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_turn_t) const skip )
+    NS(be_monitor_turn_t) const skip ) SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR ) monitor->skip = skip;
-    return;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->skip = skip;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_set_is_rolling)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_is_rolling)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    bool const is_rolling )
+    bool const is_rolling ) SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR )
-        monitor->is_rolling = ( is_rolling ) ? 1 : 0;
-    return;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->is_rolling = ( is_rolling )
+        ? ( NS(be_monitor_flag_t) )1 : ( NS(be_monitor_flag_t) )0;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_set_is_turn_ordered)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_is_turn_ordered)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    bool const is_turn_ordered )
+    bool const is_turn_ordered ) SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR )
-        monitor->is_turn_ordered = ( is_turn_ordered ) ? 1 : 0;
-
-    return;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->is_turn_ordered = ( is_turn_ordered )
+        ? ( NS(be_monitor_flag_t) )1 : ( NS(be_monitor_flag_t) )0;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_set_is_particle_ordered)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_is_particle_ordered)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    bool const is_particle_ordered )
+    bool const is_particle_ordered ) SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR )
-        monitor->is_turn_ordered = ( is_particle_ordered ) ? 0 : 1;
-
-    return;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->is_turn_ordered = ( is_particle_ordered )
+        ? ( NS(be_monitor_flag_t) )0 : ( NS(be_monitor_flag_t) )1;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_set_out_address)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_out_address)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_addr_t) const out_address )
+    NS(be_monitor_addr_t) const out_address ) SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR ) monitor->out_address = out_address;
-    return;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->out_address = out_address;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_set_min_particle_id)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_min_particle_id)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_index_t) const min_particle_id )
+    NS(be_monitor_index_t) const min_particle_id ) SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR ) monitor->min_particle_id = min_particle_id;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->min_particle_id = min_particle_id;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_set_max_particle_id)(
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_set_max_particle_id)(
     SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT monitor,
-    NS(be_monitor_index_t) const max_particle_id )
+    NS(be_monitor_index_t) const max_particle_id ) SIXTRL_NOEXCEPT
 {
-    if( monitor != SIXTRL_NULLPTR ) monitor->max_particle_id = max_particle_id;
+    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
+    monitor->max_particle_id = max_particle_id;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Buffer management functions: */
 
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* SIXTRL_RESTRICT dst,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( dst != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
+    {
+        if( dst != src )
+        {
+            status  = NS(BeamMonitor_set_num_stores)(
+                dst, NS(BeamMonitor_num_stores)( src ) );
+
+            status |= NS(BeamMonitor_set_start)(
+                dst, NS(BeamMonitor_start)( src ) );
+
+            status |= NS(BeamMonitor_set_skip)(
+                dst, NS(BeamMonitor_skip)( src ) );
+
+            status |= NS(BeamMonitor_set_out_address)(
+                dst, NS(BeamMonitor_out_address)( src ) );
+
+            status |= NS(BeamMonitor_set_max_particle_id)(
+                dst, NS(BeamMonitor_max_particle_id)( src ) );
+
+            status |= NS(BeamMonitor_set_min_particle_id)(
+                dst, NS(BeamMonitor_min_particle_id)( src ) );
+
+            status |= NS(BeamMonitor_set_is_rolling)(
+                dst, NS(BeamMonitor_is_rolling)( src ) );
+
+            status |= NS(BeamMonitor_set_is_turn_ordered)(
+                dst, NS(BeamMonitor_is_turn_ordered)( src ) );
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
 SIXTRL_INLINE NS(arch_status_t)
 NS(BeamMonitor_get_beam_monitor_indices_from_managed_buffer)(
@@ -842,21 +813,22 @@ NS(BeamMonitor_get_beam_monitor_indices_from_managed_buffer)(
     NS(buffer_size_t) const max_num_of_indices,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_be_monitors,
-    NS(buffer_size_t) const slot_s )
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
-
     NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
     SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
 
-    if( ( buffer != SIXTRL_NULLPTR ) && ( slot_s > ZERO ) &&
-        ( !NS(ManagedBuffer_needs_remapping)( buffer, slot_s ) ) &&
-        ( NS(ManagedBuffer_get_num_objects)( buffer, slot_s ) > ZERO ) )
+    if( ( buffer != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( !NS(ManagedBuffer_needs_remapping)( buffer, slot_size ) ) &&
+        ( NS(ManagedBuffer_get_num_objects)( buffer, slot_size ) > ZERO ) )
     {
         status = NS(BeamMonitor_get_beam_monitor_indices_from_index_range)(
-            NS(ManagedBuffer_get_const_objects_index_begin)( buffer, slot_s ),
-            NS(ManagedBuffer_get_const_objects_index_end)( buffer, slot_s ),
-            ZERO, max_num_of_indices, indices_begin, ptr_num_be_monitors );
+            NS(ManagedBuffer_get_const_objects_index_begin)(
+                buffer, slot_size ),
+            NS(ManagedBuffer_get_const_objects_index_end)(
+                buffer, slot_size ), ZERO, max_num_of_indices, indices_begin,
+                    ptr_num_be_monitors );
     }
 
     return status;
@@ -864,12 +836,13 @@ NS(BeamMonitor_get_beam_monitor_indices_from_managed_buffer)(
 
 SIXTRL_INLINE NS(arch_status_t)
 NS(BeamMonitor_get_beam_monitor_indices_from_index_range)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* index_it,
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* index_end,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_it,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end,
     NS(buffer_size_t) const start_index,
     NS(buffer_size_t) const max_num_of_indices,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_be_monitors )
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_num_be_monitors ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t)    buf_size_t;
     typedef NS(buffer_addr_t)    address_t;
@@ -882,8 +855,8 @@ NS(BeamMonitor_get_beam_monitor_indices_from_index_range)(
     SIXTRL_STATIC_VAR address_t  const ZERO_ADDR = ( address_t )0u;
     buf_size_t num_be_monitors = ZERO;
 
-    if( ( index_it != SIXTRL_NULLPTR ) && ( index_end != SIXTRL_NULLPTR ) &&
-        ( ( ( uintptr_t )index_end ) >= ( ( uintptr_t )index_it ) ) &&
+    if( ( obj_it != SIXTRL_NULLPTR ) && ( obj_end != SIXTRL_NULLPTR ) &&
+        ( ( ( uintptr_t )obj_end ) >= ( ( uintptr_t )obj_it ) ) &&
         ( max_num_of_indices > ZERO ) &&
         ( indices_begin != SIXTRL_NULLPTR ) )
     {
@@ -892,14 +865,14 @@ NS(BeamMonitor_get_beam_monitor_indices_from_index_range)(
         status = SIXTRL_ARCH_STATUS_SUCCESS;
 
         while( ( num_be_monitors < max_num_of_indices ) &&
-               ( index_it != index_end ) )
+               ( obj_it != obj_end ) )
         {
-            obj_type_t const type_id = NS(Object_get_type_id)( index_it );
-            address_t const addr = NS(Object_get_begin_addr)( index_it );
+            obj_type_t const type_id = NS(Object_get_type_id)( obj_it );
+            address_t const addr = NS(Object_get_begin_addr)( obj_it );
 
             if( ( type_id == NS(OBJECT_TYPE_BEAM_MONITOR ) ) &&
                 ( addr > ZERO_ADDR ) &&
-                ( NS(Object_get_size)( index_it ) >= MON_SIZE ) )
+                ( NS(Object_get_size)( obj_it ) >= MON_SIZE ) )
             {
                 ptr_be_monitor_t mon = ( ptr_be_monitor_t )( uintptr_t )addr;
 
@@ -915,13 +888,12 @@ NS(BeamMonitor_get_beam_monitor_indices_from_index_range)(
             }
 
             ++next_index;
-            ++index_it;
+            ++obj_it;
         }
     }
 
     if( ( status == SIXTRL_ARCH_STATUS_SUCCESS ) &&
-        ( num_be_monitors == max_num_of_indices ) &&
-        ( index_it != index_end ) )
+        ( num_be_monitors == max_num_of_indices ) && ( obj_it != obj_end ) )
     {
         status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
     }
@@ -934,406 +906,301 @@ NS(BeamMonitor_get_beam_monitor_indices_from_index_range)(
     return status;
 }
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor) const*
-NS(BufferIndex_get_const_beam_monitor)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const*
+NS(BeamMonitor_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
 {
-    typedef NS(BeamMonitor) beam_element_t;
-    typedef SIXTRL_BUFFER_OBJ_DATAPTR_DEC beam_element_t const* ptr_to_be_t;
-    ptr_to_be_t ptr_to_be = SIXTRL_NULLPTR;
+    typedef SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const* ptr_elem_t;
+    ptr_elem_t elem = SIXTRL_NULLPTR;
 
-    if( ( index_obj != SIXTRL_NULLPTR ) &&
-        ( NS(Object_get_type_id)( index_obj ) == NS(OBJECT_TYPE_BEAM_MONITOR) ) &&
-        ( NS(Object_get_size)( index_obj ) >= sizeof( beam_element_t ) ) )
+    if( ( obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_BEAM_MONITOR) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(BeamMonitor) ) ) )
     {
-        ptr_to_be = ( ptr_to_be_t )( uintptr_t
-            )NS(Object_get_begin_addr)( index_obj );
+        elem = ( ptr_elem_t )( uintptr_t )NS(Object_get_begin_addr)( obj );
     }
 
-    return ptr_to_be;
+    return elem;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-NS(BufferIndex_get_beam_monitor)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+NS(BeamMonitor_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
 {
-    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-        )NS(BufferIndex_get_const_beam_monitor)( index_obj );
+    return ( SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+        )NS(BeamMonitor_const_from_obj_index)( obj );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor) const*
-NS(BeamElements_managed_buffer_get_const_beam_monitor)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
-{
-    return NS(BufferIndex_get_const_beam_monitor)(
-        NS(ManagedBuffer_get_const_object)( pbuffer, be_index, slot_size ) );
-}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-NS(BeamElements_managed_buffer_get_beam_monitor)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const*
+NS(BeamMonitor_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BufferIndex_get_beam_monitor)(
-        NS(ManagedBuffer_get_object)( pbuffer, be_index, slot_size ) );
+    return NS(BeamMonitor_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
 }
 
-#if !defined( _GPUCODE )
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor) const*
-NS(BeamElements_buffer_get_const_beam_monitor)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*
+NS(BeamMonitor_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_const_beam_monitor)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return NS(BeamMonitor_from_obj_index)( NS(ManagedBuffer_get_object)(
+        buffer_begin, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-NS(BeamElements_buffer_get_beam_monitor)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
-{
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_beam_monitor)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
-}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE bool NS(BeamMonitor_are_present_in_buffer)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT
-        beam_elements_buffer )
+SIXTRL_INLINE bool NS(BeamMonitor_are_present_in_obj_index_range)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_it,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT
 {
-    bool beam_monitors_are_present = false;
-
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* obj_it =
-        NS(Buffer_get_const_objects_begin)( beam_elements_buffer );
+    bool are_available = false;
 
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* obj_end =
-        NS(Buffer_get_const_objects_end)( beam_elements_buffer );
-
-    for( ; obj_it != obj_end ; ++obj_it )
+    if( ( obj_it != SIXTRL_NULLPTR ) && ( obj_end != SIXTRL_NULLPTR ) )
     {
-        if( ( NS(Object_get_type_id)( obj_it ) ==
-                NS(OBJECT_TYPE_BEAM_MONITOR ) ) &&
-            ( ( uintptr_t )NS(Object_get_begin_addr)( obj_it ) !=
-              ( uintptr_t )0u ) )
-        {
-            typedef SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const* ptr_monitor_t;
-            typedef NS(be_monitor_turn_t) nturn_t;
+        SIXTRL_ASSERT( ( ( uintptr_t )( obj_it ) ) <= ( uintptr_t )obj_end );
 
-            ptr_monitor_t monitor = ( ptr_monitor_t
-                )( uintptr_t )NS(Object_get_begin_addr)( obj_it );
-
-            if( ( monitor != SIXTRL_NULLPTR ) &&
-                ( NS(BeamMonitor_get_num_stores)( monitor ) > ( nturn_t )0u ) )
+        for( ; obj_it != obj_end ; ++obj_it )
+        {
+            if( ( NS(Object_get_type_id)( obj_it ) ==
+                  NS(OBJECT_TYPE_BEAM_MONITOR) ) &&
+                ( NS(BeamMonitor_const_from_obj_index)( obj_it ) !=
+                  SIXTRL_NULLPTR ) )
             {
-                beam_monitors_are_present = true;
+                are_available = true;
                 break;
             }
         }
     }
 
-    return beam_monitors_are_present;
+    return are_available;
 }
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(BeamMonitor_get_num_of_beam_monitor_objects)( SIXTRL_BUFFER_ARGPTR_DEC const
-        NS(Buffer) *const SIXTRL_RESTRICT beam_elements_buffer )
-{
-    return NS(BeamMonitor_get_num_of_beam_monitor_objects_from_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( beam_elements_buffer ),
-        NS(Buffer_get_slot_size)( beam_elements_buffer ) );
-}
-
-SIXTRL_INLINE NS(arch_status_t)
-NS(BeamMonitor_get_beam_monitor_indices_from_buffer)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const max_num_of_indices,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_be_monitors )
-{
-    return NS(BeamMonitor_get_beam_monitor_indices_from_managed_buffer)(
-        NS(Buffer_get_const_data_begin)( buffer ),
-        max_num_of_indices, indices_begin, ptr_num_be_monitors,
-        NS(Buffer_get_slot_size)( buffer ) );
-}
-
-SIXTRL_INLINE void NS(BeamMonitor_clear_all)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT beam_elements_buffer )
-{
-    NS(BeamMonitor_clear_all_on_managed_buffer)(
-        NS(Buffer_get_data_begin)( beam_elements_buffer),
-        NS(Buffer_get_slot_size)( beam_elements_buffer ) );
-
-    return;
-}
-
-
-SIXTRL_INLINE bool NS(BeamMonitor_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs )
-{
-    typedef NS(buffer_size_t) buf_size_t;
-
-    buf_size_t const num_dataptrs =
-        NS(BeamMonitor_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes  = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts = SIXTRL_NULLPTR;
-
-    return NS(Buffer_can_add_object)( buffer, sizeof( NS(BeamMonitor) ),
-        num_dataptrs, sizes, counts, requ_objects, requ_slots, requ_dataptrs );
-}
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)* NS(BeamMonitor_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
-{
-    typedef NS(buffer_size_t)                       buf_size_t;
-    typedef NS(BeamMonitor)                         elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC   elem_t*     ptr_elem_t;
-    typedef NS(be_monitor_turn_t)                   nturn_t;
-    typedef NS(be_monitor_flag_t)                   flag_t;
-    typedef NS(be_monitor_addr_t)                   addr_t;
-
-    buf_size_t const num_dataptrs =
-        NS(BeamMonitor_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.num_stores        = ( nturn_t )0u;
-    temp_obj.start             = ( nturn_t )0u;
-    temp_obj.skip              = ( nturn_t )1u;
-    temp_obj.out_address       = ( addr_t )0u;
-    temp_obj.min_particle_id   = ( NS(be_monitor_index_t) )0u;
-    temp_obj.max_particle_id   = ( NS(be_monitor_index_t) )0u;
-    temp_obj.is_rolling        = ( flag_t )0;
-    temp_obj.is_turn_ordered   = ( flag_t )1;
-
-    return ( ptr_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( temp_obj ),
-        NS(OBJECT_TYPE_BEAM_MONITOR), num_dataptrs, offsets, sizes, counts ) );
-}
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)* NS(BeamMonitor_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(be_monitor_turn_t) const num_stores, NS(be_monitor_turn_t) const start,
-    NS(be_monitor_turn_t) const skip,  NS(be_monitor_addr_t) const out_address,
-    NS(be_monitor_index_t) const min_particle_id,
-    NS(be_monitor_index_t) const max_particle_id,
-    bool const is_rolling, bool const is_turn_ordered )
-{
-    typedef NS(BeamMonitor) elem_t;
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC elem_t* ptr_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(BeamMonitor_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.num_stores        = num_stores;
-    temp_obj.start             = start;
-    temp_obj.skip              = skip;
-    temp_obj.out_address       = out_address;
-    temp_obj.min_particle_id   = min_particle_id;
-    temp_obj.max_particle_id   = max_particle_id;
-    temp_obj.is_rolling        = ( is_rolling      ) ? 1 : 0;
-    temp_obj.is_turn_ordered   = ( is_turn_ordered ) ? 1 : 0;
-
-    return ( ptr_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( temp_obj ),
-        NS(OBJECT_TYPE_BEAM_MONITOR), num_dataptrs, offsets, sizes, counts ) );
-}
-
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BeamMonitor)*
-NS(BeamMonitor_add_copy)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
+SIXTRL_INLINE bool NS(BeamMonitor_are_present_in_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    return NS(BeamMonitor_add)( buffer,
-        NS(BeamMonitor_get_num_stores)( monitor ),
-        NS(BeamMonitor_get_start)( monitor ),
-        NS(BeamMonitor_get_skip)( monitor ),
-        NS(BeamMonitor_get_out_address)( monitor ),
-        NS(BeamMonitor_get_min_particle_id)( monitor ),
-        NS(BeamMonitor_get_max_particle_id)( monitor ),
-        NS(BeamMonitor_is_rolling)( monitor ),
-        NS(BeamMonitor_is_turn_ordered)( monitor ) );
+    return NS(BeamMonitor_are_present_in_obj_index_range)(
+        NS(ManagedBuffer_get_const_objects_index_begin)( buffer, slot_size ),
+        NS(ManagedBuffer_get_const_objects_index_end)( buffer, slot_size ) );
 }
 
-#endif /* !defined( _GPUCODE ) */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE NS(buffer_size_t)
-NS(BeamMonitor_get_num_of_beam_monitor_objects_from_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const*
-        SIXTRL_RESTRICT beam_elements, NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_num_monitors_in_obj_index_range)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_it,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end
+) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* ptr_obj_t;
-
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
-    buf_size_t num_beam_monitors = ZERO;
+    NS(buffer_size_t) num_be_monitors = ( NS(buffer_size_t) )0u;
 
-    if( ( beam_elements != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
-        ( NS(ManagedBuffer_get_num_objects)(
-            beam_elements, slot_size ) ) > ZERO )
+    if( ( obj_it != SIXTRL_NULLPTR ) && ( obj_end != SIXTRL_NULLPTR ) )
     {
-        ptr_obj_t be_it  = NS(ManagedBuffer_get_const_objects_index_begin)(
-            beam_elements, slot_size );
+        SIXTRL_ASSERT( ( ( uintptr_t )( obj_it ) ) <= ( uintptr_t )obj_end );
 
-        ptr_obj_t be_end = NS(ManagedBuffer_get_const_objects_index_end)(
-            beam_elements, slot_size );
-
-        for( ; be_it != be_end ; ++be_it )
+        for( ; obj_it != obj_end ; ++obj_it )
         {
-            NS(object_type_id_t) const type_id =
-                NS(Object_get_type_id)( be_it );
-
-            if( ( type_id == NS(OBJECT_TYPE_BEAM_MONITOR) ) &&
-                ( NS(Object_get_const_begin_ptr)( be_it ) !=
-                    SIXTRL_NULLPTR ) &&
-                ( NS(Object_get_size)( be_it ) >= sizeof( NS(BeamMonitor) ) ) )
+            if( ( NS(Object_get_type_id)( obj_it ) ==
+                  NS(OBJECT_TYPE_BEAM_MONITOR) ) &&
+                ( NS(BeamMonitor_const_from_obj_index)( obj_it ) !=
+                  SIXTRL_NULLPTR ) )
             {
-                ++num_beam_monitors;
+                ++num_be_monitors;
             }
         }
     }
 
-    return num_beam_monitors;
+    return num_be_monitors;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_clear_all_on_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT beam_elements,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_num_monitors_in_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* ptr_obj_t;
-    typedef SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* ptr_beam_monitor_t;
+    return NS(BeamMonitor_num_monitors_in_obj_index_range)(
+        NS(ManagedBuffer_get_const_objects_index_begin)( buffer, slot_size ),
+        NS(ManagedBuffer_get_const_objects_index_end)( buffer, slot_size ) );
+}
 
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    if( ( beam_elements != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
-        ( NS(ManagedBuffer_get_num_objects)(
-            beam_elements, slot_size ) ) > ZERO )
+SIXTRL_INLINE NS(buffer_size_t)
+NS(BeamMonitor_monitor_indices_from_obj_index_range)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_it,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT obj_end,
+    NS(buffer_size_t) const start_index ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_be_monitors = ( NS(buffer_size_t) )0;
+    if( ( obj_it != SIXTRL_NULLPTR ) && ( obj_end != SIXTRL_NULLPTR ) &&
+        ( indices_begin != SIXTRL_NULLPTR ) &&
+        ( max_num_of_indices > ( NS(buffer_size_t) )0 ) )
     {
-        ptr_obj_t be_it  = NS(ManagedBuffer_get_objects_index_begin)(
-            beam_elements, slot_size );
-
-        ptr_obj_t be_end = NS(ManagedBuffer_get_objects_index_end)(
-            beam_elements, slot_size );
+        NS(buffer_size_t) be_index = start_index;
+        SIXTRL_ASSERT( ( ( uintptr_t )obj_it ) <= ( uintptr_t )obj_end );
 
-        for( ; be_it != be_end ; ++be_it )
+        for( ; obj_it != obj_end ; ++obj_it, ++be_index )
         {
-            NS(object_type_id_t) const type_id =
-                NS(Object_get_type_id)( be_it );
-
-            if( type_id == NS(OBJECT_TYPE_BEAM_MONITOR) )
+            if( ( NS(Object_get_type_id)( obj_it ) ==
+                  NS(OBJECT_TYPE_BEAM_MONITOR) ) &&
+                ( NS(BeamMonitor_const_from_obj_index)( obj_it ) !=
+                  SIXTRL_NULLPTR ) )
             {
-                ptr_beam_monitor_t monitor = ( ptr_beam_monitor_t
-                    )NS(Object_get_begin_ptr)( be_it );
-
-                if( monitor != SIXTRL_NULLPTR )
+                if( num_be_monitors < max_num_of_indices )
                 {
-                    NS(BeamMonitor_clear)( monitor );
+                    indices_begin[ num_be_monitors ] = be_index;
                 }
+
+                ++num_be_monitors;
             }
         }
     }
 
-    return;
+    return num_be_monitors;
 }
 
-SIXTRL_INLINE void NS(BeamMonitor_clear_all_on_managed_buffer_debug)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT beam_elements,
-    NS(buffer_size_t) const slot_size,
-    SIXTRL_ARGPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags )
+SIXTRL_INLINE NS(buffer_size_t)
+NS(BeamMonitor_monitor_indices_from_managed_buffer)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* ptr_obj_t;
-    typedef SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* ptr_beam_monitor_t;
+    return NS(BeamMonitor_monitor_indices_from_obj_index_range)( indices_begin,
+        max_num_of_indices,
+        NS(ManagedBuffer_get_const_objects_index_begin)( buffer, slot_size ),
+        NS(ManagedBuffer_get_const_objects_index_end)( buffer, slot_size ),
+        ( NS(buffer_size_t) )0 );
+}
 
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    NS(arch_debugging_t) flags = SIXTRL_ARCH_DEBUGGING_MIN_FLAG;
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_reset)( SIXTRL_BE_ARGPTR_DEC
+    NS(BeamMonitor)* SIXTRL_RESTRICT monitor ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    NS(arch_debugging_t) const BELEM_BUFFER_NULL_FLAG           = flags;
-    NS(arch_debugging_t) const SLOT_SIZE_ILLEGAL_FLAG           = flags <<  1u;
-    NS(arch_debugging_t) const BELEM_BUFFER_REQUIRES_REMAP_FLAG = flags <<  2u;
-    NS(arch_debugging_t) const BELEM_BUFFER_EMPTY_FLAG          = flags <<  3u;
+    if( monitor != SIXTRL_NULLPTR )
+    {
+        status = NS(BeamMonitor_set_out_address)(
+            monitor, ( NS(be_monitor_addr_t) )0 );
 
-    flags = ( NS(arch_debugging_t) )0u;
+        status |= NS(BeamMonitor_set_min_particle_id)(
+            monitor, ( NS(be_monitor_index_t) )-1 );
 
-    if( ( beam_elements != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
-        ( NS(ManagedBuffer_get_num_objects)(
-            beam_elements, slot_size ) ) > ZERO )
-    {
-        ptr_obj_t be_it  = NS(ManagedBuffer_get_objects_index_begin)(
-            beam_elements, slot_size );
+        status |= NS(BeamMonitor_set_max_particle_id)(
+            monitor, ( NS(be_monitor_index_t) )-1 );
+    }
 
-        ptr_obj_t be_end = NS(ManagedBuffer_get_objects_index_end)(
-            beam_elements, slot_size );
+    return status;
+}
 
-        for( ; be_it != be_end ; ++be_it )
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_reset_all_in_obj_index_range)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj_it,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+        SIXTRL_RESTRICT obj_end ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    if( ( obj_it != SIXTRL_NULLPTR ) && ( obj_end != SIXTRL_NULLPTR ) )
+    {
+        SIXTRL_ASSERT( ( ( uintptr_t )obj_it ) <= ( uintptr_t )obj_end );
+        for( ; obj_it != obj_end ; ++obj_it )
         {
-            NS(object_type_id_t) const type_id =
-                NS(Object_get_type_id)( be_it );
-
-            if( type_id == NS(OBJECT_TYPE_BEAM_MONITOR) )
+            if( NS(Object_get_type_id)( obj_it ) ==
+                NS(OBJECT_TYPE_BEAM_MONITOR) )
             {
-                ptr_beam_monitor_t monitor = ( ptr_beam_monitor_t
-                    )NS(Object_get_begin_ptr)( be_it );
+                SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* be_monitor =
+                    NS(BeamMonitor_from_obj_index)( obj_it );
 
-                if( monitor != SIXTRL_NULLPTR )
-                {
-                    NS(BeamMonitor_clear)( monitor );
-                }
+                SIXTRL_ASSERT( be_monitor != SIXTRL_NULLPTR );
+                status |= NS(BeamMonitor_reset)( be_monitor );
             }
         }
     }
-    else
-    {
-        if( beam_elements == SIXTRL_NULLPTR )
-        {
-            flags |= BELEM_BUFFER_NULL_FLAG;
-        }
 
-        if( slot_size == ( buf_size_t )0u )
-        {
-            flags |= SLOT_SIZE_ILLEGAL_FLAG;
-        }
+    return status;
+}
 
-        if( NS(ManagedBuffer_needs_remapping)( beam_elements, slot_size ) )
-        {
-            flags |= BELEM_BUFFER_REQUIRES_REMAP_FLAG;
-        }
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_reset_all_in_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_reset_all_in_obj_index_range)(
+        NS(ManagedBuffer_get_objects_index_begin)( buffer_begin, slot_size ),
+        NS(ManagedBuffer_get_objects_index_end)( buffer_begin, slot_size ) );
+}
 
-        if( NS(ManagedBuffer_get_num_objects)( beam_elements, slot_size ) ==
-            ZERO )
-        {
-            flags |= BELEM_BUFFER_EMPTY_FLAG;
-        }
-    }
+#if !defined( _GPUCODE )
 
-    if( ptr_status_flags != SIXTRL_NULLPTR ) *ptr_status_flags = flags;
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const*
+NS(BeamMonitor_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* NS(BeamMonitor_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
+}
+
+SIXTRL_INLINE bool NS(BeamMonitor_are_present_in_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const
+        SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_are_present_in_obj_index_range)(
+        NS(Buffer_get_const_objects_begin)( buffer ),
+        NS(Buffer_get_const_objects_end)( buffer ) );
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_num_monitors_in_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const
+        SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_num_monitors_in_obj_index_range)(
+        NS(Buffer_get_const_objects_begin)( buffer ),
+        NS(Buffer_get_const_objects_end)( buffer ) );
 }
 
+SIXTRL_INLINE NS(buffer_size_t) NS(BeamMonitor_monitor_indices_from_buffer)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT indices_begin,
+    NS(buffer_size_t) const max_num_of_indices,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer
+) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_monitor_indices_from_obj_index_range)(
+        indices_begin, max_num_of_indices,
+        NS(Buffer_get_const_objects_begin)( buffer ),
+        NS(Buffer_get_const_objects_end)( buffer ),
+        ( NS(buffer_size_t) )0 );
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_reset_all_in_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer ) SIXTRL_NOEXCEPT
+{
+    return NS(BeamMonitor_reset_all_in_obj_index_range)(
+        NS(Buffer_get_objects_begin)( buffer ),
+        NS(Buffer_get_objects_end)( buffer ) );
+}
+
+#endif /* !defined( _GPUCODE ) */
+
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRACKL_COMMON_BE_MONITOR_BE_MONITOR_C99_HEADER_H__ */
-
-/* end: sixtracklib/common/be_monitor/be_monitor.h */
diff --git a/sixtracklib/common/be_monitor/be_monitor.hpp b/sixtracklib/common/be_monitor/be_monitor.hpp
index d943cf3d..931c5d4d 100644
--- a/sixtracklib/common/be_monitor/be_monitor.hpp
+++ b/sixtracklib/common/be_monitor/be_monitor.hpp
@@ -366,14 +366,13 @@ namespace SIXTRL_CXX_NAMESPACE
     BeamMonitor::getNumOfBeamMonitorObjects( BeamMonitor::buffer_t&
         SIXTRL_RESTRICT_REF belements_buffer ) SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_num_of_beam_monitor_objects)(
-            &belements_buffer );
+        return ::NS(BeamMonitor_num_monitors_in_buffer)( &belements_buffer );
     }
 
     SIXTRL_INLINE void BeamMonitor::clearAll( BeamMonitor::buffer_t&
         SIXTRL_RESTRICT_REF belements_buffer ) SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_clear_all)( &belements_buffer );
+        ::NS(BeamMonitor_reset_all_in_buffer)( &belements_buffer );
     }
 
     #endif /* !defined( _GPUCODE ) */
@@ -383,20 +382,19 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE BeamMonitor::type_id_t
     BeamMonitor::getTypeId() const SIXTRL_NOEXCEPT
     {
-        return ::NS(OBJECT_TYPE_BEAM_MONITOR);
+        return ::NS(BeamMonitor_type_id)();
     }
 
     SIXTRL_INLINE BeamMonitor::size_type
     BeamMonitor::getNumDataPtrs() const SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_num_dataptrs)( this->getCApiPtr() );
+        return ::NS(BeamMonitor_num_dataptrs)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE BeamMonitor::size_type
     BeamMonitor::getNumSlots( size_type const slot_size ) const SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_num_slots)(
-            this->getCApiPtr(), slot_size );
+        return ::NS(BeamMonitor_num_slots)( this->getCApiPtr(), slot_size );
     }
 
     SIXTRL_INLINE BeamMonitor::c_api_t const*
@@ -425,19 +423,19 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE BeamMonitor::turn_t
     BeamMonitor::getNumStores() const SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_num_stores)( this->getCApiPtr() );
+        return ::NS(BeamMonitor_num_stores)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE BeamMonitor::turn_t
     BeamMonitor::getStart() const SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_start)( this->getCApiPtr() );
+        return ::NS(BeamMonitor_start)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE BeamMonitor::turn_t
     BeamMonitor::getSkip() const SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_skip)( this->getCApiPtr() );
+        return ::NS(BeamMonitor_skip)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE bool BeamMonitor::isRolling() const SIXTRL_NOEXCEPT
@@ -458,19 +456,19 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE BeamMonitor::address_t
     BeamMonitor::getOutAddress() const SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_out_address)( this->getCApiPtr() );
+        return ::NS(BeamMonitor_out_address)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE BeamMonitor::index_t
     BeamMonitor::getMinParticleId() const SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_min_particle_id)( this->getCApiPtr() );
+        return ::NS(BeamMonitor_min_particle_id)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE BeamMonitor::index_t
     BeamMonitor::getMaxParticleId()  const SIXTRL_NOEXCEPT
     {
-        return ::NS(BeamMonitor_get_max_particle_id)( this->getCApiPtr() );
+        return ::NS(BeamMonitor_max_particle_id)( this->getCApiPtr() );
     }
 
     /* ----------------------------------------------------------------- */
@@ -541,7 +539,7 @@ namespace SIXTRL_CXX_NAMESPACE
         BeamMonitor::index_t const max_particle_id ) SIXTRL_NOEXCEPT
     {
         ::NS(BeamMonitor_set_max_particle_id)(
-            this->getCApiPtr(), min_particle_id );
+            this->getCApiPtr(), max_particle_id );
 
         return;
     }
diff --git a/sixtracklib/common/be_monitor/be_monitor_kernel_impl.h b/sixtracklib/common/be_monitor/be_monitor_kernel_impl.h
index 2a73b285..6d81ca6b 100644
--- a/sixtracklib/common/be_monitor/be_monitor_kernel_impl.h
+++ b/sixtracklib/common/be_monitor/be_monitor_kernel_impl.h
@@ -116,7 +116,7 @@ NS(BeamMonitor_assign_output_kernel_impl)(
                 ( be_mon_addr != ( uintptr_t )0u ) )
             {
                 ptr_be_monitor_t be_mon = ( ptr_be_monitor_t )be_mon_addr;
-                nturn_t const nn = NS(BeamMonitor_get_num_stores)( be_mon );
+                nturn_t const nn = NS(BeamMonitor_num_stores)( be_mon );
 
                 SIXTRL_ASSERT( be_mon != SIXTRL_NULLPTR );
                 SIXTRL_ASSERT( out_it != out_end );
@@ -132,10 +132,10 @@ NS(BeamMonitor_assign_output_kernel_impl)(
                         NS(Particles_get_num_of_particles)( particles );
 
                     mon_index_t const min_part_id =
-                        NS(BeamMonitor_get_min_particle_id)( be_mon );
+                        NS(BeamMonitor_min_particle_id)( be_mon );
 
                     mon_index_t const max_part_id =
-                        NS(BeamMonitor_get_max_particle_id)( be_mon );
+                        NS(BeamMonitor_max_particle_id)( be_mon );
 
                     buf_size_t const stored_particles_per_turn =
                         ( max_part_id >= min_part_id )
@@ -257,8 +257,7 @@ NS(BeamMonitor_assign_output_debug_kernel_impl)(
                         ptr_be_monitor_t be_mon =
                             ( ptr_be_monitor_t )be_mon_addr;
 
-                        nturn_t const nn =
-                            NS(BeamMonitor_get_num_stores)( be_mon );
+                        nturn_t const nn = NS(BeamMonitor_num_stores)( be_mon );
 
                         if( nn > ( nturn_t )0u )
                         {
@@ -271,10 +270,10 @@ NS(BeamMonitor_assign_output_debug_kernel_impl)(
                                 NS(Particles_get_num_of_particles)( particles );
 
                             mon_index_t const min_part_id =
-                                NS(BeamMonitor_get_min_particle_id)( be_mon );
+                                NS(BeamMonitor_min_particle_id)( be_mon );
 
                             mon_index_t const max_part_id =
-                                NS(BeamMonitor_get_max_particle_id)( be_mon );
+                                NS(BeamMonitor_max_particle_id)( be_mon );
 
                             buf_size_t const stored_particles_per_turn =
                                 ( max_part_id >= min_part_id )
diff --git a/sixtracklib/common/be_monitor/output_buffer.c b/sixtracklib/common/be_monitor/output_buffer.c
index ba268ac5..89b14764 100644
--- a/sixtracklib/common/be_monitor/output_buffer.c
+++ b/sixtracklib/common/be_monitor/output_buffer.c
@@ -88,17 +88,17 @@ NS(arch_status_t) NS(BeamMonitor_calculate_output_buffer_params_detailed)(
     NS(particle_index_t) const min_turn_id,
     NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_objects,
     NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_slots,
-    NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_data_ptrs,
+    NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_ptrs,
     NS(buffer_size_t)* SIXTRL_RESTRICT ptr_num_garbage,
     NS(buffer_size_t) const out_buffer_slot_size )
 {
-    typedef NS(buffer_size_t)                               buf_size_t;
-    typedef NS(particle_index_t)                            index_t;
-    typedef NS(be_monitor_turn_t)                           nturn_t;
-    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*  ptr_obj_t;
-    typedef SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*           ptr_beam_monitor_t;
-    typedef NS(buffer_addr_t)                               address_t;
-    typedef NS(object_type_id_t)                            type_id_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef NS(particle_index_t) index_t;
+    typedef NS(be_monitor_turn_t) nturn_t;
+    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* ptr_obj_t;
+    typedef SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)* ptr_beam_monitor_t;
+    typedef NS(buffer_addr_t) address_t;
+    typedef NS(object_type_id_t) type_id_t;
 
     NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
@@ -140,10 +140,9 @@ NS(arch_status_t) NS(BeamMonitor_calculate_output_buffer_params_detailed)(
 
                 buf_size_t required_store_particles = ZERO;
 
-                nturn_t const skip  = NS(BeamMonitor_get_skip)( monitor );
-                nturn_t const start = NS(BeamMonitor_get_start)( monitor );
-                nturn_t const num_stores =
-                    NS(BeamMonitor_get_num_stores)( monitor );
+                nturn_t const skip  = NS(BeamMonitor_skip)( monitor );
+                nturn_t const start = NS(BeamMonitor_start)( monitor );
+                nturn_t const num_stores = NS(BeamMonitor_num_stores)( monitor );
 
                 if( ( start >= first_turn_id ) ||
                     ( NS(BeamMonitor_is_rolling)( monitor ) ) )
@@ -181,25 +180,10 @@ NS(arch_status_t) NS(BeamMonitor_calculate_output_buffer_params_detailed)(
 
     if( status == SIXTRL_ARCH_STATUS_SUCCESS )
     {
-        if(  ptr_num_objects != SIXTRL_NULLPTR )
-        {
-            *ptr_num_objects  = num_objects;
-        }
-
-        if(  ptr_num_slots != SIXTRL_NULLPTR )
-        {
-            *ptr_num_slots = num_slots;
-        }
-
-        if(  ptr_num_data_ptrs != SIXTRL_NULLPTR )
-        {
-            *ptr_num_data_ptrs  = num_dataptrs;
-        }
-
-        if(  ptr_num_garbage != SIXTRL_NULLPTR )
-        {
-            *ptr_num_garbage  = num_garbage;
-        }
+        if( ptr_num_objects != SIXTRL_NULLPTR ) *ptr_num_objects = num_objects;
+        if( ptr_num_slots   != SIXTRL_NULLPTR ) *ptr_num_slots   = num_slots;
+        if( ptr_num_garbage != SIXTRL_NULLPTR ) *ptr_num_garbage = num_garbage;
+        if( ptr_num_ptrs    != SIXTRL_NULLPTR ) *ptr_num_ptrs    = num_dataptrs;
     }
 
     return status;
@@ -309,9 +293,7 @@ NS(arch_status_t) NS(BeamMonitor_prepare_output_buffer_detailed)(
         return status;
     }
 
-    num_particles_per_turn = ( buf_size_t )(
-        1u + max_part_id - min_part_id );
-
+    num_particles_per_turn = ( buf_size_t )( 1u + max_part_id - min_part_id );
     SIXTRL_ASSERT( num_particles_per_turn > ZERO );
     status = SIXTRL_ARCH_STATUS_SUCCESS;
 
@@ -325,8 +307,8 @@ NS(arch_status_t) NS(BeamMonitor_prepare_output_buffer_detailed)(
             ptr_beam_monitor_t monitor = ( ptr_beam_monitor_t )( uintptr_t
                 )NS(Object_get_begin_addr)( be_it );
 
-            nturn_t const start = NS(BeamMonitor_get_start)( monitor );
-            nturn_t const nstores = NS(BeamMonitor_get_num_stores)( monitor );
+            nturn_t const start = NS(BeamMonitor_start)( monitor );
+            nturn_t const nstores = NS(BeamMonitor_num_stores)( monitor );
 
             if( ( start >= first_turn_id ) && ( nstores > TZERO ) )
             {
@@ -338,15 +320,9 @@ NS(arch_status_t) NS(BeamMonitor_prepare_output_buffer_detailed)(
 
                 if( particles != SIXTRL_NULLPTR )
                 {
-                    NS(BeamMonitor_set_min_particle_id)(
-                        monitor, min_part_id );
-
-                    NS(BeamMonitor_set_max_particle_id)(
-                        monitor, max_part_id );
-
-                    NS(BeamMonitor_set_out_address)(
-                        monitor, ( address_t )0u );
-
+                    NS(BeamMonitor_set_min_particle_id)( monitor, min_part_id );
+                    NS(BeamMonitor_set_max_particle_id)( monitor, max_part_id );
+                    NS(BeamMonitor_set_out_address)( monitor, ( address_t )0u );
                     ++num_beam_monitors;
                 }
                 else
diff --git a/sixtracklib/common/be_monitor/output_buffer.h b/sixtracklib/common/be_monitor/output_buffer.h
index 78156ecf..d5f718a7 100644
--- a/sixtracklib/common/be_monitor/output_buffer.h
+++ b/sixtracklib/common/be_monitor/output_buffer.h
@@ -306,8 +306,8 @@ SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_assign_managed_output_buffer)(
         {
             ptr_beam_monitor_t monitor = ( ptr_beam_monitor_t )addr;
 
-            nturn_t const    nn = NS(BeamMonitor_get_num_stores)( monitor );
-            nturn_t const start = NS(BeamMonitor_get_start)( monitor );
+            nturn_t const    nn = NS(BeamMonitor_num_stores)( monitor );
+            nturn_t const start = NS(BeamMonitor_start)( monitor );
 
             if( ( nn > ( nturn_t )0u ) &&
                 ( start >= first_turn_id ) && ( out_it != out_end ) )
@@ -319,10 +319,10 @@ SIXTRL_INLINE NS(arch_status_t) NS(BeamMonitor_assign_managed_output_buffer)(
                     NS(Particles_get_num_of_particles)( particles );
 
                 mon_index_t const min_particle_id =
-                    NS(BeamMonitor_get_min_particle_id)( monitor );
+                    NS(BeamMonitor_min_particle_id)( monitor );
 
                 mon_index_t const max_particle_id =
-                    NS(BeamMonitor_get_max_particle_id)( monitor );
+                    NS(BeamMonitor_max_particle_id)( monitor );
 
                 buf_size_t const stored_particles_per_turn =
                     ( max_particle_id >= min_particle_id )
diff --git a/sixtracklib/common/be_monitor/track.h b/sixtracklib/common/be_monitor/track.h
index b3e54450..d3186e68 100644
--- a/sixtracklib/common/be_monitor/track.h
+++ b/sixtracklib/common/be_monitor/track.h
@@ -57,9 +57,9 @@ NS(BeamMonitor_get_store_particle_index)(
 
     num_elements_t out_particle_id = ( num_elements_t )-1;
 
-    nturn_t const monitor_start = NS(BeamMonitor_get_start)( monitor );
-    nturn_t const num_stores = NS(BeamMonitor_get_num_stores)( monitor );
-    nturn_t const skip = NS(BeamMonitor_get_skip)( monitor );
+    nturn_t const monitor_start = NS(BeamMonitor_start)( monitor );
+    nturn_t const num_stores = NS(BeamMonitor_num_stores)( monitor );
+    nturn_t const skip = NS(BeamMonitor_skip)( monitor );
     nturn_t turns_since_start = ZERO_TURNS;
 
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
@@ -67,10 +67,10 @@ NS(BeamMonitor_get_store_particle_index)(
     SIXTRL_ASSERT( skip >= ( nturn_t )1u );
 
     SIXTRL_ASSERT( in_particle_id >= ( NS(be_monitor_index_t)
-        )NS(BeamMonitor_get_min_particle_id)( monitor ) );
+        )NS(BeamMonitor_min_particle_id)( monitor ) );
 
     SIXTRL_ASSERT( in_particle_id <= ( NS(be_monitor_index_t)
-        )NS(BeamMonitor_get_max_particle_id)( monitor ) );
+        )NS(BeamMonitor_max_particle_id)( monitor ) );
 
     turns_since_start = at_turn_number - monitor_start;
 
@@ -88,11 +88,11 @@ NS(BeamMonitor_get_store_particle_index)(
         if( store_idx < num_stores )
         {
             num_elements_t const particle_id_offset = ( num_elements_t )(
-                in_particle_id - NS(BeamMonitor_get_min_particle_id)( monitor ) );
+                in_particle_id - NS(BeamMonitor_min_particle_id)( monitor ) );
 
             num_elements_t const num_particles_to_store = ( num_elements_t )(
-                    NS(BeamMonitor_get_max_particle_id)( monitor ) -
-                    NS(BeamMonitor_get_min_particle_id)( monitor ) +
+                    NS(BeamMonitor_max_particle_id)( monitor ) -
+                    NS(BeamMonitor_min_particle_id)( monitor ) +
                         ( num_elements_t )1u );
 
             if( NS(BeamMonitor_is_turn_ordered)( monitor ) )
@@ -131,18 +131,18 @@ SIXTRL_INLINE int NS(Track_particle_beam_monitor)(
         )NS(Particles_get_at_turn_value)( in_particles, idx );
 
     SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( NS(BeamMonitor_get_skip)( monitor ) > ( nturn_t )0u  );
-    SIXTRL_ASSERT( NS(BeamMonitor_get_num_stores)( monitor ) > ( nturn_t)0u );
+    SIXTRL_ASSERT( NS(BeamMonitor_skip)( monitor ) > ( nturn_t )0u  );
+    SIXTRL_ASSERT( NS(BeamMonitor_num_stores)( monitor ) > ( nturn_t)0u );
 
     SIXTRL_ASSERT( in_particles != SIXTRL_NULLPTR );
 
-    SIXTRL_ASSERT( NS(BeamMonitor_get_min_particle_id)( monitor ) <=
-                   NS(BeamMonitor_get_max_particle_id)( monitor ) );
+    SIXTRL_ASSERT( NS(BeamMonitor_min_particle_id)( monitor ) <=
+                   NS(BeamMonitor_max_particle_id)( monitor ) );
 
     SIXTRL_ASSERT( NS(Particles_get_state_value)( in_particles, idx ) ==
                    ( NS(particle_index_t) )1u );
 
-    if( NS(BeamMonitor_get_out_address)( monitor ) != ( addr_t )0 )
+    if( NS(BeamMonitor_out_address)( monitor ) != ( addr_t )0 )
     {
         index_t const particle_id = NS(Particles_get_particle_id_value)(
             in_particles, idx );
@@ -154,7 +154,7 @@ SIXTRL_INLINE int NS(Track_particle_beam_monitor)(
         if( out_particle_id >= ( num_elements_t )0u )
         {
             ptr_out_particles_t out_particles = ( ptr_out_particles_t )(
-                uintptr_t )NS(BeamMonitor_get_out_address)( monitor );
+                uintptr_t )NS(BeamMonitor_out_address)( monitor );
 
             success = NS(Particles_copy_to_generic_addr_data)(
                 out_particles, out_particle_id, in_particles, idx );
diff --git a/sixtracklib/common/be_multipole/CMakeLists.txt b/sixtracklib/common/be_multipole/CMakeLists.txt
index d6aec7a7..9e2c5d55 100644
--- a/sixtracklib/common/be_multipole/CMakeLists.txt
+++ b/sixtracklib/common/be_multipole/CMakeLists.txt
@@ -1,51 +1,37 @@
-set( SIXTRACKLIB_COMMON_BE_MULTIPOLE_C99_HEADERS
-     be_multipole.h
-)
+set( SIXTRL_COMMON_BE_MULTIPOLE_C99_HEADERS be_multipole.h track.h )
+set( SIXTRL_COMMON_BE_MULTIPOLE_C99_SOURCES be_multipole.c )
+set( SIXTRL_COMMON_BE_MULTIPOLE_CXX_HEADERS be_multipole.hpp )
 
-set( SIXTRACKLIB_COMMON_BE_MULTIPOLE_CXX_HEADERS
-     be_multipole.hpp
-)
+add_library( sixtrack_common_be_multipole OBJECT
+    ${SIXTRL_COMMON_BE_MULTIPOLE_C99_HEADERS}
+    ${SIXTRL_COMMON_BE_MULTIPOLE_C99_SOURCES} )
 
-if( SIXTRACKLIB_COMMON_BE_MULTIPOLE_C99_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_multipole/\\1" LOCAL_C99_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_MULTIPOLE_C99_HEADERS}" )
+target_include_directories( sixtrack_common_be_multipole PRIVATE
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-    set(  SIXTRACKLIB_COMMON_C99_HEADERS
-        ${SIXTRACKLIB_COMMON_C99_HEADERS}
-        ${LOCAL_C99_HEADERS} PARENT_SCOPE )
-endif()
+set_target_properties( sixtrack_common_be_multipole PROPERTIES
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
+    C_STANDARD_REQUIRED ON )
 
-if( SIXTRACKLIB_COMMON_BE_MULTIPOLE_CXX_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_multipole/\\1" LOCAL_CXX_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_MULTIPOLE_CXX_HEADERS}" )
+target_compile_options( sixtrack_common_be_multipole PRIVATE
+        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
-    set(  SIXTRACKLIB_COMMON_CXX_HEADERS
-        ${SIXTRACKLIB_COMMON_CXX_HEADERS}
-        ${LOCAL_CXX_HEADERS} PARENT_SCOPE )
-endif()
+# ------------------------------------------------------------------------------
+# pass on sixtrack_common_be_beambeam as a module for sixtracklib:
+
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_common_be_multipole> CACHE INTERNAL "" FORCE )
 
 # ----------------------------------------------------------------------------
 # install :
 
-if( SIXTRACKLIB_COMMON_BE_MULTIPOLE_C99_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_MULTIPOLE_C99_INSTALL_PATH
-         include/sixtracklib/common/be_multipole )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_MULTIPOLE_C99_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_MULTIPOLE_C99_INSTALL_PATH} )
-endif()
-
-
-if( SIXTRACKLIB_COMMON_BE_MULTIPOLE_CXX_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_MULTIPOLE_CXX_INSTALL_PATH
-         include/sixtracklib/common/be_multipole )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_MULTIPOLE_CXX_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_MULTIPOLE_CXX_INSTALL_PATH} )
+if( SIXTRL_COMMON_BE_MULTIPOLE_C99_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_MULTIPOLE_C99_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/be_multipole" )
 endif()
 
-#end: sixtracklib/common/be_multipole/CMakeLists.txt
-
-
+if( SIXTRACKL_ENABLE_CXX AND SIXTRL_COMMON_BE_MULTIPOLE_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_MULTIPOLE_CXX_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/be_multipole" )
+ endif()
diff --git a/sixtracklib/common/be_multipole/be_multipole.c b/sixtracklib/common/be_multipole/be_multipole.c
new file mode 100644
index 00000000..cf5fcae9
--- /dev/null
+++ b/sixtracklib/common/be_multipole/be_multipole.c
@@ -0,0 +1,313 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/be_multipole/be_multipole.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+NS(arch_status_t) NS(Multipole_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( multipole != SIXTRL_NULLPTR ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) &&
+        ( max_num_offsets > ( NS(buffer_size_t) )0 ) )
+    {
+        offsets[ 0 ] = ( NS(buffer_size_t) )offsetof( NS(Multipole), bal_addr );
+        SIXTRL_ASSERT( offsets[ 0 ] % slot_size == ( NS(buffer_size_t) )0 );
+
+        if( max_num_offsets > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_offsets ; ++ii ) offsets[ ii ] = 0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+NS(arch_status_t) NS(Multipole_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( multipole != SIXTRL_NULLPTR ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) &&
+        ( max_num_sizes > ( NS(buffer_size_t) )0 ) )
+    {
+        sizes[ 0 ] = ( NS(buffer_size_t) )sizeof( NS(multipole_real_t) );
+        if( max_num_sizes > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_sizes ; ++ii ) sizes[ ii ] = 0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+NS(arch_status_t) NS(Multipole_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( multipole != SIXTRL_NULLPTR ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) &&
+        ( max_num_counts > ( NS(buffer_size_t) )0 ) )
+    {
+        counts[ 0 ] = NS(Multipole_bal_length)( multipole );
+        if( max_num_counts > ( NS(buffer_size_t) )1 )
+        {
+            NS(buffer_size_t) ii = ( NS(buffer_size_t) )1u;
+            for( ; ii < max_num_counts ; ++ii ) counts[ ii ] = 0u;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(object_type_id_t) NS(Multipole_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(Multipole_type_id)();
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(Multipole_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(multipole_order_t) const order,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objs,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    bool can_be_added = false;
+
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+    buf_size_t ndataptrs = ( buf_size_t )0u;
+
+    NS(Multipole) data;
+    NS(arch_status_t) status = NS(Multipole_clear)( &data );
+    status |= NS(Multipole_set_order)( &data, order );
+    ndataptrs = NS(Multipole_num_dataptrs)( &data );
+
+    if( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( ndataptrs == ( buf_size_t )1u ) && ( slot_size > ( buf_size_t )0 ) &&
+        ( buffer != SIXTRL_NULLPTR ) && ( order >= ( NS(multipole_order_t) )0 ) )
+    {
+        NS(buffer_size_t) sizes[ 1 ];
+        NS(buffer_size_t) counts[ 1 ];
+
+        status = NS(Multipole_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )1u, &data, slot_size );
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            status = NS(Multipole_attributes_counts)(
+                &counts[ 0 ], ( buf_size_t )1u, &data, slot_size );
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            can_be_added = NS(Buffer_can_add_object)( buffer, sizeof(
+                NS(Multipole) ), ndataptrs, &sizes[ 0 ], &counts[ 0 ],
+                    ptr_requ_objs, ptr_requ_slots, ptr_requ_dataptrs );
+        }
+    }
+
+    return can_be_added;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Multipole)* NS(Multipole_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(multipole_order_t) const order )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(Multipole)*
+        added_elem = SIXTRL_NULLPTR;
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( order >= ( NS(multipole_order_t) )0 ) )
+    {
+        buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1u ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1u ];
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1u ];
+
+        buf_size_t ndataptrs = ( buf_size_t )0u;
+
+        NS(Multipole) data;
+        NS(arch_status_t) status = NS(Multipole_clear)( &data );
+        status |= NS(Multipole_set_order)( &data, order );
+        ndataptrs = NS(Multipole_num_dataptrs)( &data );
+
+        if( ( ndataptrs == ( buf_size_t )1u ) &&
+            ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+            ( slot_size > ( buf_size_t )0 ) && ( buffer != SIXTRL_NULLPTR ) )
+        {
+            status = NS(Multipole_attributes_offsets)(
+                &offsets[ 0 ], ( buf_size_t )1u, &data, slot_size );
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(Multipole_attributes_sizes)(
+                    &sizes[ 0 ], ( buf_size_t )1u, &data, slot_size );
+            }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(Multipole_attributes_counts)(
+                    &counts[ 0 ], ( buf_size_t )1u, &data, slot_size );
+            }
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(Multipole)*
+                )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, &data, sizeof( NS(Multipole) ),
+                        NS(Multipole_type_id)(), ndataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Multipole)* NS(Multipole_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(multipole_order_t) const order,
+    NS(multipole_real_t) const length,
+    NS(multipole_real_t) const hxl,
+    NS(multipole_real_t) const hyl,
+    NS(buffer_addr_t) const bal_addr )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(Multipole)*
+        added_elem = SIXTRL_NULLPTR;
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( order >= ( NS(multipole_order_t) )0 ) )
+    {
+        buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1u ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1u ];
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1u ];
+
+        buf_size_t ndataptrs = ( buf_size_t )0u;
+
+        NS(Multipole) data;
+        NS(arch_status_t) status = NS(Multipole_clear)( &data );
+        status |= NS(Multipole_set_order)( &data, order );
+        status |= NS(Multipole_set_length)( &data, length );
+        status |= NS(Multipole_set_hxl)( &data, hxl );
+        status |= NS(Multipole_set_hyl)( &data, hyl );
+        status |= NS(Multipole_set_bal_addr)( &data, bal_addr );
+
+        ndataptrs = NS(Multipole_num_dataptrs)( &data );
+
+        if( ( ndataptrs == ( buf_size_t )1u ) &&
+            ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+            ( slot_size > ( buf_size_t )0 ) && ( buffer != SIXTRL_NULLPTR ) )
+        {
+            status = NS(Multipole_attributes_offsets)(
+                &offsets[ 0 ], ( buf_size_t )1u, &data, slot_size );
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(Multipole_attributes_sizes)(
+                    &sizes[ 0 ], ( buf_size_t )1u, &data, slot_size );
+            }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(Multipole_attributes_counts)(
+                    &counts[ 0 ], ( buf_size_t )1u, &data, slot_size );
+            }
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(Multipole)*
+                )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, &data, sizeof( NS(Multipole) ),
+                        NS(Multipole_type_id)(), ndataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(Multipole)* NS(Multipole_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT orig )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(Multipole)*
+        added_elem = SIXTRL_NULLPTR;
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) )
+    {
+        buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+        NS(arch_status_t) status = ( NS(arch_status_t)
+            )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 1u ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1u ];
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1u ];
+
+        buf_size_t ndataptrs = NS(Multipole_num_dataptrs)( orig );
+
+        if( ( ndataptrs == ( buf_size_t )1u ) &&
+            ( slot_size > ( buf_size_t )0 ) && ( buffer != SIXTRL_NULLPTR ) )
+        {
+            status = NS(Multipole_attributes_offsets)(
+                &offsets[ 0 ], ( buf_size_t )1u, orig, slot_size );
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(Multipole_attributes_sizes)(
+                    &sizes[ 0 ], ( buf_size_t )1u, orig, slot_size );
+            }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(Multipole_attributes_counts)(
+                    &counts[ 0 ], ( buf_size_t )1u, orig, slot_size );
+            }
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(Multipole)*
+                )( uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, orig, sizeof( NS(Multipole) ),
+                        NS(Multipole_type_id)(), ndataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
diff --git a/sixtracklib/common/be_multipole/be_multipole.h b/sixtracklib/common/be_multipole/be_multipole.h
index a7739b05..a88f563a 100644
--- a/sixtracklib/common/be_multipole/be_multipole.h
+++ b/sixtracklib/common/be_multipole/be_multipole.h
@@ -9,200 +9,279 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-/* ========================================================================= */
-
 typedef SIXTRL_INT64_T NS(multipole_order_t);
 typedef SIXTRL_REAL_T  NS(multipole_real_t);
 
-typedef struct NS(MultiPole)
+typedef struct NS(Multipole)
 {
-    NS(multipole_order_t) order   SIXTRL_ALIGN( 8 );
-    NS(multipole_real_t)  length  SIXTRL_ALIGN( 8 );
-    NS(multipole_real_t)  hxl     SIXTRL_ALIGN( 8 );
-    NS(multipole_real_t)  hyl     SIXTRL_ALIGN( 8 );
-
-    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)*
-        SIXTRL_RESTRICT bal SIXTRL_ALIGN( 8 );
+    NS(multipole_order_t) order     SIXTRL_ALIGN( 8 );
+    NS(multipole_real_t)  length    SIXTRL_ALIGN( 8 );
+    NS(multipole_real_t)  hxl       SIXTRL_ALIGN( 8 );
+    NS(multipole_real_t)  hyl       SIXTRL_ALIGN( 8 );
+    NS(buffer_addr_t)     bal_addr  SIXTRL_ALIGN( 8 );
 }
-NS(MultiPole);
+NS(Multipole);
 
-/* ========================================================================= */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(MultiPole_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(Multipole_type_id)(
+    void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(MultiPole_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(Multipole_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* NS(MultiPole_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(Multipole_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(multipole_real_t) NS(MultiPole_get_length)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC NS(multipole_real_t) NS(MultiPole_get_hxl)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+NS(Multipole_preset)( SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(multipole_real_t) NS(MultiPole_get_hyl)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(multipole_order_t) NS(MultiPole_get_order)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(MultiPole_get_bal_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN NS(multipole_real_t) NS(Multipole_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
-NS(MultiPole_get_const_bal)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN NS(multipole_real_t) NS(Multipole_hxl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)*
-NS(MultiPole_get_bal)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN NS(multipole_real_t) NS(Multipole_hyl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(multipole_real_t) NS(MultiPole_get_bal_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index );
+SIXTRL_STATIC SIXTRL_FN NS(multipole_order_t) NS(Multipole_order)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(multipole_real_t) NS(MultiPole_get_knl_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(Multipole_bal_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(multipole_real_t) NS(MultiPole_get_ksl_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(Multipole_bal_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_length)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_real_t) const length );
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_hxl)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_real_t) const length );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+NS(Multipole_const_bal_begin)( SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_hyl)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_real_t) const length );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+NS(Multipole_const_bal_end)( SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_order)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_order_t) const order );
+SIXTRL_STATIC SIXTRL_FN NS(multipole_real_t) NS(Multipole_bal)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const bal_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN NS(multipole_real_t) NS(Multipole_knl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(multipole_order_t) const knl_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_bal)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    SIXTRL_BE_ARGPTR_DEC NS(multipole_real_t) const* SIXTRL_RESTRICT bal );
+SIXTRL_STATIC SIXTRL_FN NS(multipole_real_t) NS(Multipole_ksl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(multipole_order_t) const ksl_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_knl)(
-    SIXTRL_BE_DATAPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* SIXTRL_RESTRICT knl );
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_ksl)(
-    SIXTRL_BE_DATAPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* SIXTRL_RESTRICT ksl );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)*
+NS(Multipole_bal_begin)( SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_assign_bal)(
-    SIXTRL_BE_DATAPTR_DEC  NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_order_t) const order,
-    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* SIXTRL_RESTRICT bal );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)*
+NS(Multipole_bal_end)( SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_bal_value)(
-    SIXTRL_BE_DATAPTR_DEC  NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index, NS(multipole_real_t) const bal );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_knl_value)(
-    SIXTRL_BE_DATAPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index,
-    NS(multipole_real_t) const knl_i );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const length ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(MultiPole_set_ksl_value)(
-    SIXTRL_BE_DATAPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index,
-    NS(multipole_real_t) const ksl_i );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_hxl)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const length ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_hyl)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const length ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_order)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_order_t) const order ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_bal_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(buffer_addr_t) const bal_addr ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_bal_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const bal_index,
+    NS(multipole_real_t) const bal_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_all_bal_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const bal_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_bal)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+        SIXTRL_RESTRICT bal_values_begin ) SIXTRL_NOEXCEPT;
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_knl_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const knl_index,
+    NS(multipole_real_t) const knl_value ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(MultiPole_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT src );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_all_knl_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const knl_value ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(MultiPole_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT rhs );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_knl)(
+    SIXTRL_BE_DATAPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+        SIXTRL_RESTRICT knl ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int NS(MultiPole_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT rhs,
-    NS(multipole_real_t) const treshold );
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole) const*
-NS(BufferIndex_get_const_multipole)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_ksl_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const ksl_index,
+    NS(multipole_real_t) const ksl_value ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(BufferIndex_get_multipole)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_all_ksl_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const ksl_value ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole) const*
-NS(BeamElements_managed_buffer_get_const_multipole)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_set_ksl)(
+    SIXTRL_BE_DATAPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+        SIXTRL_RESTRICT ksl ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(BeamElements_managed_buffer_get_multipole)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Multipole_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT destination,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole) const*
+NS(Multipole_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+NS(Multipole_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole) const*
+NS(Multipole_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+NS(Multipole_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole) const*
-NS(BeamElements_buffer_get_const_multipole)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole) const*
+NS(Multipole_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(BeamElements_buffer_get_multipole)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+NS(Multipole_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(Multipole_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(Multipole_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(Multipole_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC bool NS(MultiPole_can_be_added)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(Multipole_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(Multipole_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     NS(multipole_order_t) const order,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objs,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(MultiPole_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+NS(Multipole_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(multipole_order_t) const order );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(MultiPole_add)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+NS(Multipole_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(multipole_order_t) const order,
-    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* SIXTRL_RESTRICT bal,
-    NS(multipole_real_t)  const length,
-    NS(multipole_real_t)  const hxl,
-    NS(multipole_real_t)  const hyl );
+    NS(multipole_real_t) const length,
+    NS(multipole_real_t) const hxl,
+    NS(multipole_real_t) const hyl,
+    NS(buffer_addr_t) const bal_addr );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(MultiPole_add_copy)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+NS(Multipole_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole );
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole );
 
 #endif /* !defined( _GPUCODE ) */
-
-/* ========================================================================= */
-
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
@@ -212,6 +291,9 @@ NS(MultiPole_add_copy)(
 /* ************************************************************************* */
 
 #if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #include "sixtracklib/common/internal/math_factorial.h"
     #if !defined( _GPUCODE )
     #include "sixtracklib/common/buffer.h"
     #endif /* !defined( _GPUCODE ) */
@@ -221,885 +303,591 @@ NS(MultiPole_add_copy)(
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_INLINE NS(buffer_size_t) NS(MultiPole_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(object_type_id_t) NS(Multipole_type_id)( void ) SIXTRL_NOEXCEPT
 {
-    typedef NS(multipole_order_t)   mp_order_t;
-    typedef NS(buffer_size_t)       buf_size_t;
-
-    return ( ( multipole != SIXTRL_NULLPTR ) &&
-             ( multipole->order >= ( mp_order_t )0 ) )
-        ? ( buf_size_t )1u : ( buf_size_t )0u;
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_MULTIPOLE);
 }
 
-SIXTRL_INLINE NS(buffer_size_t) NS(MultiPole_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT mp,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(buffer_size_t) NS(Multipole_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC
+    const NS(Multipole) *const SIXTRL_RESTRICT
+        SIXTRL_UNUSED( multipole ) ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
-
-    buf_size_t requ_num_slots =  NS(ManagedBuffer_get_slot_based_length)(
-            sizeof( NS(MultiPole) ), slot_size );
-
-    if( ( requ_num_slots > ZERO ) && ( slot_size > ZERO ) )
-    {
-        buf_size_t const bal_size = NS(MultiPole_get_bal_size)( mp );
-
-        SIXTRL_ASSERT(
-            ( NS(MultiPole_get_num_dataptrs)( mp ) == ( buf_size_t )1u ) ||
-            ( ( NS(MultiPole_get_num_dataptrs)( mp ) == ZERO ) &&
-              ( NS(MultiPole_get_order)( mp ) <
-              ( NS(multipole_order_t) )0u ) ) );
-
-        SIXTRL_ASSERT( ( requ_num_slots % slot_size ) == ZERO );
-        SIXTRL_ASSERT( ( bal_size % 2u ) == ZERO );
-
-        if( bal_size > ZERO )
-        {
-            requ_num_slots += NS(ManagedBuffer_get_slot_based_length)(
-                bal_size * sizeof( SIXTRL_REAL_T ), slot_size );
-        }
-
-        SIXTRL_ASSERT( ZERO == ( requ_num_slots % slot_size ) );
-        SIXTRL_ASSERT( requ_num_slots >= slot_size );
-
-        requ_num_slots /= slot_size;
-    }
-
-    return requ_num_slots;
+    return ( NS(buffer_size_t) )1u;
 }
 
-SIXTRL_INLINE int NS(MultiPole_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT dest,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT src )
+SIXTRL_INLINE NS(buffer_size_t) NS(Multipole_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    int success = -1;
-
-    NS(multipole_order_t) const order = NS(MultiPole_get_order)( src );
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
 
-    if( ( dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) &&
-        ( NS(MultiPole_get_order)( dest ) == order ) )
+    if( ( multipole != SIXTRL_NULLPTR ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) )
     {
-        NS(MultiPole_set_length)( dest, NS(MultiPole_get_length)( src ) );
-        NS(MultiPole_set_hxl)( dest, NS(MultiPole_get_hxl)( src ) );
-        NS(MultiPole_set_hyl)( dest, NS(MultiPole_get_hyl)( src ) );
+        NS(buffer_size_t) num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(Multipole) ), slot_size );
 
-        if( order >= ( NS(multipole_order_t) )0u )
-        {
-            SIXTRL_ASSERT( NS(MultiPole_get_bal)( dest )     != SIXTRL_NULLPTR );
-            SIXTRL_ASSERT( NS(MultiPole_get_const_bal)( src) != SIXTRL_NULLPTR );
-            SIXTRL_ASSERT( NS(MultiPole_get_bal_size)( dest ) ==
-                           NS(MultiPole_get_bal_size)( src  ) );
-
-            SIXTRACKLIB_COPY_VALUES( SIXTRL_REAL_T,
-                 NS(MultiPole_get_bal)( dest ),
-                 NS(MultiPole_get_const_bal)( src ),
-                 NS(MultiPole_get_bal_size)( src ) );
-        }
+        NS(buffer_size_t) const bal_length = NS(Multipole_bal_length)( multipole );
 
-        success = 0;
+        SIXTRL_ASSERT( bal_length >= ( NS(buffer_size_t) )0 );
+        num_bytes += NS(ManagedBuffer_get_slot_based_length)(
+            bal_length * sizeof( NS(multipole_real_t) ), slot_size );
+
+        num_slots = num_bytes / slot_size;
+        if( num_slots * slot_size < num_bytes ) ++num_slots;
     }
 
-    return success;
+    return num_slots;
 }
 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC NS(multipole_order_t) NS(_calculate_factorial)(
-    NS(multipole_order_t) const n )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Multipole)* NS(Multipole_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+        SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
-    NS(multipole_order_t) result = 1;
-    NS(multipole_order_t) ii     = 1;
-
-    for( ; ii <= n ; ++ii )
-    {
-        result *= ii;
-    }
-
-    return result;
+    if( multipole != SIXTRL_NULLPTR ) NS(Multipole_clear)( multipole );
+    return multipole;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* NS(MultiPole_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_clear)( SIXTRL_BE_ARGPTR_DEC
+    NS(Multipole)* SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
-    typedef NS(multipole_order_t) mp_order_t;
-    SIXTRL_STATIC_VAR mp_order_t DEFAULT_ORDER = ( mp_order_t )-1;
+    NS(arch_status_t) status = NS(Multipole_set_length)(
+        multipole, ( NS(multipole_real_t) )0 );
 
-    NS(MultiPole_assign_bal)( multipole, DEFAULT_ORDER, SIXTRL_NULLPTR );
-    NS(MultiPole_clear)( multipole );
+    status |= NS(Multipole_set_hxl)( multipole, ( NS(multipole_real_t) )0 );
+    status |= NS(Multipole_set_hyl)( multipole, ( NS(multipole_real_t) )0 );
+    status |= NS(Multipole_set_order)( multipole, ( NS(multipole_order_t) )0 );
+    status |= NS(Multipole_set_bal_addr)( multipole, ( NS(buffer_addr_t) )0 );
 
-    return multipole;
+    return status;
 }
 
-SIXTRL_INLINE NS(multipole_real_t) NS(MultiPole_get_length)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(multipole_real_t) NS(Multipole_length)( SIXTRL_BE_ARGPTR_DEC
+    const NS(Multipole) *const SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
     return multipole->length;
 }
 
-SIXTRL_INLINE NS(multipole_real_t) NS(MultiPole_get_hxl)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(multipole_real_t) NS(Multipole_hxl)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Multipole) *const SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
     return multipole->hxl;
 }
 
-SIXTRL_INLINE NS(multipole_real_t) NS(MultiPole_get_hyl)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(multipole_real_t) NS(Multipole_hyl)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Multipole) *const SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
     return multipole->hyl;
 }
 
-SIXTRL_INLINE NS(multipole_order_t) NS(MultiPole_get_order)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(multipole_order_t) NS(Multipole_order)( SIXTRL_BE_ARGPTR_DEC
+    const NS(Multipole) *const SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
     return multipole->order;
 }
 
-SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
-NS(MultiPole_get_const_bal)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(buffer_size_t) NS(Multipole_bal_length)( SIXTRL_BE_ARGPTR_DEC
+    const NS(Multipole) *const SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
-
-    SIXTRL_ASSERT(
-        ( ( NS(MultiPole_get_order)( multipole ) >= 0 ) &&
-            ( multipole->bal != SIXTRL_NULLPTR ) ) ||
-          ( ( NS(MultiPole_get_order)( multipole ) < 0 ) &&
-            ( multipole->bal == SIXTRL_NULLPTR ) ) );
-
-    return multipole->bal;
+    return ( multipole->order >= ( NS(multipole_order_t) )0 )
+        ? ( NS(buffer_size_t) )( 2 * multipole->order + 2 )
+        : ( NS(buffer_size_t) )0;
 }
 
-SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* NS(MultiPole_get_bal)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(buffer_addr_t) NS(Multipole_bal_addr)( SIXTRL_BE_ARGPTR_DEC
+    const NS(Multipole) *const SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_BE_DATAPTR_DEC  NS(multipole_real_t)* ptr_ptr_bal_t;
-    return ( ptr_ptr_bal_t )NS(MultiPole_get_const_bal)( multipole );
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    return multipole->bal_addr;
 }
 
-SIXTRL_INLINE NS(multipole_real_t) NS(MultiPole_get_bal_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index )
-{
-    typedef SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* ptr_to_bal_t;
-
-    ptr_to_bal_t bal = NS(MultiPole_get_const_bal)( multipole );
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 
-    SIXTRL_ASSERT( bal != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( index < NS(MultiPole_get_bal_size)( multipole ) );
-
-    return bal[ index ];
-}
-
-SIXTRL_INLINE NS(buffer_size_t) NS(MultiPole_get_bal_size)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+NS(Multipole_const_bal_begin)( SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
-    return ( multipole != SIXTRL_NULLPTR )
-        ?  ( ( multipole->order >= ( NS(multipole_order_t ) )0 )
-                ? ( ( NS(buffer_size_t) )( 2 * multipole->order + 2 ) )
-                : ( ( NS(buffer_size_t) )0u ) )
-        :  ( ( NS(buffer_size_t) )0u );
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    return ( SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* )(
+                uintptr_t )multipole->bal_addr;
 }
 
-
-SIXTRL_INLINE NS(multipole_real_t) NS(MultiPole_get_knl_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+NS(Multipole_const_bal_end)( SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    buf_size_t const bal_index = ( buf_size_t )2u * index;
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* bal_end =
+        NS(Multipole_const_bal_begin)( multipole );
 
-    return NS(MultiPole_get_bal_value)( multipole, bal_index ) *
-           NS(_calculate_factorial)( index );
+    if( bal_end != SIXTRL_NULLPTR )
+        bal_end = bal_end + NS(Multipole_bal_length)( multipole );
+
+    return bal_end;
 }
 
-SIXTRL_INLINE NS(multipole_real_t) NS(MultiPole_get_ksl_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index )
+SIXTRL_INLINE NS(multipole_real_t) NS(Multipole_bal)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const bal_index ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    buf_size_t const bal_index = ( buf_size_t )2u * index + ( buf_size_t )1u;
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* bal_begin =
+        NS(Multipole_const_bal_begin)( multipole );
 
-    return NS(MultiPole_get_bal_value)( multipole, bal_index ) *
-           NS(_calculate_factorial)( index );
+    SIXTRL_ASSERT( bal_begin != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Multipole_bal_length)( multipole ) > bal_index );
+    return bal_begin[ bal_index ];
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_length)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_real_t) const length )
+SIXTRL_INLINE NS(multipole_real_t) NS(Multipole_knl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(multipole_order_t) const knl_index ) SIXTRL_NOEXCEPT
 {
-    if( multipole != SIXTRL_NULLPTR ) multipole->length = length;
-    return;
+    NS(buffer_size_t) const idx = ( NS(buffer_size_t) )( 2 * knl_index );
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( knl_index >= ( NS(multipole_order_t) )0 );
+    SIXTRL_ASSERT( knl_index <= NS(Multipole_order)( multipole ) );
+    return NS(Multipole_bal)( multipole, idx ) * NS(Math_factorial)( knl_index );
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_hxl)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_real_t) const hxl )
+SIXTRL_INLINE NS(multipole_real_t) NS(Multipole_ksl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT multipole,
+    NS(multipole_order_t) const ksl_index ) SIXTRL_NOEXCEPT
 {
-    if( multipole != SIXTRL_NULLPTR ) multipole->hxl = hxl;
-    return;
+    NS(buffer_size_t) const idx = ( NS(buffer_size_t) )( 2 * ksl_index + 1 );
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ksl_index >= ( NS(multipole_order_t) )0 );
+    SIXTRL_ASSERT( ksl_index <= NS(Multipole_order)( multipole ) );
+    return NS(Multipole_bal)( multipole, idx ) * NS(Math_factorial)( ksl_index );
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_hyl)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_real_t) const hyl )
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)*
+NS(Multipole_bal_begin)( SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
-    if( multipole != SIXTRL_NULLPTR ) multipole->hyl = hyl;
-    return;
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    return ( SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* )(
+                uintptr_t )multipole->bal_addr;
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_order)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_order_t) const order )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)*
+NS(Multipole_bal_end)( SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
-    #if !defined( NDEBUG ) && !defined( _GPUCODE )
-    SIXTRL_STATIC_VAR NS(multipole_order_t) const
-        INV_ORDER = ( NS(multipole_order_t) )-1;
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_end =
+        NS(Multipole_bal_begin)( multipole );
 
-    SIXTRL_ASSERT( order >= INV_ORDER );
-    #endif /* !defined( NDEBUG ) && !defined( _GPUCODE ) */
+    if( bal_end != SIXTRL_NULLPTR )
+        bal_end = bal_end + NS(Multipole_bal_length)( multipole );
 
-    if( multipole != SIXTRL_NULLPTR ) multipole->order = order;
-    return;
+    return bal_end;
 }
 
-SIXTRL_INLINE void NS(MultiPole_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole )
-{
-    typedef NS(buffer_size_t)    buf_size_t;
-    typedef NS(multipole_real_t) mp_real_t;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    buf_size_t const bal_size = NS(MultiPole_get_bal_size)( multipole );
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const length ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    multipole->length = length;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
 
-    NS(MultiPole_set_length)( multipole, ( mp_real_t )0 );
-    NS(MultiPole_set_hxl)( multipole,    ( mp_real_t )0 );
-    NS(MultiPole_set_hyl)( multipole,    ( mp_real_t )0 );
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_hxl)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const hxl ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    multipole->hxl = hxl;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
 
-    if( bal_size > ( buf_size_t )0 )
-    {
-        SIXTRL_STATIC_VAR mp_real_t const ZERO = ( mp_real_t )0;
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_hyl)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const hyl ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    multipole->hyl = hyl;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
 
-        SIXTRL_BE_DATAPTR_DEC mp_real_t* bal_begin =
-            NS(MultiPole_get_bal)( multipole );
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_order)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_order_t) const order ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-        SIXTRACKLIB_SET_VALUES( mp_real_t, bal_begin, bal_size, ZERO );
+    if( ( multipole != SIXTRL_NULLPTR ) &&
+        ( order >= ( NS(multipole_order_t) )0 ) )
+    {
+        multipole->order = order;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return;
+    return status;
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_bal)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    SIXTRL_BE_ARGPTR_DEC NS(multipole_real_t) const* SIXTRL_RESTRICT bal )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_bal_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(buffer_addr_t) const bal_addr ) SIXTRL_NOEXCEPT
 {
-    NS(buffer_size_t) const bal_size = NS(MultiPole_get_bal_size)( multipole );
-
-    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* dest =
-        NS(MultiPole_get_bal)( multipole );
-
-    SIXTRACKLIB_COPY_VALUES( NS(multipole_real_t), dest, bal, bal_size );
-
-    return;
+    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    multipole->bal_addr = bal_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_knl)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    SIXTRL_BE_ARGPTR_DEC NS(multipole_real_t) const* SIXTRL_RESTRICT knl )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_bal_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const bal_index,
+    NS(multipole_real_t) const bal_value ) SIXTRL_NOEXCEPT
 {
-    NS(multipole_order_t) const order = NS(MultiPole_get_order)( multipole );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    SIXTRL_BE_ARGPTR_DEC NS(multipole_real_t)* bal =
-        NS(MultiPole_get_bal)( multipole );
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_begin =
+        NS(Multipole_bal_begin)( multipole );
 
-    if( ( order >= 0 ) &&
-        ( bal != SIXTRL_NULLPTR ) &&
-        ( knl != SIXTRL_NULLPTR ) )
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_begin != SIXTRL_NULLPTR ) &&
+        ( bal_index < NS(Multipole_bal_length)( multipole ) ) )
     {
-        bal[ 0 ] = knl[ 0 ];
-
-        if( order > 0 )
-        {
-            NS(multipole_order_t)    ii = 1;
-            NS(buffer_size_t) jj = ( NS(buffer_size_t) )2u;
-            NS(multipole_real_t)   fact = ( NS(multipole_real_t) )1;
-
-            for( ; ii <= order ; jj += 2u,
-                    fact *= ( NS(multipole_real_t) )ii++ )
-            {
-                SIXTRL_ASSERT( fact > ( NS(multipole_real_t) )0 );
-                bal[ jj ] = knl[ ii ] / fact;
-            }
-        }
+        bal_begin[ bal_index ] = bal_value;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return;
+    return status;
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_ksl)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    SIXTRL_BE_ARGPTR_DEC NS(multipole_real_t) const* SIXTRL_RESTRICT ksl )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_all_bal_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const bal_value ) SIXTRL_NOEXCEPT
 {
-    NS(multipole_order_t) const order = NS(MultiPole_get_order)( multipole );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    SIXTRL_BE_ARGPTR_DEC NS(multipole_real_t)* bal =
-        NS(MultiPole_get_bal)( multipole );
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_it =
+            NS(Multipole_bal_begin)( multipole );
 
-    if( ( order >= 0 ) &&
-        ( bal != SIXTRL_NULLPTR ) && ( ksl != SIXTRL_NULLPTR ) )
-    {
-        bal[ 1 ] = ksl[ 0 ];
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_end =
+        NS(Multipole_bal_begin)( multipole );
 
-        if( order > 0 )
-        {
-            NS(multipole_order_t)    ii = 1;
-            NS(buffer_size_t) jj = ( NS(buffer_size_t) )3u;
-            NS(multipole_real_t)   fact = ( NS(multipole_real_t) )1;
-
-            for( ; ii <= order ; jj += 2u,
-                    fact *= ( NS(multipole_real_t) )ii++ )
-            {
-                SIXTRL_ASSERT( fact > ( NS(multipole_real_t) )0 );
-                bal[ jj ] = ksl[ ii ] / fact;
-            }
-        }
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_it != SIXTRL_NULLPTR ) &&
+        ( bal_end != SIXTRL_NULLPTR ) )
+    {
+        SIXTRL_ASSERT( ( ( uintptr_t )bal_it ) <= ( uintptr_t )bal_end );
+        for( ; bal_it != bal_end ; ++bal_it ) *bal_it = bal_value;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return;
+    return status;
 }
 
-SIXTRL_INLINE void NS(MultiPole_assign_bal)(
-    SIXTRL_BE_ARGPTR_DEC  NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(multipole_order_t) const order,
-    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* SIXTRL_RESTRICT bal_ptr )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_bal)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+        SIXTRL_RESTRICT in_bal_it ) SIXTRL_NOEXCEPT
 {
-    typedef NS(multipole_order_t) mp_order_t;
-    SIXTRL_STATIC_VAR mp_order_t const ZERO_ORDER = ( mp_order_t )0;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_it =
+            NS(Multipole_bal_begin)( multipole );
 
-    if( ( multipole != SIXTRL_NULLPTR ) &&
-        ( ( ( order <  ZERO_ORDER ) && ( bal_ptr == SIXTRL_NULLPTR ) ) ||
-          ( ( order >= ZERO_ORDER ) && ( bal_ptr != SIXTRL_NULLPTR ) ) ) )
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_end =
+        NS(Multipole_bal_end)( multipole );
+
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_it  != SIXTRL_NULLPTR ) &&
+        ( in_bal_it != SIXTRL_NULLPTR ) && ( bal_end != SIXTRL_NULLPTR ) )
     {
-        multipole->order = order;
-        multipole->bal   = bal_ptr;
+        SIXTRL_ASSERT( ( ( uintptr_t )bal_it ) <= ( uintptr_t )bal_end );
+        for( ; bal_it != bal_end ; ++bal_it, ++in_bal_it ) *bal_it = *in_bal_it;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return;
+    return status;
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_bal_value)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index, NS(multipole_real_t) const bal_value )
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_knl_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const knl_index,
+    NS(multipole_real_t) const knl_value ) SIXTRL_NOEXCEPT
 {
-    typedef NS(multipole_real_t)                mp_real_t;
-    typedef NS(buffer_size_t)                   buf_size_t;
-    typedef SIXTRL_BE_DATAPTR_DEC mp_real_t*    ptr_to_bal_t;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_values =
+        NS(Multipole_bal_begin)( multipole );
 
-    ptr_to_bal_t bal          = NS(MultiPole_get_bal)( multipole );
-    buf_size_t const bal_size = NS(MultiPole_get_bal_size)( multipole );
+    NS(buffer_size_t) const bal_index = ( NS(buffer_size_t) )( 2 * knl_index );
 
-    if( ( bal_size > index ) && ( bal != SIXTRL_NULLPTR ) )
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) &&
+        ( bal_index < NS(Multipole_bal_length)( multipole ) ) )
     {
-        bal[ index ] = bal_value;
+        bal_values[ bal_index ] = knl_value / NS(Math_factorial)( knl_index );
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return;
+    return status;
 }
 
-SIXTRL_INLINE void NS(MultiPole_set_knl_value)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index,
-    NS(multipole_real_t)  const knl_value )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_all_knl_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const knl_value ) SIXTRL_NOEXCEPT
 {
-    NS(multipole_real_t) const bal_value = knl_value / (
-        ( NS(multipole_real_t) )NS(_calculate_factorial)( index ) );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    NS(MultiPole_set_bal_value)( multipole, 2u * index, bal_value );
-    return;
-}
-
-SIXTRL_INLINE void NS(MultiPole_set_ksl_value)(
-    SIXTRL_BE_ARGPTR_DEC NS(MultiPole)* SIXTRL_RESTRICT multipole,
-    NS(buffer_size_t) const index,
-    NS(multipole_real_t) const ksl_value )
-{
-    NS(multipole_real_t) const bal_value = ksl_value / (
-        ( NS(multipole_real_t) )NS(_calculate_factorial)( index ) );
-
-    NS(MultiPole_set_bal_value)( multipole, 2u * index + 1u, bal_value );
-    return;
-}
-
-SIXTRL_INLINE int NS(MultiPole_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT rhs )
-{
-    int compare_value = -1;
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_values =
+        NS(Multipole_bal_begin)( multipole );
 
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) )
     {
-        compare_value = 0;
-
-        if( NS(MultiPole_get_order)( lhs ) >
-            NS(MultiPole_get_order)( rhs ) )
-        {
-            compare_value = +1;
-        }
-        else if( NS(MultiPole_get_order)( lhs ) <
-                 NS(MultiPole_get_order)( rhs ) )
-        {
-            compare_value = -1;
-        }
-
-        if( compare_value == 0 )
-        {
-            if( NS(MultiPole_get_length)( lhs ) >
-                NS(MultiPole_get_length)( rhs ) )
-            {
-                compare_value = +1;
-            }
-            else if( NS(MultiPole_get_length)( lhs ) <
-                     NS(MultiPole_get_length)( rhs ) )
-            {
-                compare_value = -1;
-            }
-        }
+        NS(multipole_order_t) knl_index = ( NS(multipole_order_t) )0;
+        NS(buffer_size_t) ii = ( NS(buffer_size_t) )0;
+        NS(buffer_size_t) const nn = NS(Multipole_bal_length)( multipole );
 
-        if( compare_value == 0 )
+        for( ; ii < nn ; ii += 2u, ++knl_index )
         {
-            if( NS(MultiPole_get_hxl)( lhs ) >
-                NS(MultiPole_get_hxl)( rhs ) )
-            {
-                compare_value = +1;
-            }
-            else if( NS(MultiPole_get_hxl)( lhs ) <
-                     NS(MultiPole_get_hxl)( rhs ) )
-            {
-                compare_value = -1;
-            }
+            bal_values[ ii ] = knl_value / NS(Math_factorial)( knl_index );
         }
 
-        if( compare_value == 0 )
-        {
-            if( NS(MultiPole_get_hyl)( lhs ) >
-                NS(MultiPole_get_hyl)( rhs ) )
-            {
-                compare_value = +1;
-            }
-            else if( NS(MultiPole_get_hyl)( lhs ) <
-                     NS(MultiPole_get_hyl)( rhs ) )
-            {
-                compare_value = -1;
-            }
-        }
-
-        if( ( compare_value == 0 ) &&
-            ( NS(MultiPole_get_order)( lhs ) > 0 ) )
-        {
-            SIXTRL_ASSERT( NS(MultiPole_get_const_bal)( lhs ) != SIXTRL_NULLPTR );
-            SIXTRL_ASSERT( NS(MultiPole_get_const_bal)( rhs ) != SIXTRL_NULLPTR );
-
-            SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* lhs_it =
-                NS(MultiPole_get_const_bal)( lhs );
-
-            SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* lhs_end =
-                lhs_it + NS(MultiPole_get_bal_size)( lhs );
-
-            SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* rhs_it =
-                NS(MultiPole_get_const_bal)( rhs );
-
-            for( ; lhs_it != lhs_end ; ++lhs_it, ++rhs_it )
-            {
-                if( *lhs_it > *rhs_it )
-                {
-                    compare_value = +1;
-                }
-                else if( *lhs_it < *rhs_it )
-                {
-                    compare_value = -1;
-                }
-
-                break;
-            }
-        }
-    }
-    else if( rhs != SIXTRL_NULLPTR )
-    {
-        compare_value = +1;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return compare_value;
+    return status;
 }
 
-SIXTRL_INLINE int NS(MultiPole_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT rhs,
-    NS(multipole_real_t) const treshold )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_knl)(
+    SIXTRL_BE_DATAPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+        SIXTRL_RESTRICT knl_begin ) SIXTRL_NOEXCEPT
 {
-    typedef NS(multipole_real_t) real_t;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0.0;
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_values =
+        NS(Multipole_bal_begin)( multipole );
 
-    int compare_value = -1;
-
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) &&
-        ( treshold > ZERO ) )
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) &&
+        ( knl_begin != SIXTRL_NULLPTR ) )
     {
-        compare_value = 0;
+        NS(multipole_order_t) knl_index = ( NS(multipole_order_t) )0;
+        NS(buffer_size_t) ii = ( NS(buffer_size_t) )0;
+        NS(buffer_size_t) const nn = NS(Multipole_bal_length)( multipole );
 
-        if( NS(MultiPole_get_order)( lhs ) >
-            NS(MultiPole_get_order)( rhs ) )
+        for( ; ii < nn ; ii += 2u, ++knl_index )
         {
-            compare_value = +1;
-        }
-        else if( NS(MultiPole_get_order)( lhs ) <
-                 NS(MultiPole_get_order)( rhs ) )
-        {
-            compare_value = -1;
+            bal_values[ ii ] = knl_begin[ knl_index ] /
+                NS(Math_factorial)( knl_index );
         }
 
-        if( compare_value == 0 )
-        {
-            real_t const diff = NS(MultiPole_get_length)( lhs ) -
-                                NS(MultiPole_get_length)( rhs );
-
-            real_t const abs_diff = ( diff > ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            real_t const diff = NS(MultiPole_get_hxl)( lhs ) -
-                                NS(MultiPole_get_hxl)( rhs );
-
-            real_t const abs_diff = ( diff > ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            real_t const diff = NS(MultiPole_get_hyl)( lhs ) -
-                                NS(MultiPole_get_hyl)( rhs );
-
-            real_t const abs_diff = ( diff > ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( ( compare_value == 0 ) &&
-            ( NS(MultiPole_get_order)( lhs ) > 0 ) )
-        {
-            SIXTRL_ASSERT( NS(MultiPole_get_const_bal)( lhs ) != SIXTRL_NULLPTR );
-            SIXTRL_ASSERT( NS(MultiPole_get_const_bal)( rhs ) != SIXTRL_NULLPTR );
-
-            SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* lhs_it =
-                NS(MultiPole_get_const_bal)( lhs );
-
-            SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* lhs_end =
-                lhs_it + NS(MultiPole_get_bal_size)( lhs );
-
-            SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const* rhs_it =
-                NS(MultiPole_get_const_bal)( rhs );
-
-            for( ; lhs_it != lhs_end ; ++lhs_it, ++rhs_it )
-            {
-                real_t const diff = *lhs_it - *rhs_it;
-                real_t const abs_diff = ( diff > ZERO ) ? diff : -diff;
-
-                if( abs_diff > treshold )
-                {
-                    if( diff > ZERO )
-                    {
-                        compare_value = +1;
-                    }
-                    else if( diff < ZERO )
-                    {
-                        compare_value = -1;
-                    }
-
-                    break;
-                }
-            }
-        }
-    }
-    else if( ( rhs != SIXTRL_NULLPTR ) && ( treshold > ZERO ) )
-    {
-        compare_value = +1;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return compare_value;
+    return status;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole) const*
-NS(BufferIndex_get_const_multipole)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj )
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_ksl_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const ksl_index,
+    NS(multipole_real_t) const ksl_value ) SIXTRL_NOEXCEPT
 {
-    typedef NS(MultiPole) beam_element_t;
-    typedef SIXTRL_BUFFER_OBJ_DATAPTR_DEC beam_element_t const* ptr_to_be_t;
-    ptr_to_be_t ptr_to_be = SIXTRL_NULLPTR;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_values =
+        NS(Multipole_bal_begin)( multipole );
+
+    NS(buffer_size_t) const bal_index =
+        ( NS(buffer_size_t) )( 2 * ksl_index + 1 );
 
-    if( ( index_obj != SIXTRL_NULLPTR ) &&
-        ( NS(Object_get_type_id)( index_obj ) == NS(OBJECT_TYPE_MULTIPOLE) ) &&
-        ( NS(Object_get_size)( index_obj ) >= sizeof( beam_element_t ) ) )
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) &&
+        ( bal_index < NS(Multipole_bal_length)( multipole ) ) )
     {
-        ptr_to_be = ( ptr_to_be_t )( uintptr_t
-            )NS(Object_get_begin_addr)( index_obj );
+        bal_values[ bal_index ] = ksl_value / NS(Math_factorial)( ksl_index );
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
     }
 
-    return ptr_to_be;
+    return status;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(BufferIndex_get_multipole)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_all_ksl_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    NS(multipole_real_t) const ksl_value ) SIXTRL_NOEXCEPT
 {
-    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-        )NS(BufferIndex_get_const_multipole)( index_obj );
-}
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole) const*
-NS(BeamElements_managed_buffer_get_const_multipole)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
-{
-    return NS(BufferIndex_get_const_multipole)(
-        NS(ManagedBuffer_get_const_object)( pbuffer, be_index, slot_size ) );
-}
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_values =
+        NS(Multipole_bal_begin)( multipole );
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(BeamElements_managed_buffer_get_multipole)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
-{
-    return NS(BufferIndex_get_multipole)(
-        NS(ManagedBuffer_get_object)( pbuffer, be_index, slot_size ) );
-}
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) )
+    {
+        NS(multipole_order_t) ksl_index = ( NS(multipole_order_t) )0;
+        NS(buffer_size_t) ii = ( NS(buffer_size_t) )1;
+        NS(buffer_size_t) const nn = NS(Multipole_bal_length)( multipole );
 
-#if !defined( _GPUCODE )
+        for( ; ii < nn ; ii += 2u, ++ksl_index )
+        {
+            bal_values[ ii ] = ksl_value / NS(Math_factorial)( ksl_index );
+        }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole) const*
-NS(BeamElements_buffer_get_const_multipole)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
-{
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_const_multipole)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
-}
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)*
-NS(BeamElements_buffer_get_multipole)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const be_index )
-{
-    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_raw_t;
-    return NS(BeamElements_managed_buffer_get_multipole)(
-        ( ptr_raw_t )( uintptr_t )NS(Buffer_get_data_begin_addr)( buffer ),
-        be_index, NS(Buffer_get_slot_size)( buffer ) );
+    return status;
 }
 
-SIXTRL_INLINE bool NS(MultiPole_can_be_added)(
-    SIXTRL_BE_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(multipole_order_t) const order,
-    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
-    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs )
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_set_ksl)(
+    SIXTRL_BE_DATAPTR_DEC NS(Multipole)* SIXTRL_RESTRICT multipole,
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t) const*
+        SIXTRL_RESTRICT ksl_begin ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-
-    buf_size_t const bal_size = ( buf_size_t )2u + ( ( order >= 0 )
-        ? ( buf_size_t )2u * order : ( buf_size_t )0u );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    buf_size_t const num_dataptrs = ( buf_size_t )1u;
-    buf_size_t const sizes[]  = { sizeof( NS(multipole_real_t) ) };
-    buf_size_t const counts[] = { bal_size };
-
-    return NS(Buffer_can_add_object)( buffer, sizeof( NS(MultiPole) ),
-            num_dataptrs, sizes, counts, ptr_requ_objects, ptr_requ_slots,
-                ptr_requ_dataptrs );
-}
+    SIXTRL_BE_DATAPTR_DEC NS(multipole_real_t)* bal_values =
+        NS(Multipole_bal_begin)( multipole );
 
+    if( ( multipole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) &&
+        ( ksl_begin != SIXTRL_NULLPTR ) )
+    {
+        NS(multipole_order_t) ksl_index = ( NS(multipole_order_t) )0;
+        NS(buffer_size_t) ii = ( NS(buffer_size_t) )1;
+        NS(buffer_size_t) const nn = NS(Multipole_bal_length)( multipole );
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)* NS(MultiPole_new)(
-    SIXTRL_BE_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(multipole_order_t) const order )
-{
-    typedef NS(MultiPole)                       elem_t;
-    typedef NS(buffer_size_t)                   buf_size_t;
-    typedef SIXTRL_BE_ARGPTR_DEC elem_t*        ptr_to_elem_t;
-    typedef SIXTRL_BE_ARGPTR_DEC NS(Object)*    ptr_to_obj_t;
-    typedef NS(multipole_real_t)                real_t;
+        for( ; ii < nn ; ii += 2u, ++ksl_index )
+        {
+            bal_values[ ii ] = ksl_begin[ ksl_index ] /
+                NS(Math_factorial)( ksl_index );
+        }
 
-    ptr_to_obj_t ptr_obj = SIXTRL_NULLPTR;
-    buf_size_t const obj_size = sizeof( elem_t );
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
 
-    NS(object_type_id_t) const type_id = NS(OBJECT_TYPE_MULTIPOLE);
+    return status;
+}
 
-    elem_t temp_obj;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    temp_obj.order  = order;
-    temp_obj.bal    = SIXTRL_NULLPTR;
-    temp_obj.length = ( real_t )0.0;
-    temp_obj.hxl    = ( real_t )0.0;
-    temp_obj.hyl    = ( real_t )0.0;
+SIXTRL_INLINE NS(arch_status_t) NS(Multipole_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(Multipole)* SIXTRL_RESTRICT dst,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT src
+) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    if( order >= ( NS(multipole_order_t) )0 )
+    if( ( dst != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
     {
-        buf_size_t const bal_size     = ( buf_size_t )( 2 * order + 2 );
-        buf_size_t const num_dataptrs = ( buf_size_t )1u;
-
-        buf_size_t const offsets[]    = { offsetof( elem_t, bal ) };
-        buf_size_t const sizes[]      = { sizeof( real_t ) };
-        buf_size_t const counts[]     = { bal_size };
+        if( ( src != dst ) &&
+            ( NS(Multipole_order)( src ) == NS(Multipole_order)( dst ) ) )
+        {
+            status  = NS(Multipole_set_length)(
+                dst, NS(Multipole_length)( src ) );
 
-        SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+            status |= NS(Multipole_set_hxl)(
+                dst, NS(Multipole_hxl)( src ) );
 
-        ptr_obj = NS(Buffer_add_object)( buffer, &temp_obj, obj_size , type_id,
-                num_dataptrs, offsets, sizes, counts );
-    }
-    else
-    {
-        buf_size_t const num_dataptrs = ( buf_size_t )0u;
+            status |= NS(Multipole_set_hyl)(
+                dst, NS(Multipole_hyl)( src ) );
 
-        ptr_obj = NS(Buffer_add_object)( buffer, &temp_obj, obj_size , type_id,
-                num_dataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR );
+            status |= NS(Multipole_set_bal)( dst,
+                        NS(Multipole_const_bal_begin)( src ) );
+        }
+        else if( src == dst )
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+        }
     }
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)( ptr_obj );
+    return status;
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)* NS(MultiPole_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(multipole_order_t) const order,
-    SIXTRL_BUFFER_DATAPTR_DEC NS(multipole_real_t) const* SIXTRL_RESTRICT ptr_to_bal,
-    NS(multipole_real_t)  const length,
-    NS(multipole_real_t)  const hxl,
-    NS(multipole_real_t)  const hyl )
-{
-    typedef NS(MultiPole)                               elem_t;
-    typedef NS(buffer_size_t)                           buf_size_t;
-    typedef SIXTRL_ARGPTR_DEC elem_t*                   ptr_to_elem_t;
-    typedef SIXTRL_ARGPTR_DEC NS(Object)*               ptr_to_obj_t;
-    typedef SIXTRL_ARGPTR_DEC NS(multipole_real_t )*    ptr_to_bal_t;
-
-    SIXTRL_STATIC_VAR NS(multipole_order_t) const INV_ORDER =
-        ( NS(multipole_order_t) )-1;
-
-    ptr_to_obj_t ptr_obj = SIXTRL_NULLPTR;
-    buf_size_t const obj_size = sizeof( elem_t );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    NS(object_type_id_t) const type_id = NS(OBJECT_TYPE_MULTIPOLE);
-
-    elem_t temp_obj;
-    NS(MultiPole_set_length)( &temp_obj, length );
-    NS(MultiPole_set_hxl)(    &temp_obj, hxl );
-    NS(MultiPole_set_hyl)(    &temp_obj, hyl );
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Multipole) const*
+NS(Multipole_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_BE_ARGPTR_DEC NS(Multipole) const* ptr_multipole_t;
+    ptr_multipole_t elem = SIXTRL_NULLPTR;
 
-    if( order > INV_ORDER )
+    if( ( obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_MULTIPOLE) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(Multipole) ) ) )
     {
-        buf_size_t const num_dataptrs = ( buf_size_t )1u;
-
-        buf_size_t const offsets[] =
-        {
-            offsetof( elem_t, bal )
-        };
-
-        buf_size_t const sizes[] =
-        {
-            sizeof( NS(multipole_real_t) )
-        };
+        elem = ( ptr_multipole_t )( uintptr_t )NS(Object_get_begin_addr)( obj );
+    }
 
-        buf_size_t const counts[] =
-        {
-            ( buf_size_t )( 2 * order + 2 )
-        };
+    return elem;
+}
 
-        if( ptr_to_bal != SIXTRL_NULLPTR )
-        {
-            NS(MultiPole_assign_bal)(
-                &temp_obj, order, ( ptr_to_bal_t )ptr_to_bal );
-        }
-        else
-        {
-            NS(MultiPole_assign_bal)( &temp_obj, INV_ORDER, SIXTRL_NULLPTR );
-            NS(MultiPole_set_order)( &temp_obj, order );
-        }
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Multipole)* NS(Multipole_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+        SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+        )NS(Multipole_const_from_obj_index)( obj );
+}
 
-        SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )1u );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-        ptr_obj = NS(Buffer_add_object)( buffer, &temp_obj, obj_size , type_id,
-            num_dataptrs, offsets, sizes, counts );
-    }
-    else
-    {
-        buf_size_t const num_dataptrs = ( buf_size_t )0u;
-        NS(MultiPole_assign_bal)( &temp_obj, INV_ORDER, SIXTRL_NULLPTR );
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Multipole) const*
+NS(Multipole_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(Multipole_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
 
-        ptr_obj = NS(Buffer_add_object)( buffer, &temp_obj, obj_size, type_id,
-            num_dataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR );
-    }
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Multipole)*
+NS(Multipole_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(Multipole_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
 
-    SIXTRL_ASSERT( NS(MultiPole_get_order)( &temp_obj ) == order );
+#if !defined( _GPUCODE )
 
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)( ptr_obj );
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Multipole) const*
+NS(Multipole_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(Multipole_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(MultiPole)* NS(MultiPole_add_copy)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(Multipole)* NS(Multipole_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT multipole )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    return NS(MultiPole_add)( buffer,
-        NS(MultiPole_get_order)( multipole ),
-        NS(MultiPole_get_const_bal)( multipole ),
-        NS(MultiPole_get_length)( multipole ),
-        NS(MultiPole_get_hxl)( multipole ),
-        NS(MultiPole_get_hyl)( multipole ) );
+    return NS(Multipole_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
 }
 
-#endif /* !defined( _GPUCODE ) */
-
+#endif /* Host */
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRACKLIB_COMMON_BE_MULTIPOLE_BEAM_ELEMENT_MULTIPOLE_H__ */
-/* end: sixtracklib/common/be_multipole/be_multipole.h  */
diff --git a/sixtracklib/common/be_multipole/be_multipole.hpp b/sixtracklib/common/be_multipole/be_multipole.hpp
index a4e9ca0f..e78da855 100644
--- a/sixtracklib/common/be_multipole/be_multipole.hpp
+++ b/sixtracklib/common/be_multipole/be_multipole.hpp
@@ -22,11 +22,11 @@
 namespace SIXTRL_CXX_NAMESPACE
 {
     /* ===================================================================== *
-     * ====  TMultiPole< T >:
+     * ====  TMultipole< T >:
      * ===================================================================== */
 
     template< typename T >
-    struct TMultiPole
+    struct TMultipole
     {
         using value_type = T;
         using type_id_t  = NS(object_type_id_t);
@@ -34,17 +34,17 @@ namespace SIXTRL_CXX_NAMESPACE
         using size_type  = NS(buffer_size_t);
         using buffer_t   = ::NS(Buffer);
 
-        SIXTRL_FN TMultiPole() = default;
-        SIXTRL_FN TMultiPole( TMultiPole< T > const& other ) = default;
-        SIXTRL_FN TMultiPole( TMultiPole< T >&& other ) = default;
+        SIXTRL_FN TMultipole() = default;
+        SIXTRL_FN TMultipole( TMultipole< T > const& other ) = default;
+        SIXTRL_FN TMultipole( TMultipole< T >&& other ) = default;
 
-        SIXTRL_FN TMultiPole< T >& operator=(
-            TMultiPole< T > const& rhs ) = default;
+        SIXTRL_FN TMultipole< T >& operator=(
+            TMultipole< T > const& rhs ) = default;
 
-        SIXTRL_FN TMultiPole< T >& operator=(
-            TMultiPole< T >&& rhs ) = default;
+        SIXTRL_FN TMultipole< T >& operator=(
+            TMultipole< T >&& rhs ) = default;
 
-        SIXTRL_FN ~TMultiPole() = default;
+        SIXTRL_FN ~TMultipole() = default;
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
@@ -56,17 +56,17 @@ namespace SIXTRL_CXX_NAMESPACE
             SIXTRL_ARGPTR_DEC size_type* SIXTRL_RESTRICT ptr_requ_dataptrs
             ) SIXTRL_NOEXCEPT;
 
-        SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC TMultiPole< T >*
+        SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC TMultipole< T >*
         CreateNewOnBuffer( buffer_t& SIXTRL_RESTRICT_REF buffer,
                            order_type const order );
 
-        SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC TMultiPole< T >*
+        SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC TMultipole< T >*
         AddToBuffer( buffer_t& SIXTRL_RESTRICT_REF buffer,
             order_type const order  = order_type{ 0 },
-            SIXTRL_DATAPTR_DEC value_type const* SIXTRL_RESTRICT bal = nullptr,
             value_type const length = value_type{ 0.0 },
             value_type const hxl    = value_type{ 0.0 },
-            value_type const hyl    = value_type{ 0.0 } );
+            value_type const hyl    = value_type{ 0.0 },
+            SIXTRL_DATAPTR_DEC value_type const* SIXTRL_RESTRICT bal = nullptr );
 
         SIXTRL_FN SIXTRL_STATIC value_type Factorial(
             size_type n ) SIXTRL_NOEXCEPT;
@@ -165,48 +165,48 @@ namespace SIXTRL_CXX_NAMESPACE
     };
 
     template< typename T >
-    SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole_new( Buffer& SIXTRL_RESTRICT_REF buffer,
-                    typename TMultiPole< T >::order_type const order );
+    SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole_new( Buffer& SIXTRL_RESTRICT_REF buffer,
+                    typename TMultipole< T >::order_type const order );
 
     template< typename T >
-    SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole_new( SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
-                    typename TMultiPole< T >::order_type const order );
+    SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole_new( SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
+                    typename TMultipole< T >::order_type const order );
 
     template< typename T >
-    SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole_add( Buffer& SIXTRL_RESTRICT_REF buffer,
-        typename TMultiPole< T >::order_type const order,
-        SIXTRL_DATAPTR_DEC typename TMultiPole< T >::value_type const*
-            SIXTRL_RESTRICT bal = nullptr,
-        typename TMultiPole< T >::value_type const& length =
-            typename TMultiPole< T >::value_type{},
-        typename TMultiPole< T >::value_type const& hxl =
-            typename TMultiPole< T >::value_type{},
-        typename TMultiPole< T >::value_type const& hyl =
-            typename TMultiPole< T >::value_type{} );
+    SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole_add( Buffer& SIXTRL_RESTRICT_REF buffer,
+        typename TMultipole< T >::order_type const order,
+        typename TMultipole< T >::value_type const& length =
+            typename TMultipole< T >::value_type{},
+        typename TMultipole< T >::value_type const& hxl =
+            typename TMultipole< T >::value_type{},
+        typename TMultipole< T >::value_type const& hyl =
+            typename TMultipole< T >::value_type{},
+        SIXTRL_DATAPTR_DEC typename TMultipole< T >::value_type const*
+            SIXTRL_RESTRICT bal = nullptr );
 
     template< typename T >
-    SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole_add(
+    SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole_add(
         SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
-        typename TMultiPole< T >::order_type const order,
-        SIXTRL_DATAPTR_DEC typename TMultiPole< T >::value_type const*
-            SIXTRL_RESTRICT bal = nullptr,
-        typename TMultiPole< T >::value_type const& length =
-            typename TMultiPole< T >::value_type{},
-        typename TMultiPole< T >::value_type const& hxl =
-            typename TMultiPole< T >::value_type{},
-        typename TMultiPole< T >::value_type const& hyl =
-            typename TMultiPole< T >::value_type{} );
+        typename TMultipole< T >::order_type const order,
+        typename TMultipole< T >::value_type const& length =
+            typename TMultipole< T >::value_type{},
+        typename TMultipole< T >::value_type const& hxl =
+            typename TMultipole< T >::value_type{},
+        typename TMultipole< T >::value_type const& hyl =
+            typename TMultipole< T >::value_type{},
+        SIXTRL_DATAPTR_DEC typename TMultipole< T >::value_type const*
+            SIXTRL_RESTRICT bal = nullptr );
 
     /* ===================================================================== *
-     * ====  TMultiPole< SIXTRL_REAL_T >:
+     * ====  TMultipole< SIXTRL_REAL_T >:
      * ===================================================================== */
 
     template<>
-    struct TMultiPole< SIXTRL_REAL_T > : public ::NS(MultiPole)
+    struct TMultipole< SIXTRL_REAL_T > : public ::NS(Multipole)
     {
         using value_type = SIXTRL_REAL_T;
         using type_id_t  = NS(object_type_id_t);
@@ -214,23 +214,23 @@ namespace SIXTRL_CXX_NAMESPACE
         using order_t    = order_type;
         using size_type  = NS(buffer_size_t);
         using buffer_t   = ::NS(Buffer);
-        using c_api_t    = ::NS(MultiPole);
+        using c_api_t    = ::NS(Multipole);
 
-        SIXTRL_FN TMultiPole() = default;
+        SIXTRL_FN TMultipole() = default;
 
-        SIXTRL_FN TMultiPole(
-            TMultiPole< SIXTRL_REAL_T > const& other ) = default;
+        SIXTRL_FN TMultipole(
+            TMultipole< SIXTRL_REAL_T > const& other ) = default;
 
-        SIXTRL_FN TMultiPole(
-            TMultiPole< SIXTRL_REAL_T >&& other ) = default;
+        SIXTRL_FN TMultipole(
+            TMultipole< SIXTRL_REAL_T >&& other ) = default;
 
-        SIXTRL_FN TMultiPole< SIXTRL_REAL_T >& operator=(
-            TMultiPole< SIXTRL_REAL_T > const& rhs ) = default;
+        SIXTRL_FN TMultipole< SIXTRL_REAL_T >& operator=(
+            TMultipole< SIXTRL_REAL_T > const& rhs ) = default;
 
-        SIXTRL_FN TMultiPole< SIXTRL_REAL_T >& operator=(
-            TMultiPole< SIXTRL_REAL_T >&& rhs ) = default;
+        SIXTRL_FN TMultipole< SIXTRL_REAL_T >& operator=(
+            TMultipole< SIXTRL_REAL_T >&& rhs ) = default;
 
-        SIXTRL_FN ~TMultiPole() = default;
+        SIXTRL_FN ~TMultipole() = default;
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
@@ -243,17 +243,17 @@ namespace SIXTRL_CXX_NAMESPACE
             SIXTRL_ARGPTR_DEC size_type* SIXTRL_RESTRICT
                 ptr_requ_dataptrs = nullptr ) SIXTRL_NOEXCEPT;
 
-        SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC TMultiPole< SIXTRL_REAL_T >*
+        SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC TMultipole< SIXTRL_REAL_T >*
         CreateNewOnBuffer( buffer_t& SIXTRL_RESTRICT_REF buffer,
                            order_type const order );
 
-        SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC TMultiPole< SIXTRL_REAL_T >*
+        SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC TMultipole< SIXTRL_REAL_T >*
         AddToBuffer( buffer_t& SIXTRL_RESTRICT_REF buffer,
             order_type const order,
-            SIXTRL_DATAPTR_DEC value_type const* SIXTRL_RESTRICT bal,
             value_type const length,
             value_type const hxl,
-            value_type const hyl );
+            value_type const hyl,
+            SIXTRL_DATAPTR_DEC value_type const* SIXTRL_RESTRICT bal );
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
@@ -337,17 +337,17 @@ namespace SIXTRL_CXX_NAMESPACE
             size_type n ) SIXTRL_NOEXCEPT;
     };
 
-    using MultiPole = TMultiPole< SIXTRL_REAL_T >;
+    using Multipole = TMultipole< SIXTRL_REAL_T >;
 
-    SIXTRL_ARGPTR_DEC MultiPole* MultiPole_new(
+    SIXTRL_ARGPTR_DEC Multipole* Multipole_new(
         Buffer& SIXTRL_RESTRICT_REF buffer,
         ::NS(multipole_order_t) const order );
 
-    SIXTRL_ARGPTR_DEC MultiPole* MultiPole_new(
+    SIXTRL_ARGPTR_DEC Multipole* Multipole_new(
         SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
         ::NS(multipole_order_t) const order );
 
-    SIXTRL_ARGPTR_DEC MultiPole* MultiPole_add(
+    SIXTRL_ARGPTR_DEC Multipole* Multipole_add(
         Buffer& SIXTRL_RESTRICT_REF buffer,
         ::NS(multipole_order_t) const order,
         SIXTRL_DATAPTR_DEC ::NS(multipole_real_t) const*
@@ -356,7 +356,7 @@ namespace SIXTRL_CXX_NAMESPACE
         ::NS(multipole_real_t) const hxl    = ::NS(multipole_real_t){ 0.0 },
         ::NS(multipole_real_t) const hyl    = ::NS(multipole_real_t){ 0.0 } );
 
-    SIXTRL_ARGPTR_DEC MultiPole* MultiPole_add(
+    SIXTRL_ARGPTR_DEC Multipole* Multipole_add(
         SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
         ::NS(multipole_order_t) const order,
         SIXTRL_DATAPTR_DEC ::NS(multipole_real_t) const*
@@ -365,7 +365,7 @@ namespace SIXTRL_CXX_NAMESPACE
         ::NS(multipole_real_t) const hxl    = ::NS(multipole_real_t){ 0.0 },
         ::NS(multipole_real_t) const hyl    = ::NS(multipole_real_t){ 0.0 } );
 
-    template<> struct ObjectTypeTraits< ::NS(MultiPole) >
+    template<> struct ObjectTypeTraits< ::NS(Multipole) >
     {
         SIXTRL_STATIC SIXTRL_INLINE object_type_id_t Type() SIXTRL_NOEXCEPT
         {
@@ -373,7 +373,7 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     };
 
-    template<> struct ObjectTypeTraits< MultiPole >
+    template<> struct ObjectTypeTraits< Multipole >
     {
         SIXTRL_STATIC SIXTRL_INLINE object_type_id_t Type() SIXTRL_NOEXCEPT
         {
@@ -389,21 +389,21 @@ namespace SIXTRL_CXX_NAMESPACE
 namespace SIXTRL_CXX_NAMESPACE
 {
     /* ===================================================================== *
-     * ====  TMultiPole< T >:
+     * ====  TMultipole< T >:
      * ===================================================================== */
 
     template< typename T >
-    SIXTRL_INLINE bool TMultiPole< T >::CanAddToBuffer(
-        typename TMultiPole< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        typename TMultiPole< T >::order_type const order,
-        SIXTRL_ARGPTR_DEC typename TMultiPole< T >::size_type*
+    SIXTRL_INLINE bool TMultipole< T >::CanAddToBuffer(
+        typename TMultipole< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        typename TMultipole< T >::order_type const order,
+        SIXTRL_ARGPTR_DEC typename TMultipole< T >::size_type*
             SIXTRL_RESTRICT ptr_requ_objects,
-        SIXTRL_ARGPTR_DEC typename TMultiPole< T >::size_type*
+        SIXTRL_ARGPTR_DEC typename TMultipole< T >::size_type*
             SIXTRL_RESTRICT ptr_requ_slots,
-        SIXTRL_ARGPTR_DEC typename TMultiPole< T >::size_type*
+        SIXTRL_ARGPTR_DEC typename TMultipole< T >::size_type*
             SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< T >;
+        using _this_t = TMultipole< T >;
         using  size_t = typename _this_t::size_type;
 
         static_assert( std::is_trivial< _this_t >::value, "" );
@@ -418,12 +418,12 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename T >
-    SIXTRL_INLINE SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole< T >::CreateNewOnBuffer(
-        typename TMultiPole< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        typename TMultiPole< T >::order_type const order )
+    SIXTRL_INLINE SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole< T >::CreateNewOnBuffer(
+        typename TMultipole< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        typename TMultipole< T >::order_type const order )
     {
-        using _this_t = TMultiPole< T >;
+        using _this_t = TMultipole< T >;
         using size_t  = typename _this_t::size_type;
         using value_t = typename _this_t::value_type;
 
@@ -441,24 +441,24 @@ namespace SIXTRL_CXX_NAMESPACE
         size_t const sizes[]      = { sizeof( value_t ) };
         size_t const counts[]     = { static_cast< size_t >( 2 * order + 2 ) };
 
-        return static_cast< SIXTRL_ARGPTR_DEC TMultiPole< T >* >(
+        return static_cast< SIXTRL_ARGPTR_DEC TMultipole< T >* >(
             static_cast< uintptr_t >( ::NS(Object_get_begin_addr)(
                 ::NS(Buffer_add_object)( &buffer, &temp, sizeof( _this_t ),
                     type_id, num_dataptrs, offsets, sizes, counts ) ) ) );
     }
 
     template< typename T >
-    SIXTRL_INLINE SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole< T >::AddToBuffer(
-        typename TMultiPole< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        typename TMultiPole< T >::order_type const order,
-        SIXTRL_DATAPTR_DEC typename TMultiPole< T >::value_type const*
-            SIXTRL_RESTRICT bal,
-        typename TMultiPole< T >::value_type const length,
-        typename TMultiPole< T >::value_type const hxl,
-        typename TMultiPole< T >::value_type const hyl )
-    {
-        using _this_t = TMultiPole< T >;
+    SIXTRL_INLINE SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole< T >::AddToBuffer(
+        typename TMultipole< T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        typename TMultipole< T >::order_type const order,
+        typename TMultipole< T >::value_type const length,
+        typename TMultipole< T >::value_type const hxl,
+        typename TMultipole< T >::value_type const hyl,
+        SIXTRL_DATAPTR_DEC typename TMultipole< T >::value_type const*
+            SIXTRL_RESTRICT bal )
+    {
+        using _this_t = TMultipole< T >;
         using size_t  = typename _this_t::size_type;
         using value_t = typename _this_t::value_type;
 
@@ -479,39 +479,39 @@ namespace SIXTRL_CXX_NAMESPACE
         size_t const sizes[]      = { sizeof( value_t ) };
         size_t const counts[]     = { static_cast< size_t >( 2 * order + 2 ) };
 
-        return static_cast< SIXTRL_ARGPTR_DEC TMultiPole< T >* >(
+        return static_cast< SIXTRL_ARGPTR_DEC TMultipole< T >* >(
             static_cast< uintptr_t >( ::NS(Object_get_begin_addr)(
                 ::NS(Buffer_add_object)( &buffer, &temp, sizeof( _this_t ),
                     type_id, num_dataptrs, offsets, sizes, counts ) ) ) );
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type
-    TMultiPole< T >::Factorial(
-        typename TMultiPole< T >::size_type n ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type
+    TMultipole< T >::Factorial(
+        typename TMultipole< T >::size_type n ) SIXTRL_NOEXCEPT
     {
-        using size_t  = typename TMultiPole< T >::size_type;
-        using value_t = typename TMultiPole< T >::value_type;
+        using size_t  = typename TMultipole< T >::size_type;
+        using value_t = typename TMultipole< T >::value_type;
 
         return ( n > size_t{ 1 } )
                 ? ( static_cast< value_t >( n ) *
-                    TMultiPole< T >::Factorial( n - size_t{ 1 } ) )
+                    TMultipole< T >::Factorial( n - size_t{ 1 } ) )
                 : ( value_t{ 1.0 } );
     }
 
     /* ----------------------------------------------------------------- */
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::type_id_t
-    TMultiPole< T >::getTypeId() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::type_id_t
+    TMultipole< T >::getTypeId() const SIXTRL_NOEXCEPT
     {
         return NS(OBJECT_TYPE_MULTIPOLE);
     }
 
     template< typename T >
-    SIXTRL_INLINE void TMultiPole< T >::preset() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::preset() SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< T >;
+        using _this_t = TMultipole< T >;
         using order_t = typename _this_t::order_type;
         using value_t = typename _this_t::value_type;
 
@@ -525,38 +525,38 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type
-    TMultiPole< T >::getLength() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type
+    TMultipole< T >::getLength() const SIXTRL_NOEXCEPT
     {
         return this->length;
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type
-    TMultiPole< T >::getHxl() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type
+    TMultipole< T >::getHxl() const SIXTRL_NOEXCEPT
     {
         return this->hxl;
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type
-    TMultiPole< T >::getHyl() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type
+    TMultipole< T >::getHyl() const SIXTRL_NOEXCEPT
     {
         return this->hyl;
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::order_type
-    TMultiPole< T >::getOrder() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::order_type
+    TMultipole< T >::getOrder() const SIXTRL_NOEXCEPT
     {
         return this->order;
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::size_type
-    TMultiPole< T >::getBalSize() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::size_type
+    TMultipole< T >::getBalSize() const SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< T >;
+        using _this_t = TMultipole< T >;
         using  size_t = typename _this_t::size_type;
 
         return ( this->order >= 0 )
@@ -567,29 +567,29 @@ namespace SIXTRL_CXX_NAMESPACE
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type
-    TMultiPole< T >::getKnlValue(
-        typename TMultiPole< T >::size_type const index ) const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type
+    TMultipole< T >::getKnlValue(
+        typename TMultipole< T >::size_type const index ) const SIXTRL_NOEXCEPT
     {
         return this->getBalValue( 2 * index ) *
-                TMultiPole< T >::Factorial( index );
+                TMultipole< T >::Factorial( index );
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type
-    TMultiPole< T >::getKslValue(
-        typename TMultiPole< T >::size_type const index ) const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type
+    TMultipole< T >::getKslValue(
+        typename TMultipole< T >::size_type const index ) const SIXTRL_NOEXCEPT
     {
         return this->getBalValue( 2u * index + 1u ) *
-                TMultiPole< T >::Factorial( index );
+                TMultipole< T >::Factorial( index );
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type
-    TMultiPole< T >::getBalValue(
-        typename TMultiPole< T >::size_type const index ) const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type
+    TMultipole< T >::getBalValue(
+        typename TMultipole< T >::size_type const index ) const SIXTRL_NOEXCEPT
     {
-        using _this_t        = TMultiPole< T >;
+        using _this_t        = TMultipole< T >;
         using value_t        = typename _this_t::value_type;
         using ptr_to_value_t = SIXTRL_DATAPTR_DEC value_t*;
 
@@ -603,9 +603,9 @@ namespace SIXTRL_CXX_NAMESPACE
 
     template< typename T >
     template< typename Iter >
-    SIXTRL_INLINE void TMultiPole< T >::setKnl( Iter knl_begin ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setKnl( Iter knl_begin ) SIXTRL_NOEXCEPT
     {
-        using _this_t        = TMultiPole< T >;
+        using _this_t        = TMultipole< T >;
         using size_t         = typename _this_t::size_type;
         using order_t        = typename _this_t::order_type;
 
@@ -634,9 +634,9 @@ namespace SIXTRL_CXX_NAMESPACE
 
     template< typename T >
     template< typename Iter >
-    SIXTRL_INLINE void TMultiPole< T >::setKsl( Iter ksl_begin ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setKsl( Iter ksl_begin ) SIXTRL_NOEXCEPT
     {
-        using _this_t        = TMultiPole< T >;
+        using _this_t        = TMultipole< T >;
         using size_t         = typename _this_t::size_type;
         using order_t        = typename _this_t::order_type;
 
@@ -665,9 +665,9 @@ namespace SIXTRL_CXX_NAMESPACE
 
     template< typename T >
     template< typename Iter >
-    SIXTRL_INLINE void TMultiPole< T >::setBal( Iter bal_begin ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setBal( Iter bal_begin ) SIXTRL_NOEXCEPT
     {
-        using size_t = typename TMultiPole< T >::size_type;
+        using size_t = typename TMultipole< T >::size_type;
 
         size_t const bal_length = this->getBalSize();
         size_t ii = size_t{ 0 };
@@ -691,11 +691,11 @@ namespace SIXTRL_CXX_NAMESPACE
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
 
     template< typename T >
-    SIXTRL_INLINE void TMultiPole< T >::setKnlValue(
-        typename TMultiPole< T >::value_type knl_value,
-        typename TMultiPole< T >::size_type const index ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setKnlValue(
+        typename TMultipole< T >::value_type knl_value,
+        typename TMultipole< T >::size_type const index ) SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< T >;
+        using _this_t = TMultipole< T >;
         using size_t  = typename _this_t::size_type;
 
         this->setBalValue( knl_value / _this_t::Factorial( index ),
@@ -705,11 +705,11 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename T >
-    SIXTRL_INLINE void TMultiPole< T >::setKslValue(
-        typename TMultiPole< T >::value_type ksl_value,
-        typename TMultiPole< T >::size_type const index ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setKslValue(
+        typename TMultipole< T >::value_type ksl_value,
+        typename TMultipole< T >::size_type const index ) SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< T >;
+        using _this_t = TMultipole< T >;
         using size_t  = typename _this_t::size_type;
 
         this->setBalValue( ksl_value / _this_t::Factorial( index ),
@@ -719,11 +719,11 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename T >
-    SIXTRL_INLINE void TMultiPole< T >::setBalValue(
-        typename TMultiPole< T >::value_type bal_value,
-        typename TMultiPole< T >::size_type const index ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setBalValue(
+        typename TMultipole< T >::value_type bal_value,
+        typename TMultipole< T >::size_type const index ) SIXTRL_NOEXCEPT
     {
-        using _this_t        = TMultiPole< T >;
+        using _this_t        = TMultipole< T >;
         using value_t        = typename _this_t::value_type;
         using ptr_to_value_t = SIXTRL_DATAPTR_DEC value_t*;
 
@@ -740,24 +740,24 @@ namespace SIXTRL_CXX_NAMESPACE
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type const*
-    TMultiPole< T >::begin() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type const*
+    TMultipole< T >::begin() const SIXTRL_NOEXCEPT
     {
         return this->getBalBegin<>();
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type const*
-    TMultiPole< T >::end() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type const*
+    TMultipole< T >::end() const SIXTRL_NOEXCEPT
     {
         return this->getBalEnd<>();
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type*
-    TMultiPole< T >::begin() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type*
+    TMultipole< T >::begin() SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< T >;
+        using _this_t = TMultipole< T >;
         using   ptr_t = typename _this_t::value_type*;
 
         return const_cast< ptr_t >( static_cast< _this_t const& >(
@@ -765,10 +765,10 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename T >
-    SIXTRL_INLINE typename TMultiPole< T >::value_type*
-    TMultiPole< T >::end() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE typename TMultipole< T >::value_type*
+    TMultipole< T >::end() SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< T >;
+        using _this_t = TMultipole< T >;
         using   ptr_t = typename _this_t::value_type*;
 
         return const_cast< ptr_t >( static_cast< _this_t const& >(
@@ -778,10 +778,10 @@ namespace SIXTRL_CXX_NAMESPACE
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
     template< typename T > template< typename CPtr >
-    SIXTRL_INLINE CPtr TMultiPole< T >::getBalBegin() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE CPtr TMultipole< T >::getBalBegin() const SIXTRL_NOEXCEPT
     {
-        using size_t  = typename TMultiPole< T >::size_type;
-        using value_t = typename TMultiPole< T >::value_type;
+        using size_t  = typename TMultipole< T >::size_type;
+        using value_t = typename TMultipole< T >::value_type;
 
         static_assert( sizeof( typename std::iterator_traits<
             CPtr >::value_type ) == sizeof( value_type ), "" );
@@ -795,12 +795,13 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_ASSERT(
             ( ( bal_size == 0u ) && ( this->bal == nullptr ) ) ||
             ( ( bal_size >  0u ) && ( this->bal != nullptr ) ) );
+        ( void )bal_size;
 
         return reinterpret_cast< CPtr >( this->bal );
     }
 
     template< typename T > template< typename CPtr >
-    SIXTRL_INLINE CPtr TMultiPole< T >::getBalEnd() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE CPtr TMultipole< T >::getBalEnd() const SIXTRL_NOEXCEPT
     {
         CPtr end_ptr = this->getBalBegin< CPtr >();
 
@@ -813,20 +814,20 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename T > template< typename Ptr >
-    SIXTRL_INLINE Ptr TMultiPole< T >::getBalBegin() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE Ptr TMultipole< T >::getBalBegin() SIXTRL_NOEXCEPT
     {
         using out_const_ptr_t = typename std::add_const< Ptr >::type;
-        using _this_t         = TMultiPole< T >;
+        using _this_t         = TMultipole< T >;
 
         return const_cast< Ptr >( static_cast<
             _this_t const& >( *this ).getBalBegin< out_const_ptr_t >() );
     }
 
     template< typename T > template< typename Ptr >
-    SIXTRL_INLINE Ptr TMultiPole< T >::getBalEnd() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE Ptr TMultipole< T >::getBalEnd() SIXTRL_NOEXCEPT
     {
         using out_const_ptr_t = typename std::add_const< Ptr >::type;
-        using _this_t         = TMultiPole< T >;
+        using _this_t         = TMultipole< T >;
 
         return const_cast< Ptr >( static_cast<
             _this_t const& >( *this ).getBalEnd< out_const_ptr_t >() );
@@ -835,32 +836,32 @@ namespace SIXTRL_CXX_NAMESPACE
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
     template< typename T >
-    SIXTRL_INLINE void TMultiPole< T >::setOrder(
-        typename TMultiPole< T >::order_type const order ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setOrder(
+        typename TMultipole< T >::order_type const order ) SIXTRL_NOEXCEPT
     {
         this->order = order;
         return;
     }
 
     template< typename T >
-    SIXTRL_INLINE void TMultiPole< T >::setLength(
-        typename TMultiPole< T >::value_type const length ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setLength(
+        typename TMultipole< T >::value_type const length ) SIXTRL_NOEXCEPT
     {
         this->length = length;
         return;
     }
 
     template< typename T >
-    SIXTRL_INLINE void TMultiPole< T >::setHxl(
-        typename TMultiPole< T >::value_type const hxl ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setHxl(
+        typename TMultipole< T >::value_type const hxl ) SIXTRL_NOEXCEPT
     {
         this->hxl = hxl;
         return;
     }
 
     template< typename T >
-    SIXTRL_INLINE void TMultiPole< T >::setHyl(
-        typename TMultiPole< T >::value_type const hyl ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::setHyl(
+        typename TMultipole< T >::value_type const hyl ) SIXTRL_NOEXCEPT
     {
         this->hyl = hyl;
         return;
@@ -870,9 +871,9 @@ namespace SIXTRL_CXX_NAMESPACE
 
     template< typename T >
     template< typename Ptr >
-    SIXTRL_INLINE void TMultiPole< T >::assignBal( Ptr ptr_to_bal ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< T >::assignBal( Ptr ptr_to_bal ) SIXTRL_NOEXCEPT
     {
-        using value_t   = typename TMultiPole< T >::value_type;
+        using value_t   = typename TMultipole< T >::value_type;
         using pointer_t = SIXTRL_DATAPTR_DEC value_t*;
 
         this->bal = reinterpret_cast< pointer_t >( ptr_to_bal );
@@ -882,132 +883,135 @@ namespace SIXTRL_CXX_NAMESPACE
     /* --------------------------------------------------------------------- */
 
     template< typename T >
-    SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole_new( Buffer& SIXTRL_RESTRICT_REF buffer,
-                    typename TMultiPole< T >::order_type const order )
+    SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole_new( Buffer& SIXTRL_RESTRICT_REF buffer,
+                    typename TMultipole< T >::order_type const order )
     {
-        return TMultiPole< T >::CreateNewOnBuffer(
+        return TMultipole< T >::CreateNewOnBuffer(
             *buffer.getCApiPtr(), order );
     }
 
     template< typename T >
-    SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole_new( SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
-                    typename TMultiPole< T >::order_type const order )
+    SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole_new( SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
+                    typename TMultipole< T >::order_type const order )
     {
         return ( ptr_buffer != nullptr )
-            ? ( TMultiPole< T >::CreateNewOnBuffer( *ptr_buffer, order ) )
+            ? ( TMultipole< T >::CreateNewOnBuffer( *ptr_buffer, order ) )
             : nullptr;
     }
 
     template< typename T >
-    SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole_add( Buffer& SIXTRL_RESTRICT_REF buffer,
-        typename TMultiPole< T >::order_type const order,
-        SIXTRL_DATAPTR_DEC typename TMultiPole< T >::value_type
-            const* SIXTRL_RESTRICT bal,
-        typename TMultiPole< T >::value_type const& length,
-        typename TMultiPole< T >::value_type const& hxl,
-        typename TMultiPole< T >::value_type const& hyl )
+    SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole_add( Buffer& SIXTRL_RESTRICT_REF buffer,
+        typename TMultipole< T >::order_type const order,
+        typename TMultipole< T >::value_type const& length,
+        typename TMultipole< T >::value_type const& hxl,
+        typename TMultipole< T >::value_type const& hyl,
+        SIXTRL_DATAPTR_DEC typename TMultipole< T >::value_type
+            const* SIXTRL_RESTRICT bal )
     {
-        return TMultiPole< T >::AddToBuffer(
-            *buffer.getCApiPtr(), order, bal, length, hxl, hyl );
+        return TMultipole< T >::AddToBuffer(
+            *buffer.getCApiPtr(), order, length, hxl, hyl,
+            reinterpret_cast< uintptr_t >( bal ) );
     }
 
     template< typename T >
-    SIXTRL_ARGPTR_DEC TMultiPole< T >*
-    TMultiPole_add( ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
-        typename TMultiPole< T >::order_type const order,
-        SIXTRL_DATAPTR_DEC typename TMultiPole< T >::value_type
-            const* SIXTRL_RESTRICT bal,
-        typename TMultiPole< T >::value_type const& length,
-        typename TMultiPole< T >::value_type const& hxl,
-        typename TMultiPole< T >::value_type const& hyl )
+    SIXTRL_ARGPTR_DEC TMultipole< T >*
+    TMultipole_add( ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
+        typename TMultipole< T >::order_type const order,
+        typename TMultipole< T >::value_type const& length,
+        typename TMultipole< T >::value_type const& hxl,
+        typename TMultipole< T >::value_type const& hyl,
+        SIXTRL_DATAPTR_DEC typename TMultipole< T >::value_type
+            const* SIXTRL_RESTRICT bal )
     {
         return ( ptr_buffer != nullptr )
-            ? ( TMultiPole< T >::AddToBuffer(
-                    *ptr_buffer, order, bal, length, hxl, hyl ) )
+            ? ( TMultipole< T >::AddToBuffer(
+                    *ptr_buffer, order, length, hxl, hyl,
+                    reinterpret_cast< uintptr_t >( bal ) ) )
             : ( nullptr );
     }
 
     /* ===================================================================== *
-     * ====  TMultiPole< SIXTRL_REAL_T >:
+     * ====  TMultipole< SIXTRL_REAL_T >:
      * ===================================================================== */
 
 
-    SIXTRL_INLINE bool TMultiPole< SIXTRL_REAL_T >::CanAddToBuffer(
-        TMultiPole< SIXTRL_REAL_T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        TMultiPole< SIXTRL_REAL_T >::order_type const order,
-        SIXTRL_ARGPTR_DEC TMultiPole< SIXTRL_REAL_T >::size_type*
+    SIXTRL_INLINE bool TMultipole< SIXTRL_REAL_T >::CanAddToBuffer(
+        TMultipole< SIXTRL_REAL_T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        TMultipole< SIXTRL_REAL_T >::order_type const order,
+        SIXTRL_ARGPTR_DEC TMultipole< SIXTRL_REAL_T >::size_type*
             SIXTRL_RESTRICT ptr_requ_objects,
-        SIXTRL_ARGPTR_DEC TMultiPole< SIXTRL_REAL_T >::size_type*
+        SIXTRL_ARGPTR_DEC TMultipole< SIXTRL_REAL_T >::size_type*
             SIXTRL_RESTRICT ptr_requ_slots,
-        SIXTRL_ARGPTR_DEC TMultiPole< SIXTRL_REAL_T >::size_type*
+        SIXTRL_ARGPTR_DEC TMultipole< SIXTRL_REAL_T >::size_type*
             SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
     {
-        return ::NS(MultiPole_can_be_added)( &buffer, order,
+        return ::NS(Multipole_can_be_added)( &buffer, order,
                     ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
     }
 
-    SIXTRL_INLINE SIXTRL_ARGPTR_DEC TMultiPole< SIXTRL_REAL_T >*
-    TMultiPole< SIXTRL_REAL_T >::CreateNewOnBuffer(
-        TMultiPole< SIXTRL_REAL_T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        TMultiPole< SIXTRL_REAL_T >::order_type const order )
+    SIXTRL_INLINE SIXTRL_ARGPTR_DEC TMultipole< SIXTRL_REAL_T >*
+    TMultipole< SIXTRL_REAL_T >::CreateNewOnBuffer(
+        TMultipole< SIXTRL_REAL_T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        TMultipole< SIXTRL_REAL_T >::order_type const order )
     {
-        return static_cast< SIXTRL_ARGPTR_DEC TMultiPole< SIXTRL_REAL_T >* >(
-            ::NS(MultiPole_new)( &buffer, order ) );
+        return static_cast< SIXTRL_ARGPTR_DEC TMultipole< SIXTRL_REAL_T >* >(
+            ::NS(Multipole_new)( &buffer, order ) );
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >*
-    TMultiPole< SIXTRL_REAL_T >::AddToBuffer(
-        TMultiPole< SIXTRL_REAL_T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        TMultiPole< SIXTRL_REAL_T >::order_type const order,
-        SIXTRL_DATAPTR_DEC TMultiPole< SIXTRL_REAL_T >::value_type
-            const* SIXTRL_RESTRICT bal,
-        TMultiPole< SIXTRL_REAL_T >::value_type const length,
-        TMultiPole< SIXTRL_REAL_T >::value_type const hxl,
-        TMultiPole< SIXTRL_REAL_T >::value_type const hyl )
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >*
+    TMultipole< SIXTRL_REAL_T >::AddToBuffer(
+        TMultipole< SIXTRL_REAL_T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        TMultipole< SIXTRL_REAL_T >::order_type const order,
+        TMultipole< SIXTRL_REAL_T >::value_type const length,
+        TMultipole< SIXTRL_REAL_T >::value_type const hxl,
+        TMultipole< SIXTRL_REAL_T >::value_type const hyl,
+        SIXTRL_DATAPTR_DEC TMultipole< SIXTRL_REAL_T >::value_type
+            const* SIXTRL_RESTRICT bal )
     {
-        return static_cast< SIXTRL_ARGPTR_DEC TMultiPole< SIXTRL_REAL_T >* >(
-            ::NS(MultiPole_add)( &buffer, order, bal, length, hxl, hyl ) );
+        return static_cast< SIXTRL_ARGPTR_DEC TMultipole< SIXTRL_REAL_T >* >(
+            ::NS(Multipole_add)( &buffer, order, length, hxl, hyl,
+                 reinterpret_cast< uintptr_t >( bal ) ) );
     }
 
     /* ----------------------------------------------------------------- */
 
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::preset() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::preset() SIXTRL_NOEXCEPT
     {
-        ::NS(MultiPole_preset)( this->getCApiPtr() );
+        ::NS(Multipole_preset)( this->getCApiPtr() );
         return;
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::value_type
-    TMultiPole< SIXTRL_REAL_T >::getLength() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::value_type
+    TMultipole< SIXTRL_REAL_T >::getLength() const SIXTRL_NOEXCEPT
     {
-        return ::NS(MultiPole_get_length)( this->getCApiPtr() );
+        return ::NS(Multipole_length)( this->getCApiPtr() );
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::value_type
-    TMultiPole< SIXTRL_REAL_T >::getHxl() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::value_type
+    TMultipole< SIXTRL_REAL_T >::getHxl() const SIXTRL_NOEXCEPT
     {
-        return ::NS(MultiPole_get_hxl)( this->getCApiPtr() );
+        return ::NS(Multipole_hxl)( this->getCApiPtr() );
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::value_type
-    TMultiPole< SIXTRL_REAL_T >::getHyl() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::value_type
+    TMultipole< SIXTRL_REAL_T >::getHyl() const SIXTRL_NOEXCEPT
     {
-        return ::NS(MultiPole_get_hyl)( this->getCApiPtr() );
+        return ::NS(Multipole_hyl)( this->getCApiPtr() );
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::order_type
-    TMultiPole< SIXTRL_REAL_T >::getOrder() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::order_type
+    TMultipole< SIXTRL_REAL_T >::getOrder() const SIXTRL_NOEXCEPT
     {
-        return ::NS(MultiPole_get_order)( this->getCApiPtr() );
+        return ::NS(Multipole_order)( this->getCApiPtr() );
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::size_type
-    TMultiPole< SIXTRL_REAL_T >::getBalSize() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::size_type
+    TMultipole< SIXTRL_REAL_T >::getBalSize() const SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t = TMultipole< SIXTRL_REAL_T >;
         using  size_t = typename _this_t::size_type;
         using order_t = typename _this_t::order_type;
 
@@ -1019,17 +1023,17 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* ----------------------------------------------------------------- */
 
-    SIXTRL_INLINE SIXTRL_DATAPTR_DEC TMultiPole< SIXTRL_REAL_T >::c_api_t const*
-    TMultiPole< SIXTRL_REAL_T >::getCApiPtr() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE SIXTRL_DATAPTR_DEC TMultipole< SIXTRL_REAL_T >::c_api_t const*
+    TMultipole< SIXTRL_REAL_T >::getCApiPtr() const SIXTRL_NOEXCEPT
     {
-        using c_api_t = TMultiPole< SIXTRL_REAL_T >::c_api_t;
+        using c_api_t = TMultipole< SIXTRL_REAL_T >::c_api_t;
         return reinterpret_cast< SIXTRL_DATAPTR_DEC c_api_t const* >( this );
     }
 
-    SIXTRL_INLINE SIXTRL_DATAPTR_DEC TMultiPole< SIXTRL_REAL_T >::c_api_t*
-    TMultiPole< SIXTRL_REAL_T >::getCApiPtr() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE SIXTRL_DATAPTR_DEC TMultipole< SIXTRL_REAL_T >::c_api_t*
+    TMultipole< SIXTRL_REAL_T >::getCApiPtr() SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t = TMultipole< SIXTRL_REAL_T >;
         using   ptr_t = SIXTRL_DATAPTR_DEC _this_t::c_api_t*;
 
         return const_cast< ptr_t >( static_cast< _this_t const& >(
@@ -1038,33 +1042,33 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* ----------------------------------------------------------------- */
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::value_type
-    TMultiPole< SIXTRL_REAL_T >::getKnlValue(
-        TMultiPole< SIXTRL_REAL_T >::size_type const index ) const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::value_type
+    TMultipole< SIXTRL_REAL_T >::getKnlValue(
+        TMultipole< SIXTRL_REAL_T >::size_type const index ) const SIXTRL_NOEXCEPT
     {
-        return ::NS(MultiPole_get_knl_value)( this->getCApiPtr(), index );
+        return ::NS(Multipole_knl)( this->getCApiPtr(), index );
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::value_type
-    TMultiPole< SIXTRL_REAL_T >::getKslValue(
-        TMultiPole< SIXTRL_REAL_T >::size_type const index ) const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::value_type
+    TMultipole< SIXTRL_REAL_T >::getKslValue(
+        TMultipole< SIXTRL_REAL_T >::size_type const index ) const SIXTRL_NOEXCEPT
     {
-        return ::NS(MultiPole_get_ksl_value)( this->getCApiPtr(), index );
+        return ::NS(Multipole_ksl)( this->getCApiPtr(), index );
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::value_type
-    TMultiPole< SIXTRL_REAL_T >::getBalValue(
-        TMultiPole< SIXTRL_REAL_T >::size_type const index ) const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::value_type
+    TMultipole< SIXTRL_REAL_T >::getBalValue(
+        TMultipole< SIXTRL_REAL_T >::size_type const index ) const SIXTRL_NOEXCEPT
     {
-        return ::NS(MultiPole_get_bal_value)( this->getCApiPtr(), index );
+        return ::NS(Multipole_bal)( this->getCApiPtr(), index );
     }
 
     template< typename Iter >
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setKnl(
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setKnl(
         Iter knl_begin ) SIXTRL_NOEXCEPT
     {
-        using size_t         = TMultiPole< SIXTRL_REAL_T >::size_type;
-        using order_t        = TMultiPole< SIXTRL_REAL_T >::order_type;
+        using size_t         = TMultipole< SIXTRL_REAL_T >::size_type;
+        using order_t        = TMultipole< SIXTRL_REAL_T >::order_type;
 
         order_t const order = this->getOrder();
         size_t  const    nn = ( order >= order_t{ 0 } )
@@ -1090,11 +1094,11 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename Iter >
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setKsl(
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setKsl(
         Iter ksl_begin ) SIXTRL_NOEXCEPT
     {
-        using size_t         = TMultiPole< SIXTRL_REAL_T >::size_type;
-        using order_t        = TMultiPole< SIXTRL_REAL_T >::order_type;
+        using size_t         = TMultipole< SIXTRL_REAL_T >::size_type;
+        using order_t        = TMultipole< SIXTRL_REAL_T >::order_type;
 
         order_t const order = this->getOrder();
         size_t  const    nn = ( order >= order_t{ 0 } )
@@ -1120,10 +1124,10 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename Iter >
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setBal(
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setBal(
         Iter bal_begin ) SIXTRL_NOEXCEPT
     {
-        using size_t = TMultiPole< SIXTRL_REAL_T >::size_type;
+        using size_t = TMultipole< SIXTRL_REAL_T >::size_type;
 
         size_t const bal_length = this->getBalSize();
         size_t ii = size_t{ 0 };
@@ -1144,11 +1148,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setKnlValue(
-        TMultiPole< SIXTRL_REAL_T >::value_type const knl_value,
-        TMultiPole< SIXTRL_REAL_T >::size_type  const index ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setKnlValue(
+        TMultipole< SIXTRL_REAL_T >::value_type const knl_value,
+        TMultipole< SIXTRL_REAL_T >::size_type  const index ) SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t = TMultipole< SIXTRL_REAL_T >;
         using size_t  = _this_t::size_type;
 
         this->setBalValue( knl_value / _this_t::Factorial( index ),
@@ -1157,11 +1161,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setKslValue(
-        TMultiPole< SIXTRL_REAL_T >::value_type const ksl_value,
-        TMultiPole< SIXTRL_REAL_T >::size_type  const index ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setKslValue(
+        TMultipole< SIXTRL_REAL_T >::value_type const ksl_value,
+        TMultipole< SIXTRL_REAL_T >::size_type  const index ) SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t = TMultipole< SIXTRL_REAL_T >;
         using size_t  = _this_t::size_type;
 
         this->setBalValue( ksl_value / _this_t::Factorial( index ),
@@ -1170,11 +1174,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setBalValue(
-        TMultiPole< SIXTRL_REAL_T >::value_type const bal_value,
-        TMultiPole< SIXTRL_REAL_T >::size_type const index ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setBalValue(
+        TMultipole< SIXTRL_REAL_T >::value_type const bal_value,
+        TMultipole< SIXTRL_REAL_T >::size_type const index ) SIXTRL_NOEXCEPT
     {
-        using _this_t        = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t        = TMultipole< SIXTRL_REAL_T >;
         using value_t        = _this_t::value_type;
         using ptr_to_value_t = SIXTRL_DATAPTR_DEC value_t*;
 
@@ -1191,23 +1195,23 @@ namespace SIXTRL_CXX_NAMESPACE
     /* ----------------------------------------------------------------- */
 
     SIXTRL_INLINE
-    SIXTRL_DATAPTR_DEC TMultiPole< SIXTRL_REAL_T >::value_type const*
-    TMultiPole< SIXTRL_REAL_T >::begin() const SIXTRL_NOEXCEPT
+    SIXTRL_DATAPTR_DEC TMultipole< SIXTRL_REAL_T >::value_type const*
+    TMultipole< SIXTRL_REAL_T >::begin() const SIXTRL_NOEXCEPT
     {
         return this->getBalBegin<>();
     }
 
     SIXTRL_INLINE
-    SIXTRL_DATAPTR_DEC TMultiPole< SIXTRL_REAL_T >::value_type const*
-    TMultiPole< SIXTRL_REAL_T >::end() const SIXTRL_NOEXCEPT
+    SIXTRL_DATAPTR_DEC TMultipole< SIXTRL_REAL_T >::value_type const*
+    TMultipole< SIXTRL_REAL_T >::end() const SIXTRL_NOEXCEPT
     {
         return this->getBalEnd<>();
     }
 
-    SIXTRL_INLINE SIXTRL_DATAPTR_DEC TMultiPole< SIXTRL_REAL_T >::value_type*
-    TMultiPole< SIXTRL_REAL_T >::begin() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE SIXTRL_DATAPTR_DEC TMultipole< SIXTRL_REAL_T >::value_type*
+    TMultipole< SIXTRL_REAL_T >::begin() SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t = TMultipole< SIXTRL_REAL_T >;
         using   ptr_t = SIXTRL_DATAPTR_DEC _this_t::value_type*;
 
         return const_cast< ptr_t >( static_cast< _this_t const& >(
@@ -1215,10 +1219,10 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     SIXTRL_INLINE
-    SIXTRL_DATAPTR_DEC TMultiPole< SIXTRL_REAL_T >::value_type*
-    TMultiPole< SIXTRL_REAL_T >::end() SIXTRL_NOEXCEPT
+    SIXTRL_DATAPTR_DEC TMultipole< SIXTRL_REAL_T >::value_type*
+    TMultipole< SIXTRL_REAL_T >::end() SIXTRL_NOEXCEPT
     {
-        using _this_t = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t = TMultipole< SIXTRL_REAL_T >;
         using   ptr_t = _this_t::value_type*;
 
         return const_cast< ptr_t >( static_cast< _this_t const& >(
@@ -1226,20 +1230,21 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename CPtr > SIXTRL_INLINE CPtr
-    TMultiPole< SIXTRL_REAL_T >::getBalBegin() const SIXTRL_NOEXCEPT
+    TMultipole< SIXTRL_REAL_T >::getBalBegin() const SIXTRL_NOEXCEPT
     {
         static_assert( sizeof( typename std::iterator_traits<
             CPtr >::value_type ) == sizeof( value_type ), "" );
 
         SIXTRL_ASSERT(
-            ( ( this->getBalSize() == 0u ) && ( this->bal == nullptr ) ) ||
-            ( ( this->getBalSize() >  0u ) && ( this->bal != nullptr ) ) );
+            ( ( this->getBalSize() == 0u ) && ( this->bal_addr == 0u ) ) ||
+            ( ( this->getBalSize() >  0u ) && ( this->bal_addr != 0u ) ) );
 
-        return reinterpret_cast< CPtr >( this->bal );
+        return reinterpret_cast< CPtr >(
+            static_cast< uintptr_t >( this->bal_addr ) );
     }
 
     template< typename CPtr > SIXTRL_INLINE CPtr
-    TMultiPole< SIXTRL_REAL_T >::getBalEnd() const SIXTRL_NOEXCEPT
+    TMultipole< SIXTRL_REAL_T >::getBalEnd() const SIXTRL_NOEXCEPT
     {
         CPtr end_ptr = this->getBalBegin< CPtr >();
 
@@ -1252,100 +1257,91 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     template< typename Ptr >
-    SIXTRL_INLINE Ptr TMultiPole< SIXTRL_REAL_T >::getBalBegin() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE Ptr TMultipole< SIXTRL_REAL_T >::getBalBegin() SIXTRL_NOEXCEPT
     {
         using out_const_ptr_t = typename std::add_const< Ptr >::type;
-        using _this_t         = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t         = TMultipole< SIXTRL_REAL_T >;
 
         return const_cast< Ptr >( static_cast<
             _this_t const& >( *this ).getBalBegin< out_const_ptr_t >() );
     }
 
     template< typename Ptr >
-    SIXTRL_INLINE Ptr TMultiPole< SIXTRL_REAL_T >::getBalEnd() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE Ptr TMultipole< SIXTRL_REAL_T >::getBalEnd() SIXTRL_NOEXCEPT
     {
         using out_const_ptr_t = typename std::add_const< Ptr >::type;
-        using _this_t         = TMultiPole< SIXTRL_REAL_T >;
+        using _this_t         = TMultipole< SIXTRL_REAL_T >;
 
         return const_cast< Ptr >( static_cast<
             _this_t const& >( *this ).getBalEnd< out_const_ptr_t >() );
     }
 
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setOrder(
-        TMultiPole< SIXTRL_REAL_T >::order_type const order ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setOrder(
+        TMultipole< SIXTRL_REAL_T >::order_type const order ) SIXTRL_NOEXCEPT
     {
         this->order = order;
         return;
     }
 
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setLength(
-        TMultiPole< SIXTRL_REAL_T >::value_type const length ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setLength(
+        TMultipole< SIXTRL_REAL_T >::value_type const length ) SIXTRL_NOEXCEPT
     {
         this->length = length;
         return;
     }
 
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setHxl(
-        TMultiPole< SIXTRL_REAL_T >::value_type const hxl ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setHxl(
+        TMultipole< SIXTRL_REAL_T >::value_type const hxl ) SIXTRL_NOEXCEPT
     {
         this->hxl = hxl;
         return;
     }
 
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::setHyl(
-        TMultiPole< SIXTRL_REAL_T >::value_type const hyl ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::setHyl(
+        TMultipole< SIXTRL_REAL_T >::value_type const hyl ) SIXTRL_NOEXCEPT
     {
         this->hyl = hyl;
         return;
     }
 
     template< typename Ptr >
-    SIXTRL_INLINE void TMultiPole< SIXTRL_REAL_T >::assignBal(
+    SIXTRL_INLINE void TMultipole< SIXTRL_REAL_T >::assignBal(
         Ptr ptr_to_bal ) SIXTRL_NOEXCEPT
     {
-        using value_t   = TMultiPole< SIXTRL_REAL_T >::value_type;
-        using pointer_t = SIXTRL_DATAPTR_DEC value_t*;
-
-        this->bal = reinterpret_cast< pointer_t >( ptr_to_bal );
-        return;
+        this->bal_addr = reinterpret_cast< uintptr_t >( ptr_to_bal );
     }
 
-    SIXTRL_INLINE TMultiPole< SIXTRL_REAL_T >::value_type
-    TMultiPole< SIXTRL_REAL_T >::Factorial(
-        TMultiPole< SIXTRL_REAL_T >::size_type n ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TMultipole< SIXTRL_REAL_T >::value_type
+    TMultipole< SIXTRL_REAL_T >::Factorial(
+        TMultipole< SIXTRL_REAL_T >::size_type n ) SIXTRL_NOEXCEPT
     {
-        using size_t  = TMultiPole< SIXTRL_REAL_T >::size_type;
-        using value_t = TMultiPole< SIXTRL_REAL_T >::value_type;
-
-        return ( n > size_t{ 1 } )
-                ? ( static_cast< value_t >( n ) *
-                    TMultiPole< SIXTRL_REAL_T >::Factorial( n - size_t{ 1 } ) )
-                : ( value_t{ 1.0 } );
+        return SIXTRL_CXX_NAMESPACE::Math_factorial<
+            size_type, SIXTRL_REAL_T >( n );
     }
 
     /* --------------------------------------------------------------------- */
 
-    SIXTRL_ARGPTR_DEC MultiPole* MultiPole_new(
+    SIXTRL_ARGPTR_DEC Multipole* Multipole_new(
         Buffer& SIXTRL_RESTRICT_REF buffer,
         ::NS(multipole_order_t) const order )
     {
-        using ptr_t = SIXTRL_ARGPTR_DEC MultiPole*;
+        using ptr_t = SIXTRL_ARGPTR_DEC Multipole*;
 
         return static_cast< ptr_t >(
-                ::NS(MultiPole_new)( buffer.getCApiPtr(), order ) );
+                ::NS(Multipole_new)( buffer.getCApiPtr(), order ) );
     }
 
-    SIXTRL_ARGPTR_DEC MultiPole* MultiPole_new(
+    SIXTRL_ARGPTR_DEC Multipole* Multipole_new(
         SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
         ::NS(multipole_order_t) const order )
     {
-        using ptr_t = SIXTRL_ARGPTR_DEC MultiPole*;
+        using ptr_t = SIXTRL_ARGPTR_DEC Multipole*;
 
         return static_cast< ptr_t >(
-            ::NS(MultiPole_new)( ptr_buffer, order ) );
+            ::NS(Multipole_new)( ptr_buffer, order ) );
     }
 
-    SIXTRL_ARGPTR_DEC MultiPole* MultiPole_add(
+    SIXTRL_ARGPTR_DEC Multipole* Multipole_add(
         Buffer& SIXTRL_RESTRICT_REF buffer,
         ::NS(multipole_order_t) const order,
         SIXTRL_DATAPTR_DEC ::NS(multipole_real_t) const* SIXTRL_RESTRICT bal,
@@ -1353,29 +1349,27 @@ namespace SIXTRL_CXX_NAMESPACE
         ::NS(multipole_real_t) const hxl,
         ::NS(multipole_real_t) const hyl )
     {
-        using ptr_t = SIXTRL_ARGPTR_DEC MultiPole*;
+        using ptr_t = SIXTRL_ARGPTR_DEC Multipole*;
 
-        return static_cast< ptr_t >( ::NS(MultiPole_add)(
-            buffer.getCApiPtr(), order, bal, length, hxl, hyl ) );
+        return static_cast< ptr_t >( ::NS(Multipole_add)( buffer.getCApiPtr(),
+            order, length, hxl, hyl, reinterpret_cast< uintptr_t >( bal ) ) );
     }
 
-    SIXTRL_ARGPTR_DEC MultiPole* MultiPole_add(
+    SIXTRL_ARGPTR_DEC Multipole* Multipole_add(
         SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
         ::NS(multipole_order_t) const order,
-        SIXTRL_DATAPTR_DEC ::NS(multipole_real_t) const* SIXTRL_RESTRICT bal,
         ::NS(multipole_real_t) const length,
         ::NS(multipole_real_t) const hxl,
-        ::NS(multipole_real_t) const hyl )
+        ::NS(multipole_real_t) const hyl,
+        SIXTRL_DATAPTR_DEC ::NS(multipole_real_t) const* SIXTRL_RESTRICT bal )
     {
-        using ptr_t = SIXTRL_ARGPTR_DEC MultiPole*;
+        using ptr_t = SIXTRL_ARGPTR_DEC Multipole*;
 
-        return static_cast< ptr_t >( ::NS(MultiPole_add)(
-            ptr_buffer, order, bal, length, hxl, hyl ) );
+        return static_cast< ptr_t >( ::NS(Multipole_add)(
+            ptr_buffer, order, length, hxl, hyl, reinterpret_cast< uintptr_t >(
+                bal ) ) );
     }
 }
 
 #endif /* define( __cplusplus ) */
-
 #endif /* CXX_SIXTRACKLIB_COMMON_BE_MULTIPOLE_BEAM_ELEM_BE_MULTIPOLE_HPP__ */
-
-/* end: sixtracklib/common/be_multipole/be_multipole.hpp */
diff --git a/sixtracklib/common/be_multipole/track.h b/sixtracklib/common/be_multipole/track.h
index 1f638a1c..aa522bbc 100644
--- a/sixtracklib/common/be_multipole/track.h
+++ b/sixtracklib/common/be_multipole/track.h
@@ -12,12 +12,12 @@
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-struct NS(MultiPole);
+struct NS(Multipole);
 
 SIXTRL_FN SIXTRL_STATIC SIXTRL_TRACK_RETURN NS(Track_particle_multipole)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
     NS(particle_num_elements_t) const particle_index,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(MultiPole) *const SIXTRL_RESTRICT mp );
+    SIXTRL_BE_ARGPTR_DEC const struct NS(Multipole) *const SIXTRL_RESTRICT mp );
 
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
@@ -38,7 +38,7 @@ extern "C" {
 SIXTRL_INLINE int NS(Track_particle_multipole)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
     NS(particle_num_elements_t) const index,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT mp )
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT mp )
 {
     typedef NS(particle_real_t)  real_t;
     typedef NS(particle_index_t) index_t;
@@ -46,19 +46,19 @@ SIXTRL_INLINE int NS(Track_particle_multipole)(
     SIXTRL_STATIC_VAR index_t const TWO  = ( index_t )2;
     SIXTRL_STATIC_VAR real_t  const ZERO = ( real_t )0.0;
 
-    index_t const order = NS(MultiPole_get_order)( mp );
+    index_t const order = NS(Multipole_order)( mp );
     index_t index_x = TWO * order;
     index_t index_y = index_x + ( index_t )1;
 
-    real_t dpx = NS(MultiPole_get_bal_value)( mp, index_x );
-    real_t dpy = NS(MultiPole_get_bal_value)( mp, index_y );
+    real_t dpx = NS(Multipole_bal)( mp, index_x );
+    real_t dpy = NS(Multipole_bal)( mp, index_y );
 
     real_t const x      = NS(Particles_get_x_value)( particles, index );
     real_t const y      = NS(Particles_get_y_value)( particles, index );
     real_t const chi    = NS(Particles_get_chi_value)( particles, index );
 
-    real_t const hxl    = NS(MultiPole_get_hxl)( mp );
-    real_t const hyl    = NS(MultiPole_get_hyl)( mp );
+    real_t const hxl    = NS(Multipole_hxl)( mp );
+    real_t const hyl    = NS(Multipole_hyl)( mp );
 
     SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, index ) ==
                    ( NS(particle_index_t) )1 );
@@ -74,8 +74,8 @@ SIXTRL_INLINE int NS(Track_particle_multipole)(
         index_x -= TWO;
         index_y -= TWO;
 
-        dpx = NS(MultiPole_get_bal_value)( mp, index_x ) + zre;
-        dpy = NS(MultiPole_get_bal_value)( mp, index_y ) + zim;
+        dpx = NS(Multipole_bal)( mp, index_x ) + zre;
+        dpy = NS(Multipole_bal)( mp, index_y ) + zim;
     }
 
     dpx = -chi * dpx;
@@ -84,7 +84,7 @@ SIXTRL_INLINE int NS(Track_particle_multipole)(
     if( ( hxl > ZERO ) || ( hyl > ZERO ) || ( hxl < ZERO ) || ( hyl < ZERO ) )
     {
         real_t const delta  = NS(Particles_get_delta_value)( particles, index );
-        real_t const length = NS(MultiPole_get_length)( mp );
+        real_t const length = NS(Multipole_length)( mp );
 
         real_t const hxlx   = x * hxl;
         real_t const hyly   = y * hyl;
@@ -97,8 +97,8 @@ SIXTRL_INLINE int NS(Track_particle_multipole)(
 
         if( length > ZERO )
         {
-            real_t const b1l = chi * NS(MultiPole_get_bal_value)( mp, 0 );
-            real_t const a1l = chi * NS(MultiPole_get_bal_value)( mp, 1 );
+            real_t const b1l = chi * NS(Multipole_bal)( mp, 0 );
+            real_t const a1l = chi * NS(Multipole_bal)( mp, 1 );
 
             dpx -= b1l * hxlx / length;
             dpy += a1l * hyly / length;
diff --git a/sixtracklib/common/be_rfmultipole/CMakeLists.txt b/sixtracklib/common/be_rfmultipole/CMakeLists.txt
index 3d2a1be6..19c29a43 100644
--- a/sixtracklib/common/be_rfmultipole/CMakeLists.txt
+++ b/sixtracklib/common/be_rfmultipole/CMakeLists.txt
@@ -1,47 +1,38 @@
-set( SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_C99_HEADERS
-    be_rfmultipole.h track.h
-)
+set( SIXTRL_COMMON_BE_RFMULTIPOLE_C99_HEADERS be_rfmultipole.h track.h )
+set( SIXTRL_COMMON_BE_RFMULTIPOLE_C99_SOURCES be_rfmultipole.c )
+set( SIXTRL_COMMON_BE_RFMULTIPOLE_CXX_HEADERS )
 
-set( SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_C99_SOURCES
-    be_rfmultipole.c )
+add_library( sixtrack_common_be_rfmpole OBJECT
+    ${SIXTRL_COMMON_BE_RFMULTIPOLE_C99_HEADERS}
+    ${SIXTRL_COMMON_BE_RFMULTIPOLE_C99_SOURCES} )
 
-
-add_library( sixtrack_common_be_rfmultipole_c99 OBJECT
-    ${SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_C99_HEADERS}
-    ${SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_C99_SOURCES} )
-
-target_include_directories( sixtrack_common_be_rfmultipole_c99 PRIVATE
+target_include_directories( sixtrack_common_be_rfmpole PRIVATE
     $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-set_target_properties( sixtrack_common_be_rfmultipole_c99 PROPERTIES
+set_target_properties( sixtrack_common_be_rfmpole PROPERTIES
     LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
     C_STANDARD_REQUIRED ON )
 
-target_compile_options( sixtrack_common_be_rfmultipole_c99 PRIVATE
-    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
-
-# ------------------------------------------------------------------------------
-
-set( SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_CXX_HEADERS )
-set( SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_CXX_SOURCES )
+target_compile_options( sixtrack_common_be_rfmpole PRIVATE
+        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_be_beambeam as a module for sixtracklib:
 
 set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
-    $<TARGET_OBJECTS:sixtrack_common_be_rfmultipole_c99>
-    CACHE INTERNAL "" FORCE )
+    $<TARGET_OBJECTS:sixtrack_common_be_rfmpole> CACHE INTERNAL "" FORCE )
 
-# ------------------------------------------------------------------------------
-# install:
+# ----------------------------------------------------------------------------
+# install :
 
-if( SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_C99_HEADERS )
-    install( FILES ${SIXTRACKLIB_COMMON_BE_RFMULTIPOLE_C99_HEADERS}
+if( SIXTRL_COMMON_BE_RFMULTIPOLE_C99_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_RFMULTIPOLE_C99_HEADERS}
              DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/be_rfmultipole" )
 endif()
 
-if( SIXTRACKL_ENABLE_CXX AND SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_CXX_HEADERS )
-    install( FILES ${SIXTRACKLIB_COMMON_BE_RF_MULTIPOLE_CXX_HEADERS}
+if( SIXTRACKL_ENABLE_CXX AND SIXTRL_COMMON_BE_RFMULTIPOLE_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_RFMULTIPOLE_CXX_HEADERS}
              DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/be_rfmultipole" )
-endif()
-#end: sixtracklib/common/be_rfmultipole/CMakeLists.txt
+ endif()
+
diff --git a/sixtracklib/common/be_rfmultipole/be_rfmultipole.c b/sixtracklib/common/be_rfmultipole/be_rfmultipole.c
index 9203832d..a4ca2caf 100644
--- a/sixtracklib/common/be_rfmultipole/be_rfmultipole.c
+++ b/sixtracklib/common/be_rfmultipole/be_rfmultipole.c
@@ -1,62 +1,55 @@
 #include "sixtracklib/common/be_rfmultipole/be_rfmultipole.h"
 #include "sixtracklib/common/buffer.h"
 
-SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole) const* NS(RFMultiPole_const_from_buffer)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const index )
+NS(object_type_id_t) NS(RFMultipole_type_id_ext)( void ) SIXTRL_NOEXCEPT
 {
-    return NS(RFMultiPole_const_from_obj_index)( NS(Buffer_get_const_object)(
-        buffer, index ) );
+    return NS(RFMultipole_type_id)();
 }
 
-SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* NS(RFMultiPole_from_buffer)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const index )
-{
-    return NS(RFMultiPole_from_obj_index)( NS(Buffer_get_object)(
-        buffer, index ) );
-}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-NS(arch_status_t) NS(RFMultiPole_attributes_offsets)(
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+NS(arch_status_t) NS(RFMultipole_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
     NS(buffer_size_t) const max_num_offsets,
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(buffer_size_t) const slot_size )
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+    NS(buffer_size_t) const ndataptrs = NS(RFMultipole_num_dataptrs)( mpole );
 
-    if( ( mpole != SIXTRL_NULLPTR ) &&
-        ( offsets_begin != SIXTRL_NULLPTR ) &&
+    if( ( mpole != SIXTRL_NULLPTR ) && ( offsets != SIXTRL_NULLPTR ) &&
         ( slot_size > ( NS(buffer_size_t) )0u ) &&
-        ( max_num_offsets >= NS(RFMultiPole_num_dataptrs)( mpole ) ) )
+        ( max_num_offsets >= ndataptrs ) )
     {
-        SIXTRL_ASSERT( NS(RFMultiPole_num_dataptrs)( mpole ) == 2u );
+        SIXTRL_ASSERT( ndataptrs == ( NS(buffer_size_t) )2u );
 
-        offsets_begin[ 0 ] = offsetof( NS(RFMultiPole), bal_addr );
-        offsets_begin[ 1 ] = offsetof( NS(RFMultiPole), phase_addr );
+        offsets[ 0 ] = offsetof( NS(RFMultipole), bal_addr );
+        offsets[ 1 ] = offsetof( NS(RFMultipole), phase_addr );
 
+        SIXTRL_ASSERT( offsets[ 0 ] % slot_size == ( NS(buffer_size_t) )0 );
+        SIXTRL_ASSERT( offsets[ 1 ] % slot_size == ( NS(buffer_size_t) )0 );
         status = NS(ARCH_STATUS_SUCCESS);
     }
 
     return status;
 }
 
-NS(arch_status_t) NS(RFMultiPole_attributes_sizes)(
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+NS(arch_status_t) NS(RFMultipole_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
     NS(buffer_size_t) const max_num_sizes,
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(buffer_size_t) const slot_size )
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+    NS(buffer_size_t) const ndataptrs = NS(RFMultipole_num_dataptrs)( mpole );
 
-    if( ( mpole != SIXTRL_NULLPTR ) && ( sizes_begin != SIXTRL_NULLPTR ) &&
+    if( ( mpole != SIXTRL_NULLPTR ) && ( sizes != SIXTRL_NULLPTR ) &&
         ( slot_size > ( NS(buffer_size_t) )0u ) &&
-        ( max_num_sizes >= NS(RFMultiPole_num_dataptrs)( mpole ) ) )
+        ( max_num_sizes >= ndataptrs ) )
     {
-        SIXTRL_ASSERT( NS(RFMultiPole_num_dataptrs)( mpole ) == 2u );
-
-        sizes_begin[ 0 ] = sizeof( NS(rf_multipole_real_t) );
-        sizes_begin[ 1 ] = sizeof( NS(rf_multipole_real_t) );
+        SIXTRL_ASSERT( ndataptrs == ( NS(buffer_size_t) )2u );
+        sizes[ 0 ] = sizeof( NS(rf_multipole_real_t) );
+        sizes[ 1 ] = sizeof( NS(rf_multipole_real_t) );
 
         status = NS(ARCH_STATUS_SUCCESS);
     }
@@ -64,25 +57,23 @@ NS(arch_status_t) NS(RFMultiPole_attributes_sizes)(
     return status;
 }
 
-NS(arch_status_t) NS(RFMultiPole_attributes_counts)(
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+NS(arch_status_t) NS(RFMultipole_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
     NS(buffer_size_t) const max_num_counts,
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
     NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+    NS(buffer_size_t) const ndataptrs = NS(RFMultipole_num_dataptrs)( mpole );
 
-    if( ( counts_begin != SIXTRL_NULLPTR ) &&
-        ( max_num_counts >= NS(RFMultiPole_num_dataptrs)( mpole ) ) &&
-        ( NS(RFMultiPole_order)( mpole ) >= ( NS(rf_multipole_int_t) )0u ) )
+    if( ( counts != SIXTRL_NULLPTR ) && ( max_num_counts >= ndataptrs ) &&
+        ( slot_size > ( NS(buffer_size_t) )0 ) &&
+        ( NS(RFMultipole_order)( mpole ) >= ( NS(rf_multipole_int_t) )0u ) )
     {
-        SIXTRL_ASSERT( NS(RFMultiPole_num_dataptrs)( mpole ) == 2u );
-
-        counts_begin[ 0 ] = ( NS(buffer_size_t)
-            )NS(RFMultiPole_num_bal_elements)( mpole );
-
-        counts_begin[ 1 ] = ( NS(buffer_size_t)
-            )NS(RFMultiPole_num_phase_elements)( mpole );
+        SIXTRL_ASSERT( ndataptrs == ( NS(buffer_size_t) )2u );
 
+        counts[ 0 ] = NS(RFMultipole_bal_length)( mpole );
+        counts[ 1 ] = NS(RFMultipole_phase_length)( mpole );
         status = NS(ARCH_STATUS_SUCCESS);
     }
 
@@ -91,7 +82,7 @@ NS(arch_status_t) NS(RFMultiPole_attributes_counts)(
 
 /* ------------------------------------------------------------------------- */
 
-bool NS(RFMultiPole_can_be_added)(
+bool NS(RFMultipole_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     NS(rf_multipole_int_t) const order,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
@@ -101,154 +92,191 @@ bool NS(RFMultiPole_can_be_added)(
     typedef NS(buffer_size_t) buf_size_t;
 
     bool can_be_added = false;
-    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
-
-    NS(RFMultiPole) mpole;
-    buf_size_t const num_dataptrs = NS(RFMultiPole_num_dataptrs)( &mpole );
     buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+    buf_size_t ndataptrs = ( buf_size_t )0u;
 
-    buf_size_t sizes[]  = { ( buf_size_t )0u, ( buf_size_t )0u };
-    buf_size_t counts[] = { ( buf_size_t )0u, ( buf_size_t )0u };
+    NS(RFMultipole) mpole;
+    NS(arch_status_t) status = NS(RFMultipole_clear)( &mpole );
+    status |= NS(RFMultipole_set_order)( &mpole, order );
+    ndataptrs = NS(RFMultipole_num_dataptrs)( &mpole );
 
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )2u );
-
-    NS(RFMultiPole_preset)( &mpole );
-    mpole.order = order;
+    if( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( order >= ( NS(rf_multipole_int_t) )0 ) &&
+        ( ndataptrs == ( buf_size_t )2u ) && ( buffer != SIXTRL_NULLPTR ) )
+    {
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 2 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 2 ];
 
-    status = NS(RFMultiPole_attributes_sizes)(
-        &sizes[ 0 ], num_dataptrs, &mpole, slot_size );
+        status = NS(RFMultipole_attributes_sizes)(
+            &sizes[ 0 ], ( buf_size_t )2u, &mpole, slot_size );
 
-    if( status == NS(ARCH_STATUS_SUCCESS) )
-    {
-        status = NS(RFMultiPole_attributes_counts)(
-            &counts[ 0 ], num_dataptrs, &mpole );
-    }
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(RFMultipole_attributes_counts)(
+                &counts[ 0 ], ( buf_size_t )2u, &mpole, slot_size );
+        }
 
-    if( status == NS(ARCH_STATUS_SUCCESS) )
-    {
-        can_be_added = NS(Buffer_can_add_object)( buffer,
-            sizeof( NS(RFMultiPole) ), num_dataptrs, sizes, counts,
-                ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            can_be_added = NS(Buffer_can_add_object)( buffer,
+                sizeof( NS(RFMultipole) ), ndataptrs, sizes, counts,
+                    ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
+        }
     }
 
     return can_be_added;
 }
 
-SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* NS(RFMultiPole_new)(
+SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* NS(RFMultipole_new)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(rf_multipole_int_t) const order )
 {
     typedef NS(buffer_size_t) buf_size_t;
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* ptr_multipole = SIXTRL_NULLPTR;
-    NS(arch_size_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
-
-    NS(RFMultiPole) multipole;
-    buf_size_t const num_dataptrs = NS(RFMultiPole_num_dataptrs)( &multipole );
-
-    buf_size_t offsets[] = { ( buf_size_t )0u, ( buf_size_t )0u };
-    buf_size_t sizes[]   = { ( buf_size_t )0u, ( buf_size_t )0u };
-    buf_size_t counts[]  = { ( buf_size_t )0u, ( buf_size_t )0u };
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* added_elem = SIXTRL_NULLPTR;
     buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+    buf_size_t ndataptrs = ( buf_size_t )0u;
 
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )2u );
+    NS(RFMultipole) mpole;
+    NS(arch_status_t) status = NS(RFMultipole_clear)( &mpole );
+    status |= NS(RFMultipole_set_order)( &mpole, order );
+    ndataptrs = NS(RFMultipole_num_dataptrs)( &mpole );
 
-    NS(RFMultiPole_preset)( &multipole );
-    multipole.order = order;
+    if( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( order >= ( NS(rf_multipole_int_t) )0 ) &&
+        ( ndataptrs == ( buf_size_t )2u ) && ( buffer != SIXTRL_NULLPTR ) )
+    {
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 2 ];
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 2 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 2 ];
 
-    status = NS(RFMultiPole_attributes_offsets)(
-        &offsets[ 0 ], num_dataptrs, &multipole, slot_size );
+        status = NS(RFMultipole_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )2u, &mpole, slot_size );
 
-    if( status == NS(ARCH_STATUS_SUCCESS) )
-    {
-        status = NS(RFMultiPole_attributes_counts)(
-            &counts[ 0 ], num_dataptrs, &multipole );
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            status = NS(RFMultipole_attributes_sizes)(
+                &sizes[ 0 ], ( buf_size_t )2u, &mpole, slot_size );
+        }
 
         if( status == NS(ARCH_STATUS_SUCCESS) )
         {
-            status = NS(RFMultiPole_attributes_sizes)(
-                &sizes[ 0 ], num_dataptrs, &multipole, slot_size );
+            status = NS(RFMultipole_attributes_counts)(
+                &counts[ 0 ], ( buf_size_t )2u, &mpole, slot_size );
         }
-    }
 
-    if( status == NS(ARCH_STATUS_SUCCESS) )
-    {
-        ptr_multipole = ( SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* )(
-            uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
-                buffer, &multipole, sizeof( multipole ),
-                    NS(RFMultiPole_type_id)( &multipole ), num_dataptrs,
-                        &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* )(
+                uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, &mpole, sizeof( NS(RFMultipole) ),
+                    NS(RFMultipole_type_id)(), ndataptrs, &offsets[ 0 ],
+                        &sizes[ 0 ], &counts[ 0 ] ) );
+        }
     }
 
-    return ptr_multipole;
+    return added_elem;
 }
 
-SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* NS(RFMultiPole_add)(
+SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* NS(RFMultipole_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(rf_multipole_int_t) const order,
     NS(rf_multipole_real_t) const voltage,
     NS(rf_multipole_real_t) const frequency,
     NS(rf_multipole_real_t) const lag,
-    SIXTRL_ARGPTR_DEC NS(rf_multipole_real_t) const* SIXTRL_RESTRICT bal_values,
-    SIXTRL_ARGPTR_DEC NS(rf_multipole_real_t) const*
-        SIXTRL_RESTRICT phase_values )
+    NS(buffer_addr_t) const bal_addr, NS(buffer_addr_t) const phase_addr )
 {
     typedef NS(buffer_size_t) buf_size_t;
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* ptr_multipole = SIXTRL_NULLPTR;
-    NS(arch_size_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
-
-    NS(RFMultiPole) multipole;
-    buf_size_t const num_dataptrs = NS(RFMultiPole_num_dataptrs)( &multipole );
-
-    buf_size_t offsets[] = { ( buf_size_t )0u, ( buf_size_t )0u };
-    buf_size_t sizes[]   = { ( buf_size_t )0u, ( buf_size_t )0u };
-    buf_size_t counts[]  = { ( buf_size_t )0u, ( buf_size_t )0u };
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* added_elem = SIXTRL_NULLPTR;
     buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+    buf_size_t ndataptrs = ( buf_size_t )0u;
+
+    NS(RFMultipole) mpole;
+    NS(arch_status_t) status = NS(RFMultipole_clear)( &mpole );
+    status |= NS(RFMultipole_set_order)( &mpole, order );
+    status |= NS(RFMultipole_set_voltage)( &mpole, voltage );
+    status |= NS(RFMultipole_set_frequency)( &mpole, frequency );
+    status |= NS(RFMultipole_set_lag)( &mpole, lag );
+    status |= NS(RFMultipole_set_bal_addr)( &mpole, bal_addr );
+    status |= NS(RFMultipole_set_phase_addr)( &mpole, phase_addr );
+    ndataptrs = NS(RFMultipole_num_dataptrs)( &mpole );
+
+    if( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( order >= ( NS(rf_multipole_int_t) )0 ) &&
+        ( ndataptrs == ( buf_size_t )2u ) && ( buffer != SIXTRL_NULLPTR ) )
+    {
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 2 ];
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 2 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 2 ];
 
-    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )2u );
-
-    NS(RFMultiPole_preset)( &multipole );
-    multipole.order = order;
-    multipole.voltage = voltage;
-    multipole.frequency = frequency;
-    multipole.lag = lag;
-    multipole.bal_addr = ( NS(buffer_addr_t) )( uintptr_t )bal_values;
-    multipole.phase_addr = ( NS(buffer_addr_t) )( uintptr_t )phase_values;
-
-    status = NS(RFMultiPole_attributes_offsets)(
-        &offsets[ 0 ], num_dataptrs, &multipole, slot_size );
+        status = NS(RFMultipole_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )2u, &mpole, slot_size );
 
-    if( status == NS(ARCH_STATUS_SUCCESS) )
-    {
-        status = NS(RFMultiPole_attributes_counts)(
-            &counts[ 0 ], num_dataptrs, &multipole );
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            status = NS(RFMultipole_attributes_sizes)(
+                &sizes[ 0 ], ( buf_size_t )2u, &mpole, slot_size );
+        }
 
         if( status == NS(ARCH_STATUS_SUCCESS) )
         {
-            status = NS(RFMultiPole_attributes_sizes)(
-                &sizes[ 0 ], num_dataptrs, &multipole, slot_size );
+            status = NS(RFMultipole_attributes_counts)(
+                &counts[ 0 ], ( buf_size_t )2u, &mpole, slot_size );
         }
-    }
 
-    if( status == NS(ARCH_STATUS_SUCCESS) )
-    {
-        ptr_multipole = ( SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* )(
-            uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
-                buffer, &multipole, sizeof( multipole ),
-                    NS(RFMultiPole_type_id)( &multipole ), num_dataptrs,
-                        &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* )(
+                uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, &mpole, sizeof( NS(RFMultipole) ),
+                    NS(RFMultipole_type_id)(), ndataptrs, &offsets[ 0 ],
+                        &sizes[ 0 ], &counts[ 0 ] ) );
+        }
     }
 
-    return ptr_multipole;
+    return added_elem;
 }
 
-SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* NS(RFMultiPole_add_copy)(
+SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* NS(RFMultipole_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT orig )
 {
-    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return NS(RFMultiPole_add)( buffer,
-        NS(RFMultiPole_order)( mpole ), NS(RFMultiPole_voltage)( mpole ),
-        NS(RFMultiPole_frequency)( mpole ), NS(RFMultiPole_lag)( mpole ),
-        NS(RFMultiPole_const_bal)( mpole ),
-        NS(RFMultiPole_const_phase)( mpole ) );
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* added_elem = SIXTRL_NULLPTR;
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+    buf_size_t const ndataptrs = NS(RFMultipole_num_dataptrs)( orig );
+
+    if( ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( buf_size_t )2u ) && ( buffer != SIXTRL_NULLPTR ) )
+    {
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 2 ];
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[ 2 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 2 ];
+
+        NS(arch_status_t) status = NS(RFMultipole_attributes_offsets)(
+            &offsets[ 0 ], ( buf_size_t )2u, orig, slot_size );
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            status = NS(RFMultipole_attributes_sizes)(
+                &sizes[ 0 ], ( buf_size_t )2u, orig, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(RFMultipole_attributes_counts)(
+                &counts[ 0 ], ( buf_size_t )2u, orig, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* )(
+                uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, orig, sizeof( NS(RFMultipole) ),
+                    NS(RFMultipole_type_id)(), ndataptrs, &offsets[ 0 ],
+                        &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
 }
diff --git a/sixtracklib/common/be_rfmultipole/be_rfmultipole.h b/sixtracklib/common/be_rfmultipole/be_rfmultipole.h
index 2f8086ac..5025f586 100644
--- a/sixtracklib/common/be_rfmultipole/be_rfmultipole.h
+++ b/sixtracklib/common/be_rfmultipole/be_rfmultipole.h
@@ -26,7 +26,7 @@ extern "C" {
 typedef SIXTRL_REAL_T  NS(rf_multipole_real_t);
 typedef SIXTRL_INT64_T NS(rf_multipole_int_t);
 
-typedef struct NS(RFMultiPole)
+typedef struct NS(RFMultipole)
 {
     NS(rf_multipole_int_t)    order               SIXTRL_ALIGN( 8 );
     NS(rf_multipole_real_t)   voltage             SIXTRL_ALIGN( 8 );
@@ -35,643 +35,1393 @@ typedef struct NS(RFMultiPole)
     NS(buffer_addr_t)         bal_addr            SIXTRL_ALIGN( 8 );
     NS(buffer_addr_t)         phase_addr          SIXTRL_ALIGN( 8 );
 }
-NS(RFMultiPole);
+NS(RFMultipole);
 
-/* ************************************************************************* */
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t)
+    NS(RFMultipole_type_id)( void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_int_t)
-NS(RFMultiPole_calculate_factorial)( NS(rf_multipole_int_t) const n );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(RFMultipole_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t)
-NS(RFMultiPole_calculate_factorial_real)( NS(rf_multipole_int_t) const n );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(RFMultipole_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-/* ************************************************************************* */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_preset)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(RFMultiPole_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT multipole );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT
+        multipole ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_voltage)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(RFMultiPole_type_id)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_frequency)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(RFMultiPole_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_lag)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(RFMultiPole_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_int_t) NS(RFMultipole_order )(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------- */
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(RFMultipole_bal_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultiPole_voltage)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(RFMultipole_phase_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultiPole_frequency)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultiPole_lag)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(RFMultipole_bal_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_int_t) NS(RFMultiPole_order )(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+NS(RFMultipole_const_bal_begin)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole)
+    *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_int_t) NS(RFMultiPole_num_bal_elements)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+NS(RFMultipole_const_bal_end)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole)
+    *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_int_t)
-NS(RFMultiPole_num_phase_elements)( SIXTRL_BE_ARGPTR_DEC const
-    NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_bal)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const bal_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(RFMultiPole_bal_addr)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_knl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const knl_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(RFMultiPole_phase_addr)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_ksl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const ksl_index ) SIXTRL_NOEXCEPT;
 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(RFMultipole_phase_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
-NS(RFMultiPole_const_bal)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole)
-    *const SIXTRL_RESTRICT mpole );
-
-SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
-NS(RFMultiPole_bal)( SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-    SIXTRL_RESTRICT mpole );
+NS(RFMultipole_const_phase_begin)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole)
+    *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
-NS(RFMultiPole_const_phase)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole)
-    *const SIXTRL_RESTRICT mpole );
+NS(RFMultipole_const_phase_end)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole)
+    *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
-NS(RFMultiPole_phase)( SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-    SIXTRL_RESTRICT mpole );
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_phase)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const phase_index ) SIXTRL_NOEXCEPT;
 
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_phase_n)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const pn_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultiPole_knl_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const index );
+SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultipole_phase_s)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const ps_index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(rf_multipole_real_t) NS(RFMultiPole_ksl_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const index );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_STATIC SIXTRL_FN NS(rf_multipole_real_t) NS(RFMultiPole_pn_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const index );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_voltage)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const voltage ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(rf_multipole_real_t) NS(RFMultiPole_ps_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const index );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_frequency)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const frequency ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------- */
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_lag)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const lag ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(RFMultiPole_set_voltage)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_real_t) const voltage );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_order )(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const order ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(RFMultiPole_set_frequency)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_real_t) const frequency );
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 
-SIXTRL_STATIC SIXTRL_FN void NS(RFMultiPole_set_lag)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_real_t) const lag );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_bal_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(buffer_addr_t) const bal_addr ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(RFMultiPole_set_order )(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const order );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+NS(RFMultipole_bal_begin)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+NS(RFMultipole_bal_end)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_bal_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const bal_index,
+    NS(rf_multipole_real_t) const bal_value ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(RFMultiPole_set_bal_addr)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(buffer_addr_t) const bal_addr );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_all_bal_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const bal_value ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(RFMultiPole_set_phase_addr)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(buffer_addr_t) const phase_addr );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_bal)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* SIXTRL_RESTRICT
+        bal_values_begin ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------- */
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_knl_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const knl_index,
+    NS(rf_multipole_real_t) const knl_value ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole) const*
-NS(RFMultiPole_const_from_obj_index)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const obj );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_all_knl_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const knl_value ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* obj );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_knl)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+        SIXTRL_RESTRICT knl_values_begin ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole) const*
-NS(RFMultiPole_const_from_managed_buffer)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_ksl_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const ksl_index,
+    NS(rf_multipole_real_t) const ksl_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_all_ksl_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const ksl_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_ksl)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+        SIXTRL_RESTRICT ksl_values_begin ) SIXTRL_NOEXCEPT;
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_phase_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(buffer_addr_t) const phase_addr ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+NS(RFMultipole_phase_begin)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+NS(RFMultipole_phase_end)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_phase_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const phase_index,
+    NS(rf_multipole_real_t) const phase_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_all_phase_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const phase_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_phase)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+        SIXTRL_RESTRICT phase_values_begin ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_phase_n_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const pn_index,
+    NS(rf_multipole_real_t) const pn_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_all_phase_n_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const pn_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_phase_n)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+        SIXTRL_RESTRICT pn_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_phase_s_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const ps_index,
+    NS(rf_multipole_real_t) const ps_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_all_phase_s_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const ps_value ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_set_phase_s)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+        SIXTRL_RESTRICT ps_values ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultipole_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT dst,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const*
+NS(RFMultipole_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const*
+NS(RFMultipole_const_from_managed_buffer)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
-    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_from_managed_buffer)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_from_managed_buffer)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
-    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole) const*
-NS(RFMultiPole_const_from_buffer)(
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const*
+NS(RFMultipole_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_from_buffer)(
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(buffer_size_t) const index );
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(RFMultiPole_attributes_offsets)(
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(RFMultipole_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
     NS(buffer_size_t) const max_num_offsets,
-    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT data,
-    NS(buffer_size_t) const slot_size );
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(RFMultiPole_attributes_sizes)(
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(RFMultipole_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
     NS(buffer_size_t) const max_num_sizes,
-    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT data,
-    NS(buffer_size_t) const slot_size );
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT multipole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(RFMultiPole_attributes_counts)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(RFMultipole_attributes_counts)(
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
     NS(buffer_size_t) const max_num_counts,
-    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT data );
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-/* ------------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+    NS(RFMultipole_type_id_ext)( void ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(RFMultiPole_can_be_added)(
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(RFMultipole_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     NS(rf_multipole_int_t) const order,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_new)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_new)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(rf_multipole_int_t) const order );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     NS(rf_multipole_int_t) const order,
     NS(rf_multipole_real_t) const voltage,
     NS(rf_multipole_real_t) const frequency,
     NS(rf_multipole_real_t) const lag,
-    SIXTRL_ARGPTR_DEC NS(rf_multipole_real_t) const* SIXTRL_RESTRICT bal_values,
-    SIXTRL_ARGPTR_DEC NS(rf_multipole_real_t) const*
-        SIXTRL_RESTRICT phase_values );
+    NS(buffer_addr_t) const ext_bal_addr,
+    NS(buffer_addr_t) const ext_phase_addr );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_add_copy)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole );
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT orig );
 
 #endif /* !defined( _GPUCODE ) */
-
-SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(RFMultiPole_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT dest,
-    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT src );
-
 #if defined( __cplusplus ) && !defined( _GPUCODE )
 }
 #endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
 
-/* ****************************************************************** */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer.h"
+    #include "sixtracklib/common/internal/math_factorial.h"
+    #include "sixtracklib/common/internal/math_constants.h"
+    #include "sixtracklib/common/internal/math_functions.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+
+    #if !defined( _GPUCODE )
+        #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if defined( __cplusplus ) && !defined( _GPUCODE )
 extern "C" {
 #endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
 
-SIXTRL_INLINE NS(rf_multipole_int_t) NS(RFMultiPole_calculate_factorial)(
-    NS(rf_multipole_int_t) const n )
+SIXTRL_INLINE NS(object_type_id_t)
+    NS(RFMultipole_type_id)( void ) SIXTRL_NOEXCEPT
 {
-    NS(rf_multipole_int_t) result = ( NS(rf_multipole_int_t) )1u;
-    NS(rf_multipole_int_t) ii     = ( NS(rf_multipole_int_t) )1u;
-
-    for( ; ii <= n ; ++ii ) result *= ii;
-    return result;
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_RF_MULTIPOLE);
 }
 
-SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultiPole_calculate_factorial_real)(
-    NS(rf_multipole_int_t) const n )
+SIXTRL_INLINE NS(buffer_size_t) NS(RFMultipole_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( mpole ) ) SIXTRL_NOEXCEPT
 {
-    NS(rf_multipole_real_t) result = ( NS(rf_multipole_real_t) )1.0;
-    NS(rf_multipole_int_t) ii = ( NS(rf_multipole_int_t) )1u;
-
-    for( ; ii <= n ; ++ii ) result *= ( NS(rf_multipole_real_t) )ii;
-    return result;
+    return ( NS(buffer_size_t) )2u;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(buffer_size_t) NS(RFMultipole_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    if( multipole != SIXTRL_NULLPTR )
+    typedef NS(buffer_size_t) buf_size_t;
+    buf_size_t num_slots = ( buf_size_t )0u;
+
+    if( ( slot_size > ( buf_size_t )0 ) && ( mpole != SIXTRL_NULLPTR ) )
     {
-        multipole->order = ( NS(rf_multipole_int_t) )0u;
-        NS(RFMultiPole_clear)( multipole );
+        buf_size_t num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(RFMultipole) ), slot_size );
+
+        buf_size_t const n_bal_vals = NS(RFMultipole_bal_length)( mpole );
+        buf_size_t const n_phase_vals = NS(RFMultipole_phase_length)( mpole );
+
+        num_bytes += NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(rf_multipole_real_t) ) * n_bal_vals, slot_size );
+
+        num_bytes += NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(rf_multipole_real_t) ) * n_phase_vals, slot_size );
+
+
+        num_slots = num_bytes / slot_size;
+        if( num_slots * slot_size < num_bytes ) ++num_slots;
     }
 
+    return num_slots;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* NS(RFMultipole_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT
+        multipole ) SIXTRL_NOEXCEPT
+{
+    if( multipole != SIXTRL_NULLPTR ) NS(RFMultipole_clear)( multipole );
     return multipole;
 }
 
-SIXTRL_INLINE void NS(RFMultiPole_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT multipole )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_clear)( SIXTRL_BE_ARGPTR_DEC
+    NS(RFMultipole)* SIXTRL_RESTRICT multipole ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( multipole != SIXTRL_NULLPTR );
+    typedef NS(rf_multipole_real_t) real_t;
+    typedef NS(rf_multipole_int_t)  order_t;
 
-    multipole->voltage = ( NS(rf_multipole_real_t) )0.0;
-    multipole->frequency = ( NS(rf_multipole_real_t) )0.0;
-    multipole->lag = ( NS(rf_multipole_real_t) )0.0;
+    NS(arch_status_t) status =
+        NS(RFMultipole_set_order)( multipole, ( order_t )0 );
 
-    if( multipole->order == ( NS(rf_multipole_int_t) )0u )
-    {
-        multipole->bal_addr = ( NS(buffer_addr_t) )0u;
-        multipole->phase_addr = ( NS(buffer_addr_t) )0u;
-    }
-    else if( multipole->order >= ( NS(rf_multipole_int_t) )0u )
-    {
-        typedef NS(rf_multipole_real_t) real_t;
-        SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0.0;
+    status |= NS(RFMultipole_set_voltage)( multipole, ( real_t )0 );
+    status |= NS(RFMultipole_set_frequency)( multipole, ( real_t )0 );
+    status |= NS(RFMultipole_set_lag)( multipole, ( real_t )0 );
+    status |= NS(RFMultipole_set_bal_addr)( multipole, ( NS(buffer_addr_t) )0 );
+    status |= NS(RFMultipole_set_phase_addr)(
+        multipole, ( NS(buffer_addr_t) )0 );
 
-        NS(buffer_size_t) const bal_size =
-            ( NS(buffer_size_t) )NS(RFMultiPole_num_bal_elements)( multipole );
+    return status;
+}
 
-        NS(buffer_size_t) const phase_size = ( NS(buffer_size_t)
-            )NS(RFMultiPole_num_phase_elements)( multipole );
+/* ------------------------------------------------------------------------- */
 
-        SIXTRL_BE_DATAPTR_DEC real_t* bal = NS(RFMultiPole_bal)( multipole );
-        SIXTRL_BE_DATAPTR_DEC real_t* phase =
-            NS(RFMultiPole_phase)( multipole );
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_voltage)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    return mpole->voltage;
+}
 
-        SIXTRACKLIB_SET_VALUES( real_t, bal, bal_size, ZERO );
-        SIXTRACKLIB_SET_VALUES( real_t, phase, phase_size, ZERO );
-    }
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_frequency)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    return mpole->frequency;
 }
 
-/* ----------------------------------------------------------------------- */
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_lag)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    return mpole->lag;
+}
 
-SIXTRL_INLINE NS(object_type_id_t) NS(RFMultiPole_type_id)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(rf_multipole_int_t) NS(RFMultipole_order )(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
-    ( void )mpole;
-    return NS(OBJECT_TYPE_RF_MULTIPOLE);
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    return mpole->order;
 }
 
-SIXTRL_INLINE NS(buffer_size_t) NS(RFMultiPole_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(buffer_size_t) NS(RFMultipole_bal_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
-    ( void )mpole;
-    return ( NS(buffer_size_t) )2u;
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( mpole->order >= ( NS(rf_multipole_int_t) )0 );
+    return ( NS(buffer_size_t) )( 2 * mpole->order + 2 );
 }
 
-SIXTRL_INLINE NS(buffer_size_t) NS(RFMultiPole_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(buffer_size_t) NS(RFMultipole_phase_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
-    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( mpole->order >= ( NS(rf_multipole_int_t) )0 );
+    return ( NS(buffer_size_t) )( 2 * mpole->order + 2 );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(RFMultipole_bal_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    return mpole->bal_addr;
+}
+
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+NS(RFMultipole_const_bal_begin)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole)
+    *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    return ( SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* )( uintptr_t
+        )mpole->bal_addr;
+}
+
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+NS(RFMultipole_const_bal_end)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole)
+    *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* bal_end =
+        NS(RFMultipole_const_bal_begin)( mpole );
 
-    if( slot_size > ( NS(buffer_size_t) )0u )
+    if( bal_end != SIXTRL_NULLPTR )
     {
-        NS(buffer_size_t) required_size =
-            NS(ManagedBuffer_get_slot_based_length)(
-                sizeof( NS(RFMultiPole) ), slot_size );
+        SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+        SIXTRL_ASSERT( NS(RFMultipole_order)( mpole ) >=
+            ( NS(rf_multipole_int_t) )0 );
 
-        SIXTRL_ASSERT( NS(RFMultiPole_num_dataptrs)( mpole ) ==
-            ( NS(buffer_size_t) )2u );
+        bal_end = bal_end + NS(RFMultipole_bal_length)( mpole );
+    }
 
-        if( ( mpole != SIXTRL_NULLPTR ) && ( mpole->order > 0 ) )
-        {
-            NS(buffer_size_t) const bal_size = ( NS(buffer_size_t)
-                )NS(RFMultiPole_num_bal_elements)( mpole );
+    return bal_end;
+}
 
-            NS(buffer_size_t) const phase_size = ( NS(buffer_size_t)
-                )NS(RFMultiPole_num_phase_elements)( mpole );
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_bal)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const bal_index ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* bal_values =
+        NS(RFMultipole_const_bal_begin)( mpole );
 
-            required_size += NS(ManagedBuffer_get_slot_based_length)(
-                sizeof( NS(rf_multipole_real_t) ) * bal_size, slot_size );
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( bal_values != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(RFMultipole_bal_length)( mpole ) > bal_index );
 
-            required_size += NS(ManagedBuffer_get_slot_based_length)(
-                sizeof( NS(rf_multipole_real_t) ) * phase_size, slot_size );
-        }
+    return bal_values[ bal_index ];
+}
 
-        num_slots = required_size / slot_size;
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_knl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const knl_index ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* bal_values =
+        NS(RFMultipole_const_bal_begin)( mpole );
 
-        if( ( num_slots * slot_size ) < required_size )
-        {
-            ++num_slots;
-        }
+    NS(buffer_size_t) const bal_index = ( NS(buffer_size_t) )( 2 * knl_index );
 
-        SIXTRL_ASSERT( ( num_slots * slot_size ) >= required_size );
-    }
+    SIXTRL_ASSERT( mpole      != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( bal_values != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( knl_index  >= ( NS(rf_multipole_int_t) )0 );
+    SIXTRL_ASSERT( knl_index  <= NS(RFMultipole_order)( mpole ) );
+    SIXTRL_ASSERT( NS(RFMultipole_bal_length)( mpole ) > bal_index );
 
-    return num_slots;
+    return bal_values[ bal_index ] * NS(Math_factorial)( knl_index );
+}
+
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_ksl)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const ksl_index ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* bal_values =
+        NS(RFMultipole_const_bal_begin)( mpole );
+
+    NS(buffer_size_t) const bal_index = (
+        NS(buffer_size_t) )( 2 * ksl_index +  1 );
+
+    SIXTRL_ASSERT( mpole      != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( bal_values != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ksl_index  >= ( NS(rf_multipole_int_t) )0 );
+    SIXTRL_ASSERT( ksl_index  <= NS(RFMultipole_order)( mpole ) );
+    SIXTRL_ASSERT( NS(RFMultipole_bal_length)( mpole ) > bal_index );
+
+    return bal_values[ bal_index ] * NS(Math_factorial)( ksl_index );
 }
 
-/* ------------------------------------------------------------------- */
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultiPole_voltage)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(buffer_addr_t) NS(RFMultipole_phase_addr)( SIXTRL_BE_ARGPTR_DEC
+    const NS(RFMultipole) *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return mpole->voltage;
+    return mpole->phase_addr;
 }
 
-SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultiPole_frequency)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+NS(RFMultipole_const_phase_begin)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole)
+    *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return mpole->frequency;
+    return ( SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* )( uintptr_t
+        )mpole->phase_addr;
 }
 
-SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultiPole_lag)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+NS(RFMultipole_const_phase_end)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole)
+    *const SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* phase_end =
+        NS(RFMultipole_const_phase_begin)( mpole );
+
+    if( phase_end != SIXTRL_NULLPTR )
+    {
+        SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+        SIXTRL_ASSERT( NS(RFMultipole_order)( mpole ) >=
+            ( NS(rf_multipole_int_t) )0 );
+
+        phase_end = phase_end + NS(RFMultipole_phase_length)( mpole );
+    }
+
+    return phase_end;
+}
+
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_phase)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const phase_index ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* phase_values_begin =
+        NS(RFMultipole_const_phase_begin)( mpole );
+
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return mpole->lag;
+    SIXTRL_ASSERT( phase_values_begin != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(RFMultipole_phase_length)( mpole ) > phase_index );
+
+    return phase_values_begin[ phase_index ];
+}
+
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_phase_n)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const pn_index ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* phase_values_begin =
+        NS(RFMultipole_const_phase_begin)( mpole );
+
+    NS(buffer_size_t) const phase_index = ( NS(buffer_size_t) )( 2 * pn_index );
+
+    SIXTRL_ASSERT( mpole      != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( pn_index   >= ( NS(rf_multipole_int_t) )0 );
+    SIXTRL_ASSERT( pn_index   <= NS(RFMultipole_order)( mpole ) );
+    SIXTRL_ASSERT( phase_values_begin != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(RFMultipole_phase_length)( mpole ) > phase_index );
+
+    return phase_values_begin[ phase_index ];
 }
 
-SIXTRL_INLINE NS(rf_multipole_int_t) NS(RFMultiPole_order )(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultipole_phase_s)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const ps_index ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* phase_values_begin =
+        NS(RFMultipole_const_phase_begin)( mpole );
+
+    NS(buffer_size_t) const phase_index = (
+        NS(buffer_size_t) )( 2 * ps_index + 1 );
+
+    SIXTRL_ASSERT( mpole      != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ps_index   >= ( NS(rf_multipole_int_t) )0 );
+    SIXTRL_ASSERT( ps_index   <= NS(RFMultipole_order)( mpole ) );
+    SIXTRL_ASSERT( phase_values_begin != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(RFMultipole_phase_length)( mpole ) > phase_index );
+
+    return phase_values_begin[ phase_index ];
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_voltage)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const voltage ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return mpole->order;
+    mpole->voltage = voltage;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE NS(rf_multipole_int_t) NS(RFMultiPole_num_bal_elements)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_frequency)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const frequency ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( mpole->order >= ( NS(rf_multipole_int_t) )0u );
-    return ( NS(rf_multipole_int_t) )( 2u * mpole->order + 2u );
+    mpole->frequency = frequency;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE NS(rf_multipole_int_t) NS(RFMultiPole_num_phase_elements)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_lag)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const lag ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( mpole->order >= ( NS(rf_multipole_int_t) )0u );
-    return ( NS(rf_multipole_int_t) )( 2u * mpole->order + 2u );
+    mpole->lag = lag;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE NS(buffer_addr_t) NS(RFMultiPole_bal_addr)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_order )(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const order ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return mpole->bal_addr;
+    SIXTRL_ASSERT( order >= ( NS(rf_multipole_int_t) )0 );
+    mpole->order = order;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE NS(buffer_addr_t) NS(RFMultiPole_phase_addr)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_bal_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(buffer_addr_t) const bal_addr ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return mpole->phase_addr;
+    mpole->bal_addr = bal_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
-NS(RFMultiPole_const_bal)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole)
-    *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+NS(RFMultipole_bal_begin)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return ( SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* )(
-        uintptr_t )mpole->bal_addr;
+    return ( SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* )( uintptr_t
+        )mpole->bal_addr;
 }
 
 SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
-NS(RFMultiPole_bal)( SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole )
+NS(RFMultipole_bal_end)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
     return ( SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
-        )NS(RFMultiPole_const_bal)( mpole );
+        )NS(RFMultipole_const_bal_end)( mpole );
 }
 
-SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
-NS(RFMultiPole_const_phase)( SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole)
-    *const SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_bal_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const bal_index,
+    NS(rf_multipole_real_t) const bal_value ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    return ( SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* )(
-        uintptr_t )mpole->phase_addr;
+    SIXTRL_ASSERT( mpole->bal_addr != ( NS(buffer_addr_t) )0 );
+    SIXTRL_ASSERT( bal_index < NS(RFMultipole_bal_length)( mpole ) );
+
+    NS(RFMultipole_bal_begin)( mpole )[ bal_index ] = bal_value;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
-NS(RFMultiPole_phase)( SIXTRL_BE_ARGPTR_DEC
-    NS(RFMultiPole)* SIXTRL_RESTRICT mpole )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_all_bal_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const bal_value ) SIXTRL_NOEXCEPT
 {
-    return ( SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
-        )NS(RFMultiPole_const_phase)( mpole );
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_it =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_end =
+        NS(RFMultipole_bal_end)( mpole );
+
+    SIXTRL_ASSERT( bal_it  != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( bal_end != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ( ( uintptr_t )bal_it ) <= ( uintptr_t )bal_end );
+
+    for( ; bal_it != bal_end ; ++bal_it ) *bal_it = bal_value;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultiPole_knl_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const index )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_bal)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* SIXTRL_RESTRICT
+        in_bal_it ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ( mpole->order + ( NS(rf_multipole_int_t) )1u ) >= index );
-    SIXTRL_ASSERT( mpole->bal_addr != ( NS(buffer_addr_t) )0u );
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_it =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_end =
+        NS(RFMultipole_bal_end)( mpole );
 
-    return NS(RFMultiPole_const_bal)( mpole )[ 2 * index ] *
-        NS(RFMultiPole_calculate_factorial_real)( index );
+    if( ( bal_it != SIXTRL_NULLPTR ) && ( bal_end != SIXTRL_NULLPTR ) &&
+        ( ( ( uintptr_t )bal_it ) <= ( uintptr_t )bal_end ) &&
+        ( in_bal_it != SIXTRL_NULLPTR ) )
+    {
+        for( ; bal_it != bal_end ; ++bal_it, ++in_bal_it ) *bal_it = *in_bal_it;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultiPole_ksl_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const index )
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_knl_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const knl_index,
+    NS(rf_multipole_real_t) const knl_value ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ( mpole->order + ( NS(rf_multipole_int_t) )1u ) >= index );
-    SIXTRL_ASSERT( mpole->bal_addr != ( NS(buffer_addr_t) )0u );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_values =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    NS(buffer_size_t) const bal_index = ( NS(buffer_size_t) )( 2 * knl_index );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) &&
+        ( knl_index >= ( NS(rf_multipole_int_t) )0 ) &&
+        ( knl_index >= NS(RFMultipole_order)( mpole ) ) &&
+        ( bal_index <  NS(RFMultipole_bal_length)( mpole ) ) )
+    {
+        bal_values[ bal_index ] = knl_value / NS(Math_factorial)( knl_index );
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
 
-    return NS(RFMultiPole_const_bal)( mpole )[ 2 * index + 1 ] *
-        NS(RFMultiPole_calculate_factorial_real)( index );
+    return status;
 }
 
-SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultiPole_pn_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const index )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_all_knl_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const knl_value ) SIXTRL_NOEXCEPT
 {
-    /* TODO: Implement accessor function for pn: */
-    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ( mpole->order + ( NS(rf_multipole_int_t) )1u ) >= index );
-    SIXTRL_ASSERT( mpole->phase_addr != ( NS(buffer_addr_t) )0u );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_values =
+        NS(RFMultipole_bal_begin)( mpole );
 
-    return NS(RFMultiPole_const_phase)( mpole )[ 2 * index ];
+    NS(buffer_size_t) bal_index = ( NS(buffer_size_t) )0u;
+    NS(rf_multipole_int_t) knl_index = ( NS(rf_multipole_int_t) )0;
+    NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mpole );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) )
+    {
+        for( ; knl_index <= order ; ++knl_index, bal_index += 2u )
+        {
+            bal_values[ bal_index ] = knl_value /
+                NS(Math_factorial)( knl_index );
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE NS(rf_multipole_real_t) NS(RFMultiPole_ps_value)(
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const index )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_knl)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+        SIXTRL_RESTRICT in_knl_it ) SIXTRL_NOEXCEPT
 {
-    /* TODO: Implement accessor function for pn: */
-    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
-    SIXTRL_ASSERT( ( mpole->order + ( NS(rf_multipole_int_t) )1u ) >= index );
-    SIXTRL_ASSERT( mpole->phase_addr != ( NS(buffer_addr_t) )0u );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_values =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    NS(buffer_size_t) bal_index = ( NS(buffer_size_t) )0u;
+    NS(rf_multipole_int_t) knl_index = ( NS(rf_multipole_int_t) )0;
+    NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mpole );
 
-    return NS(RFMultiPole_const_phase)( mpole )[ 2 * index + 1 ];
+    if( ( mpole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) &&
+        ( in_knl_it != SIXTRL_NULLPTR ) )
+    {
+        for( ; knl_index <= order ; ++knl_index, bal_index += 2u, ++in_knl_it )
+        {
+            bal_values[ bal_index ] = ( *in_knl_it ) /
+                NS(Math_factorial)( knl_index );
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-/* ------------------------------------------------------------------- */
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 
-SIXTRL_INLINE void NS(RFMultiPole_set_voltage)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_real_t) const voltage )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_ksl_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const ksl_index,
+    NS(rf_multipole_real_t) const ksl_value ) SIXTRL_NOEXCEPT
 {
-    if( mpole != SIXTRL_NULLPTR ) mpole->voltage = voltage;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_values =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    NS(buffer_size_t) const bal_index = (
+        NS(buffer_size_t) )( 2 * ksl_index + 1 );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) &&
+        ( ksl_index >= ( NS(rf_multipole_int_t) )0 ) &&
+        ( ksl_index >= NS(RFMultipole_order)( mpole ) ) &&
+        ( bal_index <  NS(RFMultipole_bal_length)( mpole ) ) )
+    {
+        bal_values[ bal_index ] = ksl_value / NS(Math_factorial)( ksl_index );
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE void NS(RFMultiPole_set_frequency)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_real_t) const frequency )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_all_ksl_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const ksl_value ) SIXTRL_NOEXCEPT
 {
-    if( mpole != SIXTRL_NULLPTR ) mpole->frequency = frequency;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_values =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    NS(buffer_size_t) bal_index = ( NS(buffer_size_t) )0u;
+    NS(rf_multipole_int_t) ksl_index = ( NS(rf_multipole_int_t) )1;
+    NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mpole );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) )
+    {
+        for( ; ksl_index <= order ; ++ksl_index, bal_index += 2u )
+        {
+            bal_values[ bal_index ] = ksl_value /
+                NS(Math_factorial)( ksl_index );
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE void NS(RFMultiPole_set_lag)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_real_t) const lag )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_ksl)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+        SIXTRL_RESTRICT in_ksl_it ) SIXTRL_NOEXCEPT
 {
-    if( mpole != SIXTRL_NULLPTR ) mpole->lag = lag;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* bal_values =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    NS(buffer_size_t) bal_index = ( NS(buffer_size_t) )0u;
+    NS(rf_multipole_int_t) ksl_index = ( NS(rf_multipole_int_t) )1;
+    NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mpole );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( bal_values != SIXTRL_NULLPTR ) &&
+        ( in_ksl_it != SIXTRL_NULLPTR ) )
+    {
+        for( ; ksl_index <= order ; ++ksl_index, bal_index += 2u, ++in_ksl_it )
+        {
+            bal_values[ bal_index ] = ( *in_ksl_it ) /
+                NS(Math_factorial)( ksl_index );
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE void NS(RFMultiPole_set_order )(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(rf_multipole_int_t) const order )
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_phase_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(buffer_addr_t) const phase_addr ) SIXTRL_NOEXCEPT
 {
-    if( mpole != SIXTRL_NULLPTR ) mpole->order = order;
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    mpole->phase_addr = phase_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+NS(RFMultipole_phase_begin)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    return ( SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* )( uintptr_t
+        )mpole->phase_addr;
+}
 
-SIXTRL_INLINE void NS(RFMultiPole_set_bal_addr)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(buffer_addr_t) const bal_addr )
+SIXTRL_INLINE SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+NS(RFMultipole_phase_end)( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+    SIXTRL_RESTRICT mpole ) SIXTRL_NOEXCEPT
 {
-    if( mpole != SIXTRL_NULLPTR ) mpole->bal_addr = bal_addr;
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_values_end =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+
+    if( phase_values_end != SIXTRL_NULLPTR )
+    {
+        phase_values_end = phase_values_end +
+            NS(RFMultipole_phase_length)( mpole );
+    }
+
+    return phase_values_end;
 }
 
-SIXTRL_INLINE void NS(RFMultiPole_set_phase_addr)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT mpole,
-    NS(buffer_addr_t) const phase_addr )
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_phase_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(buffer_size_t) const phase_index,
+    NS(rf_multipole_real_t) const phase_value ) SIXTRL_NOEXCEPT
 {
-    if( mpole != SIXTRL_NULLPTR ) mpole->phase_addr = phase_addr;
+    SIXTRL_ASSERT( mpole != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( mpole->phase_addr != ( NS(buffer_addr_t) )0 );
+    SIXTRL_ASSERT( phase_index < NS(RFMultipole_phase_length)( mpole ) );
+
+    NS(RFMultipole_phase_begin)( mpole )[ phase_index ] = phase_value;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-/* ------------------------------------------------------------------- */
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_all_phase_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const phase_value ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_it =
+        NS(RFMultipole_phase_begin)( mpole );
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_end =
+        NS(RFMultipole_phase_end)( mpole );
+
+    SIXTRL_ASSERT( phase_it  != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( phase_end != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ( ( uintptr_t )phase_it ) <= ( uintptr_t )phase_end );
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole) const*
-NS(RFMultiPole_const_from_obj_index)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const obj )
+    for( ; phase_it != phase_end ; ++phase_it ) *phase_it = phase_value;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_phase)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+        SIXTRL_RESTRICT in_phase_it ) SIXTRL_NOEXCEPT
 {
-    return (
-        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_RF_MULTIPOLE) ) &&
-        ( NS(Object_get_size)( obj ) >= sizeof( NS(RFMultiPole) ) ) )
-        ? ( SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole) const* )( uintptr_t
-            )NS(Object_get_begin_addr)( obj )
-        : SIXTRL_NULLPTR;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_it =
+        NS(RFMultipole_bal_begin)( mpole );
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_end =
+        NS(RFMultipole_bal_end)( mpole );
+
+    if( ( phase_it != SIXTRL_NULLPTR ) && ( phase_end != SIXTRL_NULLPTR ) &&
+        ( ( ( uintptr_t )phase_it ) <= ( uintptr_t )phase_end ) &&
+        ( in_phase_it != SIXTRL_NULLPTR ) )
+    {
+        for( ; phase_it != phase_end ; ++phase_it, ++in_phase_it )
+        {
+            *phase_it = *in_phase_it;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* obj )
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_phase_n_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const pn_index,
+    NS(rf_multipole_real_t) const pn_value ) SIXTRL_NOEXCEPT
 {
-    return ( SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-        )NS(RFMultiPole_const_from_obj_index)( obj );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_values =
+        NS(RFMultipole_phase_begin)( mpole );
+
+    NS(buffer_size_t) const phase_index = ( NS(buffer_size_t) )( 2 * pn_index );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( phase_values != SIXTRL_NULLPTR ) &&
+        ( pn_index >= ( NS(rf_multipole_int_t) )0 ) &&
+        ( pn_index >= NS(RFMultipole_order)( mpole ) ) &&
+        ( phase_index <  NS(RFMultipole_bal_length)( mpole ) ) )
+    {
+        phase_values[ phase_index ] = pn_value;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole) const*
-NS(RFMultiPole_const_from_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
-    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_all_phase_n_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const pn_value ) SIXTRL_NOEXCEPT
 {
-    return NS(RFMultiPole_const_from_obj_index)(
-        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_values =
+        NS(RFMultipole_phase_begin)( mpole );
+
+    NS(buffer_size_t) phase_index = ( NS(buffer_size_t) )0u;
+    NS(rf_multipole_int_t) pn_index = ( NS(rf_multipole_int_t) )0;
+    NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mpole );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( phase_values != SIXTRL_NULLPTR ) )
+    {
+        for( ; pn_index <= order ; ++pn_index, phase_index += 2u )
+        {
+            phase_values[ pn_index ] = pn_value;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)*
-NS(RFMultiPole_from_managed_buffer)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
-    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_phase_n)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+        SIXTRL_RESTRICT in_pn_it ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_values =
+        NS(RFMultipole_phase_begin)( mpole );
+
+    NS(buffer_size_t) phase_index = ( NS(buffer_size_t) )0u;
+    NS(rf_multipole_int_t) pn_index = ( NS(rf_multipole_int_t) )0;
+    NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mpole );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( phase_values != SIXTRL_NULLPTR ) &&
+        ( in_pn_it != SIXTRL_NULLPTR ) )
+    {
+        for( ; pn_index <= order ; ++pn_index, phase_index += 2u, ++in_pn_it )
+        {
+            phase_values[ phase_index ] = *in_pn_it;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_phase_s_value)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_int_t) const ps_index,
+    NS(rf_multipole_real_t) const ps_value ) SIXTRL_NOEXCEPT
 {
-    return NS(RFMultiPole_from_obj_index)( NS(ManagedBuffer_get_object)(
-        buffer_begin, index, slot_size ) );
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_values =
+        NS(RFMultipole_phase_begin)( mpole );
+
+    NS(buffer_size_t) const phase_index = (
+        NS(buffer_size_t) )( 2 * ps_index + 1 );
+
+    if( ( mpole != SIXTRL_NULLPTR ) && ( phase_values != SIXTRL_NULLPTR ) &&
+        ( ps_index >= ( NS(rf_multipole_int_t) )0 ) &&
+        ( ps_index >= NS(RFMultipole_order)( mpole ) ) &&
+        ( phase_index <  NS(RFMultipole_bal_length)( mpole ) ) )
+    {
+        phase_values[ phase_index ] = ps_value;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
 }
 
-SIXTRL_INLINE NS(arch_status_t) NS(RFMultiPole_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(RFMultiPole)* SIXTRL_RESTRICT dest,
-    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT src )
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_all_phase_s_values)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    NS(rf_multipole_real_t) const ps_value ) SIXTRL_NOEXCEPT
 {
-    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_values =
+        NS(RFMultipole_phase_begin)( mpole );
+
+    NS(buffer_size_t) phase_index = ( NS(buffer_size_t) )0u;
+    NS(rf_multipole_int_t) ps_index = ( NS(rf_multipole_int_t) )1;
+    NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mpole );
 
-    if( ( dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) &&
-        ( dest->order == src->order ) )
+    if( ( mpole != SIXTRL_NULLPTR ) && ( phase_values != SIXTRL_NULLPTR ) )
     {
-        if( dest != src )
+        for( ; ps_index <= order ; ++ps_index, phase_index += 2u )
         {
-            dest->voltage = src->voltage;
-            dest->frequency = src->frequency;
-            dest->lag = src->lag;
+            phase_values[ ps_index ] = ps_value;
+        }
 
-            status = SIXTRL_ARCH_STATUS_SUCCESS;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
 
-            if( src->order > ( NS(rf_multipole_int_t) )0u )
-            {
-                typedef NS(rf_multipole_real_t) real_t;
-                typedef SIXTRL_BE_DATAPTR_DEC real_t* dest_ptr_t;
-                typedef SIXTRL_BE_DATAPTR_DEC real_t const* src_ptr_t;
+    return status;
+}
 
-                SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0.0;
-                NS(buffer_size_t) const bal_size = ( NS(buffer_size_t)
-                    )NS(RFMultiPole_num_bal_elements)( src );
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_set_phase_s)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT mpole,
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+        SIXTRL_RESTRICT in_ps_it ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-                NS(buffer_size_t) const phase_size = ( NS(buffer_size_t)
-                    )NS(RFMultiPole_num_phase_elements)( src );
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)* phase_values =
+        NS(RFMultipole_phase_begin)( mpole );
 
-                dest_ptr_t dest_bal = NS(RFMultiPole_bal)( dest );
-                dest_ptr_t dest_p = NS(RFMultiPole_phase)( dest );
+    NS(buffer_size_t) phase_index = ( NS(buffer_size_t) )0u;
+    NS(rf_multipole_int_t) ps_index = ( NS(rf_multipole_int_t) )1;
+    NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mpole );
 
-                src_ptr_t src_bal = NS(RFMultiPole_const_bal)( src );
-                src_ptr_t src_p = NS(RFMultiPole_const_phase)( src );
+    if( ( mpole != SIXTRL_NULLPTR ) && ( phase_values != SIXTRL_NULLPTR ) &&
+        ( in_ps_it != SIXTRL_NULLPTR ) )
+    {
+        for( ; ps_index <= order ; ++ps_index, phase_index += 2u, ++in_ps_it )
+        {
+            phase_values[ phase_index ] = *in_ps_it;
+        }
 
-                if( ( dest_bal != SIXTRL_NULLPTR ) &&
-                    ( src_bal != SIXTRL_NULLPTR ) )
-                {
-                    SIXTRACKLIB_COPY_VALUES(
-                        real_t, dest_bal, src_bal, bal_size );
-                }
-                else if( dest_bal != SIXTRL_NULLPTR )
-                {
-                    SIXTRACKLIB_SET_VALUES( real_t, dest_bal, bal_size, ZERO );
-                }
-                else
-                {
-                    status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
-                }
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(RFMultipole_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)* SIXTRL_RESTRICT dst,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-                if( ( dest_p != SIXTRL_NULLPTR ) &&
-                    ( src_p != SIXTRL_NULLPTR ) )
+    if( ( dst != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
+    {
+        if( ( dst != src ) &&
+            ( NS(RFMultipole_order)( dst ) == NS(RFMultipole_order)( src ) ) )
+        {
+            SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+                in_phase_it = NS(RFMultipole_const_phase_begin)( src );
+
+            SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+                in_phase_end = NS(RFMultipole_const_phase_end)( src );
+
+            SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+                dst_phase_it = NS(RFMultipole_phase_begin)( dst );
+
+            SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+                in_bal_it = NS(RFMultipole_const_bal_begin)( src );
+
+            SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const*
+                in_bal_end = NS(RFMultipole_const_bal_end)( src );
+
+            SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t)*
+                dst_bal_it = NS(RFMultipole_bal_begin)( dst );
+
+            status = ( NS(arch_status_t)
+                )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+            if( ( in_phase_it  != SIXTRL_NULLPTR ) &&
+                ( in_phase_end != SIXTRL_NULLPTR ) &&
+                ( dst_phase_it != SIXTRL_NULLPTR ) )
+            {
+                for( ; in_phase_it != in_phase_end ;
+                        ++in_phase_it, ++dst_phase_it )
                 {
-                    SIXTRACKLIB_COPY_VALUES( real_t, dest_p, src_p, phase_size );
+                    *dst_phase_it = *in_phase_it;
                 }
-                else if( dest_p != SIXTRL_NULLPTR )
+
+                status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+            }
+            else if( ( in_phase_it  == SIXTRL_NULLPTR ) &&
+                     ( in_phase_end == SIXTRL_NULLPTR ) &&
+                     ( dst_phase_it == SIXTRL_NULLPTR ) )
+            {
+                status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+            }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = (
+                    NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+                if( ( in_bal_it  != SIXTRL_NULLPTR ) &&
+                    ( in_bal_end != SIXTRL_NULLPTR ) &&
+                    ( dst_bal_it != SIXTRL_NULLPTR ) )
                 {
-                    SIXTRACKLIB_SET_VALUES( real_t, dest_p, phase_size, ZERO );
+                    for( ; in_bal_it != in_bal_end ;
+                            ++in_bal_it, ++dst_bal_it )
+                    {
+                        *dst_bal_it = *in_bal_it;
+                    }
+
+                    status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
                 }
-                else
+                else if( ( in_bal_it  == SIXTRL_NULLPTR ) &&
+                         ( in_bal_end == SIXTRL_NULLPTR ) &&
+                         ( dst_bal_it == SIXTRL_NULLPTR ) )
                 {
-                    status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+                    status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
                 }
             }
+
+            if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+            {
+                status = NS(RFMultipole_set_voltage)(
+                    dst, NS(RFMultipole_voltage)( src ) );
+
+                status |= NS(RFMultipole_set_frequency)(
+                    dst, NS(RFMultipole_frequency)( src ) );
+
+                status |= NS(RFMultipole_set_lag)(
+                    dst, NS(RFMultipole_lag)( src ) );
+            }
+        }
+        else if( src == dst )
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
         }
     }
 
     return status;
 }
 
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const*
+NS(RFMultipole_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const obj ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const* elem = SIXTRL_NULLPTR;
+    if( ( obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_RF_MULTIPOLE) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(RFMultipole) ) ) )
+    {
+        elem = ( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const* )(
+            uintptr_t )NS(Object_get_begin_addr)( obj );
+    }
+
+    return elem;
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* obj ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+        )NS(RFMultipole_const_from_obj_index)( obj );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const*
+NS(RFMultipole_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(RFMultipole_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(RFMultipole_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const*
+NS(RFMultipole_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(RFMultipole_const_from_obj_index)( NS(Buffer_get_const_object)(
+        buffer, index ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(RFMultipole)*
+NS(RFMultipole_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(RFMultipole_from_obj_index)( NS(Buffer_get_object)(
+        buffer, index ) );
+}
+
+#endif /* Host */
 #if defined( __cplusplus ) && !defined( _GPUCODE )
 }
 #endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
-
 #endif /* SIXTRACKL_COMMON_BE_RFMULTIPOLE_BE_RFMULTIPOLE_C99_H__ */
diff --git a/sixtracklib/common/be_rfmultipole/track.h b/sixtracklib/common/be_rfmultipole/track.h
index 8e457832..4165b685 100644
--- a/sixtracklib/common/be_rfmultipole/track.h
+++ b/sixtracklib/common/be_rfmultipole/track.h
@@ -5,6 +5,9 @@
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/track/definitions.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
+    #include "sixtracklib/common/internal/math_constants.h"
+    #include "sixtracklib/common/internal/math_functions.h"
+    #include "sixtracklib/common/internal/physics_constants.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/particles.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
@@ -13,12 +16,12 @@
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-struct NS(RFMultiPole);
+struct NS(RFMultipole);
 
 SIXTRL_STATIC SIXTRL_FN NS(track_status_t) NS(Track_particle_rf_multipole)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
     NS(particle_num_elements_t) const particle_index,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(RFMultiPole)
+    SIXTRL_BE_ARGPTR_DEC const struct NS(RFMultipole)
         *const SIXTRL_RESTRICT mpole );
 
 #if !defined( _GPUCODE ) && defined( __cplusplus )
@@ -36,7 +39,7 @@ extern "C" {
 SIXTRL_INLINE NS(track_status_t) NS(Track_particle_rf_multipole)(
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
     NS(particle_num_elements_t) const ii,
-    SIXTRL_BE_ARGPTR_DEC const NS(RFMultiPole) *const SIXTRL_RESTRICT mpole )
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mpole )
 {
     typedef NS(rf_multipole_real_t) real_t;
     typedef NS(rf_multipole_int_t) int_t;
@@ -44,21 +47,16 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_rf_multipole)(
     SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, ii ) ==
                    ( NS(particle_index_t) )1 );
 
-    SIXTRL_BUFFER_DATAPTR_DEC NS(rf_multipole_real_t) const* bal =
-        NS(RFMultiPole_const_bal)( mpole );
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* bal =
+        NS(RFMultipole_const_bal_begin)( mpole );
 
-    SIXTRL_BUFFER_DATAPTR_DEC NS(rf_multipole_real_t) const* phase =
-        NS(RFMultiPole_const_phase)( mpole );
-
-    real_t const order = NS(RFMultiPole_order)( mpole );
-
-    real_t const voltage = NS(RFMultiPole_voltage)( mpole );
-    real_t const frequency = NS(RFMultiPole_frequency)( mpole );
-    real_t const lag = NS(RFMultiPole_lag)( mpole );
+    SIXTRL_BE_DATAPTR_DEC NS(rf_multipole_real_t) const* phase =
+        NS(RFMultipole_const_phase_begin)( mpole );
 
+    int_t const order = NS(RFMultipole_order)( mpole );
     real_t const DEG2RAD  = SIXTRL_PI / ( real_t )180.0;
-    real_t const K_FACTOR = ( ( real_t )2.0 * SIXTRL_PI ) / SIXTRL_C_LIGHT;
-    real_t const k = K_FACTOR * frequency;
+    real_t const k = NS(RFMultipole_frequency)( mpole ) *
+        ( ( real_t )2.0 * NS(MathConst_pi)() ) / NS(PhysConst_clight)();
 
     real_t const x = NS(Particles_get_x_value)( particles, ii );
     real_t const y = NS(Particles_get_y_value)( particles, ii );
@@ -66,11 +64,11 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_rf_multipole)(
     real_t const beta0  = NS(Particles_get_beta0_value)( particles, ii );
     real_t const zeta   = NS(Particles_get_zeta_value)( particles, ii );
     real_t const q      = NS(Particles_get_q0_value)( particles, ii ) *
-                          NS(Particles_get_charge_ratio_value)( particles, ii );
-    real_t const rvv    = NS(Particles_get_rvv_value)( particles, ii );
-    real_t const tau    = zeta / ( beta0 * rvv );
+                          NS(Particles_get_charge_ratio_value)( particles, ii ) *
+                          NS(PhysConst_charge0)();
 
-    real_t const ktau = k * tau;
+    real_t const rvv    = NS(Particles_get_rvv_value)( particles, ii );
+    real_t const ktau   = k * zeta / ( beta0 * rvv );
 
     real_t dpx = 0.0;
     real_t dpy = 0.0;
@@ -80,16 +78,16 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_rf_multipole)(
 
     for (int_t kk = 0; kk <= order; kk++)
     {
-        real_t const pn_kk = DEG2RAD * phase[2*kk] - ktau;
+        real_t const pn_kk = NS(MathConst_deg2rad)() * phase[2*kk] - ktau;
         real_t const ps_kk = DEG2RAD * phase[2*kk+1] - ktau;
 
         real_t const bal_n_kk = bal[2*kk];
         real_t const bal_s_kk = bal[2*kk+1];
 
-        real_t const cn = cos(pn_kk);
-        real_t const cs = cos(ps_kk);
-        real_t const sn = sin(pn_kk);
-        real_t const ss = sin(ps_kk);
+        real_t const cn = NS(cos)(pn_kk);
+        real_t const cs = NS(cos)(ps_kk);
+        real_t const sn = NS(sin)(pn_kk);
+        real_t const ss = NS(sin)(ps_kk);
 
         dpx += cn * (bal_n_kk * zre) - cs * (bal_s_kk * zim);
         dpy += cs * (bal_s_kk * zre) + cn * (bal_n_kk * zim);
@@ -101,7 +99,8 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_rf_multipole)(
         dptr += sn * (bal_n_kk * zre) - ss * (bal_s_kk * zim);
     }
 
-    real_t const cav_energy = q * ( voltage * sin(lag * DEG2RAD - ktau) );
+    real_t const cav_energy = q * ( NS(RFMultipole_voltage)( mpole ) * NS(sin)(
+            NS(RFMultipole_lag)( mpole ) * NS(MathConst_deg2rad)() - ktau) );
     real_t const p0c = NS(Particles_get_p0c_value)( particles, ii);
     real_t const rfmultipole_energy = - q * ( (k * p0c) * dptr );
 
diff --git a/sixtracklib/common/be_srotation/CMakeLists.txt b/sixtracklib/common/be_srotation/CMakeLists.txt
index e719fd43..f0bbe17a 100644
--- a/sixtracklib/common/be_srotation/CMakeLists.txt
+++ b/sixtracklib/common/be_srotation/CMakeLists.txt
@@ -1,49 +1,38 @@
-set( SIXTRACKLIB_COMMON_BE_SROTATION_C99_HEADERS
-     be_srotation.h
-)
+set( SIXTRL_COMMON_BE_SROTATION_C99_HEADERS be_srotation.h track.h )
+set( SIXTRL_COMMON_BE_SROTATION_C99_SOURCES be_srotation.c )
+set( SIXTRL_COMMON_BE_SROTATION_CXX_HEADERS be_srotation.hpp )
 
-set( SIXTRACKLIB_COMMON_BE_SROTATION_CXX_HEADERS
-     be_srotation.hpp
-)
+add_library( sixtrack_common_be_srotation OBJECT
+    ${SIXTRL_COMMON_BE_SROTATION_C99_HEADERS}
+    ${SIXTRL_COMMON_BE_SROTATION_C99_SOURCES} )
 
-if( SIXTRACKLIB_COMMON_BE_SROTATION_C99_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_srotation/\\1" LOCAL_C99_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_SROTATION_C99_HEADERS}" )
+target_include_directories( sixtrack_common_be_srotation PRIVATE
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-    set(  SIXTRACKLIB_COMMON_C99_HEADERS
-        ${SIXTRACKLIB_COMMON_C99_HEADERS}
-        ${LOCAL_C99_HEADERS} PARENT_SCOPE )
-endif()
+set_target_properties( sixtrack_common_be_srotation PROPERTIES
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
+    C_STANDARD_REQUIRED ON )
 
-if( SIXTRACKLIB_COMMON_BE_SROTATION_CXX_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_srotation/\\1" LOCAL_CXX_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_SROTATION_CXX_HEADERS}" )
+target_compile_options( sixtrack_common_be_srotation PRIVATE
+        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
-    set(  SIXTRACKLIB_COMMON_CXX_HEADERS
-        ${SIXTRACKLIB_COMMON_CXX_HEADERS}
-        ${LOCAL_CXX_HEADERS} PARENT_SCOPE )
-endif()
+# ------------------------------------------------------------------------------
+# pass on sixtrack_common_be_beambeam as a module for sixtracklib:
+
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_common_be_srotation> CACHE INTERNAL "" FORCE )
 
 # ----------------------------------------------------------------------------
 # install :
 
-if( SIXTRACKLIB_COMMON_BE_SROTATION_C99_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_SROTATION_C99_INSTALL_PATH
-         include/sixtracklib/common/be_srotation )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_SROTATION_C99_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_SROTATION_C99_INSTALL_PATH} )
+if( SIXTRL_COMMON_BE_SROTATION_C99_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_SROTATION_C99_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/be_srotation" )
 endif()
 
+if( SIXTRACKL_ENABLE_CXX AND SIXTRL_COMMON_BE_SROTATION_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_SROTATION_CXX_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/be_srotation" )
+ endif()
 
-if( SIXTRACKLIB_COMMON_BE_SROTATION_CXX_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_SROTATION_CXX_INSTALL_PATH
-         include/sixtracklib/common/be_srotation )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_SROTATION_CXX_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_SROTATION_CXX_INSTALL_PATH} )
-endif()
-
-#end: sixtracklib/common/be_srotation/CMakeLists.txt
diff --git a/sixtracklib/common/be_srotation/be_srotation.c b/sixtracklib/common/be_srotation/be_srotation.c
new file mode 100644
index 00000000..8c531131
--- /dev/null
+++ b/sixtracklib/common/be_srotation/be_srotation.c
@@ -0,0 +1,154 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/be_srotation/be_srotation.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+NS(object_type_id_t) NS(SRotation_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(SRotation_type_id)();
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(SRotation_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( srot ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ( buf_size_t )0 ) &&
+        ( max_num_offsets > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(SRotation_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( srot ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ( buf_size_t )0 ) &&
+        ( max_num_sizes > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(SRotation_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( srot ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ( buf_size_t )0 ) &&
+        ( max_num_counts > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(SRotation_can_be_added)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BE_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    NS(SRotation) temp;
+    NS(arch_status_t) const status = NS(SRotation_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(SRotation_num_dataptrs)( &temp );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof( NS(SRotation) ),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects,
+                    requ_slots, requ_dataptrs ) ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(SRotation)* NS(SRotation_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* added_elem = SIXTRL_NULLPTR;
+
+    NS(SRotation) temp;
+    NS(arch_status_t) const status = NS(SRotation_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(SRotation_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SRotation)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(SRotation) ), NS(SRotation_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(SRotation)* NS(SRotation_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_REAL_T  const cos_angle, SIXTRL_REAL_T const sin_angle )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) ndataptrs = ( NS(buffer_size_t) )0;
+
+    NS(SRotation) temp;
+    NS(arch_status_t) status = NS(SRotation_set_cos_angle)( &temp, cos_angle );
+    status |= NS(SRotation_set_sin_angle)( &temp, sin_angle );
+    ndataptrs = NS(SRotation_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SRotation)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(SRotation) ), NS(SRotation_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(SRotation)* NS(SRotation_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(SRotation_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(SRotation)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(SRotation) ), NS(SRotation_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
diff --git a/sixtracklib/common/be_srotation/be_srotation.h b/sixtracklib/common/be_srotation/be_srotation.h
index 5af857fe..a7501918 100644
--- a/sixtracklib/common/be_srotation/be_srotation.h
+++ b/sixtracklib/common/be_srotation/be_srotation.h
@@ -9,10 +9,12 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -28,83 +30,153 @@ typedef struct NS(SRotation)
 }
 NS(SRotation);
 
-/* ------------------------------------------------------------------------- */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(SRotation_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation );
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(SRotation_type_id)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(SRotation_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(SRotation_get_num_slots)(
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(SRotation_num_slots)(
     SIXTRL_BE_ARGPTR_DEC  const NS(SRotation) *const SIXTRL_RESTRICT srot,
-    NS(buffer_size_t) const slot_size );
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_ARGPTR_DEC NS(SRotation)* NS(SRotation_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation );
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_REAL_T NS(SRotation_get_angle_deg)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SRotation)*
+NS(SRotation_preset)( SIXTRL_BE_ARGPTR_DEC NS(SRotation)*
+    SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_REAL_T NS(SRotation_get_angle)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SRotation_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)*
+        SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_REAL_T NS(SRotation_get_cos_angle)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_REAL_T NS(SRotation_get_sin_angle)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SRotation_angle_deg)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SRotation_angle)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SRotation_cos_angle)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(SRotation_set_angle)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(SRotation_sin_angle)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SRotation_set_angle)(
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation,
+    SIXTRL_REAL_T const angle ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SRotation_set_angle_deg)(
     SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation,
-    SIXTRL_REAL_T const angle );
+    SIXTRL_REAL_T const angle_deg ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(SRotation_set_angle_deg)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SRotation_set_cos_angle)(
     SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation,
-    SIXTRL_REAL_T const angle_deg );
+    SIXTRL_REAL_T const cos_angle ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(SRotation_set_sin_angle)(
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation,
+    SIXTRL_REAL_T const sin_angle ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN int NS(SRotation_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT dst,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(SRotation_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC int NS(SRotation_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT source );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SRotation) const*
+NS(SRotation_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int  NS(SRotation_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT rhs );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SRotation)*
+NS(SRotation_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int  NS(SRotation_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SRotation) const*
+NS(SRotation_const_from_manged_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
+    NS(buffer_size_t) const be_index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(SRotation)*
+NS(SRotation_from_manged_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
+    NS(buffer_size_t) const be_index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_FN SIXTRL_STATIC bool NS(SRotation_can_be_added)(
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(SRotation) const*
+NS(SRotation_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const be_index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(SRotation)*
+NS(SRotation_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const be_index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(SRotation_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(SRotation_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(SRotation_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t) NS(SRotation_type_id_ext)(
+    void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(SRotation_can_be_added)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)* NS(SRotation_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)*
+NS(SRotation_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buf );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)* NS(SRotation_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)*
+NS(SRotation_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_REAL_T const angle );
+    SIXTRL_REAL_T const cos_angle, SIXTRL_REAL_T const sin_angle );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)*
-NS(SRotation_add_detailed)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_REAL_T const cos_z, SIXTRL_REAL_T const sin_z );
-
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)*
 NS(SRotation_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
     SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation );
 
 #endif /* !defined( _GPUCODE ) */
-
-/* ========================================================================= */
-
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
@@ -113,11 +185,12 @@ NS(SRotation_add_copy)(
 /* *****          Implementation of C inline functions                   *** */
 /* ************************************************************************* */
 
-#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
-    #include <math.h>
-#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
-
 #if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #include "sixtracklib/common/internal/math_functions.h"
+    #include "sixtracklib/common/internal/math_constants.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
     #if !defined( _GPUCODE )
         #include "sixtracklib/common/buffer.h"
     #endif /* !defined( _GPUCODE ) */
@@ -127,361 +200,233 @@ NS(SRotation_add_copy)(
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_INLINE NS(buffer_size_t) NS(SRotation_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation )
+SIXTRL_INLINE NS(object_type_id_t) NS(SRotation_type_id)( void ) SIXTRL_NOEXCEPT
 {
-    ( void )srotation;
-    return ( NS(buffer_size_t) )0u;
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_SROTATION);
 }
 
-SIXTRL_INLINE NS(buffer_size_t) NS(SRotation_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(SRotation) *const SIXTRL_RESTRICT srot,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(buffer_size_t) NS(SRotation_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC
+    const NS(SRotation) *const SIXTRL_RESTRICT
+        SIXTRL_UNUSED( srotation ) ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(SRotation)     beam_element_t;
-
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    return ( NS(buffer_size_t) )0u;
+}
 
-    ( void )srot;
+SIXTRL_INLINE NS(buffer_size_t) NS(SRotation_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC  const NS(SRotation) *const SIXTRL_RESTRICT
+        SIXTRL_UNUSED( srotation ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) st_size_t;
+    st_size_t num_slots = ( st_size_t )0u;
 
-    buf_size_t extent = NS(ManagedBuffer_get_slot_based_length)(
-        sizeof( beam_element_t ), slot_size );
+    if( slot_size > ( st_size_t )0 )
+    {
+        st_size_t const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(SRotation) ), slot_size );
+        num_slots = num_bytes / slot_size;
+        if( num_slots * slot_size < num_bytes ) ++num_slots;
+    }
 
-    SIXTRL_ASSERT( ( slot_size == ZERO ) || ( ( extent % slot_size ) == ZERO ) );
-    return ( slot_size > ZERO ) ? ( extent / slot_size ) : ( ZERO );
+    return num_slots;
 }
 
+/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
+
 SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SRotation)* NS(SRotation_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation )
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT
+        srotation ) SIXTRL_NOEXCEPT
 {
-    NS(SRotation_clear)( srotation );
+    if( srotation != SIXTRL_NULLPTR ) NS(SRotation_clear)( srotation );
     return srotation;
 }
 
-SIXTRL_INLINE SIXTRL_REAL_T NS(SRotation_get_angle_deg)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation )
+SIXTRL_INLINE NS(arch_status_t) NS(SRotation_clear)( SIXTRL_BE_ARGPTR_DEC
+    NS(SRotation)* SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_REAL_T const RAD2DEG = ( SIXTRL_REAL_T )180.0 / M_PI;
-    return RAD2DEG * NS(SRotation_get_angle)( srotation );
+    NS(arch_status_t) status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    status |= NS(SRotation_set_cos_angle)( srotation, ( SIXTRL_REAL_T )1 );
+    status |= NS(SRotation_set_sin_angle)( srotation, ( SIXTRL_REAL_T )0 );
+    return status;
 }
 
-SIXTRL_INLINE SIXTRL_REAL_T NS(SRotation_get_angle)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation )
-{
-    SIXTRL_STATIC_VAR SIXTRL_REAL_T const ZERO = ( SIXTRL_REAL_T )0.0;
-    SIXTRL_STATIC_VAR SIXTRL_REAL_T const ONE  = ( SIXTRL_REAL_T )1.0;
-
-    #if !defined( NDEBUG ) && !defined( _GPUCODE )
-    SIXTRL_STATIC_VAR SIXTRL_REAL_T const EPS  = ( SIXTRL_REAL_T )1e-6;
-    #endif /* !defined( NDEBUG ) && !defined( _GPUCODE )*/
-
-    SIXTRL_REAL_T const sin_z = ( srotation != SIXTRL_NULLPTR )
-        ? srotation->sin_z : ZERO;
-
-    SIXTRL_REAL_T const cos_z = ( srotation != SIXTRL_NULLPTR )
-        ? srotation->cos_z : ONE;
-
-    SIXTRL_REAL_T const angle = ( sin_z >= ZERO )
-        ? acos( cos_z ) : -acos( cos_z );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    #if !defined( NDEBUG ) && !defined( _GPUCODE )
-    SIXTRL_REAL_T const temp_sin_z = sin( angle );
-    SIXTRL_REAL_T const delta      = temp_sin_z - srotation->sin_z;
-    SIXTRL_ASSERT( fabs( delta ) < EPS );
-    #endif /* !defined( NDEBUG ) && !defined( _GPUCODE ) */
+SIXTRL_INLINE SIXTRL_REAL_T NS(SRotation_angle_deg)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SRotation) *const SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT
+{
+    return NS(MathConst_rad2deg)() * NS(SRotation_angle)( srotation );
+}
 
-    return angle;
+SIXTRL_INLINE SIXTRL_REAL_T NS(SRotation_angle)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SRotation) *const SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT
+{
+    return NS(atan2)( NS(SRotation_sin_angle)( srotation ),
+                      NS(SRotation_cos_angle)( srotation ) );
 }
 
-SIXTRL_INLINE SIXTRL_REAL_T NS(SRotation_get_cos_angle)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation )
+SIXTRL_INLINE SIXTRL_REAL_T NS(SRotation_cos_angle)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SRotation) *const SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( srotation != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Type_comp_all_less_or_equal)( NS(abs)( srotation->cos_z ),
+        ( SIXTRL_REAL_T )1 ) );
+    SIXTRL_ASSERT( NS(Type_comp_all_less_or_equal)( NS(abs)( srotation->sin_z ),
+        ( SIXTRL_REAL_T )1 ) );
+
     return srotation->cos_z;
 }
 
-SIXTRL_INLINE SIXTRL_REAL_T NS(SRotation_get_sin_angle)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srotation )
+SIXTRL_INLINE SIXTRL_REAL_T NS(SRotation_sin_angle)( SIXTRL_BE_ARGPTR_DEC const
+    NS(SRotation) *const SIXTRL_RESTRICT srotation ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( srotation != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Type_comp_all_less_or_equal)( NS(abs)( srotation->cos_z ),
+        ( SIXTRL_REAL_T )1 ) );
+    SIXTRL_ASSERT( NS(Type_comp_all_less_or_equal)( NS(abs)( srotation->sin_z ),
+        ( SIXTRL_REAL_T )1 ) );
+
     return srotation->sin_z;
 }
 
-SIXTRL_INLINE void NS(SRotation_set_angle)(
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(SRotation_set_angle)(
     SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation,
-    SIXTRL_REAL_T const angle )
+    SIXTRL_REAL_T const angle ) SIXTRL_NOEXCEPT
 {
-    if( srotation != SIXTRL_NULLPTR )
-    {
-        srotation->cos_z = cos( angle );
-        srotation->sin_z = sin( angle );
-    }
-
-    return;
+    SIXTRL_ASSERT( srotation != SIXTRL_NULLPTR );
+    srotation->cos_z = NS(cos)( angle );
+    srotation->sin_z = NS(sin)( angle );
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(SRotation_set_angle_deg)(
+SIXTRL_INLINE NS(arch_status_t) NS(SRotation_set_angle_deg)(
     SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation,
-    SIXTRL_REAL_T const angle_deg )
+    SIXTRL_REAL_T const angle_deg ) SIXTRL_NOEXCEPT
 {
-    SIXTRL_STATIC_VAR SIXTRL_REAL_T const DEG2RAD =
-        M_PI / ( SIXTRL_REAL_T )180.0;
-
-    NS(SRotation_set_angle)( srotation, DEG2RAD * angle_deg );
-
-    return;
+    return NS(SRotation_set_angle)( srotation,
+        NS(MathConst_deg2rad)() * angle_deg );
 }
 
-SIXTRL_INLINE void NS(SRotation_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation )
+SIXTRL_INLINE NS(arch_status_t) NS(SRotation_set_cos_angle)(
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation,
+    SIXTRL_REAL_T const cos_angle ) SIXTRL_NOEXCEPT
 {
-    if( srotation != SIXTRL_NULLPTR )
-    {
-        srotation->cos_z = ( SIXTRL_REAL_T )1;
-        srotation->sin_z = ( SIXTRL_REAL_T )0;
-    }
+    SIXTRL_ASSERT( srotation != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Type_comp_all_less_or_equal)( NS(abs)( cos_angle ),
+        ( SIXTRL_REAL_T )1 ) );
 
-    return;
+    srotation->cos_z = cos_angle;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE int NS(SRotation_copy)(
-    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT source )
+SIXTRL_INLINE NS(arch_status_t) NS(SRotation_set_sin_angle)(
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT srotation,
+    SIXTRL_REAL_T const sin_angle ) SIXTRL_NOEXCEPT
 {
-    int success = -1;
-
-    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) )
-    {
-        destination->cos_z = NS(SRotation_get_cos_angle)( source );
-        destination->sin_z = NS(SRotation_get_sin_angle)( source );
-        success = 0;
-    }
+    SIXTRL_ASSERT( srotation != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Type_comp_all_less_or_equal)( NS(abs)( sin_angle ),
+        ( SIXTRL_REAL_T )1 ) );
 
-    return success;
+    srotation->sin_z = sin_angle;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE int NS(SRotation_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT rhs )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE int NS(SRotation_copy)(
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation)* SIXTRL_RESTRICT dst,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
 {
-    int compare_value = -1;
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
 
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    if( ( dst != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
     {
-        compare_value = 0;
-
-        if( NS(SRotation_get_cos_angle)( lhs ) >
-            NS(SRotation_get_cos_angle)( rhs ) )
-        {
-            compare_value = +1;
-        }
-        else if( NS(SRotation_get_cos_angle)( lhs ) <
-                 NS(SRotation_get_cos_angle)( rhs ) )
+        if( dst != src )
         {
-            compare_value = -1;
-        }
+            status = NS(SRotation_set_cos_angle)(
+                dst, NS(SRotation_cos_angle)( src ) );
 
-        if( compare_value == 0 )
+            status |= NS(SRotation_set_sin_angle)(
+                dst, NS(SRotation_sin_angle)( src ) );
+        }
+        else
         {
-            if( NS(SRotation_get_sin_angle)( lhs ) >
-                NS(SRotation_get_sin_angle)( rhs ) )
-            {
-                compare_value = +1;
-            }
-            else if( NS(SRotation_get_sin_angle)( lhs ) <
-                     NS(SRotation_get_sin_angle)( rhs ) )
-            {
-                compare_value = -1;
-            }
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
         }
     }
-    else if( lhs != SIXTRL_NULLPTR )
-    {
-        compare_value = +1;
-    }
 
-    return compare_value;
+    return status;
 }
 
-SIXTRL_INLINE int NS(SRotation_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
-{
-    typedef SIXTRL_REAL_T       real_t;
-
-    SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0.0;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    int compare_value = -1;
-
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) &&
-        ( treshold >= ZERO ) )
-    {
-        compare_value = 0;
-
-        if( compare_value == 0 )
-        {
-            real_t const diff = NS(SRotation_get_cos_angle)( lhs ) -
-                                NS(SRotation_get_cos_angle)( rhs );
-
-            real_t const abs_diff = ( diff >= ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            real_t const diff = NS(SRotation_get_sin_angle)( lhs ) -
-                                NS(SRotation_get_sin_angle)( rhs );
-
-            real_t const abs_diff = ( diff >= ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-    }
-    else if( ( lhs != SIXTRL_NULLPTR ) && ( treshold >= ZERO ) )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SRotation) const*
+NS(SRotation_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const obj ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_BE_ARGPTR_DEC NS(SRotation) const* elem = SIXTRL_NULLPTR;
+    if( ( obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_SROTATION) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(SRotation) ) ) )
     {
-        compare_value = +1;
+        elem = ( SIXTRL_BE_ARGPTR_DEC NS(SRotation) const* )(
+            uintptr_t )NS(Object_get_begin_addr)( obj );
     }
 
-    return compare_value;
+    return elem;
 }
 
-#if !defined( _GPUCODE )
-
-SIXTRL_INLINE bool NS(SRotation_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SRotation)* NS(SRotation_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* obj ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-
-    buf_size_t const num_dataptrs =
-        NS(SRotation_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes  = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts = SIXTRL_NULLPTR;
-
-    return NS(Buffer_can_add_object)( buffer, sizeof( NS(SRotation) ),
-        num_dataptrs, sizes, counts, requ_objects, requ_slots, requ_dataptrs );
+    return ( SIXTRL_BE_ARGPTR_DEC NS(SRotation)*
+        )NS(SRotation_const_from_obj_index)( obj );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)* NS(SRotation_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SRotation) const*
+NS(SRotation_const_from_manged_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef SIXTRL_REAL_T                           real_t;
-    typedef NS(SRotation)                           elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC   elem_t*     ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(SRotation_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.cos_z = ( real_t )1.0;
-    temp_obj.sin_z = ( real_t )0.0;
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_SROTATION), num_dataptrs, offsets, sizes, counts ) );
+    return NS(SRotation_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)* NS(SRotation_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_REAL_T const angle )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SRotation)*
+NS(SRotation_from_manged_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(SRotation)                           elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC   elem_t*     ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(SRotation_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.cos_z = cos( angle );
-    temp_obj.sin_z = sin( angle );
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_SROTATION), num_dataptrs, offsets, sizes, counts ) );
+    return NS(SRotation_from_obj_index)( NS(ManagedBuffer_get_object)(
+        buffer, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)* NS(SRotation_add_detailed)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_REAL_T const cos_z, SIXTRL_REAL_T const sin_z )
+#if !defined( _GPUCODE )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SRotation) const*
+NS(SRotation_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(SRotation)                           elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC   elem_t*     ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(SRotation_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    #if !defined( NDEBUG )
-    typedef SIXTRL_REAL_T  real_t;
-
-    real_t temp = ( real_t )1 - ( cos_z * cos_z + sin_z * sin_z );
-    if( temp < ( real_t )0.0 ) temp = -temp;
-    SIXTRL_ASSERT( temp < ( real_t )1e-12 );
-    #endif /* !defined( NDEBUG ) */
-
-    elem_t temp_obj;
-    temp_obj.cos_z = cos_z;
-    temp_obj.sin_z = sin_z;
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_SROTATION), num_dataptrs, offsets, sizes, counts ) );
+    return NS(SRotation_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(SRotation)* NS(SRotation_add_copy)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(SRotation)* NS(SRotation_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srot )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    return NS(SRotation_add_detailed)( buffer,
-        NS(SRotation_get_cos_angle)( srot ),
-        NS(SRotation_get_sin_angle)( srot ) );
+    return NS(SRotation_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
 }
-
-#endif /* !defined( _GPUCODE ) */
+#endif /* Host */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRACKLIB_COMMON_BE_SROTATION_BEAM_ELEMENT_SROTATION_H__ */
-/*end: sixtracklib/common/be_srotation/be_srotation.h */
diff --git a/sixtracklib/common/be_srotation/be_srotation.hpp b/sixtracklib/common/be_srotation/be_srotation.hpp
index 82427469..3757f900 100644
--- a/sixtracklib/common/be_srotation/be_srotation.hpp
+++ b/sixtracklib/common/be_srotation/be_srotation.hpp
@@ -15,6 +15,7 @@
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/buffer.hpp"
+    #include "sixtracklib/common/internal/math_functions.h"
     #include "sixtracklib/common/be_srotation/be_srotation.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
@@ -462,7 +463,8 @@ namespace SIXTRL_CXX_NAMESPACE
         TSRotation< SIXTRL_REAL_T >::value_type const angle )
     {
         using ptr_t = SIXTRL_ARGPTR_DEC TSRotation< SIXTRL_REAL_T >*;
-        return static_cast< ptr_t >( ::NS(SRotation_add)( &buffer, angle ) );
+        return static_cast< ptr_t >( ::NS(SRotation_add)( &buffer,
+            NS(cos)( angle ), NS(sin)( angle ) ) );
     }
 
     SIXTRL_INLINE SIXTRL_ARGPTR_DEC TSRotation< SIXTRL_REAL_T >*
@@ -517,25 +519,25 @@ namespace SIXTRL_CXX_NAMESPACE
     SIXTRL_INLINE TSRotation< SIXTRL_REAL_T >::value_type
     TSRotation< SIXTRL_REAL_T >::getCosAngle() const SIXTRL_NOEXCEPT
     {
-        return ::NS(SRotation_get_cos_angle)( this->getCApiPtr() );
+        return ::NS(SRotation_cos_angle)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE TSRotation< SIXTRL_REAL_T >::value_type
     TSRotation< SIXTRL_REAL_T >::getSinAngle() const SIXTRL_NOEXCEPT
     {
-        return ::NS(SRotation_get_sin_angle)( this->getCApiPtr() );
+        return ::NS(SRotation_sin_angle)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE TSRotation< SIXTRL_REAL_T >::value_type
     TSRotation< SIXTRL_REAL_T >::getAngle() const SIXTRL_NOEXCEPT
     {
-        return ::NS(SRotation_get_angle)( this->getCApiPtr() );
+        return ::NS(SRotation_angle)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE TSRotation< SIXTRL_REAL_T >::value_type
     TSRotation< SIXTRL_REAL_T >::getAngleDeg() const SIXTRL_NOEXCEPT
     {
-        return ::NS(SRotation_get_angle_deg)( this->getCApiPtr() );
+        return ::NS(SRotation_angle_deg)( this->getCApiPtr() );
     }
 
     SIXTRL_INLINE void TSRotation< SIXTRL_REAL_T >::preset() SIXTRL_NOEXCEPT
@@ -578,8 +580,8 @@ namespace SIXTRL_CXX_NAMESPACE
         Buffer& buffer, SRotation::value_type const angle )
     {
         using ptr_t = SIXTRL_ARGPTR_DEC SRotation*;
-        return static_cast< ptr_t >(
-            ::NS(SRotation_add)( buffer.getCApiPtr(), angle ) );
+        return static_cast< ptr_t >( ::NS(SRotation_add)( buffer.getCApiPtr(),
+            NS(cos)( angle ), NS(sin)( angle ) ) );
     }
 
     SIXTRL_ARGPTR_DEC SRotation* SRotation_add(
@@ -587,15 +589,15 @@ namespace SIXTRL_CXX_NAMESPACE
         SRotation::value_type const angle )
     {
         using ptr_t = SIXTRL_ARGPTR_DEC SRotation*;
-        return static_cast< ptr_t >(
-            ::NS(SRotation_add)( ptr_buf, angle ) );
+        return static_cast< ptr_t >( ::NS(SRotation_add)( ptr_buf,
+            NS(cos)( angle ), NS(sin)( angle ) ) );
     }
 
     SIXTRL_ARGPTR_DEC SRotation* SRotation_add( Buffer& buffer,
         SRotation::value_type const cos_z, SRotation::value_type const sin_z )
     {
         using ptr_t = SIXTRL_ARGPTR_DEC SRotation*;
-        return static_cast< ptr_t >( ::NS(SRotation_add_detailed)(
+        return static_cast< ptr_t >( ::NS(SRotation_add)(
             buffer.getCApiPtr(), cos_z, sin_z ) );
 
     }
@@ -606,13 +608,10 @@ namespace SIXTRL_CXX_NAMESPACE
         SRotation::value_type const sin_z )
     {
         using ptr_t = SIXTRL_ARGPTR_DEC SRotation*;
-        return static_cast< ptr_t >(
-            ::NS(SRotation_add_detailed)( ptr_buffer, cos_z, sin_z ) );
+        return static_cast< ptr_t >( ::NS(SRotation_add)(
+            ptr_buffer, cos_z, sin_z ) );
     }
 }
 
 #endif /* defined( __cplusplus ) */
-
 #endif /* CXX_SIXTRACKLIB_COMMON_BE_SROTATION_BEAM_ELEM_BE_SROTATION_HPP__ */
-
-/* end: sixtracklib/common/be_srotation/be_srotation.hpp */
diff --git a/sixtracklib/common/be_srotation/track.h b/sixtracklib/common/be_srotation/track.h
index 3bd441ab..f9819ba3 100644
--- a/sixtracklib/common/be_srotation/track.h
+++ b/sixtracklib/common/be_srotation/track.h
@@ -42,8 +42,8 @@ SIXTRL_INLINE int NS(Track_particle_srotation)(
 {
     typedef NS(particle_real_t) real_t;
 
-    real_t const sin_z = NS(SRotation_get_sin_angle)( srotation );
-    real_t const cos_z = NS(SRotation_get_cos_angle)( srotation );
+    real_t const sin_z = NS(SRotation_sin_angle)( srotation );
+    real_t const cos_z = NS(SRotation_cos_angle)( srotation );
 
     real_t const x  = NS(Particles_get_x_value)(  particles, index );
     real_t const y  = NS(Particles_get_y_value)(  particles, index );
diff --git a/sixtracklib/common/be_tricub/CMakeLists.txt b/sixtracklib/common/be_tricub/CMakeLists.txt
new file mode 100644
index 00000000..1391f0d3
--- /dev/null
+++ b/sixtracklib/common/be_tricub/CMakeLists.txt
@@ -0,0 +1,35 @@
+set( SIXTRL_COMMON_BE_TRICUB_SOURCES be_tricub.c )
+set( SIXTRL_COMMON_BE_TRICUB_HEADERS be_tricub.h track.h coefficients.h)
+
+add_library( sixtrack_common_be_tricub OBJECT
+    ${SIXTRL_COMMON_BE_TRICUB_HEADERS} ${SIXTRL_COMMON_BE_TRICUB_SOURCES}
+)
+
+target_include_directories( sixtrack_common_be_tricub PRIVATE
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
+    $<INSTALL_INTERFACE:include> )
+
+set_target_properties( sixtrack_common_be_tricub PROPERTIES
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
+    C_STANDARD_REQUIRED ON )
+
+target_compile_options( sixtrack_common_be_tricub PRIVATE
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
+
+# ------------------------------------------------------------------------------
+# pass on sixtrack_common_be_tricub as a module for sixtracklib:
+
+set(  SIXTRACKL_LIBRARY_MODULES
+    ${SIXTRACKL_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_common_be_tricub> CACHE INTERNAL "" FORCE )
+
+# ------------------------------------------------------------------------------
+# install :
+
+set( SIXTRACKLIB_COMMON_BE_TRICUB_C99_INSTALL_PATH
+     "${CMAKE_INSTALL_PREFIX}/include/sixtracklib/common/be_tricub" )
+
+install( FILES ${SIXTRL_COMMON_BE_TRICUB_HEADERS}
+         DESTINATION ${SIXTRACKLIB_COMMON_BE_TRICUB_C99_INSTALL_PATH} )
+
diff --git a/sixtracklib/common/be_tricub/be_tricub.c b/sixtracklib/common/be_tricub/be_tricub.c
new file mode 100644
index 00000000..8be7a9ad
--- /dev/null
+++ b/sixtracklib/common/be_tricub/be_tricub.c
@@ -0,0 +1,520 @@
+#include "sixtracklib/common/be_tricub/be_tricub.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/control/definitions.h"
+#include "sixtracklib/common/internal/objects_type_id.h"
+#include "sixtracklib/common/buffer/assign_address_item.h"
+#include "sixtracklib/common/buffer.h"
+
+NS(object_type_id_t) NS(TriCubData_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCubData_type_id)();
+}
+
+NS(arch_size_t) NS(TriCubData_ptr_offset_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(TriCubData) *const SIXTRL_RESTRICT d ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCubData_ptr_offset)( d );
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+NS(arch_status_t) NS(TriCubData_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    buf_size_t const num_dataptrs = NS(TriCubData_num_dataptrs)( data );
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( max_num_offsets >= num_dataptrs ) &&
+        ( num_dataptrs == ( buf_size_t )1u ) &&
+        ( slot_size > ( buf_size_t )0 ) )
+    {
+        buf_size_t ii = ( buf_size_t )1u;
+        offsets[ 0 ] = NS(TriCubData_ptr_offset)( data );
+        SIXTRL_ASSERT( offsets[ 0 ] % slot_size == ( buf_size_t )0 );
+
+        for( ; ii < max_num_offsets ; ++ii ) offsets[ ii ] = ( buf_size_t )0u;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+NS(arch_status_t) NS(TriCubData_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    buf_size_t const num_dataptrs = NS(TriCubData_num_dataptrs)( data );
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( max_num_counts >= num_dataptrs ) &&
+        ( num_dataptrs == ( buf_size_t )1u ) &&
+        ( slot_size > ( buf_size_t )0 ) )
+    {
+        buf_size_t ii = ( buf_size_t )1u;
+        counts[ 0 ] = NS(TriCubData_table_size)( data );
+
+        for( ; ii < max_num_counts ; ++ii ) counts[ ii ] = ( buf_size_t )0u;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+NS(arch_status_t) NS(TriCubData_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    buf_size_t const num_dataptrs = NS(TriCubData_num_dataptrs)( data );
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( max_num_sizes >= num_dataptrs ) &&
+        ( num_dataptrs == ( buf_size_t )1u ) &&
+        ( slot_size > ( buf_size_t )0 ) )
+    {
+        buf_size_t ii = ( buf_size_t )1u;
+        sizes[ 0 ] = sizeof( NS(be_tricub_real_t) );
+
+        for( ; ii < num_dataptrs ; ++ii ) sizes[ ii ] = ( buf_size_t )0u;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+bool NS(TriCubData_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(be_tricub_int_t) const nx, NS(be_tricub_int_t) const ny,
+    NS(be_tricub_int_t) const nz,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+
+    bool can_be_added = false;
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    buf_size_t num_dataptrs = ( buf_size_t )0u;
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    NS(TriCubData) tricub_data;
+    NS(TriCubData_preset)( &tricub_data );
+    status  = NS(TriCubData_set_nx)( &tricub_data, nx );
+    status |= NS(TriCubData_set_ny)( &tricub_data, ny );
+    status |= NS(TriCubData_set_nz)( &tricub_data, nz );
+    num_dataptrs = NS(TriCubData_num_dataptrs)( &tricub_data );
+
+    if( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+        ( num_dataptrs == ( buf_size_t )1u ) &&
+        ( slot_size > ( buf_size_t )0u ) && ( buffer != SIXTRL_NULLPTR ) )
+    {
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[  1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ];
+
+        status = NS(TriCubData_attributes_sizes)(
+            &sizes[ 0 ], num_dataptrs, &tricub_data, slot_size );
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(TriCubData_attributes_counts)(
+                &counts[ 0 ], num_dataptrs, &tricub_data, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            can_be_added = NS(Buffer_can_add_object)( buffer,
+                sizeof( NS(TriCubData) ), num_dataptrs, sizes, counts,
+                    ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
+        }
+    }
+
+    return can_be_added;
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* NS(TriCubData_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(be_tricub_int_t) const nx, NS(be_tricub_int_t) const ny,
+    NS(be_tricub_int_t) const nz )
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* added_elem = SIXTRL_NULLPTR;
+    typedef NS(buffer_size_t) buf_size_t;
+
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    buf_size_t num_dataptrs = ( buf_size_t )0u;
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    NS(TriCubData) tricub_data;
+    NS(TriCubData_preset)( &tricub_data );
+    status  = NS(TriCubData_set_nx)( &tricub_data, nx );
+    status |= NS(TriCubData_set_ny)( &tricub_data, ny );
+    status |= NS(TriCubData_set_nz)( &tricub_data, nz );
+    num_dataptrs = NS(TriCubData_num_dataptrs)( &tricub_data );
+
+    if( ( status == NS(ARCH_STATUS_SUCCESS) ) && ( buffer != SIXTRL_NULLPTR ) &&
+        ( num_dataptrs == ( buf_size_t )1u ) &&
+        ( slot_size > ( buf_size_t )0u ) )
+    {
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[  1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ];
+
+        status = NS(TriCubData_attributes_sizes)(
+            &sizes[ 0 ], num_dataptrs, &tricub_data, slot_size );
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(TriCubData_attributes_counts)(
+                &counts[ 0 ], num_dataptrs, &tricub_data, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(TriCubData_attributes_offsets)(
+                &offsets[ 0 ], num_dataptrs, &tricub_data, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* )(
+                uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, &tricub_data, sizeof( tricub_data ),
+                        NS(TriCubData_type_id)(), num_dataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(be_tricub_real_t) const x0, NS(be_tricub_real_t) const dx,
+    NS(be_tricub_int_t)  const nx,
+    NS(be_tricub_real_t) const y0, NS(be_tricub_real_t) const dy,
+    NS(be_tricub_int_t)  const ny,
+    NS(be_tricub_real_t) const z0, NS(be_tricub_real_t) const dz,
+    NS(be_tricub_int_t)  const nz,
+    NS(be_tricub_int_t)  const mirror_x, NS(be_tricub_int_t)  const mirror_y,
+    NS(be_tricub_int_t)  const mirror_z, NS(buffer_addr_t) const table_addr )
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* added_elem = SIXTRL_NULLPTR;
+    typedef NS(buffer_size_t) buf_size_t;
+
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    buf_size_t num_dataptrs = ( buf_size_t )0u;
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    NS(TriCubData) tricub_data;
+    NS(TriCubData_preset)( &tricub_data );
+    status  = NS(TriCubData_set_x0)( &tricub_data, x0 );
+    status |= NS(TriCubData_set_dx)( &tricub_data, dx );
+    status |= NS(TriCubData_set_nx)( &tricub_data, nx );
+    status |= NS(TriCubData_set_y0)( &tricub_data, y0 );
+    status |= NS(TriCubData_set_dy)( &tricub_data, dy );
+    status |= NS(TriCubData_set_ny)( &tricub_data, ny );
+    status |= NS(TriCubData_set_z0)( &tricub_data, z0 );
+    status |= NS(TriCubData_set_dz)( &tricub_data, dz );
+    status |= NS(TriCubData_set_nz)( &tricub_data, nz );
+    status |= NS(TriCubData_set_mirror_x)( &tricub_data, mirror_x );
+    status |= NS(TriCubData_set_mirror_y)( &tricub_data, mirror_y );
+    status |= NS(TriCubData_set_mirror_z)( &tricub_data, mirror_z );
+    status |= NS(TriCubData_set_table_addr)( &tricub_data, table_addr );
+    num_dataptrs = NS(TriCubData_num_dataptrs)( &tricub_data );
+
+    if( ( status == NS(ARCH_STATUS_SUCCESS) ) && ( buffer != SIXTRL_NULLPTR ) &&
+        ( num_dataptrs == ( buf_size_t )1u ) &&
+        ( slot_size > ( buf_size_t )0u ) )
+    {
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[  1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ];
+
+        status = NS(TriCubData_attributes_sizes)(
+            &sizes[ 0 ], num_dataptrs, &tricub_data, slot_size );
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(TriCubData_attributes_counts)(
+                &counts[ 0 ], num_dataptrs, &tricub_data, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(TriCubData_attributes_offsets)(
+                &offsets[ 0 ], num_dataptrs, &tricub_data, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* )(
+                uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, &tricub_data, sizeof( tricub_data ),
+                        NS(TriCubData_type_id)(), num_dataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* NS(TriCubData_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* added_elem = SIXTRL_NULLPTR;
+    typedef NS(buffer_size_t) buf_size_t;
+
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    buf_size_t num_dataptrs = ( buf_size_t )0u;
+    buf_size_t const slot_size = NS(Buffer_get_slot_size)( buffer );
+
+    if( ( status == NS(ARCH_STATUS_SUCCESS) ) && ( buffer != SIXTRL_NULLPTR ) &&
+        ( num_dataptrs == ( buf_size_t )1u ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( slot_size > ( buf_size_t )0u ) )
+    {
+        SIXTRL_ARGPTR_DEC buf_size_t offsets[ 1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t sizes[  1 ];
+        SIXTRL_ARGPTR_DEC buf_size_t counts[ 1 ];
+
+        status = NS(TriCubData_attributes_sizes)(
+            &sizes[ 0 ], num_dataptrs, orig, slot_size );
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(TriCubData_attributes_counts)(
+                &counts[ 0 ], num_dataptrs, orig, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            status = NS(TriCubData_attributes_offsets)(
+                &offsets[ 0 ], num_dataptrs, orig, slot_size );
+        }
+
+        if( status == NS(ARCH_STATUS_SUCCESS) )
+        {
+            added_elem = ( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* )(
+                uintptr_t )NS(Object_get_begin_addr)( NS(Buffer_add_object)(
+                    buffer, orig, sizeof( NS(TriCubData) ),
+                        NS(TriCubData_type_id)(), num_dataptrs,
+                            &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+        }
+    }
+
+    return added_elem;
+}
+
+/* ========================================================================= */
+
+NS(object_type_id_t) NS(TriCub_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCub_type_id)();
+}
+
+NS(arch_size_t) NS(TriCub_data_addr_offset_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(TriCub) *const SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCub_data_addr_offset)( tricub );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(TriCub_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( tricub ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_offsets > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(TriCub_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub)
+        *const SIXTRL_RESTRICT SIXTRL_UNUSED( tricub ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) && ( slot_size > ZERO ) &&
+        ( max_num_sizes > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(TriCub_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub)
+        *const SIXTRL_RESTRICT SIXTRL_UNUSED( tricub ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( counts != SIXTRL_NULLPTR ) && ( slot_size > ( buf_size_t )0 ) &&
+        ( max_num_counts > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(TriCub_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs )
+{
+    ( void )ptr_requ_dataptrs;
+    return NS(Buffer_can_add_trivial_object)( buffer, sizeof( NS(TriCub) ),
+        ptr_requ_objects, ptr_requ_slots );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(TriCub)* NS(TriCub_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    NS(TriCub) tricub;
+    NS(TriCub_preset)( &tricub );
+
+    SIXTRL_ASSERT( ( NS(buffer_size_t) )0u ==
+        NS(TriCub_num_dataptrs)( &tricub ) );
+
+    return ( SIXTRL_BE_ARGPTR_DEC NS(TriCub)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_trivial_object)( buffer,
+            &tricub, sizeof( NS(TriCub) ), NS(TriCub_type_id)() ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(TriCub)* NS(TriCub_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(be_tricub_real_t) const x_shift, NS(be_tricub_real_t) const y_shift,
+    NS(be_tricub_real_t) const tau_shift,
+    NS(be_tricub_real_t) const dipolar_kick_px,
+    NS(be_tricub_real_t) const dipolar_kick_py,
+    NS(be_tricub_real_t) const dipolar_kick_ptau,
+    NS(be_tricub_real_t) const length,
+    NS(buffer_addr_t) const data_addr )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* added_elem = SIXTRL_NULLPTR;
+
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+    NS(TriCub) tricub;
+    NS(TriCub_preset)( &tricub );
+    status  = NS(TriCub_set_x_shift)( &tricub, x_shift );
+    status |= NS(TriCub_set_y_shift)( &tricub, y_shift );
+    status |= NS(TriCub_set_tau_shift)( &tricub, tau_shift );
+    status |= NS(TriCub_set_dipolar_kick_px)( &tricub, dipolar_kick_px );
+    status |= NS(TriCub_set_dipolar_kick_py)( &tricub, dipolar_kick_py );
+    status |= NS(TriCub_set_dipolar_kick_ptau)( &tricub, dipolar_kick_ptau );
+    status |= NS(TriCub_set_length)( &tricub, length );
+    status |= NS(TriCub_set_data_addr)( &tricub, data_addr );
+
+    if( ( status == NS(ARCH_STATUS_SUCCESS) ) &&
+        ( NS(buffer_size_t) )0u == NS(TriCub_num_dataptrs)( &tricub ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(TriCub)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_trivial_object)( buffer,
+                &tricub, sizeof( NS(TriCub) ), NS(TriCub_type_id)() ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)* NS(TriCub_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* added_elem = SIXTRL_NULLPTR;
+
+    if( ( orig != SIXTRL_NULLPTR ) && ( buffer != SIXTRL_NULLPTR ) &&
+        ( NS(buffer_size_t) )0u == NS(TriCub_num_dataptrs)( orig ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(TriCub)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_trivial_object)( buffer,
+                orig, sizeof( NS(TriCub) ), NS(TriCub_type_id)() ) );
+    }
+
+    return added_elem;
+}
+
+/* ------------------------------------------------------------------------ */
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+NS(TriCub_buffer_create_assign_address_item)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT assign_items_buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT belements,
+    NS(buffer_size_t) const belements_index,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const
+        SIXTRL_RESTRICT tricub_data_buffer,
+    NS(buffer_size_t) const tricub_data_buffer_id,
+    NS(buffer_size_t) const tricub_data_index )
+{
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+        assign_item = SIXTRL_NULLPTR;
+
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub) const* tricub =
+        NS(TriCub_const_from_buffer)( belements, belements_index );
+
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const* tricub_data =
+        NS(TriCubData_const_from_buffer)(
+            tricub_data_buffer, tricub_data_index );
+
+    if( ( assign_items_buffer != SIXTRL_NULLPTR ) &&
+        ( tricub != SIXTRL_NULLPTR ) && ( tricub_data != SIXTRL_NULLPTR ) &&
+        ( tricub_data_buffer_id != NS(ARCH_ILLEGAL_BUFFER_ID) ) )
+    {
+        assign_item = NS(AssignAddressItem_add)( assign_items_buffer,
+            NS(OBJECT_TYPE_TRICUB), NS(ARCH_BEAM_ELEMENTS_BUFFER_ID),
+                belements_index, NS(TriCub_data_addr_offset)( tricub ),
+            NS(OBJECT_TYPE_TRICUB_DATA), tricub_data_buffer_id,
+                tricub_data_index, NS(TriCubData_ptr_offset)( tricub_data ) );
+    }
+
+    return assign_item;
+}
+
+/* end: sixtracklib/common/be_tricub/be_tricub.c */
diff --git a/sixtracklib/common/be_tricub/be_tricub.h b/sixtracklib/common/be_tricub/be_tricub.h
new file mode 100644
index 00000000..4c2fd435
--- /dev/null
+++ b/sixtracklib/common/be_tricub/be_tricub.h
@@ -0,0 +1,1451 @@
+#ifndef SIXTRACKLIB_COMMON_BE_TRICUB_C99_H__
+#define SIXTRACKLIB_COMMON_BE_TRICUB_C99_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stdbool.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <math.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/internal/beam_elements_defines.h"
+    #include "sixtracklib/common/internal/objects_type_id.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* !defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+#if !defined( SIXTRL_BE_TRICUBMAP_MATRIX_DIM )
+    #define   SIXTRL_BE_TRICUBMAP_MATRIX_DIM 8
+#endif /* !defined( SIXTRL_BE_TRICUBMAP_MATRIX_DIM ) */
+
+typedef SIXTRL_INT64_T NS(be_tricub_int_t);
+typedef SIXTRL_REAL_T  NS(be_tricub_real_t);
+
+typedef struct NS(TriCubData)
+{
+    NS(be_tricub_real_t)    x0              SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    dx              SIXTRL_ALIGN( 8 );
+    NS(be_tricub_int_t)     nx              SIXTRL_ALIGN( 8 );
+
+    NS(be_tricub_real_t)    y0              SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    dy              SIXTRL_ALIGN( 8 );
+    NS(be_tricub_int_t)     ny              SIXTRL_ALIGN( 8 );
+
+    NS(be_tricub_real_t)    z0              SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    dz              SIXTRL_ALIGN( 8 );
+    NS(be_tricub_int_t)     nz              SIXTRL_ALIGN( 8 );
+
+    NS(be_tricub_int_t)     mirror_x        SIXTRL_ALIGN( 8 );
+    NS(be_tricub_int_t)     mirror_y        SIXTRL_ALIGN( 8 );
+    NS(be_tricub_int_t)     mirror_z        SIXTRL_ALIGN( 8 );
+
+    NS(buffer_addr_t)       table_addr      SIXTRL_ALIGN( 8 );
+}
+NS(TriCubData);
+
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(TriCubData_type_id)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(TriCubData_num_dataptrs)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(TriCubData_num_slots)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_preset)( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+    SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_clear)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCubData_x0)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCubData_dx)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_int_t) NS(TriCubData_nx)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCubData_y0)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCubData_dy)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_int_t) NS(TriCubData_ny)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCubData_z0)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCubData_dz)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_int_t) NS(TriCubData_nz)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_int_t) NS(TriCubData_mirror_x)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_int_t) NS(TriCubData_mirror_y)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_int_t) NS(TriCubData_mirror_z)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_int_t) NS(TriCubData_table_size)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(TriCubData_table_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(be_tricub_real_t) const*
+NS(TriCubData_const_table_begin)( SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData)
+    *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(be_tricub_real_t)*
+NS(TriCubData_table_begin)( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+    SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT;
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_x0)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_real_t) const x0 ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_dx)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_real_t) const dx ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_nx)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_int_t)  const nx ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_y0)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_real_t) const y0 ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_dy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_real_t) const dy ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_ny)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_int_t)  const ny ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_z0)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_real_t) const z0 ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_dz)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_real_t) const dz ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_nz)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_int_t)  const nz ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_mirror_x)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_int_t) const mirror_x ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_mirror_y)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_int_t) const mirror_y ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_mirror_z)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_int_t) const mirror_z ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_set_table_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const table_addr ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const*
+NS(TriCubData_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* obj ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const*
+NS(TriCubData_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE )
+
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const*
+NS(TriCubData_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_HOST_FN NS(arch_size_t) NS(TriCubData_ptr_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData)
+        *const SIXTRL_RESTRICT d ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(TriCubData_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(TriCubData_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(TriCubData_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+    NS(TriCubData_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t) NS(TriCubData_ptr_offset_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData)
+        *const SIXTRL_RESTRICT d ) SIXTRL_NOEXCEPT;
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TriCubData_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(be_tricub_int_t) const nx, NS(be_tricub_int_t) const ny,
+    NS(be_tricub_int_t) const nz,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(be_tricub_int_t) const nx, NS(be_tricub_int_t) const ny,
+    NS(be_tricub_int_t) const nz );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(be_tricub_real_t) const x0, NS(be_tricub_real_t) const dx,
+    NS(be_tricub_int_t)  const nx,
+    NS(be_tricub_real_t) const y0, NS(be_tricub_real_t) const dy,
+    NS(be_tricub_int_t)  const ny,
+    NS(be_tricub_real_t) const z0, NS(be_tricub_real_t) const dz,
+    NS(be_tricub_int_t)  const nz, NS(be_tricub_int_t) const mirror_x,
+    NS(be_tricub_int_t) const mirror_y, NS(be_tricub_int_t) const mirror_z,
+    NS(buffer_addr_t) const table_addr );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT orig );
+
+#endif /* !defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCubData_copy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
+
+/* ========================================================================= */
+
+typedef struct NS(TriCub)
+{
+    NS(be_tricub_real_t)    x_shift            SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    y_shift            SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    tau_shift          SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    dipolar_kick_px    SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    dipolar_kick_py    SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    dipolar_kick_ptau  SIXTRL_ALIGN( 8 );
+    NS(be_tricub_real_t)    length             SIXTRL_ALIGN( 8 );
+    NS(buffer_addr_t)       data_addr          SIXTRL_ALIGN( 8 );
+}
+NS(TriCub);
+
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(TriCub_type_id)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(TriCub_num_dataptrs)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(TriCub_num_slots)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT tricub,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(TriCub)* NS(TriCub_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+/*  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  */
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCub_x_shift)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCub_y_shift)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCub_tau_shift)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCub_dipolar_kick_px)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCub_dipolar_kick_py)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCub_dipolar_kick_ptau)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(be_tricub_real_t) NS(TriCub_length)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(TriCub_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const*
+NS(TriCub_const_data)( SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+    SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCub_data)( SIXTRL_BE_ARGPTR_DEC NS(TriCub)*
+    SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_set_x_shift)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const x_shift ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_set_y_shift)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const y_shift ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_set_tau_shift)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const tau_shift ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_set_dipolar_kick_px)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const dipolar_kick_px ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_set_dipolar_kick_py)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const dipolar_kick_py ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_set_dipolar_kick_ptau)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const dipolar_kick_ptau ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const length ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_set_data_addr)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(buffer_addr_t) const data_addr ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub) const*
+NS(TriCub_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)*
+NS(TriCub_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* obj ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub) const*
+NS(TriCub_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)*
+NS(TriCub_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE )
+
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub) const*
+NS(TriCub_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)*
+NS(TriCub_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_HOST_FN NS(arch_size_t) NS(TriCub_data_addr_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(TriCub_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(TriCub_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(TriCub_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+    NS(TriCub_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t) NS(TriCub_data_addr_offset_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT;
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TriCub_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT
+        ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)*
+NS(TriCub_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)*
+NS(TriCub_add)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(be_tricub_real_t) const x_shift, NS(be_tricub_real_t) const y_shift,
+    NS(be_tricub_real_t) const tau_shift,
+    NS(be_tricub_real_t) const dipolar_kick_px,
+    NS(be_tricub_real_t) const dipolar_kick_py,
+    NS(be_tricub_real_t) const dipolar_kick_ptau,
+    NS(be_tricub_real_t) const length,
+    NS(buffer_addr_t) const data_addr );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)*
+NS(TriCub_add_copy)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT tricub );
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN
+SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+NS(TriCub_buffer_create_assign_address_item)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT assign_items_buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT belements,
+    NS(buffer_size_t) const belements_index,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT
+        tricub_data_buffer,
+    NS(buffer_size_t) const tricub_data_buffer_id,
+    NS(buffer_size_t) const tricub_data_index );
+
+#endif /* !defined( _GPUCODE ) */
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(TriCub_copy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT;
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* !defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+/* ************************************************************************* */
+/* ***          Implementation of inline functions and methods          **** */
+/* ************************************************************************* */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer.h"
+    #include "sixtracklib/common/buffer/managed_buffer_remap.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #if !defined( _GPUCODE )
+        #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* !defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+
+SIXTRL_INLINE NS(object_type_id_t) NS(TriCubData_type_id)() SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_TRICUB_DATA);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(TriCubData_num_dataptrs)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( data ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )1u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(TriCubData_num_slots)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+
+    if( ( data != SIXTRL_NULLPTR ) && ( slot_size > ( NS(buffer_size_t) )0u ) )
+    {
+        NS(buffer_size_t) num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(TriCubData) ), slot_size );
+
+        num_bytes += NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(be_tricub_real_t) ) * NS(TriCubData_table_size)( data ),
+                slot_size );
+
+        num_slots = num_bytes / slot_size;
+        if( ( num_slots * slot_size ) < num_bytes ) ++num_slots;
+    }
+
+    return num_slots;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* NS(TriCubData_preset)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    if( data != SIXTRL_NULLPTR )
+    {
+        NS(arch_status_t) status = NS(TriCubData_set_nx)(
+            data, ( NS(be_tricub_int_t) )0.0 );
+
+        status |= NS(TriCubData_set_ny)( data, ( NS(be_tricub_int_t) )0.0 );
+        status |= NS(TriCubData_set_nz)( data, ( NS(be_tricub_int_t) )0.0 );
+        status |= NS(TriCubData_set_table_addr)(
+            data, ( NS(buffer_addr_t) )0.0 );
+
+        status |= NS(TriCubData_clear)( data );
+
+        SIXTRL_ASSERT( status == ( NS(arch_status_t)
+            )SIXTRL_ARCH_STATUS_SUCCESS );
+        ( void )status;
+    }
+
+    return data;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_clear)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data )
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( data != SIXTRL_NULLPTR )
+    {
+        NS(TriCubData_set_x0)( data, ( NS(be_tricub_real_t) )0.0 );
+        NS(TriCubData_set_dx)( data, ( NS(be_tricub_real_t) )0.0 );
+
+        NS(TriCubData_set_y0)( data, ( NS(be_tricub_real_t) )0.0 );
+        NS(TriCubData_set_dy)( data, ( NS(be_tricub_real_t) )0.0 );
+
+        NS(TriCubData_set_z0)( data, ( NS(be_tricub_real_t) )0.0 );
+        NS(TriCubData_set_dz)( data, ( NS(be_tricub_real_t) )0.0 );
+
+        NS(TriCubData_set_mirror_x)( data, ( NS(be_tricub_int_t) )0 );
+        NS(TriCubData_set_mirror_y)( data, ( NS(be_tricub_int_t) )0 );
+        NS(TriCubData_set_mirror_z)( data, ( NS(be_tricub_int_t) )0 );
+
+        if( ( NS(TriCubData_table_size)( data ) > ( NS(be_tricub_int_t) )0u ) &&
+            ( NS(TriCubData_table_addr)( data ) != ( NS(buffer_addr_t) )0u ) )
+        {
+            typedef NS(be_tricub_real_t) real_t;
+
+            SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0.0;
+
+            NS(buffer_size_t) const num_table_entries =
+                NS(TriCubData_table_size)( data );
+
+            SIXTRL_BUFFER_DATAPTR_DEC real_t* ptr_table_data =
+                NS(TriCubData_table_begin)( data );
+
+            SIXTRL_ASSERT( ptr_table_data != SIXTRL_NULLPTR );
+            SIXTRL_ASSERT( num_table_entries > ( NS(buffer_size_t) )0u );
+
+            SIXTRACKLIB_SET_VALUES(
+                real_t, ptr_table_data, num_table_entries, ZERO );
+        }
+    }
+
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCubData_x0)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->x0;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCubData_dx)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->dx;
+}
+
+SIXTRL_INLINE NS(be_tricub_int_t) NS(TriCubData_nx)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->nx;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCubData_y0)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->y0;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCubData_dy)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->dy;
+}
+
+SIXTRL_INLINE NS(be_tricub_int_t) NS(TriCubData_ny)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->ny;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCubData_z0)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->z0;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCubData_dz)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->dz;
+}
+
+SIXTRL_INLINE NS(be_tricub_int_t) NS(TriCubData_nz)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->nz;
+}
+
+SIXTRL_INLINE NS(be_tricub_int_t) NS(TriCubData_mirror_x)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->mirror_x;
+}
+
+SIXTRL_INLINE NS(be_tricub_int_t) NS(TriCubData_mirror_y)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->mirror_y;
+}
+
+SIXTRL_INLINE NS(be_tricub_int_t) NS(TriCubData_mirror_z)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->mirror_z;
+}
+
+SIXTRL_INLINE NS(be_tricub_int_t) NS(TriCubData_table_size)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->nx * data->ny * data->nz * 8u;
+}
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(TriCubData_table_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const
+        SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    return data->table_addr;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(be_tricub_real_t) const*
+NS(TriCubData_const_table_begin)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(TriCubData) *const SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT(
+        ( ( NS(TriCubData_table_size)( data ) == ( NS(be_tricub_int_t) )0u ) &&
+          ( data->table_addr == ( NS(buffer_addr_t) )0u ) &&
+          ( ( data->nx == ( NS(be_tricub_int_t) )0 ) ||
+            ( data->ny == ( NS(be_tricub_int_t) )0 ) ||
+            ( data->nz == ( NS(be_tricub_int_t) )0 ) ) ) ||
+        ( ( NS(TriCubData_table_size)( data )  > ( NS(be_tricub_int_t) )0u ) &&
+          ( data->table_addr != ( NS(buffer_addr_t) )0u ) ) );
+
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(be_tricub_real_t) const* )(
+        uintptr_t )data->table_addr;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(be_tricub_real_t)*
+NS(TriCubData_table_begin)( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+    SIXTRL_RESTRICT data ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(be_tricub_real_t)*
+        )NS(TriCubData_const_table_begin)( data );
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_x0)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(be_tricub_real_t) const x0 ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->x0 = x0;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_dx)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_real_t) const dx ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( data != SIXTRL_NULLPTR ) && ( dx >= ( NS(be_tricub_real_t) )0 ) )
+    {
+        data->dx = dx;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_nx)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_int_t)  const nx ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( data != SIXTRL_NULLPTR ) && ( nx >= ( NS(be_tricub_int_t) )0 ) )
+    {
+        data->nx = nx;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_y0)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_real_t) const y0 ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->y0 = y0;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_dy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_real_t) const dy ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( data != SIXTRL_NULLPTR ) && ( dy >= ( NS(be_tricub_real_t) )0 ) )
+    {
+        data->dy = dy;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_ny)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_int_t)  const ny ) SIXTRL_NOEXCEPT
+{
+     NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( data != SIXTRL_NULLPTR ) && ( ny >= ( NS(be_tricub_int_t) )0 ) )
+    {
+        data->ny = ny;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_z0)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_real_t) const z0 ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->z0 = z0;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_dz)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_real_t) const dz ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( data != SIXTRL_NULLPTR ) && ( dz >= ( NS(be_tricub_real_t) )0 ) )
+    {
+        data->dz = dz;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_nz)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_int_t)  const nz ) SIXTRL_NOEXCEPT
+{
+     NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( data != SIXTRL_NULLPTR ) && ( nz >= ( NS(be_tricub_int_t) )0 ) )
+    {
+        data->nz = nz;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_mirror_x)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_int_t) const mirror_x ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->mirror_x = mirror_x;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_mirror_y)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_int_t) const mirror_y ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->mirror_y = mirror_y;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_mirror_z)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+     NS(be_tricub_int_t) const mirror_z ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->mirror_z = mirror_z;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_set_table_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT data,
+    NS(buffer_addr_t) const table_addr ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
+    data->table_addr = table_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/*  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  */
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const*
+NS(TriCubData_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const obj ) SIXTRL_NOEXCEPT
+{
+    return ( ( NS(Object_get_size)( obj ) >= sizeof( NS( TriCubData ) ) ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_TRICUB_DATA) ) &&
+        ( NS(Object_get_begin_addr)( obj ) != ( NS(buffer_addr_t) )0 ) )
+            ? ( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const* )(
+                uintptr_t )NS(Object_get_begin_addr)( obj )
+            : SIXTRL_NULLPTR;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* obj ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+        )NS(TriCubData_const_from_obj_index)( obj );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const*
+NS(TriCubData_const_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC unsigned
+        char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCubData_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCubData_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#if !defined( _GPUCODE )
+    
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const*
+NS(TriCubData_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCubData_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCubData_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCubData_from_obj_index)(
+        NS(Buffer_get_object)( buffer, index ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_size_t) NS(TriCubData_ptr_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData)
+        *const SIXTRL_RESTRICT SIXTRL_UNUSED( d ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(arch_size_t) )offsetof( NS(TriCubData), table_addr );
+}
+
+#endif /* !defined( _GPUCODE ) */
+    
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCubData_copy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData)
+        *const SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
+{
+    typedef NS(be_tricub_int_t)  int_t;
+    typedef NS(be_tricub_real_t) real_t;
+
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) &&
+        ( dest != src ) )
+    {
+        int_t const src_table_size = NS(TriCubData_table_size)( src );
+        int_t const dest_table_size = NS(TriCubData_table_size)( dest );
+
+        SIXTRL_BUFFER_DATAPTR_DEC real_t* dest_table_begin =
+            NS(TriCubData_table_begin)( dest );
+
+        SIXTRL_BUFFER_DATAPTR_DEC real_t const* src_table_begin =
+            NS(TriCubData_const_table_begin)( src );
+
+        if( ( src_table_size > ( int_t )0 ) &&
+            ( src_table_size == dest_table_size ) &&
+            ( dest_table_begin != SIXTRL_NULLPTR ) &&
+            ( src_table_begin  != SIXTRL_NULLPTR ) )
+        {
+            if( dest_table_begin != src_table_begin )
+            {
+                SIXTRACKLIB_COPY_VALUES( real_t, dest_table_begin,
+                    src_table_begin, src_table_size );
+            }
+
+            status = SIXTRL_ARCH_STATUS_SUCCESS;
+        }
+        else if( ( src_table_size == ( int_t )0u ) &&
+                 ( src_table_size == dest_table_size ) &&
+                 ( src_table_begin == dest_table_begin ) )
+        {
+            status = SIXTRL_ARCH_STATUS_SUCCESS;
+        }
+
+        if( status == SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            status |= NS(TriCubData_set_x0)( dest, NS(TriCubData_x0)( src ) );
+            status |= NS(TriCubData_set_dx)( dest, NS(TriCubData_dx)( src ) );
+            status |= NS(TriCubData_set_nx)( dest, NS(TriCubData_nx)( src ) );
+
+            status |= NS(TriCubData_set_y0)( dest, NS(TriCubData_y0)( src ) );
+            status |= NS(TriCubData_set_dy)( dest, NS(TriCubData_dy)( src ) );
+            status |= NS(TriCubData_set_ny)( dest, NS(TriCubData_ny)( src ) );
+
+            status |= NS(TriCubData_set_z0)( dest, NS(TriCubData_z0)( src ) );
+            status |= NS(TriCubData_set_dz)( dest, NS(TriCubData_dz)( src ) );
+            status |= NS(TriCubData_set_nz)( dest, NS(TriCubData_nz)( src ) );
+
+            status |= NS(TriCubData_set_mirror_x)(
+                dest, NS(TriCubData_mirror_x)( src ) );
+
+            status |= NS(TriCubData_set_mirror_y)(
+                dest, NS(TriCubData_mirror_y)( src ) );
+
+            status |= NS(TriCubData_set_mirror_z)(
+                dest, NS(TriCubData_mirror_z)( src ) );
+        }
+    }
+    else if( ( dest == src ) && ( dest != SIXTRL_NULLPTR ) )
+    {
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* ========================================================================= */
+
+SIXTRL_INLINE NS(object_type_id_t) NS(TriCub_type_id)( void ) SIXTRL_NOEXCEPT
+{
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_TRICUB);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(TriCub_num_dataptrs)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT
+        SIXTRL_UNUSED( tricub ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(TriCub_num_slots)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT tricub,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    NS(buffer_size_t) const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+        sizeof( NS(TriCub) ), slot_size );
+
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    SIXTRL_ASSERT( NS(TriCub_num_dataptrs)( tricub ) ==
+        ( NS(buffer_size_t) )0u );
+    ( void )tricub;
+
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
+    return num_slots;
+}
+
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(TriCub)* NS(TriCub_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    if( tricub != SIXTRL_NULLPTR )
+    {
+        NS(TriCub_set_data_addr)( tricub, ( NS(buffer_addr_t) )0u );
+        NS(TriCub_clear)( tricub );
+    }
+
+    return tricub;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_clear)( SIXTRL_BE_ARGPTR_DEC
+    NS(TriCub)* SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = (
+        NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( tricub != SIXTRL_NULLPTR )
+    {
+        status  = NS(TriCub_set_x_shift)(
+            tricub, ( NS(be_tricub_real_t) )0.0 );
+
+        status |= NS(TriCub_set_y_shift)(
+            tricub, ( NS(be_tricub_real_t) )0.0 );
+
+        status |= NS(TriCub_set_tau_shift)(
+            tricub, ( NS(be_tricub_real_t) )0.0 );
+
+        status |= NS(TriCub_set_dipolar_kick_px)(
+            tricub, ( NS(be_tricub_real_t) )0.0 );
+
+        status |= NS(TriCub_set_dipolar_kick_py)(
+            tricub, ( NS(be_tricub_real_t) )0.0 );
+
+        status |= NS(TriCub_set_dipolar_kick_ptau)(
+            tricub, ( NS(be_tricub_real_t) )0.0 );
+
+        status |= NS(TriCub_set_length)( tricub, ( NS(be_tricub_real_t) )0.0 );
+    }
+
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCub_x_shift)( SIXTRL_BE_ARGPTR_DEC
+    const NS(TriCub) *const SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return tricub->x_shift;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCub_y_shift)( SIXTRL_BE_ARGPTR_DEC
+    const NS(TriCub) *const SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return tricub->y_shift;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCub_tau_shift)( SIXTRL_BE_ARGPTR_DEC
+    const NS(TriCub) *const SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return tricub->tau_shift;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCub_dipolar_kick_px)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return tricub->dipolar_kick_px;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCub_dipolar_kick_py)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return tricub->dipolar_kick_py;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCub_dipolar_kick_ptau)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return tricub->dipolar_kick_ptau;
+}
+
+SIXTRL_INLINE NS(be_tricub_real_t) NS(TriCub_length)( SIXTRL_BE_ARGPTR_DEC
+    const NS(TriCub) *const SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return tricub->length;
+}
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(TriCub_data_addr)( SIXTRL_BE_ARGPTR_DEC
+    const NS(TriCub) *const SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return tricub->data_addr;
+}
+
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const*
+NS(TriCub_const_data)( SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const
+    SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const* )(
+        uintptr_t )tricub->data_addr;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)*
+NS(TriCub_data)( SIXTRL_BE_ARGPTR_DEC NS(TriCub)*
+    SIXTRL_RESTRICT tricub ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData)* )( uintptr_t
+        )tricub->data_addr;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_set_x_shift)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const x_shift ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    tricub->x_shift = x_shift;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_set_y_shift)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const y_shift ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    tricub->y_shift = y_shift;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_set_tau_shift)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const tau_shift ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    tricub->tau_shift = tau_shift;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_set_dipolar_kick_px)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const dipolar_kick_px ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    tricub->dipolar_kick_px = dipolar_kick_px;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_set_dipolar_kick_py)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const dipolar_kick_py ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    tricub->dipolar_kick_py = dipolar_kick_py;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_set_dipolar_kick_ptau)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const dipolar_kick_ptau ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    tricub->dipolar_kick_ptau = dipolar_kick_ptau;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_set_length)(
+    SIXTRL_BE_ARGPTR_DEC NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(be_tricub_real_t) const length ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    tricub->length = length;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_set_data_addr)( SIXTRL_BE_ARGPTR_DEC
+    NS(TriCub)* SIXTRL_RESTRICT tricub,
+    NS(buffer_addr_t) const data_addr ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( tricub != SIXTRL_NULLPTR );
+    tricub->data_addr = data_addr;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/*  -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(TriCub) const*
+NS(TriCub_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    NS(Object) *const obj ) SIXTRL_NOEXCEPT
+{
+    return ( ( NS(Object_get_size)( obj ) >= sizeof( NS(TriCub) ) ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_TRICUB) ) &&
+        ( NS(Object_get_begin_addr)( obj ) != ( NS(buffer_addr_t) )0 ) )
+        ? ( SIXTRL_BE_ARGPTR_DEC NS(TriCub) const* )( uintptr_t
+            )NS(Object_get_begin_addr)( obj )
+        : SIXTRL_NULLPTR;
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(TriCub)* NS(TriCub_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* obj ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_BE_ARGPTR_DEC NS(TriCub)*
+        )NS(TriCub_const_from_obj_index)( obj );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(TriCub) const*
+NS(TriCub_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCub_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( buffer_begin, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(TriCub)* NS(TriCub_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCub_from_obj_index)(
+        NS(ManagedBuffer_get_object)( buffer_begin, index, slot_size ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub) const*
+NS(TriCub_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCub_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)* NS(TriCub_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return NS(TriCub_from_obj_index)( NS(Buffer_get_object)( buffer, index ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_size_t) NS(TriCub_data_addr_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT SIXTRL_UNUSED( tricub ) ) SIXTRL_NOEXCEPT
+{
+    return ( NS(arch_size_t) )offsetof( NS(TriCub), data_addr );
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(arch_status_t) NS(TriCub_copy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCub)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCub) *const
+        SIXTRL_RESTRICT src ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( dest != SIXTRL_NULLPTR ) && ( src != SIXTRL_NULLPTR ) )
+    {
+        if( dest != src )
+        {
+            status  = NS(TriCub_set_x_shift)( dest, NS(TriCub_x_shift)( src ) );
+            status |= NS(TriCub_set_y_shift)( dest, NS(TriCub_y_shift)( src ) );
+            status |= NS(TriCub_set_tau_shift)(
+                dest, NS(TriCub_tau_shift)( src ) );
+
+            status |= NS(TriCub_set_dipolar_kick_px)(
+                dest, NS(TriCub_dipolar_kick_px)( src ) );
+
+            status |= NS(TriCub_set_dipolar_kick_py)(
+                dest, NS(TriCub_dipolar_kick_py)( src ) );
+
+            status |= NS(TriCub_set_dipolar_kick_ptau)(
+                dest, NS(TriCub_dipolar_kick_ptau)( src ) );
+
+            status |= NS(TriCub_set_length)( dest, NS(TriCub_length)( src ) );
+            status |= NS(TriCub_set_data_addr)(
+                dest, NS(TriCub_data_addr)( src ) );
+        }
+        else
+        {
+            status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* !defined( __cplusplus ) && !defined( _GPUCODE ) */
+#endif /* SIXTRACKLIB_COMMON_BE_TRICUB_C99_H__ */
diff --git a/sixtracklib/common/be_tricub/coefficients.h b/sixtracklib/common/be_tricub/coefficients.h
new file mode 100644
index 00000000..8205c919
--- /dev/null
+++ b/sixtracklib/common/be_tricub/coefficients.h
@@ -0,0 +1,1053 @@
+#ifndef SIXTRACKLIB_COMMON_BE_TRICUB_COEFFICIENTS_C99_H__
+#define SIXTRACKLIB_COMMON_BE_TRICUB_COEFFICIENTS_C99_H__
+
+/*
+#if !defined(SIXTRL_NO_SYSTEM_INCLUDES)
+    #include <stddef.h>
+    #include <math.h>
+#endif */
+/* !defined(SIXTRL_NO_SYSTEM_INCLUDES) */
+
+#if !defined(SIXTRL_NO_INCLUDES)
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_tricub/be_tricub.h"
+#endif /* !defined(SIXTRL_NO_INCLUDES) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_STATIC SIXTRL_FN void NS(tricub_construct_coefs)(
+    SIXTRL_ARGPTR_DEC NS(be_tricub_real_t) const* SIXTRL_RESTRICT b,
+    SIXTRL_ARGPTR_DEC NS(be_tricub_real_t)* coefs);
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+/* ************************************************************************* */
+/* ************************************************************************* */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE void NS(tricub_construct_coefs)(
+    SIXTRL_ARGPTR_DEC NS(be_tricub_real_t) const* SIXTRL_RESTRICT b,
+    SIXTRL_ARGPTR_DEC NS(be_tricub_real_t)* coefs)
+{
+
+    NS(be_tricub_real_t) const tri_consts[9] = {2.0, 3.0, 4.0, 6.0, 8.0, 9.0, 12.0, 18.0, 27.0};
+
+    coefs[0] = b[0];
+    coefs[2] = -(tri_consts[1] * b[0]);
+    coefs[3] = tri_consts[0] * b[0];
+    coefs[8] = -(tri_consts[1] * b[0]);
+    coefs[10] = tri_consts[5] * b[0];
+    coefs[11] = -(tri_consts[3] * b[0]);
+    coefs[12] = tri_consts[0] * b[0];
+    coefs[14] = -(tri_consts[3] * b[0]);
+    coefs[15] = tri_consts[2] * b[0];
+    coefs[32] = -(tri_consts[1] * b[0]);
+    coefs[34] = tri_consts[5] * b[0];
+    coefs[35] = -(tri_consts[3] * b[0]);
+    coefs[40] = tri_consts[5] * b[0];
+    coefs[42] = -(tri_consts[8] * b[0]);
+    coefs[43] = tri_consts[7] * b[0];
+    coefs[44] = -(tri_consts[3] * b[0]);
+    coefs[46] = tri_consts[7] * b[0];
+    coefs[47] = -(tri_consts[6] * b[0]);
+    coefs[48] = tri_consts[0] * b[0];
+    coefs[50] = -(tri_consts[3] * b[0]);
+    coefs[51] = tri_consts[2] * b[0];
+    coefs[56] = -(tri_consts[3] * b[0]);
+    coefs[58] = tri_consts[7] * b[0];
+    coefs[59] = -(tri_consts[6] * b[0]);
+    coefs[60] = tri_consts[2] * b[0];
+    coefs[62] = -(tri_consts[6] * b[0]);
+    coefs[63] = tri_consts[4] * b[0];
+    coefs[2] += tri_consts[1] * b[1];
+    coefs[3] -= tri_consts[0] * b[1];
+    coefs[10] -= tri_consts[5] * b[1];
+    coefs[11] += tri_consts[3] * b[1];
+    coefs[14] += tri_consts[3] * b[1];
+    coefs[15] -= tri_consts[2] * b[1];
+    coefs[34] -= tri_consts[5] * b[1];
+    coefs[35] += tri_consts[3] * b[1];
+    coefs[42] += tri_consts[8] * b[1];
+    coefs[43] -= tri_consts[7] * b[1];
+    coefs[46] -= tri_consts[7] * b[1];
+    coefs[47] += tri_consts[6] * b[1];
+    coefs[50] += tri_consts[3] * b[1];
+    coefs[51] -= tri_consts[2] * b[1];
+    coefs[58] -= tri_consts[7] * b[1];
+    coefs[59] += tri_consts[6] * b[1];
+    coefs[62] += tri_consts[6] * b[1];
+    coefs[63] -= tri_consts[4] * b[1];
+    coefs[8] += tri_consts[1] * b[2];
+    coefs[10] -= tri_consts[5] * b[2];
+    coefs[11] += tri_consts[3] * b[2];
+    coefs[12] -= tri_consts[0] * b[2];
+    coefs[14] += tri_consts[3] * b[2];
+    coefs[15] -= tri_consts[2] * b[2];
+    coefs[40] -= tri_consts[5] * b[2];
+    coefs[42] += tri_consts[8] * b[2];
+    coefs[43] -= tri_consts[7] * b[2];
+    coefs[44] += tri_consts[3] * b[2];
+    coefs[46] -= tri_consts[7] * b[2];
+    coefs[47] += tri_consts[6] * b[2];
+    coefs[56] += tri_consts[3] * b[2];
+    coefs[58] -= tri_consts[7] * b[2];
+    coefs[59] += tri_consts[6] * b[2];
+    coefs[60] -= tri_consts[2] * b[2];
+    coefs[62] += tri_consts[6] * b[2];
+    coefs[63] -= tri_consts[4] * b[2];
+    coefs[10] += tri_consts[5] * b[3];
+    coefs[11] -= tri_consts[3] * b[3];
+    coefs[14] -= tri_consts[3] * b[3];
+    coefs[15] += tri_consts[2] * b[3];
+    coefs[42] -= tri_consts[8] * b[3];
+    coefs[43] += tri_consts[7] * b[3];
+    coefs[46] += tri_consts[7] * b[3];
+    coefs[47] -= tri_consts[6] * b[3];
+    coefs[58] += tri_consts[7] * b[3];
+    coefs[59] -= tri_consts[6] * b[3];
+    coefs[62] -= tri_consts[6] * b[3];
+    coefs[63] += tri_consts[4] * b[3];
+    coefs[32] += tri_consts[1] * b[4];
+    coefs[34] -= tri_consts[5] * b[4];
+    coefs[35] += tri_consts[3] * b[4];
+    coefs[40] -= tri_consts[5] * b[4];
+    coefs[42] += tri_consts[8] * b[4];
+    coefs[43] -= tri_consts[7] * b[4];
+    coefs[44] += tri_consts[3] * b[4];
+    coefs[46] -= tri_consts[7] * b[4];
+    coefs[47] += tri_consts[6] * b[4];
+    coefs[48] -= tri_consts[0] * b[4];
+    coefs[50] += tri_consts[3] * b[4];
+    coefs[51] -= tri_consts[2] * b[4];
+    coefs[56] += tri_consts[3] * b[4];
+    coefs[58] -= tri_consts[7] * b[4];
+    coefs[59] += tri_consts[6] * b[4];
+    coefs[60] -= tri_consts[2] * b[4];
+    coefs[62] += tri_consts[6] * b[4];
+    coefs[63] -= tri_consts[4] * b[4];
+    coefs[34] += tri_consts[5] * b[5];
+    coefs[35] -= tri_consts[3] * b[5];
+    coefs[42] -= tri_consts[8] * b[5];
+    coefs[43] += tri_consts[7] * b[5];
+    coefs[46] += tri_consts[7] * b[5];
+    coefs[47] -= tri_consts[6] * b[5];
+    coefs[50] -= tri_consts[3] * b[5];
+    coefs[51] += tri_consts[2] * b[5];
+    coefs[58] += tri_consts[7] * b[5];
+    coefs[59] -= tri_consts[6] * b[5];
+    coefs[62] -= tri_consts[6] * b[5];
+    coefs[63] += tri_consts[4] * b[5];
+    coefs[40] += tri_consts[5] * b[6];
+    coefs[42] -= tri_consts[8] * b[6];
+    coefs[43] += tri_consts[7] * b[6];
+    coefs[44] -= tri_consts[3] * b[6];
+    coefs[46] += tri_consts[7] * b[6];
+    coefs[47] -= tri_consts[6] * b[6];
+    coefs[56] -= tri_consts[3] * b[6];
+    coefs[58] += tri_consts[7] * b[6];
+    coefs[59] -= tri_consts[6] * b[6];
+    coefs[60] += tri_consts[2] * b[6];
+    coefs[62] -= tri_consts[6] * b[6];
+    coefs[63] += tri_consts[4] * b[6];
+    coefs[42] += tri_consts[8] * b[7];
+    coefs[43] -= tri_consts[7] * b[7];
+    coefs[46] -= tri_consts[7] * b[7];
+    coefs[47] += tri_consts[6] * b[7];
+    coefs[58] -= tri_consts[7] * b[7];
+    coefs[59] += tri_consts[6] * b[7];
+    coefs[62] += tri_consts[6] * b[7];
+    coefs[63] -= tri_consts[4] * b[7];
+    coefs[1] = b[8];
+    coefs[2] -= tri_consts[0] * b[8];
+    coefs[3] += b[8];
+    coefs[9] = -(tri_consts[1] * b[8]);
+    coefs[10] += tri_consts[3] * b[8];
+    coefs[11] -= tri_consts[1] * b[8];
+    coefs[13] = tri_consts[0] * b[8];
+    coefs[14] -= tri_consts[2] * b[8];
+    coefs[15] += tri_consts[0] * b[8];
+    coefs[33] = -(tri_consts[1] * b[8]);
+    coefs[34] += tri_consts[3] * b[8];
+    coefs[35] -= tri_consts[1] * b[8];
+    coefs[41] = tri_consts[5] * b[8];
+    coefs[42] -= tri_consts[7] * b[8];
+    coefs[43] += tri_consts[5] * b[8];
+    coefs[45] = -(tri_consts[3] * b[8]);
+    coefs[46] += tri_consts[6] * b[8];
+    coefs[47] -= tri_consts[3] * b[8];
+    coefs[49] = tri_consts[0] * b[8];
+    coefs[50] -= tri_consts[2] * b[8];
+    coefs[51] += tri_consts[0] * b[8];
+    coefs[57] = -(tri_consts[3] * b[8]);
+    coefs[58] += tri_consts[6] * b[8];
+    coefs[59] -= tri_consts[3] * b[8];
+    coefs[61] = tri_consts[2] * b[8];
+    coefs[62] -= tri_consts[4] * b[8];
+    coefs[63] += tri_consts[2] * b[8];
+    coefs[2] -= b[9];
+    coefs[3] += b[9];
+    coefs[10] += tri_consts[1] * b[9];
+    coefs[11] -= tri_consts[1] * b[9];
+    coefs[14] -= tri_consts[0] * b[9];
+    coefs[15] += tri_consts[0] * b[9];
+    coefs[34] += tri_consts[1] * b[9];
+    coefs[35] -= tri_consts[1] * b[9];
+    coefs[42] -= tri_consts[5] * b[9];
+    coefs[43] += tri_consts[5] * b[9];
+    coefs[46] += tri_consts[3] * b[9];
+    coefs[47] -= tri_consts[3] * b[9];
+    coefs[50] -= tri_consts[0] * b[9];
+    coefs[51] += tri_consts[0] * b[9];
+    coefs[58] += tri_consts[3] * b[9];
+    coefs[59] -= tri_consts[3] * b[9];
+    coefs[62] -= tri_consts[2] * b[9];
+    coefs[63] += tri_consts[2] * b[9];
+    coefs[9] += tri_consts[1] * b[10];
+    coefs[10] -= tri_consts[3] * b[10];
+    coefs[11] += tri_consts[1] * b[10];
+    coefs[13] -= tri_consts[0] * b[10];
+    coefs[14] += tri_consts[2] * b[10];
+    coefs[15] -= tri_consts[0] * b[10];
+    coefs[41] -= tri_consts[5] * b[10];
+    coefs[42] += tri_consts[7] * b[10];
+    coefs[43] -= tri_consts[5] * b[10];
+    coefs[45] += tri_consts[3] * b[10];
+    coefs[46] -= tri_consts[6] * b[10];
+    coefs[47] += tri_consts[3] * b[10];
+    coefs[57] += tri_consts[3] * b[10];
+    coefs[58] -= tri_consts[6] * b[10];
+    coefs[59] += tri_consts[3] * b[10];
+    coefs[61] -= tri_consts[2] * b[10];
+    coefs[62] += tri_consts[4] * b[10];
+    coefs[63] -= tri_consts[2] * b[10];
+    coefs[10] -= tri_consts[1] * b[11];
+    coefs[11] += tri_consts[1] * b[11];
+    coefs[14] += tri_consts[0] * b[11];
+    coefs[15] -= tri_consts[0] * b[11];
+    coefs[42] += tri_consts[5] * b[11];
+    coefs[43] -= tri_consts[5] * b[11];
+    coefs[46] -= tri_consts[3] * b[11];
+    coefs[47] += tri_consts[3] * b[11];
+    coefs[58] -= tri_consts[3] * b[11];
+    coefs[59] += tri_consts[3] * b[11];
+    coefs[62] += tri_consts[2] * b[11];
+    coefs[63] -= tri_consts[2] * b[11];
+    coefs[33] += tri_consts[1] * b[12];
+    coefs[34] -= tri_consts[3] * b[12];
+    coefs[35] += tri_consts[1] * b[12];
+    coefs[41] -= tri_consts[5] * b[12];
+    coefs[42] += tri_consts[7] * b[12];
+    coefs[43] -= tri_consts[5] * b[12];
+    coefs[45] += tri_consts[3] * b[12];
+    coefs[46] -= tri_consts[6] * b[12];
+    coefs[47] += tri_consts[3] * b[12];
+    coefs[49] -= tri_consts[0] * b[12];
+    coefs[50] += tri_consts[2] * b[12];
+    coefs[51] -= tri_consts[0] * b[12];
+    coefs[57] += tri_consts[3] * b[12];
+    coefs[58] -= tri_consts[6] * b[12];
+    coefs[59] += tri_consts[3] * b[12];
+    coefs[61] -= tri_consts[2] * b[12];
+    coefs[62] += tri_consts[4] * b[12];
+    coefs[63] -= tri_consts[2] * b[12];
+    coefs[34] -= tri_consts[1] * b[13];
+    coefs[35] += tri_consts[1] * b[13];
+    coefs[42] += tri_consts[5] * b[13];
+    coefs[43] -= tri_consts[5] * b[13];
+    coefs[46] -= tri_consts[3] * b[13];
+    coefs[47] += tri_consts[3] * b[13];
+    coefs[50] += tri_consts[0] * b[13];
+    coefs[51] -= tri_consts[0] * b[13];
+    coefs[58] -= tri_consts[3] * b[13];
+    coefs[59] += tri_consts[3] * b[13];
+    coefs[62] += tri_consts[2] * b[13];
+    coefs[63] -= tri_consts[2] * b[13];
+    coefs[41] += tri_consts[5] * b[14];
+    coefs[42] -= tri_consts[7] * b[14];
+    coefs[43] += tri_consts[5] * b[14];
+    coefs[45] -= tri_consts[3] * b[14];
+    coefs[46] += tri_consts[6] * b[14];
+    coefs[47] -= tri_consts[3] * b[14];
+    coefs[57] -= tri_consts[3] * b[14];
+    coefs[58] += tri_consts[6] * b[14];
+    coefs[59] -= tri_consts[3] * b[14];
+    coefs[61] += tri_consts[2] * b[14];
+    coefs[62] -= tri_consts[4] * b[14];
+    coefs[63] += tri_consts[2] * b[14];
+    coefs[42] -= tri_consts[5] * b[15];
+    coefs[43] += tri_consts[5] * b[15];
+    coefs[46] += tri_consts[3] * b[15];
+    coefs[47] -= tri_consts[3] * b[15];
+    coefs[58] += tri_consts[3] * b[15];
+    coefs[59] -= tri_consts[3] * b[15];
+    coefs[62] -= tri_consts[2] * b[15];
+    coefs[63] += tri_consts[2] * b[15];
+    coefs[4] = b[16];
+    coefs[6] = -(tri_consts[1] * b[16]);
+    coefs[7] = tri_consts[0] * b[16];
+    coefs[8] -= tri_consts[0] * b[16];
+    coefs[10] += tri_consts[3] * b[16];
+    coefs[11] -= tri_consts[2] * b[16];
+    coefs[12] += b[16];
+    coefs[14] -= tri_consts[1] * b[16];
+    coefs[15] += tri_consts[0] * b[16];
+    coefs[36] = -(tri_consts[1] * b[16]);
+    coefs[38] = tri_consts[5] * b[16];
+    coefs[39] = -(tri_consts[3] * b[16]);
+    coefs[40] += tri_consts[3] * b[16];
+    coefs[42] -= tri_consts[7] * b[16];
+    coefs[43] += tri_consts[6] * b[16];
+    coefs[44] -= tri_consts[1] * b[16];
+    coefs[46] += tri_consts[5] * b[16];
+    coefs[47] -= tri_consts[3] * b[16];
+    coefs[52] = tri_consts[0] * b[16];
+    coefs[54] = -(tri_consts[3] * b[16]);
+    coefs[55] = tri_consts[2] * b[16];
+    coefs[56] -= tri_consts[2] * b[16];
+    coefs[58] += tri_consts[6] * b[16];
+    coefs[59] -= tri_consts[4] * b[16];
+    coefs[60] += tri_consts[0] * b[16];
+    coefs[62] -= tri_consts[3] * b[16];
+    coefs[63] += tri_consts[2] * b[16];
+    coefs[6] += tri_consts[1] * b[17];
+    coefs[7] -= tri_consts[0] * b[17];
+    coefs[10] -= tri_consts[3] * b[17];
+    coefs[11] += tri_consts[2] * b[17];
+    coefs[14] += tri_consts[1] * b[17];
+    coefs[15] -= tri_consts[0] * b[17];
+    coefs[38] -= tri_consts[5] * b[17];
+    coefs[39] += tri_consts[3] * b[17];
+    coefs[42] += tri_consts[7] * b[17];
+    coefs[43] -= tri_consts[6] * b[17];
+    coefs[46] -= tri_consts[5] * b[17];
+    coefs[47] += tri_consts[3] * b[17];
+    coefs[54] += tri_consts[3] * b[17];
+    coefs[55] -= tri_consts[2] * b[17];
+    coefs[58] -= tri_consts[6] * b[17];
+    coefs[59] += tri_consts[4] * b[17];
+    coefs[62] += tri_consts[3] * b[17];
+    coefs[63] -= tri_consts[2] * b[17];
+    coefs[8] -= b[18];
+    coefs[10] += tri_consts[1] * b[18];
+    coefs[11] -= tri_consts[0] * b[18];
+    coefs[12] += b[18];
+    coefs[14] -= tri_consts[1] * b[18];
+    coefs[15] += tri_consts[0] * b[18];
+    coefs[40] += tri_consts[1] * b[18];
+    coefs[42] -= tri_consts[5] * b[18];
+    coefs[43] += tri_consts[3] * b[18];
+    coefs[44] -= tri_consts[1] * b[18];
+    coefs[46] += tri_consts[5] * b[18];
+    coefs[47] -= tri_consts[3] * b[18];
+    coefs[56] -= tri_consts[0] * b[18];
+    coefs[58] += tri_consts[3] * b[18];
+    coefs[59] -= tri_consts[2] * b[18];
+    coefs[60] += tri_consts[0] * b[18];
+    coefs[62] -= tri_consts[3] * b[18];
+    coefs[63] += tri_consts[2] * b[18];
+    coefs[10] -= tri_consts[1] * b[19];
+    coefs[11] += tri_consts[0] * b[19];
+    coefs[14] += tri_consts[1] * b[19];
+    coefs[15] -= tri_consts[0] * b[19];
+    coefs[42] += tri_consts[5] * b[19];
+    coefs[43] -= tri_consts[3] * b[19];
+    coefs[46] -= tri_consts[5] * b[19];
+    coefs[47] += tri_consts[3] * b[19];
+    coefs[58] -= tri_consts[3] * b[19];
+    coefs[59] += tri_consts[2] * b[19];
+    coefs[62] += tri_consts[3] * b[19];
+    coefs[63] -= tri_consts[2] * b[19];
+    coefs[36] += tri_consts[1] * b[20];
+    coefs[38] -= tri_consts[5] * b[20];
+    coefs[39] += tri_consts[3] * b[20];
+    coefs[40] -= tri_consts[3] * b[20];
+    coefs[42] += tri_consts[7] * b[20];
+    coefs[43] -= tri_consts[6] * b[20];
+    coefs[44] += tri_consts[1] * b[20];
+    coefs[46] -= tri_consts[5] * b[20];
+    coefs[47] += tri_consts[3] * b[20];
+    coefs[52] -= tri_consts[0] * b[20];
+    coefs[54] += tri_consts[3] * b[20];
+    coefs[55] -= tri_consts[2] * b[20];
+    coefs[56] += tri_consts[2] * b[20];
+    coefs[58] -= tri_consts[6] * b[20];
+    coefs[59] += tri_consts[4] * b[20];
+    coefs[60] -= tri_consts[0] * b[20];
+    coefs[62] += tri_consts[3] * b[20];
+    coefs[63] -= tri_consts[2] * b[20];
+    coefs[38] += tri_consts[5] * b[21];
+    coefs[39] -= tri_consts[3] * b[21];
+    coefs[42] -= tri_consts[7] * b[21];
+    coefs[43] += tri_consts[6] * b[21];
+    coefs[46] += tri_consts[5] * b[21];
+    coefs[47] -= tri_consts[3] * b[21];
+    coefs[54] -= tri_consts[3] * b[21];
+    coefs[55] += tri_consts[2] * b[21];
+    coefs[58] += tri_consts[6] * b[21];
+    coefs[59] -= tri_consts[4] * b[21];
+    coefs[62] -= tri_consts[3] * b[21];
+    coefs[63] += tri_consts[2] * b[21];
+    coefs[40] -= tri_consts[1] * b[22];
+    coefs[42] += tri_consts[5] * b[22];
+    coefs[43] -= tri_consts[3] * b[22];
+    coefs[44] += tri_consts[1] * b[22];
+    coefs[46] -= tri_consts[5] * b[22];
+    coefs[47] += tri_consts[3] * b[22];
+    coefs[56] += tri_consts[0] * b[22];
+    coefs[58] -= tri_consts[3] * b[22];
+    coefs[59] += tri_consts[2] * b[22];
+    coefs[60] -= tri_consts[0] * b[22];
+    coefs[62] += tri_consts[3] * b[22];
+    coefs[63] -= tri_consts[2] * b[22];
+    coefs[42] -= tri_consts[5] * b[23];
+    coefs[43] += tri_consts[3] * b[23];
+    coefs[46] += tri_consts[5] * b[23];
+    coefs[47] -= tri_consts[3] * b[23];
+    coefs[58] += tri_consts[3] * b[23];
+    coefs[59] -= tri_consts[2] * b[23];
+    coefs[62] -= tri_consts[3] * b[23];
+    coefs[63] += tri_consts[2] * b[23];
+    coefs[16] = b[24];
+    coefs[18] = -(tri_consts[1] * b[24]);
+    coefs[19] = tri_consts[0] * b[24];
+    coefs[24] = -(tri_consts[1] * b[24]);
+    coefs[26] = tri_consts[5] * b[24];
+    coefs[27] = -(tri_consts[3] * b[24]);
+    coefs[28] = tri_consts[0] * b[24];
+    coefs[30] = -(tri_consts[3] * b[24]);
+    coefs[31] = tri_consts[2] * b[24];
+    coefs[32] -= tri_consts[0] * b[24];
+    coefs[34] += tri_consts[3] * b[24];
+    coefs[35] -= tri_consts[2] * b[24];
+    coefs[40] += tri_consts[3] * b[24];
+    coefs[42] -= tri_consts[7] * b[24];
+    coefs[43] += tri_consts[6] * b[24];
+    coefs[44] -= tri_consts[2] * b[24];
+    coefs[46] += tri_consts[6] * b[24];
+    coefs[47] -= tri_consts[4] * b[24];
+    coefs[48] += b[24];
+    coefs[50] -= tri_consts[1] * b[24];
+    coefs[51] += tri_consts[0] * b[24];
+    coefs[56] -= tri_consts[1] * b[24];
+    coefs[58] += tri_consts[5] * b[24];
+    coefs[59] -= tri_consts[3] * b[24];
+    coefs[60] += tri_consts[0] * b[24];
+    coefs[62] -= tri_consts[3] * b[24];
+    coefs[63] += tri_consts[2] * b[24];
+    coefs[18] += tri_consts[1] * b[25];
+    coefs[19] -= tri_consts[0] * b[25];
+    coefs[26] -= tri_consts[5] * b[25];
+    coefs[27] += tri_consts[3] * b[25];
+    coefs[30] += tri_consts[3] * b[25];
+    coefs[31] -= tri_consts[2] * b[25];
+    coefs[34] -= tri_consts[3] * b[25];
+    coefs[35] += tri_consts[2] * b[25];
+    coefs[42] += tri_consts[7] * b[25];
+    coefs[43] -= tri_consts[6] * b[25];
+    coefs[46] -= tri_consts[6] * b[25];
+    coefs[47] += tri_consts[4] * b[25];
+    coefs[50] += tri_consts[1] * b[25];
+    coefs[51] -= tri_consts[0] * b[25];
+    coefs[58] -= tri_consts[5] * b[25];
+    coefs[59] += tri_consts[3] * b[25];
+    coefs[62] += tri_consts[3] * b[25];
+    coefs[63] -= tri_consts[2] * b[25];
+    coefs[24] += tri_consts[1] * b[26];
+    coefs[26] -= tri_consts[5] * b[26];
+    coefs[27] += tri_consts[3] * b[26];
+    coefs[28] -= tri_consts[0] * b[26];
+    coefs[30] += tri_consts[3] * b[26];
+    coefs[31] -= tri_consts[2] * b[26];
+    coefs[40] -= tri_consts[3] * b[26];
+    coefs[42] += tri_consts[7] * b[26];
+    coefs[43] -= tri_consts[6] * b[26];
+    coefs[44] += tri_consts[2] * b[26];
+    coefs[46] -= tri_consts[6] * b[26];
+    coefs[47] += tri_consts[4] * b[26];
+    coefs[56] += tri_consts[1] * b[26];
+    coefs[58] -= tri_consts[5] * b[26];
+    coefs[59] += tri_consts[3] * b[26];
+    coefs[60] -= tri_consts[0] * b[26];
+    coefs[62] += tri_consts[3] * b[26];
+    coefs[63] -= tri_consts[2] * b[26];
+    coefs[26] += tri_consts[5] * b[27];
+    coefs[27] -= tri_consts[3] * b[27];
+    coefs[30] -= tri_consts[3] * b[27];
+    coefs[31] += tri_consts[2] * b[27];
+    coefs[42] -= tri_consts[7] * b[27];
+    coefs[43] += tri_consts[6] * b[27];
+    coefs[46] += tri_consts[6] * b[27];
+    coefs[47] -= tri_consts[4] * b[27];
+    coefs[58] += tri_consts[5] * b[27];
+    coefs[59] -= tri_consts[3] * b[27];
+    coefs[62] -= tri_consts[3] * b[27];
+    coefs[63] += tri_consts[2] * b[27];
+    coefs[32] -= b[28];
+    coefs[34] += tri_consts[1] * b[28];
+    coefs[35] -= tri_consts[0] * b[28];
+    coefs[40] += tri_consts[1] * b[28];
+    coefs[42] -= tri_consts[5] * b[28];
+    coefs[43] += tri_consts[3] * b[28];
+    coefs[44] -= tri_consts[0] * b[28];
+    coefs[46] += tri_consts[3] * b[28];
+    coefs[47] -= tri_consts[2] * b[28];
+    coefs[48] += b[28];
+    coefs[50] -= tri_consts[1] * b[28];
+    coefs[51] += tri_consts[0] * b[28];
+    coefs[56] -= tri_consts[1] * b[28];
+    coefs[58] += tri_consts[5] * b[28];
+    coefs[59] -= tri_consts[3] * b[28];
+    coefs[60] += tri_consts[0] * b[28];
+    coefs[62] -= tri_consts[3] * b[28];
+    coefs[63] += tri_consts[2] * b[28];
+    coefs[34] -= tri_consts[1] * b[29];
+    coefs[35] += tri_consts[0] * b[29];
+    coefs[42] += tri_consts[5] * b[29];
+    coefs[43] -= tri_consts[3] * b[29];
+    coefs[46] -= tri_consts[3] * b[29];
+    coefs[47] += tri_consts[2] * b[29];
+    coefs[50] += tri_consts[1] * b[29];
+    coefs[51] -= tri_consts[0] * b[29];
+    coefs[58] -= tri_consts[5] * b[29];
+    coefs[59] += tri_consts[3] * b[29];
+    coefs[62] += tri_consts[3] * b[29];
+    coefs[63] -= tri_consts[2] * b[29];
+    coefs[40] -= tri_consts[1] * b[30];
+    coefs[42] += tri_consts[5] * b[30];
+    coefs[43] -= tri_consts[3] * b[30];
+    coefs[44] += tri_consts[0] * b[30];
+    coefs[46] -= tri_consts[3] * b[30];
+    coefs[47] += tri_consts[2] * b[30];
+    coefs[56] += tri_consts[1] * b[30];
+    coefs[58] -= tri_consts[5] * b[30];
+    coefs[59] += tri_consts[3] * b[30];
+    coefs[60] -= tri_consts[0] * b[30];
+    coefs[62] += tri_consts[3] * b[30];
+    coefs[63] -= tri_consts[2] * b[30];
+    coefs[42] -= tri_consts[5] * b[31];
+    coefs[43] += tri_consts[3] * b[31];
+    coefs[46] += tri_consts[3] * b[31];
+    coefs[47] -= tri_consts[2] * b[31];
+    coefs[58] += tri_consts[5] * b[31];
+    coefs[59] -= tri_consts[3] * b[31];
+    coefs[62] -= tri_consts[3] * b[31];
+    coefs[63] += tri_consts[2] * b[31];
+    coefs[5] = b[32];
+    coefs[6] -= tri_consts[0] * b[32];
+    coefs[7] += b[32];
+    coefs[9] -= tri_consts[0] * b[32];
+    coefs[10] += tri_consts[2] * b[32];
+    coefs[11] -= tri_consts[0] * b[32];
+    coefs[13] += b[32];
+    coefs[14] -= tri_consts[0] * b[32];
+    coefs[15] += b[32];
+    coefs[37] = -(tri_consts[1] * b[32]);
+    coefs[38] += tri_consts[3] * b[32];
+    coefs[39] -= tri_consts[1] * b[32];
+    coefs[41] += tri_consts[3] * b[32];
+    coefs[42] -= tri_consts[6] * b[32];
+    coefs[43] += tri_consts[3] * b[32];
+    coefs[45] -= tri_consts[1] * b[32];
+    coefs[46] += tri_consts[3] * b[32];
+    coefs[47] -= tri_consts[1] * b[32];
+    coefs[53] = tri_consts[0] * b[32];
+    coefs[54] -= tri_consts[2] * b[32];
+    coefs[55] += tri_consts[0] * b[32];
+    coefs[57] -= tri_consts[2] * b[32];
+    coefs[58] += tri_consts[4] * b[32];
+    coefs[59] -= tri_consts[2] * b[32];
+    coefs[61] += tri_consts[0] * b[32];
+    coefs[62] -= tri_consts[2] * b[32];
+    coefs[63] += tri_consts[0] * b[32];
+    coefs[6] -= b[33];
+    coefs[7] += b[33];
+    coefs[10] += tri_consts[0] * b[33];
+    coefs[11] -= tri_consts[0] * b[33];
+    coefs[14] -= b[33];
+    coefs[15] += b[33];
+    coefs[38] += tri_consts[1] * b[33];
+    coefs[39] -= tri_consts[1] * b[33];
+    coefs[42] -= tri_consts[3] * b[33];
+    coefs[43] += tri_consts[3] * b[33];
+    coefs[46] += tri_consts[1] * b[33];
+    coefs[47] -= tri_consts[1] * b[33];
+    coefs[54] -= tri_consts[0] * b[33];
+    coefs[55] += tri_consts[0] * b[33];
+    coefs[58] += tri_consts[2] * b[33];
+    coefs[59] -= tri_consts[2] * b[33];
+    coefs[62] -= tri_consts[0] * b[33];
+    coefs[63] += tri_consts[0] * b[33];
+    coefs[9] -= b[34];
+    coefs[10] += tri_consts[0] * b[34];
+    coefs[11] -= b[34];
+    coefs[13] += b[34];
+    coefs[14] -= tri_consts[0] * b[34];
+    coefs[15] += b[34];
+    coefs[41] += tri_consts[1] * b[34];
+    coefs[42] -= tri_consts[3] * b[34];
+    coefs[43] += tri_consts[1] * b[34];
+    coefs[45] -= tri_consts[1] * b[34];
+    coefs[46] += tri_consts[3] * b[34];
+    coefs[47] -= tri_consts[1] * b[34];
+    coefs[57] -= tri_consts[0] * b[34];
+    coefs[58] += tri_consts[2] * b[34];
+    coefs[59] -= tri_consts[0] * b[34];
+    coefs[61] += tri_consts[0] * b[34];
+    coefs[62] -= tri_consts[2] * b[34];
+    coefs[63] += tri_consts[0] * b[34];
+    coefs[10] += b[35];
+    coefs[11] -= b[35];
+    coefs[14] -= b[35];
+    coefs[15] += b[35];
+    coefs[42] -= tri_consts[1] * b[35];
+    coefs[43] += tri_consts[1] * b[35];
+    coefs[46] += tri_consts[1] * b[35];
+    coefs[47] -= tri_consts[1] * b[35];
+    coefs[58] += tri_consts[0] * b[35];
+    coefs[59] -= tri_consts[0] * b[35];
+    coefs[62] -= tri_consts[0] * b[35];
+    coefs[63] += tri_consts[0] * b[35];
+    coefs[37] += tri_consts[1] * b[36];
+    coefs[38] -= tri_consts[3] * b[36];
+    coefs[39] += tri_consts[1] * b[36];
+    coefs[41] -= tri_consts[3] * b[36];
+    coefs[42] += tri_consts[6] * b[36];
+    coefs[43] -= tri_consts[3] * b[36];
+    coefs[45] += tri_consts[1] * b[36];
+    coefs[46] -= tri_consts[3] * b[36];
+    coefs[47] += tri_consts[1] * b[36];
+    coefs[53] -= tri_consts[0] * b[36];
+    coefs[54] += tri_consts[2] * b[36];
+    coefs[55] -= tri_consts[0] * b[36];
+    coefs[57] += tri_consts[2] * b[36];
+    coefs[58] -= tri_consts[4] * b[36];
+    coefs[59] += tri_consts[2] * b[36];
+    coefs[61] -= tri_consts[0] * b[36];
+    coefs[62] += tri_consts[2] * b[36];
+    coefs[63] -= tri_consts[0] * b[36];
+    coefs[38] -= tri_consts[1] * b[37];
+    coefs[39] += tri_consts[1] * b[37];
+    coefs[42] += tri_consts[3] * b[37];
+    coefs[43] -= tri_consts[3] * b[37];
+    coefs[46] -= tri_consts[1] * b[37];
+    coefs[47] += tri_consts[1] * b[37];
+    coefs[54] += tri_consts[0] * b[37];
+    coefs[55] -= tri_consts[0] * b[37];
+    coefs[58] -= tri_consts[2] * b[37];
+    coefs[59] += tri_consts[2] * b[37];
+    coefs[62] += tri_consts[0] * b[37];
+    coefs[63] -= tri_consts[0] * b[37];
+    coefs[41] -= tri_consts[1] * b[38];
+    coefs[42] += tri_consts[3] * b[38];
+    coefs[43] -= tri_consts[1] * b[38];
+    coefs[45] += tri_consts[1] * b[38];
+    coefs[46] -= tri_consts[3] * b[38];
+    coefs[47] += tri_consts[1] * b[38];
+    coefs[57] += tri_consts[0] * b[38];
+    coefs[58] -= tri_consts[2] * b[38];
+    coefs[59] += tri_consts[0] * b[38];
+    coefs[61] -= tri_consts[0] * b[38];
+    coefs[62] += tri_consts[2] * b[38];
+    coefs[63] -= tri_consts[0] * b[38];
+    coefs[42] += tri_consts[1] * b[39];
+    coefs[43] -= tri_consts[1] * b[39];
+    coefs[46] -= tri_consts[1] * b[39];
+    coefs[47] += tri_consts[1] * b[39];
+    coefs[58] -= tri_consts[0] * b[39];
+    coefs[59] += tri_consts[0] * b[39];
+    coefs[62] += tri_consts[0] * b[39];
+    coefs[63] -= tri_consts[0] * b[39];
+    coefs[17] = b[40];
+    coefs[18] -= tri_consts[0] * b[40];
+    coefs[19] += b[40];
+    coefs[25] = -(tri_consts[1] * b[40]);
+    coefs[26] += tri_consts[3] * b[40];
+    coefs[27] -= tri_consts[1] * b[40];
+    coefs[29] = tri_consts[0] * b[40];
+    coefs[30] -= tri_consts[2] * b[40];
+    coefs[31] += tri_consts[0] * b[40];
+    coefs[33] -= tri_consts[0] * b[40];
+    coefs[34] += tri_consts[2] * b[40];
+    coefs[35] -= tri_consts[0] * b[40];
+    coefs[41] += tri_consts[3] * b[40];
+    coefs[42] -= tri_consts[6] * b[40];
+    coefs[43] += tri_consts[3] * b[40];
+    coefs[45] -= tri_consts[2] * b[40];
+    coefs[46] += tri_consts[4] * b[40];
+    coefs[47] -= tri_consts[2] * b[40];
+    coefs[49] += b[40];
+    coefs[50] -= tri_consts[0] * b[40];
+    coefs[51] += b[40];
+    coefs[57] -= tri_consts[1] * b[40];
+    coefs[58] += tri_consts[3] * b[40];
+    coefs[59] -= tri_consts[1] * b[40];
+    coefs[61] += tri_consts[0] * b[40];
+    coefs[62] -= tri_consts[2] * b[40];
+    coefs[63] += tri_consts[0] * b[40];
+    coefs[18] -= b[41];
+    coefs[19] += b[41];
+    coefs[26] += tri_consts[1] * b[41];
+    coefs[27] -= tri_consts[1] * b[41];
+    coefs[30] -= tri_consts[0] * b[41];
+    coefs[31] += tri_consts[0] * b[41];
+    coefs[34] += tri_consts[0] * b[41];
+    coefs[35] -= tri_consts[0] * b[41];
+    coefs[42] -= tri_consts[3] * b[41];
+    coefs[43] += tri_consts[3] * b[41];
+    coefs[46] += tri_consts[2] * b[41];
+    coefs[47] -= tri_consts[2] * b[41];
+    coefs[50] -= b[41];
+    coefs[51] += b[41];
+    coefs[58] += tri_consts[1] * b[41];
+    coefs[59] -= tri_consts[1] * b[41];
+    coefs[62] -= tri_consts[0] * b[41];
+    coefs[63] += tri_consts[0] * b[41];
+    coefs[25] += tri_consts[1] * b[42];
+    coefs[26] -= tri_consts[3] * b[42];
+    coefs[27] += tri_consts[1] * b[42];
+    coefs[29] -= tri_consts[0] * b[42];
+    coefs[30] += tri_consts[2] * b[42];
+    coefs[31] -= tri_consts[0] * b[42];
+    coefs[41] -= tri_consts[3] * b[42];
+    coefs[42] += tri_consts[6] * b[42];
+    coefs[43] -= tri_consts[3] * b[42];
+    coefs[45] += tri_consts[2] * b[42];
+    coefs[46] -= tri_consts[4] * b[42];
+    coefs[47] += tri_consts[2] * b[42];
+    coefs[57] += tri_consts[1] * b[42];
+    coefs[58] -= tri_consts[3] * b[42];
+    coefs[59] += tri_consts[1] * b[42];
+    coefs[61] -= tri_consts[0] * b[42];
+    coefs[62] += tri_consts[2] * b[42];
+    coefs[63] -= tri_consts[0] * b[42];
+    coefs[26] -= tri_consts[1] * b[43];
+    coefs[27] += tri_consts[1] * b[43];
+    coefs[30] += tri_consts[0] * b[43];
+    coefs[31] -= tri_consts[0] * b[43];
+    coefs[42] += tri_consts[3] * b[43];
+    coefs[43] -= tri_consts[3] * b[43];
+    coefs[46] -= tri_consts[2] * b[43];
+    coefs[47] += tri_consts[2] * b[43];
+    coefs[58] -= tri_consts[1] * b[43];
+    coefs[59] += tri_consts[1] * b[43];
+    coefs[62] += tri_consts[0] * b[43];
+    coefs[63] -= tri_consts[0] * b[43];
+    coefs[33] -= b[44];
+    coefs[34] += tri_consts[0] * b[44];
+    coefs[35] -= b[44];
+    coefs[41] += tri_consts[1] * b[44];
+    coefs[42] -= tri_consts[3] * b[44];
+    coefs[43] += tri_consts[1] * b[44];
+    coefs[45] -= tri_consts[0] * b[44];
+    coefs[46] += tri_consts[2] * b[44];
+    coefs[47] -= tri_consts[0] * b[44];
+    coefs[49] += b[44];
+    coefs[50] -= tri_consts[0] * b[44];
+    coefs[51] += b[44];
+    coefs[57] -= tri_consts[1] * b[44];
+    coefs[58] += tri_consts[3] * b[44];
+    coefs[59] -= tri_consts[1] * b[44];
+    coefs[61] += tri_consts[0] * b[44];
+    coefs[62] -= tri_consts[2] * b[44];
+    coefs[63] += tri_consts[0] * b[44];
+    coefs[34] += b[45];
+    coefs[35] -= b[45];
+    coefs[42] -= tri_consts[1] * b[45];
+    coefs[43] += tri_consts[1] * b[45];
+    coefs[46] += tri_consts[0] * b[45];
+    coefs[47] -= tri_consts[0] * b[45];
+    coefs[50] -= b[45];
+    coefs[51] += b[45];
+    coefs[58] += tri_consts[1] * b[45];
+    coefs[59] -= tri_consts[1] * b[45];
+    coefs[62] -= tri_consts[0] * b[45];
+    coefs[63] += tri_consts[0] * b[45];
+    coefs[41] -= tri_consts[1] * b[46];
+    coefs[42] += tri_consts[3] * b[46];
+    coefs[43] -= tri_consts[1] * b[46];
+    coefs[45] += tri_consts[0] * b[46];
+    coefs[46] -= tri_consts[2] * b[46];
+    coefs[47] += tri_consts[0] * b[46];
+    coefs[57] += tri_consts[1] * b[46];
+    coefs[58] -= tri_consts[3] * b[46];
+    coefs[59] += tri_consts[1] * b[46];
+    coefs[61] -= tri_consts[0] * b[46];
+    coefs[62] += tri_consts[2] * b[46];
+    coefs[63] -= tri_consts[0] * b[46];
+    coefs[42] += tri_consts[1] * b[47];
+    coefs[43] -= tri_consts[1] * b[47];
+    coefs[46] -= tri_consts[0] * b[47];
+    coefs[47] += tri_consts[0] * b[47];
+    coefs[58] -= tri_consts[1] * b[47];
+    coefs[59] += tri_consts[1] * b[47];
+    coefs[62] += tri_consts[0] * b[47];
+    coefs[63] -= tri_consts[0] * b[47];
+    coefs[20] = b[48];
+    coefs[22] = -(tri_consts[1] * b[48]);
+    coefs[23] = tri_consts[0] * b[48];
+    coefs[24] -= tri_consts[0] * b[48];
+    coefs[26] += tri_consts[3] * b[48];
+    coefs[27] -= tri_consts[2] * b[48];
+    coefs[28] += b[48];
+    coefs[30] -= tri_consts[1] * b[48];
+    coefs[31] += tri_consts[0] * b[48];
+    coefs[36] -= tri_consts[0] * b[48];
+    coefs[38] += tri_consts[3] * b[48];
+    coefs[39] -= tri_consts[2] * b[48];
+    coefs[40] += tri_consts[2] * b[48];
+    coefs[42] -= tri_consts[6] * b[48];
+    coefs[43] += tri_consts[4] * b[48];
+    coefs[44] -= tri_consts[0] * b[48];
+    coefs[46] += tri_consts[3] * b[48];
+    coefs[47] -= tri_consts[2] * b[48];
+    coefs[52] += b[48];
+    coefs[54] -= tri_consts[1] * b[48];
+    coefs[55] += tri_consts[0] * b[48];
+    coefs[56] -= tri_consts[0] * b[48];
+    coefs[58] += tri_consts[3] * b[48];
+    coefs[59] -= tri_consts[2] * b[48];
+    coefs[60] += b[48];
+    coefs[62] -= tri_consts[1] * b[48];
+    coefs[63] += tri_consts[0] * b[48];
+    coefs[22] += tri_consts[1] * b[49];
+    coefs[23] -= tri_consts[0] * b[49];
+    coefs[26] -= tri_consts[3] * b[49];
+    coefs[27] += tri_consts[2] * b[49];
+    coefs[30] += tri_consts[1] * b[49];
+    coefs[31] -= tri_consts[0] * b[49];
+    coefs[38] -= tri_consts[3] * b[49];
+    coefs[39] += tri_consts[2] * b[49];
+    coefs[42] += tri_consts[6] * b[49];
+    coefs[43] -= tri_consts[4] * b[49];
+    coefs[46] -= tri_consts[3] * b[49];
+    coefs[47] += tri_consts[2] * b[49];
+    coefs[54] += tri_consts[1] * b[49];
+    coefs[55] -= tri_consts[0] * b[49];
+    coefs[58] -= tri_consts[3] * b[49];
+    coefs[59] += tri_consts[2] * b[49];
+    coefs[62] += tri_consts[1] * b[49];
+    coefs[63] -= tri_consts[0] * b[49];
+    coefs[24] -= b[50];
+    coefs[26] += tri_consts[1] * b[50];
+    coefs[27] -= tri_consts[0] * b[50];
+    coefs[28] += b[50];
+    coefs[30] -= tri_consts[1] * b[50];
+    coefs[31] += tri_consts[0] * b[50];
+    coefs[40] += tri_consts[0] * b[50];
+    coefs[42] -= tri_consts[3] * b[50];
+    coefs[43] += tri_consts[2] * b[50];
+    coefs[44] -= tri_consts[0] * b[50];
+    coefs[46] += tri_consts[3] * b[50];
+    coefs[47] -= tri_consts[2] * b[50];
+    coefs[56] -= b[50];
+    coefs[58] += tri_consts[1] * b[50];
+    coefs[59] -= tri_consts[0] * b[50];
+    coefs[60] += b[50];
+    coefs[62] -= tri_consts[1] * b[50];
+    coefs[63] += tri_consts[0] * b[50];
+    coefs[26] -= tri_consts[1] * b[51];
+    coefs[27] += tri_consts[0] * b[51];
+    coefs[30] += tri_consts[1] * b[51];
+    coefs[31] -= tri_consts[0] * b[51];
+    coefs[42] += tri_consts[3] * b[51];
+    coefs[43] -= tri_consts[2] * b[51];
+    coefs[46] -= tri_consts[3] * b[51];
+    coefs[47] += tri_consts[2] * b[51];
+    coefs[58] -= tri_consts[1] * b[51];
+    coefs[59] += tri_consts[0] * b[51];
+    coefs[62] += tri_consts[1] * b[51];
+    coefs[63] -= tri_consts[0] * b[51];
+    coefs[36] -= b[52];
+    coefs[38] += tri_consts[1] * b[52];
+    coefs[39] -= tri_consts[0] * b[52];
+    coefs[40] += tri_consts[0] * b[52];
+    coefs[42] -= tri_consts[3] * b[52];
+    coefs[43] += tri_consts[2] * b[52];
+    coefs[44] -= b[52];
+    coefs[46] += tri_consts[1] * b[52];
+    coefs[47] -= tri_consts[0] * b[52];
+    coefs[52] += b[52];
+    coefs[54] -= tri_consts[1] * b[52];
+    coefs[55] += tri_consts[0] * b[52];
+    coefs[56] -= tri_consts[0] * b[52];
+    coefs[58] += tri_consts[3] * b[52];
+    coefs[59] -= tri_consts[2] * b[52];
+    coefs[60] += b[52];
+    coefs[62] -= tri_consts[1] * b[52];
+    coefs[63] += tri_consts[0] * b[52];
+    coefs[38] -= tri_consts[1] * b[53];
+    coefs[39] += tri_consts[0] * b[53];
+    coefs[42] += tri_consts[3] * b[53];
+    coefs[43] -= tri_consts[2] * b[53];
+    coefs[46] -= tri_consts[1] * b[53];
+    coefs[47] += tri_consts[0] * b[53];
+    coefs[54] += tri_consts[1] * b[53];
+    coefs[55] -= tri_consts[0] * b[53];
+    coefs[58] -= tri_consts[3] * b[53];
+    coefs[59] += tri_consts[2] * b[53];
+    coefs[62] += tri_consts[1] * b[53];
+    coefs[63] -= tri_consts[0] * b[53];
+    coefs[40] += b[54];
+    coefs[42] -= tri_consts[1] * b[54];
+    coefs[43] += tri_consts[0] * b[54];
+    coefs[44] -= b[54];
+    coefs[46] += tri_consts[1] * b[54];
+    coefs[47] -= tri_consts[0] * b[54];
+    coefs[56] -= b[54];
+    coefs[58] += tri_consts[1] * b[54];
+    coefs[59] -= tri_consts[0] * b[54];
+    coefs[60] += b[54];
+    coefs[62] -= tri_consts[1] * b[54];
+    coefs[63] += tri_consts[0] * b[54];
+    coefs[42] += tri_consts[1] * b[55];
+    coefs[43] -= tri_consts[0] * b[55];
+    coefs[46] -= tri_consts[1] * b[55];
+    coefs[47] += tri_consts[0] * b[55];
+    coefs[58] -= tri_consts[1] * b[55];
+    coefs[59] += tri_consts[0] * b[55];
+    coefs[62] += tri_consts[1] * b[55];
+    coefs[63] -= tri_consts[0] * b[55];
+    coefs[21] = b[56];
+    coefs[22] -= tri_consts[0] * b[56];
+    coefs[23] += b[56];
+    coefs[25] -= tri_consts[0] * b[56];
+    coefs[26] += tri_consts[2] * b[56];
+    coefs[27] -= tri_consts[0] * b[56];
+    coefs[29] += b[56];
+    coefs[30] -= tri_consts[0] * b[56];
+    coefs[31] += b[56];
+    coefs[37] -= tri_consts[0] * b[56];
+    coefs[38] += tri_consts[2] * b[56];
+    coefs[39] -= tri_consts[0] * b[56];
+    coefs[41] += tri_consts[2] * b[56];
+    coefs[42] -= tri_consts[4] * b[56];
+    coefs[43] += tri_consts[2] * b[56];
+    coefs[45] -= tri_consts[0] * b[56];
+    coefs[46] += tri_consts[2] * b[56];
+    coefs[47] -= tri_consts[0] * b[56];
+    coefs[53] += b[56];
+    coefs[54] -= tri_consts[0] * b[56];
+    coefs[55] += b[56];
+    coefs[57] -= tri_consts[0] * b[56];
+    coefs[58] += tri_consts[2] * b[56];
+    coefs[59] -= tri_consts[0] * b[56];
+    coefs[61] += b[56];
+    coefs[62] -= tri_consts[0] * b[56];
+    coefs[63] += b[56];
+    coefs[22] -= b[57];
+    coefs[23] += b[57];
+    coefs[26] += tri_consts[0] * b[57];
+    coefs[27] -= tri_consts[0] * b[57];
+    coefs[30] -= b[57];
+    coefs[31] += b[57];
+    coefs[38] += tri_consts[0] * b[57];
+    coefs[39] -= tri_consts[0] * b[57];
+    coefs[42] -= tri_consts[2] * b[57];
+    coefs[43] += tri_consts[2] * b[57];
+    coefs[46] += tri_consts[0] * b[57];
+    coefs[47] -= tri_consts[0] * b[57];
+    coefs[54] -= b[57];
+    coefs[55] += b[57];
+    coefs[58] += tri_consts[0] * b[57];
+    coefs[59] -= tri_consts[0] * b[57];
+    coefs[62] -= b[57];
+    coefs[63] += b[57];
+    coefs[25] -= b[58];
+    coefs[26] += tri_consts[0] * b[58];
+    coefs[27] -= b[58];
+    coefs[29] += b[58];
+    coefs[30] -= tri_consts[0] * b[58];
+    coefs[31] += b[58];
+    coefs[41] += tri_consts[0] * b[58];
+    coefs[42] -= tri_consts[2] * b[58];
+    coefs[43] += tri_consts[0] * b[58];
+    coefs[45] -= tri_consts[0] * b[58];
+    coefs[46] += tri_consts[2] * b[58];
+    coefs[47] -= tri_consts[0] * b[58];
+    coefs[57] -= b[58];
+    coefs[58] += tri_consts[0] * b[58];
+    coefs[59] -= b[58];
+    coefs[61] += b[58];
+    coefs[62] -= tri_consts[0] * b[58];
+    coefs[63] += b[58];
+    coefs[26] += b[59];
+    coefs[27] -= b[59];
+    coefs[30] -= b[59];
+    coefs[31] += b[59];
+    coefs[42] -= tri_consts[0] * b[59];
+    coefs[43] += tri_consts[0] * b[59];
+    coefs[46] += tri_consts[0] * b[59];
+    coefs[47] -= tri_consts[0] * b[59];
+    coefs[58] += b[59];
+    coefs[59] -= b[59];
+    coefs[62] -= b[59];
+    coefs[63] += b[59];
+    coefs[37] -= b[60];
+    coefs[38] += tri_consts[0] * b[60];
+    coefs[39] -= b[60];
+    coefs[41] += tri_consts[0] * b[60];
+    coefs[42] -= tri_consts[2] * b[60];
+    coefs[43] += tri_consts[0] * b[60];
+    coefs[45] -= b[60];
+    coefs[46] += tri_consts[0] * b[60];
+    coefs[47] -= b[60];
+    coefs[53] += b[60];
+    coefs[54] -= tri_consts[0] * b[60];
+    coefs[55] += b[60];
+    coefs[57] -= tri_consts[0] * b[60];
+    coefs[58] += tri_consts[2] * b[60];
+    coefs[59] -= tri_consts[0] * b[60];
+    coefs[61] += b[60];
+    coefs[62] -= tri_consts[0] * b[60];
+    coefs[63] += b[60];
+    coefs[38] += b[61];
+    coefs[39] -= b[61];
+    coefs[42] -= tri_consts[0] * b[61];
+    coefs[43] += tri_consts[0] * b[61];
+    coefs[46] += b[61];
+    coefs[47] -= b[61];
+    coefs[54] -= b[61];
+    coefs[55] += b[61];
+    coefs[58] += tri_consts[0] * b[61];
+    coefs[59] -= tri_consts[0] * b[61];
+    coefs[62] -= b[61];
+    coefs[63] += b[61];
+    coefs[41] += b[62];
+    coefs[42] -= tri_consts[0] * b[62];
+    coefs[43] += b[62];
+    coefs[45] -= b[62];
+    coefs[46] += tri_consts[0] * b[62];
+    coefs[47] -= b[62];
+    coefs[57] -= b[62];
+    coefs[58] += tri_consts[0] * b[62];
+    coefs[59] -= b[62];
+    coefs[61] += b[62];
+    coefs[62] -= tri_consts[0] * b[62];
+    coefs[63] += b[62];
+    coefs[42] -= b[63];
+    coefs[43] += b[63];
+    coefs[46] += b[63];
+    coefs[47] -= b[63];
+    coefs[58] += b[63];
+    coefs[59] -= b[63];
+    coefs[62] -= b[63];
+    coefs[63] += b[63];
+
+    return;
+}
+
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+#endif /* SIXTRACKLIB_COMMON_BE_TRICUB_COEFFICIENTS_C99_H__ */
+
+
diff --git a/sixtracklib/common/be_tricub/track.h b/sixtracklib/common/be_tricub/track.h
new file mode 100644
index 00000000..29f3135d
--- /dev/null
+++ b/sixtracklib/common/be_tricub/track.h
@@ -0,0 +1,275 @@
+#ifndef SIXTRACKLIB_COMMON_BE_TRICUB_TRACK_C99_H__
+#define SIXTRACKLIB_COMMON_BE_TRICUB_TRACK_C99_H__
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/track/definitions.h"
+    #include "sixtracklib/common/internal/beam_elements_defines.h"
+    #include "sixtracklib/common/internal/objects_type_id.h"
+    #include "sixtracklib/common/particles.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+struct NS(TriCub);
+
+SIXTRL_STATIC SIXTRL_FN NS(track_status_t) NS(Track_particle_tricub)(
+    SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
+    NS(particle_num_elements_t) const particle_index,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(TriCub) *const SIXTRL_RESTRICT tricub );
+
+SIXTRL_STATIC SIXTRL_FN void NS(tricub_construct_b_vector)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT tricub_data,
+    NS(be_tricub_int_t) const ix, NS(be_tricub_int_t) const iy, NS(be_tricub_int_t) const iz, 
+    SIXTRL_ARGPTR_DEC NS(be_tricub_real_t)* SIXTRL_RESTRICT b_vector);
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* ========================================================================= */
+/* =====        Implementation of Inline functions and methods         ===== */
+/* ========================================================================= */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <math.h>
+#endif /* #if !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/constants.h"
+    #include "sixtracklib/common/particles.h"
+    #include "sixtracklib/common/be_tricub/be_tricub.h"
+    #include "sixtracklib/common/be_tricub/coefficients.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE NS(track_status_t) NS(Track_particle_tricub)(
+    SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* SIXTRL_RESTRICT particles,
+    NS(particle_num_elements_t) const ii,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(TriCub) *const SIXTRL_RESTRICT tricub )
+{
+    typedef NS(be_tricub_real_t) real_t;
+    typedef NS(be_tricub_int_t)  int_t;
+
+    SIXTRL_BUFFER_DATAPTR_DEC NS(TriCubData) const* tricub_data =
+        NS(TriCub_const_data)( tricub );
+
+    real_t const length = NS(TriCub_length)( tricub );
+    
+    real_t const x_shift = NS(TriCub_x_shift)( tricub );
+    real_t const y_shift = NS(TriCub_y_shift)( tricub );
+    real_t const z_shift = NS(TriCub_tau_shift)( tricub );
+
+    // method = 1 -> Finite Differences for derivatives (Do not use)
+    // method = 2 -> Exact derivatives
+    // method = 3 -> Exact derivatives and mirrored in X, Y
+                 
+    real_t const inv_dx = 1./( NS(TriCubData_dx)( tricub_data ) );
+    real_t const inv_dy = 1./( NS(TriCubData_dy)( tricub_data ) );
+    real_t const inv_dz = 1./( NS(TriCubData_dz)( tricub_data ) );
+
+    real_t const x0 = NS(TriCubData_x0)( tricub_data );
+    real_t const y0 = NS(TriCubData_y0)( tricub_data );
+    real_t const z0 = NS(TriCubData_z0)( tricub_data );
+
+    real_t const zeta  = NS(Particles_get_zeta_value)( particles, ii );
+    real_t const rvv   = NS(Particles_get_rvv_value)( particles, ii );
+    real_t const beta0 = NS(Particles_get_beta0_value)( particles, ii );
+
+    real_t const x = NS(Particles_get_x_value)( particles, ii );
+    real_t const y = NS(Particles_get_y_value)( particles, ii );
+    real_t const z = zeta / ( beta0 * rvv);
+
+    real_t const fx = ( (x - x_shift) - x0 ) * inv_dx;
+    real_t const fy = ( (y - y_shift) - y0 ) * inv_dy;
+    real_t const fz = ( (z - z_shift) - z0 ) * inv_dz;
+
+    real_t const sign_x = ( NS(TriCubData_mirror_x)( tricub_data ) == 1 && fx < 0.0 ) ? -1. : 1.;
+    real_t const sign_y = ( NS(TriCubData_mirror_y)( tricub_data ) == 1 && fy < 0.0 ) ? -1. : 1.;
+    real_t const sign_z = ( NS(TriCubData_mirror_z)( tricub_data ) == 1 && fz < 0.0 ) ? -1. : 1.;
+
+    real_t const sfx = sign_x * fx;
+    real_t const sfy = sign_y * fy;
+    real_t const sfz = sign_z * fz;
+                 
+    real_t const ixf = floor(sfx);
+    real_t const iyf = floor(sfy);
+    real_t const izf = floor(sfz);
+
+    int_t const ix = (int_t)ixf;
+    int_t const iy = (int_t)iyf;
+    int_t const iz = (int_t)izf;
+
+    real_t const xn = sfx - ixf;
+    real_t const yn = sfy - iyf;
+    real_t const zn = sfz - izf;
+
+    // const int_t inside_box = 
+    //   ( ( ( ix < 0 || ix > NS(TriCubData_nx)( tricub_data ) - 2 )   ||
+    //       ( iy < 0 || iy > NS(TriCubData_ny)( tricub_data ) - 2 ) ) ||
+    //       ( iz < 0 || iz > NS(TriCubData_nz)( tricub_data ) - 2 ) ) ? 0 : 1;
+
+    // SIXTRL_ASSERT( inside_box == 1 );
+    // Check that coordinates are inside bounding box
+    SIXTRL_ASSERT( ix >= 0 && ix <= NS(TriCubData_nx)( tricub_data ) - 2 );
+    SIXTRL_ASSERT( iy >= 0 && iy <= NS(TriCubData_ny)( tricub_data ) - 2 ); 
+    SIXTRL_ASSERT( iz >= 0 && iz <= NS(TriCubData_nz)( tricub_data ) - 2 );
+    // =========================================================================
+    
+    real_t b_vector[64];
+    NS(tricub_construct_b_vector)(tricub_data, ix, iy, iz, b_vector);
+
+    real_t coefs[64];
+    NS(tricub_construct_coefs)(b_vector, coefs);
+
+    real_t x_power[4];
+    real_t y_power[4];
+    real_t z_power[4];
+    
+    x_power[0] = 1.;
+    y_power[0] = 1.;
+    z_power[0] = 1.;
+
+    x_power[1] = xn;
+    y_power[1] = yn;
+    z_power[1] = zn;
+
+    x_power[2] = xn * xn;
+    y_power[2] = yn * yn;
+    z_power[2] = zn * zn;
+
+    x_power[3] = x_power[2] * xn;
+    y_power[3] = y_power[2] * yn;
+    z_power[3] = z_power[2] * zn;
+
+    real_t kick_px = 0.;
+    for( int i = 1; i < 4; i++ )
+    {
+        for( int j = 0; j < 4; j++ )
+        {
+            for( int k = 0; k < 4; k++ )
+            {
+                kick_px += i * ( ( ( coefs[i + 4 * j + 16 * k] * x_power[i-1] ) 
+                            * y_power[j] ) * z_power[k] ) ;
+            }
+        }
+    }
+    kick_px *= ( length * inv_dx );
+    kick_px *= -sign_x;
+    kick_px -= NS(TriCub_dipolar_kick_px)( tricub );
+
+    real_t kick_py = 0.;
+    for( int i = 0; i < 4; i++ )
+    {
+        for( int j = 1; j < 4; j++ )
+        {
+            for( int k = 0; k < 4; k++ )
+            {
+                kick_py += j * ( ( ( coefs[i + 4 * j + 16 * k] * x_power[i] ) 
+                            * y_power[j-1] ) * z_power[k] ) ;
+            }
+        }
+    }
+    kick_py *= ( length * inv_dy );
+    kick_py *= -sign_y;
+    kick_py -= NS(TriCub_dipolar_kick_py)( tricub );
+
+    real_t kick_ptau = 0.;
+    for( int i = 0; i < 4; i++ )
+    {
+        for( int j = 0; j < 4; j++ )
+        {
+            for( int k = 1; k < 4; k++ )
+            {
+                kick_ptau += k * ( ( ( coefs[i + 4 * j + 16 * k] * x_power[i] ) 
+                            * y_power[j] ) * z_power[k-1] ) ;
+            }
+        }
+    }
+    kick_ptau *= ( length * inv_dz );
+    kick_ptau *= -sign_z;
+    kick_ptau -= NS(TriCub_dipolar_kick_ptau)( tricub );
+
+    real_t const q = NS(Particles_get_q0_value)( particles, ii ) * 
+                     NS(Particles_get_charge_ratio_value)( particles, ii );
+    real_t const p0c = NS(Particles_get_p0c_value)( particles, ii );
+    real_t const energy_kick = q * ( p0c * kick_ptau );
+
+    NS(Particles_add_to_px_value)( particles, ii, kick_px );
+    NS(Particles_add_to_py_value)( particles, ii, kick_py );
+    NS(Particles_add_to_energy_value)( particles, ii, energy_kick );
+
+
+    /* how to mark a particle in a particle set as lost */
+    /*
+    NS(Particles_mark_as_lost_value)( particles, ii );
+    */
+
+    ( void )particles;
+    ( void )ii;
+    //( void )lookup_table_begin;
+    //( void )lookup_table_size;
+
+    return SIXTRL_TRACK_SUCCESS;
+}
+
+SIXTRL_INLINE void NS(tricub_construct_b_vector)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(TriCubData) *const SIXTRL_RESTRICT tricub_data,
+    NS(be_tricub_int_t) const ix, NS(be_tricub_int_t) const iy, NS(be_tricub_int_t) const iz, 
+    SIXTRL_ARGPTR_DEC NS(be_tricub_real_t)* SIXTRL_RESTRICT b_vector)
+{
+
+    SIXTRL_BUFFER_DATAPTR_DEC NS(be_tricub_real_t) const* lookup_table_begin =
+        NS(TriCubData_const_table_begin)( tricub_data );
+
+    //NS(be_tricub_int_t) const lookup_table_size = NS(TriCubData_table_size)( tricub_data );
+    NS(be_tricub_int_t) const nx = NS(TriCubData_nx)( tricub_data );
+    NS(be_tricub_int_t) const ny = NS(TriCubData_ny)( tricub_data );
+    // NS(be_tricub_int_t) const nz = NS(TriCubData_nz)( tricub_data );
+
+    // NS(be_tricub_real_t) const dx = NS(TriCubData_dx)( tricub_data );
+    // NS(be_tricub_real_t) const dy = NS(TriCubData_dy)( tricub_data );
+    // NS(be_tricub_real_t) const dz = NS(TriCubData_dz)( tricub_data );
+
+    // NS(be_tricub_real_t) const scale[8] = { 1., dx, dy, dz, 
+    //                                       dx * dy, dx * dz, dy * dz, 
+    //                                       (dx * dy) * dz };
+    //
+    for(int l = 0; l < 8; l++)
+    {
+        b_vector[8 * l    ] = lookup_table_begin[ l + 8 * ( (ix  ) + nx * ( (iy  ) + ny * ( (iz  ) ) ) ) ];
+        b_vector[8 * l + 1] = lookup_table_begin[ l + 8 * ( (ix+1) + nx * ( (iy  ) + ny * ( (iz  ) ) ) ) ];
+        b_vector[8 * l + 2] = lookup_table_begin[ l + 8 * ( (ix  ) + nx * ( (iy+1) + ny * ( (iz  ) ) ) ) ];
+        b_vector[8 * l + 3] = lookup_table_begin[ l + 8 * ( (ix+1) + nx * ( (iy+1) + ny * ( (iz  ) ) ) ) ];
+        b_vector[8 * l + 4] = lookup_table_begin[ l + 8 * ( (ix  ) + nx * ( (iy  ) + ny * ( (iz+1) ) ) ) ];
+        b_vector[8 * l + 5] = lookup_table_begin[ l + 8 * ( (ix+1) + nx * ( (iy  ) + ny * ( (iz+1) ) ) ) ];
+        b_vector[8 * l + 6] = lookup_table_begin[ l + 8 * ( (ix  ) + nx * ( (iy+1) + ny * ( (iz+1) ) ) ) ];
+        b_vector[8 * l + 7] = lookup_table_begin[ l + 8 * ( (ix+1) + nx * ( (iy+1) + ny * ( (iz+1) ) ) ) ];
+        //b_vector[8 * l    ] = lookup_table_begin[ (ix  ) + nx * ( (iy  ) + ny * ( (iz  ) + nz * l) ) ] * scale[l];
+        //b_vector[8 * l + 1] = lookup_table_begin[ (ix+1) + nx * ( (iy  ) + ny * ( (iz  ) + nz * l) ) ] * scale[l];
+        //b_vector[8 * l + 2] = lookup_table_begin[ (ix  ) + nx * ( (iy+1) + ny * ( (iz  ) + nz * l) ) ] * scale[l];
+        //b_vector[8 * l + 3] = lookup_table_begin[ (ix+1) + nx * ( (iy+1) + ny * ( (iz  ) + nz * l) ) ] * scale[l];
+        //b_vector[8 * l + 4] = lookup_table_begin[ (ix  ) + nx * ( (iy  ) + ny * ( (iz+1) + nz * l) ) ] * scale[l];
+        //b_vector[8 * l + 5] = lookup_table_begin[ (ix+1) + nx * ( (iy  ) + ny * ( (iz+1) + nz * l) ) ] * scale[l];
+        //b_vector[8 * l + 6] = lookup_table_begin[ (ix  ) + nx * ( (iy+1) + ny * ( (iz+1) + nz * l) ) ] * scale[l];
+        //b_vector[8 * l + 7] = lookup_table_begin[ (ix+1) + nx * ( (iy+1) + ny * ( (iz+1) + nz * l) ) ] * scale[l];
+    }
+
+    return;
+}
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+#endif /* SIXTRACKLIB_COMMON_BE_TRICUB_TRACK_C99_H__ */
+
+/*end: sixtracklib/common/be_tricub/track.h */
diff --git a/sixtracklib/common/be_xyshift/CMakeLists.txt b/sixtracklib/common/be_xyshift/CMakeLists.txt
index e1fc7efb..18cb5018 100644
--- a/sixtracklib/common/be_xyshift/CMakeLists.txt
+++ b/sixtracklib/common/be_xyshift/CMakeLists.txt
@@ -1,50 +1,38 @@
+set( SIXTRL_COMMON_BE_XYSHIFT_C99_HEADERS be_xyshift.h track.h )
+set( SIXTRL_COMMON_BE_XYSHIFT_C99_SOURCES be_xyshift.c )
+set( SIXTRL_COMMON_BE_XYSHIFT_CXX_HEADERS be_xyshift.hpp )
 
-set( SIXTRACKLIB_COMMON_BE_XYSHIFT_C99_HEADERS
-     be_xyshift.h
-)
+add_library( sixtrack_common_be_xyshift OBJECT
+    ${SIXTRL_COMMON_BE_XYSHIFT_C99_HEADERS}
+    ${SIXTRL_COMMON_BE_XYSHIFT_C99_SOURCES} )
 
-set( SIXTRACKLIB_COMMON_BE_XYSHIFT_CXX_HEADERS
-     be_xyshift.hpp
-)
+target_include_directories( sixtrack_common_be_xyshift PRIVATE
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-if( SIXTRACKLIB_COMMON_BE_XYSHIFT_C99_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_xyshift/\\1" LOCAL_C99_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_XYSHIFT_C99_HEADERS}" )
+set_target_properties( sixtrack_common_be_xyshift PROPERTIES
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON C_STANDARD 99
+    C_STANDARD_REQUIRED ON )
 
-    set(  SIXTRACKLIB_COMMON_C99_HEADERS
-        ${SIXTRACKLIB_COMMON_C99_HEADERS}
-        ${LOCAL_C99_HEADERS} PARENT_SCOPE )
-endif()
+target_compile_options( sixtrack_common_be_xyshift PRIVATE
+        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
-if( SIXTRACKLIB_COMMON_BE_XYSHIFT_CXX_HEADERS )
-    string( REGEX REPLACE "([^;]+)" "be_xyshift/\\1" LOCAL_CXX_HEADERS
-            "${SIXTRACKLIB_COMMON_BE_XYSHIFT_CXX_HEADERS}" )
+# ------------------------------------------------------------------------------
+# pass on sixtrack_common_be_beambeam as a module for sixtracklib:
 
-    set(  SIXTRACKLIB_COMMON_CXX_HEADERS
-        ${SIXTRACKLIB_COMMON_CXX_HEADERS}
-        ${LOCAL_CXX_HEADERS} PARENT_SCOPE )
-endif()
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_common_be_xyshift> CACHE INTERNAL "" FORCE )
 
 # ----------------------------------------------------------------------------
 # install :
 
-if( SIXTRACKLIB_COMMON_BE_XYSHIFT_C99_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_XYSHIFT_C99_INSTALL_PATH
-         include/sixtracklib/common/be_xyshift )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_XYSHIFT_C99_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_XYSHIFT_C99_INSTALL_PATH} )
+if( SIXTRL_COMMON_BE_XYSHIFT_C99_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_XYSHIFT_C99_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/be_xyshift" )
 endif()
 
+if( SIXTRACKL_ENABLE_CXX AND SIXTRL_COMMON_BE_XYSHIFT_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BE_XYSHIFT_CXX_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/be_xyshift" )
+ endif()
 
-if( SIXTRACKLIB_COMMON_BE_XYSHIFT_CXX_HEADERS )
-
-    set( SIXTRACKLIB_COMMON_BE_XYSHIFT_CXX_INSTALL_PATH
-         include/sixtracklib/common/be_xyshift )
-
-    install( FILES ${SIXTRACKLIB_COMMON_BE_XYSHIFT_CXX_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_BE_XYSHIFT_CXX_INSTALL_PATH} )
-endif()
-
-#end: sixtracklib/common/be_xyshift/CMakeLists.txt
diff --git a/sixtracklib/common/be_xyshift/be_xyshift.c b/sixtracklib/common/be_xyshift/be_xyshift.c
new file mode 100644
index 00000000..6868ddee
--- /dev/null
+++ b/sixtracklib/common/be_xyshift/be_xyshift.c
@@ -0,0 +1,155 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/be_xyshift/be_xyshift.h"
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #if !defined( _GPUCODE )
+    #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+NS(object_type_id_t) NS(XYShift_type_id_ext)( void ) SIXTRL_NOEXCEPT
+{
+    return NS(XYShift_type_id)();
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+NS(arch_status_t) NS(XYShift_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xyshift,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( offsets != SIXTRL_NULLPTR ) &&
+        ( max_num_offsets > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, offsets, max_num_offsets, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(XYShift_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xyshift,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( sizes != SIXTRL_NULLPTR ) &&
+        ( max_num_sizes > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, sizes, max_num_sizes, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+NS(arch_status_t) NS(XYShift_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xyshift,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    if( ( counts != SIXTRL_NULLPTR ) &&
+        ( max_num_counts > ( buf_size_t )0u ) )
+    {
+        SIXTRACKLIB_SET_VALUES( buf_size_t, counts, max_num_counts, ZERO );
+    }
+
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+bool NS(XYShift_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT requ_dataptrs ) SIXTRL_NOEXCEPT
+{
+    NS(XYShift) temp;
+    NS(arch_status_t) const status = NS(XYShift_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(XYShift_num_dataptrs)( &temp );
+
+    return ( ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) &&
+             ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+             ( NS(Buffer_can_add_object)( buffer, sizeof( NS(XYShift) ),
+                ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR, requ_objects,
+                    requ_slots, requ_dataptrs ) ) );
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* added_elem = SIXTRL_NULLPTR;
+
+    NS(XYShift) temp;
+    NS(arch_status_t) const status = NS(XYShift_clear)( &temp );
+    NS(buffer_size_t) const ndataptrs = NS(XYShift_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(XYShift)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(XYShift) ), NS(XYShift_type_id)(), ndataptrs,
+                    SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_add)(
+    SIXTRL_BE_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_REAL_T const dx, SIXTRL_REAL_T const dy )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) ndataptrs = ( NS(buffer_size_t) )0u;
+
+    NS(XYShift) temp;
+    NS(arch_status_t) status = NS(XYShift_set_dx)( &temp, dx );
+    status |= NS(XYShift_set_dy)( &temp, dy );
+    ndataptrs = NS(XYShift_num_dataptrs)( &temp );
+
+    if( ( buffer != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0 ) &&
+        ( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(XYShift)* )( uintptr_t
+            )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, &temp,
+                sizeof( NS(XYShift) ), NS(XYShift_type_id)(),
+                    ndataptrs, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+                        SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
+
+SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT orig )
+{
+    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* added_elem = SIXTRL_NULLPTR;
+    NS(buffer_size_t) const ndataptrs = NS(XYShift_num_dataptrs)( orig );
+
+    if( ( buffer != SIXTRL_NULLPTR ) && ( orig != SIXTRL_NULLPTR ) &&
+        ( ndataptrs == ( NS(buffer_size_t) )0u ) )
+    {
+        added_elem = ( SIXTRL_BE_ARGPTR_DEC NS(XYShift)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_object)( buffer, orig,
+            sizeof( NS(XYShift) ), NS(XYShift_type_id)(), ndataptrs,
+                SIXTRL_NULLPTR, SIXTRL_NULLPTR, SIXTRL_NULLPTR ) );
+    }
+
+    return added_elem;
+}
diff --git a/sixtracklib/common/be_xyshift/be_xyshift.h b/sixtracklib/common/be_xyshift/be_xyshift.h
index 994300cb..c2f2b3e6 100644
--- a/sixtracklib/common/be_xyshift/be_xyshift.h
+++ b/sixtracklib/common/be_xyshift/be_xyshift.h
@@ -1,5 +1,5 @@
-#ifndef SIXTRACKLIB_COMMON_BE_XYSHIFT_BEAM_ELEMENT_XYSHIFT_H__
-#define SIXTRACKLIB_COMMON_BE_XYSHIFT_BEAM_ELEMENT_XYSHIFT_H__
+#ifndef SIXTRACKLIB_COMMON_BE_DRIFT_BEAM_ELEMENT_XY_SHIFT_H__
+#define SIXTRACKLIB_COMMON_BE_DRIFT_BEAM_ELEMENT_XY_SHIFT_H__
 
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <stdbool.h>
@@ -9,90 +9,158 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/internal/beam_elements_defines.h"
     #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-typedef SIXTRL_REAL_T NS(xyshift_real_t);
+/* ========================================================================= */
 
 typedef struct NS(XYShift)
 {
-    NS(xyshift_real_t) dx SIXTRL_ALIGN( 8 );
-    NS(xyshift_real_t) dy SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T dx SIXTRL_ALIGN( 8 );
+    SIXTRL_REAL_T dy SIXTRL_ALIGN( 8 );
 }
 NS(XYShift);
 
 /* ------------------------------------------------------------------------- */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(XYShift_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t) NS(XYShift_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(XYShift) *const SIXTRL_RESTRICT xy_shift,
-    NS(buffer_size_t) const slot_size );
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(XYShift_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC NS(xyshift_real_t) NS(XYShift_get_dx)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(XYShift_num_dataptrs)(
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const
+        SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC NS(xyshift_real_t) NS(XYShift_get_dy)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift );
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(XYShift_num_slots)(
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(XYShift_type_id)(
+    void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC void NS(XYShift_set_dx)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(XYShift_dx)(
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const
+        SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(XYShift_dy)(
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const
+        SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(XYShift_set_dx)(
     SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift,
-    NS(xyshift_real_t) const dx );
+    SIXTRL_REAL_T const dx ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(XYShift_set_dy)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(XYShift_set_dy)(
     SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift,
-    NS(xyshift_real_t) const dy );
+    SIXTRL_REAL_T const dy ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC void NS(XYShift_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC int NS(XYShift_copy)(
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(XYShift_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT source );
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const
+        SIXTRL_RESTRICT source ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift) const*
+NS(XYShift_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift)*
+NS(XYShift_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    SIXTRL_RESTRICT index_obj ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC int  NS(XYShift_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT rhs );
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_FN SIXTRL_STATIC int NS(XYShift_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift) const*
+NS(XYShift_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift)*
+NS(XYShift_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
 
 #if !defined( _GPUCODE )
 
-SIXTRL_FN SIXTRL_STATIC bool NS(XYShift_can_be_added)(
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift) const*
+NS(XYShift_const_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(XYShift_attributes_offsets)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT offsets_begin,
+    NS(buffer_size_t) const max_num_offsets,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(XYShift_attributes_sizes)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT sizes_begin,
+    NS(buffer_size_t) const max_num_sizes,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(XYShift_attributes_counts)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT counts_begin,
+    NS(buffer_size_t) const max_num_counts,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT data,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(XYShift_type_id_ext)( void ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(XYShift_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objs,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
+        SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(XYShift)* NS(XYShift_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift)*
+NS(XYShift_new)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(XYShift)* NS(XYShift_add)(
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_add)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(xyshift_real_t)  const dx,
-    NS(xyshift_real_t)  const dy );
+    SIXTRL_REAL_T const dx, SIXTRL_REAL_T const dy );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_DATAPTR_DEC NS(XYShift)*
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BE_ARGPTR_DEC NS(XYShift)*
 NS(XYShift_add_copy)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xyshift );
-
-#endif /* !defined( _GPUCODE )*/
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift );
 
+#endif /* !defined( _GPUCODE ) */
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
@@ -102,8 +170,10 @@ NS(XYShift_add_copy)(
 /* ************************************************************************* */
 
 #if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
     #if !defined( _GPUCODE )
-        #include "sixtracklib/common/buffer.h"
+    #include "sixtracklib/common/buffer.h"
     #endif /* !defined( _GPUCODE ) */
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
@@ -111,279 +181,159 @@ NS(XYShift_add_copy)(
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_INLINE NS(buffer_size_t) NS(XYShift_get_num_dataptrs)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_preset)(
+    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT
 {
-    ( void )xy_shift;
-    return ( NS(buffer_size_t) )0u;
+    if( xy_shift != SIXTRL_NULLPTR ) NS(XYShift_clear)( xy_shift );
+    return xy_shift;
 }
 
-SIXTRL_INLINE NS(buffer_size_t) NS(XYShift_get_num_slots)(
-    SIXTRL_BE_ARGPTR_DEC  const NS(XYShift) *const SIXTRL_RESTRICT xyshift,
-    NS(buffer_size_t) const slot_size )
+SIXTRL_INLINE NS(arch_status_t) NS(XYShift_clear)(
+    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t) buf_size_t;
-    typedef NS(XYShift)     beam_element_t;
-
-    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    SIXTRL_ASSERT( xy_shift != SIXTRL_NULLPTR );
+    return NS(XYShift_set_dx)( xy_shift, ( SIXTRL_REAL_T )0 ) |
+           NS(XYShift_set_dy)( xy_shift, ( SIXTRL_REAL_T )0 );
+}
 
-    ( void )xyshift;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    buf_size_t extent = NS(ManagedBuffer_get_slot_based_length)(
-        sizeof( beam_element_t ), slot_size );
+SIXTRL_INLINE NS(buffer_size_t) NS(XYShift_num_dataptrs)( SIXTRL_BE_ARGPTR_DEC
+    const NS(XYShift) *const SIXTRL_RESTRICT SIXTRL_UNUSED( xy_shift )
+) SIXTRL_NOEXCEPT
+{
+    return ( NS(buffer_size_t) )0u;
+}
 
-    SIXTRL_ASSERT( ( slot_size == ZERO ) || ( ( extent % slot_size ) == ZERO ) );
-    return ( slot_size > ZERO ) ? ( extent / slot_size ) : ( ZERO );
+SIXTRL_INLINE NS(buffer_size_t) NS(XYShift_num_slots)( SIXTRL_BE_ARGPTR_DEC const
+        NS(XYShift) *const SIXTRL_RESTRICT SIXTRL_UNUSED( xy_shift ),
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
+{
+    NS(buffer_size_t) num_slots = ( NS(buffer_size_t) )0u;
+    NS(buffer_size_t) const num_bytes = NS(ManagedBuffer_get_slot_based_length)(
+                sizeof( NS(XYShift) ), slot_size );
+
+    SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0 );
+    num_slots = num_bytes / slot_size;
+    if( num_slots * slot_size < num_bytes ) ++num_slots;
+    return num_slots;
 }
 
-SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_preset)(
-    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift )
+SIXTRL_INLINE NS(object_type_id_t) NS(XYShift_type_id)(
+    void ) SIXTRL_NOEXCEPT
 {
-    NS(XYShift_clear)( xy_shift );
-    return xy_shift;
+    return ( NS(object_type_id_t) )NS(OBJECT_TYPE_XYSHIFT);
 }
 
-SIXTRL_INLINE NS(xyshift_real_t) NS(XYShift_get_dx)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(XYShift_dx)( SIXTRL_BE_ARGPTR_DEC const
+    NS(XYShift) *const SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( xy_shift != SIXTRL_NULLPTR );
     return xy_shift->dx;
 }
 
-SIXTRL_INLINE NS(xyshift_real_t) NS(XYShift_get_dy)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift )
+SIXTRL_INLINE SIXTRL_REAL_T NS(XYShift_dy)( SIXTRL_BE_ARGPTR_DEC const
+    NS(XYShift) *const SIXTRL_RESTRICT xy_shift ) SIXTRL_NOEXCEPT
 {
     SIXTRL_ASSERT( xy_shift != SIXTRL_NULLPTR );
     return xy_shift->dy;
 }
 
-SIXTRL_INLINE void NS(XYShift_set_dx)(
+SIXTRL_INLINE NS(arch_status_t) NS(XYShift_set_dx)(
     SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift,
-    NS(xyshift_real_t) const dx )
+    SIXTRL_REAL_T const dx ) SIXTRL_NOEXCEPT
 {
-    if( xy_shift != SIXTRL_NULLPTR ) xy_shift->dx = dx;
-    return;
+    SIXTRL_ASSERT( xy_shift != SIXTRL_NULLPTR );
+    xy_shift->dx = dx;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE void NS(XYShift_set_dy)(
+SIXTRL_INLINE NS(arch_status_t) NS(XYShift_set_dy)(
     SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift,
-    NS(xyshift_real_t) const dy )
+    SIXTRL_REAL_T const dy ) SIXTRL_NOEXCEPT
 {
-    if( xy_shift != SIXTRL_NULLPTR ) xy_shift->dy = dy;
-    return;
-}
-
-SIXTRL_INLINE void NS(XYShift_clear)(
-    SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT xy_shift )
-{
-    NS(XYShift_set_dx)( xy_shift, ( NS(xyshift_real_t) )0 );
-    NS(XYShift_set_dy)( xy_shift, ( NS(xyshift_real_t) )0 );
-
-    return;
+    SIXTRL_ASSERT( xy_shift != SIXTRL_NULLPTR );
+    xy_shift->dy = dy;
+    return ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
 }
 
-SIXTRL_INLINE int NS(XYShift_copy)(
+SIXTRL_INLINE NS(arch_status_t) NS(XYShift_copy)(
     SIXTRL_BE_ARGPTR_DEC NS(XYShift)* SIXTRL_RESTRICT destination,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT source )
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT source
+) SIXTRL_NOEXCEPT
 {
-    int success = -1;
-
-    if( ( destination != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) )
-    {
-        NS(XYShift_set_dx)( destination, NS(XYShift_get_dx)( source ) );
-        NS(XYShift_set_dx)( destination, NS(XYShift_get_dy)( source ) );
-        success = 0;
-    }
-
-    return success;
+    return NS(XYShift_set_dx)( destination, NS(XYShift_dx)( source ) ) |
+           NS(XYShift_set_dy)( destination, NS(XYShift_dy)( source ) );
 }
 
-SIXTRL_INLINE int NS(XYShift_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT rhs )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(XYShift) const*
+NS(XYShift_const_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object)
+    *const SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
 {
-    int compare_value = -1;
+    typedef SIXTRL_BE_ARGPTR_DEC NS(XYShift) const* ptr_xy_shift_t;
+    ptr_xy_shift_t elem = SIXTRL_NULLPTR;
 
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    if( ( obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_XYSHIFT) ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(XYShift) ) ) )
     {
-        compare_value = 0;
-
-        if( NS(XYShift_get_dx)( lhs ) > NS(XYShift_get_dx)( rhs ) )
-        {
-            compare_value = +1;
-        }
-        else if( NS(XYShift_get_dx)( lhs ) < NS(XYShift_get_dx)( rhs ) )
-        {
-            compare_value = -1;
-        }
-
-        if( compare_value == 0 )
-        {
-            if( NS(XYShift_get_dy)( lhs ) > NS(XYShift_get_dy)( rhs ) )
-            {
-                compare_value = +1;
-            }
-            else if( NS(XYShift_get_dy)( lhs ) < NS(XYShift_get_dy)( rhs ) )
-            {
-                compare_value = -1;
-            }
-        }
-    }
-    else if( lhs != SIXTRL_NULLPTR )
-    {
-        compare_value = +1;
+        elem = ( ptr_xy_shift_t )( uintptr_t )NS(Object_get_begin_addr)( obj );
     }
 
-    return compare_value;
+    return elem;
 }
 
-SIXTRL_INLINE int NS(XYShift_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+        SIXTRL_RESTRICT obj ) SIXTRL_NOEXCEPT
 {
-    typedef SIXTRL_REAL_T real_t;
-
-    SIXTRL_STATIC_VAR real_t const ZERO = ( real_t )0.0;
-
-    int compare_value = -1;
-
-    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) &&
-        ( treshold >= ZERO ) )
-    {
-        compare_value = 0;
-
-        if( compare_value == 0 )
-        {
-            real_t const diff =
-                NS(XYShift_get_dx)( lhs ) - NS(XYShift_get_dx)( rhs );
-
-            real_t const abs_diff = ( diff >= ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-
-        if( compare_value == 0 )
-        {
-            real_t const diff =
-                NS(XYShift_get_dy)( lhs ) - NS(XYShift_get_dy)( rhs );
-
-            real_t const abs_diff = ( diff >= ZERO ) ? diff : -diff;
-
-            if( abs_diff > treshold )
-            {
-                if( diff > ZERO )
-                {
-                    compare_value = +1;
-                }
-                else if( diff < ZERO )
-                {
-                    compare_value = -1;
-                }
-            }
-        }
-    }
-    else if( ( lhs != SIXTRL_NULLPTR ) && ( treshold >= ZERO ) )
-    {
-        compare_value = +1;
-    }
-
-    return compare_value;
+    return ( SIXTRL_BE_ARGPTR_DEC NS(XYShift)*
+        )NS(XYShift_const_from_obj_index)( obj );
 }
 
-#if !defined( _GPUCODE )
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-SIXTRL_INLINE bool NS(XYShift_can_be_added)(
-    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
-    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptrs )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(XYShift) const*
+NS(XYShift_const_from_managed_buffer)( SIXTRL_BUFFER_DATAPTR_DEC unsigned char
+        const* SIXTRL_RESTRICT buffer_begin, NS(buffer_size_t) const index,
+    NS(buffer_size_t) const slot_size ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(XYShift)        elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(XYShift_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    return NS(Buffer_can_add_object)( buffer, sizeof( elem_t ),
-        num_dataptrs, sizes, counts, requ_objects, requ_slots, requ_dataptrs );
+    return NS(XYShift_const_from_obj_index)( NS(ManagedBuffer_get_const_object)(
+        buffer_begin, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(XYShift)* NS(XYShift_new)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size
+) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef SIXTRL_REAL_T      real_t;
-    typedef NS(XYShift)        elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC   elem_t*  ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(XYShift_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.dx = ( real_t )0.0;
-    temp_obj.dy = ( real_t )0.0;
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_XYSHIFT), num_dataptrs, offsets, sizes, counts ) );
+    return NS(XYShift_from_obj_index)( NS(ManagedBuffer_get_object)(
+        buffer_begin, index, slot_size ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(XYShift)* NS(XYShift_add)(
-    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    NS(xyshift_real_t)  const dx, NS(xyshift_real_t)  const dy )
+#if !defined( _GPUCODE )
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(XYShift) const* NS(XYShift_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    typedef NS(buffer_size_t)  buf_size_t;
-    typedef NS(XYShift)        elem_t;
-    typedef SIXTRL_BUFFER_DATAPTR_DEC   elem_t*  ptr_to_elem_t;
-
-    buf_size_t const num_dataptrs =
-        NS(XYShift_get_num_dataptrs)( SIXTRL_NULLPTR );
-
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* offsets = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* sizes   = SIXTRL_NULLPTR;
-    SIXTRL_BUFFER_ARGPTR_DEC buf_size_t const* counts  = SIXTRL_NULLPTR;
-
-    elem_t temp_obj;
-    temp_obj.dx = dx;
-    temp_obj.dy = dy;
-
-    return ( ptr_to_elem_t )( uintptr_t )NS(Object_get_begin_addr)(
-        NS(Buffer_add_object)( buffer, &temp_obj, sizeof( elem_t ),
-            NS(OBJECT_TYPE_XYSHIFT), num_dataptrs, offsets, sizes, counts ) );
+    return NS(XYShift_const_from_obj_index)( NS(Buffer_get_const_object)(
+        buffer, index ) );
 }
 
-SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(XYShift)* NS(XYShift_add_copy)(
+SIXTRL_INLINE SIXTRL_BE_ARGPTR_DEC NS(XYShift)* NS(XYShift_from_buffer)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xyshift )
+    NS(buffer_size_t) const index ) SIXTRL_NOEXCEPT
 {
-    return NS(XYShift_add)( buffer,
-        NS(XYShift_get_dx)( xyshift ), NS(XYShift_get_dy)( xyshift ) );
+    return NS(XYShift_from_obj_index)( NS(Buffer_get_object)(
+        buffer, index ) );
 }
-
-#endif /* #if !defined( _GPUCODE ) */
+#endif /* !defined( _GPUCODE ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
-#endif /* SIXTRACKLIB_COMMON_BE_XYSHIFT_BEAM_ELEMENT_XYSHIFT_H__ */
-
-/*end: sixtracklib/common/be_xyshift/be_xyshift.h */
+#endif /* SIXTRACKLIB_COMMON_BE_DRIFT_BEAM_ELEMENT_XY_SHIFT_H__ */
diff --git a/sixtracklib/common/be_xyshift/be_xyshift.hpp b/sixtracklib/common/be_xyshift/be_xyshift.hpp
index aadaf02f..d0f427a1 100644
--- a/sixtracklib/common/be_xyshift/be_xyshift.hpp
+++ b/sixtracklib/common/be_xyshift/be_xyshift.hpp
@@ -100,27 +100,27 @@ namespace SIXTRL_CXX_NAMESPACE
         typename TXYShift< T >::value_type const& dy );
 
     /* ===================================================================== *
-     * ====  Specialization TXYShift< NS(xyshift_real_t) > :
+     * ====  Specialization TXYShift< SIXTRL_REAL_T > :
      * ===================================================================== */
 
 
-    template<> struct TXYShift< NS(xyshift_real_t) > : public ::NS(XYShift)
+    template<> struct TXYShift< SIXTRL_REAL_T > : public ::NS(XYShift)
     {
-        using value_type = NS(xyshift_real_t);
+        using value_type = SIXTRL_REAL_T;
         using type_id_t  = NS(object_type_id_t);
         using size_type  = NS(buffer_size_t);
         using buffer_t   = ::NS(Buffer);
         using c_api_t    = ::NS(XYShift);
 
         SIXTRL_FN TXYShift() = default;
-        SIXTRL_FN TXYShift( TXYShift< NS(xyshift_real_t) > const& other ) = default;
-        SIXTRL_FN TXYShift( TXYShift< NS(xyshift_real_t) >&& other ) = default;
+        SIXTRL_FN TXYShift( TXYShift< SIXTRL_REAL_T > const& other ) = default;
+        SIXTRL_FN TXYShift( TXYShift< SIXTRL_REAL_T >&& other ) = default;
 
-        SIXTRL_FN TXYShift< NS(xyshift_real_t) >& operator=(
-            TXYShift< NS(xyshift_real_t) > const& rhs ) = default;
+        SIXTRL_FN TXYShift< SIXTRL_REAL_T >& operator=(
+            TXYShift< SIXTRL_REAL_T > const& rhs ) = default;
 
-        SIXTRL_FN TXYShift< NS(xyshift_real_t) >& operator=(
-            TXYShift< NS(xyshift_real_t) >&& rhs ) = default;
+        SIXTRL_FN TXYShift< SIXTRL_REAL_T >& operator=(
+            TXYShift< SIXTRL_REAL_T >&& rhs ) = default;
 
         SIXTRL_FN ~TXYShift() = default;
 
@@ -136,15 +136,15 @@ namespace SIXTRL_CXX_NAMESPACE
                 ptr_requ_dataptrs = nullptr ) SIXTRL_NOEXCEPT;
 
         SIXTRL_FN SIXTRL_STATIC
-        SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >*
+        SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >*
         CreateNewOnBuffer( buffer_t& SIXTRL_RESTRICT_REF buffer );
 
         SIXTRL_FN SIXTRL_STATIC
-        SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >* AddToBuffer(
+        SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >* AddToBuffer(
             buffer_t& SIXTRL_RESTRICT_REF buffer,
             value_type const dx, value_type const dy )
         {
-            using ptr_t = SIXTRL_ARGPTR_DEC TXYShift< ::NS(xyshift_real_t) >*;
+            using ptr_t = SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >*;
             return static_cast< ptr_t >( ::NS(XYShift_add)( &buffer, dx, dy ) );
         }
 
@@ -164,7 +164,7 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_FN void setDy( value_type const dy ) SIXTRL_NOEXCEPT;
     };
 
-    using XYShift = TXYShift< NS(xyshift_real_t) >;
+    using XYShift = TXYShift< SIXTRL_REAL_T >;
 
     SIXTRL_ARGPTR_DEC XYShift* XYShift_new( Buffer& buffer );
 
@@ -172,11 +172,11 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_ARGPTR_DEC ::NS(Buffer)* SIXTRL_RESTRICT ptr_buffer );
 
     SIXTRL_ARGPTR_DEC XYShift* XYShift_add( Buffer& buffer,
-        NS(xyshift_real_t) const dx, NS(xyshift_real_t) const dy );
+        SIXTRL_REAL_T const dx, SIXTRL_REAL_T const dy );
 
     SIXTRL_ARGPTR_DEC XYShift* XYShift_add(
         SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
-        NS(xyshift_real_t) const dx, NS(xyshift_real_t) const dy );
+        SIXTRL_REAL_T const dx, SIXTRL_REAL_T const dy );
 }
 
 
@@ -363,40 +363,40 @@ namespace SIXTRL_CXX_NAMESPACE
      * ====  Specialization TXYShift<  > :
      * ===================================================================== */
 
-    SIXTRL_INLINE bool TXYShift< ::NS(xyshift_real_t) >::CanAddToBuffer(
-        TXYShift< ::NS(xyshift_real_t) >::buffer_t& SIXTRL_RESTRICT_REF buffer,
-        SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >::size_type*
+    SIXTRL_INLINE bool TXYShift< SIXTRL_REAL_T >::CanAddToBuffer(
+        TXYShift< SIXTRL_REAL_T >::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >::size_type*
             SIXTRL_RESTRICT ptr_requ_objects,
-        SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >::size_type*
+        SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >::size_type*
             SIXTRL_RESTRICT ptr_requ_slots,
-        SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >::size_type*
+        SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >::size_type*
             SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
     {
         return ::NS(XYShift_can_be_added)(
             &buffer, ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
     }
 
-    SIXTRL_INLINE SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >*
-    TXYShift< NS(xyshift_real_t) >::CreateNewOnBuffer(
-        TXYShift< NS(xyshift_real_t) >::buffer_t& SIXTRL_RESTRICT_REF buffer )
+    SIXTRL_INLINE SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >*
+    TXYShift< SIXTRL_REAL_T >::CreateNewOnBuffer(
+        TXYShift< SIXTRL_REAL_T >::buffer_t& SIXTRL_RESTRICT_REF buffer )
     {
-        using ptr_t = SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >*;
+        using ptr_t = SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >*;
         return static_cast< ptr_t >( ::NS(XYShift_new)( &buffer ) );
     }
 
     /* ----------------------------------------------------------------- */
 
-    SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >::c_api_t const*
-    TXYShift< NS(xyshift_real_t) >::getCApiPtr() const SIXTRL_NOEXCEPT
+    SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >::c_api_t const*
+    TXYShift< SIXTRL_REAL_T >::getCApiPtr() const SIXTRL_NOEXCEPT
     {
-        using ptr_t = TXYShift< NS(xyshift_real_t) >::c_api_t const*;
+        using ptr_t = TXYShift< SIXTRL_REAL_T >::c_api_t const*;
         return reinterpret_cast< ptr_t >( this );
     }
 
-    SIXTRL_ARGPTR_DEC TXYShift< NS(xyshift_real_t) >::c_api_t*
-    TXYShift< NS(xyshift_real_t) >::getCApiPtr() SIXTRL_NOEXCEPT
+    SIXTRL_ARGPTR_DEC TXYShift< SIXTRL_REAL_T >::c_api_t*
+    TXYShift< SIXTRL_REAL_T >::getCApiPtr() SIXTRL_NOEXCEPT
     {
-        using _this_t = TXYShift< NS(xyshift_real_t) >;
+        using _this_t = TXYShift< SIXTRL_REAL_T >;
         using   ptr_t = _this_t::c_api_t*;
 
         return const_cast< ptr_t >( static_cast< _this_t const& >(
@@ -405,37 +405,37 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* ----------------------------------------------------------------- */
 
-    SIXTRL_INLINE TXYShift< NS(xyshift_real_t) >::type_id_t
-    TXYShift< NS(xyshift_real_t) >::getTypeId() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TXYShift< SIXTRL_REAL_T >::type_id_t
+    TXYShift< SIXTRL_REAL_T >::getTypeId() const SIXTRL_NOEXCEPT
     {
         return ::NS(OBJECT_TYPE_XYSHIFT);
     }
 
-    SIXTRL_INLINE TXYShift< NS(xyshift_real_t) >::value_type
-    TXYShift< NS(xyshift_real_t) >::getDx() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TXYShift< SIXTRL_REAL_T >::value_type
+    TXYShift< SIXTRL_REAL_T >::getDx() const SIXTRL_NOEXCEPT
     {
-        return ::NS(XYShift_get_dx)( this->getCApiPtr() );
+        return ::NS(XYShift_dx)( this->getCApiPtr() );
     }
 
-    SIXTRL_INLINE TXYShift< NS(xyshift_real_t) >::value_type
-    TXYShift< NS(xyshift_real_t) >::getDy() const SIXTRL_NOEXCEPT
+    SIXTRL_INLINE TXYShift< SIXTRL_REAL_T >::value_type
+    TXYShift< SIXTRL_REAL_T >::getDy() const SIXTRL_NOEXCEPT
     {
-        return ::NS(XYShift_get_dy)( this->getCApiPtr() );
+        return ::NS(XYShift_dy)( this->getCApiPtr() );
     }
 
-    SIXTRL_INLINE void TXYShift< NS(xyshift_real_t) >::preset() SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TXYShift< SIXTRL_REAL_T >::preset() SIXTRL_NOEXCEPT
     {
         ::NS(XYShift_preset)( this->getCApiPtr() );
     }
 
-    SIXTRL_INLINE void TXYShift< NS(xyshift_real_t) >::setDx(
-        TXYShift< NS(xyshift_real_t) >::value_type const dx ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TXYShift< SIXTRL_REAL_T >::setDx(
+        TXYShift< SIXTRL_REAL_T >::value_type const dx ) SIXTRL_NOEXCEPT
     {
         ::NS(XYShift_set_dx)( this->getCApiPtr(), dx );
     }
 
-    SIXTRL_INLINE void TXYShift< NS(xyshift_real_t) >::setDy(
-        TXYShift< NS(xyshift_real_t) >::value_type const dy ) SIXTRL_NOEXCEPT
+    SIXTRL_INLINE void TXYShift< SIXTRL_REAL_T >::setDy(
+        TXYShift< SIXTRL_REAL_T >::value_type const dy ) SIXTRL_NOEXCEPT
     {
         ::NS(XYShift_set_dy)( this->getCApiPtr(), dy );
     }
@@ -457,7 +457,7 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     SIXTRL_INLINE SIXTRL_ARGPTR_DEC XYShift* XYShift_add( Buffer& buffer,
-        NS(xyshift_real_t) const dx, NS(xyshift_real_t) const dy )
+        SIXTRL_REAL_T const dx, SIXTRL_REAL_T const dy )
     {
         using ptr_t = SIXTRL_ARGPTR_DEC XYShift*;
         return static_cast< ptr_t >(
@@ -466,7 +466,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
     SIXTRL_INLINE SIXTRL_ARGPTR_DEC XYShift* XYShift_add(
         SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
-        NS(xyshift_real_t) const dx, NS(xyshift_real_t) const dy )
+        SIXTRL_REAL_T const dx, SIXTRL_REAL_T const dy )
     {
         using ptr_t = SIXTRL_ARGPTR_DEC XYShift*;
         return static_cast< ptr_t >( ::NS(XYShift_add)( ptr_buffer, dx, dy ) );
diff --git a/sixtracklib/common/be_xyshift/track.h b/sixtracklib/common/be_xyshift/track.h
index d1f3f98f..1b322d28 100644
--- a/sixtracklib/common/be_xyshift/track.h
+++ b/sixtracklib/common/be_xyshift/track.h
@@ -42,8 +42,8 @@ SIXTRL_INLINE int NS(Track_particle_xy_shift)(
 {
     typedef NS(particle_real_t) real_t;
 
-    real_t const minus_dx = -( NS(XYShift_get_dx)( xy_shift ) );
-    real_t const minus_dy = -( NS(XYShift_get_dy)( xy_shift ) );
+    real_t const minus_dx = -( NS(XYShift_dx)( xy_shift ) );
+    real_t const minus_dy = -( NS(XYShift_dy)( xy_shift ) );
 
     SIXTRL_ASSERT( NS(Particles_get_state_value)( particles, index ) ==
                   ( NS(particle_index_t) )1 );
diff --git a/sixtracklib/common/beam_elements.h b/sixtracklib/common/beam_elements.h
index e7fad6f0..57a2d3d3 100644
--- a/sixtracklib/common/beam_elements.h
+++ b/sixtracklib/common/beam_elements.h
@@ -21,6 +21,7 @@
     #include "sixtracklib/common/be_limit/be_limit_ellipse.h"
     #include "sixtracklib/common/be_limit/be_limit_rect_ellipse.h"
     #include "sixtracklib/common/be_dipedge/be_dipedge.h"
+    #include "sixtracklib/common/be_tricub/be_tricub.h"
     #include "sixtracklib/common/buffer/buffer_object.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
@@ -163,8 +164,9 @@ SIXTRL_INLINE bool NS(BeamElements_is_beam_element_obj)(
 
             case NS(OBJECT_TYPE_BEAM_BEAM_4D):
             case NS(OBJECT_TYPE_BEAM_BEAM_6D):
-            case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
-            case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+            case NS(OBJECT_TYPE_SC_COASTING):
+            case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
+            case NS(OBJECT_TYPE_SC_INTERPOLATED_PROF):
             {
                 is_beam_element = true;
                 break;
@@ -172,6 +174,16 @@ SIXTRL_INLINE bool NS(BeamElements_is_beam_element_obj)(
 
             #endif /* !defined( SIXTRL_DISABLE_BEAM_BEAM ) */
 
+            #if !defined( SIXTRL_DISABLE_TRICUB )
+
+            case NS(OBJECT_TYPE_TRICUB):
+            {
+                is_beam_element = true;
+                break;
+            }
+
+            #endif /* !defined( SIXTRL_DISABLE_TRICUB ) */
+
             default:
             {
                 is_beam_element = false;
@@ -238,14 +250,11 @@ SIXTRL_INLINE int NS(BeamElements_calc_buffer_parameters_for_object)(
                 typedef NS(Drift) beam_element_t;
                 typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
 
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                ptr_belem_t elem = ( ptr_belem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-                requ_num_dataptrs =
-                    NS(Drift_get_num_dataptrs)( ptr_begin );
-
-                requ_num_slots    =
-                    NS(Drift_get_num_slots)( ptr_begin, slot_size );
+                requ_num_dataptrs = NS(Drift_num_dataptrs)( elem );
+                requ_num_slots    = NS(Drift_num_slots)( elem, slot_size );
                 break;
             }
 
@@ -253,93 +262,66 @@ SIXTRL_INLINE int NS(BeamElements_calc_buffer_parameters_for_object)(
             {
                 typedef NS(DriftExact) beam_element_t;
                 typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                ptr_belem_t elem = ( ptr_belem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-
-                requ_num_dataptrs =
-                    NS(DriftExact_get_num_dataptrs)( ptr_begin );
-
-                requ_num_slots    =
-                    NS(DriftExact_get_num_slots)( ptr_begin, slot_size );
+                requ_num_dataptrs = NS(DriftExact_num_dataptrs)( elem );
+                requ_num_slots = NS(DriftExact_num_slots)( elem, slot_size );
                 break;
             }
 
             case NS(OBJECT_TYPE_MULTIPOLE):
             {
-                typedef NS(MultiPole) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(Multipole) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-                requ_num_slots =
-                    NS(MultiPole_get_num_slots)( ptr_begin, slot_size );
-
-                requ_num_dataptrs =
-                    NS(MultiPole_get_num_dataptrs)( ptr_begin );
+                requ_num_slots = NS(Multipole_num_slots)( elem, slot_size );
+                requ_num_dataptrs = NS(Multipole_num_dataptrs)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_RF_MULTIPOLE):
             {
-                typedef NS(RFMultiPole) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const* ptr_t;
+                ptr_t elem = ( ptr_t )( uintptr_t )begin_addr;
 
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
                 ++requ_num_objects;
-                requ_num_slots = NS(RFMultiPole_num_slots)( ptr_begin, slot_size );
-                requ_num_dataptrs = NS(RFMultiPole_num_dataptrs)( ptr_begin );
+                requ_num_slots = NS(RFMultipole_num_slots)( elem, slot_size );
+                requ_num_dataptrs = NS(RFMultipole_num_dataptrs)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_XYSHIFT):
             {
-                typedef NS(XYShift) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(XYShift) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-                requ_num_slots =
-                    NS(XYShift_get_num_slots)( ptr_begin, slot_size );
-
-                requ_num_dataptrs =
-                    NS(XYShift_get_num_dataptrs)( ptr_begin );
-
+                requ_num_slots = NS(XYShift_num_slots)( elem, slot_size );
+                requ_num_dataptrs = NS(XYShift_num_dataptrs)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_SROTATION):
             {
-                typedef NS(SRotation) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(SRotation) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-                requ_num_slots =
-                    NS(SRotation_get_num_slots)( ptr_begin, slot_size );
-
-                requ_num_dataptrs =
-                    NS(SRotation_get_num_dataptrs)( ptr_begin );
+                requ_num_slots = NS(SRotation_num_slots)( elem, slot_size );
+                requ_num_dataptrs = NS(SRotation_num_dataptrs)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_CAVITY):
             {
-                typedef NS(Cavity) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(Cavity) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-                requ_num_slots =
-                    NS(Cavity_get_num_slots)( ptr_begin, slot_size );
-
-                requ_num_dataptrs =
-                    NS(Cavity_get_num_dataptrs)( ptr_begin );
+                requ_num_dataptrs = NS(Cavity_num_dataptrs)( elem );
+                requ_num_slots = NS(Cavity_num_slots)( elem, slot_size );
                 break;
             }
 
@@ -347,80 +329,75 @@ SIXTRL_INLINE int NS(BeamElements_calc_buffer_parameters_for_object)(
 
             case NS(OBJECT_TYPE_BEAM_BEAM_4D):
             {
-                typedef NS(BeamBeam4D) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
+                requ_num_dataptrs = NS(BeamBeam4D_num_dataptrs)( elem );
+                requ_num_slots = NS(BeamBeam4D_num_slots)( elem, slot_size );
 
-                requ_num_slots =
-                NS(BeamBeam4D_get_required_num_slots_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                break;
+            }
 
-                requ_num_dataptrs =
-                NS(BeamBeam4D_get_required_num_dataptrs_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+            {
+                typedef SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
+
+                ++requ_num_objects;
+                requ_num_dataptrs = NS(BeamBeam6D_num_dataptrs)( elem );
+                requ_num_slots = NS(BeamBeam6D_num_slots)( elem, slot_size );
 
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+            case NS(OBJECT_TYPE_SC_COASTING):
             {
-                typedef NS(SpaceChargeCoasting) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(SCCoasting) const*
+                        ptr_belem_t;
 
+                ptr_belem_t sc_elem = ( ptr_belem_t )( uintptr_t )begin_addr;
                 ++requ_num_objects;
 
                 requ_num_slots =
-                NS(SpaceChargeCoasting_get_required_num_slots_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                    NS(SCCoasting_num_slots)( sc_elem, slot_size );
 
                 requ_num_dataptrs =
-                NS(SpaceChargeCoasting_get_required_num_dataptrs_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                    NS(SCCoasting_num_dataptrs)( sc_elem );
 
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+            case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
             {
-                typedef NS(SpaceChargeBunched) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(SCQGaussProfile)
+                        const* ptr_belem_t;
 
+                ptr_belem_t sc_elem = ( ptr_belem_t )( uintptr_t )begin_addr;
                 ++requ_num_objects;
 
-                requ_num_slots =
-                NS(SpaceChargeBunched_get_required_num_slots_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                requ_num_slots = NS(SCQGaussProfile_num_slots)(
+                    sc_elem, slot_size );
 
                 requ_num_dataptrs =
-                NS(SpaceChargeBunched_get_required_num_dataptrs_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                    NS(SCQGaussProfile_num_dataptrs)( sc_elem );
 
                 break;
             }
 
-            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+            case NS(OBJECT_TYPE_SC_INTERPOLATED_PROF):
             {
-                typedef NS(BeamBeam6D) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(SCInterpolatedProfile)
+                        const* ptr_belem_t;
 
+                ptr_belem_t sc_elem = ( ptr_belem_t )( uintptr_t )begin_addr;
                 ++requ_num_objects;
 
-                requ_num_slots =
-                NS(BeamBeam6D_get_required_num_slots_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                requ_num_slots = NS(SCInterpolatedProfile_num_slots)(
+                    sc_elem, slot_size );
 
                 requ_num_dataptrs =
-                NS(BeamBeam6D_get_required_num_dataptrs_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                    NS(SCInterpolatedProfile_num_dataptrs)( sc_elem );
 
                 break;
             }
@@ -429,96 +406,81 @@ SIXTRL_INLINE int NS(BeamElements_calc_buffer_parameters_for_object)(
 
             case NS(OBJECT_TYPE_BEAM_MONITOR):
             {
-                typedef NS(BeamMonitor) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-
-                requ_num_slots = NS(BeamMonitor_get_num_slots)(
-                    ptr_begin, slot_size );
-
-                requ_num_dataptrs = NS(BeamMonitor_get_num_dataptrs)(
-                    ptr_begin );
-
+                requ_num_slots = NS(BeamMonitor_num_slots)( elem, slot_size );
+                requ_num_dataptrs = NS(BeamMonitor_num_dataptrs)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_LIMIT_RECT):
             {
-                typedef NS(LimitRect) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-
-                requ_num_slots =
-                NS(LimitRect_get_required_num_slots_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
-
-                requ_num_dataptrs =
-                NS(LimitRect_get_required_num_dataptrs_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
-
+                requ_num_slots = NS(LimitRect_num_slots)( elem, slot_size );
+                requ_num_dataptrs = NS(LimitRect_num_dataptrs)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_LIMIT_ELLIPSE):
             {
-                typedef NS(LimitEllipse) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-
-                requ_num_slots =
-                NS(LimitEllipse_get_required_num_slots_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
-
-                requ_num_dataptrs =
-                NS(LimitEllipse_get_required_num_dataptrs_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
-
+                requ_num_slots = NS(LimitEllipse_num_slots)( elem, slot_size );
+                requ_num_dataptrs = NS(LimitEllipse_num_dataptrs)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_LIMIT_RECT_ELLIPSE):
             {
-                typedef NS(LimitRectEllipse) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse) const*
+                        ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )begin_addr;
 
                 ++requ_num_objects;
-
+                requ_num_dataptrs = NS(LimitRectEllipse_num_dataptrs)( elem );
                 requ_num_slots = NS(LimitRectEllipse_num_slots)(
-                    ptr_begin, slot_size );
+                    elem, slot_size );
+                break;
+            }
 
-                requ_num_dataptrs =
-                    NS(LimitRectEllipse_num_dataptrs)( ptr_begin );
+            case NS(OBJECT_TYPE_DIPEDGE):
+            {
+                typedef SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const* ptr_belem_t;
+                ptr_belem_t elem = ( ptr_belem_t )( uintptr_t )begin_addr;
 
+                ++requ_num_objects;
+                requ_num_slots = NS(DipoleEdge_num_slots)( elem, slot_size );
+                requ_num_dataptrs = NS(DipoleEdge_num_dataptrs)( elem );
                 break;
             }
 
-            case NS(OBJECT_TYPE_DIPEDGE):
+            case NS(OBJECT_TYPE_TRICUB):
             {
-                typedef NS(DipoleEdge) beam_element_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
+                ++requ_num_objects;
+                requ_num_slots = NS(TriCub_num_slots)(
+                    SIXTRL_NULLPTR, slot_size );
 
-                ptr_belem_t ptr_begin = ( ptr_belem_t )( uintptr_t )begin_addr;
+                requ_num_dataptrs = NS(TriCub_num_dataptrs)( SIXTRL_NULLPTR );
+
+                break;
+            }
 
+            case NS(OBJECT_TYPE_TRICUB_DATA):
+            {
                 ++requ_num_objects;
 
-                requ_num_slots =
-                NS(DipoleEdge_get_required_num_slots_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                requ_num_slots = NS(TriCubData_num_slots)(
+                    SIXTRL_NULLPTR, slot_size );
 
                 requ_num_dataptrs =
-                NS(DipoleEdge_get_required_num_dataptrs_on_managed_buffer)(
-                    SIXTRL_NULLPTR, ptr_begin, slot_size );
+                    NS(TriCubData_num_dataptrs)( SIXTRL_NULLPTR );
 
                 break;
             }
@@ -604,11 +566,11 @@ SIXTRL_INLINE int NS(BeamElements_copy_object)(
 
                 case NS(OBJECT_TYPE_MULTIPOLE):
                 {
-                    typedef NS(MultiPole)                           belem_t;
+                    typedef NS(Multipole)                           belem_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t*           ptr_dest_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t const*     ptr_src_t;
 
-                    success = NS(MultiPole_copy)(
+                    success = NS(Multipole_copy)(
                         ( ptr_dest_t )( uintptr_t )dest_addr,
                         ( ptr_src_t  )( uintptr_t )src_addr );
 
@@ -617,11 +579,11 @@ SIXTRL_INLINE int NS(BeamElements_copy_object)(
 
                 case NS(OBJECT_TYPE_RF_MULTIPOLE):
                 {
-                    typedef NS(RFMultiPole) beam_element_t;
+                    typedef NS(RFMultipole) beam_element_t;
                     typedef SIXTRL_BE_ARGPTR_DEC beam_element_t* ptr_dest_t;
                     typedef SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_src_t;
 
-                    success = NS(RFMultiPole_copy)(
+                    success = NS(RFMultipole_copy)(
                         ( ptr_dest_t )( uintptr_t )dest_addr,
                         ( ptr_src_t  )( uintptr_t )src_addr );
 
@@ -671,50 +633,48 @@ SIXTRL_INLINE int NS(BeamElements_copy_object)(
 
                 case NS(OBJECT_TYPE_BEAM_BEAM_4D):
                 {
-                    typedef NS(BeamBeam4D)                      belem_t;
-                    typedef SIXTRL_BE_ARGPTR_DEC belem_t*       ptr_dest_t;
-                    typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_src_t;
-
-                    success = NS(BeamBeam4D_copy)(
-                        ( ptr_dest_t )( uintptr_t )dest_addr,
-                        ( ptr_src_t  )( uintptr_t )src_addr );
+                    success = ( ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS
+                        == NS(BeamBeam4D_copy)(
+                        ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)* )(
+                            uintptr_t )dest_addr,
+                        ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const* )(
+                            uintptr_t )src_addr ) );
 
                     break;
                 }
 
-                case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+                case NS(OBJECT_TYPE_BEAM_BEAM_6D):
                 {
-                    typedef NS(SpaceChargeCoasting)             belem_t;
-                    typedef SIXTRL_BE_ARGPTR_DEC belem_t*       ptr_dest_t;
-                    typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_src_t;
-
-                    success = NS(SpaceChargeCoasting_copy)(
-                        ( ptr_dest_t )( uintptr_t )dest_addr,
-                        ( ptr_src_t  )( uintptr_t )src_addr );
+                    success = ( ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS
+                        == NS(BeamBeam6D_copy)(
+                        ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)* )(
+                            uintptr_t )dest_addr,
+                        ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const* )(
+                            uintptr_t )src_addr ) );
 
                     break;
                 }
 
-                case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+                case NS(OBJECT_TYPE_SC_COASTING):
                 {
-                    typedef NS(SpaceChargeBunched)              belem_t;
+                    typedef NS(SCCoasting)             belem_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t*       ptr_dest_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_src_t;
 
-                    success = NS(SpaceChargeBunched_copy)(
+                    success = NS(SCCoasting_copy)(
                         ( ptr_dest_t )( uintptr_t )dest_addr,
                         ( ptr_src_t  )( uintptr_t )src_addr );
 
                     break;
                 }
 
-                case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+                case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
                 {
-                    typedef NS(BeamBeam6D)                     belem_t;
+                    typedef NS(SCQGaussProfile)              belem_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t*       ptr_dest_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_src_t;
 
-                    success = NS(BeamBeam6D_copy)(
+                    success = NS(SCQGaussProfile_copy)(
                         ( ptr_dest_t )( uintptr_t )dest_addr,
                         ( ptr_src_t  )( uintptr_t )src_addr );
 
@@ -788,6 +748,32 @@ SIXTRL_INLINE int NS(BeamElements_copy_object)(
                     break;
                 }
 
+                case NS(OBJECT_TYPE_TRICUB):
+                {
+                    typedef NS(TriCub) belem_t;
+                    typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_dest_t;
+                    typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_src_t;
+
+                    success = NS(TriCub_copy)(
+                        ( ptr_dest_t )( uintptr_t )dest_addr,
+                        ( ptr_src_t  )( uintptr_t )src_addr );
+
+                    break;
+                }
+
+                case NS(OBJECT_TYPE_TRICUB_DATA):
+                {
+                    typedef NS(TriCubData) belem_t;
+                    typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_dest_t;
+                    typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_src_t;
+
+                    success = NS(TriCubData_copy)(
+                        ( ptr_dest_t )( uintptr_t )dest_addr,
+                        ( ptr_src_t  )( uintptr_t )src_addr );
+
+                    break;
+                }
+
                 default:
                 {
                     success = -1;
@@ -832,17 +818,17 @@ SIXTRL_STATIC SIXTRL_FN void NS(BeamElements_clear_object)(
 
                 case NS(OBJECT_TYPE_MULTIPOLE):
                 {
-                    typedef NS(MultiPole)                 belem_t;
+                    typedef NS(Multipole)                 belem_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_belem_t;
-                    NS(MultiPole_clear)( ( ptr_belem_t )( uintptr_t )obj_addr );
+                    NS(Multipole_clear)( ( ptr_belem_t )( uintptr_t )obj_addr );
                     break;
                 }
 
                 case NS(OBJECT_TYPE_RF_MULTIPOLE):
                 {
-                    typedef NS(RFMultiPole) belem_t;
+                    typedef NS(RFMultipole) belem_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_belem_t;
-                    NS(RFMultiPole_clear)( ( ptr_belem_t )( uintptr_t )obj_addr );
+                    NS(RFMultipole_clear)( ( ptr_belem_t )( uintptr_t )obj_addr );
                     break;
                 }
 
@@ -874,39 +860,35 @@ SIXTRL_STATIC SIXTRL_FN void NS(BeamElements_clear_object)(
 
                 case NS(OBJECT_TYPE_BEAM_BEAM_4D):
                 {
-                    typedef NS(BeamBeam4D)                belem_t;
-                    typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_belem_t;
-
-                    NS(BeamBeam4D_clear)( ( ptr_belem_t )( uintptr_t )obj_addr );
+                    NS(BeamBeam4D_clear)( ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D)*
+                        )( uintptr_t )obj_addr );
                     break;
                 }
 
-                case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+                case NS(OBJECT_TYPE_BEAM_BEAM_6D):
                 {
-                    typedef NS(SpaceChargeCoasting)       belem_t;
-                    typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_belem_t;
-
-                    NS(SpaceChargeCoasting_clear)(
-                        ( ptr_belem_t )( uintptr_t )obj_addr );
+                    NS(BeamBeam6D_clear)( ( SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D)*
+                        )( uintptr_t )obj_addr );
                     break;
                 }
 
-                case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+                case NS(OBJECT_TYPE_SC_COASTING):
                 {
-                    typedef NS(SpaceChargeBunched)       belem_t;
+                    typedef NS(SCCoasting)       belem_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_belem_t;
 
-                    NS(SpaceChargeBunched_clear)(
+                    NS(SCCoasting_clear)(
                         ( ptr_belem_t )( uintptr_t )obj_addr );
                     break;
                 }
 
-                case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+                case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
                 {
-                    typedef NS(BeamBeam6D)                belem_t;
+                    typedef NS(SCQGaussProfile)       belem_t;
                     typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_belem_t;
 
-                    NS(BeamBeam6D_clear)( ( ptr_belem_t )( uintptr_t )obj_addr );
+                    NS(SCQGaussProfile_clear)(
+                        ( ptr_belem_t )( uintptr_t )obj_addr );
                     break;
                 }
 
@@ -958,6 +940,22 @@ SIXTRL_STATIC SIXTRL_FN void NS(BeamElements_clear_object)(
                     break;
                 }
 
+                case NS(OBJECT_TYPE_TRICUB):
+                {
+                    typedef NS(TriCub) belem_t;
+                    typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_belem_t;
+                    NS(TriCub_clear)( ( ptr_belem_t )( uintptr_t )obj_addr );
+                    break;
+                }
+
+                case NS(OBJECT_TYPE_TRICUB_DATA):
+                {
+                    typedef NS(TriCubData) belem_t;
+                    typedef SIXTRL_BE_ARGPTR_DEC belem_t* ptr_belem_t;
+                    NS(TriCubData_clear)( ( ptr_belem_t )( uintptr_t )obj_addr );
+                    break;
+                }
+
                 default: {} /* To satisfy compilers that complain if no
                                default section is available */
             };
@@ -1066,30 +1064,30 @@ SIXTRL_INLINE int NS(BeamElements_add_single_new_to_buffer)(
 
             case NS(OBJECT_TYPE_MULTIPOLE):
             {
-                typedef NS(MultiPole)                    mp_t;
+                typedef NS(Multipole)                    mp_t;
                 typedef NS(multipole_order_t)            mp_order_t;
                 typedef SIXTRL_BE_ARGPTR_DEC mp_t const* ptr_mp_t;
 
                 ptr_mp_t ptr_mp = ( ptr_mp_t )( uintptr_t )begin_addr;
-                mp_order_t const order = NS(MultiPole_get_order)( ptr_mp );
+                mp_order_t const order = NS(Multipole_order)( ptr_mp );
 
                 success = ( SIXTRL_NULLPTR !=
-                    NS(MultiPole_new)( buffer, order ) ) ? 0 : -1;
+                    NS(Multipole_new)( buffer, order ) ) ? 0 : -1;
 
                 break;
             }
 
             case NS(OBJECT_TYPE_RF_MULTIPOLE):
             {
-                typedef NS(RFMultiPole)                  mp_t;
+                typedef NS(RFMultipole)                  mp_t;
                 typedef NS(rf_multipole_int_t)           mp_order_t;
                 typedef SIXTRL_BE_ARGPTR_DEC mp_t const* ptr_mp_t;
 
                 ptr_mp_t ptr_mp = ( ptr_mp_t )( uintptr_t )begin_addr;
-                mp_order_t const order = NS(RFMultiPole_order)( ptr_mp );
+                mp_order_t const order = NS(RFMultipole_order)( ptr_mp );
 
                 success = ( SIXTRL_NULLPTR !=
-                    NS(RFMultiPole_new)( buffer, order ) ) ? 0 : -1;
+                    NS(RFMultipole_new)( buffer, order ) ) ? 0 : -1;
 
                 break;
             }
@@ -1122,78 +1120,40 @@ SIXTRL_INLINE int NS(BeamElements_add_single_new_to_buffer)(
 
             case NS(OBJECT_TYPE_BEAM_BEAM_4D):
             {
-                typedef NS(BeamBeam4D)                          beam_beam_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_beam_t const* ptr_beam_beam_t;
-
-                ptr_beam_beam_t ptr_beam_beam =
-                    ( ptr_beam_beam_t )( uintptr_t )begin_addr;
-
-                NS(buffer_size_t) const data_size =
-                    NS(BeamBeam4D_get_data_size)( ptr_beam_beam );
-
-                SIXTRL_ASSERT( ptr_beam_beam != SIXTRL_NULLPTR );
-
-                success = ( SIXTRL_NULLPTR !=
-                    NS(BeamBeam4D_new)( buffer, data_size ) );
-
+                success = ( SIXTRL_NULLPTR != NS(BeamBeam4D_new)(
+                    buffer, NS(BeamBeam4D_data_size)( ( SIXTRL_BE_ARGPTR_DEC
+                        NS(BeamBeam4D) const* )( uintptr_t )begin_addr ) ) );
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
             {
-                typedef NS(SpaceChargeCoasting) sc_coasting_t;
-                typedef SIXTRL_BE_ARGPTR_DEC sc_coasting_t const*
-                        ptr_sc_coasting_t;
-
-                ptr_sc_coasting_t ptr_sc_coasting =
-                    ( ptr_sc_coasting_t )( uintptr_t )begin_addr;
-
-                NS(buffer_size_t) const data_size =
-                    NS(SpaceChargeCoasting_get_data_size)( ptr_sc_coasting );
-
-                SIXTRL_ASSERT( ptr_sc_coasting != SIXTRL_NULLPTR );
+                success = ( SIXTRL_NULLPTR != NS(BeamBeam6D_new)(
+                    buffer, NS(BeamBeam6D_data_size)( ( SIXTRL_BE_ARGPTR_DEC
+                        NS(BeamBeam6D) const* )( uintptr_t )begin_addr ) ) );
+                break;
+            }
 
+            case NS(OBJECT_TYPE_SC_COASTING):
+            {
                 success = ( SIXTRL_NULLPTR !=
-                    NS(SpaceChargeCoasting_new)( buffer, data_size ) );
+                    NS(SCCoasting_new)( buffer ) );
 
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+            case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
             {
-                typedef NS(SpaceChargeBunched) sc_bunched_t;
-                typedef SIXTRL_BE_ARGPTR_DEC sc_bunched_t const*
-                        ptr_sc_bunched_t;
-
-                ptr_sc_bunched_t ptr_sc_bunched =
-                    ( ptr_sc_bunched_t )( uintptr_t )begin_addr;
-
-                NS(buffer_size_t) const data_size =
-                    NS(SpaceChargeBunched_get_data_size)( ptr_sc_bunched );
-
-                SIXTRL_ASSERT( ptr_sc_bunched != SIXTRL_NULLPTR );
-
                 success = ( SIXTRL_NULLPTR !=
-                    NS(SpaceChargeBunched_new)( buffer, data_size ) );
+                    NS(SCQGaussProfile_new)( buffer ) );
 
                 break;
             }
 
-            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+            case NS(OBJECT_TYPE_SC_INTERPOLATED_PROF):
             {
-                typedef NS(BeamBeam6D)                          beam_beam_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_beam_t const* ptr_beam_beam_t;
-
-                ptr_beam_beam_t ptr_beam_beam =
-                    ( ptr_beam_beam_t )( uintptr_t )begin_addr;
-
-                NS(buffer_size_t) const data_size =
-                    NS(BeamBeam6D_get_data_size)( ptr_beam_beam );
-
-                SIXTRL_ASSERT( ptr_beam_beam != SIXTRL_NULLPTR );
-
                 success = ( SIXTRL_NULLPTR !=
-                    NS(BeamBeam4D_new)( buffer, data_size ) );
+                    NS(SCInterpolatedProfile_new)( buffer ) );
 
                 break;
             }
@@ -1231,6 +1191,32 @@ SIXTRL_INLINE int NS(BeamElements_add_single_new_to_buffer)(
                 break;
             }
 
+            case NS(OBJECT_TYPE_TRICUB):
+            {
+                success = ( SIXTRL_NULLPTR != NS(TriCub_new)( buffer ) )
+                    ? 0 : -1;
+                break;
+            }
+
+            case NS(OBJECT_TYPE_TRICUB_DATA):
+            {
+                typedef NS(TriCubData) tricub_data_t;
+                typedef SIXTRL_BUFFER_DATAPTR_DEC
+                    tricub_data_t const* ptr_tricub_data_t;
+
+                ptr_tricub_data_t ptr_tricub = ( ptr_tricub_data_t )(
+                    uintptr_t )begin_addr;
+
+                NS(be_tricub_int_t) const nx = NS(TriCubData_nx)( ptr_tricub );
+                NS(be_tricub_int_t) const ny = NS(TriCubData_ny)( ptr_tricub );
+                NS(be_tricub_int_t) const nz = NS(TriCubData_nz)( ptr_tricub );
+
+                success = ( SIXTRL_NULLPTR !=
+                    NS(TriCubData_new)( buffer, nx, ny, nz ) ) ? 0 : -1;
+
+                break;
+            }
+
             default:
             {
                 success = -1;
@@ -1283,26 +1269,26 @@ SIXTRL_INLINE int NS(BeamElements_copy_single_to_buffer)(
 
             case NS(OBJECT_TYPE_MULTIPOLE):
             {
-                typedef NS(MultiPole)                    mp_t;
+                typedef NS(Multipole)                    mp_t;
                 typedef SIXTRL_BE_ARGPTR_DEC mp_t const* ptr_mp_t;
 
                 ptr_mp_t ptr_mp = ( ptr_mp_t )( uintptr_t )begin_addr;
 
                 success = ( SIXTRL_NULLPTR !=
-                    NS(MultiPole_add_copy)( buffer, ptr_mp ) ) ? 0 : -1;
+                    NS(Multipole_add_copy)( buffer, ptr_mp ) ) ? 0 : -1;
 
                 break;
             }
 
             case NS(OBJECT_TYPE_RF_MULTIPOLE):
             {
-                typedef NS(RFMultiPole) mp_t;
+                typedef NS(RFMultipole) mp_t;
                 typedef SIXTRL_BE_ARGPTR_DEC mp_t const* ptr_mp_t;
 
                 ptr_mp_t ptr_mp = ( ptr_mp_t )( uintptr_t )begin_addr;
 
                 success = ( SIXTRL_NULLPTR !=
-                    NS(RFMultiPole_add_copy)( buffer, ptr_mp ) ) ? 0 : -1;
+                    NS(RFMultipole_add_copy)( buffer, ptr_mp ) ) ? 0 : -1;
 
                 break;
             }
@@ -1350,20 +1336,25 @@ SIXTRL_INLINE int NS(BeamElements_copy_single_to_buffer)(
 
             case NS(OBJECT_TYPE_BEAM_BEAM_4D):
             {
-                typedef NS(BeamBeam4D)                          beam_beam_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_beam_t const* ptr_beam_beam_t;
+                success = ( SIXTRL_NULLPTR !=
+                    NS(BeamBeam4D_add_copy)( buffer, ( SIXTRL_BE_ARGPTR_DEC
+                        NS(BeamBeam4D) const* )( uintptr_t )begin_addr ) );
 
-                ptr_beam_beam_t orig = ( ptr_beam_beam_t )( uintptr_t )begin_addr;
+                break;
+            }
 
+            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+            {
                 success = ( SIXTRL_NULLPTR !=
-                    NS(BeamBeam4D_add_copy)( buffer, orig ) );
+                    NS(BeamBeam6D_add_copy)( buffer, ( SIXTRL_BE_ARGPTR_DEC
+                        NS(BeamBeam6D) const* )( uintptr_t )begin_addr ) );
 
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+            case NS(OBJECT_TYPE_SC_COASTING):
             {
-                typedef NS(SpaceChargeCoasting) sc_coasting_t;
+                typedef NS(SCCoasting) sc_coasting_t;
                 typedef SIXTRL_BE_ARGPTR_DEC sc_coasting_t const*
                         ptr_sc_coasting_t;
 
@@ -1371,14 +1362,14 @@ SIXTRL_INLINE int NS(BeamElements_copy_single_to_buffer)(
                     ( ptr_sc_coasting_t )( uintptr_t )begin_addr;
 
                 success = ( SIXTRL_NULLPTR !=
-                    NS(SpaceChargeCoasting_add_copy)( buffer, orig ) );
+                    NS(SCCoasting_add_copy)( buffer, orig ) );
 
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+            case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
             {
-                typedef NS(SpaceChargeBunched) sc_bunched_t;
+                typedef NS(SCQGaussProfile) sc_bunched_t;
                 typedef SIXTRL_BE_ARGPTR_DEC sc_bunched_t const*
                         ptr_sc_bunched_t;
 
@@ -1386,23 +1377,11 @@ SIXTRL_INLINE int NS(BeamElements_copy_single_to_buffer)(
                     ( ptr_sc_bunched_t )( uintptr_t )begin_addr;
 
                 success = ( SIXTRL_NULLPTR !=
-                    NS(SpaceChargeBunched_add_copy)( buffer, orig ) );
+                    NS(SCQGaussProfile_add_copy)( buffer, orig ) );
 
                 break;
             }
 
-            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
-            {
-                typedef NS(BeamBeam6D)                          beam_beam_t;
-                typedef SIXTRL_BE_ARGPTR_DEC beam_beam_t const* ptr_beam_beam_t;
-
-                ptr_beam_beam_t orig = ( ptr_beam_beam_t )( uintptr_t )begin_addr;
-
-                success = ( SIXTRL_NULLPTR !=
-                    NS(BeamBeam6D_add_copy)( buffer, orig ) );
-                break;
-            }
-
             #endif /* !defined( SIXTRL_DISABLE_BEAM_BEAM ) */
 
             case NS(OBJECT_TYPE_BEAM_MONITOR):
@@ -1470,6 +1449,32 @@ SIXTRL_INLINE int NS(BeamElements_copy_single_to_buffer)(
                 break;
             }
 
+            case NS(OBJECT_TYPE_TRICUB):
+            {
+                typedef  NS(TriCub) beam_element_t;
+                typedef  SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
+
+                ptr_belem_t orig = ( ptr_belem_t )( uintptr_t )begin_addr;
+
+                success = ( SIXTRL_NULLPTR !=
+                    NS(TriCub_add_copy)( buffer, orig ) ) ? 0 : -1;
+
+                break;
+            }
+
+            case NS(OBJECT_TYPE_TRICUB_DATA):
+            {
+                typedef  NS(TriCubData) beam_element_t;
+                typedef  SIXTRL_BE_ARGPTR_DEC beam_element_t const* ptr_belem_t;
+
+                ptr_belem_t orig = ( ptr_belem_t )( uintptr_t )begin_addr;
+
+                success = ( SIXTRL_NULLPTR !=
+                    NS(TriCubData_add_copy)( buffer, orig ) ) ? 0 : -1;
+
+                break;
+            }
+
             default:
             {
                 success = -1;
diff --git a/sixtracklib/common/buffer.h b/sixtracklib/common/buffer.h
index 711716db..c6641e40 100644
--- a/sixtracklib/common/buffer.h
+++ b/sixtracklib/common/buffer.h
@@ -11,6 +11,7 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/generated/modules.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
@@ -444,6 +445,22 @@ SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
     SIXTRL_ARGPTR_DEC NS(buffer_size_t) const* SIXTRL_RESTRICT sizes,
     SIXTRL_ARGPTR_DEC NS(buffer_size_t) const* SIXTRL_RESTRICT counts );
 
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Buffer_can_add_trivial_object)(
+        SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const  SIXTRL_RESTRICT buffer,
+        NS(buffer_size_t) const object_size,
+        SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_num_objects,
+        SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_num_slots );
+
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+    NS(Buffer_add_trivial_object)(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+        SIXTRL_ARGPTR_DEC const void *const SIXTRL_RESTRICT object_handle,
+        NS(buffer_size_t) const object_size,
+        NS(object_type_id_t) const type_id );
+
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
@@ -1467,6 +1484,17 @@ SIXTRL_INLINE bool NS(Buffer_can_add_object)(
     return success;
 }
 
+SIXTRL_INLINE bool NS(Buffer_can_add_trivial_object)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const  SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const object_size,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_num_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_num_slots )
+{
+    return NS(Buffer_can_add_object)( buffer, object_size,
+        ( NS(buffer_size_t) )0u, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+            requ_num_objects, requ_num_slots, SIXTRL_NULLPTR );
+}
+
 SIXTRL_INLINE SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
 NS(Buffer_add_object)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
@@ -1520,6 +1548,18 @@ NS(Buffer_add_object)(
     return ptr_added_object;
 }
 
+SIXTRL_INLINE SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+NS(Buffer_add_trivial_object)(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+        SIXTRL_ARGPTR_DEC const void *const SIXTRL_RESTRICT object_handle,
+        NS(buffer_size_t) const object_size,
+        NS(object_type_id_t) const type_id )
+{
+    return NS(Buffer_add_object)( buffer, object_handle, object_size, type_id,
+        ( NS(buffer_size_t) )0u, SIXTRL_NULLPTR, SIXTRL_NULLPTR,
+            SIXTRL_NULLPTR );
+}
+
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
diff --git a/sixtracklib/common/buffer.hpp b/sixtracklib/common/buffer.hpp
index 783e80a1..75e9d360 100644
--- a/sixtracklib/common/buffer.hpp
+++ b/sixtracklib/common/buffer.hpp
@@ -8,10 +8,11 @@
         #include <cstdint>
         #include <cstdlib>
         #include <cstdio>
-        #include <stdexcept>
         #include <limits>
-        #include <utility>
+        #include <memory>
+        #include <stdexcept>
         #include <string>
+        #include <utility>
     #endif /* defined( __cplusplus ) */
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
 
@@ -45,6 +46,15 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST flags_t
             DEFAULT_DATASTORE_FLAGS = ::NS(BUFFER_DATASTORE_MEMPOOL);
 
+        #if !defined( _GPUCODE )
+
+        SIXTRL_STATIC std::unique_ptr< Buffer >
+        MAKE_FROM_CBUFFER_AND_TAKE_OWNERSHIP(
+            ::NS(Buffer)* SIXTRL_RESTRICT ptr_to_take_ownership,
+            bool const delete_ptr_after_move = true );
+
+        #endif /* !defined( _GPUCODE ) */
+
         SIXTRL_FN SIXTRL_STATIC size_type CalculateBufferSize(
             size_type max_num_objects, size_type max_num_slots,
             size_type max_num_dataptrs, size_type max_num_garbage_ranges,
@@ -103,6 +113,22 @@ namespace SIXTRL_CXX_NAMESPACE
 
         SIXTRL_FN virtual ~Buffer();
 
+        friend void swap( Buffer& SIXTRL_RESTRICT_REF lhs,
+                          Buffer& SIXTRL_RESTRICT_REF rhs ) SIXTRL_NOEXCEPT
+        {
+            using std::swap;
+
+            swap( lhs.data_addr,       rhs.data_addr       );
+            swap( lhs.data_size,       rhs.data_size       );
+            swap( lhs.header_size,     rhs.header_size     );
+            swap( lhs.data_capacity,   rhs.data_capacity   );
+            swap( lhs.slot_length,     rhs.slot_length     );
+            swap( lhs.object_addr,     rhs.object_addr     );
+            swap( lhs.num_objects,     rhs.num_objects     );
+            swap( lhs.datastore_flags, rhs.datastore_flags );
+            swap( lhs.datastore_addr,  rhs.datastore_addr  );
+        }
+
         /* ----------------------------------------------------------------- */
 
         #if !defined( _GPUCODE )
@@ -240,13 +266,13 @@ namespace SIXTRL_CXX_NAMESPACE
         get( size_type const object_index ) SIXTRL_NOEXCEPT;
 
         /* ----------------------------------------------------------------- */
-        
+
         SIXTRL_FN bool reset(
             size_type const max_num_objects = size_type{ 0 },
             size_type const max_num_slots = size_type{ 0 },
             size_type const max_num_dataptrs = size_type{ 0 },
             size_type const max_num_garbage_ranges = size_type{ 0 } );
-        
+
         /* ----------------------------------------------------------------- */
 
         SIXTRL_FN bool needsRemapping() const SIXTRL_NOEXCEPT;
@@ -288,7 +314,7 @@ namespace SIXTRL_CXX_NAMESPACE
             return T::AddToBuffer(
                 *this->getCApiPtr(), std::forward< Args >( args )... );
         }
-        
+
         template< class T >
         SIXTRL_FN T* addCopy( T const& SIXTRL_RESTRICT_REF other )
         {
@@ -341,6 +367,42 @@ namespace SIXTRL_CXX_NAMESPACE
 
 namespace SIXTRL_CXX_NAMESPACE
 {
+    #if !defined( _GPUCODE )
+
+    SIXTRL_INLINE std::unique_ptr< Buffer >
+    Buffer::MAKE_FROM_CBUFFER_AND_TAKE_OWNERSHIP(
+            ::NS(Buffer)* SIXTRL_RESTRICT ptr_to_take_ownership,
+            bool const delete_ptr_after_move )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        std::unique_ptr< st::Buffer > ptr_cxx_buffer( nullptr );
+
+        if( ptr_to_take_ownership != nullptr )
+        {
+            using  size_t = st::Buffer::size_type;
+            using ptr_to_raw_t = SIXTRL_ARGPTR_DEC unsigned char*;
+
+            ptr_cxx_buffer.reset( new st::Buffer(
+                ptr_to_raw_t{ nullptr }, size_t{ 0u } ) );
+            SIXTRL_ASSERT( ptr_cxx_buffer.get() != nullptr );
+
+            ::NS(Buffer)* ptr_c_buffer = ptr_cxx_buffer->getCApiPtr();
+            SIXTRL_ASSERT( ptr_c_buffer != nullptr );
+
+            *ptr_c_buffer = *ptr_to_take_ownership;
+            ::NS(Buffer_preset)( ptr_to_take_ownership );
+
+            if( delete_ptr_after_move )
+            {
+                ::NS(Buffer_delete)( ptr_to_take_ownership );
+            }
+        }
+
+        return ptr_cxx_buffer;
+    }
+
+    #endif /* !defined( _GPUCODE ) */
+
     SIXTRL_INLINE Buffer::size_type Buffer::CalculateBufferSize(
         Buffer::size_type const max_num_objects,
         Buffer::size_type const max_num_slots,
@@ -413,14 +475,20 @@ namespace SIXTRL_CXX_NAMESPACE
         ::NS(Buffer)()
     {
         using c_api_t       = Buffer::c_api_t;
+        using size_t        = Buffer::size_type;
         using ptr_to_raw_t  = SIXTRL_ARGPTR_DEC unsigned char*;
 
         c_api_t* _buffer = ::NS(Buffer_preset)( this->getCApiPtr() );
+        ptr_to_raw_t _data_begin = reinterpret_cast< ptr_to_raw_t >(
+            data_buffer_begin );
 
-        if( 0 != ::NS(Buffer_init)( _buffer, reinterpret_cast< ptr_to_raw_t >(
-            data_buffer_begin ), max_buffer_size ) )
+        if( ( _data_begin != nullptr ) || ( max_buffer_size > size_t{ 0 } ) )
         {
-            ::NS(Buffer_free)( _buffer );
+            if( 0 != ::NS(Buffer_init)(
+                    _buffer, _data_begin, max_buffer_size ) )
+            {
+                ::NS(Buffer_free)( _buffer );
+            }
         }
     }
 
@@ -1096,7 +1164,7 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
     /* ----------------------------------------------------------------- */
-    
+
     SIXTRL_INLINE bool Buffer::reset(
             Buffer::size_type const max_num_objects,
             Buffer::size_type const max_num_slots,
@@ -1104,10 +1172,10 @@ namespace SIXTRL_CXX_NAMESPACE
             Buffer::size_type const max_num_garbage_ranges  )
     {
         return ( ::NS(Buffer_reset_detailed)( this->getCApiPtr(),
-            max_num_objects, max_num_slots, max_num_dataptrs, 
+            max_num_objects, max_num_slots, max_num_dataptrs,
                 max_num_garbage_ranges ) == 0 );
     }
-    
+
     /* ----------------------------------------------------------------- */
 
     SIXTRL_INLINE bool Buffer::needsRemapping() const SIXTRL_NOEXCEPT
diff --git a/sixtracklib/common/buffer/CMakeLists.txt b/sixtracklib/common/buffer/CMakeLists.txt
index 67552f69..5b9dd6bf 100644
--- a/sixtracklib/common/buffer/CMakeLists.txt
+++ b/sixtracklib/common/buffer/CMakeLists.txt
@@ -1,5 +1,11 @@
+set( SIXTRL_COMMON_BUFFER_CXX_HEADERS
+     assign_address_item.hpp )
+
+# -----------------------------------------------------------------------------
+
 set( SIXTRL_COMMON_BUFFER_HEADERS
      alignment.h
+     assign_address_item.h
      buffer_dev_debug.h
      buffer_garbage.h
      buffer_generic.h
@@ -16,6 +22,7 @@ set( SIXTRL_COMMON_BUFFER_HEADERS
 
 set( SIXTRL_COMMON_BUFFER_SOURCES
      alignment.c
+     assign_address_item.c
      buffer.c
      mem_pool.c
      managed_buffer_handle.c
@@ -24,38 +31,37 @@ set( SIXTRL_COMMON_BUFFER_SOURCES
 )
 
 add_library( sixtrack_common_buffer OBJECT
-    ${SIXTRL_COMMON_BUFFER_HEADERS}
-    ${SIXTRL_COMMON_BUFFER_SOURCES}
-)
+    ${SIXTRL_COMMON_BUFFER_HEADERS} ${SIXTRL_COMMON_BUFFER_SOURCES} )
 
 target_include_directories( sixtrack_common_buffer PRIVATE
     $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
     $<INSTALL_INTERFACE:include> )
 
-set_target_properties( sixtrack_common_buffer PROPERTIES LINKER_LANGUAGE C )
-set_target_properties( sixtrack_common_buffer PROPERTIES POSITION_INDEPENDENT_CODE ON )
-set_target_properties( sixtrack_common_buffer PROPERTIES C_STANDARD 99 )
-set_target_properties( sixtrack_common_buffer PROPERTIES C_STANDARD_REQUIRED ON )
+set_target_properties( sixtrack_common_buffer PROPERTIES LINKER_LANGUAGE C
+    POSITION_INDEPENDENT_CODE ON C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_buffer PRIVATE
-                        -Wall -Werror -pedantic -ansi
-                        ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_buffer as a module for sixtracklib:
 
-set(  SIXTRACKL_LIBRARY_MODULES
-    ${SIXTRACKL_LIBRARY_MODULES}
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
     $<TARGET_OBJECTS:sixtrack_common_buffer> CACHE INTERNAL "" FORCE )
 
 # -----------------------------------------------------------------------------
 # install :
 
-set( SIXTRACKLIB_COMMON_BUFFER_C99_INSTALL_PATH
-     include/sixtracklib/common/buffer )
+if( SIXTRL_COMMON_BUFFER_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BUFFER_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/buffer" )
+endif()
 
-install( FILES ${SIXTRL_COMMON_BUFFER_HEADERS}
-         DESTINATION ${SIXTRACKLIB_COMMON_BUFFER_C99_INSTALL_PATH} )
+if( SIXTRACKL_ENABLE_CXX AND SIXTRL_COMMON_BUFFER_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_BUFFER_CXX_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/buffer" )
+endif()
 
 #end: sixtracklib/common/buffer/CMakeLists.txt
 
diff --git a/sixtracklib/common/buffer/assign_address_item.c b/sixtracklib/common/buffer/assign_address_item.c
new file mode 100644
index 00000000..da115da4
--- /dev/null
+++ b/sixtracklib/common/buffer/assign_address_item.c
@@ -0,0 +1,217 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <string.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
+    #include "sixtracklib/common/buffer/assign_address_item_kernel_impl.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+NS(arch_status_t) NS(AssignAddressItem_next_buffer_id)( void )
+{
+    static NS(arch_size_t) next_buffer_id =
+        ( NS(arch_size_t) )SIXTRL_ARCH_MIN_USER_DEFINED_BUFFER_ID;
+
+    return ( next_buffer_id < NS(ARCH_MAX_USER_DEFINED_BUFFER_ID) )
+        ? next_buffer_id++ : NS(ARCH_ILLEGAL_BUFFER_ID);
+}
+
+NS(arch_status_t) NS(AssignAddressItem_perform_assignment)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT dest_buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer)
+        *const SIXTRL_RESTRICT src_buffer )
+{
+    return NS(AssignAddressItem_perform_assignment_on_managed_buffer)( item,
+        NS(Buffer_get_data_begin)( dest_buffer ),
+        NS(Buffer_get_slot_size)( dest_buffer ),
+        NS(Buffer_get_const_data_begin)( src_buffer ),
+        NS(Buffer_get_slot_size)( src_buffer ) );
+}
+
+NS(arch_status_t) NS(AssignAddressItem_assign_fixed_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_addr_t) const src_address )
+{
+    return NS(AssignAddressItem_assign_fixed_addr_on_managed_buffer)( item,
+        NS(Buffer_get_data_begin)( dest_buffer ),
+        NS(Buffer_get_slot_size)( dest_buffer ), src_address );
+}
+
+NS(arch_status_t) NS(AssignAddressItem_remap_assignment)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_addr_diff_t) const remap_offset )
+{
+    return NS(AssignAddressItem_remap_assignment_on_managed_buffer)( item,
+        NS(Buffer_get_data_begin)( dest_buffer ),
+        NS(Buffer_get_slot_size)( dest_buffer ), remap_offset );
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)*
+NS(AssignAddressItem_dest_pointer_from_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    return NS(AssignAddressItem_dest_pointer_from_managed_buffer)(
+        item, NS(Buffer_get_data_begin)( buffer ),
+            NS(Buffer_get_slot_size)( buffer ) );
+}
+
+NS(buffer_addr_t) NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer )
+{
+    return NS(AssignAddressItem_src_pointer_addr_from_managed_buffer)(
+        item, NS(Buffer_get_const_data_begin)( buffer ),
+            NS(Buffer_get_slot_size)( buffer ) );
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+NS(AssignAddressItem_const_from_buffer)(
+    SIXTRL_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index )
+{
+    return NS(AssignAddressItem_const_from_obj_index)(
+        NS(Buffer_get_const_object)( buffer, index ) );
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_from_buffer)(
+    SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index )
+{
+    return NS(AssignAddressItem_from_obj_index)( NS(Buffer_get_object)(
+        buffer, index ) );
+}
+
+/* ------------------------------------------------------------------------- */
+
+bool NS(AssignAddressItem_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs )
+{
+    ( void )ptr_requ_dataptrs;
+
+    return NS(Buffer_can_add_trivial_object)( buffer,
+        sizeof( NS(AssignAddressItem) ), ptr_requ_objects, ptr_requ_slots );
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* NS(AssignAddressItem_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
+{
+    NS(AssignAddressItem) item;
+    NS(AssignAddressItem_preset)( &item );
+
+    SIXTRL_ASSERT( ( NS(buffer_size_t) )0u ==
+        NS(AssignAddressItem_num_dataptrs)( &item ) );
+
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_trivial_object)( buffer,
+            &item, sizeof( item ), NS(AssignAddressItem_type_id)( &item ) ) );
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* NS(AssignAddressItem_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(object_type_id_t) const dest_elem_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_elem_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset )
+{
+    NS(AssignAddressItem) item;
+    NS(AssignAddressItem_preset)( &item );
+    NS(AssignAddressItem_set_dest_elem_type_id)( &item, dest_elem_type_id );
+    NS(AssignAddressItem_set_dest_buffer_id)( &item, dest_buffer_id );
+    NS(AssignAddressItem_set_dest_elem_index)( &item, dest_elem_index );
+    NS(AssignAddressItem_set_dest_pointer_offset)( &item, dest_pointer_offset );
+    NS(AssignAddressItem_set_src_elem_type_id)( &item, src_elem_type_id );
+    NS(AssignAddressItem_set_src_buffer_id)( &item, src_buffer_id );
+    NS(AssignAddressItem_set_src_elem_index)( &item, src_elem_index );
+    NS(AssignAddressItem_set_src_pointer_offset)( &item, src_pointer_offset );
+
+    SIXTRL_ASSERT( ( NS(buffer_size_t) )0u ==
+        NS(AssignAddressItem_num_dataptrs)( &item ) );
+
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_trivial_object)( buffer,
+            &item, sizeof( item ), NS(AssignAddressItem_type_id)( &item ) ) );
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* NS(AssignAddressItem_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC const NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    SIXTRL_ASSERT( ( NS(buffer_size_t) )0u ==
+        NS(AssignAddressItem_num_dataptrs)( item ) );
+
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* )( uintptr_t
+        )NS(Object_get_begin_addr)( NS(Buffer_add_trivial_object)( buffer,
+            item, sizeof( NS(AssignAddressItem) ),
+                NS(AssignAddressItem_type_id)( item ) ) );
+}
+
+/* ------------------------------------------------------------------------- */
+
+bool NS(AssignAddressItem_compare_less_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    return NS(AssignAddressItem_compare_less)( lhs, rhs );
+}
+
+bool NS(AssignAddressItem_are_equal_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    return NS(AssignAddressItem_are_equal)( lhs, rhs );
+}
+
+bool NS(AssignAddressItem_are_not_equal_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    return NS(AssignAddressItem_are_not_equal)( lhs, rhs );
+}
+
+bool NS(AssignAddressItem_dest_src_are_equal_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    return NS(AssignAddressItem_dest_src_are_equal)( lhs, rhs );
+}
+
+bool NS(AssignAddressItem_dest_src_are_not_equal_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    return NS(AssignAddressItem_dest_src_are_not_equal)( lhs, rhs );
+}
+
+/* end: sixtracklib/common/buffer/assign_address_item.c */
diff --git a/sixtracklib/common/buffer/assign_address_item.h b/sixtracklib/common/buffer/assign_address_item.h
new file mode 100644
index 00000000..95264e2d
--- /dev/null
+++ b/sixtracklib/common/buffer/assign_address_item.h
@@ -0,0 +1,1208 @@
+#ifndef SIXTRACKLIB_COMMON_BUFFER_ADDR_ASSIGNMENT_C99_H__
+#define SIXTRACKLIB_COMMON_BUFFER_ADDR_ASSIGNMENT_C99_H__
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/internal/objects_type_id.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+#if !defined( SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID )
+    #define SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID 0xffffffffffffffff
+#endif /* !defined( SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID ) */
+
+#if !defined( _GPUCODE )
+    SIXTRL_STATIC_VAR const NS(buffer_size_t)
+    NS(ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID) =
+        ( NS(buffer_size_t) )SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID;
+#endif /* !defined( _GPUCODE ) */
+
+typedef struct NS(AssignAddressItemDestSrcPair)
+{
+    NS(buffer_size_t) dest_buffer_id;
+    NS(buffer_size_t) src_buffer_id;
+}
+NS(AssignAddressItemDestSrcPair);
+
+typedef struct NS(AssignAddressItem)
+{
+    NS(buffer_size_t)    dest_buffer_id        SIXTRL_ALIGN( 8 );
+    NS(buffer_size_t)    src_buffer_id         SIXTRL_ALIGN( 8 );
+    NS(object_type_id_t) dest_elem_type_id     SIXTRL_ALIGN( 8 );
+    NS(object_type_id_t) src_elem_type_id      SIXTRL_ALIGN( 8 );
+    NS(buffer_size_t)    dest_elem_index       SIXTRL_ALIGN( 8 );
+    NS(buffer_size_t)    src_elem_index        SIXTRL_ALIGN( 8 );
+    NS(buffer_size_t)    dest_pointer_offset   SIXTRL_ALIGN( 8 );
+    NS(buffer_size_t)    src_pointer_offset    SIXTRL_ALIGN( 8 );
+}
+NS(AssignAddressItem);
+
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t)
+NS(AssignAddressItem_type_id)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(AssignAddressItem_num_dataptrs)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(AssignAddressItem_num_slots)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const slot_size );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_preset)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(AssignAddressItem)* SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_clear)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(AssignAddressItem_valid)(
+    SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t)
+NS(AssignAddressItem_dest_elem_type_id)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(AssignAddressItem_dest_buffer_id)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(AssignAddressItem_dest_elem_index)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(AssignAddressItem_dest_pointer_offset)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t)
+NS(AssignAddressItem_src_elem_type_id)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(AssignAddressItem_src_buffer_id)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(AssignAddressItem_src_elem_index)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(AssignAddressItem_src_pointer_offset)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_set_dest_elem_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(object_type_id_t) const type_id );
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_set_dest_buffer_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const dest_buffer_id );
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_set_dest_elem_index)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const dest_elem_index );
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_set_dest_pointer_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const dest_pointer_offset );
+
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_set_src_elem_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(object_type_id_t) const type_id );
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_set_src_buffer_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const src_buffer_id );
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_set_src_elem_index)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const src_elem_index );
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_set_src_pointer_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const src_pointer_offset );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+NS(AssignAddressItem_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_from_obj_index)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    NS(Object)* SIXTRL_RESTRICT obj );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+NS(AssignAddressItem_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
+    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
+    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN bool  NS(AssignAddressItem_dest_is_on_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN bool  NS(AssignAddressItem_dest_is_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN bool  NS(AssignAddressItem_src_is_on_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN bool  NS(AssignAddressItem_src_is_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(AssignAddressItem_is_on_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(AssignAddressItem_is_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)*
+NS(AssignAddressItem_dest_pointer_from_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char*
+        SIXTRL_RESTRICT dest_buffer_begin );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)*
+NS(AssignAddressItem_dest_pointer_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer_begin,
+    NS(buffer_size_t) const dest_slot_size );
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(AssignAddressItem_src_pointer_addr_from_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const*
+        SIXTRL_RESTRICT src_buffer_begin );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(AssignAddressItem_src_pointer_addr_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const*
+        SIXTRL_RESTRICT src_buffer_begin,
+    NS(buffer_size_t) const src_slot_size );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(AssignAddressItem_perform_assignment_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char*
+        SIXTRL_RESTRICT dest_buffer_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char
+        const* SIXTRL_RESTRICT src_buffer_begin );
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(AssignAddressItem_perform_assignment_on_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer_begin,
+    NS(buffer_size_t) const dest_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const*
+        SIXTRL_RESTRICT src_buffer_begin,
+    NS(buffer_size_t) const src_slot_size );
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(AssignAddressItem_assign_fixed_addr_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char*
+        SIXTRL_RESTRICT dest_buffer_begin,
+    NS(buffer_addr_t) const src_address );
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(AssignAddressItem_assign_fixed_addr_on_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* dest_buffer_begin,
+    NS(buffer_size_t) const dest_slot_size,
+    NS(buffer_addr_t) const src_address );
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(AssignAddressItem_remap_assignment_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* dest_buffer_begin,
+    NS(buffer_addr_diff_t) const remap_offset );
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(AssignAddressItem_remap_assignment_on_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* dest_buffer_begin,
+    NS(buffer_size_t) const dest_slot_size,
+    NS(buffer_addr_diff_t) const remap_offset );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN bool NS(AssignAddressItem_compare_less)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(AssignAddressItem_are_equal)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(AssignAddressItem_are_not_equal)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(AssignAddressItem_dest_src_are_equal)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(AssignAddressItem_dest_src_are_not_equal)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(AssignAddressItem_next_buffer_id)( void );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(AssignAddressItem_perform_assignment)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT dest_buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer)
+        *const SIXTRL_RESTRICT src_buffer );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(AssignAddressItem_assign_fixed_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_addr_t) const src_address );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(AssignAddressItem_remap_assignment)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_addr_diff_t) const remap_offset );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)*
+NS(AssignAddressItem_dest_pointer_from_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_addr_t)
+NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN
+SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+NS(AssignAddressItem_const_from_buffer)(
+    SIXTRL_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_from_buffer)(
+    SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const index );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(AssignAddressItem_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_objects,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_slots,
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT ptr_requ_dataptrs );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(object_type_id_t) const dest_elem_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_elem_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_ARGPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(AssignAddressItem_assign_all_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* assign_item_buffer,
+    NS(buffer_size_t) const assign_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* dest_buffer,
+    NS(buffer_size_t) const dest_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* src_buffer,
+    NS(buffer_size_t) const src_slot_size );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(AssignAddressItem_compare_less_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(AssignAddressItem_are_equal_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(AssignAddressItem_are_not_equal_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(AssignAddressItem_dest_src_are_equal_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool
+NS(AssignAddressItem_dest_src_are_not_equal_ext)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs );
+
+#endif /* defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(AssignAddressItem_copy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT source );
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* ************************************************************************* */
+/* *****          Implementation of C inline functions                   *** */
+/* ************************************************************************* */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/buffer/managed_buffer_remap.h"
+    #include "sixtracklib/common/internal/objects_type_id.h"
+    #if !defined( _GPUCODE )
+        #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE NS(object_type_id_t) NS(AssignAddressItem_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    ( void )item;
+    return NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM);
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(AssignAddressItem_num_dataptrs)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    ( void )item;
+    return ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(AssignAddressItem_num_slots)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const slot_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    buf_size_t extent = NS(ManagedBuffer_get_slot_based_length)(
+        sizeof( NS(AssignAddressItem) ), slot_size );
+
+    ( void )item;
+    SIXTRL_ASSERT( ( slot_size == ZERO ) || ( ( extent % slot_size ) == ZERO ) );
+    return ( slot_size > ZERO ) ? ( extent / slot_size ) : ( ZERO );
+
+}
+
+SIXTRL_INLINE SIXTRL_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_preset)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(AssignAddressItem)* SIXTRL_RESTRICT item )
+{
+    if( item != SIXTRL_NULLPTR )
+    {
+        item->dest_elem_type_id = NS(OBJECT_TYPE_NONE);
+        item->dest_buffer_id    = SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID;
+
+        item->src_elem_type_id  = NS(OBJECT_TYPE_NONE);
+        item->src_buffer_id     = SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID;
+
+        NS(AssignAddressItem_clear)( item );
+    }
+
+    return item;
+}
+
+SIXTRL_INLINE void NS(AssignAddressItem_clear)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item )
+{
+    SIXTRL_ASSERT( item != SIXTRL_NULLPTR );
+
+    item->dest_elem_index     = ( NS(buffer_size_t) )0u;
+    item->dest_pointer_offset = ( NS(buffer_size_t) )0u;
+    item->src_elem_index      = ( NS(buffer_size_t) )0u;
+    item->src_pointer_offset  = ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_valid)( SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    return ( ( item != SIXTRL_NULLPTR ) &&
+             ( ( NS(AssignAddressItem_dest_is_on_buffer)( item ) ) ||
+               ( NS(AssignAddressItem_dest_is_on_raw_memory)( item ) ) ) &&
+             ( ( NS(AssignAddressItem_src_is_on_buffer)( item ) ) ||
+               ( NS(AssignAddressItem_src_is_on_raw_memory)( item ) ) ) );
+}
+
+SIXTRL_INLINE NS(object_type_id_t) NS(AssignAddressItem_dest_elem_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item )
+{
+    return ( item != SIXTRL_NULLPTR )
+        ? item->dest_elem_type_id : NS(OBJECT_TYPE_NONE);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(AssignAddressItem_dest_buffer_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item )
+{
+    return ( item != SIXTRL_NULLPTR )
+        ? item->dest_buffer_id : SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID;
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(AssignAddressItem_dest_elem_index)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    return ( item != SIXTRL_NULLPTR )
+        ? item->dest_elem_index : ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(AssignAddressItem_dest_pointer_offset)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    return ( item != SIXTRL_NULLPTR )
+        ? item->dest_pointer_offset : ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(object_type_id_t) NS(AssignAddressItem_src_elem_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item )
+{
+    return ( item != SIXTRL_NULLPTR )
+        ? item->src_elem_type_id : NS(OBJECT_TYPE_NONE);
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(AssignAddressItem_src_buffer_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item )
+{
+    return ( item != SIXTRL_NULLPTR )
+        ? item->src_buffer_id : SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID;
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(AssignAddressItem_src_elem_index)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    return ( item != SIXTRL_NULLPTR )
+        ? item->src_elem_index : ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(AssignAddressItem_src_pointer_offset)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    return ( item != SIXTRL_NULLPTR )
+        ? item->src_pointer_offset : ( NS(buffer_size_t) )0u;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE void NS(AssignAddressItem_set_dest_elem_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(object_type_id_t) const type_id )
+{
+    if( item != SIXTRL_NULLPTR ) item->dest_elem_type_id = type_id;
+}
+
+SIXTRL_INLINE void NS(AssignAddressItem_set_dest_buffer_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const dest_buffer_id )
+{
+    if( item != SIXTRL_NULLPTR ) item->dest_buffer_id = dest_buffer_id;
+}
+
+SIXTRL_INLINE void NS(AssignAddressItem_set_dest_elem_index)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const dest_elem_index )
+{
+    if( item != SIXTRL_NULLPTR ) item->dest_elem_index = dest_elem_index;
+}
+
+SIXTRL_INLINE void NS(AssignAddressItem_set_dest_pointer_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const dest_pointer_offset )
+{
+    if( item != SIXTRL_NULLPTR )
+        item->dest_pointer_offset = dest_pointer_offset;
+}
+
+SIXTRL_INLINE void NS(AssignAddressItem_set_src_elem_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(object_type_id_t) const type_id )
+{
+    if( item != SIXTRL_NULLPTR ) item->src_elem_type_id = type_id;
+}
+
+SIXTRL_INLINE void NS(AssignAddressItem_set_src_buffer_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const src_buffer_id )
+{
+    if( item != SIXTRL_NULLPTR ) item->src_buffer_id = src_buffer_id;
+}
+
+SIXTRL_INLINE void NS(AssignAddressItem_set_src_elem_index)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const src_elem_index )
+{
+    if( item != SIXTRL_NULLPTR ) item->src_elem_index = src_elem_index;
+}
+
+SIXTRL_INLINE void NS(AssignAddressItem_set_src_pointer_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT item,
+    NS(buffer_size_t) const src_ptr_offset )
+{
+    if( item != SIXTRL_NULLPTR ) item->src_pointer_offset = src_ptr_offset;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(AssignAddressItem_perform_assignment_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const*
+        SIXTRL_RESTRICT src_buffer_begin )
+{
+    NS(buffer_addr_t) const src_address =
+        NS(AssignAddressItem_src_pointer_addr_from_raw_memory)(
+            item, src_buffer_begin );
+
+    return NS(AssignAddressItem_assign_fixed_addr_on_raw_memory)(
+        item, dest_buffer_begin, src_address );
+}
+
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(AssignAddressItem_perform_assignment_on_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer_begin,
+    NS(buffer_size_t) const dest_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const*
+        SIXTRL_RESTRICT src_buffer_begin,
+    NS(buffer_size_t) const src_slot_size )
+{
+    NS(buffer_addr_t) const src_address =
+    NS(AssignAddressItem_src_pointer_addr_from_managed_buffer)( item,
+        src_buffer_begin, src_slot_size );
+
+    return NS(AssignAddressItem_assign_fixed_addr_on_managed_buffer)(
+        item, dest_buffer_begin, dest_slot_size, src_address );
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(AssignAddressItem_assign_fixed_addr_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char*
+        SIXTRL_RESTRICT dest_buffer_begin,
+    NS(buffer_addr_t) const src_address )
+{
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)* dest_ptr =
+        NS(AssignAddressItem_dest_pointer_from_raw_memory)(
+            item, dest_buffer_begin );
+
+    if( dest_ptr != SIXTRL_NULLPTR )
+    {
+        *dest_ptr = src_address;
+        status = SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(AssignAddressItem_assign_fixed_addr_on_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(AssignAddressItem) *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* dest_buffer_begin,
+    NS(buffer_size_t) const dest_slot_size, NS(buffer_addr_t) const src_addr )
+{
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)* dest_ptr =
+        NS(AssignAddressItem_dest_pointer_from_managed_buffer)(
+            item, dest_buffer_begin, dest_slot_size );
+
+    if( dest_ptr != SIXTRL_NULLPTR )
+    {
+        *dest_ptr = src_addr;
+        status = SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(AssignAddressItem_remap_assignment_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(AssignAddressItem) *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* dest_buffer_begin,
+    NS(buffer_addr_diff_t) const remap_offset )
+{
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)* dest_ptr =
+    NS(AssignAddressItem_dest_pointer_from_raw_memory)(
+        item, dest_buffer_begin );
+
+    if( ( dest_ptr != SIXTRL_NULLPTR ) &&
+        ( ( NS(ManagedBuffer_check_addr_arithmetic)(
+            *dest_ptr, remap_offset, ( NS(buffer_size_t) )1u ) ) ||
+          ( ( *dest_ptr == ( NS(buffer_addr_t) )0u ) &&
+            ( remap_offset > ( NS(buffer_addr_diff_t) )0u ) ) ) )
+    {
+        *dest_ptr += remap_offset;
+        status = SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+    else if( dest_ptr == SIXTRL_NULLPTR )
+    {
+        status = SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(AssignAddressItem_remap_assignment_on_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(AssignAddressItem) *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* dest_buffer_begin,
+    NS(buffer_size_t) const dest_slot_size,
+    NS(buffer_addr_diff_t) const remap_offset )
+{
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+    SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)* dest_ptr =
+    NS(AssignAddressItem_dest_pointer_from_managed_buffer)(
+        item, dest_buffer_begin, dest_slot_size );
+
+    if( ( NS(AssignAddressItem_dest_is_on_buffer)( item ) ) &&
+        ( dest_ptr != SIXTRL_NULLPTR ) &&
+        ( ( NS(ManagedBuffer_check_addr_arithmetic)(
+              *dest_ptr, remap_offset, dest_slot_size ) ) ||
+          ( *dest_ptr == ( NS(buffer_addr_t) )0u ) ) )
+    {
+        *dest_ptr += remap_offset;
+        status = SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_INLINE bool NS(AssignAddressItem_dest_is_on_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item )
+{
+    return ( ( item != SIXTRL_NULLPTR) &&
+             ( !NS(AssignAddressItem_dest_is_on_raw_memory)( item ) ) );
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_dest_is_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item )
+{
+    return ( ( item != SIXTRL_NULLPTR ) &&
+             ( NS(AssignAddressItem_dest_buffer_id)( item ) ==
+               SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID ) &&
+             ( NS(AssignAddressItem_dest_elem_index)( item ) ==
+               ( NS(buffer_size_t) )0u ) );
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_src_is_on_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item )
+{
+    return ( ( item != SIXTRL_NULLPTR ) &&
+             ( !NS(AssignAddressItem_src_is_on_raw_memory)( item ) ) );
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_src_is_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item )
+{
+    return ( ( item != SIXTRL_NULLPTR ) &&
+             ( NS(AssignAddressItem_src_buffer_id)( item ) ==
+               SIXTRL_ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID ) &&
+             ( NS(AssignAddressItem_src_elem_index)( item ) ==
+               ( NS(buffer_size_t) )0u ) );
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_is_on_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item )
+{
+    return ( ( NS(AssignAddressItem_dest_is_on_buffer)( item ) ) &&
+             ( NS(AssignAddressItem_src_is_on_buffer)( item ) ) );
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_is_on_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT item )
+{
+    return ( ( NS(AssignAddressItem_dest_is_on_raw_memory)( item ) ) &&
+             ( NS(AssignAddressItem_src_is_on_raw_memory)( item ) ) );
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+NS(AssignAddressItem_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const index_obj )
+{
+    typedef NS(AssignAddressItem) item_t;
+    typedef SIXTRL_BUFFER_OBJ_DATAPTR_DEC item_t const* ptr_to_item_t;
+    ptr_to_item_t ptr_to_item = SIXTRL_NULLPTR;
+
+    if( ( index_obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( index_obj ) ==
+          NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM) ) &&
+        ( NS(Object_get_size)( index_obj ) >= sizeof( item_t ) ) )
+    {
+        ptr_to_item = ( ptr_to_item_t )( uintptr_t
+            )NS(Object_get_begin_addr)( index_obj );
+    }
+
+    return ptr_to_item;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* index_obj )
+{
+    return ( SIXTRL_BUFFER_OBJ_DATAPTR_DEC NS(AssignAddressItem)*
+        )NS(AssignAddressItem_const_from_obj_index)( index_obj );
+}
+
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const*
+NS(AssignAddressItem_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
+    NS(buffer_size_t) const index, NS(buffer_size_t) const slot_size )
+{
+    return NS(AssignAddressItem_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)( pbuffer, index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)*
+NS(AssignAddressItem_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
+    NS(buffer_size_t) const be_index, NS(buffer_size_t) const slot_size )
+{
+    return NS(AssignAddressItem_from_obj_index)(
+        NS(ManagedBuffer_get_object)( pbuffer, be_index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)*
+NS(AssignAddressItem_dest_pointer_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer_begin,
+    NS(buffer_size_t) const dest_slot_size )
+{
+    typedef NS(buffer_addr_t) addr_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC addr_t* dest_ptr_t;
+
+    dest_ptr_t dest_ptr = SIXTRL_NULLPTR;
+
+    if( ( NS(AssignAddressItem_dest_is_on_buffer)( item ) ) &&
+        ( dest_buffer_begin != SIXTRL_NULLPTR ) &&
+        ( dest_slot_size > ( buf_size_t )0u ) )
+    {
+        SIXTRL_STATIC_VAR buf_size_t const ADDR_SIZE =
+            ( buf_size_t )sizeof( addr_t );
+
+        buf_size_t const elem_idx =
+            NS(AssignAddressItem_dest_elem_index)( item );
+
+        buf_size_t const ptr_offset =
+            NS(AssignAddressItem_dest_pointer_offset)( item );
+
+        SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* dest_obj = SIXTRL_NULLPTR;
+        addr_t obj_addr = ( addr_t )0u;
+        addr_t ptr_addr = ( addr_t )0u;
+
+        SIXTRL_ASSERT( !NS(AssignAddressItem_dest_is_on_raw_memory)( item ) );
+
+        SIXTRL_ASSERT( NS(AssignAddressItem_dest_elem_type_id)(
+            item ) != NS(OBJECT_TYPE_NONE) );
+
+        SIXTRL_ASSERT( dest_slot_size > ( buf_size_t )0u );
+        SIXTRL_ASSERT( !NS(ManagedBuffer_needs_remapping)(
+            dest_buffer_begin, dest_slot_size ) );
+
+        SIXTRL_ASSERT( NS(ManagedBuffer_get_num_objects)(
+            dest_buffer_begin, dest_slot_size ) > elem_idx );
+
+        dest_obj = NS(ManagedBuffer_get_object)(
+            dest_buffer_begin, elem_idx, dest_slot_size );
+
+        obj_addr = NS(Object_get_begin_addr)( dest_obj );
+        ptr_addr = obj_addr + ptr_offset;
+
+        if( ( dest_obj != SIXTRL_NULLPTR ) && ( obj_addr != ( addr_t )0u ) &&
+            ( ( ptr_addr % dest_slot_size ) == ( addr_t )0u ) &&
+            ( ( ptr_addr % ADDR_SIZE ) == ( addr_t )0u ) &&
+            ( NS(Object_get_size)( dest_obj ) >= ( ptr_offset + ADDR_SIZE ) ) &&
+            ( NS(Object_get_type_id)( dest_obj ) ==
+                NS(AssignAddressItem_dest_elem_type_id)( item ) ) )
+        {
+            dest_ptr = ( dest_ptr_t )( uintptr_t )ptr_addr;
+        }
+    }
+
+    return dest_ptr;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_addr_t)*
+NS(AssignAddressItem_dest_pointer_from_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer_begin )
+{
+    typedef NS(buffer_addr_t) addr_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC addr_t* dest_ptr_t;
+
+    dest_ptr_t dest_ptr = SIXTRL_NULLPTR;
+
+    if( ( NS(AssignAddressItem_dest_is_on_raw_memory)( item ) ) &&
+        ( dest_buffer_begin != SIXTRL_NULLPTR ) )
+    {
+        addr_t const obj_addr = ( addr_t )( uintptr_t )dest_buffer_begin;
+
+        buf_size_t const ptr_offset =
+            NS(AssignAddressItem_dest_pointer_offset)( item );
+
+        addr_t const ptr_addr = obj_addr + ptr_offset;
+        SIXTRL_ASSERT( obj_addr != ( addr_t )0u );
+        SIXTRL_ASSERT( ( ptr_addr % sizeof( addr_t ) ) == ( addr_t )0u );
+        SIXTRL_ASSERT( !NS(AssignAddressItem_dest_is_on_buffer)( item ) );
+        dest_ptr = ( dest_ptr_t )( uintptr_t )ptr_addr;
+    }
+
+    return dest_ptr;
+}
+
+SIXTRL_INLINE NS(buffer_addr_t)
+NS(AssignAddressItem_src_pointer_addr_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const*
+        SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const slot_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef NS(buffer_addr_t) addr_t;
+    typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* ptr_obj_t;
+
+    addr_t address = ( addr_t )0u;
+
+    if( ( NS(AssignAddressItem_src_is_on_buffer)( item ) ) &&
+        ( buffer_begin != SIXTRL_NULLPTR ) )
+    {
+        SIXTRL_STATIC_VAR buf_size_t const ADDR_SIZE =
+            ( buf_size_t )sizeof( addr_t );
+
+        buf_size_t const elem_idx =
+            NS(AssignAddressItem_src_elem_index)( item );
+
+        buf_size_t const ptr_offset =
+            NS(AssignAddressItem_src_pointer_offset)( item );
+
+        ptr_obj_t obj = SIXTRL_NULLPTR;
+        addr_t obj_addr = ( addr_t )0u;
+        addr_t ptr_addr = ( addr_t )0u;
+
+        SIXTRL_ASSERT( !NS(AssignAddressItem_src_is_on_raw_memory)( item ) );
+        SIXTRL_ASSERT( NS(AssignAddressItem_src_elem_type_id)( item ) !=
+            NS(OBJECT_TYPE_NONE) );
+
+        SIXTRL_ASSERT( slot_size > ( buf_size_t )0u );
+
+        SIXTRL_ASSERT( !NS(ManagedBuffer_needs_remapping)(
+            buffer_begin, slot_size ) );
+
+        SIXTRL_ASSERT( NS(ManagedBuffer_get_num_objects)(
+            buffer_begin, slot_size ) > elem_idx );
+
+        obj = NS(ManagedBuffer_get_const_object)(
+            buffer_begin, elem_idx, slot_size );
+
+        obj_addr = NS(Object_get_begin_addr)( obj );
+        ptr_addr = obj_addr + ptr_offset;
+
+        if( ( obj != SIXTRL_NULLPTR ) && ( obj_addr != ( addr_t )0u ) &&
+            ( ( ( ptr_addr ) % slot_size ) == ( addr_t )0u ) &&
+            ( ( ( ptr_addr ) % ADDR_SIZE ) == ( addr_t )0u ) &&
+            ( NS(Object_get_size)( obj ) >= ( ptr_offset + ADDR_SIZE ) ) &&
+            ( NS(Object_get_type_id)( obj ) ==
+              NS(AssignAddressItem_src_elem_type_id)( item ) ) )
+        {
+            address = ptr_addr;
+        }
+    }
+
+    return address;
+}
+
+SIXTRL_INLINE NS(buffer_addr_t)
+NS(AssignAddressItem_src_pointer_addr_from_raw_memory)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const*
+        SIXTRL_RESTRICT src_buffer_begin )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef NS(buffer_addr_t) addr_t;
+
+    addr_t src_addr = ( addr_t )0u;
+
+    if( ( NS(AssignAddressItem_src_is_on_raw_memory)( item ) ) &&
+        ( src_buffer_begin != SIXTRL_NULLPTR ) )
+    {
+        addr_t const src_obj_addr = ( addr_t )( uintptr_t )src_buffer_begin;
+        buf_size_t const src_ptr_offset =
+            NS(AssignAddressItem_src_pointer_offset)( item );
+
+        addr_t const src_ptr_addr = src_obj_addr + src_ptr_offset;
+        SIXTRL_ASSERT( !NS(AssignAddressItem_src_is_on_buffer)( item ) );
+
+        if( src_obj_addr != ( addr_t )0u ) src_addr = src_ptr_addr;
+    }
+
+    return src_addr;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(arch_status_t) NS(AssignAddressItem_copy)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem)* SIXTRL_RESTRICT dest,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT source )
+{
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    SIXTRL_ASSERT( ( NS(buffer_size_t) )0u ==
+        NS(AssignAddressItem_num_dataptrs)( dest ) );
+
+    SIXTRL_ASSERT( ( NS(buffer_size_t) )0u ==
+        NS(AssignAddressItem_num_dataptrs)( source ) );
+
+    if( ( dest != SIXTRL_NULLPTR ) && ( source != SIXTRL_NULLPTR ) &&
+        ( dest != source ) )
+    {
+        *dest = *source;
+        status = SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+    else if( ( dest != SIXTRL_NULLPTR ) && ( dest == source ) )
+    {
+        status = SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_compare_less)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    SIXTRL_ASSERT( lhs != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs != SIXTRL_NULLPTR );
+
+    bool is_equal_so_far = false;
+    bool is_smaller_than = ( lhs->dest_buffer_id < rhs->dest_buffer_id );
+
+    if( ( !is_smaller_than ) &&
+        ( lhs->dest_buffer_id == rhs->dest_buffer_id ) )
+    {
+        is_smaller_than = ( lhs->src_buffer_id < rhs->src_buffer_id );
+
+        if( ( !is_smaller_than ) &&
+            ( lhs->src_buffer_id == rhs->src_buffer_id ) )
+        {
+            is_smaller_than = (
+                lhs->dest_elem_type_id < rhs->dest_elem_type_id );
+
+            if( ( !is_smaller_than ) &&
+                ( lhs->dest_elem_type_id == rhs->dest_elem_type_id ) )
+            {
+                is_smaller_than = (
+                    lhs->src_elem_type_id < rhs->src_elem_type_id );
+
+                if( ( !is_smaller_than ) &&
+                    ( lhs->src_elem_type_id == rhs->src_elem_type_id ) )
+                {
+                    is_equal_so_far = true;
+                }
+            }
+        }
+    }
+
+    if( ( !is_smaller_than ) && ( is_equal_so_far ) )
+    {
+        is_smaller_than = ( lhs->dest_elem_index < rhs->dest_elem_index );
+
+        if( ( !is_smaller_than ) &&
+            (  lhs->dest_elem_index == rhs->dest_elem_index ) )
+        {
+            is_smaller_than = ( lhs->src_elem_index < rhs->src_elem_index );
+
+            if( ( !is_smaller_than ) &&
+                ( lhs->src_elem_index == rhs->src_elem_index ) )
+            {
+                is_smaller_than = (
+                    lhs->dest_pointer_offset < rhs->dest_pointer_offset );
+
+                if( ( !is_smaller_than ) &&
+                    ( lhs->dest_pointer_offset == rhs->dest_pointer_offset ) )
+                {
+                    is_smaller_than = (
+                        lhs->src_pointer_offset < rhs->src_pointer_offset );
+                }
+            }
+        }
+    }
+
+    return is_smaller_than;
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_are_equal)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    SIXTRL_ASSERT( lhs != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs != SIXTRL_NULLPTR );
+
+    return ( ( lhs->dest_buffer_id      == rhs->dest_buffer_id ) &&
+             ( lhs->src_buffer_id       == rhs->src_buffer_id ) &&
+             ( lhs->dest_elem_type_id   == rhs->dest_elem_type_id ) &&
+             ( lhs->src_elem_type_id    == rhs->src_elem_type_id ) &&
+             ( lhs->dest_elem_index     == rhs->dest_elem_index ) &&
+             ( lhs->src_elem_index      == rhs->src_elem_index ) &&
+             ( lhs->dest_pointer_offset == rhs->dest_pointer_offset ) &&
+             ( lhs->src_pointer_offset  == rhs->src_pointer_offset ) );
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_are_not_equal)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    return !NS(AssignAddressItem_are_equal)( lhs, rhs );
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_dest_src_are_equal)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    SIXTRL_ASSERT( lhs != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs != SIXTRL_NULLPTR );
+
+    return ( ( lhs->dest_buffer_id == rhs->dest_buffer_id ) &&
+             ( lhs->src_buffer_id  == rhs->src_buffer_id ) );
+}
+
+SIXTRL_INLINE bool NS(AssignAddressItem_dest_src_are_not_equal)(
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT lhs,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT rhs )
+{
+    SIXTRL_ASSERT( lhs != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs != SIXTRL_NULLPTR );
+
+    return ( ( lhs->dest_buffer_id != rhs->dest_buffer_id ) ||
+             ( lhs->src_buffer_id  != rhs->src_buffer_id ) );
+}
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+
+#endif /* SIXTRACKLIB_COMMON_BUFFER_ADDR_ASSIGNMENT_C99_H__ */
+
diff --git a/sixtracklib/common/buffer/assign_address_item.hpp b/sixtracklib/common/buffer/assign_address_item.hpp
new file mode 100644
index 00000000..f5718cd9
--- /dev/null
+++ b/sixtracklib/common/buffer/assign_address_item.hpp
@@ -0,0 +1,755 @@
+#ifndef SIXTRACKLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_CXX_HPP__
+#define SIXTRACKLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_CXX_HPP__
+
+#if defined( __cplusplus )
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <cstddef>
+    #include <cstdint>
+    #include <cstdlib>
+    #include <type_traits>
+    #include <utility>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/buffer.hpp"
+    #include "sixtracklib/common/buffer.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    struct AssignAddressItem : public ::NS(AssignAddressItem)
+    {
+        typedef SIXTRL_CXX_NAMESPACE::Buffer buffer_t;
+        typedef buffer_t::c_api_t            c_buffer_t;
+        typedef buffer_t::size_type          size_type;
+        typedef buffer_t::type_id_t          type_id_t;
+        typedef ::NS(AssignAddressItem)      c_api_t;
+
+        SIXTRL_FN AssignAddressItem() SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN AssignAddressItem(
+            type_id_t const dest_elem_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_idx,
+            size_type const dest_pointer_offset,
+            type_id_t const src_elem_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_idx,
+            size_type const src_pointer_offset ) SIXTRL_NOEXCEPT;
+
+
+        SIXTRL_FN AssignAddressItem(
+            AssignAddressItem const& other ) = default;
+
+        SIXTRL_FN AssignAddressItem& operator=(
+            AssignAddressItem const& rhs ) = default;
+
+        SIXTRL_FN AssignAddressItem( AssignAddressItem&& other ) = default;
+        SIXTRL_FN AssignAddressItem& operator=(
+            AssignAddressItem&& rhs ) = default;
+
+        SIXTRL_FN ~AssignAddressItem() = default;
+
+        /* ----------------------------------------------------------------- */
+
+        #if !defined( _GPUCODE )
+
+        SIXTRL_STATIC SIXTRL_FN
+        SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem const* FromBuffer(
+            SIXTRL_BUFFER_ARGPTR_DEC Buffer const& SIXTRL_RESTRICT_REF buffer,
+            size_type const buffer_index ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_STATIC SIXTRL_FN
+        SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem const* FromBuffer(
+            SIXTRL_BUFFER_ARGPTR_DEC const ::NS(Buffer) *const
+                SIXTRL_RESTRICT buffer,
+            size_type const buffer_index ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_STATIC SIXTRL_FN
+        SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem const* FromBufferObject(
+            SIXTRL_BUFFER_ARGPTR_DEC SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+                NS(Object) *const SIXTRL_RESTRICT item_info ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_STATIC SIXTRL_FN
+        SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* FromBuffer(
+            SIXTRL_BUFFER_ARGPTR_DEC Buffer& SIXTRL_RESTRICT_REF buffer,
+            size_type const buffer_index ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_STATIC SIXTRL_FN
+        SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* FromBuffer(
+            SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+            size_type const buffer_index ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_STATIC SIXTRL_FN
+        SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* FromBufferObject(
+            SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+                NS(Object)* SIXTRL_RESTRICT item_info ) SIXTRL_NOEXCEPT;
+
+        #endif /* !defined( _GPUCODE ) */
+
+        /* ----------------------------------------------------------------- */
+
+        #if !defined( _GPUCODE )
+
+        SIXTRL_STATIC SIXTRL_FN bool CanAddToBuffer(
+            buffer_t& SIXTRL_RESTRICT_REF buffer,
+            SIXTRL_BUFFER_ARGPTR_DEC size_type* SIXTRL_RESTRICT
+                ptr_requ_objects  = nullptr,
+            SIXTRL_BUFFER_ARGPTR_DEC size_type* SIXTRL_RESTRICT
+                ptr_requ_slots    = nullptr,
+            SIXTRL_BUFFER_ARGPTR_DEC size_type* SIXTRL_RESTRICT
+                ptr_requ_dataptrs = nullptr ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+        CreateNewOnBuffer(
+            buffer_t& SIXTRL_RESTRICT_REF buffer ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+        AddToBuffer(
+            buffer_t& SIXTRL_RESTRICT_REF buffer,
+            type_id_t const dest_elem_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_idx,
+            size_type const dest_pointer_offset,
+            type_id_t const src_elem_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_idx,
+            size_type const src_pointer_offset );
+
+        #endif /* !defined( _GPUCODE ) */
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_FN type_id_t getTypeId() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN size_type getNumDataPtrs() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC c_api_t const*
+            getCApiPtr() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC c_api_t*
+            getCApiPtr() SIXTRL_NOEXCEPT;
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_FN void preset() SIXTRL_NOEXCEPT;
+        SIXTRL_FN bool valid() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN bool is_on_buffer() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN bool is_on_raw_memory() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN bool dest_is_on_buffer() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN bool src_is_on_buffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN bool dest_is_on_raw_memory() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN bool src_is_on_raw_memory() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN type_id_t getDestElemTypeId() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN size_type getDestBufferId() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN size_type getDestElemIndex() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN size_type getDestElemPointerOffset() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN type_id_t getSrcElemTypeId() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN size_type getSrcBufferId() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN size_type getSrcElemIndex() const SIXTRL_NOEXCEPT;
+        SIXTRL_FN size_type getSrcElemPointerOffset() const SIXTRL_NOEXCEPT;
+
+        /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
+
+        SIXTRL_FN void setDestElemTypeId(
+            type_id_t const dest_elem_type_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN void setDestBufferId(
+            size_type const dest_buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN void setDestElemIndex(
+            size_type const dest_elem_idx ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN void setDestElemPointerOffset(
+            size_type const dest_elem_pointer_offset ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN void setSrcElemTypeId(
+            type_id_t const dest_elem_type_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN void setSrcBufferId(
+            size_type const dest_buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN void setSrcElemIndex(
+            size_type const dest_elem_idx ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN void setSrcElemPointerOffset(
+            size_type const dest_elem_pointer_offset ) SIXTRL_NOEXCEPT;
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_FN bool operator<( AssignAddressItem const&
+            SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN bool operator==( AssignAddressItem const&
+            SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN bool operator!=( AssignAddressItem const&
+            SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN bool operator>=( AssignAddressItem const&
+            SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN bool operator>( AssignAddressItem const&
+            SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_FN bool operator<=( AssignAddressItem const&
+            SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT;
+    };
+
+    #if !defined( _GPUCODE )
+
+    SIXTRL_STATIC SIXTRL_FN
+    SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* AssignAddressItem_new(
+        Buffer& SIXTRL_RESTRICT_REF buffer );
+
+    SIXTRL_STATIC SIXTRL_FN
+    SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* AssignAddressItem_new(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT ptr_buffer );
+
+    SIXTRL_STATIC SIXTRL_FN
+    SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* AssignAddressItem_add(
+        AssignAddressItem::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        AssignAddressItem::type_id_t const dest_elem_type_id,
+        AssignAddressItem::size_type const dest_buffer_id,
+        AssignAddressItem::size_type const dest_elem_idx,
+        AssignAddressItem::size_type const dest_pointer_offset,
+        AssignAddressItem::type_id_t const src_elem_type_id,
+        AssignAddressItem::size_type const src_buffer_id,
+        AssignAddressItem::size_type const src_elem_idx,
+        AssignAddressItem::size_type const src_pointer_offset );
+
+    SIXTRL_STATIC SIXTRL_FN
+    SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* AssignAddressItem_add(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
+        AssignAddressItem::type_id_t const dest_elem_type_id,
+        AssignAddressItem::size_type const dest_buffer_id,
+        AssignAddressItem::size_type const dest_elem_idx,
+        AssignAddressItem::size_type const dest_pointer_offset,
+        AssignAddressItem::type_id_t const src_elem_type_id,
+        AssignAddressItem::size_type const src_buffer_id,
+        AssignAddressItem::size_type const src_elem_idx,
+        AssignAddressItem::size_type const src_pointer_offset );
+
+    SIXTRL_STATIC SIXTRL_FN
+    SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* AssignAddressItem_add_copy(
+        Buffer& SIXTRL_RESTRICT_REF buffer,
+        AssignAddressItem const& SIXTRL_RESTRICT_REF orig );
+
+    SIXTRL_STATIC SIXTRL_FN
+    SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem* AssignAddressItem_add_copy(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
+        AssignAddressItem const& SIXTRL_RESTRICT_REF orig );
+
+    #endif /* !defined( _GPUCODE ) */
+
+    template<> struct ObjectTypeTraits< ::NS(AssignAddressItem) >
+    {
+        SIXTRL_STATIC SIXTRL_INLINE object_type_id_t Type() SIXTRL_NOEXCEPT
+        {
+            return NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM);
+        }
+    };
+
+    template<> struct ObjectTypeTraits< AssignAddressItem >
+    {
+        SIXTRL_STATIC SIXTRL_INLINE object_type_id_t Type() SIXTRL_NOEXCEPT
+        {
+            return NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM);
+        }
+    };
+}
+
+/* ************************************************************************* */
+/* ************************************************************************* */
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    SIXTRL_INLINE AssignAddressItem::AssignAddressItem() SIXTRL_NOEXCEPT :
+        ::NS(AssignAddressItem)()
+    {
+        ::NS(AssignAddressItem_preset)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::AssignAddressItem(
+        AssignAddressItem::type_id_t const dest_elem_type_id,
+        AssignAddressItem::size_type const dest_buffer_id,
+        AssignAddressItem::size_type const dest_elem_idx,
+        AssignAddressItem::size_type const dest_pointer_offset,
+        AssignAddressItem::type_id_t const src_elem_type_id,
+        AssignAddressItem::size_type const src_buffer_id,
+        AssignAddressItem::size_type const src_elem_idx,
+        AssignAddressItem::size_type const src_pointer_offset
+            ) SIXTRL_NOEXCEPT : ::NS(AssignAddressItem)()
+    {
+        ::NS(AssignAddressItem_set_dest_elem_type_id)(
+            this->getCApiPtr(), dest_elem_type_id );
+
+        ::NS(AssignAddressItem_set_dest_buffer_id)(
+            this->getCApiPtr(), dest_buffer_id );
+
+        ::NS(AssignAddressItem_set_dest_elem_index)(
+            this->getCApiPtr(), dest_elem_idx );
+
+        ::NS(AssignAddressItem_set_dest_pointer_offset)(
+            this->getCApiPtr(), dest_pointer_offset );
+
+        ::NS(AssignAddressItem_set_src_elem_type_id)(
+            this->getCApiPtr(), src_elem_type_id );
+
+        ::NS(AssignAddressItem_set_src_buffer_id)(
+            this->getCApiPtr(), src_buffer_id );
+
+        ::NS(AssignAddressItem_set_src_elem_index)(
+            this->getCApiPtr(), src_elem_idx );
+
+        ::NS(AssignAddressItem_set_src_pointer_offset)(
+            this->getCApiPtr(), src_pointer_offset );
+    }
+
+    #if !defined( _GPUCODE )
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem const*
+    AssignAddressItem::FromBuffer( SIXTRL_BUFFER_ARGPTR_DEC Buffer const&
+        SIXTRL_RESTRICT_REF buffer,
+        AssignAddressItem::size_type const buffer_index ) SIXTRL_NOEXCEPT
+    {
+        return AssignAddressItem::FromBufferObject( buffer[ buffer_index ] );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem const*
+    AssignAddressItem::FromBuffer( SIXTRL_BUFFER_ARGPTR_DEC const
+        ::NS(Buffer) *const SIXTRL_RESTRICT buffer,
+        AssignAddressItem::size_type const buffer_index ) SIXTRL_NOEXCEPT
+    {
+        return AssignAddressItem::FromBufferObject(
+            ::NS(Buffer_get_const_object)( buffer, buffer_index ) );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem const*
+    AssignAddressItem::FromBufferObject(
+        SIXTRL_BUFFER_ARGPTR_DEC SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+            const ::NS(Object) *const SIXTRL_RESTRICT item_info ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem const*;
+
+        return ( ( item_info != nullptr ) &&
+                 ( ::NS(Object_get_type_id)( item_info ) ==
+                    ::NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM) ) &&
+                 ( ::NS(Object_get_size)( item_info ) >=
+                    sizeof( AssignAddressItem ) ) )
+            ? reinterpret_cast< ptr_t >( static_cast< uintptr_t >(
+                ::NS(Object_get_begin_addr)( item_info ) ) )
+            : nullptr;
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem::FromBuffer(
+        SIXTRL_BUFFER_ARGPTR_DEC Buffer& SIXTRL_RESTRICT_REF buffer,
+        AssignAddressItem::size_type const buffer_index ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*;
+        return const_cast< ptr_t >( AssignAddressItem::FromBufferObject(
+            ::NS(Buffer_get_const_object)(
+                buffer.getCApiPtr(), buffer_index ) ) );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem::FromBuffer(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+        AssignAddressItem::size_type const buffer_index ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*;
+        return const_cast< ptr_t >( AssignAddressItem::FromBufferObject(
+            ::NS(Buffer_get_const_object)( buffer, buffer_index ) ) );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem::FromBufferObject( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+        NS(Object)* SIXTRL_RESTRICT item_info ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*;
+        using ptr_c_obj_t = SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*;
+
+        ptr_c_obj_t c_item_info = item_info;
+
+        return const_cast< ptr_t >( AssignAddressItem::FromBufferObject(
+            c_item_info ) );
+    }
+
+    #endif /* !defined( _GPUCODE ) */
+
+    /* ----------------------------------------------------------------- */
+
+    #if !defined( _GPUCODE )
+
+    SIXTRL_INLINE bool AssignAddressItem::CanAddToBuffer(
+        AssignAddressItem::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        SIXTRL_BUFFER_ARGPTR_DEC AssignAddressItem::size_type*
+            SIXTRL_RESTRICT ptr_requ_objects,
+        SIXTRL_BUFFER_ARGPTR_DEC AssignAddressItem::size_type*
+            SIXTRL_RESTRICT ptr_requ_slots,
+        SIXTRL_BUFFER_ARGPTR_DEC AssignAddressItem::size_type*
+            SIXTRL_RESTRICT ptr_requ_dataptrs ) SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_can_be_added)( buffer.getCApiPtr(),
+                ptr_requ_objects, ptr_requ_slots, ptr_requ_dataptrs );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem::CreateNewOnBuffer( AssignAddressItem::buffer_t&
+        SIXTRL_RESTRICT_REF buffer ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*;
+        return static_cast< ptr_t >( ::NS(AssignAddressItem_new)(
+            buffer.getCApiPtr() ) );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem::AddToBuffer(
+        AssignAddressItem::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        AssignAddressItem::type_id_t const dest_elem_type_id,
+        AssignAddressItem::size_type const dest_buffer_id,
+        AssignAddressItem::size_type const dest_elem_idx,
+        AssignAddressItem::size_type const dest_pointer_offset,
+        AssignAddressItem::type_id_t const src_elem_type_id,
+        AssignAddressItem::size_type const src_buffer_id,
+        AssignAddressItem::size_type const src_elem_idx,
+        AssignAddressItem::size_type const src_pointer_offset )
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*;
+        return static_cast< ptr_t >( ::NS(AssignAddressItem_add)(
+            buffer.getCApiPtr(), dest_elem_type_id, dest_buffer_id,
+                    dest_elem_idx, dest_pointer_offset,
+            src_elem_type_id, src_buffer_id,
+                    src_elem_idx, src_pointer_offset ) );
+    }
+
+    #endif /* !defined( _GPUCODE ) */
+
+    /* ----------------------------------------------------------------- */
+
+    SIXTRL_INLINE AssignAddressItem::type_id_t
+    AssignAddressItem::getTypeId() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_type_id)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::size_type
+    AssignAddressItem::getNumDataPtrs() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_num_dataptrs)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem::c_api_t const*
+    AssignAddressItem::getCApiPtr() const SIXTRL_NOEXCEPT
+    {
+        return reinterpret_cast<
+            SIXTRL_BUFFER_DATAPTR_DEC c_api_t const* >( this );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem::c_api_t*
+    AssignAddressItem::getCApiPtr() SIXTRL_NOEXCEPT
+    {
+        return reinterpret_cast< SIXTRL_BUFFER_DATAPTR_DEC c_api_t* >( this );
+    }
+
+    /* ----------------------------------------------------------------- */
+
+    SIXTRL_INLINE void AssignAddressItem::preset() SIXTRL_NOEXCEPT
+    {
+        ::NS(AssignAddressItem_preset)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool AssignAddressItem::valid() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_valid)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool AssignAddressItem::is_on_buffer() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_is_on_buffer)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool
+    AssignAddressItem::is_on_raw_memory() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_is_on_raw_memory)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool
+    AssignAddressItem::dest_is_on_buffer() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_dest_is_on_buffer)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool
+    AssignAddressItem::src_is_on_buffer() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_src_is_on_buffer)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool
+    AssignAddressItem::dest_is_on_raw_memory() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_dest_is_on_raw_memory)(
+            this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool
+    AssignAddressItem::src_is_on_raw_memory() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_src_is_on_raw_memory)(
+            this->getCApiPtr() );
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    SIXTRL_INLINE AssignAddressItem::type_id_t
+    AssignAddressItem::getDestElemTypeId() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_dest_elem_type_id)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::size_type
+    AssignAddressItem::getDestBufferId() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_dest_buffer_id)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::size_type
+    AssignAddressItem::getDestElemIndex() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_dest_elem_index)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::size_type
+    AssignAddressItem::getDestElemPointerOffset() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_dest_pointer_offset)(
+            this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::type_id_t
+    AssignAddressItem::getSrcElemTypeId() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_src_elem_type_id)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::size_type
+    AssignAddressItem::getSrcBufferId() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_src_buffer_id)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::size_type
+    AssignAddressItem::getSrcElemIndex() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_src_elem_index)( this->getCApiPtr() );
+    }
+
+    SIXTRL_INLINE AssignAddressItem::size_type
+    AssignAddressItem::getSrcElemPointerOffset() const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_src_pointer_offset)( this->getCApiPtr() );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
+
+    SIXTRL_INLINE void AssignAddressItem::setDestElemTypeId(
+        AssignAddressItem::type_id_t const dest_elem_type_id ) SIXTRL_NOEXCEPT
+    {
+        ::NS(AssignAddressItem_set_dest_elem_type_id)(
+            this->getCApiPtr(), dest_elem_type_id );
+    }
+
+    SIXTRL_INLINE void AssignAddressItem::setDestBufferId(
+        AssignAddressItem::size_type const dest_buffer_id ) SIXTRL_NOEXCEPT
+    {
+        ::NS(AssignAddressItem_set_dest_buffer_id)(
+            this->getCApiPtr(), dest_buffer_id );
+    }
+
+    SIXTRL_INLINE void AssignAddressItem::setDestElemIndex(
+        AssignAddressItem::size_type const dest_elem_idx ) SIXTRL_NOEXCEPT
+    {
+        ::NS(AssignAddressItem_set_dest_elem_index)(
+            this->getCApiPtr(), dest_elem_idx );
+    }
+
+    SIXTRL_INLINE void AssignAddressItem::setDestElemPointerOffset(
+        AssignAddressItem::size_type const
+            dest_elem_pointer_offset ) SIXTRL_NOEXCEPT
+    {
+        ::NS(AssignAddressItem_set_dest_pointer_offset)(
+            this->getCApiPtr(), dest_elem_pointer_offset );
+    }
+
+    SIXTRL_INLINE void AssignAddressItem::setSrcElemTypeId(
+        AssignAddressItem::type_id_t const src_elem_type_id ) SIXTRL_NOEXCEPT
+    {
+        ::NS(AssignAddressItem_set_src_elem_type_id)(
+            this->getCApiPtr(), src_elem_type_id );
+    }
+
+    SIXTRL_INLINE void AssignAddressItem::setSrcBufferId(
+        AssignAddressItem::size_type const src_buffer_id ) SIXTRL_NOEXCEPT
+    {
+         ::NS(AssignAddressItem_set_src_buffer_id)(
+            this->getCApiPtr(), src_buffer_id );
+    }
+
+    SIXTRL_INLINE void AssignAddressItem::setSrcElemIndex(
+        AssignAddressItem::size_type const src_elem_idx ) SIXTRL_NOEXCEPT
+    {
+        ::NS(AssignAddressItem_set_src_elem_index)(
+            this->getCApiPtr(), src_elem_idx );
+    }
+
+    SIXTRL_INLINE void AssignAddressItem::setSrcElemPointerOffset(
+        AssignAddressItem::size_type const
+            dest_elem_pointer_offset ) SIXTRL_NOEXCEPT
+    {
+        ::NS(AssignAddressItem_set_src_pointer_offset)(
+            this->getCApiPtr(), dest_elem_pointer_offset );
+    }
+
+     /* ----------------------------------------------------------------- */
+
+    SIXTRL_INLINE bool AssignAddressItem::operator<( AssignAddressItem const&
+        SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_compare_less)(
+            this->getCApiPtr(), rhs.getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool AssignAddressItem::operator==( AssignAddressItem const&
+        SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_are_equal)(
+            this->getCApiPtr(), rhs.getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool AssignAddressItem::operator!=( AssignAddressItem const&
+        SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT
+    {
+        return !::NS(AssignAddressItem_compare_less)(
+            this->getCApiPtr(), rhs.getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool AssignAddressItem::operator>=( AssignAddressItem const&
+        SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT
+    {
+        return ::NS(AssignAddressItem_compare_less)(
+            this->getCApiPtr(), rhs.getCApiPtr() );
+    }
+
+    SIXTRL_INLINE bool AssignAddressItem::operator>( AssignAddressItem const&
+        SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT
+    {
+        return ( ( !::NS(AssignAddressItem_are_equal)(
+                     this->getCApiPtr(), rhs.getCApiPtr() ) ) &&
+                 ( !::NS(AssignAddressItem_compare_less)(
+                     this->getCApiPtr(), rhs.getCApiPtr() ) ) );
+    }
+
+    SIXTRL_INLINE bool AssignAddressItem::operator<=( AssignAddressItem const&
+        SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT
+    {
+        return ( ( ::NS(AssignAddressItem_are_equal)(
+                     this->getCApiPtr(), rhs.getCApiPtr() ) ) ||
+                 ( ::NS(AssignAddressItem_compare_less)(
+                     this->getCApiPtr(), rhs.getCApiPtr() ) ) );
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    #if !defined( _GPUCODE )
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem_new( Buffer& SIXTRL_RESTRICT_REF buffer )
+    {
+        return AssignAddressItem::CreateNewOnBuffer( buffer );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem_new(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT ptr_buffer )
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*;
+        return static_cast< ptr_t >(
+            ::NS(AssignAddressItem_new)( ptr_buffer ) );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem_add(
+        AssignAddressItem::buffer_t& SIXTRL_RESTRICT_REF buffer,
+        AssignAddressItem::type_id_t const dest_elem_type_id,
+        AssignAddressItem::size_type const dest_buffer_id,
+        AssignAddressItem::size_type const dest_elem_idx,
+        AssignAddressItem::size_type const dest_pointer_offset,
+        AssignAddressItem::type_id_t const src_elem_type_id,
+        AssignAddressItem::size_type const src_buffer_id,
+        AssignAddressItem::size_type const src_elem_idx,
+        AssignAddressItem::size_type const src_pointer_offset )
+    {
+        return AssignAddressItem::AddToBuffer( buffer, dest_elem_type_id,
+            dest_buffer_id, dest_elem_idx, dest_pointer_offset,
+            src_elem_type_id, src_buffer_id, src_elem_idx, src_pointer_offset );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem_add(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
+        AssignAddressItem::type_id_t const dest_elem_type_id,
+        AssignAddressItem::size_type const dest_buffer_id,
+        AssignAddressItem::size_type const dest_elem_idx,
+        AssignAddressItem::size_type const dest_pointer_offset,
+        AssignAddressItem::type_id_t const src_elem_type_id,
+        AssignAddressItem::size_type const src_buffer_id,
+        AssignAddressItem::size_type const src_elem_idx,
+        AssignAddressItem::size_type const src_pointer_offset )
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*;
+        return static_cast< ptr_t >( ::NS(AssignAddressItem_add)(
+            ptr_buffer, dest_elem_type_id, dest_buffer_id,
+                dest_elem_idx, dest_pointer_offset,
+            src_elem_type_id, src_buffer_id, src_elem_idx,
+                src_pointer_offset ) );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem_add_copy(
+        Buffer& SIXTRL_RESTRICT_REF buffer,
+        AssignAddressItem const& SIXTRL_RESTRICT_REF orig )
+    {
+        return SIXTRL_CXX_NAMESPACE::AssignAddressItem_add(
+            buffer, orig.getDestElemTypeId(), orig.getDestBufferId(),
+            orig.getDestElemIndex(), orig.getDestElemPointerOffset(),
+            orig.getSrcElemTypeId(), orig.getSrcBufferId(),
+            orig.getSrcElemIndex(),  orig.getSrcElemPointerOffset() );
+    }
+
+    SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*
+    AssignAddressItem_add_copy(
+        SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT ptr_buffer,
+        AssignAddressItem const& SIXTRL_RESTRICT_REF orig )
+    {
+        using ptr_t = SIXTRL_BUFFER_DATAPTR_DEC AssignAddressItem*;
+        return static_cast< ptr_t >( ::NS(AssignAddressItem_add_copy)(
+            ptr_buffer, orig.getCApiPtr() ) );
+    }
+
+    #endif /* !defined( _GPUCODE ) */
+}
+
+#endif /* defined( __cplusplus ) */
+
+#endif /* SIXTRACKLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_CXX_HPP__ */
diff --git a/sixtracklib/common/buffer/assign_address_item_kernel_impl.h b/sixtracklib/common/buffer/assign_address_item_kernel_impl.h
new file mode 100644
index 00000000..5010d796
--- /dev/null
+++ b/sixtracklib/common/buffer/assign_address_item_kernel_impl.h
@@ -0,0 +1,94 @@
+#ifndef SIXTRACKLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_KERNEL_IMPL_H__
+#define SIXTRACKLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_KERNEL_IMPL_H__
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(AssignAddressItem_perform_address_assignment_kernel_impl)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT assign_buffer,
+    NS(buffer_size_t) const assign_slot_size,
+    NS(buffer_size_t) const start_item_idx,
+    NS(buffer_size_t) const item_idx_stride,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_size_t) const dest_slot_size,
+    NS(arch_size_t) const dest_buffer_id,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT src_buffer,
+    NS(buffer_size_t) const src_slot_size,
+    NS(arch_size_t) const src_buffer_id );
+
+/* ************************************************************************* */
+/* ************************************************************************* */
+
+SIXTRL_INLINE NS(arch_status_t)
+NS(AssignAddressItem_perform_address_assignment_kernel_impl)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT assign_buffer,
+    NS(buffer_size_t) const assign_slot_size,
+    NS(buffer_size_t) const start_item_idx,
+    NS(buffer_size_t) const item_idx_stride,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_size_t) const dest_slot_size,
+    NS(arch_size_t) const dest_buffer_id,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT src_buffer,
+    NS(buffer_size_t) const src_slot_size,
+    NS(arch_size_t) const src_buffer_id )
+{
+    NS(buffer_size_t) const num_assign_items =
+        NS(ManagedBuffer_get_num_objects)( assign_buffer, assign_slot_size );
+
+    NS(buffer_size_t) idx = start_item_idx;
+    NS(arch_status_t) status = SIXTRL_ARCH_STATUS_SUCCESS;
+
+    SIXTRL_ASSERT( assign_buffer != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( assign_slot_size > ( NS(buffer_size_t) )0u );
+    SIXTRL_ASSERT( item_idx_stride  > ( NS(buffer_size_t) )0u );
+
+    SIXTRL_ASSERT( dest_buffer != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( dest_buffer_id != SIXTRL_ARCH_ILLEGAL_BUFFER_ID );
+
+    SIXTRL_ASSERT( src_buffer != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( src_buffer_id != SIXTRL_ARCH_ILLEGAL_BUFFER_ID );
+
+    for( ; idx < num_assign_items ; idx += item_idx_stride )
+    {
+        SIXTRL_BUFFER_DATAPTR_DEC NS(AssignAddressItem) const* item =
+            NS(AssignAddressItem_const_from_managed_buffer)(
+                assign_buffer, idx, assign_slot_size );
+
+        if( ( item != SIXTRL_NULLPTR ) &&
+            ( NS(AssignAddressItem_src_buffer_id)( item ) == src_buffer_id ) &&
+            ( NS(AssignAddressItem_dest_buffer_id)( item ) ==
+                dest_buffer_id ) )
+        {
+            NS(buffer_addr_t) const src_addr = (
+                NS(AssignAddressItem_src_is_on_buffer)( item ) )
+                ? NS(AssignAddressItem_src_pointer_addr_from_managed_buffer)(
+                    item, src_buffer, src_slot_size )
+                : NS(AssignAddressItem_src_pointer_addr_from_raw_memory)(
+                    item, src_buffer );
+
+            if( NS(AssignAddressItem_dest_is_on_buffer)( item ) )
+            {
+                status |= NS(AssignAddressItem_assign_fixed_addr_on_managed_buffer)(
+                    item, dest_buffer, dest_slot_size, src_addr );
+            }
+            else if( NS(AssignAddressItem_dest_is_on_raw_memory)( item ) )
+            {
+                status |= NS(AssignAddressItem_assign_fixed_addr_on_raw_memory)(
+                    item, dest_buffer, src_addr );
+            }
+            else
+            {
+                status |= SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+            }
+        }
+    }
+
+    return status;
+}
+
+#endif /* SIXTRACKLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_KERNEL_IMPL_H__ */
+/* end: */
diff --git a/sixtracklib/common/buffer/binary_vector.h b/sixtracklib/common/buffer/binary_vector.h
new file mode 100644
index 00000000..e8094b27
--- /dev/null
+++ b/sixtracklib/common/buffer/binary_vector.h
@@ -0,0 +1,1277 @@
+#ifndef SIXTRACKLIB_COMMON_BUFFER_BUFFER_ARRAY_OBJECT_H__
+#define SIXTRACKLIB_COMMON_BUFFER_BUFFER_ARRAY_OBJECT_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stdbool.h>
+    #include <stddef.h>
+    #include <stdlib.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #if !defined( _GPUCODE )
+        #include "sixtracklib/common/buffer.h"
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+typedef struct NS(BufferArrayObj)
+{
+    NS(buffer_addr_t)    begin_addr       SIXTRL_ALIGN( 8u );
+    NS(buffer_addr_t)    offset_addr      SIXTRL_ALIGN( 8u );
+    NS(buffer_size_t)    num_elements     SIXTRL_ALIGN( 8u );
+    NS(buffer_size_t)    max_num_elements SIXTRL_ALIGN( 8u );
+    NS(buffer_size_t)    capacity         SIXTRL_ALIGN( 8u );
+    NS(buffer_size_t)    slot_size        SIXTRL_ALIGN( 8u );
+    NS(object_type_id_t) base_type_id     SIXTRL_ALIGN( 8u );
+}
+NS(BufferArrayObj);
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_preset)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(BufferArrayObj_get_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(BufferArrayObj_get_element_offset_list_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC void const*
+NS(BufferArrayObj_get_const_data_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC void const*
+NS(BufferArrayObj_get_const_data_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC void*
+NS(BufferArrayObj_get_data_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC void*
+NS(BufferArrayObj_get_data_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const*
+NS(BufferArrayObj_get_element_offset_list_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const*
+NS(BufferArrayObj_get_element_offset_list_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_element_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index );
+
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_max_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BufferArrayObj_get_length)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BufferArrayObj_get_capacity)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t) NS(BufferArrayObj_get_slot_size)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN NS(object_type_id_t) NS(BufferArrayObj_get_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(BufferArrayObj_get_element_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_element_length)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t)
+NS(BufferArrayObj_get_element_end_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_set_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_addr_t) const begin_addr );
+
+SIXTRL_STATIC SIXTRL_FN void
+NS(BufferArrayObj_set_element_offset_list_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_addr_t) const offset_list_begin_addr );
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_set_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const num_elements );
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_set_max_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const max_num_elements );
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_set_length)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const length );
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_set_capacity)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const capacity );
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_set_slot_size)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const slot_size );
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_set_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(object_type_id_t) const num_elements );
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_set_element_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index, NS(buffer_size_t) const offset );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN void NS(BufferArrayObj_clear)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(BufferArrayObj_append_element)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    SIXTRL_ARGPTR_DEC const void *const SIXTRL_RESTRICT obj_handle_begin,
+    NS(buffer_size_t) const obj_handle_size );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(BufferArrayObj_append_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const obj_handle_size,
+    NS(buffer_size_t) const num_elements );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(BufferArrayObj_remove_last_element)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(BufferArrayObj_remove_last_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const num_elements );
+
+/* ------------------------------------------------------------------------- */
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_preset_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_addr_t)
+NS(BufferArrayObj_get_begin_addr_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_addr_t)
+NS(BufferArrayObj_get_element_offset_list_begin_addr_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC void const*
+NS(BufferArrayObj_get_const_data_begin_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC void const*
+NS(BufferArrayObj_get_const_data_end_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC void*
+NS(BufferArrayObj_get_data_begin_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC void*
+NS(BufferArrayObj_get_data_end_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const*
+NS(BufferArrayObj_get_element_offset_list_begin_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const*
+NS(BufferArrayObj_get_element_offset_list_end_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_element_offset_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index );
+
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_num_elements_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_max_num_elements_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_length_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_capacity_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_slot_size_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(object_type_id_t)
+NS(BufferArrayObj_get_type_id_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_addr_t)
+NS(BufferArrayObj_get_element_begin_addr_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    const NS(BufferArrayObj) *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_element_length_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_addr_t)
+NS(BufferArrayObj_get_element_end_addr_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
+    NS(BufferArrayObj) *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BufferArrayObj_clear_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(BufferArrayObj_append_element_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    SIXTRL_ARGPTR_DEC const void *const SIXTRL_RESTRICT obj_handle_begin,
+    NS(buffer_size_t) const obj_handle_size );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool
+NS(BufferArrayObj_append_num_elements_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const obj_handle_size,
+    NS(buffer_size_t) const num_elements );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool
+NS(BufferArrayObj_remove_last_element_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool
+NS(BufferArrayObj_remove_last_num_elements_ext)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const num_elements );
+
+#endif /* !defiend( _GPUcODE ) */
+
+/* ------------------------------------------------------------------------ */
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_slots_on_managed_buffer)(
+    NS(buffer_size_t) const max_num_elements,
+    NS(buffer_size_t) const capacity,
+    NS(buffer_size_t) const slot_size );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_dataptrs_on_managed_buffer)(
+    NS(buffer_size_t) const max_num_elements,
+    NS(buffer_size_t) const capacity,
+    NS(buffer_size_t) const slot_size );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_slots)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_dataptrs)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(BufferArrayObj_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptr );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity,
+    NS(object_type_id_t) const base_type_id );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_addr_t) const data_begin_addr,
+    NS(buffer_addr_t) const element_offset_list_begin_addr,
+    NS(buffer_size_t) const nelements, NS(buffer_size_t) const max_nelements,
+    NS(buffer_size_t) const capacity, NS(buffer_size_t) const slot_size,
+    NS(object_type_id_t) const base_type_id );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_add_copy)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(BufferArrayObj) *const
+        SIXTRL_RESTRICT other );
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_slots_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_dataptrs_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(BufferArrayObj_can_be_added_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_dataptr );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_new_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity,
+    NS(object_type_id_t) const base_type_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_add_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_addr_t) const data_begin_addr,
+    NS(buffer_addr_t) const element_offset_list_begin_addr,
+    NS(buffer_size_t) const nelements, NS(buffer_size_t) const max_nelements,
+    NS(buffer_size_t) const capacity, NS(buffer_size_t) const slot_size,
+    NS(object_type_id_t) const base_type_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_add_copy_ext)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(BufferArrayObj) *const
+        SIXTRL_RESTRICT other );
+
+#endif /* !defined( _GPUCODE ) */
+
+/* ************************************************************************* */
+/* *********         Implementation of Inline Functions          *********** */
+/* ************************************************************************* */
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_preset)( SIXTRL_BUFFER_DATAPTR_DEC
+    NS(BufferArrayObj)* SIXTRL_RESTRICT array )
+{
+    if( array != SIXTRL_NULLPTR )
+    {
+        array->begin_addr       = ( NS(buffer_addr_t) )0u;
+        array->offset_addr      = ( NS(buffer_addr_t) )0u;
+
+        array->num_elements     = ( NS(buffer_size_t) )0u;
+        array->max_num_elements = ( NS(buffer_size_t) )0u;
+        array->capacity         = ( NS(buffer_size_t) )0u;
+        array->slot_size        = NS(BUFFER_DEFAULT_SLOT_SIZE);
+
+        array->base_type_id     =
+            ( NS(object_type_id_t) )SIXTRL_OBJECT_TYPE_UNDEFINED;
+    }
+
+    return array;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(BufferArrayObj_get_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    return ( array != SIXTRL_NULLPTR )
+        ? array->begin_addr : ( NS(buffer_addr_t ) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_addr_t)
+NS(BufferArrayObj_get_element_offset_list_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj) *const
+        SIXTRL_RESTRICT array )
+{
+    return ( array != SIXTRL_NULLPTR )
+        ? array->offset_addr : ( NS(buffer_addr_t ) )0u;
+}
+
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC void const*
+NS(BufferArrayObj_get_const_data_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    typedef SIXTRL_BUFFER_DATAPTR_DEC void const* ptr_t;
+    return ( ptr_t )( uintptr_t )NS(BufferArrayObj_get_begin_addr)( array );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC void const*
+NS(BufferArrayObj_get_const_data_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    typedef SIXTRL_BUFFER_DATAPTR_DEC void const* ptr_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* ptr_raw_t;
+
+    ptr_t end_ptr = NS(BufferArrayObj_get_const_data_begin)( array );
+
+    if( end_ptr != SIXTRL_NULLPTR )
+    {
+        end_ptr = ( ptr_t )( ( ( ptr_raw_t )end_ptr ) +
+            NS(BufferArrayObj_get_length)( array ) );
+    }
+
+    return end_ptr;
+}
+
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC void*
+NS(BufferArrayObj_get_data_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array )
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC void* )( uintptr_t
+        )NS(BufferArrayObj_get_const_data_begin)( array );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC void*
+NS(BufferArrayObj_get_data_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array )
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC void* )( uintptr_t
+        )NS(BufferArrayObj_get_const_data_end)( array );
+}
+
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const*
+NS(BufferArrayObj_get_element_offset_list_begin)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const* ptr_offset_t;
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+
+    return ( ptr_offset_t )( uintptr_t )array->offset_addr;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const*
+NS(BufferArrayObj_get_element_offset_list_end)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const* ptr_offset_t;
+
+    ptr_offset_t end_ptr =
+        NS(BufferArrayObj_get_element_offset_list_begin)( array );
+
+    if( end_ptr != SIXTRL_NULLPTR )
+    {
+        end_ptr = end_ptr + NS(BufferArrayObj_get_num_elements)( array );
+    }
+
+    return end_ptr;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BufferArrayObj_get_element_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index )
+{
+    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const* ptr_offset_t;
+
+    ptr_offset_t offset_list =
+        NS(BufferArrayObj_get_element_offset_list_begin)( array );
+
+    return ( ( offset_list != SIXTRL_NULLPTR ) &&
+             ( index <= NS(BufferArrayObj_get_num_elements)( array ) ) )
+        ? offset_list[ index ] : ( NS(buffer_size_t) )0u;
+}
+
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BufferArrayObj_get_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    return ( array != SIXTRL_NULLPTR )
+        ? array->num_elements : ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BufferArrayObj_get_max_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    return ( array != SIXTRL_NULLPTR )
+        ? array->max_num_elements : ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BufferArrayObj_get_length)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    return NS(BufferArrayObj_get_element_offset)(
+        array, NS(BufferArrayObj_get_num_elements)( array ) );
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BufferArrayObj_get_capacity)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    return ( array != SIXTRL_NULLPTR )
+        ? array->capacity : ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BufferArrayObj_get_slot_size)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    return ( array != SIXTRL_NULLPTR )
+        ? array->slot_size : ( NS(buffer_size_t) )0u;
+}
+
+SIXTRL_INLINE NS(object_type_id_t) NS(BufferArrayObj_get_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array )
+{
+    return ( array != SIXTRL_NULLPTR ) ? array->base_type_id
+        : ( NS(object_type_id_t) )SIXTRL_OBJECT_TYPE_UNDEFINED;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(BufferArrayObj_get_element_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index )
+{
+    typedef NS(buffer_addr_t) addr_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const* ptr_offset_t;
+
+    addr_t const base_addr = NS(BufferArrayObj_get_begin_addr)( array );
+
+    ptr_offset_t offset_list =
+        NS(BufferArrayObj_get_element_offset_list_begin)( array );
+
+    SIXTRL_ASSERT( base_addr > ( NS(buffer_addr_t) )0u );
+    SIXTRL_ASSERT( offset_list != SIXTRL_NULLPTR );
+
+    SIXTRL_ASSERT( NS(BufferArrayObj_get_slot_size)( array ) >
+                   ( NS(buffer_size_t) )0u );
+
+    SIXTRL_ASSERT( index < NS(BufferArrayObj_get_num_elements)( array ) );
+
+    SIXTRL_ASSERT( NS(BufferArrayObj_get_num_elements)( array ) <=
+                   NS(BufferArrayObj_get_max_num_elements)( array ) );
+
+    SIXTRL_ASSERT( NS(BufferArrayObj_get_length)( array ) <=
+                   NS(BufferArrayObj_get_capacity)( array ) );
+
+    SIXTRL_ASSERT( offset_list[ index ] <
+                   NS(BufferArrayObj_get_length)( array ) );
+
+    SIXTRL_ASSERT( ( ( NS(buffer_size_t) )0u ) == ( offset_list[ index ] %
+        NS(BufferArrayObj_get_slot_size)( array ) ) );
+
+    return base_addr + offset_list[ index ];
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BufferArrayObj_get_element_length)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index )
+{
+    typedef NS(buffer_size_t) size_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const* ptr_offset_t;
+
+    SIXTRL_STATIC_VAR size_t const ZERO = ( size_t )0u;
+
+    ptr_offset_t offset_list =
+        NS(BufferArrayObj_get_element_offset_list_begin)( array );
+
+    size_t const end_index = index + ( size_t )1u;
+    size_t length = ZERO;
+
+    SIXTRL_ASSERT( NS(BufferArrayObj_get_slot_size)( array ) > ZERO );
+
+    SIXTRL_ASSERT( offset_list != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(BufferArrayObj_get_num_elements)( array ) >=
+                   end_index );
+
+    SIXTRL_ASSERT( NS(BufferArrayObj_get_num_elements)( array ) <=
+                   NS(BufferArrayObj_get_max_num_elements)( array ) );
+
+    SIXTRL_ASSERT( NS(BufferArrayObj_get_length)( array ) <=
+                   NS(BufferArrayObj_get_capacity)( array ) );
+
+    SIXTRL_ASSERT( offset_list[ end_index ] <=
+                   NS(BufferArrayObj_get_length)( array ) );
+
+    length = ( offset_list[ end_index ] >= offset_list[ index ] )
+        ? ( offset_list[ end_index ] - offset_list[ index ] ) : ZERO;
+
+    SIXTRL_ASSERT( ZERO == ( length % NS(BufferArrayObj_get_slot_size)(
+        array ) ) );
+
+    return length;
+}
+
+SIXTRL_INLINE NS(buffer_addr_t) NS(BufferArrayObj_get_element_end_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
+        *const SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index )
+{
+    typedef NS(buffer_addr_t) addr_t;
+
+    addr_t element_end_addr =
+        NS(BufferArrayObj_get_element_begin_addr)( array, index );
+
+    if( element_end_addr > ( addr_t )0u )
+    {
+        element_end_addr += NS(BufferArrayObj_get_element_length)(
+            array, index );
+    }
+
+    return element_end_addr;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_addr_t) const begin_addr )
+{
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+    array->begin_addr = begin_addr;
+}
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_element_offset_list_begin_addr)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_addr_t) const offset_list_begin_addr )
+{
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+    array->offset_addr = offset_list_begin_addr;
+}
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const num_elements )
+{
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+    array->num_elements = num_elements;
+}
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_max_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const max_num_elements )
+{
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+    array->max_num_elements = max_num_elements;
+}
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_length)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const length )
+{
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+    NS(BufferArrayObj_set_element_offset)(
+        array, NS(BufferArrayObj_get_num_elements)( array ), length );
+}
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_capacity)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const capacity )
+{
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+    array->capacity = capacity;
+}
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_slot_size)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const slot_size )
+{
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+    array->slot_size = slot_size;
+}
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_type_id)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(object_type_id_t) const base_type_id )
+{
+    SIXTRL_ASSERT( array != SIXTRL_NULLPTR );
+    array->base_type_id = base_type_id;
+}
+
+SIXTRL_INLINE void NS(BufferArrayObj_set_element_offset)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const index, NS(buffer_size_t) const offset )
+{
+    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t)* ptr_offset_t;
+
+    ptr_offset_t offset_list = ( ptr_offset_t )( uintptr_t
+        )NS(BufferArrayObj_get_element_offset_list_begin_addr)( array );
+
+    SIXTRL_ASSERT( offset_list != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( index <= NS(BufferArrayObj_get_num_elements)( array ) );
+    SIXTRL_ASSERT( NS(BufferArrayObj_get_max_num_elements)( array ) >=
+                   NS(BufferArrayObj_get_num_elements)( array ) );
+
+    offset_list[ index ] = offset;
+    return;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE void NS(BufferArrayObj_clear)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array )
+{
+    typedef NS(buffer_size_t) size_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_t;
+
+    SIXTRL_STATIC_VAR size_t const ZERO = ( size_t )0u;
+    size_t const nelem = NS(BufferArrayObj_get_num_elements)( array );
+
+    if( nelem > ZERO )
+    {
+        ptr_t begin = ( ptr_t )NS(BufferArrayObj_get_data_begin)( array );
+        size_t const bin_length = NS(BufferArrayObj_get_length)( array );
+
+        size_t ii = ZERO;
+
+        for( ; ii <= nelem ; ++ii )
+        {
+            NS(BufferArrayObj_set_element_offset)( array, ii, ZERO );
+        }
+
+        if( begin != SIXTRL_NULLPTR )
+        {
+            SIXTRL_STATIC_VAR unsigned char const CZERO = ( unsigned char )0u;
+            SIXTRACKLIB_SET_VALUES( unsigned char, begin, bin_length, CZERO );
+        }
+
+        NS(BufferArrayObj_set_num_elements)( array, ZERO );
+    }
+
+    return;
+}
+
+SIXTRL_INLINE bool NS(BufferArrayObj_append_element)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    SIXTRL_ARGPTR_DEC const void *const SIXTRL_RESTRICT obj_handle_begin,
+    NS(buffer_size_t) const obj_handle_size )
+{
+    typedef NS(buffer_size_t) size_t;
+
+    SIXTRL_STATIC_VAR size_t const ZERO = ( size_t )0u;
+
+    bool success = false;
+    size_t const slot_size = NS(BufferArrayObj_get_slot_size)( array );
+
+    if( ( array != SIXTRL_NULLPTR ) && ( obj_handle_size > ZERO ) &&
+        ( slot_size > ZERO ) )
+    {
+        size_t const nelem = NS(BufferArrayObj_get_num_elements)( array );
+        size_t const length = NS(BufferArrayObj_get_length)( array );
+        size_t const capacity = NS(BufferArrayObj_get_capacity)( array );
+
+        size_t const elem_length = NS(ManagedBuffer_get_slot_based_length)(
+            obj_handle_size, slot_size );
+
+        size_t const new_length = elem_length + length;
+
+        SIXTRL_ASSERT( ( length % slot_size ) == ZERO );
+
+        if( ( ( elem_length % slot_size ) == ZERO ) &&
+            ( new_length <= capacity ) &&
+            ( nelem < NS(BufferArrayObj_get_max_num_elements)( array ) ) )
+        {
+            if( obj_handle_begin != SIXTRL_NULLPTR )
+            {
+                SIXTRL_ASSERT( NS(BufferArrayObj_get_data_begin)( array ) !=
+                               SIXTRL_NULLPTR );
+
+                SIXTRACKLIB_COPY_VALUES( unsigned char,
+                    NS(BufferArrayObj_get_data_begin)( array ),
+                    obj_handle_begin, obj_handle_size );
+            }
+
+            NS(BufferArrayObj_set_element_offset)(
+                array, nelem, new_length );
+
+            NS(BufferArrayObj_set_num_elements)(
+                array, nelem + ( size_t )1u );
+
+            success = true;
+        }
+    }
+
+    return success;
+}
+
+SIXTRL_INLINE bool NS(BufferArrayObj_append_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const obj_handle_size,
+    NS(buffer_size_t) const num_elements )
+{
+    bool success = false;
+
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef unsigned char raw_t;
+
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+
+    buf_size_t const current_nelems =
+        NS(BufferArrayObj_get_num_elements)( array );
+
+    buf_size_t const max_nelems =
+        NS(BufferArrayObj_get_max_num_elements)( array );
+
+    if( ( array != SIXTRL_NULLPTR ) &&
+        ( ( current_nelems + num_elements ) <= max_nelems ) )
+    {
+        typedef SIXTRL_BUFFER_DATAPTR_DEC raw_t* ptr_data_t;
+
+        buf_size_t const current_length =
+            NS(BufferArrayObj_get_length)( array );
+
+        ptr_data_t current_end_ptr =
+            NS(BufferArrayObj_get_data_end)( array );
+
+        buf_size_t ii = ZERO;
+        success = true;
+
+        for( ; ii < num_elements ; ++ii )
+        {
+            success &= NS(BufferArrayObj_append_element)(
+                array, SIXTRL_NULLPTR, obj_handle_size );
+
+            if( !success ) break;
+        }
+
+        if( !success )
+        {
+            buf_size_t const new_length =
+                NS(BufferArrayObj_get_length)( array );
+
+            buf_size_t const new_nelems =
+                NS(BufferArrayObj_get_num_elements)( array );
+
+            if( current_nelems < new_nelems )
+            {
+                buf_size_t ii = current_nelems + ( buf_size_t )1u;
+
+                while( ii <= new_nelems )
+                {
+                    NS(BufferArrayObj_set_element_offset)(
+                        array, ii++, ZERO );
+                }
+            }
+
+            if( current_length < new_length )
+            {
+                SIXTRL_ASSERT( current_end_ptr != SIXTRL_NULLPTR );
+                SIXTRL_STATIC_VAR raw_t const CZERO = ( raw_t )0u;
+
+                SIXTRACKLIB_SET_VALUES( raw_t, current_end_ptr,
+                        ( new_length - current_length ), CZERO );
+            }
+
+            if( current_nelems < new_nelems )
+            {
+                NS(BufferArrayObj_set_num_elements)(
+                    array, current_nelems );
+
+                NS(BufferArrayObj_set_element_offset)(
+                    array, current_nelems, current_length );
+            }
+        }
+    }
+
+    return success;
+}
+
+SIXTRL_INLINE bool NS(BufferArrayObj_remove_last_element)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array )
+{
+    typedef NS(buffer_size_t) size_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_data_t;
+
+    bool success = false;
+
+    SIXTRL_STATIC_VAR size_t const ZERO = ( size_t )0u;
+
+    size_t const current_nelems =
+        NS(BufferArrayObj_get_num_elements)( array );
+
+    if( ( array != SIXTRL_NULLPTR ) && ( current_nelems > ZERO ) )
+    {
+        size_t const last_index = current_nelems - ( size_t )1u;
+
+        ptr_data_t elem_begin = ( ptr_data_t )( uintptr_t
+            )NS(BufferArrayObj_get_element_begin_addr)( array, last_index );
+
+        size_t const elem_length =
+            NS(BufferArrayObj_get_element_length)( array, last_index );
+
+        if( ( elem_length > ZERO ) && ( elem_begin != SIXTRL_NULLPTR ) )
+        {
+            SIXTRL_STATIC_VAR unsigned char CZERO = ( unsigned char )0u;
+
+            SIXTRACKLIB_SET_VALUES(
+                unsigned char, elem_begin, elem_length, CZERO );
+        }
+
+        NS(BufferArrayObj_set_element_offset)(
+            array, current_nelems, ZERO );
+
+        NS(BufferArrayObj_set_num_elements)(
+            array, current_nelems - ( size_t )1u );
+
+        success = true;
+    }
+
+    return success;
+}
+
+SIXTRL_INLINE bool NS(BufferArrayObj_remove_last_num_elements)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array,
+    NS(buffer_size_t) const num_elements_to_remove )
+{
+    typedef NS(buffer_size_t) size_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC unsigned char* ptr_data_t;
+
+    bool success = false;
+
+    SIXTRL_STATIC_VAR size_t const ZERO = ( size_t )0u;
+
+    size_t const current_nelems =
+        NS(BufferArrayObj_get_num_elements)( array );
+
+    if( ( array != SIXTRL_NULLPTR ) && ( num_elements_to_remove > ZERO ) &&
+        ( current_nelems >= num_elements_to_remove ) )
+    {
+        size_t const new_nelems = current_nelems - num_elements_to_remove;
+
+        if( new_nelems > ZERO )
+        {
+            size_t ii = new_nelems + ( size_t )1u;
+
+            size_t const current_length =
+                NS(BufferArrayObj_get_length)( array );
+
+            size_t const new_length = NS(BufferArrayObj_get_element_offset)(
+                array, new_nelems - ( size_t )1u );
+
+            if( current_length > new_length )
+            {
+                SIXTRL_STATIC_VAR unsigned char CZERO = ( unsigned char )0u;
+
+                ptr_data_t removed_elem_begin = ( ptr_data_t )( uintptr_t
+                    )NS(BufferArrayObj_get_element_begin_addr)(
+                        array, new_nelems );
+
+                SIXTRACKLIB_SET_VALUES( unsigned char, removed_elem_begin,
+                                        current_length - new_length, CZERO );
+            }
+
+            for( ; ii <= current_nelems ; ++ii )
+            {
+                NS(BufferArrayObj_set_element_offset)( array, ii, ZERO );
+            }
+        }
+        else
+        {
+            NS(BufferArrayObj_clear)( array );
+        }
+
+        success = true;
+    }
+
+    return success;
+}
+
+/* ------------------------------------------------------------------------- */
+
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_slots_on_managed_buffer)(
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity,
+    NS(buffer_size_t) const slot_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    buf_size_t num_slots = ( buf_size_t )0u;
+
+    if( slot_size > ( buf_size_t )0u )
+    {
+        buf_size_t const offset_list_length =
+            max_nelements + ( buf_size_t )1u;
+
+        buf_size_t required_size = NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( NS(BufferArrayObj) ), slot_size );
+
+        if( capacity > ( buf_size_t )0u )
+        {
+            required_size += NS(ManagedBuffer_get_slot_based_length)(
+                capacity, slot_size );
+        }
+
+        required_size += NS(ManagedBuffer_get_slot_based_length)(
+            sizeof( buf_size_t ) * offset_list_length, slot_size );
+
+        SIXTRL_ASSERT( ( required_size % slot_size ) == ( buf_size_t )0u );
+        num_slots = required_size / slot_size;
+    }
+
+    return num_slots;
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_dataptrs_on_managed_buffer)(
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity,
+    NS(buffer_size_t) const slot_size )
+{
+    ( void )capacity;
+    ( void )max_nelements;
+    ( void )slot_size;
+
+    return ( NS(buffer_size_t) )2u;
+}
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE NS(buffer_size_t) NS(BufferArrayObj_get_required_num_slots)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity )
+{
+    return NS(BufferArrayObj_get_required_num_slots_on_managed_buffer)(
+        max_nelements, capacity, NS(Buffer_get_slot_size)( buffer ) );
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(BufferArrayObj_get_required_num_dataptrs)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity )
+{
+    return NS(BufferArrayObj_get_required_num_dataptrs_on_managed_buffer)(
+        max_nelements, capacity, NS(Buffer_get_slot_size)( buffer ) );
+}
+
+SIXTRL_INLINE bool NS(BufferArrayObj_can_be_added)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_objects,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_slots,
+    SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT requ_ptrs )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+
+    buf_size_t const nptrs = NS(BufferArrayObj_get_required_num_dataptrs)(
+        buffer, max_nelements, capacity );
+
+    buf_size_t sizes[]      = { ( buf_size_t )1u, sizeof( buf_size_t ) };
+    buf_size_t counts[]     = { capacity, max_nelements + ( buf_size_t )1u };
+
+    return NS(Buffer_can_add_object)( buffer, sizeof( NS(BufferArrayObj) ),
+        nptrs, &sizes[ 0 ], &counts[ 0 ], requ_objects, requ_slots, requ_ptrs );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_new)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const max_nelements, NS(buffer_size_t) const capacity,
+    NS(object_type_id_t) const base_type_id )
+{
+    typedef NS(BufferArrayObj) array_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC array_t* ptr_array_t;
+
+    buf_size_t const nptrs = NS(BufferArrayObj_get_required_num_dataptrs)(
+        buffer, max_nelements, capacity );
+
+    buf_size_t offsets[] =
+    {
+        offsetof( array_t, begin_addr ),
+        offsetof( array_t, offset_addr )
+    };
+
+    buf_size_t sizes[]     = { ( buf_size_t )1u, sizeof( buf_size_t ) };
+    buf_size_t counts[]    = { capacity, max_nelements + ( buf_size_t )1u };
+
+    array_t array;
+    array.begin_addr       = ( NS(buffer_addr_t) )0u;
+    array.offset_addr      = ( NS(buffer_addr_t) )0u;
+    array.num_elements     = ( buf_size_t )0u;
+    array.capacity         = capacity;
+    array.base_type_id     = NS(OBJECT_TYPE_ARRAY);
+    array.max_num_elements = max_nelements;
+    array.slot_size        = NS(BUFFER_DEFAULT_SLOT_SIZE);
+    array.base_type_id     = base_type_id;
+
+    return ( ptr_array_t )( uintptr_t )NS(Object_get_begin_addr)(
+        NS(Buffer_add_object)( buffer, &array, sizeof( array_t ),
+            NS(OBJECT_TYPE_ARRAY), nptrs,
+                &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_add)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_addr_t) const data_begin_addr,
+    NS(buffer_addr_t) const element_offset_list_begin_addr,
+    NS(buffer_size_t) const num_elements, NS(buffer_size_t) const max_nelem,
+    NS(buffer_size_t) const capacity, NS(buffer_size_t) const slot_size,
+    NS(object_type_id_t) const base_type_id )
+{
+    typedef NS(BufferArrayObj) array_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef NS(buffer_addr_t) addr_t;
+
+    typedef SIXTRL_BUFFER_DATAPTR_DEC array_t*    ptr_array_t;
+    typedef SIXTRL_ARGPTR_DEC buf_size_t const*   ptr_const_offset_t;
+    typedef SIXTRL_BUFFER_DATAPTR_DEC buf_size_t* ptr_offset_t;
+    typedef unsigned char raw_t;
+    typedef SIXTRL_ARGPTR_DEC raw_t const* ptr_const_raw_t;
+    typedef SIXTRL_ARGPTR_DEC raw_t*       ptr_raw_t;
+
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    SIXTRL_STATIC_VAR addr_t    const ZADDR = ( addr_t )0u;
+
+    ptr_array_t a = NS(BufferArrayObj_new)(
+        buffer, max_nelem, capacity, base_type_id );
+
+    if( a != SIXTRL_NULLPTR )
+    {
+        NS(BufferArrayObj_set_max_num_elements)( a, max_nelem );
+        NS(BufferArrayObj_set_capacity)( a, capacity );
+        NS(BufferArrayObj_set_slot_size)( a, slot_size );
+        NS(BufferArrayObj_set_type_id)( a, base_type_id );
+
+        if( ( element_offset_list_begin_addr > ZADDR ) &&
+            ( num_elements <= max_nelem ) && ( num_elements > ZERO ) )
+        {
+            ptr_offset_t out = ( ptr_offset_t )( uintptr_t
+                )NS(BufferArrayObj_get_element_offset_list_begin_addr)( a );
+
+            ptr_const_offset_t in = ( ptr_const_offset_t )( uintptr_t
+                )element_offset_list_begin_addr;
+
+            buf_size_t const nlist_elem = num_elements + ( buf_size_t )1u;
+            buf_size_t const in_length = in[ num_elements ];
+
+            SIXTRACKLIB_COPY_VALUES( buf_size_t, out, in, nlist_elem );
+
+            if( ( data_begin_addr > ZADDR ) && ( capacity >= in_length ) )
+            {
+                ptr_const_raw_t raw_in =
+                    ( ptr_const_raw_t )( uintptr_t )data_begin_addr;
+
+                ptr_raw_t raw_out = ( ptr_raw_t )( uintptr_t
+                    )NS(BufferArrayObj_get_begin_addr)( a );
+
+                SIXTRACKLIB_COPY_VALUES( raw_t, raw_out, raw_in, in_length );
+
+                if( in_length < capacity )
+                {
+                    SIXTRL_STATIC_VAR raw_t const CZERO = ( raw_t )0u;
+
+                    SIXTRACKLIB_SET_VALUES( raw_t, raw_out + in_length,
+                        capacity - in_length, CZERO );
+                }
+            }
+
+            NS(BufferArrayObj_set_num_elements)( a, num_elements );
+        }
+        else if( ( data_begin_addr > ZADDR ) && ( capacity > ZERO ) )
+        {
+            ptr_const_raw_t raw_in =
+                    ( ptr_const_raw_t )( uintptr_t )data_begin_addr;
+
+            ptr_raw_t raw_out = ( ptr_raw_t )( uintptr_t
+                    )NS(BufferArrayObj_get_begin_addr)( a );
+
+            SIXTRACKLIB_COPY_VALUES( raw_t, raw_out, raw_in, capacity );
+        }
+    }
+
+    return a;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
+NS(BufferArrayObj_add_copy)( SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)*
+    SIXTRL_RESTRICT buffer, SIXTRL_BUFFER_ARGPTR_DEC const
+        NS(BufferArrayObj) *const SIXTRL_RESTRICT other )
+{
+    return NS(BufferArrayObj_add)( buffer,
+        NS(BufferArrayObj_get_begin_addr)( other ),
+        NS(BufferArrayObj_get_element_offset_list_begin_addr)( other ),
+        NS(BufferArrayObj_get_num_elements)( other ),
+        NS(BufferArrayObj_get_max_num_elements)( other ),
+        NS(BufferArrayObj_get_capacity)( other ),
+        NS(BufferArrayObj_get_slot_size)( other ),
+        NS(BufferArrayObj_get_type_id)( other ) );
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+#endif /* SIXTRACKLIB_COMMON_BUFFER_BUFFER_ARRAY_OBJECT_H__ */
+
+/* end: sixtracklib/common/buffer/managed_buffer_handle.h */
diff --git a/sixtracklib/common/buffer/buffer_array_object.c b/sixtracklib/common/buffer/buffer_array_object.c
index a432dc86..a4c2b4f5 100644
--- a/sixtracklib/common/buffer/buffer_array_object.c
+++ b/sixtracklib/common/buffer/buffer_array_object.c
@@ -51,7 +51,7 @@ NS(BufferArrayObj_get_const_data_end_ext)( SIXTRL_BUFFER_DATAPTR_DEC const
 SIXTRL_BUFFER_DATAPTR_DEC void* NS(BufferArrayObj_get_data_begin_ext)(
     SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)* SIXTRL_RESTRICT array )
 {
-    return NS(BufferArrayObj_get_data_begin_ext)( array );
+    return NS(BufferArrayObj_get_data_begin)( array );
 }
 
 SIXTRL_BUFFER_DATAPTR_DEC void* NS(BufferArrayObj_get_data_end_ext)(
@@ -66,7 +66,7 @@ NS(BufferArrayObj_get_element_offset_list_begin_ext)(
     SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj)
         *const SIXTRL_RESTRICT array )
 {
-    return NS(BufferArrayObj_get_element_offset_list_begin_ext)( array );
+    return NS(BufferArrayObj_get_element_offset_list_begin)( array );
 }
 
 SIXTRL_BUFFER_DATAPTR_DEC NS(buffer_size_t) const*
@@ -81,7 +81,7 @@ NS(buffer_size_t) NS(BufferArrayObj_get_element_offset_ext)(
     SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferArrayObj) *const
         SIXTRL_RESTRICT array, NS(buffer_size_t) const index )
 {
-    return NS(BufferArrayObj_get_element_offset_ext)( array, index );
+    return NS(BufferArrayObj_get_element_offset)( array, index );
 }
 
 
diff --git a/sixtracklib/common/buffer/buffer_array_object.h b/sixtracklib/common/buffer/buffer_array_object.h
index e8094b27..051857dc 100644
--- a/sixtracklib/common/buffer/buffer_array_object.h
+++ b/sixtracklib/common/buffer/buffer_array_object.h
@@ -413,6 +413,10 @@ NS(BufferArrayObj_add_copy_ext)(
 /* *********         Implementation of Inline Functions          *********** */
 /* ************************************************************************* */
 
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/internal/objects_type_id.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
 SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(BufferArrayObj)*
 NS(BufferArrayObj_preset)( SIXTRL_BUFFER_DATAPTR_DEC
     NS(BufferArrayObj)* SIXTRL_RESTRICT array )
@@ -1157,14 +1161,14 @@ NS(BufferArrayObj_new)(
     array.offset_addr      = ( NS(buffer_addr_t) )0u;
     array.num_elements     = ( buf_size_t )0u;
     array.capacity         = capacity;
-    array.base_type_id     = NS(OBJECT_TYPE_ARRAY);
+    array.base_type_id     = NS(OBJECT_TYPE_BINARY_ARRAY);
     array.max_num_elements = max_nelements;
     array.slot_size        = NS(BUFFER_DEFAULT_SLOT_SIZE);
     array.base_type_id     = base_type_id;
 
     return ( ptr_array_t )( uintptr_t )NS(Object_get_begin_addr)(
         NS(Buffer_add_object)( buffer, &array, sizeof( array_t ),
-            NS(OBJECT_TYPE_ARRAY), nptrs,
+            NS(OBJECT_TYPE_BINARY_ARRAY), nptrs,
                 &offsets[ 0 ], &sizes[ 0 ], &counts[ 0 ] ) );
 }
 
diff --git a/sixtracklib/common/buffer/buffer_dev_debug.h b/sixtracklib/common/buffer/buffer_dev_debug.h
index cbf50290..0a67227d 100644
--- a/sixtracklib/common/buffer/buffer_dev_debug.h
+++ b/sixtracklib/common/buffer/buffer_dev_debug.h
@@ -69,5 +69,4 @@ SIXTRL_INLINE void NS(Buffer_disable_developer_debug_mode)(
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
-
-#endif /* SIXTRACKLIB_COMMON_BUFFER_BUFFER_DEV_DEBUG_H__ */
\ No newline at end of file
+#endif /* SIXTRACKLIB_COMMON_BUFFER_BUFFER_DEV_DEBUG_H__ */
diff --git a/sixtracklib/common/buffer/buffer_object.h b/sixtracklib/common/buffer/buffer_object.h
index b7369ea9..be078450 100644
--- a/sixtracklib/common/buffer/buffer_object.h
+++ b/sixtracklib/common/buffer/buffer_object.h
@@ -31,70 +31,70 @@ NS(Object);
 
 /* ========================================================================= */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)*
 NS(Object_preset)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT ob );
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_addr_t) NS(Object_get_begin_addr)(
+SIXTRL_STATIC SIXTRL_FN NS(buffer_addr_t) NS(Object_get_begin_addr)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT ob );
 
-SIXTRL_FN SIXTRL_STATIC void NS(Object_set_begin_addr)(
+SIXTRL_STATIC SIXTRL_FN void NS(Object_set_begin_addr)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT object,
     NS(buffer_addr_t) const begin_addr );
 
-SIXTRL_FN SIXTRL_STATIC  NS(object_type_id_t) NS(Object_get_type_id)(
+SIXTRL_STATIC SIXTRL_FN  NS(object_type_id_t) NS(Object_get_type_id)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT ob );
 
-SIXTRL_FN SIXTRL_STATIC  void NS(Object_set_type_id)(
+SIXTRL_STATIC SIXTRL_FN  void NS(Object_set_type_id)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT object,
     NS(object_type_id_t) const type_id );
 
-SIXTRL_FN SIXTRL_STATIC  NS(buffer_size_t) NS(Object_get_size)(
+SIXTRL_STATIC SIXTRL_FN  NS(buffer_size_t) NS(Object_get_size)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT ob );
 
-SIXTRL_FN SIXTRL_STATIC  void NS(Object_set_size)(
+SIXTRL_STATIC SIXTRL_FN  void NS(Object_set_size)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT ob,
     NS(buffer_size_t) const size );
 
-SIXTRL_FN SIXTRL_STATIC  void NS(Object_set_size_priv)(
+SIXTRL_STATIC SIXTRL_FN  void NS(Object_set_size_priv)(
     SIXTRL_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT ob,
     NS(buffer_size_t) const size );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_OBJ_DATAPTR_DEC unsigned char const*
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_OBJ_DATAPTR_DEC unsigned char const*
 NS(Object_get_const_begin_ptr)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
     NS(Object) *const SIXTRL_RESTRICT ob );
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_BUFFER_OBJ_DATAPTR_DEC unsigned char*
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_OBJ_DATAPTR_DEC unsigned char*
 NS(Object_get_begin_ptr)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT ob );
 
-SIXTRL_FN SIXTRL_STATIC void NS(Object_set_begin_ptr)(
+SIXTRL_STATIC SIXTRL_FN void NS(Object_set_begin_ptr)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT ob,
     SIXTRL_BUFFER_OBJ_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin_ptr );
 
 /* ========================================================================= */
 
-SIXTRL_FN SIXTRL_STATIC SIXTRL_ARGPTR_DEC NS(Object)*
+SIXTRL_STATIC SIXTRL_FN SIXTRL_ARGPTR_DEC NS(Object)*
 NS(Object_preset_priv)( SIXTRL_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT ob );
 
-SIXTRL_FN SIXTRL_STATIC  void NS(Object_set_size_priv)(
+SIXTRL_STATIC SIXTRL_FN  void NS(Object_set_size_priv)(
     SIXTRL_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT object,
     NS(buffer_size_t) const obj_size );
 
-SIXTRL_FN SIXTRL_STATIC  void NS(Object_set_begin_addr_priv)(
+SIXTRL_STATIC SIXTRL_FN  void NS(Object_set_begin_addr_priv)(
     SIXTRL_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT object,
     NS(buffer_addr_t) const address );
 
-SIXTRL_FN SIXTRL_STATIC  void NS(Object_set_type_id_priv)(
+SIXTRL_STATIC SIXTRL_FN  void NS(Object_set_type_id_priv)(
     SIXTRL_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT object,
     NS(object_type_id_t) const type_id );
 
-SIXTRL_FN SIXTRL_STATIC void NS(Object_set_begin_ptr_priv)(
+SIXTRL_STATIC SIXTRL_FN void NS(Object_set_begin_ptr_priv)(
     SIXTRL_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT ob,
     SIXTRL_BUFFER_OBJ_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin_ptr );
 
 /* ========================================================================= */
 
-SIXTRL_FN SIXTRL_STATIC void NS(Object_print_slots)(
+SIXTRL_STATIC SIXTRL_FN void NS(Object_print_slots)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj,
     NS(buffer_size_t) const num_slots_to_print );
 
diff --git a/sixtracklib/common/buffer/buffer_string_object.c b/sixtracklib/common/buffer/buffer_string_object.c
index 31aadad3..02cc5ca3 100644
--- a/sixtracklib/common/buffer/buffer_string_object.c
+++ b/sixtracklib/common/buffer/buffer_string_object.c
@@ -99,7 +99,7 @@ NS(buffer_size_t) NS(BufferStringObj_get_available_length_ext)(
     SIXTRL_BUFFER_DATAPTR_DEC const NS(BufferStringObj) *const
         SIXTRL_RESTRICT str_obj )
 {
-    return NS(BufferStringObj_get_available_length_ext)( str_obj );
+    return NS(BufferStringObj_get_available_length)( str_obj );
 }
 
 void NS(BufferStringObj_clear_ext)(
diff --git a/sixtracklib/common/buffer/buffer_type.h b/sixtracklib/common/buffer/buffer_type.h
index 62c4e9dd..f320577b 100644
--- a/sixtracklib/common/buffer/buffer_type.h
+++ b/sixtracklib/common/buffer/buffer_type.h
@@ -114,21 +114,12 @@ typedef SIXTRL_UINT64_T NS(object_type_id_t);
 
 #if !defined( _GPUCODE )
 
-SIXTRL_STATIC_VAR NS(object_type_id_t) const NS(OBJECT_TYPE_UNDEFINED) =
-    ( NS(object_type_id_t) )SIXTRL_OBJECT_TYPE_UNDEFINED;
-
 SIXTRL_STATIC_VAR NS(object_type_id_t) const
     NS(OBJECT_TYPE_FIRST_RESERVED_ID) = ( NS(object_type_id_t) )0x40000000;
 
 SIXTRL_STATIC_VAR NS(object_type_id_t) const
     NS(OBJECT_TYPE_MANAGED_BUFFER_HANDLE) = ( NS(object_type_id_t) )0x40000000;
 
-SIXTRL_STATIC_VAR NS(object_type_id_t) const
-    NS(OBJECT_TYPE_CSTRING) = ( NS(object_type_id_t) )0x40000001;
-
-SIXTRL_STATIC_VAR NS(object_type_id_t) const
-    NS(OBJECT_TYPE_ARRAY) = ( NS(object_type_id_t) )0x40000002;
-
 /* ------------------------------------------------------------------------- */
 
 SIXTRL_STATIC_VAR NS(buffer_flags_t) const NS(BUFFER_FLAGS_NONE) =
@@ -235,10 +226,6 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
-        OBJECT_TYPE_UNDEFINED = static_cast< object_type_id_t >(
-            SIXTRL_OBJECT_TYPE_UNDEFINED );
-
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
         OBJECT_TYPE_FIRST_RESERVED_ID =
             static_cast< object_type_id_t >( 0x40000000 );
@@ -247,12 +234,6 @@ namespace SIXTRL_CXX_NAMESPACE
         OBJECT_TYPE_MANAGED_BUFFER_HANDLE =
             static_cast< object_type_id_t >( 0x40000000 );
 
-    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
-        OBJECT_TYPE_CSTRING = static_cast< object_type_id_t >( 0x40000001 );
-
-    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
-        OBJECT_TYPE_ARRAY = static_cast< object_type_id_t >( 0x40000002 );
-
     /* --------------------------------------------------------------------- */
 
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST buffer_flags_t
diff --git a/sixtracklib/common/buffer/managed_buffer.h b/sixtracklib/common/buffer/managed_buffer.h
index 5d653707..dc6839f5 100644
--- a/sixtracklib/common/buffer/managed_buffer.h
+++ b/sixtracklib/common/buffer/managed_buffer.h
@@ -11,6 +11,7 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/internal/buffer_main_defines.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
@@ -21,32 +22,32 @@ extern "C" {
 
 /* ------------------------------------------------------------------------- */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t)
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
 NS(ManagedBuffer_calculate_section_size)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT begin,
     NS(buffer_size_t) const header_section_id,
     NS(buffer_size_t) const num_entities,
     NS(buffer_size_t) const slot_size );
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t)
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
 NS(ManagedBuffer_get_section_offset)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin,
     NS(buffer_size_t) const header_section_id,
     NS(buffer_size_t) const slot_size );
 
-SIXTRL_FN SIXTRL_STATIC void NS(ManagedBuffer_set_section_num_entities)(
+SIXTRL_STATIC SIXTRL_FN void NS(ManagedBuffer_set_section_num_entities)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin,
     NS(buffer_size_t) const section_id,
     NS(buffer_size_t) const num_entities,
     NS(buffer_size_t) const slot_size );
 
-SIXTRL_FN SIXTRL_STATIC void NS(ManagedBuffer_set_section_max_size)(
+SIXTRL_STATIC SIXTRL_FN void NS(ManagedBuffer_set_section_max_size)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin,
     NS(buffer_size_t) const section_id,
     NS(buffer_size_t) const max_section_size,
     NS(buffer_size_t) const slot_size );
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t)
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
 NS(ManagedBuffer_predict_required_num_slots)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT begin,
     NS(buffer_size_t) const obj_handle_size,
@@ -58,7 +59,7 @@ NS(ManagedBuffer_predict_required_num_slots)(
 
 /* ========================================================================= */
 
-SIXTRL_FN SIXTRL_STATIC NS(buffer_size_t)
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
 NS(ManagedBuffer_calculate_buffer_length)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin,
     NS(buffer_size_t) const max_num_objects,
@@ -67,7 +68,7 @@ NS(ManagedBuffer_calculate_buffer_length)(
     NS(buffer_size_t) const max_num_garbage_ranges,
     NS(buffer_size_t) const slot_size );
 
-SIXTRL_FN SIXTRL_STATIC bool NS(ManagedBuffer_can_reserve)(
+SIXTRL_STATIC SIXTRL_FN bool NS(ManagedBuffer_can_reserve)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
         SIXTRL_RESTRICT ptr_requ_buffer_len,
@@ -78,7 +79,7 @@ SIXTRL_FN SIXTRL_STATIC bool NS(ManagedBuffer_can_reserve)(
     NS(buffer_size_t) const max_num_garbage_ranges,
     NS(buffer_size_t) const slot_size );
 
-SIXTRL_FN SIXTRL_STATIC int NS(ManagedBuffer_reserve)(
+SIXTRL_STATIC SIXTRL_FN int NS(ManagedBuffer_reserve)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
         SIXTRL_RESTRICT ptr_new_buffer_length,
@@ -91,7 +92,7 @@ SIXTRL_FN SIXTRL_STATIC int NS(ManagedBuffer_reserve)(
 
 /* ========================================================================= */
 
-SIXTRL_FN SIXTRL_STATIC int NS(ManagedBuffer_init)(
+SIXTRL_STATIC SIXTRL_FN int NS(ManagedBuffer_init)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin,
     SIXTRL_BUFFER_ARGPTR_DEC NS(buffer_size_t)*
         SIXTRL_RESTRICT ptr_buffer_length,
@@ -104,16 +105,25 @@ SIXTRL_FN SIXTRL_STATIC int NS(ManagedBuffer_init)(
 
 /* ========================================================================= */
 
-SIXTRL_FN SIXTRL_STATIC void NS(ManagedBuffer_clear)(
+SIXTRL_STATIC SIXTRL_FN void NS(ManagedBuffer_clear)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT begin,
     bool const set_data_to_zero, NS(buffer_size_t) const slot_size );
 
-/* ========================================================================= */
-
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
 
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
+NS(Buffer_set_attr_arrays_for_trivial_object)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT attr_begin,
+    NS(buffer_size_t) const max_num_attributes,
+    NS(buffer_size_t) const slot_size );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(Buffer_num_slots_for_trivial_object)( NS(buffer_size_t) const
+    obj_handle_size, NS(buffer_size_t) const slot_size );
+
 /* ========================================================================= *
  * ======== INLINE IMPLEMENTATION                                            *
  * ========================================================================= */
@@ -1092,6 +1102,45 @@ SIXTRL_INLINE void NS(ManagedBuffer_clear)(
 }
 #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
 
+SIXTRL_INLINE NS(buffer_size_t) NS(Buffer_num_slots_for_trivial_object)(
+    NS(buffer_size_t) const obj_handle_size, NS(buffer_size_t) const slot_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    buf_size_t num_slots = ( buf_size_t )0u;
+
+    if( ( slot_size > ( buf_size_t )0u ) &&
+        ( obj_handle_size > ( buf_size_t )0u ) )
+    {
+        buf_size_t const data_size = NS(ManagedBuffer_get_slot_based_length)(
+            obj_handle_size, slot_size );
+
+        num_slots = data_size / slot_size;
+        if( ( num_slots * slot_size ) < data_size ) ++num_slots;
+        SIXTRL_ASSERT( ( num_slots * slot_size ) >= data_size );
+    }
+
+    return num_slots;
+}
+
+
+SIXTRL_INLINE NS(arch_status_t) NS(Buffer_set_attr_arrays_for_trivial_object)(
+    SIXTRL_ARGPTR_DEC NS(buffer_size_t)* SIXTRL_RESTRICT attr_begin,
+    NS(buffer_size_t) const max_num_attributes,
+    NS(buffer_size_t) const slot_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+    SIXTRL_STATIC_VAR buf_size_t const ZERO = ( buf_size_t )0u;
+    ( void )slot_size;
+
+    if( ( attr_begin != SIXTRL_NULLPTR ) && ( max_num_attributes > ZERO ) )
+    {
+        SIXTRACKLIB_SET_VALUES(
+            buf_size_t, attr_begin, max_num_attributes, ZERO );
+    }
+
+    return SIXTRL_ARCH_STATUS_SUCCESS;
+}
+
 #endif /* SIXTRL_COMMON_BUFFER_BUFFER_MEM_H__ */
 
 /*end: sixtracklib/common/buffer/managed_buffer.h */
diff --git a/sixtracklib/common/buffer/mem_pool.c b/sixtracklib/common/buffer/mem_pool.c
index db97c344..ce3a1ccf 100644
--- a/sixtracklib/common/buffer/mem_pool.c
+++ b/sixtracklib/common/buffer/mem_pool.c
@@ -44,11 +44,11 @@ SIXTRL_STATIC void NS( MemPool_set_buffer )(
     SIXTRL_GLOBAL_DEC unsigned char* new_buffer );
 
 SIXTRL_STATIC void NS( MemPool_set_begin_pos )(
-    NS( MemPool )* SIXTRL_RESTRICT SIXTRL_RESTRICT pool,
+    NS( MemPool )* SIXTRL_RESTRICT pool,
     SIXTRL_GLOBAL_DEC unsigned char* SIXTRL_RESTRICT begin_pos );
 
 SIXTRL_STATIC void NS( MemPool_set_begin_offset )(
-    NS( MemPool )* SIXTRL_RESTRICT SIXTRL_RESTRICT pool,
+    NS( MemPool )* SIXTRL_RESTRICT pool,
     SIXTRL_UINT64_T const begin_offset );
 
 /* ========================================================================= */
@@ -281,7 +281,7 @@ void NS( MemPool_set_buffer )( NS( MemPool ) * SIXTRL_RESTRICT pool,
 /* -------------------------------------------------------------------------- */
 
 void NS( MemPool_set_begin_pos )(
-    NS( MemPool )* SIXTRL_RESTRICT SIXTRL_RESTRICT pool,
+    NS( MemPool )* SIXTRL_RESTRICT pool,
     SIXTRL_GLOBAL_DEC unsigned char* SIXTRL_RESTRICT begin_pos )
 {
     if( pool != 0 ) pool->begin_pos = begin_pos;
@@ -290,8 +290,7 @@ void NS( MemPool_set_begin_pos )(
 
 /* -------------------------------------------------------------------------- */
 
-void NS( MemPool_set_begin_offset )(
-    NS( MemPool )* SIXTRL_RESTRICT SIXTRL_RESTRICT pool,
+void NS( MemPool_set_begin_offset )( NS( MemPool )* SIXTRL_RESTRICT pool,
     SIXTRL_UINT64_T const begin_offset )
 {
     if( pool != 0 ) pool->begin_offset = begin_offset;
diff --git a/sixtracklib/common/context/CMakeLists.txt b/sixtracklib/common/context/CMakeLists.txt
index 563bf947..302c5d7a 100644
--- a/sixtracklib/common/context/CMakeLists.txt
+++ b/sixtracklib/common/context/CMakeLists.txt
@@ -1,47 +1,35 @@
-set( SIXTRL_COMMON_CONTEXT_C99_HEADERS
-     compute_arch.h
-     definitions.h
-)
-
-set( SIXTRL_COMMON_CONTEXT_C99_SOURCES
-    compute_arch.c
-)
+set( SIXTRL_COMMON_CONTEXT_C99_HEADERS compute_arch.h definitions.h )
+set( SIXTRL_COMMON_CONTEXT_C99_SOURCES compute_arch.c )
+set( SIXTRL_COMMON_CONTEXT_CXX_HEADERS )
 
 add_library( sixtrack_common_context OBJECT
-    ${SIXTRL_COMMON_CONTEXT_C99_HEADERS}
-    ${SIXTRL_COMMON_CONTEXT_C99_SOURCES}
-)
+    ${SIXTRL_COMMON_CONTEXT_C99_HEADERS} ${SIXTRL_COMMON_CONTEXT_C99_SOURCES} )
 
 target_include_directories( sixtrack_common_context PRIVATE
-    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
-    $<INSTALL_INTERFACE:include> )
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-set_target_properties( sixtrack_common_context PROPERTIES LINKER_LANGUAGE C )
-set_target_properties( sixtrack_common_context PROPERTIES POSITION_INDEPENDENT_CODE ON )
-set_target_properties( sixtrack_common_context PROPERTIES C_STANDARD 99 )
-set_target_properties( sixtrack_common_context PROPERTIES C_STANDARD_REQUIRED ON )
+set_target_properties( sixtrack_common_context PROPERTIES LINKER_LANGUAGE C
+    POSITION_INDEPENDENT_CODE ON C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_context PRIVATE
-    -Wall -Werror -pedantic -ansi ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_internal as a module for sixtracklib:
 
-set(  SIXTRACKL_LIBRARY_MODULES
-    ${SIXTRACKL_LIBRARY_MODULES}
-    $<TARGET_OBJECTS:sixtrack_common_context>
-    CACHE INTERNAL "" FORCE )
+set( SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_common_context> CACHE INTERNAL "" FORCE )
 
 # -----------------------------------------------------------------------------
 # install :
 
-set( SIXTRACKLIB_COMMON_CONTEXT_INSTALL_PATH
-     include/sixtracklib/common/context )
-
 if( SIXTRL_COMMON_CONTEXT_C99_HEADERS )
     install( FILES ${SIXTRL_COMMON_CONTEXT_C99_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_CONTEXT_INSTALL_PATH} )
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/context" )
 endif()
 
-#end: sixtracklib/common/buffer/CMakeLists.txt
-
+if( SIXTRACKL_ENABLE_CXX AND SIXTRL_COMMON_CONTEXT_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_CONTEXT_CXX_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/context" )
+endif()
diff --git a/sixtracklib/common/context/compute_arch.c b/sixtracklib/common/context/compute_arch.c
index 96bd8a64..4b30bfd0 100644
--- a/sixtracklib/common/context/compute_arch.c
+++ b/sixtracklib/common/context/compute_arch.c
@@ -12,97 +12,329 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
-#if !defined( GPUCODE )
+NS(ComputeNodeId)* NS(ComputeNodeId_create)( void )
+{
+    return NS(ComputeNodeId_preset)( ( NS(ComputeNodeId)* )malloc(
+        sizeof( NS(ComputeNodeId) ) ) );
+}
 
-int NS(ComputeNodeId_to_string)(
-    const NS(ComputeNodeId) *const SIXTRL_RESTRICT id,
-    char* SIXTRL_RESTRICT str_buffer,
-    SIXTRL_UINT64_T const str_buffer_capacity )
+void NS(ComputeNodeId_delete)( NS(ComputeNodeId)* SIXTRL_RESTRICT node_id )
 {
-    int success = -1;
+    free( node_id );
+}
 
-    char temp[ 64 ];
-    memset( &temp[ 0 ], ( int )'\0', 64 );
+NS(comp_node_id_num_t) NS(ComputeNodeId_get_platform_id_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT id )
+{
+    return NS(ComputeNodeId_get_platform_id)( id );
+}
 
-    if( ( str_buffer != SIXTRL_NULLPTR ) &&
-        ( str_buffer_capacity > 0u ) &&
-        ( id != SIXTRL_NULLPTR ) &&
-        ( NS(ComputeNodeId_get_platform_id)( id ) >= 0 ) &&
-        ( NS(ComputeNodeId_get_device_id)( id )   >= 0 ) )
-    {
-        memset( str_buffer, ( int )'\0', str_buffer_capacity );
+NS(comp_node_id_num_t) NS(ComputeNodeId_get_device_id_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT id )
+{
+    return NS(ComputeNodeId_get_device_id)( id );
+}
 
-        sprintf( &temp[ 0 ], "%d.%d",
-                 ( int )NS(ComputeNodeId_get_platform_id)( id ),
-                 ( int )NS(ComputeNodeId_get_device_id)( id ) );
+void NS(ComputeNodeId_set_platform_id_ext)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT id,
+    NS(comp_node_id_num_t) const platform_id )
+{
+    NS(ComputeNodeId_set_platform_id)( id, platform_id );
+}
 
-        strncpy( str_buffer, &temp[ 0 ], str_buffer_capacity - 1 );
-        success = ( strlen( str_buffer ) > 0 ) ? 0 : -1;
-    }
+void NS(ComputeNodeId_set_device_id_ext)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT id,
+    NS(comp_node_id_num_t) const device_id )
+{
+    NS(ComputeNodeId_set_device_id)( id, device_id );
+}
 
-    return success;
+bool NS(ComputeNodeId_is_valid_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT id )
+{
+    return NS(ComputeNodeId_is_valid)( id );
+}
+
+int NS(ComputeNodeId_compare_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT lhs,
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT rhs )
+{
+    return NS(ComputeNodeId_compare)( lhs, rhs );
+}
+
+bool NS(ComputeNodeId_are_equal_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT lhs,
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT rhs )
+{
+    return NS(ComputeNodeId_are_equal)( lhs, rhs );
 }
 
-int NS(ComputeNodeId_from_string)( NS(ComputeNodeId)* SIXTRL_RESTRICT id,
+#if !defined( GPUCODE )
+
+NS(arch_status_t) NS(ComputeNodeId_from_string)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT node_id,
     char const* SIXTRL_RESTRICT str_buffer )
 {
-    int success = -1;
+    return NS(ComputeNodeId_from_string_with_format)(
+        node_id, str_buffer, NS(NODE_ID_STR_FORMAT_NOARCH), SIXTRL_NULLPTR );
+}
+
+NS(arch_status_t) NS(ComputeNodeId_from_string_with_format)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT id,
+    char const* SIXTRL_RESTRICT str_buffer,
+    NS(node_id_str_fmt_t) const node_id_str_fmt,
+    NS(arch_id_t)* SIXTRL_RESTRICT ptr_arch_id )
+{
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
 
     if( ( str_buffer != SIXTRL_NULLPTR ) &&
         ( strlen( str_buffer ) > 0u ) &&
-        ( id != SIXTRL_NULLPTR ) )
+        ( id != SIXTRL_NULLPTR ) &&
+        ( node_id_str_fmt != NS(NODE_ID_STR_FORMAT_ILLEGAL) ) )
     {
+        int num_parsed_elem = 0;
+        int required_num_parsed_elem = 1;
+
         int temp_platform_idx = -1;
         int temp_device_idx   = -1;
 
-        int const ret = sscanf( str_buffer, "%d.%d",
-                                &temp_platform_idx, &temp_device_idx );
+        long long unsigned temp_arch_id =
+            ( long long unsigned )SIXTRL_ARCHITECTURE_ILLEGAL;
 
-        if( ( ret == 2 ) && ( temp_platform_idx >= 0 ) &&
-            ( temp_device_idx >= 0 ) )
+        if( node_id_str_fmt == NS(NODE_ID_STR_FORMAT_NOARCH) )
+        {
+            required_num_parsed_elem = 2;
+            num_parsed_elem = sscanf( str_buffer, "%d.%d",
+                &temp_platform_idx, &temp_device_idx );
+        }
+        else if( node_id_str_fmt == NS(NODE_ID_STR_FORMAT_ARCHID) )
+        {
+            required_num_parsed_elem = 3;
+            num_parsed_elem = sscanf( str_buffer, "%llu:%d.%d",
+                &temp_arch_id, &temp_platform_idx, &temp_device_idx );
+        }
+        else if( node_id_str_fmt == NS(NODE_ID_STR_FORMAT_ARCHSTR) )
+        {
+            char TEMP_ARCH_NAME[ 32 ] =
+            {
+                '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+            };
+
+            required_num_parsed_elem = 3;
+            num_parsed_elem = sscanf( str_buffer, "%31[^:]:%d.%d",
+                TEMP_ARCH_NAME, &temp_platform_idx, &temp_device_idx );
+
+            if( num_parsed_elem > 0 )
+            {
+                if( strncmp( TEMP_ARCH_NAME,
+                             SIXTRL_ARCHITECTURE_CPU_STR, 31 ) == 0 )
+                {
+                    temp_arch_id = ( long long unsigned
+                        )SIXTRL_ARCHITECTURE_CPU;
+                }
+                else if( strncmp( TEMP_ARCH_NAME,
+                        SIXTRL_ARCHITECTURE_OPENCL_STR, 31 ) == 0 )
+                {
+                    temp_arch_id = ( long long unsigned
+                        )SIXTRL_ARCHITECTURE_OPENCL;
+                }
+                else if( strncmp( TEMP_ARCH_NAME,
+                        SIXTRL_ARCHITECTURE_CUDA_STR, 31 ) == 0 )
+                {
+                    temp_arch_id = ( long long unsigned
+                        )SIXTRL_ARCHITECTURE_CUDA;
+                }
+                else
+                {
+                    temp_arch_id = ( long long unsigned
+                        )SIXTRL_ARCHITECTURE_ILLEGAL;
+                }
+            }
+        }
+
+        if( ( num_parsed_elem == required_num_parsed_elem ) &&
+            ( temp_platform_idx >= 0 ) && ( temp_device_idx >= 0 ) )
         {
             NS(ComputeNodeId_set_platform_id)( id, temp_platform_idx );
             NS(ComputeNodeId_set_device_id)( id, temp_device_idx );
 
-            success = 0;
+            if( ptr_arch_id != SIXTRL_NULLPTR )
+            {
+                *ptr_arch_id = ( NS(arch_id_t) )temp_arch_id;
+            }
+
+            status = NS(ARCH_STATUS_SUCCESS);
         }
     }
 
-    return success;
+    return status;
 }
 
-#endif /* !defined( _GPUCODE ) */
+NS(arch_status_t) NS(ComputeNodeId_to_string)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT node_id,
+    char* SIXTRL_RESTRICT out_string_begin,
+    NS(arch_size_t) const out_string_capacity )
+{
+    return NS(ComputeNodeId_to_string_with_format)(
+        node_id, out_string_begin, out_string_capacity, NS(ARCHITECTURE_NONE),
+            NS(NODE_ID_STR_FORMAT_NOARCH) );
+}
 
-NS(ComputeNodeId)* NS(ComputeNodeId_preset)(
-    NS(ComputeNodeId)* SIXTRL_RESTRICT id )
+NS(arch_status_t) NS(ComputeNodeId_to_string_with_format)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT node_id,
+    char* SIXTRL_RESTRICT out_string_begin,
+    NS(arch_size_t) const out_string_capacity,
+    NS(arch_id_t) const arch_id, NS(node_id_str_fmt_t) const node_id_str_fmt )
 {
-    if( id != 0 )
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+
+    if( ( node_id != SIXTRL_NULLPTR ) &&
+        ( NS(ComputeNodeId_is_valid)( node_id ) ) &&
+        ( out_string_begin != SIXTRL_NULLPTR ) &&
+        ( out_string_capacity > ( NS(arch_size_t) )0u ) &&
+        ( node_id_str_fmt != NS(NODE_ID_STR_FORMAT_ILLEGAL) ) )
     {
-        id->platform_id = -1;
-        id->device_id   = -1;
+        int ret = 0;
+        memset( out_string_begin, ( int )'\0', out_string_capacity );
+
+        SIXTRL_ASSERT( NS(ComputeNodeId_get_platform_id)( node_id ) >= 0 );
+        SIXTRL_ASSERT( NS(ComputeNodeId_get_device_id)( node_id ) >= 0 );
+
+        if( node_id_str_fmt == NS(NODE_ID_STR_FORMAT_NOARCH) )
+        {
+            ret = snprintf( out_string_begin, out_string_capacity, "%u.%u",
+                ( unsigned )NS(ComputeNodeId_get_platform_id)( node_id ),
+                ( unsigned )NS(ComputeNodeId_get_device_id)( node_id ) );
+
+            if( ( ret >= 0 ) &&
+                ( out_string_capacity > ( NS(arch_size_t) )ret ) )
+            {
+                status = NS(ARCH_STATUS_SUCCESS);
+            }
+        }
+        else if( ( node_id_str_fmt == NS(NODE_ID_STR_FORMAT_ARCHID) ) &&
+                 ( arch_id != NS(ARCHITECTURE_ILLEGAL) ) &&
+                 ( arch_id != NS(ARCHITECTURE_NONE) ) )
+        {
+            ret = snprintf( out_string_begin, out_string_capacity, "%llu:%u.%u",
+                ( long long unsigned )arch_id,
+                ( unsigned )NS(ComputeNodeId_get_platform_id)( node_id ),
+                ( unsigned )NS(ComputeNodeId_get_device_id)( node_id ) );
+
+            if( ( ret >= 0 ) &&
+                ( out_string_capacity > ( NS(arch_size_t) )ret ) )
+            {
+                status = NS(ARCH_STATUS_SUCCESS);
+            }
+        }
+        else if( ( node_id_str_fmt == NS(NODE_ID_STR_FORMAT_ARCHSTR) ) &&
+                 ( arch_id != NS(ARCHITECTURE_ILLEGAL) ) &&
+                 ( arch_id != NS(ARCHITECTURE_NONE) ) )
+        {
+            char TEMP_ARCH_NAME[ 32 ] =
+            {
+                '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+            };
+
+            if( arch_id == NS(ARCHITECTURE_CPU) )
+            {
+                strcpy( TEMP_ARCH_NAME, SIXTRL_ARCHITECTURE_CPU_STR );
+            }
+            else if( arch_id == NS(ARCHITECTURE_OPENCL) )
+            {
+                strcpy( TEMP_ARCH_NAME, SIXTRL_ARCHITECTURE_OPENCL_STR );
+            }
+            else if( arch_id == NS(ARCHITECTURE_CUDA) )
+            {
+                strcpy( TEMP_ARCH_NAME, SIXTRL_ARCHITECTURE_CUDA_STR );
+            }
+
+            ret = snprintf( out_string_begin, out_string_capacity, "%s:%u.%u",
+                    TEMP_ARCH_NAME,
+                    ( unsigned )NS(ComputeNodeId_get_platform_id)( node_id ),
+                    ( unsigned )NS(ComputeNodeId_get_device_id)( node_id ) );
+
+            if( ( ret >= 0 ) &&
+                ( out_string_capacity > ( NS(arch_size_t) )ret ) )
+            {
+                status = NS(ARCH_STATUS_SUCCESS);
+            }
+        }
     }
 
-    return id;
+    return status;
 }
 
-NS(ComputeNodeInfo)* NS(ComputeNodeInfo_preset)(
+#endif /* !defined( _GPUCODE ) */
+
+/* ------------------------------------------------------------------------- */
+
+NS(ComputeNodeInfo)* NS(ComputeNodeInfo_preset_ext)(
     NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info )
 {
-    if( node_info != 0 )
-    {
-        NS(ComputeNodeId_preset)( &node_info->id );
-        node_info->arch        = 0;
-        node_info->platform    = 0;
-        node_info->name        = 0;
-        node_info->description = 0;
-    }
+    return NS(ComputeNodeInfo_preset)( node_info );
+}
+
+bool NS(ComputeNodeInfo_is_valid_ext)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
+{
+    return NS(ComputeNodeInfo_is_valid)( node_info );
+}
+
+NS(ComputeNodeId) NS(ComputeNodeInfo_get_id_ext)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
+{
+    return NS(ComputeNodeInfo_get_id)( node_info );
+}
 
-    return node_info;
+NS(comp_node_id_num_t) NS(ComputeNodeInfo_get_platform_id_ext)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
+{
+    return NS(ComputeNodeInfo_get_platform_id)( node_info );
+}
+
+NS(comp_node_id_num_t) NS(ComputeNodeInfo_get_device_id_ext)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
+{
+    return NS(ComputeNodeInfo_get_device_id)( node_info );
 }
 
-SIXTRL_HOST_FN void NS(ComputeNodeInfo_free)(
+char const* NS(ComputeNodeInfo_get_arch_ext)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
+{
+    return NS(ComputeNodeInfo_get_arch)( node_info );
+}
+
+char const* NS(ComputeNodeInfo_get_platform_ext)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
+{
+    return NS(ComputeNodeInfo_get_platform)( node_info );
+}
+
+char const* NS(ComputeNodeInfo_get_name_ext)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
+{
+    return NS(ComputeNodeInfo_get_name)( node_info );
+}
+
+char const* NS(ComputeNodeInfo_get_description_ext)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
+{
+    return NS(ComputeNodeInfo_get_description)( node_info );
+}
+
+#if !defined( _GPUCODE )
+
+void NS(ComputeNodeInfo_free)(
     NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info )
 {
     free( ( char* )NS(ComputeNodeInfo_get_arch)( node_info ) );
@@ -111,20 +343,26 @@ SIXTRL_HOST_FN void NS(ComputeNodeInfo_free)(
     free( ( char* )NS(ComputeNodeInfo_get_description)( node_info ) );
 
     NS(ComputeNodeInfo_preset)( node_info );
+}
 
-    return;
+void NS(ComputeNodeInfo_delete)(
+    NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info )
+{
+    NS(ComputeNodeInfo_free)( node_info );
+    free( node_info );
 }
 
-SIXTRL_HOST_FN NS(ComputeNodeInfo)* NS(ComputeNodeInfo_reserve)(
+NS(ComputeNodeInfo)* NS(ComputeNodeInfo_reserve)(
     NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info,
     SIXTRL_SIZE_T const arch_str_len,
     SIXTRL_SIZE_T const platform_str_len,
     SIXTRL_SIZE_T const name_str_len,
     SIXTRL_SIZE_T const description_str_len )
 {
-    NS(ComputeNodeInfo)* ptr_result = 0;
+    NS(ComputeNodeInfo)* ptr_result = SIXTRL_NULLPTR;
 
-    if( ( node_info != 0 ) && ( arch_str_len > 0u ) && ( name_str_len > 0u ) )
+    if( ( node_info != SIXTRL_NULLPTR ) &&
+        ( arch_str_len > 0u ) && ( name_str_len > 0u ) )
     {
         size_t const arch_size = sizeof( char ) * ( arch_str_len + 1u );
         char* arch_str = ( char* )malloc( arch_size );
@@ -132,8 +370,8 @@ SIXTRL_HOST_FN NS(ComputeNodeInfo)* NS(ComputeNodeInfo_reserve)(
         size_t const name_size = sizeof( char ) * ( name_str_len + 1u );
         char* name_str = ( char* )malloc( name_size );
 
-        char* platform_str = 0;
-        char* description_str = 0;
+        char* platform_str = SIXTRL_NULLPTR;
+        char* description_str = SIXTRL_NULLPTR;
 
         if( platform_str_len > 0u )
         {
@@ -142,7 +380,7 @@ SIXTRL_HOST_FN NS(ComputeNodeInfo)* NS(ComputeNodeInfo_reserve)(
 
             platform_str = ( char* )malloc( platform_size );
 
-            if( platform_str != 0 )
+            if( platform_str != SIXTRL_NULLPTR )
             {
                 memset( platform_str, ( int )'\0', platform_size );
             }
@@ -155,15 +393,17 @@ SIXTRL_HOST_FN NS(ComputeNodeInfo)* NS(ComputeNodeInfo_reserve)(
 
             description_str = ( char* )malloc( description_size );
 
-            if( description_str != 0 )
+            if( description_str != SIXTRL_NULLPTR )
             {
                 memset( description_str, ( int )'\0', description_size );
             }
         }
 
-        if( ( arch_str != 0 ) && ( name_str != 0 ) &&
-            ( ( platform_str_len    == 0u ) || ( platform_str    != 0 ) ) &&
-            ( ( description_str_len == 0u ) || ( description_str != 0 ) ) )
+        if( ( arch_str != 0 ) && ( name_str != SIXTRL_NULLPTR ) &&
+            ( ( platform_str_len    == 0u ) ||
+              ( platform_str    != SIXTRL_NULLPTR ) ) &&
+            ( ( description_str_len == 0u ) ||
+              ( description_str != SIXTRL_NULLPTR ) ) )
         {
             NS(ComputeNodeInfo_free)( node_info );
 
@@ -184,17 +424,17 @@ SIXTRL_HOST_FN NS(ComputeNodeInfo)* NS(ComputeNodeInfo_reserve)(
             free( platform_str );
             free( description_str );
 
-            arch_str        = 0;
-            name_str        = 0;
-            platform_str    = 0;
-            description_str = 0;
+            arch_str        = SIXTRL_NULLPTR;
+            name_str        = SIXTRL_NULLPTR;
+            platform_str    = SIXTRL_NULLPTR;
+            description_str = SIXTRL_NULLPTR;
         }
     }
 
     return ptr_result;
 }
 
-SIXTRL_HOST_FN int NS(ComputeNodeInfo_make)(
+int NS(ComputeNodeInfo_make)(
     NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info,
     NS(ComputeNodeId) const id,
     const char *const SIXTRL_RESTRICT arch_str,
@@ -260,7 +500,6 @@ SIXTRL_HOST_FN int NS(ComputeNodeInfo_make)(
 }
 
 
-#if !defined( _GPUCODE )
 
 void NS(ComputeNodeInfo_print)(
     FILE* SIXTRL_RESTRICT fp,
@@ -322,8 +561,6 @@ void NS(ComputeNodeInfo_print)(
 
         fprintf( fp, "\r\n" );
     }
-
-    return;
 }
 
 void NS(ComputeNodeInfo_print_out)(
@@ -331,7 +568,6 @@ void NS(ComputeNodeInfo_print_out)(
     const NS(ComputeNodeId)   *const SIXTRL_RESTRICT default_node_id )
 {
     NS(ComputeNodeInfo_print)( stdout, node_info, default_node_id );
-    return;
 }
 
 NS(arch_status_t) NS(ComputeNodeInfo_print_to_str)(
diff --git a/sixtracklib/common/context/compute_arch.h b/sixtracklib/common/context/compute_arch.h
index af8b5fa1..26d916d9 100644
--- a/sixtracklib/common/context/compute_arch.h
+++ b/sixtracklib/common/context/compute_arch.h
@@ -44,50 +44,95 @@ SIXTRL_FN SIXTRL_STATIC bool operator<(
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(ComputeNodeId)* NS(ComputeNodeId_preset)(
+SIXTRL_STATIC SIXTRL_FN NS(ComputeNodeId)* NS(ComputeNodeId_preset)(
     NS(ComputeNodeId)* SIXTRL_RESTRICT id );
 
-SIXTRL_HOST_FN SIXTRL_STATIC NS(comp_node_id_num_t)
+SIXTRL_STATIC SIXTRL_FN NS(comp_node_id_num_t)
 NS(ComputeNodeId_get_platform_id)(
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT id );
 
-SIXTRL_HOST_FN SIXTRL_STATIC NS(comp_node_id_num_t)
+SIXTRL_STATIC SIXTRL_FN NS(comp_node_id_num_t)
 NS(ComputeNodeId_get_device_id)(
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT id );
 
-SIXTRL_HOST_FN SIXTRL_STATIC void NS(ComputeNodeId_set_platform_id)(
+SIXTRL_STATIC SIXTRL_FN void NS(ComputeNodeId_set_platform_id)(
     NS(ComputeNodeId)* SIXTRL_RESTRICT id,
     NS(comp_node_id_num_t) const platform_id );
 
-SIXTRL_HOST_FN SIXTRL_STATIC void NS(ComputeNodeId_set_device_id)(
+SIXTRL_STATIC SIXTRL_FN void NS(ComputeNodeId_set_device_id)(
     NS(ComputeNodeId)* SIXTRL_RESTRICT id,
     NS(comp_node_id_num_t) const device_id );
 
-SIXTRL_HOST_FN SIXTRL_STATIC int NS(ComputeNodeId_is_valid)(
+SIXTRL_STATIC SIXTRL_FN bool NS(ComputeNodeId_is_valid)(
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT id );
 
-SIXTRL_HOST_FN SIXTRL_STATIC int NS(ComputeNodeId_compare)(
+SIXTRL_STATIC SIXTRL_FN int NS(ComputeNodeId_compare)(
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT lhs,
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT rhs );
 
-SIXTRL_HOST_FN SIXTRL_STATIC bool NS(ComputeNodeId_are_equal)(
+SIXTRL_STATIC SIXTRL_FN bool NS(ComputeNodeId_are_equal)(
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT lhs,
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT rhs );
 
 #if !defined( GPUCODE )
 
-SIXTRL_HOST_FN int NS(ComputeNodeId_to_string)(
-    const NS(ComputeNodeId) *const SIXTRL_RESTRICT id,
-    char* SIXTRL_RESTRICT str_buffer,
-    SIXTRL_UINT64_T const str_buffer_capacity );
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ComputeNodeId)*
+    NS(ComputeNodeId_create)( void );
 
-SIXTRL_HOST_FN int NS(ComputeNodeId_from_string)(
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ComputeNodeId_delete)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT node_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(comp_node_id_num_t)
+NS(ComputeNodeId_get_platform_id_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(comp_node_id_num_t)
+NS(ComputeNodeId_get_device_id_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ComputeNodeId_set_platform_id_ext)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT id,
+    NS(comp_node_id_num_t) const platform_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ComputeNodeId_set_device_id_ext)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT id,
+    NS(comp_node_id_num_t) const device_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ComputeNodeId_is_valid_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN int NS(ComputeNodeId_compare_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT lhs,
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ComputeNodeId_are_equal_ext)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT lhs,
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(ComputeNodeId_from_string)(
     NS(ComputeNodeId)* SIXTRL_RESTRICT id,
     char const* SIXTRL_RESTRICT str_buffer );
 
-#endif /* !defined( _GPUCODE ) */
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(ComputeNodeId_to_string)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT node_id,
+    char* SIXTRL_RESTRICT out_string_begin,
+    NS(arch_size_t) const max_out_string_capacity );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(ComputeNodeId_to_string_with_format)(
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT node_id,
+    char* SIXTRL_RESTRICT out_string_begin,
+    NS(arch_size_t) const out_string_capacity,
+    NS(arch_id_t) const arch_id, NS(node_id_str_fmt_t) const node_id_str_fmt );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(ComputeNodeId_from_string_with_format)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT id,
+    char const* SIXTRL_RESTRICT str_buffer,
+    NS(node_id_str_fmt_t) const node_id_str_fmt,
+    NS(arch_id_t)* SIXTRL_RESTRICT ptr_arch_id );
+
+#endif /* !defined( _GPUCODE ) */
 
 typedef struct NS(ComputeNodeInfo)
 {
@@ -99,12 +144,56 @@ typedef struct NS(ComputeNodeInfo)
 }
 NS(ComputeNodeInfo);
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(ComputeNodeInfo)* NS(ComputeNodeInfo_preset)(
+SIXTRL_STATIC SIXTRL_FN NS(ComputeNodeInfo)* NS(ComputeNodeInfo_preset)(
+    NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info );
+
+SIXTRL_STATIC SIXTRL_FN bool NS(ComputeNodeInfo_is_valid)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
+
+SIXTRL_STATIC SIXTRL_FN NS(ComputeNodeId) NS(ComputeNodeInfo_get_id)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
+
+SIXTRL_STATIC SIXTRL_FN NS(comp_node_id_num_t)
+NS(ComputeNodeInfo_get_platform_id)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
+
+SIXTRL_STATIC SIXTRL_FN NS(comp_node_id_num_t)
+NS(ComputeNodeInfo_get_device_id)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
+
+SIXTRL_STATIC SIXTRL_FN char const* NS(ComputeNodeInfo_get_arch)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
+
+SIXTRL_STATIC SIXTRL_FN char const* NS(ComputeNodeInfo_get_platform)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
+
+SIXTRL_STATIC SIXTRL_FN char const* NS(ComputeNodeInfo_get_name)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
+
+SIXTRL_STATIC SIXTRL_FN char const* NS(ComputeNodeInfo_get_description)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ComputeNodeInfo_print)(
+    FILE* SIXTRL_RESTRICT fp,
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info,
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT default_node_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ComputeNodeInfo_print_out)(
+    const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info,
+    const NS(ComputeNodeId) *const SIXTRL_RESTRICT default_node_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ComputeNodeInfo)*
+NS(ComputeNodeInfo_preset_ext)(
     NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info );
 
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ComputeNodeInfo_free)(
     NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ComputeNodeInfo_delete)(
+    NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info );
+
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(ComputeNodeInfo)* NS(ComputeNodeInfo_reserve)(
     NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info,
     SIXTRL_SIZE_T const arch_str_len,
@@ -120,36 +209,33 @@ SIXTRL_EXTERN SIXTRL_HOST_FN int NS(ComputeNodeInfo_make)(
     const char *const SIXTRL_RESTRICT name_str,
     const char *const SIXTRL_RESTRICT description_str );
 
-SIXTRL_HOST_FN SIXTRL_STATIC int NS(ComputeNodeInfo_is_valid)(
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ComputeNodeInfo_is_valid_ext)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
 
-SIXTRL_HOST_FN SIXTRL_STATIC NS(ComputeNodeId)
-NS(ComputeNodeInfo_get_id)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ComputeNodeId) NS(ComputeNodeInfo_get_id_ext)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
 
-SIXTRL_HOST_FN SIXTRL_STATIC NS(comp_node_id_num_t)
-NS(ComputeNodeInfo_get_platform_id)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(comp_node_id_num_t)
+NS(ComputeNodeInfo_get_platform_id_ext)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
 
-SIXTRL_HOST_FN SIXTRL_STATIC NS(comp_node_id_num_t)
-NS(ComputeNodeInfo_get_device_id)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(comp_node_id_num_t)
+NS(ComputeNodeInfo_get_device_id_ext)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
 
-SIXTRL_HOST_FN SIXTRL_STATIC char const* NS(ComputeNodeInfo_get_arch)(
+SIXTRL_EXTERN SIXTRL_HOST_FN char const* NS(ComputeNodeInfo_get_arch_ext)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
 
-SIXTRL_HOST_FN SIXTRL_STATIC char const* NS(ComputeNodeInfo_get_platform)(
+SIXTRL_EXTERN SIXTRL_HOST_FN char const* NS(ComputeNodeInfo_get_platform_ext)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
 
-SIXTRL_HOST_FN SIXTRL_STATIC char const* NS(ComputeNodeInfo_get_name)(
+SIXTRL_EXTERN SIXTRL_HOST_FN char const* NS(ComputeNodeInfo_get_name_ext)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
 
-SIXTRL_HOST_FN SIXTRL_STATIC char const* NS(ComputeNodeInfo_get_description)(
+SIXTRL_EXTERN SIXTRL_HOST_FN char const*
+NS(ComputeNodeInfo_get_description_ext)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info );
 
-
-#if !defined( _GPUCODE )
-
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ComputeNodeInfo_print)(
     FILE* SIXTRL_RESTRICT fp,
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info,
@@ -167,7 +253,7 @@ SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(ComputeNodeInfo_print_to_str)(
 
 #else /* !defined( _GPUCODE ) */
 
-SIXTRL_FN SIXTRL_STATIC void NS(ComputeNodeInfo_print_out)(
+SIXTRL_STATIC SIXTRL_FN void NS(ComputeNodeInfo_print_out)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info,
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT default_node_id );
 
@@ -199,23 +285,37 @@ SIXTRL_INLINE bool operator<( NS(ComputeNodeId) const& lhs,
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
+SIXTRL_INLINE NS(ComputeNodeId)* NS(ComputeNodeId_preset)(
+    NS(ComputeNodeId)* SIXTRL_RESTRICT node_id )
+{
+    if( node_id != SIXTRL_NULLPTR )
+    {
+        node_id->platform_id = ( NS(comp_node_id_num_t) )-1;
+        node_id->device_id = ( NS(comp_node_id_num_t) )-1;
+    }
+
+    return node_id;
+}
+
 SIXTRL_INLINE NS(comp_node_id_num_t) NS(ComputeNodeId_get_platform_id)(
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT id )
 {
-    return ( id != 0 ) ? id->platform_id : -1;
+    return ( id != SIXTRL_NULLPTR )
+        ? id->platform_id : ( NS(comp_node_id_num_t) )-1;
 }
 
 SIXTRL_INLINE NS(comp_node_id_num_t) NS(ComputeNodeId_get_device_id)(
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT id )
 {
-    return ( id != 0 ) ? id->device_id : -1;
+    return ( id != SIXTRL_NULLPTR )
+        ? id->device_id : ( NS(comp_node_id_num_t) )-1;
 }
 
 SIXTRL_INLINE void NS(ComputeNodeId_set_platform_id)(
     NS(ComputeNodeId)* SIXTRL_RESTRICT id,
     NS(comp_node_id_num_t) const platform_id )
 {
-    SIXTRL_ASSERT( id != 0 );
+    SIXTRL_ASSERT( id != SIXTRL_NULLPTR );
     id->platform_id = platform_id;
     return;
 }
@@ -224,17 +324,16 @@ SIXTRL_INLINE void NS(ComputeNodeId_set_device_id)(
     NS(ComputeNodeId)* SIXTRL_RESTRICT id,
     NS(comp_node_id_num_t) const dev_id )
 {
-    SIXTRL_ASSERT( id != 0 );
+    SIXTRL_ASSERT( id != SIXTRL_NULLPTR );
     id->device_id = dev_id;
-    return;
 }
 
-SIXTRL_INLINE int NS(ComputeNodeId_is_valid)(
+SIXTRL_INLINE bool NS(ComputeNodeId_is_valid)(
     const NS(ComputeNodeId) *const SIXTRL_RESTRICT id )
 {
-    return ( ( id != 0 ) &&
-             ( id->platform_id != -1 ) &&
-             ( id->device_id   != -1 ) );
+    return ( ( id != SIXTRL_NULLPTR ) &&
+             ( id->platform_id != ( NS(comp_node_id_num_t) )-1 ) &&
+             ( id->device_id   != ( NS(comp_node_id_num_t) )-1 ) );
 }
 
 SIXTRL_INLINE int NS(ComputeNodeId_compare)(
@@ -290,11 +389,27 @@ SIXTRL_INLINE bool NS(ComputeNodeId_are_equal)(
     return ( NS(ComputeNodeId_compare)( lhs, rhs ) == 0 );
 }
 
+/* ************************************************************************* */
+
+SIXTRL_INLINE NS(ComputeNodeInfo)* NS(ComputeNodeInfo_preset)(
+    NS(ComputeNodeInfo)* SIXTRL_RESTRICT node_info )
+{
+    if( node_info != SIXTRL_NULLPTR )
+    {
+        NS(ComputeNodeId_preset)( &node_info->id );
+        node_info->arch = SIXTRL_NULLPTR;
+        node_info->platform = SIXTRL_NULLPTR;
+        node_info->name = SIXTRL_NULLPTR;
+        node_info->description = SIXTRL_NULLPTR;
+    }
+
+    return node_info;
+}
 
-SIXTRL_INLINE int NS(ComputeNodeInfo_is_valid)(
+SIXTRL_INLINE bool NS(ComputeNodeInfo_is_valid)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
 {
-    return ( ( node_info != 0 ) &&
+    return ( ( node_info != SIXTRL_NULLPTR ) &&
              ( NS(ComputeNodeId_is_valid)( &node_info->id ) ) &&
              ( NS(ComputeNodeInfo_get_arch)( node_info ) != 0 ) &&
              ( strlen( NS(ComputeNodeInfo_get_arch)( node_info ) ) > 0u ) &&
@@ -318,7 +433,7 @@ SIXTRL_INLINE NS(ComputeNodeId) NS(ComputeNodeInfo_get_id)(
 SIXTRL_INLINE NS(comp_node_id_num_t) NS(ComputeNodeInfo_get_platform_id)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
 {
-    return ( node_info != 0 )
+    return ( node_info != SIXTRL_NULLPTR )
         ? NS(ComputeNodeId_get_platform_id)( &node_info->id )
         : NS(ComputeNodeId_get_platform_id)( 0 );
 }
@@ -326,7 +441,7 @@ SIXTRL_INLINE NS(comp_node_id_num_t) NS(ComputeNodeInfo_get_platform_id)(
 SIXTRL_INLINE NS(comp_node_id_num_t) NS(ComputeNodeInfo_get_device_id)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
 {
-    return ( node_info != 0 )
+    return ( node_info != SIXTRL_NULLPTR )
         ? NS(ComputeNodeId_get_device_id)( &node_info->id )
         : NS(ComputeNodeId_get_device_id)( 0 );
 }
@@ -334,25 +449,27 @@ SIXTRL_INLINE NS(comp_node_id_num_t) NS(ComputeNodeInfo_get_device_id)(
 SIXTRL_INLINE char const* NS(ComputeNodeInfo_get_arch)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
 {
-    return ( node_info != 0 ) ? node_info->arch : 0;
+    return ( node_info != SIXTRL_NULLPTR ) ? node_info->arch : SIXTRL_NULLPTR;
 }
 
 SIXTRL_INLINE char const* NS(ComputeNodeInfo_get_platform)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
 {
-    return ( node_info != 0 ) ? node_info->platform : 0;
+    return ( node_info != SIXTRL_NULLPTR )
+        ? node_info->platform : SIXTRL_NULLPTR;
 }
 
 SIXTRL_INLINE char const* NS(ComputeNodeInfo_get_name)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
 {
-    return ( node_info != 0 ) ? node_info->name : 0;
+    return ( node_info != SIXTRL_NULLPTR ) ? node_info->name : SIXTRL_NULLPTR;
 }
 
 SIXTRL_INLINE char const* NS(ComputeNodeInfo_get_description)(
     const NS(ComputeNodeInfo) *const SIXTRL_RESTRICT node_info )
 {
-    return ( node_info != 0 ) ? node_info->description : 0;
+    return ( node_info != SIXTRL_NULLPTR )
+        ? node_info->description : SIXTRL_NULLPTR;
 }
 
 #if !defined( _GPUCODE ) && defined( __cplusplus )
diff --git a/sixtracklib/common/control/CMakeLists.txt b/sixtracklib/common/control/CMakeLists.txt
index 4b7e5422..8bb1a7b6 100644
--- a/sixtracklib/common/control/CMakeLists.txt
+++ b/sixtracklib/common/control/CMakeLists.txt
@@ -1,20 +1,11 @@
 # ----------------------------------------------------------------------------
 # sixtracklib/common/control/CMakeLists.txt
 
-set( SIXTRL_COMMON_CONTROL_C99_HEADERS
-     definitions.h
-     debug_register.h
-     arch_info.h
-     arch_base.h
-     node_id.h
-     node_info.h
-     kernel_config_base.h
-     controller_base.h
-     node_controller_base.h
-     argument_base.h
-)
-
 set( SIXTRL_COMMON_CONTROL_C99_SOURCES )
+set( SIXTRL_COMMON_CONTROL_C99_HEADERS
+     definitions.h debug_register.h arch_info.h arch_base.h node_id.h
+     node_info.h kernel_config_base.h controller_base.h node_controller_base.h
+     argument_base.h )
 
 # add_library( sixtrack_common_control_c99 OBJECT
 #     ${SIXTRL_COMMON_CONTROL_C99_HEADERS}
@@ -42,84 +33,49 @@ set( SIXTRL_COMMON_CONTROL_C99_SOURCES )
 
 # ------------------------------------------------------------------------------
 
-set( SIXTRL_COMMON_CONTROL_CXX_HEADERS
-     arch_info.hpp
-     arch_base.hpp
-     node_id.hpp
-     node_info.hpp
-     kernel_config_base.hpp
-     controller_base.hpp
-     node_controller_base.hpp
-     argument_base.hpp
-)
-
-set( SIXTRL_COMMON_CONTROL_CXX_SOURCES
-     arch_info.cpp
-     arch_info_c99.cpp
-     arch_base.cpp
-     arch_base_c99.cpp
-     node_id.cpp
-     node_id_c99.cpp
-     node_info.cpp
-     node_info_c99.cpp
-     kernel_config_base.cpp
-     kernel_config_base_c99.cpp
-     controller_base.cpp
-     controller_base_c99.cpp
-     node_controller_base.cpp
-     node_controller_base_c99.cpp
-     argument_base.cpp
-     argument_base_c99.cpp
-)
+set( SIXTRL_COMMON_CONTROL_CXX_HEADERS arch_info.hpp arch_base.hpp node_id.hpp
+    node_info.hpp kernel_config_base.hpp controller_base.hpp
+    node_controller_base.hpp argument_base.hpp )
+
+set( SIXTRL_COMMON_CONTROL_CXX_SOURCES arch_info.cpp arch_info_c99.cpp
+     arch_base.cpp arch_base_c99.cpp node_id.cpp node_id_c99.cpp node_info.cpp
+     node_info_c99.cpp kernel_config_base.cpp kernel_config_base_c99.cpp
+     controller_base.cpp controller_base_c99.cpp node_controller_base.cpp
+     node_controller_base_c99.cpp argument_base.cpp argument_base_c99.cpp )
 
 add_library( sixtrack_common_control_cxx OBJECT
     ${SIXTRL_COMMON_CONTROL_C99_HEADERS}
     ${SIXTRL_COMMON_CONTROL_CXX_HEADERS}
-    ${SIXTRL_COMMON_CONTROL_CXX_SOURCES}
-)
+    ${SIXTRL_COMMON_CONTROL_CXX_SOURCES} )
 
 target_include_directories( sixtrack_common_control_cxx PRIVATE
-    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
-    $<INSTALL_INTERFACE:include> )
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-set_target_properties( sixtrack_common_control_cxx
-                       PROPERTIES LINKER_LANGUAGE C )
-
-set_target_properties( sixtrack_common_control_cxx
-                       PROPERTIES POSITION_INDEPENDENT_CODE ON )
-
-set_target_properties( sixtrack_common_control_cxx
-                       PROPERTIES CXX_STANDARD 11 )
-
-set_target_properties( sixtrack_common_control_cxx
-                       PROPERTIES CXX_STANDARD_REQUIRED ON )
+set_target_properties( sixtrack_common_control_cxx PROPERTIES CXX_STANDARD 11
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON CXX_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_control_cxx
-    PRIVATE -Wall -Werror -pedantic -ansi ${SIXTRACKLIB_CPU_FLAGS} )
+    PRIVATE ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_CXX_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_internal as a module for sixtracklib:
 
-set(  SIXTRACKL_LIBRARY_MODULES
-    ${SIXTRACKL_LIBRARY_MODULES}
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
 #     $<TARGET_OBJECTS:sixtrack_common_control_c99>
-    $<TARGET_OBJECTS:sixtrack_common_control_cxx>
-    CACHE INTERNAL "" FORCE )
+    $<TARGET_OBJECTS:sixtrack_common_control_cxx> CACHE INTERNAL "" FORCE )
 
 # -----------------------------------------------------------------------------
 # install :
 
-set( SIXTRACKLIB_COMMON_CONTROL_INSTALL_PATH
-     include/sixtracklib/common/control )
-
 if( SIXTRL_COMMON_CONTROL_C99_HEADERS )
     install( FILES ${SIXTRL_COMMON_CONTROL_C99_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_CONTROL_INSTALL_PATH} )
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/control" )
 endif()
 
-if( SIXTRL_COMMON_CONTROL_CXX_HEADERS )
+if( SIXTACKL_ENABLE_CXX AND SIXTRL_COMMON_CONTROL_CXX_HEADERS )
     install( FILES ${SIXTRL_COMMON_CONTROL_CXX_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_CONTROL_INSTALL_PATH} )
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/control" )
 endif()
 
 #end: sixtracklib/common/buffer/CMakeLists.txt
diff --git a/sixtracklib/common/control/definitions.h b/sixtracklib/common/control/definitions.h
index 68b2fcec..3d1e085e 100644
--- a/sixtracklib/common/control/definitions.h
+++ b/sixtracklib/common/control/definitions.h
@@ -24,6 +24,7 @@ typedef NS(arch_program_id_t) NS(ctrl_program_id_t);
 typedef SIXTRL_INT64_T        NS(node_platform_id_t);
 typedef SIXTRL_INT64_T        NS(node_device_id_t);
 typedef SIXTRL_UINT32_T       NS(node_index_t);
+typedef SIXTRL_UINT16_T       NS(node_id_str_fmt_t);
 
 typedef enum NS(ctrl_perform_remap_flag_e)
 {
@@ -128,6 +129,66 @@ NS(ctrl_perform_remap_flag_t);
     #define SIXTRL_ARCH_DEBUGGING_GENERAL_FAILURE 0xFFFFFFFF00000000
 #endif /* !defined( SIXTRL_ARCH_DEBUGGING_GENERAL_FAILURE ) */
 
+/* ------------------------------------------------------------------------- */
+
+#if !defined( SIXTRL_ARCH_ILLEGAL_BUFFER_ID)
+    #define SIXTRL_ARCH_ILLEGAL_BUFFER_ID 0
+#endif /* !defined( SIXTRL_ARCH_ILLEGAL_BUFFER_ID) */
+
+#if !defined( SIXTRL_ARCH_PARTICLES_BUFFER_ID )
+    #define SIXTRL_ARCH_PARTICLES_BUFFER_ID 1
+#endif /* !defined( SIXTRL_ARCH_PARTICLES_BUFFER_ID ) */
+
+#if !defined( SIXTRL_ARCH_BEAM_ELEMENTS_BUFFER_ID )
+    #define SIXTRL_ARCH_BEAM_ELEMENTS_BUFFER_ID 2
+#endif /* !defined( SIXTRL_ARCH_BEAM_ELEMENTS_BUFFER_ID ) */
+
+#if !defined( SIXTRL_ARCH_OUTPUT_BUFFER_ID )
+    #define SIXTRL_ARCH_OUTPUT_BUFFER_ID 3
+#endif /* !defined( SIXTRL_ARCH_OUTPUT_BUFFER_ID ) */
+
+#if !defined( SIXTRL_ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID )
+    #define SIXTRL_ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID 4
+#endif /* !defined( SIXTRL_ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID ) */
+
+#if !defined( SIXTRL_ARCH_PARTICLE_ADDR_BUFFER_ID )
+    #define SIXTRL_ARCH_PARTICLE_ADDR_BUFFER_ID 5
+#endif /* !defined( SIXTRL_ARCH_PARTICLE_ADDR_BUFFER_ID ) */
+
+#if !defined( SIXTRL_ARCH_MIN_USER_DEFINED_BUFFER_ID )
+    #define SIXTRL_ARCH_MIN_USER_DEFINED_BUFFER_ID 1024
+#endif /* !defined( SIXTRL_ARCH_MIN_USER_DEFINED_BUFFER_ID ) */
+
+#if !defined( SIXTRL_ARCH_EXTERNAL_BUFFER_ID )
+    #define SIXTRL_ARCH_EXTERNAL_BUFFER_ID 1024
+#endif /* !defined( SIXTRL_ARCH_EXTERNAL_BUFFER_ID ) */
+
+#if !defined( SIXTRL_ARCH_MAX_USER_DEFINED_BUFFER_ID )
+    #define SIXTRL_ARCH_MAX_USER_DEFINED_BUFFER_ID 0xFFFFFFFFFFFFFFFE
+#endif /* !defined( SIXTRL_ARCH_MAX_USER_DEFINED_BUFFER_ID ) */
+
+/* ------------------------------------------------------------------------- */
+
+#if !defined( SIXTRL_NODE_ID_STR_FORMAT_NOARCH)
+    #define SIXTRL_NODE_ID_STR_FORMAT_NOARCH 0
+#endif /* !defined( SIXTRL_NODE_ID_STR_FORMAT_NOARCH) */
+
+#if !defined( SIXTRL_NODE_ID_STR_FORMAT_ARCHID)
+    #define SIXTRL_NODE_ID_STR_FORMAT_ARCHID 1
+#endif /* !defined( SIXTRL_NODE_ID_STR_FORMAT_ARCHID) */
+
+#if !defined( SIXTRL_NODE_ID_STR_FORMAT_ARCHSTR)
+    #define SIXTRL_NODE_ID_STR_FORMAT_ARCHSTR 2
+#endif /* !defined( SIXTRL_NODE_ID_STR_FORMAT_ARCHSTR) */
+
+#if !defined( SIXTRL_NODE_ID_STR_FORMAT_DEFAULT)
+    #define SIXTRL_NODE_ID_STR_FORMAT_DEFAULT 0
+#endif /* !defined( SIXTRL_NODE_ID_STR_FORMAT_DEFAULT) */
+
+#if !defined( SIXTRL_NODE_ID_STR_FORMAT_ILLEGAL)
+    #define SIXTRL_NODE_ID_STR_FORMAT_ILLEGAL 0xffff
+#endif /* !defined( SIXTRL_NODE_ID_STR_FORMAT_ILLEGAL) */
+
 #if !defined( _GPUCODE )
 
 SIXTRL_STATIC_VAR NS(arch_id_t) const NS(ARCHITECTURE_ID_BITMASK) =
@@ -212,12 +273,62 @@ SIXTRL_STATIC_VAR NS(node_device_id_t) const NS(NODE_ILLEGAL_DEVICE_ID) =
 SIXTRL_STATIC_VAR NS(node_index_t) const NS(NODE_UNDEFINED_INDEX) =
     ( NS(node_index_t) )0xFFFFFFFF;
 
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_ILLEGAL_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_ILLEGAL_BUFFER_ID;
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_PARTICLES_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_PARTICLES_BUFFER_ID;
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_BEAM_ELEMENTS_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_BEAM_ELEMENTS_BUFFER_ID;
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_OUTPUT_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_OUTPUT_BUFFER_ID;
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID;
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_PARTICLE_ADDR_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_PARTICLE_ADDR_BUFFER_ID;
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_MIN_USER_DEFINED_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_MIN_USER_DEFINED_BUFFER_ID;
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_EXTERNAL_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_EXTERNAL_BUFFER_ID;
+
+SIXTRL_STATIC_VAR NS(arch_size_t) const NS(ARCH_MAX_USER_DEFINED_BUFFER_ID) =
+    ( NS(arch_size_t) )SIXTRL_ARCH_MAX_USER_DEFINED_BUFFER_ID;
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC_VAR NS(node_id_str_fmt_t) const NS(NODE_ID_STR_FORMAT_NOARCH) =
+    ( NS(node_id_str_fmt_t) )SIXTRL_NODE_ID_STR_FORMAT_NOARCH;
+
+SIXTRL_STATIC_VAR NS(node_id_str_fmt_t) const NS(NODE_ID_STR_FORMAT_ARCHID) =
+    ( NS(node_id_str_fmt_t) )SIXTRL_NODE_ID_STR_FORMAT_ARCHID;
+
+SIXTRL_STATIC_VAR NS(node_id_str_fmt_t) const NS(NODE_ID_STR_FORMAT_ARCHSTR) =
+    ( NS(node_id_str_fmt_t) )SIXTRL_NODE_ID_STR_FORMAT_ARCHSTR;
+
+SIXTRL_STATIC_VAR NS(node_id_str_fmt_t) const NS(NODE_ID_STR_FORMAT_DEFAULT) =
+    ( NS(node_id_str_fmt_t) )SIXTRL_NODE_ID_STR_FORMAT_DEFAULT;
+
+
+SIXTRL_STATIC_VAR NS(node_id_str_fmt_t) const NS(NODE_ID_STR_FORMAT_ILLEGAL) =
+    ( NS(node_id_str_fmt_t) )SIXTRL_NODE_ID_STR_FORMAT_ILLEGAL;
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
 
 #endif /* !defined( _GPUCODE ) */
 
 #if defined( __cplusplus ) && !defined( _GPUCODE )
 }
+#endif /* C++. Host */
 
+#if defined( __cplusplus )
 namespace SIXTRL_CXX_NAMESPACE
 {
     typedef ::NS(ctrl_status_t)       ctrl_status_t;
@@ -235,6 +346,7 @@ namespace SIXTRL_CXX_NAMESPACE
     typedef ::NS(node_platform_id_t)  node_platform_id_t;
     typedef ::NS(node_device_id_t)    node_device_id_t;
     typedef ::NS(node_index_t)        node_index_t;
+    typedef ::NS(node_id_str_fmt_t)   node_id_str_fmt_t;
 
     typedef enum
     {
@@ -332,9 +444,68 @@ namespace SIXTRL_CXX_NAMESPACE
 
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST node_index_t
         NODE_UNDEFINED_INDEX = static_cast< node_index_t >( 0xFFFFFFFF );
-}
 
-#endif /* C++, Host */
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  */
+
+    SIXTRL_STATIC_VAR arch_size_t SIXTRL_CONSTEXPR_OR_CONST
+        ARCH_ILLEGAL_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_ILLEGAL_BUFFER_ID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST arch_size_t
+        ARCH_PARTICLES_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_PARTICLES_BUFFER_ID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST arch_size_t
+        ARCH_BEAM_ELEMENTS_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_BEAM_ELEMENTS_BUFFER_ID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST arch_size_t
+        ARCH_OUTPUT_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_OUTPUT_BUFFER_ID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST arch_size_t
+        ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST arch_size_t
+        ARCH_PARTICLE_ADDR_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_PARTICLE_ADDR_BUFFER_ID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST arch_size_t
+        ARCH_MIN_USER_DEFINED_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_MIN_USER_DEFINED_BUFFER_ID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST arch_size_t
+        ARCH_EXTERNAL_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_EXTERNAL_BUFFER_ID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST arch_size_t
+        ARCH_MAX_USER_DEFINED_BUFFER_ID = static_cast< arch_size_t >(
+            SIXTRL_ARCH_MAX_USER_DEFINED_BUFFER_ID );
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  */
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST node_id_str_fmt_t
+        NODE_ID_STR_FORMAT_NOARCH = static_cast< node_id_str_fmt_t >(
+            SIXTRL_NODE_ID_STR_FORMAT_NOARCH );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST node_id_str_fmt_t
+        NODE_ID_STR_FORMAT_ARCHID = static_cast< node_id_str_fmt_t >(
+            SIXTRL_NODE_ID_STR_FORMAT_ARCHID );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST node_id_str_fmt_t
+        NODE_ID_STR_FORMAT_ARCHSTR = static_cast< node_id_str_fmt_t >(
+            SIXTRL_NODE_ID_STR_FORMAT_ARCHSTR );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST node_id_str_fmt_t
+        NODE_ID_STR_FORMAT_ILLEGAL = static_cast< node_id_str_fmt_t >(
+            SIXTRL_NODE_ID_STR_FORMAT_ILLEGAL );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST node_id_str_fmt_t
+        NODE_ID_STR_FORMAT_DEFAULT = static_cast< node_id_str_fmt_t >(
+            SIXTRL_NODE_ID_STR_FORMAT_DEFAULT );
+}
+#endif /* C++ */
 
 #endif /* SIXTRACKLIB_COMMON_CONTROL_DEFINITIONS_H__ */
 
diff --git a/sixtracklib/common/control/node_controller_base.cpp b/sixtracklib/common/control/node_controller_base.cpp
index c25add0e..bb18a31d 100644
--- a/sixtracklib/common/control/node_controller_base.cpp
+++ b/sixtracklib/common/control/node_controller_base.cpp
@@ -103,7 +103,7 @@ namespace SIXTRL_CXX_NAMESPACE
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
     bool NodeControllerBase::isNodeAvailable(
-        NodeControllerBase::node_index_t const idx ) const SIXTRL_RESTRICT
+        NodeControllerBase::node_index_t const idx ) const SIXTRL_NOEXCEPT
     {
         return ( ( idx != NodeId::UNDEFINED_INDEX ) &&
             ( idx <  this->numAvailableNodes() ) &&
diff --git a/sixtracklib/common/control/node_controller_base.hpp b/sixtracklib/common/control/node_controller_base.hpp
index 52b3ef69..89b4f01d 100644
--- a/sixtracklib/common/control/node_controller_base.hpp
+++ b/sixtracklib/common/control/node_controller_base.hpp
@@ -68,7 +68,7 @@ namespace SIXTRL_CXX_NAMESPACE
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
         SIXTRL_HOST_FN bool isNodeAvailable(
-            node_index_t const node_index ) const SIXTRL_RESTRICT;
+            node_index_t const node_index ) const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN bool isNodeAvailable(
             node_id_t const& node_id ) const SIXTRL_NOEXCEPT;
@@ -371,7 +371,7 @@ namespace SIXTRL_CXX_NAMESPACE
         node_index_t m_max_available_node_index;
 
         bool m_can_directly_change_selected_node;
-        bool m_node_change_requires_kernels;
+        //bool m_node_change_requires_kernels;
         bool m_can_unselect_node;
         bool m_use_autoselect;
     };
diff --git a/sixtracklib/common/control/node_id.cpp b/sixtracklib/common/control/node_id.cpp
index 424b5283..d2f04947 100644
--- a/sixtracklib/common/control/node_id.cpp
+++ b/sixtracklib/common/control/node_id.cpp
@@ -15,6 +15,8 @@ namespace st = SIXTRL_CXX_NAMESPACE;
 
 namespace SIXTRL_CXX_NAMESPACE
 {
+    using _this_t = st::NodeId;
+
     NodeId::NodeId(
         NodeId::platform_id_t const platform_id,
         NodeId::device_id_t const device_id,
@@ -126,6 +128,84 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
+    NodeId::status_t NodeId::to_string( char* SIXTRL_RESTRICT node_id_str,
+        _this_t::size_type const node_id_str_capacity,
+        _this_t::arch_id_t const arch_id,
+        _this_t::str_format_t const format ) const SIXTRL_NOEXCEPT
+    {
+        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( ( node_id_str != nullptr ) &&
+            ( node_id_str_capacity > _this_t::size_type{ 0 } ) &&
+            ( format != st::NODE_ID_STR_FORMAT_ILLEGAL ) &&
+            ( this->valid() ) )
+        {
+            int ret = int{ 0 };
+            _this_t::size_type const nn =
+                node_id_str_capacity - _this_t::size_type{ 1 };
+
+            if( format == st::NODE_ID_STR_FORMAT_NOARCH )
+            {
+                ret = std::snprintf( node_id_str, nn, "%d.%d",
+                    static_cast< int >( this->platformId() ),
+                    static_cast< int >( this->deviceId() ) );
+            }
+            else if( ( arch_id != st::ARCHITECTURE_ILLEGAL ) &&
+                     ( arch_id != st::ARCHITECTURE_NONE ) )
+            {
+                if( format == st::NODE_ID_STR_FORMAT_ARCHID )
+                {
+                    ret = std::snprintf( node_id_str, nn, "%u:%d.%d",
+                        static_cast< unsigned >( arch_id ),
+                        static_cast< int >( this->platformId() ),
+                        static_cast< int >( this->deviceId() ) );
+
+                }
+                else if( format == st::NODE_ID_STR_FORMAT_ARCHSTR )
+                {
+                    char TEMP_ARCH_NAME[ 32 ] =
+                    {
+                        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+                        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+                    };
+
+                    if( arch_id == st::ARCHITECTURE_CPU )
+                    {
+                        strncpy( TEMP_ARCH_NAME,
+                                 SIXTRL_ARCHITECTURE_CPU_STR, 31 );
+                    }
+                    else if( arch_id == st::ARCHITECTURE_OPENCL )
+                    {
+                        strncpy( TEMP_ARCH_NAME,
+                                 SIXTRL_ARCHITECTURE_OPENCL_STR, 31 );
+                    }
+                    else if( arch_id == st::ARCHITECTURE_CUDA )
+                    {
+                        strncpy( TEMP_ARCH_NAME,
+                                 SIXTRL_ARCHITECTURE_CUDA_STR, 31 );
+                    }
+
+                    if( std::strlen( TEMP_ARCH_NAME ) > 0u )
+                    {
+                        ret = std::snprintf( node_id_str, nn, "%s:%d.%d",
+                            TEMP_ARCH_NAME,
+                            static_cast< int >( this->platformId() ),
+                            static_cast< int >( this->deviceId() ) );
+                    }
+                }
+            }
+
+            if( ( ret > 0 ) && ( ret <= static_cast< int >( nn ) ) )
+            {
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
     NodeId::status_t NodeId::fromString(
         std::string const& SIXTRL_RESTRICT_REF id_str ) SIXTRL_NOEXCEPT
     {
diff --git a/sixtracklib/common/control/node_id.hpp b/sixtracklib/common/control/node_id.hpp
index e6ddaee9..485b9b20 100644
--- a/sixtracklib/common/control/node_id.hpp
+++ b/sixtracklib/common/control/node_id.hpp
@@ -34,6 +34,8 @@ namespace SIXTRL_CXX_NAMESPACE
         using device_id_t   = SIXTRL_CXX_NAMESPACE::node_device_id_t;
         using index_t       = SIXTRL_CXX_NAMESPACE::node_index_t;
         using status_t      = SIXTRL_CXX_NAMESPACE::arch_status_t;
+        using str_format_t  = SIXTRL_CXX_NAMESPACE::node_id_str_fmt_t;
+        using arch_id_t     = SIXTRL_CXX_NAMESPACE::arch_id_t;
 
         static SIXTRL_CONSTEXPR_OR_CONST platform_id_t ILLEGAL_PLATFORM_ID =
             SIXTRL_CXX_NAMESPACE::NODE_ILLEGAL_PATFORM_ID;
@@ -88,6 +90,12 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_FN status_t toString( char* SIXTRL_RESTRICT node_id_str,
             size_type const node_id_str_capacity ) const SIXTRL_NOEXCEPT;
 
+        SIXTRL_FN status_t to_string( char* SIXTRL_RESTRICT node_id_str,
+            size_type const node_id_str_capacity,
+            arch_id_t const arch_id, str_format_t const format =
+                SIXTRL_CXX_NAMESPACE::NODE_ID_STR_FORMAT_DEFAULT
+        ) const SIXTRL_NOEXCEPT;
+
         SIXTRL_FN bool operator<(
             NodeId const& SIXTRL_RESTRICT_REF rhs ) const SIXTRL_NOEXCEPT;
 
diff --git a/sixtracklib/common/controller.h b/sixtracklib/common/controller.h
index 6bc0315f..f0ac6861 100644
--- a/sixtracklib/common/controller.h
+++ b/sixtracklib/common/controller.h
@@ -21,7 +21,5 @@
     #include "sixtracklib/common/control/controller_base.h"
     #include "sixtracklib/common/control/node_controller_base.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
-
 #endif /* SIXTRACKLIB_COMMON_CONTEXT_H__ */
-
-/* end: sixtracklib/common/controller.h */
\ No newline at end of file
+/* end: sixtracklib/common/controller.h */
diff --git a/sixtracklib/common/definitions.h b/sixtracklib/common/definitions.h
index 4f4d88ba..a55a2f1a 100644
--- a/sixtracklib/common/definitions.h
+++ b/sixtracklib/common/definitions.h
@@ -155,9 +155,13 @@
         /* static, inline and restrict keywords:                                    */
 
         #if !defined( SIXTRL_RESTRICT )
-        #define SIXTRL_RESTRICT SIXTRL_GPUKERNEL_RESTRICT
+            #define SIXTRL_RESTRICT SIXTRL_GPUKERNEL_RESTRICT
         #endif /* !defined( SIXTRL_RESTRICT ) */
 
+        #if !defined( SIXTRL_RESTRICT_REF )
+            #define SIXTRL_RESTRICT_REF
+        #endif /* !defined( SIXTRL_RESTRICT_REF ) */
+
         #if !defined( SIXTRL_STATIC )
             #define SIXTRL_STATIC
         #endif /* !defined( SIXTRL_STATIC ) */
@@ -205,35 +209,35 @@
         #endif /* !defined( SIXTRL_FLOAT_T ) */
 
         #if !defined( SIXTRL_UINT64_T )
-            #define SIXTRL_UINT64_T  uint64_t
+            #define SIXTRL_UINT64_T  unsigned long long int
         #endif /* !defined( SIXTRL_UINT64_T ) */
 
         #if !defined( SIXTRL_INT64_T )
-            #define SIXTRL_INT64_T int64_t
+            #define SIXTRL_INT64_T long long int
         #endif /* !defined( SIXTRL_INT64_T ) */
 
         #if !defined( SIXTRL_UINT32_T )
-            #define SIXTRL_UINT32_T uint32_t
+            #define SIXTRL_UINT32_T unsigned int
         #endif /* !defined( SIXTRL_UINT32_T ) */
 
         #if !defined( SIXTRL_INT32_T )
-            #define SIXTRL_INT32_T int32_t
+            #define SIXTRL_INT32_T int
         #endif /* !defined( SIXTRL_INT32_T ) */
 
         #if !defined( SIXTRL_UINT16_T )
-            #define SIXTRL_UINT16_T uint16_t
+            #define SIXTRL_UINT16_T unsigned short int
         #endif /* !defined( SIXTRL_UINT32_T ) */
 
         #if !defined( SIXTRL_INT16_T )
-            #define SIXTRL_INT16_T int16_t
+            #define SIXTRL_INT16_T short int
         #endif /* !defined( SIXTRL_INT16_T ) */
 
         #if !defined( SIXTRL_UINT8_T )
-            #define SIXTRL_UINT8_T uint8_t
+            #define SIXTRL_UINT8_T unsigned char
         #endif /* !defined( SIXTRL_UINT32_T ) */
 
         #if !defined( SIXTRL_INT8_T )
-            #define SIXTRL_INT8_T int8_t
+            #define SIXTRL_INT8_T char
         #endif /* !defined( SIXTRL_INT8_T ) */
 
         #if !defined( SIXTRL_SIZE_T )
@@ -278,9 +282,13 @@
         /* static, inline and restrict keywords:                            */
 
         #if !defined( SIXTRL_RESTRICT )
-        #define SIXTRL_RESTRICT SIXTRL_GPUKERNEL_RESTRICT
+            #define SIXTRL_RESTRICT SIXTRL_GPUKERNEL_RESTRICT
         #endif /* !defined( SIXTRL_RESTRICT ) */
 
+        #if !defined( SIXTRL_RESTRICT_REF )
+            #define SIXTRL_RESTRICT_REF
+        #endif /* !defined( SIXTRL_RESTRICT_REF ) */
+
         #if !defined( SIXTRL_STATIC )
             #define SIXTRL_STATIC static
         #endif /* !defined( SIXTRL_STATIC ) */
diff --git a/sixtracklib/common/generated/CMakeLists.txt b/sixtracklib/common/generated/CMakeLists.txt
index d5aeb055..1ffc9014 100644
--- a/sixtracklib/common/generated/CMakeLists.txt
+++ b/sixtracklib/common/generated/CMakeLists.txt
@@ -121,12 +121,6 @@ install( CODE "
 # create a header file common/generated/config.h with encoding top-level
 # configuration options from Settings.cmake:
 
-if( SIXTRACKL_ENABLE_APERTURE_CHECK )
-    set( SIXTRACKL_ENABLE_APERTURE_CHECK_FLAG "1" )
-else()
-    set( SIXTRACKL_ENABLE_APERTURE_CHECK_FLAG "0" )
-endif()
-
 set( CONFIG_H_IN_PATH  "${CMAKE_CURRENT_SOURCE_DIR}/config.h.template" )
 set( CONFIG_H_OUT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/config.h" )
 
@@ -135,34 +129,16 @@ configure_file( ${CONFIG_H_IN_PATH} ${CONFIG_H_OUT_PATH} @ONLY )
 set(  SIXTRACKL_COMMON_GENERATED_HEADERS
     ${SIXTRACKL_COMMON_GENERATED_HEADERS} "generated/config.h" )
 
-
-if( SIXTRACKL_ENABLE_PYTHON )
-    if( SIXTRACKL_ENABLE_APERTURE_CHECK )
-        set( PY_SIXTRL_ENABLE_APERTURE_CHECK "True" CACHE INTERNAL "" FORCE )
-    else()
-        set( PY_SIXTRL_ENABLE_APERTURE_CHECK "False" CACHE INTERNAL "" FORCE )
-    endif()
-
-    set( PY_SIXTRL_APERTURE_X_LIMIT "${SIXTRACKL_APERTURE_X_LIMIT_VALUE}"
-         CACHE INTERNAL "" FORCE )
-
-    set( PY_SIXTRL_APERTURE_Y_LIMIT "${SIXTRACKL_APERTURE_Y_LIMIT_VALUE}"
-         CACHE INTERNAL "" FORCE )
-endif()
-
 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 # install:
 
 set( CONFIG_H_INSTALL_PATH
      "${CMAKE_INSTALL_PREFIX}/${GENERATED_INSTALL_PATH}/config.h" )
 
-install( CODE "
-         set( SIXTRACKL_ENABLE_APERTURE_CHECK_FLAG
-              \"${SIXTRACKL_ENABLE_APERTURE_CHECK_FLAG}\" )
-         set( SIXTRACKL_APERTURE_X_LIMIT_VALUE ${SIXTRACKL_APERTURE_X_LIMIT_VALUE} )
-         set( SIXTRACKL_APERTURE_Y_LIMIT_VALUE ${SIXTRACKL_APERTURE_Y_LIMIT_VALUE} )
-         message( STATUS \"Generating: ${CONFIG_H_INSTALL_PATH}\" )
-         configure_file( \"${CONFIG_H_IN_PATH}\" \"${CONFIG_H_INSTALL_PATH}\" @ONLY ) " )
+install( CODE "${SIXTRL_TRACK_FEATURES_INSTALL_STR}
+               ${SIXTRL_APERTURE_CHECK_FEATURES_INSTALL_STR}
+               message( STATUS \"Generating: ${CONFIG_H_INSTALL_PATH}\" )
+               configure_file( \"${CONFIG_H_IN_PATH}\" \"${CONFIG_H_INSTALL_PATH}\" @ONLY ) " )
 
 # ------------------------------------------------------------------------------
 # Create a header file encapsulating the choices for the C and C++
diff --git a/sixtracklib/common/generated/config.h.template b/sixtracklib/common/generated/config.h.template
index e99378ec..b591aad7 100644
--- a/sixtracklib/common/generated/config.h.template
+++ b/sixtracklib/common/generated/config.h.template
@@ -1,20 +1,90 @@
 #ifndef SIXTRACKLIB_COMMON_GENERATED_CONFIGURATION_HEADER_H__
 #define SIXTRACKLIB_COMMON_GENERATED_CONFIGURATION_HEADER_H__
 
-/* ************************************************************************** *
- * ******             SixTrackLib Feature configuration                ****** *
- * ************************************************************************** */
+/* ************************************************************************* *
+ * ******             SixTrackLib Feature configuration                ***** *
+ * ************************************************************************* */
 
-#if !defined( SIXTRL_ENABLE_APERTURE_CHECK )
-    #define SIXTRL_ENABLE_APERTURE_CHECK @SIXTRACKL_ENABLE_APERTURE_CHECK_FLAG@
-#endif /* !defined( SIXTRL_ENABLE_APERTURE_CHECK ) */
+/* ------------------------------------------------------------------------- */
+/* ----  Enable / disable / skip tracking over specific beam elements   ---- */
+/* ------------------------------------------------------------------------- */
+
+ #if !defined( SIXTRL_TRACK_MAP_ENABLED )
+    #define SIXTRL_TRACK_MAP_ENABLED @SIXTRL_TRACK_MAP_ENABLED_VALUE@
+    #define SIXTRL_TRACK_MAP_ENABLED_STR "@SIXTRL_TRACK_MAP_ENABLED_VALUE@"
+ #endif /* !defined( SIXTRL_TRACK_MAP_ENABLED ) */
+
+ #if !defined( SIXTRL_TRACK_MAP_SKIP )
+    #define SIXTRL_TRACK_MAP_SKIP @SIXTRL_TRACK_MAP_SKIP_VALUE@
+    #define SIXTRL_TRACK_MAP_SKIP_STR "@SIXTRL_TRACK_MAP_SKIP_VALUE@"
+ #endif /* !defined( SIXTRL_TRACK_MAP_SKIP ) */
+
+ #if !defined( SIXTRL_TRACK_MAP_DISABLED )
+    #define SIXTRL_TRACK_MAP_DISABLED @SIXTRL_TRACK_MAP_DISABLED_VALUE@
+    #define SIXTRL_TRACK_MAP_DISABLED_STR "@SIXTRL_TRACK_MAP_DISABLED_VALUE@"
+ #endif /* !defined( @SIXTRL_TRACK_MAP_DISABLED ) */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#if !defined( SIXTRL_TRACK_BEAMBEAM4D )
+    #define SIXTRL_TRACK_BEAMBEAM4D @SIXTRL_TRACK_BEAMBEAM4D_FLAG@
+    #define SIXTRL_TRACK_BEAMBEAM4D_STR "@SIXTRL_TRACK_BEAMBEAM4D_FLAG@"
+#endif /* !defined( SIXTRL_TRACK_BEAMBEAM4D ) */
+
+#if !defined( SIXTRL_TRACK_BEAMBEAM6D )
+    #define SIXTRL_TRACK_BEAMBEAM6D @SIXTRL_TRACK_BEAMBEAM6D_FLAG@
+    #define SIXTRL_TRACK_BEAMBEAM6D_STR "@SIXTRL_TRACK_BEAMBEAM6D_FLAG@"
+#endif /* !defined( SIXTRL_TRACK_BEAMBEAM6D ) */
+
+#if !defined( SIXTRL_TRACK_SPACECHARGE )
+    #define SIXTRL_TRACK_SPACECHARGE @SIXTRL_TRACK_SC_FLAG@
+    #define SIXTRL_TRACK_SPACECHARGE_STR "@SIXTRL_TRACK_SC_FLAG@"
+#endif /* !defined( SIXTRL_TRACK_SPACECHARGE ) */
+
+#if !defined( SIXTRL_TRACK_TRICUB )
+    #define SIXTRL_TRACK_TRICUB @SIXTRL_TRACK_TRICUB_FLAG@
+    #define SIXTRL_TRACK_TRICUB_STR "@SIXTRL_TRACK_TRICUB_FLAG@"
+#endif /* !defined( SIXTRL_TRACK_TRICUB ) */
+
+/* ------------------------------------------------------------------------- */
+/* ----                     Global aperture check                       ---- */
+/* ------------------------------------------------------------------------- */
+
+#if !defined( SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS )
+    #define SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS @SIXTRL_GLOBAL_APERATURE_CHECK_ALWAYS_VALUE@
+    #define SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS_STR "@SIXTRL_GLOBAL_APERATURE_CHECK_ALWAYS_VALUE@"
+#endif /* !defined( SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS ) */
+
+#if !defined( SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL )
+    #define SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL @SIXTRL_GLOBAL_APERATURE_CHECK_CONDITIONAL_VALUE@
+    #define SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL_STR "@SIXTRL_GLOBAL_APERATURE_CHECK_CONDITIONAL_VALUE@"
+#endif /* !defined( SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL ) */
+
+#if !defined( SIXTRL_GLOBAL_APERTURE_CHECK_NEVER )
+    #define SIXTRL_GLOBAL_APERTURE_CHECK_NEVER @SIXTRL_GLOBAL_APERATURE_CHECK_NEVER_VALUE@
+    #define SIXTRL_GLOBAL_APERTURE_CHECK_NEVER_STR "@SIXTRL_GLOBAL_APERATURE_CHECK_NEVER_VALUE@"
+#endif /* !defined( SIXTRL_GLOBAL_APERTURE_CHECK_NEVER ) */
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+#if !defined( SIXTRL_APERTURE_CHECK_AT_DRIFT )
+    #define SIXTRL_APERTURE_CHECK_AT_DRIFT @SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG@
+    #define SIXTRL_APERTURE_CHECK_AT_DRIFT_STR "@SIXTRL_APERTURE_CHECK_AT_DRIFT_FLAG@"
+#endif /* !defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) */
+
+#if !defined( SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH )
+    #define SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH @SIXTRACKL_APERTURE_CHECK_MIN_DRIFT_LENGTH@
+    #define SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH_STR "@SIXTRACKL_APERTURE_CHECK_MIN_DRIFT_LENGTH@"
+#endif /* !defined( SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH ) */
 
 #if !defined( SIXTRL_APERTURE_X_LIMIT )
     #define SIXTRL_APERTURE_X_LIMIT @SIXTRACKL_APERTURE_X_LIMIT_VALUE@
+    #define SIXTRL_APERTURE_X_LIMIT_STR "@SIXTRACKL_APERTURE_X_LIMIT_VALUE@"
 #endif /* !defined( SIXTRL_APERTURE_X_LIMIT ) */
 
 #if !defined( SIXTRL_APERTURE_Y_LIMIT )
     #define SIXTRL_APERTURE_Y_LIMIT @SIXTRACKL_APERTURE_Y_LIMIT_VALUE@
+    #define SIXTRL_APERTURE_Y_LIMIT_STR "@SIXTRACKL_APERTURE_Y_LIMIT_VALUE@"
 #endif /* SIXTRL_APERTURE_Y_LIMIT */
 
 #endif /* SIXTRACKLIB_COMMON_GENERATED_CONFIGURATION_HEADER_H__ */
diff --git a/sixtracklib/common/internal/CMakeLists.txt b/sixtracklib/common/internal/CMakeLists.txt
index 9868a99d..c677d0b4 100644
--- a/sixtracklib/common/internal/CMakeLists.txt
+++ b/sixtracklib/common/internal/CMakeLists.txt
@@ -1,49 +1,37 @@
-set( SIXTRL_COMMON_INTERNAL_C99_SOURCES )
-set( SIXTRL_COMMON_INTERNAL_C99_HEADERS
-    beam_elements_defines.h
-    beam_elements_undef.h
-    buffer_garbage_defines.h
-    buffer_garbage_undef.h
-    buffer_main_defines.h
-    buffer_main_undef.h
-    buffer_object_defines.h
-    buffer_object_undef.h
-    namespace_defines.h
-    namespace_undef.h
-    objects_type_id.h
-    particles_defines.h
-    particles_undef.h
-    tools.h
-)
+set( SIXTRL_COMMON_INTERNAL_C99_SOURCES math_qgauss.c )
 
+set( SIXTRL_COMMON_INTERNAL_C99_HEADERS beam_elements_defines.h
+    beam_elements_undef.h buffer_garbage_defines.h buffer_garbage_undef.h
+    buffer_main_defines.h buffer_main_undef.h buffer_object_defines.h
+    buffer_object_undef.h math_constants.h math_factorial.h math_functions.h
+    math_interpol.h math_qgauss.h namespace_defines.h namespace_undef.h
+    objects_type_id.h particles_defines.h particles_undef.h tools.h )
 
-# add_library( sixtrack_common_internal OBJECT
-#     ${SIXTRL_COMMON_INTERNAL_C99_HEADERS}
-#     ${SIXTRL_COMMON_INTERNAL_C99_SOURCES}
-# )
+add_library( sixtrack_common_internal OBJECT
+    ${SIXTRL_COMMON_INTERNAL_C99_HEADERS}
+    ${SIXTRL_COMMON_INTERNAL_C99_SOURCES}
+)
 
-# target_include_directories( sixtrack_common_internal PRIVATE
-#     $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
-#     $<INSTALL_INTERFACE:include> )
+target_include_directories( sixtrack_common_internal PRIVATE
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
-# set_target_properties( sixtrack_common_internal PROPERTIES LINKER_LANGUAGE C
-#     POSITION_INDEPENDENT_CODE ON C_STANDARD 99 C_STANDARD_REQUIRED ON )
+set_target_properties( sixtrack_common_internal PROPERTIES LINKER_LANGUAGE C
+    POSITION_INDEPENDENT_CODE ON C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
-# target_compile_options( sixtrack_common_internal PRIVATE
-#     ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+target_compile_options( sixtrack_common_internal PRIVATE
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKLIB_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 
 set( SIXTRL_COMMON_INTERNAL_CXX_HEADERS track_job_base.h )
-
 set( SIXTRL_COMMON_INTERNAL_CXX_SOURCES
      track_job_base.cpp track_job.cpp track_job_cpu.cpp )
 
 add_library( sixtrack_common_internal_cxx OBJECT
     ${SIXTRL_COMMON_INTERNAL_CXX_HEADERS}
     ${SIXTRL_COMMON_INTERNAL_CXX_SOURCES}
-    ${SIXTRL_COMMON_INTERNAL_C99_HEADERS}
-)
+    ${SIXTRL_COMMON_INTERNAL_C99_HEADERS} )
 
 target_include_directories( sixtrack_common_internal_cxx PRIVATE
     $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
@@ -52,13 +40,14 @@ set_target_properties( sixtrack_common_internal_cxx PROPERTIES LINKER_LANGUAGE C
     POSITION_INDEPENDENT_CODE ON CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_internal_cxx PRIVATE
-    ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_CXX_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_internal as a module for sixtracklib:
 
 set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
-#     $<TARGET_OBJECTS:sixtrack_common_internal>
+    $<TARGET_OBJECTS:sixtrack_common_internal>
     $<TARGET_OBJECTS:sixtrack_common_internal_cxx> CACHE INTERNAL "" FORCE )
 
 # -----------------------------------------------------------------------------
diff --git a/sixtracklib/common/internal/compiler_attributes.h b/sixtracklib/common/internal/compiler_attributes.h
new file mode 100644
index 00000000..c34e8c80
--- /dev/null
+++ b/sixtracklib/common/internal/compiler_attributes.h
@@ -0,0 +1,15 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_COMPILER_ATTRIBUTES_H__
+#define SIXTRACKLIB_COMMON_INTERNAL_COMPILER_ATTRIBUTES_H__
+
+#if !defined SIXTRL_UNUSED
+    #if defined( __cplusplus )
+        #define SIXTRL_UNUSED( arg ) /* can be omitted -> nothing to do here! */
+    #elif ( ( defined( __GNUC__ ) && ( __GNUC__ >= 3 ) ) ) || \
+          ( defined( __clang__ ) )
+        #define SIXTRL_UNUSED( arg ) arg __attribute__((unused))
+    #else
+        #define SIXTRL_UNUSED( arg ) arg
+    #endif /* C++ / compiler */
+#endif /* !defined( SIXTRL_UNUSED ) */
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_COMPILER_ATTRIBUTES_H__ */
diff --git a/sixtracklib/common/internal/compiler_compability.h b/sixtracklib/common/internal/compiler_compability.h
new file mode 100644
index 00000000..5c1a4ed4
--- /dev/null
+++ b/sixtracklib/common/internal/compiler_compability.h
@@ -0,0 +1,44 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_COMPILER_COMPABILITY__
+#define SIXTRACKLIB_COMMON_INTERNAL_COMPILER_COMPABILITY__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <cstddef>
+    #include <iterator>
+    #include <memory>
+    #include <utility>
+    #include <type_traits>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if defined( __cplusplus )
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename T, typename... Args >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN std::unique_ptr< T >
+    make_unique( Args&&... args )
+    {
+        return std::unique_ptr< T >( new T( std::forward< Args >( args )... ) );
+    }
+
+    /* type-trait for is_iterator */
+
+    template< typename T, typename Enabled = void >
+    struct is_iterator
+    {
+       static constexpr bool value = false;
+    };
+
+    template< typename T >
+    struct is_iterator< T, typename std::enable_if<
+        !std::is_same< typename std::iterator_traits< T >::value_type,
+            void>::value, void >::type >
+    {
+       static constexpr bool value = true;
+    };
+
+    template< typename T, typename Enabled >
+    constexpr bool is_iterator< T, Enabled >::value;
+
+}
+#endif /* C++ */
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_COMPILER_COMPABILITY__ */
diff --git a/sixtracklib/common/internal/math_constants.h b/sixtracklib/common/internal/math_constants.h
new file mode 100644
index 00000000..ca6e49d4
--- /dev/null
+++ b/sixtracklib/common/internal/math_constants.h
@@ -0,0 +1,200 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_MATH_CONSTANTS_H__
+#define SIXTRACKLIB_COMMON_INTERNAL_MATH_CONSTANTS_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #if defined( __cplusplus )
+        #include <cstddef>
+        #include <cstdint>
+        #include <cstdlib>
+        #include <cmath>
+        #include <type_traits>
+    #else /* defined( __cplusplus ) */
+        #include <stddef.h>
+        #include <stdint.h>
+        #include <stdlib.h>
+        #include <math.h>
+    #endif /* defined( __cplusplus ) */
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/particles/definitions.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_MATH_CONST_PI )
+    #define SIXTRL_MATH_CONST_PI \
+        3.1415926535897932384626433832795028841971693993751L
+#endif /* !defined( SIXTRL_MATH_CONST_PI ) */
+
+#if !defined( SIXTRL_MATH_CONST_DEG2RAD )
+    #define SIXTRL_MATH_CONST_DEG2RAD \
+        0.0174532925199432957692369076848861271344287188854172546L
+#endif /* !defined( SIXTRL_MATH_CONST_DEG2RAD ) */
+
+#if !defined( SIXTRL_MATH_CONST_RAD2DEG )
+    #define SIXTRL_MATH_CONST_RAD2DEG \
+        57.29577951308232087679815481410517033240547246656432154916L
+#endif /* !defined( SIXTRL_MATH_CONST_RAD2DEG ) */
+
+#if !defined( SIXTRL_MATH_CONST_SQRT_PI )
+    #define SIXTRL_MATH_CONST_SQRT_PI \
+        1.77245385090551602729816748334114518279754945612238712821381L
+#endif /* !defined( SIXTRL_MATH_CONST_SQRT_PI ) */
+
+#if defined( __cplusplus )
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/internal/type_store_traits.hpp"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< class R, typename SFINAE_Enabled = void >
+    struct MathConstHelper
+    {
+        SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R get_pi() SIXTRL_NOEXCEPT_COND(
+            std::is_nothrow_copy_constructible< R >::value &&
+            std::is_nothrow_move_constructible< R >::value )
+        {
+            return static_cast< R >( SIXTRL_MATH_CONST_PI );
+        }
+
+        SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R get_deg2rad() SIXTRL_NOEXCEPT_COND(
+            std::is_nothrow_copy_constructible< R >::value &&
+            std::is_nothrow_move_constructible< R >::value )
+        {
+            return static_cast< R >( SIXTRL_MATH_CONST_DEG2RAD );
+        }
+
+        SIXTRL_STATIC SIXTRL_INLINE R get_rad2deg() SIXTRL_NOEXCEPT_COND(
+            std::is_nothrow_copy_constructible< R >::value &&
+            std::is_nothrow_move_constructible< R >::value )
+        {
+            return static_cast< R >( SIXTRL_MATH_CONST_RAD2DEG );
+        }
+
+        SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R get_sqrt_pi() SIXTRL_NOEXCEPT_COND(
+            std::is_nothrow_copy_constructible< R >::value &&
+            std::is_nothrow_move_constructible< R >::value )
+        {
+            return static_cast< R >( SIXTRL_MATH_CONST_SQRT_PI );
+        }
+    };
+
+    /* --------------------------------------------------------------------- */
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R MathConst_pi()
+        SIXTRL_NOEXCEPT_COND(
+            std::is_nothrow_copy_constructible< R >::value &&
+            std::is_nothrow_move_constructible< R >::value )
+    {
+        return MathConstHelper< R >::get_pi();
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R MathConst_deg2rad()
+        SIXTRL_NOEXCEPT_COND(
+            std::is_nothrow_copy_constructible< R >::value &&
+            std::is_nothrow_move_constructible< R >::value )
+    {
+        return MathConstHelper< R >::get_deg2rad();
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R MathConst_rad2deg()
+        SIXTRL_NOEXCEPT_COND(
+            std::is_nothrow_copy_constructible< R >::value &&
+            std::is_nothrow_move_constructible< R >::value )
+    {
+        return MathConstHelper< R >::get_rad2deg();
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R MathConst_sqrt_pi()
+        SIXTRL_NOEXCEPT_COND(
+            std::is_nothrow_copy_constructible< R >::value &&
+            std::is_nothrow_move_constructible< R >::value )
+    {
+        return MathConstHelper< R >::get_sqrt_pi();
+    }
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R NS(MathConst_pi)()
+{
+    return SIXTRL_CXX_NAMESPACE::MathConst_pi< R >();
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R NS(MathConst_deg2rad)()
+{
+    return SIXTRL_CXX_NAMESPACE::MathConst_deg2rad< R >();
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R NS(MathConst_rad2deg)()
+{
+    return SIXTRL_CXX_NAMESPACE::MathConst_rad2deg< R >();
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN R NS(MathConst_sqrt_pi)()
+{
+    return SIXTRL_CXX_NAMESPACE::MathConst_sqrt_pi< R >();
+}
+
+#endif /* C++ */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(MathConst_pi)( void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(MathConst_deg2rad)( void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+    NS(MathConst_rad2deg)( void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+    NS(MathConst_sqrt_pi)( void ) SIXTRL_NOEXCEPT;
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!        Inline Methods and Functions Implementations       !!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(MathConst_pi)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_MATH_CONST_PI;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(MathConst_deg2rad)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_MATH_CONST_DEG2RAD;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(MathConst_rad2deg)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_MATH_CONST_RAD2DEG;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(MathConst_sqrt_pi)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_MATH_CONST_SQRT_PI;
+}
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_MATH_CONSTANTS_H__ */
diff --git a/sixtracklib/common/internal/math_factorial.h b/sixtracklib/common/internal/math_factorial.h
new file mode 100644
index 00000000..e494f909
--- /dev/null
+++ b/sixtracklib/common/internal/math_factorial.h
@@ -0,0 +1,248 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_MATH_FACTORIAL_H__
+#define SIXTRACKLIB_COMMON_INTERNAL_MATH_FACTORIAL_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/type_store_traits.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus )
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <type_traits>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename I, typename T = SIXTRL_REAL_T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        std::is_integral< I >::value, T >::type
+    Math_factorial(
+        typename TypeMethodParamTraits< I >::const_argument_type n )
+    {
+        T result = T{ 1 };
+
+        switch( n )
+        {
+            case I{  0 }: { result = static_cast< T >(                   1 ); break; }
+            case I{  1 }: { result = static_cast< T >(                   1 ); break; }
+            case I{  2 }: { result = static_cast< T >(                   2 ); break; }
+            case I{  3 }: { result = static_cast< T >(                   6 ); break; }
+            case I{  4 }: { result = static_cast< T >(                  24 ); break; }
+            case I{  5 }: { result = static_cast< T >(                 120 ); break; }
+            case I{  6 }: { result = static_cast< T >(                 720 ); break; }
+            case I{  7 }: { result = static_cast< T >(                5040 ); break; }
+            case I{  8 }: { result = static_cast< T >(               40320 ); break; }
+            case I{  9 }: { result = static_cast< T >(              362880 ); break; }
+            case I{ 10 }: { result = static_cast< T >(             3628800 ); break; }
+            case I{ 11 }: { result = static_cast< T >(             3628800 ); break; }
+            case I{ 12 }: { result = static_cast< T >(           479001600 ); break; }
+            case I{ 13 }: { result = static_cast< T >(          6227020800 ); break; }
+            case I{ 14 }: { result = static_cast< T >(         87178291200 ); break; }
+            case I{ 15 }: { result = static_cast< T >(       1307674368000 ); break; }
+            case I{ 16 }: { result = static_cast< T >(      20922789888000 ); break; }
+            case I{ 17 }: { result = static_cast< T >(     355687428096000 ); break; }
+            case I{ 18 }: { result = static_cast< T >(    6402373705728000 ); break; }
+            case I{ 19 }: { result = static_cast< T >(  121645100408832000 ); break; }
+            case I{ 20 }: { result = static_cast< T >( 2432902008176640000 ); break; }
+
+            default:
+            {
+                I const nd = n / I{ 20 };
+                I const remainder = n % I{ 20 };
+
+                result = static_cast< T >( nd ) *
+                         static_cast< T >( 2432902008176640000 );
+
+                if( remainder != I{ 0 } )
+                {
+                    result += SIXTRL_CXX_NAMESPACE::Math_factorial<
+                        I, T >( remainder );
+                }
+            }
+        };
+
+        return result;
+    }
+
+    template< typename I, typename T = SIXTRL_REAL_T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        std::is_integral< I >::value, T >::type
+    Math_inv_factorial( typename TypeMethodParamTraits<
+        I >::const_argument_type n )
+    {
+        T result = T{ 1.0 };
+
+        switch( n )
+        {
+            case I{  0 }: { result = T{ 1   }; break; }
+            case I{  1 }: { result = T{ 1   }; break; }
+            case I{  2 }: { result = T{ 0.5 }; break; }
+            case I{  3 }: { result = T{ 0.166666666666666657    }; break; }
+            case I{  4 }: { result = T{ 0.0416666666666666644   }; break; }
+            case I{  5 }: { result = T{ 0.00833333333333333322  }; break; }
+            case I{  6 }: { result = T{ 0.00138888888888888894  }; break; }
+            case I{  7 }: { result = T{ 0.000198412698412698413 }; break; }
+            case I{  8 }: { result = T{ 2.48015873015873016e-05 }; break; }
+            case I{  9 }: { result = T{ 2.75573192239858925e-06 }; break; }
+            case I{ 10 }: { result = T{ 2.75573192239858883e-07 }; break; }
+            case I{ 11 }: { result = T{ 2.50521083854417202e-08 }; break; }
+            case I{ 12 }: { result = T{ 2.50521083854417202e-08 }; break; }
+            case I{ 13 }: { result = T{ 1.60590438368216133e-10 }; break; }
+            case I{ 14 }: { result = T{ 1.14707455977297245e-11 }; break; }
+            case I{ 15 }: { result = T{ 7.64716373181981641e-13 }; break; }
+            case I{ 16 }: { result = T{ 4.77947733238738525e-14 }; break; }
+            case I{ 17 }: { result = T{ 2.8114572543455206e-15  }; break; }
+            case I{ 18 }: { result = T{ 1.56192069685862253e-16 }; break; }
+            case I{ 19 }: { result = T{ 8.2206352466243295e-18  }; break; }
+            case I{ 20 }: { result = T{ 4.11031762331216484e-19 }; break; }
+
+            default:
+            {
+                result = T{ 1 } /
+                    SIXTRL_CXX_NAMESPACE::Math_factorial< I, T >( n );
+            }
+        };
+
+        return result;
+    }
+}
+
+template< typename I, typename T = SIXTRL_REAL_T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+    std::is_integral< I >::value, T >::type
+NS(Math_factorial)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    I >::const_argument_type n )
+{
+    return SIXTRL_CXX_NAMESPACE::Math_factorial< I, T >( n );
+}
+
+template< typename I, typename T = SIXTRL_REAL_T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+    std::is_integral< I >::value, T >::type
+NS(Math_inv_factorial)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    I >::const_argument_type n )
+{
+    return SIXTRL_CXX_NAMESPACE::Math_inv_factorial< I, T >( n );
+}
+
+#endif /* C++ */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_factorial)(
+    SIXTRL_UINT64_T const n ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_inv_factorial)(
+    SIXTRL_UINT64_T const n ) SIXTRL_NOEXCEPT;
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_factorial)(
+    SIXTRL_UINT64_T const n ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_REAL_T   real_t;
+    typedef SIXTRL_UINT64_T uint_t;
+
+    real_t result = ( real_t )1;
+
+    switch( n )
+    {
+        case ( uint_t )0:  { result = ( real_t )1;                   break; }
+        case ( uint_t )1:  { result = ( real_t )1;                   break; }
+        case ( uint_t )2:  { result = ( real_t )2;                   break; }
+        case ( uint_t )3:  { result = ( real_t )6;                   break; }
+        case ( uint_t )4:  { result = ( real_t )24;                  break; }
+        case ( uint_t )5:  { result = ( real_t )120;                 break; }
+        case ( uint_t )6:  { result = ( real_t )720;                 break; }
+        case ( uint_t )7:  { result = ( real_t )5040;                break; }
+        case ( uint_t )8:  { result = ( real_t )40320;               break; }
+        case ( uint_t )9:  { result = ( real_t )362880;              break; }
+        case ( uint_t )10: { result = ( real_t )3628800;             break; }
+        case ( uint_t )11: { result = ( real_t )3628800;             break; }
+        case ( uint_t )12: { result = ( real_t )479001600;           break; }
+        case ( uint_t )13: { result = ( real_t )6227020800;          break; }
+        case ( uint_t )14: { result = ( real_t )87178291200;         break; }
+        case ( uint_t )15: { result = ( real_t )1307674368000;       break; }
+        case ( uint_t )16: { result = ( real_t )20922789888000;      break; }
+        case ( uint_t )17: { result = ( real_t )355687428096000;     break; }
+        case ( uint_t )18: { result = ( real_t )6402373705728000;    break; }
+        case ( uint_t )19: { result = ( real_t )121645100408832000;  break; }
+        case ( uint_t )20: { result = ( real_t )2432902008176640000; break; }
+
+        default:
+        {
+            uint_t const nd = n / ( uint_t )20;
+            uint_t const remainder = n % ( uint_t )20;
+
+            result = ( ( real_t )nd ) * ( real_t )2432902008176640000;
+
+            if( remainder != ( uint_t )0 )
+            {
+                result += NS(Math_factorial)( remainder );
+            }
+        }
+    };
+
+    return result;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_inv_factorial)(
+    SIXTRL_UINT64_T const n ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_REAL_T   real_t;
+    typedef SIXTRL_UINT64_T uint_t;
+
+    real_t result = ( real_t )1.0;
+
+    switch( n )
+    {
+        case ( uint_t )0:  { result = ( real_t )1.0;                     break; }
+        case ( uint_t )1:  { result = ( real_t )1.0;                     break; }
+        case ( uint_t )2:  { result = ( real_t )0.5;                     break; }
+        case ( uint_t )3:  { result = ( real_t )0.166666666666666657;    break; }
+        case ( uint_t )4:  { result = ( real_t )0.0416666666666666644;   break; }
+        case ( uint_t )5:  { result = ( real_t )0.00833333333333333322;  break; }
+        case ( uint_t )6:  { result = ( real_t )0.00138888888888888894;  break; }
+        case ( uint_t )7:  { result = ( real_t )0.000198412698412698413; break; }
+        case ( uint_t )8:  { result = ( real_t )2.48015873015873016e-05; break; }
+        case ( uint_t )9:  { result = ( real_t )2.75573192239858925e-06; break; }
+        case ( uint_t )10: { result = ( real_t )2.75573192239858883e-07; break; }
+        case ( uint_t )11: { result = ( real_t )2.50521083854417202e-08; break; }
+        case ( uint_t )12: { result = ( real_t )2.50521083854417202e-08; break; }
+        case ( uint_t )13: { result = ( real_t )1.60590438368216133e-10; break; }
+        case ( uint_t )14: { result = ( real_t )1.14707455977297245e-11; break; }
+        case ( uint_t )15: { result = ( real_t )7.64716373181981641e-13; break; }
+        case ( uint_t )16: { result = ( real_t )4.77947733238738525e-14; break; }
+        case ( uint_t )17: { result = ( real_t )2.8114572543455206e-15;  break; }
+        case ( uint_t )18: { result = ( real_t )1.56192069685862253e-16; break; }
+        case ( uint_t )19: { result = ( real_t )8.2206352466243295e-18;  break; }
+        case ( uint_t )20: { result = ( real_t )4.11031762331216484e-19; break; }
+
+        default:
+        {
+            result = ( real_t )1.0 / NS(Math_factorial)( n );
+        }
+    };
+
+    return result;
+}
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_MATH_FACTORIAL_H__ */
diff --git a/sixtracklib/common/internal/math_functions.h b/sixtracklib/common/internal/math_functions.h
new file mode 100644
index 00000000..4fe91b8e
--- /dev/null
+++ b/sixtracklib/common/internal/math_functions.h
@@ -0,0 +1,1009 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_MATH_FUNCTIONS_H__
+#define SIXTRACKLIB_COMMON_INTERNAL_MATH_FUNCTIONS_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #if defined( __cplusplus )
+        #include <algorithm>
+        #include <type_traits>
+        #include <cfloat>
+        #include <cmath>
+    #else
+        #include <math.h>
+        #include <float.h>
+    #endif /* __cplusplus */
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/type_store_traits.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus )
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+        typename TypeMethodParamTraits< T >::value_type >::type
+    sign( typename TypeMethodParamTraits< T >::const_argument_type
+        arg ) SIXTRL_NOEXCEPT
+    {
+        typedef typename TypeMethodParamTraits< T >::value_type value_t;
+        return ( arg >= value_t{ 0 } ) ? value_t{ 1 } : value_t{ -1 };
+    }
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        !SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+        typename TypeMethodParamTraits< T >::value_type >::type
+    sign( typename TypeMethodParamTraits< T >::const_argument_type
+        arg ) SIXTRL_NOEXCEPT
+    {
+        typedef typename TypeMethodParamTraits< T >::value_type value_t;
+
+        return static_cast< value_t >( value_t{ 0 } < arg ) -
+               static_cast< value_t >( arg < value_t{ 0 } );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+        typename TypeMethodParamTraits< T >::value_type >::type
+    abs( typename TypeMethodParamTraits< T >::const_argument_type
+        arg ) SIXTRL_NOEXCEPT
+    {
+        typedef typename TypeMethodParamTraits< T >::value_type value_t;
+        return ( arg >= value_t{ 0 } ) ? arg : -arg;
+    }
+
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        !SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+        typename TypeMethodParamTraits< T >::value_type >::type
+    abs( typename TypeMethodParamTraits< T >::const_argument_type
+        arg ) SIXTRL_NOEXCEPT
+    {
+        return arg * SIXTRL_CXX_NAMESPACE::sign< T >( arg );
+    }
+}
+#endif /* C++ */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus )
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type sin( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::sin;
+        #endif /* ADL / Host */
+        return sin( arg );
+    }
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type asin( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::asin;
+        #endif /* ADL / Host */
+
+        SIXTRL_ASSERT( st::Type_comp_all_more_or_equal< typename
+            TypeMethodParamTraits< T >::value_type >( arg,
+                typename TypeMethodParamTraits< T >::value_type{ -1 } ) );
+        SIXTRL_ASSERT( st::Type_comp_all_less_or_equal< typename
+            TypeMethodParamTraits< T >::value_type >( arg,
+                typename TypeMethodParamTraits< T >::value_type{ +1 } ) );
+
+        asin( arg );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type cos( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::cos;
+        #endif /* ADL / Host */
+        return cos( arg );
+    }
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type acos( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::acos;
+        #endif /* ADL / Host */
+        SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more_or_equal<
+            typename TypeMethodParamTraits< T >::value_type >( arg,
+                typename TypeMethodParamTraits< T >::value_type{ -1 } ) );
+        SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_less_or_equal<
+            typename TypeMethodParamTraits< T >::value_type >( arg,
+                typename TypeMethodParamTraits< T >::value_type{ +1 } ) );
+
+        return acos( arg );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type tan( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::tan;
+        #endif /* ADL / Host */
+        return tan( arg );
+    }
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type atan2(
+        typename TypeMethodParamTraits< T >::const_argument_type y,
+        typename TypeMethodParamTraits< T >::const_argument_type x
+    ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::atan2;
+        #endif /* ADL / Host */
+        return atan2( y, x );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type sqrt( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::sqrt;
+        #endif /* ADL / Host */
+        SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more_or_equal<
+            typename TypeMethodParamTraits< T >::value_type >( arg,
+                typename TypeMethodParamTraits< T >::value_type{ 0 } ) );
+
+        return sqrt( arg );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type exp( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::exp;
+        #endif /* ADL / Host */
+        return exp( arg );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type log( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::log;
+        #endif /* ADL / Host */
+        SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more< typename
+            TypeMethodParamTraits< T >::value_type >( arg, typename
+                TypeMethodParamTraits< T >::value_type{ 0 } ) );
+
+        return log( arg );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< T >::value_type gamma( typename
+        TypeMethodParamTraits< T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::tgamma;
+        #endif /* ADL / Host */
+
+        #if !defined( _GPUCODE )
+        SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more_or_equal< T >(
+                arg, typename TypeMethodParamTraits< T >::value_type{ 1 } /
+                    std::numeric_limits< typename TypeMethodParamTraits<
+                        T >::value_type >::max() ) &&
+            SIXTRL_CXX_NAMESPACE::Type_comp_all_less_or_equal< typename
+            TypeMethodParamTraits< T >::value_type >( arg, typename
+                TypeMethodParamTraits< T >::value_type{ 171.7 } ) );
+        #endif /* Host */
+
+        return tgamma( arg );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+        typename TypeMethodParamTraits< T >::value_type >::type
+    pow( typename TypeMethodParamTraits< T >::const_argument_type arg,
+         typename TypeMethodParamTraits< T >::const_argument_type n
+       ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::pow;
+        #endif /* !defined( _GPUCODE ) */
+        return pow( arg, n );
+    }
+
+    template< typename T, typename I = int64_t >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >() &&
+        SIXTRL_CXX_NAMESPACE::Type_is_scalar< I >() &&
+        std::is_integral< I >(),
+        typename TypeMethodParamTraits< T >::value_type >::type
+    pow_int_exp(
+        typename TypeMethodParamTraits< T >::const_argument_type base,
+        typename TypeMethodParamTraits< I >::const_argument_type n
+    ) SIXTRL_NOEXCEPT
+    {
+        #if defined( _GPUCODE ) && defined( __OPENCL_VERSION__ )
+        return pown( base, n );
+        #elif ( __cplusplus >= 201103L )
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::pow;
+        #endif /* ADL / Host */
+        return pow( base, n );
+        #else
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::abs;
+        #endif /* ADL / Host */
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        typedef typename st::TypeMethodParamTraits< I >::value_type int_t;
+        typedef typename st::TypeMethodParamTraits< T >::value_type real_t;
+
+        real_t result;
+        int_t const pos_exp = abs( n );
+
+        SIXTRL_ASSERT( ( st::Type_comp_all_more< T >(
+            st::abs< T >( base ), real_t{ 0 } ) ) || ( n > int_t{ 0 } ) );
+
+        switch( pos_exp )
+        {
+            case 0:
+            {
+                result = real_t{ 1 };
+                break;
+            }
+
+            case 1:
+            {
+                result = base;
+                break;
+            }
+
+            case 2:
+            {
+                result = base * base;
+                break;
+            }
+
+            case 3:
+            {
+                result = base * base * base;
+                break;
+            }
+
+            case 4:
+            {
+                real_t const base_squ = base * base;
+                result = base_squ * base_squ;
+                break;
+            }
+
+            case 5:
+            {
+                real_t const base_squ = base * base;
+                result = base_squ * base_squ * base;
+                break;
+            }
+
+            case 6:
+            {
+                real_t const base_cub = base * base * base;
+                result = base_cub * base_cub;
+                break;
+            }
+
+            case 7:
+            {
+                real_t const base_cub = base * base * base;
+                result = base_cub * base_cub * base;
+                break;
+            }
+
+            case 8:
+            {
+                real_t const base_squ = base * base;
+                real_t const base_quad = base_squ * base_squ;
+                result = base_quad * base_quad;
+                break;
+            }
+
+            default:
+            {
+                real_t const base_pow_8 =
+                    st::pow_int_exp< T, I >( base, int_t{ 8 } );
+
+                result  = st::pow_int_exp< T, I >( base_pow_8, pos_exp >> 3 );
+                result *= st::pow_int_exp< T, I >( base_pow_8,
+                    pos_exp - ( ( pos_exp >> 3 ) << 3 ) );
+            }
+        };
+
+        return ( n >= int_t{ 0 } ) ? result : real_t{ 1 }  / result;
+        #endif
+    }
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+        SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+        typename TypeMethodParamTraits< T >::value_type >::type
+    pow_positive_base(
+        typename TypeMethodParamTraits< T >::const_argument_type base,
+        typename TypeMethodParamTraits< T >::const_argument_type n
+    ) SIXTRL_NOEXCEPT
+    {
+        #if defined( _GPUCODE ) && defined( __OPENCL_VERSION__ )
+        return powr( base, n );
+        #else
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::pow;
+        #endif /* ADL / Host */
+        return pow( base, n );
+        #endif
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename std::enable_if< SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+    typename TypeMethodParamTraits< T >::value_type >::type
+    max( typename TypeMethodParamTraits< T >::const_argument_type lhs,
+         typename TypeMethodParamTraits< T >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::max;
+        #endif /* ADL / Host */
+        return max( lhs, rhs );
+    }
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename std::enable_if< SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+    typename TypeMethodParamTraits< T >::value_type >::type
+    min( typename TypeMethodParamTraits< T >::const_argument_type lhs,
+         typename TypeMethodParamTraits< T >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        #if !defined( _GPUCODE ) /* ADL! */
+        using std::min;
+        #endif /* ADL / Host */
+        return min( lhs, rhs );
+    }
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(sin)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    using std::sin;
+    return sin( arg );
+}
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(asin)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    using std::asin;
+    SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more_or_equal< typename
+        SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type >( arg,
+            typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+                T >::value_type{ -1 } ) );
+    SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more_or_equal< typename
+        SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type >( arg,
+            typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+                T >::value_type{ +1 } ) );
+
+    return asin( arg );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(cos)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    using std::cos;
+    return cos( arg );
+}
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(acos)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    using std::acos;
+    SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more_or_equal< typename
+        SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type >( arg,
+            typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+                T >::value_type{ -1 } ) );
+    SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more_or_equal< typename
+        SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type >( arg,
+            typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+                T >::value_type{ +1 } ) );
+
+    return acos( arg );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(tan)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    using std::tan;
+    return tan( arg );
+}
+
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(atan2)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+                T >::const_argument_type y,
+           typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+                T >::const_argument_type x ) SIXTRL_NOEXCEPT
+{
+    using std::atan2;
+    return atan2( y, x );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(sqrt)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    using std::sqrt;
+    SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more_or_equal< typename
+        SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type >( arg,
+            typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+                T >::value_type{ 0 } ) );
+
+    return sqrt( arg );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(exp)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    using std::exp;
+    return exp( arg );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(log)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    using std::log;
+    SIXTRL_ASSERT( SIXTRL_CXX_NAMESPACE::Type_comp_all_more< typename
+        SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type >( arg,
+            typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+                T >::value_type{ 0 } ) );
+
+    return log( arg );
+}
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(gamma)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    return SIXTRL_CXX_NAMESPACE::gamma< T >( arg );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+    SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::value_type >::type
+NS(sign)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    typedef typename st::TypeMethodParamTraits< T >::value_type value_t;
+    return ( arg >= value_t{ 0 } ) ? value_t{  1  } : value_t{ -1  };
+}
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+    !SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::value_type >::type
+NS(sign)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    typedef typename st::TypeMethodParamTraits< T >::value_type value_t;
+    return static_cast< value_t >( value_t{ 0 } < arg ) -
+           static_cast< value_t >( arg < value_t{ 0 } );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+    SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::value_type >::type
+NS(abs)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    typedef typename st::TypeMethodParamTraits< T >::value_type value_t;
+    return ( arg >= value_t{ 0 } ) ? arg : -arg;
+}
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename std::enable_if<
+    !SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >(),
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::value_type >::type
+NS(abs)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    T >::const_argument_type arg ) SIXTRL_NOEXCEPT
+{
+    return arg * SIXTRL_CXX_NAMESPACE::sign< T >( arg );
+}
+
+ /* - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type NS(pow)(
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type arg,
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type n ) SIXTRL_NOEXCEPT
+{
+    return SIXTRL_CXX_NAMESPACE::pow< T >( arg, n );
+}
+
+template< typename T, typename I = int64_t >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(pow_int_exp)(
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type base,
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        I >::const_argument_type n ) SIXTRL_NOEXCEPT
+{
+    return SIXTRL_CXX_NAMESPACE::pow_int_exp< T, I >( base, n );
+}
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type
+NS(pow_positive_base)(
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type base,
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type n ) SIXTRL_NOEXCEPT
+{
+    return SIXTRL_CXX_NAMESPACE::pow_positive_base< T >( base, n );
+}
+
+/* - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type NS(max)(
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type lhs,
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type rhs ) SIXTRL_NOEXCEPT
+{
+    return SIXTRL_CXX_NAMESPACE::max( lhs, rhs );
+}
+
+template< typename T >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< T >::value_type NS(min)(
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type lhs,
+    typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+        T >::const_argument_type rhs ) SIXTRL_NOEXCEPT
+{
+    return SIXTRL_CXX_NAMESPACE::min( lhs, rhs );
+}
+
+#endif /* defined( __cplusplus ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(sin)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(asin)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(cos)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(acos)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(tan)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(atan2)( SIXTRL_REAL_T const y, SIXTRL_REAL_T const x ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(sqrt)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(exp)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(log)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(gamma)(
+    SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(sign)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(abs)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(pow)( SIXTRL_REAL_T const base, SIXTRL_REAL_T const n ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(pow_positive_base)( SIXTRL_REAL_T const base,
+                       SIXTRL_REAL_T const n ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(pow_int_exp)( SIXTRL_REAL_T const base,
+                 SIXTRL_INT64_T const n ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(min)( SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(max)( SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(sin)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::sin;
+    #endif /* Host, ADL */
+
+    return sin( arg );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(asin)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::asin;
+    #endif /* Host, ADL */
+
+    SIXTRL_ASSERT( ( arg >= ( SIXTRL_REAL_T )-1 ) &&
+                   ( arg <= ( SIXTRL_REAL_T )+1 ) );
+    return asin( arg );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(cos)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::cos;
+    #endif /* Host, ADL */
+
+    return cos( arg );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(acos)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::acos;
+    #endif /* Host, ADL */
+
+    SIXTRL_ASSERT( ( arg >= ( SIXTRL_REAL_T )-1 ) &&
+                   ( arg <= ( SIXTRL_REAL_T )+1 ) );
+    return acos( arg );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(tan)( SIXTRL_REAL_T const x ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::tan;
+    #endif /* Host, ADL */
+    return tan( x );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(atan2)(
+    SIXTRL_REAL_T const y, SIXTRL_REAL_T const x ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::atan2;
+    #endif /* Host, ADL */
+    return atan2( y, x );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(sqrt)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::sqrt;
+    #endif /* Host, ADL */
+    SIXTRL_ASSERT( arg >= ( SIXTRL_REAL_T )0 );
+    return sqrt( arg );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(exp)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::exp;
+    #endif /* ADL / Host */
+    return exp( arg );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(log)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::log;
+    #endif /* ADL / Host */
+
+    SIXTRL_ASSERT( arg > ( SIXTRL_REAL_T )0 );
+    return log( arg );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(gamma)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::tgamma;
+    #endif /* ADL / Host */
+
+    #if !defined( _GPUCODE )
+    SIXTRL_ASSERT( ( SIXTRL_REAL_T )171.7 >= arg );
+    SIXTRL_ASSERT( ( SIXTRL_REAL_T )1 / DBL_MAX <= arg );
+    #endif /* _GPUCODE */
+
+    return tgamma( arg );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(sign)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    typedef SIXTRL_REAL_T real_t;
+    return ( arg >= ( real_t )0 ) ? ( ( real_t )1 ) : ( ( real_t )-1 );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(abs)( SIXTRL_REAL_T const arg ) SIXTRL_NOEXCEPT
+{
+    #if defined( _GPUCODE )
+    return fabs( arg );
+    #elif defined( __cplusplus )
+    using std::fabs; /* ADL */
+    return fabs( arg );
+    #else
+    typedef SIXTRL_REAL_T real_t;
+    return ( arg >= ( real_t )0 ) ? arg : -arg;
+    #endif
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(pow)(
+    SIXTRL_REAL_T const base, SIXTRL_REAL_T const n ) SIXTRL_NOEXCEPT
+{
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::pow;
+    #endif /* ADL / Host */
+
+    return pow( base, n );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(pow_positive_base)(
+    SIXTRL_REAL_T const base, SIXTRL_REAL_T const n ) SIXTRL_NOEXCEPT
+{
+    #if defined( _GPUCODE ) && defined( __OPENCL_VERSION__ )
+    return powr( base, n );
+    #else
+    #if defined( __cplusplus ) && !defined( _GPUCODE ) /* ADL */
+    using std::pow;
+    #endif /* ADL / Host */
+    return pow( base, n );
+    #endif
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(pow_int_exp)( SIXTRL_REAL_T const base,
+                 SIXTRL_INT64_T const n ) SIXTRL_NOEXCEPT
+{
+    #if defined( _GPUCODE ) && defined( __OPENCL_VERSION__ )
+        return pown( base, n );
+        #elif defined( __cplusplus ) && ( __cplusplus >= 201103L )
+        #if !defined( _GPUCODE ) /* ADL */
+        using std::pow;
+        #endif /* ADL / Host */
+        return pow( base, n );
+        #else
+        #if !defined( _GPUCODE ) && defined( __cplusplus ) /* ADL */
+        using std::llabs;
+        #endif /* ADL / Host */
+        typedef SIXTRL_REAL_T real_t;
+        typedef SIXTRL_INT64_T int_t;
+
+        real_t result;
+        int_t const pos_exp = llabs( n );
+
+        switch( pos_exp )
+        {
+            case 0:
+            {
+                result = ( real_t )1;
+                break;
+            }
+
+            case 1:
+            {
+                result = base;
+                break;
+            }
+
+            case 2:
+            {
+                result = base * base;
+                break;
+            }
+
+            case 3:
+            {
+                result = base * base * base;
+                break;
+            }
+
+            case 4:
+            {
+                real_t const base_squ = base * base;
+                result = base_squ * base_squ;
+                break;
+            }
+
+            case 5:
+            {
+                real_t const base_squ = base * base;
+                result = base_squ * base_squ * base;
+                break;
+            }
+
+            case 6:
+            {
+                real_t const base_cub = base * base * base;
+                result = base_cub * base_cub;
+                break;
+            }
+
+            case 7:
+            {
+                real_t const base_cub = base * base * base;
+                result = base_cub * base_cub * base;
+                break;
+            }
+
+            case 8:
+            {
+                real_t const base_squ = base * base;
+                real_t const base_quad = base_squ * base_squ;
+                result = base_quad * base_quad;
+                break;
+            }
+
+            default:
+            {
+                real_t const base_pow_8 = NS(pow_int_exp)( base, ( int_t )8 );
+                result  = NS(pow_int_exp)( base_pow_8, pos_exp >> 3 );
+                result *= NS(pow_int_exp)( base_pow_8,
+                    pos_exp - ( ( pos_exp >> 3 ) << 3 ) );
+            }
+        };
+
+        return ( n >= ( int_t )0 ) ? result : ( real_t )1  / result;
+        #endif
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(min)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    #if defined( _GPUCODE )
+    return min( lhs, rhs );
+    #elif defined( __cplusplus ) /* ADL */
+    using std::min;
+    return min( lhs, rhs );
+    #else
+    return ( lhs <= rhs ) ? lhs : rhs;
+    #endif /* _GPUCODE */
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(max)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    #if defined( _GPUCODE )
+    return max( lhs, rhs );
+    #elif defined( __cplusplus ) /* ADL */
+    using std::max;
+    return max( lhs, rhs );
+    #else
+    return ( lhs >= rhs ) ? lhs : rhs;
+    #endif /* _GPUCODE */
+}
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_MATH_FUNCTIONS_H__ */
diff --git a/sixtracklib/common/internal/math_interpol.h b/sixtracklib/common/internal/math_interpol.h
new file mode 100644
index 00000000..19c3fcec
--- /dev/null
+++ b/sixtracklib/common/internal/math_interpol.h
@@ -0,0 +1,1037 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_MATH_INTERPOL_H__
+#define SIXTRACKLIB_COMMON_INTERNAL_MATH_INTERPOL_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <math.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/internal/math_functions.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* C++, Host */
+
+typedef SIXTRL_INT64_T NS(math_abscissa_idx_t);
+
+SIXTRL_STATIC SIXTRL_FN NS(math_abscissa_idx_t) NS(Math_abscissa_index_equ)(
+    SIXTRL_REAL_T const x_value, SIXTRL_REAL_T const x0,
+    SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_x_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(math_abscissa_idx_t) NS(Math_abscissa_index_equ_ex)(
+    SIXTRL_REAL_T const x_value, SIXTRL_REAL_T const x0,
+    SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_x_values ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+typedef SIXTRL_UINT64_T NS(math_interpol_int_t);
+
+typedef enum
+{
+    NS(MATH_INTERPOL_LINEAR) = 0,
+    NS(MATH_INTERPOL_CUBIC) = 1,
+    NS(MATH_INTERPOL_NONE)  = 255
+}
+NS(math_interpol_t);
+
+typedef enum
+{
+    NS(MATH_INTERPOL_LINEAR_BOUNDARY_NONE)        = 0,
+    NS(MATH_INTERPOL_LINEAR_BOUNDARY_DEFAULT)     = 0,
+    NS(MATH_INTERPOL_CUBIC_BOUNDARY_NATURAL)      = 1,
+    NS(MATH_INTERPOL_CUBIC_BOUNDARY_CLAMPED)      = 2,
+    NS(MATH_INTERPOL_CUBIC_BOUNDARY_PROPORTIONAL) = 3,
+    NS(MATH_INTERPOL_CUBIC_BOUNDARY_NOT_A_KNOT)   = 4,
+    NS(MATH_INTERPOL_CUBIC_BOUNDARY_DEFAULT)      = 1
+}
+NS(math_interpol_boundary_t);
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(Math_interpol_boundary_begin_default_param)(
+    NS(math_interpol_boundary_t) const boundary_type ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(Math_interpol_boundary_end_default_param)(
+    NS(math_interpol_boundary_t) const boundary_type ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Math_interpol_linear_prepare_equ)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT yp_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_boundary_t) const begin_boundary_type,
+    NS(math_interpol_boundary_t) const end_boundary_type,
+    SIXTRL_REAL_T const begin_boundary_param,
+    SIXTRL_REAL_T const end_boundary_param ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Math_interpol_cubic_prepare_equ)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT yp_begin,
+    SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT temp_values_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_boundary_t) const begin_boundary_type,
+    NS(math_interpol_boundary_t) const end_boundary_type,
+    SIXTRL_REAL_T const begin_boundary_param,
+    SIXTRL_REAL_T const end_boundary_param ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN NS(arch_status_t) NS(Math_interpol_prepare_equ)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT derivatives_begin,
+    SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT temp_values_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_linear_y_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_linear_yp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_linear_ypp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_linear_y_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_linear_yp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_linear_ypp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_cubic_y_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_cubic_yp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_cubic_ypp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_cubic_y_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_cubic_yp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_cubic_ypp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp_begin,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_y_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_yp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_ypp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_y_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_yp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_interpol_ypp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT;
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+
+/* ************************************************************************* */
+/* ************************************************************************* */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_INLINE NS(math_abscissa_idx_t) NS(Math_abscissa_index_equ)(
+    SIXTRL_REAL_T const x_value, SIXTRL_REAL_T const x0,
+    SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_x_values ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( !isinf( dx ) && !isnan( dx ) );
+    SIXTRL_ASSERT( !isinf( x_value ) && !isnan( x_value ) );
+    SIXTRL_ASSERT( !isinf( x0 ) && !isnan( x0 ) );
+    SIXTRL_ASSERT( num_x_values >= ( NS(math_abscissa_idx_t) )0 );
+    SIXTRL_ASSERT( dx > ( SIXTRL_REAL_T )0 );
+    SIXTRL_ASSERT( x_value >= x0 );
+    SIXTRL_ASSERT( x_value <= ( x0 + dx * ( SIXTRL_REAL_T )num_x_values ) );
+    ( void )num_x_values;
+
+    return ( NS(math_abscissa_idx_t) )( ( x_value - x0 ) / dx );
+}
+
+SIXTRL_INLINE NS(math_abscissa_idx_t) NS(Math_abscissa_index_equ_ex)(
+    SIXTRL_REAL_T const x_value, SIXTRL_REAL_T const x0,
+    SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_x_values ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T const max_x = x0 + dx * ( SIXTRL_REAL_T )num_x_values;
+
+    SIXTRL_ASSERT( !isinf( dx ) && !isnan( dx ) );
+    SIXTRL_ASSERT( !isinf( x_value ) && !isnan( x_value ) );
+    SIXTRL_ASSERT( !isinf( x0 ) && !isnan( x0 ) );
+    SIXTRL_ASSERT( num_x_values >= ( NS(math_abscissa_idx_t) )0 );
+    SIXTRL_ASSERT( dx > ( SIXTRL_REAL_T )0 );
+
+    return ( x_value >= x0 )
+        ? ( ( x_value < max_x )
+                ? NS(Math_abscissa_index_equ)( x_value, x0, dx, num_x_values )
+                : num_x_values )
+        : ( NS(math_abscissa_idx_t) )-1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_boundary_begin_default_param)(
+    NS(math_interpol_boundary_t) const boundary_type ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T param = ( SIXTRL_REAL_T )0;
+
+    switch( boundary_type )
+    {
+        case NS(MATH_INTERPOL_CUBIC_BOUNDARY_PROPORTIONAL):
+        {
+            param = ( SIXTRL_REAL_T )1;
+            break;
+        }
+
+        default:
+        {
+            param = ( SIXTRL_REAL_T )0;
+        }
+    }
+
+    return param;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_boundary_end_default_param)(
+    NS(math_interpol_boundary_t) const boundary_type ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_interpol_boundary_begin_default_param)( boundary_type );
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE NS(arch_status_t) NS(Math_interpol_linear_prepare_equ)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT yp,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_boundary_t) const begin_boundary_type,
+    NS(math_interpol_boundary_t) const end_boundary_type,
+    SIXTRL_REAL_T const begin_boundary_param,
+    SIXTRL_REAL_T const end_boundary_param ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    ( void )begin_boundary_type;
+    ( void )begin_boundary_param;
+
+    ( void )end_boundary_type;
+    ( void )end_boundary_param;
+
+    if( ( yp != SIXTRL_NULLPTR ) && ( y != SIXTRL_NULLPTR ) &&
+        ( yp != y ) && ( !isnan( x0 ) ) && ( !isinf( x0 ) ) &&
+        ( !isnan( dx ) ) && ( !isinf( dx ) ) && ( dx > ( SIXTRL_REAL_T )0 ) &&
+        ( num_values > ( NS(math_abscissa_idx_t) )1 ) )
+    {
+        NS(math_abscissa_idx_t) const nn = num_values - 1;
+        NS(math_abscissa_idx_t) ii = ( NS(math_abscissa_idx_t) )0;
+
+        SIXTRL_REAL_T y_ii_plus_1 = y[ 0 ];
+        SIXTRL_ASSERT( !isnan( y_ii_plus_1 ) );
+        SIXTRL_ASSERT( !isinf( y_ii_plus_1 ) );
+
+        for( ; ii < nn ; ++ii )
+        {
+            SIXTRL_REAL_T const y_ii = y_ii_plus_1;
+            y_ii_plus_1 = y[ ii + 1 ];
+            SIXTRL_ASSERT( !isnan( y_ii_plus_1 ) );
+            SIXTRL_ASSERT( !isinf( y_ii_plus_1 ) );
+
+            yp[ ii ] = ( y_ii_plus_1 - y_ii ) / dx;
+        }
+
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(Math_interpol_cubic_prepare_equ)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT ypp,
+    SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT temp_values,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_boundary_t) const begin_boundary_type,
+    NS(math_interpol_boundary_t) const end_boundary_type,
+    SIXTRL_REAL_T const begin_boundary_param,
+    SIXTRL_REAL_T const end_boundary_param ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( ( ypp != SIXTRL_NULLPTR ) && ( y  != SIXTRL_NULLPTR ) &&
+        ( temp_values != SIXTRL_NULLPTR ) &&
+        ( ypp != y ) &&
+        ( ( uintptr_t )ypp != ( uintptr_t )temp_values ) &&
+        ( ( uintptr_t )y   != ( uintptr_t )temp_values ) &&
+        ( !isnan( x0 ) ) && ( !isinf( x0 ) ) &&
+        ( !isnan( dx ) ) && ( !isinf( dx ) ) && ( dx > ( SIXTRL_REAL_T )0 ) &&
+        ( num_values > ( NS(math_abscissa_idx_t) )3 ) )
+    {
+        NS(math_abscissa_idx_t) const n_minus_1 = num_values - 1;
+        NS(math_abscissa_idx_t) const n_minus_2 = num_values - 2;
+        NS(math_abscissa_idx_t) const n_minus_3 = num_values - 3;
+
+        SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* l  = temp_values;
+        SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* d  = l  + num_values;
+        SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* h  = d  + num_values;
+        SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* g  = h  + num_values;
+        SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* dy = g  + num_values;
+
+        NS(math_abscissa_idx_t) ii = ( NS(math_abscissa_idx_t) )0;
+        status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS;
+
+        h[  0 ] = dx;
+        g[  0 ] = ( SIXTRL_REAL_T )0;
+        l[  0 ] = ( SIXTRL_REAL_T )0;
+        d[  0 ] = ( SIXTRL_REAL_T )0;
+        dy[ 0 ] = ( SIXTRL_REAL_T )0;
+
+        for( ii = 1 ; ii < n_minus_1 ; ++ii )
+        {
+            h[  ii ]  = dx;
+            g[  ii ]  = ( h[ ii - 1 ] + h[ ii ] ) * ( SIXTRL_REAL_T )2;
+
+            SIXTRL_ASSERT( !isnan( y[ ii + 1 ] ) && !isinf( y[ ii + 1 ] ) );
+            SIXTRL_ASSERT( !isnan( y[ ii     ] ) && !isinf( y[ ii     ] ) );
+            SIXTRL_ASSERT( !isnan( y[ ii - 1 ] ) && !isinf( y[ ii - 1 ] ) );
+
+            dy[ ii ]  = ( y[ ii + 1 ] - y[ ii ] ) / h[ ii ];
+            dy[ ii ] -= ( y[ ii ] - y[ ii - 1 ] ) / h[ ii - 1 ];
+            dy[ ii ] *= ( SIXTRL_REAL_T )6;
+        }
+
+        h[  n_minus_1 ] = dx;
+        g[  n_minus_1 ] = ( SIXTRL_REAL_T )0;
+        l[  n_minus_1 ] = ( SIXTRL_REAL_T )0;
+        d[  n_minus_1 ] = ( SIXTRL_REAL_T )0;
+        dy[ n_minus_1 ] = ( SIXTRL_REAL_T )0;
+
+        switch( begin_boundary_type )
+        {
+            case NS(MATH_INTERPOL_CUBIC_BOUNDARY_NATURAL):
+            {
+                break;
+            };
+
+            case NS(MATH_INTERPOL_CUBIC_BOUNDARY_CLAMPED):
+            {
+                dy[ 1 ] -= begin_boundary_param * h[ 0 ];
+                break;
+            }
+
+            case NS(MATH_INTERPOL_CUBIC_BOUNDARY_PROPORTIONAL):
+            {
+                g[ 1 ]  = ( begin_boundary_param + ( SIXTRL_REAL_T )2 );
+                g[ 1 ] *= h[ 0 ];
+                g[ 1 ] += h[ 1 ] * ( SIXTRL_REAL_T )2;
+                break;
+            }
+
+            case NS(MATH_INTERPOL_CUBIC_BOUNDARY_NOT_A_KNOT):
+            {
+                SIXTRL_REAL_T const d_h = ( h[ 0 ] * h[ 0 ] ) / h[ 1 ];
+
+                g[ 1 ]  = h[ 0 ] * ( SIXTRL_REAL_T )3;
+                g[ 1 ] += h[ 1 ] * ( SIXTRL_REAL_T )2;
+                g[ 1 ] += d_h;
+
+                h[ 1 ] -= d_h;
+                break;
+            }
+
+            default:
+            {
+                status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+            }
+        };
+
+        switch( end_boundary_type )
+        {
+            case NS(MATH_INTERPOL_CUBIC_BOUNDARY_NATURAL):
+            {
+                break;
+            };
+
+            case NS(MATH_INTERPOL_CUBIC_BOUNDARY_CLAMPED):
+            {
+                dy[ n_minus_2 ] -= end_boundary_param * h[ n_minus_2 ];
+                break;
+            }
+
+            case NS(MATH_INTERPOL_CUBIC_BOUNDARY_PROPORTIONAL):
+            {
+                g[ n_minus_2 ]  = h[ n_minus_1 ] * ( SIXTRL_REAL_T )2;
+                g[ n_minus_2 ] += h[ n_minus_2 ] * (
+                    end_boundary_param + ( SIXTRL_REAL_T )2 );
+                break;
+            }
+
+            case NS(MATH_INTERPOL_CUBIC_BOUNDARY_NOT_A_KNOT):
+            {
+                SIXTRL_REAL_T const d_h = ( h[ n_minus_2 ] *
+                    h[ n_minus_2 ] ) / h[ n_minus_3 ];
+
+                g[ n_minus_2 ]  = h[ n_minus_3 ] * ( SIXTRL_REAL_T )2;
+                g[ n_minus_2 ] += h[ n_minus_2 ] * ( SIXTRL_REAL_T )3;
+                g[ n_minus_2 ] += d_h;
+
+                h[ n_minus_3 ] -= d_h;
+                break;
+            }
+
+            default:
+            {
+                status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+            }
+        };
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            d[ 0 ] = g[ 1 ];
+            ypp[ 0 ] = dy[ 1 ];
+
+            for( ii = 1 ; ii < n_minus_2 ; ++ii )
+            {
+                SIXTRL_ASSERT( NS(abs)( d[ ii - 1 ] ) > ( SIXTRL_REAL_T )0 );
+                l[ ii ] = h[ ii ] / d[ ii -1 ];
+                d[ ii ] = g[ ii + 1 ] - l[ ii ] * h[ ii ];
+                ypp[ ii ] = dy[ ii + 1 ] - ypp[ ii -1 ] * l[ ii ];
+            }
+
+            ii = n_minus_3;
+            SIXTRL_ASSERT( NS(abs)( d[ ii ] ) > ( SIXTRL_REAL_T )0 );
+            ypp[ ii + 1 ] = ypp[ ii ] / d[ ii ];
+
+            for( ii = n_minus_3 - 1 ; ii >= 0 ; --ii )
+            {
+                SIXTRL_ASSERT( NS(abs)( d[ ii ] ) > ( SIXTRL_REAL_T )0 );
+                ypp[ ii + 1 ]  = ( ypp[ ii ] - h[ ii + 1 ] * ypp[ ii + 2 ] );
+                ypp[ ii + 1 ] /= d[ ii ];
+            }
+        }
+
+        if( status == ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS )
+        {
+            switch( begin_boundary_type )
+            {
+                case NS(MATH_INTERPOL_CUBIC_BOUNDARY_NATURAL):
+                {
+                    ypp[ 0 ] = ( SIXTRL_REAL_T )0;
+                    break;
+                };
+
+                case NS(MATH_INTERPOL_CUBIC_BOUNDARY_CLAMPED):
+                {
+                    ypp[ 0 ] = begin_boundary_param;
+                    break;
+                }
+
+                case NS(MATH_INTERPOL_CUBIC_BOUNDARY_PROPORTIONAL):
+                {
+                    ypp[ 0 ] = begin_boundary_param * ypp[ 1 ];
+                    break;
+                }
+
+                case NS(MATH_INTERPOL_CUBIC_BOUNDARY_NOT_A_KNOT):
+                {
+                    break;
+                }
+
+                default:
+                {
+                    status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+                }
+            };
+
+            switch( end_boundary_type )
+            {
+                case NS(MATH_INTERPOL_CUBIC_BOUNDARY_NATURAL):
+                {
+                    ypp[ n_minus_1 ] = ( SIXTRL_REAL_T )0;
+                    break;
+                };
+
+                case NS(MATH_INTERPOL_CUBIC_BOUNDARY_CLAMPED):
+                {
+                    ypp[ n_minus_1 ] = end_boundary_param;
+                    break;
+                }
+
+                case NS(MATH_INTERPOL_CUBIC_BOUNDARY_PROPORTIONAL):
+                {
+                    ypp[ n_minus_1 ] = end_boundary_param * ypp[ n_minus_2 ];
+                    break;
+                }
+
+                case NS(MATH_INTERPOL_CUBIC_BOUNDARY_NOT_A_KNOT):
+                {
+                    break;
+                }
+
+                default:
+                {
+                    status = ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+                }
+            };
+        }
+    }
+
+    return status;
+}
+
+SIXTRL_INLINE NS(arch_status_t) NS(Math_interpol_prepare_equ)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT yp,
+    SIXTRL_ARGPTR_DEC SIXTRL_REAL_T* SIXTRL_RESTRICT temp_values,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT
+{
+    NS(arch_status_t) status = ( NS(arch_status_t)
+        )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
+
+    if( interpol_type == NS(MATH_INTERPOL_LINEAR) )
+    {
+        SIXTRL_REAL_T const begin_param =
+            NS(Math_interpol_boundary_begin_default_param)(
+                NS(MATH_INTERPOL_LINEAR_BOUNDARY_DEFAULT) );
+
+        SIXTRL_REAL_T const end_param =
+            NS(Math_interpol_boundary_begin_default_param)(
+                NS(MATH_INTERPOL_LINEAR_BOUNDARY_DEFAULT) );
+
+        status = NS(Math_interpol_linear_prepare_equ)( yp, y, x0, dx,
+            num_values, NS(MATH_INTERPOL_LINEAR_BOUNDARY_DEFAULT),
+            NS(MATH_INTERPOL_LINEAR_BOUNDARY_DEFAULT), begin_param, end_param );
+    }
+    else if( interpol_type == NS(MATH_INTERPOL_CUBIC) )
+    {
+        SIXTRL_REAL_T const begin_param =
+            NS(Math_interpol_boundary_begin_default_param)(
+                NS(MATH_INTERPOL_CUBIC_BOUNDARY_DEFAULT) );
+
+        SIXTRL_REAL_T const end_param =
+            NS(Math_interpol_boundary_begin_default_param)(
+                NS(MATH_INTERPOL_CUBIC_BOUNDARY_DEFAULT) );
+
+        status = NS(Math_interpol_cubic_prepare_equ)( yp, temp_values, y,
+            x0, dx, num_values, NS(MATH_INTERPOL_CUBIC_BOUNDARY_DEFAULT),
+            NS(MATH_INTERPOL_CUBIC_BOUNDARY_DEFAULT), begin_param, end_param );
+    }
+
+    return status;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_linear_y_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    NS(math_abscissa_idx_t) const idx =
+        NS(Math_abscissa_index_equ)( x, x0, dx, num_values );
+
+    SIXTRL_ASSERT( idx >= ( NS(math_abscissa_idx_t) )0 );
+    SIXTRL_ASSERT( idx < num_values );
+    SIXTRL_ASSERT( y  != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( yp != SIXTRL_NULLPTR );
+
+    return y[ idx ] + ( x - ( x0 + dx * idx ) ) * yp[ idx ];
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_linear_yp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    NS(math_abscissa_idx_t) const idx =
+        NS(Math_abscissa_index_equ)( x, x0, dx, num_values );
+
+    SIXTRL_ASSERT( idx >= ( NS(math_abscissa_idx_t) )0 );
+    SIXTRL_ASSERT( idx < num_values );
+    SIXTRL_ASSERT( y  != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( yp != SIXTRL_NULLPTR );
+    ( void )y;
+
+    return yp[ idx ];
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_linear_ypp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( y  != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( yp != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Math_abscissa_index_equ)( x, x0, dx, num_values ) >=
+        ( NS(math_abscissa_idx_t) )0 );
+    SIXTRL_ASSERT( NS(Math_abscissa_index_equ)( x, x0, dx, num_values ) <
+        num_values );
+
+    ( void )x;
+    ( void )dx;
+    ( void )x0;
+    ( void )num_values;
+    ( void )y;
+    ( void )yp;
+
+    return ( SIXTRL_REAL_T )0;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_linear_y_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T y_interpolated = ( SIXTRL_REAL_T )0;
+
+    NS(math_abscissa_idx_t) idx =
+        NS(Math_abscissa_index_equ)( x, x0, dx, num_values );
+
+    if( ( idx >= num_values ) &&
+        ( num_values > ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        idx = num_values - 1;
+    }
+
+    SIXTRL_ASSERT( y  != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( yp != SIXTRL_NULLPTR );
+
+    if( ( idx >= ( NS(math_abscissa_idx_t) )0 ) && ( idx < num_values ) )
+    {
+        y_interpolated = y[ idx ] + ( x - ( x0 + dx * idx ) ) * yp[ idx ];
+    }
+    else if( ( idx < ( NS(math_abscissa_idx_t) )0 ) &&
+             ( num_values > ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        y_interpolated = y[ 0 ] - yp[ 0 ] * ( x0 - x );
+    }
+
+    return y_interpolated;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_linear_yp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T yp_interpolated = ( SIXTRL_REAL_T )0;
+
+    NS(math_abscissa_idx_t) idx =
+        NS(Math_abscissa_index_equ)( x, x0, dx, num_values );
+
+    if( ( idx >= num_values ) &&
+        ( num_values > ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        yp_interpolated = yp[ num_values - 1 ];
+    }
+    else if( ( idx < ( NS(math_abscissa_idx_t) )0 ) &&
+             ( num_values > ( NS(math_abscissa_idx_t) )0 ) )
+    {
+        yp_interpolated = yp[ 0 ];
+    }
+
+    SIXTRL_ASSERT( y  != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( yp != SIXTRL_NULLPTR );
+
+    ( void )y;
+
+    return yp_interpolated;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_linear_ypp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT yp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_interpol_linear_ypp_equ)( x, x0, dx, y, yp, num_values );
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_cubic_y_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ypp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T y_interpolated = ( SIXTRL_REAL_T )0;
+
+    NS(math_abscissa_idx_t) const idx =
+        NS(Math_abscissa_index_equ)( x, x0, dx, num_values );
+
+    SIXTRL_STATIC_VAR SIXTRL_REAL_T const SIX = ( SIXTRL_REAL_T )6;
+    SIXTRL_REAL_T const t2 = ( x0 + dx * ( idx + 1 ) - x ) / dx;
+    SIXTRL_REAL_T const t1 = ( x - ( x0 + dx * idx ) ) / dx;
+
+    SIXTRL_ASSERT( idx >= ( NS(math_abscissa_idx_t) )0 );
+    SIXTRL_ASSERT( idx < num_values );
+    SIXTRL_ASSERT( y != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ypp != SIXTRL_NULLPTR );
+
+    y_interpolated  = y[   idx + 1 ] * t1 + y[ idx ] * t2;
+    y_interpolated -= ypp[ idx     ] * dx * dx * ( t2 - t2 * t2 * t2 ) / SIX;
+    y_interpolated -= ypp[ idx + 1 ] * dx * dx * ( t1 - t1 * t1 * t1 ) / SIX;
+
+    return y_interpolated;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_cubic_yp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ypp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T yp_interpolated = ( SIXTRL_REAL_T )0;
+
+    SIXTRL_STATIC_VAR SIXTRL_REAL_T const ONE   = ( SIXTRL_REAL_T )1;
+    SIXTRL_STATIC_VAR SIXTRL_REAL_T const THREE = ( SIXTRL_REAL_T )3;
+    SIXTRL_STATIC_VAR SIXTRL_REAL_T const SIX   = ( SIXTRL_REAL_T )6;
+
+    NS(math_abscissa_idx_t) const idx =
+        NS(Math_abscissa_index_equ)( x, x0, dx, num_values );
+
+    SIXTRL_REAL_T const t2 = ( x0 + dx * ( idx + 1 ) - x ) / dx;
+    SIXTRL_REAL_T const t1 = ( x - ( x0 + dx * idx ) ) / dx;
+
+    SIXTRL_ASSERT( idx >= ( NS(math_abscissa_idx_t) )0 );
+    SIXTRL_ASSERT( idx <  num_values );
+    SIXTRL_ASSERT( y   != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ypp != SIXTRL_NULLPTR );
+
+    yp_interpolated  = ( y[ idx + 1 ] - y[ idx ] ) / dx;
+    yp_interpolated -= ypp[ idx     ] * dx * ( THREE * t2 * t2 - ONE ) / SIX;
+    yp_interpolated -= ypp[ idx + 1 ] * dx * ( ONE - THREE * t1 * t1 ) / SIX;
+
+    return yp_interpolated;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_cubic_ypp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ypp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    NS(math_abscissa_idx_t) const idx =
+        NS(Math_abscissa_index_equ)( x, x0, dx, num_values );
+
+    SIXTRL_ASSERT( idx >= ( NS(math_abscissa_idx_t) )0 );
+    SIXTRL_ASSERT( idx <  num_values );
+    SIXTRL_ASSERT( y   != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ypp != SIXTRL_NULLPTR );
+
+    return ( ypp[ idx     ] * ( x0 + dx * ( idx + 1 ) - x ) +
+             ypp[ idx + 1 ] * ( x - ( x0 + dx * idx ) ) ) / dx;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_cubic_y_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ypp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_interpol_cubic_y_equ)( x, x0, dx, y, ypp, num_values );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_cubic_yp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ypp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_interpol_cubic_yp_equ)( x, x0, dx, y, ypp, num_values );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_cubic_ypp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT ypp,
+    NS(math_abscissa_idx_t) const num_values ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_interpol_cubic_ypp_equ)( x, x0, dx, y, ypp, num_values );
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_y_equ)( SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT
+{
+    if( interpol_type == NS(MATH_INTERPOL_LINEAR) )
+    {
+        return NS(Math_interpol_linear_y_equ)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+    else if( interpol_type == NS(MATH_INTERPOL_CUBIC) )
+    {
+        return NS(Math_interpol_cubic_y_equ)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+
+    return ( SIXTRL_REAL_T )0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_yp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT
+{
+    if( interpol_type == NS(MATH_INTERPOL_LINEAR) )
+    {
+        return NS(Math_interpol_linear_yp_equ)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+    else if( interpol_type == NS(MATH_INTERPOL_CUBIC) )
+    {
+        return NS(Math_interpol_cubic_yp_equ)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+
+    return ( SIXTRL_REAL_T )0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_ypp_equ)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT
+{
+    if( interpol_type == NS(MATH_INTERPOL_LINEAR) )
+    {
+        return NS(Math_interpol_linear_ypp_equ)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+    else if( interpol_type == NS(MATH_INTERPOL_CUBIC) )
+    {
+        return NS(Math_interpol_cubic_ypp_equ)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+
+    return ( SIXTRL_REAL_T )0;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_y_equ_ex)( SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT
+{
+    if( interpol_type == NS(MATH_INTERPOL_LINEAR) )
+    {
+        return NS(Math_interpol_linear_y_equ_ex)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+    else if( interpol_type == NS(MATH_INTERPOL_CUBIC) )
+    {
+        return NS(Math_interpol_cubic_y_equ_ex)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+
+    return ( SIXTRL_REAL_T )0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_yp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT
+{
+    if( interpol_type == NS(MATH_INTERPOL_LINEAR) )
+    {
+        return NS(Math_interpol_linear_yp_equ_ex)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+    else if( interpol_type == NS(MATH_INTERPOL_CUBIC) )
+    {
+        return NS(Math_interpol_cubic_yp_equ_ex)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+
+    return ( SIXTRL_REAL_T )0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_interpol_ypp_equ_ex)(
+    SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const x0, SIXTRL_REAL_T const dx,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT y,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT derivatives,
+    NS(math_abscissa_idx_t) const num_values,
+    NS(math_interpol_t) const interpol_type ) SIXTRL_NOEXCEPT
+{
+    if( interpol_type == NS(MATH_INTERPOL_LINEAR) )
+    {
+        return NS(Math_interpol_linear_ypp_equ_ex)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+    else if( interpol_type == NS(MATH_INTERPOL_CUBIC) )
+    {
+        return NS(Math_interpol_cubic_ypp_equ_ex)(
+            x, x0, dx, y, derivatives, num_values );
+    }
+
+    return ( SIXTRL_REAL_T )0;
+}
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_MATH_INTERPOL_H__ */
diff --git a/sixtracklib/common/internal/math_qgauss.c b/sixtracklib/common/internal/math_qgauss.c
new file mode 100644
index 00000000..a5fe40e9
--- /dev/null
+++ b/sixtracklib/common/internal/math_qgauss.c
@@ -0,0 +1,47 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/math_qgauss.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+SIXTRL_REAL_T NS(Math_q_gauss_min_support_ext)(
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_q_gauss_min_support)( q, sqrt_beta );
+}
+
+SIXTRL_REAL_T NS(Math_q_gauss_max_support_ext)(
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_q_gauss_max_support)( q, sqrt_beta );
+}
+
+SIXTRL_REAL_T NS(Math_q_gauss_cq_ext)( SIXTRL_REAL_T const q ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_q_gauss_cq)( q );
+}
+
+SIXTRL_REAL_T NS(Math_q_gauss_sqrt_beta_from_gauss_sigma_ext)(
+    SIXTRL_REAL_T const sigma ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_q_gauss_sqrt_beta_from_gauss_sigma)( sigma );
+}
+
+SIXTRL_REAL_T NS(Math_q_gauss_exp_q_ext)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_q_gauss_exp_q)( x, q );
+}
+
+SIXTRL_REAL_T NS(Math_q_gauss_ext)( SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta,
+    SIXTRL_REAL_T const cq ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_q_gauss)( x, q, sqrt_beta, cq );
+}
+
+SIXTRL_REAL_T NS(Math_q_gauss_shifted_ext)( SIXTRL_REAL_T const x,
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta,
+    SIXTRL_REAL_T const cq, SIXTRL_REAL_T const mu ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_q_gauss_shifted)( x, q, sqrt_beta, cq, mu );
+}
diff --git a/sixtracklib/common/internal/math_qgauss.h b/sixtracklib/common/internal/math_qgauss.h
new file mode 100644
index 00000000..74ed77ac
--- /dev/null
+++ b/sixtracklib/common/internal/math_qgauss.h
@@ -0,0 +1,191 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_QGAUSS_H__
+#define SIXTRACKLIB_COMMON_INTERNAL_QGAUSS_H__
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+#if !defined( SIXTRL_MATH_QGAUSSIAN_Q_EPS )
+    #define SIXTRL_MATH_QGAUSSIAN_Q_EPS 1e-6L
+#endif /* SIXTRL_MATH_QGAUSSIAN_Q_EPS */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_q_gauss_min_support)(
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_q_gauss_max_support)(
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_q_gauss_cq)(
+    SIXTRL_REAL_T const q ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T
+NS(Math_q_gauss_sqrt_beta_from_gauss_sigma)(
+    SIXTRL_REAL_T const sigma ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_q_gauss_exp_q)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_q_gauss)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta,
+    SIXTRL_REAL_T const cq ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(Math_q_gauss_shifted)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta,
+    SIXTRL_REAL_T const cq, SIXTRL_REAL_T const mu ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(Math_q_gauss_min_support_ext)(
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(Math_q_gauss_max_support_ext)(
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(Math_q_gauss_cq_ext)(
+    SIXTRL_REAL_T const q ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T
+NS(Math_q_gauss_sqrt_beta_from_gauss_sigma_ext)(
+    SIXTRL_REAL_T const sigma ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(Math_q_gauss_exp_q_ext)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(Math_q_gauss_ext)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta,
+    SIXTRL_REAL_T const cq ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_REAL_T NS(Math_q_gauss_shifted_ext)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta,
+    SIXTRL_REAL_T const cq, SIXTRL_REAL_T const mu ) SIXTRL_NOEXCEPT;
+
+#endif /* Host */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* ************************************************************************* */
+/* ************************************************************************* */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <math.h>
+    #include <float.h>
+#endif /* #if !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/internal/math_constants.h"
+    #include "sixtracklib/common/internal/math_functions.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_q_gauss_min_support)(
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( q < ( SIXTRL_REAL_T )3 );
+    SIXTRL_ASSERT( sqrt_beta > ( SIXTRL_REAL_T )0 );
+    return ( q >= ( SIXTRL_REAL_T )1 )
+        ? ( SIXTRL_REAL_T )-1e10
+        : ( SIXTRL_REAL_T )-1 / NS(sqrt)( sqrt_beta * sqrt_beta *
+            ( ( SIXTRL_REAL_T )1 - q ) );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_q_gauss_max_support)(
+    SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( q < ( SIXTRL_REAL_T )3 );
+    SIXTRL_ASSERT( sqrt_beta > ( SIXTRL_REAL_T )0 );
+    return ( q >= ( SIXTRL_REAL_T )1 )
+        ? ( SIXTRL_REAL_T )1e10
+        : ( SIXTRL_REAL_T )1 / NS(sqrt)( sqrt_beta * sqrt_beta *
+            ( ( SIXTRL_REAL_T )1 - q ) );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_q_gauss_exp_q)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_STATIC_VAR SIXTRL_REAL_T const ONE = ( SIXTRL_REAL_T )1;
+    SIXTRL_REAL_T const one_minus_q = ONE - q;
+    SIXTRL_REAL_T const abs_one_minus_q = ( one_minus_q >= ( SIXTRL_REAL_T )0 )
+					? one_minus_q : -one_minus_q;
+
+    SIXTRL_ASSERT( q < ( SIXTRL_REAL_T )3 );
+
+    if( abs_one_minus_q >= ( SIXTRL_REAL_T )SIXTRL_MATH_QGAUSSIAN_Q_EPS )
+    {
+        SIXTRL_REAL_T u_plus = ONE + one_minus_q * x;
+        if( u_plus < ( SIXTRL_REAL_T )0 ) u_plus = ( SIXTRL_REAL_T )0;
+        return NS(pow_positive_base)( u_plus,  ONE / one_minus_q );
+    }
+    else
+    {
+        return NS(exp)( x );
+    }
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_q_gauss_cq)(
+    SIXTRL_REAL_T const q ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T cq = NS(MathConst_sqrt_pi)();
+    SIXTRL_STATIC_VAR SIXTRL_REAL_T const ONE = ( SIXTRL_REAL_T )1;
+
+    SIXTRL_ASSERT( q < ( SIXTRL_REAL_T )3 );
+    if( q >= ( ONE + ( SIXTRL_REAL_T )SIXTRL_MATH_QGAUSSIAN_Q_EPS ) )
+    {
+        SIXTRL_REAL_T const q_minus_1 = q - ONE;
+        cq *= NS(gamma)( ( ( SIXTRL_REAL_T )3 - q ) /
+                         ( ( SIXTRL_REAL_T )2 * q_minus_1 ) );
+        cq /= NS(sqrt)( q_minus_1 ) * NS(gamma)( ONE / q_minus_1 );
+    }
+    else if( q <= ( ONE - ( SIXTRL_REAL_T )SIXTRL_MATH_QGAUSSIAN_Q_EPS ) )
+    {
+        SIXTRL_REAL_T const one_minus_q = ONE - q;
+        SIXTRL_REAL_T const three_minus_q = ( SIXTRL_REAL_T )3 - q;
+        cq *= ( SIXTRL_REAL_T )2 * NS(gamma)( ONE / one_minus_q );
+        cq /= three_minus_q * NS(sqrt)( one_minus_q ) *
+              NS(gamma)( three_minus_q / ( ( SIXTRL_REAL_T )2 * one_minus_q ) );
+    }
+
+    return cq;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_q_gauss_sqrt_beta_from_gauss_sigma)(
+    SIXTRL_REAL_T const sigma ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( sigma > ( SIXTRL_REAL_T )0 );
+    return ( SIXTRL_REAL_T )1 / ( NS(sqrt)( ( SIXTRL_REAL_T )2 ) * sigma );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_q_gauss)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta,
+    SIXTRL_REAL_T const cq ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_ASSERT( q  < ( SIXTRL_REAL_T )3 );
+    SIXTRL_ASSERT( cq > ( SIXTRL_REAL_T )0 );
+    SIXTRL_ASSERT( sqrt_beta > ( SIXTRL_REAL_T )0 );
+
+    return ( sqrt_beta / cq ) * NS(Math_q_gauss_exp_q)(
+        -( sqrt_beta * sqrt_beta * x * x ), q );
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(Math_q_gauss_shifted)(
+    SIXTRL_REAL_T const x, SIXTRL_REAL_T const q, SIXTRL_REAL_T const sqrt_beta,
+    SIXTRL_REAL_T const cq, SIXTRL_REAL_T const mu ) SIXTRL_NOEXCEPT
+{
+    return NS(Math_q_gauss)( x - mu, q, sqrt_beta, cq );
+}
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_QGAUSS_H__ */
diff --git a/sixtracklib/common/internal/objects_type_id.h b/sixtracklib/common/internal/objects_type_id.h
index c1169de5..51b9032d 100644
--- a/sixtracklib/common/internal/objects_type_id.h
+++ b/sixtracklib/common/internal/objects_type_id.h
@@ -5,36 +5,52 @@
     #include "sixtracklib/common/definitions.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
+#if !defined( SIXTRL_OBJECT_TYPE_UNDEFINED )
+    #define SIXTRL_OBJECT_TYPE_UNDEFINED 0
+#endif /* !defined( SIXTRL_OBJECT_TYPE_UNDEFINED ) */
+
 #if defined( __cplusplus )
 extern "C" {
 #endif /* defined( __cplusplus ) */
 
 typedef enum NS(object_type_values_e)
 {
-    NS(OBJECT_TYPE_NONE)                  =          0,
-    NS(OBJECT_TYPE_PARTICLE)              =          1,
-    NS(OBJECT_TYPE_DRIFT)                 =          2,
-    NS(OBJECT_TYPE_DRIFT_EXACT)           =          3,
-    NS(OBJECT_TYPE_MULTIPOLE)             =          4,
-    NS(OBJECT_TYPE_RF_MULTIPOLE)          =        256,
-    NS(OBJECT_TYPE_CAVITY)                =          5,
-    NS(OBJECT_TYPE_XYSHIFT)               =          6,
-    NS(OBJECT_TYPE_SROTATION)             =          7,
-    NS(OBJECT_TYPE_BEAM_BEAM_4D)          =          8,
-    NS(OBJECT_TYPE_BEAM_BEAM_6D)          =          9,
-    NS(OBJECT_TYPE_BEAM_MONITOR)          =         10,
-    NS(OBJECT_TYPE_LIMIT_RECT)            =         11,
-    NS(OBJECT_TYPE_LIMIT_ELLIPSE)         =         12,
-    NS(OBJECT_TYPE_LIMIT_RECT_ELLIPSE)    =         16,
-    NS(OBJECT_TYPE_SPACE_CHARGE_COASTING) =         13,
-    NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED)  =         14,
-    NS(OBJECT_TYPE_DIPEDGE)               =         24,
-    NS(OBJECT_TYPE_PARTICLES_ADDR)        =        512,
-    NS(OBJECT_TYPE_LINE)                  =       1024,
-    NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF)     =      65534,
-    NS(OBJECT_TYPE_NODE_ID)               =      65535,
-    NS(OBJECT_TYPE_LAST_AVAILABLE)        =      65535,
-    NS(OBJECT_TYPE_INVALID)               = 0x7fffffff
+    NS(OBJECT_TYPE_NONE)                      =          0,
+    NS(OBJECT_TYPE_UNDEFINED)                 =          0,
+    NS(OBJECT_TYPE_PARTICLE)                  =          1,
+    NS(OBJECT_TYPE_DRIFT)                     =          2,
+    NS(OBJECT_TYPE_DRIFT_EXACT)               =          3,
+    NS(OBJECT_TYPE_MULTIPOLE)                 =          4,
+    NS(OBJECT_TYPE_RF_MULTIPOLE)              =        256,
+    NS(OBJECT_TYPE_CAVITY)                    =          5,
+    NS(OBJECT_TYPE_XYSHIFT)                   =          6,
+    NS(OBJECT_TYPE_SROTATION)                 =          7,
+    NS(OBJECT_TYPE_LIN_DECOUPLED_ROTATION)    =        259,
+    NS(OBJECT_TYPE_BEAM_BEAM_4D)              =          8,
+    NS(OBJECT_TYPE_BEAM_BEAM_6D)              =          9,
+    NS(OBJECT_TYPE_BEAM_MONITOR)              =         10,
+    NS(OBJECT_TYPE_LIMIT_RECT)                =         11,
+    NS(OBJECT_TYPE_LIMIT_ELLIPSE)             =         12,
+    NS(OBJECT_TYPE_LIMIT_RECT_ELLIPSE)        =         16,
+    NS(OBJECT_TYPE_SC_COASTING)               =         13,
+    NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF)         =         14,
+    NS(OBJECT_TYPE_SC_INTERPOLATED_PROF)      =        257,
+    NS(OBJECT_TYPE_LINE_DENSITY_PROF_DATA)    =        258,
+    NS(OBJECT_TYPE_TRICUB_DATA)               =        260,
+    NS(OBJECT_TYPE_TRICUB)                    =        261,
+    NS(OBJECT_TYPE_DIPEDGE)                   =         24,
+    NS(OBJECT_TYPE_PARTICLES_ADDR)            =        512,
+    NS(OBJECT_TYPE_LINE)                      =       1024,
+    NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF)         =      65534,
+    NS(OBJECT_TYPE_NODE_ID)                   =      65535,
+    NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM)       =      65536,
+    NS(OBJECT_TYPE_BINARY_PATCH_ITEM)         =      65537,
+    NS(OBJECT_TYPE_CSTRING)                   =      65538,
+    NS(OBJECT_TYPE_BINARY_ARRAY)              =      65539,
+    NS(OBJECT_TYPE_LAST_AVAILABLE)            =      65538,
+    NS(OBJECT_TYPE_MIN_USERDEFINED)           = 0x10000000,
+    NS(OBJECT_TYPE_MAX_USERDEFINED)           = 0x7ffffffe,
+    NS(OBJECT_TYPE_INVALID)                   = 0x7fffffff
 }
 NS(object_type_values_t);
 
@@ -54,6 +70,10 @@ namespace SIXTRL_CXX_NAMESPACE
         OBJECT_TYPE_NONE = static_cast< object_type_id_t >(
             NS(OBJECT_TYPE_NONE) );
 
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_UNDEFINED = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_UNDEFINED) );
+
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
         OBJECT_TYPE_PARTICLE     = static_cast< object_type_id_t >(
             NS(OBJECT_TYPE_PARTICLE) );
@@ -86,14 +106,6 @@ namespace SIXTRL_CXX_NAMESPACE
         OBJECT_TYPE_SROTATION    = static_cast< object_type_id_t >(
             NS(OBJECT_TYPE_SROTATION) );
 
-    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
-        OBJECT_TYPE_BEAM_BEAM_4D = static_cast< object_type_id_t >(
-            NS(OBJECT_TYPE_BEAM_BEAM_4D) );
-
-    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
-        OBJECT_TYPE_BEAM_BEAM_6D = static_cast< object_type_id_t >(
-            NS(OBJECT_TYPE_BEAM_BEAM_6D) );
-
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
         OBJECT_TYPE_BEAM_MONITOR = static_cast< object_type_id_t >(
             NS(OBJECT_TYPE_BEAM_MONITOR) );
@@ -106,10 +118,38 @@ namespace SIXTRL_CXX_NAMESPACE
         OBJECT_TYPE_LIMIT_ELLIPSE = static_cast< object_type_id_t >(
             NS(OBJECT_TYPE_LIMIT_ELLIPSE) );
 
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_LIMIT_RECT_ELLIPSE = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_LIMIT_RECT_ELLIPSE) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_SC_COASTING = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_SC_COASTING) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_SC_QGAUSSIAN_PROF = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_SC_INTERPOLATED_PROF = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_SC_INTERPOLATED_PROF) );
+
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
         OBJECT_TYPE_DIPEDGE = static_cast< object_type_id_t >(
             NS(OBJECT_TYPE_DIPEDGE) );
 
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_PARTICLES_ADDR = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_PARTICLES_ADDR) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_ASSIGN_ADDRESS_ITEM = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_BINARY_PATCH_ITEM = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_BINARY_PATCH_ITEM) );
+
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
         OBJECT_TYPE_LINE         = static_cast< object_type_id_t >(
             NS(OBJECT_TYPE_LINE) );
@@ -123,8 +163,32 @@ namespace SIXTRL_CXX_NAMESPACE
             NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF) );
 
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
-        OBJECT_TYPE_PARTICLES_ADDR = static_cast< object_type_id_t >(
-            NS(OBJECT_TYPE_PARTICLES_ADDR) );
+        OBJECT_TYPE_MIN_USERDEFINED = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_MIN_USERDEFINED) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_TRICUB = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_TRICUB) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_CSTRING = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_CSTRING) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_BINARY_ARRAY = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_BINARY_ARRAY) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_TRICUB_DATA = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_TRICUB_DATA) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_MAX_USERDEFINED = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_MAX_USERDEFINED) );
+
+    SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
+        OBJECT_TYPE_LAST_AVAILABLE = static_cast< object_type_id_t >(
+            NS(OBJECT_TYPE_LAST_AVAILABLE) );
 
     SIXTRL_STATIC_VAR SIXTRL_CONSTEXPR_OR_CONST object_type_id_t
         OBJECT_TYPE_INVALID = static_cast< object_type_id_t >(
diff --git a/sixtracklib/common/internal/physics_constants.h b/sixtracklib/common/internal/physics_constants.h
new file mode 100644
index 00000000..3d76c208
--- /dev/null
+++ b/sixtracklib/common/internal/physics_constants.h
@@ -0,0 +1,404 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_PHYSICS_CONSTANTS_H__
+#define SIXTRACKLIB_COMMON_INTERNAL_PHYSICS_CONSTANTS_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #if defined( __cplusplus )
+        #include <cstddef>
+        #include <cstdint>
+        #include <cstdlib>
+        #include <cmath>
+        #include <type_traits>
+    #else /* defined( __cplusplus ) */
+        #include <stddef.h>
+        #include <stdint.h>
+        #include <stdlib.h>
+        #include <math.h>
+    #endif /* defined( __cplusplus ) */
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/particles/definitions.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #include "sixtracklib/common/internal/type_store_traits.hpp"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_PHYS_CONST_CLIGHT )
+    #define SIXTRL_PHYS_CONST_CLIGHT 299792458.0
+#endif /* SIXTRL_PHYS_CONST_CLIGHT */
+
+#if !defined( SIXTRL_PHYS_CONST_EPSILON0 )
+    #define SIXTRL_PHYS_CONST_EPSILON0 8.854187817620e-12
+#endif /* SIXTRL_PHYS_CONST_EPSILON0 */
+
+#if !defined( SIXTRL_PHYS_CONST_MU0 )
+    #define SIXTRL_PHYS_CONST_MU0 \
+        1.25663706143591729538505735331180115367886775975004232839e-6
+#endif /* SIXTRL_PHYS_CONST_MU0 */
+
+#if !defined( SIXTRL_PHYS_CONST_MASS_ATOMIC_SI )
+    #define SIXTRL_PHYS_CONST_MASS_ATOMIC_SI 1.66053906660e-27
+#endif /* SIXTRL_PHYS_CONST_MASS_ATOMIC_SI */
+
+#if !defined( SIXTRL_PHYS_CONST_MASS_ATOMIC_EV )
+    #define SIXTRL_PHYS_CONST_MASS_ATOMIC_EV 931494102.42
+#endif /* SIXTRL_PHYS_CONST_MASS_ATOMIC_EV */
+
+#if !defined( SIXTRL_PHYS_CONST_MASS_PROTON_SI )
+    #define SIXTRL_PHYS_CONST_MASS_PROTON_SI 1.67262192369e-27
+#endif /* SIXTRL_PHYS_CONST_MASS_PROTON_SI */
+
+#if !defined( SIXTRL_PHYS_CONST_MASS_PROTON_EV )
+    #define SIXTRL_PHYS_CONST_MASS_PROTON_EV 938272088.16
+#endif /* SIXTRL_PHYS_CONST_MASS_PROTON_EV */
+
+#if !defined( SIXTRL_PHYS_CONST_MASS_ELECTRON_SI )
+    #define SIXTRL_PHYS_CONST_MASS_ELECTRON_SI 9.1093837015e-31
+#endif /* SIXTRL_PHYS_CONST_MASS_ELECTRON_SI */
+
+#if !defined( SIXTRL_PHYS_CONST_MASS_ELECTRON_EV )
+    #define SIXTRL_PHYS_CONST_MASS_ELECTRON_EV 510998.95
+#endif /* SIXTRL_PHYS_CONST_MASS_ELECTRON_EV */
+
+#if !defined( SIXTRL_PHYS_CONST_CHARGE0_SI )
+    #define SIXTRL_PHYS_CONST_CHARGE0_SI 1.602176634e-19
+#endif /* SIXTRL_PHYS_CONST_CHARGE0_SI */
+
+#if !defined( SIXTRL_PHYS_CONST_CHARGE0 )
+    #define SIXTRL_PHYS_CONST_CHARGE0 1
+#endif /* SIXTRL_PHYS_CONST_CHARGE0 */
+
+#if defined( __cplusplus )
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeMethodParamTraits< R >::value_type
+    PhysConst_clight( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_CLIGHT );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_epsilon0( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_EPSILON0 );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_mu0( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_MU0 );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_mass_atomic_si( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_MASS_ATOMIC_SI );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_mass_atomic_ev( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_MASS_ATOMIC_EV );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_mass_proton_si( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_MASS_PROTON_SI );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_mass_proton_ev( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_MASS_PROTON_EV );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_mass_electron_si( typename TypeMethodParamTraits<
+        R >::const_pointer SIXTRL_RESTRICT
+            SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_MASS_ELECTRON_SI );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE  SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_mass_electron_ev( typename TypeMethodParamTraits<
+        R >::const_pointer SIXTRL_RESTRICT
+            SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_MASS_ELECTRON_EV );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_charge0_si( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_CHARGE0_SI );
+    }
+
+    template< class R >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN typename TypeMethodParamTraits<
+        R >::value_type
+    PhysConst_charge0( typename TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT SIXTRL_UNUSED( dummy ) = SIXTRL_NULLPTR )
+    {
+        return static_cast< typename TypeMethodParamTraits< R >::value_type >(
+            SIXTRL_PHYS_CONST_CHARGE0 );
+    }
+}
+
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_clight)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    R >::const_pointer SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_clight< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_epsilon0)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    R >::const_pointer SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_epsilon0< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_mu0)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    R >::const_pointer SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_mu0< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_mass_atomic_si)( typename
+    SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_mass_atomic_si< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_mass_atomic_ev)( typename
+    SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_mass_atomic_ev< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_mass_proton_si)( typename
+    SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_mass_proton_si< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_mass_proton_ev)( typename
+    SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_mass_proton_ev< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_mass_electron_si)( typename
+    SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_mass_electron_si< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_mass_electron_ev)( typename
+    SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::const_pointer
+        SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_mass_electron_ev< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_charge0_si)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    R >::const_pointer SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_charge0_si< R >( dummy );
+}
+
+template< class R >
+SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits< R >::value_type
+NS(PhysConst_charge0)( typename SIXTRL_CXX_NAMESPACE::TypeMethodParamTraits<
+    R >::const_pointer SIXTRL_RESTRICT dummy = SIXTRL_NULLPTR )
+{
+    return SIXTRL_CXX_NAMESPACE::PhysConst_charge0< R >( dummy );
+}
+
+#endif
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_clight)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_epsilon0)(
+    void )  SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_mu0)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_charge0_si)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_charge0)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_mass_atomic_si)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_mass_atomic_ev)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_mass_proton_si)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_mass_proton_ev)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_mass_electron_si)(
+    void ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_REAL_T NS(PhysConst_mass_electron_ev)(
+    void ) SIXTRL_NOEXCEPT;
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!        Inline Methods and Functions Implementations       !!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_clight)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_CLIGHT;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_epsilon0)( void )  SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_EPSILON0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_mu0)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_MU0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_charge0_si)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_CHARGE0_SI;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_charge0)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_CHARGE0;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_mass_atomic_si)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_MASS_ATOMIC_SI;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_mass_atomic_ev)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_MASS_ATOMIC_EV;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_mass_proton_si)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_MASS_PROTON_SI;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_mass_proton_ev)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_MASS_PROTON_EV;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_mass_electron_si)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_MASS_ELECTRON_SI;
+}
+
+SIXTRL_INLINE SIXTRL_REAL_T NS(PhysConst_mass_electron_ev)( void ) SIXTRL_NOEXCEPT
+{
+    return ( SIXTRL_REAL_T )SIXTRL_PHYS_CONST_MASS_ELECTRON_EV;
+}
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_PHYSICS_CONSTANTS_H__ */
diff --git a/sixtracklib/common/internal/stl_buffer_helper.hpp b/sixtracklib/common/internal/stl_buffer_helper.hpp
new file mode 100644
index 00000000..f2e9b6d1
--- /dev/null
+++ b/sixtracklib/common/internal/stl_buffer_helper.hpp
@@ -0,0 +1,953 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_STL_BUFFER_HELPER_CXX_HPP__
+#define SIXTRACKLIB_COMMON_INTERNAL_STL_BUFFER_HELPER_CXX_HPP__
+
+#if defined( __cplusplus   ) && !defined( _GPUCODE ) && \
+   !defined( __CUDA_ARCH__ ) && !defined( __CUDACC__ )
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <algorithm>
+    #include <cstddef>
+    #include <cstdlib>
+    #include <iterator>
+    #include <map>
+    #include <unordered_map>
+    #include <vector>
+    #include <utility>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename Iter, typename T >
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Vector_sorted_has_value(
+        Iter begin, Iter end, T const& SIXTRL_RESTRICT_REF value,
+        bool const check_sorting = false );
+
+    template< typename T, class Allocator >
+    SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_CXX_NAMESPACE::arch_status_t
+    Vector_add_sorted( std::vector< T, Allocator >& SIXTRL_RESTRICT_REF vector,
+        T const& SIXTRL_RESTRICT_REF value_to_insert,
+        T const& SIXTRL_RESTRICT_REF save_value_to_compare_against = T{},
+        bool const keep_ordered = true );
+
+    template< typename T, class Allocator, class IncrementPred >
+    SIXTRL_STATIC SIXTRL_HOST_FN void Vector_add_next_sorted(
+        std::vector< T, Allocator >& SIXTRL_RESTRICT_REF vector,
+        IncrementPred increment_fn );
+
+    template< typename T, class Allocator >
+    SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_CXX_NAMESPACE::arch_status_t
+    Vector_sorted_remove_key(
+        std::vector< T, Allocator >& SIXTRL_RESTRICT_REF vector,
+        T const& SIXTRL_RESTRICT_REF key );
+
+    /* --------------------------------------------------------------------- */
+
+    template< typename Key, typename Value, class Cmp, class Allocator >
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Map_has_key(
+        std::map< Key, Value, Cmp, Allocator > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename Value, class Cmp, class Allocator >
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Map_has_value_for_key(
+        std::map< Key, Value, Cmp, Allocator > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        Value const& SIXTRL_RESTRICT_REF value );
+
+    template< typename Key, typename Value, class Cmp, class Allocator >
+    SIXTRL_STATIC SIXTRL_HOST_FN Value const& Map_get_value_or_default_for_key(
+        std::map< Key, Value, Cmp, Allocator > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        Value const& SIXTRL_RESTRICT_REF default_value = Value{} );
+
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Map_ordered_vec_has_value(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Map_ordered_vec_empty(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_CXX_NAMESPACE::arch_size_t
+    Map_ordered_vec_size( std::map< Key, std::vector< T, VecAlloc >,
+            Cmp, Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_CXX_NAMESPACE::arch_size_t
+    Map_ordered_vec_size( std::map< Key, std::vector< T, VecAlloc >,
+            Cmp, Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_remove_if_ordered_vec_empty( std::map< Key, std::vector< T, VecAlloc >,
+            Cmp, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_CXX_NAMESPACE::arch_status_t Map_remove_value_from_ordered_vec(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc >&
+            SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value,
+        bool const remove_entry_if_ordered_vec_is_empty = false );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_CXX_NAMESPACE::arch_status_t Map_ordered_vec_insert_value(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc >&
+            SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value,
+        T const& SIXTRL_RESTRICT_REF save_value_to_compare_against = T{},
+        bool const keep_ordered = true );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN T const* Map_ordered_vec_begin(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN T const* Map_ordered_vec_end(
+        std::map< Key, std::vector< T, VecAlloc >,
+            Cmp, Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN T* Map_ordered_vec_begin(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc >&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN T* Map_ordered_vec_end(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc >&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN std::size_t Map_ordered_vec_get_value_index(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+                T const& SIXTRL_RESTRICT_REF value );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN T* Map_ordered_vec_get_ptr_value(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc >&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+                T const& SIXTRL_RESTRICT_REF value );
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN T const* Map_ordered_vec_get_ptr_const_value(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+                T const& SIXTRL_RESTRICT_REF value );
+
+    /* --------------------------------------------------------------------- */
+
+    template< typename Key, typename Value, class Hash,
+              class KeyEqual, class Alloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Map_has_key(
+        std::unordered_map< Key, Value, Hash, KeyEqual, Alloc > const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename Value, class Hash,
+              class KeyEqual, class Alloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Map_has_value_for_key(
+        std::unordered_map< Key, Value, Hash, KeyEqual, Alloc >  const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+        Value const& SIXTRL_RESTRICT_REF value );
+
+    template< typename Key, typename Value, class Hash,
+              class KeyEqual, class Alloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN Value const& Map_get_value_or_default_for_key(
+        std::unordered_map< Key, Value, Hash, KeyEqual, Alloc >  const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+        Value const& SIXTRL_RESTRICT_REF default_value = Value{} );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Map_ordered_vec_has_value(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN bool Map_ordered_vec_empty(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_remove_if_ordered_vec_empty(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_remove_value_from_ordered_vec( std::unordered_map< Key, std::vector<
+        T, VecAlloc >, Hash, KeyEqual, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value,
+        bool remove_entry_if_ordered_vec_is_empty = false );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_ordered_vec_insert_value(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value,
+        T const& SIXTRL_RESTRICT_REF save_value_to_compare_against = T{},
+        bool const keep_ordered = true );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN T const* Map_ordered_vec_begin(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN T const* Map_ordered_vec_end(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN T* Map_ordered_vec_begin(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN T* Map_ordered_vec_end(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash,
+            KeyEqual, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN std::size_t Map_ordered_vec_get_value_index(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash,
+            KeyEqual, Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN T* Map_ordered_vec_get_ptr_value(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash,
+            KeyEqual, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value );
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN T const* Map_ordered_vec_get_ptr_const_value(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash,
+            KeyEqual, Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value );
+}
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_STL_BUFFER_HELPER_CXX_HPP__ */
+
+#if defined( __cplusplus   ) && !defined( _GPUCODE ) && \
+   !defined( __CUDA_ARCH__ ) && !defined( __CUDACC__ )
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename Iter, typename T >
+    SIXTRL_INLINE bool Vector_sorted_has_value(
+        Iter begin, Iter end, T const& SIXTRL_RESTRICT_REF value,
+        bool const check_sorting )
+    {
+        bool has_value = false;
+
+        if( ( std::distance( begin, end ) > std::ptrdiff_t{ 0 } ) &&
+            ( ( !check_sorting ) || (  std::is_sorted( begin, end ) ) ) )
+        {
+            has_value = std::binary_search( begin, end, value );
+        }
+
+        return has_value;
+    }
+
+    template< typename T, class Allocator >
+    SIXTRL_INLINE SIXTRL_CXX_NAMESPACE::arch_status_t Vector_add_sorted(
+        std::vector< T, Allocator >& SIXTRL_RESTRICT_REF vector,
+        T const& SIXTRL_RESTRICT_REF value_to_insert,
+        T const& SIXTRL_RESTRICT_REF save_value_to_compare_against,
+        bool const keep_ordered )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using vec_t  = std::vector< T, Allocator >;
+        using value_type = typename vec_t::value_type;
+
+        st::arch_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        SIXTRL_ASSERT( std::is_sorted( vector.begin(), vector.end() ) );
+
+        if( !std::binary_search( vector.begin(), vector.end(),
+                value_to_insert ) )
+        {
+            value_type const prev_back = ( !vector.empty() )
+                ? vector.back() : save_value_to_compare_against;
+
+            vector.push_back( value_to_insert );
+            if( ( keep_ordered ) && ( prev_back > value_to_insert ) )
+            {
+                std::sort( vector.begin(), vector.end() );
+            }
+
+            SIXTRL_ASSERT( ( !keep_ordered ) ||
+                ( std::is_sorted( vector.begin(), vector.end() ) ) );
+
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    template< typename T, class Allocator, class IncrementPred >
+    void Vector_add_next_sorted(
+        std::vector< T, Allocator >& SIXTRL_RESTRICT_REF vector,
+        IncrementPred increment_fn )
+    {
+        if( !vector.empty() )
+        {
+            SIXTRL_ASSERT( std::is_sorted( vector.begin(), vector.end() ) );
+            vector.emplace_back( increment_fn( vector.back() ) );
+        }
+        else
+        {
+            vector.emplace_back( increment_fn( T{} ) );
+        }
+    }
+
+    template< typename T, class Allocator >
+    SIXTRL_CXX_NAMESPACE::arch_status_t Vector_sorted_remove_key(
+        std::vector< T, Allocator >& SIXTRL_RESTRICT_REF vector,
+        T const& SIXTRL_RESTRICT_REF key )
+    {
+        SIXTRL_CXX_NAMESPACE::arch_status_t status =
+            SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( ( !vector.empty() ) &&
+            ( std::is_sorted( vector.begin(), vector.end() ) ) )
+        {
+            auto it = std::lower_bound( vector.begin(), vector.end(),
+                key );
+
+            if( it != vector.end() )
+            {
+                vector.erase( it );
+                status = SIXTRL_CXX_NAMESPACE::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    template< typename Key, typename Value, class Cmp, class Allocator >
+    SIXTRL_INLINE bool Map_has_key(
+        std::map< Key, Value, Cmp, Allocator > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        return ( map.find( key ) != map.end() );
+    }
+
+    template< typename Key, typename Value, class Cmp, class Allocator >
+    SIXTRL_INLINE bool Map_has_value_for_key(
+        std::map< Key, Value, Cmp, Allocator > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        Value const& SIXTRL_RESTRICT_REF value )
+    {
+        auto it = map.find( key );
+        return ( ( it != map.end() ) && ( it->second == value ) );
+    }
+
+    template< typename Key, typename Value, class Cmp, class Allocator >
+    SIXTRL_INLINE Value const& Map_get_value_or_default_for_key(
+        std::map< Key, Value, Cmp, Allocator > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        Value const& SIXTRL_RESTRICT_REF default_value  )
+    {
+        auto it = map.find( key );
+        return ( it != map.end() ) ? it->second : default_value;
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE bool Map_ordered_vec_has_value(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value )
+    {
+        bool has_value = false;
+        auto it = map.find( key );
+        if( it != map.end() )
+        {
+            SIXTRL_ASSERT( std::is_sorted(
+                it->second.begin(), it->second.end() ) );
+
+            has_value = std::binary_search( it->second.begin(),
+                it->second.end(), value );
+        }
+
+        return has_value;
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE  bool Map_ordered_vec_empty(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key )
+    {
+        auto it = map.find( key );
+        return ( ( it != map.end() ) && ( it->second.empty() ) );
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE SIXTRL_CXX_NAMESPACE::arch_size_t Map_ordered_vec_size(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key )
+    {
+        auto it = map.find( key );
+        return ( it != map.end() )
+            ? it->second.size() : SIXTRL_CXX_NAMESPACE::arch_size_t{ 0 };
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_remove_if_ordered_vec_empty( std::map< Key, std::vector< T, VecAlloc >,
+            Cmp, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+
+        st::arch_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        auto it = map.find( key );
+
+        if( it != map.end() )
+        {
+            SIXTRL_ASSERT( std::is_sorted(
+                it->second.begin(), it->seconed.end() ) );
+
+            if( it->second.empty() )
+            {
+                map.erase( it );
+            }
+
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_remove_value_from_ordered_vec( std::map< Key, std::vector< T, VecAlloc >,
+            Cmp, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value,
+        bool remove_entry_if_ordered_vec_is_empty )
+    {
+        namespace  st = SIXTRL_CXX_NAMESPACE;
+        st::arch_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        auto it = map.find( key );
+
+        if( it != map.end() )
+        {
+            SIXTRL_ASSERT( std::is_sorted( it->second.begin(),
+                it->second.end() ) );
+
+            auto val_it = std::lower_bound( it->second.begin(),
+                it->second.end(), value );
+
+            if( val_it != it->second.end() )
+            {
+                it->second.erase( val_it );
+
+                if( ( remove_entry_if_ordered_vec_is_empty ) &&
+                    ( it->second.empty() ) )
+                {
+                    map.erase( it );
+                }
+
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_CXX_NAMESPACE::arch_status_t Map_ordered_vec_insert_value(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc >&
+            SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value,
+        T const& SIXTRL_RESTRICT_REF save_value_to_cmp_against,
+        bool const keep_ordered )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        auto it = map.find( key );
+        return ( it != map.end() )
+            ? st::Vector_add_sorted(
+                it->second, value, save_value_to_cmp_against, keep_ordered )
+            : st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE T const* Map_ordered_vec_begin(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc >
+            const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        T const* ptr = nullptr;
+
+        auto it = map.find( key );
+        if( ( it != map.end() ) && ( !it->second.empty() ) )
+        {
+            ptr = it->second.data();
+        }
+
+        return ptr;
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE T const* Map_ordered_vec_end( std::map< Key, std::vector< T,
+            VecAlloc >, Cmp, Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        T const* ptr = nullptr;
+
+        auto it = map.find( key );
+        if( ( it != map.end() ) && ( !it->second.empty() ) )
+        {
+            ptr = it->second.data();
+            SIXTRL_ASSERT( ptr != nullptr );
+            std::advance( ptr, it->second.size() );
+        }
+
+        return ptr;
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE T* Map_ordered_vec_begin( std::map< Key, std::vector< T,
+            VecAlloc >, Cmp, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        using vec_t = std::vector< T, VecAlloc >;
+        using map_t = std::map< Key, vec_t, Cmp, Alloc >;
+
+        return const_cast< T* >( SIXTRL_CXX_NAMESPACE::Map_ordered_vec_begin(
+            static_cast< map_t const& >( map ), key ) );
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc >
+    SIXTRL_INLINE T* Map_ordered_vec_end( std::map< Key, std::vector< T,
+            VecAlloc >, Cmp, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        using vec_t = std::vector< T, VecAlloc >;
+        using map_t = std::map< Key, vec_t, Cmp, Alloc >;
+
+        return const_cast< T* >( SIXTRL_CXX_NAMESPACE::Map_ordered_vec_end(
+            static_cast< map_t const& >( map ), key ) );
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN std::size_t Map_ordered_vec_get_value_index(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+                T const& SIXTRL_RESTRICT_REF value )
+    {
+        auto it = map.find( key );
+        if( ( it != map.end() ) && ( !it->second.empty() ) )
+        {
+            SIXTRL_ASSERT( std::is_sorted(
+                it->second.begin(), it->second.end() ) );
+
+            auto val_it = std::lower_bound(
+                it->second.begin(), it->second.end(), value );
+
+            if( val_it != it->second.end() )
+            {
+                return static_cast< std::size_t >( std::distance(
+                    it->second.begin(), val_it ) );
+            }
+
+            return it->second.size();
+        }
+
+        return std::numeric_limits< std::size_t >::max();
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN T* Map_ordered_vec_get_ptr_value(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc >&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+                T const& SIXTRL_RESTRICT_REF value )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return const_cast< T* >( st::Map_ordered_vec_get_ptr_const_value(
+            map, key, value ) );
+    }
+
+    template< typename Key, typename T, class Cmp, class Alloc, class VecAlloc>
+    SIXTRL_STATIC SIXTRL_HOST_FN T const* Map_ordered_vec_get_ptr_const_value(
+        std::map< Key, std::vector< T, VecAlloc >, Cmp, Alloc > const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+                T const& SIXTRL_RESTRICT_REF value )
+    {
+        auto it = map.find( key );
+
+        if( ( it != map.end() ) && ( !it->second.empty() ) )
+        {
+            SIXTRL_ASSERT( std::is_sorted(
+                it->second.begin(), it->second.end() ) );
+
+            auto val_it = std::lower_bound(
+                it->second.begin(), it->second.end(), value );
+
+            if( val_it != it->second.end() )
+            {
+                return std::addressof( *val_it );
+            }
+        }
+
+        return nullptr;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    template< typename Key, typename Value, class Hash,
+              class KeyEqual, class Alloc >
+    SIXTRL_INLINE bool Map_has_key(
+        std::unordered_map< Key, Value, Hash, KeyEqual, Alloc > const&
+            SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        return ( map.find( key ) != map.end() );
+    }
+
+    template< typename Key, typename Value, class Hash,
+              class KeyEqual, class Alloc >
+    SIXTRL_INLINE bool Map_has_value_for_key(
+        std::unordered_map< Key, Value, Hash, KeyEqual, Alloc >  const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+        Value const& SIXTRL_RESTRICT_REF value )
+    {
+        auto it = map.find( key );
+        return ( ( it != map.end() ) && ( it->second == value ) );
+    }
+
+    template< typename Key, typename Value, class Hash,
+              class KeyEqual, class Alloc >
+    SIXTRL_INLINE Value const& Map_get_value_or_default_for_key(
+        std::unordered_map< Key, Value, Hash, KeyEqual, Alloc >  const&
+            SIXTRL_RESTRICT_REF map, Key const& SIXTRL_RESTRICT_REF key,
+        Value const& SIXTRL_RESTRICT_REF default_value )
+    {
+        auto it = map.find( key );
+        return ( it != map.end() ) ? it->second : default_value;
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE bool Map_ordered_vec_has_value(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value )
+    {
+        bool has_value = false;
+
+        auto it = map.find( key );
+
+        if( it != map.end() )
+        {
+            SIXTRL_ASSERT( std::is_sorted(
+                it->second.begin(), it->second.end() ) );
+
+            has_value = std::binary_search( it->second.begin(),
+                it->second.end(), value );
+        }
+
+        return has_value;
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_remove_if_ordered_vec_empty( std::unordered_map< Key, std::vector< T,
+            VecAlloc >, Hash, KeyEqual, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+
+        st::arch_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        auto it = map.find( key );
+
+        if( it != map.end() )
+        {
+            SIXTRL_ASSERT( std::is_sorted(
+                it->second.begin(), it->second.end() ) );
+
+            if( it->second.empty() )
+            {
+                map.erase( key );
+            }
+
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE bool Map_ordered_vec_empty(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        auto it = map.find( key );
+        return( ( it != map.end() ) && ( it->second.empty() ) );
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE SIXTRL_CXX_NAMESPACE::arch_size_t Map_ordered_vec_size(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        auto it = map.find( key );
+        return ( it != map.end() )
+            ? it->second.size() : SIXTRL_CXX_NAMESPACE::arch_size_t{ 0 };
+    }
+
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_remove_value_from_ordered_vec( std::unordered_map< Key, std::vector< T,
+            VecAlloc >, Hash, KeyEqual, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value,
+        bool remove_entry_if_ordered_vec_is_empty  )
+    {
+        namespace  st = SIXTRL_CXX_NAMESPACE;
+        st::arch_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        auto it = map.find( key );
+
+        if( it != map.end() )
+        {
+            SIXTRL_ASSERT( std::is_sorted( it->second.begin(),
+                it->second.end() ) );
+
+            auto val_it = std::lower_bound( it->second.begin(),
+                it->second.end(), value );
+
+            if( val_it != it->second.end() )
+            {
+                it->second.erase( val_it );
+
+                if( ( remove_entry_if_ordered_vec_is_empty ) &&
+                    ( it->second.empty() ) )
+                {
+                    map.erase( it );
+                }
+
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE SIXTRL_CXX_NAMESPACE::arch_status_t
+    Map_ordered_vec_insert_value(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key,
+        T const& SIXTRL_RESTRICT_REF value,
+        T const& SIXTRL_RESTRICT_REF save_value_to_cmp_against,
+        bool const keep_ordered )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using vec_t = std::vector< T, VecAlloc >;
+        using map_t = std::unordered_map< Key, vec_t, Hash, KeyEqual, Alloc >;
+
+        typename map_t::iterator it = map.find( key );
+        return ( it != map.end() )
+            ? st::Vector_add_sorted(
+                it->second, value, save_value_to_cmp_against, keep_ordered )
+            : st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE T const* Map_ordered_vec_begin(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        T const* ptr = nullptr;
+
+        auto it = map.find( key );
+        if( ( it != map.end() ) && ( !it->second.empty() ) )
+        {
+            ptr = it->second.data();
+        }
+
+        return ptr;
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE T const* Map_ordered_vec_end(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc > const& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        T const* ptr = nullptr;
+
+        auto it = map.find( key );
+        if( ( it != map.end() ) && ( !it->second.empty() ) )
+        {
+            ptr = it->second.data();
+            SIXTRL_ASSERT( ptr != nullptr );
+            std::advance( ptr, it->second.size() );
+        }
+
+        return ptr;
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE T* Map_ordered_vec_begin( std::unordered_map< Key, std::vector<
+        T, VecAlloc >, Hash, KeyEqual, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        using vec_t = std::vector< T, VecAlloc >;
+        using map_t = std::unordered_map< Key, vec_t, Hash, KeyEqual, Alloc >;
+
+        return const_cast< T* >( SIXTRL_CXX_NAMESPACE::Map_ordered_vec_begin(
+            static_cast< map_t const& >( map ), key ) );
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_INLINE T* Map_ordered_vec_end( std::unordered_map< Key, std::vector<
+        T, VecAlloc >, Hash, KeyEqual, Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key )
+    {
+        using vec_t = std::vector< T, VecAlloc >;
+        using map_t = std::unordered_map< Key, vec_t, Hash, KeyEqual, Alloc >;
+
+        return const_cast< T* >( SIXTRL_CXX_NAMESPACE::Map_ordered_vec_end(
+            static_cast< map_t const& >( map ), key ) );
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN std::size_t Map_ordered_vec_get_value_index(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key, T const& SIXTRL_RESTRICT_REF value )
+    {
+        auto it = map.find( key );
+        if( ( it != map.end() ) && ( !it->second.empty() ) )
+        {
+            SIXTRL_ASSERT( std::is_sorted(
+                it->second.begin(), it->second.end() ) );
+
+            auto val_it = std::lower_bound(
+                it->second.begin(), it->second.end(), value );
+
+            if( val_it != it->second.end() )
+            {
+                return static_cast< std::size_t >( std::distance(
+                    it->second.begin(), val_it ) );
+            }
+
+            return it->second.size();
+        }
+
+        return std::numeric_limits< std::size_t >::max();
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN T* Map_ordered_vec_get_ptr_value(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key, T const& SIXTRL_RESTRICT_REF value )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return const_cast< T* >( st::Map_ordered_vec_get_ptr_const_value(
+            map, key, value ) );
+    }
+
+    template< typename Key, typename T, class Hash,
+              class KeyEqual, class Alloc, class VecAlloc >
+    SIXTRL_STATIC SIXTRL_HOST_FN T const* Map_ordered_vec_get_ptr_const_value(
+        std::unordered_map< Key, std::vector< T, VecAlloc >, Hash, KeyEqual,
+            Alloc >& SIXTRL_RESTRICT_REF map,
+        Key const& SIXTRL_RESTRICT_REF key, T const& SIXTRL_RESTRICT_REF value )
+    {
+        auto it = map.find( key );
+        if( ( it != map.end() ) && ( !it->second.empty() ) )
+        {
+            SIXTRL_ASSERT( std::is_sorted(
+                it->second.begin(), it->second.end() ) );
+
+            auto val_it = std::lower_bound(
+                it->second.begin(), it->second.end(), value );
+
+            if( val_it != it->second.end() )
+            {
+                return std::addressof( *val_it );
+            }
+        }
+
+        return nullptr;
+    }
+}
+
+#endif /* c++, Host */
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_STL_BUFFER_HELPER_CXX_HPP__ */
+
+/* end: sixtracklib/common/internal/stl_buffer_helper.hpp */
diff --git a/sixtracklib/common/internal/track_job.cpp b/sixtracklib/common/internal/track_job.cpp
index 0f5557e9..84c89414 100644
--- a/sixtracklib/common/internal/track_job.cpp
+++ b/sixtracklib/common/internal/track_job.cpp
@@ -26,7 +26,7 @@
     #include "sixtracklib/common/track_job_cpu.h"
 
     #if defined( SIXTRACKLIB_ENABLE_MODULE_OPENCL ) && \
-        ( SIXTRACKLIB_ENABLE_MODULE_OPENCL == 1 )
+               ( SIXTRACKLIB_ENABLE_MODULE_OPENCL == 1 )
 
     #include "sixtracklib/opencl/make_track_job.h"
 
@@ -37,9 +37,13 @@
 #if !defined( _GPUCODE )
 #if defined( __cplusplus )
 
-namespace st = SIXTRL_CXX_NAMESPACE;
 namespace SIXTRL_CXX_NAMESPACE
 {
+    namespace
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+    }
+
     TrackJobBase* TrackJob_create( const char *const SIXTRL_RESTRICT arch_str,
         const char *const SIXTRL_RESTRICT config_str )
     {
@@ -469,6 +473,14 @@ void NS(TrackJob_collect_output)( ::NS(TrackJobBase)* SIXTRL_RESTRICT job )
     if( job != nullptr ) job->collectOutput();
 }
 
+void NS(TrackJob_collect_particles_addresses)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job )
+{
+    if( job != nullptr ) job->collectParticlesAddresses();
+}
+
+/* ------------------------------------------------------------------------- */
+
 void NS(TrackJob_enable_collect_particles)(
     ::NS(TrackJobBase)* SIXTRL_RESTRICT job )
 {
@@ -543,6 +555,7 @@ bool NS(TrackJob_requires_collecting)(
     return ( job != nullptr ) ? job->requiresCollecting() : false;
 }
 
+/* ------------------------------------------------------------------------- */
 
 void NS(TrackJob_push)( ::NS(TrackJobBase)* SIXTRL_RESTRICT track_job,
     ::NS(track_job_push_flag_t) const flags )
@@ -553,33 +566,570 @@ void NS(TrackJob_push)( ::NS(TrackJobBase)* SIXTRL_RESTRICT track_job,
 void NS(TrackJob_push_particles)(
     ::NS(TrackJobBase)* SIXTRL_RESTRICT track_job )
 {
-    if( track_job != nullptr ) track_job->push( st::TRACK_JOB_IO_PARTICLES );
+    if( track_job != nullptr ) track_job->push(
+            SIXTRL_CXX_NAMESPACE::TRACK_JOB_IO_PARTICLES );
 }
 
 void NS(TrackJob_push_beam_elements)(
     ::NS(TrackJobBase)* SIXTRL_RESTRICT track_job )
 {
-    if( track_job != nullptr ) track_job->push( st::TRACK_JOB_IO_BEAM_ELEMENTS );
+    if( track_job != nullptr ) track_job->push(
+        SIXTRL_CXX_NAMESPACE::TRACK_JOB_IO_BEAM_ELEMENTS );
 }
 
 void NS(TrackJob_push_output)(
     ::NS(TrackJobBase)* SIXTRL_RESTRICT track_job )
 {
-    if( track_job != nullptr ) track_job->push( st::TRACK_JOB_IO_OUTPUT );
+    if( track_job != nullptr ) track_job->push(
+            SIXTRL_CXX_NAMESPACE::TRACK_JOB_IO_OUTPUT );
 }
 
-bool NS(TrackJob_can_fetch_particle_addresses)(
-    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT track_job )
+void NS(TrackJob_push_particles_addresses)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job )
 {
-    ( void )track_job; /* not supported by track jobs based on this API */
-    return false;
+    if( job != nullptr ) job->push(
+        SIXTRL_CXX_NAMESPACE::TRACK_JOB_IO_PARTICLES_ADDR );
 }
 
-bool NS(TrackJob_has_particle_addresses)(
+/* ------------------------------------------------------------------------- */
+
+bool NS(TrackJob_can_fetch_particles_addr)(
     const ::NS(TrackJobBase) *const SIXTRL_RESTRICT track_job )
 {
-    ( void )track_job; /* not supported by track jobs based on this API */
-    return false;
+    return ( ( track_job != nullptr ) &&
+             ( track_job->canFetchParticleAddresses() ) );
+}
+
+bool NS(TrackJob_has_particles_addr)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( ( job != nullptr ) && ( job->has_particles_addr() ) );
+}
+
+::NS(arch_status_t) NS(TrackJob_fetch_particles_addr)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr ) ? job->fetch_particles_addr()
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJob_clear_particles_addr)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const particle_set_index )
+{
+    return ( job != nullptr ) ? job->clear_particles_addr( particle_set_index )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJob_clear_all_particles_addr)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr ) ? job->clear_all_particles_addr()
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(ParticlesAddr) const* NS(TrackJob_particles_addr)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const particle_set_index )
+{
+    return ( job != nullptr )
+        ? job->particles_addr( particle_set_index ) : nullptr;
+}
+
+::NS(Buffer) const* NS(TrackJob_particles_addr_buffer)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr ) ? job->ptr_particles_addr_cbuffer() : nullptr;
+}
+
+/* ------------------------------------------------------------------------- */
+
+::NS(AssignAddressItem)* NS(TrackJob_add_assign_address_item)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT_REF assign_item_to_add )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    st::AssignAddressItem const* ptr_cxx_item = reinterpret_cast<
+        st::AssignAddressItem const* >( assign_item_to_add );
+
+    return ( ( job != nullptr ) && ( ptr_cxx_item != nullptr ) )
+        ? job->add_assign_address_item( *ptr_cxx_item ) : nullptr;
+}
+
+::NS(AssignAddressItem)* NS(TrackJob_add_assign_address_item_detailed)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    ::NS(object_type_id_t) const dest_type_id,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const dest_elem_index,
+    ::NS(buffer_size_t) const dest_pointer_offset,
+    ::NS(object_type_id_t) const src_type_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const src_elem_index,
+    ::NS(buffer_size_t) const src_pointer_offset )
+{
+    return ( job != nullptr )
+        ? job->add_assign_address_item(
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset )
+        : nullptr;
+}
+
+::NS(arch_status_t) NS(TrackJob_remove_assign_address_item)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT_REF item_to_remove )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    st::AssignAddressItem const* ptr_cxx_item = reinterpret_cast<
+        st::AssignAddressItem const* >( item_to_remove );
+
+    return ( ( job != nullptr ) && ( ptr_cxx_item != nullptr ) )
+        ? job->remove_assign_address_item( *ptr_cxx_item )
+        : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+
+::NS(arch_status_t) NS(TrackJob_remove_assign_address_item_by_key_and_index)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    const ::NS(TrackJobDestSrcBufferIds) *const SIXTRL_RESTRICT_REF key,
+    ::NS(buffer_size_t) const index_of_item_to_remove )
+{
+    return ( ( job != nullptr ) && ( key != nullptr ) )
+        ? job->remove_assign_address_item( *key, index_of_item_to_remove )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+bool NS(TrackJob_has_assign_address_item)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    st::AssignAddressItem  const* ptr_cxx_item = reinterpret_cast<
+        st::AssignAddressItem const* >( item );
+
+    return ( ( job != nullptr ) && ( ptr_cxx_item != nullptr ) &&
+             ( job->has_assign_address_item( *ptr_cxx_item ) ) );
+}
+
+bool NS(TrackJob_has_assign_item_by_index)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const assign_item_index )
+{
+    return ( ( job != nullptr ) && ( job->num_assign_items(
+                dest_buffer_id, src_buffer_id ) > assign_item_index ) );
+}
+
+bool NS(TrackJob_has_assign_address_item_detailed)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(object_type_id_t) const dest_type_id,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const dest_elem_index,
+    ::NS(buffer_size_t) const dest_pointer_offset,
+    ::NS(object_type_id_t) const src_type_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const src_elem_index,
+    ::NS(buffer_size_t) const src_pointer_offset )
+{
+    return ( ( job != nullptr ) &&
+             ( job->has_assign_address_item(
+                dest_type_id, dest_buffer_id, dest_elem_index,
+                    dest_pointer_offset,
+                src_type_id, src_buffer_id, src_elem_index,
+                    src_pointer_offset ) ) );
+}
+
+::NS(buffer_size_t) NS(TrackJob_index_of_assign_address_item_detailed)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(object_type_id_t) const dest_type_id,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const dest_elem_index,
+    ::NS(buffer_size_t) const dest_pointer_offset,
+    ::NS(object_type_id_t) const src_type_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const src_elem_index,
+    ::NS(buffer_size_t) const src_pointer_offset )
+{
+    return ( job != nullptr )
+        ? job->index_of_assign_address_item(
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset )
+        : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(buffer_size_t) NS(TrackJob_index_of_assign_address_item)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT assign_item )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    st::AssignAddressItem const* ptr_cxx_item = reinterpret_cast<
+        st::AssignAddressItem const* >( assign_item );
+
+    return ( ( job != nullptr ) && ( ptr_cxx_item != nullptr ) )
+        ? job->index_of_assign_address_item( *ptr_cxx_item )
+        : ::NS(buffer_size_t){ 0 };
+}
+
+bool NS(TrackJob_has_assign_items)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id )
+{
+    return ( ( job != nullptr ) &&
+             ( job->has_assign_items( dest_buffer_id, src_buffer_id ) ) );
+}
+
+::NS(buffer_size_t) NS(TrackJob_num_assign_items)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id )
+{
+    return ( job != nullptr )
+        ? job->num_assign_items( dest_buffer_id, src_buffer_id )
+        : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(buffer_size_t) NS(TrackJob_total_num_assign_items)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->total_num_assign_items() : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(AssignAddressItem) const* NS(TrackJob_ptr_assign_address_item)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT item )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    ::NS(AssignAddressItem) const* ptr_item = nullptr;
+
+    if( ( job != nullptr ) && ( item != nullptr ) )
+    {
+        st::AssignAddressItem const* _ptr = job->ptr_assign_address_item(
+            *( reinterpret_cast< st::AssignAddressItem const* >( item ) ) );
+        if( _ptr != nullptr ) ptr_item = _ptr->getCApiPtr();
+    }
+
+    return ptr_item;
+}
+
+::NS(AssignAddressItem) const* NS(TrackJob_ptr_assign_address_item_detailed)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(object_type_id_t) const dest_type_id,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const dest_elem_index,
+    ::NS(buffer_size_t) const dest_pointer_offset,
+    ::NS(object_type_id_t) const src_type_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const src_elem_index,
+    ::NS(buffer_size_t) const src_pointer_offset )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    ::NS(AssignAddressItem) const* ptr_item = nullptr;
+
+    if( job != nullptr )
+    {
+        st::TrackJobBase::size_type const assign_address_item_index =
+            job->index_of_assign_address_item( dest_type_id, dest_buffer_id,
+                dest_elem_index, dest_pointer_offset, src_type_id,
+                    src_buffer_id, src_elem_index, src_pointer_offset );
+
+        ptr_item = job->ptr_assign_address_item(
+            dest_buffer_id, src_buffer_id, assign_address_item_index );
+    }
+
+    return ptr_item;
+}
+
+::NS(AssignAddressItem) const* NS(TrackJob_ptr_assign_address_item_by_index)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const assign_address_item_index )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    ::NS(AssignAddressItem) const* ptr_item = nullptr;
+
+    if( job != nullptr )
+    {
+        st::AssignAddressItem const* _ptr = job->ptr_assign_address_item(
+            dest_buffer_id, src_buffer_id, assign_address_item_index );
+
+        if( _ptr != nullptr ) ptr_item = _ptr->getCApiPtr();
+    }
+
+    return ptr_item;
+}
+
+::NS(buffer_size_t)
+NS(TrackJob_num_distinct_available_assign_address_items_dest_src_pairs)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->num_distinct_available_assign_address_items_dest_src_pairs()
+        : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(buffer_size_t) NS(TrackJob_available_assign_address_items_dest_src_pairs)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const max_num_pairs,
+    ::NS(TrackJobDestSrcBufferIds)* pairs_begin )
+{
+    return ( job != nullptr )
+        ? job->available_assign_address_items_dest_src_pairs(
+            max_num_pairs, pairs_begin )
+        : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(Buffer)* NS(TrackJob_buffer_by_buffer_id)( ::NS(TrackJobBase)*
+    SIXTRL_RESTRICT job, ::NS(buffer_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->buffer_by_buffer_id( buffer_id ) : nullptr;
+
+}
+
+::NS(Buffer) const* NS(TrackJob_const_buffer_by_buffer_id)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->buffer_by_buffer_id( buffer_id ) : nullptr;
+}
+
+bool NS(TrackJob_is_buffer_by_buffer_id)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id )
+{
+    return ( ( job != nullptr ) &&
+             ( job->is_buffer_by_buffer_id)( buffer_id ) );
+}
+
+bool NS(TrackJob_is_raw_memory_by_buffer_id)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id )
+{
+    return ( ( job != nullptr ) &&
+             ( job->is_raw_memory_by_buffer_id( buffer_id ) ) );
+}
+
+SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object) const*
+NS(TrackJob_assign_items_begin)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id )
+{
+    return ( job != nullptr )
+        ? job->assign_items_begin( dest_buffer_id, src_buffer_id ) : nullptr;
+}
+
+SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object) const*
+NS(TrackJob_assign_items_end)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id )
+{
+    return ( job != nullptr )
+        ? job->assign_items_end( dest_buffer_id, src_buffer_id ) : nullptr;
+}
+
+::NS(TrackJobDestSrcBufferIds) const*
+NS(TrackJob_assign_item_dest_src_begin)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->assign_item_dest_src_begin() : nullptr;
+}
+
+::NS(TrackJobDestSrcBufferIds) const*
+NS(TrackJob_assign_item_dest_src_end)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->assign_item_dest_src_end() : nullptr;
+}
+
+::NS(arch_status_t) NS(TrackJob_commit_address_assignments)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->commit_address_assignments()
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJob_assign_all_addresses)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->assign_all_addresses()
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJob_assign_addresses)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id )
+{
+    return ( job != nullptr )
+        ? job->assign_addresses( dest_buffer_id, src_buffer_id )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+/* ------------------------------------------------------------------------- */
+
+::NS(arch_status_t) NS(TrackJob_fetch_particle_addresses)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT track_job )
+{
+    return ( track_job != nullptr )
+        ? track_job->fetchParticleAddresses()
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJob_clear_particle_addresses)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT track_job,
+    ::NS(arch_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return ( track_job != nullptr )
+        ? track_job->clearParticleAddresses( index )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJob_clear_all_particle_addresses)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT track_job ) SIXTRL_NOEXCEPT
+{
+    return ( track_job != nullptr )
+        ? track_job->clearAllParticleAddresses()
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(ParticlesAddr) const* NS(TrackJob_particle_addresses)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const index ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->particleAddresses( index ) : nullptr;
+}
+
+::NS(Buffer)* NS(TrackJob_get_particles_addr_buffer)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->ptrParticleAddressesBuffer() : nullptr;
+}
+
+::NS(Buffer) const* NS(TrackJob_get_const_particles_addr_buffer)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->ptrParticleAddressesBuffer() : nullptr;
+}
+
+/* ------------------------------------------------------------------------- */
+
+::NS(arch_size_t) NS(TrackJob_stored_buffers_capacity)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job ) {
+    return ( job != nullptr )
+        ? job->stored_buffers_capacity() : ::NS(arch_size_t){ 0 };
+}
+
+::NS(arch_status_t) NS(TrackJob_reserve_stored_buffers_capacity)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job, ::NS(arch_size_t) const capacity )
+{
+    return ( job != nullptr )
+        ? job->reserve_stored_buffers_capacity( capacity )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+bool NS(TrackJob_has_stored_buffers)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( ( job != nullptr ) && ( job->has_stored_buffers() ) );
+}
+
+::NS(arch_size_t) NS(TrackJob_num_stored_buffers)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->num_stored_buffers() : ::NS(arch_size_t){ 0 };
+}
+
+::NS(arch_size_t) NS(TrackJob_min_stored_buffer_id)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->min_stored_buffer_id()
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_BUFFER_ID;
+}
+
+::NS(arch_size_t) NS(TrackJob_max_stored_buffer_id)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->max_stored_buffer_id()
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_BUFFER_ID;
+}
+
+::NS(arch_size_t) NS(TrackJob_create_stored_buffer)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_capacity )
+{
+    return ( job != nullptr )
+        ? job->add_stored_buffer( buffer_capacity )
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_BUFFER_ID;
+}
+
+::NS(arch_size_t) NS(TrackJob_add_stored_buffer)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    ::NS(Buffer)* SIXTRL_RESTRICT buffer, bool const take_ownership,
+    bool const delete_ptr_after_move )
+{
+    return ( job != nullptr )
+        ? job->add_stored_buffer(
+                buffer, take_ownership, delete_ptr_after_move )
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_BUFFER_ID;
+}
+
+bool NS(TrackJob_owns_stored_buffer)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_id )
+{
+    return ( ( job != nullptr ) &&
+             ( job->owns_stored_buffer( buffer_id ) ) );
+}
+
+::NS(arch_status_t) NS(TrackJob_remove_stored_buffer)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_index )
+{
+    return ( job != nullptr )
+        ? job->remove_stored_buffer( buffer_index )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(Buffer)* NS(TrackJob_stored_buffer)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job, ::NS(arch_size_t) const buffer_id )
+{
+    return ( job != nullptr ) ? job->ptr_stored_buffer( buffer_id ) : nullptr;
+}
+
+::NS(Buffer) const* NS(TrackJob_const_stored_buffer)(
+    const ::NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_id )
+{
+    return ( job != nullptr ) ? job->ptr_stored_buffer( buffer_id ) : nullptr;
+}
+
+::NS(arch_status_t) NS(TrackJob_push_stored_buffer)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job, ::NS(arch_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->push_stored_buffer( buffer_id )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJob_collect_stored_buffer)(
+    ::NS(TrackJobBase)* SIXTRL_RESTRICT job, ::NS(arch_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->collect_stored_buffer( buffer_id )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -977,5 +1527,3 @@ void NS(TrackJob_set_default_elem_by_elem_config_order)(
 
 #endif /* defined( __cplusplus ) */
 #endif /* !defined( _GPUCODE ) */
-
-/* end: sixtracklib/common/internal/track_job.cpp */
diff --git a/sixtracklib/common/internal/track_job_base.cpp b/sixtracklib/common/internal/track_job_base.cpp
index d3ffb4e7..ed538aab 100644
--- a/sixtracklib/common/internal/track_job_base.cpp
+++ b/sixtracklib/common/internal/track_job_base.cpp
@@ -6,7 +6,9 @@
         #include <cstddef>
         #include <cstdint>
         #include <cstdlib>
+        #include <iostream>
         #include <memory>
+        #include <numeric>
         #include <string>
         #include <vector>
     #else /* !defined( __cplusplus ) */
@@ -28,252 +30,357 @@
 
     #include "sixtracklib/common/buffer.h"
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+    #include "sixtracklib/common/buffer/assign_address_item_kernel_impl.h"
     #include "sixtracklib/common/particles.h"
     #include "sixtracklib/common/beam_elements.h"
     #include "sixtracklib/common/be_monitor/be_monitor.h"
     #include "sixtracklib/common/be_monitor/output_buffer.h"
     #include "sixtracklib/common/output/elem_by_elem_config.h"
     #include "sixtracklib/common/output/output_buffer.h"
+    #include "sixtracklib/common/particles/particles_addr.h"
+    #include "sixtracklib/common/internal/stl_buffer_helper.hpp"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if defined( __cplusplus )
-
-namespace st = SIXTRL_CXX_NAMESPACE;
 namespace SIXTRL_CXX_NAMESPACE
 {
     namespace
     {
-        using _this_t   = st::TrackJobBase;
-        using _size_t   = _this_t::size_type;
-        using _status_t = _this_t::status_t;
+        namespace st            = SIXTRL_CXX_NAMESPACE;
+        using tjob_t            = st::TrackJobBase;
+        using st_size_t         = st_size_t;
+        using st_status_t       = tjob_t::status_t;
+        using st_track_status_t = tjob_t::track_status_t;
+        using paddr_t           = tjob_t::particles_addr_t;
+    }
+
+    constexpr st_size_t tjob_t::ILLEGAL_BUFFER_ID;
+
+    void tjob_t::COPY_PTR_BUFFER(
+        tjob_t::ptr_buffer_t& SIXTRL_RESTRICT_REF dest_ptr_buffer,
+        tjob_t::ptr_buffer_t const& SIXTRL_RESTRICT_REF src_ptr_buffer )
+    {
+        if( src_ptr_buffer.get() != nullptr )
+        {
+            dest_ptr_buffer.reset(
+                new tjob_t::buffer_t( *src_ptr_buffer.get() ) );
+        }
+        else
+        {
+            dest_ptr_buffer.reset( nullptr );
+        }
     }
 
-    _size_t TrackJobBase::DefaultNumParticleSetIndices() SIXTRL_NOEXCEPT
+    /* --------------------------------------------------------------------- */
+
+    st_size_t tjob_t::DefaultNumParticleSetIndices() SIXTRL_NOEXCEPT
     {
         return st::TRACK_JOB_DEFAULT_NUM_PARTICLE_SETS;
     }
 
-    _size_t const*
-    TrackJobBase::DefaultParticleSetIndicesBegin() SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::DefaultParticleSetIndicesBegin() SIXTRL_NOEXCEPT
     {
-        _size_t const* ptr = &st::TRACK_JOB_DEFAULT_PARTICLE_SET_INDICES[ 0 ];
+        st_size_t const* ptr = &st::TRACK_JOB_DEFAULT_PARTICLE_SET_INDICES[ 0 ];
         return ptr;
     }
 
-    _size_t const* TrackJobBase::DefaultParticleSetIndicesEnd() SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::DefaultParticleSetIndicesEnd() SIXTRL_NOEXCEPT
     {
-        _size_t const* end_ptr = TrackJobBase::DefaultParticleSetIndicesBegin();
+        st_size_t const* end_ptr = tjob_t::DefaultParticleSetIndicesBegin();
         std::advance( end_ptr, st::TRACK_JOB_DEFAULT_NUM_PARTICLE_SETS );
         return end_ptr;
     }
 
-    void TrackJobBase::clear()
+    void tjob_t::clear()
     {
         this->doClear();
     }
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBase::collect()
+    void tjob_t::collect()
     {
         this->doCollect( this->m_collect_flags );
     }
 
-    void TrackJobBase::collect( _this_t::collect_flag_t const flags )
+    void tjob_t::collect( tjob_t::collect_flag_t const flags )
     {
         this->doCollect( flags & st::TRACK_JOB_COLLECT_ALL );
     }
 
-    void TrackJobBase::collectParticles()
+    void tjob_t::collectParticles()
     {
         this->doCollect( st::TRACK_JOB_IO_PARTICLES );
     }
 
-
-    void TrackJobBase::collectBeamElements()
+    void tjob_t::collectBeamElements()
     {
         this->doCollect( st::TRACK_JOB_IO_BEAM_ELEMENTS );
     }
 
-    void TrackJobBase::collectOutput()
+    void tjob_t::collectOutput()
     {
         this->doCollect( st::TRACK_JOB_IO_OUTPUT );
     }
 
-    void TrackJobBase::enableCollectParticles()  SIXTRL_NOEXCEPT
+    st_status_t tjob_t::collectParticlesAddresses()
+    {
+        this->doCollect( st::TRACK_JOB_IO_PARTICLES_ADDR );
+        return st::ARCH_STATUS_SUCCESS;
+    }
+
+    void tjob_t::enableCollectParticles()  SIXTRL_NOEXCEPT
     {
         this->m_collect_flags |= st::TRACK_JOB_IO_PARTICLES;
     }
 
-    void TrackJobBase::disableCollectParticles() SIXTRL_NOEXCEPT
+    void tjob_t::disableCollectParticles() SIXTRL_NOEXCEPT
     {
-        this->m_collect_flags = TrackJobBase::UnsetCollectFlag(
+        this->m_collect_flags = tjob_t::UnsetCollectFlag(
             this->m_collect_flags, st::TRACK_JOB_IO_PARTICLES );
     }
 
-    bool TrackJobBase::isCollectingParticles() const SIXTRL_NOEXCEPT
+    bool tjob_t::isCollectingParticles() const SIXTRL_NOEXCEPT
     {
-        return TrackJobBase::IsCollectFlagSet( this->m_collect_flags,
+        return tjob_t::IsCollectFlagSet( this->m_collect_flags,
             st::TRACK_JOB_IO_PARTICLES );
     }
 
-    void TrackJobBase::enableCollectBeamElements()  SIXTRL_NOEXCEPT
+    void tjob_t::enableCollectBeamElements()  SIXTRL_NOEXCEPT
     {
         this->m_collect_flags |= st::TRACK_JOB_IO_BEAM_ELEMENTS;
     }
 
-    void TrackJobBase::disableCollectBeamElements() SIXTRL_NOEXCEPT
+    void tjob_t::disableCollectBeamElements() SIXTRL_NOEXCEPT
     {
-        this->m_collect_flags = TrackJobBase::UnsetCollectFlag(
+        this->m_collect_flags = tjob_t::UnsetCollectFlag(
             this->m_collect_flags, st::TRACK_JOB_IO_BEAM_ELEMENTS );
     }
 
-    bool TrackJobBase::isCollectingBeamElements() const SIXTRL_NOEXCEPT
+    bool tjob_t::isCollectingBeamElements() const SIXTRL_NOEXCEPT
     {
-        return TrackJobBase::IsCollectFlagSet( this->m_collect_flags,
+        return tjob_t::IsCollectFlagSet( this->m_collect_flags,
                 st::TRACK_JOB_IO_BEAM_ELEMENTS );
     }
 
-    void TrackJobBase::enableCollectOutput()  SIXTRL_NOEXCEPT
+    void tjob_t::enableCollectOutput()  SIXTRL_NOEXCEPT
     {
         this->m_collect_flags |= st::TRACK_JOB_IO_OUTPUT;
     }
 
-    void TrackJobBase::disableCollectOutput() SIXTRL_NOEXCEPT
+    void tjob_t::disableCollectOutput() SIXTRL_NOEXCEPT
     {
-        this->m_collect_flags = TrackJobBase::UnsetCollectFlag(
+        this->m_collect_flags = tjob_t::UnsetCollectFlag(
             this->m_collect_flags, st::TRACK_JOB_IO_OUTPUT );
     }
 
-    bool TrackJobBase::isCollectingOutput() const SIXTRL_NOEXCEPT
+    bool tjob_t::isCollectingOutput() const SIXTRL_NOEXCEPT
     {
-        return TrackJobBase::IsCollectFlagSet( this->m_collect_flags,
+        return tjob_t::IsCollectFlagSet( this->m_collect_flags,
                 st::TRACK_JOB_IO_OUTPUT );
     }
 
-    _this_t::collect_flag_t TrackJobBase::collectFlags() const SIXTRL_NOEXCEPT
+    tjob_t::collect_flag_t tjob_t::collectFlags() const SIXTRL_NOEXCEPT
     {
         return this->m_collect_flags;
     }
 
-    void TrackJobBase::setCollectFlags(
-        _this_t::collect_flag_t const flags ) SIXTRL_NOEXCEPT
+    void tjob_t::setCollectFlags(
+        tjob_t::collect_flag_t const flags ) SIXTRL_NOEXCEPT
     {
         this->m_collect_flags = ( flags & st::TRACK_JOB_COLLECT_ALL );
     }
 
-    bool TrackJobBase::requiresCollecting() const SIXTRL_NOEXCEPT
+    bool tjob_t::requiresCollecting() const SIXTRL_NOEXCEPT
     {
         return this->m_requires_collect;
     }
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBase::push( _this_t::push_flag_t const flags )
+    void tjob_t::push( tjob_t::push_flag_t const flags )
     {
         this->doPush( flags );
     }
 
-    void TrackJobBase::pushParticles()
+    void tjob_t::pushParticles()
     {
         this->doPush( st::TRACK_JOB_IO_PARTICLES );
     }
 
-    void TrackJobBase::pushBeamElements()
+    void tjob_t::pushBeamElements()
     {
         this->doPush( st::TRACK_JOB_IO_BEAM_ELEMENTS );
     }
 
-    void TrackJobBase::pushOutput()
+    void tjob_t::pushOutput()
     {
         this->doPush( st::TRACK_JOB_IO_OUTPUT );
     }
 
+    void tjob_t::pushParticlesAddresses()
+    {
+        this->doPush( st::TRACK_JOB_IO_PARTICLES_ADDR );
+    }
+
     /* --------------------------------------------------------------------- */
 
-    _this_t::track_status_t TrackJobBase::track( _size_t const until_turn )
+    bool tjob_t::canFetchParticleAddresses() const SIXTRL_NOEXCEPT
+    {
+        return ( this->doGetPtrParticlesAddrBuffer() != nullptr );
+    }
+
+    bool tjob_t::hasParticleAddresses() const SIXTRL_NOEXCEPT
+    {
+        SIXTRL_ASSERT( ( !this->m_has_particle_addresses ) ||
+            ( ( this->m_has_particle_addresses ) &&
+              ( this->canFetchParticleAddresses() ) ) );
+
+        return this->m_has_particle_addresses;
+    }
+
+    paddr_t const* tjob_t::particleAddresses( st_size_t const index ) const SIXTRL_NOEXCEPT
+    {
+        paddr_t const* ptr_paddr = nullptr;
+
+        if( ( this->doGetPtrParticlesAddrBuffer() != nullptr ) &&
+            ( this->doGetPtrParticlesAddrBuffer()->getNumObjects() > index ) &&
+            ( this->hasParticleAddresses() ) )
+        {
+            ptr_paddr = ::NS(ParticlesAddr_buffer_get_const_particle_addr)(
+                this->doGetPtrParticlesAddrBuffer()->getCApiPtr(), index );
+        }
+
+        return ptr_paddr;
+    }
+
+    st_status_t tjob_t::fetchParticleAddresses()
+    {
+        st_status_t status = this->doFetchParticleAddresses();
+
+        if( ( status == st::ARCH_STATUS_SUCCESS ) &&
+            ( this->requiresCollecting() ) )
+        {
+            status = this->collectParticlesAddresses();
+        }
+
+        if( status == st::ARCH_STATUS_SUCCESS )
+        {
+            this->doSetHasParticleAddressesFlag( true );
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::clearParticleAddresses( st_size_t const index )
+    {
+        return this->doClearParticleAddresses( index );
+    }
+
+    st_status_t tjob_t::clearAllParticleAddresses()
+    {
+        return this->doClearAllParticleAddresses();
+    }
+
+    tjob_t::buffer_t const*
+    tjob_t::ptrParticleAddressesBuffer() const SIXTRL_NOEXCEPT
+    {
+        return this->doGetPtrParticlesAddrBuffer();
+    }
+
+    tjob_t::c_buffer_t const*
+    tjob_t::ptrCParticleAddressesBuffer() const SIXTRL_NOEXCEPT
+    {
+        return ( this->doGetPtrParticlesAddrBuffer() != nullptr )
+            ? this->doGetPtrParticlesAddrBuffer()->getCApiPtr() : nullptr;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    st_track_status_t tjob_t::track( st_size_t const until_turn )
     {
         return this->doTrackUntilTurn( until_turn );
     }
 
-    _this_t::track_status_t TrackJobBase::trackElemByElem(
-        _size_t const until_turn )
+    st_track_status_t tjob_t::trackElemByElem( st_size_t const until_turn )
     {
         return this->doTrackElemByElem( until_turn );
     }
 
-    _this_t::track_status_t TrackJobBase::trackLine(
-        _size_t const beam_elements_begin_index,
-        _size_t const beam_elements_end_index, bool const finish_turn )
+    st_track_status_t tjob_t::trackLine(
+        st_size_t const beam_elements_begin_index,
+        st_size_t const beam_elements_end_index, bool const finish_turn )
     {
         return this->doTrackLine(
             beam_elements_begin_index, beam_elements_end_index, finish_turn );
     }
 
-    bool TrackJobBase::reset(
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF be_buffer,
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::reset(
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF be_buffer,
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        _size_t const particle_set_indices[] = { _size_t{ 0 }, _size_t{ 0 } };
+        st_size_t const particle_set_indices[] = { st_size_t{ 0 }, st_size_t{ 0 } };
 
         return this->reset( particles_buffer,
             &particle_set_indices[ 0 ], &particle_set_indices[ 1 ], be_buffer,
                 ptr_output_buffer, until_turn_elem_by_elem );
     }
 
-    bool TrackJobBase::reset(
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        _size_t const pset_index,
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF be_buffer,
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::reset(
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
+        st_size_t const pset_index,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF be_buffer,
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        _size_t const particle_set_indices[] = { pset_index, _size_t{ 0 } };
+        st_size_t const particle_set_indices[] = { pset_index, st_size_t{ 0 } };
 
         return this->reset( particles_buffer, &particle_set_indices[ 0 ],
             &particle_set_indices[ 1 ], be_buffer, ptr_output_buffer,
                 until_turn_elem_by_elem );
     }
 
-    bool TrackJobBase::reset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::reset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        _size_t const pset_index = _size_t{ 0 };
-        return this->reset( particles_buffer, _size_t{ 1 }, &pset_index,
+        st_size_t const pset_index = st_size_t{ 0 };
+        return this->reset( particles_buffer, st_size_t{ 1 }, &pset_index,
             be_buffer, ptr_output_buffer, until_turn_elem_by_elem );
     }
 
-    bool TrackJobBase::reset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _size_t const particle_set_index,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::reset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        st_size_t const particle_set_index,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
         return this->reset( particles_buffer,
-            _size_t{ 1 }, &particle_set_index, be_buffer,
+            st_size_t{ 1 }, &particle_set_index, be_buffer,
                 ptr_output_buffer, until_turn_elem_by_elem );
     }
 
-    bool TrackJobBase::reset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _size_t const num_particle_sets,
-        _size_t const* SIXTRL_RESTRICT
+    bool tjob_t::reset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        st_size_t const num_particle_sets,
+        st_size_t const* SIXTRL_RESTRICT
             particle_set_indices_begin,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem )
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        _size_t const* particle_set_indices_end =
+        st_size_t const* particle_set_indices_end =
             particle_set_indices_begin;
 
         if( ( particle_set_indices_end != nullptr ) &&
-            ( num_particle_sets > _size_t{ 0 } ) )
+            ( num_particle_sets > st_size_t{ 0 } ) )
         {
             std::advance( particle_set_indices_end, num_particle_sets );
         }
@@ -283,12 +390,10 @@ namespace SIXTRL_CXX_NAMESPACE
             be_buffer, ptr_output_buffer, until_turn_elem_by_elem );
     }
 
-    bool TrackJobBase::selectParticleSet( _size_t const particle_set_index )
+    bool tjob_t::selectParticleSet( st_size_t const particle_set_index )
     {
-        using buffer_t   = _this_t::buffer_t;
-        using c_buffer_t = _this_t::c_buffer_t;
-        using size_t = _size_t;
-
+        using buffer_t   = tjob_t::buffer_t;
+        using c_buffer_t = tjob_t::c_buffer_t;
         bool success = false;
 
         buffer_t*   ptr_particles_buffer   = this->ptrOutputBuffer();
@@ -299,7 +404,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
         if( ( ptr_c_particles_buffer != nullptr ) &&
             ( !::NS(Buffer_needs_remapping)( ptr_c_particles_buffer ) ) &&
-            ( static_cast< size_t >( ::NS(Buffer_get_num_of_objects)(
+            ( static_cast< st_size_t >( ::NS(Buffer_get_num_of_objects)(
                 ptr_c_particles_buffer ) ) > particle_set_index ) &&
             ( ptr_c_beam_elem_buffer != nullptr ) &&
             ( !::NS(Buffer_needs_remapping)( ptr_c_beam_elem_buffer ) ) )
@@ -336,7 +441,7 @@ namespace SIXTRL_CXX_NAMESPACE
                     ::NS(Buffer_clear)( ptr_c_output_buffer, true );
                 }
 
-                size_t particle_set_indices[ 1 ] = { size_t{ 0 } };
+                st_size_t particle_set_indices[ 1 ] = { st_size_t{ 0 } };
                 particle_set_indices[ 0 ] = particle_set_index;
 
                 success = this->reset( *ptr_particles_buffer,
@@ -352,7 +457,7 @@ namespace SIXTRL_CXX_NAMESPACE
                     ::NS(Buffer_clear)( ptr_c_output_buffer, true );
                 }
 
-                success = this->reset( ptr_c_particles_buffer, size_t{ 1 },
+                success = this->reset( ptr_c_particles_buffer, st_size_t{ 1 },
                     &particle_set_index, ptr_c_beam_elem_buffer,
                         ptr_c_output_buffer, this->untilTurnElemByElem() );
             }
@@ -361,8 +466,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobBase::assignOutputBuffer(
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF output_buffer )
+    bool tjob_t::assignOutputBuffer(
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF output_buffer )
     {
         bool success = false;
 
@@ -382,62 +487,62 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobBase::assignOutputBuffer(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer )
+    bool tjob_t::assignOutputBuffer(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer )
     {
         return this->doAssignNewOutputBuffer( ptr_output_buffer );
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::type_t TrackJobBase::type() const SIXTRL_NOEXCEPT
+    tjob_t::type_t tjob_t::type() const SIXTRL_NOEXCEPT
     {
         return this->m_type_id;
     }
 
-    std::string const& TrackJobBase::typeStr() const SIXTRL_NOEXCEPT
+    std::string const& tjob_t::typeStr() const SIXTRL_NOEXCEPT
     {
         return this->m_type_str;
     }
 
-    char const* TrackJobBase::ptrTypeStr() const SIXTRL_NOEXCEPT
+    char const* tjob_t::ptrTypeStr() const SIXTRL_NOEXCEPT
     {
         return this->m_type_str.c_str();
     }
 
-    bool TrackJobBase::hasDeviceIdStr() const SIXTRL_RESTRICT
+    bool tjob_t::hasDeviceIdStr() const SIXTRL_NOEXCEPT
     {
         return ( !this->m_device_id_str.empty() );
     }
 
-    std::string const& TrackJobBase::deviceIdStr() const SIXTRL_NOEXCEPT
+    std::string const& tjob_t::deviceIdStr() const SIXTRL_NOEXCEPT
     {
         return this->m_device_id_str;
     }
 
-    char const* TrackJobBase::ptrDeviceIdStr() const SIXTRL_NOEXCEPT
+    char const* tjob_t::ptrDeviceIdStr() const SIXTRL_NOEXCEPT
     {
         return this->m_device_id_str.c_str();
     }
 
-    bool TrackJobBase::hasConfigStr() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasConfigStr() const SIXTRL_NOEXCEPT
     {
         return ( !this->m_config_str.empty() );
     }
 
-    std::string const& TrackJobBase::configStr() const SIXTRL_NOEXCEPT
+    std::string const& tjob_t::configStr() const SIXTRL_NOEXCEPT
     {
         return this->m_config_str;
     }
 
-    char const* TrackJobBase::ptrConfigStr() const SIXTRL_NOEXCEPT
+    char const* tjob_t::ptrConfigStr() const SIXTRL_NOEXCEPT
     {
         return this->m_config_str.c_str();
     }
 
     /* --------------------------------------------------------------------- */
 
-    _size_t TrackJobBase::numParticleSets() const SIXTRL_NOEXCEPT
+    st_size_t tjob_t::numParticleSets() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_num_particles_in_sets.size() ==
                        this->m_particle_set_indices.size() );
@@ -445,7 +550,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_particle_set_indices.size();
     }
 
-    _size_t const* TrackJobBase::particleSetIndicesBegin() const SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::particleSetIndicesBegin() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_num_particles_in_sets.size() ==
                        this->m_particle_set_indices.size() );
@@ -453,16 +558,15 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_particle_set_indices.data();
     }
 
-    _size_t const* TrackJobBase::particleSetIndicesEnd() const SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::particleSetIndicesEnd() const SIXTRL_NOEXCEPT
     {
-        _size_t const* end_ptr = this->particleSetIndicesBegin();
+        st_size_t const* end_ptr = this->particleSetIndicesBegin();
         SIXTRL_ASSERT( end_ptr != nullptr );
         std::advance( end_ptr, this->numParticleSets() );
         return end_ptr;
     }
 
-    _size_t TrackJobBase::particleSetIndex(
-        _size_t const n ) const
+    st_size_t tjob_t::particleSetIndex( st_size_t const n ) const
     {
         SIXTRL_ASSERT( this->m_num_particles_in_sets.size() ==
                        this->m_particle_set_indices.size() );
@@ -471,7 +575,7 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
 
-    _size_t const* TrackJobBase::numParticlesInSetsBegin() const SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::numParticlesInSetsBegin() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_num_particles_in_sets.size() ==
                        this->m_particle_set_indices.size() );
@@ -479,15 +583,15 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_num_particles_in_sets.data();
     }
 
-    _size_t const* TrackJobBase::numParticlesInSetsEnd() const SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::numParticlesInSetsEnd() const SIXTRL_NOEXCEPT
     {
-        _size_t const* end_ptr = this->numParticlesInSetsBegin();
+        st_size_t const* end_ptr = this->numParticlesInSetsBegin();
         SIXTRL_ASSERT( end_ptr != nullptr );
         std::advance( end_ptr, this->numParticleSets() );
         return end_ptr;
     }
 
-    _size_t TrackJobBase::numParticlesInSet( _size_t const n ) const
+    st_size_t tjob_t::numParticlesInSet( st_size_t const n ) const
     {
         SIXTRL_ASSERT( this->m_num_particles_in_sets.size() ==
                        this->m_particle_set_indices.size() );
@@ -495,7 +599,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_num_particles_in_sets.at( n );
     }
 
-    _size_t TrackJobBase::totalNumParticlesInSets() const
+    st_size_t tjob_t::totalNumParticlesInSets() const
     {
         SIXTRL_ASSERT( this->m_num_particles_in_sets.size() ==
                        this->m_particle_set_indices.size() );
@@ -505,54 +609,45 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::particle_index_t
-    TrackJobBase::minParticleId() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t tjob_t::minParticleId() const SIXTRL_NOEXCEPT
     {
         return this->m_min_particle_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBase::maxParticleId() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t tjob_t::maxParticleId() const SIXTRL_NOEXCEPT
     {
         return this->m_max_particle_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBase::minElementId()  const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t tjob_t::minElementId()  const SIXTRL_NOEXCEPT
     {
         return this->m_min_element_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBase::maxElementId()  const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t tjob_t::maxElementId()  const SIXTRL_NOEXCEPT
     {
         return this->m_max_element_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBase::minInitialTurnId() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t tjob_t::minInitialTurnId() const SIXTRL_NOEXCEPT
     {
         return this->m_min_initial_turn_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBase::maxInitialTurnId() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t tjob_t::maxInitialTurnId() const SIXTRL_NOEXCEPT
     {
         return this->m_max_initial_turn_id;
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::buffer_t* TrackJobBase::ptrParticlesBuffer() SIXTRL_NOEXCEPT
+    tjob_t::buffer_t* tjob_t::ptrParticlesBuffer() SIXTRL_NOEXCEPT
     {
-        using ptr_t   = _this_t::buffer_t*;
-
-        return const_cast< ptr_t >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::buffer_t* >( static_cast< tjob_t const& >(
             *this ).ptrParticlesBuffer() );
     }
 
-    _this_t::buffer_t const*
-    TrackJobBase::ptrParticlesBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::buffer_t const* tjob_t::ptrParticlesBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( this->m_ptr_particles_buffer == nullptr ) ||
@@ -562,17 +657,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_ptr_particles_buffer;
     }
 
-    _this_t::c_buffer_t*
-    TrackJobBase::ptrCParticlesBuffer() SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t* tjob_t::ptrCParticlesBuffer() SIXTRL_NOEXCEPT
     {
-        using ptr_t   = _this_t::c_buffer_t*;
-
-        return const_cast< ptr_t >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::c_buffer_t* >( static_cast< tjob_t const& >(
             *this ).ptrCParticlesBuffer() );
     }
 
-    _this_t::c_buffer_t const*
-    TrackJobBase::ptrCParticlesBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t const*
+    tjob_t::ptrCParticlesBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( this->m_ptr_particles_buffer == nullptr ) ||
@@ -582,18 +674,28 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_ptr_c_particles_buffer;
     }
 
-    /* --------------------------------------------------------------------- */
+    tjob_t::buffer_t* tjob_t::ptrParticleAddressesBuffer() SIXTRL_NOEXCEPT
+    {
+        return ( this->doGetPtrParticlesAddrBuffer() != nullptr )
+            ? this->doGetPtrParticlesAddrBuffer() : nullptr;
+    }
 
-    _this_t::buffer_t* TrackJobBase::ptrBeamElementsBuffer() SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t* tjob_t::ptrCParticleAddressesBuffer() SIXTRL_NOEXCEPT
     {
-        using ptr_t   = _this_t::buffer_t*;
+        return ( this->doGetPtrParticlesAddrBuffer() != nullptr )
+            ? this->doGetPtrParticlesAddrBuffer()->getCApiPtr() : nullptr;
+    }
 
-        return const_cast< ptr_t >( static_cast< _this_t const& >(
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::buffer_t* tjob_t::ptrBeamElementsBuffer() SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::buffer_t* >( static_cast< tjob_t const& >(
             *this ).ptrBeamElementsBuffer() );
     }
 
-    _this_t::buffer_t const*
-    TrackJobBase::ptrBeamElementsBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::buffer_t const*
+    tjob_t::ptrBeamElementsBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( this->m_ptr_beam_elem_buffer == nullptr ) ||
@@ -603,17 +705,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_ptr_beam_elem_buffer;
     }
 
-    _this_t::c_buffer_t*
-    TrackJobBase::ptrCBeamElementsBuffer() SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t* tjob_t::ptrCBeamElementsBuffer() SIXTRL_NOEXCEPT
     {
-        using ptr_t   = _this_t::c_buffer_t*;
-
-        return const_cast< ptr_t >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::c_buffer_t* >( static_cast< tjob_t const& >(
             *this ).ptrCBeamElementsBuffer() );
     }
 
-    _this_t::c_buffer_t const*
-    TrackJobBase::ptrCBeamElementsBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t const*
+    tjob_t::ptrCBeamElementsBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( this->m_ptr_beam_elem_buffer == nullptr ) ||
@@ -625,12 +724,555 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    bool TrackJobBase::hasOutputBuffer() const SIXTRL_NOEXCEPT
+    bool tjob_t::can_fetch_particles_addr() const SIXTRL_NOEXCEPT
+    {
+        return false;
+    }
+
+    bool tjob_t::has_particles_addr() const SIXTRL_NOEXCEPT
+    {
+        return false;
+    }
+
+    st_status_t tjob_t::fetch_particles_addr()
+    {
+        return st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    st_status_t tjob_t::clear_all_particles_addr()
+    {
+        return st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    st_status_t tjob_t::clear_particles_addr( st_size_t const )
+    {
+        return st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    paddr_t const* tjob_t::particles_addr(
+        st_size_t const ) const SIXTRL_NOEXCEPT
+    {
+        return nullptr;
+    }
+
+    tjob_t::buffer_t const*
+    tjob_t::ptr_particles_addr_buffer() const SIXTRL_NOEXCEPT
+    {
+        return nullptr;
+    }
+
+    tjob_t::c_buffer_t const*
+    tjob_t::ptr_particles_addr_cbuffer() const SIXTRL_NOEXCEPT
+    {
+        return nullptr;
+    }
+
+    /* ----------------------------------------------------------------- */
+
+    tjob_t::assign_item_t* tjob_t::add_assign_address_item(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT assign_item_to_add )
+    {
+        tjob_t::assign_item_t* item = nullptr;
+
+        if( assign_item_to_add.valid() )
+        {
+            tjob_t::assign_item_key_t const key =
+            tjob_t::assign_item_key_t{
+                assign_item_to_add.getDestBufferId(),
+                assign_item_to_add.getSrcBufferId() };
+
+            st_size_t item_index =
+                std::numeric_limits< st_size_t >::max();
+
+            st_status_t const status = this->doAddAssignAddressItem(
+                assign_item_to_add, &item_index );
+
+            if( status == st::ARCH_STATUS_SUCCESS )
+            {
+                item = this->doGetAssignAddressItem( key, item_index );
+            }
+        }
+
+        return item;
+    }
+
+    tjob_t::assign_item_t* tjob_t::add_assign_address_item(
+        tjob_t::object_type_id_t const dest_type_id,
+        st_size_t const dest_buffer_id,
+        st_size_t const dest_elem_index,
+        st_size_t const dest_pointer_offset,
+        tjob_t::object_type_id_t const src_type_id,
+        st_size_t const src_buffer_id,
+        st_size_t const src_elem_index,
+        st_size_t const src_pointer_offset )
+    {
+        return this->add_assign_address_item( tjob_t::assign_item_t{
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset } );
+    }
+
+    st_status_t tjob_t::remove_assign_address_item(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF item_to_remove )
+    {
+        tjob_t::assign_item_key_t const key =
+        tjob_t::assign_item_key_t{
+            item_to_remove.getDestBufferId(),
+            item_to_remove.getSrcBufferId() };
+
+        st_size_t const item_index =
+            this->doFindAssingAddressItem( item_to_remove );
+
+        return this->doRemoveAssignAddressItem( key, item_index );
+    }
+
+    st_status_t tjob_t::remove_assign_address_item(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+        st_size_t const index_of_item_to_remove )
+    {
+        return this->doRemoveAssignAddressItem( key, index_of_item_to_remove );
+    }
+
+    bool tjob_t::has_assign_address_item( tjob_t::assign_item_t const&
+        SIXTRL_RESTRICT_REF assign_item ) const SIXTRL_NOEXCEPT
+    {
+        st_size_t const item_index =
+            this->doFindAssingAddressItem( assign_item );
+
+        return ( item_index < this->num_assign_items(
+            assign_item.getDestBufferId(), assign_item.getSrcBufferId() ) );
+    }
+
+    bool tjob_t::has_assign_address_item(
+        tjob_t::object_type_id_t const dest_type_id,
+        st_size_t const dest_buffer_id,
+        st_size_t const dest_elem_index,
+        st_size_t const dest_pointer_offset,
+        tjob_t::object_type_id_t const src_type_id,
+        st_size_t const src_buffer_id,
+        st_size_t const src_elem_index,
+        st_size_t const src_pointer_offset ) const SIXTRL_NOEXCEPT
+    {
+        return this->has_assign_address_item( tjob_t::assign_item_t{
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset } );
+    }
+
+    st_size_t tjob_t::index_of_assign_address_item(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF
+            assign_item ) const SIXTRL_NOEXCEPT
+    {
+        return this->doFindAssingAddressItem( assign_item );
+    }
+
+    st_size_t tjob_t::index_of_assign_address_item(
+        tjob_t::object_type_id_t const dest_type_id,
+        st_size_t const dest_buffer_id,
+        st_size_t const dest_elem_index,
+        st_size_t const dest_pointer_offset,
+        tjob_t::object_type_id_t const src_type_id,
+        st_size_t const src_buffer_id,
+        st_size_t const src_elem_index,
+        st_size_t const src_pointer_offset ) const SIXTRL_NOEXCEPT
+    {
+        return this->doFindAssingAddressItem( tjob_t::assign_item_t{
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset } );
+    }
+
+    bool tjob_t::has_assign_items( st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        return ( this->num_assign_items(
+            dest_buffer_id, src_buffer_id ) > st_size_t{ 0 } );
+    }
+
+    st_size_t tjob_t::num_assign_items( st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        st_size_t num_items = st_size_t{ 0 };
+        auto it = this->m_assign_address_items.find(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id } );
+
+        if( it != this->m_assign_address_items.end() )
+        {
+            num_items = it->second.getNumObjects();
+        }
+
+        return num_items;
+    }
+
+    st_size_t
+    tjob_t::num_distinct_available_assign_address_items_dest_src_pairs()
+        const SIXTRL_NOEXCEPT
+    {
+        return this->m_assign_item_keys.size();
+    }
+
+    st_size_t tjob_t::available_assign_address_items_dest_src_pairs(
+        st_size_t const max_num_pairs,
+        tjob_t::assign_item_key_t* pairs_begin ) const SIXTRL_NOEXCEPT
+    {
+        using size_t = st_size_t;
+        size_t num_pairs = size_t{ 0 };
+
+        if( ( max_num_pairs > size_t{ 0 } ) && ( pairs_begin != nullptr ) &&
+            ( !this->m_assign_address_items.empty() ) )
+        {
+            tjob_t::assign_item_key_t* pairs_end = pairs_begin;
+            std::advance( pairs_end, max_num_pairs );
+
+            num_pairs = this->available_assign_address_items_dest_src_pairs(
+                pairs_begin, pairs_end );
+        }
+
+        return num_pairs;
+    }
+
+    tjob_t::c_buffer_t* tjob_t::buffer_by_buffer_id(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = tjob_t::c_buffer_t*;
+        return const_cast< ptr_t >( static_cast< tjob_t const& >(
+            *this ).buffer_by_buffer_id( buffer_id ) );
+    }
+
+    tjob_t::c_buffer_t const* tjob_t::buffer_by_buffer_id(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::c_buffer_t const* ptr_buffer = nullptr;
+
+        switch( buffer_id )
+        {
+            case st::ARCH_PARTICLES_BUFFER_ID:
+            {
+                ptr_buffer = this->ptrCParticlesBuffer();
+                break;
+            }
+
+            case st::ARCH_BEAM_ELEMENTS_BUFFER_ID:
+            {
+                ptr_buffer = this->ptrCBeamElementsBuffer();
+                break;
+            }
+
+            case st::ARCH_OUTPUT_BUFFER_ID:
+            {
+                ptr_buffer = this->ptrCOutputBuffer();
+                break;
+            }
+
+            case st::ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID:
+            {
+                ptr_buffer = this->m_elem_by_elem_buffer.get();
+                break;
+            }
+
+            case st::ARCH_PARTICLE_ADDR_BUFFER_ID:
+            {
+                ptr_buffer = this->m_particles_addr_buffer.get();
+                break;
+            }
+
+            default:
+            {
+                if( ( buffer_id >= st::ARCH_MIN_USER_DEFINED_BUFFER_ID ) &&
+                    ( buffer_id <= st::ARCH_MAX_USER_DEFINED_BUFFER_ID ) )
+                {
+                    ptr_buffer = this->ptr_stored_buffer( buffer_id );
+                }
+            }
+        };
+
+        return ptr_buffer;
+    }
+
+    bool tjob_t::is_buffer_by_buffer_id(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        return ( ( buffer_id == st::ARCH_PARTICLES_BUFFER_ID ) ||
+                 ( buffer_id == st::ARCH_BEAM_ELEMENTS_BUFFER_ID ) ||
+                 ( buffer_id == st::ARCH_OUTPUT_BUFFER_ID ) ||
+                 ( buffer_id == st::ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID ) ||
+                 ( buffer_id == st::ARCH_PARTICLE_ADDR_BUFFER_ID ) ||
+                 ( ( buffer_id >= st::ARCH_MIN_USER_DEFINED_BUFFER_ID ) &&
+                   ( buffer_id <= st::ARCH_MAX_USER_DEFINED_BUFFER_ID ) ) );
+    }
+
+    bool tjob_t::is_raw_memory_by_buffer_id(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        return ( ( buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+                 ( !this->is_buffer_by_buffer_id( buffer_id ) ) );
+    }
+
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object) const* tjob_t::assign_items_begin(
+        st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        auto it = this->m_assign_address_items.find(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id } );
+
+        return ( it != this->m_assign_address_items.end() )
+            ? ::NS(Buffer_get_const_objects_begin)( it->second.getCApiPtr() )
+            : nullptr;
+    }
+
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object) const* tjob_t::assign_items_end(
+        st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        auto it = this->m_assign_address_items.find(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id } );
+
+        return ( it != this->m_assign_address_items.end() )
+            ? ::NS(Buffer_get_const_objects_begin)( it->second.getCApiPtr() )
+            : nullptr;
+    }
+
+    tjob_t::assign_item_key_t const*
+    tjob_t::assign_item_dest_src_begin() const SIXTRL_NOEXCEPT
+    {
+        return this->m_assign_item_keys.data();
+    }
+
+    tjob_t::assign_item_key_t const*
+    tjob_t::assign_item_dest_src_end() const SIXTRL_NOEXCEPT
+    {
+        tjob_t::assign_item_key_t const* end_ptr =
+            this->assign_item_dest_src_begin();
+
+        if( ( end_ptr != nullptr ) && ( this->m_assign_item_keys.empty() ) )
+        {
+            std::advance( end_ptr, this->m_assign_address_items.size() );
+        }
+
+        return end_ptr;
+    }
+
+    st_size_t tjob_t::total_num_assign_items() const SIXTRL_NOEXCEPT
+    {
+        using size_t = st_size_t;
+        size_t total_num_items = size_t{ 0 };
+
+        auto it = this->m_assign_address_items.begin();
+        auto end = this->m_assign_address_items.end();
+
+        for( ; it != end ; ++it ) total_num_items += it->second.getNumObjects();
+        return total_num_items;
+    }
+
+    tjob_t::assign_item_t const* tjob_t::ptr_assign_address_item(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF
+            assign_address_item ) const SIXTRL_NOEXCEPT
+    {
+        st_size_t const assign_item_idx =
+            this->doFindAssingAddressItem( assign_address_item );
+
+        return this->doGetAssignAddressItem( tjob_t::assign_item_key_t{
+                assign_address_item.getDestBufferId(),
+                assign_address_item.getSrcBufferId() }, assign_item_idx );
+    }
+
+
+    tjob_t::assign_item_t const* tjob_t::ptr_assign_address_item(
+        st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id,
+        st_size_t const assign_item_index ) const SIXTRL_NOEXCEPT
+    {
+        return this->doGetAssignAddressItem(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id },
+                assign_item_index );
+    }
+
+    tjob_t::assign_item_t const* tjob_t::ptr_assign_address_item(
+        tjob_t::object_type_id_t const dest_type_id,
+        st_size_t const dest_buffer_id,
+        st_size_t const dest_elem_index,
+        st_size_t const dest_pointer_offset,
+        tjob_t::object_type_id_t const src_type_id,
+        st_size_t const src_buffer_id,
+        st_size_t const src_elem_index,
+        st_size_t const src_pointer_offset ) const SIXTRL_NOEXCEPT
+    {
+        return this->ptr_assign_address_item(
+            tjob_t::assign_item_t{ dest_type_id, dest_buffer_id,
+                dest_elem_index, dest_pointer_offset, src_type_id,
+                    src_buffer_id, src_elem_index, src_pointer_offset } );
+    }
+
+    st_status_t tjob_t::commit_address_assignments()
+    {
+        return this->doCommitAddressAssignments();
+    }
+
+    st_status_t tjob_t::assign_all_addresses()
+    {
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+
+        auto it = this->m_assign_address_items.begin();
+        auto end = this->m_assign_address_items.end();
+
+        for( ; it != end ; ++it )
+        {
+            status = this->doPerformAddressAssignments( it->first );
+            if( status != st::ARCH_STATUS_SUCCESS ) break;
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::assign_addresses( st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id )
+    {
+        return this->doPerformAddressAssignments(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id } );
+    }
+
+    /* ---------------------------------------------------------------- */
+
+    st_size_t tjob_t::stored_buffers_capacity() const SIXTRL_NOEXCEPT
+    {
+        return this->m_stored_buffers.capacity();
+    }
+
+    st_status_t tjob_t::reserve_stored_buffers_capacity(
+        st_size_t const capacity )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( capacity < this->m_stored_buffers.capacity() )
+        {
+            this->m_stored_buffers.reserve( capacity );
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    bool tjob_t::has_stored_buffers() const SIXTRL_NOEXCEPT
+    {
+        return ( this->num_stored_buffers() > st_size_t{ 0 } );
+    }
+
+    st_size_t tjob_t::num_stored_buffers() const SIXTRL_NOEXCEPT
+    {
+        SIXTRL_ASSERT( std::count_if( this->m_stored_buffers.begin(),
+            this->m_stored_buffers.end(),
+            []( tjob_t::buffer_store_t const& s) { return s.active(); } ) ==
+            static_cast< std::ptrdiff_t >( this->m_num_stored_buffers ) );
+
+        SIXTRL_ASSERT( this->m_stored_buffers.size() >=
+                       this->m_num_stored_buffers );
+
+        return this->m_num_stored_buffers;
+    }
+
+    st_size_t tjob_t::min_stored_buffer_id() const SIXTRL_NOEXCEPT
+    {
+        return ( this->has_stored_buffers() )
+            ? st::ARCH_MIN_USER_DEFINED_BUFFER_ID : st::ARCH_ILLEGAL_BUFFER_ID;
+    }
+
+    st_size_t tjob_t::max_stored_buffer_id() const SIXTRL_NOEXCEPT
+    {
+        st_size_t max_stored_buffers_id = this->min_stored_buffer_id();
+
+        if( max_stored_buffers_id != st::ARCH_ILLEGAL_BUFFER_ID )
+        {
+            SIXTRL_ASSERT( this->m_stored_buffers.size() >= st_size_t{ 1 } );
+            max_stored_buffers_id += this->m_stored_buffers.size();
+            max_stored_buffers_id -= st_size_t{ 1 };
+        }
+
+        return max_stored_buffers_id;
+    }
+
+    bool tjob_t::owns_stored_buffer(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        auto ptr_buffer_store = this->doGetPtrBufferStore( buffer_id );
+        return ( ( ptr_buffer_store != nullptr ) &&
+                 ( ptr_buffer_store->owns_buffer() ) );
+    }
+
+    st_status_t tjob_t::remove_stored_buffer( st_size_t const buffer_index )
+    {
+        return this->doRemoveStoredBuffer( buffer_index );
+    }
+
+    tjob_t::buffer_t& tjob_t::stored_cxx_buffer( st_size_t const buffer_id )
+    {
+        return const_cast< tjob_t::buffer_t& >( static_cast< tjob_t const& >(
+            *this ).stored_cxx_buffer( buffer_id ) );
+    }
+
+    tjob_t::buffer_t const& tjob_t::stored_cxx_buffer(
+        st_size_t const buffer_id ) const
+    {
+        tjob_t::buffer_t const* ptr_buffer =
+            this->ptr_stored_cxx_buffer( buffer_id );
+
+        if( ptr_buffer == nullptr )
+        {
+            throw std::runtime_error(
+                "stored buffer does not have a c++ representation" );
+        }
+
+        return *ptr_buffer;
+    }
+
+    tjob_t::buffer_t* tjob_t::ptr_stored_cxx_buffer(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::buffer_t* >( static_cast< tjob_t const& >(
+            *this ).ptr_stored_cxx_buffer( buffer_id ) );
+    }
+
+    tjob_t::buffer_t const* tjob_t::ptr_stored_cxx_buffer(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::buffer_store_t const* ptr_stored_buffer =
+            this->doGetPtrBufferStore( buffer_id );
+
+        return ( ptr_stored_buffer != nullptr )
+            ? ptr_stored_buffer->ptr_cxx_buffer() : nullptr;
+    }
+
+    tjob_t::c_buffer_t* tjob_t::ptr_stored_buffer(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::c_buffer_t* >( static_cast<
+            tjob_t const& >( *this ).ptr_stored_buffer( buffer_id ) );
+    }
+
+    tjob_t::c_buffer_t const* tjob_t::ptr_stored_buffer(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::buffer_store_t const* ptr_stored_buffer =
+            this->doGetPtrBufferStore( buffer_id );
+
+        return ( ptr_stored_buffer != nullptr )
+            ? ptr_stored_buffer->ptr_buffer() : nullptr;
+    }
+
+    st_status_t tjob_t::push_stored_buffer( st_size_t const buffer_id )
+    {
+        return this->doPushStoredBuffer( buffer_id );
+    }
+
+    st_status_t tjob_t::collect_stored_buffer( st_size_t const buffer_id )
+    {
+        return this->doCollectStoredBuffer( buffer_id );
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    bool tjob_t::hasOutputBuffer() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCOutputBuffer() != nullptr );
     }
 
-    bool TrackJobBase::ownsOutputBuffer() const SIXTRL_NOEXCEPT
+    bool tjob_t::ownsOutputBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( this->m_my_output_buffer.get() == nullptr ) ||
@@ -643,12 +1285,12 @@ namespace SIXTRL_CXX_NAMESPACE
                  ( this->m_my_output_buffer.get() != nullptr ) );
     }
 
-    bool TrackJobBase::hasElemByElemOutput() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasElemByElemOutput() const SIXTRL_NOEXCEPT
     {
         return this->m_has_elem_by_elem_output;
     }
 
-    bool TrackJobBase::hasBeamMonitorOutput() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasBeamMonitorOutput() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             (  !this->m_has_beam_monitor_output ) ||
@@ -658,61 +1300,54 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_has_beam_monitor_output;
     }
 
-    _size_t TrackJobBase::beamMonitorsOutputBufferOffset() const SIXTRL_NOEXCEPT
+    st_size_t tjob_t::beamMonitorsOutputBufferOffset() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( ( this->hasOutputBuffer() ) &&
               ( ::NS(Buffer_get_size)( this->ptrCOutputBuffer() ) >
                 this->m_be_mon_output_buffer_offset ) ) ||
-            ( this->m_be_mon_output_buffer_offset ==
-                _size_t{ 0 } ) );
+            ( this->m_be_mon_output_buffer_offset == st_size_t{ 0 } ) );
 
         return this->m_be_mon_output_buffer_offset;
     }
 
-    _size_t TrackJobBase::elemByElemOutputBufferOffset() const SIXTRL_NOEXCEPT
+    st_size_t tjob_t::elemByElemOutputBufferOffset() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( ( this->hasOutputBuffer() ) &&
               ( ::NS(Buffer_get_size)( this->ptrCOutputBuffer() ) >
                 this->m_elem_by_elem_output_offset ) ) ||
-            ( this->m_elem_by_elem_output_offset ==
-                _size_t{ 0 } ) );
+            ( this->m_elem_by_elem_output_offset == st_size_t{ 0 } ) );
 
         return this->m_elem_by_elem_output_offset;
     }
 
-    _this_t::particle_index_t
-    TrackJobBase::untilTurnElemByElem() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t tjob_t::untilTurnElemByElem() const SIXTRL_NOEXCEPT
     {
         return this->m_until_turn_elem_by_elem;
     }
 
-    _size_t
-    TrackJobBase::numElemByElemTurns() const SIXTRL_NOEXCEPT
+    st_size_t tjob_t::numElemByElemTurns() const SIXTRL_NOEXCEPT
     {
-        using index_t = _this_t::particle_index_t;
-        using size_t  = _size_t;
+        using index_t = tjob_t::particle_index_t;
 
         if( ( this->m_until_turn_elem_by_elem > this->m_min_initial_turn_id ) &&
             ( this->m_min_initial_turn_id >= index_t{ 0 } ) )
         {
-            return static_cast< size_t >( this->m_until_turn_elem_by_elem -
+            return static_cast< st_size_t >( this->m_until_turn_elem_by_elem -
                 this->m_min_initial_turn_id );
         }
 
-        return size_t{ 0 };
+        return st_size_t{ 0 };
     }
 
-    _this_t::buffer_t* TrackJobBase::ptrOutputBuffer() SIXTRL_RESTRICT
+    tjob_t::buffer_t* tjob_t::ptrOutputBuffer() SIXTRL_NOEXCEPT
     {
-        using ptr_t   = _this_t::buffer_t*;
-
-        return const_cast< ptr_t >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::buffer_t* >( static_cast< tjob_t const& >(
             *this ).ptrOutputBuffer() );
     }
 
-    _this_t::buffer_t* TrackJobBase::ptrOutputBuffer() const SIXTRL_RESTRICT
+    tjob_t::buffer_t const* tjob_t::ptrOutputBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( this->m_ptr_output_buffer == nullptr ) ||
@@ -722,17 +1357,13 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_ptr_output_buffer;
     }
 
-    _this_t::c_buffer_t*
-    TrackJobBase::ptrCOutputBuffer() SIXTRL_RESTRICT
+    tjob_t::c_buffer_t* tjob_t::ptrCOutputBuffer() SIXTRL_NOEXCEPT
     {
-        using ptr_t   = _this_t::c_buffer_t*;
-
-        return const_cast< ptr_t >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::c_buffer_t* >( static_cast< tjob_t const& >(
             *this ).ptrCOutputBuffer() );
     }
 
-    _this_t::c_buffer_t const*
-    TrackJobBase::ptrCOutputBuffer() const SIXTRL_RESTRICT
+    tjob_t::c_buffer_t const* tjob_t::ptrCOutputBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT(
             ( this->m_ptr_output_buffer == nullptr ) ||
@@ -744,110 +1375,122 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    bool TrackJobBase::hasBeamMonitors() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasBeamMonitors() const SIXTRL_NOEXCEPT
     {
         return !this->m_beam_monitor_indices.empty();
     }
 
-    _size_t
-    TrackJobBase::numBeamMonitors() const SIXTRL_NOEXCEPT
+    st_size_t tjob_t::numBeamMonitors() const SIXTRL_NOEXCEPT
     {
         return this->m_beam_monitor_indices.size();
     }
 
 
-    _size_t const*
-    TrackJobBase::beamMonitorIndicesBegin() const SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::beamMonitorIndicesBegin() const SIXTRL_NOEXCEPT
     {
         return this->m_beam_monitor_indices.data();
     }
 
-    _size_t const*
-    TrackJobBase::beamMonitorIndicesEnd() const SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::beamMonitorIndicesEnd() const SIXTRL_NOEXCEPT
     {
-        _size_t const* end_ptr =
-            this->beamMonitorIndicesBegin();
-
-        if( end_ptr != nullptr )
-        {
-            std::advance( end_ptr, this->numBeamMonitors() );
-        }
-
+        st_size_t const* end_ptr = this->beamMonitorIndicesBegin();
+        st_size_t const num_be_monitors = this->numBeamMonitors();
+        if( end_ptr != nullptr ) std::advance( end_ptr, num_be_monitors );
         return end_ptr;
     }
 
-    _size_t
-    TrackJobBase::beamMonitorIndex( _size_t const n ) const
+    st_size_t tjob_t::beamMonitorIndex( st_size_t const n ) const
     {
         return this->m_beam_monitor_indices.at( n );
     }
 
     /* --------------------------------------------------------------------- */
 
-    bool
-    TrackJobBase::hasElemByElemConfig() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasElemByElemConfig() const SIXTRL_NOEXCEPT
     {
-        SIXTRL_ASSERT(
-            ( this->m_my_elem_by_elem_config.get() == nullptr ) ||
-            ( this->m_ptr_c_output_buffer != nullptr ) );
+        tjob_t::elem_by_elem_config_t const* conf = this->ptrElemByElemConfig();
+        return ( ( conf != nullptr ) &&
+                 ( ::NS(ElemByElemConfig_is_active)( conf ) ) );
+    }
 
-        return ( ::NS(ElemByElemConfig_is_active)(
-            this->m_my_elem_by_elem_config.get() ) );
+    tjob_t::c_buffer_t const*
+    tjob_t::ptrElemByElemConfigCBuffer() const SIXTRL_NOEXCEPT
+    {
+        return ( this->m_elem_by_elem_buffer.get() != nullptr )
+            ? this->m_elem_by_elem_buffer->getCApiPtr() : nullptr;
+    }
+
+    tjob_t::c_buffer_t*
+    tjob_t::ptrElemByElemConfigCBuffer() SIXTRL_NOEXCEPT
+    {
+        return ( this->m_elem_by_elem_buffer.get() != nullptr )
+            ? this->m_elem_by_elem_buffer->getCApiPtr() : nullptr;
     }
 
-    _this_t::elem_by_elem_config_t*
-    TrackJobBase::ptrElemByElemConfig() SIXTRL_NOEXCEPT
+    tjob_t::buffer_t const*
+    tjob_t::ptrElemByElemConfigBuffer() const SIXTRL_NOEXCEPT
     {
-        using  ptr_t  = _this_t::elem_by_elem_config_t*;
+        return this->m_elem_by_elem_buffer.get();
+    }
 
-        return const_cast< ptr_t >( static_cast< _this_t const& >(
+    tjob_t::buffer_t* tjob_t::ptrElemByElemConfigBuffer() SIXTRL_NOEXCEPT
+    {
+        return this->m_elem_by_elem_buffer.get();
+    }
+
+    tjob_t::elem_by_elem_config_t*
+    tjob_t::ptrElemByElemConfig() SIXTRL_NOEXCEPT
+    {
+        using  ptr_t = tjob_t::elem_by_elem_config_t*;
+        return const_cast< ptr_t >( static_cast< tjob_t const& >(
             *this ).ptrElemByElemConfig() );
     }
 
-    _this_t::elem_by_elem_order_t
-    TrackJobBase::elemByElemOrder() const SIXTRL_NOEXCEPT
+    tjob_t::elem_by_elem_order_t tjob_t::elemByElemOrder() const SIXTRL_NOEXCEPT
     {
-        return ::NS(ElemByElemConfig_get_order)(
-            this->m_my_elem_by_elem_config.get() );
+        return ::NS(ElemByElemConfig_get_order)( this->ptrElemByElemConfig() );
     }
 
-    _this_t::elem_by_elem_order_t
-    TrackJobBase::defaultElemByElemOrder() const SIXTRL_NOEXCEPT
+    tjob_t::elem_by_elem_order_t
+    tjob_t::defaultElemByElemOrder() const SIXTRL_NOEXCEPT
     {
         return this->m_default_elem_by_elem_order;
     }
 
-    void TrackJobBase::setDefaultElemByElemOrder(
-        _this_t::elem_by_elem_order_t const order ) SIXTRL_NOEXCEPT
+    void tjob_t::setDefaultElemByElemOrder(
+        tjob_t::elem_by_elem_order_t const order ) SIXTRL_NOEXCEPT
     {
         this->m_default_elem_by_elem_order = order;
     }
 
-    bool TrackJobBase::debugMode() const SIXTRL_NOEXCEPT
+    bool tjob_t::debugMode() const SIXTRL_NOEXCEPT
     {
         return this->m_debug_mode;
     }
 
-    _this_t::elem_by_elem_config_t const*
-    TrackJobBase::ptrElemByElemConfig() const SIXTRL_NOEXCEPT
+    tjob_t::elem_by_elem_config_t const*
+    tjob_t::ptrElemByElemConfig() const SIXTRL_NOEXCEPT
     {
-        return this->m_my_elem_by_elem_config.get();
+        return ( ( this->m_elem_by_elem_buffer.get() != nullptr ) &&
+                 ( this->m_elem_by_elem_buffer->getNumObjects() >
+                    st_size_t{ 0 } ) )
+            ? this->m_elem_by_elem_buffer->get<
+                tjob_t::elem_by_elem_config_t >( st_size_t{ 0 } )
+            : nullptr;
     }
 
-    bool
-    TrackJobBase::elemByElemRolling() const SIXTRL_NOEXCEPT
+    bool tjob_t::elemByElemRolling() const SIXTRL_NOEXCEPT
     {
         return ::NS(ElemByElemConfig_is_rolling)(
             this->ptrElemByElemConfig() );
     }
 
-    bool
-    TrackJobBase::defaultElemByElemRolling() const SIXTRL_NOEXCEPT
+    bool tjob_t::defaultElemByElemRolling() const SIXTRL_NOEXCEPT
     {
         return this->m_default_elem_by_elem_rolling;
     }
 
-    void TrackJobBase::setDefaultElemByElemRolling(
+    void tjob_t::setDefaultElemByElemRolling(
         bool is_rolling ) SIXTRL_NOEXCEPT
     {
         this->m_default_elem_by_elem_rolling = is_rolling;
@@ -855,61 +1498,65 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    TrackJobBase::TrackJobBase(
+    tjob_t::TrackJobBase(
         const char *const SIXTRL_RESTRICT type_str,
         track_job_type_t const type_id ) :
         m_type_str(),
         m_device_id_str(),
         m_config_str(),
+        m_assign_address_items(),
         m_particle_set_indices(),
         m_num_particles_in_sets(),
         m_beam_monitor_indices(),
+        m_stored_buffers(),
         m_my_output_buffer( nullptr ),
-        m_my_elem_by_elem_config( nullptr ),
+        m_elem_by_elem_buffer( nullptr ),
+        m_particles_addr_buffer( nullptr ),
         m_ptr_particles_buffer( nullptr ),
         m_ptr_beam_elem_buffer( nullptr ),
         m_ptr_output_buffer( nullptr ),
         m_ptr_c_particles_buffer( nullptr ),
         m_ptr_c_beam_elem_buffer( nullptr ),
         m_ptr_c_output_buffer( nullptr ),
-        m_be_mon_output_buffer_offset( _size_t{ 0 } ),
-        m_elem_by_elem_output_offset( _size_t{ 0 } ),
-        m_total_num_particles_in_sets( _size_t{ 0 } ),
+        m_be_mon_output_buffer_offset( st_size_t{ 0 } ),
+        m_elem_by_elem_output_offset( st_size_t{ 0 } ),
+        m_total_num_particles_in_sets( st_size_t{ 0 } ),
+        m_num_stored_buffers( st_size_t{ 0 } ),
         m_type_id( type_id ),
         m_default_elem_by_elem_order( ::NS(ELEM_BY_ELEM_ORDER_DEFAULT) ),
-        m_min_particle_id( _this_t::particle_index_t{ 0 } ),
-        m_max_particle_id( _this_t::particle_index_t{ 0 } ),
-        m_min_element_id( _this_t::particle_index_t{ 0 } ),
-        m_max_element_id( _this_t::particle_index_t{ 0 } ),
-        m_min_initial_turn_id( _this_t::particle_index_t{ 0 } ),
-        m_max_initial_turn_id( _this_t::particle_index_t{ 0 } ),
-        m_until_turn_elem_by_elem( _size_t{ 0 } ),
-        m_collect_flags(
-            st::TRACK_JOB_IO_DEFAULT_FLAGS ),
+        m_min_particle_id( tjob_t::particle_index_t{ 0 } ),
+        m_max_particle_id( tjob_t::particle_index_t{ 0 } ),
+        m_min_element_id( tjob_t::particle_index_t{ 0 } ),
+        m_max_element_id( tjob_t::particle_index_t{ 0 } ),
+        m_min_initial_turn_id( tjob_t::particle_index_t{ 0 } ),
+        m_max_initial_turn_id( tjob_t::particle_index_t{ 0 } ),
+        m_until_turn_elem_by_elem( st_size_t{ 0 } ),
+        m_collect_flags( st::TRACK_JOB_IO_DEFAULT_FLAGS ),
         m_requires_collect( true ),
         m_default_elem_by_elem_rolling( true ),
         m_has_beam_monitor_output( false ),
         m_has_elem_by_elem_output( false ),
+        m_has_particle_addresses( false ),
         m_debug_mode( false )
     {
-        if( type_str != nullptr )
-        {
-            this->m_type_str = type_str;
-        }
+        if( type_str != nullptr ) this->m_type_str = type_str;
 
         this->doInitDefaultParticleSetIndices();
         this->doInitDefaultBeamMonitorIndices();
     }
 
-    TrackJobBase::TrackJobBase( TrackJobBase const& other ) :
+    tjob_t::TrackJobBase( TrackJobBase const& other ) :
         m_type_str( other.m_type_str ),
         m_device_id_str( other.m_type_str ),
         m_config_str( other.m_config_str ),
+        m_assign_address_items( other.m_assign_address_items ),
         m_particle_set_indices( other.m_particle_set_indices ),
         m_num_particles_in_sets( other.m_num_particles_in_sets ),
         m_beam_monitor_indices( other.m_beam_monitor_indices ),
-        m_my_output_buffer( nullptr  ),
-        m_my_elem_by_elem_config( nullptr ),
+        m_stored_buffers( other.m_stored_buffers ),
+        m_my_output_buffer( nullptr ),
+        m_elem_by_elem_buffer( nullptr ),
+        m_particles_addr_buffer( nullptr ),
         m_ptr_particles_buffer( other.m_ptr_particles_buffer  ),
         m_ptr_beam_elem_buffer( other.m_ptr_beam_elem_buffer ),
         m_ptr_output_buffer( nullptr ),
@@ -919,6 +1566,7 @@ namespace SIXTRL_CXX_NAMESPACE
         m_be_mon_output_buffer_offset( other.m_be_mon_output_buffer_offset ),
         m_elem_by_elem_output_offset( other.m_elem_by_elem_output_offset ),
         m_total_num_particles_in_sets( other.m_total_num_particles_in_sets ),
+        m_num_stored_buffers( other.m_num_stored_buffers ),
         m_type_id( other.m_type_id ),
         m_default_elem_by_elem_order( other.m_default_elem_by_elem_order ),
         m_min_particle_id( other.m_min_particle_id ),
@@ -935,32 +1583,39 @@ namespace SIXTRL_CXX_NAMESPACE
         m_has_elem_by_elem_output( other.m_has_elem_by_elem_output ),
         m_debug_mode( other.m_debug_mode )
     {
-        using elem_by_elem_config_t = _this_t::elem_by_elem_config_t;
-
         if( other.ownsOutputBuffer() )
         {
+            tjob_t::COPY_PTR_BUFFER(
+                this->m_my_output_buffer, other.m_my_output_buffer );
 
+            this->m_ptr_output_buffer = this->m_my_output_buffer.get();
+            if( this->m_ptr_output_buffer != nullptr )
+            {
+                this->m_ptr_c_output_buffer =
+                    this->m_ptr_output_buffer->getCApiPtr();
+            }
         }
 
-        if( other.m_my_elem_by_elem_config.get() != nullptr )
-        {
-            this->m_my_elem_by_elem_config.reset(
-                new elem_by_elem_config_t );
+        tjob_t::COPY_PTR_BUFFER(
+            this->m_elem_by_elem_buffer, other.m_elem_by_elem_buffer );
 
-            *this->m_my_elem_by_elem_config =  *other.ptrElemByElemConfig();
-        }
+        tjob_t::COPY_PTR_BUFFER(
+            this->m_particles_addr_buffer, other.m_particles_addr_buffer );
     }
 
-    TrackJobBase::TrackJobBase(
+    tjob_t::TrackJobBase(
         TrackJobBase&& o ) SIXTRL_NOEXCEPT :
         m_type_str( std::move( o.m_type_str ) ),
         m_device_id_str( std::move( o.m_type_str ) ),
         m_config_str( std::move( o.m_config_str ) ),
+        m_assign_address_items( std::move( o.m_assign_address_items ) ),
         m_particle_set_indices( std::move( o.m_particle_set_indices ) ),
         m_num_particles_in_sets( std::move( o.m_num_particles_in_sets ) ),
         m_beam_monitor_indices( std::move( o.m_beam_monitor_indices ) ),
+        m_stored_buffers( std::move( o.m_stored_buffers ) ),
         m_my_output_buffer( std::move( o.m_my_output_buffer ) ),
-        m_my_elem_by_elem_config( std::move( o.m_my_elem_by_elem_config ) ),
+        m_elem_by_elem_buffer( std::move( o.m_elem_by_elem_buffer ) ),
+        m_particles_addr_buffer( std::move( o.m_particles_addr_buffer ) ),
         m_ptr_particles_buffer( std::move( o.m_ptr_particles_buffer  ) ),
         m_ptr_beam_elem_buffer( std::move( o.m_ptr_beam_elem_buffer ) ),
         m_ptr_output_buffer( std::move( o.m_ptr_output_buffer ) ),
@@ -973,6 +1628,7 @@ namespace SIXTRL_CXX_NAMESPACE
             o.m_elem_by_elem_output_offset ) ),
         m_total_num_particles_in_sets( std::move(
             o.m_total_num_particles_in_sets ) ),
+        m_num_stored_buffers( std::move( o.m_num_stored_buffers ) ),
         m_type_id( std::move( o.m_type_id ) ),
         m_default_elem_by_elem_order( std::move(
             o.m_default_elem_by_elem_order ) ),
@@ -989,6 +1645,7 @@ namespace SIXTRL_CXX_NAMESPACE
             o.m_default_elem_by_elem_rolling ) ),
         m_has_beam_monitor_output( std::move( o.m_has_beam_monitor_output ) ),
         m_has_elem_by_elem_output( std::move( o.m_has_elem_by_elem_output ) ),
+        m_has_particle_addresses( std::move( o.m_has_particle_addresses ) ),
         m_debug_mode( std::move( o.m_debug_mode ) )
     {
         o.m_type_str.clear();
@@ -998,7 +1655,7 @@ namespace SIXTRL_CXX_NAMESPACE
         o.doClearBaseImpl();
     }
 
-    TrackJobBase& TrackJobBase::operator=(
+    TrackJobBase& tjob_t::operator=(
         TrackJobBase const& rhs )
     {
         if( this != &rhs )
@@ -1023,6 +1680,8 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_total_num_particles_in_sets =
                 rhs.m_total_num_particles_in_sets;
 
+            this->m_num_stored_buffers = rhs.m_num_stored_buffers;
+
             this->m_default_elem_by_elem_order =
                 rhs.m_default_elem_by_elem_order;
 
@@ -1042,11 +1701,20 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_has_elem_by_elem_output = rhs.m_has_elem_by_elem_output;
             this->m_requires_collect        = rhs.m_requires_collect;
             this->m_collect_flags           = rhs.m_collect_flags;
+            this->m_assign_address_items    = rhs.m_assign_address_items;
+            this->m_stored_buffers          = rhs.m_stored_buffers;
 
             if( rhs.ownsOutputBuffer() )
             {
-               this->m_ptr_output_buffer    = nullptr;
-               this->m_ptr_c_output_buffer  = nullptr;
+                tjob_t::COPY_PTR_BUFFER(
+                    this->m_my_output_buffer, rhs.m_my_output_buffer );
+
+               this->m_ptr_output_buffer = this->m_my_output_buffer.get();
+               if( this->m_ptr_output_buffer != nullptr )
+               {
+                   this->m_ptr_c_output_buffer =
+                    this->m_ptr_output_buffer->getCApiPtr();
+               }
             }
             else
             {
@@ -1054,17 +1722,11 @@ namespace SIXTRL_CXX_NAMESPACE
                 this->m_ptr_c_output_buffer = rhs.m_ptr_c_output_buffer;
             }
 
-            if( rhs.m_my_elem_by_elem_config.get() != nullptr )
-            {
-                this->m_my_elem_by_elem_config.reset(
-                    new elem_by_elem_config_t );
+            tjob_t::COPY_PTR_BUFFER(
+                this->m_elem_by_elem_buffer, rhs.m_elem_by_elem_buffer );
 
-                *this->m_my_elem_by_elem_config =  *rhs.ptrElemByElemConfig();
-            }
-            else
-            {
-                this->m_my_elem_by_elem_config.reset( nullptr );
-            }
+            tjob_t::COPY_PTR_BUFFER(
+                this->m_particles_addr_buffer, rhs.m_particles_addr_buffer );
 
             this->m_debug_mode = rhs.m_debug_mode;
         }
@@ -1072,7 +1734,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return *this;
     }
 
-    TrackJobBase& TrackJobBase::operator=(
+    TrackJobBase& tjob_t::operator=(
         TrackJobBase&& rhs ) SIXTRL_NOEXCEPT
     {
         if( this != &rhs )
@@ -1090,10 +1752,17 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_beam_monitor_indices =
                 std::move( rhs.m_beam_monitor_indices );
 
+            this->m_stored_buffers   = std::move( rhs.m_stored_buffers );
             this->m_my_output_buffer = std::move( rhs.m_my_output_buffer );
 
-            this->m_my_elem_by_elem_config =
-                std::move( rhs.m_my_elem_by_elem_config );
+            this->m_elem_by_elem_buffer =
+                std::move( rhs.m_elem_by_elem_buffer );
+
+            this->m_particles_addr_buffer =
+                std::move( rhs.m_particles_addr_buffer );
+
+            this->m_assign_address_items =
+                std::move( rhs.m_assign_address_items );
 
             this->m_ptr_particles_buffer =
                 std::move( rhs.m_ptr_particles_buffer );
@@ -1121,6 +1790,9 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_total_num_particles_in_sets =
                 std::move( rhs.m_total_num_particles_in_sets );
 
+            this->m_num_stored_buffers =
+                std::move( rhs.m_num_stored_buffers );
+
             this->m_type_id = std::move( rhs.m_type_id );
 
             this->m_default_elem_by_elem_order =
@@ -1148,6 +1820,9 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_has_elem_by_elem_output =
                 std::move( rhs.m_has_elem_by_elem_output );
 
+            this->m_has_particle_addresses =
+                std::move( rhs.m_has_particle_addresses );
+
             this->m_debug_mode = std::move( rhs.m_debug_mode );
 
             rhs.m_type_str.clear();
@@ -1163,52 +1838,104 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBase::doClear()
+    void tjob_t::doClear()
+    {
+        this->doClearBaseImpl();
+    }
+
+    void tjob_t::doCollect( collect_flag_t const ) {}
+    void tjob_t::doPush( push_flag_t const ) {}
+
+    /* --------------------------------------------------------------------- */
+
+    st_status_t tjob_t::doFetchParticleAddresses()
+    {
+        return st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    st_status_t tjob_t::doClearParticleAddressesBaseImpl(
+        st_size_t const index )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( ( this->doGetPtrParticlesAddrBuffer() != nullptr ) &&
+            ( this->doGetPtrParticlesAddrBuffer()->getNumObjects() > index ) )
+        {
+            status = ::NS(ParticlesAddr_buffer_clear_single)(
+                this->doGetPtrParticlesAddrBuffer()->getCApiPtr(), index );
+
+            this->doSetHasParticleAddressesFlag( false );
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::doClearParticleAddresses(
+        st_size_t const index )
+    {
+        return this->doClearParticleAddressesBaseImpl( index );
+    }
+
+    st_status_t tjob_t::doClearAllParticleAddressesBaseImpl()
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( this->doGetPtrParticlesAddrBuffer() != nullptr )
+        {
+            status = ::NS(ParticlesAddr_buffer_clear_all)(
+                this->doGetPtrParticlesAddrBuffer()->getCApiPtr() );
+
+            this->doSetHasParticleAddressesFlag( false );
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::doClearAllParticleAddresses()
     {
-        this->doClearBaseImpl();
+        return this->doClearAllParticleAddressesBaseImpl();
     }
 
-    void TrackJobBase::doCollect( collect_flag_t const ) {}
-    void TrackJobBase::doPush( push_flag_t const ) {}
-
-    _this_t::track_status_t TrackJobBase::doTrackUntilTurn( size_type const )
+    st_track_status_t tjob_t::doTrackUntilTurn(
+        st_size_t const SIXTRL_UNUSED( until_turn ) )
     {
-        return _this_t::track_status_t{ -1 };
+        return st_track_status_t{ -1 };
     }
 
-    _this_t::track_status_t TrackJobBase::doTrackElemByElem( size_type const )
+    st_track_status_t tjob_t::doTrackElemByElem(
+        st_size_t const SIXTRL_UNUSED( until_turn_elem_by_elem ) )
     {
-        return _this_t::track_status_t{ -1 };
+        return st_track_status_t{ -1 };
     }
 
-    _this_t::track_status_t
-    TrackJobBase::doTrackLine( size_type const, size_type const, bool const )
+    st_track_status_t tjob_t::doTrackLine(
+        st_size_t const SIXTRL_UNUSED( be_idx_begin ) ,
+        st_size_t const SIXTRL_UNUSED( be_idx_end ),
+        bool const SIXTRL_UNUSED( finish_turn ) )
     {
-        return _this_t::track_status_t{ -1 };
+        return st_track_status_t{ -1 };
     }
 
     /* --------------------------------------------------------------------- */
 
-    bool TrackJobBase::doPrepareParticlesStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT pb )
+    bool tjob_t::doPrepareParticlesStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pb )
     {
         bool success = false;
+        using p_index_t = tjob_t::particle_index_t;
 
-        using size_t    = _size_t;
-        using p_index_t = _this_t::particle_index_t;
+        SIXTRL_STATIC_VAR st_size_t const ZERO = st_size_t{ 0 };
+        SIXTRL_STATIC_VAR st_size_t const ONE  = st_size_t{ 1 };
 
-        SIXTRL_STATIC_VAR size_t const ZERO = size_t{ 0 };
-        SIXTRL_STATIC_VAR size_t const ONE  = size_t{ 1 };
-
-        size_t const nn = this->numParticleSets();
-        size_t const num_psets = ::NS(Buffer_get_num_of_objects)( pb );
+        st_size_t const nn = this->numParticleSets();
+        st_size_t const num_psets = ::NS(Buffer_get_num_of_objects)( pb );
 
         if( ( pb != nullptr ) && ( ( nn > ZERO ) || ( nn == ZERO ) ) &&
             ( !::NS(Buffer_needs_remapping)( pb ) ) && ( num_psets >= nn ) )
         {
-            int ret = int{ -1 };
+            tjob_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-            size_t const first_index = ( nn > ZERO )
+            st_size_t const first_index = ( nn > ZERO )
                 ? this->particleSetIndex( ZERO ) : ZERO;
 
             p_index_t min_part_id, max_part_id, min_elem_id, max_elem_id,
@@ -1216,21 +1943,35 @@ namespace SIXTRL_CXX_NAMESPACE
 
             if( ( nn <= ONE ) && ( first_index == ZERO ) )
             {
-                ret = ::NS(Particles_get_min_max_attributes)(
-                        ::NS(Particles_buffer_get_const_particles)( pb, ZERO ),
-                        &min_part_id, &max_part_id, &min_elem_id, &max_elem_id,
-                        &min_turn_id, &max_turn_id );
+                status = ::NS(Particles_get_min_max_attributes)(
+                    ::NS(Particles_buffer_get_const_particles)( pb, ZERO ),
+                    &min_part_id, &max_part_id, &min_elem_id, &max_elem_id,
+                    &min_turn_id, &max_turn_id );
             }
             else if( nn > ZERO )
             {
-                ret =
+                status =
                 ::NS(Particles_buffer_get_min_max_attributes_of_particles_set)(
                     pb, nn, this->particleSetIndicesBegin(),
                     &min_part_id, &max_part_id, &min_elem_id, &max_elem_id,
                     &min_turn_id, &max_turn_id );
             }
 
-            if( ret == int{ 0 } )
+            if( this->doGetPtrParticlesAddrBuffer() == nullptr )
+            {
+                this->doUpdateStoredParticlesAddrBuffer( tjob_t::ptr_buffer_t{
+                    new tjob_t::buffer_t } );
+            }
+
+            if( ( status == st::ARCH_STATUS_SUCCESS ) &&
+                ( this->doGetPtrParticlesAddrBuffer() != nullptr )  )
+            {
+                status =
+                ::NS(ParticlesAddr_prepare_buffer_based_on_particles_buffer)(
+                    this->doGetPtrParticlesAddrBuffer()->getCApiPtr(), pb );
+            }
+
+            if( status == st::ARCH_STATUS_SUCCESS )
             {
                 this->doSetMinParticleId( min_part_id );
                 this->doSetMaxParticleId( max_part_id );
@@ -1243,23 +1984,40 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 success = true;
             }
+
+            if( success )
+            {
+                if( this->m_particles_addr_buffer.get() == nullptr )
+                {
+                    tjob_t::ptr_buffer_t particles_addr_buffer(
+                        new tjob_t::buffer_t );
+
+                    this->doUpdateStoredParticlesAddrBuffer(
+                        std::move( particles_addr_buffer ) );
+                }
+
+                if( this->m_particles_addr_buffer.get() != nullptr )
+                {
+                    success = ( st::ARCH_STATUS_SUCCESS ==
+                    ::NS(ParticlesAddr_prepare_buffer_based_on_particles_buffer)(
+                        this->m_particles_addr_buffer->getCApiPtr(), pb ) );
+                }
+            }
         }
 
         return success;
     }
 
-    bool TrackJobBase::doPrepareBeamElementsStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belems )
+    bool tjob_t::doPrepareBeamElementsStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems )
     {
-        bool success = false;
-
-        using size_t        = _size_t;
-        using p_index_t     = _this_t::particle_index_t;
-        using buf_size_t    = ::NS(buffer_size_t);
-        using obj_ptr_t     = SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object)*;
-        using ptr_t         = SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*;
+        bool success     = false;
+        using p_index_t  = tjob_t::particle_index_t;
+        using buf_size_t = ::NS(buffer_size_t);
+        using obj_ptr_t  = SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object)*;
+        using ptr_t      = SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*;
 
-        SIXTRL_STATIC_VAR size_t const ZERO = size_t{ 0 };
+        SIXTRL_STATIC_VAR st_size_t const ZERO = st_size_t{ 0 };
         SIXTRL_STATIC_VAR uintptr_t const UZERO = uintptr_t{ 0 };
 
         if( ( belems != nullptr ) &&
@@ -1281,26 +2039,31 @@ namespace SIXTRL_CXX_NAMESPACE
             if( ret == 0 )
             {
                 buf_size_t num_be_monitors = buf_size_t{ 0 };
-                std::vector< size_t > be_mon_indices( num_e_by_e_objs, ZERO );
+                std::vector< st_size_t > be_mon_indices( num_e_by_e_objs, ZERO );
 
-                ret = ::NS(BeamMonitor_get_beam_monitor_indices_from_buffer)(
-                    belems, be_mon_indices.size(), be_mon_indices.data(),
-                        &num_be_monitors );
+                num_be_monitors = ::NS(BeamMonitor_monitor_indices_from_buffer)(
+                    be_mon_indices.data(), be_mon_indices.size(), belems );
 
-                SIXTRL_ASSERT( num_be_monitors <= be_mon_indices.size() );
+                if( num_be_monitors <= be_mon_indices.size() )
+                {
+                    auto ind_end = be_mon_indices.begin();
+
+                    if( num_be_monitors > buf_size_t{ 0 } )
+                    {
+                        std::advance( ind_end, num_be_monitors );
+                    }
 
-                auto ind_end = be_mon_indices.begin();
+                    this->doSetBeamMonitorIndices(
+                        be_mon_indices.begin(), ind_end );
+                    SIXTRL_ASSERT( num_be_monitors == this->numBeamMonitors() );
 
-                if( num_be_monitors > buf_size_t{ 0 } )
+                    this->doSetMinElementId( min_elem_id );
+                    this->doSetMaxElementId( max_elem_id );
+                }
+                else
                 {
-                    std::advance( ind_end, num_be_monitors );
+                    ret = -1;
                 }
-
-                this->doSetBeamMonitorIndices( be_mon_indices.begin(), ind_end );
-                SIXTRL_ASSERT( num_be_monitors == this->numBeamMonitors() );
-
-                this->doSetMinElementId( min_elem_id );
-                this->doSetMaxElementId( max_elem_id );
             }
 
             success = ( ret == 0 );
@@ -1341,37 +2104,33 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobBase::doPrepareOutputStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::doPrepareOutputStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
         bool success = false;
 
-        using size_t                    = _size_t;
-        using buffer_t                  = _this_t::buffer_t;
-        using c_buffer_t                = _this_t::c_buffer_t;
-        using buf_size_t                = ::NS(buffer_size_t);
-        using elem_by_elem_config_t     = _this_t::elem_by_elem_config_t;
-        using ptr_output_buffer_t       = _this_t::ptr_output_buffer_t;
-        using par_index_t               = _this_t::particle_index_t;
+        using c_buffer_t = tjob_t::c_buffer_t;
+        using elem_by_elem_config_t = tjob_t::elem_by_elem_config_t;
+        using ptr_output_buffer_t = tjob_t::ptr_buffer_t;
+        using par_index_t = tjob_t::particle_index_t;
 
-        using ptr_elem_by_elem_config_t =
-            _this_t::ptr_elem_by_elem_config_t;
+        ( void )particles_buffer;
 
         SIXTRL_ASSERT( particles_buffer != nullptr );
         SIXTRL_ASSERT( !::NS(Buffer_needs_remapping)( particles_buffer ) );
 
         SIXTRL_ASSERT( ( ::NS(Buffer_get_num_of_objects)( particles_buffer ) ==
-            size_t{ 0 } ) || ( ::NS(Buffer_is_particles_buffer)(
+            st_size_t{ 0 } ) || ( ::NS(Buffer_is_particles_buffer)(
                 particles_buffer ) ) );
 
         SIXTRL_ASSERT( beam_elements_buffer != nullptr );
         SIXTRL_ASSERT( !::NS(Buffer_needs_remapping)( beam_elements_buffer ) );
 
         SIXTRL_ASSERT( ::NS(Buffer_get_num_of_objects)( beam_elements_buffer )
-            > size_t{ 0 } );
+            > st_size_t{ 0 } );
 
         SIXTRL_ASSERT( ::NS(BeamElements_is_beam_elements_buffer)(
             beam_elements_buffer ) );
@@ -1383,7 +2142,8 @@ namespace SIXTRL_CXX_NAMESPACE
             if( !this->hasOutputBuffer() )
             {
                 SIXTRL_ASSERT( !this->ownsOutputBuffer() );
-                ptr_output_buffer_t managed_output_buffer( new buffer_t );
+                tjob_t::ptr_buffer_t managed_output_buffer(
+                    new tjob_t::buffer_t );
 
                 SIXTRL_ASSERT(  managed_output_buffer.get() != nullptr );
                 output_buffer = managed_output_buffer.get()->getCApiPtr();
@@ -1429,16 +2189,16 @@ namespace SIXTRL_CXX_NAMESPACE
 
         if( output_buffer != nullptr )
         {
-            SIXTRL_STATIC_VAR const size_t ZERO = size_t{ 0 };
+            SIXTRL_STATIC_VAR const st_size_t ZERO = st_size_t{ 0 };
             SIXTRL_ASSERT( !::NS(Buffer_needs_remapping)( output_buffer ) );
 
             SIXTRL_ASSERT(
                 ( ::NS(Buffer_get_num_of_objects)( output_buffer ) == ZERO )||
                 ( ::NS(Buffer_is_particles_buffer)( output_buffer ) ) );
 
-            buf_size_t  elem_by_elem_out_idx_offset = buf_size_t{ 0 };
-            buf_size_t  be_monitor_out_idx_offset   = buf_size_t{ 0 };
-            par_index_t max_elem_by_elem_turn_id    = par_index_t{ 0 };
+            st_size_t elem_by_elem_out_idx_offset = st_size_t{ 0 };
+            st_size_t be_monitor_out_idx_offset   = st_size_t{ 0 };
+            par_index_t max_elem_by_elem_turn_id  = par_index_t{ 0 };
 
             int ret = ::NS(OutputBuffer_prepare_detailed)(
                 beam_elements_buffer, output_buffer,
@@ -1449,17 +2209,37 @@ namespace SIXTRL_CXX_NAMESPACE
                 &elem_by_elem_out_idx_offset, &be_monitor_out_idx_offset,
                 &max_elem_by_elem_turn_id );
 
+            if( this->m_elem_by_elem_buffer.get() == nullptr )
+            {
+                tjob_t::ptr_buffer_t elem_by_elem_buffer(
+                    new tjob_t::buffer_t );
+
+                this->doUpdateStoredElemByElemConfig(
+                    std::move( elem_by_elem_buffer ) );
+            }
+            else
+            {
+                this->m_elem_by_elem_buffer->reset();
+            }
+
+            SIXTRL_ASSERT( this->m_elem_by_elem_buffer.get() != nullptr );
+            SIXTRL_ASSERT( this->m_elem_by_elem_buffer->getNumObjects() ==
+                           st_size_t{ 0 } );
+
             if( ( ret == 0 ) && ( until_turn_elem_by_elem > ZERO ) &&
                 ( this->minInitialTurnId() >= par_index_t{ 0 } ) &&
                 ( max_elem_by_elem_turn_id >= this->minInitialTurnId() ) &&
-                ( until_turn_elem_by_elem > static_cast< buf_size_t >(
+                ( until_turn_elem_by_elem > static_cast< st_size_t >(
                     this->minInitialTurnId() ) ) )
             {
-                ptr_elem_by_elem_config_t conf( new elem_by_elem_config_t );
-                ::NS(ElemByElemConfig_preset)( conf.get() );
+                elem_by_elem_config_t* conf = ::NS(ElemByElemConfig_preset)(
+                    ::NS(ElemByElemConfig_new)(
+                        this->m_elem_by_elem_buffer->getCApiPtr() ) );
+
+                SIXTRL_ASSERT( conf != nullptr );
 
-                ret = ::NS(ElemByElemConfig_init_detailed)(
-                    conf.get(), this->defaultElemByElemOrder(),
+                ret = ::NS(ElemByElemConfig_init_detailed)( conf,
+                    this->defaultElemByElemOrder(),
                     this->minParticleId(), this->maxParticleId(),
                     this->minElementId(),  this->maxElementId(),
                     this->minInitialTurnId(), max_elem_by_elem_turn_id,
@@ -1467,19 +2247,13 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 if( ret == 0 )
                 {
-                    this->doUpdateStoredElemByElemConfig( std::move( conf ) );
-                    this->doSetUntilTurnElemByElem(
-                        until_turn_elem_by_elem );
-
+                    this->doSetUntilTurnElemByElem( until_turn_elem_by_elem );
                     SIXTRL_ASSERT( this->hasElemByElemConfig() );
                 }
             }
             else if( ret == 0 )
             {
-                ptr_elem_by_elem_config_t dummy( nullptr );
-                this->doUpdateStoredElemByElemConfig( std::move( dummy ) );
                 this->doSetUntilTurnElemByElem( ZERO );
-
                 ret = ( !this->hasElemByElemConfig() ) ? 0 : -1;
             }
 
@@ -1498,19 +2272,19 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobBase::doAssignOutputBufferToBeamMonitors(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        _this_t::particle_index_t const min_turn_id,
-        _this_t::size_type const output_buffer_offset_index )
+    bool tjob_t::doAssignOutputBufferToBeamMonitors(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        tjob_t::particle_index_t const min_turn_id,
+        st_size_t const output_buffer_offset_index )
     {
         bool success = false;
 
         this->doSetBeamMonitorOutputEnabledFlag( false );
 
         if( ( output_buffer != nullptr ) && ( beam_elem_buffer != nullptr ) &&
-            ( this->numBeamMonitors() > _this_t::size_type{ 0 } ) &&
-            ( min_turn_id >= _this_t::particle_index_t{ 0 } ) &&
+            ( this->numBeamMonitors() > st_size_t{ 0 } ) &&
+            ( min_turn_id >= tjob_t::particle_index_t{ 0 } ) &&
             ( ::NS(Buffer_get_num_of_objects)( output_buffer ) >
               output_buffer_offset_index ) )
         {
@@ -1550,10 +2324,10 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobBase::doAssignOutputBufferToElemByElemConfig(
-        _this_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_config,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        _this_t::size_type const output_buffer_offset_index )
+    bool tjob_t::doAssignOutputBufferToElemByElemConfig(
+        tjob_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_config,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        st_size_t const output_buffer_offset_index )
     {
         bool success = false;
 
@@ -1596,14 +2370,13 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobBase::doReset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::doReset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        using output_buffer_flag_t = _this_t::output_buffer_flag_t;
-
+        using output_buffer_flag_t = tjob_t::output_buffer_flag_t;
         bool success = this->doPrepareParticlesStructures( particles_buffer );
 
         if( success )
@@ -1656,7 +2429,6 @@ namespace SIXTRL_CXX_NAMESPACE
             if( ( success ) && ( output_buffer != nullptr ) &&
                 ( !this->hasOutputBuffer() ) )
             {
-                /* ( !this->ownsOutputBuffer() ) */
                 this->doSetPtrCOutputBuffer( output_buffer );
             }
         }
@@ -1664,13 +2436,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobBase::doAssignNewOutputBuffer(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer )
+    bool tjob_t::doAssignNewOutputBuffer(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer )
     {
         bool success = false;
-        using flags_t = _this_t::output_buffer_flag_t;
-
-        flags_t const flags =
+        tjob_t::output_buffer_flag_t const flags =
         ::NS(OutputBuffer_required_for_tracking_of_particle_sets)(
             this->ptrCParticlesBuffer(), this->numParticleSets(),
                 this->particleSetIndicesBegin(),
@@ -1711,15 +2481,336 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
+    st_size_t tjob_t::doAddStoredBuffer(
+        tjob_t::buffer_store_t&& buffer_store_handle )
+    {
+        st_size_t buffer_index = st::ARCH_MIN_USER_DEFINED_BUFFER_ID +
+            this->m_stored_buffers.size();
+
+        tjob_t::c_buffer_t* ptr_cbuffer_null = nullptr;
+
+        if( buffer_store_handle.active() )
+        {
+            ++this->m_num_stored_buffers;
+        }
+
+        this->m_stored_buffers.emplace_back( ptr_cbuffer_null, false );
+        this->m_stored_buffers.back() = std::move( buffer_store_handle );
+
+        return buffer_index;
+    }
+
+    st_status_t tjob_t::doRemoveStoredBuffer(
+        st_size_t const buffer_index )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_size_t const min_buffer_id = this->min_stored_buffer_id();
+        st_size_t const max_buffer_id_plus_one =
+            min_buffer_id + this->m_stored_buffers.size();
+
+        if( ( min_buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_index != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_index >= min_buffer_id ) &&
+            ( buffer_index < max_buffer_id_plus_one ) )
+        {
+            st_size_t const ii = buffer_index - min_buffer_id;
+
+            if( this->m_stored_buffers[ ii ].active() )
+            {
+                SIXTRL_ASSERT( this->m_num_stored_buffers > st_size_t{ 0 } );
+                this->m_stored_buffers[ ii ].clear();
+                --this->m_num_stored_buffers;
+            }
+
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::doPushStoredBuffer(
+        st_size_t const buffer_id )
+    {
+        tjob_t::buffer_store_t const* ptr_stored_buffer =
+            this->doGetPtrBufferStore( buffer_id );
+
+        return ( ptr_stored_buffer != nullptr )
+            ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    st_status_t tjob_t::doCollectStoredBuffer(
+        st_size_t const buffer_id )
+    {
+        tjob_t::buffer_store_t const* ptr_stored_buffer =
+            this->doGetPtrBufferStore( buffer_id );
+
+        return ( ptr_stored_buffer != nullptr )
+            ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    st_status_t tjob_t::doAddAssignAddressItem(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF assign_item,
+        st_size_t* SIXTRL_RESTRICT ptr_item_index )
+    {
+        using size_t = st_size_t;
+        using buffer_t = tjob_t::buffer_t;
+        using key_t = tjob_t::assign_item_key_t;
+
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        size_t item_index = std::numeric_limits< size_t >::max();
+
+        if( assign_item.valid() )
+        {
+            key_t const key = key_t{ assign_item.getDestBufferId(),
+                                     assign_item.getSrcBufferId() };
+
+            auto it = this->m_assign_address_items.find( key );
+
+            if( it == this->m_assign_address_items.end() )
+            {
+                auto cmp_key_fn = []( key_t const& SIXTRL_RESTRICT_REF lhs,
+                                      key_t const& SIXTRL_RESTRICT_REF rhs )
+                {
+                    return ( ( lhs.dest_buffer_id < rhs.dest_buffer_id ) ||
+                             ( ( lhs.dest_buffer_id == rhs.dest_buffer_id ) &&
+                               ( lhs.src_buffer_id < rhs.src_buffer_id ) ) );
+                };
+
+                SIXTRL_ASSERT( std::is_sorted( this->m_assign_item_keys.begin(),
+                    this->m_assign_item_keys.end(), cmp_key_fn ) );
+
+                SIXTRL_ASSERT( !std::binary_search(
+                    this->m_assign_item_keys.begin(),
+                    this->m_assign_item_keys.end(), key, cmp_key_fn ) );
+
+                SIXTRL_ASSERT( this->m_assign_address_items.size() ==
+                               this->m_assign_item_keys.size() );
+
+                bool const keys_need_sorting = !(
+                    ( this->m_assign_item_keys.empty() ) ||
+                    ( cmp_key_fn( this->m_assign_item_keys.back(), key ) ) );
+
+                this->m_assign_item_keys.push_back( key );
+
+                if( keys_need_sorting )
+                {
+                    std::sort( this->m_assign_item_keys.begin(),
+                               this->m_assign_item_keys.end(), cmp_key_fn );
+                }
+
+                buffer_t buffer;
+
+                auto ret = this->m_assign_address_items.emplace(
+                    std::make_pair( key, std::move( buffer ) ) );
+
+                if( ret.second )
+                {
+                    buffer_t& buffer = ret.first->second;
+                    SIXTRL_ASSERT( buffer.getNumObjects() == size_t{ 0 } );
+
+                    item_index = buffer.getNumObjects();
+
+                    ::NS(AssignAddressItem)* item =
+                        ::NS(AssignAddressItem_add_copy)( buffer.getCApiPtr(),
+                            assign_item.getCApiPtr() );
+
+                    if( ( item != nullptr ) &&
+                        ( buffer.getNumObjects() > item_index ) )
+                    {
+                        status = st::ARCH_STATUS_SUCCESS;
+                    }
+                }
+            }
+            else
+            {
+                item_index = this->doFindAssingAddressItem( assign_item );
+
+                if( item_index < it->second.getNumObjects() )
+                {
+                    status = st::ARCH_STATUS_SUCCESS;
+                }
+                else
+                {
+                    item_index = it->second.getNumObjects();
+
+                    ::NS(AssignAddressItem)* item =
+                        ::NS(AssignAddressItem_add_copy)(
+                            it->second.getCApiPtr(), assign_item.getCApiPtr() );
+
+                    if( ( item != nullptr ) &&
+                        ( item_index < it->second.getNumObjects() ) )
+                    {
+                        status = st::ARCH_STATUS_SUCCESS;
+                    }
+                }
+            }
+
+            if( ( status == st::ARCH_STATUS_SUCCESS ) &&
+                ( ptr_item_index != nullptr ) )
+            {
+                *ptr_item_index = item_index;
+            }
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::doRemoveAssignAddressItem(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+        st_size_t const index_of_item_to_remove )
+    {
+        using size_t = st_size_t;
+        using item_t = tjob_t::assign_item_t;
+        using key_t  = tjob_t::assign_item_key_t;
+
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        auto it = this->m_assign_address_items.find( key );
+
+        auto cmp_key_fn = []( key_t const& SIXTRL_RESTRICT_REF lhs,
+                              key_t const& SIXTRL_RESTRICT_REF rhs )
+        {
+            return ( ( lhs.dest_buffer_id < rhs.dest_buffer_id ) ||
+                     ( ( lhs.dest_buffer_id == rhs.dest_buffer_id ) &&
+                       ( lhs.src_buffer_id < rhs.src_buffer_id ) ) );
+        };
+
+        SIXTRL_ASSERT( std::is_sorted( this->m_assign_item_keys.begin(),
+                this->m_assign_item_keys.end(), cmp_key_fn ) );
+
+        if( ( it != this->m_assign_address_items.end() ) &&
+            ( it->second.getNumObjects() > index_of_item_to_remove ) )
+        {
+            buffer_t& current_buffer = it->second;
+            buffer_t new_buffer( current_buffer.getNumObjects(),
+                                 current_buffer.getNumSlots(),
+                                 current_buffer.getNumDataptrs(),
+                                 current_buffer.getNumGarbageRanges(),
+                                 current_buffer.getFlags() );
+
+            size_t const nn = current_buffer.getNumObjects();
+            status = st::ARCH_STATUS_SUCCESS;
+
+            SIXTRL_ASSERT( std::binary_search( this->m_assign_item_keys.begin(),
+                this->m_assign_item_keys.end(), key, cmp_key_fn ) );
+
+            SIXTRL_ASSERT( this->m_assign_address_items.size() ==
+                           this->m_assign_item_keys.size() );
+
+            for( size_t ii = size_t{ 0 } ; ii < nn ; ++ii )
+            {
+                if( ii == index_of_item_to_remove ) continue;
+                item_t const* in_item = current_buffer.get< item_t >( ii );
+
+                if( in_item == nullptr )
+                {
+                    status = st::ARCH_STATUS_GENERAL_FAILURE;
+                    break;
+                }
+
+                ::NS(AssignAddressItem)* copied_item =
+                    ::NS(AssignAddressItem_add_copy)(
+                        current_buffer.getCApiPtr(), in_item->getCApiPtr() );
+
+                if( copied_item == nullptr )
+                {
+                    status = st::ARCH_STATUS_GENERAL_FAILURE;
+                    break;
+                }
+            }
+
+            if( status == st::ARCH_STATUS_SUCCESS )
+            {
+                using std::swap;
+                swap( it->second, new_buffer );
+            }
+        }
+
+        if( status == st::ARCH_STATUS_SUCCESS )
+        {
+            it = this->m_assign_address_items.find( key );
+
+            if( it->second.getNumObjects() == size_t{ 0 } )
+            {
+                this->m_assign_address_items.erase( key );
+
+                auto key_it = std::lower_bound(
+                    this->m_assign_item_keys.begin(),
+                    this->m_assign_item_keys.end(), key, cmp_key_fn );
+
+                SIXTRL_ASSERT( key_it != this->m_assign_item_keys.end() );
+                this->m_assign_item_keys.erase( key_it );
+            }
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::doPerformAddressAssignments(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key )
+    {
+        using size_t = st_size_t;
+        using c_buffer_t = tjob_t::c_buffer_t;
+
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        size_t const dest_buffer_id = key.dest_buffer_id;
+        c_buffer_t* dest_buffer = this->buffer_by_buffer_id( dest_buffer_id );
+
+        size_t const src_buffer_id = key.src_buffer_id;
+        c_buffer_t const* src_buffer =
+            this->buffer_by_buffer_id( src_buffer_id );
+
+        auto it = this->m_assign_address_items.find( key );
+
+        if( ( it != this->m_assign_address_items.end() ) &&
+            ( dest_buffer != nullptr ) && ( src_buffer != nullptr ) )
+        {
+            unsigned char* dest_buffer_begin =
+            ::NS(Buffer_get_data_begin)( dest_buffer );
+
+            unsigned char const* src_buffer_begin =
+                ::NS(Buffer_get_const_data_begin)( src_buffer );
+
+            size_t const dest_slot_size =
+                ( this->is_buffer_by_buffer_id( dest_buffer_id ) )
+                    ? ::NS(Buffer_get_slot_size)( dest_buffer ) : size_t{ 0 };
+
+            size_t const src_slot_size =
+                ( this->is_buffer_by_buffer_id( src_buffer_id ) )
+                    ? ::NS(Buffer_get_slot_size)( src_buffer ) : size_t{ 0 };
+
+            SIXTRL_ASSERT( dest_buffer_begin != nullptr );
+            SIXTRL_ASSERT( src_buffer_begin  != nullptr );
+
+            status = ::NS(AssignAddressItem_perform_address_assignment_kernel_impl)(
+                it->second.dataBegin< unsigned char const* >(),
+                it->second.getSlotSize(), size_t{ 0 }, size_t{ 1 },
+                dest_buffer_begin, dest_slot_size, dest_buffer_id,
+                src_buffer_begin, src_slot_size, src_buffer_id );
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::doRebuildAssignItemsBufferArg()
+    {
+        return st::ARCH_STATUS_SUCCESS;
+    }
+
+    st_status_t tjob_t::doCommitAddressAssignments()
+    {
+        return st::ARCH_STATUS_SUCCESS;
+    }
+
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBase::doParseConfigStr(
+    void tjob_t::doParseConfigStr(
         const char *const SIXTRL_RESTRICT config_str )
     {
         this->doParseConfigStrBaseImpl( config_str );
     }
 
-    void TrackJobBase::doSetDeviceIdStr(
+    void tjob_t::doSetDeviceIdStr(
         const char *const SIXTRL_RESTRICT device_id_str )
     {
         if( device_id_str != nullptr )
@@ -1732,7 +2823,7 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    void TrackJobBase::doSetConfigStr(
+    void tjob_t::doSetConfigStr(
         const char *const SIXTRL_RESTRICT config_str )
     {
         if( config_str != nullptr )
@@ -1745,8 +2836,8 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    void TrackJobBase::doSetPtrParticleBuffer(
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrParticleBuffer(
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ptr_buffer != nullptr )
         {
@@ -1762,8 +2853,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_particles_buffer = ptr_buffer;
     }
 
-    void TrackJobBase::doSetPtrCParticleBuffer(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrCParticleBuffer(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ( this->m_ptr_particles_buffer   != nullptr ) &&
             ( this->m_ptr_c_particles_buffer ==
@@ -1776,8 +2867,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_c_particles_buffer = ptr_buffer;
     }
 
-    void TrackJobBase::doSetPtrBeamElementsBuffer(
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrBeamElementsBuffer(
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ptr_buffer != nullptr )
         {
@@ -1793,8 +2884,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_beam_elem_buffer = ptr_buffer;
     }
 
-    void TrackJobBase::doSetPtrCBeamElementsBuffer(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrCBeamElementsBuffer(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ( this->m_ptr_beam_elem_buffer != nullptr ) &&
             ( this->m_ptr_c_beam_elem_buffer ==
@@ -1807,8 +2898,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_c_beam_elem_buffer = ptr_buffer;
     }
 
-    void TrackJobBase::doSetPtrOutputBuffer(
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrOutputBuffer(
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ptr_buffer != nullptr )
         {
@@ -1824,8 +2915,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_output_buffer = ptr_buffer;
     }
 
-    void TrackJobBase::doSetPtrCOutputBuffer(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrCOutputBuffer(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ( this->m_ptr_output_buffer != nullptr ) &&
             ( this->m_ptr_c_output_buffer ==
@@ -1838,113 +2929,290 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_c_output_buffer = ptr_buffer;
     }
 
-    void TrackJobBase::doSetBeamMonitorOutputBufferOffset(
-        _size_t const output_buffer_offset ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetBeamMonitorOutputBufferOffset(
+        st_size_t const output_buffer_offset ) SIXTRL_NOEXCEPT
     {
         this->m_be_mon_output_buffer_offset = output_buffer_offset;
     }
 
-    void TrackJobBase::doSetUntilTurnElemByElem(
-        _this_t::particle_index_t const
+    void tjob_t::doSetUntilTurnElemByElem( tjob_t::particle_index_t const
             until_turn_elem_by_elem ) SIXTRL_NOEXCEPT
     {
         this->m_until_turn_elem_by_elem = until_turn_elem_by_elem;
     }
 
-    void TrackJobBase::doSetElemByElemOutputIndexOffset(
-        _size_t const elem_by_elem_output_offset ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetElemByElemOutputIndexOffset(
+        st_size_t const elem_by_elem_output_offset ) SIXTRL_NOEXCEPT
     {
         this->m_elem_by_elem_output_offset = elem_by_elem_output_offset;
     }
 
-    void TrackJobBase::doSetRequiresCollectFlag(
+    void tjob_t::doSetRequiresCollectFlag(
         bool const requires_collect_flag ) SIXTRL_NOEXCEPT
     {
         this->m_requires_collect = requires_collect_flag;
     }
 
-    void TrackJobBase::doSetBeamMonitorOutputEnabledFlag(
+    void tjob_t::doSetBeamMonitorOutputEnabledFlag(
         bool const has_beam_monitor_output ) SIXTRL_NOEXCEPT
     {
         this->m_has_beam_monitor_output = has_beam_monitor_output;
     }
 
-    void TrackJobBase::doSetElemByElemOutputEnabledFlag(
+    void tjob_t::doSetElemByElemOutputEnabledFlag(
         bool const elem_by_elem_flag ) SIXTRL_NOEXCEPT
     {
         this->m_has_elem_by_elem_output = elem_by_elem_flag;
     }
 
-    void TrackJobBase::doInitDefaultParticleSetIndices()
+    void tjob_t::doInitDefaultParticleSetIndices()
     {
         this->m_particle_set_indices.clear();
-        this->m_particle_set_indices.push_back( _size_t{ 0 } );
+        this->m_particle_set_indices.push_back( st_size_t{ 0 } );
 
         this->m_num_particles_in_sets.clear();
-        this->m_num_particles_in_sets.push_back( _size_t{ 0 } );
+        this->m_num_particles_in_sets.push_back( st_size_t{ 0 } );
     }
 
-    void TrackJobBase::doInitDefaultBeamMonitorIndices()
+    void tjob_t::doInitDefaultBeamMonitorIndices()
     {
         this->m_beam_monitor_indices.clear();
     }
 
-    void TrackJobBase::doSetMinParticleId(
-        _this_t::particle_index_t const min_particle_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMinParticleId(
+        tjob_t::particle_index_t const min_particle_id ) SIXTRL_NOEXCEPT
     {
         this->m_min_particle_id = min_particle_id;
     }
 
-    void TrackJobBase::doSetMaxParticleId(
-        _this_t::particle_index_t const max_particle_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMaxParticleId(
+        tjob_t::particle_index_t const max_particle_id ) SIXTRL_NOEXCEPT
     {
         this->m_max_particle_id = max_particle_id;
     }
 
-    void TrackJobBase::doSetMinElementId(
-        _this_t::particle_index_t const min_element_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMinElementId(
+        tjob_t::particle_index_t const min_element_id ) SIXTRL_NOEXCEPT
     {
         this->m_min_element_id = min_element_id;
     }
 
-    void TrackJobBase::doSetMaxElementId(
-        _this_t::particle_index_t const max_element_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMaxElementId(
+        tjob_t::particle_index_t const max_element_id ) SIXTRL_NOEXCEPT
     {
         this->m_max_element_id = max_element_id;
     }
 
-    void TrackJobBase::doSetMinInitialTurnId(
-        _this_t::particle_index_t const min_turn_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMinInitialTurnId(
+        tjob_t::particle_index_t const min_turn_id ) SIXTRL_NOEXCEPT
     {
         this->m_min_initial_turn_id = min_turn_id;
     }
 
-    void TrackJobBase::doSetMaxInitialTurnId(
-        _this_t::particle_index_t const max_turn_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMaxInitialTurnId(
+        tjob_t::particle_index_t const max_turn_id ) SIXTRL_NOEXCEPT
     {
         this->m_max_initial_turn_id = max_turn_id;
     }
 
-    void TrackJobBase::doUpdateStoredOutputBuffer(
-        _this_t::ptr_output_buffer_t&& ptr_output_buffer ) SIXTRL_NOEXCEPT
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::buffer_t const*
+    tjob_t::doGetPtrParticlesAddrBuffer() const SIXTRL_NOEXCEPT
+    {
+        return this->m_particles_addr_buffer.get();
+    }
+
+    tjob_t::buffer_t*
+    tjob_t::doGetPtrParticlesAddrBuffer() SIXTRL_NOEXCEPT
+    {
+        return this->m_particles_addr_buffer.get();
+    }
+
+    void tjob_t::doUpdateStoredParticlesAddrBuffer(
+        tjob_t::ptr_buffer_t&& ptr_buffer ) SIXTRL_NOEXCEPT
+    {
+        this->m_particles_addr_buffer = std::move( ptr_buffer );
+    }
+
+    void tjob_t::doSetHasParticleAddressesFlag(
+            bool const has_particle_addresses ) SIXTRL_NOEXCEPT
+    {
+        this->m_has_particle_addresses = has_particle_addresses;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    void tjob_t::doUpdateStoredOutputBuffer(
+        tjob_t::ptr_buffer_t&& ptr_output_buffer ) SIXTRL_NOEXCEPT
     {
         this->doSetPtrOutputBuffer( ptr_output_buffer.get() );
         this->m_my_output_buffer = std::move( ptr_output_buffer );
     }
 
-    void TrackJobBase::doUpdateStoredElemByElemConfig(
-        _this_t::ptr_elem_by_elem_config_t&& ptr_config ) SIXTRL_NOEXCEPT
+    void tjob_t::doUpdateStoredElemByElemConfig(
+        tjob_t::ptr_buffer_t&& ptr_elem_by_elem_buffer ) SIXTRL_NOEXCEPT
+    {
+        this->m_elem_by_elem_buffer = std::move( ptr_elem_by_elem_buffer );
+    }
+
+    tjob_t::buffer_store_t* tjob_t::doGetPtrBufferStore(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::buffer_store_t* >( static_cast<
+            tjob_t const& >( *this ).doGetPtrBufferStore( buffer_id ) );
+    }
+
+    tjob_t::buffer_store_t const* tjob_t::doGetPtrBufferStore(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::buffer_store_t const* ptr_buffer_store = nullptr;
+
+        st_size_t const min_buffer_id = this->min_stored_buffer_id();
+        st_size_t const max_buffer_id_plus_one =
+            min_buffer_id + this->m_stored_buffers.size();
+
+        if( ( min_buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_id >= min_buffer_id ) &&
+            ( buffer_id <  max_buffer_id_plus_one ) )
+        {
+            SIXTRL_ASSERT( this->doGetStoredBufferSize() >=
+                           this->m_num_stored_buffers );
+
+            ptr_buffer_store = &this->m_stored_buffers[
+                buffer_id - min_buffer_id ];
+        }
+
+        return ptr_buffer_store;
+    }
+
+    st_size_t
+    tjob_t::doGetStoredBufferSize() const SIXTRL_NOEXCEPT
+    {
+        return this->m_stored_buffers.size();
+    }
+
+    st_size_t tjob_t::doFindAssingAddressItem(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF
+            item_to_search ) const SIXTRL_NOEXCEPT
+    {
+        using size_t = st_size_t;
+        using item_t = tjob_t::assign_item_t;
+        using key_t  = tjob_t::assign_item_key_t;
+
+        size_t index = std::numeric_limits< size_t >::max();
+
+        key_t const key = key_t{ item_to_search.getDestBufferId(),
+                                 item_to_search.getSrcBufferId() };
+
+        auto it = this->m_assign_address_items.find( key );
+
+        SIXTRL_ASSERT( this->m_assign_address_items.size() ==
+                       this->m_assign_item_keys.size() );
+
+        if( it != this->m_assign_address_items.end() )
+        {
+            auto cmp_key_fn = []( key_t const& SIXTRL_RESTRICT_REF lhs,
+                                  key_t const& SIXTRL_RESTRICT_REF rhs )
+            {
+                return ( ( lhs.dest_buffer_id < rhs.dest_buffer_id ) ||
+                         ( ( lhs.dest_buffer_id == rhs.dest_buffer_id ) &&
+                           ( lhs.src_buffer_id < rhs.src_buffer_id ) ) );
+            };
+
+            SIXTRL_ASSERT( std::is_sorted( this->m_assign_item_keys.begin(),
+                this->m_assign_item_keys.end(), cmp_key_fn ) );
+
+            SIXTRL_ASSERT( std::binary_search( this->m_assign_item_keys.begin(),
+                this->m_assign_item_keys.end(), key, cmp_key_fn ) );
+
+            ( void )cmp_key_fn;
+
+            size_t const nn = it->second.getNumObjects();
+            ::NS(AssignAddressItem) const* ptr_item_to_search =
+                item_to_search.getCApiPtr();
+
+            for( size_t ii = size_t{ 0 } ; ii < nn ; ++ii )
+            {
+                tjob_t::assign_item_t const* item =
+                    it->second.get< item_t >( ii );
+
+                if( ( item != nullptr ) &&
+                    ( ::NS(AssignAddressItem_are_equal)(
+                        item->getCApiPtr(), ptr_item_to_search ) ) )
+                {
+                    index = ii;
+                    break;
+                }
+            }
+
+            if( index > nn ) index = nn;
+        }
+
+        return index;
+    }
+
+    tjob_t::assign_item_t const* tjob_t::doGetAssignAddressItem(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+        st_size_t const item_index ) const SIXTRL_NOEXCEPT
+    {
+        using item_t = tjob_t::assign_item_t;
+        item_t const* ptr_found_item = nullptr;
+
+        auto it = this->m_assign_address_items.find( key );
+
+        if( ( it != this->m_assign_address_items.end() ) &&
+            ( it->second.getNumObjects() > item_index ) )
+        {
+            ptr_found_item = it->second.get< item_t >( item_index );
+        }
+
+        return ptr_found_item;
+    }
+
+    tjob_t::assign_item_t* tjob_t::doGetAssignAddressItem(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+        st_size_t const item_index ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = tjob_t::assign_item_t*;
+        return const_cast< ptr_t >( static_cast< tjob_t const& >(
+            *this ).doGetAssignAddressItem( key, item_index ) );
+    }
+
+    tjob_t::c_buffer_t* tjob_t::doGetPtrAssignAddressItemsBuffer(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF
+            key ) SIXTRL_NOEXCEPT
     {
-        this->m_my_elem_by_elem_config = std::move( ptr_config );
+        tjob_t::c_buffer_t* ptr_assign_address_items_buffer = nullptr;
+        auto it = this->m_assign_address_items.find( key );
+
+        if( it != this->m_assign_address_items.end() )
+        {
+            ptr_assign_address_items_buffer = it->second.getCApiPtr();
+        }
+
+        return ptr_assign_address_items_buffer;
     }
 
-    void TrackJobBase::doClearBaseImpl() SIXTRL_NOEXCEPT
+    void tjob_t::doClearBaseImpl() SIXTRL_NOEXCEPT
     {
         this->doInitDefaultParticleSetIndices();
         this->doInitDefaultBeamMonitorIndices();
 
+
         this->m_my_output_buffer.reset( nullptr );
-        this->m_my_elem_by_elem_config.reset( nullptr );
+        this->m_stored_buffers.clear();
+        this->m_assign_address_items.clear();
+
+        this->m_elem_by_elem_buffer.reset( nullptr );
+        this->m_particles_addr_buffer.reset( nullptr );
+
+        if( this->doGetPtrParticlesAddrBuffer() != nullptr )
+        {
+            this->doGetPtrParticlesAddrBuffer()->clear( true );
+            this->doGetPtrParticlesAddrBuffer()->reset();
+        }
 
         this->m_ptr_particles_buffer         = nullptr;
         this->m_ptr_beam_elem_buffer         = nullptr;
@@ -1954,9 +3222,10 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_c_beam_elem_buffer       = nullptr;
         this->m_ptr_c_output_buffer          = nullptr;
 
-        this->m_be_mon_output_buffer_offset  = _size_t{ 0 };
-        this->m_elem_by_elem_output_offset   = _size_t{ 0 };
+        this->m_be_mon_output_buffer_offset  = st_size_t{ 0 };
+        this->m_elem_by_elem_output_offset   = st_size_t{ 0 };
         this->m_default_elem_by_elem_order   = ::NS(ELEM_BY_ELEM_ORDER_DEFAULT);
+        this->m_num_stored_buffers           = st_size_t{ 0 };
 
         ::NS(Particles_init_min_max_attributes_for_find)(
             &this->m_min_particle_id, &this->m_max_particle_id,
@@ -1964,14 +3233,16 @@ namespace SIXTRL_CXX_NAMESPACE
             &this->m_min_initial_turn_id,
             &this->m_max_initial_turn_id );
 
-        this->m_until_turn_elem_by_elem      = _size_t{ 0 };
+        this->m_until_turn_elem_by_elem      = st_size_t{ 0 };
 
         this->m_default_elem_by_elem_rolling = true;
         this->m_has_beam_monitor_output      = false;
         this->m_has_elem_by_elem_output      = false;
+
+        this->doSetHasParticleAddressesFlag( false );
     }
 
-    void TrackJobBase::doParseConfigStrBaseImpl(
+    void tjob_t::doParseConfigStrBaseImpl(
         const char *const SIXTRL_RESTRICT config_str )
     {
         ( void )config_str;
@@ -1979,4 +3250,3 @@ namespace SIXTRL_CXX_NAMESPACE
 }
 
 #endif /* defined( __cplusplus ) */
-/* end: sixtracklib/common/internal/track_job_base.cpp */
diff --git a/sixtracklib/common/internal/track_job_base.h b/sixtracklib/common/internal/track_job_base.h
index 694de2ce..9d65727c 100644
--- a/sixtracklib/common/internal/track_job_base.h
+++ b/sixtracklib/common/internal/track_job_base.h
@@ -7,6 +7,7 @@
         #include <cstddef>
         #include <cstdint>
         #include <cstdlib>
+        #include <map>
         #include <memory>
         #include <string>
         #include <vector>
@@ -24,38 +25,50 @@
 
     #if defined( __cplusplus )
         #include "sixtracklib/common/buffer.hpp"
+        #include "sixtracklib/common/particles/particles_addr.hpp"
     #endif /* defined( __cplusplus ) */
 
     #include "sixtracklib/common/buffer.h"
+    #include "sixtracklib/common/buffer/assign_address_item.hpp"
     #include "sixtracklib/common/particles.h"
+    #include "sixtracklib/common/particles/particles_addr.h"
     #include "sixtracklib/common/output/output_buffer.h"
     #include "sixtracklib/common/output/elem_by_elem_config.h"
+    #include "sixtracklib/common/track/track_job_buffer_store.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
-#if defined( __cplusplus ) && !defined( _GPUCODE )
-
+#if defined( __cplusplus )
 namespace SIXTRL_CXX_NAMESPACE
 {
     class TrackJobBase
     {
         public:
 
-        using buffer_t              = Buffer;
-        using c_buffer_t            = ::NS(Buffer);
-        using elem_by_elem_config_t = ::NS(ElemByElemConfig);
-        using elem_by_elem_order_t  = ::NS(elem_by_elem_order_t);
-        using particle_index_t      = ::NS(particle_index_t);
-        using size_type             = SIXTRL_CXX_NAMESPACE::track_job_size_t;
-        using type_t                = SIXTRL_CXX_NAMESPACE::track_job_type_t;
-        using track_status_t        = SIXTRL_CXX_NAMESPACE::track_status_t;
-        using status_t              = SIXTRL_CXX_NAMESPACE::arch_status_t;
-        using output_buffer_flag_t  = ::NS(output_buffer_flag_t);
+        using buffer_t               = SIXTRL_CXX_NAMESPACE::Buffer;
+        using c_buffer_t             = ::NS(Buffer);
+        using elem_by_elem_config_t  = ::NS(ElemByElemConfig);
+        using elem_by_elem_order_t   = ::NS(elem_by_elem_order_t);
+        using particle_index_t       = ::NS(particle_index_t);
+        using size_type              = SIXTRL_CXX_NAMESPACE::track_job_size_t;
+        using type_t                 = SIXTRL_CXX_NAMESPACE::track_job_type_t;
+        using track_status_t         = SIXTRL_CXX_NAMESPACE::track_status_t;
+        using status_t               = SIXTRL_CXX_NAMESPACE::arch_status_t;
+        using assign_item_t          = SIXTRL_CXX_NAMESPACE::AssignAddressItem;
+        using assign_item_key_t      = ::NS(TrackJobDestSrcBufferIds);
+        using output_buffer_flag_t   = ::NS(output_buffer_flag_t);
+        using object_type_id_t       = ::NS(object_type_id_t);
+        using particles_addr_t       = ::NS(ParticlesAddr);
 
         using collect_flag_t = SIXTRL_CXX_NAMESPACE::track_job_collect_flag_t;
         using push_flag_t    = SIXTRL_CXX_NAMESPACE::track_job_push_flag_t;
 
         /* ----------------------------------------------------------------- */
 
+        static constexpr size_type ILLEGAL_BUFFER_ID =
+                    SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_BUFFER_ID;
+
+        /* ----------------------------------------------------------------- */
+
         SIXTRL_HOST_FN static bool IsCollectFlagSet(
             collect_flag_t const haystack,
             collect_flag_t const needle ) SIXTRL_NOEXCEPT;
@@ -81,6 +94,7 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN void collectParticles();
         SIXTRL_HOST_FN void collectBeamElements();
         SIXTRL_HOST_FN void collectOutput();
+        SIXTRL_HOST_FN status_t collectParticlesAddresses();
 
         SIXTRL_HOST_FN void enableCollectParticles()  SIXTRL_NOEXCEPT;
         SIXTRL_HOST_FN void disableCollectParticles() SIXTRL_NOEXCEPT;
@@ -106,6 +120,35 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN void pushParticles();
         SIXTRL_HOST_FN void pushBeamElements();
         SIXTRL_HOST_FN void pushOutput();
+        SIXTRL_HOST_FN void pushParticlesAddresses();
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN bool canFetchParticleAddresses() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool hasParticleAddresses() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t fetchParticleAddresses();
+
+        SIXTRL_HOST_FN status_t clearParticleAddresses(
+            size_type const index = size_type{ 0 } );
+
+        SIXTRL_HOST_FN status_t clearAllParticleAddresses();
+
+        SIXTRL_HOST_FN particles_addr_t const* particleAddresses(
+            size_type const index = size_type{ 0 } ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t const*
+        ptrParticleAddressesBuffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t const*
+        ptrCParticleAddressesBuffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t*
+            ptrParticleAddressesBuffer() SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t*
+            ptrCParticleAddressesBuffer() SIXTRL_NOEXCEPT;
 
         /* ----------------------------------------------------------------- */
 
@@ -193,7 +236,7 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN std::string const& typeStr()     const SIXTRL_NOEXCEPT;
         SIXTRL_HOST_FN char const* ptrTypeStr()         const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN bool hasDeviceIdStr()            const SIXTRL_RESTRICT;
+        SIXTRL_HOST_FN bool hasDeviceIdStr()            const SIXTRL_NOEXCEPT;
         SIXTRL_HOST_FN std::string const& deviceIdStr() const SIXTRL_NOEXCEPT;
         SIXTRL_HOST_FN char const* ptrDeviceIdStr()     const SIXTRL_NOEXCEPT;
 
@@ -258,6 +301,197 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN c_buffer_t const*
         ptrCBeamElementsBuffer() const SIXTRL_NOEXCEPT;
 
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN bool can_fetch_particles_addr() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN bool has_particles_addr() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t fetch_particles_addr();
+        SIXTRL_HOST_FN status_t clear_all_particles_addr();
+        SIXTRL_HOST_FN status_t clear_particles_addr(
+            size_type const index = size_type{ 0 } );
+
+        SIXTRL_HOST_FN particles_addr_t const* particles_addr(
+            size_type const index = size_type{ 0 } ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t const*
+        ptr_particles_addr_buffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t const*
+        ptr_particles_addr_cbuffer() const SIXTRL_NOEXCEPT;
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN assign_item_t* add_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF assign_item_to_add );
+
+        SIXTRL_HOST_FN assign_item_t* add_assign_address_item(
+            object_type_id_t const dest_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_index,
+            size_type const dest_pointer_offset,
+            object_type_id_t const src_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_index,
+            size_type const src_pointer_offset );
+
+        SIXTRL_HOST_FN status_t remove_assign_address_item(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+            size_type const index_of_item_to_remove );
+
+        SIXTRL_HOST_FN status_t remove_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF item_to_remove );
+
+        SIXTRL_HOST_FN bool has_assign_address_item( assign_item_t const&
+            SIXTRL_RESTRICT_REF assign_item ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool has_assign_address_item(
+            object_type_id_t const dest_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_index,
+            size_type const dest_pointer_offset,
+            object_type_id_t const src_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_index,
+            size_type const src_pointer_offset ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type index_of_assign_address_item(
+            object_type_id_t const dest_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_index,
+            size_type const dest_pointer_offset,
+            object_type_id_t const src_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_index,
+            size_type const src_pointer_offset ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type index_of_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF
+                assign_item ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool has_assign_items(
+            size_type const dest_buffer_id,
+            size_type const src_buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type num_assign_items(
+            size_type const dest_buffer_id,
+            size_type const src_buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type total_num_assign_items() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t const* ptr_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF
+                assign_address_item ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t const* ptr_assign_address_item(
+            size_type const dest_buffer_id,  size_type const src_buffer_id,
+            size_type const assign_item_index ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t const* ptr_assign_address_item(
+            object_type_id_t const dest_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_index,
+            size_type const dest_pointer_offset,
+            object_type_id_t const src_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_index,
+            size_type const src_pointer_offset ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            num_distinct_available_assign_address_items_dest_src_pairs() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type available_assign_address_items_dest_src_pairs(
+            size_type const max_num_pairs,
+            assign_item_key_t* pairs_begin ) const SIXTRL_NOEXCEPT;
+
+        template< typename PairIter >
+        SIXTRL_HOST_FN size_type available_assign_address_items_dest_src_pairs(
+            PairIter pairs_begin, PairIter pairs_end ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t* buffer_by_buffer_id(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t const* buffer_by_buffer_id(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool is_buffer_by_buffer_id(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool is_raw_memory_by_buffer_id(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*
+        assign_items_begin( size_type const dest_buffer_id,
+            size_type const src_buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*
+        assign_items_end( size_type const dest_buffer_id,
+            size_type const src_buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_key_t const*
+        assign_item_dest_src_begin() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_key_t const*
+        assign_item_dest_src_end() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t commit_address_assignments();
+
+        SIXTRL_HOST_FN status_t assign_all_addresses();
+        SIXTRL_HOST_FN status_t assign_addresses(
+            size_type const dest_buffer_id, size_type const src_buffer_id );
+
+        /* ---------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN size_type
+        stored_buffers_capacity() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t reserve_stored_buffers_capacity(
+            size_type const capacity );
+
+        SIXTRL_HOST_FN bool has_stored_buffers() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            num_stored_buffers() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            min_stored_buffer_id() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            max_stored_buffer_id() const SIXTRL_NOEXCEPT;
+
+        template< typename... Args >
+        SIXTRL_HOST_FN size_type add_stored_buffer( Args&&... args );
+
+        SIXTRL_HOST_FN bool owns_stored_buffer(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t remove_stored_buffer(
+            size_type const buffer_index );
+
+        SIXTRL_HOST_FN buffer_t& stored_cxx_buffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN buffer_t const& stored_cxx_buffer(
+            size_type const buffer_id ) const;
+
+        SIXTRL_HOST_FN buffer_t* ptr_stored_cxx_buffer(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t const* ptr_stored_cxx_buffer(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t* ptr_stored_buffer(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t const* ptr_stored_buffer(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t push_stored_buffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t collect_stored_buffer(
+            size_type const buffer_id );
+
         /* ---------------------------------------------------------------- */
 
         SIXTRL_HOST_FN bool hasOutputBuffer()      const SIXTRL_NOEXCEPT;
@@ -276,13 +510,13 @@ namespace SIXTRL_CXX_NAMESPACE
 
         SIXTRL_HOST_FN size_type numElemByElemTurns() const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN buffer_t* ptrOutputBuffer() SIXTRL_RESTRICT;
-        SIXTRL_HOST_FN buffer_t* ptrOutputBuffer() const SIXTRL_RESTRICT;
+        SIXTRL_HOST_FN buffer_t* ptrOutputBuffer() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN buffer_t const* ptrOutputBuffer() const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN c_buffer_t* ptrCOutputBuffer() SIXTRL_RESTRICT;
+        SIXTRL_HOST_FN c_buffer_t* ptrCOutputBuffer() SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN c_buffer_t const*
-        ptrCOutputBuffer() const SIXTRL_RESTRICT;
+            ptrCOutputBuffer() const SIXTRL_NOEXCEPT;
 
         /* ----------------------------------------------------------------- */
 
@@ -301,6 +535,17 @@ namespace SIXTRL_CXX_NAMESPACE
 
         SIXTRL_HOST_FN bool hasElemByElemConfig() const SIXTRL_NOEXCEPT;
 
+        SIXTRL_HOST_FN c_buffer_t const*
+        ptrElemByElemConfigCBuffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t*
+        ptrElemByElemConfigCBuffer() SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t const*
+        ptrElemByElemConfigBuffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t* ptrElemByElemConfigBuffer() SIXTRL_NOEXCEPT;
+
         SIXTRL_HOST_FN elem_by_elem_config_t const*
         ptrElemByElemConfig() const SIXTRL_NOEXCEPT;
 
@@ -328,11 +573,16 @@ namespace SIXTRL_CXX_NAMESPACE
 
         protected:
 
-        using ptr_output_buffer_t =
-            std::unique_ptr< buffer_t >;
+        using ptr_buffer_t   = std::unique_ptr< buffer_t >;
+        using buffer_store_t = TrackJobBufferStore;
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_STATIC SIXTRL_HOST_FN void COPY_PTR_BUFFER(
+            ptr_buffer_t& SIXTRL_RESTRICT_REF dest_ptr_buffer,
+            ptr_buffer_t const& SIXTRL_RESTRICT_REF src_ptr_buffer );
 
-        using ptr_elem_by_elem_config_t =
-            std::unique_ptr< elem_by_elem_config_t >;
+        /* ----------------------------------------------------------------- */
 
         SIXTRL_HOST_FN static collect_flag_t UnsetCollectFlag(
             collect_flag_t const haystack,
@@ -390,8 +640,42 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN virtual bool doAssignNewOutputBuffer(
             c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer );
 
+        SIXTRL_HOST_FN virtual size_type doAddStoredBuffer(
+            buffer_store_t&& assigned_buffer_handle );
+
+        SIXTRL_HOST_FN virtual status_t doRemoveStoredBuffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN virtual status_t doPushStoredBuffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN virtual status_t doCollectStoredBuffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN virtual status_t doAddAssignAddressItem(
+            assign_item_t const& SIXTRL_RESTRICT_REF assign_item,
+            size_type* SIXTRL_RESTRICT ptr_item_index );
+
+        SIXTRL_HOST_FN virtual status_t doRemoveAssignAddressItem(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF assign_item_key,
+            size_type const index_of_item_to_remove );
+
+        SIXTRL_HOST_FN virtual status_t doPerformAddressAssignments(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF assign_item_key );
+
+        SIXTRL_HOST_FN virtual status_t doCommitAddressAssignments();
+
+        SIXTRL_HOST_FN virtual status_t doRebuildAssignItemsBufferArg();
+
         /* ----------------------------------------------------------------- */
 
+        SIXTRL_HOST_FN virtual status_t doFetchParticleAddresses();
+
+        SIXTRL_HOST_FN virtual status_t doClearParticleAddresses(
+            size_type const index );
+
+        SIXTRL_HOST_FN virtual status_t doClearAllParticleAddresses();
+
         SIXTRL_HOST_FN virtual track_status_t doTrackUntilTurn(
             size_type const until_turn );
 
@@ -479,29 +763,80 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN void doSetMaxInitialTurnId(
             particle_index_t const max_initial_turn_id ) SIXTRL_NOEXCEPT;
 
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN buffer_t const*
+        doGetPtrParticlesAddrBuffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t* doGetPtrParticlesAddrBuffer() SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN void doUpdateStoredParticlesAddrBuffer(
+            ptr_buffer_t&& ptr_buffer ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN void doSetHasParticleAddressesFlag(
+            bool const has_particle_addresses ) SIXTRL_NOEXCEPT;
+
+        /* ----------------------------------------------------------------- */
+
         SIXTRL_HOST_FN void doUpdateStoredOutputBuffer(
-            ptr_output_buffer_t&& ptr_output_buffer ) SIXTRL_NOEXCEPT;
+            ptr_buffer_t&& ptr_output_buffer ) SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN void doUpdateStoredElemByElemConfig(
-            ptr_elem_by_elem_config_t&& ptr_config ) SIXTRL_NOEXCEPT;
+            ptr_buffer_t&& ptr_config ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_store_t* doGetPtrBufferStore(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_store_t const* doGetPtrBufferStore(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type doGetStoredBufferSize() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type doFindAssingAddressItem( assign_item_t const&
+            SIXTRL_RESTRICT_REF item_to_search ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t const* doGetAssignAddressItem(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+            size_type const item_index ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t* doGetAssignAddressItem(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+            size_type const item_index ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t* doGetPtrAssignAddressItemsBuffer(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF key ) SIXTRL_NOEXCEPT;
+
 
         private:
 
+        using assing_item_map_t = std::map< assign_item_key_t, buffer_t,
+            SIXTRL_CXX_NAMESPACE::TrackJobDestSrcBufferIdsLessCmp >;
+        using assign_item_keys_list_t = std::vector< assign_item_key_t >;
+
         SIXTRL_HOST_FN void doClearBaseImpl() SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN void doParseConfigStrBaseImpl(
             const char *const SIXTRL_RESTRICT config_str );
 
+        SIXTRL_HOST_FN status_t doClearParticleAddressesBaseImpl(
+            size_type const index );
+
+        SIXTRL_HOST_FN status_t doClearAllParticleAddressesBaseImpl();
+
         std::string                     m_type_str;
         std::string                     m_device_id_str;
         std::string                     m_config_str;
 
+        assing_item_map_t               m_assign_address_items;
         std::vector< size_type >        m_particle_set_indices;
         std::vector< size_type >        m_num_particles_in_sets;
         std::vector< size_type >        m_beam_monitor_indices;
+        std::vector< buffer_store_t >   m_stored_buffers;
+        assign_item_keys_list_t         m_assign_item_keys;
 
-        ptr_output_buffer_t             m_my_output_buffer;
-        ptr_elem_by_elem_config_t       m_my_elem_by_elem_config;
+        ptr_buffer_t                    m_my_output_buffer;
+        ptr_buffer_t                    m_elem_by_elem_buffer;
+        ptr_buffer_t                    m_particles_addr_buffer;
 
         buffer_t*   SIXTRL_RESTRICT     m_ptr_particles_buffer;
         buffer_t*   SIXTRL_RESTRICT     m_ptr_beam_elem_buffer;
@@ -514,6 +849,7 @@ namespace SIXTRL_CXX_NAMESPACE
         size_type                       m_be_mon_output_buffer_offset;
         size_type                       m_elem_by_elem_output_offset;
         size_type                       m_total_num_particles_in_sets;
+        size_type                       m_num_stored_buffers;
 
         type_t                          m_type_id;
         elem_by_elem_order_t            m_default_elem_by_elem_order;
@@ -533,6 +869,7 @@ namespace SIXTRL_CXX_NAMESPACE
         bool                            m_default_elem_by_elem_rolling;
         bool                            m_has_beam_monitor_output;
         bool                            m_has_elem_by_elem_output;
+        bool                            m_has_particle_addresses;
         bool                            m_debug_mode;
     };
 }
@@ -642,6 +979,54 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
+    template< typename... Args >
+    TrackJobBase::size_type TrackJobBase::add_stored_buffer( Args&&... args )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using _this_t = st::TrackJobBase;
+
+        _this_t::buffer_store_t temp_buffer_store(
+            std::forward< Args >( args )... );
+
+        _this_t::size_type const buffer_id =
+            this->doAddStoredBuffer( std::move( temp_buffer_store ) );
+
+        return buffer_id;
+    }
+
+    template< typename PairIter >
+    SIXTRL_HOST_FN TrackJobBase::size_type
+    TrackJobBase::available_assign_address_items_dest_src_pairs(
+        PairIter out_it, PairIter out_end ) const SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using _this_t = st::TrackJobBase;
+        using size_t = _this_t::size_type;
+        size_t num_pairs = size_t{ 0 };
+
+        if( !this->m_assign_address_items.empty() )
+        {
+            SIXTRL_ASSERT( this->m_assign_address_items.size() ==
+                           this->m_assign_item_keys.size() );
+
+            auto it = this->m_assign_item_keys.begin();
+            auto end = this->m_assign_item_keys.end();
+
+            while( ( out_it != out_end ) && ( it != end ) )
+            {
+                *out_it = *it;
+                ++num_pairs;
+                ++out_it;
+                ++it;
+            }
+        }
+
+        std::fill( out_it, out_end, _this_t::assign_item_key_t{
+            _this_t::ILLEGAL_BUFFER_ID, _this_t::ILLEGAL_BUFFER_ID } );
+
+        return num_pairs;
+    }
+
     template< typename ParSetIndexIter >
     SIXTRL_HOST_FN void TrackJobBase::doSetParticleSetIndices(
         ParSetIndexIter begin, ParSetIndexIter end,
diff --git a/sixtracklib/common/internal/track_job_cpu.cpp b/sixtracklib/common/internal/track_job_cpu.cpp
index e1007089..d60e040b 100644
--- a/sixtracklib/common/internal/track_job_cpu.cpp
+++ b/sixtracklib/common/internal/track_job_cpu.cpp
@@ -289,6 +289,21 @@ namespace SIXTRL_CXX_NAMESPACE
 
     TrackJobCpu::~TrackJobCpu() SIXTRL_NOEXCEPT {}
 
+    TrackJobCpu::status_t TrackJobCpu::doFetchParticleAddresses()
+    {
+        TrackJobCpu::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        TrackJobCpu::buffer_t* ptr_addr_buffer =
+            this->doGetPtrParticlesAddrBuffer();
+
+        if( ptr_addr_buffer != nullptr )
+        {
+            status = ::NS(ParticlesAddr_buffer_store_all_addresses)(
+                ptr_addr_buffer->getCApiPtr(), this->ptrCParticlesBuffer() );
+        }
+
+        return status;
+    }
+
     TrackJobCpu::track_status_t TrackJobCpu::doTrackUntilTurn(
         TrackJobCpu::size_type const until_turn )
     {
@@ -383,6 +398,14 @@ namespace SIXTRL_CXX_NAMESPACE
             size_t const slot_size  = ::NS(Buffer_get_slot_size)(
                     job.ptrCParticlesBuffer() );
 
+            _this_t::c_buffer_t* elem_by_elem_config_buffer =
+                job.buffer_by_buffer_id( st::ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID );
+
+            unsigned char* elem_by_elem_config_buffer_begin =
+                ::NS(Buffer_get_data_begin)( elem_by_elem_config_buffer );
+
+            size_t const elem_by_elem_config_index = size_t{ 0 };
+
             if( job.numParticleSets() == size_t{ 1 } )
             {
                 SIXTRL_ASSERT( job.particleSetIndicesBegin() != nullptr );
@@ -391,7 +414,9 @@ namespace SIXTRL_CXX_NAMESPACE
                     ::NS(Buffer_get_data_begin)( job.ptrCParticlesBuffer() ),
                     *job.particleSetIndicesBegin(), pindex_t{ 0 }, pindex_t{ 1 },
                     ::NS(Buffer_get_data_begin)( job.ptrCBeamElementsBuffer() ),
-                    job.ptrElemByElemConfig(), _until_turn_num, slot_size );
+                        elem_by_elem_config_buffer_begin,
+                            elem_by_elem_config_index, _until_turn_num,
+                                slot_size );
             }
             else if( job.numParticleSets() > size_t{ 1 } )
             {
@@ -413,7 +438,9 @@ namespace SIXTRL_CXX_NAMESPACE
                         *pset_it, pindex_t{ 0 }, pindex_t{ 1 },
                         ::NS(Buffer_get_data_begin)(
                             job.ptrCBeamElementsBuffer() ),
-                        job.ptrElemByElemConfig(), _until_turn_num, slot_size );
+                                elem_by_elem_config_buffer_begin,
+                                    elem_by_elem_config_index,
+                                        _until_turn_num, slot_size );
                 }
             }
         }
@@ -457,7 +484,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             for( ; pset_it != pset_end ; ++pset_it )
             {
-                status |= status = NS(Track_particles_line_kernel_impl)(
+                status |= NS(Track_particles_line_kernel_impl)(
                 ::NS(Buffer_get_data_begin)( job.ptrCParticlesBuffer() ),
                 *pset_it, pindex_t{ 0 }, pindex_t{ 1 },
                 ::NS(Buffer_get_data_begin)( job.ptrCBeamElementsBuffer() ),
diff --git a/sixtracklib/common/internal/type_comparison_helpers.hpp b/sixtracklib/common/internal/type_comparison_helpers.hpp
new file mode 100644
index 00000000..0f192782
--- /dev/null
+++ b/sixtracklib/common/internal/type_comparison_helpers.hpp
@@ -0,0 +1,971 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_TYPE_COMPARISON_HELPERS_CXX_HPP__
+#define SIXTRACKLIB_COMMON_INTERNAL_TYPE_COMPARISON_HELPERS_CXX_HPP__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #if defined( __cplusplus )
+        #include <cstdlib>
+        #include <iterator>
+        #include <limits>
+        #include <type_traits>
+    #else /* C++ */
+        #include <stdint.h>
+        #include <limits.h>
+        #include <stdbool.h>
+    #endif /* C++ */
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
+    #include "sixtracklib/common/control/definitions.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus )
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/internal/type_store_traits.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename T >
+    struct TypeCompLogicTypeTraits
+    {
+        typedef bool logic_t;
+        typedef int  cmp_result_t;
+    };
+
+    /* ********************************************************************** */
+
+    template< class E >
+    struct ObjDataLogicTypeTraits
+    {
+        typedef int cmp_result_t;
+        typedef bool logic_t;
+    };
+
+    template< typename CmpResultT >
+    struct TypeCompResultTraits
+    {
+        static_assert(
+            std::numeric_limits< CmpResultT >::min() < CmpResultT{ 0 } &&
+            std::numeric_limits< CmpResultT >::max() > CmpResultT{ 0 },
+            "CmpResultT unsuitable for use as a value comparison result type" );
+
+        static constexpr CmpResultT CMP_LHS_EQUAL_RHS =
+            CmpResultT{ 0 };
+
+        static constexpr CmpResultT CMP_LHS_LARGER_RHS =
+            std::numeric_limits< CmpResultT >::max();
+
+        static constexpr CmpResultT CMP_LHS_SMALLER_RHS =
+            std::numeric_limits< CmpResultT >::min();
+    };
+
+    template< typename CmpResultT >
+    constexpr CmpResultT TypeCompResultTraits< CmpResultT >::CMP_LHS_EQUAL_RHS;
+
+    template< typename CmpResultT >
+    constexpr CmpResultT TypeCompResultTraits< CmpResultT >::CMP_LHS_LARGER_RHS;
+
+    template< typename CmpResultT >
+    constexpr CmpResultT TypeCompResultTraits< CmpResultT >::CMP_LHS_SMALLER_RHS;
+
+    /* ********************************************************************** */
+
+    template< class Logic >
+    struct TypeCompLogicOps
+    {
+        typedef typename TypeMethodParamTraits< Logic >::argument_type
+                logic_arg_t;
+
+        static SIXTRL_FN bool any( logic_arg_t expr ) SIXTRL_NOEXCEPT
+        {
+            return ( expr ) ? true : false;
+        }
+
+        static SIXTRL_FN bool all( logic_arg_t expr ) SIXTRL_NOEXCEPT
+        {
+            return ( expr ) ? true : false;
+        }
+    };
+
+    /* Specialization */
+
+    template<> struct TypeCompLogicOps< bool >
+    {
+        typedef bool const logic_arg_t;
+
+        static SIXTRL_INLINE SIXTRL_FN bool any(
+            logic_arg_t expr ) SIXTRL_NOEXCEPT
+        {
+            return expr;
+        }
+
+        static SIXTRL_INLINE SIXTRL_FN bool all(
+            logic_arg_t expr ) SIXTRL_NOEXCEPT
+        {
+            return expr;
+        }
+    };
+
+    template< typename T >
+    SIXTRL_STATIC SIXTRL_INLINE bool Type_comp_all(
+        typename TypeMethodParamTraits< typename TypeCompLogicTypeTraits<
+            T >::logic_t >::argument_type expression ) SIXTRL_NOEXCEPT
+    {
+        typedef typename TypeCompLogicTypeTraits< T >::logic_t logic_t;
+        return TypeCompLogicOps< logic_t >::all( expression );
+    }
+
+    template< typename T >
+    static SIXTRL_FN bool Type_comp_any(
+        typename TypeMethodParamTraits< typename TypeCompLogicTypeTraits<
+            T >::logic_t >::argument_type expression ) SIXTRL_NOEXCEPT
+    {
+        typedef typename TypeCompLogicTypeTraits< T >::logic_t logic_t;
+        return TypeCompLogicOps< logic_t >::any( expression );
+    }
+
+    /* ********************************************************************** */
+
+    template< typename T >
+    static SIXTRL_FN constexpr bool
+    TypeComp_consitent_logic_type() SIXTRL_NOEXCEPT
+    {
+        /* The type T and its associated logic_t type have to share the same
+         * behaviour with respect to being a scalar
+         *
+         * TODO: Expand this to enforce cardinality -> i.e. a vector valued
+         *       type neeeds a vector valued logic_t with the same dimensions,
+         *       etc. */
+
+        return
+            ( ( SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >() ) &&
+              ( SIXTRL_CXX_NAMESPACE::Type_is_scalar<
+                    typename TypeCompLogicTypeTraits< T >::logic_t >() )
+            ) ||
+            ( ( !SIXTRL_CXX_NAMESPACE::Type_is_scalar< T >() ) &&
+              ( !SIXTRL_CXX_NAMESPACE::Type_is_scalar<
+                    typename TypeCompLogicTypeTraits< T >::logic_t >() ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeCompLogicTypeTraits< LhsT >::logic_t Type_comp_less(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        typedef typename TypeCompLogicTypeTraits< LhsT >::logic_t logic_t;
+        static_assert(
+            SIXTRL_CXX_NAMESPACE::TypeComp_consitent_logic_type< LhsT >(),
+            "base type LhsT and logic type are inconsistent" );
+
+        return static_cast< logic_t >( lhs < rhs );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeCompLogicTypeTraits< LhsT >::logic_t Type_comp_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        typedef typename TypeCompLogicTypeTraits< LhsT >::logic_t logic_t;
+        static_assert(
+            SIXTRL_CXX_NAMESPACE::TypeComp_consitent_logic_type< LhsT >(),
+            "base type LhsT and logic type are inconsistent" );
+
+        return static_cast< logic_t >( lhs == rhs );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeCompLogicTypeTraits< LhsT >::logic_t Type_comp_less_or_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        typedef typename TypeCompLogicTypeTraits< LhsT >::logic_t logic_t;
+        static_assert(
+            SIXTRL_CXX_NAMESPACE::TypeComp_consitent_logic_type< LhsT >(),
+            "base type LhsT and logic type are inconsistent" );
+
+        return static_cast< logic_t >( ( lhs < rhs ) || ( lhs == rhs ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeCompLogicTypeTraits< LhsT >::logic_t
+    Type_comp_more(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return !st::Type_comp_less_or_equal< LhsT, RhsT >( lhs, rhs );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeCompLogicTypeTraits< LhsT >::logic_t
+    Type_comp_more_or_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return !SIXTRL_CXX_NAMESPACE::Type_comp_less< LhsT, RhsT >( lhs, rhs );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeCompLogicTypeTraits< LhsT >::logic_t
+    Type_comp_not_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return !st::Type_comp_equal< LhsT, RhsT >( lhs, rhs );
+    }
+
+    /* ====================================================================== */
+
+    template< typename LhsT, typename RhsT = LhsT >
+    static SIXTRL_FN bool Type_comp_all_less(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::Type_comp_all< LhsT >(
+            SIXTRL_CXX_NAMESPACE::Type_comp_less< LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_any_less(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::Type_comp_any< LhsT >(
+            SIXTRL_CXX_NAMESPACE::Type_comp_less< LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_all_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::Type_comp_all< LhsT >(
+            SIXTRL_CXX_NAMESPACE::Type_comp_equal< LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_any_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::Type_comp_any< LhsT >(
+            SIXTRL_CXX_NAMESPACE::Type_comp_equal< LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_all_less_or_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return st::Type_comp_all< LhsT >( st::Type_comp_less_or_equal<
+            LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_any_less_or_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return st::Type_comp_any< LhsT >( st::Type_comp_less_or_equal<
+                LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_all_more(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return st::Type_comp_all< LhsT >( st::Type_comp_more<
+            LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_any_more(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return st::Type_comp_any< LhsT >( st::Type_comp_more<
+            LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_all_more_or_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::Type_comp_all< LhsT >(
+            SIXTRL_CXX_NAMESPACE::Type_comp_more_or_equal<
+                LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_any_more_or_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::Type_comp_any< LhsT >(
+            SIXTRL_CXX_NAMESPACE::Type_comp_more_or_equal<
+                LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_all_not_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::Type_comp_all< LhsT >(
+            SIXTRL_CXX_NAMESPACE::Type_comp_not_equal<
+                LhsT, RhsT >( lhs, rhs ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_any_not_equal(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs
+    ) SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::Type_comp_any< LhsT >(
+            SIXTRL_CXX_NAMESPACE::Type_comp_not_equal< LhsT, RhsT >(
+                lhs, rhs ) );
+    }
+}
+#endif /* defined( __cplusplus ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/internal/math_functions.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus )
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename TypeCompLogicTypeTraits< LhsT >::logic_t
+    Type_comp_is_close(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rel_tol,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type abs_tol )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        typedef typename TypeMethodParamTraits< LhsT >::value_type lhs_t;
+        typedef typename TypeMethodParamTraits< RhsT >::value_type rhs_t;
+
+        lhs_t diff = lhs;
+        diff -= rhs;
+        diff  = st::abs< lhs_t >( diff );
+
+        rhs_t cmp_value = st::abs< rhs_t >( rhs );
+        cmp_value *= rel_tol;
+        cmp_value += abs_tol;
+
+        return st::Type_comp_less_or_equal< lhs_t >( diff, cmp_value );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_all_are_close(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rel_tol,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type abs_tol
+    ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return st::Type_comp_all< LhsT >( st::Type_comp_is_close< LhsT, RhsT >(
+                lhs, rhs, rel_tol, abs_tol ) );
+    }
+
+    template< typename LhsT, typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN bool Type_comp_any_are_close(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rel_tol,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type abs_tol
+    ) SIXTRL_NOEXCEPT
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        return st::Type_comp_any< LhsT >( st::Type_comp_is_close< LhsT, RhsT >(
+                lhs, rhs, rel_tol, abs_tol ) );
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    template< typename LhsT, typename CmpResultT = typename
+                    TypeCompLogicTypeTraits< LhsT >::cmp_result_t,
+              typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN CmpResultT Type_value_comp_result(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        typedef CmpResultT result_t;
+        typedef TypeCompResultTraits< result_t > cmp_traits_t;
+
+        result_t cmp_result = cmp_traits_t::CMP_LHS_SMALLER_RHS;
+
+        if( st::Type_comp_all_equal< LhsT, RhsT >( rhs, lhs ) )
+        {
+            cmp_result = cmp_traits_t::CMP_LHS_EQUAL_RHS;
+        }
+        else if( st::Type_comp_any_more< LhsT, RhsT >( rhs, lhs ) )
+        {
+            cmp_result = cmp_traits_t::CMP_LHS_LARGER_RHS;
+        }
+
+        return cmp_result;
+    }
+
+    template< typename LhsT, typename CmpResultT = typename
+                TypeCompLogicTypeTraits< LhsT >::cmp_result_t,
+              typename RhsT = LhsT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN CmpResultT Type_value_comp_result(
+        typename TypeMethodParamTraits< LhsT >::const_argument_type lhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rhs,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type rel_tol,
+        typename TypeMethodParamTraits< RhsT >::const_argument_type abs_tol )
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        typedef CmpResultT result_t;
+        typedef TypeCompResultTraits< result_t > cmp_traits_t;
+
+        result_t cmp_result = cmp_traits_t::CMP_LHS_SMALLER_RHS;
+
+        if( st::Type_comp_all_are_close< LhsT, RhsT >(
+                rhs, lhs, rel_tol, abs_tol ) )
+        {
+            cmp_result = cmp_traits_t::CMP_LHS_EQUAL_RHS;
+        }
+        else if( st::Type_comp_any_more< LhsT, RhsT >( rhs, lhs ) )
+        {
+            cmp_result = cmp_traits_t::CMP_LHS_LARGER_RHS;
+        }
+
+        return cmp_result;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    template< typename LhsIter, typename CmpResultT = typename
+                TypeCompLogicTypeTraits< typename std::iterator_traits< LhsIter
+                    >::value_type >::cmp_result_t,
+              typename RhsIter = LhsIter >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN CmpResultT
+    Type_value_comp_result_for_range( LhsIter lhs_it, LhsIter lhs_end,
+                                      RhsIter rhs_it )
+    {
+        typedef CmpResultT result_t;
+        typedef TypeCompResultTraits< result_t > cmp_traits_t;
+        typedef typename std::iterator_traits< LhsIter >::value_type lhs_value_t;
+        typedef typename std::iterator_traits< RhsIter >::value_type rhs_value_t;
+
+        result_t cmp_result = cmp_traits_t::CMP_LHS_EQUAL_RHS;
+
+        while( ( cmp_result == cmp_traits_t::CMP_LHS_EQUAL_RHS ) &&
+               ( lhs_it != lhs_end ) )
+        {
+            cmp_result = SIXTRL_CXX_NAMESPACE::Type_value_comp_result<
+                lhs_value_t, result_t, rhs_value_t >( *lhs_it, *rhs_it );
+            ++lhs_it;
+            ++rhs_it;
+        }
+
+        return cmp_result;
+    }
+
+    template< typename LhsIter, typename CmpResultT = typename
+                TypeCompLogicTypeTraits< typename std::iterator_traits< LhsIter
+                    >::value_type >::cmp_result_t,
+              typename RhsIter = LhsIter >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN CmpResultT
+    Type_value_comp_result_for_range(
+        LhsIter lhs_it, LhsIter lhs_end, RhsIter rhs_it,
+        typename TypeMethodParamTraits< typename std::iterator_traits<
+            RhsIter >::value_type >::const_argument_type rel_tol,
+        typename TypeMethodParamTraits< typename std::iterator_traits<
+            RhsIter >::value_type >::const_argument_type abs_tol )
+    {
+        typedef CmpResultT result_t;
+        typedef TypeCompResultTraits< result_t > cmp_traits_t;
+        typedef typename std::iterator_traits< LhsIter >::value_type lhs_value_t;
+        typedef typename std::iterator_traits< RhsIter >::value_type rhs_value_t;
+
+        result_t cmp_result = cmp_traits_t::CMP_LHS_EQUAL_RHS;
+
+        while( ( cmp_result == cmp_traits_t::CMP_LHS_EQUAL_RHS ) &&
+               ( lhs_it != lhs_end ) )
+        {
+            cmp_result = SIXTRL_CXX_NAMESPACE::Type_value_comp_result<
+                lhs_value_t, rhs_value_t >( *lhs_it, *rhs_it, rel_tol, abs_tol );
+            ++lhs_it;
+            ++rhs_it;
+        }
+
+        return cmp_result;
+    }
+
+    /* ===================================================================== */
+
+    template< class LhsT, class RhsT = LhsT, typename CmpResultT =
+                    typename ObjDataLogicTypeTraits< LhsT >::cmp_result_t,
+              typename SFINAE_Enabled = void >
+    struct ObjDataComparisonHelper
+    {
+        SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN CmpResultT compare(
+            SIXTRL_ARGPTR_DEC const LhsT *const
+                SIXTRL_RESTRICT SIXTRL_UNUSED( lhs ),
+            SIXTRL_ARGPTR_DEC const RhsT *const
+                SIXTRL_RESTRICT SIXTRL_UNUSED( rhs ) ) SIXTRL_NOEXCEPT
+        {
+            return TypeCompResultTraits< CmpResultT >::CMP_LHS_SMALLER_RHS;
+        }
+
+        template< typename... Args >
+        SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+        CmpResultT compare_with_tolerances(
+            SIXTRL_ARGPTR_DEC const LhsT *const
+                SIXTRL_RESTRICT SIXTRL_UNUSED( lhs ),
+            SIXTRL_ARGPTR_DEC const RhsT *const
+                SIXTRL_RESTRICT SIXTRL_UNUSED( rhs ),
+            Args&&... SIXTRL_UNUSED( tolerances ) ) SIXTRL_NOEXCEPT
+        {
+            return TypeCompResultTraits< CmpResultT >::CMP_LHS_SMALLER_RHS;
+        }
+    };
+
+    template< class LhsT, class RhsT, class DiffT,
+              typename SFINAE_Enable = void >
+    struct ObjDataDiffHelper
+    {
+        SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN arch_status_t calculate(
+            SIXTRL_ARGPTR_DEC DiffT* SIXTRL_RESTRICT SIXTRL_UNUSED( diff ),
+            SIXTRL_ARGPTR_DEC const LhsT *const SIXTRL_RESTRICT
+                SIXTRL_UNUSED( lhs ),
+            SIXTRL_ARGPTR_DEC const RhsT *const SIXTRL_RESTRICT
+                SIXTRL_UNUSED( rhs ) ) SIXTRL_NOEXCEPT
+        {
+            return SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+        }
+    };
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< class LhsElemT, class RhsElemT >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename ObjDataComparisonHelper< LhsElemT, RhsElemT >::cmp_result_t
+    ObjData_compare( const LhsElemT *const SIXTRL_RESTRICT lhs,
+                     const RhsElemT *const SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
+    {
+        typedef ObjDataComparisonHelper< LhsElemT, RhsElemT > helper_t;
+        return helper_t::compare( lhs, rhs );
+    }
+
+    template< class LhsElemT, class RhsElemT, typename... Args >
+    SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN
+    typename ObjDataComparisonHelper< LhsElemT, RhsElemT >::cmp_result_t
+    ObjData_compare_with_tolerances(
+        const LhsElemT *const SIXTRL_RESTRICT lhs,
+        const RhsElemT *const SIXTRL_RESTRICT rhs,
+        Args&&... tolerances ) SIXTRL_NOEXCEPT
+    {
+        typedef ObjDataComparisonHelper< LhsElemT, RhsElemT > helper_t;
+        return helper_t::compare_with_tolerances(
+            lhs, rhs, std::forward< Args >( tolerances )... );
+    }
+}
+#endif /* C++ */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_less)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_less_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_not_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_more_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_more)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_all_less)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_all_less_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_all_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_all_not_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_all_more_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_all_more)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_any_less)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_any_less_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_any_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_any_not_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_any_more_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_any_more)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_is_close)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_all_are_close)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN bool NS(Type_comp_any_are_close)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT;
+
+/* --------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN int NS(Type_value_comp_result)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(Type_value_comp_result_with_tolerances)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(Type_value_comp_result_for_range)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_it,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_end,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT rhs_it
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int
+NS(Type_value_comp_result_with_tolerances_for_range)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_it,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_end,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT rhs_it,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT;
+
+/* --------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN int NS(Type_value_comp_result_int64)(
+    SIXTRL_INT64_T const lhs, SIXTRL_INT64_T const rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(Type_value_comp_result_int64_for_range)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_INT64_T const* SIXTRL_RESTRICT lhs_it,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_INT64_T const* SIXTRL_RESTRICT lhs_end,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_INT64_T const* SIXTRL_RESTRICT rhs_it
+) SIXTRL_NOEXCEPT;
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_INLINE bool NS(Type_comp_less)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs < rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_less_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs <= rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs == rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_not_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs != rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_more_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs >= rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_more)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs > rhs );
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE bool NS(Type_comp_all_less)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs < rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_all_less_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs <= rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_all_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs == rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_all_not_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs != rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_all_more_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs >= rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_all_more)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs > rhs );
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_INLINE bool NS(Type_comp_any_less)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs < rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_any_less_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs <= rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_any_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs == rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_any_not_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs != rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_any_more_or_equal)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs >= rhs );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_any_more)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs > rhs );
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE bool NS(Type_comp_is_close)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT
+{
+    SIXTRL_REAL_T const diff = ( lhs >= rhs ) ? lhs - rhs : rhs - lhs;
+    SIXTRL_REAL_T cmp_value = ( rhs >= ( SIXTRL_REAL_T )0 ) ? rhs : -rhs;
+    cmp_value *= rel_tol;
+    cmp_value += abs_tol;
+
+    return ( diff <= cmp_value );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_all_are_close)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT
+{
+    return NS(Type_comp_is_close)( lhs, rhs, rel_tol, abs_tol );
+}
+
+SIXTRL_INLINE bool NS(Type_comp_any_are_close)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT
+{
+    return NS(Type_comp_is_close)( lhs, rhs, rel_tol, abs_tol );
+}
+
+/* --------------------------------------------------------------------- */
+
+SIXTRL_INLINE int NS(Type_value_comp_result)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( NS(Type_comp_equal)( lhs, rhs ) )
+        ? 0 : ( ( NS(Type_comp_more)( lhs, rhs ) ) ? +1 : -1 );
+}
+
+SIXTRL_INLINE int NS(Type_value_comp_result_with_tolerances)(
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT
+{
+    return ( NS(Type_comp_is_close)( lhs, rhs, rel_tol, abs_tol ) )
+        ? 0 : ( ( NS(Type_comp_more)( lhs, rhs ) ) ? +1 : -1 );
+}
+
+SIXTRL_INLINE int NS(Type_value_comp_result_for_range)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_it,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_end,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT rhs_it
+) SIXTRL_NOEXCEPT
+{
+    int cmp_result = 0;
+
+    SIXTRL_ASSERT( lhs_it != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs_it != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs_it != SIXTRL_NULLPTR );
+
+    while( ( cmp_result == 0 ) && ( lhs_it != lhs_end ) )
+    {
+        cmp_result = NS(Type_value_comp_result)( *lhs_it++, *rhs_it++ );
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(Type_value_comp_result_with_tolerances_for_range)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_it,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_end,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT rhs_it,
+    SIXTRL_REAL_T const rel_tol, SIXTRL_REAL_T const abs_tol ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = 0;
+
+    SIXTRL_ASSERT( lhs_it != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs_it != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs_it != SIXTRL_NULLPTR );
+
+    while( ( cmp_result == 0 ) && ( lhs_it != lhs_end ) )
+    {
+        cmp_result = NS(Type_value_comp_result_with_tolerances)(
+            *lhs_it++, *rhs_it++, rel_tol, abs_tol );
+    }
+
+    return cmp_result;
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE int NS(Type_value_comp_result_int64)(
+    SIXTRL_INT64_T const lhs, SIXTRL_INT64_T const rhs ) SIXTRL_NOEXCEPT
+{
+    return ( lhs == rhs ) ? 0 : ( lhs > rhs ) ? +1 : -1;
+}
+
+SIXTRL_INLINE int NS(Type_value_comp_result_int64_for_range)(
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_INT64_T const* SIXTRL_RESTRICT lhs_it,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_INT64_T const* SIXTRL_RESTRICT lhs_end,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_INT64_T const* SIXTRL_RESTRICT rhs_it
+) SIXTRL_NOEXCEPT
+{
+    int cmp_result = 0;
+
+    SIXTRL_ASSERT( lhs_it != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs_it != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( rhs_it != SIXTRL_NULLPTR );
+
+    while( ( cmp_result == 0 ) && ( lhs_it != lhs_end ) )
+    {
+        cmp_result = NS(Type_value_comp_result_int64)( *lhs_it++, *rhs_it++ );
+    }
+
+    return cmp_result;
+}
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_TYPE_COMPARISON_HELPERS_CXX_HPP__ */
diff --git a/sixtracklib/common/internal/type_store_traits.hpp b/sixtracklib/common/internal/type_store_traits.hpp
new file mode 100644
index 00000000..57a26dcc
--- /dev/null
+++ b/sixtracklib/common/internal/type_store_traits.hpp
@@ -0,0 +1,625 @@
+#ifndef SIXTRACKLIB_COMMON_INTERNAL_TYPE_STORE_TRAITS_CXX_HPP__
+#define SIXTRACKLIB_COMMON_INTERNAL_TYPE_STORE_TRAITS_CXX_HPP__
+
+#if defined( __cplusplus )
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <cstdlib>
+    #include <limits>
+    #include <stdint.h>
+    #include <type_traits>
+
+    #if !defined( _GPUCODE )
+        #include <iterator>
+        #include <string>
+    #endif /* !defined( _GPUCODE ) */
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template< typename T >
+    struct TypeStoreTraits
+    {
+        typedef T           value_type;
+        typedef T const&    const_reference;
+        typedef T const*    const_pointer;
+        typedef T&          reference;
+        typedef T*          pointer;
+
+        static constexpr bool is_signed = std::numeric_limits< T >::is_signed;
+    };
+
+    template< typename T > constexpr bool TypeStoreTraits< T >::is_signed;
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    struct TypeMethodParamTraits
+    {
+        typedef T           value_type;
+        typedef T const&    argument_type;
+        typedef T const&    const_argument_type;
+        typedef T&          ref_argument_type;
+        typedef T const&    const_existing_type;
+        typedef T&          existing_type;
+        typedef T&          ref_existing_type;
+        typedef T const*    const_pointer;
+        typedef T*          pointer;
+        typedef T&&         rvalue_ref;
+    };
+
+    /* ********************************************************************* */
+
+    template< typename T >
+    struct TypeDimensionalityTraits
+    {
+        static constexpr arch_size_t min_dimension = arch_size_t{ 1 };
+        static constexpr arch_size_t max_dimension = arch_size_t{ 1 };
+    };
+
+    template< typename T >
+    static SIXTRL_FN constexpr bool
+    Type_consistent_dimensionality() SIXTRL_NOEXCEPT
+    {
+        return ( ( TypeDimensionalityTraits< T >::min_dimension >
+                   arch_size_t{ 0 } ) &&
+                 ( TypeDimensionalityTraits< T >::min_dimension <=
+                   TypeDimensionalityTraits< T >::max_dimension ) );
+    }
+
+    template< typename T >
+    static SIXTRL_FN constexpr bool
+    Type_has_fixed_dimensionality() SIXTRL_NOEXCEPT
+    {
+        return (
+            ( SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality< T >() ) &&
+            ( TypeDimensionalityTraits< T >::min_dimension ==
+              TypeDimensionalityTraits< T >::max_dimension ) );
+    }
+
+    template< typename T >
+    static SIXTRL_FN constexpr bool
+    Type_has_variable_dimensionality() SIXTRL_NOEXCEPT
+    {
+        return (
+            ( SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality< T >() ) &&
+            ( TypeDimensionalityTraits< T >::min_dimension !=
+              TypeDimensionalityTraits< T >::max_dimension ) );
+    }
+
+    template< typename T >
+    static SIXTRL_FN constexpr arch_size_t Type_min_dimension() SIXTRL_NOEXCEPT
+    {
+        return TypeDimensionalityTraits< T >::min_dimension;
+    }
+
+    template< typename T >
+    static SIXTRL_FN constexpr arch_size_t Type_max_dimension() SIXTRL_NOEXCEPT
+    {
+        return TypeDimensionalityTraits< T >::max_dimension;
+    }
+
+    template< typename T >
+    static SIXTRL_FN constexpr bool Type_is_scalar() SIXTRL_NOEXCEPT
+    {
+        return (
+            ( SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality< T >() ) &&
+            ( SIXTRL_CXX_NAMESPACE::Type_has_fixed_dimensionality< T >() ) &&
+            ( TypeDimensionalityTraits< T >::min_dimension ==
+              arch_size_t{ 1 } ) );
+    }
+
+    template< typename T >
+    static SIXTRL_FN constexpr bool Type_is_vector_valued() SIXTRL_NOEXCEPT
+    {
+        return (
+            ( SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality<T>() ) &&
+            ( ( SIXTRL_CXX_NAMESPACE::Type_has_variable_dimensionality<T>() ) ||
+              ( TypeDimensionalityTraits< T >::max_dimension >
+                arch_size_t{ 1 } ) ) );
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    template< typename T >
+    struct TypeDimensionalityHelper
+    {
+        static arch_size_t dimension( typename TypeMethodParamTraits< T
+            >::const_pointer SIXTRL_RESTRICT /* ptr */ ) SIXTRL_NOEXCEPT
+        {
+            return
+                ( SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality< T >() )
+                    ? SIXTRL_CXX_NAMESPACE::Type_max_dimension< T >()
+                    : arch_size_t{ 0 };
+        }
+    };
+
+    template< typename T >
+    static SIXTRL_FN typename std::enable_if<
+        !SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality< T >(),
+        arch_size_t >::type
+    Type_dimensionality( typename TypeMethodParamTraits< T >::const_pointer
+            /* ptr */ = nullptr ) SIXTRL_NOEXCEPT
+    {
+        static_assert(
+            SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality< T >(),
+            "Inconsistent dimensionality traits for type T" );
+
+        return arch_size_t{ 0 };
+    }
+
+    template< typename T >
+    static SIXTRL_FN constexpr typename std::enable_if<
+        SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality< T >() &&
+        SIXTRL_CXX_NAMESPACE::Type_has_fixed_dimensionality< T >(),
+        arch_size_t >::type
+    Type_dimensionality( typename TypeMethodParamTraits< T >::const_pointer
+            /* ptr */ = nullptr ) SIXTRL_NOEXCEPT
+    {
+        return TypeDimensionalityTraits< T >::min_dimension;
+    }
+
+    template< typename T >
+    static SIXTRL_FN constexpr typename std::enable_if<
+        SIXTRL_CXX_NAMESPACE::Type_consistent_dimensionality< T >() &&
+        SIXTRL_CXX_NAMESPACE::Type_has_variable_dimensionality< T >(),
+        arch_size_t >::type
+    Type_dimensionality( typename TypeMethodParamTraits< T >::const_pointer
+            ptr = nullptr ) SIXTRL_NOEXCEPT
+    {
+        return TypeDimensionalityHelper< T >::dimension( ptr );
+    }
+
+    /* ********************************************************************* */
+
+    template< typename ArgT, typename BaseType >
+    static SIXTRL_FN constexpr bool Type_arg_type_is_base_type() SIXTRL_NOEXCEPT
+    {
+        return std::is_same< typename std::decay< ArgT >::type, BaseType >();
+    }
+
+    /* ********************************************************************* */
+
+    template< typename T >
+    struct TypeStorageAlignTraits
+    {
+        static SIXTRL_FN constexpr SIXTRL_CXX_NAMESPACE::arch_size_t
+        Alignment() SIXTRL_NOEXCEPT
+        {
+            #if !defined( SIXTRL_ALIGN_NUM )
+                #define SIXTRL_ALIGN_NUM_UNDEF
+                #define SIXTRL_ALIGN_NUM 8
+            #endif /* SIXTRL_ALIGN_NUM  */
+
+            return ( alignof( T ) <= SIXTRL_ALIGN_NUM )
+                ? static_cast< SIXTRL_CXX_NAMESPACE::arch_size_t >(
+                    SIXTRL_ALIGN_NUM )
+                : static_cast< SIXTRL_CXX_NAMESPACE::arch_size_t >(
+                    ( ( alignof( T ) / SIXTRL_ALIGN_NUM ) +
+                      ( ( ( alignof( T ) % SIXTRL_ALIGN_NUM ) == 0u ) ? 0 : 1 )
+                    ) * SIXTRL_ALIGN_NUM );
+
+            #if defined( SIXTRL_ALIGN_NUM_UNDEF )
+                #undef SIXTRL_ALIGN_NUM
+                #undef SIXTRL_ALIGN_NUM_UNDEF
+            #endif  /* defined( SIXTRL_ALIGN_NUM_UNDEF ) */
+        }
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* Convenience functions: */
+
+    template< typename T >
+    static SIXTRL_FN constexpr
+    SIXTRL_CXX_NAMESPACE::arch_size_t Type_storage_align() SIXTRL_NOEXCEPT
+    {
+        return SIXTRL_CXX_NAMESPACE::TypeStorageAlignTraits< T >::Alignment();
+    }
+
+    /* ====================================================================== */
+
+    template< class Source, class Dest >
+    static SIXTRL_FN constexpr bool Types_are_assignable() SIXTRL_NOEXCEPT
+    {
+         return std::is_assignable<
+                 typename std::add_lvalue_reference<
+                     typename std::decay< Dest >::type >::type,
+                 typename std::decay< Source >::type >::value;
+    }
+
+    template< class Source, class Dest >
+    static SIXTRL_FN constexpr bool Types_are_convertible() SIXTRL_NOEXCEPT
+    {
+         return std::is_convertible<
+             typename std::decay< Source >::type,
+             typename std::decay< Dest >::type >::value;
+    }
+
+    template< class Source, class Dest, typename _Enabled = void >
+    struct TypePerformAssignmentHelper
+    {
+        static SIXTRL_FN constexpr bool can_assign() SIXTRL_NOEXCEPT
+        {
+            return false;
+        }
+
+        static SIXTRL_FN constexpr arch_status_t assign(
+            SIXTRL_ARGPTR_DEC typename TypeMethodParamTraits<
+                Dest >::ref_argument_type /*destination*/,
+            SIXTRL_ARGPTR_DEC typename TypeMethodParamTraits<
+                Source >::const_argument_type /*source*/ ) SIXTRL_NOEXCEPT
+        {
+            return SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+        }
+    };
+
+    template< class Source, class Dest >
+    struct TypePerformAssignmentHelper< Source, Dest, typename std::enable_if<
+       SIXTRL_CXX_NAMESPACE::Types_are_assignable< Source, Dest >() >::type >
+    {
+        static SIXTRL_FN constexpr bool can_assign() SIXTRL_NOEXCEPT
+        {
+            return true;
+        }
+
+        static SIXTRL_FN arch_status_t assign(
+            SIXTRL_ARGPTR_DEC typename TypeMethodParamTraits<
+                Dest >::ref_argument_type destination,
+            SIXTRL_ARGPTR_DEC typename TypeMethodParamTraits<
+                Source >::const_argument_type source ) SIXTRL_NOEXCEPT
+        {
+            destination = source;
+            return SIXTRL_CXX_NAMESPACE::ARCH_STATUS_SUCCESS;
+        }
+    };
+
+    template< class Source, class Dest >
+    struct TypePerformAssignmentHelper< Source, Dest, typename std::enable_if<
+       !SIXTRL_CXX_NAMESPACE::Types_are_assignable< Source, Dest >() &&
+        SIXTRL_CXX_NAMESPACE::Types_are_convertible< Source, Dest >() >::type >
+    {
+        static SIXTRL_FN constexpr bool can_assign() SIXTRL_NOEXCEPT
+        {
+            return true;
+        }
+
+        static SIXTRL_FN arch_status_t assign(
+            SIXTRL_ARGPTR_DEC typename TypeMethodParamTraits<
+                Dest >::ref_argument_type destination,
+            SIXTRL_ARGPTR_DEC typename TypeMethodParamTraits<
+                Source >::const_argument_type source ) SIXTRL_NOEXCEPT
+        {
+            destination = source;
+            return SIXTRL_CXX_NAMESPACE::ARCH_STATUS_SUCCESS;
+        }
+    };
+
+    /* ---------------------------------------------------------------------- */
+
+    template< class Source, class Dest >
+    static SIXTRL_FN constexpr bool
+        Types_can_perform_assignment() SIXTRL_NOEXCEPT
+    {
+        return TypePerformAssignmentHelper< Source, Dest >::can_assign();
+    }
+
+    template< class Source, class Dest >
+    static SIXTRL_INLINE SIXTRL_FN arch_status_t Types_perform_assignment(
+        SIXTRL_ARGPTR_DEC typename TypeMethodParamTraits< Dest
+            >::ref_argument_type destination,
+        SIXTRL_ARGPTR_DEC typename TypeMethodParamTraits< Source
+            >::const_argument_type source )
+    {
+        return TypePerformAssignmentHelper< Source, Dest >::assign(
+            destination, source );
+    }
+
+    #if !defined( __CUDACC__ )
+    template< class SrcIter, class DstIter >
+    static SIXTRL_FN arch_status_t Types_perform_assignment_for_range(
+        SrcIter src_it, SrcIter src_end, DstIter dest_it )
+    {
+        typedef typename std::iterator_traits<
+            SrcIter >::value_type src_value_t;
+
+        typedef typename std::iterator_traits<
+            DstIter >::value_type dest_value_t;
+    #else /* Cuda */
+    template< class T >
+    static SIXTRL_FN arch_status_t Types_perform_assignment_for_range(
+        T const* SIXTRL_RESTRICT src_it, T const* SIXTRL_RESTRICT src_end,
+        T* SIXTRL_RESTRICT dest_it )
+    {
+        typedef T src_value_t;
+        typedef T dest_value_t;
+    #endif /* Cuda */
+
+        arch_status_t success = ( src_it != src_end )
+            ? SIXTRL_CXX_NAMESPACE::ARCH_STATUS_SUCCESS
+            : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+
+        for( ; src_it != src_end ; ++src_it, ++dest_it )
+        {
+            success = TypePerformAssignmentHelper<
+                src_value_t, dest_value_t >::assign( *dest_it, *src_it );
+
+            if( success != SIXTRL_CXX_NAMESPACE::ARCH_STATUS_SUCCESS )
+            {
+                break;
+            }
+        }
+
+        return success;
+    }
+
+    template< class SrcIter, class DstIter >
+    static SIXTRL_FN arch_status_t Types_perform_assignment_for_range(
+        SrcIter src_begin, DstIter dest_begin,
+        arch_size_t const num_items_to_assign )
+    {
+        SrcIter src_end = src_begin;
+        #if !defined( __CUDACC__ )
+        std::advance( src_end, num_items_to_assign );
+        #else /* !Cuda */
+        src_end = src_end + num_items_to_assign;
+        #endif /* Cuda */
+
+        return SIXTRL_CXX_NAMESPACE::Types_perform_assignment_for_range(
+            src_begin, src_end, dest_begin );
+    }
+
+    /* ********************************************************************* */
+
+    template< class SrcT, typename DstT >
+    SIXTRL_STATIC SIXTRL_FN constexpr bool
+    Types_same_and_direct_assignable() SIXTRL_NOEXCEPT
+    {
+        return  std::is_same< SrcT, typename TypeMethodParamTraits< typename
+                    std::decay< DstT >::type >::value_type >::value ||
+                std::is_same< SrcT, typename TypeMethodParamTraits< typename
+                    std::decay< DstT >::type >::const_argument_type >::value ||
+                std::is_same< SrcT, typename TypeMethodParamTraits< typename
+                    std::decay< DstT >::type >::ref_argument_type >::value;
+    }
+
+    template< class SrcT, typename DstT >
+    SIXTRL_STATIC SIXTRL_FN constexpr bool
+    Types_same_and_move_assignable() SIXTRL_NOEXCEPT
+    {
+        return !SIXTRL_CXX_NAMESPACE::Types_same_and_direct_assignable<
+                    SrcT, DstT >() &&
+               std::is_same< SrcT, typename TypeMethodParamTraits< typename
+                   std::decay< DstT >::type >::rvalue_ref >::value;
+    }
+
+    template< class SrcT, typename DstT >
+    SIXTRL_STATIC SIXTRL_FN constexpr bool
+    Types_same_allow_arithmetic() SIXTRL_NOEXCEPT
+    {
+        return  SIXTRL_CXX_NAMESPACE::Types_same_and_direct_assignable<
+                    SrcT, DstT >() ||
+                std::is_same< SrcT, typename TypeMethodParamTraits< typename
+                   std::decay< DstT >::type >::rvalue_ref >::value;
+    }
+
+    /* ********************************************************************* */
+    /* Specializations: */
+    /* ********************************************************************* */
+
+    /* --------------------------------------------------------------------- */
+    /* double: */
+
+    template<> struct TypeMethodParamTraits< double >
+    {
+        typedef double                                  value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* float: */
+
+    template<> struct TypeMethodParamTraits< float >
+    {
+        typedef float                                   value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* uint64: */
+
+    template<> struct TypeMethodParamTraits< uint64_t >
+    {
+        typedef uint64_t                                value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* int64: */
+
+    template<> struct TypeMethodParamTraits< int64_t >
+    {
+        typedef int64_t                                 value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* uint32: */
+
+    template<> struct TypeMethodParamTraits< uint32_t >
+    {
+        typedef uint32_t                                value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* int32: */
+
+    template<> struct TypeMethodParamTraits< int32_t >
+    {
+        typedef int32_t                                 value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* uint16_t: */
+
+    template<> struct TypeMethodParamTraits< uint16_t >
+    {
+        typedef uint16_t                                value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* int16_t: */
+
+    template<> struct TypeMethodParamTraits< int16_t >
+    {
+        typedef int16_t                                 value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* uint8_t: */
+
+    template<> struct TypeMethodParamTraits< uint8_t >
+    {
+        typedef uint8_t                                 value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type&                             ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* int8_t: */
+
+    template<> struct TypeMethodParamTraits< int8_t >
+    {
+        typedef int8_t                                  value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    /* --------------------------------------------------------------------- */
+    /* bool: */
+
+    template<> struct TypeMethodParamTraits< bool >
+    {
+        typedef bool                                    value_type;
+        typedef value_type const                        const_argument_type;
+        typedef value_type                              argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type                              const_existing_type;
+        typedef value_type                              existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    #if !defined( _GPUCODE )
+
+    /* --------------------------------------------------------------------- */
+    /* std::string: */
+
+    template<> struct TypeMethodParamTraits< std::string >
+    {
+        typedef std::string                             value_type;
+        typedef value_type  const& SIXTRL_RESTRICT_REF  const_argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         argument_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_argument_type;
+        typedef value_type const& SIXTRL_RESTRICT_REF   const_existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         existing_type;
+        typedef value_type& SIXTRL_RESTRICT_REF         ref_existing_type;
+        typedef value_type const*                       const_pointer;
+        typedef value_type*                             pointer;
+        typedef value_type&&                            rvalue_ref;
+    };
+
+    #endif /* !defined( _GPUCODE ) */
+}
+
+#endif /* defined( __cplusplus ) */
+
+#endif /* SIXTRACKLIB_COMMON_INTERNAL_TYPE_STORE_TRAITS_CXX_HPP__ */
diff --git a/sixtracklib/common/output/CMakeLists.txt b/sixtracklib/common/output/CMakeLists.txt
index 6c1dc0aa..faa1c126 100644
--- a/sixtracklib/common/output/CMakeLists.txt
+++ b/sixtracklib/common/output/CMakeLists.txt
@@ -1,20 +1,13 @@
 # sixtracklib/common/output/CMakeLists.txt
 
-set( SIXTRACKLIB_COMMON_OUTPUT_C99_HEADERS
-     elem_by_elem_config.h elem_by_elem_output_buffer.h
-     elem_by_elem_kernel_impl.h output_buffer.h
-)
+set( SIXTRACKLIB_COMMON_OUTPUT_C99_HEADERS elem_by_elem_config.h
+    elem_by_elem_output_buffer.h elem_by_elem_kernel_impl.h output_buffer.h )
 
-set( SIXTRACKLIB_COMMON_OUTPUT_C99_SOURCES
-     elem_by_elem_config.c
-     elem_by_elem_output_buffer.c
-     output_buffer.c
-)
+set( SIXTRACKLIB_COMMON_OUTPUT_C99_SOURCES elem_by_elem_config.c
+     elem_by_elem_output_buffer.c output_buffer.c )
 
 set( SIXTRACKLIB_COMMON_OUTPUT_CXX_SOURCES )
-set( SIXTRACKLIB_COMMON_OUTPUT_CXX_HEADERS
-     output_buffer.hpp
-)
+set( SIXTRACKLIB_COMMON_OUTPUT_CXX_HEADERS output_buffer.hpp )
 
 # ------------------------------------------------------------------------------
 # build sixtrack_common_output  submodule object library
@@ -31,7 +24,8 @@ set_target_properties( sixtrack_common_output PROPERTIES LINKER_LANGUAGE C
     POSITION_INDEPENDENT_CODE ON C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_output PRIVATE
-                        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_output as a module for sixtracklib:
diff --git a/sixtracklib/common/output/elem_by_elem_config.c b/sixtracklib/common/output/elem_by_elem_config.c
index 1c0230ec..e9a42c4e 100644
--- a/sixtracklib/common/output/elem_by_elem_config.c
+++ b/sixtracklib/common/output/elem_by_elem_config.c
@@ -387,4 +387,26 @@ NS(arch_status_t) NS(ElemByElemConfig_assign_output_buffer_debug)(
         ptr_dbg_register );
 }
 
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig) const*
+NS(ElemByElemConfig_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const elem_by_elem_index )
+{
+    return NS(ElemByElemConfig_const_from_managed_buffer)(
+        NS(Buffer_get_const_data_begin)( buffer ),
+        elem_by_elem_index, NS(Buffer_get_slot_size)( buffer ) );
+}
+
+SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig)*
+NS(ElemByElemConfig_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const elem_by_elem_index )
+{
+    return NS(ElemByElemConfig_from_managed_buffer)(
+        NS(Buffer_get_data_begin)( buffer ),
+        elem_by_elem_index, NS(Buffer_get_slot_size)( buffer ) );
+}
+
 /* end: sixtracklib/common/output/elem_by_elem_config.c */
diff --git a/sixtracklib/common/output/elem_by_elem_config.h b/sixtracklib/common/output/elem_by_elem_config.h
index bcd31893..0396c65d 100644
--- a/sixtracklib/common/output/elem_by_elem_config.h
+++ b/sixtracklib/common/output/elem_by_elem_config.h
@@ -16,6 +16,7 @@
     #include "sixtracklib/common/buffer/buffer_type.h"
     #include "sixtracklib/common/buffer/buffer_object.h"
     #include "sixtracklib/common/internal/elem_by_elem_config_defines.h"
+    #include "sixtracklib/common/internal/objects_type_id.h"
     #include "sixtracklib/common/particles.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
@@ -199,6 +200,28 @@ SIXTRL_STATIC SIXTRL_FN void NS(ElemByElemConfig_set_output_store_address)(
         NS(ElemByElemConfig)* SIXTRL_RESTRICT config,
     NS(elem_by_elem_out_addr_t) const out_address );
 
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig) const*
+NS(ElemByElemConfig_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig)*
+NS(ElemByElemConfig_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig) const*
+NS(ElemByElemConfig_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const elem_by_elem_index,
+    NS(buffer_size_t) const slot_size );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig)*
+NS(ElemByElemConfig_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const elem_by_elem_index,
+    NS(buffer_size_t) const slot_size );
+
 #if !defined( _GPUCODE )
 
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ElemByElemConfig_is_active_ext)(
@@ -444,6 +467,19 @@ NS(ElemByElemConfig_assign_output_buffer_debug)(
     NS(buffer_size_t) const out_buffer_index_offset,
     SIXTRL_ARGPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_dbg_register );
 
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN
+SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig) const*
+NS(ElemByElemConfig_const_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const elem_by_elem_index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig)*
+NS(ElemByElemConfig_from_buffer)(
+    SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const elem_by_elem_index );
+
 #endif /* !defined( _GPUCODE ) */
 
 SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
@@ -466,10 +502,33 @@ NS(ElemByElemConfig_get_stored_num_particles_detailed)(
     NS(particle_index_t) const min_turn_id,
     NS(particle_index_t) const max_elem_by_elem_turn_id );
 
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+#if defined( __cplusplus )
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    template<> struct ObjectTypeTraits< ::NS(ElemByElemConfig) >
+    {
+        SIXTRL_STATIC SIXTRL_INLINE object_type_id_t Type() SIXTRL_NOEXCEPT
+        {
+            return NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF);
+        }
+    };
+}
+
+#endif /* defined( __cplusplus ) */
+
  /* ------------------------------------------------------------------------ */
  /*  Implementation of inline functions: */
  /* ------------------------------------------------------------------------ */
 
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
 SIXTRL_INLINE bool NS(ElemByElemConfig_is_active)(
     SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const
         NS(ElemByElemConfig) *const SIXTRL_RESTRICT config )
@@ -1127,6 +1186,56 @@ SIXTRL_INLINE void NS(ElemByElemConfig_set_output_store_address)(
     return;
 }
 
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig) const*
+NS(ElemByElemConfig_const_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj )
+{
+    typedef SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig) const*
+            ptr_const_elem_by_elem_conf_t;
+
+    ptr_const_elem_by_elem_conf_t ptr = SIXTRL_NULLPTR;
+
+    if( ( obj != SIXTRL_NULLPTR ) &&
+        ( NS(Object_get_type_id)( obj ) == NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF) ) &&
+        ( NS(Object_get_begin_addr)( obj ) != ( NS(buffer_addr_t) )0u ) &&
+        ( NS(Object_get_size)( obj ) >= sizeof( NS(ElemByElemConfig) ) ) )
+    {
+        ptr = ( ptr_const_elem_by_elem_conf_t )( uintptr_t
+            )NS(Object_get_begin_addr)( obj );
+    }
+
+    return ptr;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig)*
+NS(ElemByElemConfig_from_obj_index)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object)* SIXTRL_RESTRICT obj )
+{
+    return ( SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig)*
+                )NS(ElemByElemConfig_const_from_obj_index)( obj );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig) const*
+NS(ElemByElemConfig_const_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const elem_by_elem_index,
+    NS(buffer_size_t) const slot_size )
+{
+    return NS(ElemByElemConfig_const_from_obj_index)(
+        NS(ManagedBuffer_get_const_object)(
+            buffer_begin, elem_by_elem_index, slot_size ) );
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(ElemByElemConfig)*
+NS(ElemByElemConfig_from_managed_buffer)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
+    NS(buffer_size_t) const elem_by_elem_index,
+    NS(buffer_size_t) const slot_size )
+{
+    return NS(ElemByElemConfig_from_obj_index)( NS(ManagedBuffer_get_object)(
+            buffer_begin, elem_by_elem_index, slot_size ) );
+}
+
 #if !defined( _GPUCODE )
 
 SIXTRL_INLINE NS(buffer_size_t)
diff --git a/sixtracklib/common/output/elem_by_elem_kernel_impl.h b/sixtracklib/common/output/elem_by_elem_kernel_impl.h
index 9ce80a7c..7f8a8018 100644
--- a/sixtracklib/common/output/elem_by_elem_kernel_impl.h
+++ b/sixtracklib/common/output/elem_by_elem_kernel_impl.h
@@ -13,16 +13,16 @@ extern "C" {
 
 SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
 NS(ElemByElemConfig_assign_output_buffer_kernel_impl)(
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT out_buffer,
     NS(buffer_size_t) const output_buffer_index_offset,
     NS(buffer_size_t) const slot_size );
 
 SIXTRL_STATIC SIXTRL_FN NS(arch_status_t)
 NS(ElemByElemConfig_assign_output_buffer_debug_kernel_impl)(
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT out_buffer,
     NS(buffer_size_t) const output_buffer_index_offset,
     NS(buffer_size_t) const slot_size,
@@ -65,8 +65,8 @@ extern "C" {
 
 SIXTRL_INLINE NS(arch_status_t)
 NS(ElemByElemConfig_assign_output_buffer_kernel_impl)(
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT out_buffer,
     NS(buffer_size_t) const output_buffer_index_offset,
     NS(buffer_size_t) const slot_size )
@@ -74,6 +74,12 @@ NS(ElemByElemConfig_assign_output_buffer_kernel_impl)(
     typedef NS(particle_num_elements_t) nelements_t;
     typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* out_iter_t;
     typedef SIXTRL_BUFFER_DATAPTR_DEC NS(Particles) const* ptr_out_particles_t;
+    typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
+            ptr_elem_by_elem_config_t;
+
+    ptr_elem_by_elem_config_t elem_by_elem_config =
+    NS(ElemByElemConfig_from_managed_buffer)( config_buffer,
+        elem_by_elem_config_index, slot_size );
 
     nelements_t const required_num_out_particles =
         NS(ElemByElemConfig_get_out_store_num_particles)( elem_by_elem_config );
@@ -115,8 +121,8 @@ NS(ElemByElemConfig_assign_output_buffer_kernel_impl)(
 
 SIXTRL_INLINE NS(arch_status_t)
 NS(ElemByElemConfig_assign_output_buffer_debug_kernel_impl)(
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT out_buffer,
     NS(buffer_size_t) const output_buffer_index_offset,
     NS(buffer_size_t) const slot_size,
@@ -125,6 +131,8 @@ NS(ElemByElemConfig_assign_output_buffer_debug_kernel_impl)(
     typedef NS(particle_num_elements_t) nelements_t;
     typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* out_iter_t;
     typedef SIXTRL_BUFFER_DATAPTR_DEC NS(Particles) const* ptr_out_particles_t;
+    typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
+            ptr_elem_by_elem_config_t;
 
     NS(arch_status_t) status = SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
     NS(arch_debugging_t) flags = SIXTRL_ARCH_DEBUGGING_MIN_FLAG;
@@ -136,6 +144,10 @@ NS(ElemByElemConfig_assign_output_buffer_debug_kernel_impl)(
     NS(arch_debugging_t) const OUT_PARTICLES_ILLEGAL_FLAG       = flags <<  4u;
     NS(arch_debugging_t) const OUT_BUFFER_REQUIRES_REMAP_FLAG   = flags <<  5u;
 
+    ptr_elem_by_elem_config_t elem_by_elem_config =
+    NS(ElemByElemConfig_from_managed_buffer)( config_buffer,
+        elem_by_elem_config_index, slot_size );
+
     flags = ( NS(arch_debugging_t) )0u;
 
     if( ( elem_by_elem_config != SIXTRL_NULLPTR ) &&
diff --git a/sixtracklib/common/output/output_buffer.c b/sixtracklib/common/output/output_buffer.c
index 8aa3899e..74b528e7 100644
--- a/sixtracklib/common/output/output_buffer.c
+++ b/sixtracklib/common/output/output_buffer.c
@@ -191,7 +191,7 @@ NS(output_buffer_flag_t) NS(OutputBuffer_required_for_tracking_detailed)(
                         ( ptr_monitor_t )( uintptr_t )addr;
 
                     if( ( be_monitor != SIXTRL_NULLPTR ) &&
-                        ( NS(BeamMonitor_get_num_stores)( be_monitor ) > 0 ) )
+                        ( NS(BeamMonitor_num_stores)( be_monitor ) > 0 ) )
                     {
                         flags |= NS(OUTPUT_BUFFER_BEAM_MONITORS);
                         break;
diff --git a/sixtracklib/common/particles.h b/sixtracklib/common/particles.h
index c401f994..66dc1f33 100644
--- a/sixtracklib/common/particles.h
+++ b/sixtracklib/common/particles.h
@@ -5280,6 +5280,13 @@ SIXTRL_INLINE void NS(Particles_add_to_energy_value)(
     real_t const one_plus_delta = delta + ONE;
     real_t const rvv = one_plus_delta / ( ONE + ptau_beta0 );
 
+    SIXTRL_ASSERT( NS(Particles_get_rvv_value)( p, ii ) > ( real_t )0.0 );
+    SIXTRL_ASSERT( beta0 >  ( real_t )0.0 );
+    SIXTRL_ASSERT( beta0 <= ( real_t )1.0 );
+    SIXTRL_ASSERT( one_plus_delta > ( real_t )0.0 );
+    SIXTRL_ASSERT( ( ( ONE + ptau_beta0 ) > ( real_t )0.0 ) ||
+                   ( ( ONE + ptau_beta0 ) < ( real_t )0.0 ) );
+
     NS(Particles_set_delta_value)(  p, ii, delta );
     NS(Particles_set_psigma_value)( p, ii, psigma );
     NS(Particles_scale_zeta_value)( p, ii,
diff --git a/sixtracklib/common/particles/CMakeLists.txt b/sixtracklib/common/particles/CMakeLists.txt
index c60da9f9..925e8f2e 100644
--- a/sixtracklib/common/particles/CMakeLists.txt
+++ b/sixtracklib/common/particles/CMakeLists.txt
@@ -1,61 +1,41 @@
 # ----------------------------------------------------------------------------
 # sixtracklib/common/particles/CMakeLists.txt
 
-set( SIXTRL_COMMON_PARTICLES_C99_HEADERS
-     definitions.h
-     particles_addr.h
-)
-
-set( SIXTRL_COMMON_PARTICLES_C99_SOURCES
-     particles.c
-     particles_addr.c
-)
+set( SIXTRL_COMMON_PARTICLES_C99_HEADERS definitions.h particles_addr.h )
+set( SIXTRL_COMMON_PARTICLES_C99_SOURCES particles.c particles_addr.c )
 
 add_library( sixtrack_common_particles_c99 OBJECT
     ${SIXTRL_COMMON_PARTICLES_C99_HEADERS}
-    ${SIXTRL_COMMON_PARTICLES_C99_SOURCES}
-)
+    ${SIXTRL_COMMON_PARTICLES_C99_SOURCES} )
 
 target_include_directories( sixtrack_common_particles_c99 PRIVATE
-    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
-    $<INSTALL_INTERFACE:include> )
+    $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
 
 set_target_properties( sixtrack_common_particles_c99 PROPERTIES
     POSITION_INDEPENDENT_CODE ON LINKER_LANGUAGE C C_STANDARD 99
     C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_particles_c99 PRIVATE
-    -Wall -Werror -pedantic -ansi ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
-    $<TARGET_OBJECTS:sixtrack_common_particles_c99>
-    CACHE INTERNAL "" FORCE )
+    $<TARGET_OBJECTS:sixtrack_common_particles_c99> CACHE INTERNAL "" FORCE )
 
 # -----------------------------------------------------------------------------
 
-set( SIXTRL_COMMON_PARTICLES_CXX_HEADERS
-     particles_addr.hpp
-)
-
+set( SIXTRL_COMMON_PARTICLES_CXX_HEADERS particles_addr.hpp )
 set( SIXTRL_COMMON_PARTICLES_CXX_SOURCES )
 
 # ==============================================================================
 # Handle install:
 
 if( SIXTRL_COMMON_PARTICLES_C99_HEADERS )
-    set( SIXTRACKLIB_COMMON_PARTICLES_C99_INSTALL_PATH
-        "${CMAKE_INSTALL_PREFIX}/include/sixtracklib/common/particles" )
-
     install( FILES ${SIXTRL_COMMON_INTERNAL_C99_HEADERS}
-             DESTINATION ${SIXTRACKLIB_COMMON_PARTICLES_C99_INSTALL_PATH} )
+             DESTINATION "${SIXTRL_COMMON_C99_INSTALL_PREFIX}/particles" )
 endif()
 
-if( SIXTRL_COMMON_PARTICLES_CXX_HEADERS )
-    set( SIXTRACKLIB_COMMON_PARTICLES_CXX_INSTALL_PATH
-         "${CMAKE_INSTALL_PREFIX}/include/sixtracklib/common/particles" )
-
-    install( FILES ${SIXTRL_COMMON_INTERNAL_CXX_HEADERS}
-             DESTINATION ${SIXTRL_COMMON_PARTICLES_CXX_HEADERS} )
+if( SIXTRACKL_CXX_ENABLE AND SIXTRL_COMMON_PARTICLES_CXX_HEADERS )
+    install( FILES ${SIXTRL_COMMON_PARTICLES_CXX_HEADERS}
+             DESTINATION "${SIXTRL_COMMON_CXX_INSTALL_PREFIX}/particles" )
 endif()
-
-#end: sixtracklib/common/particles/CMakeLists.txt
diff --git a/sixtracklib/common/particles/definitions.h b/sixtracklib/common/particles/definitions.h
index b28cde13..265ec4be 100644
--- a/sixtracklib/common/particles/definitions.h
+++ b/sixtracklib/common/particles/definitions.h
@@ -89,7 +89,5 @@ namespace SIXTRL_CXX_NAMESPACE
 }
 
 #endif /* C++, Host  */
-
 #endif /* SIXTRACKLIB_COMMON_PARTICLES_DEFINITIONS_H__ */
-
-/* end: sixtracklib/common/particles/definitions.h */
\ No newline at end of file
+/* end: sixtracklib/common/particles/definitions.h */
diff --git a/sixtracklib/common/particles/particles.c b/sixtracklib/common/particles/particles.c
index 2925c1a0..df143a37 100644
--- a/sixtracklib/common/particles/particles.c
+++ b/sixtracklib/common/particles/particles.c
@@ -47,7 +47,7 @@ NS(BufferIndex_get_total_num_of_particles_in_range_ext)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT begin,
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT end )
 {
-    return NS(BufferIndex_get_total_num_of_particles_in_range_ext)(
+    return NS(BufferIndex_get_total_num_of_particles_in_range)(
         begin, end );
 }
 
@@ -56,7 +56,7 @@ NS(BufferIndex_get_total_num_of_particle_blocks_in_range_ext)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT begin,
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT end )
 {
-    return NS(BufferIndex_get_total_num_of_particle_blocks_in_range_ext)(
+    return NS(BufferIndex_get_total_num_of_particle_blocks_in_range)(
         begin, end );
 }
 
@@ -147,14 +147,14 @@ void NS(Particles_buffers_calculate_difference_ext)(
     SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT rhs,
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT diff )
 {
-    NS(Particles_buffers_calculate_difference_ext)( lhs, rhs, diff );
+    NS(Particles_buffers_calculate_difference)( lhs, rhs, diff );
     return;
 }
 
 void NS(Particles_buffer_clear_particles_ext)(
     SIXTRL_BUFFER_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer )
 {
-    NS(Particles_buffer_clear_particles_ext)( buffer );
+    NS(Particles_buffer_clear_particles)( buffer );
 }
 
 /* ------------------------------------------------------------------------- */
diff --git a/sixtracklib/common/particles/particles_addr.h b/sixtracklib/common/particles/particles_addr.h
index 1b0b3ccb..a4e6c43f 100644
--- a/sixtracklib/common/particles/particles_addr.h
+++ b/sixtracklib/common/particles/particles_addr.h
@@ -177,7 +177,7 @@ NS(Particles_managed_buffer_store_all_addresses_debug)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT paddr_buffer,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT pbuffer,
     NS(buffer_size_t) const slot_size,
-    SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_error_flag );
+    SIXTRL_ARGPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_error_flag );
 
 
 /* ------------------------------------------------------------------------- */
@@ -455,16 +455,131 @@ SIXTRL_INLINE int NS(ParticlesAddr_compare_values)(
     SIXTRL_PARTICLE_ARGPTR_DEC const NS(ParticlesAddr) *const
         SIXTRL_RESTRICT rhs )
 {
+    int cmp_result = -1;
+
     if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
     {
-        return memcmp( lhs, rhs, sizeof( NS(ParticlesAddr) ) );
+        cmp_result = ( lhs->num_particles == rhs->num_particles )
+            ? 0 : ( ( lhs->num_particles > rhs->num_particles ) ? +1 : -1 );
+
+        if( ( cmp_result == 0 ) && ( lhs->q0_addr != rhs->q0_addr ) )
+        {
+            cmp_result = ( lhs->q0_addr > rhs->q0_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->mass0_addr != rhs->mass0_addr ) )
+        {
+            cmp_result = ( lhs->mass0_addr > rhs->mass0_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->beta0_addr != rhs->beta0_addr ) )
+        {
+            cmp_result = ( lhs->beta0_addr > rhs->beta0_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->gamma0_addr != rhs->gamma0_addr ) )
+        {
+            cmp_result = ( lhs->gamma0_addr > rhs->gamma0_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->p0c_addr != rhs->p0c_addr ) )
+        {
+            cmp_result = ( lhs->p0c_addr > rhs->p0c_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->s_addr != rhs->s_addr ) )
+        {
+            cmp_result = ( lhs->s_addr > rhs->s_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->x_addr != rhs->x_addr ) )
+        {
+            cmp_result = ( lhs->x_addr > rhs->x_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->y_addr != rhs->y_addr ) )
+        {
+            cmp_result = ( lhs->y_addr > rhs->y_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->px_addr != rhs->px_addr ) )
+        {
+            cmp_result = ( lhs->px_addr > rhs->px_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->py_addr != rhs->py_addr ) )
+        {
+            cmp_result = ( lhs->py_addr > rhs->py_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->zeta_addr != rhs->zeta_addr ) )
+        {
+            cmp_result = ( lhs->zeta_addr > rhs->zeta_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->psigma_addr != rhs->psigma_addr ) )
+        {
+            cmp_result = ( lhs->psigma_addr > rhs->psigma_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->delta_addr != rhs->delta_addr ) )
+        {
+            cmp_result = ( lhs->delta_addr > rhs->delta_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->rpp_addr != rhs->rpp_addr ) )
+        {
+            cmp_result = ( lhs->rpp_addr > rhs->rpp_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->rvv_addr != rhs->rvv_addr ) )
+        {
+            cmp_result = ( lhs->rvv_addr > rhs->rvv_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->chi_addr != rhs->chi_addr ) )
+        {
+            cmp_result = ( lhs->chi_addr > rhs->chi_addr ) ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) &&
+            ( lhs->charge_ratio_addr != rhs->charge_ratio_addr ) )
+        {
+            cmp_result = ( lhs->charge_ratio_addr > rhs->charge_ratio_addr )
+                ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) &&
+            ( lhs->particle_id_addr != rhs->particle_id_addr ) )
+        {
+            cmp_result = ( lhs->particle_id_addr > rhs->particle_id_addr )
+                ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) &&
+            ( lhs->at_element_id_addr != rhs->at_element_id_addr ) )
+        {
+            cmp_result = ( lhs->at_element_id_addr > rhs->at_element_id_addr )
+                ? +1 : -1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->at_turn_addr != rhs->at_turn_addr ) )
+        {
+            cmp_result = ( lhs->at_turn_addr > rhs->at_turn_addr ) ? +1 : -1;
+        }
+
+
+        if( ( cmp_result == 0 ) && ( lhs->state_addr != rhs->state_addr ) )
+        {
+            cmp_result = ( lhs->state_addr > rhs->state_addr ) ? +1 : -1;
+        }
     }
     else if( lhs != SIXTRL_NULLPTR )
     {
-        return 1;
+        cmp_result = 1;
     }
 
-    return -1;
+    return cmp_result;
 }
 
 /* ------------------------------------------------------------------------- */
diff --git a/sixtracklib/common/track/CMakeLists.txt b/sixtracklib/common/track/CMakeLists.txt
index e62e73e6..77b8a23a 100644
--- a/sixtracklib/common/track/CMakeLists.txt
+++ b/sixtracklib/common/track/CMakeLists.txt
@@ -1,18 +1,10 @@
 # ----------------------------------------------------------------------------
 # sixtracklib/common/track/CMakeLists.txt
 
-set( SIXTRL_COMMON_TRACK_C99_HEADERS
-     definitions.h
-     track.h
-     track_kernel_impl.h
-     track_kernel_opt_impl.h
-     track_job_base.h
-     track_job_cpu.h
-)
-
-set( SIXTRL_COMMON_TRACK_C99_SOURCES
-     track.c
-)
+set( SIXTRL_COMMON_TRACK_C99_SOURCES track.c )
+set( SIXTRL_COMMON_TRACK_C99_HEADERS definitions.h track.h track_kernel_impl.h
+     track_kernel_opt_impl.h track_job_base.h track_job_cpu.h
+     track_job_buffer_store.h )
 
 add_library( sixtrack_common_track OBJECT
     ${SIXTRL_COMMON_TRACK_C99_HEADERS} ${SIXTRL_COMMON_TRACK_C99_SOURCES} )
@@ -30,30 +22,23 @@ set_target_properties( sixtrack_common_track PROPERTIES
     C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_track PRIVATE
-    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 
-set( SIXTRL_COMMON_TRACK_CXX_HEADERS
-     track_job_base.hpp
-     track_job_ctrl_arg_base.hpp
-     track_job_nodectrl_arg_base.hpp
-     track_job_cpu.hpp
-)
-
-set( SIXTRL_COMMON_TRACK_CXX_SOURCES
-     track_job_base.cpp
-     track_job_base_c99.cpp
-     track_job_ctrl_arg_base.cpp
-     track_job_nodectrl_arg_base.cpp
-     track_job_cpu.cpp
-     track_job_cpu_c99.cpp
-)
+set( SIXTRL_COMMON_TRACK_CXX_HEADERS track_job_base.hpp
+     track_job_ctrl_arg_base.hpp track_job_nodectrl_arg_base.hpp
+     track_job_cpu.hpp )
+
+set( SIXTRL_COMMON_TRACK_CXX_SOURCES track_job_base.cpp track_job_base_c99.cpp
+    track_job_ctrl_arg_base.cpp track_job_nodectrl_arg_base.cpp
+     track_job_cpu.cpp track_job_cpu_c99.cpp
+     track_job_buffer_store.cpp )
 
 add_library( sixtrack_common_track_cxx OBJECT
     ${SIXTRL_COMMON_TRACK_CXX_HEADERS} ${SIXTRL_COMMON_TRACK_CXX_SOURCES}
-    ${SIXTRL_COMMON_TRACK_C99_HEADERS}
-)
+    ${SIXTRL_COMMON_TRACK_C99_HEADERS} )
 
 target_include_directories( sixtrack_common_track_cxx PRIVATE
     $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}> $<INSTALL_INTERFACE:include> )
@@ -68,7 +53,8 @@ set_target_properties( sixtrack_common_track_cxx PROPERTIES
     CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_common_track_cxx PRIVATE
-    ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_common_track and sixtrack_common_track_cxx
@@ -76,8 +62,7 @@ target_compile_options( sixtrack_common_track_cxx PRIVATE
 
 set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
     $<TARGET_OBJECTS:sixtrack_common_track>
-    $<TARGET_OBJECTS:sixtrack_common_track_cxx>
-    CACHE INTERNAL "" FORCE )
+    $<TARGET_OBJECTS:sixtrack_common_track_cxx> CACHE INTERNAL "" FORCE )
 
 # -----------------------------------------------------------------------------
 # install :
diff --git a/sixtracklib/common/track/definitions.h b/sixtracklib/common/track/definitions.h
index 1e9997e2..02fed757 100644
--- a/sixtracklib/common/track/definitions.h
+++ b/sixtracklib/common/track/definitions.h
@@ -3,6 +3,7 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/generated/config.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
@@ -16,18 +17,6 @@
     #define SIXTRL_TRACK_STATUS_GENERAL_FAILURE -1
 #endif /* !defined( SIXTRL_TRACK_STATUS_GENERAL_FAILURE ) */
 
-#if !defined( SIXTRL_GLOBAL_APERTURE_CHECK_NEVER )
-    #define SIXTRL_GLOBAL_APERTURE_CHECK_NEVER 0
-#endif /* !defined( SIXTRL_GLOBAL_APERTURE_CHECK_NEVER ) */
-
-#if !defined( SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL )
-    #define SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL 1
-#endif /* !defined( SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL ) */
-
-#if !defined( SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS )
-    #define SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS 2
-#endif /* !defined( SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS ) */
-
 #if defined( __cplusplus ) && !defined( _GPUCODE )
 extern "C" {
 #endif /* defined( __cplusplus ) && ( !defined( _GPUCODE ) */
diff --git a/sixtracklib/common/track/track.h b/sixtracklib/common/track/track.h
index 0ff753dc..48c84547 100644
--- a/sixtracklib/common/track/track.h
+++ b/sixtracklib/common/track/track.h
@@ -167,10 +167,8 @@ SIXTRL_EXTERN SIXTRL_HOST_FN NS(track_status_t) NS(Track_all_particles_line)(
     #include "sixtracklib/common/be_limit/track.h"
     #include "sixtracklib/common/be_dipedge/track.h"
     #include "sixtracklib/common/be_rfmultipole/track.h"
-
-    #if !defined( SIXTRL_DISABLE_BEAM_BEAM )
-        #include "sixtracklib/common/be_beamfields/track.h"
-    #endif /* !defined( SIXTRL_DISABLE_BEAM_BEAM ) */
+    #include "sixtracklib/common/be_beamfields/track.h"
+    #include "sixtracklib/common/be_tricub/track.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined( _GPUCODE ) && defined( __cplusplus )
@@ -183,33 +181,29 @@ SIXTRL_INLINE NS(track_status_t) NS(Track_particle_beam_element_obj_dispatcher)(
     NS(particle_num_elements_t) const index,
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const* SIXTRL_RESTRICT be_info )
 {
-    #if defined( SIXTRL_ENABLE_APERTURE_CHECK ) && \
-        ( defined( SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL ) || \
-          defined( SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS ) || \
-          defined( SIXTRL_GLOBAL_APERTURE_CHECK_NEVER ) )
+    #if defined( SIXTRL_APERTURE_CHECK_AT_DRIFT )
 
-        #if ( SIXTRL_ENABLE_APERTURE_CHECK == \
-              SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL ) || \
-            ( SIXTRL_ENABLE_APERTURE_CHECK == \
-              SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS )
+        #if ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+              SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS ) || \
+            ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+              SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL )
 
         return NS(Track_particle_beam_element_obj_dispatcher_aperture_check)(
             particles, index, be_info, true );
 
-        #elif SIXTRL_ENABLE_APERTURE_CHECK == \
-              SIXTRL_GLOBAL_APERTURE_CHECK_NEVER
+        # else
 
         return NS(Track_particle_beam_element_obj_dispatcher_aperture_check)(
             particles, index, be_info, false );
 
-        #endif /* SIXTRL_ENABLE_APERTURE_CHECK */
+        #endif /* SIXTRL_APERTURE_CHECK_AT_DRIFT */
 
-    #else  /* !defined( SIXTRL_ENABLE_APERTURE_CHECK ) */
+    #else  /* !defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) */
 
         return NS(Track_particle_beam_element_obj_dispatcher_aperture_check)(
             particles, index, be_info, true );
 
-    #endif /*  defined( SIXTRL_ENABLE_APERTURE_CHECK ) */
+    #endif /*  defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) */
 }
 
 SIXTRL_INLINE NS(track_status_t)
@@ -242,11 +236,39 @@ NS(Track_particle_beam_element_obj_dispatcher_aperture_check)(
 
             ret = NS(Track_particle_drift)( particles, index, belem );
 
+            #if !defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) || \
+                ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                  SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS )
+
+            if( perform_global_aperture_check )
+            {
+                ret |= NS(Track_particle_limit_global)( particles, index );
+            }
+
+            #elif defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) && \
+                  ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                    SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL )
+
             if( perform_global_aperture_check )
             {
+                #if defined( SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH )
+
+                if( ( belem != SIXTRL_NULLPTR ) &&
+                    ( NS(Drift_get_length)( belem ) >=
+                        ( SIXTRL_REAL_T )SIXTRL_APERTURE_CHECK_AT_DRIFT ) )
+                {
+                    ret |= NS(Track_particle_limit_global)( particles, index );
+                }
+
+                #else
+
                 ret |= NS(Track_particle_limit_global)( particles, index );
+
+                #endif /* defined( SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH ) */
             }
 
+            #endif
+
             break;
         }
 
@@ -258,17 +280,45 @@ NS(Track_particle_beam_element_obj_dispatcher_aperture_check)(
 
             ret = NS(Track_particle_drift_exact)( particles, index, belem );
 
+            #if !defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) || \
+                ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                  SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS )
+
+            if( perform_global_aperture_check )
+            {
+                ret |= NS(Track_particle_limit_global)( particles, index );
+            }
+
+            #elif defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) && \
+                  ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                    SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL )
+
             if( perform_global_aperture_check )
             {
+                #if defined( SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH )
+
+                if( ( belem != SIXTRL_NULLPTR ) &&
+                    ( NS(Drift_get_length)( belem ) >=
+                        ( SIXTRL_REAL_T )SIXTRL_APERTURE_CHECK_AT_DRIFT ) )
+                {
+                    ret |= NS(Track_particle_limit_global)( particles, index );
+                }
+
+                #else
+
                 ret |= NS(Track_particle_limit_global)( particles, index );
+
+                #endif /* defined( SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH ) */
             }
 
+            #endif
+
             break;
         }
 
         case NS(OBJECT_TYPE_MULTIPOLE):
         {
-            typedef NS(MultiPole)   belem_t;
+            typedef NS(Multipole)   belem_t;
             typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_to_belem_t;
             ptr_to_belem_t belem = ( ptr_to_belem_t )( uintptr_t )begin_addr;
 
@@ -278,7 +328,7 @@ NS(Track_particle_beam_element_obj_dispatcher_aperture_check)(
 
         case NS(OBJECT_TYPE_RF_MULTIPOLE):
         {
-            typedef NS(RFMultiPole) belem_t;
+            typedef NS(RFMultipole)   belem_t;
             typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_to_belem_t;
             ptr_to_belem_t belem = ( ptr_to_belem_t )( uintptr_t )begin_addr;
 
@@ -368,52 +418,162 @@ NS(Track_particle_beam_element_obj_dispatcher_aperture_check)(
             break;
         }
 
-        #if !defined( SIXTRL_DISABLE_BEAM_BEAM )
+        case NS(OBJECT_TYPE_TRICUB):
+        {
+            #if !defined( SIXTRL_TRACK_TRICUB ) || \
+                ( SIXTRL_TRACK_TRICUB == SIXTRL_TRACK_MAP_ENABLED )
+
+            typedef NS(TriCub)  belem_t;
+            typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_to_belem_t;
+            ptr_to_belem_t belem = ( ptr_to_belem_t )( uintptr_t )begin_addr;
+
+            ret = NS(Track_particle_tricub)( particles, index, belem );
+
+            #elif defined( SIXTRL_TRACK_TRICUB ) && \
+                  ( SIXTRL_TRACK_TRICUB == SIXTRL_TRACK_MAP_SKIP )
+
+            /* Skip particle and do nothing! */
+            ret = SIXTRL_TRACK_SUCCESS;
+
+            #else
+
+            ret = SIXTRL_TRACK_STATUS_GENERAL_FAILURE;
+
+            #endif /* SIXTRL_TRACK_TRICUB */
+            break;
+        }
+
+        case NS(OBJECT_TYPE_TRICUB_DATA):
+        {
+            #if defined( SIXTRL_TRACK_TRICUB ) && \
+                SIXTRL_TRACK_TRICUB != SIXTRL_TRACK_MAP_DISABLED
+
+            /* Always skip the tricub data part, which should probably not be
+             * in the lattice anyway */
+            ret = SIXTRL_TRACK_SUCCESS;
+
+            #else /* explicitly disabled the TriCub map! */
+
+            ret = SIXTRL_TRACK_STATUS_GENERAL_FAILURE;
+
+            #endif /* defined( SIXTRL_TRACK_TRICUB ) */
+            break;
+        }
 
         case NS(OBJECT_TYPE_BEAM_BEAM_4D):
         {
+            #if !defined( SIXTRL_TRACK_BEAMBEAM4D ) || \
+                ( SIXTRL_TRACK_BEAMBEAM4D == SIXTRL_TRACK_MAP_ENABLED )
+
             typedef NS(BeamBeam4D)   belem_t;
             typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_to_belem_t;
             ptr_to_belem_t belem = ( ptr_to_belem_t )( uintptr_t )begin_addr;
 
             ret = NS(Track_particle_beam_beam_4d)( particles, index, belem );
+
+            #elif defined( SIXTRL_TRACK_BEAMBEAM4D ) && \
+                  ( SIXTRL_TRACK_BEAMBEAM4D == SIXTRL_TRACK_MAP_SKIP )
+
+            /* Skip particle and do nothing! */
+            ret = SIXTRL_TRACK_SUCCESS;
+
+            #else
+
+            ret = SIXTRL_TRACK_STATUS_GENERAL_FAILURE;
+
+            #endif /* defined( SIXTRL_ENABLE_BEAM_FIELDS_BEAM_BEAM_4D ) */
             break;
         }
 
-        case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+        case NS(OBJECT_TYPE_BEAM_BEAM_6D):
         {
-            typedef NS(SpaceChargeCoasting)   belem_t;
+            #if !defined( SIXTRL_TRACK_BEAMBEAM6D ) || \
+                ( SIXTRL_TRACK_BEAMBEAM6D == SIXTRL_TRACK_MAP_ENABLED )
+
+            typedef NS(BeamBeam6D)   belem_t;
+            typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_to_belem_t;
+            ptr_to_belem_t belem = ( ptr_to_belem_t )( uintptr_t )begin_addr;
+
+            ret = NS(Track_particle_beam_beam_6d)( particles, index, belem );
+
+            #elif defined( SIXTRL_TRACK_BEAMBEAM6D ) && \
+                  ( SIXTRL_TRACK_BEAMBEAM6D == SIXTRL_TRACK_MAP_SKIP )
+
+
+            /* Skip particle and do nothing! */
+            ret = SIXTRL_TRACK_SUCCESS;
+
+            #else
+
+            ret = SIXTRL_TRACK_STATUS_GENERAL_FAILURE;
+
+            #endif /* SIXTRL_ENABLE_BEAM_FIELDS_BEAM_BEAM_6D */
+            break;
+        }
+
+        case NS(OBJECT_TYPE_SC_COASTING):
+        {
+            #if !defined( SIXTRL_TRACK_SPACECHARGE ) || \
+                ( SIXTRL_TRACK_SPACECHARGE == SIXTRL_TRACK_MAP_ENABLED )
+
+            typedef NS(SCCoasting)   belem_t;
             typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_to_belem_t;
             ptr_to_belem_t belem = ( ptr_to_belem_t )( uintptr_t )begin_addr;
 
             ret = NS(Track_particle_space_charge_coasting)(
                 particles, index, belem );
+
+            #elif defined( SIXTRL_TRACK_SPACECHARGE ) && \
+                  ( SIXTRL_TRACK_SPACECHARGE == SIXTRL_TRACK_MAP_SKIP )
+
+            /* Skip particle and do nothing! */
+            ret = SIXTRL_TRACK_SUCCESS;
+
+            #else
+
+            ret = SIXTRL_TRACK_STATUS_GENERAL_FAILURE;
+
+            #endif /* SIXTRL_ENABLE_SPACE_CHARGE_COASTING */
             break;
         }
 
-        case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+        case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
         {
-            typedef NS(SpaceChargeBunched)   belem_t;
+            #if !defined( SIXTRL_TRACK_SPACECHARGE ) || \
+                ( SIXTRL_TRACK_SPACECHARGE == SIXTRL_TRACK_MAP_ENABLED )
+
+            typedef NS(SCQGaussProfile) belem_t;
             typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_to_belem_t;
             ptr_to_belem_t belem = ( ptr_to_belem_t )( uintptr_t )begin_addr;
 
-            ret = NS(Track_particle_space_charge_bunched)(
+            ret = NS(Track_particle_space_charge_qgaussian_profile)(
                 particles, index, belem );
             break;
         }
 
-        case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+        case NS(OBJECT_TYPE_SC_INTERPOLATED_PROF):
         {
-            typedef NS(BeamBeam6D)   belem_t;
+            typedef NS(SCInterpolatedProfile) belem_t;
             typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_to_belem_t;
             ptr_to_belem_t belem = ( ptr_to_belem_t )( uintptr_t )begin_addr;
 
-            ret = NS(Track_particle_beam_beam_6d)( particles, index, belem );
+            ret = NS(Track_particle_space_charge_interpolated_profile)(
+                particles, index, belem );
+
+            #elif defined( SIXTRL_TRACK_SPACECHARGE ) && \
+                  ( SIXTRL_TRACK_SPACECHARGE == SIXTRL_TRACK_MAP_SKIP )
+
+            /* Skip particle and do nothing! */
+            ret = SIXTRL_TRACK_SUCCESS;
+
+            #else
+
+            ret = SIXTRL_TRACK_STATUS_GENERAL_FAILURE;
+
+            #endif /* SIXTRL_ENABLE_SPACE_CHARGE_BUNCHED */
             break;
         }
 
-        #endif /* !defined( SIXTRL_DISABLE_BEAM_BEAM ) */
-
         default:
         {
             NS(Particles_mark_as_lost_value)( particles, index );
diff --git a/sixtracklib/common/track/track_job_base.cpp b/sixtracklib/common/track/track_job_base.cpp
index cfff23ec..90c3c4d7 100644
--- a/sixtracklib/common/track/track_job_base.cpp
+++ b/sixtracklib/common/track/track_job_base.cpp
@@ -16,8 +16,10 @@
     #include "sixtracklib/common/be_monitor/be_monitor.h"
     #include "sixtracklib/common/be_monitor/output_buffer.h"
     #include "sixtracklib/common/beam_elements.h"
-    #include "sixtracklib/common/buffer.hpp"
     #include "sixtracklib/common/buffer.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+    #include "sixtracklib/common/buffer/assign_address_item_kernel_impl.h"
+    #include "sixtracklib/common/buffer.hpp"
     #include "sixtracklib/common/particles/definitions.h"
     #include "sixtracklib/common/particles/particles_addr.h"
     #include "sixtracklib/common/particles/particles_addr.hpp"
@@ -37,187 +39,179 @@
 
     #endif /* CUDA */
 
-
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
-namespace st = SIXTRL_CXX_NAMESPACE;
 namespace SIXTRL_CXX_NAMESPACE
 {
-    using _this_t = st::TrackJobBaseNew;
+    namespace
+    {
+        namespace st            = SIXTRL_CXX_NAMESPACE;
+        using tjob_t            = st::TrackJobBaseNew;
+        using st_size_t         = tjob_t::size_type;
+        using st_collect_flag_t = tjob_t::collect_flag_t;
+        using st_push_flag_t    = tjob_t::push_flag_t;
+        using st_status_t       = tjob_t::status_t;
+    }
 
-    _this_t::size_type
-    TrackJobBaseNew::DefaultNumParticleSetIndices() SIXTRL_NOEXCEPT
+    st_size_t tjob_t::DefaultNumParticleSetIndices() SIXTRL_NOEXCEPT
     {
         return st::TRACK_JOB_DEFAULT_NUM_PARTICLE_SETS;
     }
 
-    _this_t::size_type const*
-    TrackJobBaseNew::DefaultParticleSetIndicesBegin() SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::DefaultParticleSetIndicesBegin() SIXTRL_NOEXCEPT
     {
         return &st::TRACK_JOB_DEFAULT_PARTICLE_SET_INDICES[ 0 ];
     }
 
-    _this_t::size_type const*
-    TrackJobBaseNew::DefaultParticleSetIndicesEnd() SIXTRL_NOEXCEPT
+    st_size_t const* tjob_t::DefaultParticleSetIndicesEnd() SIXTRL_NOEXCEPT
     {
-        _this_t::size_type const* end_ptr =
-            TrackJobBaseNew::DefaultParticleSetIndicesBegin();
-
+        st_size_t const* end_ptr = tjob_t::DefaultParticleSetIndicesBegin();
         std::advance( end_ptr, st::TRACK_JOB_DEFAULT_NUM_PARTICLE_SETS );
         return end_ptr;
     }
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBaseNew::clear()
+    void tjob_t::clear()
     {
         this->doClear( this->doGetDefaultAllClearFlags() );
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::collect_flag_t TrackJobBaseNew::collect()
+    st_collect_flag_t tjob_t::collect()
     {
         return this->doCollect( this->m_collect_flags );
     }
 
-    _this_t::collect_flag_t TrackJobBaseNew::collect(
-        _this_t::collect_flag_t const flags )
+    st_collect_flag_t tjob_t::collect( st_collect_flag_t const flags )
     {
         return this->doCollect( flags & st::TRACK_JOB_COLLECT_ALL );
     }
 
-    _this_t::status_t TrackJobBaseNew::collectParticles()
+    st_status_t tjob_t::collectParticles()
     {
-        return ( st::TrackJobBaseNew::IsCollectFlagSet(
-            this->doCollect( st::TRACK_JOB_IO_PARTICLES ),
-                st::TRACK_JOB_IO_PARTICLES ) )
+        return ( tjob_t::IsCollectFlagSet( this->doCollect(
+            st::TRACK_JOB_IO_PARTICLES ), st::TRACK_JOB_IO_PARTICLES ) )
             ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
     }
 
-    _this_t::status_t TrackJobBaseNew::collectBeamElements()
+    st_status_t tjob_t::collectBeamElements()
     {
-        return ( st::TrackJobBaseNew::IsCollectFlagSet(
-            this->doCollect( st::TRACK_JOB_IO_BEAM_ELEMENTS ),
-                st::TRACK_JOB_IO_BEAM_ELEMENTS ) )
+        return ( tjob_t::IsCollectFlagSet( this->doCollect(
+            st::TRACK_JOB_IO_BEAM_ELEMENTS ), st::TRACK_JOB_IO_BEAM_ELEMENTS ) )
             ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
     }
 
-    _this_t::status_t TrackJobBaseNew::collectOutput()
+    st_status_t tjob_t::collectOutput()
     {
-        return ( TrackJobBaseNew::IsCollectFlagSet(
-            this->doCollect( st::TRACK_JOB_IO_OUTPUT ),
-                st::TRACK_JOB_IO_OUTPUT ) )
+        return ( tjob_t::IsCollectFlagSet( this->doCollect(
+            st::TRACK_JOB_IO_OUTPUT ), st::TRACK_JOB_IO_OUTPUT ) )
             ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
     }
 
-    _this_t::status_t TrackJobBaseNew::collectDebugFlag()
+    st_status_t tjob_t::collectDebugFlag()
     {
-        return ( TrackJobBaseNew::IsCollectFlagSet(
-            this->doCollect( st::TRACK_JOB_IO_DEBUG_REGISTER ),
-                st::TRACK_JOB_IO_DEBUG_REGISTER ) )
+        return ( tjob_t::IsCollectFlagSet( this->doCollect(
+            st::TRACK_JOB_IO_DEBUG_REGISTER ), st::TRACK_JOB_IO_DEBUG_REGISTER ) )
             ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
     }
 
-    _this_t::status_t TrackJobBaseNew::collectParticlesAddresses()
+    st_status_t tjob_t::collectParticlesAddresses()
     {
-        return ( TrackJobBaseNew::IsCollectFlagSet(
-            this->doCollect( st::TRACK_JOB_IO_PARTICLES_ADDR ),
-                st::TRACK_JOB_IO_PARTICLES_ADDR ) )
+        return ( tjob_t::IsCollectFlagSet( this->doCollect(
+            st::TRACK_JOB_IO_PARTICLES_ADDR ), st::TRACK_JOB_IO_PARTICLES_ADDR ) )
             ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
     }
 
-    void TrackJobBaseNew::enableCollectParticles()  SIXTRL_NOEXCEPT
+    void tjob_t::enableCollectParticles()  SIXTRL_NOEXCEPT
     {
         this->m_collect_flags |= st::TRACK_JOB_IO_PARTICLES;
     }
 
-    void TrackJobBaseNew::disableCollectParticles() SIXTRL_NOEXCEPT
+    void tjob_t::disableCollectParticles() SIXTRL_NOEXCEPT
     {
-        this->m_collect_flags = TrackJobBaseNew::UnsetCollectFlag(
+        this->m_collect_flags = tjob_t::UnsetCollectFlag(
             this->m_collect_flags, st::TRACK_JOB_IO_PARTICLES );
     }
 
-    bool TrackJobBaseNew::isCollectingParticles() const SIXTRL_NOEXCEPT
+    bool tjob_t::isCollectingParticles() const SIXTRL_NOEXCEPT
     {
-        return TrackJobBaseNew::IsCollectFlagSet( this->m_collect_flags,
+        return tjob_t::IsCollectFlagSet( this->m_collect_flags,
             st::TRACK_JOB_IO_PARTICLES );
     }
 
-    void TrackJobBaseNew::enableCollectBeamElements()  SIXTRL_NOEXCEPT
+    void tjob_t::enableCollectBeamElements()  SIXTRL_NOEXCEPT
     {
         this->m_collect_flags |= st::TRACK_JOB_IO_BEAM_ELEMENTS;
     }
 
-    void TrackJobBaseNew::disableCollectBeamElements() SIXTRL_NOEXCEPT
+    void tjob_t::disableCollectBeamElements() SIXTRL_NOEXCEPT
     {
-        this->m_collect_flags = TrackJobBaseNew::UnsetCollectFlag(
+        this->m_collect_flags = tjob_t::UnsetCollectFlag(
             this->m_collect_flags, st::TRACK_JOB_IO_BEAM_ELEMENTS );
     }
 
-    bool TrackJobBaseNew::isCollectingBeamElements() const SIXTRL_NOEXCEPT
+    bool tjob_t::isCollectingBeamElements() const SIXTRL_NOEXCEPT
     {
-        return TrackJobBaseNew::IsCollectFlagSet( this->m_collect_flags,
+        return tjob_t::IsCollectFlagSet( this->m_collect_flags,
                 st::TRACK_JOB_IO_BEAM_ELEMENTS );
     }
 
-    void TrackJobBaseNew::enableCollectOutput()  SIXTRL_NOEXCEPT
+    void tjob_t::enableCollectOutput()  SIXTRL_NOEXCEPT
     {
         this->m_collect_flags |= st::TRACK_JOB_IO_OUTPUT;
     }
 
-    void TrackJobBaseNew::disableCollectOutput() SIXTRL_NOEXCEPT
+    void tjob_t::disableCollectOutput() SIXTRL_NOEXCEPT
     {
-        this->m_collect_flags = TrackJobBaseNew::UnsetCollectFlag(
+        this->m_collect_flags = tjob_t::UnsetCollectFlag(
             this->m_collect_flags, st::TRACK_JOB_IO_OUTPUT );
     }
 
-    bool TrackJobBaseNew::isCollectingOutput() const SIXTRL_NOEXCEPT
+    bool tjob_t::isCollectingOutput() const SIXTRL_NOEXCEPT
     {
-        return TrackJobBaseNew::IsCollectFlagSet( this->m_collect_flags,
+        return tjob_t::IsCollectFlagSet( this->m_collect_flags,
                 st::TRACK_JOB_IO_OUTPUT );
     }
 
-    _this_t::collect_flag_t
-    TrackJobBaseNew::collectFlags() const SIXTRL_NOEXCEPT
+    st_collect_flag_t tjob_t::collectFlags() const SIXTRL_NOEXCEPT
     {
         return this->m_collect_flags;
     }
 
-    void TrackJobBaseNew::setCollectFlags(
-        _this_t::collect_flag_t const flags ) SIXTRL_NOEXCEPT
+    void tjob_t::setCollectFlags( st_collect_flag_t const flags ) SIXTRL_NOEXCEPT
     {
         this->m_collect_flags = ( flags & st::TRACK_JOB_COLLECT_ALL );
     }
 
-    bool TrackJobBaseNew::requiresCollecting() const SIXTRL_NOEXCEPT
+    bool tjob_t::requiresCollecting() const SIXTRL_NOEXCEPT
     {
         return this->m_requires_collect;
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::push_flag_t TrackJobBaseNew::push(
-        _this_t::push_flag_t const push_flag )
+    st_push_flag_t tjob_t::push( st_push_flag_t const push_flag )
     {
         return this->doPush( push_flag & st::TRACK_JOB_PUSH_ALL );
     }
 
-    _this_t::status_t TrackJobBaseNew::pushParticles()
+    st_status_t tjob_t::pushParticles()
     {
         return ( ( st::TRACK_JOB_IO_PARTICLES & this->push(
             st::TRACK_JOB_IO_PARTICLES ) ) == st::TRACK_JOB_IO_PARTICLES )
             ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
     }
 
-    _this_t::status_t TrackJobBaseNew::pushBeamElements()
+    st_status_t tjob_t::pushBeamElements()
     {
         return ( ( st::TRACK_JOB_IO_BEAM_ELEMENTS & this->push(
             st::TRACK_JOB_IO_BEAM_ELEMENTS ) ) == st::TRACK_JOB_IO_BEAM_ELEMENTS )
             ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
     }
 
-    _this_t::status_t TrackJobBaseNew::pushOutput()
+    st_status_t tjob_t::pushOutput()
     {
         return ( ( st::TRACK_JOB_IO_OUTPUT & this->push(
             st::TRACK_JOB_IO_OUTPUT ) ) == st::TRACK_JOB_IO_OUTPUT )
@@ -226,9 +220,9 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::status_t TrackJobBaseNew::fetchParticleAddresses()
+    st_status_t tjob_t::fetchParticleAddresses()
     {
-        _this_t::status_t status = this->doFetchParticleAddresses();
+        st_status_t status = this->doFetchParticleAddresses();
 
         if( ( status == st::ARCH_STATUS_SUCCESS ) &&
             ( this->requiresCollecting() ) )
@@ -244,23 +238,22 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t TrackJobBaseNew::clearParticleAddresses(
-        _this_t::size_type const index )
+    st_status_t tjob_t::clearParticleAddresses( st_size_t const index )
     {
         return this->doClearParticleAddresses( index );
     }
 
-    _this_t::status_t TrackJobBaseNew::clearAllParticleAddresses()
+    st_status_t tjob_t::clearAllParticleAddresses()
     {
         return this->doClearAllParticleAddresses();
     }
 
-    bool TrackJobBaseNew::canFetchParticleAddresses() const SIXTRL_NOEXCEPT
+    bool tjob_t::canFetchParticleAddresses() const SIXTRL_NOEXCEPT
     {
         return ( this->doGetPtrParticlesAddrBuffer() != nullptr );
     }
 
-    bool TrackJobBaseNew::hasParticleAddresses() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasParticleAddresses() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( !this->m_has_particle_addresses ) ||
             ( ( this->m_has_particle_addresses ) &&
@@ -269,11 +262,10 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_has_particle_addresses;
     }
 
-    TrackJobBaseNew::particles_addr_t const*
-    TrackJobBaseNew::particleAddresses(
-        _this_t::size_type const index ) const SIXTRL_NOEXCEPT
+    tjob_t::particles_addr_t const* tjob_t::particleAddresses(
+        st_size_t const index ) const SIXTRL_NOEXCEPT
     {
-        using ptr_paddr_t = TrackJobBaseNew::particles_addr_t const*;
+        using ptr_paddr_t = tjob_t::particles_addr_t const*;
         ptr_paddr_t ptr_paddr = nullptr;
 
         if( ( this->doGetPtrParticlesAddrBuffer() != nullptr ) &&
@@ -287,14 +279,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return ptr_paddr;
     }
 
-    _this_t::buffer_t const*
-    TrackJobBaseNew::ptrParticleAddressesBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::buffer_t const*
+    tjob_t::ptrParticleAddressesBuffer() const SIXTRL_NOEXCEPT
     {
         return this->doGetPtrParticlesAddrBuffer();
     }
 
-    _this_t::c_buffer_t const*
-    TrackJobBaseNew::ptrCParticleAddressesBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t const*
+    tjob_t::ptrCParticleAddressesBuffer() const SIXTRL_NOEXCEPT
     {
         return ( this->doGetPtrParticlesAddrBuffer() != nullptr )
             ? this->doGetPtrParticlesAddrBuffer()->getCApiPtr() : nullptr;
@@ -302,21 +294,19 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    TrackJobBaseNew::track_status_t TrackJobBaseNew::trackUntil(
-        _this_t::size_type const until_turn )
+    tjob_t::track_status_t tjob_t::trackUntil( st_size_t const until_turn )
     {
         return this->doTrackUntilTurn( until_turn );
     }
 
-    TrackJobBaseNew::track_status_t TrackJobBaseNew::trackElemByElem(
-        _this_t::size_type const until_turn_elem_by_elem )
+    tjob_t::track_status_t tjob_t::trackElemByElem(
+        st_size_t const until_turn_elem_by_elem )
     {
         return this->doTrackElemByElem( until_turn_elem_by_elem );
     }
 
-    TrackJobBaseNew::track_status_t TrackJobBaseNew::trackLine(
-        _this_t::size_type const be_begin_index,
-        _this_t::size_type const be_end_index,
+    tjob_t::track_status_t tjob_t::trackLine(
+        st_size_t const be_begin_index, st_size_t const be_end_index,
         bool const finish_turn )
     {
         return this->doTrackLine( be_begin_index, be_end_index, finish_turn );
@@ -324,16 +314,16 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::status_t TrackJobBaseNew::reset(
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF be_buffer,
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+    st_status_t tjob_t::reset(
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF be_buffer,
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
         size_type const until_turn_elem_by_elem  )
     {
-        using c_buffer_t = _this_t::c_buffer_t;
-        using clear_flag_t = TrackJobBaseNew::clear_flag_t;
+        using c_buffer_t = tjob_t::c_buffer_t;
+        using clear_flag_t = tjob_t::clear_flag_t;
 
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         c_buffer_t* ptr_pb  = particles_buffer.getCApiPtr();
         c_buffer_t* ptr_eb  = be_buffer.getCApiPtr();
@@ -358,17 +348,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t TrackJobBaseNew::reset(
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        _this_t::size_type const pset_index,
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF beam_elements_buffer,
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _this_t::size_type const until_turn_elem_by_elem  )
+    st_status_t tjob_t::reset(
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
+        st_size_t const pset_index,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF beam_elements_buffer,
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem  )
     {
-        _this_t::c_buffer_t* ptr_out = ( ptr_output_buffer != nullptr )
+        tjob_t::c_buffer_t* ptr_out = ( ptr_output_buffer != nullptr )
             ? ptr_output_buffer->getCApiPtr() : nullptr;
 
-        _this_t::status_t status = TrackJobBaseNew::reset(
+        st_status_t status = tjob_t::reset(
             particles_buffer.getCApiPtr(), size_t{ 1 }, &pset_index,
                 beam_elements_buffer.getCApiPtr(), ptr_out,
                     until_turn_elem_by_elem );
@@ -382,13 +372,13 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t TrackJobBaseNew::reset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _this_t::size_type const until_turn_elem_by_elem  )
+    st_status_t tjob_t::reset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem  )
     {
-        using clear_flag_t = TrackJobBaseNew::clear_flag_t;
+        using clear_flag_t = tjob_t::clear_flag_t;
 
         clear_flag_t const clear_flags = this->doPrepareResetClearFlags(
             particles_buffer, this->numParticleSets(),
@@ -401,36 +391,36 @@ namespace SIXTRL_CXX_NAMESPACE
             until_turn_elem_by_elem );
     }
 
-    _this_t::status_t TrackJobBaseNew::reset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::size_type const particle_set_index,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _this_t::size_type const until_turn_elem_by_elem  )
+    st_status_t tjob_t::reset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        st_size_t const particle_set_index,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT be_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem  )
     {
-        return TrackJobBaseNew::reset( particles_buffer,
-            _this_t::size_type{ 1 }, &particle_set_index, be_buffer,
+        return tjob_t::reset( particles_buffer,
+            st_size_t{ 1 }, &particle_set_index, be_buffer,
                 ptr_output_buffer, until_turn_elem_by_elem );
     }
 
-    _this_t::status_t TrackJobBaseNew::reset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::size_type const num_particle_sets,
-        _this_t::size_type const* SIXTRL_RESTRICT pset_indices_begin,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _this_t::size_type const until_turn_elem_by_elem  )
+    st_status_t tjob_t::reset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        st_size_t const num_particle_sets,
+        st_size_t const* SIXTRL_RESTRICT pset_indices_begin,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem  )
     {
-        using size_t = _this_t::size_type;
+        using size_t = st_size_t;
 
-        TrackJobBaseNew::clear_flag_t const clear_flags =
+        tjob_t::clear_flag_t const clear_flags =
             this->doPrepareResetClearFlags( particles_buffer,
                 num_particle_sets, pset_indices_begin, beam_elements_buffer,
                     ptr_output_buffer, until_turn_elem_by_elem );
 
         this->doClear( clear_flags );
 
-        _this_t::status_t status = st::ARCH_STATUS_SUCCESS;
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
 
         if( ( pset_indices_begin != nullptr ) &&
             ( num_particle_sets > size_t{ 0 } ) )
@@ -455,12 +445,12 @@ namespace SIXTRL_CXX_NAMESPACE
     /* --------------------------------------------------------------------- */
 
     /*
-    _this_t::status_t TrackJobBaseNew::selectParticleSets(
-        _this_t::size_type const num_particle_sets,
-        _this_t::size_type const*
+    st_status_t tjob_t::selectParticleSets(
+        st_size_t const num_particle_sets,
+        st_size_t const*
             SIXTRL_RESTRICT particle_set_indices_begin )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         if( this->ptrCParticlesBuffer() != nullptr )
         {
@@ -472,14 +462,14 @@ namespace SIXTRL_CXX_NAMESPACE
     }
     */
 
-    _this_t::status_t TrackJobBaseNew::selectParticleSet(
-        _this_t::size_type const particle_set_index )
+    st_status_t tjob_t::selectParticleSet(
+        st_size_t const particle_set_index )
     {
-        using buffer_t   = _this_t::buffer_t;
-        using c_buffer_t = _this_t::c_buffer_t;
-        using size_t = _this_t::size_type;
+        using buffer_t   = tjob_t::buffer_t;
+        using c_buffer_t = tjob_t::c_buffer_t;
+        using size_t = st_size_t;
 
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         buffer_t*   ptr_particles_buffer   = this->ptrOutputBuffer();
         buffer_t*   ptr_beam_elem_buffer   = this->ptrBeamElementsBuffer();
@@ -555,10 +545,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::status_t TrackJobBaseNew::assignOutputBuffer(
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF output_buffer )
+    st_status_t tjob_t::assignOutputBuffer(
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF output_buffer )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         if( this->doAssignNewOutputBuffer( output_buffer.getCApiPtr() ) )
         {
@@ -576,29 +566,29 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t TrackJobBaseNew::assignOutputBuffer(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer )
+    st_status_t tjob_t::assignOutputBuffer(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer )
     {
         return this->doAssignNewOutputBuffer( ptr_output_buffer );
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::size_type TrackJobBaseNew::numParticleSets() const SIXTRL_NOEXCEPT
+    st_size_t tjob_t::numParticleSets() const SIXTRL_NOEXCEPT
     {
         return this->m_particle_set_indices.size();
     }
 
-    _this_t::size_type const*
-    TrackJobBaseNew::particleSetIndicesBegin() const SIXTRL_NOEXCEPT
+    st_size_t const*
+    tjob_t::particleSetIndicesBegin() const SIXTRL_NOEXCEPT
     {
         return this->m_particle_set_indices.data();
     }
 
-    _this_t::size_type const*
-    TrackJobBaseNew::particleSetIndicesEnd() const SIXTRL_NOEXCEPT
+    st_size_t const*
+    tjob_t::particleSetIndicesEnd() const SIXTRL_NOEXCEPT
     {
-        _this_t::size_type const* ptr =
+        st_size_t const* ptr =
             this->particleSetIndicesBegin();
 
         SIXTRL_ASSERT( ptr != nullptr );
@@ -606,30 +596,30 @@ namespace SIXTRL_CXX_NAMESPACE
         return ptr;
     }
 
-    _this_t::size_type TrackJobBaseNew::particleSetIndex(
-        _this_t::size_type const idx ) const
+    st_size_t tjob_t::particleSetIndex(
+        st_size_t const idx ) const
     {
         return this->m_particle_set_indices.at( idx );
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::num_particles_t TrackJobBaseNew::particleSetBeginIndexOffset(
-        _this_t::size_type const pset_index ) const
+    tjob_t::num_particles_t tjob_t::particleSetBeginIndexOffset(
+        st_size_t const pset_index ) const
     {
         return this->m_particle_set_begin_offsets.at( pset_index );
     }
 
-    _this_t::num_particles_t TrackJobBaseNew::particleSetEndIndexOffset(
-        _this_t::size_type const pset_index ) const
+    tjob_t::num_particles_t tjob_t::particleSetEndIndexOffset(
+        st_size_t const pset_index ) const
     {
         return this->m_particle_set_end_offsets.at( pset_index );
     }
 
-    _this_t::num_particles_t TrackJobBaseNew::numParticlesInSet(
-        _this_t::size_type const pset_index ) const SIXTRL_NOEXCEPT
+    tjob_t::num_particles_t tjob_t::numParticlesInSet(
+        st_size_t const pset_index ) const SIXTRL_NOEXCEPT
     {
-        using num_particles_t = _this_t::num_particles_t;
+        using num_particles_t = tjob_t::num_particles_t;
         num_particles_t num_particles_in_set = num_particles_t{ 0 };
 
         if( ( pset_index < this->numParticleSets() ) &&
@@ -653,19 +643,19 @@ namespace SIXTRL_CXX_NAMESPACE
         return num_particles_in_set;
     }
 
-    _this_t::num_particles_t const*
-    TrackJobBaseNew::particleSetBeginOffsetsBegin() const SIXTRL_NOEXCEPT
+    tjob_t::num_particles_t const*
+    tjob_t::particleSetBeginOffsetsBegin() const SIXTRL_NOEXCEPT
     {
         return this->m_particle_set_begin_offsets.data();
     }
 
-    _this_t::num_particles_t const*
-    TrackJobBaseNew::particleSetBeginOffsetsEnd() const SIXTRL_NOEXCEPT
+    tjob_t::num_particles_t const*
+    tjob_t::particleSetBeginOffsetsEnd() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->numParticleSets() ==
                        this->m_particle_set_begin_offsets.size() );
 
-        _this_t::num_particles_t const* end_ptr =
+        tjob_t::num_particles_t const* end_ptr =
             this->particleSetBeginOffsetsBegin();
 
         if( end_ptr != nullptr )
@@ -676,19 +666,19 @@ namespace SIXTRL_CXX_NAMESPACE
         return end_ptr;
     }
 
-    _this_t::num_particles_t const*
-    TrackJobBaseNew::particleSetEndOffsetsBegin() const SIXTRL_NOEXCEPT
+    tjob_t::num_particles_t const*
+    tjob_t::particleSetEndOffsetsBegin() const SIXTRL_NOEXCEPT
     {
         return this->m_particle_set_end_offsets.data();
     }
 
-    _this_t::num_particles_t const*
-    TrackJobBaseNew::particleSetEndOffsetsEnd() const SIXTRL_NOEXCEPT
+    tjob_t::num_particles_t const*
+    tjob_t::particleSetEndOffsetsEnd() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->numParticleSets() ==
                        this->m_particle_set_end_offsets.size() );
 
-        _this_t::num_particles_t const* end_ptr =
+        tjob_t::num_particles_t const* end_ptr =
             this->particleSetEndOffsetsBegin();
 
         if( end_ptr != nullptr )
@@ -699,81 +689,81 @@ namespace SIXTRL_CXX_NAMESPACE
         return end_ptr;
     }
 
-    _this_t::num_particles_t
-    TrackJobBaseNew::totalNumParticles() const SIXTRL_NOEXCEPT
+    tjob_t::num_particles_t
+    tjob_t::totalNumParticles() const SIXTRL_NOEXCEPT
     {
         return this->m_total_num_particles;
     }
 
-    _this_t::num_particles_t
-    TrackJobBaseNew::totalNumParticlesInParticleSets() const SIXTRL_NOEXCEPT
+    tjob_t::num_particles_t
+    tjob_t::totalNumParticlesInParticleSets() const SIXTRL_NOEXCEPT
     {
         return this->m_total_num_particles_in_sets;
     }
 
-    _this_t::size_type
-    TrackJobBaseNew::totalNumOfAvailableParticleSets() const SIXTRL_NOEXCEPT
+    st_size_t
+    tjob_t::totalNumOfAvailableParticleSets() const SIXTRL_NOEXCEPT
     {
         return this->m_num_particle_sets_in_buffer;
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::particle_index_t
-    TrackJobBaseNew::minParticleId() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t
+    tjob_t::minParticleId() const SIXTRL_NOEXCEPT
     {
         return this->m_min_particle_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBaseNew::maxParticleId() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t
+    tjob_t::maxParticleId() const SIXTRL_NOEXCEPT
     {
         return this->m_max_particle_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBaseNew::minElementId()  const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t
+    tjob_t::minElementId()  const SIXTRL_NOEXCEPT
     {
         return this->m_min_element_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBaseNew::maxElementId()  const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t
+    tjob_t::maxElementId()  const SIXTRL_NOEXCEPT
     {
         return this->m_max_element_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBaseNew::minInitialTurnId() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t
+    tjob_t::minInitialTurnId() const SIXTRL_NOEXCEPT
     {
         return this->m_min_initial_turn_id;
     }
 
-    _this_t::particle_index_t
-    TrackJobBaseNew::maxInitialTurnId() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t
+    tjob_t::maxInitialTurnId() const SIXTRL_NOEXCEPT
     {
         return this->m_max_initial_turn_id;
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::size_type
-    TrackJobBaseNew::totalNumOfAvailableBeamElements() const SIXTRL_NOEXCEPT
+    st_size_t
+    tjob_t::totalNumOfAvailableBeamElements() const SIXTRL_NOEXCEPT
     {
         return this->m_num_beam_elements_in_buffer;
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::buffer_t*
-    TrackJobBaseNew::ptrParticlesBuffer() SIXTRL_NOEXCEPT
+    tjob_t::buffer_t*
+    tjob_t::ptrParticlesBuffer() SIXTRL_NOEXCEPT
     {
-        return const_cast< st::_this_t::buffer_t* >( static_cast<
+        return const_cast< st::tjob_t::buffer_t* >( static_cast<
             st::TrackJobBaseNew const& >( *this ).ptrParticlesBuffer() );
     }
 
-    _this_t::buffer_t const*
-    TrackJobBaseNew::ptrParticlesBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::buffer_t const*
+    tjob_t::ptrParticlesBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( this->m_ptr_particles_buffer == nullptr ) ||
             ( this->m_ptr_particles_buffer->getCApiPtr() ==
@@ -782,15 +772,15 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_ptr_particles_buffer;
     }
 
-    _this_t::c_buffer_t*
-    TrackJobBaseNew::ptrCParticlesBuffer() SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t*
+    tjob_t::ptrCParticlesBuffer() SIXTRL_NOEXCEPT
     {
-        return const_cast< st::_this_t::c_buffer_t* >( static_cast<
+        return const_cast< st::tjob_t::c_buffer_t* >( static_cast<
             st::TrackJobBaseNew const& >( *this ).ptrCParticlesBuffer() );
     }
 
-    _this_t::c_buffer_t const*
-    TrackJobBaseNew::ptrCParticlesBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t const*
+    tjob_t::ptrCParticlesBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( this->m_ptr_particles_buffer == nullptr ) ||
             ( this->m_ptr_particles_buffer->getCApiPtr() ==
@@ -801,15 +791,15 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::buffer_t*
-    TrackJobBaseNew::ptrBeamElementsBuffer() SIXTRL_NOEXCEPT
+    tjob_t::buffer_t*
+    tjob_t::ptrBeamElementsBuffer() SIXTRL_NOEXCEPT
     {
-        return const_cast< st::_this_t::buffer_t* >( static_cast<
+        return const_cast< st::tjob_t::buffer_t* >( static_cast<
             st::TrackJobBaseNew const& >( *this ).ptrBeamElementsBuffer() );
     }
 
-    _this_t::buffer_t const*
-    TrackJobBaseNew::ptrBeamElementsBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::buffer_t const*
+    tjob_t::ptrBeamElementsBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( this->m_ptr_beam_elem_buffer == nullptr ) ||
             ( this->m_ptr_beam_elem_buffer->getCApiPtr() ==
@@ -818,15 +808,15 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_ptr_beam_elem_buffer;
     }
 
-    _this_t::c_buffer_t*
-    TrackJobBaseNew::ptrCBeamElementsBuffer() SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t*
+    tjob_t::ptrCBeamElementsBuffer() SIXTRL_NOEXCEPT
     {
-        return const_cast< st::_this_t::c_buffer_t* >( static_cast<
+        return const_cast< st::tjob_t::c_buffer_t* >( static_cast<
             st::TrackJobBaseNew const& >( *this ).ptrCBeamElementsBuffer() );
     }
 
-    _this_t::c_buffer_t const*
-    TrackJobBaseNew::ptrCBeamElementsBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::c_buffer_t const*
+    tjob_t::ptrCBeamElementsBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( this->m_ptr_beam_elem_buffer == nullptr ) ||
             ( this->m_ptr_beam_elem_buffer->getCApiPtr() ==
@@ -835,14 +825,515 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_ptr_c_beam_elem_buffer;
     }
 
+    /* ----------------------------------------------------------------- */
+
+    tjob_t::assign_item_t* tjob_t::add_assign_address_item(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF assign_item_to_add )
+    {
+        tjob_t::assign_item_t* item = nullptr;
+
+        if( assign_item_to_add.valid() )
+        {
+            tjob_t::assign_item_key_t const key =
+            tjob_t::assign_item_key_t{
+                assign_item_to_add.getDestBufferId(),
+                assign_item_to_add.getSrcBufferId() };
+
+            st_size_t item_index = std::numeric_limits< st_size_t >::max();
+            st_status_t const status = this->do_add_assign_address_item(
+                assign_item_to_add, &item_index );
+
+            if( status == st::ARCH_STATUS_SUCCESS )
+            {
+                item = this->do_get_assign_address_item( key, item_index );
+            }
+        }
+
+        return item;
+    }
+
+    tjob_t::assign_item_t* tjob_t::add_assign_address_item(
+        tjob_t::object_type_id_t const dest_type_id,
+        st_size_t const dest_buffer_id,
+        st_size_t const dest_elem_index,
+        st_size_t const dest_pointer_offset,
+        tjob_t::object_type_id_t const src_type_id,
+        st_size_t const src_buffer_id,
+        st_size_t const src_elem_index,
+        st_size_t const src_pointer_offset )
+    {
+        return this->add_assign_address_item( tjob_t::assign_item_t{
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset } );
+    }
+
+    st_status_t tjob_t::remove_assign_address_item(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF item_to_remove )
+    {
+        using key_t = tjob_t::assign_item_key_t;
+        key_t const key = key_t { item_to_remove.getDestBufferId(),
+                                  item_to_remove.getSrcBufferId() };
+        st_size_t const item_index = this->do_find_assign_address_item(
+            item_to_remove );
+        return this->do_remove_assign_address_item( key, item_index );
+    }
+
+    st_status_t tjob_t::remove_assign_address_item(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+        st_size_t const index_of_item_to_remove )
+    {
+        return this->do_remove_assign_address_item(
+            key, index_of_item_to_remove );
+    }
+
+    bool tjob_t::has_assign_address_item( tjob_t::assign_item_t const&
+        SIXTRL_RESTRICT_REF assign_item ) const SIXTRL_NOEXCEPT
+    {
+        st_size_t const item_index = this->do_find_assign_address_item(
+            assign_item );
+
+        return ( item_index < this->num_assign_items(
+            assign_item.getDestBufferId(), assign_item.getSrcBufferId() ) );
+    }
+
+    bool tjob_t::has_assign_address_item(
+        tjob_t::object_type_id_t const dest_type_id,
+        st_size_t const dest_buffer_id,
+        st_size_t const dest_elem_index,
+        st_size_t const dest_pointer_offset,
+        tjob_t::object_type_id_t const src_type_id,
+        st_size_t const src_buffer_id,
+        st_size_t const src_elem_index,
+        st_size_t const src_pointer_offset ) const SIXTRL_NOEXCEPT
+    {
+        return this->has_assign_address_item( tjob_t::assign_item_t{
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset } );
+    }
+
+    st_size_t tjob_t::index_of_assign_address_item( tjob_t::assign_item_t
+        const& SIXTRL_RESTRICT_REF assign_item ) const SIXTRL_NOEXCEPT
+    {
+        return this->do_find_assign_address_item( assign_item );
+    }
+
+    st_size_t tjob_t::index_of_assign_address_item(
+        tjob_t::object_type_id_t const dest_type_id,
+        st_size_t const dest_buffer_id,
+        st_size_t const dest_elem_index,
+        st_size_t const dest_pointer_offset,
+        tjob_t::object_type_id_t const src_type_id,
+        st_size_t const src_buffer_id,
+        st_size_t const src_elem_index,
+        st_size_t const src_pointer_offset ) const SIXTRL_NOEXCEPT
+    {
+        return this->do_find_assign_address_item( tjob_t::assign_item_t{
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset } );
+    }
+
+    bool tjob_t::has_assign_items( st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        return ( this->num_assign_items( dest_buffer_id, src_buffer_id ) >
+                    st_size_t{ 0 } );
+    }
+
+    st_size_t tjob_t::num_assign_items( st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        st_size_t num_items = st_size_t{ 0 };
+
+        auto it = this->m_assign_address_items.find(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id } );
+
+        if( it != this->m_assign_address_items.end() )
+        {
+            num_items = it->second.getNumObjects();
+        }
+
+        return num_items;
+    }
+
+    st_size_t tjob_t::num_distinct_available_assign_address_items_dest_src_pairs()
+        const SIXTRL_NOEXCEPT
+    {
+        return this->m_assign_item_keys.size();
+    }
+
+    st_size_t tjob_t::available_assign_address_items_dest_src_pairs(
+        st_size_t const max_num_pairs,
+        tjob_t::assign_item_key_t* pairs_begin ) const SIXTRL_NOEXCEPT
+    {
+        using size_t = st_size_t;
+        size_t num_pairs = size_t{ 0 };
+
+        if( ( max_num_pairs > size_t{ 0 } ) && ( pairs_begin != nullptr ) &&
+            ( !this->m_assign_address_items.empty() ) )
+        {
+            tjob_t::assign_item_key_t* pairs_end = pairs_begin;
+            std::advance( pairs_end, max_num_pairs );
+
+            num_pairs = this->available_assign_address_items_dest_src_pairs(
+                pairs_begin, pairs_end );
+        }
+
+        return num_pairs;
+    }
+
+    tjob_t::c_buffer_t* tjob_t::buffer_by_buffer_id(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = tjob_t::c_buffer_t*;
+        return const_cast< ptr_t >( static_cast< tjob_t const& >(
+            *this ).buffer_by_buffer_id( buffer_id ) );
+    }
+
+    tjob_t::c_buffer_t const* tjob_t::buffer_by_buffer_id(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::c_buffer_t const* ptr_buffer = nullptr;
+
+        switch( buffer_id )
+        {
+            case st::ARCH_PARTICLES_BUFFER_ID:
+            {
+                ptr_buffer = this->ptrCParticlesBuffer();
+                break;
+            }
+
+            case st::ARCH_BEAM_ELEMENTS_BUFFER_ID:
+            {
+                ptr_buffer = this->ptrCBeamElementsBuffer();
+                break;
+            }
+
+            case st::ARCH_OUTPUT_BUFFER_ID:
+            {
+                ptr_buffer = this->ptrCOutputBuffer();
+                break;
+            }
+
+            case st::ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID:
+            {
+                if( this->m_my_elem_by_elem_buffer.get() != nullptr )
+                {
+                    ptr_buffer = this->m_my_elem_by_elem_buffer->getCApiPtr();
+                }
+
+                break;
+            }
+
+            case st::ARCH_PARTICLE_ADDR_BUFFER_ID:
+            {
+                if( this->ptrParticleAddressesBuffer() != nullptr )
+                {
+                    ptr_buffer = this->ptrParticleAddressesBuffer(
+                        )->getCApiPtr();
+                }
+                break;
+            }
+
+            default:
+            {
+                if( ( buffer_id >= st::ARCH_MIN_USER_DEFINED_BUFFER_ID ) &&
+                    ( buffer_id <= st::ARCH_MAX_USER_DEFINED_BUFFER_ID ) )
+                {
+                    ptr_buffer = this->ptr_stored_buffer( buffer_id );
+                }
+            }
+        };
+
+        return ptr_buffer;
+    }
+
+    bool tjob_t::is_buffer_by_buffer_id(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        return ( ( buffer_id == st::ARCH_PARTICLES_BUFFER_ID ) ||
+                 ( buffer_id == st::ARCH_BEAM_ELEMENTS_BUFFER_ID ) ||
+                 ( buffer_id == st::ARCH_OUTPUT_BUFFER_ID ) ||
+                 ( buffer_id == st::ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID ) ||
+                 ( buffer_id == st::ARCH_PARTICLE_ADDR_BUFFER_ID ) ||
+                 ( ( buffer_id >= st::ARCH_MIN_USER_DEFINED_BUFFER_ID ) &&
+                   ( buffer_id <= st::ARCH_MAX_USER_DEFINED_BUFFER_ID ) ) );
+    }
+
+    bool tjob_t::is_raw_memory_by_buffer_id(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        return ( ( buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+                 ( !this->is_buffer_by_buffer_id( buffer_id ) ) );
+    }
+
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object) const*
+    tjob_t::assign_items_begin( st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        auto it = this->m_assign_address_items.find(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id } );
+
+        return ( it != this->m_assign_address_items.end() )
+            ? ::NS(Buffer_get_const_objects_begin)( it->second.getCApiPtr() )
+            : nullptr;
+    }
+
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object) const*
+    tjob_t::assign_items_end( st_size_t const dest_buffer_id,
+        st_size_t const src_buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        auto it = this->m_assign_address_items.find(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id } );
+
+        return ( it != this->m_assign_address_items.end() )
+            ? ::NS(Buffer_get_const_objects_begin)( it->second.getCApiPtr() )
+            : nullptr;
+    }
+
+    tjob_t::assign_item_key_t const*
+    tjob_t::assign_item_dest_src_begin() const SIXTRL_NOEXCEPT
+    {
+        return this->m_assign_item_keys.data();
+    }
+
+    tjob_t::assign_item_key_t const*
+    tjob_t::assign_item_dest_src_end() const SIXTRL_NOEXCEPT
+    {
+        tjob_t::assign_item_key_t const* end_ptr =
+            this->assign_item_dest_src_begin();
+
+        if( ( end_ptr != nullptr ) && ( this->m_assign_item_keys.empty() ) )
+        {
+            std::advance( end_ptr, this->m_assign_address_items.size() );
+        }
+
+        return end_ptr;
+    }
+
+    st_size_t tjob_t::total_num_assign_items() const SIXTRL_NOEXCEPT
+    {
+        using size_t = st_size_t;
+        size_t total_num_items = size_t{ 0 };
+
+        auto it = this->m_assign_address_items.begin();
+        auto end = this->m_assign_address_items.end();
+
+        for( ; it != end ; ++it ) total_num_items += it->second.getNumObjects();
+        return total_num_items;
+    }
+
+    tjob_t::assign_item_t const* tjob_t::ptr_assign_address_item(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF
+            assign_address_item ) const SIXTRL_NOEXCEPT
+    {
+        st_size_t const assign_item_idx =
+            this->do_find_assign_address_item( assign_address_item );
+
+        return this->do_get_assign_address_item( tjob_t::assign_item_key_t{
+                assign_address_item.getDestBufferId(),
+                assign_address_item.getSrcBufferId() }, assign_item_idx );
+    }
+
+
+    tjob_t::assign_item_t const* tjob_t::ptr_assign_address_item(
+        st_size_t const dest_buffer_id, st_size_t const src_buffer_id,
+        st_size_t const assign_item_index ) const SIXTRL_NOEXCEPT
+    {
+        return this->do_get_assign_address_item(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id },
+                assign_item_index );
+    }
+
+    tjob_t::assign_item_t const* tjob_t::ptr_assign_address_item(
+        tjob_t::object_type_id_t const dest_type_id,
+        st_size_t const dest_buffer_id,
+        st_size_t const dest_elem_index,
+        st_size_t const dest_pointer_offset,
+        tjob_t::object_type_id_t const src_type_id,
+        st_size_t const src_buffer_id,
+        st_size_t const src_elem_index,
+        st_size_t const src_pointer_offset ) const SIXTRL_NOEXCEPT
+    {
+        return this->ptr_assign_address_item(
+            tjob_t::assign_item_t{ dest_type_id, dest_buffer_id,
+                dest_elem_index, dest_pointer_offset, src_type_id,
+                    src_buffer_id, src_elem_index, src_pointer_offset } );
+    }
+
+    st_status_t tjob_t::commit_address_assignments()
+    {
+        return this->do_commit_address_assignments();
+    }
+
+    st_status_t tjob_t::assign_all_addresses()
+    {
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+
+        auto it = this->m_assign_address_items.begin();
+        auto end = this->m_assign_address_items.end();
+
+        for( ; it != end ; ++it )
+        {
+            status = this->do_perform_address_assignments( it->first );
+            if( status != st::ARCH_STATUS_SUCCESS ) break;
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::assign_addresses(
+        st_size_t const dest_buffer_id, st_size_t const src_buffer_id )
+    {
+        return this->do_perform_address_assignments(
+            tjob_t::assign_item_key_t{ dest_buffer_id, src_buffer_id } );
+    }
+
     /* ---------------------------------------------------------------- */
 
-    bool TrackJobBaseNew::hasOutputBuffer() const SIXTRL_NOEXCEPT
+    st_size_t tjob_t::stored_buffers_capacity() const SIXTRL_NOEXCEPT
+    {
+        return this->m_stored_buffers.capacity();
+    }
+
+    st_status_t tjob_t::reserve_stored_buffers_capacity(
+        st_size_t const capacity )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        if( capacity < this->m_stored_buffers.capacity() )
+        {
+            this->m_stored_buffers.reserve( capacity );
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    bool tjob_t::has_stored_buffers() const SIXTRL_NOEXCEPT
+    {
+        return ( this->num_stored_buffers() > st_size_t{ 0 } );
+    }
+
+    st_size_t tjob_t::num_stored_buffers() const SIXTRL_NOEXCEPT
+    {
+        SIXTRL_ASSERT( std::count_if( this->m_stored_buffers.begin(),
+            this->m_stored_buffers.end(),
+            []( tjob_t::buffer_store_t const& s) { return s.active(); } ) ==
+            static_cast< std::ptrdiff_t >( this->m_num_stored_buffers ) );
+
+        SIXTRL_ASSERT( this->m_stored_buffers.size() >=
+                       this->m_num_stored_buffers );
+
+        return this->m_num_stored_buffers;
+    }
+
+    st_size_t tjob_t::min_stored_buffer_id() const SIXTRL_NOEXCEPT
+    {
+        return ( this->has_stored_buffers() )
+            ? st::ARCH_MIN_USER_DEFINED_BUFFER_ID : st::ARCH_ILLEGAL_BUFFER_ID;
+    }
+
+    st_size_t tjob_t::max_stored_buffer_id() const SIXTRL_NOEXCEPT
+    {
+        st_size_t max_stored_buffers_id = this->min_stored_buffer_id();
+
+        if( max_stored_buffers_id != st::ARCH_ILLEGAL_BUFFER_ID )
+        {
+            SIXTRL_ASSERT( this->m_stored_buffers.size() >= st_size_t{ 1 } );
+            max_stored_buffers_id += this->m_stored_buffers.size();
+            max_stored_buffers_id -= st_size_t{ 1 };
+        }
+
+        return max_stored_buffers_id;
+    }
+
+    bool tjob_t::owns_stored_buffer( st_size_t const buffer_id
+        ) const SIXTRL_NOEXCEPT
+    {
+        auto ptr_buffer_store = this->do_get_ptr_buffer_store( buffer_id );
+        return ( ( ptr_buffer_store != nullptr ) &&
+                 ( ptr_buffer_store->owns_buffer() ) );
+    }
+
+    st_status_t tjob_t::remove_stored_buffer( st_size_t const buffer_index )
+    {
+        return this->do_remove_stored_buffer( buffer_index );
+    }
+
+    tjob_t::buffer_t& tjob_t::stored_cxx_buffer( st_size_t const buffer_id )
+    {
+        return const_cast< tjob_t::buffer_t& >( static_cast< tjob_t const& >(
+            *this ).stored_cxx_buffer( buffer_id ) );
+    }
+
+    tjob_t::buffer_t const& tjob_t::stored_cxx_buffer(
+        st_size_t const buffer_id ) const
+    {
+        tjob_t::buffer_t const* ptr_buffer =
+            this->ptr_stored_cxx_buffer( buffer_id );
+
+        if( ptr_buffer == nullptr )
+        {
+            throw std::runtime_error(
+                "stored buffer does not have a c++ representation" );
+        }
+
+        return *ptr_buffer;
+    }
+
+    tjob_t::buffer_t* tjob_t::ptr_stored_cxx_buffer(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::buffer_t* >( static_cast< tjob_t const& >(
+            *this ).ptr_stored_cxx_buffer( buffer_id ) );
+    }
+
+    tjob_t::buffer_t const* tjob_t::ptr_stored_cxx_buffer(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::buffer_store_t const* ptr_stored_buffer =
+            this->do_get_ptr_buffer_store( buffer_id );
+
+        return ( ptr_stored_buffer != nullptr )
+            ? ptr_stored_buffer->ptr_cxx_buffer() : nullptr;
+    }
+
+    tjob_t::c_buffer_t* tjob_t::ptr_stored_buffer(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::c_buffer_t* >( static_cast<
+            tjob_t const& >( *this ).ptr_stored_buffer( buffer_id ) );
+    }
+
+    tjob_t::c_buffer_t const* tjob_t::ptr_stored_buffer(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::buffer_store_t const* ptr_stored_buffer =
+            this->do_get_ptr_buffer_store( buffer_id );
+
+        return ( ptr_stored_buffer != nullptr )
+            ? ptr_stored_buffer->ptr_buffer() : nullptr;
+    }
+
+    st_status_t tjob_t::push_stored_buffer(
+        st_size_t const buffer_id )
+    {
+        return this->do_push_stored_buffer( buffer_id );
+    }
+
+    st_status_t tjob_t::collect_stored_buffer(
+        st_size_t const buffer_id )
+    {
+        return this->do_collect_stored_buffer( buffer_id );
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    bool tjob_t::hasOutputBuffer() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCOutputBuffer() != nullptr );
     }
 
-    bool TrackJobBaseNew::ownsOutputBuffer() const SIXTRL_NOEXCEPT
+    bool tjob_t::ownsOutputBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( this->m_my_output_buffer.get() == nullptr ) ||
             ( ( this->m_my_output_buffer.get() ==
@@ -854,12 +1345,12 @@ namespace SIXTRL_CXX_NAMESPACE
                  ( this->m_my_output_buffer.get() != nullptr ) );
     }
 
-    bool TrackJobBaseNew::hasElemByElemOutput() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasElemByElemOutput() const SIXTRL_NOEXCEPT
     {
         return this->m_has_elem_by_elem_output;
     }
 
-    bool TrackJobBaseNew::hasBeamMonitorOutput() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasBeamMonitorOutput() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( (  !this->m_has_beam_monitor_output ) ||
             ( ( this->m_has_beam_monitor_output ) &&
@@ -868,59 +1359,59 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_has_beam_monitor_output;
     }
 
-    _this_t::size_type
-    TrackJobBaseNew::beamMonitorsOutputBufferOffset() const SIXTRL_NOEXCEPT
+    st_size_t
+    tjob_t::beamMonitorsOutputBufferOffset() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( ( this->hasOutputBuffer() ) &&
               ( ::NS(Buffer_get_size)( this->ptrCOutputBuffer() ) >
                 this->m_be_mon_output_buffer_offset ) ) ||
             ( this->m_be_mon_output_buffer_offset ==
-                _this_t::size_type{ 0 } ) );
+                st_size_t{ 0 } ) );
 
         return this->m_be_mon_output_buffer_offset;
     }
 
-    _this_t::size_type
-    TrackJobBaseNew::elemByElemOutputBufferOffset() const SIXTRL_NOEXCEPT
+    st_size_t
+    tjob_t::elemByElemOutputBufferOffset() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( ( this->hasOutputBuffer() ) &&
               ( ::NS(Buffer_get_size)( this->ptrCOutputBuffer() ) >
                 this->m_elem_by_elem_output_offset ) ) ||
             ( this->m_elem_by_elem_output_offset ==
-                _this_t::size_type{ 0 } ) );
+                st_size_t{ 0 } ) );
 
         return this->m_elem_by_elem_output_offset;
     }
 
-    _this_t::particle_index_t
-    TrackJobBaseNew::untilTurnElemByElem() const SIXTRL_NOEXCEPT
+    tjob_t::particle_index_t
+    tjob_t::untilTurnElemByElem() const SIXTRL_NOEXCEPT
     {
         return this->m_until_turn_elem_by_elem;
     }
 
-    _this_t::size_type
-    TrackJobBaseNew::numElemByElemTurns() const SIXTRL_NOEXCEPT
+    st_size_t
+    tjob_t::numElemByElemTurns() const SIXTRL_NOEXCEPT
     {
         if( ( this->m_until_turn_elem_by_elem > this->m_min_initial_turn_id ) &&
-            ( this->m_min_initial_turn_id >= _this_t::particle_index_t{ 0 } ) )
+            ( this->m_min_initial_turn_id >= tjob_t::particle_index_t{ 0 } ) )
         {
             return static_cast< size_t >( this->m_until_turn_elem_by_elem -
                 this->m_min_initial_turn_id );
         }
 
-        return _this_t::size_type{ 0 };
+        return st_size_t{ 0 };
     }
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    _this_t::buffer_t* TrackJobBaseNew::ptrOutputBuffer() SIXTRL_RESTRICT
+    tjob_t::buffer_t* tjob_t::ptrOutputBuffer() SIXTRL_NOEXCEPT
     {
-        return const_cast< st::_this_t::buffer_t* >( static_cast<
+        return const_cast< st::tjob_t::buffer_t* >( static_cast<
             st::TrackJobBaseNew const& >( *this ).ptrOutputBuffer() );
     }
 
-    _this_t::buffer_t const*
-    TrackJobBaseNew::ptrOutputBuffer() const SIXTRL_RESTRICT
+    tjob_t::buffer_t const*
+    tjob_t::ptrOutputBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( this->m_ptr_output_buffer == nullptr ) ||
             ( this->m_ptr_output_buffer->getCApiPtr() ==
@@ -929,14 +1420,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_ptr_output_buffer;
     }
 
-    _this_t::c_buffer_t* TrackJobBaseNew::ptrCOutputBuffer() SIXTRL_RESTRICT
+    tjob_t::c_buffer_t* tjob_t::ptrCOutputBuffer() SIXTRL_NOEXCEPT
     {
-        return const_cast< st::_this_t::c_buffer_t* >( static_cast<
+        return const_cast< st::tjob_t::c_buffer_t* >( static_cast<
             st::TrackJobBaseNew const& >( *this ).ptrCOutputBuffer() );
     }
 
-    _this_t::c_buffer_t const*
-    TrackJobBaseNew::ptrCOutputBuffer() const SIXTRL_RESTRICT
+    tjob_t::c_buffer_t const*
+    tjob_t::ptrCOutputBuffer() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( ( this->m_ptr_output_buffer == nullptr ) ||
             ( this->m_ptr_output_buffer->getCApiPtr() ==
@@ -947,73 +1438,72 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    bool TrackJobBaseNew::hasBeamMonitors() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasBeamMonitors() const SIXTRL_NOEXCEPT
     {
         return !this->m_beam_monitor_indices.empty();
     }
 
-    _this_t::size_type TrackJobBaseNew::numBeamMonitors() const SIXTRL_NOEXCEPT
+    st_size_t tjob_t::numBeamMonitors() const SIXTRL_NOEXCEPT
     {
         return this->m_beam_monitor_indices.size();
     }
 
-    _this_t::size_type const*
-    TrackJobBaseNew::beamMonitorIndicesBegin() const SIXTRL_NOEXCEPT
+    st_size_t const*
+    tjob_t::beamMonitorIndicesBegin() const SIXTRL_NOEXCEPT
     {
         return this->m_beam_monitor_indices.data();
     }
 
-    _this_t::size_type const*
-    TrackJobBaseNew::beamMonitorIndicesEnd() const SIXTRL_NOEXCEPT
+    st_size_t const*
+    tjob_t::beamMonitorIndicesEnd() const SIXTRL_NOEXCEPT
     {
-        _this_t::size_type const* ptr = this->beamMonitorIndicesBegin();
+        st_size_t const* ptr = this->beamMonitorIndicesBegin();
         if( ptr != nullptr ) std::advance( ptr, this->numBeamMonitors() );
         return ptr;
     }
 
-    _this_t::size_type TrackJobBaseNew::beamMonitorIndex(
-        _this_t::size_type const idx ) const
+    st_size_t tjob_t::beamMonitorIndex(
+        st_size_t const idx ) const
     {
         return this->m_beam_monitor_indices.at( idx );
     }
 
     /* --------------------------------------------------------------------- */
 
-    bool TrackJobBaseNew::hasElemByElemConfig() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasElemByElemConfig() const SIXTRL_NOEXCEPT
     {
-        SIXTRL_ASSERT(
-            ( this->m_my_elem_by_elem_config.get() == nullptr ) ||
-            ( this->m_ptr_c_output_buffer != nullptr ) );
-
-        return ( ::NS(ElemByElemConfig_is_active)(
-            this->m_my_elem_by_elem_config.get() ) );
+        return ( this->ptrElemByElemConfig() != nullptr );
     }
 
-    _this_t::elem_by_elem_config_t const*
-    TrackJobBaseNew::ptrElemByElemConfig() const SIXTRL_NOEXCEPT
+    tjob_t::elem_by_elem_config_t const*
+    tjob_t::ptrElemByElemConfig() const SIXTRL_NOEXCEPT
     {
-        return this->m_my_elem_by_elem_config.get();
+        SIXTRL_ASSERT( this->m_my_elem_by_elem_buffer.get() != nullptr );
+        return ::NS(ElemByElemConfig_const_from_buffer)(
+            this->m_my_elem_by_elem_buffer->getCApiPtr(),
+                this->m_elem_by_elem_config_index );
     }
 
-    _this_t::elem_by_elem_config_t*
-    TrackJobBaseNew::ptrElemByElemConfig() SIXTRL_NOEXCEPT
+    tjob_t::elem_by_elem_config_t*
+    tjob_t::ptrElemByElemConfig() SIXTRL_NOEXCEPT
     {
-        return const_cast< st::TrackJobBaseNew::elem_by_elem_config_t* >(
-            static_cast< st::TrackJobBaseNew const& >(
-                *this ).ptrElemByElemConfig() );
+        SIXTRL_ASSERT( this->m_my_elem_by_elem_buffer.get() != nullptr );
+        return ::NS(ElemByElemConfig_from_buffer)(
+            this->m_my_elem_by_elem_buffer->getCApiPtr(),
+                this->m_elem_by_elem_config_index );
     }
 
-    bool TrackJobBaseNew::elemByElemRolling() const SIXTRL_NOEXCEPT
+    bool tjob_t::elemByElemRolling() const SIXTRL_NOEXCEPT
     {
-        return NS(ElemByElemConfig_is_rolling)( this->ptrElemByElemConfig() );
+        return ::NS(ElemByElemConfig_is_rolling)( this->ptrElemByElemConfig() );
     }
 
-    bool TrackJobBaseNew::defaultElemByElemRolling() const SIXTRL_NOEXCEPT
+    bool tjob_t::defaultElemByElemRolling() const SIXTRL_NOEXCEPT
     {
         return this->m_default_elem_by_elem_rolling;
     }
 
-    void TrackJobBaseNew::setDefaultElemByElemRolling(
+    void tjob_t::setDefaultElemByElemRolling(
         bool const is_rolling ) SIXTRL_NOEXCEPT
     {
         this->m_default_elem_by_elem_rolling = is_rolling;
@@ -1021,83 +1511,259 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::clear_flag_t
-    TrackJobBaseNew::doGetDefaultAllClearFlags() const SIXTRL_NOEXCEPT
+    tjob_t::clear_flag_t
+    tjob_t::doGetDefaultAllClearFlags() const SIXTRL_NOEXCEPT
     {
         return this->m_clear_all_flags;
     }
 
-    void TrackJobBaseNew::doSetDefaultAllClearFlags(
-        _this_t::clear_flag_t const flags ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetDefaultAllClearFlags(
+        tjob_t::clear_flag_t const flags ) SIXTRL_NOEXCEPT
     {
         this->m_clear_all_flags = flags;
     }
 
-    _this_t::clear_flag_t
-    TrackJobBaseNew::doGetDefaultPrepareResetClearFlags() const SIXTRL_NOEXCEPT
+    tjob_t::clear_flag_t
+    tjob_t::doGetDefaultPrepareResetClearFlags() const SIXTRL_NOEXCEPT
     {
         return this->m_clear_prepare_reset_flags;
     }
 
-    void TrackJobBaseNew::doSetDefaultPrepareResetClearFlags(
-        _this_t::clear_flag_t const flags ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetDefaultPrepareResetClearFlags(
+        tjob_t::clear_flag_t const flags ) SIXTRL_NOEXCEPT
     {
         this->m_clear_prepare_reset_flags = flags;
     }
 
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    tjob_t::buffer_store_t const* tjob_t::do_get_ptr_buffer_store(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::buffer_store_t const* ptr_buffer_store = nullptr;
+        st_size_t const min_buffer_id = this->min_stored_buffer_id();
+        st_size_t const max_buffer_id_plus_one =
+            min_buffer_id + this->m_stored_buffers.size();
+
+        if( ( min_buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_id >= min_buffer_id ) &&
+            ( buffer_id <  max_buffer_id_plus_one ) )
+        {
+            SIXTRL_ASSERT( this->do_get_stored_buffer_size() >=
+                           this->m_num_stored_buffers );
+
+            ptr_buffer_store = &this->m_stored_buffers[
+                buffer_id - min_buffer_id ];
+        }
+
+        return ptr_buffer_store;
+    }
+
+    tjob_t::buffer_store_t* tjob_t::do_get_ptr_buffer_store(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::buffer_store_t* >( static_cast<
+            tjob_t const& >( *this ).do_get_ptr_buffer_store( buffer_id ) );
+    }
+
+    st_size_t tjob_t::do_get_stored_buffer_size() const SIXTRL_NOEXCEPT
+    {
+        return this->m_stored_buffers.size();
+    }
+
+    st_size_t tjob_t::do_find_assign_address_item( tjob_t::assign_item_t const&
+        SIXTRL_RESTRICT_REF item_to_search ) const SIXTRL_NOEXCEPT
+    {
+        using item_t = tjob_t::assign_item_t;
+        using key_t  = tjob_t::assign_item_key_t;
+
+        size_t index = std::numeric_limits< size_t >::max();
+
+        key_t const key = key_t{ item_to_search.getDestBufferId(),
+                                 item_to_search.getSrcBufferId() };
+
+        auto it = this->m_assign_address_items.find( key );
+
+        SIXTRL_ASSERT( this->m_assign_address_items.size() ==
+                       this->m_assign_item_keys.size() );
+
+        if( it != this->m_assign_address_items.end() )
+        {
+            auto cmp_key_fn = []( key_t const& SIXTRL_RESTRICT_REF lhs,
+                                  key_t const& SIXTRL_RESTRICT_REF rhs )
+            {
+                return ( ( lhs.dest_buffer_id < rhs.dest_buffer_id ) ||
+                         ( ( lhs.dest_buffer_id == rhs.dest_buffer_id ) &&
+                           ( lhs.src_buffer_id < rhs.src_buffer_id ) ) );
+            };
+
+            SIXTRL_ASSERT( std::is_sorted( this->m_assign_item_keys.begin(),
+                this->m_assign_item_keys.end(), cmp_key_fn ) );
+
+            SIXTRL_ASSERT( std::binary_search( this->m_assign_item_keys.begin(),
+                this->m_assign_item_keys.end(), key, cmp_key_fn ) );
+
+            ( void )cmp_key_fn;
+
+            size_t const nn = it->second.getNumObjects();
+            ::NS(AssignAddressItem) const* ptr_item_to_search =
+                item_to_search.getCApiPtr();
+
+            for( size_t ii = size_t{ 0 } ; ii < nn ; ++ii )
+            {
+                tjob_t::assign_item_t const* item =
+                    it->second.get< item_t >( ii );
+
+                if( ( item != nullptr ) &&
+                    ( ::NS(AssignAddressItem_are_equal)(
+                        item->getCApiPtr(), ptr_item_to_search ) ) )
+                {
+                    index = ii;
+                    break;
+                }
+            }
+
+            if( index > nn ) index = nn;
+        }
+
+        return index;
+    }
+
+    tjob_t::assign_item_t const* tjob_t::do_get_assign_address_item(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+        st_size_t const item_index ) const SIXTRL_NOEXCEPT
+    {
+        using item_t = tjob_t::assign_item_t;
+        item_t const* ptr_found_item = nullptr;
+
+        auto it = this->m_assign_address_items.find( key );
+
+        if( ( it != this->m_assign_address_items.end() ) &&
+            ( it->second.getNumObjects() > item_index ) )
+        {
+            ptr_found_item = it->second.get< item_t >( item_index );
+        }
+
+        return ptr_found_item;
+    }
+
+    tjob_t::assign_item_t* tjob_t::do_get_assign_address_item(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+        st_size_t const item_index ) SIXTRL_NOEXCEPT
+    {
+        using ptr_t = tjob_t::assign_item_t*;
+        return const_cast< ptr_t >( static_cast< tjob_t const& >(
+            *this ).do_get_assign_address_item( key, item_index ) );
+    }
+
+    tjob_t::c_buffer_t* tjob_t::do_get_ptr_assign_address_items_buffer(
+        tjob_t::assign_item_key_t const&
+            SIXTRL_RESTRICT_REF key ) SIXTRL_NOEXCEPT
+    {
+        tjob_t::c_buffer_t* ptr_assign_address_items_buffer = nullptr;
+        auto it = this->m_assign_address_items.find( key );
+
+        if( it != this->m_assign_address_items.end() )
+        {
+            ptr_assign_address_items_buffer = it->second.getCApiPtr();
+        }
+
+        return ptr_assign_address_items_buffer;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::buffer_t const& tjob_t::elem_by_elem_config_cxx_buffer() const
+    {
+        if( this->m_my_elem_by_elem_buffer.get() == nullptr )
+        {
+            throw std::runtime_error( "no elem-by-elem config buffer available" );
+        }
+
+        return *( this->m_my_elem_by_elem_buffer.get() );
+    }
+
+    tjob_t::buffer_t& tjob_t::elem_by_elem_config_cxx_buffer()
+    {
+        return const_cast< tjob_t::buffer_t& >( static_cast< tjob_t const& >(
+            *this ).elem_by_elem_config_cxx_buffer() );
+    }
+
+    tjob_t::c_buffer_t const*
+    tjob_t::elem_by_elem_config_buffer() const SIXTRL_NOEXCEPT
+    {
+        return ( this->m_my_elem_by_elem_buffer.get() != nullptr )
+            ? this->m_my_elem_by_elem_buffer->getCApiPtr() : nullptr;
+    }
+
+    tjob_t::c_buffer_t* tjob_t::elem_by_elem_config_buffer() SIXTRL_NOEXCEPT
+    {
+        return ( this->m_my_elem_by_elem_buffer.get() != nullptr )
+            ? this->m_my_elem_by_elem_buffer->getCApiPtr() : nullptr;
+    }
+
+    st_size_t tjob_t::elem_by_elem_config_index() const SIXTRL_NOEXCEPT
+    {
+        return this->m_elem_by_elem_config_index;
+    }
+
     /* --------------------------------------------------------------------- */
 
-    _this_t::elem_by_elem_order_t
-    TrackJobBaseNew::elemByElemOrder() const SIXTRL_NOEXCEPT
+    tjob_t::elem_by_elem_order_t tjob_t::elemByElemOrder() const SIXTRL_NOEXCEPT
     {
-        return ::NS(ElemByElemConfig_get_order)(
-            this->m_my_elem_by_elem_config.get() );
+        return ::NS(ElemByElemConfig_get_order)( this->ptrElemByElemConfig() );
     }
 
-    _this_t::elem_by_elem_order_t
-    TrackJobBaseNew::defaultElemByElemOrder() const SIXTRL_NOEXCEPT
+    tjob_t::elem_by_elem_order_t
+    tjob_t::defaultElemByElemOrder() const SIXTRL_NOEXCEPT
     {
         return this->m_default_elem_by_elem_order;
     }
 
-    void TrackJobBaseNew::setDefaultElemByElemOrder(
-        _this_t::elem_by_elem_order_t const order ) SIXTRL_NOEXCEPT
+    void tjob_t::setDefaultElemByElemOrder(
+        tjob_t::elem_by_elem_order_t const order ) SIXTRL_NOEXCEPT
     {
         this->m_default_elem_by_elem_order = order;
     }
 
     /* --------------------------------------------------------------------- */
 
-    TrackJobBaseNew::TrackJobBaseNew(
-        _this_t::arch_id_t const arch_id,
+    tjob_t::TrackJobBaseNew(
+        tjob_t::arch_id_t const arch_id,
         char const* SIXTRL_RESTRICT arch_str,
         char const* SIXTRL_RESTRICT config_str ) :
         st::ArchDebugBase( arch_id, arch_str, config_str ),
+        m_assign_address_items(),
         m_particle_set_indices(),
         m_particle_set_begin_offsets(),
         m_particle_set_end_offsets(),
         m_beam_monitor_indices(),
+        m_stored_buffers(),
+        m_assign_item_keys(),
         m_my_output_buffer( nullptr ),
-        m_my_particles_addr_buffer( new _this_t::buffer_t ),
-        m_my_elem_by_elem_config( nullptr ),
+        m_my_elem_by_elem_buffer( new tjob_t::buffer_t ),
+        m_my_particles_addr_buffer( new tjob_t::buffer_t ),
         m_ptr_particles_buffer( nullptr ),
         m_ptr_beam_elem_buffer( nullptr ), m_ptr_output_buffer( nullptr ),
         m_ptr_c_particles_buffer( nullptr ),
         m_ptr_c_beam_elem_buffer( nullptr ), m_ptr_c_output_buffer( nullptr ),
-        m_be_mon_output_buffer_offset( _this_t::size_type{ 0 } ),
-        m_elem_by_elem_output_offset( _this_t::size_type{ 0 } ),
-        m_num_particle_sets_in_buffer( _this_t::size_type{ 0 } ),
-        m_num_beam_elements_in_buffer( _this_t::size_type{ 0 } ),
+        m_be_mon_output_buffer_offset( st_size_t{ 0 } ),
+        m_elem_by_elem_output_offset( st_size_t{ 0 } ),
+        m_num_particle_sets_in_buffer( st_size_t{ 0 } ),
+        m_num_beam_elements_in_buffer( st_size_t{ 0 } ),
+        m_elem_by_elem_config_index( st_size_t{ 0 } ),
+        m_num_stored_buffers( st_size_t{ 0 } ),
         m_default_elem_by_elem_order( ::NS(ELEM_BY_ELEM_ORDER_DEFAULT) ),
-        m_total_num_particles( _this_t::num_particles_t{ 0 } ),
-        m_total_num_particles_in_sets( _this_t::num_particles_t{ 0 } ),
-        m_min_particle_id( _this_t::particle_index_t{ 0 } ),
-        m_max_particle_id( _this_t::particle_index_t{ 0 } ),
-        m_min_element_id( _this_t::particle_index_t{ 0 } ),
-        m_max_element_id( _this_t::particle_index_t{ 0 } ),
-        m_min_initial_turn_id( _this_t::particle_index_t{ 0 } ),
-        m_max_initial_turn_id( _this_t::particle_index_t{ 0 } ),
-        m_until_turn_elem_by_elem( _this_t::size_type{ 0 } ),
+        m_total_num_particles( tjob_t::num_particles_t{ 0 } ),
+        m_total_num_particles_in_sets( tjob_t::num_particles_t{ 0 } ),
+        m_min_particle_id( tjob_t::particle_index_t{ 0 } ),
+        m_max_particle_id( tjob_t::particle_index_t{ 0 } ),
+        m_min_element_id( tjob_t::particle_index_t{ 0 } ),
+        m_max_element_id( tjob_t::particle_index_t{ 0 } ),
+        m_min_initial_turn_id( tjob_t::particle_index_t{ 0 } ),
+        m_max_initial_turn_id( tjob_t::particle_index_t{ 0 } ),
+        m_until_turn_elem_by_elem( st_size_t{ 0 } ),
         m_collect_flags( st::TRACK_JOB_IO_DEFAULT_FLAGS ),
         m_clear_prepare_reset_flags( st::TRACK_JOB_DEFAULT_CLEAR_FLAGS ),
         m_clear_all_flags( st::TRACK_JOB_CLEAR_ALL_FLAGS ),
@@ -1110,15 +1776,18 @@ namespace SIXTRL_CXX_NAMESPACE
         this->doInitDefaultBeamMonitorIndices();
     }
 
-    TrackJobBaseNew::TrackJobBaseNew( TrackJobBaseNew const& other ) :
+    tjob_t::TrackJobBaseNew( TrackJobBaseNew const& other ) :
         st::ArchDebugBase( other ),
+        m_assign_address_items( other.m_assign_address_items ),
         m_particle_set_indices( other.m_particle_set_indices ),
         m_particle_set_begin_offsets( other.m_particle_set_begin_offsets ),
         m_particle_set_end_offsets( other.m_particle_set_end_offsets ),
         m_beam_monitor_indices( other.m_beam_monitor_indices ),
+        m_stored_buffers( other.m_stored_buffers ),
+        m_assign_item_keys( other.m_assign_item_keys ),
         m_my_output_buffer( nullptr ),
+        m_my_elem_by_elem_buffer( nullptr ),
         m_my_particles_addr_buffer( nullptr ),
-        m_my_elem_by_elem_config( nullptr ),
         m_ptr_particles_buffer( other.m_ptr_particles_buffer ),
         m_ptr_beam_elem_buffer( other.m_ptr_beam_elem_buffer ),
         m_ptr_output_buffer( nullptr ),
@@ -1129,6 +1798,8 @@ namespace SIXTRL_CXX_NAMESPACE
         m_elem_by_elem_output_offset( other.m_elem_by_elem_output_offset ),
         m_num_particle_sets_in_buffer( other.m_num_particle_sets_in_buffer ),
         m_num_beam_elements_in_buffer( other.m_num_beam_elements_in_buffer ),
+        m_elem_by_elem_config_index( other.m_elem_by_elem_config_index ),
+        m_num_stored_buffers( other.m_num_stored_buffers ),
         m_default_elem_by_elem_order( other.m_default_elem_by_elem_order ),
         m_total_num_particles( other.m_total_num_particles ),
         m_total_num_particles_in_sets( other.m_total_num_particles_in_sets ),
@@ -1150,12 +1821,10 @@ namespace SIXTRL_CXX_NAMESPACE
         m_uses_controller( other.m_uses_controller ),
         m_uses_arguments( other.m_uses_arguments )
     {
-        using elem_by_elem_config_t = TrackJobBaseNew::elem_by_elem_config_t;
-
         if( other.ownsOutputBuffer() )
         {
             this->m_my_output_buffer.reset( new
-                _this_t::buffer_t( *other.ptrOutputBuffer() ) );
+                tjob_t::buffer_t( *other.ptrOutputBuffer() ) );
 
             this->m_ptr_output_buffer = this->m_my_output_buffer.get();
             this->m_ptr_c_output_buffer =
@@ -1168,40 +1837,29 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_ptr_c_output_buffer = other.m_ptr_c_output_buffer;
         }
 
-        if( other.m_my_particles_addr_buffer.get() != nullptr )
-        {
-            this->m_my_particles_addr_buffer.reset(
-                new _this_t::buffer_t(
-                    *other.doGetPtrParticlesAddrBuffer() ) );
-        }
-        else
-        {
-            this->m_my_particles_addr_buffer.reset(
-                new _this_t::buffer_t );
-        }
+        tjob_t::COPY_PTR_BUFFER( this->m_my_elem_by_elem_buffer,
+                                 other.m_my_elem_by_elem_buffer );
 
-        if( other.m_my_elem_by_elem_config.get() != nullptr )
-        {
-            this->m_my_elem_by_elem_config.reset(
-                new elem_by_elem_config_t );
-
-            *this->m_my_elem_by_elem_config =  *other.ptrElemByElemConfig();
-        }
+        tjob_t::COPY_PTR_BUFFER( this->m_my_particles_addr_buffer,
+                                 other.m_my_particles_addr_buffer );
     }
 
-    TrackJobBaseNew::TrackJobBaseNew(
+    tjob_t::TrackJobBaseNew(
         TrackJobBaseNew&& other ) SIXTRL_NOEXCEPT :
         st::ArchDebugBase( std::move( other ) ),
+        m_assign_address_items( std::move( other.m_assign_address_items ) ),
         m_particle_set_indices( std::move( other.m_particle_set_indices ) ),
         m_particle_set_begin_offsets(
             std::move( other.m_particle_set_begin_offsets ) ),
         m_particle_set_end_offsets(
             std::move( other.m_particle_set_end_offsets ) ),
         m_beam_monitor_indices( std::move( other.m_beam_monitor_indices ) ),
+        m_stored_buffers( std::move( other.m_stored_buffers ) ),
+        m_assign_item_keys( std::move( other.m_assign_item_keys ) ),
         m_my_output_buffer( std::move( other.m_my_output_buffer ) ),
+        m_my_elem_by_elem_buffer( std::move( other.m_my_elem_by_elem_buffer ) ),
         m_my_particles_addr_buffer(
             std::move( other.m_my_particles_addr_buffer ) ),
-        m_my_elem_by_elem_config( std::move( other.m_my_elem_by_elem_config ) ),
         m_ptr_particles_buffer( std::move( other.m_ptr_particles_buffer ) ),
         m_ptr_beam_elem_buffer( std::move( other.m_ptr_beam_elem_buffer ) ),
         m_ptr_output_buffer( std::move( other.m_ptr_output_buffer ) ),
@@ -1216,6 +1874,9 @@ namespace SIXTRL_CXX_NAMESPACE
             std::move( other.m_num_particle_sets_in_buffer ) ),
         m_num_beam_elements_in_buffer(
             std::move( other.m_num_beam_elements_in_buffer ) ),
+        m_elem_by_elem_config_index(
+            std::move( other.m_elem_by_elem_config_index ) ),
+        m_num_stored_buffers( std::move( other.m_num_stored_buffers ) ),
         m_default_elem_by_elem_order(
             std::move( other.m_default_elem_by_elem_order ) ),
         m_total_num_particles( std::move( other.m_total_num_particles ) ),
@@ -1250,7 +1911,7 @@ namespace SIXTRL_CXX_NAMESPACE
         other.doClearOutputStructuresBaseImpl();
     }
 
-    TrackJobBaseNew& TrackJobBaseNew::operator=( TrackJobBaseNew const& rhs )
+    TrackJobBaseNew& tjob_t::operator=( TrackJobBaseNew const& rhs )
     {
         if( ( this != &rhs ) && ( this->isArchCompatibleWith( rhs ) ) )
         {
@@ -1305,25 +1966,13 @@ namespace SIXTRL_CXX_NAMESPACE
             if( rhs.m_my_particles_addr_buffer.get() != nullptr )
             {
                 this->m_my_particles_addr_buffer.reset(
-                    new _this_t::buffer_t(
+                    new tjob_t::buffer_t(
                         *rhs.m_my_particles_addr_buffer ) );
             }
             else
             {
                 this->m_my_particles_addr_buffer.reset(
-                    new _this_t::buffer_t );
-            }
-
-            if( rhs.m_my_elem_by_elem_config.get() != nullptr )
-            {
-                this->m_my_elem_by_elem_config.reset(
-                    new elem_by_elem_config_t );
-
-                *this->m_my_elem_by_elem_config = *rhs.ptrElemByElemConfig();
-            }
-            else if( this->m_my_elem_by_elem_config.get() != nullptr )
-            {
-                this->m_my_elem_by_elem_config.reset( nullptr );
+                    new tjob_t::buffer_t );
             }
 
             this->m_ptr_particles_buffer = rhs.m_ptr_particles_buffer;
@@ -1344,6 +1993,11 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_num_beam_elements_in_buffer =
                 rhs.m_num_beam_elements_in_buffer;
 
+            this->m_elem_by_elem_config_index =
+                rhs.m_elem_by_elem_config_index;
+
+            this->m_num_stored_buffers = rhs.m_num_stored_buffers;
+
             this->m_default_elem_by_elem_order =
                 rhs.m_default_elem_by_elem_order;
 
@@ -1381,13 +2035,16 @@ namespace SIXTRL_CXX_NAMESPACE
         return *this;
     }
 
-    TrackJobBaseNew& TrackJobBaseNew::operator=(
+    TrackJobBaseNew& tjob_t::operator=(
         TrackJobBaseNew&& rhs ) SIXTRL_NOEXCEPT
     {
         if( this != &rhs )
         {
             st::ArchDebugBase::operator=( std::move( rhs ) );
 
+            this->m_assign_address_items =
+                std::move( rhs.m_assign_address_items );
+
             this->m_particle_set_indices =
                 std::move( rhs.m_particle_set_indices );
 
@@ -1400,14 +2057,17 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_beam_monitor_indices =
                 std::move( rhs.m_beam_monitor_indices );
 
+            this->m_stored_buffers = std::move( rhs.m_stored_buffers );
+            this->m_assign_item_keys = std::move( rhs.m_assign_item_keys );
+
             this->m_my_output_buffer = std::move( rhs.m_my_output_buffer );
 
+            this->m_my_elem_by_elem_buffer =
+                std::move( rhs.m_my_elem_by_elem_buffer );
+
             this->m_my_particles_addr_buffer =
                 std::move( rhs.m_my_particles_addr_buffer );
 
-            this->m_my_elem_by_elem_config =
-                std::move( rhs.m_my_elem_by_elem_config );
-
             this->m_ptr_particles_buffer =
                 std::move( rhs.m_ptr_particles_buffer );
 
@@ -1434,6 +2094,9 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_num_beam_elements_in_buffer =
                 std::move( rhs.m_num_beam_elements_in_buffer );
 
+            this->m_elem_by_elem_config_index =
+                std::move( rhs.m_elem_by_elem_config_index );
+
             this->m_default_elem_by_elem_order = std::move(
                 rhs.m_default_elem_by_elem_order );
 
@@ -1491,21 +2154,21 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBaseNew::doClear( _this_t::clear_flag_t const flags )
+    void tjob_t::doClear( tjob_t::clear_flag_t const flags )
     {
-        if( _this_t::IsClearFlagSet(
+        if( tjob_t::IsClearFlagSet(
                 flags, st::TRACK_JOB_CLEAR_PARTICLE_STRUCTURES ) )
         {
             this->doClearParticlesStructures();
         }
 
-        if( _this_t::IsClearFlagSet(
+        if( tjob_t::IsClearFlagSet(
                 flags, st::TRACK_JOB_CLEAR_BEAM_ELEMENT_STRUCTURES ) )
         {
             this->doClearBeamElementsStructures();
         }
 
-        if( _this_t::IsClearFlagSet(
+        if( tjob_t::IsClearFlagSet(
                 flags,st::TRACK_JOB_CLEAR_OUTPUT_STRUCTURES ) )
         {
             this->doClearOutputStructures();
@@ -1514,27 +2177,27 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    _this_t::collect_flag_t TrackJobBaseNew::doCollect(
-        _this_t::collect_flag_t const flags )
+    st_collect_flag_t tjob_t::doCollect(
+        st_collect_flag_t const flags )
     {
         return ( flags & st::TRACK_JOB_COLLECT_ALL );
     }
 
-    _this_t::push_flag_t TrackJobBaseNew::doPush(
-        _this_t::collect_flag_t const flags )
+    st_push_flag_t tjob_t::doPush(
+        st_collect_flag_t const flags )
     {
         return ( flags & st::TRACK_JOB_PUSH_ALL );
     }
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::status_t TrackJobBaseNew::doPrepareParticlesStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT pb )
+    st_status_t tjob_t::doPrepareParticlesStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pb )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        using size_t = _this_t::size_type;
-        using p_index_t = _this_t::particle_index_t;
+        using size_t = st_size_t;
+        using p_index_t = tjob_t::particle_index_t;
 
         SIXTRL_STATIC_VAR size_t const ZERO = size_t{ 0 };
         SIXTRL_STATIC_VAR size_t const ONE  = size_t{ 1 };
@@ -1568,8 +2231,8 @@ namespace SIXTRL_CXX_NAMESPACE
 
             if( this->doGetPtrParticlesAddrBuffer() == nullptr )
             {
-                _this_t::ptr_particles_addr_buffer_t partaddr_buffer_store(
-                    new _this_t::buffer_t );
+                tjob_t::ptr_particles_addr_buffer_t partaddr_buffer_store(
+                    new tjob_t::buffer_t );
 
                 this->doUpdateStoredParticlesAddrBuffer(
                     std::move( partaddr_buffer_store ) );
@@ -1598,18 +2261,18 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    void TrackJobBaseNew::doClearParticlesStructures()
+    void tjob_t::doClearParticlesStructures()
     {
         this->doClearParticlesStructuresBaseImpl();
     }
 
-    _this_t::status_t TrackJobBaseNew::doPrepareBeamElementsStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belems )
+    st_status_t tjob_t::doPrepareBeamElementsStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        using size_t        = _this_t::size_type;
-        using p_index_t     = _this_t::particle_index_t;
+        using size_t        = st_size_t;
+        using p_index_t     = tjob_t::particle_index_t;
         using buf_size_t    = ::NS(buffer_size_t);
         using obj_ptr_t     = SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object)*;
         using ptr_t         = SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor)*;
@@ -1636,11 +2299,13 @@ namespace SIXTRL_CXX_NAMESPACE
                 buf_size_t num_be_monitors = buf_size_t{ 0 };
                 std::vector< size_t > be_mon_indices( num_e_by_e_objs, ZERO );
 
-                status = ::NS(BeamMonitor_get_beam_monitor_indices_from_buffer)(
-                    belems, be_mon_indices.size(), be_mon_indices.data(),
-                        &num_be_monitors );
+                num_be_monitors = ::NS(BeamMonitor_monitor_indices_from_buffer)(
+                    be_mon_indices.data(), be_mon_indices.size(), belems );
 
-                SIXTRL_ASSERT( num_be_monitors <= be_mon_indices.size() );
+                if( num_be_monitors > be_mon_indices.size() )
+                {
+                    status = st::ARCH_STATUS_GENERAL_FAILURE;
+                }
 
                 auto ind_end = be_mon_indices.begin();
 
@@ -1695,29 +2360,26 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    void TrackJobBaseNew::doClearBeamElementsStructures()
+    void tjob_t::doClearBeamElementsStructures()
     {
         this->doClearBeamElementsStructuresBaseImpl();
     }
 
-    _this_t::status_t TrackJobBaseNew::doPrepareOutputStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _this_t::size_type const until_turn_elem_by_elem )
+    st_status_t tjob_t::doPrepareOutputStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        using size_t                 = _this_t::size_type;
-        using buffer_t               = _this_t::buffer_t;
-        using c_buffer_t             = _this_t::c_buffer_t;
+        using size_t                 = st_size_t;
+        using buffer_t               = tjob_t::buffer_t;
+        using c_buffer_t             = tjob_t::c_buffer_t;
         using buf_size_t             = ::NS(buffer_size_t);
-        using elem_by_elem_config_t  = TrackJobBaseNew::elem_by_elem_config_t;
-        using ptr_output_buffer_t    = TrackJobBaseNew::ptr_output_buffer_t;
-        using par_index_t            = _this_t::particle_index_t;
-
-        using ptr_elem_by_elem_config_t =
-            TrackJobBaseNew::ptr_elem_by_elem_config_t;
+        using elem_by_elem_config_t  = tjob_t::elem_by_elem_config_t;
+        using ptr_output_buffer_t    = tjob_t::ptr_output_buffer_t;
+        using par_index_t            = tjob_t::particle_index_t;
 
         SIXTRL_ASSERT( particles_buffer != nullptr );
         SIXTRL_ASSERT( !::NS(Buffer_needs_remapping)( particles_buffer ) );
@@ -1808,6 +2470,9 @@ namespace SIXTRL_CXX_NAMESPACE
                 &elem_by_elem_out_idx_offset, &be_monitor_out_idx_offset,
                 &max_elem_by_elem_turn_id );
 
+            SIXTRL_ASSERT( this->m_my_elem_by_elem_buffer.get() != nullptr );
+            this->m_my_elem_by_elem_buffer->reset();
+
             if( ( status == st::ARCH_STATUS_SUCCESS ) &&
                 ( until_turn_elem_by_elem > ZERO ) &&
                 ( this->minInitialTurnId() >= par_index_t{ 0 } ) &&
@@ -1815,31 +2480,33 @@ namespace SIXTRL_CXX_NAMESPACE
                 ( until_turn_elem_by_elem > static_cast< buf_size_t >(
                     this->minInitialTurnId() ) ) )
             {
-                ptr_elem_by_elem_config_t conf( new elem_by_elem_config_t );
-                ::NS(ElemByElemConfig_preset)( conf.get() );
+                SIXTRL_ASSERT( this->m_my_elem_by_elem_buffer.get() !=
+                    nullptr );
+
+                elem_by_elem_config_t* conf = ::NS(ElemByElemConfig_preset)(
+                    ::NS(ElemByElemConfig_new)(
+                        this->m_my_elem_by_elem_buffer->getCApiPtr() ) );
 
-                status = ::NS(ElemByElemConfig_init_detailed)(
-                    conf.get(), this->defaultElemByElemOrder(),
+                SIXTRL_ASSERT( conf != nullptr );
+
+                status = ::NS(ElemByElemConfig_init_detailed)( conf,
+                    this->defaultElemByElemOrder(),
                     this->minParticleId(), this->maxParticleId(),
                     this->minElementId(),  this->maxElementId(),
                     this->minInitialTurnId(), max_elem_by_elem_turn_id,
                     this->defaultElemByElemRolling() );
 
+                this->m_elem_by_elem_config_index = size_t{ 0 };
+
                 if( status == st::ARCH_STATUS_SUCCESS )
                 {
-                    this->doUpdateStoredElemByElemConfig( std::move( conf ) );
-                    this->doSetUntilTurnElemByElem(
-                        until_turn_elem_by_elem );
-
+                    this->doSetUntilTurnElemByElem( until_turn_elem_by_elem );
                     SIXTRL_ASSERT( this->hasElemByElemConfig() );
                 }
             }
             else if( status == st::ARCH_STATUS_SUCCESS )
             {
-                ptr_elem_by_elem_config_t dummy( nullptr );
-                this->doUpdateStoredElemByElemConfig( std::move( dummy ) );
                 this->doSetUntilTurnElemByElem( ZERO );
-
                 status = ( !this->hasElemByElemConfig() )
                     ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
             }
@@ -1857,24 +2524,24 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    void TrackJobBaseNew::doClearOutputStructures()
+    void tjob_t::doClearOutputStructures()
     {
         this->doClearOutputStructuresBaseImpl();
     }
 
-    _this_t::status_t TrackJobBaseNew::doAssignOutputBufferToBeamMonitors(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        _this_t::particle_index_t const min_turn_id,
-        _this_t::size_type const output_buffer_offset_index )
+    st_status_t tjob_t::doAssignOutputBufferToBeamMonitors(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        tjob_t::particle_index_t const min_turn_id,
+        st_size_t const output_buffer_offset_index )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         this->doSetBeamMonitorOutputEnabledFlag( false );
 
         if( ( output_buffer != nullptr ) && ( beam_elem_buffer != nullptr ) &&
-            ( this->numBeamMonitors() > _this_t::size_type{ 0 } ) &&
-            ( min_turn_id >= _this_t::particle_index_t{ 0 } ) &&
+            ( this->numBeamMonitors() > st_size_t{ 0 } ) &&
+            ( min_turn_id >= tjob_t::particle_index_t{ 0 } ) &&
             ( ::NS(Buffer_get_num_of_objects)( output_buffer ) >
               output_buffer_offset_index ) )
         {
@@ -1914,12 +2581,12 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
 
-    _this_t::status_t TrackJobBaseNew::doAssignOutputBufferToElemByElemConfig(
-        _this_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_config,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        _this_t::size_type const output_buffer_offset_index )
+    st_status_t tjob_t::doAssignOutputBufferToElemByElemConfig(
+        tjob_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_config,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        st_size_t const output_buffer_offset_index )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         if( ( elem_by_elem_config != nullptr ) &&
             ( output_buffer != nullptr ) &&
@@ -1960,15 +2627,15 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::clear_flag_t TrackJobBaseNew::doPrepareResetClearFlags(
-        const _this_t::c_buffer_t *const SIXTRL_RESTRICT pbuffer,
-        _this_t::size_type const num_psets,
-        _this_t::size_type const* SIXTRL_RESTRICT pset_indices_begin,
-        const _this_t::c_buffer_t *const SIXTRL_RESTRICT belems_buffer,
-        const _this_t::c_buffer_t *const SIXTRL_RESTRICT output_buffer,
-        _this_t::size_type const )
+    tjob_t::clear_flag_t tjob_t::doPrepareResetClearFlags(
+        const tjob_t::c_buffer_t *const SIXTRL_RESTRICT pbuffer,
+        st_size_t const num_psets,
+        st_size_t const* SIXTRL_RESTRICT pset_indices_begin,
+        const tjob_t::c_buffer_t *const SIXTRL_RESTRICT belems_buffer,
+        const tjob_t::c_buffer_t *const SIXTRL_RESTRICT output_buffer,
+        st_size_t const )
     {
-        using clear_flag_t = _this_t::clear_flag_t;
+        using clear_flag_t = tjob_t::clear_flag_t;
         clear_flag_t clear_flags = this->doGetDefaultPrepareResetClearFlags();
 
         bool const has_same_particle_sets = (
@@ -1978,46 +2645,46 @@ namespace SIXTRL_CXX_NAMESPACE
               ( std::equal( pset_indices_begin, pset_indices_begin + num_psets,
                             this->particleSetIndicesBegin() ) ) ) );
 
-        if( ( _this_t::IsClearFlagSet( clear_flags,
+        if( ( tjob_t::IsClearFlagSet( clear_flags,
                 st::TRACK_JOB_CLEAR_PARTICLE_STRUCTURES ) ) &&
             ( pbuffer != nullptr ) &&
             ( pbuffer == this->ptrCParticlesBuffer() ) &&
             ( has_same_particle_sets ) )
         {
-            clear_flags = _this_t::UnsetClearFlag( clear_flags,
+            clear_flags = tjob_t::UnsetClearFlag( clear_flags,
                st::TRACK_JOB_CLEAR_PARTICLE_STRUCTURES );
         }
 
-        if( ( _this_t::IsClearFlagSet( clear_flags,
+        if( ( tjob_t::IsClearFlagSet( clear_flags,
                 st::TRACK_JOB_CLEAR_BEAM_ELEMENT_STRUCTURES ) ) &&
             ( belems_buffer != nullptr ) &&
             ( belems_buffer == this->ptrCBeamElementsBuffer() ) )
         {
-            clear_flags = _this_t::UnsetClearFlag( clear_flags,
+            clear_flags = tjob_t::UnsetClearFlag( clear_flags,
                st::TRACK_JOB_CLEAR_BEAM_ELEMENT_STRUCTURES );
         }
 
-        if( ( _this_t::IsClearFlagSet( clear_flags,
+        if( ( tjob_t::IsClearFlagSet( clear_flags,
                 st::TRACK_JOB_CLEAR_OUTPUT_STRUCTURES ) ) &&
             ( output_buffer != nullptr ) &&
             ( output_buffer == this->ptrCOutputBuffer() ) )
         {
-            clear_flags = _this_t::UnsetClearFlag( clear_flags,
+            clear_flags = tjob_t::UnsetClearFlag( clear_flags,
                st::TRACK_JOB_CLEAR_OUTPUT_STRUCTURES );
         }
 
         return clear_flags;
     }
 
-    _this_t::status_t TrackJobBaseNew::doReset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        _this_t::size_type const until_turn_elem_by_elem )
+    st_status_t tjob_t::doReset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        using output_buffer_flag_t = _this_t::output_buffer_flag_t;
+        using output_buffer_flag_t = tjob_t::output_buffer_flag_t;
 
-        _this_t::status_t status =
+        st_status_t status =
             this->doPrepareParticlesStructures( particles_buffer );
 
         if( status == st::ARCH_STATUS_SUCCESS )
@@ -2078,11 +2745,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t TrackJobBaseNew::doAssignNewOutputBuffer(
+    st_status_t tjob_t::doAssignNewOutputBuffer(
         c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
-        using flags_t = _this_t::output_buffer_flag_t;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        using flags_t = tjob_t::output_buffer_flag_t;
 
         flags_t const flags =
             ::NS(OutputBuffer_required_for_tracking_of_particle_sets)(
@@ -2127,15 +2794,323 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::status_t TrackJobBaseNew::doFetchParticleAddresses()
+    st_size_t tjob_t::do_add_stored_buffer(
+        tjob_t::buffer_store_t&& buffer_store_handle )
+    {
+        tjob_t::c_buffer_t* ptr_cbuffer_null = nullptr;
+        st_size_t buffer_index = st::ARCH_MIN_USER_DEFINED_BUFFER_ID +
+            this->m_stored_buffers.size();
+
+        if( buffer_store_handle.active() ) ++this->m_num_stored_buffers;
+        this->m_stored_buffers.emplace_back( ptr_cbuffer_null, false );
+        this->m_stored_buffers.back() = std::move( buffer_store_handle );
+        return buffer_index;
+    }
+
+    st_status_t tjob_t::do_remove_stored_buffer( st_size_t const buffer_idx )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_size_t const min_buffer_id = this->min_stored_buffer_id();
+        st_size_t const max_buffer_id_plus_one =
+            min_buffer_id + this->m_stored_buffers.size();
+
+        if( ( min_buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_idx != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_idx >= min_buffer_id ) &&
+            ( buffer_idx < max_buffer_id_plus_one ) )
+        {
+            st_size_t const ii = buffer_idx - min_buffer_id;
+            if( this->m_stored_buffers[ ii ].active() )
+            {
+                SIXTRL_ASSERT( this->m_num_stored_buffers > st_size_t{ 0 } );
+                this->m_stored_buffers[ ii ].clear();
+                --this->m_num_stored_buffers;
+            }
+
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_push_stored_buffer( st_size_t const buffer_id )
+    {
+        tjob_t::buffer_store_t const* ptr_stored_buffer =
+            this->do_get_ptr_buffer_store( buffer_id );
+
+        return ( ptr_stored_buffer != nullptr )
+            ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    st_status_t tjob_t::do_collect_stored_buffer( st_size_t const buffer_id )
+    {
+        tjob_t::buffer_store_t const* ptr_stored_buffer =
+            this->do_get_ptr_buffer_store( buffer_id );
+
+        return ( ptr_stored_buffer != nullptr )
+            ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
+    }
+
+    st_status_t tjob_t::do_add_assign_address_item(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF assign_item,
+        st_size_t* SIXTRL_RESTRICT ptr_item_index )
+    {
+        using buffer_t = tjob_t::buffer_t;
+        using key_t    = tjob_t::assign_item_key_t;
+
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        size_t item_index = std::numeric_limits< size_t >::max();
+
+        if( assign_item.valid() )
+        {
+            key_t const key = key_t{ assign_item.getDestBufferId(),
+                                     assign_item.getSrcBufferId() };
+
+            auto it = this->m_assign_address_items.find( key );
+            if( it == this->m_assign_address_items.end() )
+            {
+                auto cmp_key_fn = []( key_t const& SIXTRL_RESTRICT_REF lhs,
+                                      key_t const& SIXTRL_RESTRICT_REF rhs )
+                {
+                    return ( ( lhs.dest_buffer_id < rhs.dest_buffer_id ) ||
+                             ( ( lhs.dest_buffer_id == rhs.dest_buffer_id ) &&
+                               ( lhs.src_buffer_id < rhs.src_buffer_id ) ) );
+                };
+
+                SIXTRL_ASSERT( std::is_sorted( this->m_assign_item_keys.begin(),
+                    this->m_assign_item_keys.end(), cmp_key_fn ) );
+
+                SIXTRL_ASSERT( !std::binary_search(
+                    this->m_assign_item_keys.begin(),
+                    this->m_assign_item_keys.end(), key, cmp_key_fn ) );
+
+                SIXTRL_ASSERT( this->m_assign_address_items.size() ==
+                               this->m_assign_item_keys.size() );
+
+                bool const keys_need_sorting = !(
+                    ( this->m_assign_item_keys.empty() ) ||
+                    ( cmp_key_fn( this->m_assign_item_keys.back(), key ) ) );
+
+                this->m_assign_item_keys.push_back( key );
+
+                if( keys_need_sorting )
+                {
+                    std::sort( this->m_assign_item_keys.begin(),
+                               this->m_assign_item_keys.end(), cmp_key_fn );
+                }
+
+                buffer_t buffer;
+
+                auto ret = this->m_assign_address_items.emplace(
+                    std::make_pair( key, std::move( buffer ) ) );
+
+                if( ret.second )
+                {
+                    buffer_t& buffer = ret.first->second;
+                    SIXTRL_ASSERT( buffer.getNumObjects() == size_t{ 0 } );
+
+                    item_index = buffer.getNumObjects();
+
+                    ::NS(AssignAddressItem)* item =
+                        ::NS(AssignAddressItem_add_copy)( buffer.getCApiPtr(),
+                            assign_item.getCApiPtr() );
+
+                    if( ( item != nullptr ) &&
+                        ( buffer.getNumObjects() > item_index ) )
+                    {
+                        status = st::ARCH_STATUS_SUCCESS;
+                    }
+                }
+            }
+            else
+            {
+                item_index = this->do_find_assign_address_item( assign_item );
+                if( item_index < it->second.getNumObjects() )
+                {
+                    status = st::ARCH_STATUS_SUCCESS;
+                }
+                else
+                {
+                    item_index = it->second.getNumObjects();
+
+                    ::NS(AssignAddressItem)* item =
+                        ::NS(AssignAddressItem_add_copy)(
+                            it->second.getCApiPtr(), assign_item.getCApiPtr() );
+
+                    if( ( item != nullptr ) &&
+                        ( item_index < it->second.getNumObjects() ) )
+                    {
+                        status = st::ARCH_STATUS_SUCCESS;
+                    }
+                }
+            }
+
+            if( ( status == st::ARCH_STATUS_SUCCESS ) &&
+                ( ptr_item_index != nullptr ) )
+            {
+                *ptr_item_index = item_index;
+            }
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_remove_assign_address_item(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+        st_size_t const index_of_item_to_remove )
+    {
+        using item_t = tjob_t::assign_item_t;
+        using key_t  = tjob_t::assign_item_key_t;
+
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        auto it = this->m_assign_address_items.find( key );
+
+        auto cmp_key_fn = []( key_t const& SIXTRL_RESTRICT_REF lhs,
+                              key_t const& SIXTRL_RESTRICT_REF rhs )
+        {
+            return ( ( lhs.dest_buffer_id < rhs.dest_buffer_id ) ||
+                     ( ( lhs.dest_buffer_id == rhs.dest_buffer_id ) &&
+                       ( lhs.src_buffer_id < rhs.src_buffer_id ) ) );
+        };
+
+        SIXTRL_ASSERT( std::is_sorted( this->m_assign_item_keys.begin(),
+                this->m_assign_item_keys.end(), cmp_key_fn ) );
+
+        if( ( it != this->m_assign_address_items.end() ) &&
+            ( it->second.getNumObjects() > index_of_item_to_remove ) )
+        {
+            buffer_t& current_buffer = it->second;
+            buffer_t new_buffer( current_buffer.getNumObjects(),
+                                 current_buffer.getNumSlots(),
+                                 current_buffer.getNumDataptrs(),
+                                 current_buffer.getNumGarbageRanges(),
+                                 current_buffer.getFlags() );
+
+            size_t const nn = current_buffer.getNumObjects();
+            status = st::ARCH_STATUS_SUCCESS;
+
+            SIXTRL_ASSERT( std::binary_search( this->m_assign_item_keys.begin(),
+                this->m_assign_item_keys.end(), key, cmp_key_fn ) );
+
+            SIXTRL_ASSERT( this->m_assign_address_items.size() ==
+                           this->m_assign_item_keys.size() );
+
+            for( size_t ii = size_t{ 0 } ; ii < nn ; ++ii )
+            {
+                if( ii == index_of_item_to_remove ) continue;
+                item_t const* in_item = current_buffer.get< item_t >( ii );
+
+                if( in_item == nullptr )
+                {
+                    status = st::ARCH_STATUS_GENERAL_FAILURE;
+                    break;
+                }
+
+                ::NS(AssignAddressItem)* copied_item =
+                    ::NS(AssignAddressItem_add_copy)(
+                        current_buffer.getCApiPtr(), in_item->getCApiPtr() );
+
+                if( copied_item == nullptr )
+                {
+                    status = st::ARCH_STATUS_GENERAL_FAILURE;
+                    break;
+                }
+            }
+
+            if( status == st::ARCH_STATUS_SUCCESS )
+            {
+                using std::swap;
+                swap( it->second, new_buffer );
+            }
+        }
+
+        if( status == st::ARCH_STATUS_SUCCESS )
+        {
+            it = this->m_assign_address_items.find( key );
+
+            if( it->second.getNumObjects() == size_t{ 0 } )
+            {
+                this->m_assign_address_items.erase( key );
+
+                auto key_it = std::lower_bound(
+                    this->m_assign_item_keys.begin(),
+                    this->m_assign_item_keys.end(), key, cmp_key_fn );
+
+                SIXTRL_ASSERT( key_it != this->m_assign_item_keys.end() );
+                this->m_assign_item_keys.erase( key_it );
+            }
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_perform_address_assignments(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key )
+    {
+        using c_buffer_t = tjob_t::c_buffer_t;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        size_t const dest_buffer_id = key.dest_buffer_id;
+        c_buffer_t* dest_buffer = this->buffer_by_buffer_id( dest_buffer_id );
+
+        size_t const src_buffer_id = key.src_buffer_id;
+        c_buffer_t const* src_buffer =
+            this->buffer_by_buffer_id( src_buffer_id );
+
+        auto it = this->m_assign_address_items.find( key );
+
+        if( ( it != this->m_assign_address_items.end() ) &&
+            ( dest_buffer != nullptr ) && ( src_buffer != nullptr ) )
+        {
+            unsigned char* dest_buffer_begin =
+            ::NS(Buffer_get_data_begin)( dest_buffer );
+
+            unsigned char const* src_buffer_begin =
+                ::NS(Buffer_get_const_data_begin)( src_buffer );
+
+            size_t const dest_slot_size =
+                ( this->is_buffer_by_buffer_id( dest_buffer_id ) )
+                    ? ::NS(Buffer_get_slot_size)( dest_buffer ) : size_t{ 0 };
+
+            size_t const src_slot_size =
+                ( this->is_buffer_by_buffer_id( src_buffer_id ) )
+                    ? ::NS(Buffer_get_slot_size)( src_buffer ) : size_t{ 0 };
+
+            SIXTRL_ASSERT( dest_buffer_begin != nullptr );
+            SIXTRL_ASSERT( src_buffer_begin  != nullptr );
+
+            status =
+            ::NS(AssignAddressItem_perform_address_assignment_kernel_impl)(
+                it->second.dataBegin< unsigned char const* >(),
+                it->second.getSlotSize(), st_size_t{ 0 }, st_size_t{ 1 },
+                dest_buffer_begin, dest_slot_size, dest_buffer_id,
+                src_buffer_begin, src_slot_size, src_buffer_id );
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_commit_address_assignments()
+    {
+        return st::ARCH_STATUS_SUCCESS;
+    }
+
+    st_status_t tjob_t::do_rebuild_assign_items_buffer_arg()
+    {
+        return st::ARCH_STATUS_SUCCESS;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    st_status_t tjob_t::doFetchParticleAddresses()
     {
         return st::ARCH_STATUS_GENERAL_FAILURE;
     }
 
-    _this_t::status_t TrackJobBaseNew::doClearParticleAddresses(
-        _this_t::size_type const index )
+    st_status_t tjob_t::doClearParticleAddresses(
+        st_size_t const index )
     {
-        using status_t = _this_t::status_t;
+        using status_t = st_status_t;
 
         status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
@@ -2151,9 +3126,9 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t TrackJobBaseNew::doClearAllParticleAddresses()
+    st_status_t tjob_t::doClearAllParticleAddresses()
     {
-        using status_t = _this_t::status_t;
+        using status_t = st_status_t;
 
         status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
@@ -2168,20 +3143,21 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::track_status_t TrackJobBaseNew::doTrackUntilTurn(
-        _this_t::size_type const )
+    tjob_t::track_status_t tjob_t::doTrackUntilTurn(
+        st_size_t const )
     {
         return st::TRACK_STATUS_GENERAL_FAILURE;
     }
 
-    TrackJobBaseNew::track_status_t TrackJobBaseNew::doTrackElemByElem(
-        _this_t::size_type const until_turn_elem_by_elem )
+    tjob_t::track_status_t tjob_t::doTrackElemByElem(
+        st_size_t const until_turn_elem_by_elem )
     {
+        ( void )until_turn_elem_by_elem;
         return st::TRACK_STATUS_GENERAL_FAILURE;
     }
 
-    TrackJobBaseNew::track_status_t TrackJobBaseNew::doTrackLine(
-        _this_t::size_type const, _this_t::size_type const,
+    tjob_t::track_status_t tjob_t::doTrackLine(
+        st_size_t const, st_size_t const,
             bool const )
     {
         return st::TRACK_STATUS_GENERAL_FAILURE;
@@ -2189,8 +3165,8 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBaseNew::doSetPtrParticlesBuffer(
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrParticlesBuffer(
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ptr_buffer != nullptr )
         {
@@ -2206,8 +3182,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_particles_buffer = ptr_buffer;
     }
 
-    void TrackJobBaseNew::doSetPtrBeamElementsBuffer(
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrBeamElementsBuffer(
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ptr_buffer != nullptr )
         {
@@ -2223,8 +3199,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_beam_elem_buffer = ptr_buffer;
     }
 
-    void TrackJobBaseNew::doSetPtrOutputBuffer(
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrOutputBuffer(
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ptr_buffer != nullptr )
         {
@@ -2240,10 +3216,10 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_output_buffer = ptr_buffer;
     }
 
-    void TrackJobBaseNew::doSetCxxBufferPointers(
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        _this_t::buffer_t& SIXTRL_RESTRICT_REF beam_elements_buffer,
-        _this_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetCxxBufferPointers(
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF beam_elements_buffer,
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer ) SIXTRL_NOEXCEPT
     {
         this->doSetPtrParticlesBuffer( &particles_buffer );
         this->doSetPtrBeamElementsBuffer( &beam_elements_buffer );
@@ -2258,7 +3234,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    void TrackJobBaseNew::doSetPtrCParticlesBuffer( _this_t::c_buffer_t*
+    void tjob_t::doSetPtrCParticlesBuffer( tjob_t::c_buffer_t*
         SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ( this->m_ptr_particles_buffer   != nullptr ) &&
@@ -2272,8 +3248,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_c_particles_buffer = ptr_buffer;
     }
 
-    void TrackJobBaseNew::doSetPtrCBeamElementsBuffer(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetPtrCBeamElementsBuffer(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ( this->m_ptr_beam_elem_buffer != nullptr ) &&
             ( this->m_ptr_c_beam_elem_buffer ==
@@ -2286,7 +3262,7 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_c_beam_elem_buffer = ptr_buffer;
     }
 
-    void TrackJobBaseNew::doSetPtrCOutputBuffer( _this_t::c_buffer_t*
+    void tjob_t::doSetPtrCOutputBuffer( tjob_t::c_buffer_t*
         SIXTRL_RESTRICT ptr_buffer ) SIXTRL_NOEXCEPT
     {
         if( ( this->m_ptr_output_buffer != nullptr ) &&
@@ -2300,40 +3276,40 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_ptr_c_output_buffer = ptr_buffer;
     }
 
-    void TrackJobBaseNew::doSetBeamMonitorOutputBufferOffset(
-        _this_t::size_type const
+    void tjob_t::doSetBeamMonitorOutputBufferOffset(
+        st_size_t const
             output_buffer_offset ) SIXTRL_NOEXCEPT
     {
         this->m_be_mon_output_buffer_offset = output_buffer_offset;
     }
 
-    void TrackJobBaseNew::doSetElemByElemOutputIndexOffset(
-        _this_t::size_type const
+    void tjob_t::doSetElemByElemOutputIndexOffset(
+        st_size_t const
             elem_by_elem_output_offset ) SIXTRL_NOEXCEPT
     {
         this->m_elem_by_elem_output_offset = elem_by_elem_output_offset;
     }
 
-    void TrackJobBaseNew::doSetUntilTurnElemByElem(
-        _this_t::particle_index_t
+    void tjob_t::doSetUntilTurnElemByElem(
+        tjob_t::particle_index_t
             const until_turn_elem_by_elem ) SIXTRL_NOEXCEPT
     {
         this->m_until_turn_elem_by_elem = until_turn_elem_by_elem;
     }
 
-    void TrackJobBaseNew::doSetRequiresCollectFlag(
+    void tjob_t::doSetRequiresCollectFlag(
         bool const requires_collect_flag ) SIXTRL_NOEXCEPT
     {
         this->m_requires_collect = requires_collect_flag;
     }
 
-    void TrackJobBaseNew::doSetBeamMonitorOutputEnabledFlag(
+    void tjob_t::doSetBeamMonitorOutputEnabledFlag(
         bool const has_beam_monitor_output ) SIXTRL_NOEXCEPT
     {
         this->m_has_beam_monitor_output = has_beam_monitor_output;
     }
 
-    void TrackJobBaseNew::doSetElemByElemOutputEnabledFlag(
+    void tjob_t::doSetElemByElemOutputEnabledFlag(
         bool const has_elem_by_elem_output ) SIXTRL_NOEXCEPT
     {
         this->m_has_elem_by_elem_output = has_elem_by_elem_output;
@@ -2341,85 +3317,85 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBaseNew::doInitDefaultParticleSetIndices()
+    void tjob_t::doInitDefaultParticleSetIndices()
     {
         this->m_particle_set_indices.clear();
-        this->m_particle_set_indices.push_back( _this_t::size_type{ 0 } );
+        this->m_particle_set_indices.push_back( st_size_t{ 0 } );
 
         this->m_particle_set_begin_offsets.clear();
         this->m_particle_set_begin_offsets.push_back(
-            _this_t::num_particles_t{ 0 } );
+            tjob_t::num_particles_t{ 0 } );
 
         this->m_particle_set_end_offsets.clear();
         this->m_particle_set_end_offsets.push_back(
-            _this_t::num_particles_t{ 0 } );
+            tjob_t::num_particles_t{ 0 } );
     }
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBaseNew::doInitDefaultBeamMonitorIndices()
+    void tjob_t::doInitDefaultBeamMonitorIndices()
     {
         this->m_beam_monitor_indices.clear();
     }
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBaseNew::doSetNumParticleSetsInBuffer(
-        _this_t::size_type const num_psets ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetNumParticleSetsInBuffer(
+        st_size_t const num_psets ) SIXTRL_NOEXCEPT
     {
         this->m_num_particle_sets_in_buffer = num_psets;
     }
 
-    SIXTRL_HOST_FN void TrackJobBaseNew::doSetNumBeamElementsInBuffer(
-        _this_t::size_type const num_belems ) SIXTRL_NOEXCEPT
+    SIXTRL_HOST_FN void tjob_t::doSetNumBeamElementsInBuffer(
+        st_size_t const num_belems ) SIXTRL_NOEXCEPT
     {
         this->m_num_beam_elements_in_buffer = num_belems;
     }
 
-    void TrackJobBaseNew::doSetTotalNumParticles(
-        _this_t::num_particles_t const num_particles ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetTotalNumParticles(
+        tjob_t::num_particles_t const num_particles ) SIXTRL_NOEXCEPT
     {
         this->m_total_num_particles = num_particles;
     }
 
-    void TrackJobBaseNew::doSetTotalNumParticlesInSets(
-        _this_t::num_particles_t const pnum_in_sets ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetTotalNumParticlesInSets(
+        tjob_t::num_particles_t const pnum_in_sets ) SIXTRL_NOEXCEPT
     {
         this->m_total_num_particles_in_sets = pnum_in_sets;
     }
 
-    void TrackJobBaseNew::doSetMinParticleId(
-        _this_t::particle_index_t const min_part_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMinParticleId(
+        tjob_t::particle_index_t const min_part_id ) SIXTRL_NOEXCEPT
     {
          this->m_min_particle_id = min_part_id;
     }
 
-    void TrackJobBaseNew::doSetMaxParticleId(
-        _this_t::particle_index_t const max_part_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMaxParticleId(
+        tjob_t::particle_index_t const max_part_id ) SIXTRL_NOEXCEPT
     {
         this->m_max_particle_id = max_part_id;
     }
 
-    void TrackJobBaseNew::doSetMinElementId(
-        _this_t::particle_index_t const min_elem_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMinElementId(
+        tjob_t::particle_index_t const min_elem_id ) SIXTRL_NOEXCEPT
     {
         this->m_min_element_id = min_elem_id;
     }
 
-    void TrackJobBaseNew::doSetMaxElementId(
-        _this_t::particle_index_t const max_elem_id ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetMaxElementId(
+        tjob_t::particle_index_t const max_elem_id ) SIXTRL_NOEXCEPT
     {
         this->m_max_element_id = max_elem_id;
     }
 
-    void TrackJobBaseNew::doSetMinInitialTurnId(
-        _this_t::particle_index_t const
+    void tjob_t::doSetMinInitialTurnId(
+        tjob_t::particle_index_t const
             min_initial_turn_id ) SIXTRL_NOEXCEPT
     {
         this->m_min_initial_turn_id = min_initial_turn_id;
     }
 
-    void TrackJobBaseNew::doSetMaxInitialTurnId( particle_index_t const
+    void tjob_t::doSetMaxInitialTurnId( particle_index_t const
         max_initial_turn_id ) SIXTRL_NOEXCEPT
     {
         this->m_max_initial_turn_id = max_initial_turn_id;
@@ -2427,26 +3403,26 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _this_t::buffer_t const*
-        TrackJobBaseNew::doGetPtrParticlesAddrBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::buffer_t const*
+        tjob_t::doGetPtrParticlesAddrBuffer() const SIXTRL_NOEXCEPT
     {
         return this->m_my_particles_addr_buffer.get();
     }
 
-    _this_t::buffer_t*
-    TrackJobBaseNew::doGetPtrParticlesAddrBuffer() SIXTRL_NOEXCEPT
+    tjob_t::buffer_t*
+    tjob_t::doGetPtrParticlesAddrBuffer() SIXTRL_NOEXCEPT
     {
         return this->m_my_particles_addr_buffer.get();
     }
 
-    void TrackJobBaseNew::doUpdateStoredParticlesAddrBuffer(
-        TrackJobBaseNew::ptr_particles_addr_buffer_t&&
+    void tjob_t::doUpdateStoredParticlesAddrBuffer(
+        tjob_t::ptr_particles_addr_buffer_t&&
             ptr_buffer ) SIXTRL_NOEXCEPT
     {
         this->m_my_particles_addr_buffer = std::move( ptr_buffer );
     }
 
-    void TrackJobBaseNew::doSetHasParticleAddressesFlag(
+    void tjob_t::doSetHasParticleAddressesFlag(
             bool const has_particle_addresses ) SIXTRL_NOEXCEPT
     {
         this->m_has_particle_addresses = has_particle_addresses;
@@ -2454,26 +3430,20 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBaseNew::doUpdateStoredOutputBuffer(
-        TrackJobBaseNew::ptr_output_buffer_t&& ptr_out_buffer ) SIXTRL_NOEXCEPT
+    void tjob_t::doUpdateStoredOutputBuffer(
+        tjob_t::ptr_output_buffer_t&& ptr_out_buffer ) SIXTRL_NOEXCEPT
     {
         this->doSetPtrOutputBuffer( ptr_out_buffer.get() );
         this->m_my_output_buffer = std::move( ptr_out_buffer );
     }
 
-    void TrackJobBaseNew::doUpdateStoredElemByElemConfig(
-        TrackJobBaseNew::ptr_elem_by_elem_config_t&& ptr_conf ) SIXTRL_NOEXCEPT
-    {
-        this->m_my_elem_by_elem_config = std::move( ptr_conf );
-    }
-
-    void TrackJobBaseNew::doSetUsesControllerFlag(
+    void tjob_t::doSetUsesControllerFlag(
         bool const uses_controller_flag ) SIXTRL_NOEXCEPT
     {
         this->m_uses_controller = uses_controller_flag;
     }
 
-    void TrackJobBaseNew::doSetUsesArgumentsFlag(
+    void tjob_t::doSetUsesArgumentsFlag(
         bool const arguments_flag ) SIXTRL_NOEXCEPT
     {
         this->m_uses_arguments = arguments_flag;
@@ -2481,10 +3451,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    void TrackJobBaseNew::doClearParticlesStructuresBaseImpl() SIXTRL_NOEXCEPT
+    void tjob_t::doClearParticlesStructuresBaseImpl() SIXTRL_NOEXCEPT
     {
-        using num_particles_t = _this_t::num_particles_t;
-        using size_t = _this_t::size_type;
+        using num_particles_t = tjob_t::num_particles_t;
+        using size_t = st_size_t;
 
         this->doSetPtrParticlesBuffer( nullptr );
         this->doSetPtrCParticlesBuffer( nullptr );
@@ -2511,9 +3481,9 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    void TrackJobBaseNew::doClearBeamElementsStructuresBaseImpl() SIXTRL_NOEXCEPT
+    void tjob_t::doClearBeamElementsStructuresBaseImpl() SIXTRL_NOEXCEPT
     {
-        using size_t = _this_t::size_type;
+        using size_t = st_size_t;
 
         this->doSetPtrBeamElementsBuffer( nullptr );
         this->doSetPtrCBeamElementsBuffer( nullptr );
@@ -2522,9 +3492,9 @@ namespace SIXTRL_CXX_NAMESPACE
         this->doSetNumBeamElementsInBuffer( size_t{ 0 } );
     }
 
-    void TrackJobBaseNew::doClearOutputStructuresBaseImpl() SIXTRL_NOEXCEPT
+    void tjob_t::doClearOutputStructuresBaseImpl() SIXTRL_NOEXCEPT
     {
-        using size_t = _this_t::size_type;
+        using size_t = st_size_t;
 
         this->doSetPtrOutputBuffer( nullptr );
         this->doSetPtrCOutputBuffer( nullptr );
@@ -2536,8 +3506,11 @@ namespace SIXTRL_CXX_NAMESPACE
         this->doSetElemByElemOutputIndexOffset( size_t{ 0 } );
         this->doSetUntilTurnElemByElem( size_t{ 0 } );
 
+        SIXTRL_ASSERT( this->m_my_elem_by_elem_buffer.get() != nullptr );
+        this->m_my_elem_by_elem_buffer->reset();
+        this->m_elem_by_elem_config_index = size_t{ 0 };
+
         this->m_my_output_buffer.reset( nullptr );
-        this->m_my_elem_by_elem_config.reset( nullptr );
 
         this->m_default_elem_by_elem_order   =
             ::NS(ELEM_BY_ELEM_ORDER_DEFAULT);
@@ -2549,8 +3522,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* ********************************************************************* */
 
-    TrackJobBaseNew* TrackJobNew_create(
-        TrackJobBaseNew::arch_id_t const arch_id,
+    TrackJobBaseNew* TrackJobNew_create( tjob_t::arch_id_t const arch_id,
         char const* SIXTRL_RESTRICT conf_str )
     {
         TrackJobBaseNew* ptr_track_job = nullptr;
@@ -2573,6 +3545,7 @@ namespace SIXTRL_CXX_NAMESPACE
             }
         };
 
+        ( void )conf_str;
         return ptr_track_job;
     }
 
@@ -2670,8 +3643,7 @@ namespace SIXTRL_CXX_NAMESPACE
                     output_buffer, until_turn_elem_by_elem, config_str );
     }
 
-    TrackJobBaseNew* TrackJobNew_new(
-        ::NS(arch_id_t) const SIXTRL_RESTRICT arch_id,
+    TrackJobBaseNew* TrackJobNew_new( ::NS(arch_id_t) const arch_id,
         ::NS(Buffer)* SIXTRL_RESTRICT particles_buffer,
         ::NS(buffer_size_t) const num_psets,
         ::NS(buffer_size_t) const* SIXTRL_RESTRICT pset_indices_begin,
@@ -2796,7 +3768,7 @@ namespace SIXTRL_CXX_NAMESPACE
         Buffer::size_type const until_turn_elem_by_elem,
         std::string const& SIXTRL_RESTRICT_REF config_str )
     {
-        using size_t = _this_t::size_type;
+        using size_t = st_size_t;
 
         TrackJobBaseNew* ptr_track_job =
             st::TrackJobNew_create( arch_id, config_str );
diff --git a/sixtracklib/common/track/track_job_base.h b/sixtracklib/common/track/track_job_base.h
index 664c3b06..6201174c 100644
--- a/sixtracklib/common/track/track_job_base.h
+++ b/sixtracklib/common/track/track_job_base.h
@@ -412,6 +412,238 @@ SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_uses_controller)(
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_uses_arguments)(
     const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job );
 
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem)*
+NS(TrackJobNew_add_assign_address_item)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT_REF assign_item_to_add );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem)*
+NS(TrackJobNew_add_assign_address_item_detailed)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_remove_assign_address_item)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(AssignAddressItem)* SIXTRL_RESTRICT item_to_remove );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_remove_assign_address_item_by_key_and_index)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    const NS(TrackJobDestSrcBufferIds) *const SIXTRL_RESTRICT_REF key,
+    NS(buffer_size_t) const index_of_item_to_remove );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_has_assign_address_item)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT_REF
+        assign_item_to_add ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_has_assign_item_by_index)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const assign_item_index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_has_assign_address_item_detailed)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJobNew_index_of_assign_address_item_detailed)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJobNew_index_of_assign_address_item)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const
+        SIXTRL_RESTRICT assign_item_to_add ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_has_assign_items)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t) NS(TrackJobNew_num_assign_items)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJobNew_total_num_assign_items)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem) const*
+NS(TrackJobNew_ptr_assign_address_item)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT
+        assign_address_item ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem) const*
+NS(TrackJobNew_ptr_assign_address_item_detailed)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem) const*
+NS(TrackJobNew_ptr_assign_address_item_by_index)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const assign_address_item_index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJobNew_num_distinct_available_assign_address_items_dest_src_pairs)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJobNew_available_assign_address_items_dest_src_pairs)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const max_num_pairs,
+    NS(TrackJobDestSrcBufferIds)* pairs_begin ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer)* NS(TrackJobNew_buffer_by_buffer_id)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer) const*
+NS(TrackJobNew_const_buffer_by_buffer_id)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_is_buffer_by_buffer_id)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_is_raw_memory_by_buffer_id)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*
+NS(TrackJobNew_assign_items_begin)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*
+NS(TrackJobNew_assign_items_end)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(TrackJobDestSrcBufferIds) const*
+NS(TrackJobNew_assign_item_dest_src_begin)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(TrackJobDestSrcBufferIds) const*
+NS(TrackJobNew_assign_item_dest_src_end)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_commit_address_assignments)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_assign_all_addresses)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_assign_addresses)( NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJobNew_stored_buffers_capacity)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_reserve_stored_buffers_capacity)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(arch_size_t) const capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_has_stored_buffers)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJobNew_num_stored_buffers)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJobNew_min_stored_buffer_id)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJobNew_max_stored_buffer_id)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJobNew_create_stored_buffer)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJobNew_add_stored_buffer)( NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(Buffer)* SIXTRL_RESTRICT buffer, bool const take_ownership,
+    bool const delete_ptr_after_move );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobNew_owns_stored_buffer)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_remove_stored_buffer)( NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer)* NS(TrackJobNew_stored_buffer)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer) const*
+NS(TrackJobNew_const_stored_buffer)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_push_stored_buffer)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJobNew_collect_stored_buffer)(
+    NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id );
+
 #if defined( __cplusplus ) && !defined( _GPUCODE ) && !defined( __CUDA_ARCH__ )
 } /* extern "C" { */
 #endif /* C++, Host */
diff --git a/sixtracklib/common/track/track_job_base.hpp b/sixtracklib/common/track/track_job_base.hpp
index fdc66d7e..06dd5fb1 100644
--- a/sixtracklib/common/track/track_job_base.hpp
+++ b/sixtracklib/common/track/track_job_base.hpp
@@ -8,6 +8,7 @@
         #include <cstdint>
         #include <cstdlib>
         #include <memory>
+        #include <map>
         #include <string>
         #include <vector>
     #else /* !defined( __cplusplus ) */
@@ -21,19 +22,20 @@
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/control/definitions.h"
-    #include "sixtracklib/common/control/arch_base.hpp"
     #include "sixtracklib/common/track/definitions.h"
-
+    #include "sixtracklib/common/buffer.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+    #include "sixtracklib/common/control/arch_base.hpp"
+    #include "sixtracklib/common/output/output_buffer.h"
+    #include "sixtracklib/common/output/elem_by_elem_config.h"
+    #include "sixtracklib/common/particles.h"
+    #include "sixtracklib/common/particles/particles_addr.h"
+    #include "sixtracklib/common/track/track_job_buffer_store.h"
     #if defined( __cplusplus )
         #include "sixtracklib/common/buffer.hpp"
         #include "sixtracklib/common/particles/particles_addr.hpp"
+        #include "sixtracklib/common/internal/stl_buffer_helper.hpp"
     #endif /* defined( __cplusplus ) */
-
-    #include "sixtracklib/common/buffer.h"
-    #include "sixtracklib/common/particles/particles_addr.h"
-    #include "sixtracklib/common/particles.h"
-    #include "sixtracklib/common/output/output_buffer.h"
-    #include "sixtracklib/common/output/elem_by_elem_config.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if defined( __cplusplus ) && !defined( _GPUCODE )
@@ -56,12 +58,21 @@ namespace SIXTRL_CXX_NAMESPACE
         using elem_by_elem_config_t = ::NS(ElemByElemConfig);
         using elem_by_elem_order_t  = ::NS(elem_by_elem_order_t);
         using particle_index_t      = ::NS(particle_index_t);
-        using collect_flag_t        = ::NS(track_job_collect_flag_t);
-        using push_flag_t           = ::NS(track_job_push_flag_t);
+        using assign_item_t         = SIXTRL_CXX_NAMESPACE::AssignAddressItem;
+        using assign_item_key_t     = ::NS(TrackJobDestSrcBufferIds);
         using output_buffer_flag_t  = ::NS(output_buffer_flag_t);
+        using object_type_id_t      = ::NS(object_type_id_t);
         using particles_addr_t      = ::NS(ParticlesAddr);
         using num_particles_t       = ::NS(particle_num_elements_t);
 
+        using collect_flag_t        = ::NS(track_job_collect_flag_t);
+        using push_flag_t           = ::NS(track_job_push_flag_t);
+
+        /* ----------------------------------------------------------------- */
+
+        static constexpr size_type ILLEGAL_BUFFER_ID =
+                    SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_BUFFER_ID;
+
         /* ----------------------------------------------------------------- */
 
         SIXTRL_HOST_FN bool usesController() const SIXTRL_NOEXCEPT;
@@ -324,6 +335,178 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN c_buffer_t const*
         ptrCBeamElementsBuffer() const SIXTRL_NOEXCEPT;
 
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN assign_item_t* add_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF assign_item_to_add );
+
+        SIXTRL_HOST_FN assign_item_t* add_assign_address_item(
+            object_type_id_t const dest_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_index,
+            size_type const dest_pointer_offset,
+            object_type_id_t const src_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_index,
+            size_type const src_pointer_offset );
+
+        SIXTRL_HOST_FN status_t remove_assign_address_item(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+            size_type const index_of_item_to_remove );
+
+        SIXTRL_HOST_FN status_t remove_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF item_to_remove );
+
+        SIXTRL_HOST_FN bool has_assign_address_item( assign_item_t const&
+            SIXTRL_RESTRICT_REF assign_item ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool has_assign_address_item(
+            object_type_id_t const dest_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_index,
+            size_type const dest_pointer_offset,
+            object_type_id_t const src_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_index,
+            size_type const src_pointer_offset ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type index_of_assign_address_item(
+            object_type_id_t const dest_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_index,
+            size_type const dest_pointer_offset,
+            object_type_id_t const src_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_index,
+            size_type const src_pointer_offset ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type index_of_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF
+                assign_item ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool has_assign_items(
+            size_type const dest_buffer_id,
+            size_type const src_buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type num_assign_items(
+            size_type const dest_buffer_id,
+            size_type const src_buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type total_num_assign_items() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t const* ptr_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF
+                assign_address_item ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t const* ptr_assign_address_item(
+            size_type const dest_buffer_id,  size_type const src_buffer_id,
+            size_type const assign_item_index ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t const* ptr_assign_address_item(
+            object_type_id_t const dest_type_id,
+            size_type const dest_buffer_id,
+            size_type const dest_elem_index,
+            size_type const dest_pointer_offset,
+            object_type_id_t const src_type_id,
+            size_type const src_buffer_id,
+            size_type const src_elem_index,
+            size_type const src_pointer_offset ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            num_distinct_available_assign_address_items_dest_src_pairs() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type available_assign_address_items_dest_src_pairs(
+            size_type const max_num_pairs,
+            assign_item_key_t* pairs_begin ) const SIXTRL_NOEXCEPT;
+
+        template< typename PairIter >
+        SIXTRL_HOST_FN size_type available_assign_address_items_dest_src_pairs(
+            PairIter pairs_begin, PairIter pairs_end ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t* buffer_by_buffer_id(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t const* buffer_by_buffer_id(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool is_buffer_by_buffer_id(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN bool is_raw_memory_by_buffer_id(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*
+        assign_items_begin( size_type const dest_buffer_id,
+            size_type const src_buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*
+        assign_items_end( size_type const dest_buffer_id,
+            size_type const src_buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_key_t const*
+        assign_item_dest_src_begin() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_key_t const*
+        assign_item_dest_src_end() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t commit_address_assignments();
+
+        SIXTRL_HOST_FN status_t assign_all_addresses();
+        SIXTRL_HOST_FN status_t assign_addresses(
+            size_type const dest_buffer_id, size_type const src_buffer_id );
+
+        /* ---------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN size_type
+        stored_buffers_capacity() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t reserve_stored_buffers_capacity(
+            size_type const capacity );
+
+        SIXTRL_HOST_FN bool has_stored_buffers() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            num_stored_buffers() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            min_stored_buffer_id() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            max_stored_buffer_id() const SIXTRL_NOEXCEPT;
+
+        template< typename... Args >
+        SIXTRL_HOST_FN size_type add_stored_buffer( Args&&... args );
+
+        SIXTRL_HOST_FN bool owns_stored_buffer(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t remove_stored_buffer(
+            size_type const buffer_index );
+
+        SIXTRL_HOST_FN buffer_t& stored_cxx_buffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN buffer_t const& stored_cxx_buffer(
+            size_type const buffer_id ) const;
+
+        SIXTRL_HOST_FN buffer_t* ptr_stored_cxx_buffer(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t const* ptr_stored_cxx_buffer(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t* ptr_stored_buffer(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t const* ptr_stored_buffer(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t push_stored_buffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t collect_stored_buffer(
+            size_type const buffer_id );
+
         /* ---------------------------------------------------------------- */
 
         SIXTRL_HOST_FN bool hasOutputBuffer()      const SIXTRL_NOEXCEPT;
@@ -344,13 +527,13 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-        SIXTRL_HOST_FN buffer_t* ptrOutputBuffer() SIXTRL_RESTRICT;
-        SIXTRL_HOST_FN buffer_t const* ptrOutputBuffer() const SIXTRL_RESTRICT;
+        SIXTRL_HOST_FN buffer_t* ptrOutputBuffer() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN buffer_t const* ptrOutputBuffer() const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN c_buffer_t* ptrCOutputBuffer() SIXTRL_RESTRICT;
+        SIXTRL_HOST_FN c_buffer_t* ptrCOutputBuffer() SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN c_buffer_t const*
-        ptrCOutputBuffer() const SIXTRL_RESTRICT;
+        ptrCOutputBuffer() const SIXTRL_NOEXCEPT;
 
         /* ----------------------------------------------------------------- */
 
@@ -390,6 +573,17 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN void setDefaultElemByElemOrder(
             elem_by_elem_order_t const order ) SIXTRL_NOEXCEPT;
 
+        SIXTRL_HOST_FN buffer_t const& elem_by_elem_config_cxx_buffer() const;
+        SIXTRL_HOST_FN buffer_t& elem_by_elem_config_cxx_buffer();
+
+        SIXTRL_HOST_FN c_buffer_t const*
+        elem_by_elem_config_buffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t* elem_by_elem_config_buffer() SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            elem_by_elem_config_index() const SIXTRL_NOEXCEPT;
+
         /* ================================================================ */
 
         template< class Derived >
@@ -404,11 +598,21 @@ namespace SIXTRL_CXX_NAMESPACE
 
         protected:
 
-        using clear_flag_t = SIXTRL_CXX_NAMESPACE::track_job_clear_flag_t;
-        using el_by_el_conf_t = elem_by_elem_config_t;
+        using ptr_buffer_t = std::unique_ptr< buffer_t >;
         using ptr_output_buffer_t = std::unique_ptr< buffer_t >;
         using ptr_particles_addr_buffer_t = std::unique_ptr< buffer_t >;
-        using ptr_elem_by_elem_config_t = std::unique_ptr< el_by_el_conf_t >;
+        using buffer_store_t = SIXTRL_CXX_NAMESPACE::TrackJobBufferStore;
+
+        using clear_flag_t = SIXTRL_CXX_NAMESPACE::track_job_clear_flag_t;
+        using el_by_el_conf_t = elem_by_elem_config_t;
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_STATIC SIXTRL_HOST_FN void COPY_PTR_BUFFER(
+            ptr_buffer_t& SIXTRL_RESTRICT_REF dest_ptr_buffer,
+            ptr_buffer_t const& SIXTRL_RESTRICT_REF src_ptr_buffer );
+
+        /* ----------------------------------------------------------------- */
 
         SIXTRL_HOST_FN static bool IsClearFlagSet( clear_flag_t const haystack,
             clear_flag_t const needle ) SIXTRL_NOEXCEPT;
@@ -496,6 +700,34 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* ----------------------------------------------------------------- */
 
+        SIXTRL_HOST_FN virtual size_type do_add_stored_buffer(
+            buffer_store_t&& assigned_buffer_handle );
+
+        SIXTRL_HOST_FN virtual status_t do_remove_stored_buffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN virtual status_t do_push_stored_buffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN virtual status_t do_collect_stored_buffer(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN virtual status_t do_add_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF assign_item,
+            size_type* SIXTRL_RESTRICT ptr_item_index );
+
+        SIXTRL_HOST_FN virtual status_t do_remove_assign_address_item(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF assign_item_key,
+            size_type const index_of_item_to_remove );
+
+        SIXTRL_HOST_FN virtual status_t do_perform_address_assignments(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF assign_item_key );
+
+        SIXTRL_HOST_FN virtual status_t do_commit_address_assignments();
+        SIXTRL_HOST_FN virtual status_t do_rebuild_assign_items_buffer_arg();
+
+        /* ----------------------------------------------------------------- */
+
         SIXTRL_HOST_FN virtual status_t doFetchParticleAddresses();
 
         SIXTRL_HOST_FN virtual status_t doClearParticleAddresses(
@@ -625,9 +857,6 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN void doUpdateStoredOutputBuffer(
             ptr_output_buffer_t&& ptr_output_buffer ) SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN void doUpdateStoredElemByElemConfig(
-            ptr_elem_by_elem_config_t&& ptr_config ) SIXTRL_NOEXCEPT;
-
         /* ----------------------------------------------------------------- */
 
         SIXTRL_HOST_FN void doSetUsesControllerFlag(
@@ -650,10 +879,38 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN void doSetDefaultPrepareResetClearFlags(
             clear_flag_t const flags ) SIXTRL_NOEXCEPT;
 
-        /* ----------------------------------------------------------------- */
+        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+        SIXTRL_HOST_FN buffer_store_t* do_get_ptr_buffer_store(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_store_t const* do_get_ptr_buffer_store(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+            do_get_stored_buffer_size() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type do_find_assign_address_item(
+            assign_item_t const& SIXTRL_RESTRICT_REF item_to_search
+        ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t const* do_get_assign_address_item(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+            size_type const item_index ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN assign_item_t* do_get_assign_address_item(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF key,
+            size_type const item_index ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t* do_get_ptr_assign_address_items_buffer(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF key ) SIXTRL_NOEXCEPT;
 
         private:
 
+        using assing_item_map_t = std::map< assign_item_key_t, buffer_t,
+            SIXTRL_CXX_NAMESPACE::TrackJobDestSrcBufferIdsLessCmp >;
+        using assign_item_keys_list_t = std::vector< assign_item_key_t >;
+
         SIXTRL_HOST_FN void
         doSetDefaultPrepareResetClearFlags() SIXTRL_NOEXCEPT;
 
@@ -665,14 +922,17 @@ namespace SIXTRL_CXX_NAMESPACE
 
         SIXTRL_HOST_FN void doClearOutputStructuresBaseImpl() SIXTRL_NOEXCEPT;
 
+        assing_item_map_t               m_assign_address_items;
         std::vector< size_type >        m_particle_set_indices;
         std::vector< num_particles_t >  m_particle_set_begin_offsets;
         std::vector< num_particles_t >  m_particle_set_end_offsets;
         std::vector< size_type >        m_beam_monitor_indices;
+        std::vector< buffer_store_t >   m_stored_buffers;
+        assign_item_keys_list_t         m_assign_item_keys;
 
         ptr_output_buffer_t             m_my_output_buffer;
+        ptr_buffer_t                    m_my_elem_by_elem_buffer;
         ptr_particles_addr_buffer_t     m_my_particles_addr_buffer;
-        ptr_elem_by_elem_config_t       m_my_elem_by_elem_config;
 
         buffer_t*   SIXTRL_RESTRICT     m_ptr_particles_buffer;
         buffer_t*   SIXTRL_RESTRICT     m_ptr_beam_elem_buffer;
@@ -686,6 +946,8 @@ namespace SIXTRL_CXX_NAMESPACE
         size_type                       m_elem_by_elem_output_offset;
         size_type                       m_num_particle_sets_in_buffer;
         size_type                       m_num_beam_elements_in_buffer;
+        size_type                       m_elem_by_elem_config_index;
+        size_type                       m_num_stored_buffers;
 
         elem_by_elem_order_t            m_default_elem_by_elem_order;
         num_particles_t                 m_total_num_particles;
@@ -766,7 +1028,7 @@ namespace SIXTRL_CXX_NAMESPACE
         char const* SIXTRL_RESTRICT config_str );
 
     SIXTRL_HOST_FN TrackJobBaseNew* TrackJobNew_new(
-        ::NS(arch_id_t) const SIXTRL_RESTRICT arch_str,
+        ::NS(arch_id_t) const arch_id,
         ::NS(Buffer)* SIXTRL_RESTRICT particles_buffer,
         ::NS(buffer_size_t) const num_particle_sets,
         ::NS(buffer_size_t) const* SIXTRL_RESTRICT particle_set_indices_begin,
@@ -945,6 +1207,50 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
+    template< typename... Args >
+    TrackJobBaseNew::size_type
+    TrackJobBaseNew::add_stored_buffer( Args&&... args )
+    {
+        SIXTRL_CXX_NAMESPACE::TrackJobBaseNew::buffer_store_t temp_buffer_store(
+            std::forward< Args >( args )... );
+        return this->do_add_stored_buffer( std::move( temp_buffer_store ) );
+    }
+
+    template< typename PairIter >
+    SIXTRL_HOST_FN TrackJobBaseNew::size_type
+    TrackJobBaseNew::available_assign_address_items_dest_src_pairs(
+        PairIter out_it, PairIter out_end ) const SIXTRL_NOEXCEPT
+    {
+        using st_size_t = SIXTRL_CXX_NAMESPACE::TrackJobBaseNew::size_type;
+        st_size_t num_pairs = st_size_t{ 0 };
+
+        if( !this->m_assign_address_items.empty() )
+        {
+            SIXTRL_ASSERT( this->m_assign_address_items.size() ==
+                           this->m_assign_item_keys.size() );
+
+            auto it = this->m_assign_item_keys.begin();
+            auto end = this->m_assign_item_keys.end();
+
+            while( ( out_it != out_end ) && ( it != end ) )
+            {
+                *out_it = *it;
+                ++num_pairs;
+                ++out_it;
+                ++it;
+            }
+        }
+
+        std::fill( out_it, out_end,
+            SIXTRL_CXX_NAMESPACE::TrackJobBaseNew::assign_item_key_t{
+                SIXTRL_CXX_NAMESPACE::TrackJobBaseNew::ILLEGAL_BUFFER_ID,
+                SIXTRL_CXX_NAMESPACE::TrackJobBaseNew::ILLEGAL_BUFFER_ID } );
+
+        return num_pairs;
+    }
+
+    /* --------------------------------------------------------------------- */
+
     template< class Derived > Derived const* TrackJobBaseNew::asDerivedTrackJob(
         TrackJobBaseNew::arch_id_t const required_arch_id,
         bool requires_exact_match ) const SIXTRL_NOEXCEPT
@@ -1156,6 +1462,23 @@ namespace SIXTRL_CXX_NAMESPACE
         return flag_set & ~flag;
     }
 
+    /* --------------------------------------------------------------------- */
+
+    SIXTRL_INLINE void TrackJobBaseNew::COPY_PTR_BUFFER(
+        TrackJobBaseNew::ptr_buffer_t& SIXTRL_RESTRICT_REF dest_ptr_buffer,
+        TrackJobBaseNew::ptr_buffer_t const& SIXTRL_RESTRICT_REF src_ptr_buffer )
+    {
+        if( src_ptr_buffer.get() != nullptr )
+        {
+            dest_ptr_buffer.reset(
+                new TrackJobBaseNew::buffer_t( *src_ptr_buffer.get() ) );
+        }
+        else
+        {
+            dest_ptr_buffer.reset( nullptr );
+        }
+    }
+
     /* ********************************************************************* */
 
     template< typename Iter > TrackJobBaseNew* TrackJobNew_new(
diff --git a/sixtracklib/common/track/track_job_base_c99.cpp b/sixtracklib/common/track/track_job_base_c99.cpp
index 36d9639b..304c1394 100644
--- a/sixtracklib/common/track/track_job_base_c99.cpp
+++ b/sixtracklib/common/track/track_job_base_c99.cpp
@@ -292,7 +292,8 @@ ::NS(ParticlesAddr) const* NS(TrackJobNew_get_particle_addresses)(
     const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
     ::NS(buffer_size_t) const particle_set_index )
 {
-    return ( job != nullptr ) ? job->particleAddresses() : nullptr;
+    return ( job != nullptr )
+        ? job->particleAddresses( particle_set_index ) : nullptr;
 }
 
 ::NS(Buffer) const* NS(TrackJobNew_get_ptr_particle_addresses_buffer)(
@@ -696,6 +697,428 @@ bool NS(TrackJobNew_uses_arguments)(
     return ( ( job != nullptr ) && ( job->usesArguments() ) );
 }
 
-#endif /* C++, Host */
+/* ------------------------------------------------------------------------- */
+
+::NS(AssignAddressItem)* NS(TrackJobNew_add_assign_address_item)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT assign_item_to_add )
+{
+    st::AssignAddressItem const* ptr_cxx_item = reinterpret_cast<
+        st::AssignAddressItem const* >( assign_item_to_add );
+
+    return ( ( job != nullptr ) && ( ptr_cxx_item != nullptr ) )
+        ? job->add_assign_address_item( *ptr_cxx_item ) : nullptr;
+}
+
+::NS(AssignAddressItem)* NS(TrackJobNew_add_assign_address_item_detailed)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(object_type_id_t) const dest_type_id,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const dest_elem_index,
+    ::NS(buffer_size_t) const dest_pointer_offset,
+    ::NS(object_type_id_t) const src_type_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const src_elem_index,
+    ::NS(buffer_size_t) const src_pointer_offset )
+{
+    return ( job != nullptr )
+        ? job->add_assign_address_item(
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset )
+        : nullptr;
+}
+
+::NS(arch_status_t) NS(TrackJobNew_remove_assign_address_item)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(AssignAddressItem)* SIXTRL_RESTRICT item_to_remove )
+{
+    st::AssignAddressItem const* ptr_cxx_item = reinterpret_cast<
+        st::AssignAddressItem const* >( item_to_remove );
+
+    return ( ( job != nullptr ) && ( ptr_cxx_item != nullptr ) )
+        ? job->remove_assign_address_item( *ptr_cxx_item )
+        : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJobNew_remove_assign_address_item_by_key_and_index)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    const ::NS(TrackJobDestSrcBufferIds) *const SIXTRL_RESTRICT_REF key,
+    ::NS(buffer_size_t) const index_of_item_to_remove )
+{
+    return ( ( job != nullptr ) && ( key != nullptr ) )
+        ? job->remove_assign_address_item( *key, index_of_item_to_remove )
+        : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+bool NS(TrackJobNew_has_assign_address_item)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT item ) SIXTRL_NOEXCEPT
+{
+    st::AssignAddressItem const* ptr_cxx_item = reinterpret_cast<
+        st::AssignAddressItem const* >( item );
+
+    return ( ( job != nullptr ) && ( ptr_cxx_item != nullptr ) &&
+             ( job->has_assign_address_item( *ptr_cxx_item ) ) );
+}
+
+bool NS(TrackJobNew_has_assign_item_by_index)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const item_index ) SIXTRL_NOEXCEPT
+{
+    return ( ( job != nullptr ) && ( job->num_assign_items(
+                dest_buffer_id, src_buffer_id ) > item_index ) );
+}
+
+bool NS(TrackJobNew_has_assign_address_item_detailed)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(object_type_id_t) const dest_type_id,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const dest_elem_index,
+    ::NS(buffer_size_t) const dest_pointer_offset,
+    ::NS(object_type_id_t) const src_type_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const src_elem_index,
+    ::NS(buffer_size_t) const src_pointer_offset ) SIXTRL_NOEXCEPT
+{
+    return ( ( job != nullptr ) &&
+        ( job->has_assign_address_item( dest_type_id, dest_buffer_id,
+                dest_elem_index, dest_pointer_offset, src_type_id,
+                    src_buffer_id, src_elem_index, src_pointer_offset ) ) );
+}
+
+::NS(buffer_size_t) NS(TrackJobNew_index_of_assign_address_item_detailed)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(object_type_id_t) const dest_type_id,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const dest_elem_index,
+    ::NS(buffer_size_t) const dest_pointer_offset,
+    ::NS(object_type_id_t) const src_type_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const src_elem_index,
+    ::NS(buffer_size_t) const src_pointer_offset ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->index_of_assign_address_item(
+            dest_type_id, dest_buffer_id, dest_elem_index, dest_pointer_offset,
+            src_type_id, src_buffer_id, src_elem_index, src_pointer_offset )
+        : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(buffer_size_t) NS(TrackJobNew_index_of_assign_address_item)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT item ) SIXTRL_NOEXCEPT
+{
+    st::AssignAddressItem const* ptr_cxx_item = reinterpret_cast<
+        st::AssignAddressItem const* >( item );
+
+    return ( ( job != nullptr ) && ( ptr_cxx_item != nullptr ) )
+        ? job->index_of_assign_address_item( *ptr_cxx_item )
+        : ::NS(buffer_size_t){ 0 };
+}
+
+bool NS(TrackJobNew_has_assign_items)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( ( job != nullptr ) &&
+             ( job->has_assign_items( dest_buffer_id, src_buffer_id ) ) );
+}
+
+::NS(buffer_size_t) NS(TrackJobNew_num_assign_items)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->num_assign_items( dest_buffer_id, src_buffer_id )
+        : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(buffer_size_t) NS(TrackJobNew_total_num_assign_items)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->total_num_assign_items() : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(AssignAddressItem) const* NS(TrackJobNew_ptr_assign_address_item)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    const ::NS(AssignAddressItem) *const SIXTRL_RESTRICT item ) SIXTRL_NOEXCEPT
+{
+    ::NS(AssignAddressItem) const* ptr_item = nullptr;
+
+    if( ( job != nullptr ) && ( item != nullptr ) )
+    {
+        st::AssignAddressItem const* _ptr = job->ptr_assign_address_item(
+            *( reinterpret_cast< st::AssignAddressItem const* >( item ) ) );
+        if( _ptr != nullptr ) ptr_item = _ptr->getCApiPtr();
+    }
+
+    return ptr_item;
+}
+
+::NS(AssignAddressItem) const* NS(TrackJobNew_ptr_assign_address_item_detailed)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(object_type_id_t) const dest_type_id,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const dest_elem_index,
+    ::NS(buffer_size_t) const dest_pointer_offset,
+    ::NS(object_type_id_t) const src_type_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const src_elem_index,
+    ::NS(buffer_size_t) const src_pointer_offset ) SIXTRL_NOEXCEPT
+{
+    ::NS(AssignAddressItem) const* ptr_item = nullptr;
+    if( job != nullptr )
+    {
+        st::TrackJobBaseNew::size_type const assign_address_item_index =
+            job->index_of_assign_address_item( dest_type_id, dest_buffer_id,
+                dest_elem_index, dest_pointer_offset, src_type_id,
+                    src_buffer_id, src_elem_index, src_pointer_offset );
+
+        ptr_item = job->ptr_assign_address_item(
+            dest_buffer_id, src_buffer_id, assign_address_item_index );
+    }
+
+    return ptr_item;
+}
+
+::NS(AssignAddressItem) const* NS(TrackJobNew_ptr_assign_address_item_by_index)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id,
+    ::NS(buffer_size_t) const assign_address_item_index ) SIXTRL_NOEXCEPT
+{
+    ::NS(AssignAddressItem) const* ptr_item = nullptr;
+    if( job != nullptr )
+    {
+        st::AssignAddressItem const* _ptr = job->ptr_assign_address_item(
+            dest_buffer_id, src_buffer_id, assign_address_item_index );
+        if( _ptr != nullptr ) ptr_item = _ptr->getCApiPtr();
+    }
+
+    return ptr_item;
+}
+
+::NS(buffer_size_t)
+NS(TrackJobNew_num_distinct_available_assign_address_items_dest_src_pairs)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->num_distinct_available_assign_address_items_dest_src_pairs()
+        : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(buffer_size_t) NS(TrackJobNew_available_assign_address_items_dest_src_pairs)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const max_num_pairs,
+    ::NS(TrackJobDestSrcBufferIds)* pairs_begin ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->available_assign_address_items_dest_src_pairs(
+            max_num_pairs, pairs_begin )
+        : ::NS(buffer_size_t){ 0 };
+}
+
+::NS(Buffer)* NS(TrackJobNew_buffer_by_buffer_id)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->buffer_by_buffer_id( buffer_id ) : nullptr;
+}
+
+::NS(Buffer) const* NS(TrackJobNew_const_buffer_by_buffer_id)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->buffer_by_buffer_id( buffer_id ) : nullptr;
+}
+
+bool NS(TrackJobNew_is_buffer_by_buffer_id)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( ( job != nullptr ) &&
+             ( job->is_buffer_by_buffer_id)( buffer_id ) );
+}
+
+bool NS(TrackJobNew_is_raw_memory_by_buffer_id)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( ( job != nullptr ) &&
+             ( job->is_raw_memory_by_buffer_id( buffer_id ) ) );
+}
+
+SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object) const*
+NS(TrackJobNew_assign_items_begin)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->assign_items_begin( dest_buffer_id, src_buffer_id ) : nullptr;
+}
+
+SIXTRL_BUFFER_OBJ_ARGPTR_DEC ::NS(Object) const*
+NS(TrackJobNew_assign_items_end)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->assign_items_end( dest_buffer_id, src_buffer_id ) : nullptr;
+}
+
+::NS(TrackJobDestSrcBufferIds) const*
+NS(TrackJobNew_assign_item_dest_src_begin)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->assign_item_dest_src_begin() : nullptr;
+}
+
+::NS(TrackJobDestSrcBufferIds) const*
+NS(TrackJobNew_assign_item_dest_src_end)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->assign_item_dest_src_end() : nullptr;
+}
+
+::NS(arch_status_t) NS(TrackJobNew_commit_address_assignments)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->commit_address_assignments() : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJobNew_assign_all_addresses)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr )
+        ? job->assign_all_addresses() : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJobNew_assign_addresses)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(buffer_size_t) const src_buffer_id )
+{
+    return ( job != nullptr )
+        ? job->assign_addresses( dest_buffer_id, src_buffer_id )
+        : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+/* ------------------------------------------------------------------------- */
+
+::NS(arch_size_t) NS(TrackJobNew_stored_buffers_capacity)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->stored_buffers_capacity() : ::NS(arch_size_t){ 0 };
+}
+
+::NS(arch_status_t) NS(TrackJobNew_reserve_stored_buffers_capacity)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const capacity )
+{
+    return ( job != nullptr )
+        ? job->reserve_stored_buffers_capacity( capacity )
+        : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+bool NS(TrackJobNew_has_stored_buffers)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( ( job != nullptr ) && ( job->has_stored_buffers() ) );
+}
+
+::NS(arch_size_t) NS(TrackJobNew_num_stored_buffers)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->num_stored_buffers() : ::NS(arch_size_t){ 0 };
+}
+
+::NS(arch_size_t) NS(TrackJobNew_min_stored_buffer_id)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->min_stored_buffer_id() : st::ARCH_ILLEGAL_BUFFER_ID;
+}
+
+::NS(arch_size_t) NS(TrackJobNew_max_stored_buffer_id)(
+    const NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr )
+        ? job->max_stored_buffer_id() : st::ARCH_ILLEGAL_BUFFER_ID;
+}
+
+::NS(arch_size_t) NS(TrackJobNew_create_stored_buffer)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_capacity )
+{
+    return ( job != nullptr ) ? job->add_stored_buffer( buffer_capacity )
+        : st::ARCH_ILLEGAL_BUFFER_ID;
+}
+
+::NS(arch_size_t) NS(TrackJobNew_add_stored_buffer)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(Buffer)* SIXTRL_RESTRICT buffer, bool const take_ownership,
+    bool const delete_ptr_after_move )
+{
+    return ( job != nullptr )
+        ? job->add_stored_buffer( buffer, take_ownership, delete_ptr_after_move )
+        : st::ARCH_ILLEGAL_BUFFER_ID;
+}
+
+bool NS(TrackJobNew_owns_stored_buffer)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( ( job != nullptr ) && ( job->owns_stored_buffer( buffer_id ) ) );
+}
+
+::NS(arch_status_t) NS(TrackJobNew_remove_stored_buffer)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_index )
+{
+    return ( job != nullptr )
+        ? job->remove_stored_buffer( buffer_index )
+        : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(Buffer)* NS(TrackJobNew_stored_buffer)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->ptr_stored_buffer( buffer_id ) : nullptr;
+}
+
+::NS(Buffer) const* NS(TrackJobNew_const_stored_buffer)(
+    const ::NS(TrackJobBaseNew) *const SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_id ) SIXTRL_NOEXCEPT
+{
+    return ( job != nullptr ) ? job->ptr_stored_buffer( buffer_id ) : nullptr;
+}
 
-/* end: sixtracklib/common/track/track_job_base_c99.cpp */
+::NS(arch_status_t) NS(TrackJobNew_push_stored_buffer)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->push_stored_buffer( buffer_id )
+        : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+::NS(arch_status_t) NS(TrackJobNew_collect_stored_buffer)(
+    ::NS(TrackJobBaseNew)* SIXTRL_RESTRICT job,
+    ::NS(arch_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->collect_stored_buffer( buffer_id )
+        : st::ARCH_STATUS_GENERAL_FAILURE;
+}
+#endif /* C++, Host */
diff --git a/sixtracklib/common/track/track_job_buffer_store.cpp b/sixtracklib/common/track/track_job_buffer_store.cpp
new file mode 100644
index 00000000..c28da1a0
--- /dev/null
+++ b/sixtracklib/common/track/track_job_buffer_store.cpp
@@ -0,0 +1,309 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/track/track_job_buffer_store.h"
+#endif /* !defined SIXTRL_NO_INCLUDES */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #if defined( __cplusplus )
+        #include <cstddef>
+        #include <cstdint>
+        #include <cstdlib>
+        #include <memory>
+    #else /* !defined( __cplusplus ) */
+        #include <stdbool.h>
+        #include <stddef.h>
+        #include <stdint.h>
+        #include <stdlib.h>
+        #include <limits.h>
+    #endif /* !defined( __cplusplus ) */
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/track/definitions.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+    #include "sixtracklib/common/buffer.h"
+    #if defined( __cplusplus )
+        #include "sixtracklib/common/buffer.hpp"
+    #endif /* defined( __cplusplus ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus )
+namespace SIXTRL_CXX_NAMESPACE
+{
+    namespace
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using buf_store_t = st::TrackJobBufferStore;
+        using st_size_t   = buf_store_t::size_type;
+        using st_flags_t  = buf_store_t::flags_t;
+    }
+
+    buf_store_t::TrackJobBufferStore(
+        st_size_t const buffer_capacity,
+        st_flags_t const buffer_flags ) :
+        m_ptr_cxx_buffer( nullptr ), m_ptr_c99_buffer( nullptr ),
+        m_own_buffer( nullptr )
+    {
+        this->reset( buffer_capacity, buffer_flags );
+    }
+
+    buf_store_t::TrackJobBufferStore(
+        buf_store_t::buffer_t* SIXTRL_RESTRICT cxx_buffer,
+        bool const take_ownership ) :
+        m_ptr_cxx_buffer( nullptr ), m_ptr_c99_buffer( nullptr ),
+        m_own_buffer( nullptr )
+    {
+        this->reset( cxx_buffer, take_ownership );
+    }
+
+    buf_store_t::TrackJobBufferStore(
+        buf_store_t::c_buffer_t* SIXTRL_RESTRICT c99_buffer,
+        bool const take_ownership, bool const delete_ptr_after_move ) :
+        m_ptr_cxx_buffer( nullptr ), m_ptr_c99_buffer( nullptr ),
+        m_own_buffer( nullptr )
+    {
+        this->reset( c99_buffer, take_ownership, delete_ptr_after_move );
+    }
+
+    buf_store_t::TrackJobBufferStore(
+        std::unique_ptr< buf_store_t::buffer_t >&& stored_ptr_buffer ) :
+        m_ptr_cxx_buffer( nullptr ), m_ptr_c99_buffer( nullptr ),
+        m_own_buffer( nullptr )
+    {
+        this->reset( std::move( stored_ptr_buffer ) );
+    }
+
+    buf_store_t::TrackJobBufferStore(
+        buf_store_t::buffer_t&& cxx_buffer ) :
+        m_ptr_cxx_buffer( nullptr ), m_ptr_c99_buffer( nullptr ),
+        m_own_buffer( nullptr )
+    {
+        this->reset( std::move( cxx_buffer ) );
+    }
+
+    buf_store_t::TrackJobBufferStore(
+        TrackJobBufferStore const& other ) :
+        m_ptr_cxx_buffer( nullptr ), m_ptr_c99_buffer( nullptr ),
+        m_own_buffer( nullptr )
+    {
+        if( other.owns_buffer() )
+        {
+            SIXTRL_ASSERT( other.m_own_buffer.get() != nullptr );
+            this->m_own_buffer.reset(
+                new st::Buffer( *other.m_own_buffer.get() ) );
+
+            this->m_ptr_cxx_buffer = this->m_own_buffer.get();
+            this->m_ptr_c99_buffer = this->m_own_buffer->getCApiPtr();
+        }
+        else
+        {
+            this->m_ptr_cxx_buffer = other.m_ptr_cxx_buffer;
+            this->m_ptr_c99_buffer = other.m_ptr_c99_buffer;
+        }
+    }
+
+    buf_store_t::TrackJobBufferStore(
+        TrackJobBufferStore&& other ) SIXTRL_NOEXCEPT:
+        m_ptr_cxx_buffer( std::move( other.m_ptr_cxx_buffer ) ),
+        m_ptr_c99_buffer( std::move( other.m_ptr_c99_buffer ) ),
+        m_own_buffer( std::move( other.m_own_buffer ) )
+    {
+        if( other.owns_buffer() )
+        {
+            SIXTRL_ASSERT( other.m_own_buffer.get() != nullptr );
+            this->m_own_buffer.reset(
+                new st::Buffer( *other.m_own_buffer.get() ) );
+
+            this->m_ptr_cxx_buffer = this->m_own_buffer.get();
+            this->m_ptr_c99_buffer = this->m_own_buffer->getCApiPtr();
+        }
+        else
+        {
+            this->m_ptr_cxx_buffer = other.m_ptr_cxx_buffer;
+            this->m_ptr_c99_buffer = other.m_ptr_c99_buffer;
+        }
+    }
+
+    TrackJobBufferStore& buf_store_t::operator=(
+        TrackJobBufferStore const& rhs )
+    {
+        if( this != &rhs )
+        {
+            if( rhs.owns_buffer() )
+            {
+                SIXTRL_ASSERT( rhs.m_own_buffer.get() != nullptr );
+
+                this->m_own_buffer.reset(
+                    new st::Buffer( *rhs.m_own_buffer.get() ) );
+
+                this->m_ptr_cxx_buffer = this->m_own_buffer.get();
+                this->m_ptr_c99_buffer = this->m_own_buffer->getCApiPtr();
+            }
+            else
+            {
+                this->m_ptr_cxx_buffer = rhs.m_ptr_cxx_buffer;
+                this->m_ptr_c99_buffer = rhs.m_ptr_c99_buffer;
+            }
+        }
+
+        return *this;
+    }
+
+    TrackJobBufferStore&
+    buf_store_t::operator=( TrackJobBufferStore&& rhs ) SIXTRL_NOEXCEPT
+    {
+        if( this != &rhs )
+        {
+            this->m_own_buffer = std::move( rhs.m_own_buffer );
+            this->m_ptr_cxx_buffer = std::move( rhs.m_ptr_cxx_buffer );
+            this->m_ptr_c99_buffer = std::move( rhs.m_ptr_c99_buffer );
+        }
+
+        return *this;
+    }
+
+    bool buf_store_t::active() const SIXTRL_NOEXCEPT
+    {
+        SIXTRL_ASSERT(
+            ( ( this->m_ptr_c99_buffer == nullptr ) &&
+                ( this->m_ptr_cxx_buffer == nullptr ) &&
+                ( this->m_own_buffer.get() == nullptr ) ) ||
+            ( ( this->m_ptr_c99_buffer != nullptr ) &&
+                ( ( this->m_ptr_cxx_buffer == nullptr ) ||
+                ( this->m_ptr_cxx_buffer->getCApiPtr() ==
+                    this->m_ptr_c99_buffer ) ) &&
+                ( ( this->m_own_buffer == nullptr ) ||
+                ( this->m_own_buffer.get() ==
+                    this->m_ptr_cxx_buffer ) ) ) );
+
+        return ( this->m_ptr_c99_buffer != nullptr );
+    }
+
+    bool buf_store_t::owns_buffer() const SIXTRL_NOEXCEPT
+    {
+        return ( ( this->active() ) &&
+                 ( this->m_own_buffer.get() != nullptr ) );
+    }
+
+    buf_store_t::c_buffer_t const*
+    buf_store_t::ptr_buffer() const SIXTRL_NOEXCEPT
+    {
+        return this->m_ptr_c99_buffer;
+    }
+
+    buf_store_t::c_buffer_t* buf_store_t::ptr_buffer() SIXTRL_NOEXCEPT
+    {
+        return this->m_ptr_c99_buffer;
+    }
+
+    buf_store_t::buffer_t const*
+    buf_store_t::ptr_cxx_buffer() const SIXTRL_NOEXCEPT
+    {
+        return this->m_ptr_cxx_buffer;
+    }
+
+    buf_store_t::buffer_t* buf_store_t::ptr_cxx_buffer() SIXTRL_NOEXCEPT
+    {
+        return this->m_ptr_cxx_buffer;
+    }
+
+    void buf_store_t::clear() SIXTRL_NOEXCEPT
+    {
+        this->m_ptr_cxx_buffer = nullptr;
+        this->m_ptr_c99_buffer = nullptr;
+        this->m_own_buffer.reset( nullptr );
+    }
+
+    void buf_store_t::reset( st_size_t const buffer_capacity,
+        st_flags_t const buffer_flags )
+    {
+        this->m_own_buffer.reset(
+            new buf_store_t::buffer_t( buffer_capacity, buffer_flags ) );
+
+        if( this->m_own_buffer.get() != nullptr )
+        {
+            this->m_ptr_cxx_buffer = this->m_own_buffer.get();
+            this->m_ptr_c99_buffer = this->m_own_buffer->getCApiPtr();
+        }
+        else
+        {
+            this->m_ptr_cxx_buffer = nullptr;
+            this->m_ptr_c99_buffer = nullptr;
+        }
+    }
+
+    void buf_store_t::reset( buf_store_t::buffer_t* SIXTRL_RESTRICT cxx_buffer,
+        bool const take_ownership )
+    {
+        if( ( cxx_buffer != nullptr ) &&
+            ( this->m_ptr_cxx_buffer != cxx_buffer ) )
+        {
+            this->m_ptr_cxx_buffer = cxx_buffer;
+            this->m_ptr_c99_buffer = cxx_buffer->getCApiPtr();
+
+            if( take_ownership )
+            {
+                this->m_own_buffer.reset( cxx_buffer );
+            }
+            else if( this->m_own_buffer.get() != nullptr )
+            {
+                this->m_own_buffer.reset( nullptr );
+            }
+        }
+    }
+
+    void buf_store_t::reset( buf_store_t::c_buffer_t* SIXTRL_RESTRICT c99_buffer,
+        bool const take_ownership, bool const delete_ptr_after_move )
+    {
+        using buffer_t = buf_store_t::buffer_t;
+
+        if( ( c99_buffer != nullptr ) &&
+            ( this->m_ptr_c99_buffer != c99_buffer ) )
+        {
+            if( take_ownership )
+            {
+                this->m_own_buffer =
+                buffer_t::MAKE_FROM_CBUFFER_AND_TAKE_OWNERSHIP(
+                    c99_buffer, delete_ptr_after_move );
+
+                this->m_ptr_cxx_buffer = this->m_own_buffer.get();
+
+                if( this->m_own_buffer.get() != nullptr )
+                {
+                    this->m_ptr_c99_buffer = this->m_own_buffer->getCApiPtr();
+                }
+            }
+            else
+            {
+                this->m_ptr_c99_buffer = c99_buffer;
+                this->m_ptr_cxx_buffer = nullptr;
+                this->m_own_buffer.reset( nullptr );
+            }
+        }
+    }
+
+    void buf_store_t::reset(
+        std::unique_ptr< buf_store_t::buffer_t >&& stored_ptr_buffer )
+    {
+        this->m_own_buffer = std::move( stored_ptr_buffer );
+        this->m_ptr_cxx_buffer = this->m_own_buffer.get();
+
+        this->m_ptr_c99_buffer = ( this->m_own_buffer.get() != nullptr )
+            ? this->m_own_buffer->getCApiPtr() : nullptr;
+    }
+
+    void buf_store_t::reset( buf_store_t::buffer_t&& cxx_buffer )
+    {
+        if( &cxx_buffer != this->m_ptr_cxx_buffer )
+        {
+            this->m_own_buffer.reset(
+                new buf_store_t::buffer_t( std::move( cxx_buffer ) ) );
+
+            this->m_ptr_cxx_buffer = this->m_own_buffer.get();
+            SIXTRL_ASSERT( this->m_own_buffer.get() != nullptr );
+            this->m_ptr_c99_buffer = this->m_own_buffer->getCApiPtr();
+        }
+    }
+}
+
+#endif /* C++ */
diff --git a/sixtracklib/common/track/track_job_buffer_store.h b/sixtracklib/common/track/track_job_buffer_store.h
new file mode 100644
index 00000000..e84fa170
--- /dev/null
+++ b/sixtracklib/common/track/track_job_buffer_store.h
@@ -0,0 +1,145 @@
+#ifndef SIXTRACKLIB_COMMON_TRACK_TRACK_JOB_BUFFER_STORE_H__
+#define SIXTRACKLIB_COMMON_TRACK_TRACK_JOB_BUFFER_STORE_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #if defined( __cplusplus )
+        #include <cstddef>
+        #include <cstdint>
+        #include <cstdlib>
+        #include <memory>
+    #else /* !defined( __cplusplus ) */
+        #include <stdbool.h>
+        #include <stddef.h>
+        #include <stdint.h>
+        #include <stdlib.h>
+    #endif /* !defined( __cplusplus ) */
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/track/definitions.h"
+    #include "sixtracklib/common/buffer.h"
+    #include "sixtracklib/common/buffer/assign_address_item.hpp"
+    #if defined( __cplusplus )
+        #include "sixtracklib/common/buffer.hpp"
+    #endif /* defined( __cplusplus ) */
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+typedef struct NS(TrackJobDestSrcBufferIds)
+{
+    NS(buffer_size_t)   dest_buffer_id;
+    NS(buffer_size_t)   src_buffer_id;
+}
+NS(TrackJobDestSrcBufferIds);
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* C++, Host */
+
+#if defined( __cplusplus )
+namespace SIXTRL_CXX_NAMESPACE
+{
+    struct TrackJobDestSrcBufferIdsLessCmp
+    {
+        bool operator()(
+            ::NS(TrackJobDestSrcBufferIds) const& SIXTRL_RESTRICT_REF lhs,
+            ::NS(TrackJobDestSrcBufferIds) const& SIXTRL_RESTRICT_REF rhs
+        ) const SIXTRL_NOEXCEPT
+        {
+            return ( ( lhs.dest_buffer_id < rhs.dest_buffer_id ) ||
+                     ( ( lhs.dest_buffer_id == rhs.dest_buffer_id ) &&
+                       ( lhs.src_buffer_id < rhs.src_buffer_id ) ) );
+        }
+    };
+
+    /* ********************************************************************* */
+
+    class TrackJobBufferStore
+    {
+        public:
+
+        using buffer_t    = SIXTRL_CXX_NAMESPACE::Buffer;
+        using c_buffer_t  = ::NS(Buffer);
+        using size_type   = buffer_t::size_type;
+        using flags_t     = buffer_t::flags_t;
+
+        static size_type constexpr DEFAULT_BUFFER_CAPACITY =
+            buffer_t::DEFAULT_BUFFER_CAPACITY;
+
+        static flags_t constexpr DEFAULT_DATASTORE_FLAGS =
+            buffer_t::DEFAULT_DATASTORE_FLAGS;
+
+        SIXTRL_HOST_FN explicit TrackJobBufferStore(
+            size_type const buffer_capacity = DEFAULT_BUFFER_CAPACITY,
+            flags_t const buffer_flags = DEFAULT_DATASTORE_FLAGS );
+
+        SIXTRL_HOST_FN explicit TrackJobBufferStore(
+            buffer_t* SIXTRL_RESTRICT cxx_buffer,
+            bool const take_ownership = false );
+
+        SIXTRL_HOST_FN explicit TrackJobBufferStore(
+            c_buffer_t* SIXTRL_RESTRICT c99_buffer,
+            bool const take_ownership = false,
+            bool const delete_ptr_after_move = true );
+
+        SIXTRL_HOST_FN explicit TrackJobBufferStore(
+            std::unique_ptr< buffer_t >&& stored_ptr_buffer );
+
+        SIXTRL_HOST_FN explicit TrackJobBufferStore( buffer_t&& cxx_buffer );
+
+        SIXTRL_HOST_FN TrackJobBufferStore( TrackJobBufferStore const& other );
+        SIXTRL_HOST_FN TrackJobBufferStore(
+            TrackJobBufferStore&& other ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN TrackJobBufferStore& operator=(
+            TrackJobBufferStore const& rhs );
+
+        SIXTRL_HOST_FN TrackJobBufferStore& operator=(
+            TrackJobBufferStore&& other ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN ~TrackJobBufferStore() = default;
+
+        SIXTRL_HOST_FN bool active() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN bool owns_buffer() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN c_buffer_t const* ptr_buffer() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN c_buffer_t* ptr_buffer() SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN buffer_t const* ptr_cxx_buffer() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN buffer_t* ptr_cxx_buffer() SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN void clear() SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN void reset(
+            buffer_t::size_type const buffer_capacity,
+            buffer_t::flags_t const buffer_flags = DEFAULT_DATASTORE_FLAGS );
+
+        SIXTRL_HOST_FN void reset(
+            buffer_t* SIXTRL_RESTRICT cxx_buffer,
+            bool const take_ownership = false );
+
+        SIXTRL_HOST_FN void reset(
+            c_buffer_t* SIXTRL_RESTRICT c99_buffer,
+            bool const take_ownership = false,
+            bool const delete_ptr_after_move = true );
+
+        SIXTRL_HOST_FN void reset(
+            std::unique_ptr< buffer_t >&& stored_ptr_buffer );
+
+        SIXTRL_HOST_FN void reset( buffer_t&& cxx_buffer );
+
+        private:
+
+        buffer_t*   m_ptr_cxx_buffer;
+        c_buffer_t* m_ptr_c99_buffer;
+        std::unique_ptr< buffer_t > m_own_buffer;
+    };
+}
+#endif /* C++ */
+
+#endif /* SIXTRACKLIB_COMMON_TRACK_TRACK_JOB_BUFFER_STORE_H__ */
diff --git a/sixtracklib/common/track/track_job_cpu.cpp b/sixtracklib/common/track/track_job_cpu.cpp
index f17a0311..2398f2b7 100644
--- a/sixtracklib/common/track/track_job_cpu.cpp
+++ b/sixtracklib/common/track/track_job_cpu.cpp
@@ -100,6 +100,15 @@ namespace SIXTRL_CXX_NAMESPACE
         if( ( job.hasOutputBuffer() ) && ( job.hasElemByElemOutput() ) &&
             ( job.hasElemByElemConfig() ) )
         {
+            _this_t::c_buffer_t* elem_by_elem_config_buffer =
+                job.elem_by_elem_config_buffer();
+
+            unsigned char* elem_by_elem_config_buffer_begin =
+                ::NS(Buffer_get_data_begin)( elem_by_elem_config_buffer );
+
+            _this_t::size_type const elem_by_elem_config_index =
+                _this_t::size_type{ 0 };
+
             SIXTRL_ASSERT( job.ptrCParticlesBuffer()    != nullptr );
             SIXTRL_ASSERT( job.ptrCBeamElementsBuffer() != nullptr );
             SIXTRL_ASSERT( job.ptrElemByElemConfig()    != nullptr );
@@ -115,7 +124,8 @@ namespace SIXTRL_CXX_NAMESPACE
                     ::NS(Buffer_get_data_begin)( job.ptrCParticlesBuffer() ),
                     *job.particleSetIndicesBegin(), pindex_t{ 0 }, pindex_t{ 1 },
                     ::NS(Buffer_get_data_begin)( job.ptrCBeamElementsBuffer() ),
-                    job.ptrElemByElemConfig(), _until_turn_num, slot_size );
+                    elem_by_elem_config_buffer_begin,
+                        elem_by_elem_config_index, _until_turn_num, slot_size );
             }
             else if( job.numParticleSets() > size_t{ 1 } )
             {
@@ -137,7 +147,9 @@ namespace SIXTRL_CXX_NAMESPACE
                         *pset_it, pindex_t{ 0 }, pindex_t{ 1 },
                         ::NS(Buffer_get_data_begin)(
                             job.ptrCBeamElementsBuffer() ),
-                        job.ptrElemByElemConfig(), _until_turn_num, slot_size );
+                        elem_by_elem_config_buffer_begin,
+                            elem_by_elem_config_index, _until_turn_num,
+                                slot_size );
                 }
             }
         }
@@ -184,7 +196,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             for( ; pset_it != pset_end ; ++pset_it )
             {
-                status |= status = NS(Track_particles_line_kernel_impl)(
+                status |= NS(Track_particles_line_kernel_impl)(
                 ::NS(Buffer_get_data_begin)( job.ptrCParticlesBuffer() ),
                 *pset_it, pindex_t{ 0 }, pindex_t{ 1 },
                 ::NS(Buffer_get_data_begin)( job.ptrCBeamElementsBuffer() ),
diff --git a/sixtracklib/common/track/track_job_cpu.hpp b/sixtracklib/common/track/track_job_cpu.hpp
index 1998aa32..a173f51b 100644
--- a/sixtracklib/common/track/track_job_cpu.hpp
+++ b/sixtracklib/common/track/track_job_cpu.hpp
@@ -201,7 +201,7 @@ namespace SIXTRL_CXX_NAMESPACE
         CpuTrackJob::size_type const until_turn_elem_by_elem,
         std::string const& config_str ) : SIXTRL_CXX_NAMESPACE::TrackJobBaseNew(
             SIXTRL_CXX_NAMESPACE::ARCHITECTURE_CPU,
-            SIXTRL_ARCHITECTURE_CPU_STR, config_str )
+            SIXTRL_ARCHITECTURE_CPU_STR, config_str.c_str() )
     {
         using _base_track_job_t = SIXTRL_CXX_NAMESPACE::TrackJobBaseNew;
 
diff --git a/sixtracklib/common/track/track_job_ctrl_arg_base.cpp b/sixtracklib/common/track/track_job_ctrl_arg_base.cpp
index e4308075..c8659b65 100644
--- a/sixtracklib/common/track/track_job_ctrl_arg_base.cpp
+++ b/sixtracklib/common/track/track_job_ctrl_arg_base.cpp
@@ -177,6 +177,27 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
+    bool TrackJobCtrlArgBase::has_assign_addresses_kernel() const SIXTRL_NOEXCEPT
+    {
+        return st::TrackJobCtrlArgBase_has_kernel_id(
+            *this, this->assign_addresses_kernel_id() );
+    }
+
+    TrackJobCtrlArgBase::kernel_id_t
+    TrackJobCtrlArgBase::assign_addresses_kernel_id() const SIXTRL_NOEXCEPT
+    {
+        return this->m_assign_addresses_kernel_id;
+    }
+
+    TrackJobCtrlArgBase::status_t
+    TrackJobCtrlArgBase::set_assign_addresses_kernel_id(
+        TrackJobCtrlArgBase::kernel_id_t const kernel_id )
+    {
+        return this->do_set_assign_addresses_kernel_id( kernel_id );
+    }
+
+    /* --------------------------------------------------------------------- */
+
     TrackJobCtrlArgBase::TrackJobCtrlArgBase(
         TrackJobCtrlArgBase::arch_id_t const arch_id,
         char const* SIXTRL_RESTRICT arch_str,
@@ -189,6 +210,7 @@ namespace SIXTRL_CXX_NAMESPACE
         m_stored_elem_by_elem_conf_arg( nullptr ),
         m_stored_particles_addr_arg( nullptr ),
         m_stored_debug_flag_arg( nullptr ),
+        m_stored_assign_addres_items_arg( nullptr ),
         m_assign_output_bemon_kernel_id(
             st::ControllerBase::ILLEGAL_KERNEL_ID ),
         m_assign_output_elem_by_elem_kernel_id(
@@ -198,6 +220,8 @@ namespace SIXTRL_CXX_NAMESPACE
         m_track_elem_by_elem_kernel_id(
             st::ControllerBase::ILLEGAL_KERNEL_ID ),
         m_fetch_particles_addr_kernel_id(
+            st::ControllerBase::ILLEGAL_KERNEL_ID ),
+        m_assign_addresses_kernel_id(
             st::ControllerBase::ILLEGAL_KERNEL_ID )
     {
         this->doSetDefaultPrepareResetClearFlags(
@@ -223,6 +247,7 @@ namespace SIXTRL_CXX_NAMESPACE
         m_stored_elem_by_elem_conf_arg( nullptr ),
         m_stored_particles_addr_arg( nullptr ),
         m_stored_debug_flag_arg( nullptr ),
+        m_stored_assign_addres_items_arg( nullptr ),
         m_assign_output_bemon_kernel_id(
             other.m_assign_output_bemon_kernel_id ),
         m_assign_output_elem_by_elem_kernel_id(
@@ -231,7 +256,8 @@ namespace SIXTRL_CXX_NAMESPACE
         m_track_line_kernel_id( other.m_track_line_kernel_id ),
         m_track_elem_by_elem_kernel_id( other.m_track_elem_by_elem_kernel_id ),
         m_fetch_particles_addr_kernel_id(
-            other.m_fetch_particles_addr_kernel_id )
+            other.m_fetch_particles_addr_kernel_id ),
+        m_assign_addresses_kernel_id( other.m_assign_addresses_kernel_id )
     {
 //         using base_ctrl_t = TrackJobCtrlArgBase::controller_base_t;
 //         using base_arg_t  = TrackJobCtrlArgBase::argument_base_t;
@@ -256,6 +282,8 @@ namespace SIXTRL_CXX_NAMESPACE
             std::move( other.m_stored_particles_addr_arg ) ),
         m_stored_debug_flag_arg(
             std::move( other.m_stored_debug_flag_arg ) ),
+        m_stored_assign_addres_items_arg(
+            std::move( other.m_stored_assign_addres_items_arg ) ),
         m_assign_output_bemon_kernel_id( std::move(
             other.m_assign_output_bemon_kernel_id ) ),
         m_assign_output_elem_by_elem_kernel_id( std::move(
@@ -265,7 +293,9 @@ namespace SIXTRL_CXX_NAMESPACE
         m_track_elem_by_elem_kernel_id( std::move(
             other.m_track_elem_by_elem_kernel_id ) ),
         m_fetch_particles_addr_kernel_id(
-            std::move( other.m_fetch_particles_addr_kernel_id ) )
+            std::move( other.m_fetch_particles_addr_kernel_id ) ),
+        m_assign_addresses_kernel_id(
+            std::move( other.m_assign_addresses_kernel_id ) )
     {
         other.doClearAllCtrlArgBaseImpl();
     }
@@ -283,6 +313,7 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_stored_elem_by_elem_conf_arg.reset( nullptr );
             this->m_stored_particles_addr_arg.reset( nullptr );
             this->m_stored_debug_flag_arg.reset( nullptr );
+            this->m_stored_assign_addres_items_arg.reset( nullptr );
 
             this->m_assign_output_bemon_kernel_id =
                 rhs.m_assign_output_bemon_kernel_id;
@@ -299,6 +330,9 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_fetch_particles_addr_kernel_id =
                 rhs.m_fetch_particles_addr_kernel_id;
 
+            this->m_assign_addresses_kernel_id =
+                rhs.m_assign_addresses_kernel_id;
+
             /* TODO: Implement copying of arguments and controller */
         }
 
@@ -329,6 +363,9 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_stored_debug_flag_arg =
                 std::move( rhs.m_stored_debug_flag_arg );
 
+            this->m_stored_assign_addres_items_arg =
+                std::move( rhs.m_stored_assign_addres_items_arg );
+
             this->m_assign_output_bemon_kernel_id =
                 std::move( rhs.m_assign_output_bemon_kernel_id );
 
@@ -347,6 +384,9 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_fetch_particles_addr_kernel_id =
                 std::move( rhs.m_fetch_particles_addr_kernel_id );
 
+            this->m_assign_addresses_kernel_id =
+                std::move( rhs.m_assign_addresses_kernel_id );
+
             rhs.doClearAllCtrlArgBaseImpl();
         }
 
@@ -800,6 +840,14 @@ namespace SIXTRL_CXX_NAMESPACE
             kernel_id );
     }
 
+    TrackJobCtrlArgBase::status_t
+    TrackJobCtrlArgBase::do_set_assign_addresses_kernel_id(
+        TrackJobCtrlArgBase::kernel_id_t const kernel_id )
+    {
+        return this->do_set_assign_addresses_kernel_id_ctrl_arg_base_impl(
+            kernel_id );
+    }
+
     /* --------------------------------------------------------------------- */
 
     TrackJobCtrlArgBase::status_t TrackJobCtrlArgBase::doPrepareController(
@@ -912,6 +960,20 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_stored_debug_flag_arg.get();
     }
 
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    TrackJobCtrlArgBase::argument_base_t const*
+    TrackJobCtrlArgBase::ptr_address_assign_items_arg_base() const SIXTRL_NOEXCEPT
+    {
+        return this->m_stored_assign_addres_items_arg.get();
+    }
+
+    TrackJobCtrlArgBase::argument_base_t*
+    TrackJobCtrlArgBase::ptr_address_assign_items_arg_base() SIXTRL_NOEXCEPT
+    {
+        return this->m_stored_assign_addres_items_arg.get();
+    }
+
     /* --------------------------------------------------------------------- */
 
     void TrackJobCtrlArgBase::doUpdateStoredController(
@@ -965,6 +1027,14 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_stored_debug_flag_arg = std::move( ptr_debug_flag_arg );
     }
 
+    void TrackJobCtrlArgBase::do_update_stored_address_assign_items_arg(
+        TrackJobCtrlArgBase::stored_arg_base_t&&
+            ptr_address_assign_items_arg ) SIXTRL_NOEXCEPT
+    {
+        this->m_stored_assign_addres_items_arg =
+            std::move( ptr_address_assign_items_arg );
+    }
+
     /* --------------------------------------------------------------------- */
 
     void TrackJobCtrlArgBase::doClearAllCtrlArgBaseImpl() SIXTRL_NOEXCEPT
@@ -975,6 +1045,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->doClearParticlesStructuresCtrlArgBaseImpl();
         this->doClearBeamElementsStructuresCtrlArgBaseImpl();
         this->doClearOutputStructuresCtrlArgBaseImpl();
+
+        this->m_stored_assign_addres_items_arg.reset( nullptr );
     }
 
     void TrackJobCtrlArgBase::doClearParticlesStructuresCtrlArgBaseImpl(
@@ -1011,6 +1083,8 @@ namespace SIXTRL_CXX_NAMESPACE
         this->m_track_elem_by_elem_kernel_id = base_ctrl_t::ILLEGAL_KERNEL_ID;
         this->m_fetch_particles_addr_kernel_id =
             base_ctrl_t::ILLEGAL_KERNEL_ID;
+
+        this->m_assign_addresses_kernel_id = base_ctrl_t::ILLEGAL_KERNEL_ID;
     }
 
     void TrackJobCtrlArgBase::doClearControllerCtrlArgBaseImpl(
@@ -1069,6 +1143,14 @@ namespace SIXTRL_CXX_NAMESPACE
             *this, this->m_fetch_particles_addr_kernel_id, kernel_id );
     }
 
+    TrackJobCtrlArgBase::status_t
+    TrackJobCtrlArgBase::do_set_assign_addresses_kernel_id_ctrl_arg_base_impl(
+        TrackJobCtrlArgBase::kernel_id_t const kernel_id )
+    {
+        return st::TrackJobCtrlArgBase_do_set_kernel_id(
+            *this, this->m_assign_addresses_kernel_id, kernel_id );
+    }
+
     namespace
     {
         SIXTRL_INLINE st::TrackJobCtrlArgBase::status_t
diff --git a/sixtracklib/common/track/track_job_ctrl_arg_base.hpp b/sixtracklib/common/track/track_job_ctrl_arg_base.hpp
index 700bde3e..f55fd024 100644
--- a/sixtracklib/common/track/track_job_ctrl_arg_base.hpp
+++ b/sixtracklib/common/track/track_job_ctrl_arg_base.hpp
@@ -104,6 +104,16 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* ---------------------------------------------------------------- */
 
+        SIXTRL_HOST_FN bool has_assign_addresses_kernel() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN kernel_id_t
+            assign_addresses_kernel_id() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t set_assign_addresses_kernel_id(
+            kernel_id_t const kernel_id );
+
+        /* ---------------------------------------------------------------- */
+
         SIXTRL_HOST_FN controller_base_t const*
         ptrControllerBase() const SIXTRL_NOEXCEPT;
 
@@ -181,6 +191,9 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN virtual status_t
         doSetFetchParticlesAddressesKernelId( kernel_id_t const id );
 
+        SIXTRL_HOST_FN virtual status_t
+        do_set_assign_addresses_kernel_id( kernel_id_t const id );
+
         /* ----------------------------------------------------------------- */
 
         SIXTRL_HOST_FN virtual status_t doPrepareController(
@@ -240,6 +253,14 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN argument_base_t*
         ptrDebugRegisterArgBase() SIXTRL_NOEXCEPT;
 
+        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+        SIXTRL_HOST_FN argument_base_t const*
+        ptr_address_assign_items_arg_base() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN argument_base_t*
+        ptr_address_assign_items_arg_base() SIXTRL_NOEXCEPT;
+
         /* ----------------------------------------------------------------- */
 
         SIXTRL_HOST_FN void doUpdateStoredController(
@@ -265,6 +286,9 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN void doUpdateStoredDebugRegisterArg(
             stored_arg_base_t&& ptr_debug_flag_arg ) SIXTRL_NOEXCEPT;
 
+        SIXTRL_HOST_FN void do_update_stored_address_assign_items_arg(
+            stored_arg_base_t&& ptr_address_assign_items_arg ) SIXTRL_NOEXCEPT;
+
         private:
 
         SIXTRL_HOST_FN void doClearAllCtrlArgBaseImpl() SIXTRL_NOEXCEPT;
@@ -307,6 +331,10 @@ namespace SIXTRL_CXX_NAMESPACE
         doSetFetchParticlesAddressesKernelIdCtrlArgBaseImpl(
             kernel_id_t const id );
 
+        SIXTRL_HOST_FN status_t
+        do_set_assign_addresses_kernel_id_ctrl_arg_base_impl(
+            kernel_id_t const id );
+
         stored_ctrl_base_t      m_stored_controller;
 
         stored_arg_base_t       m_stored_particles_arg;
@@ -315,6 +343,7 @@ namespace SIXTRL_CXX_NAMESPACE
         stored_arg_base_t       m_stored_elem_by_elem_conf_arg;
         stored_arg_base_t       m_stored_particles_addr_arg;
         stored_arg_base_t       m_stored_debug_flag_arg;
+        stored_arg_base_t       m_stored_assign_addres_items_arg;
 
         kernel_id_t             m_assign_output_bemon_kernel_id;
         kernel_id_t             m_assign_output_elem_by_elem_kernel_id;
@@ -322,6 +351,7 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_id_t             m_track_line_kernel_id;
         kernel_id_t             m_track_elem_by_elem_kernel_id;
         kernel_id_t             m_fetch_particles_addr_kernel_id;
+        kernel_id_t             m_assign_addresses_kernel_id;
     };
 }
 
diff --git a/sixtracklib/common/track/track_kernel_impl.h b/sixtracklib/common/track/track_kernel_impl.h
index 4cb263fb..f4b4372d 100644
--- a/sixtracklib/common/track/track_kernel_impl.h
+++ b/sixtracklib/common/track/track_kernel_impl.h
@@ -46,8 +46,8 @@ NS(Track_particles_elem_by_elem_until_turn_kernel_impl)(
     NS(particle_num_elements_t) particle_idx,
     NS(particle_num_elements_t) const particle_idx_stride,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(particle_index_t) const until_turn, NS(buffer_size_t) const slot_size );
 
 SIXTRL_STATIC SIXTRL_FN NS(track_status_t)
@@ -57,8 +57,8 @@ NS(Track_particles_elem_by_elem_until_turn_debug_kernel_impl)(
     NS(particle_num_elements_t) particle_idx,
     NS(particle_num_elements_t) const particle_idx_stride,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(particle_index_t) const until_turn, NS(buffer_size_t) const slot_size,
     SIXTRL_ARGPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags );
 
@@ -255,13 +255,15 @@ NS(Track_particles_elem_by_elem_until_turn_kernel_impl)(
     NS(buffer_size_t) const particle_set_index,
     NS(particle_num_elements_t) pidx, NS(particle_num_elements_t) const stride,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(particle_index_t) const until_turn, NS(buffer_size_t) const slot_size )
 {
     typedef NS(particle_num_elements_t) nelements_t;
     typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* ptr_particles_t;
     typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*  be_iter_t;
+    typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig) const*
+            ptr_elem_by_elem_conf_t;
 
     ptr_particles_t p = NS(Particles_managed_buffer_get_particles)(
         pbuffer, particle_set_index, slot_size );
@@ -274,6 +276,10 @@ NS(Track_particles_elem_by_elem_until_turn_kernel_impl)(
     be_iter_t belem_end = NS(ManagedBuffer_get_const_objects_index_end)(
         belem_buffer, slot_size );
 
+    ptr_elem_by_elem_conf_t elem_by_elem_config =
+    NS(ElemByElemConfig_const_from_managed_buffer)(
+        config_buffer, elem_by_elem_config_index, slot_size );
+
     NS(track_status_t) status = SIXTRL_TRACK_SUCCESS;
 
     SIXTRL_ASSERT( slot_size > ( SIXTRL_UINT64_T )0u );
@@ -305,14 +311,16 @@ NS(Track_particles_elem_by_elem_until_turn_debug_kernel_impl)(
     NS(buffer_size_t) const particle_set_index,
     NS(particle_num_elements_t) pidx, NS(particle_num_elements_t) const stride,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(particle_index_t) const until_turn, NS(buffer_size_t) const slot_size,
     SIXTRL_ARGPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags )
 {
     typedef NS(particle_num_elements_t) nelements_t;
     typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles)* ptr_particles_t;
     typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC  NS(Object) const* be_iter_t;
+    typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig) const*
+            ptr_elem_by_elem_conf_t;
 
     NS(track_status_t)  status = SIXTRL_TRACK_STATUS_GENERAL_FAILURE;
     NS(arch_debugging_t) flags = SIXTRL_ARCH_DEBUGGING_MIN_FLAG;
@@ -332,7 +340,7 @@ NS(Track_particles_elem_by_elem_until_turn_debug_kernel_impl)(
 
     if( ( pbuffer != SIXTRL_NULLPTR ) && ( belem_buffer != SIXTRL_NULLPTR ) &&
         ( slot_size > ( SIXTRL_UINT64_T )0u ) &&
-        ( elem_by_elem_config != SIXTRL_NULLPTR ) &&
+        ( config_buffer != SIXTRL_NULLPTR ) &&
         ( pidx >= ( nelements_t )0u ) && ( stride > ( nelements_t )0u ) )
     {
         ptr_particles_t p = NS(Particles_managed_buffer_get_particles)(
@@ -347,6 +355,10 @@ NS(Track_particles_elem_by_elem_until_turn_debug_kernel_impl)(
         be_iter_t belem_end = NS(ManagedBuffer_get_const_objects_index_end)(
             belem_buffer, slot_size );
 
+        ptr_elem_by_elem_conf_t elem_by_elem_config =
+            NS(ElemByElemConfig_const_from_managed_buffer)(
+                config_buffer, elem_by_elem_config_index, slot_size );
+
         if( ( !NS(ManagedBuffer_needs_remapping)( pbuffer, slot_size ) ) &&
             ( !NS(ManagedBuffer_needs_remapping)( belem_buffer, slot_size ) ) &&
             ( p != SIXTRL_NULLPTR ) && ( belem_begin != SIXTRL_NULLPTR ) &&
@@ -391,8 +403,8 @@ NS(Track_particles_elem_by_elem_until_turn_debug_kernel_impl)(
         if( pidx < ( nelements_t )0u )       flags |= PARTICLE_IDX_ILLEGAL_FLAG;
         if( stride <= ( nelements_t )0u )    flags |= PARTICLE_IDX_ILLEGAL_FLAG;
 
-        if( elem_by_elem_config == SIXTRL_NULLPTR )
-                flags |= ELEM_BY_ELEM_CONFIG_ILLEGAL_FLAG;
+        if( config_buffer == SIXTRL_NULLPTR )
+            flags |= ELEM_BY_ELEM_CONFIG_ILLEGAL_FLAG;
     }
 
     if( status != SIXTRL_TRACK_SUCCESS )
diff --git a/sixtracklib/common/track/track_kernel_opt_impl.h b/sixtracklib/common/track/track_kernel_opt_impl.h
index f24aeb0f..c972ad0c 100644
--- a/sixtracklib/common/track/track_kernel_opt_impl.h
+++ b/sixtracklib/common/track/track_kernel_opt_impl.h
@@ -46,8 +46,8 @@ NS(Track_particles_elem_by_elem_until_turn_opt_kernel_impl)(
     NS(particle_num_elements_t) particle_idx,
     NS(particle_num_elements_t) const particle_idx_stride,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(particle_index_t) const until_turn, NS(buffer_size_t) const slot_size );
 
 SIXTRL_STATIC SIXTRL_FN NS(track_status_t)
@@ -57,8 +57,8 @@ NS(Track_particles_elem_by_elem_until_turn_debug_opt_kernel_impl)(
     NS(particle_num_elements_t) particle_idx,
     NS(particle_num_elements_t) const particle_idx_stride,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(particle_index_t) const until_turn, NS(buffer_size_t) const slot_size,
     SIXTRL_ARGPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags );
 
@@ -326,8 +326,8 @@ NS(Track_particles_elem_by_elem_until_turn_opt_kernel_impl)(
     NS(buffer_size_t) const particle_set_index,
     NS(particle_num_elements_t) pidx, NS(particle_num_elements_t) const stride,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(particle_index_t) const until_turn, NS(buffer_size_t) const slot_size )
 {
     typedef NS(particle_num_elements_t) nelements_t;
@@ -336,6 +336,8 @@ NS(Track_particles_elem_by_elem_until_turn_opt_kernel_impl)(
     typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*  be_iter_t;
     typedef NS(particle_real_t) real_t;
     typedef NS(particle_index_t) index_t;
+    typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig) const*
+            ptr_elem_by_elem_config_t;
 
     SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles) particles;
 
@@ -371,6 +373,10 @@ NS(Track_particles_elem_by_elem_until_turn_opt_kernel_impl)(
     be_iter_t belem_end = NS(ManagedBuffer_get_const_objects_index_end)(
         belem_buffer, slot_size );
 
+    ptr_elem_by_elem_config_t elem_by_elem_config =
+        NS(ElemByElemConfig_const_from_managed_buffer)(
+            config_buffer, elem_by_elem_config_index, slot_size );
+
     NS(track_status_t) status = SIXTRL_TRACK_SUCCESS;
 
     NS(Particles_init_from_flat_arrays)(
@@ -413,8 +419,8 @@ NS(Track_particles_elem_by_elem_until_turn_debug_opt_kernel_impl)(
     NS(buffer_size_t) const particle_set_index,
     NS(particle_num_elements_t) pidx, NS(particle_num_elements_t) const stride,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(particle_index_t) const until_turn, NS(buffer_size_t) const slot_size,
     SIXTRL_ARGPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags )
 {
@@ -424,6 +430,8 @@ NS(Track_particles_elem_by_elem_until_turn_debug_opt_kernel_impl)(
     typedef SIXTRL_BUFFER_OBJ_ARGPTR_DEC  NS(Object) const* be_iter_t;
     typedef NS(particle_real_t) real_t;
     typedef NS(particle_index_t) index_t;
+    typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig) const*
+            ptr_elem_by_elem_config_t;
 
     NS(track_status_t)  status = SIXTRL_TRACK_STATUS_GENERAL_FAILURE;
     NS(arch_debugging_t) flags = SIXTRL_ARCH_DEBUGGING_MIN_FLAG;
@@ -443,7 +451,7 @@ NS(Track_particles_elem_by_elem_until_turn_debug_opt_kernel_impl)(
 
     if( ( pbuffer != SIXTRL_NULLPTR ) && ( belem_buffer != SIXTRL_NULLPTR ) &&
         ( slot_size > ( SIXTRL_UINT64_T )0u ) &&
-        ( elem_by_elem_config != SIXTRL_NULLPTR ) &&
+        ( config_buffer != SIXTRL_NULLPTR ) &&
         ( pidx >= ( nelements_t )0u ) && ( stride > ( nelements_t )0u ) )
     {
         pset_iter_t pset_it = NS(ManagedBuffer_get_object)(
@@ -463,6 +471,10 @@ NS(Track_particles_elem_by_elem_until_turn_debug_opt_kernel_impl)(
         be_iter_t belem_end = NS(ManagedBuffer_get_const_objects_index_end)(
             belem_buffer, slot_size );
 
+        ptr_elem_by_elem_config_t elem_by_elem_config =
+            NS(ElemByElemConfig_const_from_managed_buffer)(
+                config_buffer, elem_by_elem_config_index, slot_size );
+
         if( ( !NS(ManagedBuffer_needs_remapping)( pbuffer, slot_size ) ) &&
             ( !NS(ManagedBuffer_needs_remapping)( belem_buffer, slot_size ) ) &&
             ( in_particles != SIXTRL_NULLPTR ) && ( belem_begin != SIXTRL_NULLPTR ) &&
@@ -533,7 +545,7 @@ NS(Track_particles_elem_by_elem_until_turn_debug_opt_kernel_impl)(
         if( pidx < ( nelements_t )0u )       flags |= PARTICLE_IDX_ILLEGAL_FLAG;
         if( stride <= ( nelements_t )0u )    flags |= PARTICLE_IDX_ILLEGAL_FLAG;
 
-        if( elem_by_elem_config == SIXTRL_NULLPTR )
+        if( config_buffer == SIXTRL_NULLPTR )
                 flags |= ELEM_BY_ELEM_CONFIG_ILLEGAL_FLAG;
     }
 
diff --git a/sixtracklib/common/track_job.h b/sixtracklib/common/track_job.h
index 90da7422..7fb8d7c9 100644
--- a/sixtracklib/common/track_job.h
+++ b/sixtracklib/common/track_job.h
@@ -201,6 +201,11 @@ SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TrackJob_collect_beam_elements)(
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TrackJob_collect_output)(
     NS(TrackJobBase)* SIXTRL_RESTRICT job );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TrackJob_collect_particles_addresses)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job );
+
+/* ------------------------------------------------------------------------- */
+
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TrackJob_enable_collect_particles)(
     NS(TrackJobBase)* SIXTRL_RESTRICT job );
 
@@ -253,13 +258,43 @@ SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TrackJob_push_beam_elements)(
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TrackJob_push_output)(
     NS(TrackJobBase)* SIXTRL_RESTRICT track_job );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TrackJob_push_particles_addresses)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_can_fetch_particle_addresses)(
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_can_fetch_particles_addr)(
     const NS(TrackJobBase) *const SIXTRL_RESTRICT track_job );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_particle_addresses)(
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_particles_addr)(
     const NS(TrackJobBase) *const SIXTRL_RESTRICT track_job );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_fetch_particle_addresses)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT track_job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_clear_particle_addresses)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT track_job,
+    NS(arch_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_clear_all_particle_addresses)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT track_job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ParticlesAddr) const*
+NS(TrackJob_particle_addresses)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const index ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer)*
+NS(TrackJob_get_particles_addr_buffer)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer) const*
+NS(TrackJob_get_const_particles_addr_buffer)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job ) SIXTRL_NOEXCEPT;
+
 /* ------------------------------------------------------------------------- */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TrackJob_clear)(
@@ -435,6 +470,307 @@ NS(TrackJob_get_const_output_buffer)(
 
 /* ------------------------------------------------------------------------- */
 
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_can_fetch_particles_addr)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_particles_addr)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_fetch_particles_addr)( NS(TrackJobBase)* SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_clear_particles_addr)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const particle_set_index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_clear_all_particles_addr)( NS(TrackJobBase)* SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN struct NS(ParticlesAddr) const*
+NS(TrackJob_particles_addr)( const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const particle_set_index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer) const*
+NS(TrackJob_particles_addr_buffer)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem)*
+NS(TrackJob_add_assign_address_item)( NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT assign_item_to_add );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem)*
+NS(TrackJob_add_assign_address_item_detailed)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_remove_assign_address_item)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(AssignAddressItem)* SIXTRL_RESTRICT item_to_remove );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_remove_assign_address_item_by_key_and_index)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    const NS(TrackJobDestSrcBufferIds) *const SIXTRL_RESTRICT key,
+    NS(buffer_size_t) const index_of_item_to_remove );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_assign_address_item)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_assign_item_by_index)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const assign_item_index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_assign_address_item_detailed)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJob_index_of_assign_address_item_detailed)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJob_index_of_assign_address_item)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const  SIXTRL_RESTRICT assign_item_to_add );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_assign_items)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t) NS(TrackJob_num_assign_items)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJob_total_num_assign_items)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem) const*
+NS(TrackJob_ptr_assign_address_item)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT assign_address_item );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem) const*
+NS(TrackJob_ptr_assign_address_item_detailed)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const dest_elem_index,
+    NS(buffer_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const src_elem_index,
+    NS(buffer_size_t) const src_pointer_offset );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem) const*
+NS(TrackJob_ptr_assign_address_item_by_index)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id,
+    NS(buffer_size_t) const assign_address_item_index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJob_num_distinct_available_assign_address_items_dest_src_pairs)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
+NS(TrackJob_available_assign_address_items_dest_src_pairs)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const max_num_pairs,
+    NS(TrackJobDestSrcBufferIds)* pairs_begin );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer)* NS(TrackJob_buffer_by_buffer_id)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job, NS(buffer_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer) const*
+NS(TrackJob_const_buffer_by_buffer_id)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_is_buffer_by_buffer_id)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_is_raw_memory_by_buffer_id)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*
+NS(TrackJob_assign_items_begin)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN SIXTRL_BUFFER_OBJ_ARGPTR_DEC NS(Object) const*
+NS(TrackJob_assign_items_end)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(TrackJobDestSrcBufferIds) const*
+NS(TrackJob_assign_item_dest_src_begin)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(TrackJobDestSrcBufferIds) const*
+NS(TrackJob_assign_item_dest_src_end)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_commit_address_assignments)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_assign_all_addresses)( NS(TrackJobBase)* SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_assign_addresses)( NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(buffer_size_t) const src_buffer_id );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem)*
+NS(TrackJob_add_assign_address_item)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    const NS(AssignAddressItem) *const SIXTRL_RESTRICT assign_item_to_add );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem)*
+NS(TrackJob_add_assign_address_item_detail)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(object_type_id_t) const dest_type_id,
+    NS(arch_size_t) const dest_buffer_id, NS(arch_size_t) const dest_elem_index,
+    NS(arch_size_t) const dest_pointer_offset,
+    NS(object_type_id_t) const src_type_id,
+    NS(arch_size_t) const src_buffer_id, NS(arch_size_t) const src_elem_index,
+    NS(arch_size_t) const src_pointer_offset );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_assign_items)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const dest_buffer_id, NS(arch_size_t) const src_buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t) NS(TrackJob_num_assign_items)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const dest_buffer_id, NS(arch_size_t) const src_buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer)* NS(TrackJob_buffer_by_buffer_id)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job, NS(arch_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer) const*
+NS(TrackJob_const_buffer_by_buffer_id)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJob_num_distinct_assign_items_dest_src_pairs)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN
+NS(arch_size_t) NS(TrackJob_assign_items_dest_src_pairs)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const max_num_pairs,
+    NS(AssignAddressItemDestSrcPair)* pairs_begin );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem) const*
+NS(TrackJob_assign_items_dest_src_begin)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const dest_buffer_id, NS(arch_size_t) const src_buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(AssignAddressItem) const*
+NS(TrackJob_assign_items_dest_src_end)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const dest_buffer_id, NS(arch_size_t) const src_buffer_id );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJob_stored_buffers_capacity)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_reserve_stored_buffers_capacity)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job, NS(arch_size_t) const capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_stored_buffers)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJob_num_stored_buffers)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJob_min_stored_buffer_id)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJob_max_stored_buffer_id)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJob_create_stored_buffer)( NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(TrackJob_add_stored_buffer)( NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(Buffer)* SIXTRL_RESTRICT buffer, bool const take_ownership,
+    bool const delete_ptr_after_move );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_owns_stored_buffer)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_remove_stored_buffer)( NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_index );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer)* NS(TrackJob_stored_buffer)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(Buffer) const*
+NS(TrackJob_const_stored_buffer)(
+    const NS(TrackJobBase) *const SIXTRL_RESTRICT job,
+    NS(arch_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(TrackJob_push_stored_buffer)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job, NS(arch_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(TrackJob_collect_stored_buffer)(
+    NS(TrackJobBase)* SIXTRL_RESTRICT job, NS(arch_size_t) const buffer_id );
+
+/* ------------------------------------------------------------------------- */
+
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJob_has_beam_monitors)(
     const NS(TrackJobBase) *const SIXTRL_RESTRICT job );
 
@@ -489,7 +825,6 @@ NS(TrackJob_set_default_elem_by_elem_config_order)(
     NS(TrackJobBase)* SIXTRL_RESTRICT job,
     NS(elem_by_elem_order_t) const order );
 
-
 #if defined( __cplusplus )
 } /* extern "C" { */
 #endif /* defined( __cplusplus ) */
diff --git a/sixtracklib/common/track_job_cpu.h b/sixtracklib/common/track_job_cpu.h
index 3884989b..acd8d600 100644
--- a/sixtracklib/common/track_job_cpu.h
+++ b/sixtracklib/common/track_job_cpu.h
@@ -137,18 +137,20 @@ namespace SIXTRL_CXX_NAMESPACE
 
         protected:
 
-        virtual track_status_t doTrackUntilTurn(
+        SIXTRL_HOST_FN status_t doFetchParticleAddresses() override;
+
+        SIXTRL_HOST_FN track_status_t doTrackUntilTurn(
             size_type const until_turn ) override;
 
-        virtual track_status_t doTrackElemByElem(
+        SIXTRL_HOST_FN track_status_t doTrackElemByElem(
             size_type const until_turn_elem_by_elem ) override;
 
-        virtual track_status_t doTrackLine(
+        SIXTRL_HOST_FN track_status_t doTrackLine(
             size_type const beam_elements_begin_index,
             size_type const beam_elements_end_index,
             bool const finish_turn ) override;
 
-        virtual void doCollect( collect_flag_t const flags ) override;
+        SIXTRL_HOST_FN void doCollect( collect_flag_t const flags ) override;
     };
 
     SIXTRL_HOST_FN void collect( TrackJobCpu& job ) SIXTRL_NOEXCEPT;
diff --git a/sixtracklib/cuda/CMakeLists.txt b/sixtracklib/cuda/CMakeLists.txt
index 46cc1c6e..0b0c6985 100644
--- a/sixtracklib/cuda/CMakeLists.txt
+++ b/sixtracklib/cuda/CMakeLists.txt
@@ -67,16 +67,17 @@ target_include_directories( sixtrack_cuda_host
     PRIVATE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
     PUBLIC  $<BUILD_INTERFACE:${SIXTRACKL_CUDA_INCLUDE_DIRS}> )
 
-set_target_properties( sixtrack_cuda_host PROPERTIES POSITION_INDEPENDENT_CODE ON )
-set_target_properties( sixtrack_cuda_host PROPERTIES LINKER_LANGUAGE C )
-set_target_properties( sixtrack_cuda_host PROPERTIES CXX_STANDARD 11 )
-set_target_properties( sixtrack_cuda_host PROPERTIES CXX_STANDARD_REQUIRED ON )
+set_target_properties( sixtrack_cuda_host PROPERTIES
+    POSITION_INDEPENDENT_CODE ON LINKER_LANGUAGE C CXX_STANDARD 11
+    CXX_STANDARD_REQUIRED ON )
+
+# target_compile_options( sixtrack_cuda_host BEFORE PUBLIC
+#         ${SIXTRACKLIB_CXX_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_cuda_host as a module for sixtracklib:
 
-set(  SIXTRACKL_LIBRARY_MODULES
-    ${SIXTRACKL_LIBRARY_MODULES}
+set(  SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
     $<TARGET_OBJECTS:sixtrack_cuda_host> CACHE INTERNAL "" FORCE )
 
 find_library( CUDA_LIBRARY cuda ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES} )
@@ -88,25 +89,15 @@ else()
     set( CUDA_NVRTC_LIBRARY )
 endif()
 
-set(   SIXTRACKL_LINK_LIBRARIES
-     ${SIXTRACKL_LINK_LIBRARIES}
-     ${CUDA_NVRTC_LIBRARY} ${CUDA_LIBRARY} ${CUDART_LIBRARY}
-     CACHE INTERNAL "" FORCE )
+set( SIXTRACKL_LINK_LIBRARIES ${SIXTRACKL_LINK_LIBRARIES} ${CUDA_NVRTC_LIBRARY}
+    ${CUDA_LIBRARY} ${CUDART_LIBRARY} CACHE INTERNAL "" FORCE )
 
 # ------------------------------------------------------------------------------
 # --- CUDA Host C++ object library
 
-set( SIXTRACKL_CUDA_C99_HEADERS
-     definitions.h
-     control/argument_base.h
-     argument.h
-     controller.h
-)
-
-set( SIXTRACKL_CUDA_CXX_HEADERS
-     argument.hpp
-     controller.hpp
-)
+set( SIXTRACKL_CUDA_CXX_HEADERS argument.hpp controller.hpp )
+set( SIXTRACKL_CUDA_C99_HEADERS definitions.h control/argument_base.h
+     argument.h controller.h )
 
 # ------------------------------------------------------------------------------
 # --- CUDA Kernel object library:
@@ -122,6 +113,7 @@ set( SIXTRACKLIB_CUDA_PART_DEVICE_HEADERS
      kernels/extract_particles_addr.cuh
      kernels/managed_buffer_remap.cuh
      kernels/track_particles.cuh
+     kernels/assign_address_item.cuh
 )
 
 set( SIXTRACKLIB_CUDA_PART_DEVICE_SOURCES
@@ -130,32 +122,27 @@ set( SIXTRACKLIB_CUDA_PART_DEVICE_SOURCES
      kernels/extract_particles_addr.cu
      kernels/managed_buffer_remap.cu
      kernels/track_particles.cu
+     kernels/assign_address_item.cu
 )
 
 add_library( sixtrack_cuda_device OBJECT
-             ${SIXTRACKLIB_CUDA_PART_DEVICE_HEADERS}
-             ${SIXTRACKLIB_CUDA_PART_DEVICE_SOURCES}
-)
+    ${SIXTRACKLIB_CUDA_PART_DEVICE_HEADERS}
+    ${SIXTRACKLIB_CUDA_PART_DEVICE_SOURCES} )
 
 target_compile_definitions( sixtrack_cuda_device
     PUBLIC ${SIXTRACKL_CUDA_DEVICE_DEFINITIONS} )
 
-set_target_properties( sixtrack_cuda_device PROPERTIES POSITION_INDEPENDENT_CODE ON )
-set_target_properties( sixtrack_cuda_device PROPERTIES LINKER_LANGUAGE C )
-set_target_properties( sixtrack_cuda_device PROPERTIES CXX_STANDARD 11 )
-set_target_properties( sixtrack_cuda_device PROPERTIES CXX_STANDARD_REQUIRED ON )
-set_target_properties( sixtrack_cuda_device PROPERTIES CUDA_SEPARABLE_COMPILATION  ON  )
-set_target_properties( sixtrack_cuda_device PROPERTIES CUDA_RESOLVE_DEVICE_SYMBOLS OFF )
-set_target_properties( sixtrack_cuda_device PROPERTIES CUDA_STANDARD 11 )
-set_target_properties( sixtrack_cuda_device PROPERTIES CUDA_STANDARD_REQUIRED 11 )
+set_target_properties( sixtrack_cuda_device PROPERTIES
+    POSITION_INDEPENDENT_CODE ON LINKER_LANGUAGE C CXX_STANDARD 11
+    CXX_STANDARD_REQUIRED ON CUDA_SEPARABLE_COMPILATION  ON
+    CUDA_RESOLVE_DEVICE_SYMBOLS ON CUDA_STANDARD 11 CUDA_STANDARD_REQUIRED 11 )
 
 target_include_directories( sixtrack_cuda_device PRIVATE ${CMAKE_SOURCE_DIR} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_cuda_device as a module for sixtracklib:
 
-set(  SIXTRACKL_LIBRARY_MODULES
-    ${SIXTRACKL_LIBRARY_MODULES}
+set( SIXTRACKL_LIBRARY_MODULES ${SIXTRACKL_LIBRARY_MODULES}
     $<TARGET_OBJECTS:sixtrack_cuda_device> CACHE INTERNAL "" FORCE )
 
 # ------------------------------------------------------------------------------
@@ -191,5 +178,3 @@ if( SIXTRACKL_ENABLE_CXX )
                  DESTINATION ${SIXTRACKLIB_CUDA_INSTALL_PATH} )
     endif()
 endif()
-
-# end: sixtracklib/cuda/CMakeLists.txt
diff --git a/sixtracklib/cuda/control/controller.cpp b/sixtracklib/cuda/control/controller.cpp
index 29dbf245..eeadb80b 100644
--- a/sixtracklib/cuda/control/controller.cpp
+++ b/sixtracklib/cuda/control/controller.cpp
@@ -19,6 +19,227 @@ namespace st = SIXTRL_CXX_NAMESPACE;
 
 namespace SIXTRL_CXX_NAMESPACE
 {
+    using _this_t = st::CudaController;
+
+    CudaController::size_type CudaController::NUM_ALL_NODES()
+    {
+        using _size_t = _this_t::size_type;
+        int num_count = int{ 0 };
+        ::cudaError_t err = ::cudaGetDeviceCount( &num_count );
+
+        return ( err == ::cudaSuccess )
+            ? static_cast< _size_t >( num_count ) : _size_t{ 0 };
+    }
+
+    CudaController::size_type CudaController::GET_ALL_NODES(
+        CudaController::node_id_t* SIXTRL_RESTRICT out_node_ids_begin,
+        CudaController::size_type const max_num_node_ids )
+    {
+        using _size_t = _this_t::size_type;
+        _size_t num_nodes_added = _size_t{ 0 };
+
+        if( ( out_node_ids_begin != nullptr ) &&
+            ( max_num_node_ids > _size_t{ 0 } ) )
+        {
+            _size_t num_avail_nodes = _this_t::NUM_ALL_NODES();
+
+            if( num_avail_nodes > max_num_node_ids )
+            {
+                num_avail_nodes = max_num_node_ids;
+            }
+
+            _this_t::node_id_t* it = out_node_ids_begin;
+            _this_t::node_id_t* end = it;
+            std::advance( end, num_avail_nodes );
+
+            for( _size_t ii = _size_t{ 0 } ; it != end ; ++ii, ++it )
+            {
+                it->setPlatformId( ii );
+                it->setDeviceId( 0 );
+                it->setIndex( ii );
+
+                ++num_nodes_added;
+            }
+
+            end = out_node_ids_begin;
+            std::advance( end, max_num_node_ids );
+
+            for( ; it != end ; ++it )
+            {
+                it->clear();
+            }
+        }
+
+        return num_nodes_added;
+    }
+
+    void CudaController::PRINT_ALL_NODES()
+    {
+        using _size_t = _this_t::size_type;
+        _size_t const num_avail_nodes = _this_t::NUM_ALL_NODES();
+
+        if( num_avail_nodes > _size_t{ 0 } )
+        {
+            ::cudaError_t err = ::cudaSuccess;
+
+            for( _size_t ii = _size_t{ 0 } ; ii < num_avail_nodes ; ++ii )
+            {
+                ::cudaDeviceProp cu_properties;
+                err = ::cudaGetDeviceProperties( &cu_properties, ii );
+
+                if( err != ::cudaSuccess ) continue;
+
+                std::unique_ptr< _this_t::node_info_t > ptr_node_info(
+                    new _this_t::node_info_t( ii, cu_properties ) );
+
+                if( ptr_node_info.get() == nullptr ) continue;
+
+                ptr_node_info->setNodeIndex( ii );
+                ptr_node_info->setPlatformId( ii );
+                ptr_node_info->setDeviceId( 0 );
+
+                std::cout << *ptr_node_info << "\r\n";
+            }
+        }
+        else
+        {
+            std::cout << "No CUDA nodes available for printing\r\n";
+        }
+
+
+        std::cout << std::endl;
+    }
+
+    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    CudaController::size_type CudaController::NUM_AVAILABLE_NODES(
+        char const* SIXTRL_RESTRICT filter_str,
+        char const* SIXTRL_RESTRICT env_variable_name )
+    {
+        ( void )filter_str;
+        ( void )env_variable_name;
+
+        return st::CudaController::NUM_ALL_NODES();
+    }
+
+    CudaController::size_type CudaController::GET_AVAILABLE_NODES(
+        CudaController::node_id_t* SIXTRL_RESTRICT out_node_ids_begin,
+        CudaController::size_type const max_num_node_ids,
+        CudaController::size_type const skip_first_num_nodes,
+        char const* SIXTRL_RESTRICT filter_str,
+        char const* SIXTRL_RESTRICT env_variable_name )
+    {
+        using _this_t = st::CudaController;
+        using _size_t = _this_t::size_type;
+
+        _size_t num_nodes_added = _size_t{ 0 };
+
+        ( void )filter_str;
+        ( void )env_variable_name;
+
+        if( ( out_node_ids_begin != nullptr ) &&
+            ( max_num_node_ids > _size_t{ 0 } ) )
+        {
+            _size_t num_avail_nodes = _this_t::NUM_ALL_NODES();
+
+            if( num_avail_nodes >= skip_first_num_nodes )
+            {
+                num_avail_nodes -= skip_first_num_nodes;
+            }
+            else
+            {
+                num_avail_nodes = _size_t{ 0 };
+            }
+
+            if( num_avail_nodes > max_num_node_ids )
+            {
+                num_avail_nodes = max_num_node_ids;
+            }
+
+            _this_t::node_id_t* it = out_node_ids_begin;
+            _this_t::node_id_t* end = it;
+            std::advance( end, num_avail_nodes );
+
+            for( _size_t ii = _size_t{ 0 } ; it != end ; ++ii, ++it )
+            {
+                it->setPlatformId( ii );
+                it->setDeviceId( 0 );
+                it->setIndex( ii );
+
+                ++num_nodes_added;
+            }
+
+            end = out_node_ids_begin;
+            std::advance( end, max_num_node_ids );
+
+            for( ; it != end ; ++it )
+            {
+                it->clear();
+            }
+        }
+
+        return num_nodes_added;
+    }
+
+    void CudaController::PRINT_AVAILABLE_NODES(
+        char const* SIXTRL_RESTRICT filter_str,
+        char const* SIXTRL_RESTRICT env_variable_name )
+    {
+        ( void )filter_str;
+        ( void )env_variable_name;
+
+        st::CudaController::PRINT_ALL_NODES();
+    }
+
+    CudaController::size_type CudaController::GET_AVAILABLE_NODE_ID_STR(
+        char** SIXTRL_RESTRICT out_node_id_strs,
+        CudaController::size_type const max_num_node_ids,
+        CudaController::size_type const node_id_str_capacity,
+        ::NS(node_id_str_fmt_t) const node_id_str_format,
+        CudaController::size_type const skip_first_num_nodes,
+        char const* SIXTRL_RESTRICT filter_str,
+        char const* SIXTRL_RESTRICT env_variable_name )
+    {
+        using _this_t = st::CudaController;
+        using _size_t = _this_t::size_type;
+
+        _size_t num_nodes_added = _size_t{ 0 };
+
+        if( ( out_node_id_strs != nullptr ) &&
+            ( max_num_node_ids > size_t{ 0 } ) &&
+            ( node_id_str_capacity > _size_t{ 0 } ) )
+        {
+            std::vector< _this_t::node_id_t > temp_node_ids( max_num_node_ids );
+
+            _size_t num_nodes_available = _this_t::GET_AVAILABLE_NODES(
+                temp_node_ids.data(), max_num_node_ids, skip_first_num_nodes,
+                    filter_str, env_variable_name );
+
+            if( num_nodes_available > 0 )
+            {
+                auto it = temp_node_ids.begin();
+                auto end = it;
+                std::advance( it, num_nodes_available );
+
+                for( _size_t ii = _size_t{ 0 } ; it != end ; ++it, ++ii )
+                {
+                    if( out_node_id_strs[ ii ] == nullptr ) continue;
+
+                    if( st::ARCH_STATUS_SUCCESS == it->to_string(
+                            &out_node_id_strs[ ii ][ 0 ], node_id_str_capacity,
+                                st::ARCHITECTURE_CUDA, node_id_str_format ) )
+                    {
+                        ++num_nodes_added;
+                    }
+                }
+            }
+        }
+
+        return num_nodes_added;
+    }
+
+    /* --------------------------------------------------------------------- */
+
     CudaController::CudaController( char const* config_str ) :
         st::NodeControllerBase( st::ARCHITECTURE_CUDA,
             SIXTRL_ARCHITECTURE_CUDA_STR, config_str ),
diff --git a/sixtracklib/cuda/control/controller_c99.cpp b/sixtracklib/cuda/control/controller_c99.cpp
index d525413d..043bbc71 100644
--- a/sixtracklib/cuda/control/controller_c99.cpp
+++ b/sixtracklib/cuda/control/controller_c99.cpp
@@ -12,6 +12,106 @@
 
 namespace st = SIXTRL_CXX_NAMESPACE;
 
+/* ------------------------------------------------------------------------- */
+
+::NS(arch_size_t) NS(Cuda_get_num_all_nodes)( void )
+{
+    return st::CudaController::NUM_ALL_NODES();
+}
+
+::NS(arch_size_t) NS(Cuda_get_all_nodes)(
+    ::NS(NodeId)* SIXTRL_RESTRICT out_node_ids_begin,
+    ::NS(arch_size_t) const max_num_node_ids )
+{
+    return st::CudaController::GET_ALL_NODES(
+        out_node_ids_begin, max_num_node_ids );
+}
+
+void NS(Cuda_print_all_nodes)( void )
+{
+    return st::CudaController::PRINT_ALL_NODES();
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+::NS(arch_size_t) NS(Cuda_num_available_nodes)(
+    char const* SIXTRL_RESTRICT env_variable_name )
+{
+    return st::CudaController::NUM_AVAILABLE_NODES(
+        nullptr, env_variable_name );
+}
+
+::NS(arch_size_t) NS(Cuda_num_available_nodes_detailed)(
+    char const* SIXTRL_RESTRICT filter_str,
+    char const* SIXTRL_RESTRICT env_variable_name )
+{
+    return st::CudaController::NUM_AVAILABLE_NODES(
+        filter_str, env_variable_name );
+}
+
+::NS(arch_size_t) NS(Cuda_get_available_nodes)(
+    ::NS(NodeId)* SIXTRL_RESTRICT out_node_ids_begin,
+    ::NS(arch_size_t) const max_num_node_ids )
+{
+    return st::CudaController::GET_AVAILABLE_NODES(
+        out_node_ids_begin, max_num_node_ids );
+}
+
+::NS(arch_size_t) NS(Cuda_get_available_nodes_detailed)(
+    ::NS(NodeId)* SIXTRL_RESTRICT out_node_ids_begin,
+    ::NS(arch_size_t) const max_num_node_ids,
+    ::NS(arch_size_t) const skip_first_num_nodes,
+    char const* SIXTRL_RESTRICT filter_str,
+    char const* SIXTRL_RESTRICT env_variable_name )
+{
+    return st::CudaController::GET_AVAILABLE_NODES(
+        out_node_ids_begin, max_num_node_ids, skip_first_num_nodes,
+            filter_str, env_variable_name );
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+void NS(Cuda_print_available_nodes)( void )
+{
+    return st::CudaController::PRINT_AVAILABLE_NODES( nullptr, nullptr );
+}
+
+void NS(Cuda_print_available_nodes_detailed)(
+    char const* SIXTRL_RESTRICT filter_str,
+    char const* SIXTRL_RESTRICT env_variable_name )
+{
+    return st::CudaController::PRINT_AVAILABLE_NODES(
+        filter_str, env_variable_name );
+}
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+::NS(arch_size_t) NS(Cuda_get_available_node_id_strs)(
+    char** SIXTRL_RESTRICT out_node_id_strs,
+    ::NS(arch_size_t) const max_num_node_ids,
+    ::NS(arch_size_t) const node_id_str_capacity )
+{
+    return st::CudaController::GET_AVAILABLE_NODE_ID_STR(
+        out_node_id_strs, max_num_node_ids, node_id_str_capacity );
+}
+
+::NS(arch_size_t) NS(Cuda_get_available_node_id_strs_detailed)(
+    char** SIXTRL_RESTRICT out_node_id_strs,
+    ::NS(arch_size_t) const max_num_node_ids,
+    ::NS(arch_size_t) const node_id_str_capacity,
+    ::NS(node_id_str_fmt_t) const node_id_str_format,
+    ::NS(arch_size_t) const skip_first_num_nodes,
+    char const* SIXTRL_RESTRICT filter_str,
+    char const* SIXTRL_RESTRICT env_variable_name )
+{
+    return st::CudaController::GET_AVAILABLE_NODE_ID_STR(
+        out_node_id_strs, max_num_node_ids, node_id_str_capacity,
+            node_id_str_format, skip_first_num_nodes, filter_str,
+                env_variable_name );
+}
+
+/* ------------------------------------------------------------------------- */
+
 ::NS(CudaController)* NS(CudaController_create)( void )
 {
     return new st::CudaController( "" );
diff --git a/sixtracklib/cuda/control/default_kernel_config.c b/sixtracklib/cuda/control/default_kernel_config.c
index 39c7ce3e..cfd3a815 100644
--- a/sixtracklib/cuda/control/default_kernel_config.c
+++ b/sixtracklib/cuda/control/default_kernel_config.c
@@ -15,35 +15,39 @@ SIXTRL_STATIC SIXTRL_HOST_FN NS(arch_status_t)
 NS(CudaKernelConfig_configure_generic_track_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const total_num_particles_to_track );
+    NS(buffer_size_t) const total_num_particles_to_track,
+    NS(buffer_size_t) const threads_per_block );
 
 
 NS(arch_status_t) NS(CudaKernelConfig_configure_track_until_turn_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const total_num_particles_to_track )
+    NS(buffer_size_t) const total_num_particles_to_track,
+    NS(buffer_size_t) const threads_per_block )
 {
-    return NS(CudaKernelConfig_configure_generic_track_kernel)(
-        kernel_config, node_info, total_num_particles_to_track );
+    return NS(CudaKernelConfig_configure_generic_track_kernel)( kernel_config,
+        node_info, total_num_particles_to_track, threads_per_block );
 }
 
 NS(arch_status_t)
 NS(CudaKernelConfig_configure_track_elem_by_elem_until_turn_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const total_num_particles_to_track )
+    NS(buffer_size_t) const total_num_particles_to_track,
+    NS(buffer_size_t) const threads_per_block )
 {
-    return NS(CudaKernelConfig_configure_generic_track_kernel)(
-        kernel_config, node_info, total_num_particles_to_track );
+    return NS(CudaKernelConfig_configure_generic_track_kernel)( kernel_config,
+        node_info, total_num_particles_to_track, threads_per_block );
 }
 
 NS(arch_status_t) NS(CudaKernelConfig_configure_track_line_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const total_num_particles_to_track )
+    NS(buffer_size_t) const total_num_particles_to_track,
+    NS(buffer_size_t) const threads_per_block )
 {
-    return NS(CudaKernelConfig_configure_generic_track_kernel)(
-        kernel_config, node_info, total_num_particles_to_track );
+    return NS(CudaKernelConfig_configure_generic_track_kernel)( kernel_config,
+        node_info, total_num_particles_to_track, threads_per_block );
 }
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -51,19 +55,18 @@ NS(arch_status_t) NS(CudaKernelConfig_configure_track_line_kernel)(
 NS(arch_status_t) NS(CudaKernelConfig_configure_fetch_particles_addresses_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const num_particle_sets )
+    NS(buffer_size_t) const num_particle_sets,
+    NS(buffer_size_t) const threads_per_block )
 {
     NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
 
      if( ( kernel_config != SIXTRL_NULLPTR ) &&
-        ( node_info != SIXTRL_NULLPTR ) )
+         ( threads_per_block > ( NS(buffer_size_t) )0u ) &&
+         ( node_info != SIXTRL_NULLPTR ) )
     {
         NS(buffer_size_t) const warp_size =
             NS(CudaNodeInfo_get_warp_size)( node_info );
 
-        NS(buffer_size_t) threads_per_block = ( NS(buffer_size_t) )128;
-
-
         NS(buffer_size_t) num_blocks = num_particle_sets / threads_per_block;
 
         if( ( num_blocks * threads_per_block ) < num_particle_sets )
@@ -92,16 +95,17 @@ NS(arch_status_t)
 NS(CudaKernelConfig_configure_assign_output_to_beam_monitors_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const num_beam_monitors )
+    NS(buffer_size_t) const num_beam_monitors,
+    NS(buffer_size_t) const threads_per_block )
 {
     ( void )num_beam_monitors;
 
     NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
 
      if( ( kernel_config != SIXTRL_NULLPTR ) &&
+         ( threads_per_block > ( NS(buffer_size_t) )0u ) &&
          ( node_info != SIXTRL_NULLPTR ) )
     {
-        NS(buffer_size_t) const threads_per_block = ( NS(buffer_size_t) )1u;
         NS(buffer_size_t) const num_blocks = ( NS(buffer_size_t) )1u;
 
         NS(buffer_size_t) const warp_size =
@@ -126,6 +130,38 @@ NS(CudaKernelConfig_configure_assign_output_to_beam_monitors_kernel)(
 
 NS(arch_status_t)
 NS(CudaKernelConfig_configure_assign_output_to_elem_by_elem_config_kernel)(
+    NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
+    const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
+    NS(buffer_size_t) const threads_per_block )
+{
+    NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
+
+     if( ( kernel_config != SIXTRL_NULLPTR ) &&
+         ( threads_per_block > ( NS(buffer_size_t) )0u ) &&
+         ( node_info != SIXTRL_NULLPTR ) )
+    {
+        NS(buffer_size_t) const num_blocks = ( NS(buffer_size_t) )1u;
+        NS(buffer_size_t) const warp_size =
+            NS(CudaNodeInfo_get_warp_size)( node_info );
+
+        if( ( NS(ARCH_STATUS_SUCCESS) ==
+              NS(KernelConfig_set_num_work_items_1d)(
+                kernel_config, num_blocks ) ) &&
+            ( NS(ARCH_STATUS_SUCCESS) ==
+              NS(KernelConfig_set_work_group_sizes_1d)(
+                kernel_config, threads_per_block ) ) &&
+            ( NS(ARCH_STATUS_SUCCESS) ==
+              NS(KernelConfig_set_preferred_work_group_multiple_1d)(
+                kernel_config, warp_size ) ) )
+        {
+            status = NS(KernelConfig_update)( kernel_config );
+        }
+    }
+
+    return status;
+}
+
+NS(arch_status_t) NS(CudaKernelConfig_configure_assign_address_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info )
 {
@@ -162,19 +198,18 @@ NS(CudaKernelConfig_configure_assign_output_to_elem_by_elem_config_kernel)(
 NS(arch_status_t) NS(CudaKernelConfig_configure_generic_track_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const total_num_particles_to_track )
+    NS(buffer_size_t) const total_num_particles_to_track,
+    NS(buffer_size_t) const threads_per_block )
 {
     NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
 
      if( ( kernel_config != SIXTRL_NULLPTR ) &&
-        ( node_info != SIXTRL_NULLPTR ) )
+         ( threads_per_block > ( NS(buffer_size_t) )0u ) &&
+         ( node_info != SIXTRL_NULLPTR ) )
     {
         NS(buffer_size_t) const warp_size =
             NS(CudaNodeInfo_get_warp_size)( node_info );
 
-        NS(buffer_size_t) threads_per_block = ( NS(buffer_size_t) )128;
-
-
         NS(buffer_size_t) num_blocks =
             total_num_particles_to_track / threads_per_block;
 
@@ -205,6 +240,4 @@ NS(arch_status_t) NS(CudaKernelConfig_configure_generic_track_kernel)(
     return status;
 }
 
-
-
 /* end: sixtracklib/cuda/control/default_kernel_config.c */
diff --git a/sixtracklib/cuda/control/default_kernel_config.h b/sixtracklib/cuda/control/default_kernel_config.h
index 9561d7a8..91723530 100644
--- a/sixtracklib/cuda/control/default_kernel_config.h
+++ b/sixtracklib/cuda/control/default_kernel_config.h
@@ -19,19 +19,22 @@ SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(CudaKernelConfig_configure_track_until_turn_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const total_num_particles_to_track );
+    NS(buffer_size_t) const total_num_particles_to_track,
+    NS(buffer_size_t) const threads_per_block );
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(CudaKernelConfig_configure_track_elem_by_elem_until_turn_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const total_num_particles_to_track );
+    NS(buffer_size_t) const total_num_particles_to_track,
+    NS(buffer_size_t) const threads_per_block );
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(CudaKernelConfig_configure_track_line_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const total_num_particles_to_track );
+    NS(buffer_size_t) const total_num_particles_to_track,
+    NS(buffer_size_t) const threads_per_block );
 
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
@@ -39,20 +42,26 @@ SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(CudaKernelConfig_configure_fetch_particles_addresses_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const num_particle_sets );
+    NS(buffer_size_t) const num_particle_sets,
+    NS(buffer_size_t) const threads_per_block );
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(CudaKernelConfig_configure_assign_output_to_beam_monitors_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
     const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
-    NS(buffer_size_t) const num_beam_monitors );
+    NS(buffer_size_t) const num_beam_monitors,
+    NS(buffer_size_t) const threads_per_block );
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(CudaKernelConfig_configure_assign_output_to_elem_by_elem_config_kernel)(
     NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
-    const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info );
-
+    const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info,
+    NS(buffer_size_t) const threads_per_block );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(CudaKernelConfig_configure_assign_address_kernel)(
+    NS(CudaKernelConfig)* SIXTRL_RESTRICT kernel_config,
+    const NS(CudaNodeInfo) *const SIXTRL_RESTRICT node_info );
 
 #endif /* !defined( _GPUCODE ) */
 
diff --git a/sixtracklib/cuda/controller.h b/sixtracklib/cuda/controller.h
index 25292529..ae371e75 100644
--- a/sixtracklib/cuda/controller.h
+++ b/sixtracklib/cuda/controller.h
@@ -20,6 +20,65 @@ extern "C" {
 
 #if !defined( _GPUCODE )
 
+/* ------------------------------------------------------------------------ */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t) NS(Cuda_get_num_all_nodes)( void );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t) NS(Cuda_get_all_nodes)(
+    NS(NodeId)* SIXTRL_RESTRICT out_node_ids_begin,
+    NS(arch_size_t) const max_num_node_ids );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Cuda_print_all_nodes)( void );
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t) NS(Cuda_num_available_nodes)(
+    char const* SIXTRL_RESTRICT env_variable_name );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(Cuda_num_available_nodes_detailed)(
+    char const* SIXTRL_RESTRICT filter_str,
+    char const* SIXTRL_RESTRICT env_variable_name );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(Cuda_get_available_nodes)(
+    NS(NodeId)* SIXTRL_RESTRICT out_node_ids_begin,
+    NS(arch_size_t) const max_num_node_ids );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(Cuda_get_available_nodes_detailed)(
+    NS(NodeId)* SIXTRL_RESTRICT out_node_ids_begin,
+    NS(arch_size_t) const max_num_node_ids,
+    NS(arch_size_t) const skip_first_num_nodes,
+    char const* SIXTRL_RESTRICT filter_str,
+    char const* SIXTRL_RESTRICT env_variable_name );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Cuda_print_available_nodes)( void );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Cuda_print_available_nodes_detailed)(
+    char const* SIXTRL_RESTRICT filter_str,
+    char const* SIXTRL_RESTRICT env_variable_name );
+
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(Cuda_get_available_node_id_strs)(
+    char** SIXTRL_RESTRICT out_node_id_strs,
+    NS(arch_size_t) const max_num_node_ids,
+    NS(arch_size_t) const node_id_str_capacity );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(Cuda_get_available_node_id_strs_detailed)(
+    char** SIXTRL_RESTRICT out_node_id_strs,
+    NS(arch_size_t) const max_num_node_ids,
+    NS(arch_size_t) const node_id_str_capacity,
+    NS(node_id_str_fmt_t) const node_id_str_format,
+    NS(arch_size_t) const skip_first_num_nodes,
+    char const* SIXTRL_RESTRICT filter_str,
+    char const* SIXTRL_RESTRICT env_variable_name );
+
+/* ------------------------------------------------------------------------ */
+
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(CudaController)*
 NS(CudaController_create)( void );
 
diff --git a/sixtracklib/cuda/controller.hpp b/sixtracklib/cuda/controller.hpp
index 636db2c9..17022d50 100644
--- a/sixtracklib/cuda/controller.hpp
+++ b/sixtracklib/cuda/controller.hpp
@@ -53,6 +53,45 @@ namespace SIXTRL_CXX_NAMESPACE
         static SIXTRL_CONSTEXPR_OR_CONST size_type DEFAULT_WARP_SIZE =
                 SIXTRL_CXX_NAMESPACE::ARCH_CUDA_DEFAULT_WARP_SIZE;
 
+        /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
+
+        static SIXTRL_HOST_FN size_type NUM_ALL_NODES();
+
+        static SIXTRL_HOST_FN size_type GET_ALL_NODES(
+            node_id_t* SIXTRL_RESTRICT out_node_ids_begin,
+            size_type const max_num_node_ids );
+
+        static SIXTRL_HOST_FN void PRINT_ALL_NODES();
+
+        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+        static SIXTRL_HOST_FN size_type NUM_AVAILABLE_NODES(
+            char const* SIXTRL_RESTRICT filter_str = nullptr,
+            char const* SIXTRL_RESTRICT env_variable_name = nullptr );
+
+        static SIXTRL_HOST_FN size_type GET_AVAILABLE_NODES(
+            node_id_t* SIXTRL_RESTRICT out_node_ids_begin,
+            size_type const max_num_node_ids,
+            size_type const skip_first_num_nodes = size_type{ 0 },
+            char const* SIXTRL_RESTRICT filter_str = nullptr,
+            char const* SIXTRL_RESTRICT env_variable_name = nullptr );
+
+        static SIXTRL_HOST_FN void PRINT_AVAILABLE_NODES(
+            char const* SIXTRL_RESTRICT filter_str = nullptr,
+            char const* SIXTRL_RESTRICT env_variable_name = nullptr );
+
+        static SIXTRL_HOST_FN size_type GET_AVAILABLE_NODE_ID_STR(
+            char** SIXTRL_RESTRICT out_node_id_strs,
+            size_type const max_num_node_ids,
+            size_type const node_id_str_capacity,
+            ::NS(node_id_str_fmt_t) const node_id_str_format =
+                ::NS(NODE_ID_STR_FORMAT_DEFAULT),
+            size_type const skip_first_num_nodes = size_type{ 0 },
+            char const* SIXTRL_RESTRICT filter_str = nullptr,
+            char const* SIXTRL_RESTRICT env_variable_name = nullptr );
+
+        /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
+
         SIXTRL_HOST_FN explicit CudaController(
             char const* config_str = nullptr );
 
diff --git a/sixtracklib/cuda/cuda_tools.h b/sixtracklib/cuda/cuda_tools.h
index 5af22e54..89843a8f 100644
--- a/sixtracklib/cuda/cuda_tools.h
+++ b/sixtracklib/cuda/cuda_tools.h
@@ -55,13 +55,11 @@ SIXTRL_STATIC SIXTRL_DEVICE_FN unsigned long
 SIXTRL_STATIC SIXTRL_DEVICE_FN unsigned long
     NS(Cuda_get_total_num_threads_in_kernel)( void );
 
-// SIXTRL_STATIC SIXTRL_DEVICE_FN void NS(Cuda_handle_debug_flag_in_kernel)(
-//     SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* ptr_debug_flag,
-//     NS(arch_debugging_t) const debug_flag );
+SIXTRL_STATIC SIXTRL_DEVICE_FN void NS(Cuda_collect_status_flag_value)(
+    SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* ptr_status_flags,
+    NS(arch_debugging_t) const status_flags );
 
 #endif /* #if defined( _GPUCODE ) */
-
-
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
@@ -144,11 +142,9 @@ SIXTRL_INLINE SIXTRL_HOST_FN unsigned long NS(Cuda_get_total_num_threads)(
     return ( grid_dim.x  * grid_dim.y  * grid_dim.z  ) *
            ( block_dim.x * block_dim.y * block_dim.z );
 }
-
 #endif /* !defined( _GPUCODE ) */
 
 #if defined( _GPUCODE )
-
 SIXTRL_INLINE SIXTRL_DEVICE_FN unsigned long NS(Cuda_get_1d_thread_id_in_kernel)()
 {
     unsigned long const num_threads_per_block =
@@ -219,24 +215,25 @@ SIXTRL_INLINE SIXTRL_DEVICE_FN void NS(Cuda_collect_status_flag_value)(
         #if ( defined( __CUDA_ARCH__ ) && ( __CUDA_ARCH__ >= 350 ) )
             /* sm_35 or larger defines atomicOr also for
              * 64Bit variables -> this is the only clean solution */
-            ::atomicOr( ptr_status_flags, status_flags );
+            ::atomicOr( ( NS(arch_debugging_t)* )ptr_status_flags,
+			( NS(arch_debugging_t) )status_flags );
 
-//         #elif defined( __CUDA_ARCH__ ) && ( __CUDA_ARCH__ >= 120 )
+        #elif defined( __CUDA_ARCH__ ) && ( __CUDA_ARCH__ >= 120 )
             /* NOTE: 64 bit atomic support is available but not atomicOr ->
              * use a spin-lock + copy&swap to emulate proper atomics.
              * this is not exactly a clean solution but since this is
              * intended to be used only in the debug kernels, it should not
              * be a big problem. */
 
-//             SIXTRL_UINT64_T old;
-//             SIXTRL_UINT64_T ret = *ptr_status_flags;
-//
-//             do
-//             {
-//                 old = ret;
-//             }
-//             while( ( ret = ::atomicCAS( ptr_status_flags, old,
-//                     ( SIXTRL_UINT64_T )( old | status_flags ) ) ) != old );
+            NS(arch_debugging_t) old;
+            NS(arch_debugging_t) ret = *ptr_status_flags;
+
+            do
+            {
+                old = ret;
+            }
+            while( ( ret = ::atomicCAS( ptr_status_flags, old,
+                ( NS(arch_debugging_t) )( old | status_flags ) ) ) != old );
         #else
 
             /* No integer atomic support. let's cross fingers and hope for the
@@ -247,13 +244,9 @@ SIXTRL_INLINE SIXTRL_DEVICE_FN void NS(Cuda_collect_status_flag_value)(
         #endif /* defined( __CUDA_ARCH__ ) && ( __CUDA_ARCH__ >= 350 ) */
     }
 }
-
 #endif /* defined( _GPUCODE ) */
 
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
 #endif /* SIXTRACKLIB_CUDA_IMPL_CUDA_TOOLS_H__ */
-
-/* end: sixtracklib/cuda/impl/cuda_tools.h */
diff --git a/sixtracklib/cuda/kernels/assign_address_item.cu b/sixtracklib/cuda/kernels/assign_address_item.cu
new file mode 100644
index 00000000..ef8be2dc
--- /dev/null
+++ b/sixtracklib/cuda/kernels/assign_address_item.cu
@@ -0,0 +1,39 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/cuda/kernels/assign_address_item.cuh"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #include <cuda_runtime_api.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+    #include "sixtracklib/common/buffer/assign_address_item_kernel_impl.h"
+    #include "sixtracklib/cuda/definitions.h"
+    #include "sixtracklib/cuda/cuda_tools.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+__global__ void NS(AssignAddressItem_process_managed_buffer_cuda)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT assign_buffer,
+    NS(buffer_size_t) const assign_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_size_t) const dest_slot_size,
+    NS(arch_size_t) const dest_buffer_id,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT src_buffer,
+    NS(buffer_size_t) const src_slot_size,
+    NS(arch_size_t) const src_buffer_id )
+{
+    NS(buffer_size_t) const start_idx = NS(Cuda_get_1d_thread_id_in_kernel)();
+    NS(buffer_size_t) const stride = NS(Cuda_get_total_num_threads_in_kernel)();
+
+    NS(arch_status_t) const status =
+    NS(AssignAddressItem_perform_address_assignment_kernel_impl)(
+        assign_buffer, assign_slot_size, start_idx, stride,
+        dest_buffer, dest_slot_size, dest_buffer_id,
+        src_buffer,  src_slot_size,  src_buffer_id );
+}
diff --git a/sixtracklib/cuda/kernels/assign_address_item.cuh b/sixtracklib/cuda/kernels/assign_address_item.cuh
new file mode 100644
index 00000000..e4f7dbf0
--- /dev/null
+++ b/sixtracklib/cuda/kernels/assign_address_item.cuh
@@ -0,0 +1,27 @@
+#ifndef SIXTRACKLIB_CUDA_KERNELS_ASSIGN_ADDRESS_ITEM_CUDA_CUH__
+#define SIXTRACKLIB_CUDA_KERNELS_ASSIGN_ADDRESS_ITEM_CUDA_CUH__
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/buffer/assign_address_item_kernel_impl.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus )
+extern "C" {
+#endif /* defined( __cplusplus ) */
+
+__global__ void NS(AssignAddressItem_process_managed_buffer_cuda)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT assign_buffer,
+    NS(buffer_size_t) const assign_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_size_t) const dest_slot_size,
+    NS(arch_size_t) const dest_buffer_id,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT src_buffer,
+    NS(buffer_size_t) const src_slot_size,
+    NS(arch_size_t) const src_buffer_id );
+
+#if defined( __cplusplus )
+}
+#endif /* defined( __cplusplus ) */
+#endif /* SIXTRACKLIB_CUDA_KERNELS_ASSIGN_ADDRESS_ITEM_CUDA_CUH__ */
diff --git a/sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cu b/sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cu
index a69a581b..6844251e 100644
--- a/sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cu
+++ b/sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cu
@@ -20,22 +20,26 @@
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 __global__ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda)(
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t) const out_buffer_offset_index,
     NS(buffer_size_t) const slot_size )
 {
     if( NS(Cuda_get_1d_thread_id_in_kernel)() == ( size_t )0u )
     {
+        SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
+            elem_by_elem_config = NS(ElemByElemConfig_from_managed_buffer)(
+                config_buffer, elem_by_elem_config_index, slot_size );
+
         NS(ElemByElemConfig_assign_managed_output_buffer)( elem_by_elem_config,
             output_buffer, out_buffer_offset_index, slot_size );
     }
 }
 
 __global__ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_debug)(
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t) const out_buffer_offset_index,
     NS(buffer_size_t) const slot_size,
@@ -45,6 +49,10 @@ __global__ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_debug)(
     {
         NS(arch_debugging_t) dbg = SIXTRL_ARCH_DEBUGGING_GENERAL_FAILURE;
 
+        SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
+            elem_by_elem_config = NS(ElemByElemConfig_from_managed_buffer)(
+                config_buffer, elem_by_elem_config_index, slot_size );
+
         NS(ElemByElemConfig_assign_managed_output_buffer_debug)(
             elem_by_elem_config, output_buffer, out_buffer_offset_index,
                 slot_size, &dbg );
diff --git a/sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cuh b/sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cuh
index b21c8a9d..c9fd7306 100644
--- a/sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cuh
+++ b/sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cuh
@@ -14,15 +14,15 @@ extern "C" {
 #endif /* defined( __cplusplus ) */
 
 __global__ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda)(
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t) const out_buffer_offset_index,
     NS(buffer_size_t) const slot_size );
 
 __global__ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_debug)(
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t) const out_buffer_offset_index,
     NS(buffer_size_t) const slot_size,
diff --git a/sixtracklib/cuda/kernels/track_particles.cu b/sixtracklib/cuda/kernels/track_particles.cu
index bf987247..d03493f3 100644
--- a/sixtracklib/cuda/kernels/track_particles.cu
+++ b/sixtracklib/cuda/kernels/track_particles.cu
@@ -63,8 +63,8 @@ __global__ void NS(Track_track_elem_by_elem_until_turn_cuda)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
     NS(buffer_size_t) const part_set_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer_begin,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(buffer_size_t) const until_turn, NS(buffer_size_t) const slot_size )
 {
     typedef NS(particle_num_elements_t) nelements_t;
@@ -74,15 +74,16 @@ __global__ void NS(Track_track_elem_by_elem_until_turn_cuda)(
 
     NS(Track_particles_elem_by_elem_until_turn_kernel_impl)( pbuffer,
         part_set_index, part_idx, part_idx_stride, belem_buffer,
-            elem_by_elem_config, until_turn, slot_size );
+            config_buffer_begin, elem_by_elem_config_index,
+                until_turn, slot_size );
 }
 
 __global__ void NS(Track_track_elem_by_elem_until_turn_cuda_debug)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
     NS(buffer_size_t) const part_set_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer_begin,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(buffer_size_t) const until_turn, NS(buffer_size_t) const slot_size,
     SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags )
 {
@@ -95,7 +96,8 @@ __global__ void NS(Track_track_elem_by_elem_until_turn_cuda_debug)(
 
     NS(Track_particles_elem_by_elem_until_turn_debug_kernel_impl)( pbuffer,
         part_set_index, part_idx, part_idx_stride, belem_buffer,
-            elem_by_elem_config, until_turn, slot_size, &status_flags );
+            config_buffer_begin, elem_by_elem_config_index, until_turn,
+                slot_size, &status_flags );
 
     NS(Cuda_collect_status_flag_value)( ptr_status_flags, status_flags );
 }
diff --git a/sixtracklib/cuda/kernels/track_particles.cuh b/sixtracklib/cuda/kernels/track_particles.cuh
index e15c4396..1bb6d52c 100644
--- a/sixtracklib/cuda/kernels/track_particles.cuh
+++ b/sixtracklib/cuda/kernels/track_particles.cuh
@@ -36,7 +36,8 @@ __global__ void NS(Track_track_elem_by_elem_until_turn_cuda)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer_begin,
     NS(buffer_size_t) const pset_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT be_buffer_begin,
-    SIXTRL_DATAPTR_DEC const NS(ElemByElemConfig) *const SIXTRL_RESTRICT conf,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer_begin,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(buffer_size_t) const until_turn_elem_by_elem,
     NS(buffer_size_t) const slot_size );
 
@@ -44,7 +45,8 @@ __global__ void NS(Track_track_elem_by_elem_until_turn_cuda_debug)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer_begin,
     NS(buffer_size_t) const pset_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT be_buffer_begin,
-    SIXTRL_DATAPTR_DEC const NS(ElemByElemConfig) *const SIXTRL_RESTRICT conf,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer_begin,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(buffer_size_t) const until_turn_elem_by_elem,
     NS(buffer_size_t) const slot_size,
     SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_dbg_register);
diff --git a/sixtracklib/cuda/track/track_job.cpp b/sixtracklib/cuda/track/track_job.cpp
index f8c1c3da..4848959a 100644
--- a/sixtracklib/cuda/track/track_job.cpp
+++ b/sixtracklib/cuda/track/track_job.cpp
@@ -9,6 +9,7 @@
     #include <cstddef>
     #include <cstdlib>
     #include <stdexcept>
+    #include <sstream>
 
     #include <cuda_runtime_api.h>
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
@@ -19,6 +20,7 @@
     #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/control/arch_base.hpp"
     #include "sixtracklib/common/control/kernel_config_base.hpp"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
     #include "sixtracklib/common/track/definitions.h"
     #include "sixtracklib/common/track/track_job_ctrl_arg_base.hpp"
     #include "sixtracklib/common/track/track_job_nodectrl_arg_base.hpp"
@@ -31,44 +33,50 @@
     #include "sixtracklib/cuda/control/default_kernel_config.h"
     #include "sixtracklib/cuda/wrappers/track_job_wrappers.h"
 
+    #include "external/toml11/toml.hpp"
+
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if defined( __cplusplus ) && !defined( _GPUCODE ) && \
    !defined( __CUDACC__  ) && !defined( __CUDA_ARCH__ )
 
-namespace st = SIXTRL_CXX_NAMESPACE;
-
 namespace SIXTRL_CXX_NAMESPACE
 {
+    namespace
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using tjob_t = st::CudaTrackJob;
+        using base_tjob_t = st::TrackJobNodeCtrlArgBase;
+        using st_size_t = tjob_t::size_type;
+        using st_status_t = tjob_t::status_t;
+        using st_track_status_t = tjob_t::track_status_t;
+    }
+
+    constexpr st_size_t tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK;
+    constexpr st_size_t tjob_t::DEFAULT_THREADS_PER_BLOCK;
+
     /* --------------------------------------------------------------------- */
 
-    CudaTrackJob::size_type CudaTrackJob::NumAvailableNodes()
+    st_size_t tjob_t::NumAvailableNodes()
     {
-        CudaTrackJob::size_type num_available_nodes =
-            CudaTrackJob::size_type{ 0 };
+        st_size_t num_available_nodes = st_size_t{ 0 };
 
         int temp_num_devices = int{ -1 };
         ::cudaError_t err = ::cudaGetDeviceCount( &temp_num_devices );
 
         if( ( err == ::cudaSuccess ) && ( temp_num_devices > int{ 0 } ) )
         {
-            num_available_nodes = static_cast< CudaTrackJob::size_type >(
-                temp_num_devices );
+            num_available_nodes = static_cast< st_size_t >( temp_num_devices );
         }
 
         return num_available_nodes;
     }
 
-    CudaTrackJob::size_type CudaTrackJob::GetAvailableNodeIdsList(
-        CudaTrackJob::size_type const max_num_node_ids,
-        CudaTrackJob::node_id_t* SIXTRL_RESTRICT node_ids_begin )
+    st_size_t tjob_t::GetAvailableNodeIdsList( st_size_t const max_num_node_ids,
+        tjob_t::node_id_t* SIXTRL_RESTRICT node_ids_begin )
     {
-        using size_t = CudaTrackJob::size_type;
-
-        size_t num_retrieved_nodes = size_t{ 0 };
-
-        if( ( max_num_node_ids > size_t{ 0 } ) &&
-            ( node_ids_begin != nullptr ) )
+        st_size_t num_retrieved_nodes = st_size_t{ 0 };
+        if( ( max_num_node_ids > size_t{ 0 } ) && ( node_ids_begin != nullptr ) )
         {
             std::unique_ptr< st::CudaController > ptr_ctrl(
                 new st::CudaController );
@@ -80,7 +88,6 @@ namespace SIXTRL_CXX_NAMESPACE
                     max_num_node_ids, node_ids_begin );
 
                 SIXTRL_ASSERT( num_retrieved_nodes <= max_num_node_ids );
-
                 SIXTRL_ASSERT( num_retrieved_nodes <=
                     ptr_ctrl->numAvailableNodes() );
             }
@@ -89,14 +96,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return num_retrieved_nodes;
     }
 
-    CudaTrackJob::size_type CudaTrackJob::GetAvailableNodeIndicesList(
-        CudaTrackJob::size_type const max_num_node_indices,
-        CudaTrackJob::node_index_t* SIXTRL_RESTRICT node_indices_begin )
+    st_size_t tjob_t::GetAvailableNodeIndicesList(
+        st_size_t const max_num_node_indices,
+        tjob_t::node_index_t* SIXTRL_RESTRICT node_indices_begin )
     {
-        using size_t = CudaTrackJob::size_type;
-
-        size_t num_retrieved_nodes = size_t{ 0 };
-
+        st_size_t num_retrieved_nodes = st_size_t{ 0 };
         if( ( max_num_node_indices > size_t{ 0 } ) &&
             ( node_indices_begin != nullptr ) )
         {
@@ -104,13 +108,12 @@ namespace SIXTRL_CXX_NAMESPACE
                 new st::CudaController );
 
             if( ( ptr_ctrl.get() != nullptr ) &&
-                ( ptr_ctrl->numAvailableNodes() > size_t{ 0 } ) )
+                ( ptr_ctrl->numAvailableNodes() > st_size_t{ 0 } ) )
             {
                 num_retrieved_nodes = ptr_ctrl->availableNodeIndices(
                     max_num_node_indices, node_indices_begin );
 
                 SIXTRL_ASSERT( num_retrieved_nodes <= max_num_node_indices );
-
                 SIXTRL_ASSERT( num_retrieved_nodes <=
                     ptr_ctrl->numAvailableNodes() );
             }
@@ -122,35 +125,61 @@ namespace SIXTRL_CXX_NAMESPACE
     /* --------------------------------------------------------------------- */
 
 
-    CudaTrackJob::CudaTrackJob(
-        const char *const SIXTRL_RESTRICT config_str ) :
+    tjob_t::CudaTrackJob( const char *const SIXTRL_RESTRICT config_str ) :
             st::TrackJobNodeCtrlArgBase( st::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str ),
+        m_track_threads_per_block( tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( tjob_t::DEFAULT_THREADS_PER_BLOCK )
     {
-        CudaTrackJob::status_t status =
-            this->doPrepareControllerCudaImpl( config_str );
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+
+        if( config_str != nullptr )
+        {
+            status = this->doParseConfigStrCudaImpl( config_str );
+        }
+
+        if( status == st::ARCH_STATUS_SUCCESS )
+        {
+            status = this->doPrepareControllerCudaImpl( config_str );
+        }
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
             status = this->doPrepareDefaultKernelsCudaImpl( config_str );
         }
+
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+        ( void )status;
     }
 
-    CudaTrackJob::CudaTrackJob(
-        std::string const& SIXTRL_RESTRICT_REF config_str ) :
+    tjob_t::CudaTrackJob( std::string const& SIXTRL_RESTRICT_REF config_str ) :
             st::TrackJobNodeCtrlArgBase( st::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() ),
+        m_track_threads_per_block( tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( tjob_t::DEFAULT_THREADS_PER_BLOCK )
     {
-        CudaTrackJob::status_t status =
-            this->doPrepareControllerCudaImpl( config_str.c_str() );
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+
+        if( !config_str.empty() )
+        {
+            status = this->doParseConfigStrCudaImpl( config_str.c_str() );
+        }
+
+        if( status == st::ARCH_STATUS_SUCCESS )
+        {
+            status = this->doPrepareControllerCudaImpl( config_str.c_str() );
+        }
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
             status = this->doPrepareDefaultKernelsCudaImpl( config_str.c_str() );
         }
+
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+        ( void )status;
     }
 
-    CudaTrackJob::CudaTrackJob(
+    tjob_t::CudaTrackJob(
         const char *const SIXTRL_RESTRICT node_id_str,
         c_buffer_t* SIXTRL_RESTRICT particles_buffer,
         c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
@@ -158,17 +187,20 @@ namespace SIXTRL_CXX_NAMESPACE
         size_type const until_turn_elem_by_elem,
         const char *const SIXTRL_RESTRICT config_str ) :
             st::TrackJobNodeCtrlArgBase( st::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str ),
+        m_track_threads_per_block( tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( tjob_t::DEFAULT_THREADS_PER_BLOCK )
     {
-        CudaTrackJob::status_t const status = this->doInitCudaTrackJob(
-            config_str, particles_buffer,
-            CudaTrackJob::DefaultParticleSetIndicesBegin(),
-                CudaTrackJob::DefaultParticleSetIndicesEnd(),
-                   beam_elements_buffer, output_buffer,
-                       until_turn_elem_by_elem );
+        st_status_t const status = this->doInitCudaTrackJob( node_id_str,
+            particles_buffer, tjob_t::DefaultParticleSetIndicesBegin(),
+                tjob_t::DefaultParticleSetIndicesEnd(), beam_elements_buffer,
+                    output_buffer, until_turn_elem_by_elem, config_str );
+
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+        ( void )status;
     }
 
-    CudaTrackJob::CudaTrackJob(
+    tjob_t::CudaTrackJob(
         std::string const& SIXTRL_RESTRICT_REF node_id_str,
         buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
         buffer_t& SIXTRL_RESTRICT_REF beam_elements_buffer,
@@ -176,14 +208,14 @@ namespace SIXTRL_CXX_NAMESPACE
         size_type const until_turn_elem_by_elem,
         std::string const& config_str ) :
             st::TrackJobNodeCtrlArgBase( st::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() ),
+        m_track_threads_per_block( tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( tjob_t::DEFAULT_THREADS_PER_BLOCK )
     {
-        CudaTrackJob::status_t const status = this->doInitCudaTrackJob(
-            config_str, particles_buffer,
-                st::CudaTrackJob::DefaultParticleSetIndicesBegin(),
-                    st::CudaTrackJob::DefaultParticleSetIndicesEnd(),
-                        beam_elements_buffer, ptr_output_buffer,
-                            until_turn_elem_by_elem );
+        st_status_t const status = this->doInitCudaTrackJob( node_id_str,
+            particles_buffer, tjob_t::DefaultParticleSetIndicesBegin(),
+                tjob_t::DefaultParticleSetIndicesEnd(), beam_elements_buffer,
+                    ptr_output_buffer, until_turn_elem_by_elem, config_str );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
@@ -198,24 +230,26 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    CudaTrackJob::CudaTrackJob(
+    tjob_t::CudaTrackJob(
         std::string const& SIXTRL_RESTRICT_REF node_id_str,
-        CudaTrackJob::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        CudaTrackJob::size_type const particle_set_index,
-        CudaTrackJob::buffer_t& SIXTRL_RESTRICT_REF belems_buffer,
-        CudaTrackJob::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        CudaTrackJob::size_type const until_turn_elem_by_elem,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
+        st_size_t const particle_set_index,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF belems_buffer,
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem,
         std::string const& config_str ) :
             st::TrackJobNodeCtrlArgBase( st::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() ),
+        m_track_threads_per_block( tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( tjob_t::DEFAULT_THREADS_PER_BLOCK )
     {
-        CudaTrackJob::size_type const* psets_begin = &particle_set_index;
-        CudaTrackJob::size_type const* psets_end = psets_begin;
-        std::advance( psets_end, CudaTrackJob::size_type{ 1 } );
+        st_size_t const* psets_begin = &particle_set_index;
+        st_size_t const* psets_end = psets_begin;
+        std::advance( psets_end, st_size_t{ 1 } );
 
-        CudaTrackJob::status_t const status = this->doInitCudaTrackJob(
-            config_str, particles_buffer, psets_begin, psets_end, belems_buffer,
-                ptr_output_buffer, until_turn_elem_by_elem );
+        st_status_t const status = this->doInitCudaTrackJob( node_id_str,
+            particles_buffer, psets_begin, psets_end, belems_buffer,
+                ptr_output_buffer, until_turn_elem_by_elem, config_str );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
@@ -230,102 +264,114 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    CudaTrackJob::CudaTrackJob(
-        char const* SIXTRL_RESTRICT node_id_str,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        CudaTrackJob::size_type const particle_set_index,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        CudaTrackJob::size_type const until_turn_elem_by_elem,
+    tjob_t::CudaTrackJob( char const* SIXTRL_RESTRICT node_id_str,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        st_size_t const particle_set_index,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem,
         char const* SIXTRL_RESTRICT config_str ) :
             st::TrackJobNodeCtrlArgBase( st::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str ),
+        m_track_threads_per_block( tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( tjob_t::DEFAULT_THREADS_PER_BLOCK )
     {
-        CudaTrackJob::size_type const* psets_begin = &particle_set_index;
-        CudaTrackJob::size_type const* psets_end = psets_begin;
-        std::advance( psets_end, CudaTrackJob::size_type{ 1 } );
+        st_size_t const* psets_begin = &particle_set_index;
+        st_size_t const* psets_end = psets_begin;
+        std::advance( psets_end, st_size_t{ 1 } );
 
-        CudaTrackJob::status_t const status = this->doInitCudaTrackJob(
-            config_str, particles_buffer, psets_begin, psets_end, belems_buffer,
-                ptr_output_buffer, until_turn_elem_by_elem );
+        st_status_t const status = this->doInitCudaTrackJob( node_id_str,
+            particles_buffer, psets_begin, psets_end, belems_buffer,
+                ptr_output_buffer, until_turn_elem_by_elem, config_str );
 
         SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
         ( void )status;
     }
 
-    CudaTrackJob::CudaTrackJob(
+    tjob_t::CudaTrackJob(
         std::string const& SIXTRL_RESTRICT_REF node_id_str,
-        CudaTrackJob::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        CudaTrackJob::size_type const num_particle_sets,
-        CudaTrackJob::size_type const* SIXTRL_RESTRICT pset_indices_begin,
-        CudaTrackJob::buffer_t& SIXTRL_RESTRICT_REF belems_buffer,
-        CudaTrackJob::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        CudaTrackJob::size_type const until_turn_elem_by_elem,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
+        st_size_t const num_particle_sets,
+        st_size_t const* SIXTRL_RESTRICT pset_indices_begin,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF belems_buffer,
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem,
         std::string const& config_str ) :
             st::TrackJobNodeCtrlArgBase( st::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() ),
+        m_track_threads_per_block( tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( tjob_t::DEFAULT_THREADS_PER_BLOCK )
     {
-        CudaTrackJob::size_type const* pset_indices_end = pset_indices_begin;
+        st_size_t const* pset_indices_end = pset_indices_begin;
 
         if( pset_indices_end != nullptr )
         {
             std::advance( pset_indices_end, num_particle_sets );
         }
 
-        CudaTrackJob::status_t const status = this->doInitCudaTrackJob(
-            config_str, particles_buffer, pset_indices_begin, pset_indices_end,
-                belems_buffer, ptr_output_buffer, until_turn_elem_by_elem );
+        st_status_t const status = this->doInitCudaTrackJob(
+            node_id_str, particles_buffer, pset_indices_begin, pset_indices_end,
+                belems_buffer, ptr_output_buffer, until_turn_elem_by_elem,
+                    config_str );
 
         SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
         ( void )status;
     }
 
-    CudaTrackJob::CudaTrackJob(
+    tjob_t::CudaTrackJob(
         char const* SIXTRL_RESTRICT node_id_str,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        CudaTrackJob::size_type const num_particle_sets,
-        CudaTrackJob::size_type const* SIXTRL_RESTRICT pset_indices_begin,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        CudaTrackJob::size_type const until_turn_elem_by_elem,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        st_size_t const num_particle_sets,
+        st_size_t const* SIXTRL_RESTRICT pset_indices_begin,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem,
         char const* SIXTRL_RESTRICT config_str ) :
             st::TrackJobNodeCtrlArgBase( st::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str ),
+        m_track_threads_per_block( tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( tjob_t::DEFAULT_THREADS_PER_BLOCK )
     {
-        CudaTrackJob::size_type const* pset_indices_end = pset_indices_begin;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_size_t const* pset_indices_end = pset_indices_begin;
 
-        if( pset_indices_end != nullptr )
+        if( ( pset_indices_end != nullptr ) &&
+            ( num_particle_sets > st_size_t{ 0 } ) )
         {
             std::advance( pset_indices_end, num_particle_sets );
+            status = this->doInitCudaTrackJob( node_id_str, particles_buffer,
+                pset_indices_begin, pset_indices_end, belems_buffer,
+                    ptr_output_buffer, until_turn_elem_by_elem, config_str );
+        }
+        else
+        {
+            status = this->doInitCudaTrackJob( node_id_str, particles_buffer,
+                tjob_t::DefaultParticleSetIndicesBegin(),
+                tjob_t::DefaultParticleSetIndicesEnd(),
+                    belems_buffer, ptr_output_buffer, until_turn_elem_by_elem,
+                        config_str );
         }
-
-        CudaTrackJob::status_t const status = this->doInitCudaTrackJob(
-            config_str, particles_buffer, pset_indices_begin, pset_indices_end,
-                belems_buffer, ptr_output_buffer, until_turn_elem_by_elem );
 
         SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
         ( void )status;
     }
 
-    CudaTrackJob::~CudaTrackJob()
-    {
-
-    }
+    tjob_t::~CudaTrackJob() SIXTRL_NOEXCEPT {}
 
     /* ===================================================================== */
 
-    bool CudaTrackJob::hasCudaController() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasCudaController() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCudaController() != nullptr );
     }
 
-    CudaTrackJob::cuda_controller_t& CudaTrackJob::cudaController()
+    tjob_t::cuda_controller_t& tjob_t::cudaController()
     {
-        return const_cast< CudaTrackJob::cuda_controller_t& >( static_cast<
-            CudaTrackJob const& >( *this ).cudaController() );
+        return const_cast< tjob_t::cuda_controller_t& >( static_cast<
+            tjob_t const& >( *this ).cudaController() );
     }
 
-    CudaTrackJob::cuda_controller_t const& CudaTrackJob::cudaController() const
+    tjob_t::cuda_controller_t const& tjob_t::cudaController() const
     {
         if( !this->hasCudaController() )
         {
@@ -335,18 +381,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return *this->ptrCudaController();
     }
 
-    CudaTrackJob::cuda_controller_t*
-    CudaTrackJob::ptrCudaController() SIXTRL_NOEXCEPT
+    tjob_t::cuda_controller_t* tjob_t::ptrCudaController() SIXTRL_NOEXCEPT
     {
-        return const_cast< CudaTrackJob::cuda_controller_t* >( static_cast<
-            CudaTrackJob const& >( *this ).ptrCudaController() );
+        return const_cast< tjob_t::cuda_controller_t* >( static_cast<
+            tjob_t const& >( *this ).ptrCudaController() );
     }
 
-    CudaTrackJob::cuda_controller_t const*
-    CudaTrackJob::ptrCudaController() const SIXTRL_NOEXCEPT
+    tjob_t::cuda_controller_t const*
+    tjob_t::ptrCudaController() const SIXTRL_NOEXCEPT
     {
-        using ctrl_t = CudaTrackJob::cuda_controller_t;
-        using ptr_base_ctrl_t = CudaTrackJob::controller_base_t const*;
+        using ctrl_t = tjob_t::cuda_controller_t;
+        using ptr_base_ctrl_t = tjob_t::controller_base_t const*;
 
         ptr_base_ctrl_t ptr_base_ctrl = this->ptrControllerBase();
 
@@ -357,127 +402,122 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    bool CudaTrackJob::hasCudaParticlesArg() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasCudaParticlesArg() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCudaParticlesArg() != nullptr );
     }
 
-    CudaTrackJob::cuda_argument_t& CudaTrackJob::cudaParticlesArg()
+    tjob_t::cuda_argument_t& tjob_t::cudaParticlesArg()
     {
         return this->doGetRefCudaArgument( this->ptrParticlesArgBase(),
             "ptrParticlesArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t const& CudaTrackJob::cudaParticlesArg() const
+    tjob_t::cuda_argument_t const& tjob_t::cudaParticlesArg() const
     {
         return this->doGetRefCudaArgument( this->ptrParticlesArgBase(),
             "ptrParticlesArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t*
-    CudaTrackJob::ptrCudaParticlesArg() SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t* tjob_t::ptrCudaParticlesArg() SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrParticlesArgBase() );
     }
 
-    CudaTrackJob::cuda_argument_t const*
-    CudaTrackJob::ptrCudaParticlesArg() const SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t const*
+    tjob_t::ptrCudaParticlesArg() const SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrParticlesArgBase() );
     }
 
     /* --------------------------------------------------------------------- */
 
-    bool CudaTrackJob::hasCudaBeamElementsArg() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasCudaBeamElementsArg() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCudaBeamElementsArg() != nullptr );
     }
 
-    CudaTrackJob::cuda_argument_t& CudaTrackJob::cudaBeamElementsArg()
+    tjob_t::cuda_argument_t& tjob_t::cudaBeamElementsArg()
     {
         return this->doGetRefCudaArgument( this->ptrBeamElementsArgBase(),
             "ptrBeamElementsArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t const&
-    CudaTrackJob::cudaBeamElementsArg() const
+    tjob_t::cuda_argument_t const& tjob_t::cudaBeamElementsArg() const
     {
         return this->doGetRefCudaArgument( this->ptrBeamElementsArgBase(),
             "ptrBeamElementsArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t const*
-    CudaTrackJob::ptrCudaBeamElementsArg() const SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t const*
+    tjob_t::ptrCudaBeamElementsArg() const SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrBeamElementsArgBase() );
     }
 
-    CudaTrackJob::cuda_argument_t*
-    CudaTrackJob::ptrCudaBeamElementsArg() SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t*
+    tjob_t::ptrCudaBeamElementsArg() SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrBeamElementsArgBase() );
     }
 
     /* --------------------------------------------------------------------- */
 
-    bool CudaTrackJob::hasCudaOutputArg() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasCudaOutputArg() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCudaOutputArg() != nullptr );
     }
 
-    CudaTrackJob::cuda_argument_t& CudaTrackJob::cudaOutputArg()
+    tjob_t::cuda_argument_t& tjob_t::cudaOutputArg()
     {
         return this->doGetRefCudaArgument( this->ptrOutputArgBase(),
             "ptrOutputArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t const& CudaTrackJob::cudaOutputArg() const
+    tjob_t::cuda_argument_t const& tjob_t::cudaOutputArg() const
     {
         return this->doGetRefCudaArgument( this->ptrOutputArgBase(),
             "ptrOutputArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t*
-    CudaTrackJob::ptrCudaOutputArg() SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t* tjob_t::ptrCudaOutputArg() SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrOutputArgBase() );
     }
 
-    CudaTrackJob::cuda_argument_t const*
-    CudaTrackJob::ptrCudaOutputArg() const SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t const*
+    tjob_t::ptrCudaOutputArg() const SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrOutputArgBase() );
     }
 
     /* --------------------------------------------------------------------- */
 
-    bool CudaTrackJob::hasCudaElemByElemConfigArg() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasCudaElemByElemConfigArg() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCudaElemByElemConfigArg() != nullptr );
     }
 
-    CudaTrackJob::cuda_argument_t& CudaTrackJob::cudaElemByElemConfigArg()
+    tjob_t::cuda_argument_t& tjob_t::cudaElemByElemConfigArg()
     {
         return this->doGetRefCudaArgument( this->ptrElemByElemConfigArgBase(),
             "ptrElemByElemConfigArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t const&
-    CudaTrackJob::cudaElemByElemConfigArg() const
+    tjob_t::cuda_argument_t const& tjob_t::cudaElemByElemConfigArg() const
     {
         return this->doGetRefCudaArgument( this->ptrElemByElemConfigArgBase(),
             "ptrElemByElemConfigArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t*
-    CudaTrackJob::ptrCudaElemByElemConfigArg() SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t* tjob_t::ptrCudaElemByElemConfigArg() SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument(
             this->ptrElemByElemConfigArgBase() );
     }
 
-    CudaTrackJob::cuda_argument_t const*
-    CudaTrackJob::ptrCudaElemByElemConfigArg() const SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t const*
+    tjob_t::ptrCudaElemByElemConfigArg() const SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument(
             this->ptrElemByElemConfigArgBase() );
@@ -485,107 +525,248 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    bool CudaTrackJob::hasCudaDebugRegisterArg() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasCudaDebugRegisterArg() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCudaDebugRegisterArg() != nullptr );
     }
 
-    CudaTrackJob::cuda_argument_t& CudaTrackJob::cudaDebugRegisterArg()
+    tjob_t::cuda_argument_t& tjob_t::cudaDebugRegisterArg()
     {
         return this->doGetRefCudaArgument(
             this->ptrDebugRegisterArgBase(), "ptrDebugRegisterArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t const&
-    CudaTrackJob::cudaDebugRegisterArg() const
+    tjob_t::cuda_argument_t const& tjob_t::cudaDebugRegisterArg() const
     {
         return this->doGetRefCudaArgument(
             this->ptrDebugRegisterArgBase(), "ptrDebugRegisterArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t*
-    CudaTrackJob::ptrCudaDebugRegisterArg() SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t* tjob_t::ptrCudaDebugRegisterArg() SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrDebugRegisterArgBase() );
     }
 
-    CudaTrackJob::cuda_argument_t const*
-    CudaTrackJob::ptrCudaDebugRegisterArg() const SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t const*
+    tjob_t::ptrCudaDebugRegisterArg() const SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrDebugRegisterArgBase() );
     }
 
     /* --------------------------------------------------------------------- */
 
-    bool CudaTrackJob::hasCudaParticlesAddrArg() const SIXTRL_NOEXCEPT
+    bool tjob_t::hasCudaParticlesAddrArg() const SIXTRL_NOEXCEPT
     {
         return ( this->ptrCudaParticlesAddrArg() != nullptr );
     }
 
-    CudaTrackJob::cuda_argument_t const&
-    CudaTrackJob::cudaParticlesAddrArg() const
+    tjob_t::cuda_argument_t const& tjob_t::cudaParticlesAddrArg() const
     {
         return this->doGetRefCudaArgument(
             this->ptrParticlesAddrArgBase(), "ptrParticlesAddrArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t& CudaTrackJob::cudaParticlesAddrArg()
+    tjob_t::cuda_argument_t& tjob_t::cudaParticlesAddrArg()
     {
         return this->doGetRefCudaArgument(
             this->ptrParticlesAddrArgBase(), "ptrParticlesAddrArgBase()" );
     }
 
-    CudaTrackJob::cuda_argument_t*
-    CudaTrackJob::ptrCudaParticlesAddrArg() SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t* tjob_t::ptrCudaParticlesAddrArg() SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrParticlesAddrArgBase() );
     }
 
-    CudaTrackJob::cuda_argument_t const*
-    CudaTrackJob::ptrCudaParticlesAddrArg() const SIXTRL_NOEXCEPT
+    tjob_t::cuda_argument_t const*
+    tjob_t::ptrCudaParticlesAddrArg() const SIXTRL_NOEXCEPT
     {
         return this->doGetPtrCudaArgument( this->ptrParticlesAddrArgBase() );
     }
 
+    st_size_t tjob_t::default_threads_per_block() const SIXTRL_NOEXCEPT
+    {
+        return this->m_default_threads_per_block;
+    }
+
+    st_size_t tjob_t::default_track_threads_per_block() const SIXTRL_NOEXCEPT
+    {
+        return this->m_track_threads_per_block;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::cuda_argument_t const* tjob_t::ptr_const_argument_by_buffer_id(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::cuda_argument_t const* ptr_arg = nullptr;
+
+        switch( buffer_id )
+        {
+            case st::ARCH_PARTICLES_BUFFER_ID:
+            {
+                ptr_arg = this->ptrCudaParticlesArg();
+                break;
+            }
+
+            case st::ARCH_BEAM_ELEMENTS_BUFFER_ID:
+            {
+                ptr_arg = this->ptrCudaBeamElementsArg();
+                break;
+            }
+
+            case st::ARCH_OUTPUT_BUFFER_ID:
+            {
+                ptr_arg = this->ptrCudaOutputArg();
+                break;
+            }
+
+            case st::ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID:
+            {
+                ptr_arg = this->ptrCudaElemByElemConfigArg();
+                break;
+            }
+
+            case st::ARCH_PARTICLE_ADDR_BUFFER_ID:
+            {
+                ptr_arg = this->ptrCudaParticlesAddrArg();
+                break;
+            }
+
+            default:
+            {
+                ptr_arg = this->ptr_const_stored_buffer_argument( buffer_id );
+            }
+        };
+
+        return ptr_arg;
+    }
+
+    tjob_t::cuda_argument_t* tjob_t::ptr_argument_by_buffer_id(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::cuda_argument_t* >(
+            this->ptr_const_argument_by_buffer_id( buffer_id ) );
+    }
+
+    tjob_t::cuda_argument_t const& tjob_t::argument_by_buffer_id(
+        st_size_t const buffer_id ) const
+    {
+        tjob_t::cuda_argument_t const* ptr_arg =
+            this->ptr_const_argument_by_buffer_id( buffer_id );
+
+        if( ptr_arg == nullptr )
+        {
+            std::ostringstream a2str;
+            a2str << "unable to get buffer argument for buffer_id="
+                  << buffer_id;
+
+            throw std::runtime_error( a2str.str() );
+        }
+
+        return *ptr_arg;
+    }
+
+    tjob_t::cuda_argument_t& tjob_t::argument_by_buffer_id(
+        st_size_t const buffer_id )
+    {
+        return const_cast< tjob_t::cuda_argument_t& >( static_cast<
+            tjob_t const& >( *this ).argument_by_buffer_id( buffer_id ) );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --  */
+
+    tjob_t::cuda_argument_t const* tjob_t::ptr_const_stored_buffer_argument(
+        st_size_t const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::cuda_argument_t const* ptr_arg = nullptr;
+
+        st_size_t const min_buffer_id = this->min_stored_buffer_id();
+        st_size_t const max_buffer_id_plus_one =
+            this->max_stored_buffer_id() + st_size_t{ 1 };
+
+        if( ( min_buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_id >= min_buffer_id ) &&
+            ( buffer_id <  max_buffer_id_plus_one ) )
+        {
+            st_size_t const stored_buffer_id = buffer_id - min_buffer_id;
+
+            if( stored_buffer_id < this->m_stored_buffer_args.size() )
+            {
+                ptr_arg = this->m_stored_buffer_args[ stored_buffer_id ].get();
+            }
+        }
+
+        return ptr_arg;
+    }
+
+    tjob_t::cuda_argument_t* tjob_t::ptr_stored_buffer_argument(
+        st_size_t const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::cuda_argument_t* >(
+            this->ptr_const_stored_buffer_argument( buffer_id ) );
+    }
+
+    tjob_t::cuda_argument_t const& tjob_t::stored_buffer_argument(
+        st_size_t const buffer_id ) const
+    {
+        tjob_t::cuda_argument_t const* ptr_arg =
+            this->ptr_const_stored_buffer_argument( buffer_id );
+
+        if( ptr_arg == nullptr )
+        {
+            std::ostringstream a2str;
+            a2str << "unable to get stored buffer argument for buffer_id="
+                  << buffer_id;
+
+            throw std::runtime_error( a2str.str() );
+        }
+
+        return *ptr_arg;
+    }
+
+    tjob_t::cuda_argument_t& tjob_t::stored_buffer_argument(
+        st_size_t const buffer_id )
+    {
+        return const_cast< tjob_t::cuda_argument_t& >( static_cast<
+            tjob_t const& >( *this ).stored_buffer_argument( buffer_id ) );
+    }
+
     /* ===================================================================== */
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareController(
+    st_status_t tjob_t::doPrepareController(
         char const* SIXTRL_RESTRICT config_str )
     {
         return this->doPrepareControllerCudaImpl( config_str );
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareDefaultKernels(
+    st_status_t tjob_t::doPrepareDefaultKernels(
         char const* SIXTRL_RESTRICT config_str )
     {
         return this->doPrepareDefaultKernelsCudaImpl( config_str );
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareParticlesStructures(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT ptr_pbuffer )
+    st_status_t tjob_t::doPrepareParticlesStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_pbuffer )
     {
-        using _base_t = st::CudaTrackJob::_base_track_job_t;
-        return ( ( _base_t::doPrepareParticlesStructures( ptr_pbuffer ) ) &&
+        return ( ( base_tjob_t::doPrepareParticlesStructures( ptr_pbuffer ) ) &&
                  ( this->doPrepareParticlesStructuresCudaImpl( ptr_pbuffer ) ) );
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareBeamElementsStructures(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems )
+    st_status_t tjob_t::doPrepareBeamElementsStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems )
     {
-        using _base_t = st::CudaTrackJob::_base_track_job_t;
-        return ( ( _base_t::doPrepareBeamElementsStructures( belems ) ) &&
+        return ( ( base_tjob_t::doPrepareBeamElementsStructures( belems ) ) &&
                  ( this->doPrepareBeamElementsStructuresCudaImpl( belems ) ) );
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareOutputStructures(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT pbuffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT output,
-        CudaTrackJob::size_type const until_turn_elem_by_elem )
+    st_status_t tjob_t::doPrepareOutputStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pbuffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output,
+        st_size_t const until_turn_elem_by_elem )
     {
-        using _base_t = st::CudaTrackJob::_base_track_job_t;
-
-        CudaTrackJob::status_t status = _base_t::doPrepareOutputStructures(
+        st_status_t status = base_tjob_t::doPrepareOutputStructures(
                 pbuffer, belems, output, until_turn_elem_by_elem );
 
         if( ( status == st::ARCH_STATUS_SUCCESS ) &&
@@ -598,17 +779,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doAssignOutputBufferToBeamMonitors(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT output,
-        CudaTrackJob::particle_index_t const min_turn_id,
-        CudaTrackJob::size_type const output_buffer_offset_index )
+    st_status_t tjob_t::doAssignOutputBufferToBeamMonitors(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output,
+        tjob_t::particle_index_t const min_turn_id,
+        st_size_t const output_buffer_offset_index )
     {
-        using _base_t = st::CudaTrackJob::_base_track_job_t;
-
-        CudaTrackJob::status_t status =
-            _base_t::doAssignOutputBufferToBeamMonitors( belems, output,
-                min_turn_id, output_buffer_offset_index );
+        st_status_t status = base_tjob_t::doAssignOutputBufferToBeamMonitors(
+            belems, output, min_turn_id, output_buffer_offset_index );
 
         if( ( status == st::ARCH_STATUS_SUCCESS ) && ( this->hasBeamMonitorOutput() ) )
         {
@@ -619,16 +797,13 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doAssignOutputBufferToElemByElemConfig(
-        CudaTrackJob::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_conf,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT output,
-        CudaTrackJob::size_type const output_buffer_offset_index )
+    st_status_t tjob_t::doAssignOutputBufferToElemByElemConfig(
+        tjob_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_conf,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output,
+        st_size_t const output_buffer_offset_index )
     {
-        using _base_t = st::CudaTrackJob::_base_track_job_t;
-
-        CudaTrackJob::status_t status =
-        _base_t::doAssignOutputBufferToElemByElemConfig( elem_by_elem_conf,
-            output, output_buffer_offset_index );
+        st_status_t status = base_tjob_t::doAssignOutputBufferToElemByElemConfig(
+            elem_by_elem_conf, output, output_buffer_offset_index );
 
         if( ( status == st::ARCH_STATUS_SUCCESS ) &&
             ( this->hasElemByElemOutput() ) )
@@ -640,67 +815,118 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-
-    CudaTrackJob::status_t CudaTrackJob::doReset(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT pbuffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT output,
-        CudaTrackJob::size_type const until_turn_elem_by_elem )
+    st_status_t tjob_t::doReset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pbuffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output,
+        st_size_t const until_turn_elem_by_elem )
     {
         return this->doResetCudaImpl(
             pbuffer, belems, output, until_turn_elem_by_elem );
     }
 
+    bool tjob_t::doParseConfigStr(
+        const char *const SIXTRL_RESTRICT config_str )
+    {
+        return ( ( base_tjob_t::doParseConfigStr( config_str ) ) &&
+                 (  st::ARCH_STATUS_SUCCESS ==
+                    this->doParseConfigStrCudaImpl( config_str ) ) );
+    }
+
     /* ----------------------------------------------------------------- */
 
-    CudaTrackJob::status_t
-    CudaTrackJob::doSetAssignOutputToBeamMonitorsKernelId(
-        CudaTrackJob::kernel_id_t const id )
+    st_size_t tjob_t::do_add_stored_buffer(
+        tjob_t::buffer_store_t&& assigned_buffer_handle )
+    {
+        st_size_t buffer_id = tjob_t::_base_track_job_t::do_add_stored_buffer(
+            std::move( assigned_buffer_handle ) );
+
+        if( buffer_id != st::ARCH_ILLEGAL_BUFFER_ID )
+        {
+            if( st::ARCH_STATUS_SUCCESS != this->do_add_stored_buffer_cuda_impl(
+                    buffer_id ) )
+            {
+                this->do_remove_stored_buffer_cuda_impl( buffer_id );
+                buffer_id = st::ARCH_ILLEGAL_BUFFER_ID;
+            }
+        }
+
+        return buffer_id;
+    }
+
+    st_status_t tjob_t::do_remove_stored_buffer( st_size_t const buffer_id )
+    {
+        return tjob_t::_base_track_job_t::do_remove_stored_buffer( buffer_id ) |
+               this->do_remove_stored_buffer_cuda_impl( buffer_id );
+    }
+
+    st_status_t tjob_t::do_push_stored_buffer( st_size_t const buffer_id )
+    {
+        return this->do_push_stored_buffer_cuda_impl( buffer_id );
+    }
+
+    st_status_t tjob_t::do_collect_stored_buffer( st_size_t const buffer_id )
+    {
+        return this->do_collect_stored_buffer_cuda_impl( buffer_id );
+    }
+
+    st_status_t tjob_t::do_perform_address_assignments(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key )
+    {
+        return this->do_perform_address_assignments_cuda_impl( key );
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    st_status_t tjob_t::doSetAssignOutputToBeamMonitorsKernelId(
+        tjob_t::kernel_id_t const id )
     {
         return this->doSetAssignOutputToBeamMonitorsKernelIdCudaImpl( id );
     }
 
-    CudaTrackJob::status_t
-    CudaTrackJob::doSetAssignOutputToElemByElemConfigKernelId(
-        CudaTrackJob::kernel_id_t const id )
+    st_status_t tjob_t::doSetAssignOutputToElemByElemConfigKernelId(
+        tjob_t::kernel_id_t const id )
     {
         return this->doSetAssignOutputToElemByElemConfigKernelIdCudaImpl( id );
     }
 
-    CudaTrackJob::status_t
-    CudaTrackJob::doSetTrackUntilKernelId( CudaTrackJob::kernel_id_t const id )
+    st_status_t tjob_t::doSetTrackUntilKernelId( tjob_t::kernel_id_t const id )
     {
         return this->doSetTrackUntilKernelIdCudaImpl( id );
     }
 
-    CudaTrackJob::status_t
-    CudaTrackJob::doSetTrackLineKernelId( CudaTrackJob::kernel_id_t const id )
+    st_status_t tjob_t::doSetTrackLineKernelId( tjob_t::kernel_id_t const id )
     {
         return this->doSetTrackLineKernelIdCudaImpl( id );
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doSetTrackElemByElemKernelId(
-        CudaTrackJob::kernel_id_t const id )
+    st_status_t tjob_t::doSetTrackElemByElemKernelId(
+        tjob_t::kernel_id_t const id )
     {
         return this->doSetTrackElemByElemKernelIdCudaImpl( id );
     }
 
-    CudaTrackJob::status_t
-    CudaTrackJob::doSetFetchParticlesAddressesKernelId(
-        CudaTrackJob::kernel_id_t const id )
+    st_status_t tjob_t::doSetFetchParticlesAddressesKernelId(
+        tjob_t::kernel_id_t const id )
     {
         return this->doSetFetchParticlesAddressesKernelIdCudaImpl( id );
     }
 
+    st_status_t tjob_t::do_set_assign_addresses_kernel_id(
+        tjob_t::kernel_id_t const id )
+    {
+        return this->do_set_assign_addresses_kernel_id_cuda_impl( id );
+    }
+
     /* --------------------------------------------------------------------- */
 
-    CudaTrackJob::cuda_argument_t const& CudaTrackJob::doGetRefCudaArgument(
-        CudaTrackJob::argument_base_t const* ptr_base_arg,
+    tjob_t::cuda_argument_t const& tjob_t::doGetRefCudaArgument(
+        tjob_t::argument_base_t const* ptr_base_arg,
         char const* SIXTRL_RESTRICT arg_name,
-        bool const requires_exact_match ) const
+        bool const SIXTRL_UNUSED( requires_exact_match ) ) const
     {
-        using arg_t  = CudaTrackJob::cuda_argument_t;
-        using size_t = CudaTrackJob::size_type;
+        using arg_t  = tjob_t::cuda_argument_t;
+        using size_t = st_size_t;
 
         arg_t const* cuda_arg = ( ptr_base_arg != nullptr )
             ? ptr_base_arg->asDerivedArgument< arg_t >( this->archId() )
@@ -729,50 +955,48 @@ namespace SIXTRL_CXX_NAMESPACE
         return *cuda_arg;
     }
 
-    CudaTrackJob::cuda_argument_t& CudaTrackJob::doGetRefCudaArgument(
-        CudaTrackJob::argument_base_t const* ptr_base_arg,
+    tjob_t::cuda_argument_t& tjob_t::doGetRefCudaArgument(
+        tjob_t::argument_base_t const* ptr_base_arg,
         char const* SIXTRL_RESTRICT arg_name,
         bool const requires_exact_match )
     {
-        return const_cast< CudaTrackJob::cuda_argument_t& >( static_cast<
-            CudaTrackJob const& >( *this ).doGetRefCudaArgument( ptr_base_arg,
+        return const_cast< tjob_t::cuda_argument_t& >( static_cast<
+            tjob_t const& >( *this ).doGetRefCudaArgument( ptr_base_arg,
                 arg_name, requires_exact_match ) );
     }
 
-    CudaTrackJob::cuda_argument_t const* CudaTrackJob::doGetPtrCudaArgument(
-        CudaTrackJob::argument_base_t const* ptr_base_arg,
+    tjob_t::cuda_argument_t const* tjob_t::doGetPtrCudaArgument(
+        tjob_t::argument_base_t const* ptr_base_arg,
         bool const requires_exact_match ) const SIXTRL_NOEXCEPT
     {
-        using arg_t = CudaTrackJob::cuda_argument_t;
+        using arg_t = tjob_t::cuda_argument_t;
 
         return ( ptr_base_arg != nullptr )
             ? ptr_base_arg->asDerivedArgument< arg_t >(
                 this->archId(), requires_exact_match ) : nullptr;
     }
 
-    CudaTrackJob::cuda_argument_t* CudaTrackJob::doGetPtrCudaArgument(
-        CudaTrackJob::argument_base_t* ptr_base_arg,
+    tjob_t::cuda_argument_t* tjob_t::doGetPtrCudaArgument(
+        tjob_t::argument_base_t* ptr_base_arg,
         bool const requires_exact_match ) SIXTRL_NOEXCEPT
     {
-        return const_cast< CudaTrackJob::cuda_argument_t* >( static_cast<
-            CudaTrackJob const& >( *this ).doGetPtrCudaArgument(
+        return const_cast< tjob_t::cuda_argument_t* >( static_cast<
+            tjob_t const& >( *this ).doGetPtrCudaArgument(
                 ptr_base_arg, requires_exact_match ) );
     }
 
     /* ===================================================================== */
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareControllerCudaImpl(
+    st_status_t tjob_t::doPrepareControllerCudaImpl(
         char const* SIXTRL_RESTRICT config_str )
     {
-        CudaTrackJob::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        using cuda_ctrl_t       = tjob_t::cuda_controller_t;
+        using cuda_ctrl_store_t = tjob_t::cuda_ctrl_store_t;
 
-        using _this_t           = st::CudaTrackJob;
-        using cuda_ctrl_t       = _this_t::cuda_controller_t;
-        using cuda_ctrl_store_t = _this_t::cuda_ctrl_store_t;
-
-        using cuda_arg_t        = _this_t::cuda_argument_t;
-        using cuda_arg_store_t  = _this_t::cuda_arg_store_t;
-        using debug_register_t  = _this_t::debug_register_t;
+        using cuda_arg_t        = tjob_t::cuda_argument_t;
+        using cuda_arg_store_t  = tjob_t::cuda_arg_store_t;
+        using debug_register_t  = tjob_t::debug_register_t;
 
         SIXTRL_ASSERT( this->ptrControllerBase() == nullptr );
 
@@ -801,20 +1025,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareDefaultKernelsCudaImpl(
-        char const* SIXTRL_RESTRICT config_str )
+    st_status_t tjob_t::doPrepareDefaultKernelsCudaImpl(
+        char const* SIXTRL_RESTRICT SIXTRL_UNUSED( config_str ) )
     {
-        using _this_t = st::CudaTrackJob;
-        using _base_t = _this_t::_base_track_job_t;
-        using size_t  = _this_t::size_type;
-        using cuda_ctrl_t = _this_t::cuda_controller_t;
-        using cuda_kernel_config_t = _this_t::cuda_kernel_config_t;
-        using kernel_id_t = _this_t::kernel_id_t;
-        using cuda_node_info_t = _this_t::cuda_node_info_t;
-        using node_index_t = _this_t::node_index_t;
-
-        CudaTrackJob::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        using tjob_t = st::CudaTrackJob;
+        using size_t  = st_size_t;
+        using cuda_ctrl_t = tjob_t::cuda_controller_t;
+        using kernel_id_t = tjob_t::kernel_id_t;
+        using cuda_node_info_t = tjob_t::cuda_node_info_t;
+        using node_index_t = tjob_t::node_index_t;
 
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
 
         if( ( ptr_cuda_ctrl != nullptr ) &&
@@ -833,8 +1054,6 @@ namespace SIXTRL_CXX_NAMESPACE
             std::string kernel_name( 256, '\0' );
             std::string const kernel_prefix( SIXTRL_C99_NAMESPACE_PREFIX_STR );
 
-            bool const use_debug = this->isInDebugMode();
-
             size_t num_kernel_args = size_t{ 0 };
             kernel_id_t kernel_id = cuda_controller_t::ILLEGAL_KERNEL_ID;
 
@@ -853,7 +1072,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             /* trackElemByElemKernelId() */
 
-            num_kernel_args = size_t{ 6 };
+            num_kernel_args = size_t{ 7 };
             kernel_name.clear();
             kernel_name += kernel_prefix;
             kernel_name +=
@@ -894,7 +1113,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             /* assignOutputToElemByElemConfigKernelId() */
 
-            num_kernel_args = size_t{ 4 };
+            num_kernel_args = size_t{ 5 };
             kernel_name.clear();
             kernel_name += kernel_prefix;
             kernel_name +=
@@ -923,6 +1142,18 @@ namespace SIXTRL_CXX_NAMESPACE
             {
                 status = st::ARCH_STATUS_SUCCESS;
             }
+
+            /* assign_addresses_kernel_id() */
+
+            size_t nargs = size_t{ 8 };
+            kernel_name.clear();
+            kernel_name += kernel_prefix;
+            kernel_name += "AssignAddressItem_process_managed_buffer_cuda_wrapper";
+            kernel_id = ptr_cuda_ctrl->addCudaKernelConfig( kernel_name, nargs );
+
+            success &= ( this->do_set_assign_addresses_kernel_id(
+                    kernel_id ) == st::ARCH_STATUS_SUCCESS );
+            if( success ) status = st::ARCH_STATUS_SUCCESS;
         }
         else if( ( ptr_cuda_ctrl != nullptr ) &&
             ( ptr_cuda_ctrl->numAvailableNodes() > node_index_t{ 0 } ) )
@@ -933,17 +1164,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareParticlesStructuresCudaImpl(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT particles_buffer )
+    st_status_t tjob_t::doPrepareParticlesStructuresCudaImpl(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer )
     {
-        using _this_t = st::CudaTrackJob;
-
-        using cuda_ctrl_t      = _this_t::cuda_controller_t;
-        using cuda_arg_t       = _this_t::cuda_argument_t;
-        using store_base_arg_t = _this_t::stored_arg_base_t;
-
-        CudaTrackJob::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        using cuda_ctrl_t      = tjob_t::cuda_controller_t;
+        using cuda_arg_t       = tjob_t::cuda_argument_t;
+        using store_base_arg_t = tjob_t::stored_arg_base_t;
 
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
 
         if( ( ptr_cuda_ctrl != nullptr ) && ( particles_buffer != nullptr ) )
@@ -1015,16 +1243,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareBeamElementsStructuresCudaImpl(
-         CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems_buffer )
+    st_status_t tjob_t::doPrepareBeamElementsStructuresCudaImpl(
+         tjob_t::c_buffer_t* SIXTRL_RESTRICT belems_buffer )
     {
-        using _this_t          = st::CudaTrackJob;
-        using cuda_ctrl_t      = _this_t::cuda_controller_t;
-        using cuda_arg_t       = _this_t::cuda_argument_t;
-        using store_base_arg_t = _this_t::stored_arg_base_t;
-
-        CudaTrackJob::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        using cuda_ctrl_t      = tjob_t::cuda_controller_t;
+        using cuda_arg_t       = tjob_t::cuda_argument_t;
+        using store_base_arg_t = tjob_t::stored_arg_base_t;
 
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
 
         if( ( ptr_cuda_ctrl != nullptr ) && ( belems_buffer != nullptr ) )
@@ -1054,21 +1280,19 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doPrepareOutputStructuresCudaImpl(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        CudaTrackJob::size_type const )
+    st_status_t tjob_t::doPrepareOutputStructuresCudaImpl(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        st_size_t const )
     {
-        using _this_t          = st::CudaTrackJob;
-        using cuda_ctrl_t      = _this_t::cuda_controller_t;
-        using cuda_arg_t       = _this_t::cuda_argument_t;
-        using store_base_arg_t = _this_t::stored_arg_base_t;
-        using elem_config_t    = _this_t::elem_by_elem_config_t;
-        using ctrl_status_t    = _this_t::status_t;
-
-        CudaTrackJob::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        using cuda_ctrl_t      = tjob_t::cuda_controller_t;
+        using cuda_arg_t       = tjob_t::cuda_argument_t;
+        using store_base_arg_t = tjob_t::stored_arg_base_t;
+//         using elem_config_t    = tjob_t::elem_by_elem_config_t;
+//         using ctrl_status_t    = st_status_t;
 
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
 
         if( ( ptr_cuda_ctrl != nullptr ) && ( output_buffer != nullptr ) &&
@@ -1083,8 +1307,7 @@ namespace SIXTRL_CXX_NAMESPACE
             else
             {
                 cuda_elem_by_elem_conf_arg.reset( new cuda_arg_t(
-                    this->ptrElemByElemConfig(), sizeof( elem_config_t ),
-                        ptr_cuda_ctrl ) );
+                    this->elem_by_elem_config_cxx_buffer(), ptr_cuda_ctrl ) );
 
                 status = ( ( cuda_elem_by_elem_conf_arg.get() != nullptr ) &&
                     ( cuda_elem_by_elem_conf_arg->ptrControllerBase() ==
@@ -1101,30 +1324,32 @@ namespace SIXTRL_CXX_NAMESPACE
                         ( this->ptrElemByElemConfigArgBase(
                             )->ptrControllerBase() == ptr_cuda_ctrl ) )
                     {
-                        status == st::ARCH_STATUS_SUCCESS;
+                        status = st::ARCH_STATUS_SUCCESS;
                     }
                     else
                     {
-                        status == st::ARCH_STATUS_GENERAL_FAILURE;
+                        status = st::ARCH_STATUS_GENERAL_FAILURE;
                     }
                 }
 
                 if( status == st::ARCH_STATUS_SUCCESS )
                 {
                     status = this->ptrElemByElemConfigArgBase()->send(
-                        this->ptrElemByElemConfig(), sizeof( elem_config_t ) );
+                        this->elem_by_elem_config_cxx_buffer() );
 
                     if( status == st::ARCH_STATUS_SUCCESS )
                     {
-                        if( ( this->ptrElemByElemConfigArgBase()->usesRawArgument() ) &&
-                            ( this->ptrElemByElemConfigArgBase()->ptrRawArgument()
-                              == this->ptrElemByElemConfig() ) )
+                        if( ( this->ptrElemByElemConfigArgBase(
+                            )->usesCObjectsCxxBuffer() ) &&
+                            ( this->ptrElemByElemConfigArgBase(
+                                )->ptrCObjectsCxxBuffer() == std::addressof(
+                                this->elem_by_elem_config_cxx_buffer() ) ) )
                         {
-                            status == st::ARCH_STATUS_SUCCESS;
+                            status = st::ARCH_STATUS_SUCCESS;
                         }
                         else
                         {
-                            status == st::ARCH_STATUS_GENERAL_FAILURE;
+                            status = st::ARCH_STATUS_GENERAL_FAILURE;
                         }
                     }
                 }
@@ -1172,20 +1397,19 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doAssignOutputBufferToBeamMonitorsCudaImpl(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        CudaTrackJob::particle_index_t const min_turn_id,
-        CudaTrackJob::size_type const output_buffer_offset_index )
+    st_status_t tjob_t::doAssignOutputBufferToBeamMonitorsCudaImpl(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        tjob_t::particle_index_t const min_turn_id,
+        st_size_t const output_buffer_offset_index )
     {
-        using _this_t            = st::CudaTrackJob;
-        using cuda_ctrl_t        = _this_t::cuda_controller_t;
-        using cuda_arg_t         = _this_t::cuda_argument_t;
-        using cuda_kernel_conf_t = _this_t::cuda_kernel_config_t;
-        using kernel_id_t        = _this_t::kernel_id_t;
-        using ctrl_status_t      = _this_t::status_t;
-        using size_t             = _this_t::size_type;
-        using particle_index_t   = _this_t::particle_index_t;
+        using cuda_ctrl_t        = tjob_t::cuda_controller_t;
+        using cuda_arg_t         = tjob_t::cuda_argument_t;
+        using cuda_kernel_conf_t = tjob_t::cuda_kernel_config_t;
+        using kernel_id_t        = tjob_t::kernel_id_t;
+        using ctrl_status_t      = st_status_t;
+//         using size_t             = st_size_t;
+        using particle_index_t   = tjob_t::particle_index_t;
 
         ctrl_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
@@ -1223,7 +1447,6 @@ namespace SIXTRL_CXX_NAMESPACE
         if( ( controller_ready ) && ( output_ready ) &&
             ( belems_ready ) && ( kernel_conf != nullptr ) )
         {
-            size_t const offset = this->beamMonitorsOutputBufferOffset();
             particle_index_t const min_turn_id = this->minInitialTurnId();
 
             if( !this->isInDebugMode() )
@@ -1252,18 +1475,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doAssignOutputBufferToElemByElemConfigCudaImpl(
-        CudaTrackJob::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_config,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        CudaTrackJob::size_type const output_buffer_offset_index )
+    st_status_t tjob_t::doAssignOutputBufferToElemByElemConfigCudaImpl(
+        tjob_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_config,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        st_size_t const output_buffer_offset_index )
     {
-        using _this_t            = st::CudaTrackJob;
-        using cuda_ctrl_t        = _this_t::cuda_controller_t;
-        using cuda_arg_t         = _this_t::cuda_argument_t;
-        using cuda_kernel_conf_t = _this_t::cuda_kernel_config_t;
-        using kernel_id_t        = _this_t::kernel_id_t;
-        using ctrl_status_t      = _this_t::status_t;
-        using size_t             = _this_t::size_type;
+        using tjob_t            = st::CudaTrackJob;
+        using cuda_ctrl_t        = tjob_t::cuda_controller_t;
+        using cuda_arg_t         = tjob_t::cuda_argument_t;
+        using cuda_kernel_conf_t = tjob_t::cuda_kernel_config_t;
+        using kernel_id_t        = tjob_t::kernel_id_t;
+        using ctrl_status_t      = st_status_t;
 
         ctrl_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
@@ -1293,9 +1515,9 @@ namespace SIXTRL_CXX_NAMESPACE
             ( elem_by_elem_conf_arg != nullptr ) &&
             ( elem_by_elem_config != nullptr ) &&
             ( elem_by_elem_conf_arg->ptrControllerBase() == ptr_cuda_ctrl ) &&
-            ( elem_by_elem_conf_arg->usesRawArgument() ) &&
-            ( elem_by_elem_conf_arg->ptrRawArgument() ==
-                elem_by_elem_config ) );
+            ( elem_by_elem_conf_arg->usesCObjectsCxxBuffer() ) &&
+            ( elem_by_elem_conf_arg->ptrCObjectsCxxBuffer() ==
+                std::addressof( this->elem_by_elem_config_cxx_buffer() ) ) );
 
         cuda_kernel_conf_t const* kernel_conf = ( controller_ready )
             ? ptr_cuda_ctrl->ptrKernelConfig( kid ) : nullptr;
@@ -1306,8 +1528,9 @@ namespace SIXTRL_CXX_NAMESPACE
             if( !this->isInDebugMode() )
             {
                 ::NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
-                    kernel_conf, elem_by_elem_conf_arg, output_arg,
-                        output_buffer_offset_index, nullptr );
+                    kernel_conf, elem_by_elem_conf_arg,
+                        this->elem_by_elem_config_index(), output_arg,
+                            output_buffer_offset_index, nullptr );
 
                 status = st::ARCH_STATUS_SUCCESS;
             }
@@ -1317,9 +1540,10 @@ namespace SIXTRL_CXX_NAMESPACE
                     st::ARCH_STATUS_SUCCESS )
                 {
                     ::NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
-                        kernel_conf, elem_by_elem_conf_arg, output_arg,
-                        output_buffer_offset_index,
-                        this->ptrCudaDebugRegisterArg() );
+                        kernel_conf, elem_by_elem_conf_arg,
+                            this->elem_by_elem_config_index(), output_arg,
+                                output_buffer_offset_index,
+                                    this->ptrCudaDebugRegisterArg() );
 
                     status = this->evaluateDebugRegisterAfterUse();
                 }
@@ -1331,19 +1555,15 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    CudaTrackJob::status_t CudaTrackJob::doFetchParticleAddresses()
+    st_status_t tjob_t::doFetchParticleAddresses()
     {
-        using _this_t            = st::CudaTrackJob;
-        using cuda_ctrl_t        = _this_t::cuda_controller_t;
-        using cuda_arg_t         = _this_t::cuda_argument_t;
-        using cuda_kernel_conf_t = _this_t::cuda_kernel_config_t;
-        using kernel_id_t        = _this_t::kernel_id_t;
-        using ctrl_status_t      = _this_t::status_t;
-        using size_t             = _this_t::size_type;
-        using particle_index_t   = _this_t::particle_index_t;
-        using debug_register_t     = _this_t::debug_register_t;
-        using buffer_t           = _this_t::buffer_t;
-        using c_buffer_t         = _this_t::c_buffer_t;
+        using tjob_t            = st::CudaTrackJob;
+        using cuda_ctrl_t        = tjob_t::cuda_controller_t;
+        using cuda_arg_t         = tjob_t::cuda_argument_t;
+        using cuda_kernel_conf_t = tjob_t::cuda_kernel_config_t;
+        using kernel_id_t        = tjob_t::kernel_id_t;
+        using buffer_t           = tjob_t::buffer_t;
+        using c_buffer_t         = tjob_t::c_buffer_t;
 
         status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
@@ -1380,7 +1600,7 @@ namespace SIXTRL_CXX_NAMESPACE
         cuda_kernel_conf_t const* kernel_conf = ( controller_ready )
             ? ptr_ctrl->ptrKernelConfig( kid ) : nullptr;
 
-        cuda_arg_t* debug_flag_arg = nullptr;
+        //cuda_arg_t* debug_flag_arg = nullptr;
 
         if( ( controller_ready ) && ( particles_ready ) &&
             ( particles_addr_ready ) && ( kernel_conf != nullptr ) )
@@ -1409,22 +1629,21 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::track_status_t CudaTrackJob::doTrackUntilTurn(
-        CudaTrackJob::size_type const until_turn )
+    st_track_status_t tjob_t::doTrackUntilTurn(
+        st_size_t const until_turn )
     {
         return st::trackUntilTurn( *this, until_turn );
     }
 
-    CudaTrackJob::track_status_t CudaTrackJob::doTrackElemByElem(
-        CudaTrackJob::size_type const until_turn_elem_by_elem )
+    st_track_status_t tjob_t::doTrackElemByElem(
+        st_size_t const until_turn_elem_by_elem )
     {
         return st::trackElemByElemUntilTurn( *this, until_turn_elem_by_elem );
     }
 
-    CudaTrackJob::track_status_t CudaTrackJob::doTrackLine(
-            CudaTrackJob::size_type const be_begin_index,
-            CudaTrackJob::size_type const be_end_index,
-            bool const finish_turn )
+    st_track_status_t tjob_t::doTrackLine(
+            st_size_t const be_begin_index,
+            st_size_t const be_end_index, bool const finish_turn )
     {
         return st::trackLine(
             *this, be_begin_index, be_end_index, finish_turn );
@@ -1432,27 +1651,24 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    CudaTrackJob::status_t CudaTrackJob::doResetCudaImpl(
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT pbuffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
-        CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        CudaTrackJob::size_type const until_turn_elem_by_elem )
+    st_status_t tjob_t::doResetCudaImpl(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pbuffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        using _this_t = st::CudaTrackJob;
-        using _base_t = _this_t::_base_track_job_t;
-        using output_buffer_flag_t = _this_t::output_buffer_flag_t;
+        using output_buffer_flag_t = tjob_t::output_buffer_flag_t;
 
-        CudaTrackJob::status_t status =
-            _base_t::doPrepareParticlesStructures( pbuffer );
+        st_status_t status = base_tjob_t::doPrepareParticlesStructures( pbuffer );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
-            status = _base_t::doPrepareBeamElementsStructures( belem_buffer );
+            status = this->doPrepareParticlesStructuresCudaImpl( pbuffer );
         }
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
-            status = this->doPrepareParticlesStructuresCudaImpl( pbuffer );
+            status = base_tjob_t::doPrepareBeamElementsStructures( belem_buffer );
         }
 
         if( status == st::ARCH_STATUS_SUCCESS )
@@ -1482,7 +1698,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
         if( ( requires_output_buffer ) || ( ptr_output_buffer != nullptr ) )
         {
-            status = _base_t::doPrepareOutputStructures( pbuffer,
+            status = base_tjob_t::doPrepareOutputStructures( pbuffer,
                 belem_buffer, ptr_output_buffer, until_turn_elem_by_elem );
 
             if( ( status == st::ARCH_STATUS_SUCCESS ) &&
@@ -1503,7 +1719,7 @@ namespace SIXTRL_CXX_NAMESPACE
         {
             if( ::NS(OutputBuffer_requires_elem_by_elem_output)( out_buffer_flags ) )
             {
-                status = _base_t::doAssignOutputBufferToElemByElemConfig(
+                status = base_tjob_t::doAssignOutputBufferToElemByElemConfig(
                     this->ptrElemByElemConfig(), this->ptrCOutputBuffer(),
                         this->elemByElemOutputBufferOffset() );
 
@@ -1520,7 +1736,7 @@ namespace SIXTRL_CXX_NAMESPACE
             {
                 if( status == st::ARCH_STATUS_SUCCESS )
                 {
-                    status = _base_t::doAssignOutputBufferToBeamMonitors(
+                    status = base_tjob_t::doAssignOutputBufferToBeamMonitors(
                     belem_buffer, this->ptrCOutputBuffer(),
                     this->minInitialTurnId(),
                     this->beamMonitorsOutputBufferOffset() );
@@ -1547,32 +1763,102 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
+    st_status_t tjob_t::doParseConfigStrCudaImpl(
+        const char *const SIXTRL_RESTRICT config_str )
+    {
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+
+        if( ( config_str != nullptr ) &&
+            ( std::strlen( config_str ) > st_size_t{ 0 } ) )
+        {
+            status = st::ARCH_STATUS_SUCCESS;
+
+            std::stringstream a2str;
+            a2str << config_str;
+
+            bool has_cuda_table = false;
+            toml::value data;
+
+            try
+            {
+                data = toml::parse( a2str );
+            }
+            catch( toml::exception& exp )
+            {
+                status = st::ARCH_STATUS_GENERAL_FAILURE;
+            }
+
+            if( status != st::ARCH_STATUS_SUCCESS ) return status;
+
+            try
+            {
+                auto const& cuda = toml::find( data, "cuda" );
+
+                this->m_default_threads_per_block = toml::find_or(
+                    cuda, "threads_per_block",
+                        tjob_t::DEFAULT_THREADS_PER_BLOCK );
+
+                this->m_track_threads_per_block = toml::find_or(
+                    cuda, "track_threads_per_block",
+                        this->m_default_threads_per_block );
+
+                if( ( this->m_default_threads_per_block ==
+                        st_size_t{ 0 } ) ||
+                    ( ( this->m_default_threads_per_block %
+                        tjob_t::cuda_kernel_config_t::DEFAULT_WARP_SIZE ) !=
+                        st_size_t{ 0 } ) )
+                {
+                    this->m_default_threads_per_block =
+                        tjob_t::DEFAULT_THREADS_PER_BLOCK;
+                }
+
+                if( ( this->m_track_threads_per_block ==
+                        st_size_t{ 0 } ) ||
+                    ( ( this->m_track_threads_per_block %
+                        tjob_t::cuda_kernel_config_t::DEFAULT_WARP_SIZE ) !=
+                        st_size_t{ 0 } ) )
+                {
+                    this->m_track_threads_per_block =
+                        tjob_t::DEFAULT_TRACK_THREADS_PER_BLOCK;
+                }
+            }
+            catch( toml::exception& exp )
+            {
+                status = st::ARCH_STATUS_GENERAL_FAILURE;
+            }
+        }
+
+        return status;
+    }
+
     /* --------------------------------------------------------------------- */
 
-    CudaTrackJob::status_t
-    CudaTrackJob::doSetAssignOutputToBeamMonitorsKernelIdCudaImpl(
-        CudaTrackJob::kernel_id_t const kernel_id ) SIXTRL_HOST_FN
+    st_status_t tjob_t::doSetAssignOutputToBeamMonitorsKernelIdCudaImpl(
+        tjob_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
-        using _base_t         = CudaTrackJob::_base_track_job_t;
-        using cuda_ctrl_t     = CudaTrackJob::cuda_controller_t;
-        using kernel_config_t = CudaTrackJob::cuda_kernel_config_t;
-        using size_t          = CudaTrackJob::size_type;
-        using status_t        = CudaTrackJob::status_t;
+        using cuda_ctrl_t     = tjob_t::cuda_controller_t;
+        using kernel_config_t = tjob_t::cuda_kernel_config_t;
+        using size_t          = st_size_t;
+        using status_t        = st_status_t;
         using node_index_t    = cuda_ctrl_t::node_index_t;
         using node_info_t     = cuda_ctrl_t::node_info_t;
 
-        cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
+        tjob_t::cuda_controller_t* ptr_cuda_ctrl = this->ptrCudaController();
 
         node_index_t const selected_node_index = ( ptr_cuda_ctrl != nullptr )
             ? ptr_cuda_ctrl->selectedNodeIndex()
-            : cuda_ctrl_t::UNDEFINED_INDEX;
+            : tjob_t::cuda_controller_t::UNDEFINED_INDEX;
 
         node_info_t const* node_info = ( ptr_cuda_ctrl != nullptr )
             ? ptr_cuda_ctrl->ptrNodeInfo( selected_node_index ) : nullptr;
 
-        kernel_config_t* kernel_conf = ( ptr_cuda_ctrl != nullptr )
+        tjob_t::cuda_kernel_config_t* kernel_conf = ( ptr_cuda_ctrl != nullptr )
             ? ptr_cuda_ctrl->ptrKernelConfig( kernel_id ) : nullptr;
 
+        SIXTRL_ASSERT( this->m_default_threads_per_block > size_t{ 0 } );
+        SIXTRL_ASSERT( ( this->m_default_threads_per_block %
+                         kernel_config_t::DEFAULT_WARP_SIZE ) == size_t{ 0 } );
+
         size_t num_beam_monitors = size_t{ 0 };
 
         if( this->hasBeamMonitorOutput() )
@@ -1584,31 +1870,28 @@ namespace SIXTRL_CXX_NAMESPACE
             num_beam_monitors = size_t{ 1 };
         }
 
-        status_t status =
+        st_status_t status =
         ::NS(CudaKernelConfig_configure_assign_output_to_beam_monitors_kernel)(
-            kernel_conf, node_info, num_beam_monitors );
+            kernel_conf, node_info, num_beam_monitors,
+                this->m_default_threads_per_block );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
-            status = _base_t::doSetAssignOutputToBeamMonitorsKernelId(
+            status = base_tjob_t::doSetAssignOutputToBeamMonitorsKernelId(
                 kernel_id );
         }
 
         return status;
     }
 
-    CudaTrackJob::status_t
-    CudaTrackJob::doSetAssignOutputToElemByElemConfigKernelIdCudaImpl(
-        CudaTrackJob::kernel_id_t const kernel_id ) SIXTRL_HOST_FN
+    st_status_t tjob_t::doSetAssignOutputToElemByElemConfigKernelIdCudaImpl(
+        tjob_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
-        using _base_t         = CudaTrackJob::_base_track_job_t;
-        using cuda_ctrl_t     = CudaTrackJob::cuda_controller_t;
-        using kernel_config_t = CudaTrackJob::cuda_kernel_config_t;
-        using status_t        = CudaTrackJob::status_t;
+        using cuda_ctrl_t     = tjob_t::cuda_controller_t;
+        using kernel_config_t = tjob_t::cuda_kernel_config_t;
         using node_index_t    = cuda_ctrl_t::node_index_t;
         using node_info_t     = cuda_ctrl_t::node_info_t;
 
-        status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
 
         node_index_t const selected_node_index = ( ptr_cuda_ctrl != nullptr )
@@ -1621,26 +1904,28 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_config_t* kernel_conf = ( ptr_cuda_ctrl != nullptr )
             ? ptr_cuda_ctrl->ptrKernelConfig( kernel_id ) : nullptr;
 
-        return
+        SIXTRL_ASSERT( this->m_default_threads_per_block > size_t{ 0 } );
+        SIXTRL_ASSERT( ( this->m_default_threads_per_block %
+            kernel_config_t::DEFAULT_WARP_SIZE ) == size_t{ 0 } );
+
+        st_status_t status =
         ::NS(CudaKernelConfig_configure_assign_output_to_elem_by_elem_config_kernel)(
-            kernel_conf, node_info );
+            kernel_conf, node_info, this->m_default_threads_per_block );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
             status =
-            _base_t::doSetAssignOutputToElemByElemConfigKernelId( kernel_id );
+            base_tjob_t::doSetAssignOutputToElemByElemConfigKernelId( kernel_id );
         }
 
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doSetTrackUntilKernelIdCudaImpl(
-        CudaTrackJob::kernel_id_t const kernel_id ) SIXTRL_HOST_FN
+    st_status_t tjob_t::doSetTrackUntilKernelIdCudaImpl(
+        tjob_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
-        using _base_t         = CudaTrackJob::_base_track_job_t;
-        using cuda_ctrl_t     = CudaTrackJob::cuda_controller_t;
-        using kernel_config_t = CudaTrackJob::cuda_kernel_config_t;
-        using status_t        = CudaTrackJob::status_t;
+        using cuda_ctrl_t     = tjob_t::cuda_controller_t;
+        using kernel_config_t = tjob_t::cuda_kernel_config_t;
         using node_index_t    = cuda_ctrl_t::node_index_t;
         using node_info_t     = cuda_ctrl_t::node_info_t;
 
@@ -1656,25 +1941,28 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_config_t* kernel_conf = ( ptr_cuda_ctrl != nullptr )
             ? ptr_cuda_ctrl->ptrKernelConfig( kernel_id ) : nullptr;
 
-        status_t status =
+        SIXTRL_ASSERT( this->m_track_threads_per_block > st_size_t{ 0 } );
+        SIXTRL_ASSERT( st_size_t{ 0 } == this->m_track_threads_per_block %
+                         kernel_config_t::DEFAULT_WARP_SIZE );
+
+        st_status_t status =
         ::NS(CudaKernelConfig_configure_track_until_turn_kernel)(
-            kernel_conf, node_info, this->totalNumParticlesInParticleSets() );
+            kernel_conf, node_info, this->totalNumParticlesInParticleSets(),
+                this->m_track_threads_per_block );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
-            status = _base_t::doSetTrackUntilKernelId( kernel_id );
+            status = base_tjob_t::doSetTrackUntilKernelId( kernel_id );
         }
 
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doSetTrackLineKernelIdCudaImpl(
-        CudaTrackJob::kernel_id_t const kernel_id ) SIXTRL_HOST_FN
+    st_status_t tjob_t::doSetTrackLineKernelIdCudaImpl(
+        tjob_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
-        using _base_t         = CudaTrackJob::_base_track_job_t;
-        using cuda_ctrl_t     = CudaTrackJob::cuda_controller_t;
-        using kernel_config_t = CudaTrackJob::cuda_kernel_config_t;
-        using status_t        = CudaTrackJob::status_t;
+        using cuda_ctrl_t     = tjob_t::cuda_controller_t;
+        using kernel_config_t = tjob_t::cuda_kernel_config_t;
         using node_index_t    = cuda_ctrl_t::node_index_t;
         using node_info_t     = cuda_ctrl_t::node_info_t;
 
@@ -1690,25 +1978,27 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_config_t* kernel_conf = ( ptr_cuda_ctrl != nullptr )
             ? ptr_cuda_ctrl->ptrKernelConfig( kernel_id ) : nullptr;
 
-        status_t status =
-        ::NS(CudaKernelConfig_configure_track_line_kernel)(
-            kernel_conf, node_info, this->totalNumParticlesInParticleSets() );
+        SIXTRL_ASSERT( this->m_track_threads_per_block > st_size_t{ 0 } );
+        SIXTRL_ASSERT( st_size_t{ 0 } == this->m_track_threads_per_block %
+                         kernel_config_t::DEFAULT_WARP_SIZE );
+
+        st_status_t status = ::NS(CudaKernelConfig_configure_track_line_kernel)(
+            kernel_conf, node_info, this->totalNumParticlesInParticleSets(),
+                this->m_track_threads_per_block );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
-            status = _base_t::doSetTrackLineKernelId( kernel_id );
+            status = base_tjob_t::doSetTrackLineKernelId( kernel_id );
         }
 
         return status;
     }
 
-    CudaTrackJob::status_t CudaTrackJob::doSetTrackElemByElemKernelIdCudaImpl(
-        CudaTrackJob::kernel_id_t const kernel_id ) SIXTRL_HOST_FN
+    st_status_t tjob_t::doSetTrackElemByElemKernelIdCudaImpl(
+        tjob_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
-        using _base_t         = CudaTrackJob::_base_track_job_t;
-        using cuda_ctrl_t     = CudaTrackJob::cuda_controller_t;
-        using kernel_config_t = CudaTrackJob::cuda_kernel_config_t;
-        using status_t        = CudaTrackJob::status_t;
+        using cuda_ctrl_t     = tjob_t::cuda_controller_t;
+        using kernel_config_t = tjob_t::cuda_kernel_config_t;
         using node_index_t    = cuda_ctrl_t::node_index_t;
         using node_info_t     = cuda_ctrl_t::node_info_t;
 
@@ -1724,27 +2014,28 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_config_t* kernel_conf = ( ptr_cuda_ctrl != nullptr )
             ? ptr_cuda_ctrl->ptrKernelConfig( kernel_id ) : nullptr;
 
-        status_t status =
+        SIXTRL_ASSERT( this->m_track_threads_per_block > st_size_t{ 0 } );
+        SIXTRL_ASSERT( st_size_t{ 0 } == this->m_track_threads_per_block %
+                       kernel_config_t::DEFAULT_WARP_SIZE );
+
+        st_status_t status =
         ::NS(CudaKernelConfig_configure_track_elem_by_elem_until_turn_kernel)(
-            kernel_conf, node_info, this->totalNumParticlesInParticleSets() );
+            kernel_conf, node_info, this->totalNumParticlesInParticleSets(),
+                this->m_track_threads_per_block );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
-            status = _base_t::doSetTrackElemByElemKernelId( kernel_id );
+            status = base_tjob_t::doSetTrackElemByElemKernelId( kernel_id );
         }
 
         return status;
     }
 
-    CudaTrackJob::status_t
-    CudaTrackJob::doSetFetchParticlesAddressesKernelIdCudaImpl(
-            CudaTrackJob::kernel_id_t const kernel_id ) SIXTRL_HOST_FN
+    st_status_t tjob_t::doSetFetchParticlesAddressesKernelIdCudaImpl(
+            tjob_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
-        using _base_t         = CudaTrackJob::_base_track_job_t;
-        using cuda_ctrl_t     = CudaTrackJob::cuda_controller_t;
-        using kernel_config_t = CudaTrackJob::cuda_kernel_config_t;
-        using status_t        = CudaTrackJob::status_t;
-        using size_t          = CudaTrackJob::size_type;
+        using cuda_ctrl_t     = tjob_t::cuda_controller_t;
+        using kernel_config_t = tjob_t::cuda_kernel_config_t;
         using node_index_t    = cuda_ctrl_t::node_index_t;
         using node_info_t     = cuda_ctrl_t::node_info_t;
 
@@ -1760,6 +2051,10 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_config_t* kernel_conf = ( ptr_cuda_ctrl != nullptr )
             ? ptr_cuda_ctrl->ptrKernelConfig( kernel_id ) : nullptr;
 
+        SIXTRL_ASSERT( this->m_default_threads_per_block > st_size_t{ 0 } );
+        SIXTRL_ASSERT( st_size_t{ 0 } == this->m_default_threads_per_block %
+                         kernel_config_t::DEFAULT_WARP_SIZE );
+
         size_t num_particle_sets = size_t{ 0 };
 
         if( this->doGetPtrParticlesAddrBuffer() != nullptr )
@@ -1772,12 +2067,235 @@ namespace SIXTRL_CXX_NAMESPACE
                 this->ptrCParticlesBuffer() );
         }
 
-        status_t status = ::NS(CudaKernelConfig_configure_track_line_kernel)(
-            kernel_conf, node_info, num_particle_sets );
+        st_status_t status =
+        ::NS(CudaKernelConfig_configure_track_line_kernel)( kernel_conf,
+            node_info, num_particle_sets, this->m_default_threads_per_block );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
-            status = _base_t::doSetFetchParticlesAddressesKernelId( kernel_id );
+            status = base_tjob_t::doSetFetchParticlesAddressesKernelId( kernel_id );
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_set_assign_addresses_kernel_id_cuda_impl(
+        tjob_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
+    {
+        using cuda_ctrl_t     = tjob_t::cuda_controller_t;
+        using kernel_config_t = tjob_t::cuda_kernel_config_t;
+        using status_t        = st_status_t;
+        using node_index_t    = cuda_ctrl_t::node_index_t;
+        using node_info_t     = cuda_ctrl_t::node_info_t;
+
+        cuda_ctrl_t* ptr_cuda_ctrl = this->ptrCudaController();
+
+        node_index_t const selected_node_index = ( ptr_cuda_ctrl != nullptr )
+            ? ptr_cuda_ctrl->selectedNodeIndex()
+            : cuda_ctrl_t::UNDEFINED_INDEX;
+
+        node_info_t const* node_info = ( ptr_cuda_ctrl != nullptr )
+            ? ptr_cuda_ctrl->ptrNodeInfo( selected_node_index ) : nullptr;
+
+        kernel_config_t* kernel_conf = ( ptr_cuda_ctrl != nullptr )
+            ? ptr_cuda_ctrl->ptrKernelConfig( kernel_id ) : nullptr;
+
+        status_t status = ::NS(CudaKernelConfig_configure_assign_address_kernel)(
+            kernel_conf, node_info );
+
+        if( status == st::ARCH_STATUS_SUCCESS )
+        {
+            status = base_tjob_t::do_set_assign_addresses_kernel_id( kernel_id );
+        }
+
+        return status;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    st_status_t tjob_t::do_add_stored_buffer_cuda_impl(
+        st_size_t const buffer_id )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        tjob_t::buffer_store_t* ptr_stored_buffer =
+                this->do_get_ptr_buffer_store( buffer_id );
+
+        tjob_t::cuda_controller_t* controller = this->ptrCudaController();
+
+        if( ( controller != nullptr ) && ( ptr_stored_buffer != nullptr ) &&
+            ( buffer_id >= st::ARCH_MIN_USER_DEFINED_BUFFER_ID ) )
+        {
+            st_size_t const stored_buffer_id =
+                buffer_id - st::ARCH_MIN_USER_DEFINED_BUFFER_ID;
+
+            st_size_t const nn = this->do_get_stored_buffer_size();
+            st_size_t ii = this->m_stored_buffer_args.size();
+
+            for( ; ii < nn ; ++ii )
+            {
+                this->m_stored_buffer_args.emplace_back( nullptr );
+            }
+
+            SIXTRL_ASSERT( this->m_stored_buffer_args.size() >= nn );
+            SIXTRL_ASSERT( this->m_stored_buffer_args.size() >
+                           stored_buffer_id );
+
+            if( ptr_stored_buffer->ptr_cxx_buffer() != nullptr )
+            {
+                tjob_t::buffer_t& stored_buffer =
+                    *ptr_stored_buffer->ptr_cxx_buffer();
+
+                this->m_stored_buffer_args[ stored_buffer_id ].reset(
+                    new tjob_t::cuda_argument_t( stored_buffer, controller ) );
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+            else if( ptr_stored_buffer->ptr_buffer() != nullptr )
+            {
+                tjob_t::c_buffer_t* stored_buffer =
+                    ptr_stored_buffer->ptr_buffer();
+
+                this->m_stored_buffer_args[ stored_buffer_id ].reset( new
+                    tjob_t::cuda_argument_t( stored_buffer, controller ) );
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_remove_stored_buffer_cuda_impl(
+        st_size_t const buffer_id )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        if( buffer_id >= st::ARCH_MIN_USER_DEFINED_BUFFER_ID )
+        {
+            st_size_t const stored_buffer_id =
+                buffer_id - st::ARCH_MIN_USER_DEFINED_BUFFER_ID;
+
+            SIXTRL_ASSERT( this->m_stored_buffer_args.size() > stored_buffer_id );
+            this->m_stored_buffer_args[ stored_buffer_id ].reset( nullptr );
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_push_stored_buffer_cuda_impl(
+        st_size_t const buffer_id )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        tjob_t::buffer_store_t* ptr_stored_buffer =
+                this->do_get_ptr_buffer_store( buffer_id );
+
+        tjob_t::cuda_argument_t* ptr_arg =
+            this->ptr_stored_buffer_argument( buffer_id );
+
+        if( ( ptr_stored_buffer != nullptr ) && ( ptr_arg != nullptr ) )
+        {
+            SIXTRL_ASSERT( ptr_arg->ptrControllerBase() ==
+                           this->ptrControllerBase() );
+
+            if( ptr_stored_buffer->ptr_cxx_buffer() != nullptr )
+            {
+                status = ptr_arg->send( *ptr_stored_buffer->ptr_cxx_buffer() );
+            }
+            else if( ptr_stored_buffer->ptr_buffer() != nullptr )
+            {
+                status = ptr_arg->send( ptr_stored_buffer->ptr_buffer() );
+            }
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_collect_stored_buffer_cuda_impl(
+        st_size_t const buffer_id )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        tjob_t::buffer_store_t* stored_buffer =
+                this->do_get_ptr_buffer_store( buffer_id );
+
+        tjob_t::cuda_argument_t* ptr_arg =
+            this->ptr_stored_buffer_argument( buffer_id );
+
+        if( ( stored_buffer != nullptr ) && ( ptr_arg != nullptr ) )
+        {
+            SIXTRL_ASSERT( ptr_arg->ptrControllerBase() ==
+                          this->ptrControllerBase() );
+
+            if( stored_buffer->ptr_cxx_buffer() != nullptr )
+            {
+                status = ptr_arg->receive( *stored_buffer->ptr_cxx_buffer() );
+            }
+            else if( stored_buffer->ptr_buffer() != nullptr )
+            {
+                status = ptr_arg->receive( stored_buffer->ptr_buffer() );
+            }
+        }
+
+        return status;
+    }
+
+    st_status_t tjob_t::do_add_assign_address_cuda_impl(
+        assign_item_t const& SIXTRL_RESTRICT_REF assign_item,
+        st_size_t* SIXTRL_RESTRICT ptr_item_index )
+    {
+        ( void )assign_item;
+        ( void )ptr_item_index;
+
+        return st::ARCH_STATUS_SUCCESS;
+    }
+
+    st_status_t tjob_t::do_perform_address_assignments_cuda_impl(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        st_size_t const dest_buffer_id = key.dest_buffer_id;
+        tjob_t::c_buffer_t* dest_buffer =
+            this->buffer_by_buffer_id( dest_buffer_id );
+        tjob_t::cuda_argument_t* dest_arg =
+            this->ptr_argument_by_buffer_id( dest_buffer_id );
+
+        size_t const src_buffer_id = key.src_buffer_id;
+        c_buffer_t const* src_buffer =
+            this->buffer_by_buffer_id( src_buffer_id );
+        tjob_t::cuda_argument_t* src_arg =
+            this->ptr_argument_by_buffer_id( src_buffer_id );
+
+        c_buffer_t* assign_buffer =
+            this->do_get_ptr_assign_address_items_buffer( key );
+
+        if( ( this->has_assign_items( dest_buffer_id, src_buffer_id ) ) &&
+            ( this->ptrCudaController() != nullptr ) &&
+            ( assign_buffer != nullptr ) &&
+            ( src_buffer != nullptr ) && ( dest_buffer != nullptr ) &&
+            ( src_arg != nullptr ) && ( src_arg->usesCObjectsBuffer() ) &&
+            ( src_arg->ptrCObjectsBuffer() == src_buffer ) &&
+            ( src_arg->cudaController() == this->ptrCudaController() ) &&
+            ( dest_arg != nullptr ) && ( dest_arg->usesCObjectsBuffer() ) &&
+            ( dest_arg->ptrCObjectsBuffer() == dest_buffer ) &&
+            ( dest_arg->cudaController() == this->ptrCudaController() ) &&
+            ( this->has_assign_addresses_kernel() ) )
+        {
+            tjob_t::kernel_id_t const kid = this->assign_addresses_kernel_id();
+            tjob_t::cuda_kernel_config_t* kernel_conf =
+                this->ptrCudaController()->ptrKernelConfig( kid );
+
+            if( ( kid != st::ARCH_ILLEGAL_KERNEL_ID ) &&
+                ( kernel_conf != nullptr ) )
+            {
+                tjob_t::cuda_argument_t assign_items_arg(
+                    assign_buffer, this->ptrCudaController() );
+
+                NS(AssignAddressItem_process_managed_buffer_cuda_wrapper)(
+                    kernel_conf, &assign_items_arg, dest_arg, dest_buffer_id,
+                        src_arg, src_buffer_id );
+
+                status = st::ARCH_STATUS_SUCCESS;
+            }
         }
 
         return status;
@@ -1787,31 +2305,31 @@ namespace SIXTRL_CXX_NAMESPACE
     /* ********    Implement CudaTrackJob stand-alone functions   ********** */
     /* ********************************************************************* */
 
-    CudaTrackJob::collect_flag_t collect(
+    tjob_t::collect_flag_t collect(
         CudaTrackJob& SIXTRL_RESTRICT_REF track_job )
     {
         return track_job.collect();
     }
 
-    CudaTrackJob::push_flag_t push(
+    tjob_t::push_flag_t push(
         CudaTrackJob& SIXTRL_RESTRICT_REF track_job,
-        CudaTrackJob::push_flag_t const flag )
+        tjob_t::push_flag_t const flag )
     {
         return track_job.push( flag );
     }
 
-    CudaTrackJob::track_status_t trackUntilTurn(
+    st_track_status_t trackUntilTurn(
         CudaTrackJob& SIXTRL_RESTRICT_REF trackjob,
-        CudaTrackJob::size_type const until_turn )
+        st_size_t const until_turn )
     {
         using track_job_t     = CudaTrackJob;
         using controller_t    = track_job_t::cuda_controller_t;
-        using argument_t      = track_job_t::cuda_argument_t;
+//         using argument_t      = track_job_t::cuda_argument_t;
         using kernel_config_t = track_job_t::cuda_kernel_config_t;
         using kernel_id_t     = track_job_t::kernel_id_t;
         using size_t          = track_job_t::size_type;
 
-        CudaTrackJob::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        st_track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
 
         kernel_id_t const kid = trackjob.trackUntilKernelId();
         SIXTRL_ASSERT( kid != controller_t::ILLEGAL_KERNEL_ID );
@@ -1868,17 +2386,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::track_status_t trackElemByElemUntilTurn(
+    st_track_status_t trackElemByElemUntilTurn(
         CudaTrackJob& SIXTRL_RESTRICT_REF trackjob,
-        CudaTrackJob::size_type const until_turn_elem_by_elem )
+        st_size_t const until_turn_elem_by_elem )
     {
         using track_job_t     = CudaTrackJob;
         using controller_t    = track_job_t::cuda_controller_t;
-        using argument_t      = track_job_t::cuda_argument_t;
+//         using argument_t      = track_job_t::cuda_argument_t;
         using kernel_config_t = track_job_t::cuda_kernel_config_t;
         using kernel_id_t     = track_job_t::kernel_id_t;
 
-        CudaTrackJob::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        st_track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
 
         kernel_id_t const kid = trackjob.trackElemByElemKernelId();
         SIXTRL_ASSERT( kid != controller_t::ILLEGAL_KERNEL_ID );
@@ -1907,7 +2425,8 @@ namespace SIXTRL_CXX_NAMESPACE
             ::NS(Track_particles_elem_by_elem_until_turn_cuda_wrapper)(
                 kernel_conf, trackjob.ptrCudaParticlesArg(), pset_index,
                 trackjob.ptrCudaBeamElementsArg(),
-                trackjob.ptrCudaElemByElemConfigArg(), until_turn_elem_by_elem,
+                trackjob.ptrCudaElemByElemConfigArg(),
+                trackjob.elem_by_elem_config_index(), until_turn_elem_by_elem,
                 nullptr );
 
             status = st::TRACK_SUCCESS;
@@ -1924,6 +2443,7 @@ namespace SIXTRL_CXX_NAMESPACE
                     kernel_conf, trackjob.ptrCudaParticlesArg(), pset_index,
                     trackjob.ptrCudaBeamElementsArg(),
                     trackjob.ptrCudaElemByElemConfigArg(),
+                    trackjob.elem_by_elem_config_index(),
                     until_turn_elem_by_elem,
                     trackjob.ptrCudaDebugRegisterArg() );
 
@@ -1943,19 +2463,18 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    CudaTrackJob::track_status_t trackLine(
+    st_track_status_t trackLine(
         CudaTrackJob& SIXTRL_RESTRICT_REF trackjob,
-        CudaTrackJob::size_type const belem_begin_id,
-        CudaTrackJob::size_type const belem_end_id,
-        bool const finish_turn )
+        st_size_t const belem_begin_id,
+        st_size_t const belem_end_id, bool const finish_turn )
     {
         using track_job_t     = CudaTrackJob;
         using controller_t    = track_job_t::cuda_controller_t;
-        using argument_t      = track_job_t::cuda_argument_t;
+//         using argument_t      = track_job_t::cuda_argument_t;
         using kernel_config_t = track_job_t::cuda_kernel_config_t;
         using kernel_id_t     = track_job_t::kernel_id_t;
 
-        CudaTrackJob::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        st_track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
 
         kernel_id_t const kid = trackjob.trackElemByElemKernelId();
         SIXTRL_ASSERT( kid != controller_t::ILLEGAL_KERNEL_ID );
@@ -2014,7 +2533,4 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 }
-
 #endif /* C++, Host */
-
-/* end: sixtracklib/cuda/track/track_job.cpp */
diff --git a/sixtracklib/cuda/track/track_job_c99.cpp b/sixtracklib/cuda/track/track_job_c99.cpp
index 8bea679f..ab865e1f 100644
--- a/sixtracklib/cuda/track/track_job_c99.cpp
+++ b/sixtracklib/cuda/track/track_job_c99.cpp
@@ -95,13 +95,13 @@ bool NS(CudaTrackJob_has_controller)(
              ( track_job->hasCudaController() ) );
 }
 
-NS(CudaController)* NS(CudaTrackJob_get_ptr_controller)(
+::NS(CudaController)* NS(CudaTrackJob_get_ptr_controller)(
     ::NS(CudaTrackJob)* SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr ) ? track_job->ptrCudaController() : nullptr;
 }
 
-NS(CudaController) const* NS(CudaTrackJob_get_ptr_const_controller)(
+::NS(CudaController) const* NS(CudaTrackJob_get_ptr_const_controller)(
     const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr ) ? track_job->ptrCudaController() : nullptr;
@@ -115,14 +115,14 @@ bool NS(CudaTrackJob_has_particles_arg)(
     return ( ( track_job != nullptr ) && ( track_job->hasCudaParticlesArg() ) );
 }
 
-NS(CudaArgument)* NS(CudaTrackJob_get_ptr_particles_arg)(
+::NS(CudaArgument)* NS(CudaTrackJob_get_ptr_particles_arg)(
     ::NS(CudaTrackJob)* SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
         ? track_job->ptrCudaParticlesArg() : nullptr;
 }
 
-NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_particles_arg)(
+::NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_particles_arg)(
     const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
@@ -137,14 +137,14 @@ bool NS(CudaTrackJob_has_beam_elements_arg)(
     return ( ( track_job != nullptr ) && ( track_job->hasCudaParticlesArg() ) );
 }
 
-NS(CudaArgument)* NS(CudaTrackJob_get_ptr_beam_elements_arg)(
+::NS(CudaArgument)* NS(CudaTrackJob_get_ptr_beam_elements_arg)(
     ::NS(CudaTrackJob)* SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
         ? track_job->ptrCudaBeamElementsArg() : nullptr;
 }
 
-NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_beam_elements_arg)(
+::NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_beam_elements_arg)(
     const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
@@ -160,14 +160,14 @@ bool NS(CudaTrackJob_has_output_arg)(
              ( track_job->hasCudaOutputArg() ) );
 }
 
-NS(CudaArgument)* NS(CudaTrackJob_get_ptr_output_arg)(
+::NS(CudaArgument)* NS(CudaTrackJob_get_ptr_output_arg)(
     ::NS(CudaTrackJob)* SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
         ? track_job->ptrCudaOutputArg() : nullptr;
 }
 
-NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_output_arg)(
+::NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_output_arg)(
     const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
@@ -183,14 +183,14 @@ bool NS(CudaTrackJob_has_elem_by_elem_config_arg)(
              ( track_job->hasCudaElemByElemConfigArg() ) );
 }
 
-NS(CudaArgument)* NS(CudaTrackJob_get_ptr_elem_by_elem_config_arg)(
+::NS(CudaArgument)* NS(CudaTrackJob_get_ptr_elem_by_elem_config_arg)(
     ::NS(CudaTrackJob)* SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
         ? track_job->ptrCudaElemByElemConfigArg() : nullptr;
 }
 
-NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_elem_by_elem_config_arg)(
+::NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_elem_by_elem_config_arg)(
     const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
@@ -206,14 +206,14 @@ bool NS(CudaTrackJob_has_debug_register_arg)(
              ( track_job->hasCudaDebugRegisterArg() ) );
 }
 
-NS(CudaArgument)* NS(CudaTrackJob_get_ptr_debug_register_arg)(
+::NS(CudaArgument)* NS(CudaTrackJob_get_ptr_debug_register_arg)(
     ::NS(CudaTrackJob)* SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
         ? track_job->ptrCudaDebugRegisterArg() : nullptr;
 }
 
-NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_debug_register_arg)(
+::NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_debug_register_arg)(
     const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
@@ -229,18 +229,32 @@ bool NS(CudaTrackJob_has_particles_addr_arg)(
              ( track_job->hasCudaParticlesAddrArg() ) );
 }
 
-NS(CudaArgument)* NS(CudaTrackJob_get_ptr_particles_addr_arg)(
+::NS(CudaArgument)* NS(CudaTrackJob_get_ptr_particles_addr_arg)(
     ::NS(CudaTrackJob)* SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
         ? track_job->ptrCudaParticlesAddrArg() : nullptr;
 }
 
-NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_particles_addr_arg)(
+::NS(CudaArgument) const* NS(CudaTrackJob_get_ptr_const_particles_addr_arg)(
     const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
 {
     return ( track_job != nullptr )
         ? track_job->ptrCudaParticlesAddrArg() : nullptr;
 }
 
+::NS(arch_size_t) NS(CudaTrackJob_default_threads_per_block)(
+    const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
+{
+    return ( track_job != nullptr )
+        ? track_job->default_threads_per_block() : ::NS(arch_size_t){ 0 };
+}
+
+::NS(arch_size_t) NS(CudaTrackJob_default_track_threads_per_block)(
+    const ::NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job )
+{
+    return ( track_job != nullptr )
+        ? track_job->default_track_threads_per_block() : ::NS(arch_size_t){ 0 };
+}
+
 /* end: sixtracklib/cuda/track/track_job_c99.cpp */
diff --git a/sixtracklib/cuda/track_job.h b/sixtracklib/cuda/track_job.h
index 344eb560..a384b041 100644
--- a/sixtracklib/cuda/track_job.h
+++ b/sixtracklib/cuda/track_job.h
@@ -163,6 +163,14 @@ NS(CudaTrackJob_get_ptr_const_particles_addr_arg)(
 
 /* ------------------------------------------------------------------------- */
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(CudaTrackJob_default_threads_per_block)(
+    const NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(CudaTrackJob_default_track_threads_per_block)(
+    const NS(CudaTrackJob) *const SIXTRL_RESTRICT track_job );
+
 #endif /* !defined( _GPUCODE ) */
 
 #if defined( __cplusplus ) && !defined( _GPUCODE )
diff --git a/sixtracklib/cuda/track_job.hpp b/sixtracklib/cuda/track_job.hpp
index bfaa8824..1b27155b 100644
--- a/sixtracklib/cuda/track_job.hpp
+++ b/sixtracklib/cuda/track_job.hpp
@@ -3,12 +3,10 @@
 
 #if defined( __cplusplus   ) && !defined( _GPUCODE ) && \
    !defined( __CUDA_ARCH__ ) && !defined( __CUDACC__ )
-
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <cstddef>
     #include <cstdlib>
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
-
 #endif /* C++, Host */
 
 #if !defined( SIXTRL_NO_INCLUDES )
@@ -16,6 +14,7 @@
     #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/control/arch_base.hpp"
     #include "sixtracklib/common/control/kernel_config_base.h"
+    #include "sixtracklib/common/internal/compiler_attributes.h"
     #include "sixtracklib/common/track/definitions.h"
     #include "sixtracklib/common/buffer.h"
     #include "sixtracklib/cuda/definitions.h"
@@ -73,6 +72,14 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* ----------------------------------------------------------------- */
 
+        static constexpr size_type DEFAULT_TRACK_THREADS_PER_BLOCK =
+            size_type{ 128u };
+
+        static constexpr size_type DEFAULT_THREADS_PER_BLOCK =
+            size_type{ 128u };
+
+        /* ----------------------------------------------------------------- */
+
         SIXTRL_STATIC SIXTRL_HOST_FN size_type NumAvailableNodes();
 
         SIXTRL_STATIC SIXTRL_HOST_FN size_type
@@ -259,8 +266,42 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN cuda_argument_t*
         ptrCudaParticlesAddrArg() SIXTRL_NOEXCEPT;
 
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN cuda_argument_t const* ptr_const_argument_by_buffer_id(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cuda_argument_t* ptr_argument_by_buffer_id(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cuda_argument_t const& argument_by_buffer_id(
+            size_type const buffer_id ) const;
+
+        SIXTRL_HOST_FN cuda_argument_t& argument_by_buffer_id(
+            size_type const buffer_id );
+
+        /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
+
+        SIXTRL_HOST_FN cuda_argument_t const* ptr_const_stored_buffer_argument(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cuda_argument_t* ptr_stored_buffer_argument(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cuda_argument_t const& stored_buffer_argument(
+            size_type const buffer_id ) const;
+
+        SIXTRL_HOST_FN cuda_argument_t& stored_buffer_argument(
+            size_type const buffer_id );
+
         /* ================================================================= */
 
+        SIXTRL_HOST_FN size_type
+        default_threads_per_block() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN size_type
+        default_track_threads_per_block() const SIXTRL_NOEXCEPT;
+
         protected:
 
         using argument_base_t   = _base_track_job_t::argument_base_t;
@@ -270,43 +311,63 @@ namespace SIXTRL_CXX_NAMESPACE
         using cuda_kernel_conf_store_t =
             std::unique_ptr< cuda_kernel_config_t >;
 
-        SIXTRL_HOST_FN virtual status_t doPrepareController(
+        SIXTRL_HOST_FN status_t doPrepareController(
             char const* SIXTRL_RESTRICT config_str ) override;
 
-        SIXTRL_HOST_FN virtual status_t doPrepareDefaultKernels(
+        SIXTRL_HOST_FN status_t doPrepareDefaultKernels(
             char const* SIXTRL_RESTRICT config_str ) override;
 
         /* ----------------------------------------------------------------- */
 
-        SIXTRL_HOST_FN virtual status_t doPrepareParticlesStructures(
+        SIXTRL_HOST_FN status_t doPrepareParticlesStructures(
             c_buffer_t* SIXTRL_RESTRICT ptr_particles_buffer ) override;
 
-        SIXTRL_HOST_FN virtual status_t doPrepareBeamElementsStructures(
+        SIXTRL_HOST_FN status_t doPrepareBeamElementsStructures(
             c_buffer_t* SIXTRL_RESTRICT ptr_beam_elem_buffer ) override;
 
-        SIXTRL_HOST_FN virtual status_t doPrepareOutputStructures(
+        SIXTRL_HOST_FN status_t doPrepareOutputStructures(
             c_buffer_t* SIXTRL_RESTRICT particles_buffer,
             c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
             c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
             size_type const until_turn_elem_by_elem ) override;
 
-        SIXTRL_HOST_FN virtual status_t doAssignOutputBufferToBeamMonitors(
+        SIXTRL_HOST_FN status_t doAssignOutputBufferToBeamMonitors(
             c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
             c_buffer_t* SIXTRL_RESTRICT output_buffer,
             particle_index_t const min_turn_id,
             size_type const output_buffer_offset_index ) override;
 
-        SIXTRL_HOST_FN virtual status_t doAssignOutputBufferToElemByElemConfig(
+        SIXTRL_HOST_FN status_t doAssignOutputBufferToElemByElemConfig(
             elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_config,
             c_buffer_t* SIXTRL_RESTRICT output_buffer,
             size_type const output_buffer_offset_index ) override;
 
-        SIXTRL_HOST_FN virtual status_t doReset(
+        SIXTRL_HOST_FN status_t doReset(
             c_buffer_t* SIXTRL_RESTRICT particles_buffer,
             c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
             c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
             size_type const until_turn_elem_by_elem ) override;
 
+        SIXTRL_HOST_FN bool doParseConfigStr(
+            const char *const SIXTRL_RESTRICT config_str ) override;
+         /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN size_type do_add_stored_buffer(
+            buffer_store_t&& assigned_buffer_handle ) override;
+
+        SIXTRL_HOST_FN status_t do_remove_stored_buffer(
+            size_type const buffer_id ) override;
+
+        SIXTRL_HOST_FN status_t do_push_stored_buffer(
+            size_type const buffer_id ) override;
+
+        SIXTRL_HOST_FN status_t do_collect_stored_buffer(
+            size_type const buffer_id ) override;
+
+        SIXTRL_HOST_FN status_t do_perform_address_assignments(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF
+                assign_item_key ) override;
+
         /* ----------------------------------------------------------------- */
 
         SIXTRL_HOST_FN virtual status_t
@@ -329,6 +390,9 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN virtual status_t
         doSetFetchParticlesAddressesKernelId( kernel_id_t const id ) override;
 
+        SIXTRL_HOST_FN status_t do_set_assign_addresses_kernel_id(
+            kernel_id_t const id ) override;
+
         /* ----------------------------------------------------------------- */
 
         SIXTRL_HOST_FN virtual status_t doFetchParticleAddresses() override;
@@ -368,23 +432,25 @@ namespace SIXTRL_CXX_NAMESPACE
 
         template< typename PartSetIndexIter >
         SIXTRL_HOST_FN status_t doInitCudaTrackJob(
-            const char *const SIXTRL_RESTRICT config_str,
+            char const* SIXTRL_RESTRICT node_id_str,
             c_buffer_t* SIXTRL_RESTRICT particles_buffer,
             PartSetIndexIter particle_set_indices_begin,
             PartSetIndexIter particle_set_indices_end,
             c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
             c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-            size_type const until_turn_elem_by_elem );
+            size_type const until_turn_elem_by_elem,
+            char const* SIXTRL_RESTRICT config_str = nullptr );
 
         template< typename PartSetIndexIter >
         SIXTRL_HOST_FN status_t doInitCudaTrackJob(
-            std::string const& SIXTRL_RESTRICT_REF config_str,
+            std::string const& SIXTRL_RESTRICT_REF node_id_str,
             buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
             PartSetIndexIter particle_set_indices_begin,
             PartSetIndexIter particle_set_indices_end,
             buffer_t& SIXTRL_RESTRICT_REF beam_elements_buffer,
             buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-            size_type const until_turn_elem_by_elem );
+            size_type const until_turn_elem_by_elem,
+            std::string const& SIXTRL_RESTRICT_REF config_str = std::string{} );
 
         SIXTRL_HOST_FN status_t doPrepareControllerCudaImpl(
             const char *const SIXTRL_RESTRICT ptr_config_str );
@@ -421,31 +487,59 @@ namespace SIXTRL_CXX_NAMESPACE
             c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
             size_type const until_turn_elem_by_elem );
 
+        SIXTRL_HOST_FN status_t doParseConfigStrCudaImpl(
+            const char *const SIXTRL_RESTRICT config_str );
+
         /* ---------------------------------------------------------------- */
 
         SIXTRL_HOST_FN status_t
         doSetAssignOutputToBeamMonitorsKernelIdCudaImpl(
-            kernel_id_t const id ) SIXTRL_HOST_FN;
+            kernel_id_t const id ) SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN status_t
         doSetAssignOutputToElemByElemConfigKernelIdCudaImpl(
-            kernel_id_t const id ) SIXTRL_HOST_FN;
+            kernel_id_t const id ) SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN status_t
-        doSetTrackUntilKernelIdCudaImpl(
-            kernel_id_t const id ) SIXTRL_HOST_FN;
+        SIXTRL_HOST_FN status_t doSetTrackUntilKernelIdCudaImpl(
+            kernel_id_t const id ) SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN status_t
-        doSetTrackLineKernelIdCudaImpl(
-            kernel_id_t const id ) SIXTRL_HOST_FN;
+        SIXTRL_HOST_FN status_t doSetTrackLineKernelIdCudaImpl(
+            kernel_id_t const id ) SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN status_t
-        doSetTrackElemByElemKernelIdCudaImpl(
-            kernel_id_t const id ) SIXTRL_HOST_FN;
+        SIXTRL_HOST_FN status_t doSetTrackElemByElemKernelIdCudaImpl(
+            kernel_id_t const id ) SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN status_t
-        doSetFetchParticlesAddressesKernelIdCudaImpl(
-            kernel_id_t const id ) SIXTRL_HOST_FN;
+        SIXTRL_HOST_FN status_t doSetFetchParticlesAddressesKernelIdCudaImpl(
+            kernel_id_t const id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN status_t do_set_assign_addresses_kernel_id_cuda_impl(
+            kernel_id_t const id ) SIXTRL_NOEXCEPT;
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN status_t do_add_stored_buffer_cuda_impl(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t do_remove_stored_buffer_cuda_impl(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t do_push_stored_buffer_cuda_impl(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t do_collect_stored_buffer_cuda_impl(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t do_add_assign_address_cuda_impl(
+            assign_item_t const& SIXTRL_RESTRICT_REF assign_item,
+            size_type* SIXTRL_RESTRICT ptr_item_index );
+
+        SIXTRL_HOST_FN status_t do_perform_address_assignments_cuda_impl(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF assign_item_key );
+
+        std::vector< cuda_arg_store_t > m_stored_buffer_args;
+
+        size_type m_track_threads_per_block;
+        size_type m_default_threads_per_block;
     };
 
     CudaTrackJob::push_flag_t push(
@@ -513,19 +607,22 @@ namespace SIXTRL_CXX_NAMESPACE
         std::string const& config_str ) :
         SIXTRL_CXX_NAMESPACE::TrackJobNodeCtrlArgBase(
                 SIXTRL_CXX_NAMESPACE::ARCHITECTURE_CUDA,
-                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() )
+                SIXTRL_ARCHITECTURE_CUDA_STR, config_str.c_str() ),
+        m_track_threads_per_block( CudaTrackJob::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( CudaTrackJob::DEFAULT_THREADS_PER_BLOCK )
+
     {
         CudaTrackJob::status_t const status = this->doInitCudaTrackJob(
-            config_str, particles_buffer, pset_indices_begin, pset_indices_end,
-                belems_buffer, ptr_output_buffer, until_turn_elem_by_elem );
+            node_id_str, particles_buffer, pset_indices_begin, pset_indices_end,
+                belems_buffer, ptr_output_buffer, until_turn_elem_by_elem,
+                    config_str );
 
         SIXTRL_ASSERT( status == SIXTRL_CXX_NAMESPACE::ARCH_STATUS_SUCCESS );
         ( void )status;
     }
 
     template< typename PartSetIndexIter >
-    CudaTrackJob::CudaTrackJob(
-        char const* SIXTRL_RESTRICT node_id_str,
+    CudaTrackJob::CudaTrackJob( char const* SIXTRL_RESTRICT node_id_str,
         CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
         PartSetIndexIter pset_indices_begin, PartSetIndexIter pset_indices_end,
         CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belems_buffer,
@@ -534,11 +631,14 @@ namespace SIXTRL_CXX_NAMESPACE
         char const* SIXTRL_RESTRICT config_str ) :
         SIXTRL_CXX_NAMESPACE::TrackJobNodeCtrlArgBase(
             SIXTRL_CXX_NAMESPACE::ARCHITECTURE_CUDA,
-            SIXTRL_ARCHITECTURE_CUDA_STR, config_str )
+            SIXTRL_ARCHITECTURE_CUDA_STR, config_str ),
+        m_track_threads_per_block( CudaTrackJob::DEFAULT_TRACK_THREADS_PER_BLOCK ),
+        m_default_threads_per_block( CudaTrackJob::DEFAULT_THREADS_PER_BLOCK )
     {
         CudaTrackJob::status_t const status = this->doInitCudaTrackJob(
-            config_str, particles_buffer, pset_indices_begin, pset_indices_end,
-                belems_buffer, ptr_output_buffer, until_turn_elem_by_elem );
+            node_id_str, particles_buffer, pset_indices_begin, pset_indices_end,
+                belems_buffer, ptr_output_buffer, until_turn_elem_by_elem,
+                    config_str );
 
         SIXTRL_ASSERT( status == SIXTRL_CXX_NAMESPACE::ARCH_STATUS_SUCCESS );
         ( void )status;
@@ -547,13 +647,13 @@ namespace SIXTRL_CXX_NAMESPACE
 
     template< typename PartSetIndexIter >
     CudaTrackJob::status_t CudaTrackJob::doInitCudaTrackJob(
-        std::string const& SIXTRL_RESTRICT_REF config_str,
+        std::string const& SIXTRL_RESTRICT_REF node_id_str,
         CudaTrackJob::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        PartSetIndexIter pset_begin,
-        PartSetIndexIter pset_end,
+        PartSetIndexIter pset_begin, PartSetIndexIter pset_end,
         CudaTrackJob::buffer_t& SIXTRL_RESTRICT_REF beam_elements_buffer,
         CudaTrackJob::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        CudaTrackJob::size_type const until_turn_elem_by_elem )
+        CudaTrackJob::size_type const until_turn_elem_by_elem,
+        std::string const& SIXTRL_RESTRICT_REF config_str )
     {
         using c_buffer_t = SIXTRL_CXX_NAMESPACE::CudaTrackJob::c_buffer_t;
 
@@ -561,10 +661,10 @@ namespace SIXTRL_CXX_NAMESPACE
             ? ptr_output_buffer->getCApiPtr() : nullptr;
 
         CudaTrackJob::status_t status =
-            this->doInitCudaTrackJob( config_str.c_str(),
+            this->doInitCudaTrackJob( node_id_str.c_str(),
                 particles_buffer.getCApiPtr(), pset_begin, pset_end,
                     beam_elements_buffer.getCApiPtr(), ptr_c_out_buffer,
-                        until_turn_elem_by_elem );
+                        until_turn_elem_by_elem, config_str.c_str() );
 
         if( status == SIXTRL_CXX_NAMESPACE::ARCH_STATUS_SUCCESS )
         {
@@ -577,16 +677,18 @@ namespace SIXTRL_CXX_NAMESPACE
 
     template< typename PartSetIndexIter >
     CudaTrackJob::status_t CudaTrackJob::doInitCudaTrackJob(
-        const char *const SIXTRL_RESTRICT config_str,
+        char const* SIXTRL_RESTRICT node_id_str,
         CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT pbuffer,
         PartSetIndexIter pset_begin,
         PartSetIndexIter pset_end,
         CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
         CudaTrackJob::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        CudaTrackJob::size_type const until_turn_elem_by_elem )
+        CudaTrackJob::size_type const until_turn_elem_by_elem,
+        const char *const SIXTRL_RESTRICT config_str )
     {
-        using _this_t     = SIXTRL_CXX_NAMESPACE::CudaTrackJob;
-        using _base_t     = SIXTRL_CXX_NAMESPACE::TrackJobNodeCtrlArgBase;
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using _this_t     = st::CudaTrackJob;
+        using _base_t     = st::TrackJobNodeCtrlArgBase;
         using cuda_ctrl_t = _this_t::cuda_controller_t;
         using size_t      = _this_t::size_type;
         using diff_t      = std::ptrdiff_t;
@@ -600,19 +702,35 @@ namespace SIXTRL_CXX_NAMESPACE
 
         cuda_ctrl_t* ptr_ctrl = this->ptrCudaController();
 
-        if( ptr_ctrl == nullptr ) status = ::NS(ARCH_STATUS_GENERAL_FAILURE);
+        if( ptr_ctrl == nullptr ) status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        if( status == ::NS(ARCH_STATUS_SUCCESS) )
+        if( ( status == st::ARCH_STATUS_SUCCESS ) && ( config_str != nullptr ) )
+        {
+            if( !_base_t::doParseConfigStr( config_str ) )
+                status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+            if( status == st::ARCH_STATUS_SUCCESS )
+            {
+                status = this->doParseConfigStrCudaImpl( config_str );
+            }
+        }
+
+        if( ( status == st::ARCH_STATUS_SUCCESS ) && ( node_id_str != nullptr ) )
+        {
+            status = ptr_ctrl->selectNode( node_id_str );
+        }
+
+        if( status == st::ARCH_STATUS_SUCCESS )
         {
             status = _base_t::doPrepareParticlesStructures( pbuffer );
         }
 
-        if( status == ::NS(ARCH_STATUS_SUCCESS) )
+        if( status == st::ARCH_STATUS_SUCCESS )
         {
             status = this->doPrepareParticlesStructuresCudaImpl( pbuffer );
         }
 
-        if( status == ::NS(ARCH_STATUS_SUCCESS) )
+        if( status == st::ARCH_STATUS_SUCCESS )
         {
             this->doSetPtrCParticlesBuffer( pbuffer );
         }
@@ -628,9 +746,6 @@ namespace SIXTRL_CXX_NAMESPACE
             status = ::NS(ARCH_STATUS_GENERAL_FAILURE);
         }
 
-        size_t const num_psets = this->numParticleSets();
-        size_t const* pset_id_begin = this->particleSetIndicesBegin();
-
         if( status == ::NS(ARCH_STATUS_SUCCESS) )
         {
             status = _base_t::doPrepareBeamElementsStructures( belem_buffer );
@@ -721,7 +836,5 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 }
-
 #endif /* C++, Host */
-
 #endif /* SIXTRACKLIB_CUDA_TRACK_JOB_HPP__ */
diff --git a/sixtracklib/cuda/wrappers/track_job_wrappers.cu b/sixtracklib/cuda/wrappers/track_job_wrappers.cu
index 0e1413b7..40305ad5 100644
--- a/sixtracklib/cuda/wrappers/track_job_wrappers.cu
+++ b/sixtracklib/cuda/wrappers/track_job_wrappers.cu
@@ -17,6 +17,7 @@
 #include "sixtracklib/cuda/kernels/extract_particles_addr.cuh"
 #include "sixtracklib/cuda/kernels/be_monitors_assign_out_buffer.cuh"
 #include "sixtracklib/cuda/kernels/elem_by_elem_assign_out_buffer.cuh"
+#include "sixtracklib/cuda/kernels/assign_address_item.cuh"
 #include "sixtracklib/cuda/kernels/track_particles.cuh"
 
 void NS(Track_particles_until_turn_cuda_wrapper)(
@@ -93,7 +94,8 @@ void NS(Track_particles_elem_by_elem_until_turn_cuda_wrapper)(
     NS(CudaArgument)* SIXTRL_RESTRICT particles_arg,
     NS(buffer_size_t) const pset_index,
     NS(CudaArgument)* SIXTRL_RESTRICT beam_elem_arg,
-    NS(CudaArgument)* SIXTRL_RESTRICT elem_by_elem_config_arg,
+    NS(CudaArgument)* SIXTRL_RESTRICT config_buffer_arg,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(buffer_size_t) const until_turn_elem_by_elem,
     NS(CudaArgument)* SIXTRL_RESTRICT dbg_register_arg )
 {
@@ -128,30 +130,30 @@ void NS(Track_particles_elem_by_elem_until_turn_cuda_wrapper)(
         SIXTRL_ASSERT( NS(Argument_get_const_cobjects_buffer)(
             beam_elem_arg ) != SIXTRL_NULLPTR );
 
-        SIXTRL_ASSERT( elem_by_elem_config_arg != SIXTRL_NULLPTR );
-        SIXTRL_ASSERT( NS(Argument_get_arch_id)( elem_by_elem_config_arg ) ==
+        SIXTRL_ASSERT( config_buffer_arg != SIXTRL_NULLPTR );
+        SIXTRL_ASSERT( NS(Argument_get_arch_id)( config_buffer_arg ) ==
                    NS(ARCHITECTURE_CUDA) );
 
-        SIXTRL_ASSERT( NS(Argument_uses_raw_argument)(
-            elem_by_elem_config_arg ) );
-
-        SIXTRL_ASSERT( NS(Argument_get_ptr_raw_argument)(
-            elem_by_elem_config_arg ) != SIXTRL_NULLPTR );
-
-        SIXTRL_ASSERT( NS(Argument_get_size)( elem_by_elem_config_arg ) >
-            ( NS(buffer_size_t) )0u );
+        SIXTRL_ASSERT( NS(Argument_uses_cobjects_buffer)( config_buffer_arg ) );
+        SIXTRL_ASSERT( NS(Argument_get_const_cobjects_buffer)(
+            config_buffer_arg ) != SIXTRL_NULLPTR );
 
         SIXTRL_ASSERT(
             NS(Argument_get_cobjects_buffer_slot_size)( particles_arg ) ==
             NS(Argument_get_cobjects_buffer_slot_size)( beam_elem_arg ) );
 
+        SIXTRL_ASSERT(
+            NS(Argument_get_cobjects_buffer_slot_size)( config_buffer_arg ) ==
+            NS(Argument_get_cobjects_buffer_slot_size)( particles_arg ) );
+
         NS(Track_track_elem_by_elem_until_turn_cuda)<<< *ptr_blocks, *ptr_threads >>>(
             NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
                 particles_arg ), pset_index,
             NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
                 beam_elem_arg ),
-            NS(CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin)(
-                elem_by_elem_config_arg ), until_turn_elem_by_elem,
+            NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
+                config_buffer_arg ), elem_by_elem_config_index,
+            until_turn_elem_by_elem,
             NS(Argument_get_cobjects_buffer_slot_size)( particles_arg ) );
     }
     else if( ( ptr_blocks != SIXTRL_NULLPTR ) &&
@@ -165,8 +167,9 @@ void NS(Track_particles_elem_by_elem_until_turn_cuda_wrapper)(
                 particles_arg ), pset_index,
             NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
                 beam_elem_arg ),
-            NS(CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin)(
-                elem_by_elem_config_arg ), until_turn_elem_by_elem,
+            NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
+                config_buffer_arg ), elem_by_elem_config_index,
+            until_turn_elem_by_elem,
             NS(Argument_get_cobjects_buffer_slot_size)( particles_arg ),
             NS(CudaArgument_get_cuda_arg_buffer_as_debugging_register_begin)(
                 dbg_register_arg ) );
@@ -323,7 +326,8 @@ void NS(BeamMonitor_assign_out_buffer_from_offset_cuda_wrapper)(
 
 void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
     const NS(CudaKernelConfig) *const SIXTRL_RESTRICT kernel_config,
-    NS(CudaArgument)* SIXTRL_RESTRICT elem_by_elem_config_arg,
+    NS(CudaArgument)* SIXTRL_RESTRICT config_buffer_arg,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(CudaArgument)* SIXTRL_RESTRICT output_arg,
     NS(buffer_size_t) const out_buffer_offset_index,
     NS(CudaArgument)* SIXTRL_RESTRICT dbg_register_arg )
@@ -351,18 +355,17 @@ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
         SIXTRL_ASSERT( NS(Argument_get_const_cobjects_buffer)(
             output_arg ) != SIXTRL_NULLPTR );
 
-        SIXTRL_ASSERT( elem_by_elem_config_arg != SIXTRL_NULLPTR );
-        SIXTRL_ASSERT( NS(Argument_get_arch_id)( elem_by_elem_config_arg ) ==
+        SIXTRL_ASSERT( config_buffer_arg != SIXTRL_NULLPTR );
+        SIXTRL_ASSERT( NS(Argument_get_arch_id)( config_buffer_arg ) ==
                    NS(ARCHITECTURE_CUDA) );
 
-        SIXTRL_ASSERT( NS(Argument_uses_raw_argument)(
-            elem_by_elem_config_arg ) );
-
-        SIXTRL_ASSERT( NS(Argument_get_ptr_raw_argument)(
-            elem_by_elem_config_arg ) != SIXTRL_NULLPTR );
+        SIXTRL_ASSERT( NS(Argument_uses_cobjects_buffer)( config_buffer_arg ) );
+        SIXTRL_ASSERT( NS(Argument_get_const_cobjects_buffer)(
+            config_buffer_arg ) != SIXTRL_NULLPTR );
 
-        SIXTRL_ASSERT( NS(Argument_get_size)( elem_by_elem_config_arg ) >
-            ( NS(buffer_size_t) )0u );
+        SIXTRL_ASSERT(
+            NS(Argument_get_cobjects_buffer_slot_size)( config_buffer_arg ) ==
+            NS(Argument_get_cobjects_buffer_slot_size)( output_arg ) );
 
         SIXTRL_ASSERT( out_buffer_offset_index <
             NS(Buffer_get_num_of_objects)(
@@ -373,8 +376,8 @@ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
 
         NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda)<<<
             *ptr_blocks, *ptr_threads >>>(
-            NS(CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin)(
-                elem_by_elem_config_arg ),
+            NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
+                config_buffer_arg ), elem_by_elem_config_index,
             NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
                 output_arg ), out_buffer_offset_index,
             NS(Argument_get_cobjects_buffer_slot_size)( output_arg ) );
@@ -389,8 +392,8 @@ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
     {
         NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_debug)<<<
             *ptr_blocks, *ptr_threads >>>(
-            NS(CudaArgument_get_cuda_arg_buffer_as_elem_by_elem_config_begin)(
-                elem_by_elem_config_arg ),
+            NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
+                config_buffer_arg ), elem_by_elem_config_index,
             NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
                 output_arg ), out_buffer_offset_index,
             NS(Argument_get_cobjects_buffer_slot_size)( output_arg ),
@@ -399,6 +402,76 @@ void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
     }
 }
 
+void NS(AssignAddressItem_process_managed_buffer_cuda_wrapper)(
+    const NS(CudaKernelConfig) *const SIXTRL_RESTRICT kernel_config,
+    NS(CudaArgument)* SIXTRL_RESTRICT assign_buffer_arg,
+    NS(CudaArgument)* SIXTRL_RESTRICT dest_buffer_arg,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(CudaArgument)* SIXTRL_RESTRICT src_buffer_arg,
+    NS(buffer_size_t) const src_buffer_id )
+{
+    dim3 const* ptr_blocks =
+        NS(CudaKernelConfig_get_ptr_const_blocks)( kernel_config );
+
+    dim3 const* ptr_threads =
+        NS(CudaKernelConfig_get_ptr_const_threads_per_block)( kernel_config );
+
+    NS(buffer_size_t) const assign_slot_size =  NS(Buffer_get_slot_size)(
+        NS(Argument_get_const_cobjects_buffer)( dest_buffer_arg ) );
+
+    NS(buffer_size_t) const dest_slot_size = NS(Buffer_get_slot_size)(
+        NS(Argument_get_const_cobjects_buffer)( dest_buffer_arg ) );
+
+    NS(buffer_size_t) const src_slot_size = NS(Buffer_get_slot_size)(
+        NS(Argument_get_const_cobjects_buffer)( src_buffer_arg ) );
+
+    SIXTRL_ASSERT( ptr_blocks  != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( ptr_threads != SIXTRL_NULLPTR );
+
+    SIXTRL_ASSERT( !NS(KernelConfig_needs_update)( kernel_config ) );
+    SIXTRL_ASSERT( NS(KernelConfig_get_arch_id)( kernel_config ) ==
+        NS(ARCHITECTURE_CUDA) );
+
+    SIXTRL_ASSERT( assign_buffer_arg != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Argument_get_arch_id)( assign_buffer_arg ) ==
+               NS(ARCHITECTURE_CUDA) );
+
+    SIXTRL_ASSERT( NS(Argument_uses_cobjects_buffer)( assign_buffer_arg ) );
+    SIXTRL_ASSERT( NS(Argument_get_const_cobjects_buffer)(
+        assign_buffer_arg ) != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( assign_slot_size > ( NS(buffer_size_t) )0 );
+
+    SIXTRL_ASSERT( dest_buffer_arg != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Argument_get_arch_id)( dest_buffer_arg ) ==
+               NS(ARCHITECTURE_CUDA) );
+    SIXTRL_ASSERT( NS(Argument_uses_cobjects_buffer)( dest_buffer_arg ) );
+    SIXTRL_ASSERT( NS(Argument_get_const_cobjects_buffer)(
+        dest_buffer_arg ) != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( dest_slot_size > ( NS(buffer_size_t) )0u );
+    SIXTRL_ASSERT( dest_buffer_id != (
+        NS(buffer_size_t) )SIXTRL_ARCH_ILLEGAL_BUFFER_ID );
+
+    SIXTRL_ASSERT( src_buffer_arg != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( NS(Argument_get_arch_id)( src_buffer_arg ) ==
+               NS(ARCHITECTURE_CUDA) );
+
+    SIXTRL_ASSERT( NS(Argument_uses_cobjects_buffer)( src_buffer_arg ) );
+    SIXTRL_ASSERT( NS(Argument_get_const_cobjects_buffer)(
+        src_buffer_arg ) != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( src_slot_size > ( NS(buffer_size_t) )0u );
+    SIXTRL_ASSERT( src_buffer_id != (
+        NS(buffer_size_t) )SIXTRL_ARCH_ILLEGAL_BUFFER_ID );
+
+    NS(AssignAddressItem_process_managed_buffer_cuda)<<< *ptr_blocks,
+        *ptr_threads >>>(
+        NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
+            assign_buffer_arg ), assign_slot_size,
+        NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
+            dest_buffer_arg ), dest_slot_size, dest_buffer_id,
+        NS(CudaArgument_get_cuda_arg_buffer_as_cobject_buffer_begin)(
+            src_buffer_arg ), src_slot_size, src_buffer_id );
+}
+
 void NS(Particles_buffer_store_all_addresses_cuda_wrapper)(
     const NS(CudaKernelConfig) *const SIXTRL_RESTRICT kernel_config,
     NS(CudaArgument)* SIXTRL_RESTRICT particles_addresses_arg,
diff --git a/sixtracklib/cuda/wrappers/track_job_wrappers.h b/sixtracklib/cuda/wrappers/track_job_wrappers.h
index c6ac7bed..fb927e60 100644
--- a/sixtracklib/cuda/wrappers/track_job_wrappers.h
+++ b/sixtracklib/cuda/wrappers/track_job_wrappers.h
@@ -34,7 +34,8 @@ void NS(Track_particles_elem_by_elem_until_turn_cuda_wrapper)(
     NS(CudaArgument)* SIXTRL_RESTRICT particles_arg,
     NS(buffer_size_t) const pset_index,
     NS(CudaArgument)* SIXTRL_RESTRICT beam_elements_arg,
-    NS(CudaArgument)* SIXTRL_RESTRICT elem_by_elem_config_arg,
+    NS(CudaArgument)* SIXTRL_RESTRICT config_buffer_arg,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(buffer_size_t) const until_turn_elem_by_elem,
     NS(CudaArgument)* SIXTRL_RESTRICT debug_register_arg );
 
@@ -59,11 +60,21 @@ void NS(BeamMonitor_assign_out_buffer_from_offset_cuda_wrapper)(
 SIXTRL_EXTERN SIXTRL_HOST_FN
 void NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
     const NS(CudaKernelConfig) *const SIXTRL_RESTRICT kernel_config,
-    NS(CudaArgument)* SIXTRL_RESTRICT elem_by_elem_config_arg,
+    NS(CudaArgument)* SIXTRL_RESTRICT config_buffer_arg,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(CudaArgument)* SIXTRL_RESTRICT output_buffer_arg,
     NS(buffer_size_t) const out_buffer_offset_index,
     NS(CudaArgument)* SIXTRL_RESTRICT debug_register_arg );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN
+void NS(AssignAddressItem_process_managed_buffer_cuda_wrapper)(
+    const NS(CudaKernelConfig) *const SIXTRL_RESTRICT kernel_config,
+    NS(CudaArgument)* SIXTRL_RESTRICT assign_buffer_arg,
+    NS(CudaArgument)* SIXTRL_RESTRICT dest_buffer_arg,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(CudaArgument)* SIXTRL_RESTRICT src_buffer_arg,
+    NS(buffer_size_t) const src_buffer_id );
+
 SIXTRL_EXTERN SIXTRL_HOST_FN
 void NS(Particles_buffer_store_all_addresses_cuda_wrapper)(
     const NS(CudaKernelConfig) *const SIXTRL_RESTRICT kernel_config,
diff --git a/sixtracklib/opencl/CMakeLists.txt b/sixtracklib/opencl/CMakeLists.txt
index de6659f7..b6581735 100644
--- a/sixtracklib/opencl/CMakeLists.txt
+++ b/sixtracklib/opencl/CMakeLists.txt
@@ -5,6 +5,12 @@ message( STATUS "---- processing sixtracklib/opencl/CMakeLists.txt" )
 
 set( C99_HEADERS_INSTALL_PATH "include/sixtracklib/opencl" )
 set( CXX_HEADERS_INSTALL_PATH ${C99_HEADERS_INSTALL_PATH}  )
+set( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS "" )
+
+if( SIXTRACKL_OPENCL_DEFAULT_COMPILER_FLAGS )
+    set( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS
+         "${SIXTRACKL_OPENCL_DEFAULT_COMPILER_FLAGS}" )
+endif()
 
 set( CL_H_IN_FILE  "${CMAKE_CURRENT_SOURCE_DIR}/cl.h.template" )
 set( CL_H_OUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cl.h" )
@@ -53,17 +59,15 @@ set( SIXTRACKLIB_OPENCL_KERNEL_SOURCES
      kernels/track_particles_optimized_priv_particles_debug.cl
      kernels/be_monitors_assign_out_buffer.cl
      kernels/be_monitors_assign_out_buffer_debug.cl
+     kernels/assign_address_item.cl
 )
 
 add_library( sixtrack_opencl OBJECT
-             ${SIXTRACKLIB_OPENCL_HEADERS}
-             ${SIXTRACKLIB_OPENCL_SOURCES}
-)
+    ${SIXTRACKLIB_OPENCL_HEADERS} ${SIXTRACKLIB_OPENCL_SOURCES} )
 
 target_include_directories( sixtrack_opencl
     PUBLIC $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
-    PUBLIC $<BUILD_INTERFACE:${SIXTRACKL_OPENCL_INCLUDE_DIR}>
-)
+    PUBLIC $<BUILD_INTERFACE:${SIXTRACKL_OPENCL_INCLUDE_DIR}> )
 
 set_target_properties( sixtrack_opencl PROPERTIES LINKER_LANGUAGE C
     POSITION_INDEPENDENT_CODE True CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON )
@@ -72,7 +76,8 @@ target_compile_definitions( sixtrack_opencl PUBLIC
         ${SIXTRACKLIB_NAMESPACE_FLAGS} -DCL_USE_DEPRECATED_OPENCL_1_2_APIS )
 
 target_compile_options( sixtrack_opencl BEFORE PUBLIC
-        ${SIXTRACKLIB_CPU_FLAGS} ${SIXTRACKLIB_CXX_FLAGS} )
+        ${SIXTRACKLIB_CPU_FLAGS} ${SIXTRACKLIB_CXX_FLAGS}
+        ${SIXTRACKL_CXX_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_opencl as a module for sixtracklib:
diff --git a/sixtracklib/opencl/cl.h.template b/sixtracklib/opencl/cl.h.template
index 853189fb..b0efc096 100644
--- a/sixtracklib/opencl/cl.h.template
+++ b/sixtracklib/opencl/cl.h.template
@@ -8,6 +8,11 @@
 #if defined( __cplusplus ) && !defined( _GPUCODE ) && \
     !defined( __CUDACC__ ) && !defined( __CUDA_ARCH__ )
 
+    #if !defined( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS )
+        #define SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS \
+            "@SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS@"
+    #endif /* !defined( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS ) */
+
     #if !defined( CL_HPP_MINIMUM_OPENCL_VERSION )
         #define CL_HPP_MINIMUM_OPENCL_VERSION @SIXTRACKL_MIN_OPENCL_VERSION@
     #endif /* !defined( CL_HPP_MINIMUM_OPENCL_VERSION ) */
@@ -34,16 +39,16 @@
     #endif /* !defined( SIXTRL_OPENCL_CXX_ENABLES_HOST_EXCEPTIONS ) */
 
     /* Attempt to disable -Wignored-attributes warnings on affected compilers
-     * only for the C++ OpenCL header -> cf. 
+     * only for the C++ OpenCL header -> cf.
      * http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1221 for reference */
-    
-    #if defined( __GNUC__ ) && __GNUC__ >= 6 
+
+    #if defined( __GNUC__ ) && __GNUC__ >= 6
         #pragma GCC diagnostic push
         #pragma GCC diagnostic ignored "-Wignored-attributes"
-    #endif 
-    
+    #endif
+
     #include <@SIXTRL_OPENCL_CL_HPP@>
-    
+
     #if defined( __GNUC__ ) && __GNUC__ >= 6
         #pragma GCC diagnostic pop
     #endif
diff --git a/sixtracklib/opencl/context.h b/sixtracklib/opencl/context.h
index 7159cb08..e16420f9 100644
--- a/sixtracklib/opencl/context.h
+++ b/sixtracklib/opencl/context.h
@@ -12,6 +12,8 @@
 
     #if defined( __cplusplus )
         #include <algorithm>
+        #include <string>
+        #include <map>
     #endif /* !defined( __cplusplus ) */
 
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
@@ -56,13 +58,19 @@ namespace SIXTRL_CXX_NAMESPACE
         using  track_status_t        = SIXTRL_CXX_NAMESPACE::track_status_t;
         using  elem_by_elem_config_t = ::NS(ElemByElemConfig);
         using  num_turns_t           = ::NS(particle_index_t);
+        using  feature_flag_t        = uint16_t;
 
         static constexpr size_type MIN_NUM_TRACK_UNTIL_ARGS   = size_type{ 5 };
         static constexpr size_type MIN_NUM_TRACK_LINE_ARGS    = size_type{ 7 };
-        static constexpr size_type MIN_NUM_TRACK_ELEM_ARGS    = size_type{ 6 };
+        static constexpr size_type MIN_NUM_TRACK_ELEM_ARGS    = size_type{ 7 };
         static constexpr size_type MIN_NUM_ASSIGN_BE_MON_ARGS = size_type{ 5 };
         static constexpr size_type MIN_NUM_CLEAR_BE_MON_ARGS  = size_type{ 2 };
         static constexpr size_type MIN_NUM_ASSIGN_ELEM_ARGS   = size_type{ 4 };
+        static constexpr size_type MIN_NUM_FETCH_PARTICLES_ADDR_ARGS =
+            size_type{ 3 };
+
+        static constexpr size_type
+            DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX = size_type{ 0 };
 
         explicit ClContext(
             const char *const SIXTRL_RESTRICT config_str = nullptr );
@@ -91,20 +99,26 @@ namespace SIXTRL_CXX_NAMESPACE
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
         status_t assign_particles_arg(
-            ClArgument& SIXTRL_RESTRICT_REF particles_arg );
+            cl_argument_t& SIXTRL_RESTRICT_REF particles_arg );
 
         status_t assign_particle_set_arg(
             size_type const particle_set_index,
             size_type const num_particles_in_set );
 
         status_t assign_beam_elements_arg(
-            ClArgument& SIXTRL_RESTRICT_REF beam_elements_arg );
+            cl_argument_t& SIXTRL_RESTRICT_REF beam_elements_arg );
 
         status_t assign_output_buffer_arg(
-            ClArgument& SIXTRL_RESTRICT_REF output_buffer_arg );
+            cl_argument_t& SIXTRL_RESTRICT_REF output_buffer_arg );
+
+        status_t assign_elem_by_elem_config_buffer_arg(
+            cl_argument_t& SIXTRL_RESTRICT_REF elem_by_elem_config_buffer_arg );
+
+        status_t assign_elem_by_elem_config_index_arg(
+            size_type const elem_by_elem_config_index );
 
-        status_t assign_elem_by_elem_config_arg(
-            cl_buffer_t& SIXTRL_RESTRICT_REF elem_by_elem_config_arg );
+        status_t assign_particles_addr_buffer_arg(
+            ClArgument& SIXTRL_RESTRICT_REF particles_addr_arg );
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
@@ -177,6 +191,19 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
+        bool has_assign_addresses_kernel() const SIXTRL_NOEXCEPT;
+        kernel_id_t assign_addresses_kernel_id() const SIXTRL_NOEXCEPT;
+        status_t set_assign_addresses_kernel_id( kernel_id_t const kernel_id );
+
+        status_t assign_addresses(
+            cl_argument_t& SIXTRL_RESTRICT_REF assign_items_arg,
+            cl_argument_t& SIXTRL_RESTRICT_REF dest_buffer_arg,
+            size_type const dest_buffer_id,
+            cl_argument_t& SIXTRL_RESTRICT_REF src_buffer_arg,
+            size_type const src_buffer_id );
+
+        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
         size_type selected_particle_set() const SIXTRL_NOEXCEPT;
         size_type num_particles_in_selected_set() const SIXTRL_NOEXCEPT;
 
@@ -188,43 +215,29 @@ namespace SIXTRL_CXX_NAMESPACE
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-        bool is_beam_beam_tracking_enabled() const SIXTRL_NOEXCEPT;
+        bool is_beam_beam_tracking_enabled() const;
         void enable_beam_beam_tracking();
         void disable_beam_beam_tracking();
+        void skip_beam_beam_tracking();
 
         /* ----------------------------------------------------------------- */
 
-        std::unique_ptr< SIXTRL_CXX_NAMESPACE::ClContext::cl_buffer_t >
-        create_elem_by_elem_config_arg();
-
-        void delete_elem_by_elem_config_arg(
-            std::unique_ptr< SIXTRL_CXX_NAMESPACE::ClContext::cl_buffer_t >&& );
-
-        status_t init_elem_by_elem_config_arg(
-            cl_buffer_t& SIXTRL_RESTRICT_REF elem_by_elem_config_arg,
-            elem_by_elem_config_t& SIXTRL_RESTRICT_REF elem_by_elem_config,
-            const ::NS(Buffer) *const SIXTRL_RESTRICT particles_buffer,
-            size_type const num_particle_sets,
-            size_type const* SIXTRL_RESTRICT pset_indices_begin,
-            const ::NS(Buffer) *const SIXTRL_RESTRICT beam_elements_buffer,
-            size_type const until_turn_elem_by_elem,
-            particle_index_t const start_elem_id = particle_index_t{ 0 } );
-
-        status_t collect_elem_by_elem_config_arg(
-            cl_buffer_t& SIXTRL_RESTRICT_REF elem_by_elem_config_arg,
-            elem_by_elem_config_t& SIXTRL_RESTRICT_REF elem_by_elem_config );
-
-        status_t push_elem_by_elem_config_arg(
-            cl_buffer_t& SIXTRL_RESTRICT_REF elem_by_elem_config_arg,
-            elem_by_elem_config_t const& SIXTRL_RESTRICT_REF
-                elem_by_elem_config );
+        bool has_fetch_particles_addr_kernel() const SIXTRL_NOEXCEPT;
+        kernel_id_t fetch_particles_addr_kernel_id() const SIXTRL_NOEXCEPT;
+        status_t set_fetch_particles_addr_kernel_id(
+            kernel_id_t const kernel_id );
+        status_t fetch_particles_addr();
 
         protected:
 
         bool doSelectNode( size_type node_index ) override;
+        status_t doInitDefaultFeatureFlags() override;
         bool doInitDefaultPrograms() override;
         bool doInitDefaultKernels()  override;
 
+        virtual status_t doAssignElemByElemConfigIndexArg(
+            size_type const elem_by_elem_config_index );
+
         status_t doAssignStatusFlagsArg(
             cl::Buffer& SIXTRL_RESTRICT_REF status_flags_arg ) override;
 
@@ -234,6 +247,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
         bool doInitDefaultProgramsPrivImpl();
         bool doInitDefaultKernelsPrivImpl();
+        status_t doInitDefaultFeatureFlagsPrivImpl();
+
+        status_t doAssignElemByElemConfigIndexArgPrivImpl(
+            size_type const elem_by_elem_config_index );
 
         status_t doAssignStatusFlagsArgPrivImpl(
             cl::Buffer& SIXTRL_RESTRICT_REF status_flags_arg );
@@ -243,23 +260,28 @@ namespace SIXTRL_CXX_NAMESPACE
 
         size_type    m_num_particles_in_pset;
         size_type    m_pset_index;
+        size_type    m_elem_by_elem_config_index;
 
         program_id_t m_track_until_turn_program_id;
         program_id_t m_track_elem_by_elem_program_id;
         program_id_t m_track_line_program_id;
         program_id_t m_assign_elem_by_elem_out_buffer_program_id;
         program_id_t m_assign_be_mon_out_buffer_program_id;
+        program_id_t m_fetch_particles_addr_program_id;
         program_id_t m_clear_be_mon_program_id;
+        program_id_t m_assign_addr_program_id;
 
         kernel_id_t  m_track_until_turn_kernel_id;
         kernel_id_t  m_track_elem_by_elem_kernel_id;
         kernel_id_t  m_track_line_kernel_id;
         kernel_id_t  m_assign_elem_by_elem_out_buffer_kernel_id;
         kernel_id_t  m_assign_be_mon_out_buffer_kernel_id;
+        kernel_id_t  m_fetch_particles_addr_kernel_id;
         kernel_id_t  m_clear_be_mon_kernel_id;
+        kernel_id_t  m_assign_addr_kernel_id;
 
         bool         m_use_optimized_tracking;
-        bool         m_enable_beam_beam;
+
     };
 }
 
@@ -316,8 +338,14 @@ NS(ClContext_assign_output_buffer_arg)( NS(ClContext)* SIXTRL_RESTRICT ctx,
     NS(ClArgument)* SIXTRL_RESTRICT_REF out_buffer_arg );
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
-NS(ClContext_assign_elem_by_elem_config_arg)(
-    NS(ClContext)* SIXTRL_RESTRICT ctx, cl_mem elem_by_elem_config_arg  );
+NS(ClContext_assign_elem_by_elem_config_buffer_arg)(
+    NS(ClContext)* SIXTRL_RESTRICT ctx,
+    NS(ClArgument)* SIXTRL_RESTRICT elem_by_elem_config_arg );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(ClContext_assign_elem_by_elem_config_index_arg)(
+    NS(ClContext)* SIXTRL_RESTRICT ctx,
+    NS(buffer_size_t) const elem_by_elem_config_index );
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(ClContext_assign_slot_size_arg)(
@@ -399,7 +427,8 @@ NS(ClContext_track_elem_by_elem)(
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(track_status_t)
 NS(ClContext_track_elem_by_elem_for_particle_set)(
-    NS(ClContext)* SIXTRL_RESTRICT ctx, NS(buffer_size_t) const until_turn,
+    NS(ClContext)* SIXTRL_RESTRICT ctx,
+    NS(context_num_turns_t) const until_turn,
     NS(buffer_size_t) const particle_set_index,
     NS(buffer_size_t) const num_particles_in_set,
     bool const restore_particle_set_index );
@@ -462,6 +491,27 @@ NS(ClContext_set_clear_beam_monitor_output_kernel_id)(
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(ClContext_clear_beam_monitor_output)( NS(ClContext)*  SIXTRL_RESTRICT ctx );
 
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ClContext_has_assign_addresses_kernel)(
+    const NS(ClContext) *const SIXTRL_RESTRICT ctx );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ctrl_kernel_id_t)
+NS(ClContext_assign_addresses_kernel_id)(
+    const NS(ClContext) *const SIXTRL_RESTRICT ctx );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(ClContext_set_assign_addresses_kernel_id)(
+    NS(ClContext)* SIXTRL_RESTRICT ctx, NS(ctrl_kernel_id_t) const kernel_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t) NS(ClContext_assign_addresses)(
+    NS(ClContext)* SIXTRL_RESTRICT ctx,
+    NS(ClArgument)* SIXTRL_RESTRICT assign_items_arg,
+    NS(ClArgument)* SIXTRL_RESTRICT dest_buffer_arg,
+    NS(buffer_size_t) const dest_buffer_id,
+    NS(ClArgument)* SIXTRL_RESTRICT src_buffer_arg,
+    NS(buffer_size_t) const src_buffer_id );
+
 /* ========================================================================= */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(buffer_size_t)
@@ -494,36 +544,9 @@ SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContext_enable_beam_beam_tracking)(
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContext_disable_beam_beam_tracking)(
     NS(ClContext)* SIXTRL_RESTRICT ctx );
 
-/* ------------------------------------------------------------------------- */
-
-cl_mem NS(ClContext_create_elem_by_elem_config_arg)(
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContext_skip_beam_beam_tracking)(
     NS(ClContext)* SIXTRL_RESTRICT ctx );
 
-void NS(ClContext_delete_elem_by_elem_config_arg)(
-    NS(ClContext)* SIXTRL_RESTRICT ctx, cl_mem elem_by_elem_config_arg );
-
-NS(arch_status_t) NS(ClContext_init_elem_by_elem_config_arg)(
-    NS(ClContext)* SIXTRL_RESTRICT ctx,
-    cl_mem elem_by_elem_config_arg,
-    NS(ElemByElemConfig)* SIXTRL_RESTRICT elem_by_elem_config,
-    const NS(Buffer) *const SIXTRL_RESTRICT particles_buffer,
-    NS(buffer_size_t) const num_particle_sets,
-    NS(buffer_size_t) const* SIXTRL_RESTRICT pset_indices_begin,
-    const NS(Buffer) *const SIXTRL_RESTRICT beam_elements_buffer,
-    NS(buffer_size_t) const until_turn_elem_by_elem,
-    NS(particle_index_t) const start_elem_id );
-
-NS(arch_status_t) NS(ClContext_collect_elem_by_elem_config_arg)(
-    NS(ClContext)* SIXTRL_RESTRICT ctx,
-    cl_mem elem_by_elem_config_arg,
-    NS(ElemByElemConfig)* SIXTRL_RESTRICT elem_by_elem_config );
-
-NS(arch_status_t) NS(ClContext_push_elem_by_elem_config_arg)(
-    NS(ClContext)* SIXTRL_RESTRICT ctx,
-    cl_mem elem_by_elem_config_arg,
-    const NS(ElemByElemConfig) *const SIXTRL_RESTRICT elem_by_elem_config );
-
-
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
diff --git a/sixtracklib/opencl/internal/base_context.cpp b/sixtracklib/opencl/internal/base_context.cpp
index ee6510f3..2b1a1ff8 100644
--- a/sixtracklib/opencl/internal/base_context.cpp
+++ b/sixtracklib/opencl/internal/base_context.cpp
@@ -15,6 +15,7 @@
 #include <locale>
 #include <regex>
 #include <sstream>
+#include <stdexcept>
 #include <string>
 #include <vector>
 
@@ -27,21 +28,32 @@
 #include "sixtracklib/opencl/cl.h"
 #include "sixtracklib/opencl/argument.h"
 
-namespace st = SIXTRL_CXX_NAMESPACE;
 namespace SIXTRL_CXX_NAMESPACE
 {
-    using  _this_t = st::ClContextBase;
+    namespace
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using  ctx_t = st::ClContextBase;
+        using  st_size_t = st_size_t;
+        using  st_kernel_id_t = ctx_t::kernel_id_t;
+        using  st_kernel_arg_type_t = ctx_t::kernel_arg_type_t;
+        using  st_status_t = ctx_t::status_t;
+    }
+
+    constexpr st_kernel_arg_type_t ctx_t::ARG_TYPE_NONE;
+    constexpr st_kernel_arg_type_t ctx_t::ARG_TYPE_VALUE;
+    constexpr st_kernel_arg_type_t ctx_t::ARG_TYPE_RAW_PTR;
+    constexpr st_kernel_arg_type_t ctx_t::ARG_TYPE_CL_ARGUMENT;
+    constexpr st_kernel_arg_type_t ctx_t::ARG_TYPE_CL_BUFFER;
+    constexpr st_kernel_arg_type_t ctx_t::ARG_TYPE_INVALID;
+    constexpr st_size_t ctx_t::MIN_NUM_REMAP_BUFFER_ARGS;
 
-    constexpr _this_t::kernel_arg_type_t _this_t::ARG_TYPE_NONE;
-    constexpr _this_t::kernel_arg_type_t _this_t::ARG_TYPE_VALUE;
-    constexpr _this_t::kernel_arg_type_t _this_t::ARG_TYPE_RAW_PTR;
-    constexpr _this_t::kernel_arg_type_t _this_t::ARG_TYPE_CL_ARGUMENT;
-    constexpr _this_t::kernel_arg_type_t _this_t::ARG_TYPE_CL_BUFFER;
-    constexpr _this_t::kernel_arg_type_t _this_t::ARG_TYPE_INVALID;
-    constexpr _this_t::size_type _this_t::MIN_NUM_REMAP_BUFFER_ARGS;
+    constexpr ctx_t::program_path_type_t ctx_t::PROGRAM_PATH_ABSOLUTE;
+    constexpr ctx_t::program_path_type_t ctx_t::PROGRAM_PATH_RELATIVE;
 
-    ClContextBase::ClContextBase(
+    ctx_t::ClContextBase(
         const char *const SIXTRL_RESTRICT config_str ) :
+        m_feature_flags(),
         m_cl_programs(),
         m_cl_kernels(),
         m_cl_buffers(),
@@ -50,7 +62,9 @@ namespace SIXTRL_CXX_NAMESPACE
         m_available_devices(),
         m_program_data(),
         m_kernel_data(),
-        m_default_compile_options(),
+        m_default_path_to_kernel_dir(),
+        m_default_sixtrlib_inc_dir(),
+        m_default_compile_options( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS ),
         m_config_str(),
         m_cl_context(),
         m_cl_queue(),
@@ -67,9 +81,23 @@ namespace SIXTRL_CXX_NAMESPACE
             this->doParseConfigStringBaseImpl( this->configStr() );
         }
 
-        _this_t::status_t const status = _this_t::GetAvailableNodes(
-            this->m_available_nodes_id, &this->m_available_nodes_info,
-            &this->m_available_devices );
+        if( this->m_default_path_to_kernel_dir.empty() )
+        {
+            this->m_default_path_to_kernel_dir =
+                ctx_t::GetDefaultPathKernelDir();
+        }
+
+        if( this->m_default_sixtrlib_inc_dir.empty() )
+        {
+            this->m_default_sixtrlib_inc_dir =
+                ctx_t::GetDefaultSixTrlLibIncludeDir();
+        }
+
+        st_status_t status = this->doInitDefaultFeatureFlagsBaseImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+
+        status = ctx_t::GetAvailableNodes( this->m_available_nodes_id,
+            &this->m_available_nodes_info, &this->m_available_devices );
 
         SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
         ( void )status;
@@ -77,9 +105,10 @@ namespace SIXTRL_CXX_NAMESPACE
         this->doInitDefaultProgramsBaseImpl();
     }
 
-    ClContextBase::ClContextBase(
-        _this_t::size_type const node_index,
+    ctx_t::ClContextBase(
+        st_size_t const node_index,
         const char *const SIXTRL_RESTRICT config_str ) :
+        m_feature_flags(),
         m_cl_programs(),
         m_cl_kernels(),
         m_cl_buffers(),
@@ -88,7 +117,9 @@ namespace SIXTRL_CXX_NAMESPACE
         m_available_devices(),
         m_program_data(),
         m_kernel_data(),
-        m_default_compile_options(),
+        m_default_path_to_kernel_dir(),
+        m_default_sixtrlib_inc_dir(),
+        m_default_compile_options( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS ),
         m_config_str(),
         m_cl_context(),
         m_cl_queue(),
@@ -106,9 +137,23 @@ namespace SIXTRL_CXX_NAMESPACE
             this->doParseConfigStringBaseImpl( this->configStr() );
         }
 
-        _this_t::status_t const status = _this_t::GetAvailableNodes(
-            this->m_available_nodes_id, &this->m_available_nodes_info,
-            &this->m_available_devices );
+        if( this->m_default_path_to_kernel_dir.empty() )
+        {
+            this->m_default_path_to_kernel_dir =
+                ctx_t::GetDefaultPathKernelDir();
+        }
+
+        if( this->m_default_sixtrlib_inc_dir.empty() )
+        {
+            this->m_default_sixtrlib_inc_dir =
+                ctx_t::GetDefaultSixTrlLibIncludeDir();
+        }
+
+        st_status_t status = this->doInitDefaultFeatureFlagsBaseImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+
+        status = ctx_t::GetAvailableNodes( this->m_available_nodes_id,
+            &this->m_available_nodes_info, &this->m_available_devices );
 
         SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
         ( void )status;
@@ -125,9 +170,10 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    ClContextBase::ClContextBase(
-        _this_t::node_id_t const node_id,
+    ctx_t::ClContextBase(
+        ctx_t::node_id_t const node_id,
         const char *const SIXTRL_RESTRICT config_str ) :
+        m_feature_flags(),
         m_cl_programs(),
         m_cl_kernels(),
         m_cl_buffers(),
@@ -136,7 +182,9 @@ namespace SIXTRL_CXX_NAMESPACE
         m_available_devices(),
         m_program_data(),
         m_kernel_data(),
-        m_default_compile_options(),
+        m_default_path_to_kernel_dir(),
+        m_default_sixtrlib_inc_dir(),
+        m_default_compile_options( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS ),
         m_config_str(),
         m_cl_context(),
         m_cl_queue(),
@@ -154,9 +202,23 @@ namespace SIXTRL_CXX_NAMESPACE
             this->doParseConfigStringBaseImpl( this->configStr() );
         }
 
-        _this_t::status_t const status = _this_t::GetAvailableNodes(
-            this->m_available_nodes_id, &this->m_available_nodes_info,
-            &this->m_available_devices );
+        if( this->m_default_path_to_kernel_dir.empty() )
+        {
+            this->m_default_path_to_kernel_dir =
+                ctx_t::GetDefaultPathKernelDir();
+        }
+
+        if( this->m_default_sixtrlib_inc_dir.empty() )
+        {
+            this->m_default_sixtrlib_inc_dir =
+                ctx_t::GetDefaultSixTrlLibIncludeDir();
+        }
+
+        st_status_t status = this->doInitDefaultFeatureFlagsBaseImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+
+        status = ctx_t::GetAvailableNodes( this->m_available_nodes_id,
+            &this->m_available_nodes_info, &this->m_available_devices );
 
         SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
         ( void )status;
@@ -177,9 +239,10 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    ClContextBase::ClContextBase(
+    ctx_t::ClContextBase(
         char const* node_id_str,
         const char *const SIXTRL_RESTRICT config_str ) :
+        m_feature_flags(),
         m_cl_programs(),
         m_cl_kernels(),
         m_cl_buffers(),
@@ -188,7 +251,9 @@ namespace SIXTRL_CXX_NAMESPACE
         m_available_devices(),
         m_program_data(),
         m_kernel_data(),
-        m_default_compile_options(),
+        m_default_path_to_kernel_dir(),
+        m_default_sixtrlib_inc_dir(),
+        m_default_compile_options( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS ),
         m_config_str(),
         m_cl_context(),
         m_cl_queue(),
@@ -206,16 +271,30 @@ namespace SIXTRL_CXX_NAMESPACE
             this->doParseConfigStringBaseImpl( this->configStr() );
         }
 
-        _this_t::status_t const status = _this_t::GetAvailableNodes(
-            this->m_available_nodes_id, &this->m_available_nodes_info,
-            &this->m_available_devices );
+        if( this->m_default_path_to_kernel_dir.empty() )
+        {
+            this->m_default_path_to_kernel_dir =
+                ctx_t::GetDefaultPathKernelDir();
+        }
+
+        if( this->m_default_sixtrlib_inc_dir.empty() )
+        {
+            this->m_default_sixtrlib_inc_dir =
+                ctx_t::GetDefaultSixTrlLibIncludeDir();
+        }
+
+        st_status_t status = this->doInitDefaultFeatureFlagsBaseImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+
+        status = ctx_t::GetAvailableNodes( this->m_available_nodes_id,
+            &this->m_available_nodes_info, &this->m_available_devices );
 
         SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
         ( void )status;
 
         this->doInitDefaultProgramsBaseImpl();
 
-        _this_t::size_type const node_index =
+        st_size_t const node_index =
             this->findAvailableNodesIndex( node_id_str );
 
         if( ( node_index < this->numAvailableNodes() ) &&
@@ -228,10 +307,11 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    ClContextBase::ClContextBase(
-        _this_t::platform_id_t const platform_idx,
-        _this_t::device_id_t const device_idx,
+    ctx_t::ClContextBase(
+        ctx_t::platform_id_t const platform_idx,
+        ctx_t::device_id_t const device_idx,
         const char *const SIXTRL_RESTRICT config_str ) :
+        m_feature_flags(),
         m_cl_programs(),
         m_cl_kernels(),
         m_cl_buffers(),
@@ -240,7 +320,9 @@ namespace SIXTRL_CXX_NAMESPACE
         m_available_devices(),
         m_program_data(),
         m_kernel_data(),
-        m_default_compile_options(),
+        m_default_path_to_kernel_dir(),
+        m_default_sixtrlib_inc_dir(),
+        m_default_compile_options( SIXTRL_DEFAULT_OPENCL_COMPILER_FLAGS ),
         m_config_str(),
         m_cl_context(),
         m_cl_queue(),
@@ -258,16 +340,30 @@ namespace SIXTRL_CXX_NAMESPACE
             this->doParseConfigStringBaseImpl( this->configStr() );
         }
 
-        _this_t::status_t const status = _this_t::GetAvailableNodes(
-            this->m_available_nodes_id, &this->m_available_nodes_info,
-            &this->m_available_devices );
+        if( this->m_default_path_to_kernel_dir.empty() )
+        {
+            this->m_default_path_to_kernel_dir =
+                ctx_t::GetDefaultPathKernelDir();
+        }
+
+        if( this->m_default_sixtrlib_inc_dir.empty() )
+        {
+            this->m_default_sixtrlib_inc_dir =
+                ctx_t::GetDefaultSixTrlLibIncludeDir();
+        }
+
+        st_status_t status = this->doInitDefaultFeatureFlagsBaseImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+
+        status = ctx_t::GetAvailableNodes( this->m_available_nodes_id,
+            &this->m_available_nodes_info, &this->m_available_devices );
 
         SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
         ( void )status;
 
         this->doInitDefaultProgramsBaseImpl();
 
-        _this_t::size_type const node_index =
+        st_size_t const node_index =
             this->findAvailableNodesIndex( platform_idx, device_idx );
 
         if( ( node_index < this->numAvailableNodes() ) &&
@@ -280,7 +376,7 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    ClContextBase::~ClContextBase() SIXTRL_NOEXCEPT
+    ctx_t::~ClContextBase() SIXTRL_NOEXCEPT
     {
         if( !this->m_available_nodes_info.empty() )
         {
@@ -293,17 +389,77 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    cl::Buffer const& ClContextBase::internalStatusFlagsBuffer() const SIXTRL_NOEXCEPT
+    /* --------------------------------------------------------------------- */
+
+    std::string const&
+    ctx_t::default_path_to_kernel_dir_str() const SIXTRL_NOEXCEPT
+    {
+        return this->m_default_path_to_kernel_dir;
+    }
+
+    char const* ctx_t::default_to_kernel_dir() const SIXTRL_NOEXCEPT
+    {
+        return this->m_default_path_to_kernel_dir.c_str();
+    }
+
+    void ctx_t::set_default_path_to_kernel_dir(
+        std::string const& SIXTRL_RESTRICT_REF default_path )
+    {
+        this->m_default_path_to_kernel_dir = default_path;
+    }
+
+    void ctx_t::set_default_path_to_kernel_dir(
+        char const* SIXTRL_RESTRICT default_path )
+    {
+        if( ( default_path != nullptr ) &&
+            ( std::strlen( default_path ) > st_size_t{ 0 } ) )
+        {
+            this->m_default_path_to_kernel_dir = default_path;
+        }
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    std::string const&
+    ctx_t::default_sixtrlib_inc_dir_str() const SIXTRL_NOEXCEPT
+    {
+        return this->m_default_sixtrlib_inc_dir;
+    }
+
+    char const* ctx_t::default_sixtrlib_inc_dir() const SIXTRL_NOEXCEPT
+    {
+        return this->m_default_sixtrlib_inc_dir.c_str();
+    }
+
+    void ctx_t::set_default_sixtrlib_inc_dir(
+        std::string const& SIXTRL_RESTRICT_REF include_path )
+    {
+        this->m_default_sixtrlib_inc_dir = include_path;
+    }
+
+    void ctx_t::set_default_sixtrlib_inc_dir(
+        char const* SIXTRL_RESTRICT include_path )
+    {
+        if( ( include_path != nullptr ) &&
+            ( std::strlen( include_path ) > st_size_t{ 0 } ) )
+        {
+            this->m_default_path_to_kernel_dir = include_path;
+        }
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    cl::Buffer const& ctx_t::internalStatusFlagsBuffer() const SIXTRL_NOEXCEPT
     {
         return this->m_cl_success_flag;
     }
 
-    cl::Buffer& ClContextBase::internalStatusFlagsBuffer() SIXTRL_NOEXCEPT
+    cl::Buffer& ctx_t::internalStatusFlagsBuffer() SIXTRL_NOEXCEPT
     {
         return this->m_cl_success_flag;
     }
 
-    _this_t::size_type ClContextBase::numAvailableNodes() const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::numAvailableNodes() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_available_nodes_id.size() ==
                        this->m_available_nodes_info.size() );
@@ -311,16 +467,16 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_available_nodes_id.size();
     }
 
-    _this_t::node_info_t const*
-    ClContextBase::availableNodesInfoBegin() const SIXTRL_NOEXCEPT
+    ctx_t::node_info_t const*
+    ctx_t::availableNodesInfoBegin() const SIXTRL_NOEXCEPT
     {
         return this->m_available_nodes_info.data();
     }
 
-    _this_t::node_info_t const*
-    ClContextBase::availableNodesInfoEnd()   const SIXTRL_NOEXCEPT
+    ctx_t::node_info_t const*
+    ctx_t::availableNodesInfoEnd()   const SIXTRL_NOEXCEPT
     {
-        _this_t::node_info_t const* ptr_end =
+        ctx_t::node_info_t const* ptr_end =
             this->availableNodesInfoBegin();
 
         if( ptr_end != nullptr )
@@ -331,17 +487,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return ptr_end;
     }
 
-    _this_t::node_info_t const*
-    ClContextBase::defaultNodeInfo() const SIXTRL_NOEXCEPT
+    ctx_t::node_info_t const*
+    ctx_t::defaultNodeInfo() const SIXTRL_NOEXCEPT
     {
         return this->availableNodesInfoBegin();
     }
 
-    _this_t::node_id_t ClContextBase::defaultNodeId() const SIXTRL_NOEXCEPT
+    ctx_t::node_id_t ctx_t::defaultNodeId() const SIXTRL_NOEXCEPT
     {
         NS(ComputeNodeId) default_node_id;
 
-        _this_t::node_info_t const* default_node_info = this->defaultNodeInfo();
+        ctx_t::node_info_t const* default_node_info = this->defaultNodeInfo();
         NS(ComputeNodeId_preset)( &default_node_id );
 
         if( default_node_info != nullptr )
@@ -352,14 +508,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return default_node_id;
     }
 
-    bool ClContextBase::isNodeIndexAvailable(
-         _this_t::size_type const node_index ) const SIXTRL_RESTRICT
+    bool ctx_t::isNodeIndexAvailable(
+         st_size_t const node_index ) const SIXTRL_NOEXCEPT
     {
         return ( node_index < this->numAvailableNodes() );
     }
 
-    bool ClContextBase::isNodeIdAvailable(
-        _this_t::node_id_t const node_id ) const SIXTRL_NOEXCEPT
+    bool ctx_t::isNodeIdAvailable(
+        ctx_t::node_id_t const node_id ) const SIXTRL_NOEXCEPT
     {
         platform_id_t const platform_index =
             NS(ComputeNodeId_get_platform_id)( &node_id );
@@ -371,22 +527,22 @@ namespace SIXTRL_CXX_NAMESPACE
                  this->findAvailableNodesIndex( platform_index, device_index ) );
     }
 
-    bool ClContextBase::isNodeIdAvailable(
-        _this_t::platform_id_t const platform_index,
-        _this_t::device_id_t  const device_index ) const SIXTRL_NOEXCEPT
+    bool ctx_t::isNodeIdAvailable(
+        ctx_t::platform_id_t const platform_index,
+        ctx_t::device_id_t  const device_index ) const SIXTRL_NOEXCEPT
     {
         return ( this->numAvailableNodes() > this->findAvailableNodesIndex(
             platform_index, device_index ) );
     }
 
-    bool ClContextBase::isNodeIdAvailable(
+    bool ctx_t::isNodeIdAvailable(
         char const* node_id_str ) const SIXTRL_NOEXCEPT
     {
         return ( this->numAvailableNodes() >
                  this->findAvailableNodesIndex( node_id_str ) );
     }
 
-    bool ClContextBase::isDefaultNode(
+    bool ctx_t::isDefaultNode(
         char const* node_id_str ) const SIXTRL_NOEXCEPT
     {
         node_id_t const default_node_id = this->defaultNodeId();
@@ -395,15 +551,15 @@ namespace SIXTRL_CXX_NAMESPACE
             this->ptrAvailableNodesId( node_id_str ), &default_node_id ) );
     }
 
-    bool ClContextBase::isDefaultNode(
-        _this_t::node_id_t const node_id ) const SIXTRL_NOEXCEPT
+    bool ctx_t::isDefaultNode(
+        ctx_t::node_id_t const node_id ) const SIXTRL_NOEXCEPT
     {
         node_id_t const default_node_id = this->defaultNodeId();
         return ( NS(ComputeNodeId_are_equal)( &node_id, &default_node_id ) );
     }
 
-    bool ClContextBase::isDefaultNode(
-        _this_t::size_type const node_index ) const SIXTRL_NOEXCEPT
+    bool ctx_t::isDefaultNode(
+        st_size_t const node_index ) const SIXTRL_NOEXCEPT
     {
         node_id_t const default_node_id = this->defaultNodeId();
 
@@ -411,9 +567,9 @@ namespace SIXTRL_CXX_NAMESPACE
             this->ptrAvailableNodesId( node_index ), &default_node_id ) );
     }
 
-    bool ClContextBase::isDefaultNode(
-        _this_t::platform_id_t const platform_index,
-        _this_t::device_id_t const device_index ) const SIXTRL_NOEXCEPT
+    bool ctx_t::isDefaultNode(
+        ctx_t::platform_id_t const platform_index,
+        ctx_t::device_id_t const device_index ) const SIXTRL_NOEXCEPT
     {
         node_id_t const default_node_id = this->defaultNodeId();
 
@@ -422,16 +578,16 @@ namespace SIXTRL_CXX_NAMESPACE
                                        &default_node_id ) );
     }
 
-    _this_t::node_id_t const* ClContextBase::ptrAvailableNodesId(
-        _this_t::size_type const index ) const SIXTRL_NOEXCEPT
+    ctx_t::node_id_t const* ctx_t::ptrAvailableNodesId(
+        st_size_t const index ) const SIXTRL_NOEXCEPT
     {
         return ( index < this->numAvailableNodes() )
                ? &this->m_available_nodes_id[ index ] : nullptr;
     }
 
-    _this_t::node_id_t const* ClContextBase::ptrAvailableNodesId(
-        _this_t::platform_id_t const platform_index,
-        _this_t::device_id_t   const device_index ) const SIXTRL_NOEXCEPT
+    ctx_t::node_id_t const* ctx_t::ptrAvailableNodesId(
+        ctx_t::platform_id_t const platform_index,
+        ctx_t::device_id_t   const device_index ) const SIXTRL_NOEXCEPT
     {
         size_type const index =
             this->findAvailableNodesIndex( platform_index, device_index );
@@ -440,7 +596,7 @@ namespace SIXTRL_CXX_NAMESPACE
                ? &this->m_available_nodes_id[ index ] : nullptr;
     }
 
-    _this_t::node_id_t const* ClContextBase::ptrAvailableNodesId(
+    ctx_t::node_id_t const* ctx_t::ptrAvailableNodesId(
         char const* SIXTRL_RESTRICT node_id_str ) const SIXTRL_NOEXCEPT
     {
         size_type const index = this->findAvailableNodesIndex( node_id_str );
@@ -449,14 +605,14 @@ namespace SIXTRL_CXX_NAMESPACE
                ? &this->m_available_nodes_id[ index ] : nullptr;
     }
 
-    _this_t::node_info_t const* ClContextBase::ptrAvailableNodesInfo(
+    ctx_t::node_info_t const* ctx_t::ptrAvailableNodesInfo(
         size_type const index ) const SIXTRL_NOEXCEPT
     {
         return ( index < this->numAvailableNodes() )
                ? &this->m_available_nodes_info[ index ] : nullptr;
     }
 
-    _this_t::node_info_t const* ClContextBase::ptrAvailableNodesInfo(
+    ctx_t::node_info_t const* ctx_t::ptrAvailableNodesInfo(
         char const* SIXTRL_RESTRICT node_id_str ) const SIXTRL_NOEXCEPT
     {
         size_type const index = this->findAvailableNodesIndex( node_id_str );
@@ -465,8 +621,8 @@ namespace SIXTRL_CXX_NAMESPACE
                ? &this->m_available_nodes_info[ index ] : nullptr;
     }
 
-    _this_t::node_info_t const* ClContextBase::ptrAvailableNodesInfo(
-        _this_t::node_id_t const node_id ) const SIXTRL_NOEXCEPT
+    ctx_t::node_info_t const* ctx_t::ptrAvailableNodesInfo(
+        ctx_t::node_id_t const node_id ) const SIXTRL_NOEXCEPT
     {
         size_type const index = this->findAvailableNodesIndex(
                                     NS(ComputeNodeId_get_platform_id)( &node_id ),
@@ -476,12 +632,12 @@ namespace SIXTRL_CXX_NAMESPACE
                ? &this->m_available_nodes_info[ index ] : nullptr;
     }
 
-    bool ClContextBase::isAvailableNodeAMDPlatform(
-        _this_t::size_type const index ) const SIXTRL_NOEXCEPT
+    bool ctx_t::isAvailableNodeAMDPlatform(
+        st_size_t const index ) const SIXTRL_NOEXCEPT
     {
         bool is_amd_platform = false;
 
-        _this_t::node_info_t const* node_info =
+        ctx_t::node_info_t const* node_info =
             this->ptrAvailableNodesInfo( index );
 
         if( node_info != nullptr )
@@ -491,7 +647,7 @@ namespace SIXTRL_CXX_NAMESPACE
             std::strncpy( &_temp[ 0 ], ::NS(ComputeNodeInfo_get_platform)(
                 node_info ), 4u );
 
-            std::transform( &_temp[ 0 ], &_temp[ 5 ], &_temp[ 0 ],
+            std::transform( &_temp[ 0 ], &_temp[ 4 ], &_temp[ 0 ],
                 [](unsigned char c){ return std::tolower(c); } );
 
             is_amd_platform = ( 0 == std::strncmp( &_temp[ 0 ], "amd ", 4u ) );
@@ -500,14 +656,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return is_amd_platform;
     }
 
-    bool ClContextBase::hasSelectedNode() const SIXTRL_NOEXCEPT
+    bool ctx_t::hasSelectedNode() const SIXTRL_NOEXCEPT
     {
         return ( ( this->m_selected_node_index >= 0 ) &&
                  ( this->numAvailableNodes() > static_cast< size_type >(
                        this->m_selected_node_index ) ) );
     }
 
-    cl::Device const* ClContextBase::selectedNodeDevice() const SIXTRL_NOEXCEPT
+    cl::Device const* ctx_t::selectedNodeDevice() const SIXTRL_NOEXCEPT
     {
         cl::Device const* ptr_selected_device = nullptr;
 
@@ -525,36 +681,36 @@ namespace SIXTRL_CXX_NAMESPACE
         return ptr_selected_device;
     }
 
-    cl::Device* ClContextBase::selectedNodeDevice() SIXTRL_NOEXCEPT
+    cl::Device* ctx_t::selectedNodeDevice() SIXTRL_NOEXCEPT
     {
         return const_cast< cl::Device* >(
             static_cast< ClContextBase const& >( *this ).selectedNodeDevice() );
     }
 
-    _this_t::node_id_t const*
-    ClContextBase::ptrSelectedNodeId() const SIXTRL_NOEXCEPT
+    ctx_t::node_id_t const*
+    ctx_t::ptrSelectedNodeId() const SIXTRL_NOEXCEPT
     {
         return this->ptrAvailableNodesId( static_cast< size_type >(
             this->m_selected_node_index ) );
     }
 
-    _this_t::node_info_t const*
-    ClContextBase::ptrSelectedNodeInfo() const SIXTRL_NOEXCEPT
+    ctx_t::node_info_t const*
+    ctx_t::ptrSelectedNodeInfo() const SIXTRL_NOEXCEPT
     {
         return this->ptrAvailableNodesInfo( static_cast< size_type >(
             this->m_selected_node_index ) );
     }
 
-    _this_t::size_type ClContextBase::selectedNodeIndex() const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::selectedNodeIndex() const SIXTRL_NOEXCEPT
     {
-        using size_t = _this_t::size_type;
+        using size_t = st_size_t;
 
         return ( this->hasSelectedNode() )
             ? static_cast< size_t >( this->m_selected_node_index )
             : this->numAvailableNodes();
     }
 
-    std::string ClContextBase::selectedNodeIdStr() const SIXTRL_NOEXCEPT
+    std::string ctx_t::selectedNodeIdStr() const SIXTRL_NOEXCEPT
     {
         char node_id_str[ 32 ];
         std::memset( &node_id_str[ 0 ], ( int )'\0', 32 );
@@ -567,14 +723,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return std::string{ "" };
     }
 
-    bool ClContextBase::selectedNodeIdStr( char* SIXTRL_RESTRICT node_id_str,
-        _this_t::size_type const max_str_length ) const SIXTRL_NOEXCEPT
+    bool ctx_t::selectedNodeIdStr( char* SIXTRL_RESTRICT node_id_str,
+        st_size_t const max_str_length ) const SIXTRL_NOEXCEPT
     {
         return ( 0 == NS(ComputeNodeId_to_string)(
             this->ptrSelectedNodeId(), node_id_str, max_str_length ) );
     }
 
-    bool ClContextBase::selectNode( size_type const node_index )
+    bool ctx_t::selectNode( size_type const node_index )
     {
         bool success = false;
 
@@ -597,7 +753,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool ClContextBase::selectNode( node_id_t const node_id )
+    bool ctx_t::selectNode( node_id_t const node_id )
     {
         bool success = false;
 
@@ -616,9 +772,9 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool ClContextBase::selectNode(
-         _this_t::platform_id_t const platform_idx,
-         _this_t::device_id_t   const device_idx )
+    bool ctx_t::selectNode(
+         ctx_t::platform_id_t const platform_idx,
+         ctx_t::device_id_t   const device_idx )
     {
         bool success = false;
 
@@ -631,7 +787,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool ClContextBase::selectNode( char const* node_id_str )
+    bool ctx_t::selectNode( char const* node_id_str )
     {
         bool success = false;
 
@@ -643,15 +799,15 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool ClContextBase::doSelectNode( size_type const node_index )
+    bool ctx_t::doSelectNode( size_type const node_index )
     {
         return this->doSelectNodeBaseImpl( node_index );
     }
 
-    _this_t::status_t ClContextBase::doSetStatusFlags(
-        _this_t::status_flag_t const value )
+    st_status_t ctx_t::doSetStatusFlags(
+        ctx_t::status_flag_t const value )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cl::CommandQueue* queue = this->openClQueue();
 
         if( ( queue != nullptr ) &&
@@ -661,7 +817,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             cl_int const ret = queue->enqueueWriteBuffer(
                 this->internalStatusFlagsBuffer(), CL_TRUE, 0,
-                    sizeof( _this_t::status_flag_t ),
+                    sizeof( ctx_t::status_flag_t ),
                         this->doGetPtrLocalStatusFlags() );
 
             if( ret == CL_SUCCESS )
@@ -673,10 +829,10 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t ClContextBase::doFetchStatusFlags(
-        _this_t::status_flag_t* SIXTRL_RESTRICT ptr_status_flags )
+    st_status_t ctx_t::doFetchStatusFlags(
+        ctx_t::status_flag_t* SIXTRL_RESTRICT ptr_status_flags )
     {
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
         cl::CommandQueue* queue = this->openClQueue();
 
         if( ( queue != nullptr ) &&
@@ -687,7 +843,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             cl_int const ret = queue->enqueueReadBuffer(
                 this->internalStatusFlagsBuffer(), CL_TRUE, 0,
-                    sizeof( _this_t::status_flag_t ),
+                    sizeof( ctx_t::status_flag_t ),
                         this->doGetPtrLocalStatusFlags() );
 
             if( ret == CL_SUCCESS )
@@ -696,26 +852,39 @@ namespace SIXTRL_CXX_NAMESPACE
                     *this->doGetPtrLocalStatusFlags() );
             }
 
+            if( ( ptr_status_flags != SIXTRL_NULLPTR ) &&
+                ( status == st::ARCH_STATUS_SUCCESS ) )
+            {
+                *ptr_status_flags = *this->doGetPtrLocalStatusFlags();
+            }
+
             queue->finish();
         }
 
+        if( ( status == st::ARCH_STATUS_SUCCESS ) &&
+            ( ptr_status_flags != nullptr ) &&
+            ( this->doGetPtrLocalStatusFlags() != nullptr ) )
+        {
+            *ptr_status_flags = *this->doGetPtrLocalStatusFlags();
+        }
+
         return status;
     }
 
-    _this_t::status_t ClContextBase::doAssignStatusFlagsArg(
+    st_status_t ctx_t::doAssignStatusFlagsArg(
         cl::Buffer& SIXTRL_RESTRICT_REF status_flags_arg )
     {
         return this->doAssignStatusFlagsArgBaseImpl( status_flags_arg );
     }
 
 
-    _this_t::status_t ClContextBase::doAssignStatusFlagsArgBaseImpl(
+    st_status_t ctx_t::doAssignStatusFlagsArgBaseImpl(
             cl::Buffer& SIXTRL_RESTRICT_REF status_flags_arg )
     {
-        using kernel_id_t = _this_t::kernel_id_t;
-        using size_t = _this_t::size_type;
+        using kernel_id_t = ctx_t::kernel_id_t;
+        using size_t = st_size_t;
 
-        _this_t::status_t status = st::ARCH_STATUS_SUCCESS;
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
 
         if( this->has_remapping_kernel() )
         {
@@ -727,10 +896,10 @@ namespace SIXTRL_CXX_NAMESPACE
             {
                 size_t const num_args = this->kernelNumArgs( kernel_id );
 
-                if( num_args >= _this_t::MIN_NUM_REMAP_BUFFER_ARGS )
+                if( num_args >= ctx_t::MIN_NUM_REMAP_BUFFER_ARGS )
                 {
                     if( ( this->debugMode() ) &&
-                        ( num_args > _this_t::MIN_NUM_REMAP_BUFFER_ARGS ) )
+                        ( num_args > ctx_t::MIN_NUM_REMAP_BUFFER_ARGS ) )
                     {
                         SIXTRL_ASSERT( num_args > size_t{ 1 } );
 
@@ -742,7 +911,7 @@ namespace SIXTRL_CXX_NAMESPACE
                         status = st::ARCH_STATUS_GENERAL_FAILURE;
                     }
                 }
-                else if( num_args < _this_t::MIN_NUM_REMAP_BUFFER_ARGS )
+                else if( num_args < ctx_t::MIN_NUM_REMAP_BUFFER_ARGS )
                 {
                     status = st::ARCH_STATUS_GENERAL_FAILURE;
                 }
@@ -752,17 +921,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t ClContextBase::doAssignSlotSizeArg(
-        _this_t::size_type const slot_size )
+    st_status_t ctx_t::doAssignSlotSizeArg(
+        st_size_t const slot_size )
     {
          return this->doAssignSlotSizeArgBaseImpl( slot_size );
     }
 
-    _this_t::status_t ClContextBase::doAssignSlotSizeArgBaseImpl(
-        _this_t::size_type const slot_size )
+    st_status_t ctx_t::doAssignSlotSizeArgBaseImpl(
+        st_size_t const slot_size )
     {
-        using size_t = _this_t::size_type;
-        _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        using size_t = st_size_t;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         if( slot_size > size_t{ 0 } )
         {
@@ -770,16 +939,16 @@ namespace SIXTRL_CXX_NAMESPACE
 
             if( this->has_remapping_kernel() )
             {
-                _this_t::kernel_id_t const kernel_id =
+                ctx_t::kernel_id_t const kernel_id =
                     this->remapping_kernel_id();
 
                 if( ( kernel_id != st::ARCH_ILLEGAL_KERNEL_ID ) &&
-                    ( kernel_id >= _this_t::kernel_id_t{ 0 } ) &&
+                    ( kernel_id >= ctx_t::kernel_id_t{ 0 } ) &&
                     ( kernel_id <  static_cast< size_t >(
                             this->numAvailableKernels() ) ) )
                 {
                     if( this->kernelNumArgs( kernel_id ) >=
-                        _this_t::MIN_NUM_REMAP_BUFFER_ARGS )
+                        ctx_t::MIN_NUM_REMAP_BUFFER_ARGS )
                     {
                         uint64_t const slot_size_arg =
                             static_cast< uint64_t >( slot_size );
@@ -798,11 +967,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    void ClContextBase::doSetConfigStr(
+    void ctx_t::doSetConfigStr(
         const char *const SIXTRL_RESTRICT config_str )
     {
         if( ( config_str != nullptr ) &&
-            ( std::strlen( config_str ) > _this_t::size_type{ 0 } ) )
+            ( std::strlen( config_str ) > st_size_t{ 0 } ) )
         {
             this->m_config_str = std::string{ config_str };
         }
@@ -814,7 +983,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    bool ClContextBase::doSelectNodeBaseImpl( size_type const index )
+    bool ctx_t::doSelectNodeBaseImpl( size_type const index )
     {
         bool success = false;
 
@@ -879,7 +1048,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    void ClContextBase::printNodesInfo() const SIXTRL_NOEXCEPT
+    void ctx_t::printNodesInfo() const SIXTRL_NOEXCEPT
     {
         if( this->numAvailableNodes() > size_type{ 0 } )
         {
@@ -901,19 +1070,35 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    char const* ClContextBase::configStr() const SIXTRL_NOEXCEPT
+    char const* ctx_t::configStr() const SIXTRL_NOEXCEPT
     {
         return this->m_config_str.c_str();
     }
 
-    void ClContextBase::clear()
+    st_status_t ctx_t::reinit_default_programs()
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( !this->hasSelectedNode() )
+        {
+            this->clear();
+            this->doInitDefaultPrograms();
+            this->doInitDefaultKernels();
+
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    void ctx_t::clear()
     {
         this->doClear();
         this->doInitDefaultPrograms();
         return;
     }
 
-    void ClContextBase::setDefaultCompileOptions(
+    void ctx_t::setDefaultCompileOptions(
         std::string const& compile_options_str )
     {
         this->setDefaultCompileOptions( compile_options_str.c_str() );
@@ -921,35 +1106,35 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
 
-    void ClContextBase::setDefaultCompileOptions( char const* compile_options_str )
+    void ctx_t::setDefaultCompileOptions( char const* compile_options_str )
     {
         SIXTRL_ASSERT( compile_options_str != nullptr );
         this->m_default_compile_options = compile_options_str;
         return;
     }
 
-    char const* ClContextBase::defaultCompileOptions() const SIXTRL_NOEXCEPT
+    char const* ctx_t::defaultCompileOptions() const SIXTRL_NOEXCEPT
     {
         return this->m_default_compile_options.c_str();
     }
 
-    _this_t::program_id_t ClContextBase::addProgramCode(
+    ctx_t::program_id_t ctx_t::addProgramCode(
         std::string const& source_code )
     {
         return this->addProgramCode(
             source_code.c_str(), this->defaultCompileOptions() );
     }
 
-    _this_t::program_id_t ClContextBase::addProgramCode( char const* source_code )
+    ctx_t::program_id_t ctx_t::addProgramCode( char const* source_code )
     {
         return this->addProgramCode(
             source_code, this->defaultCompileOptions() );
     }
 
-    _this_t::program_id_t ClContextBase::addProgramCode(
+    ctx_t::program_id_t ctx_t::addProgramCode(
         std::string const& source_code, std::string const& compile_options )
     {
-        _this_t::program_id_t program_id = st::ARCH_ILLEGAL_PROGRAM_ID;
+        ctx_t::program_id_t program_id = st::ARCH_ILLEGAL_PROGRAM_ID;
 
         if( !source_code.empty() )
         {
@@ -980,8 +1165,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return program_id;
     }
 
-    _this_t::program_id_t
-    ClContextBase::addProgramCode(
+    ctx_t::program_id_t
+    ctx_t::addProgramCode(
         char const* source_code, char const* compile_options )
     {
         std::string const str_source_code( ( source_code != nullptr )
@@ -994,66 +1179,86 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->addProgramCode( str_source_code, str_compile_options );
     }
 
-    _this_t::program_id_t
-    ClContextBase::addProgramFile( std::string const& path_to_program )
+    ctx_t::program_id_t ctx_t::addProgramFile( std::string const& path_to_prg,
+        program_path_type_t const path_type )
     {
-        return this->addProgramFile(
-                   path_to_program, this->m_default_compile_options );
+        return this->addProgramFile( path_to_prg.c_str(),
+            this->m_default_compile_options.c_str(), path_type );
     }
 
-    _this_t::program_id_t
-    ClContextBase::addProgramFile( char const* path_to_program )
+    ctx_t::program_id_t ctx_t::addProgramFile( char const* path_to_prg,
+        ctx_t::program_path_type_t const path_type )
     {
-        return ( path_to_program != nullptr )
-               ? this->addProgramFile( std::string( path_to_program ) )
-               : st::ARCH_ILLEGAL_PROGRAM_ID;
+        return this->addProgramFile( path_to_prg,
+            this->m_default_compile_options.c_str(), path_type );
     }
 
-    _this_t::program_id_t
-    ClContextBase::addProgramFile(
-        std::string const& path_to_program, std::string const& compile_options )
+    ctx_t::program_id_t ctx_t::addProgramFile(
+        char const* SIXTRL_RESTRICT in_path_to_program,
+        char const* SIXTRL_RESTRICT in_compile_options,
+        ctx_t::program_path_type_t const path_type )
     {
-        std::fstream kernel_file( path_to_program, std::ios::in );
+        ctx_t::program_id_t program_id = st::ARCH_ILLEGAL_PROGRAM_ID;
+        std::string path_to_program;
 
-        if( kernel_file.is_open() )
+        if( ( in_path_to_program != nullptr ) &&
+            ( std::strlen( in_path_to_program ) > st_size_t{ 0 } ) )
         {
-            std::string const source_code(
-                ( std::istreambuf_iterator< char >( kernel_file ) ),
-                std::istreambuf_iterator< char >() );
+            if( path_type == ctx_t::PROGRAM_PATH_ABSOLUTE )
+            {
+                path_to_program = in_path_to_program;
+            }
+            else if( path_type == ctx_t::PROGRAM_PATH_RELATIVE )
+            {
+                path_to_program  = this->m_default_path_to_kernel_dir;
+                path_to_program += in_path_to_program;
+            }
+        }
 
-            if( !source_code.empty() )
+        if( !path_to_program.empty() )
+        {
+            std::fstream program_file( path_to_program, std::ios::in );
+
+            if( program_file.is_open() )
             {
-                program_id_t program_id = this->addProgramCode(
-                                              source_code, compile_options );
+                std::string const source_code(
+                    ( std::istreambuf_iterator< char >( program_file ) ),
+                    std::istreambuf_iterator< char >() );
 
-                if( program_id >= program_id_t{ 0 } )
+                if( !source_code.empty() )
                 {
-                    this->m_program_data[ program_id ].m_file_path =
-                        path_to_program;
-                }
+                    std::string const compile_options =
+                        ( ( in_compile_options != nullptr ) &&
+                          ( std::strlen( in_compile_options ) > st_size_t{ 0 } )
+                        )
+                        ? in_compile_options
+                        : this->m_default_compile_options;
 
-                return program_id;
+                    program_id = this->addProgramCode(
+                        source_code, compile_options );
+
+                    if( program_id >= program_id_t{ 0 } )
+                    {
+                        this->m_program_data[ program_id ].m_file_path =
+                            path_to_program;
+                    }
+                }
             }
         }
 
-        return st::ARCH_ILLEGAL_PROGRAM_ID;
+        return program_id;
     }
 
-    _this_t::program_id_t
-    ClContextBase::addProgramFile(
-        char const* path_to_program, char const* compile_options )
+    ctx_t::program_id_t ctx_t::addProgramFile(
+        std::string const& SIXTRL_RESTRICT_REF path_to_program,
+        std::string const& SIXTRL_RESTRICT_REF compile_options,
+        ctx_t::program_path_type_t const path_type )
     {
-        std::string options_str = ( compile_options != nullptr )
-                                  ? std::string( compile_options )
-                                  : this->m_default_compile_options;
-
-        return ( path_to_program != nullptr )
-               ? this->addProgramFile( std::string( path_to_program ), options_str )
-               : st::ARCH_ILLEGAL_PROGRAM_ID;
+        return this->addProgramFile( path_to_program.c_str(),
+            compile_options.c_str(), path_type );
     }
 
-    bool ClContextBase::compileProgram(
-        _this_t::program_id_t const program_id )
+    bool ctx_t::compileProgram( ctx_t::program_id_t const program_id )
     {
         bool success = false;
 
@@ -1072,8 +1277,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    char const* ClContextBase::programSourceCode(
-        _this_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
+    char const* ctx_t::programSourceCode(
+        ctx_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( program_id >= program_id_t{ 0 } ) &&
                  ( this->m_program_data.size() >
@@ -1082,8 +1287,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : nullptr;
     }
 
-    bool ClContextBase::programHasFilePath(
-         _this_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
+    bool ctx_t::programHasFilePath(
+         ctx_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( program_id >= program_id_t{ 0 } ) &&
                  ( this->m_program_data.size() >
@@ -1091,8 +1296,8 @@ namespace SIXTRL_CXX_NAMESPACE
                  ( !this->m_program_data[ program_id ].m_file_path.empty() ) );
     }
 
-    char const* ClContextBase::programPathToFile(
-        _this_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
+    char const* ctx_t::programPathToFile(
+        ctx_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( program_id >= program_id_t{ 0 } ) &&
                  ( this->m_program_data.size() >
@@ -1101,8 +1306,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : nullptr;
     }
 
-    char const* ClContextBase::programCompileOptions(
-        _this_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
+    char const* ctx_t::programCompileOptions(
+        ctx_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( program_id >= program_id_t{ 0 } ) &&
                  ( this->m_program_data.size() >
@@ -1111,8 +1316,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : nullptr;
     }
 
-    char const* ClContextBase::programCompileReport(
-        _this_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
+    char const* ctx_t::programCompileReport(
+        ctx_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( program_id >= program_id_t{ 0 } ) &&
                  ( this->m_program_data.size() >
@@ -1121,8 +1326,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : nullptr;
     }
 
-    bool ClContextBase::isProgramCompiled(
-        _this_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
+    bool ctx_t::isProgramCompiled(
+        ctx_t::program_id_t const program_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( program_id >= program_id_t{ 0 } ) &&
                  ( this->m_program_data.size() >
@@ -1130,21 +1335,20 @@ namespace SIXTRL_CXX_NAMESPACE
             ? this->m_program_data[ program_id ].m_compiled : false;
     }
 
-    _this_t::size_type
-    ClContextBase::numAvailablePrograms() const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::numAvailablePrograms() const SIXTRL_NOEXCEPT
     {
         return this->m_program_data.size();
     }
 
-    _this_t::kernel_id_t ClContextBase::enableKernel(
+    ctx_t::kernel_id_t ctx_t::enableKernel(
         std::string const& kernel_name,
-        _this_t::program_id_t const program_id )
+        ctx_t::program_id_t const program_id )
     {
         return this->enableKernel( kernel_name.c_str(), program_id );
     }
 
-    _this_t::kernel_id_t
-    ClContextBase::enableKernel(
+    ctx_t::kernel_id_t
+    ctx_t::enableKernel(
         char const* kernel_name, program_id_t const program_id )
     {
         kernel_id_t kernel_id = st::ARCH_ILLEGAL_KERNEL_ID;
@@ -1234,8 +1438,8 @@ namespace SIXTRL_CXX_NAMESPACE
                 SIXTRL_ASSERT( num_kernel_args  >= size_type{  0 } );
                 SIXTRL_ASSERT( num_kernel_args  <  size_type{ 32 } );
                 SIXTRL_ASSERT( pref_work_group_size > size_type{ 0 } );
-                SIXTRL_ASSERT( max_work_group_size  >= pref_work_group_size );
-                SIXTRL_ASSERT( max_work_group_size  <= size_type{ 65535 } );
+                SIXTRL_ASSERT( max_work_group_size >= pref_work_group_size );
+                SIXTRL_ASSERT( max_work_group_size <= size_type{ 0x7fffffff } );
 
                 this->m_kernel_data.back().resetArguments( num_kernel_args );
 
@@ -1255,7 +1459,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return kernel_id;
     }
 
-    _this_t::kernel_id_t ClContextBase::findKernelByName(
+    ctx_t::kernel_id_t ctx_t::findKernelByName(
         char const* SIXTRL_RESTRICT kernel_name ) const SIXTRL_NOEXCEPT
     {
         kernel_id_t kernel_id = st::ARCH_ILLEGAL_KERNEL_ID;
@@ -1295,21 +1499,21 @@ namespace SIXTRL_CXX_NAMESPACE
         return kernel_id;
     }
 
-    bool ClContextBase::has_remapping_program() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_remapping_program() const SIXTRL_NOEXCEPT
     {
         return ( ( this->m_remap_program_id >= program_id_t{ 0 } ) &&
                  ( static_cast< size_type >( this->m_remap_program_id ) <
                    this->numAvailablePrograms() ) );
     }
 
-    _this_t::program_id_t
-    ClContextBase::remapping_program_id() const SIXTRL_NOEXCEPT
+    ctx_t::program_id_t
+    ctx_t::remapping_program_id() const SIXTRL_NOEXCEPT
     {
         return ( this->has_remapping_program() )
             ? this->m_remap_program_id : st::ARCH_ILLEGAL_PROGRAM_ID;
     }
 
-    bool ClContextBase::has_remapping_kernel() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_remapping_kernel() const SIXTRL_NOEXCEPT
     {
         return ( ( this->hasSelectedNode() ) &&
                  ( this->m_remap_kernel_id >= kernel_id_t{ 0 } ) &&
@@ -1317,8 +1521,8 @@ namespace SIXTRL_CXX_NAMESPACE
                    this->m_cl_kernels.size() ) );
     }
 
-    char const* ClContextBase::kernelFunctionName(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    char const* ctx_t::kernelFunctionName(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_cl_kernels.size() ==
                        this->m_kernel_data.size() );
@@ -1331,8 +1535,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : nullptr;
     }
 
-    _this_t::size_type ClContextBase::kernelLocalMemSize(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::kernelLocalMemSize(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_cl_kernels.size() ==
                        this->m_kernel_data.size() );
@@ -1345,8 +1549,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : size_type{ 0 };
     }
 
-    _this_t::size_type ClContextBase::kernelNumArgs(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::kernelNumArgs(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_cl_kernels.size() ==
                        this->m_kernel_data.size() );
@@ -1359,8 +1563,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : size_type{ 0 };
     }
 
-    _this_t::size_type ClContextBase::kernelWorkGroupSize(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::kernelWorkGroupSize(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_cl_kernels.size() ==
                        this->m_kernel_data.size() );
@@ -1379,8 +1583,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return work_group_size;
     }
 
-    _this_t::size_type ClContextBase::kernelMaxWorkGroupSize(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::kernelMaxWorkGroupSize(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_cl_kernels.size() ==
                        this->m_kernel_data.size() );
@@ -1393,9 +1597,9 @@ namespace SIXTRL_CXX_NAMESPACE
             : size_type{ 0 };
     }
 
-    bool ClContextBase::setKernelWorkGroupSize(
-        _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type work_group_size ) SIXTRL_NOEXCEPT
+    bool ctx_t::setKernelWorkGroupSize(
+        ctx_t::kernel_id_t const kernel_id,
+        st_size_t work_group_size ) SIXTRL_NOEXCEPT
     {
         bool success = false;
 
@@ -1416,8 +1620,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    _this_t::size_type ClContextBase::kernelPreferredWorkGroupSizeMultiple(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::kernelPreferredWorkGroupSizeMultiple(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_cl_kernels.size() ==
                        this->m_kernel_data.size() );
@@ -1430,8 +1634,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : size_type{ 0 };
     }
 
-    _this_t::program_id_t ClContextBase::programIdByKernelId(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    ctx_t::program_id_t ctx_t::programIdByKernelId(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_cl_kernels.size() ==
                        this->m_kernel_data.size() );
@@ -1444,8 +1648,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : st::ARCH_ILLEGAL_PROGRAM_ID;
     }
 
-    _this_t::size_type ClContextBase::kernelExecCounter(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::kernelExecCounter(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( kernel_id >= kernel_id_t{ 0 } ) &&
                  ( static_cast< size_type >( kernel_id ) <
@@ -1454,20 +1658,20 @@ namespace SIXTRL_CXX_NAMESPACE
             : size_type{ 0 };
     }
 
-    ClArgument* ClContextBase::ptrKernelArgument(
-        _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type const arg_index ) SIXTRL_NOEXCEPT
+    ClArgument* ctx_t::ptrKernelArgument(
+        ctx_t::kernel_id_t const kernel_id,
+        st_size_t const arg_index ) SIXTRL_NOEXCEPT
     {
-        using _this_t = ClContextBase;
+        using ctx_t = ClContextBase;
         using   ptr_t = ClArgument*;
 
-        return const_cast< ptr_t >( static_cast< _this_t const& >(
+        return const_cast< ptr_t >( static_cast< ctx_t const& >(
             *this ).ptrKernelArgument( kernel_id, arg_index ) );
     }
 
-    ClArgument const* ClContextBase::ptrKernelArgument(
-        _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type const arg_index ) const SIXTRL_NOEXCEPT
+    ClArgument const* ctx_t::ptrKernelArgument(
+        ctx_t::kernel_id_t const kernel_id,
+        st_size_t const arg_index ) const SIXTRL_NOEXCEPT
     {
         ClArgument const* ptr_arg = nullptr;
 
@@ -1486,47 +1690,86 @@ namespace SIXTRL_CXX_NAMESPACE
         return ptr_arg;
     }
 
-    _this_t::kernel_arg_type_t ClContextBase::kernelArgumentType(
-        _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type const arg_index) const SIXTRL_NOEXCEPT
+    ctx_t::kernel_arg_type_t ctx_t::kernelArgumentType(
+        ctx_t::kernel_id_t const kernel_id,
+        st_size_t const arg_index) const SIXTRL_NOEXCEPT
     {
         return ( ( static_cast< size_t >( kernel_id ) <
                    this->m_kernel_data.size() ) &&
                  ( arg_index < this->m_kernel_data[ kernel_id ].m_num_args ) )
             ? this->m_kernel_data[ kernel_id ].m_arg_types[ arg_index ]
-            : st::ClContextBase::ARG_TYPE_INVALID;
+            : st::ctx_t::ARG_TYPE_INVALID;
     }
 
-    void ClContextBase::assignKernelArgument(
-        _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type const index,
+    void ctx_t::assignKernelArgument(
+        ctx_t::kernel_id_t const kernel_id, st_size_t const index,
         ClArgument& SIXTRL_RESTRICT_REF arg )
     {
         SIXTRL_ASSERT( arg.context() == this );
-        SIXTRL_ASSERT( arg.size() > _this_t::size_type{ 0 } );
+        SIXTRL_ASSERT( arg.size() > st_size_t{ 0 } );
 
         this->m_kernel_data.at( kernel_id ).setKernelArg(
-            _this_t::ARG_TYPE_CL_ARGUMENT, index, &arg );
+            ctx_t::ARG_TYPE_CL_ARGUMENT, index, &arg );
 
         cl::Kernel* kernel = this->openClKernel( kernel_id );
         if( kernel != nullptr ) kernel->setArg( index, arg.openClBuffer() );
 
     }
 
-    void ClContextBase::assignKernelArgumentClBuffer(
-            _this_t::kernel_id_t const kernel_id,
-            _this_t::size_type const arg_index,
+    void ctx_t::assignKernelArgumentRawPtr(
+        ctx_t::kernel_id_t const kernel_id,
+        st_size_t const arg_index,
+        st_size_t const arg_size, void* ptr )
+    {
+        SIXTRL_ASSERT( arg_size > st_size_t{ 0 } );
+        SIXTRL_ASSERT( ptr != nullptr );
+
+        this->m_kernel_data.at( kernel_id ).setKernelArg(
+            ctx_t::ARG_TYPE_RAW_PTR, arg_index, ptr );
+
+        cl::Kernel* kernel = this->openClKernel( kernel_id );
+        if( kernel != nullptr ) kernel->setArg( arg_index, arg_size, ptr );
+    }
+
+    void ctx_t::assignKernelArgumentClBuffer(
+            ctx_t::kernel_id_t const kernel_id,
+            st_size_t const arg_index,
             cl::Buffer& SIXTRL_RESTRICT_REF cl_buffer_arg )
     {
         this->m_kernel_data.at( kernel_id ).setKernelArg(
-            _this_t::ARG_TYPE_CL_BUFFER, arg_index, &cl_buffer_arg );
+            ctx_t::ARG_TYPE_CL_BUFFER, arg_index, &cl_buffer_arg );
 
         cl::Kernel* kernel = this->openClKernel( kernel_id );
         if( kernel != nullptr ) kernel->setArg( arg_index, cl_buffer_arg );
     }
 
-    void ClContextBase::resetKernelArguments(
-        _this_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
+    void ctx_t::assignKernelArgumentRawPtr(
+            ctx_t::kernel_id_t const kernel_id, st_size_t const arg_index,
+            st_size_t const arg_size,
+            SIXTRL_ARGPTR_DEC void const* ptr ) SIXTRL_NOEXCEPT
+        {
+            SIXTRL_ASSERT( kernel_id >= ctx_t::kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< ctx_t::size_type >(
+                kernel_id ) < this->numAvailableKernels() );
+
+            this->m_kernel_data[ kernel_id ].setKernelArg(
+                    ctx_t::ARG_TYPE_RAW_PTR, arg_index, nullptr );
+
+            cl::Kernel* cxx_kernel = this->openClKernel( kernel_id );
+
+            if( cxx_kernel != nullptr )
+            {
+                ::cl_kernel kernel = cxx_kernel->operator()();
+                cl_int const ret = ::clSetKernelArg(
+                    kernel, arg_index, arg_size, ptr );
+
+                SIXTRL_ASSERT( ret == CL_SUCCESS );
+                ( void )ret;
+            }
+        }
+
+    void ctx_t::resetKernelArguments(
+        ctx_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
         if( ( kernel_id >= kernel_id_t{ 0 } ) && ( static_cast< size_type >(
               kernel_id ) < this->numAvailableKernels() ) )
@@ -1557,23 +1800,21 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    void ClContextBase::resetSingleKernelArgument(
-        _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type const arg_index ) SIXTRL_NOEXCEPT
+    void ctx_t::resetSingleKernelArgument(
+        ctx_t::kernel_id_t const kernel_id,
+        st_size_t const arg_index ) SIXTRL_NOEXCEPT
     {
-        using _this_t = ClContextBase;
-
         cl::Kernel* kernel = this->openClKernel( kernel_id );
         if( kernel != nullptr ) kernel->setArg(
                 arg_index, this->m_default_kernel_arg );
 
         this->m_kernel_data.at( kernel_id ).setKernelArg(
-            _this_t::ARG_TYPE_NONE, arg_index, nullptr );
+            ctx_t::ARG_TYPE_NONE, arg_index, nullptr );
     }
 
-    _this_t::size_type ClContextBase::calculateKernelNumWorkItems(
-        _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type const min_num_work_items ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::calculateKernelNumWorkItems(
+        ctx_t::kernel_id_t const kernel_id,
+        st_size_t const min_num_work_items ) const SIXTRL_NOEXCEPT
     {
         size_type num_threads = min_num_work_items;
         size_type work_group_size = this->kernelWorkGroupSize( kernel_id );
@@ -1598,17 +1839,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return num_threads;
     }
 
-    bool ClContextBase::runKernel(
-        _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type min_num_work_items )
+    bool ctx_t::runKernel(
+        ctx_t::kernel_id_t const kernel_id,
+        st_size_t min_num_work_items )
     {
         return this->runKernel( kernel_id, min_num_work_items,
                          this->kernelWorkGroupSize( kernel_id ) );
     }
 
-    bool ClContextBase::runKernel( _this_t::kernel_id_t const kernel_id,
-        _this_t::size_type const min_num_work_items,
-        _this_t::size_type work_group_size )
+    bool ctx_t::runKernel( ctx_t::kernel_id_t const kernel_id,
+        st_size_t const min_num_work_items,
+        st_size_t work_group_size )
     {
         bool success = false;
 
@@ -1674,8 +1915,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    double ClContextBase::lastExecTime(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    double ctx_t::lastExecTime(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( kernel_id >= kernel_id_t{ 0 } ) &&
                  ( static_cast< size_type >( kernel_id ) <
@@ -1683,8 +1924,8 @@ namespace SIXTRL_CXX_NAMESPACE
             ? this->m_kernel_data[ kernel_id ].m_last_exec_time : double{ 0 };
     }
 
-    double ClContextBase::minExecTime(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    double ctx_t::minExecTime(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( kernel_id >= kernel_id_t{ 0 } ) &&
                  ( static_cast< size_type >( kernel_id ) <
@@ -1692,8 +1933,8 @@ namespace SIXTRL_CXX_NAMESPACE
             ? this->m_kernel_data[ kernel_id ].m_min_exec_time : double{ 0 };
     }
 
-    double ClContextBase::maxExecTime(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    double ctx_t::maxExecTime(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( kernel_id >= kernel_id_t{ 0 } ) &&
                  ( static_cast< size_type >( kernel_id ) <
@@ -1701,8 +1942,8 @@ namespace SIXTRL_CXX_NAMESPACE
             ? this->m_kernel_data[ kernel_id ].m_max_exec_time : double{ 0 };
     }
 
-    double ClContextBase::avgExecTime(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    double ctx_t::avgExecTime(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( kernel_id >= kernel_id_t{ 0 } ) &&
                  ( static_cast< size_type >( kernel_id ) <
@@ -1710,8 +1951,8 @@ namespace SIXTRL_CXX_NAMESPACE
             ? this->m_kernel_data[ kernel_id ].avgExecTime() : double{ 0 };
     }
 
-    _this_t::size_type ClContextBase::lastExecWorkGroupSize(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::lastExecWorkGroupSize(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( kernel_id >= kernel_id_t{ 0 } ) &&
                  ( static_cast< size_type >( kernel_id ) <
@@ -1720,8 +1961,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : size_type{ 0 };
     }
 
-    _this_t::size_type ClContextBase::lastExecNumWorkItems(
-        _this_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::lastExecNumWorkItems(
+        ctx_t::kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT
     {
         return ( ( kernel_id >= kernel_id_t{ 0 } ) &&
                  ( static_cast< size_type >( kernel_id ) <
@@ -1730,8 +1971,8 @@ namespace SIXTRL_CXX_NAMESPACE
             : size_type{ 0 };
     }
 
-    void ClContextBase::resetKernelExecTiming(
-         _this_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
+    void ctx_t::resetKernelExecTiming(
+         ctx_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
         if( ( kernel_id >= kernel_id_t{ 0 } ) &&
             ( static_cast< size_type >( kernel_id ) <
@@ -1743,8 +1984,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    void ClContextBase::addKernelExecTime( double const time,
-        _this_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
+    void ctx_t::addKernelExecTime( double const time,
+        ctx_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
         if( ( kernel_id >= kernel_id_t{ 0 } ) &&
             ( static_cast< size_type >( kernel_id ) <
@@ -1756,15 +1997,15 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    _this_t::kernel_id_t
-    ClContextBase::remapping_kernel_id() const SIXTRL_NOEXCEPT
+    ctx_t::kernel_id_t
+    ctx_t::remapping_kernel_id() const SIXTRL_NOEXCEPT
     {
         return ( this->has_remapping_kernel() )
             ? this->m_remap_kernel_id : st::ARCH_ILLEGAL_KERNEL_ID;
     }
 
-    bool ClContextBase::set_remapping_kernel_id(
-        _this_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
+    bool ctx_t::set_remapping_kernel_id(
+        ctx_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
         bool success = false;
 
@@ -1788,8 +2029,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    _this_t::size_type
-    ClContextBase::numAvailableKernels() const SIXTRL_NOEXCEPT
+    st_size_t
+    ctx_t::numAvailableKernels() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->m_cl_kernels.size() ==
                        this->m_kernel_data.size() );
@@ -1797,8 +2038,8 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->m_cl_kernels.size();
     }
 
-    cl::Program* ClContextBase::openClProgram(
-        _this_t::program_id_t const program_id ) SIXTRL_NOEXCEPT
+    cl::Program* ctx_t::openClProgram(
+        ctx_t::program_id_t const program_id ) SIXTRL_NOEXCEPT
     {
         return ( ( program_id >= program_id_t{ 0 } ) &&
         ( this->m_cl_programs.size() >
@@ -1806,30 +2047,40 @@ namespace SIXTRL_CXX_NAMESPACE
         ? &this->m_cl_programs[ program_id ] : nullptr;
     }
 
-    cl::Kernel* ClContextBase::openClKernel(
-        _this_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
+    cl::Kernel* ctx_t::openClKernel(
+        ctx_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
         return ( ( kernel_id >= kernel_id_t{ 0 } ) &&
             ( this->m_cl_kernels.size() > static_cast< size_type >( kernel_id ) ) )
             ? &this->m_cl_kernels[ kernel_id ] : nullptr;
     }
 
-    cl::CommandQueue* ClContextBase::openClQueue() SIXTRL_NOEXCEPT
+    cl::CommandQueue* ctx_t::openClQueue() SIXTRL_NOEXCEPT
     {
         return &this->m_cl_queue;
     }
 
-    cl::Context* ClContextBase::openClContext() SIXTRL_NOEXCEPT
+    std::uintptr_t ctx_t::openClQueueAddr() const SIXTRL_NOEXCEPT
+    {
+        return reinterpret_cast< std::uintptr_t >( &this->m_cl_queue() );
+    }
+
+    cl::Context* ctx_t::openClContext() SIXTRL_NOEXCEPT
     {
         return &this->m_cl_context;
     }
 
-    bool ClContextBase::debugMode() const  SIXTRL_NOEXCEPT
+    std::uintptr_t ctx_t::openClContextAddr() const SIXTRL_NOEXCEPT
+    {
+        return reinterpret_cast< std::uintptr_t >( &this->m_cl_context() );
+    }
+
+    bool ctx_t::debugMode() const  SIXTRL_NOEXCEPT
     {
         return this->m_debug_mode;
     }
 
-    void ClContextBase::enableDebugMode()  SIXTRL_NOEXCEPT
+    void ctx_t::enableDebugMode()  SIXTRL_NOEXCEPT
     {
         if( ( !this->debugMode() ) && ( !this->hasSelectedNode() ) )
         {
@@ -1841,7 +2092,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    void ClContextBase::disableDebugMode() SIXTRL_NOEXCEPT
+    void ctx_t::disableDebugMode() SIXTRL_NOEXCEPT
     {
         if( ( this->debugMode() ) && ( !this->hasSelectedNode() ) )
         {
@@ -1853,9 +2104,9 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    _this_t::status_flag_t ClContextBase::status_flags()
+    ctx_t::status_flag_t ctx_t::status_flags()
     {
-        _this_t::status_t const status = this->doFetchStatusFlags(
+        st_status_t const status = this->doFetchStatusFlags(
             this->doGetPtrLocalStatusFlags() );
 
         return ( status == st::ARCH_STATUS_SUCCESS )
@@ -1863,15 +2114,15 @@ namespace SIXTRL_CXX_NAMESPACE
             : st::ARCH_DEBUGGING_GENERAL_FAILURE;
     }
 
-    _this_t::status_flag_t ClContextBase::set_status_flags(
-        _this_t::status_flag_t const status_flags )
+    ctx_t::status_flag_t ctx_t::set_status_flags(
+        ctx_t::status_flag_t const status_flags )
     {
         return this->doSetStatusFlags( status_flags );
     }
 
-    _this_t::status_t ClContextBase::prepare_status_flags_for_use()
+    st_status_t ctx_t::prepare_status_flags_for_use()
     {
-        _this_t::status_t const status = this->doSetStatusFlags(
+        st_status_t const status = this->doSetStatusFlags(
             st::ARCH_DEBUGGING_REGISTER_EMPTY );
 
         SIXTRL_ASSERT( ( status != st::ARCH_STATUS_SUCCESS ) ||
@@ -1882,9 +2133,9 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t ClContextBase::eval_status_flags_after_use()
+    st_status_t ctx_t::eval_status_flags_after_use()
     {
-        _this_t::status_t status = this->doFetchStatusFlags(
+        st_status_t status = this->doFetchStatusFlags(
             this->doGetPtrLocalStatusFlags() );
 
         if( status == st::ARCH_STATUS_SUCCESS )
@@ -1905,25 +2156,244 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t ClContextBase::assign_slot_size_arg(
-        _this_t::size_type const slot_size )
+    st_status_t ctx_t::assign_slot_size_arg(
+        st_size_t const slot_size )
     {
         return this->doAssignSlotSizeArg( slot_size );
     }
 
-    _this_t::status_t ClContextBase::assign_status_flags_arg(
-        _this_t::cl_buffer_t& SIXTRL_RESTRICT_REF success_flag_arg )
+    st_status_t ctx_t::assign_status_flags_arg(
+        ctx_t::cl_buffer_t& SIXTRL_RESTRICT_REF success_flag_arg )
     {
         return this->doAssignStatusFlagsArg( success_flag_arg );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ClContextBase::status_t ClContextBase::GetAllowedNodesFromEnvVariable(
-        std::vector< ClContextBase::node_id_t >& allowed_node_ids,
+    st_size_t ctx_t::num_feature_flags() const SIXTRL_NOEXCEPT
+    {
+        return this->m_feature_flags.size();
+    }
+
+    ctx_t::feature_flags_iter_t
+    ctx_t::feature_flags_begin() const SIXTRL_NOEXCEPT
+    {
+        return this->m_feature_flags.begin();
+    }
+
+    ctx_t::feature_flags_iter_t
+    ctx_t::feature_flags_end() const SIXTRL_NOEXCEPT
+    {
+        return this->m_feature_flags.end();
+    }
+
+    bool ctx_t::has_feature_flag(
+        std::string const& SIXTRL_RESTRICT_REF str ) const SIXTRL_NOEXCEPT
+    {
+        return ( ( !str.empty() ) &&
+                 ( this->m_feature_flags.find( str ) !=
+                   this->m_feature_flags.end() ) );
+    }
+
+    bool ctx_t::has_feature_flag(
+        char const* SIXTRL_RESTRICT str ) const SIXTRL_NOEXCEPT
+    {
+        return ( ( str != nullptr ) && ( std::strlen( str ) > 0u ) &&
+                 ( this->m_feature_flags.find( str ) !=
+                   this->m_feature_flags.end() ) );
+    }
+
+    std::string const& ctx_t::feature_flag_str(
+        std::string const& SIXTRL_RESTRICT_REF str ) const
+    {
+        auto it = this->m_feature_flags.end();
+
+        if( !str.empty() )
+        {
+            it = this->m_feature_flags.find( str );
+        }
+
+        if( it == this->m_feature_flags.end() )
+        {
+            std::string error_msg( "feature_flag \"" );
+            error_msg += str;
+            error_msg += "\" not found";
+
+            throw std::runtime_error( error_msg.c_str() );
+        }
+
+        return it->second;
+    }
+
+    std::string const& ctx_t::feature_flag_str(
+        char const* SIXTRL_RESTRICT str ) const
+    {
+        auto it = this->m_feature_flags.end();
+        bool valid_str = false;
+
+        if( ( str != nullptr ) && ( std::strlen( str ) > 0 ) )
+        {
+            valid_str = true;
+            it = this->m_feature_flags.find( str );
+        }
+
+        if( it == this->m_feature_flags.end() )
+        {
+            std::string error_msg( "feature_flag " );
+
+            if( valid_str )
+            {
+                error_msg += "\"";
+                error_msg += str;
+                error_msg += "\" not found";
+            }
+            else
+            {
+                error_msg += " not found, input str empty / illegal";
+            }
+
+            throw std::runtime_error( error_msg.c_str() );
+        }
+
+        return it->second;
+    }
+
+    char const* ctx_t::feature_flag(
+        std::string const& SIXTRL_RESTRICT_REF str ) const SIXTRL_NOEXCEPT
+    {
+        char const* flag_value = nullptr;
+
+        if( !str.empty() )
+        {
+            auto it = this->m_feature_flags.find( str );
+
+            if( it != this->m_feature_flags.end() )
+            {
+                flag_value = it->second.c_str();
+            }
+        }
+
+        return flag_value;
+    }
+
+    char const* ctx_t::feature_flag(
+        char const* SIXTRL_RESTRICT str ) const SIXTRL_NOEXCEPT
+    {
+        char const* flag_value = nullptr;
+
+        if( ( str != nullptr ) && ( std::strlen( str ) > 0u ) )
+        {
+            auto it = this->m_feature_flags.find( str );
+
+            if( it != this->m_feature_flags.end() )
+            {
+                flag_value = it->second.c_str();
+            }
+        }
+
+        return flag_value;
+    }
+
+    void ctx_t::set_feature_flag(
+        std::string const& SIXTRL_RESTRICT_REF str,
+        std::string const& SIXTRL_RESTRICT_REF flag_value )
+    {
+        if( !str.empty() )
+        {
+            this->m_feature_flags.emplace( std::make_pair( str, flag_value ) );
+        }
+    }
+
+    void ctx_t::set_feature_flag( char const* SIXTRL_RESTRICT str,
+        char const* SIXTRL_RESTRICT flag_value )
+    {
+        if( ( str != nullptr ) && ( std::strlen( str ) > 0u ) &&
+            ( flag_value != nullptr ) )
+        {
+            this->m_feature_flags.emplace( std::make_pair( str, flag_value ) );
+        }
+    }
+
+    std::string ctx_t::feature_flag_repr(
+        std::string const& SIXTRL_RESTRICT_REF str,
+        std::string const& SIXTRL_RESTRICT_REF prefix,
+        std::string const& SIXTRL_RESTRICT_REF sep  ) const
+    {
+        std::ostringstream a2str;
+
+        if( this->has_feature_flag( str ) )
+        {
+            a2str << prefix << str << sep << this->feature_flag_str( str );
+        }
+
+        return a2str.str();
+    }
+
+    std::string ctx_t::feature_flag_repr(
+        char const* SIXTRL_RESTRICT str,
+        char const* SIXTRL_RESTRICT prefix,
+        char const* SIXTRL_RESTRICT sep ) const
+    {
+        if( ( str != nullptr ) && ( std::strlen( str ) > 0u ) )
+        {
+            std::string const prefix_str = ( prefix != nullptr )
+                ? std::string{ prefix } : std::string{ "-D" };
+
+            std::string const sep_str = ( sep != nullptr )
+                ? std::string{ sep } : std::string{ "=" };
+
+            return this->feature_flag_repr(
+                std::string{ str }, prefix_str, sep_str );
+        }
+
+        return std::string{};
+    }
+
+    ctx_t::size_type ctx_t::feature_flag_repr_required_capacity(
+        char const* SIXTRL_RESTRICT str, char const* SIXTRL_RESTRICT prefix,
+        char const* SIXTRL_RESTRICT sep ) const
+    {
+        std::string const temp_str_repr(
+            this->feature_flag_repr( str, prefix, sep ) );
+
+        return ( !temp_str_repr.empty() ) ? ( temp_str_repr.size() + 1u ) : 0u;
+    }
+
+    st_status_t ctx_t::feature_flag_repr_as_cstr(
+        char* out_str, size_type out_str_capacity,
+        char const* SIXTRL_RESTRICT str,
+        char const* SIXTRL_RESTRICT prefix,
+        char const* SIXTRL_RESTRICT sep ) const
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( ( out_str != nullptr ) && ( out_str_capacity > 0u ) )
+        {
+            std::string const temp_str_repr(
+                this->feature_flag_repr( str, prefix, sep ) );
+
+            std::memset( out_str, ( int )'\0', out_str_capacity );
+
+            if( ( !temp_str_repr.empty() ) &&
+                ( temp_str_repr.size() < out_str_capacity ) )
+            {
+                std::strncpy( out_str, temp_str_repr.c_str(),
+                              out_str_capacity - 1u );
+
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    st_status_t ctx_t::GetAllowedNodesFromEnvVariable(
+        std::vector< ctx_t::node_id_t >& allowed_node_ids,
         char const* SIXTRL_RESTRICT env_variable_name )
     {
-        _this_t::status_t status = st::ARCH_STATUS_SUCCESS;
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
 
         allowed_node_ids.clear();
         char const* env_var_begin = nullptr;
@@ -1948,7 +2418,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             auto expr_end = (std::cregex_iterator());
 
-            _this_t::node_id_t tnode_id;
+            ctx_t::node_id_t tnode_id;
 
             for( ; expr_it != expr_end ; ++expr_it )
             {
@@ -1965,8 +2435,8 @@ namespace SIXTRL_CXX_NAMESPACE
             if( !allowed_node_ids.empty() )
             {
                 auto cmp_node_ids =
-                []( _this_t::node_id_t const& SIXTRL_RESTRICT_REF lhs,
-                    _this_t::node_id_t const& SIXTRL_RESTRICT_REF rhs )
+                []( ctx_t::node_id_t const& SIXTRL_RESTRICT_REF lhs,
+                    ctx_t::node_id_t const& SIXTRL_RESTRICT_REF rhs )
                 {
                     return (
                         ( ::NS(ComputeNodeId_get_platform_id)( &lhs ) <
@@ -1982,8 +2452,8 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 allowed_node_ids.erase(
                     std::unique( allowed_node_ids.begin(), allowed_node_ids.end(),
-                    []( _this_t::node_id_t const& SIXTRL_RESTRICT_REF lhs,
-                        _this_t::node_id_t const& SIXTRL_RESTRICT_REF rhs )
+                    []( ctx_t::node_id_t const& SIXTRL_RESTRICT_REF lhs,
+                        ctx_t::node_id_t const& SIXTRL_RESTRICT_REF rhs )
                     {
                         return ::NS(ComputeNodeId_are_equal)( &lhs, &rhs );
                     } ), allowed_node_ids.end() );
@@ -1996,13 +2466,13 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t ClContextBase::GetAllAvailableNodes(
+    st_status_t ctx_t::GetAllAvailableNodes(
             std::vector< cl::Platform>& available_platforms,
             std::vector< cl::Device >&  available_devices,
-            std::vector< _this_t::node_id_t >* ptr_available_nodes_id,
-            std::vector< _this_t::node_info_t >* ptr_available_nodes_info )
+            std::vector< ctx_t::node_id_t >* ptr_available_nodes_id,
+            std::vector< ctx_t::node_info_t >* ptr_available_nodes_info )
     {
-        _this_t::status_t status = st::ARCH_STATUS_SUCCESS;
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
 
         if( ptr_available_nodes_id != nullptr )
         {
@@ -2026,8 +2496,8 @@ namespace SIXTRL_CXX_NAMESPACE
         temp_devices.clear();
         temp_devices.reserve( 100 );
 
-        _this_t::platform_id_t platform_idx = _this_t::platform_id_t{ 0 };
-        _this_t::device_id_t device_idx = _this_t::device_id_t{ 0 };
+        ctx_t::platform_id_t platform_idx = ctx_t::platform_id_t{ 0 };
+        ctx_t::device_id_t device_idx = ctx_t::device_id_t{ 0 };
 
         cl::Platform::get( &available_platforms );
         std::string const arch_str( "opencl" );
@@ -2065,7 +2535,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             for( auto const& device : temp_devices )
             {
-                _this_t::node_id_t temp_node_id;
+                ctx_t::node_id_t temp_node_id;
 
                 ::NS(ComputeNodeId_preset)( &temp_node_id );
 
@@ -2095,9 +2565,9 @@ namespace SIXTRL_CXX_NAMESPACE
                     ret |= device.getInfo( CL_DEVICE_EXTENSIONS, &description );
 
                     ptr_available_nodes_info->push_back(
-                        _this_t::node_info_t{} );
+                        ctx_t::node_info_t{} );
 
-                    _this_t::node_info_t* ptr_node_info =
+                    ctx_t::node_info_t* ptr_node_info =
                         &ptr_available_nodes_info->back();
 
                     ::NS(ComputeNodeInfo_preset)( ptr_node_info );
@@ -2138,14 +2608,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::status_t ClContextBase::GetAvailableNodes(
-            std::vector< ClContextBase::node_id_t>& available_nodes_id,
-            std::vector< ClContextBase::node_info_t >* ptr_available_nodes_info,
+    st_status_t ctx_t::GetAvailableNodes(
+            std::vector< ctx_t::node_id_t>& available_nodes_id,
+            std::vector< ctx_t::node_info_t >* ptr_available_nodes_info,
             std::vector< cl::Device >* ptr_available_devices,
             char const* SIXTRL_RESTRICT env_variable_name,
             char const* SIXTRL_RESTRICT filter_str )
     {
-        using node_id_t = _this_t::node_id_t;
+        using node_id_t = ctx_t::node_id_t;
 
         ( void )filter_str;
 
@@ -2172,9 +2642,9 @@ namespace SIXTRL_CXX_NAMESPACE
         std::vector< cl::Device > all_available_devices;
         std::vector< cl::Platform > all_available_platforms;
         std::vector< node_id_t > all_available_nodes_id;
-        std::vector< _this_t::node_info_t > all_available_nodes_info;
+        std::vector< ctx_t::node_info_t > all_available_nodes_info;
 
-        _this_t::status_t status = _this_t::GetAllAvailableNodes(
+        st_status_t status = ctx_t::GetAllAvailableNodes(
             all_available_platforms, all_available_devices,
                 &all_available_nodes_id, &all_available_nodes_info );
 
@@ -2190,7 +2660,7 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_ASSERT( all_available_devices.size() ==
                        all_available_nodes_info.size() );
 
-        std::vector< _this_t::node_id_t > allowed_node_ids;
+        std::vector< ctx_t::node_id_t > allowed_node_ids;
 
         bool first_available_node = false;
         bool ext_list_of_nodes    = false;
@@ -2210,16 +2680,16 @@ namespace SIXTRL_CXX_NAMESPACE
 
         if( ext_list_of_nodes )
         {
-            status = _this_t::GetAllowedNodesFromEnvVariable(
+            status = ctx_t::GetAllowedNodesFromEnvVariable(
                 allowed_node_ids, env_variable_name );
         }
 
         if( status != st::ARCH_STATUS_SUCCESS ) return status;
 
-        _this_t::size_type const max_expected_num_nodes = ( ext_list_of_nodes )
+        st_size_t const max_expected_num_nodes = ( ext_list_of_nodes )
             ? allowed_node_ids.size() : all_available_devices.size();
 
-        if( max_expected_num_nodes > _this_t::size_type{ 0 } )
+        if( max_expected_num_nodes > st_size_t{ 0 } )
         {
             available_nodes_id.reserve( max_expected_num_nodes );
 
@@ -2248,13 +2718,13 @@ namespace SIXTRL_CXX_NAMESPACE
                 SIXTRL_ASSERT( std::is_sorted( allowed_node_ids.begin(),
                        allowed_node_ids.end(), cmp_node_ids ) );
 
-                _this_t::size_type const num_available_nodes =
+                st_size_t const num_available_nodes =
                     all_available_devices.size();
 
-                for( _this_t::size_type ii = _this_t::size_type{ 0 } ;
+                for( st_size_t ii = st_size_t{ 0 } ;
                         ii < num_available_nodes ; ++ii )
                 {
-                    _this_t::node_id_t const& node_id =
+                    ctx_t::node_id_t const& node_id =
                         all_available_nodes_id[ ii ];
 
                     if( std::binary_search( allowed_node_ids.begin(),
@@ -2340,21 +2810,21 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::kernel_data_list_t const&
-    ClContextBase::kernelData() const SIXTRL_NOEXCEPT
+    ctx_t::kernel_data_list_t const&
+    ctx_t::kernelData() const SIXTRL_NOEXCEPT
     {
         return this->m_kernel_data;
     }
 
-    _this_t::program_data_list_t const&
-    ClContextBase::programData() const SIXTRL_NOEXCEPT
+    ctx_t::program_data_list_t const&
+    ctx_t::programData() const SIXTRL_NOEXCEPT
     {
         return this->m_program_data;
     }
 
-    void ClContextBase::setLastWorkGroupSize(
-         _this_t::size_type const work_group_size,
-         _this_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
+    void ctx_t::setLastWorkGroupSize(
+         st_size_t const work_group_size,
+         ctx_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
         if( ( kernel_id >= kernel_id_t{ 0 } ) &&
             ( static_cast< size_type >( kernel_id ) <
@@ -2367,9 +2837,9 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    void ClContextBase::setLastNumWorkItems(
-        _this_t::size_type const num_work_items,
-        _this_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
+    void ctx_t::setLastNumWorkItems(
+        st_size_t const num_work_items,
+        ctx_t::kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT
     {
         if( ( kernel_id >= kernel_id_t{ 0 } ) &&
             ( static_cast< size_type >( kernel_id ) <
@@ -2382,9 +2852,9 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    _this_t::size_type ClContextBase::findAvailableNodesIndex(
-        _this_t::platform_id_t const platform_index,
-        _this_t::device_id_t const device_index ) const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::findAvailableNodesIndex(
+        ctx_t::platform_id_t const platform_index,
+        ctx_t::device_id_t const device_index ) const SIXTRL_NOEXCEPT
     {
         size_type index = this->numAvailableNodes();
 
@@ -2412,7 +2882,7 @@ namespace SIXTRL_CXX_NAMESPACE
         return index;
     }
 
-    _this_t::size_type ClContextBase::findAvailableNodesIndex(
+    st_size_t ctx_t::findAvailableNodesIndex(
         char const* node_id_str ) const SIXTRL_NOEXCEPT
     {
         if( ( node_id_str != nullptr ) && ( std::strlen( node_id_str ) >= 3u ) )
@@ -2434,39 +2904,39 @@ namespace SIXTRL_CXX_NAMESPACE
         return this->numAvailableNodes();
     }
 
-    _this_t::status_flag_t*
-    ClContextBase::doGetPtrLocalStatusFlags() SIXTRL_NOEXCEPT
+    ctx_t::status_flag_t*
+    ctx_t::doGetPtrLocalStatusFlags() SIXTRL_NOEXCEPT
     {
         return &this->m_local_status_flags;
     }
 
-    _this_t::status_flag_t const*
-    ClContextBase::doGetPtrLocalStatusFlags() const SIXTRL_NOEXCEPT
+    ctx_t::status_flag_t const*
+    ctx_t::doGetPtrLocalStatusFlags() const SIXTRL_NOEXCEPT
     {
         return &this->m_local_status_flags;
     }
 
-    void ClContextBase::doParseConfigString(
+    void ctx_t::doParseConfigString(
         const char *const SIXTRL_RESTRICT config_str )
     {
         this->doParseConfigStringBaseImpl( config_str );
         return;
     }
 
-    void ClContextBase::doParseConfigStringBaseImpl(
+    void ctx_t::doParseConfigStringBaseImpl(
         const char *const SIXTRL_RESTRICT config_str )
     {
         ( void )config_str;
         return;
     }
 
-    void ClContextBase::doClear()
+    void ctx_t::doClear()
     {
         this->doClearBaseImpl();
         return;
     }
 
-    void ClContextBase::doClearBaseImpl() SIXTRL_NOEXCEPT
+    void ctx_t::doClearBaseImpl() SIXTRL_NOEXCEPT
     {
         cl::CommandQueue dummy_queue;
         cl::Context dummy_context;
@@ -2487,17 +2957,38 @@ namespace SIXTRL_CXX_NAMESPACE
         return;
     }
 
-    bool ClContextBase::doInitDefaultPrograms()
+    st_status_t ctx_t::doInitDefaultFeatureFlags()
+    {
+        return this->doInitDefaultFeatureFlagsBaseImpl();
+    }
+
+    st_status_t ctx_t::doInitDefaultFeatureFlagsBaseImpl()
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        this->set_feature_flag( "_GPUCODE", "1" );
+        this->set_feature_flag( "SIXTRL_BUFFER_ARGPTR_DEC", "__private" );
+        this->set_feature_flag( "SIXTRL_BUFFER_DATAPTR_DEC", "__global" );
+
+        if( this->num_feature_flags() >= st_size_t{ 2 } )
+        {
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    bool ctx_t::doInitDefaultPrograms()
     {
         return this->doInitDefaultProgramsBaseImpl();
     }
 
-    bool ClContextBase::doInitDefaultProgramsBaseImpl()
+    bool ctx_t::doInitDefaultProgramsBaseImpl()
     {
         bool success = false;
 
-        std::string path_to_remap_kernel_program( NS(PATH_TO_BASE_DIR) );
-        path_to_remap_kernel_program += "sixtracklib/opencl/kernels/";
+        std::string path_to_remap_kernel_program(
+            this->default_path_to_kernel_dir_str() );
 
         if( !this->debugMode() )
         {
@@ -2508,17 +2999,22 @@ namespace SIXTRL_CXX_NAMESPACE
             path_to_remap_kernel_program += "managed_buffer_remap_debug.cl";
         }
 
-        std::string remap_program_compile_options = "-D_GPUCODE=1";
-        remap_program_compile_options += " -DSIXTRL_BUFFER_ARGPTR_DEC=__private";
-        remap_program_compile_options += " -DSIXTRL_BUFFER_DATAPTR_DEC=__global";
-        #if !defined( SIXTRL_DISABLE_BEAM_BEAM )
-        remap_program_compile_options += " -DSIXTRL_DISABLE_BEAM_BEAM=1";
-        #endif /* !defined( SIXTRL_DISABLE_BEAM_BEAM ) */
-        remap_program_compile_options += " -I";
-        remap_program_compile_options += NS(PATH_TO_SIXTRL_INCLUDE_DIR);
+        std::ostringstream remap_program_compile_options;
+
+        if( !this->m_default_compile_options.empty() )
+        {
+            remap_program_compile_options <<
+                this->defaultCompileOptions() << " ";
+        }
+
+        remap_program_compile_options
+            << this->feature_flag_repr( "_GPUCODE" ) << " "
+            << this->feature_flag_repr( "SIXTRL_BUFFER_ARGPTR_DEC" ) << " "
+            << this->feature_flag_repr( "SIXTRL_BUFFER_DATAPTR_DEC" ) << " "
+            << "-I " << NS(PATH_TO_SIXTRL_INCLUDE_DIR);
 
         program_id_t const remap_program_id = this->addProgramFile(
-            path_to_remap_kernel_program, remap_program_compile_options );
+            path_to_remap_kernel_program, remap_program_compile_options.str() );
 
         if( remap_program_id >= program_id_t{ 0 } )
         {
@@ -2529,12 +3025,12 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool ClContextBase::doInitDefaultKernels()
+    bool ctx_t::doInitDefaultKernels()
     {
         return this->doInitDefaultKernelsBaseImpl();
     }
 
-    bool ClContextBase::doInitDefaultKernelsBaseImpl()
+    bool ctx_t::doInitDefaultKernelsBaseImpl()
     {
         bool success = false;
 
@@ -2568,14 +3064,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool ClContextBase::doCompileProgram(
-         cl::Program& cl_program, ClContextBase::program_data_t& program_data )
+    bool ctx_t::doCompileProgram(
+         cl::Program& cl_program, ctx_t::program_data_t& program_data )
     {
         return this->doCompileProgramBaseImpl( cl_program, program_data );
     }
 
-    bool ClContextBase::doCompileProgramBaseImpl(
-         cl::Program& cl_program, ClContextBase::program_data_t& program_data )
+    bool ctx_t::doCompileProgramBaseImpl(
+         cl::Program& cl_program, ctx_t::program_data_t& program_data )
     {
         bool success = false;
 
@@ -2699,43 +3195,45 @@ namespace SIXTRL_CXX_NAMESPACE
 
 ::NS(arch_size_t) NS(OpenCL_get_num_all_nodes)( void )
 {
-    return st::ClContextBase::NUM_ALL_NODES();
+    return SIXTRL_CXX_NAMESPACE::ctx_t::NUM_ALL_NODES();
 }
 
 ::NS(arch_size_t) NS(OpenCL_get_all_nodes)(
     NS(ComputeNodeId)* SIXTRL_RESTRICT out_node_ids_begin,
     NS(arch_size_t) const max_num_node_ids )
 {
-    return st::ClContextBase::GET_ALL_NODES(
+    return SIXTRL_CXX_NAMESPACE::ctx_t::GET_ALL_NODES(
         out_node_ids_begin, max_num_node_ids );
 }
 
 void NS(OpenCL_print_all_nodes)( void )
 {
-    st::ClContextBase::PRINT_ALL_NODES();
+    SIXTRL_CXX_NAMESPACE::ctx_t::PRINT_ALL_NODES();
 }
 
 ::NS(arch_size_t) NS(OpenCL_get_all_nodes_required_str_capacity)( void )
 {
-    return st::ClContextBase::GET_ALL_NODES_REQUIRED_STRING_CAPACITY();
+    return SIXTRL_CXX_NAMESPACE::ctx_t::GET_ALL_NODES_REQUIRED_STRING_CAPACITY();
 }
 
 ::NS(arch_status_t) NS(OpenCL_get_all_nodes_as_string)(
     char* SIXTRL_RESTRICT out_node_info_str,
     ::NS(arch_size_t) const out_node_info_str_capacity )
 {
-    using _this_t = st::ClContextBase;
-    _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    st::st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
     if( ( out_node_info_str != nullptr ) &&
-        ( out_node_info_str_capacity > _this_t::size_type{ 0 } ) )
+        ( out_node_info_str_capacity > st::ctx_t::size_type{ 0 } ) )
     {
         std::memset( out_node_info_str, ( int )'\0',
                      out_node_info_str_capacity );
 
-        std::string const temp_str( _this_t::PRINT_ALL_NODES_TO_STRING() );
+        std::string const temp_str(
+            st::ctx_t::PRINT_ALL_NODES_TO_STRING() );
+
         std::strncpy( out_node_info_str, temp_str.c_str(),
-                      out_node_info_str_capacity - _this_t::size_type{ 1 } );
+            out_node_info_str_capacity - st::ctx_t::size_type{ 1 } );
 
         status = st::ARCH_STATUS_SUCCESS;
     }
@@ -2748,14 +3246,15 @@ ::NS(arch_status_t) NS(OpenCL_get_all_nodes_as_string)(
 ::NS(arch_size_t) NS(OpenCL_num_available_nodes)(
     char const* SIXTRL_RESTRICT env_variable_name )
 {
-    return st::ClContextBase::NUM_AVAILABLE_NODES( nullptr, env_variable_name );
+    return SIXTRL_CXX_NAMESPACE::ctx_t::NUM_AVAILABLE_NODES(
+        nullptr, env_variable_name );
 }
 
 ::NS(arch_size_t) NS(OpenCL_num_available_nodes_detailed)(
     char const* SIXTRL_RESTRICT filter_str,
     char const* SIXTRL_RESTRICT env_variable_name )
 {
-    return st::ClContextBase::NUM_AVAILABLE_NODES(
+    return SIXTRL_CXX_NAMESPACE::ctx_t::NUM_AVAILABLE_NODES(
         filter_str, env_variable_name );
 }
 
@@ -2763,7 +3262,7 @@ ::NS(arch_size_t) NS(OpenCL_get_available_nodes)(
     ::NS(ComputeNodeId)* SIXTRL_RESTRICT out_node_ids_begin,
     ::NS(arch_size_t) const max_num_node_ids )
 {
-    return st::ClContextBase::GET_AVAILABLE_NODES(
+    return SIXTRL_CXX_NAMESPACE::ctx_t::GET_AVAILABLE_NODES(
         out_node_ids_begin, max_num_node_ids );
 }
 
@@ -2774,28 +3273,29 @@ ::NS(arch_size_t) NS(OpenCL_get_available_nodes_detailed)(
     char const* SIXTRL_RESTRICT filter_str,
     char const* SIXTRL_RESTRICT env_variable_name )
 {
-    return st::ClContextBase::GET_AVAILABLE_NODES(
+    return SIXTRL_CXX_NAMESPACE::ctx_t::GET_AVAILABLE_NODES(
         out_node_ids_begin, max_num_node_ids, skip_first_num_nodes,
             filter_str, env_variable_name );
 }
 
 void NS(OpenCL_print_available_nodes)( void )
 {
-    st::ClContextBase::PRINT_AVAILABLE_NODES();
+    SIXTRL_CXX_NAMESPACE::ctx_t::PRINT_AVAILABLE_NODES();
 }
 
 void NS(OpenCL_print_available_nodes_detailed)(
     char const* SIXTRL_RESTRICT filter_str,
     char const* SIXTRL_RESTRICT env_variable_name )
 {
-    st::ClContextBase::PRINT_AVAILABLE_NODES( filter_str, env_variable_name );
+    SIXTRL_CXX_NAMESPACE::ctx_t::PRINT_AVAILABLE_NODES( filter_str, env_variable_name );
 }
 
 ::NS(arch_size_t) NS(OpenCL_get_available_nodes_required_str_capacity)(
     char const* SIXTRL_RESTRICT filter_str,
     char const* SIXTRL_RESTRICT env_variable_name )
 {
-    return st::ClContextBase::GET_AVAILABLE_NODES_REQUIRED_STRING_CAPACITY(
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    return st::ctx_t::GET_AVAILABLE_NODES_REQUIRED_STRING_CAPACITY(
         filter_str, env_variable_name );
 }
 
@@ -2805,20 +3305,21 @@ ::NS(arch_status_t) NS(OpenCL_get_available_nodes_as_string)(
     char const* SIXTRL_RESTRICT filter_str,
     char const* SIXTRL_RESTRICT env_variable_name )
 {
-    using _this_t = st::ClContextBase;
-    _this_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    using ctx_t = st::ClContextBase;
+    st::st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
     if( ( out_node_info_str != nullptr ) &&
-        ( out_node_info_str_capacity > _this_t::size_type{ 0 } ) )
+        ( out_node_info_str_capacity > st_size_t{ 0 } ) )
     {
         std::memset( out_node_info_str, ( int )'\0',
                      out_node_info_str_capacity );
 
-        std::string const temp_str( _this_t::PRINT_AVAILABLE_NODES_TO_STRING(
+        std::string const temp_str( ctx_t::PRINT_AVAILABLE_NODES_TO_STRING(
             filter_str, env_variable_name ) );
 
         std::strncpy( out_node_info_str, temp_str.c_str(),
-                      out_node_info_str_capacity - _this_t::size_type{ 1 } );
+                      out_node_info_str_capacity - st_size_t{ 1 } );
 
         status = st::ARCH_STATUS_SUCCESS;
     }
@@ -2830,8 +3331,7 @@ ::NS(arch_status_t) NS(OpenCL_get_available_nodes_as_string)(
 
 ::NS(ClContextBase)* NS(ClContextBase_create)()
 {
-    ::NS(ClContextBase)* ptr_base_ctx = new st::ClContextBase;
-    return ptr_base_ctx;
+    return new SIXTRL_CXX_NAMESPACE::ClContextBase;
 }
 
 ::NS(arch_size_t) NS(ClContextBase_get_num_available_nodes)(
@@ -2863,7 +3363,7 @@ ::NS(context_node_info_t) const* NS(ClContextBase_get_default_node_info)(
 ::NS(context_node_id_t) NS(ClContextBase_get_default_node_id)(
     const ::NS(ClContextBase) *const SIXTRL_RESTRICT context )
 {
-    st::ClContextBase::node_id_t default_node_id;
+    SIXTRL_CXX_NAMESPACE::ctx_t::node_id_t default_node_id;
     ::NS(ComputeNodeId_preset)( &default_node_id );
     ::NS(context_node_info_t) const* default_node_info =
         ::NS(ClContextBase_get_default_node_info)( context );
@@ -3026,6 +3526,14 @@ void NS(ClContextBase_clear)( ::NS(ClContextBase)* SIXTRL_RESTRICT ctx )
     if( ctx != nullptr ) ctx->clear();
 }
 
+::NS(arch_status_t) NS(ClContextBase_reinit_default_programs)(
+    NS(ClContextBase)* SIXTRL_RESTRICT ctx )
+{
+    return ( ctx != nullptr )
+        ? ctx->reinit_default_programs()
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
 bool NS(ClContextBase_select_node)( ::NS(ClContextBase)* SIXTRL_RESTRICT ctx,
     char const* SIXTRL_RESTRICT node_id_str )
 {
@@ -3053,7 +3561,7 @@ ::NS(ClContextBase)* NS(ClContextBase_new_on_selected_node_id_str)(
 
     if( ctx != nullptr )
     {
-        using node_id_t = st::ClContextBase::node_id_t;
+        using node_id_t = SIXTRL_CXX_NAMESPACE::ctx_t::node_id_t;
         node_id_t const* ptr_node_id = ctx->ptrAvailableNodesId( node_id_str );
 
         if( ( ptr_node_id == nullptr ) || ( !ctx->selectNode( *ptr_node_id ) ) )
@@ -3074,7 +3582,7 @@ ::NS(ClContextBase)* NS(ClContextBase_new_on_selected_node_id)(
     if( ( node_id != nullptr ) &&
         ( ::NS(ComputeNodeId_is_valid)( node_id ) ) )
     {
-        ctx = new st::ClContextBase( *node_id );
+        ctx = new SIXTRL_CXX_NAMESPACE::ClContextBase( *node_id );
 
         if( ( ctx != nullptr ) && ( !ctx->hasSelectedNode() ) )
         {
@@ -3108,6 +3616,20 @@ ::NS(ClContextBase)* NS(ClContextBase_new)()
     return ::NS(ClContextBase_new_on_selected_node_id)( nullptr );
 }
 
+void NS(ClContextBase_set_default_compile_options)(
+    ::NS(ClContextBase)* SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT default_compile_options )
+{
+    if( ctx != nullptr ) ctx->setDefaultCompileOptions(
+            default_compile_options );
+}
+
+char const* NS(ClContextBase_default_compile_options)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx ) SIXTRL_NOEXCEPT
+{
+    return ( ctx != nullptr ) ? ctx->defaultCompileOptions() : nullptr;
+}
+
 ::NS(arch_size_t) NS(ClContextBase_get_num_available_programs)(
     const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx )
 {
@@ -3122,7 +3644,7 @@ ::NS(arch_program_id_t) NS(ClContextBase_add_program_file)(
 {
     return ( ctx != nullptr )
         ? ctx->addProgramFile( path_to_program_file, compile_options )
-        : st::ARCH_ILLEGAL_PROGRAM_ID;
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_PROGRAM_ID;
 }
 
 bool NS(ClContextBase_compile_program)(
@@ -3132,6 +3654,26 @@ bool NS(ClContextBase_compile_program)(
     return ( ctx != nullptr ) ? ctx->compileProgram( program_id ) : false;
 }
 
+::NS(arch_size_t)
+NS(ClContextBase_get_required_program_source_code_capacity)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    ::NS(arch_program_id_t) const program_id )
+{
+    ::NS(arch_size_t) capacity = ::NS(arch_size_t){ 0 };
+
+    if( ctx != nullptr )
+    {
+        char const* ptr_code = ctx->programSourceCode( program_id );
+
+        if( ptr_code != nullptr )
+        {
+            capacity = ::NS(arch_size_t){ 1 } + std::strlen( ptr_code );
+        }
+    }
+
+    return capacity;
+}
+
 char const* NS(ClContextBase_get_program_source_code)(
     const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     ::NS(arch_program_id_t) const program_id )
@@ -3146,6 +3688,25 @@ bool NS(ClContextBase_has_program_file_path)(
     return ( ctx != nullptr ) ? ctx->programHasFilePath( program_id ) : false;
 }
 
+::NS(arch_size_t) NS(ClContextBase_get_required_program_path_capacity)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    ::NS(arch_program_id_t) const program_id )
+{
+    ::NS(arch_size_t) capacity = ::NS(arch_size_t){ 0 };
+
+    if( ctx != nullptr )
+    {
+        char const* ptr_path = ctx->programPathToFile( program_id );
+
+        if( ptr_path != nullptr )
+        {
+            capacity = ::NS(arch_size_t){ 1 } + std::strlen( ptr_path );
+        }
+    }
+
+    return capacity;
+}
+
 char const* NS(ClContextBase_get_program_path_to_file)(
     const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     ::NS(arch_program_id_t) const program_id )
@@ -3153,6 +3714,26 @@ char const* NS(ClContextBase_get_program_path_to_file)(
     return ( ctx != nullptr ) ? ctx->programPathToFile( program_id ) : nullptr;
 }
 
+::NS(arch_size_t)
+NS(ClContextBase_get_required_program_compile_options_capacity)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    ::NS(arch_program_id_t) const program_id )
+{
+    ::NS(arch_size_t) capacity = ::NS(arch_size_t){ 0 };
+
+    if( ctx != nullptr )
+    {
+        char const* ptr_options = ctx->programCompileOptions( program_id );
+
+        if( ptr_options != nullptr )
+        {
+            capacity = ::NS(arch_size_t){ 1 } + std::strlen( ptr_options );
+        }
+    }
+
+    return capacity;
+}
+
 char const* NS(ClContextBase_get_program_compile_options)(
     const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     ::NS(arch_program_id_t) const program_id )
@@ -3161,6 +3742,25 @@ char const* NS(ClContextBase_get_program_compile_options)(
         ? ctx->programCompileOptions( program_id ) : nullptr;
 }
 
+::NS(arch_size_t) NS(ClContextBase_get_required_program_compile_report_capacity)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    ::NS(arch_program_id_t) const program_id )
+{
+    ::NS(arch_size_t) capacity = ::NS(arch_size_t){ 0 };
+
+    if( ctx != nullptr )
+    {
+        char const* ptr_report = ctx->programCompileReport( program_id );
+
+        if( ptr_report != nullptr )
+        {
+            capacity = ::NS(arch_size_t){ 1 } + std::strlen( ptr_report );
+        }
+    }
+
+    return capacity;
+}
+
 char const* NS(ClContextBase_get_program_compile_report)(
     const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     ::NS(arch_program_id_t) const program_id )
@@ -3182,7 +3782,7 @@ ::NS(arch_kernel_id_t) NS(ClContextBase_enable_kernel)(
 {
     return ( ctx != nullptr )
         ? ctx->enableKernel( kernel_name, program_id )
-        : st::ARCH_ILLEGAL_KERNEL_ID;
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_KERNEL_ID;
 }
 
 ::NS(arch_size_t) NS(ClContextBase_get_num_available_kernels)(
@@ -3281,7 +3881,7 @@ ::NS(kernel_arg_type_t) NS(ClContextBase_get_kernel_argument_type)(
     ::NS(arch_size_t) const arg_index )
 {
     return ( ctx != nullptr ) ? ctx->kernelArgumentType( kernel_id, arg_index )
-        : st::ClContextBase::ARG_TYPE_INVALID;
+        : SIXTRL_CXX_NAMESPACE::ctx_t::ARG_TYPE_INVALID;
 }
 
 ::NS(ClArgument) const* NS(ClContextBase_get_const_ptr_kernel_argument)(
@@ -3319,12 +3919,13 @@ void NS(ClContextBase_reset_single_kernel_argument)(
     if( ctx != nullptr ) ctx->resetSingleKernelArgument( kernel_id, arg_index );
 }
 
-void NS(ClContextBase_assign_kernel_argument_ptr)(
+void NS(ClContextBase_assign_kernel_argument_raw_ptr)(
     ::NS(ClContextBase)* SIXTRL_RESTRICT ctx,
     ::NS(arch_kernel_id_t) const kernel_id, ::NS(arch_size_t) const arg_idx,
-    void* SIXTRL_RESTRICT ptr )
+    ::NS(arch_size_t) const arg_size, void const* ptr )
 {
-    if( ctx != nullptr ) ctx->assignKernelArgumentPtr( kernel_id, arg_idx, ptr );
+    if( ctx != nullptr ) ctx->assignKernelArgumentRawPtr(
+            kernel_id, arg_idx, arg_size, ptr );
 }
 
 void NS(ClContextBase_assign_kernel_argument_value)(
@@ -3354,7 +3955,7 @@ ::NS(arch_size_t) NS(ClContextBase_calculate_kernel_num_work_items)(
 {
     return ( ctx != nullptr )
         ? ctx->calculateKernelNumWorkItems( kernel_id, min_num_work_items )
-        : st::ClContextBase::size_type{ 0 };
+        : SIXTRL_CXX_NAMESPACE::ctx_t::size_type{ 0 };
 }
 
 bool NS(ClContextBase_run_kernel)( ::NS(ClContextBase)* SIXTRL_RESTRICT ctx,
@@ -3469,7 +4070,7 @@ ::NS(arch_program_id_t) NS(ClContextBase_remapping_program_id)(
     const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx )
 {
     return ( ctx != nullptr ) ? ctx->remapping_program_id()
-        : st::ARCH_ILLEGAL_PROGRAM_ID;
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_PROGRAM_ID;
 }
 
 cl_program NS(ClContextBase_get_program)(
@@ -3516,6 +4117,12 @@ cl_command_queue NS(ClContextBase_get_queue)(
     return cl_command_queue{};
 }
 
+uintptr_t NS(ClContextBase_get_queue_addr)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx ) SIXTRL_NOEXCEPT
+{
+    return ( ctx != nullptr ) ? ctx->openClQueueAddr() : std::uintptr_t{ 0 };
+}
+
 cl_context NS(ClContextBase_get_opencl_context)(
     ::NS(ClContextBase)* SIXTRL_RESTRICT ctx )
 {
@@ -3530,6 +4137,11 @@ cl_context NS(ClContextBase_get_opencl_context)(
     return cl_context{};
 }
 
+uintptr_t NS(ClContextBase_get_opencl_context_addr)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx ) SIXTRL_NOEXCEPT
+{
+    return ( ctx != nullptr ) ? ctx->openClContextAddr() : std::uintptr_t{ 0 };
+}
 
 void NS(ClContextBase_delete)(
     ::NS(ClContextBase)* SIXTRL_RESTRICT ctx )
@@ -3555,8 +4167,56 @@ void NS(ClContextBase_disable_debug_mode)(
     if( ctx != nullptr ) ctx->disableDebugMode();
 }
 
-#endif /* !defined( __CUDACC__ )  */
 
-/* end: sixtracklib/opencl/internal/cl_context_base.cpp */
+::NS(arch_size_t) NS(ClContextBase_num_feature_flags)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx )SIXTRL_NOEXCEPT
+{
+    return ( ctx != nullptr )
+        ? ctx->num_feature_flags() : ::NS(arch_size_t){ 0 };
+}
+
+bool NS(ClContextBase_has_feature_flag)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT str ) SIXTRL_NOEXCEPT
+{
+    return ( ( ctx != nullptr ) && ( ctx->has_feature_flag)( str ) );
+}
+
+char const* NS(ClContextBase_feature_flag)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT str ) SIXTRL_NOEXCEPT
+{
+    return ( ctx != nullptr ) ? ctx->feature_flag( str ) : SIXTRL_NULLPTR;
+}
+
+void NS(ClContextBase_set_feature_flag)(
+    ::NS(ClContextBase)* SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT str, char const* flag_val )
+{
+    if( ctx != nullptr ) ctx->set_feature_flag( str, flag_val );
+}
 
+::NS(arch_size_t) NS(ClContextBase_feature_flag_repr_required_capacity)(
+    const ::NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT str,
+    char const* SIXTRL_RESTRICT prefix,
+    char const* SIXTRL_RESTRICT sep )
+{
+    return ( ctx != nullptr )
+        ? ctx->feature_flag_repr_required_capacity( str, prefix, sep )
+        : ::NS(arch_size_t){ 0 };
+}
 
+::NS(arch_status_t)  NS(ClContextBase_feature_flag_repr_as_cstr)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    char* out_str, NS(arch_size_t) const out_str_capacity,
+    char const* SIXTRL_RESTRICT str,
+    char const* SIXTRL_RESTRICT prefix,
+    char const* SIXTRL_RESTRICT sep )
+{
+    return ( ctx != nullptr )
+        ? ctx->feature_flag_repr_as_cstr(
+            out_str, out_str_capacity, str, prefix, sep )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+#endif /* !defined( __CUDACC__ )  */
diff --git a/sixtracklib/opencl/internal/base_context.h b/sixtracklib/opencl/internal/base_context.h
index 3956ea4c..b39744bc 100644
--- a/sixtracklib/opencl/internal/base_context.h
+++ b/sixtracklib/opencl/internal/base_context.h
@@ -13,6 +13,7 @@
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/generated/path.h"
     #include "sixtracklib/common/control/definitions.h"
     #include "sixtracklib/common/context/compute_arch.h"
     #include "sixtracklib/opencl/cl.h"
@@ -50,12 +51,20 @@ namespace SIXTRL_CXX_NAMESPACE
         using device_id_t       = ::NS(comp_node_id_num_t);
         using status_t          = ::NS(arch_status_t);
 
-        using kernel_id_t       = ::NS(ctrl_kernel_id_t);
-        using program_id_t      = ::NS(ctrl_kernel_id_t);
-        using kernel_arg_id_t   = int64_t;
-        using kernel_arg_type_t = uint32_t;
-        using status_flag_t     = SIXTRL_CXX_NAMESPACE::arch_debugging_t;
-        using cl_buffer_t       = cl::Buffer;
+        using kernel_id_t         = ::NS(ctrl_kernel_id_t);
+        using program_id_t        = ::NS(ctrl_kernel_id_t);
+        using kernel_arg_id_t     = int64_t;
+        using kernel_arg_type_t   = uint32_t;
+        using program_path_type_t = uint64_t;
+        using status_flag_t       = SIXTRL_CXX_NAMESPACE::arch_debugging_t;
+        using cl_buffer_t         = cl::Buffer;
+        using cl_argument_t       = SIXTRL_CXX_NAMESPACE::ClArgument;
+
+        protected:
+        using feature_flags_map_t  = std::map< std::string, std::string >;
+
+        public:
+        using feature_flags_iter_t = feature_flags_map_t::const_iterator;
 
         static constexpr kernel_arg_type_t ARG_TYPE_NONE =
             kernel_arg_type_t{ 0x00000000 };
@@ -77,6 +86,12 @@ namespace SIXTRL_CXX_NAMESPACE
 
         static constexpr size_type MIN_NUM_REMAP_BUFFER_ARGS = size_type{ 2 };
 
+        static constexpr program_path_type_t PROGRAM_PATH_RELATIVE =
+            program_path_type_t{ 0 };
+
+        static constexpr program_path_type_t PROGRAM_PATH_ABSOLUTE =
+            program_path_type_t{ 1 };
+
         /* ***************************************************************** */
 
         static SIXTRL_HOST_FN size_type NUM_ALL_NODES()
@@ -106,7 +121,7 @@ namespace SIXTRL_CXX_NAMESPACE
         }
 
         static SIXTRL_HOST_FN size_type GET_ALL_NODES(
-            node_id_t* SIXTRL_RESTRICT_REF out_node_ids_begin,
+            node_id_t* SIXTRL_RESTRICT out_node_ids_begin,
             size_type const max_num_node_ids )
         {
             namespace  st = SIXTRL_CXX_NAMESPACE;
@@ -317,9 +332,14 @@ namespace SIXTRL_CXX_NAMESPACE
                     if( num_avail_nodes > _this_t::size_type{ 0 } )
                     {
                         auto in_node_begin = available_node_ids.begin();
+                        std::advance( in_node_begin, skip_first_num_nodes );
+
                         auto in_node_end = in_node_begin;
                         std::advance( in_node_end, num_avail_nodes );
 
+                        SIXTRL_ASSERT( std::distance(
+                            in_node_end, available_node_ids.end() ) >= 0 );
+
                         std::copy( in_node_begin, in_node_end,
                                    &out_node_ids_begin[ 0 ] );
                     }
@@ -466,6 +486,36 @@ namespace SIXTRL_CXX_NAMESPACE
 
         SIXTRL_HOST_FN virtual ~ClContextBase() SIXTRL_NOEXCEPT;
 
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN std::string const&
+            default_path_to_kernel_dir_str() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN char const*
+            default_to_kernel_dir() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN void set_default_path_to_kernel_dir(
+            std::string const& SIXTRL_RESTRICT_REF default_path );
+
+        SIXTRL_HOST_FN void set_default_path_to_kernel_dir(
+            char const* SIXTRL_RESTRICT default_path );
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN std::string const&
+            default_sixtrlib_inc_dir_str() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN char const*
+            default_sixtrlib_inc_dir() const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN void set_default_sixtrlib_inc_dir(
+            std::string const& SIXTRL_RESTRICT_REF default_path );
+
+        SIXTRL_HOST_FN void set_default_sixtrlib_inc_dir(
+            char const* SIXTRL_RESTRICT default_path );
+
+        /* ----------------------------------------------------------------- */
+
         SIXTRL_HOST_FN size_type numAvailableNodes() const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN node_info_t const*
@@ -480,7 +530,7 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN node_id_t defaultNodeId() const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN bool isNodeIndexAvailable(
-            size_type const node_index ) const SIXTRL_RESTRICT;
+            size_type const node_index ) const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN bool isNodeIdAvailable(
             node_id_t const node_id ) const SIXTRL_NOEXCEPT;
@@ -557,6 +607,7 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN void printNodesInfo() const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN void clear();
+        SIXTRL_HOST_FN status_t reinit_default_programs();
 
         SIXTRL_HOST_FN char const* configStr() const SIXTRL_NOEXCEPT;
 
@@ -570,29 +621,36 @@ namespace SIXTRL_CXX_NAMESPACE
             defaultCompileOptions() const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN program_id_t addProgramCode(
-            std::string const& source_code );
+            std::string const& SIXTRL_RESTRICT_REF source_code );
 
-        SIXTRL_HOST_FN program_id_t addProgramCode( char const* source_code );
+        SIXTRL_HOST_FN program_id_t addProgramCode(
+            char const* SIXTRL_RESTRICT source_code );
 
         SIXTRL_HOST_FN program_id_t addProgramCode(
-            std::string const& source_code,
-            std::string const& compile_options );
+            std::string const& SIXTRL_RESTRICT_REF source_code,
+            std::string const& SIXTRL_RESTRICT_REF compile_options );
 
-        SIXTRL_HOST_FN program_id_t addProgramCode( char const* source_code,
-                                     char const* compile_options );
+        SIXTRL_HOST_FN program_id_t addProgramCode(
+            char const* SIXTRL_RESTRICT source_code,
+            char const* SIXTRL_RESTRICT compile_options );
 
         SIXTRL_HOST_FN program_id_t addProgramFile(
-            std::string const& path_to_program );
+            std::string const& SIXTRL_RESTRICT_REF path_to_program,
+            program_path_type_t const path_type = PROGRAM_PATH_ABSOLUTE );
 
         SIXTRL_HOST_FN program_id_t addProgramFile(
-            char const* path_to_program );
+            char const* SIXTRL_RESTRICT path_to_program,
+            program_path_type_t const path_type = PROGRAM_PATH_ABSOLUTE );
 
         SIXTRL_HOST_FN program_id_t addProgramFile(
-            std::string const& path_to_program,
-            std::string const& compile_options );
+            std::string const& SIXTRL_RESTRICT_REF path_to_program,
+            std::string const& SIXTRL_RESTRICT_REF compile_options,
+            program_path_type_t const path_type = PROGRAM_PATH_ABSOLUTE );
 
-        SIXTRL_HOST_FN program_id_t addProgramFile( char const* path_to_program,
-            char const* compile_options );
+        SIXTRL_HOST_FN program_id_t addProgramFile(
+            char const* SIXTRL_RESTRICT path_to_program,
+            char const* SIXTRL_RESTRICT compile_options,
+            program_path_type_t const path_type = PROGRAM_PATH_ABSOLUTE );
 
         SIXTRL_HOST_FN bool compileProgram( program_id_t const program_id );
 
@@ -650,7 +708,7 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN size_type kernelExecCounter(
             kernel_id_t const kernel_id ) const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN ClArgument* ptrKernelArgument(
+        SIXTRL_HOST_FN cl_argument_t* ptrKernelArgument(
             kernel_id_t const kernel_id,
             size_type const arg_index ) SIXTRL_NOEXCEPT;
 
@@ -658,7 +716,7 @@ namespace SIXTRL_CXX_NAMESPACE
             kernel_id_t const kernel_id,
             size_type const arg_index) const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN ClArgument const* ptrKernelArgument(
+        SIXTRL_HOST_FN cl_argument_t const* ptrKernelArgument(
             kernel_id_t const kernel_id,
             size_type const arg_index ) const SIXTRL_NOEXCEPT;
 
@@ -670,26 +728,33 @@ namespace SIXTRL_CXX_NAMESPACE
             kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN void assignKernelArgument( kernel_id_t const kernel_id,
-            size_type const arg_index, ClArgument& SIXTRL_RESTRICT_REF arg );
+            size_type const arg_index, cl_argument_t& SIXTRL_RESTRICT_REF arg );
+
+        SIXTRL_HOST_FN void assignKernelArgumentRawPtr(
+            kernel_id_t const kernel_id, size_type const arg_index,
+            size_type const arg_size, void* ptr );
 
         template< typename T >
         SIXTRL_HOST_FN void assignKernelArgumentPtr(
             kernel_id_t const kernel_id, size_type const arg_index,
-                T* SIXTRL_RESTRICT ptr ) SIXTRL_NOEXCEPT
+            SIXTRL_ARGPTR_DEC T* ptr ) SIXTRL_NOEXCEPT
         {
-            using _this_t = ClContextBase;
-
-            SIXTRL_ASSERT( kernel_id >= kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _this_t::size_type >( kernel_id ) <
-                           this->numAvailableKernels() );
+            SIXTRL_ASSERT( kernel_id >= ClContextBase::kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< ClContextBase::size_type >(
+                kernel_id ) < this->numAvailableKernels() );
 
             this->m_kernel_data[ kernel_id ].setKernelArg(
-                    _this_t::ARG_TYPE_RAW_PTR, arg_index, nullptr );
+                    ClContextBase::ARG_TYPE_RAW_PTR, arg_index, nullptr );
 
             cl::Kernel* kernel = this->openClKernel( kernel_id );
-            if( kernel != nullptr ) kernel->setArg( arg_index, ptr );
+            if( kernel != nullptr ) kernel->setArg( arg_index, *ptr );
         }
 
+        SIXTRL_HOST_FN void assignKernelArgumentRawPtr(
+            kernel_id_t const kernel_id, size_type const arg_index,
+            size_type const arg_size,
+            SIXTRL_ARGPTR_DEC void const* ptr ) SIXTRL_NOEXCEPT;
+
         template< typename T >
         SIXTRL_HOST_FN void assignKernelArgumentValue(
             kernel_id_t const kernel_id, size_type const arg_index,
@@ -760,7 +825,10 @@ namespace SIXTRL_CXX_NAMESPACE
         openClKernel( kernel_id_t const kernel_id ) SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN cl::CommandQueue* openClQueue() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN std::uintptr_t openClQueueAddr() const SIXTRL_NOEXCEPT;
+
         SIXTRL_HOST_FN cl::Context* openClContext() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN std::uintptr_t openClContextAddr() const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN cl_buffer_t const&
         internalStatusFlagsBuffer() const SIXTRL_NOEXCEPT;
@@ -785,6 +853,59 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN status_t assign_status_flags_arg(
             cl_buffer_t& SIXTRL_RESTRICT_REF success_flag_arg );
 
+        /* ----------------------------------------------------------------- */
+
+        size_type num_feature_flags() const SIXTRL_NOEXCEPT;
+
+        feature_flags_iter_t feature_flags_begin() const SIXTRL_NOEXCEPT;
+        feature_flags_iter_t feature_flags_end() const SIXTRL_NOEXCEPT;
+
+        bool has_feature_flag(
+            std::string const& SIXTRL_RESTRICT_REF str ) const SIXTRL_NOEXCEPT;
+
+        bool has_feature_flag(
+            char const* SIXTRL_RESTRICT str ) const SIXTRL_NOEXCEPT;
+
+        std::string const& feature_flag_str(
+            std::string const& SIXTRL_RESTRICT_REF str ) const;
+
+        std::string const& feature_flag_str(
+            char const* SIXTRL_RESTRICT str ) const;
+
+        char const* feature_flag(
+            std::string const& SIXTRL_RESTRICT_REF str ) const SIXTRL_NOEXCEPT;
+
+        char const* feature_flag(
+            char const* SIXTRL_RESTRICT str ) const SIXTRL_NOEXCEPT;
+
+        void set_feature_flag( std::string const& SIXTRL_RESTRICT_REF str,
+            std::string const& SIXTRL_RESTRICT_REF flag_value );
+
+        void set_feature_flag( char const* SIXTRL_RESTRICT str,
+            char const* SIXTRL_RESTRICT flag_value );
+
+        std::string feature_flag_repr(
+            std::string const& SIXTRL_RESTRICT_REF str,
+            std::string const& SIXTRL_RESTRICT_REF prefix = std::string{ "-D" },
+            std::string const& SIXTRL_RESTRICT_REF sep =
+                std::string{"="} ) const;
+
+        std::string feature_flag_repr(
+            char const* SIXTRL_RESTRICT str,
+            char const* SIXTRL_RESTRICT prefix = nullptr,
+            char const* SIXTRL_RESTRICT sep = nullptr ) const;
+
+        size_type feature_flag_repr_required_capacity(
+            char const* SIXTRL_RESTRICT str,
+            char const* SIXTRL_RESTRICT prefix = nullptr,
+            char const* SIXTRL_RESTRICT sep = nullptr ) const;
+
+        status_t feature_flag_repr_as_cstr(
+            char* out_str, size_type out_str_capacity,
+            char const* SIXTRL_RESTRICT str,
+            char const* SIXTRL_RESTRICT prefix = nullptr,
+            char const* SIXTRL_RESTRICT sep = nullptr ) const;
+
         protected:
 
         static SIXTRL_HOST_FN status_t GetAllAvailableNodes(
@@ -804,6 +925,18 @@ namespace SIXTRL_CXX_NAMESPACE
             std::vector< node_id_t >& allowed_node_ids,
             char const* SIXTRL_RESTRICT env_variable_name = nullptr );
 
+        static SIXTRL_HOST_FN std::string GetDefaultPathKernelDir()
+        {
+            std::ostringstream a2str;
+            a2str << NS(PATH_TO_BASE_DIR) << "sixtracklib/opencl/kernels/";
+            return a2str.str();
+        }
+
+        static SIXTRL_HOST_FN std::string GetDefaultSixTrlLibIncludeDir()
+        {
+            return std::string{ NS(PATH_TO_SIXTRL_INCLUDE_DIR) };
+        }
+
         using program_data_t = struct ProgramData
         {
             ProgramData() :
@@ -893,7 +1026,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 {
                     this->m_arg_types[ index ] = type;
                     this->m_arguments[ index ] =
-                        reinterpret_cast< ClArgument* >( ptr );
+                        reinterpret_cast< cl_argument_t* >( ptr );
                 }
             }
 
@@ -933,7 +1066,7 @@ namespace SIXTRL_CXX_NAMESPACE
                       static_cast< double >( this->m_exec_count ) : double{ 0 };
             }
 
-            ClArgument const* argument(
+            cl_argument_t const* argument(
                 size_type const arg_index ) const SIXTRL_NOEXCEPT
             {
                 SIXTRL_ASSERT( arg_index < this->m_num_args );
@@ -941,7 +1074,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 return this->m_arguments[ arg_index ];
             }
 
-            ClArgument* argument( size_type const arg_index ) SIXTRL_NOEXCEPT
+            cl_argument_t* argument( size_type const arg_index ) SIXTRL_NOEXCEPT
             {
                 SIXTRL_ASSERT( arg_index < this->m_num_args );
                 SIXTRL_ASSERT( this->m_arguments.size() > arg_index );
@@ -949,7 +1082,7 @@ namespace SIXTRL_CXX_NAMESPACE
             }
 
             void assignArgument( size_type const arg_index,
-                                 ClArgument* ptr_to_arg )
+                                 cl_argument_t* ptr_to_arg )
             {
                 SIXTRL_ASSERT( arg_index < this->m_num_args );
                 SIXTRL_ASSERT( this->m_arguments.size() > arg_index );
@@ -987,7 +1120,7 @@ namespace SIXTRL_CXX_NAMESPACE
             double        m_last_exec_time;
             double        m_sum_exec_time;
 
-            std::vector< ClArgument* >       m_arguments;
+            std::vector< cl_argument_t* >       m_arguments;
             std::vector< kernel_arg_type_t > m_arg_types;
         };
 
@@ -999,6 +1132,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
         virtual void doClear();
 
+        virtual status_t doInitDefaultFeatureFlags();
         virtual bool doInitDefaultPrograms();
         virtual bool doInitDefaultKernels();
 
@@ -1044,6 +1178,7 @@ namespace SIXTRL_CXX_NAMESPACE
         void doParseConfigStringBaseImpl(
             const char *const SIXTRL_RESTRICT config_str );
 
+        status_t doInitDefaultFeatureFlagsBaseImpl();
         bool doInitDefaultProgramsBaseImpl();
         bool doInitDefaultKernelsBaseImpl();
 
@@ -1060,6 +1195,7 @@ namespace SIXTRL_CXX_NAMESPACE
         status_t doAssignSlotSizeArgBaseImpl(
             size_type const slot_size );
 
+        feature_flags_map_t             m_feature_flags;
         std::vector< cl::Program >      m_cl_programs;
         std::vector< cl::Kernel  >      m_cl_kernels;
         std::vector< cl_buffer_t >      m_cl_buffers;
@@ -1070,6 +1206,8 @@ namespace SIXTRL_CXX_NAMESPACE
         std::vector< program_data_t >   m_program_data;
         std::vector< kernel_data_t  >   m_kernel_data;
 
+        std::string                     m_default_path_to_kernel_dir;
+        std::string                     m_default_sixtrlib_inc_dir;
         std::string                     m_default_compile_options;
         std::string                     m_config_str;
 
@@ -1093,8 +1231,6 @@ typedef SIXTRL_CXX_NAMESPACE::ClContextBase::node_info_t NS(context_node_info_t)
 typedef SIXTRL_CXX_NAMESPACE::ClContextBase::kernel_arg_type_t
         NS(kernel_arg_type_t);
 
-
-
 #else /* defined( __cplusplus ) */
 
     #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
@@ -1138,7 +1274,7 @@ NS(OpenCL_get_all_nodes_as_string)(
     char* SIXTRL_RESTRICT out_node_info_str,
     NS(arch_size_t) const out_node_info_str_capacity );
 
-/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+/* ------------------------------------------------------------------------- */
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
 NS(OpenCL_num_available_nodes)( char const* SIXTRL_RESTRICT env_variable_name );
@@ -1169,6 +1305,8 @@ NS(OpenCL_print_available_nodes_detailed)(
     char const* SIXTRL_RESTRICT filter_str,
     char const* SIXTRL_RESTRICT env_variable_name );
 
+/* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - */
+
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
 NS(OpenCL_get_available_nodes_required_str_capacity)(
     char const* SIXTRL_RESTRICT filter_str,
@@ -1185,6 +1323,30 @@ NS(OpenCL_get_available_nodes_as_string)(
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClContextBase)* NS(ClContextBase_create)();
 
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN char const*
+NS(ClContextBase_default_to_kernel_dir)( const NS(ClContextBase) *const
+    SIXTRL_RESTRICT ctx ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void
+NS(ClContextBase_set_default_path_to_kernel_dir)(
+    NS(ClContextBase)* SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT default_path );
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN char const*
+NS(ClContextBase_default_sixtrlib_inc_dir)( const NS(ClContextBase) *const
+    SIXTRL_RESTRICT ctx ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void
+NS(ClContextBase_set_default_sixtrlib_inc_dir)(
+    NS(ClContextBase)* SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT default_path );
+
+/* ------------------------------------------------------------------------- */
+
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
 NS(ClContextBase_get_num_available_nodes)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx );
@@ -1286,6 +1448,10 @@ SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_print_nodes_info)(
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_clear)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(ClContextBase_reinit_default_programs)(
+    NS(ClContextBase)* SIXTRL_RESTRICT ctx );
+
 SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ClContextBase_select_node)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx,
     char const* node_id_str );
@@ -1298,6 +1464,15 @@ SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ClContextBase_select_node_by_index)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx,
     NS(arch_size_t) const index );
 
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_set_default_compile_options)(
+    NS(ClContextBase)* SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT default_compile_options );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN char const*
+NS(ClContextBase_default_compile_options)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx ) SIXTRL_NOEXCEPT;
+
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
 NS(ClContextBase_get_num_available_programs)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx );
@@ -1312,6 +1487,11 @@ SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ClContextBase_compile_program)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx,
     NS(arch_program_id_t) const program_id );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(ClContextBase_get_required_program_source_code_capacity)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    NS(arch_program_id_t) const program_id );
+
 SIXTRL_EXTERN SIXTRL_HOST_FN char const*
 NS(ClContextBase_get_program_source_code)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
@@ -1321,16 +1501,31 @@ SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ClContextBase_has_program_file_path)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     NS(arch_program_id_t) const program_id );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(ClContextBase_get_required_program_path_capacity)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    NS(arch_program_id_t) const program_id );
+
 SIXTRL_EXTERN SIXTRL_HOST_FN char const*
 NS(ClContextBase_get_program_path_to_file)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     NS(arch_program_id_t) const program_id );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(ClContextBase_get_required_program_compile_options_capacity)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    NS(arch_program_id_t) const program_id );
+
 SIXTRL_EXTERN SIXTRL_HOST_FN char const*
 NS(ClContextBase_get_program_compile_options)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     NS(arch_program_id_t) const program_id );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(ClContextBase_get_required_program_compile_report_capacity)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    NS(arch_program_id_t) const program_id );
+
 SIXTRL_EXTERN SIXTRL_HOST_FN char const* NS(ClContextBase_get_program_compile_report)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     NS(arch_program_id_t) const program_id );
@@ -1380,11 +1575,13 @@ NS(ClContextBase_get_kernel_preferred_work_group_size_multiple)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     NS(arch_kernel_id_t) const kernel_id );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t) NS(ClContextBase_get_kernel_exec_counter)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(ClContextBase_get_kernel_exec_counter)(
     const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
     NS(arch_kernel_id_t) const kernel_id );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument)* NS(ClContextBase_get_ptr_kernel_argument)(
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument)*
+NS(ClContextBase_get_ptr_kernel_argument)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx,
     NS(arch_kernel_id_t) const kernel_id,
     NS(arch_size_t) const arg_index );
@@ -1411,11 +1608,11 @@ SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_reset_single_kernel_argument)
     NS(arch_kernel_id_t) const kernel_id,
     NS(arch_size_t) const arg_index );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_assign_kernel_argument_ptr)(
+SIXTRL_EXTERN SIXTRL_HOST_FN void
+NS(ClContextBase_assign_kernel_argument_raw_ptr)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx,
-    NS(arch_kernel_id_t) const kernel_id,
-    NS(arch_size_t) const arg_index,
-    void* SIXTRL_RESTRICT ptr );
+    NS(arch_kernel_id_t) const kernel_id, NS(arch_size_t) const arg_index,
+    NS(arch_size_t) const arg_size, void const* ptr );
 
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_assign_kernel_argument_value)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx,
@@ -1510,9 +1707,15 @@ SIXTRL_EXTERN SIXTRL_HOST_FN cl_kernel NS(ClContextBase_get_kernel)(
 SIXTRL_EXTERN SIXTRL_HOST_FN cl_command_queue NS(ClContextBase_get_queue)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN uintptr_t NS(ClContextBase_get_queue_addr)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx ) SIXTRL_NOEXCEPT;
+
 SIXTRL_EXTERN SIXTRL_HOST_FN cl_context NS(ClContextBase_get_opencl_context)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN uintptr_t NS(ClContextBase_get_opencl_context_addr)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx ) SIXTRL_NOEXCEPT;
+
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClContextBase)*
 NS(ClContextBase_new_on_selected_node_id_str)(
     char const* SIXTRL_RESTRICT node_id_str );
@@ -1523,9 +1726,6 @@ NS(ClContextBase_new_on_selected_node_id)(
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClContextBase)* NS(ClContextBase_new)( void );
 
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_free)(
-    NS(ClContextBase)* SIXTRL_RESTRICT ctx );
-
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_delete)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx );
 
@@ -1541,6 +1741,38 @@ SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_enable_debug_mode)(
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_disable_debug_mode)(
     NS(ClContextBase)* SIXTRL_RESTRICT ctx );
 
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(ClContextBase_num_feature_flags)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx )SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(ClContextBase_has_feature_flag)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT str ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN char const* NS(ClContextBase_feature_flag)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT str ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(ClContextBase_set_feature_flag)(
+    NS(ClContextBase)* SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT str, char const* flag_val );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_size_t)
+NS(ClContextBase_feature_flag_repr_required_capacity)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    char const* SIXTRL_RESTRICT str,
+    char const* SIXTRL_RESTRICT prefix,
+    char const* SIXTRL_RESTRICT sep );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
+NS(ClContextBase_feature_flag_repr_as_cstr)(
+    const NS(ClContextBase) *const SIXTRL_RESTRICT ctx,
+    char* out_str, NS(arch_size_t) const out_str_capacity,
+    char const* SIXTRL_RESTRICT str,
+    char const* SIXTRL_RESTRICT prefix,
+    char const* SIXTRL_RESTRICT sep );
+
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
diff --git a/sixtracklib/opencl/internal/context.cpp b/sixtracklib/opencl/internal/context.cpp
index d045cb3a..c2e56344 100644
--- a/sixtracklib/opencl/internal/context.cpp
+++ b/sixtracklib/opencl/internal/context.cpp
@@ -28,58 +28,75 @@
 
 #if defined( __cplusplus )
 
-namespace st = SIXTRL_CXX_NAMESPACE;
 namespace SIXTRL_CXX_NAMESPACE
 {
-    using _base_t       = st::ClContextBase;
-    using _this_t       = st::ClContext;
-    using _size_t       = _this_t::size_type;
-    using _kernel_id_t  = _this_t::kernel_id_t;
-    using _program_id_t = _this_t::program_id_t;
-    using _status_t     = _this_t::status_t;
-
-    constexpr _size_t _this_t::MIN_NUM_TRACK_UNTIL_ARGS;
-    constexpr _size_t _this_t::MIN_NUM_TRACK_LINE_ARGS;
-    constexpr _size_t _this_t::MIN_NUM_TRACK_ELEM_ARGS;
-    constexpr _size_t _this_t::MIN_NUM_ASSIGN_BE_MON_ARGS;
-    constexpr _size_t _this_t::MIN_NUM_CLEAR_BE_MON_ARGS;
-    constexpr _size_t _this_t::MIN_NUM_ASSIGN_ELEM_ARGS;
-
-    ClContext::ClContext( const char *const SIXTRL_RESTRICT config_str ) :
-        _base_t( config_str ),
-        m_num_particles_in_pset( _size_t{ 0 } ), m_pset_index( _size_t{ 0 } ),
+    namespace
+    {
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using base_ctx_t = st::ClContextBase;
+        using ctx_t = st::ClContext;
+        using st_size_t    = ctx_t::size_type;
+        using st_kernel_id_t  = ctx_t::kernel_id_t;
+        using st_program_id_t = ctx_t::program_id_t;
+        using st_status_t  = ctx_t::status_t;
+    }
+
+    constexpr st_size_t ctx_t::MIN_NUM_TRACK_UNTIL_ARGS;
+    constexpr st_size_t ctx_t::MIN_NUM_TRACK_LINE_ARGS;
+    constexpr st_size_t ctx_t::MIN_NUM_TRACK_ELEM_ARGS;
+    constexpr st_size_t ctx_t::MIN_NUM_ASSIGN_BE_MON_ARGS;
+    constexpr st_size_t ctx_t::MIN_NUM_CLEAR_BE_MON_ARGS;
+    constexpr st_size_t ctx_t::MIN_NUM_ASSIGN_ELEM_ARGS;
+    constexpr st_size_t ctx_t::MIN_NUM_FETCH_PARTICLES_ADDR_ARGS;
+
+    ctx_t::ClContext( char const* SIXTRL_RESTRICT config_str ) :
+        base_ctx_t( config_str ),
+        m_num_particles_in_pset( st_size_t{ 0 } ), m_pset_index( st_size_t{ 0 } ),
+        m_elem_by_elem_config_index(
+            ctx_t::DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX ),
         m_track_until_turn_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_line_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_elem_by_elem_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_be_mon_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
+        m_fetch_particles_addr_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_clear_be_mon_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_track_line_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_elem_by_elem_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_be_mon_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
+        m_fetch_particles_addr_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_clear_be_mon_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
-        m_use_optimized_tracking( false ), m_enable_beam_beam( true )
+        m_use_optimized_tracking( false )
     {
+        ctx_t::status_t const status =
+            this->doInitDefaultFeatureFlagsPrivImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+        ( void )status;
+
         this->doInitDefaultProgramsPrivImpl();
     }
 
-    ClContext::ClContext( _size_t const node_index,
-                          const char *const SIXTRL_RESTRICT config_str ) :
-        _base_t( config_str ),
-        m_num_particles_in_pset( _size_t{ 0 } ), m_pset_index( _size_t{ 0 } ),
+    ctx_t::ClContext( st_size_t const node_index,
+            char const* SIXTRL_RESTRICT config_str ) :
+        base_ctx_t( config_str ),
+        m_num_particles_in_pset( st_size_t{ 0 } ),
+        m_pset_index( st_size_t{ 0 } ),
+        m_elem_by_elem_config_index( ctx_t::DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX ),
         m_track_until_turn_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_line_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_elem_by_elem_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_be_mon_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
+        m_fetch_particles_addr_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_clear_be_mon_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_track_line_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_elem_by_elem_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_be_mon_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
+        m_fetch_particles_addr_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_clear_be_mon_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
-        m_use_optimized_tracking( false ), m_enable_beam_beam( true )
+        m_use_optimized_tracking( false )
     {
         if( config_str != nullptr )
         {
@@ -93,6 +110,11 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_use_optimized_tracking = true;
         }
 
+        ctx_t::status_t const status =
+            this->doInitDefaultFeatureFlagsPrivImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+        ( void )status;
+
         this->doInitDefaultProgramsPrivImpl();
 
         if( ( node_index < this->numAvailableNodes() ) &&
@@ -100,32 +122,49 @@ namespace SIXTRL_CXX_NAMESPACE
         {
             ClContextBase::doInitDefaultKernels();
             this->doInitDefaultKernelsPrivImpl();
-            this->doAssignSlotSizeArgPrivImpl( st::BUFFER_DEFAULT_SLOT_SIZE );
+
+            this->doAssignSlotSizeArgPrivImpl(
+                st::BUFFER_DEFAULT_SLOT_SIZE );
+
+            this->doAssignElemByElemConfigIndexArgPrivImpl(
+                ctx_t::DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX );
+
             this->doAssignStatusFlagsArgPrivImpl(
                 this->internalStatusFlagsBuffer() );
         }
     }
 
-    ClContext::ClContext( ClContext::node_id_t const node_id,
+    ctx_t::ClContext( ctx_t::node_id_t const node_id,
                           const char *const SIXTRL_RESTRICT config_str ) :
-        _base_t( config_str ),
-        m_num_particles_in_pset( _size_t{ 0 } ), m_pset_index( _size_t{ 0 } ),
+        base_ctx_t( config_str ),
+        m_num_particles_in_pset( st_size_t{ 0 } ),
+        m_pset_index( st_size_t{ 0 } ),
+        m_elem_by_elem_config_index( ctx_t::DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX ),
         m_track_until_turn_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_line_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_elem_by_elem_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_be_mon_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
+        m_fetch_particles_addr_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_clear_be_mon_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
+        m_assign_addr_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_track_line_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_elem_by_elem_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_be_mon_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
+        m_fetch_particles_addr_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_clear_be_mon_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
-        m_use_optimized_tracking( false ), m_enable_beam_beam( true )
+        m_assign_addr_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
+        m_use_optimized_tracking( false )
     {
+        ctx_t::status_t const status =
+            this->doInitDefaultFeatureFlagsPrivImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+        ( void )status;
+
         this->doInitDefaultProgramsPrivImpl();
 
-        _size_t  const node_index = this->findAvailableNodesIndex(
+        st_size_t  const node_index = this->findAvailableNodesIndex(
             NS(ComputeNodeId_get_platform_id)( &node_id ),
             NS(ComputeNodeId_get_device_id)( &node_id ) );
 
@@ -136,34 +175,46 @@ namespace SIXTRL_CXX_NAMESPACE
         }
 
         if( ( node_index < this->numAvailableNodes() ) &&
-            ( _base_t::doSelectNode( node_index ) ) )
+            ( base_ctx_t::doSelectNode( node_index ) ) )
         {
-            _base_t::doInitDefaultKernels();
+            base_ctx_t::doInitDefaultKernels();
             this->doInitDefaultKernelsPrivImpl();
-            this->doAssignSlotSizeArgPrivImpl( st::BUFFER_DEFAULT_SLOT_SIZE );
+
+            this->doAssignSlotSizeArgPrivImpl(
+                st::BUFFER_DEFAULT_SLOT_SIZE );
+
+            this->doAssignElemByElemConfigIndexArgPrivImpl(
+                ctx_t::DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX );
+
             this->doAssignStatusFlagsArgPrivImpl(
                 this->internalStatusFlagsBuffer() );
         }
     }
 
-    ClContext::ClContext( char const* node_id_str,
+    ctx_t::ClContext( char const* node_id_str,
                           const char *const SIXTRL_RESTRICT config_str ) :
-        _base_t( config_str ),
-        m_num_particles_in_pset( _size_t{ 0 } ), m_pset_index( _size_t{ 0 } ),
+        base_ctx_t( config_str ),
+        m_num_particles_in_pset( st_size_t{ 0 } ),
+        m_pset_index( st_size_t{ 0 } ),
+        m_elem_by_elem_config_index( ctx_t::DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX ),
         m_track_until_turn_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_line_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_elem_by_elem_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_be_mon_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
+        m_fetch_particles_addr_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_clear_be_mon_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
+        m_assign_addr_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_track_line_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_elem_by_elem_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_be_mon_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
+        m_fetch_particles_addr_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_clear_be_mon_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
-        m_use_optimized_tracking( false ), m_enable_beam_beam( true )
+        m_assign_addr_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
+        m_use_optimized_tracking( false )
     {
-        _size_t  node_index = this->findAvailableNodesIndex( node_id_str );
+        st_size_t  node_index = this->findAvailableNodesIndex( node_id_str );
 
         /* WARNING: Workaround for AMD Heisenbug */
         if( !this->isAvailableNodeAMDPlatform( node_index ) )
@@ -171,16 +222,21 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_use_optimized_tracking = true;
         }
 
+        ctx_t::status_t const status =
+            this->doInitDefaultFeatureFlagsPrivImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+        ( void )status;
+
         this->doInitDefaultProgramsPrivImpl();
 
         if( node_index >= this->numAvailableNodes() )
         {
-            _this_t::node_id_t const default_node_id = this->defaultNodeId();
+            ctx_t::node_id_t const default_node_id = this->defaultNodeId();
 
-            _this_t::platform_id_t const platform_index =
+            ctx_t::platform_id_t const platform_index =
                 NS(ComputeNodeId_get_platform_id)( &default_node_id );
 
-            _this_t::device_id_t const device_index =
+            ctx_t::device_id_t const device_index =
                 NS(ComputeNodeId_get_device_id)( &default_node_id );
 
             node_index = this->findAvailableNodesIndex(
@@ -188,36 +244,48 @@ namespace SIXTRL_CXX_NAMESPACE
         }
 
         if( ( node_index < this->numAvailableNodes() ) &&
-            ( _base_t::doSelectNode( node_index ) ) )
+            ( base_ctx_t::doSelectNode( node_index ) ) )
         {
-            _base_t::doInitDefaultKernels();
+            base_ctx_t::doInitDefaultKernels();
             this->doInitDefaultKernelsPrivImpl();
-            this->doAssignSlotSizeArgPrivImpl( st::BUFFER_DEFAULT_SLOT_SIZE );
+
+            this->doAssignSlotSizeArgPrivImpl(
+                st::BUFFER_DEFAULT_SLOT_SIZE );
+
+            this->doAssignElemByElemConfigIndexArgPrivImpl(
+                ctx_t::DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX );
+
             this->doAssignStatusFlagsArgPrivImpl(
                 this->internalStatusFlagsBuffer() );
         }
     }
 
-    ClContext::ClContext(
-        ClContext::platform_id_t const platform_idx,
-        ClContext::device_id_t const device_idx,
+    ctx_t::ClContext(
+        ctx_t::platform_id_t const platform_idx,
+        ctx_t::device_id_t const device_idx,
         const char *const SIXTRL_RESTRICT config_str ) :
-        _base_t( config_str ),
-        m_num_particles_in_pset( _size_t{ 0 } ), m_pset_index( _size_t{ 0 } ),
+        base_ctx_t( config_str ),
+        m_num_particles_in_pset( st_size_t{ 0 } ),
+        m_pset_index( st_size_t{ 0 } ),
+        m_elem_by_elem_config_index( ctx_t::DEFAULT_ELEM_BY_ELEM_CONFIG_INDEX ),
         m_track_until_turn_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_line_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_elem_by_elem_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_assign_be_mon_out_buffer_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
+        m_fetch_particles_addr_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_clear_be_mon_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
+        m_assign_addr_program_id( st::ARCH_ILLEGAL_PROGRAM_ID ),
         m_track_elem_by_elem_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_track_line_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_elem_by_elem_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_assign_be_mon_out_buffer_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
+        m_fetch_particles_addr_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
         m_clear_be_mon_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
-        m_use_optimized_tracking( false ), m_enable_beam_beam( true )
+        m_assign_addr_kernel_id( st::ARCH_ILLEGAL_KERNEL_ID ),
+        m_use_optimized_tracking( false )
     {
-        _size_t const node_index =
+        st_size_t const node_index =
             this->findAvailableNodesIndex( platform_idx, device_idx );
 
         /* WARNING: Workaround for AMD Heisenbug */
@@ -226,25 +294,36 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_use_optimized_tracking = true;
         }
 
+        ctx_t::status_t const status =
+            this->doInitDefaultFeatureFlagsPrivImpl();
+        SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+        ( void )status;
+
         this->doInitDefaultProgramsPrivImpl();
 
         if( ( node_index < this->numAvailableNodes() ) &&
-            ( _base_t::doSelectNode( node_index ) ) )
+            ( base_ctx_t::doSelectNode( node_index ) ) )
         {
-            _base_t::doInitDefaultKernels();
+            base_ctx_t::doInitDefaultKernels();
             this->doInitDefaultKernelsPrivImpl();
-            this->doAssignSlotSizeArgPrivImpl( st::BUFFER_DEFAULT_SLOT_SIZE );
+
+            this->doAssignSlotSizeArgPrivImpl(
+                st::BUFFER_DEFAULT_SLOT_SIZE );
+
+            this->doAssignElemByElemConfigIndexArgPrivImpl(
+                this->m_elem_by_elem_config_index );
+
             this->doAssignStatusFlagsArgPrivImpl(
                 this->internalStatusFlagsBuffer() );
         }
     }
 
-    ClContext::~ClContext() SIXTRL_NOEXCEPT {}
+    ctx_t::~ClContext() SIXTRL_NOEXCEPT {}
 
-    _status_t ClContext::assign_particles_arg(
-        ClArgument& SIXTRL_RESTRICT_REF particles_arg )
+    st_status_t ctx_t::assign_particles_arg(
+        ctx_t::cl_argument_t& SIXTRL_RESTRICT_REF particles_arg )
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         if( ( !particles_arg.usesCObjectBuffer() ) ||
             (  particles_arg.ptrCObjectBuffer() == nullptr ) )
@@ -252,42 +331,45 @@ namespace SIXTRL_CXX_NAMESPACE
             return status;
         }
 
-        constexpr _size_t NUM_KERNELS = _size_t{ 3 };
+        constexpr st_size_t NUM_KERNELS = st_size_t{ 4 };
         status = st::ARCH_STATUS_SUCCESS;
 
-        _kernel_id_t kernel_ids[ NUM_KERNELS ] =
+        st_kernel_id_t kernel_ids[ NUM_KERNELS ] =
         {
             st::ARCH_ILLEGAL_KERNEL_ID, st::ARCH_ILLEGAL_KERNEL_ID,
-            st::ARCH_ILLEGAL_KERNEL_ID
+            st::ARCH_ILLEGAL_KERNEL_ID, st::ARCH_ILLEGAL_KERNEL_ID
         };
 
         kernel_ids[ 0 ] = this->track_until_kernel_id();
         kernel_ids[ 1 ] = this->track_line_kernel_id();
         kernel_ids[ 2 ] = this->track_elem_by_elem_kernel_id();
+        kernel_ids[ 3 ] = this->fetch_particles_addr_kernel_id();
 
         size_t const min_num_kernel_args[ NUM_KERNELS ] =
         {
-            _this_t::MIN_NUM_TRACK_UNTIL_ARGS, _this_t::MIN_NUM_TRACK_LINE_ARGS,
-            _this_t::MIN_NUM_TRACK_ELEM_ARGS
+            ctx_t::MIN_NUM_TRACK_UNTIL_ARGS, ctx_t::MIN_NUM_TRACK_LINE_ARGS,
+            ctx_t::MIN_NUM_TRACK_ELEM_ARGS,
+            ctx_t::MIN_NUM_FETCH_PARTICLES_ADDR_ARGS
         };
 
-        _size_t const particles_arg_idx[ NUM_KERNELS ] =
+        st_size_t const particles_arg_idx[ NUM_KERNELS ] =
         {
-            _size_t{ 0 }, // track_until
-            _size_t{ 0 }, // track_line
-            _size_t{ 0 }, // track_elem_elem
+            st_size_t{ 0 }, // track_until
+            st_size_t{ 0 }, // track_line
+            st_size_t{ 0 }, // track_elem_elem
+            st_size_t{ 0 }  // fetch_particles_addr
         };
 
-        for( _size_t ii = _size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
+        for( st_size_t ii = st_size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
         {
-            _kernel_id_t const kernel_id = kernel_ids[ ii ];
-            _size_t const min_num_args = min_num_kernel_args[ ii ];
+            st_kernel_id_t const kernel_id = kernel_ids[ ii ];
+            st_size_t const min_num_args = min_num_kernel_args[ ii ];
 
             if( kernel_id == st::ARCH_ILLEGAL_KERNEL_ID ) continue;
-            if( min_num_args == _size_t{ 0 } ) continue;
+            if( min_num_args == st_size_t{ 0 } ) continue;
 
-            _size_t const num_args = this->kernelNumArgs( kernel_id );
-            _size_t const arg_idx = particles_arg_idx[ ii ];
+            st_size_t const num_args = this->kernelNumArgs( kernel_id );
+            st_size_t const arg_idx = particles_arg_idx[ ii ];
 
             if( ( num_args <= arg_idx ) || ( num_args < min_num_args ) )
             {
@@ -301,14 +383,14 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::assign_particle_set_arg(
-        _size_t const particle_set_index,
-        _size_t const num_particles_in_selected_set )
+    st_status_t ctx_t::assign_particle_set_arg(
+        st_size_t const particle_set_index,
+        st_size_t const num_particles_in_selected_set )
     {
-        _status_t status = st::ARCH_STATUS_SUCCESS;
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
         constexpr size_t NUM_KERNELS = size_t{ 3 };
 
-        _kernel_id_t kernel_ids[ NUM_KERNELS ] =
+        st_kernel_id_t kernel_ids[ NUM_KERNELS ] =
         {
             st::ARCH_ILLEGAL_KERNEL_ID, st::ARCH_ILLEGAL_KERNEL_ID,
             st::ARCH_ILLEGAL_KERNEL_ID
@@ -318,30 +400,30 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_ids[ 1 ] = this->track_line_kernel_id();
         kernel_ids[ 2 ] = this->track_elem_by_elem_kernel_id();
 
-        _size_t const min_num_kernel_args[ NUM_KERNELS ] =
+        st_size_t const min_num_kernel_args[ NUM_KERNELS ] =
         {
-            _this_t::MIN_NUM_TRACK_UNTIL_ARGS, _this_t::MIN_NUM_TRACK_LINE_ARGS,
-            _this_t::MIN_NUM_TRACK_ELEM_ARGS
+            ctx_t::MIN_NUM_TRACK_UNTIL_ARGS, ctx_t::MIN_NUM_TRACK_LINE_ARGS,
+            ctx_t::MIN_NUM_TRACK_ELEM_ARGS
         };
 
-        _size_t const pset_arg_idx[ NUM_KERNELS ] =
+        st_size_t const pset_arg_idx[ NUM_KERNELS ] =
         {
-            _size_t{ 1 }, _size_t{ 1 }, _size_t{ 1 },
+            st_size_t{ 1 }, st_size_t{ 1 }, st_size_t{ 1 },
         };
 
         uint64_t const pset_idx_arg =
             static_cast< uint64_t >( particle_set_index );
 
-        for( _size_t ii = _size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
+        for( st_size_t ii = st_size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
         {
-            _kernel_id_t const kernel_id = kernel_ids[ ii ];
-            _size_t const min_num_args = min_num_kernel_args[ ii ];
+            st_kernel_id_t const kernel_id = kernel_ids[ ii ];
+            st_size_t const min_num_args = min_num_kernel_args[ ii ];
 
             if( kernel_id == st::ARCH_ILLEGAL_KERNEL_ID ) continue;
-            if( min_num_args == _size_t{ 0 } ) continue;
+            if( min_num_args == st_size_t{ 0 } ) continue;
 
-            _size_t const num_args = this->kernelNumArgs( kernel_id );
-            _size_t const arg_idx  = pset_arg_idx[ ii ];
+            st_size_t const num_args = this->kernelNumArgs( kernel_id );
+            st_size_t const arg_idx  = pset_arg_idx[ ii ];
 
             if( ( num_args <= arg_idx ) || ( num_args < min_num_args ) )
             {
@@ -361,13 +443,13 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::assign_beam_elements_arg(
-        ClArgument& SIXTRL_RESTRICT_REF beam_elements_arg )
+    st_status_t ctx_t::assign_beam_elements_arg(
+        ctx_t::cl_argument_t& SIXTRL_RESTRICT_REF beam_elements_arg )
     {
-        using size_t       = _size_t;
-        using kernel_id_t  = _kernel_id_t;
+        using size_t       = st_size_t;
+        using st_kernel_id_t  = st_kernel_id_t;
 
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         if( ( !beam_elements_arg.usesCObjectBuffer() ) ||
             (  beam_elements_arg.ptrCObjectBuffer() == nullptr ) ||
@@ -381,7 +463,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
         status = st::ARCH_STATUS_SUCCESS;
 
-        kernel_id_t kernel_ids[ NUM_KERNELS ];
+        st_kernel_id_t kernel_ids[ NUM_KERNELS ];
         std::fill( &kernel_ids[ 0 ], &kernel_ids[ NUM_KERNELS ],
                    st::ARCH_ILLEGAL_KERNEL_ID );
 
@@ -393,10 +475,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
         size_t const min_num_kernel_args[ NUM_KERNELS ] =
         {
-            _this_t::MIN_NUM_TRACK_UNTIL_ARGS, _this_t::MIN_NUM_TRACK_LINE_ARGS,
-            _this_t::MIN_NUM_TRACK_ELEM_ARGS,
-            _this_t::MIN_NUM_ASSIGN_BE_MON_ARGS,
-            _this_t::MIN_NUM_CLEAR_BE_MON_ARGS
+            ctx_t::MIN_NUM_TRACK_UNTIL_ARGS, ctx_t::MIN_NUM_TRACK_LINE_ARGS,
+            ctx_t::MIN_NUM_TRACK_ELEM_ARGS,
+            ctx_t::MIN_NUM_ASSIGN_BE_MON_ARGS,
+            ctx_t::MIN_NUM_CLEAR_BE_MON_ARGS
         };
 
         size_t const beam_elems_arg_idx[ NUM_KERNELS ] =
@@ -410,7 +492,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
         for( size_t ii = size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
         {
-            kernel_id_t const kernel_id = kernel_ids[ ii ];
+            st_kernel_id_t const kernel_id = kernel_ids[ ii ];
             size_t const min_num_args = min_num_kernel_args[ ii ];
 
             if( kernel_id == st::ARCH_ILLEGAL_KERNEL_ID ) continue;
@@ -431,13 +513,13 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::assign_output_buffer_arg(
-        ClArgument& SIXTRL_RESTRICT_REF out_buffer_arg )
+    st_status_t ctx_t::assign_output_buffer_arg(
+        ctx_t::cl_argument_t& SIXTRL_RESTRICT_REF out_buffer_arg )
     {
-        using size_t       = _size_t;
-        using kernel_id_t  = _kernel_id_t;
+        using size_t       = st_size_t;
+        using st_kernel_id_t  = st_kernel_id_t;
 
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         if( ( !out_buffer_arg.usesCObjectBuffer() ) ||
             (  out_buffer_arg.ptrCObjectBuffer() == nullptr ) )
@@ -448,7 +530,7 @@ namespace SIXTRL_CXX_NAMESPACE
         status = st::ARCH_STATUS_SUCCESS;
         constexpr size_t NUM_KERNELS = size_t{ 2 };
 
-        kernel_id_t kernel_ids[ NUM_KERNELS ] =
+        st_kernel_id_t kernel_ids[ NUM_KERNELS ] =
         {
             st::ARCH_ILLEGAL_KERNEL_ID, st::ARCH_ILLEGAL_KERNEL_ID
         };
@@ -458,19 +540,19 @@ namespace SIXTRL_CXX_NAMESPACE
 
         size_t const min_num_kernel_args[ NUM_KERNELS ] =
         {
-            _this_t::MIN_NUM_ASSIGN_BE_MON_ARGS,
-            _this_t::MIN_NUM_ASSIGN_ELEM_ARGS
+            ctx_t::MIN_NUM_ASSIGN_BE_MON_ARGS,
+            ctx_t::MIN_NUM_ASSIGN_ELEM_ARGS
         };
 
         size_t const out_buffer_arg_idx[ NUM_KERNELS ] =
         {
-            size_t{ 1 }, // assign_be_mon
-            size_t{ 1 }, // clear_be_mon
+            size_t{ 1 }, // assign_beam_monitor_output_kernel
+            size_t{ 2 }, // assign_elem_by_elem_output_kernel
         };
 
         for( size_t ii = size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
         {
-            kernel_id_t const kernel_id = kernel_ids[ ii ];
+            st_kernel_id_t const kernel_id = kernel_ids[ ii ];
             size_t const min_num_args = min_num_kernel_args[ ii ];
 
             if( kernel_id == st::ARCH_ILLEGAL_KERNEL_ID ) continue;
@@ -491,16 +573,21 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::assign_elem_by_elem_config_arg(
-        _this_t::cl_buffer_t& SIXTRL_RESTRICT_REF elem_by_elem_config_arg )
+    st_status_t ctx_t::assign_elem_by_elem_config_buffer_arg(
+            ctx_t::cl_argument_t& SIXTRL_RESTRICT_REF config_buffer_arg )
     {
-        using size_t       = _size_t;
-        using kernel_id_t  = _kernel_id_t;
+        constexpr st_size_t NUM_KERNELS = st_size_t{ 2 };
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        _status_t status = st::ARCH_STATUS_SUCCESS;
-        constexpr size_t NUM_KERNELS = size_t{ 2 };
+        if( ( !config_buffer_arg.usesCObjectBuffer() ) ||
+            (  config_buffer_arg.ptrCObjectBuffer() == nullptr ) )
+        {
+            return status;
+        }
+
+        status = st::ARCH_STATUS_SUCCESS;
 
-        kernel_id_t kernel_ids[ NUM_KERNELS ] =
+        st_kernel_id_t kernel_ids[ NUM_KERNELS ] =
         {
             st::ARCH_ILLEGAL_KERNEL_ID, st::ARCH_ILLEGAL_KERNEL_ID
         };
@@ -508,28 +595,28 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_ids[ 0 ] = this->track_elem_by_elem_kernel_id();
         kernel_ids[ 1 ] = this->assign_elem_by_elem_output_kernel_id();
 
-        size_t const min_num_kernel_args[ NUM_KERNELS ] =
+        st_size_t const min_num_kernel_args[ NUM_KERNELS ] =
         {
-            _this_t::MIN_NUM_TRACK_ELEM_ARGS,
-            _this_t::MIN_NUM_ASSIGN_ELEM_ARGS
+            ctx_t::MIN_NUM_TRACK_ELEM_ARGS,
+            ctx_t::MIN_NUM_ASSIGN_ELEM_ARGS
         };
 
-        size_t const elem_by_elem_arg_idx[ NUM_KERNELS ] =
+        st_size_t const elem_by_elem_arg_idx[ NUM_KERNELS ] =
         {
-            size_t{ 3 }, // assign_be_mon
-            size_t{ 0 }, // clear_be_mon
+            st_size_t{ 3 }, // track_elem_by_elem_kernel
+            st_size_t{ 0 }, // assign_elem_by_elem_output_kernel
         };
 
-        for( size_t ii = size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
+        for( st_size_t ii = st_size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
         {
-            kernel_id_t const kernel_id = kernel_ids[ ii ];
-            size_t const min_num_args = min_num_kernel_args[ ii ];
+            st_kernel_id_t const kernel_id = kernel_ids[ ii ];
+            st_size_t const min_num_args = min_num_kernel_args[ ii ];
 
             if( kernel_id == st::ARCH_ILLEGAL_KERNEL_ID ) continue;
-            if( min_num_args == size_t{ 0 } ) continue;
+            if( min_num_args == st_size_t{ 0 } ) continue;
 
-            size_t const num_args = this->kernelNumArgs( kernel_id );
-            size_t const arg_idx  = elem_by_elem_arg_idx[ ii ];
+            st_size_t const num_args = this->kernelNumArgs( kernel_id );
+            st_size_t const arg_idx  = elem_by_elem_arg_idx[ ii ];
 
             if( ( num_args <= arg_idx ) || ( num_args < min_num_args ) )
             {
@@ -537,43 +624,77 @@ namespace SIXTRL_CXX_NAMESPACE
                 continue;
             }
 
-            this->assignKernelArgumentClBuffer(
-                kernel_id, arg_idx, elem_by_elem_config_arg );
+            this->assignKernelArgument( kernel_id, arg_idx, config_buffer_arg );
         }
 
         return status;
     }
 
+    st_status_t ctx_t::assign_particles_addr_buffer_arg(
+        ClArgument& SIXTRL_RESTRICT_REF particles_addr_arg )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( ( !particles_addr_arg.usesCObjectBuffer() ) ||
+            (  particles_addr_arg.ptrCObjectBuffer() == nullptr ) )
+        {
+            return status;
+        }
+
+        status = st::ARCH_STATUS_SUCCESS;
+        st_kernel_id_t const kernel_id = this->fetch_particles_addr_kernel_id();
+
+        if( ( kernel_id != st::ARCH_ILLEGAL_KERNEL_ID ) &&
+            ( st_size_t{ 1 } <= ctx_t::MIN_NUM_FETCH_PARTICLES_ADDR_ARGS ) &&
+            ( ctx_t::MIN_NUM_FETCH_PARTICLES_ADDR_ARGS <=
+                this->kernelNumArgs( kernel_id ) ) )
+        {
+            this->assignKernelArgument( kernel_id, st_size_t{ 1 },
+                                        particles_addr_arg );
+
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    st_status_t ctx_t::assign_elem_by_elem_config_index_arg(
+        st_size_t const elem_by_elem_config_index )
+    {
+        return this->doAssignElemByElemConfigIndexArg(
+            elem_by_elem_config_index );
+    }
+
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    bool ClContext::has_track_until_kernel() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_track_until_kernel() const SIXTRL_NOEXCEPT
     {
         return ( ( this->hasSelectedNode() ) &&
-                 ( this->m_track_until_turn_kernel_id >= _kernel_id_t{ 0 } ) &&
-                 ( static_cast< _size_t >( this->m_track_until_turn_kernel_id )
+                 ( this->m_track_until_turn_kernel_id >= st_kernel_id_t{ 0 } ) &&
+                 ( static_cast< st_size_t >( this->m_track_until_turn_kernel_id )
                     < this->numAvailableKernels() ) );
     }
 
-    _kernel_id_t ClContext::track_until_kernel_id() const SIXTRL_NOEXCEPT
+    st_kernel_id_t ctx_t::track_until_kernel_id() const SIXTRL_NOEXCEPT
     {
         return ( this->has_track_until_kernel() )
             ? this->m_track_until_turn_kernel_id : st::ARCH_ILLEGAL_KERNEL_ID;
     }
 
-    _status_t ClContext::set_track_until_kernel_id(
-        _kernel_id_t const kernel_id )
+    st_status_t ctx_t::set_track_until_kernel_id(
+        st_kernel_id_t const kernel_id )
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        if( ( this->hasSelectedNode() ) && ( kernel_id >= _kernel_id_t{ 0 } ) &&
-            ( static_cast< _size_t >( kernel_id ) <
+        if( ( this->hasSelectedNode() ) && ( kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >( kernel_id ) <
                 this->numAvailableKernels() ) )
         {
-            _program_id_t const program_id =
+            st_program_id_t const program_id =
                 this->programIdByKernelId( kernel_id );
 
-            if( ( program_id >= _program_id_t{ 0 } ) &&
-                ( static_cast< _size_t >( program_id ) <
+            if( ( program_id >= st_program_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( program_id ) <
                     this->numAvailablePrograms() ) )
             {
                 this->m_track_until_turn_kernel_id  = kernel_id;
@@ -585,26 +706,26 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::track_status_t ClContext::track_until(
-        _this_t::num_turns_t const until_turn )
+    ctx_t::track_status_t ctx_t::track_until(
+        ctx_t::num_turns_t const until_turn )
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
-        _kernel_id_t const kernel_id = this->track_until_kernel_id();
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        ctx_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        st_kernel_id_t const kernel_id = this->track_until_kernel_id();
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_TRACK_UNTIL_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_TRACK_UNTIL_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_TRACK_UNTIL_ARGS >= _size_t{ 4 } );
-            SIXTRL_ASSERT( this->m_num_particles_in_pset > _size_t{ 0 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_TRACK_UNTIL_ARGS >= st_size_t{ 4 } );
+            SIXTRL_ASSERT( this->m_num_particles_in_pset > st_size_t{ 0 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
             int64_t const until_turn_arg = static_cast< int64_t >( until_turn );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 3 }, until_turn_arg );
+                kernel_id, st_size_t{ 3 }, until_turn_arg );
 
             if( !this->debugMode() )
             {
@@ -620,7 +741,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 if( this->runKernel( kernel_id, this->m_num_particles_in_pset,
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
-                    status = static_cast< _this_t::track_status_t >(
+                    status = static_cast< ctx_t::track_status_t >(
                         this->eval_status_flags_after_use() );
                 }
             }
@@ -629,22 +750,22 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::track_status_t ClContext::track_until(
-        _this_t::num_turns_t const until_turn, _size_t const pset_index,
-        _size_t const num_particles_in_set, bool const restore_pset_index )
+    ctx_t::track_status_t ctx_t::track_until(
+        ctx_t::num_turns_t const until_turn, st_size_t const pset_index,
+        st_size_t const num_particles_in_set, bool const restore_pset_index )
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
-        _kernel_id_t const kernel_id = this->track_until_kernel_id();
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        ctx_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        st_kernel_id_t const kernel_id = this->track_until_kernel_id();
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_TRACK_UNTIL_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_TRACK_UNTIL_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_TRACK_UNTIL_ARGS >= _size_t{ 4 } );
-            SIXTRL_ASSERT( num_particles_in_set != _size_t{ 0 } );
-            SIXTRL_ASSERT( this->m_num_particles_in_pset > _size_t{ 0 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_TRACK_UNTIL_ARGS >= st_size_t{ 4 } );
+            SIXTRL_ASSERT( num_particles_in_set != st_size_t{ 0 } );
+            SIXTRL_ASSERT( this->m_num_particles_in_pset > st_size_t{ 0 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
             if( this->m_pset_index != pset_index )
@@ -653,13 +774,13 @@ namespace SIXTRL_CXX_NAMESPACE
                     static_cast< uint64_t >( pset_index );
 
                 this->assignKernelArgumentValue(
-                    kernel_id, _size_t{ 1 }, pset_index_arg );
+                    kernel_id, st_size_t{ 1 }, pset_index_arg );
             }
 
             int64_t const until_turn_arg = static_cast< int64_t >( until_turn );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 3 }, until_turn_arg );
+                kernel_id, st_size_t{ 3 }, until_turn_arg );
 
             if( !this->debugMode() )
             {
@@ -675,7 +796,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 if( this->runKernel( kernel_id, num_particles_in_set,
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
-                    status = static_cast< _this_t::track_status_t >(
+                    status = static_cast< ctx_t::track_status_t >(
                         this->eval_status_flags_after_use() );
                 }
             }
@@ -686,7 +807,7 @@ namespace SIXTRL_CXX_NAMESPACE
                     static_cast< uint64_t >( this->m_pset_index );
 
                 this->assignKernelArgumentValue(
-                    kernel_id, _size_t{ 1 }, pset_index_arg );
+                    kernel_id, st_size_t{ 1 }, pset_index_arg );
             }
         }
 
@@ -695,33 +816,33 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    bool ClContext::has_track_line_kernel() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_track_line_kernel() const SIXTRL_NOEXCEPT
     {
         return ( ( this->hasSelectedNode() ) &&
-            ( this->m_track_line_kernel_id >= _kernel_id_t{ 0 } ) &&
-                ( static_cast< _size_t >( this->m_track_line_kernel_id ) <
+            ( this->m_track_line_kernel_id >= st_kernel_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( this->m_track_line_kernel_id ) <
                     this->numAvailableKernels() ) );
     }
 
-    _kernel_id_t ClContext::track_line_kernel_id() const SIXTRL_NOEXCEPT
+    st_kernel_id_t ctx_t::track_line_kernel_id() const SIXTRL_NOEXCEPT
     {
         return ( this->has_track_until_kernel() )
             ? this->m_track_line_kernel_id : st::ARCH_ILLEGAL_KERNEL_ID;
     }
 
-    _status_t ClContext::set_track_line_kernel_id(
-        _kernel_id_t const kernel_id )
+    st_status_t ctx_t::set_track_line_kernel_id(
+        st_kernel_id_t const kernel_id )
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        if( ( this->hasSelectedNode() ) && ( kernel_id >= _kernel_id_t{ 0 } ) &&
-            ( static_cast< _size_t >( kernel_id ) < this->numAvailableKernels() ) )
+        if( ( this->hasSelectedNode() ) && ( kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >( kernel_id ) < this->numAvailableKernels() ) )
         {
-            _program_id_t const program_id =
+            st_program_id_t const program_id =
                 this->programIdByKernelId( kernel_id );
 
-            if( ( program_id >= _program_id_t{ 0 } ) &&
-                ( static_cast< _size_t >( program_id ) <
+            if( ( program_id >= st_program_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( program_id ) <
                     this->numAvailablePrograms() ) )
             {
                 this->m_track_line_kernel_id  = kernel_id;
@@ -733,20 +854,20 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::track_status_t ClContext::track_line( _size_t const line_begin_idx,
-        _size_t const line_end_idx, bool const finish_turn )
+    ctx_t::track_status_t ctx_t::track_line( st_size_t const line_begin_idx,
+        st_size_t const line_end_idx, bool const finish_turn )
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
-        _kernel_id_t const kernel_id = this->track_line_kernel_id();
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        ctx_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        st_kernel_id_t const kernel_id = this->track_line_kernel_id();
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_TRACK_LINE_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_TRACK_LINE_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_TRACK_LINE_ARGS >= _size_t{ 7 } );
-            SIXTRL_ASSERT( this->m_num_particles_in_pset > _size_t{ 0 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_TRACK_LINE_ARGS >= st_size_t{ 7 } );
+            SIXTRL_ASSERT( this->m_num_particles_in_pset > st_size_t{ 0 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
             uint64_t const line_begin_idx_arg =
@@ -759,13 +880,13 @@ namespace SIXTRL_CXX_NAMESPACE
                 ? uint64_t{ 1 } : uint64_t{ 0 };
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 3 }, line_begin_idx_arg );
+                kernel_id, st_size_t{ 3 }, line_begin_idx_arg );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 4 }, line_end_idx_arg );
+                kernel_id, st_size_t{ 4 }, line_end_idx_arg );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 5 }, finish_turn_arg );
+                kernel_id, st_size_t{ 5 }, finish_turn_arg );
 
             if( !this->debugMode() )
             {
@@ -781,7 +902,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 if( this->runKernel( kernel_id, this->m_num_particles_in_pset,
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
-                    status = static_cast< _this_t::track_status_t >(
+                    status = static_cast< ctx_t::track_status_t >(
                         this->eval_status_flags_after_use() );
                 }
             }
@@ -790,25 +911,25 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::track_status_t ClContext::track_line(
-        _this_t::size_type const line_begin_idx,
-        _this_t::size_type const line_end_idx,
+    ctx_t::track_status_t ctx_t::track_line(
+        ctx_t::size_type const line_begin_idx,
+        ctx_t::size_type const line_end_idx,
         bool const finish_turn,
-        _this_t::size_type const pset_index,
-        _this_t::size_type const num_particles_in_set,
+        ctx_t::size_type const pset_index,
+        ctx_t::size_type const num_particles_in_set,
         bool const restore_pset_index )
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
-        _kernel_id_t const kernel_id = this->track_line_kernel_id();
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        ctx_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        st_kernel_id_t const kernel_id = this->track_line_kernel_id();
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_TRACK_LINE_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_TRACK_LINE_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_TRACK_LINE_ARGS >= _size_t{ 7 } );
-            SIXTRL_ASSERT( num_particles_in_set != _size_t{ 0 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_TRACK_LINE_ARGS >= st_size_t{ 7 } );
+            SIXTRL_ASSERT( num_particles_in_set != st_size_t{ 0 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
             if( this->m_pset_index != pset_index )
@@ -817,7 +938,7 @@ namespace SIXTRL_CXX_NAMESPACE
                     static_cast< uint64_t >( pset_index );
 
                 this->assignKernelArgumentValue(
-                    kernel_id, _size_t{ 1 }, pset_index_arg );
+                    kernel_id, st_size_t{ 1 }, pset_index_arg );
             }
 
             uint64_t const line_begin_idx_arg =
@@ -830,13 +951,13 @@ namespace SIXTRL_CXX_NAMESPACE
                 ? uint64_t{ 1 } : uint64_t{ 0 };
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 3 }, line_begin_idx_arg );
+                kernel_id, st_size_t{ 3 }, line_begin_idx_arg );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 4 }, line_end_idx_arg );
+                kernel_id, st_size_t{ 4 }, line_end_idx_arg );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 5 }, finish_turn_arg );
+                kernel_id, st_size_t{ 5 }, finish_turn_arg );
 
             if( !this->debugMode() )
             {
@@ -852,7 +973,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 if( this->runKernel( kernel_id, num_particles_in_set,
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
-                    status = static_cast< _this_t::track_status_t >(
+                    status = static_cast< ctx_t::track_status_t >(
                         this->eval_status_flags_after_use() );
                 }
             }
@@ -864,7 +985,7 @@ namespace SIXTRL_CXX_NAMESPACE
                     static_cast< uint64_t >( this->m_pset_index );
 
                 this->assignKernelArgumentValue(
-                    kernel_id, _size_t{ 1 }, pset_index_arg );
+                    kernel_id, st_size_t{ 1 }, pset_index_arg );
             }
         }
 
@@ -873,35 +994,35 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    bool ClContext::has_track_elem_by_elem_kernel() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_track_elem_by_elem_kernel() const SIXTRL_NOEXCEPT
     {
         return ( ( this->hasSelectedNode() ) &&
-            ( this->m_track_elem_by_elem_kernel_id >= _kernel_id_t{ 0 } ) &&
-            ( static_cast< _size_t >( this->m_track_elem_by_elem_kernel_id ) <
+            ( this->m_track_elem_by_elem_kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >( this->m_track_elem_by_elem_kernel_id ) <
                          this->numAvailableKernels() ) );
     }
 
-    _kernel_id_t ClContext::track_elem_by_elem_kernel_id() const SIXTRL_NOEXCEPT
+    st_kernel_id_t ctx_t::track_elem_by_elem_kernel_id() const SIXTRL_NOEXCEPT
     {
         return ( this->has_track_elem_by_elem_kernel() )
             ? this->m_track_elem_by_elem_kernel_id : st::ARCH_ILLEGAL_KERNEL_ID;
     }
 
-    _status_t ClContext::set_track_elem_by_elem_kernel_id(
-        _kernel_id_t const kernel_id )
+    st_status_t ctx_t::set_track_elem_by_elem_kernel_id(
+        st_kernel_id_t const kernel_id )
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
         if( ( this->hasSelectedNode() ) &&
-            ( kernel_id >= _kernel_id_t{ 0 } ) &&
-            ( static_cast< _size_t >( kernel_id ) <
+            ( kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >( kernel_id ) <
                 this->numAvailableKernels() ) )
         {
-            _program_id_t const program_id =
+            st_program_id_t const program_id =
                 this->programIdByKernelId( kernel_id );
 
-            if( ( program_id >= _program_id_t{ 0 } ) &&
-                ( static_cast< _size_t >( program_id ) <
+            if( ( program_id >= st_program_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( program_id ) <
                   this->numAvailablePrograms() ) )
             {
                 this->m_track_elem_by_elem_kernel_id  = kernel_id;
@@ -913,29 +1034,29 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::track_status_t ClContext::track_elem_by_elem(
-        _size_t const until_turn )
+    ctx_t::track_status_t ctx_t::track_elem_by_elem(
+        st_size_t const until_turn )
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        ctx_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
 
-        _kernel_id_t const kernel_id =
+        st_kernel_id_t const kernel_id =
             this->track_elem_by_elem_kernel_id();
 
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_TRACK_ELEM_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_TRACK_ELEM_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_TRACK_ELEM_ARGS >= _size_t{ 6 } );
-            SIXTRL_ASSERT( this->m_num_particles_in_pset > _size_t{ 0 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_TRACK_ELEM_ARGS >= st_size_t{ 6 } );
+            SIXTRL_ASSERT( this->m_num_particles_in_pset > st_size_t{ 0 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
             int64_t const until_turn_arg = static_cast< int64_t >( until_turn );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 4 }, until_turn_arg );
+                kernel_id, st_size_t{ 5 }, until_turn_arg );
 
             if( !this->debugMode() )
             {
@@ -951,7 +1072,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 if( this->runKernel( kernel_id, this->m_num_particles_in_pset,
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
-                    status = static_cast< _this_t::track_status_t >(
+                    status = static_cast< ctx_t::track_status_t >(
                         this->eval_status_flags_after_use() );
                 }
             }
@@ -960,24 +1081,24 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _this_t::track_status_t ClContext::track_elem_by_elem(
-        _size_t const until_turn, _size_t const pset_index,
-        _size_t const num_particles_in_set, bool const restore_pset_index )
+    ctx_t::track_status_t ctx_t::track_elem_by_elem(
+        st_size_t const until_turn, st_size_t const pset_index,
+        st_size_t const num_particles_in_set, bool const restore_pset_index )
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        ctx_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
 
-        _kernel_id_t const kernel_id =
+        st_kernel_id_t const kernel_id =
             this->track_elem_by_elem_kernel_id();
 
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_TRACK_ELEM_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_TRACK_ELEM_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_TRACK_ELEM_ARGS >= _size_t{ 6 } );
-            SIXTRL_ASSERT( num_particles_in_set != _size_t{ 0 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_TRACK_ELEM_ARGS >= st_size_t{ 6 } );
+            SIXTRL_ASSERT( num_particles_in_set != st_size_t{ 0 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
             if( this->m_pset_index != pset_index )
@@ -986,13 +1107,13 @@ namespace SIXTRL_CXX_NAMESPACE
                     static_cast< uint64_t >( pset_index );
 
                 this->assignKernelArgumentValue(
-                    kernel_id, _size_t{ 1 }, pset_index_arg );
+                    kernel_id, st_size_t{ 1 }, pset_index_arg );
             }
 
             int64_t const until_turn_arg = static_cast< int64_t >( until_turn );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 4 }, until_turn_arg );
+                kernel_id, st_size_t{ 5 }, until_turn_arg );
 
             if( !this->debugMode() )
             {
@@ -1008,7 +1129,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 if( this->runKernel( kernel_id, this->m_num_particles_in_pset,
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
-                    status = static_cast< _this_t::track_status_t >(
+                    status = static_cast< ctx_t::track_status_t >(
                         this->eval_status_flags_after_use() );
                 }
             }
@@ -1020,7 +1141,7 @@ namespace SIXTRL_CXX_NAMESPACE
                     static_cast< uint64_t >( this->m_pset_index );
 
                 this->assignKernelArgumentValue(
-                    kernel_id, _size_t{ 1 }, pset_index_arg );
+                    kernel_id, st_size_t{ 1 }, pset_index_arg );
             }
         }
 
@@ -1029,17 +1150,17 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    bool ClContext::has_assign_beam_monitor_output_kernel() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_assign_beam_monitor_output_kernel() const SIXTRL_NOEXCEPT
     {
         return ( ( this->hasSelectedNode() ) &&
             ( this->m_assign_be_mon_out_buffer_kernel_id >=
-                _kernel_id_t{ 0 } ) &&
-            ( static_cast< _size_t >(
+                st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >(
                 this->m_assign_be_mon_out_buffer_kernel_id ) <
                 this->numAvailableKernels() ) );
     }
 
-    _kernel_id_t ClContext::assign_beam_monitor_output_kernel_id(
+    st_kernel_id_t ctx_t::assign_beam_monitor_output_kernel_id(
         ) const SIXTRL_NOEXCEPT
     {
         return ( this->has_assign_beam_monitor_output_kernel() )
@@ -1047,20 +1168,20 @@ namespace SIXTRL_CXX_NAMESPACE
             : st::ARCH_ILLEGAL_KERNEL_ID;
     }
 
-    _status_t ClContext::set_assign_beam_monitor_output_kernel_id(
-        _kernel_id_t const kernel_id )
+    st_status_t ctx_t::set_assign_beam_monitor_output_kernel_id(
+        st_kernel_id_t const kernel_id )
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        if( ( this->hasSelectedNode() ) && ( kernel_id >= _kernel_id_t{ 0 } ) &&
+        if( ( this->hasSelectedNode() ) && ( kernel_id >= st_kernel_id_t{ 0 } ) &&
             ( this->numAvailableKernels() >
-                static_cast< _size_t >( kernel_id ) ) )
+                static_cast< st_size_t >( kernel_id ) ) )
         {
-            _program_id_t const program_id =
+            st_program_id_t const program_id =
                 this->programIdByKernelId( kernel_id );
 
-            if( ( program_id >= _program_id_t{ 0 } ) &&
-                ( static_cast< _size_t >( program_id ) <
+            if( ( program_id >= st_program_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( program_id ) <
                     this->numAvailablePrograms() ) )
             {
                 this->m_assign_be_mon_out_buffer_kernel_id  = kernel_id;
@@ -1072,23 +1193,23 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::assign_beam_monitor_output(
-        _this_t::particle_index_t const min_turn_id,
-        _size_t const out_buffer_index_offset  )
+    st_status_t ctx_t::assign_beam_monitor_output(
+        ctx_t::particle_index_t const min_turn_id,
+        st_size_t const out_buffer_index_offset  )
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        _kernel_id_t const kernel_id =
+        st_kernel_id_t const kernel_id =
             this->assign_beam_monitor_output_kernel_id();
 
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_ASSIGN_BE_MON_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_ASSIGN_BE_MON_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_ASSIGN_BE_MON_ARGS >= _size_t{ 5 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_ASSIGN_BE_MON_ARGS >= st_size_t{ 5 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
             int64_t const min_turn_id_arg =
@@ -1098,14 +1219,14 @@ namespace SIXTRL_CXX_NAMESPACE
                 static_cast< uint64_t >( out_buffer_index_offset );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 2 }, min_turn_id_arg );
+                kernel_id, st_size_t{ 2 }, min_turn_id_arg );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 3 }, out_buffer_index_offset_arg );
+                kernel_id, st_size_t{ 3 }, out_buffer_index_offset_arg );
 
             if( !this->debugMode() )
             {
-                if( this->runKernel( kernel_id, _size_t{ 1 },
+                if( this->runKernel( kernel_id, st_size_t{ 1 },
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
                     status = st::TRACK_SUCCESS;
@@ -1114,7 +1235,7 @@ namespace SIXTRL_CXX_NAMESPACE
             else if( this->prepare_status_flags_for_use() ==
                      st::ARCH_STATUS_SUCCESS )
             {
-                if( this->runKernel( kernel_id, _size_t{ 1 },
+                if( this->runKernel( kernel_id, st_size_t{ 1 },
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
                     status = this->eval_status_flags_after_use();
@@ -1127,37 +1248,37 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    bool ClContext::has_assign_elem_by_elem_output_kernel() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_assign_elem_by_elem_output_kernel() const SIXTRL_NOEXCEPT
     {
         return ( ( this->hasSelectedNode() ) &&
             ( this->m_assign_elem_by_elem_out_buffer_kernel_id >=
-                _kernel_id_t{ 0 } ) &&
-            ( static_cast< _size_t >(
+                st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >(
                 this->m_assign_elem_by_elem_out_buffer_kernel_id ) <
                 this->numAvailableKernels() ) );
     }
 
-    _kernel_id_t ClContext::assign_elem_by_elem_output_kernel_id() const SIXTRL_NOEXCEPT
+    st_kernel_id_t ctx_t::assign_elem_by_elem_output_kernel_id() const SIXTRL_NOEXCEPT
     {
         return ( this->has_assign_elem_by_elem_output_kernel() )
             ? this->m_assign_elem_by_elem_out_buffer_kernel_id
             : st::ARCH_ILLEGAL_KERNEL_ID;
     }
 
-    _status_t ClContext::set_assign_elem_by_elem_output_kernel_id(
-        _kernel_id_t const kernel_id )
+    st_status_t ctx_t::set_assign_elem_by_elem_output_kernel_id(
+        st_kernel_id_t const kernel_id )
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        if( ( this->hasSelectedNode() ) && ( kernel_id >= _kernel_id_t{ 0 } ) &&
+        if( ( this->hasSelectedNode() ) && ( kernel_id >= st_kernel_id_t{ 0 } ) &&
             ( this->numAvailableKernels() >
-                static_cast< _size_t >( kernel_id ) ) )
+                static_cast< st_size_t >( kernel_id ) ) )
         {
-            _program_id_t const program_id = this->programIdByKernelId(
+            st_program_id_t const program_id = this->programIdByKernelId(
                 kernel_id );
 
-            if( ( program_id >= _program_id_t{ 0 } ) &&
-                ( static_cast< _size_t >( program_id ) <
+            if( ( program_id >= st_program_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( program_id ) <
                     this->numAvailablePrograms() ) )
             {
                 this->m_assign_elem_by_elem_out_buffer_kernel_id  = kernel_id;
@@ -1169,33 +1290,39 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::assign_elem_by_elem_output(
-        ClContext::size_type const out_buffer_index_offset )
+    st_status_t ctx_t::assign_elem_by_elem_output(
+        ctx_t::size_type const out_buffer_index_offset )
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        _kernel_id_t const kernel_id =
+        st_kernel_id_t const kernel_id =
             this->assign_elem_by_elem_output_kernel_id();
 
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_ASSIGN_ELEM_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_ASSIGN_ELEM_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_ASSIGN_ELEM_ARGS >= _size_t{ 4 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_ASSIGN_ELEM_ARGS >= st_size_t{ 4 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
+            uint64_t const elem_by_elem_config_index_arg =
+                static_cast< uint64_t >( this->m_elem_by_elem_config_index );
+
+            this->assignKernelArgumentValue(
+                kernel_id, st_size_t{ 1 }, elem_by_elem_config_index_arg );
+
             uint64_t const out_buffer_index_offset_arg =
                 static_cast< uint64_t >( out_buffer_index_offset );
 
             this->assignKernelArgumentValue(
-                kernel_id, _size_t{ 2 }, out_buffer_index_offset_arg );
+                kernel_id, st_size_t{ 3 }, out_buffer_index_offset_arg );
 
             if( !this->debugMode() )
             {
-                if( this->runKernel( kernel_id, _size_t{ 1 },
+                if( this->runKernel( kernel_id, st_size_t{ 1 },
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
                     status = st::TRACK_SUCCESS;
@@ -1204,7 +1331,7 @@ namespace SIXTRL_CXX_NAMESPACE
             else if( this->prepare_status_flags_for_use() ==
                      st::ARCH_STATUS_SUCCESS )
             {
-                if( this->runKernel( kernel_id, _size_t{ 1 },
+                if( this->runKernel( kernel_id, st_size_t{ 1 },
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
                     status = this->eval_status_flags_after_use();
@@ -1217,36 +1344,34 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    bool ClContext::has_clear_beam_monitor_output_kernel() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_clear_beam_monitor_output_kernel() const SIXTRL_NOEXCEPT
     {
         return ( ( this->hasSelectedNode() ) &&
-            ( this->m_clear_be_mon_kernel_id >= _kernel_id_t{ 0 } ) &&
-            ( static_cast< _size_t >( this->m_clear_be_mon_kernel_id ) <
+            ( this->m_clear_be_mon_kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >( this->m_clear_be_mon_kernel_id ) <
                 this->numAvailableKernels() ) );
     }
 
-    _kernel_id_t ClContext::clear_beam_monitor_output_kernel_id() const SIXTRL_NOEXCEPT
+    st_kernel_id_t ctx_t::clear_beam_monitor_output_kernel_id() const SIXTRL_NOEXCEPT
     {
         return ( this->has_clear_beam_monitor_output_kernel() )
             ? this->m_clear_be_mon_kernel_id : st::ARCH_ILLEGAL_KERNEL_ID;
     }
 
-    _status_t ClContext::set_clear_beam_monitor_output_kernel_id(
-        _kernel_id_t const kernel_id )
+    st_status_t ctx_t::set_clear_beam_monitor_output_kernel_id(
+        st_kernel_id_t const kernel_id )
     {
-        using size_t = _size_t;
-        using kernel_id_t = _kernel_id_t;
-
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        if( ( this->hasSelectedNode() ) && ( kernel_id >= kernel_id_t{ 0 } ) &&
-            ( static_cast< size_t >( kernel_id ) < this->numAvailableKernels() ) )
+        if( ( this->hasSelectedNode() ) && ( kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >( kernel_id ) <
+                this->numAvailableKernels() ) )
         {
-            _program_id_t const program_id =
+            st_program_id_t const program_id =
                 this->programIdByKernelId( kernel_id );
 
-            if( ( program_id >= _program_id_t{ 0 } ) &&
-                ( static_cast< _size_t >( program_id ) <
+            if( ( program_id >= st_program_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( program_id ) <
                   this->numAvailablePrograms() ) )
             {
                 this->m_clear_be_mon_kernel_id  = kernel_id;
@@ -1258,26 +1383,26 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::clear_beam_monitor_output()
+    st_status_t ctx_t::clear_beam_monitor_output()
     {
-        _status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
 
-        _kernel_id_t const kernel_id =
+        st_kernel_id_t const kernel_id =
             this->clear_beam_monitor_output_kernel_id();
 
-        _size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
+        st_size_t const num_kernel_args = this->kernelNumArgs( kernel_id );
 
         if( ( this->hasSelectedNode() ) &&
-            ( num_kernel_args >= _this_t::MIN_NUM_CLEAR_BE_MON_ARGS ) )
+            ( num_kernel_args >= ctx_t::MIN_NUM_CLEAR_BE_MON_ARGS ) )
         {
-            SIXTRL_ASSERT( _this_t::MIN_NUM_CLEAR_BE_MON_ARGS >= _size_t{ 2 } );
-            SIXTRL_ASSERT( kernel_id >= _kernel_id_t{ 0 } );
-            SIXTRL_ASSERT( static_cast< _size_t >( kernel_id ) <
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_CLEAR_BE_MON_ARGS >= st_size_t{ 2 } );
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
                            this->numAvailableKernels() );
 
             if( !this->debugMode() )
             {
-                if( this->runKernel( kernel_id, _size_t{ 1 },
+                if( this->runKernel( kernel_id, st_size_t{ 1 },
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
                     status = st::TRACK_SUCCESS;
@@ -1286,7 +1411,7 @@ namespace SIXTRL_CXX_NAMESPACE
             else if( this->prepare_status_flags_for_use() ==
                      st::ARCH_STATUS_SUCCESS )
             {
-                if( this->runKernel( kernel_id, _size_t{ 1 },
+                if( this->runKernel( kernel_id, st_size_t{ 1 },
                         this->lastExecWorkGroupSize( kernel_id ) ) )
                 {
                     status = this->eval_status_flags_after_use();
@@ -1299,24 +1424,214 @@ namespace SIXTRL_CXX_NAMESPACE
 
     /* --------------------------------------------------------------------- */
 
-    _size_t ClContext::selected_particle_set() const SIXTRL_NOEXCEPT
+    bool ctx_t::has_fetch_particles_addr_kernel() const SIXTRL_NOEXCEPT
+    {
+        return ( ( this->hasSelectedNode() ) &&
+            ( this->m_fetch_particles_addr_kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >( this->m_fetch_particles_addr_kernel_id
+                ) < this->numAvailableKernels() ) );
+    }
+
+    st_kernel_id_t
+    ctx_t::fetch_particles_addr_kernel_id() const SIXTRL_NOEXCEPT
+    {
+        return ( this->has_fetch_particles_addr_kernel() )
+            ? this->m_fetch_particles_addr_kernel_id
+            : st::ARCH_ILLEGAL_KERNEL_ID;
+    }
+
+    ctx_t::status_t ctx_t::set_fetch_particles_addr_kernel_id(
+            st_kernel_id_t const kernel_id )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( ( this->hasSelectedNode() ) && ( kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< st_size_t >( kernel_id ) <
+                this->numAvailableKernels() ) )
+        {
+            st_program_id_t const program_id =
+                this->programIdByKernelId( kernel_id );
+
+            if( ( program_id >= st_program_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( program_id ) <
+                  this->numAvailablePrograms() ) )
+            {
+                this->m_fetch_particles_addr_kernel_id  = kernel_id;
+                this->m_fetch_particles_addr_program_id = program_id;
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    bool ctx_t::has_assign_addresses_kernel() const SIXTRL_NOEXCEPT
+    {
+        return ( ( this->m_assign_addr_kernel_id !=
+            st::ARCH_ILLEGAL_KERNEL_ID ) &&
+                 ( this->m_assign_addr_kernel_id <
+                   this->numAvailableKernels() ) );
+    }
+
+    st_kernel_id_t ctx_t::assign_addresses_kernel_id() const SIXTRL_NOEXCEPT
+    {
+        return this->m_assign_addr_kernel_id;
+    }
+
+    ctx_t::status_t ctx_t::set_assign_addresses_kernel_id(
+        st_kernel_id_t const kernel_id )
+    {
+        using size_t = st_size_t;
+        using st_kernel_id_t = st_kernel_id_t;
+
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( ( this->hasSelectedNode() ) && ( kernel_id >= st_kernel_id_t{ 0 } ) &&
+            ( static_cast< size_t >( kernel_id ) < this->numAvailableKernels() ) )
+        {
+            st_program_id_t const program_id =
+                this->programIdByKernelId( kernel_id );
+
+            if( ( program_id >= st_program_id_t{ 0 } ) &&
+                ( static_cast< st_size_t >( program_id ) <
+                  this->numAvailablePrograms() ) )
+            {
+                this->m_assign_addr_kernel_id  = kernel_id;
+                this->m_assign_addr_program_id = program_id;
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    ctx_t::status_t ctx_t::fetch_particles_addr()
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        st_kernel_id_t const kernel_id =
+            this->fetch_particles_addr_kernel_id();
+
+        if( this->hasSelectedNode() )
+        {
+            SIXTRL_ASSERT( kernel_id >= st_kernel_id_t{ 0 } );
+            SIXTRL_ASSERT( ctx_t::MIN_NUM_FETCH_PARTICLES_ADDR_ARGS >=
+                           this->kernelNumArgs( kernel_id ) );
+            SIXTRL_ASSERT( static_cast< st_size_t >( kernel_id ) <
+                           this->numAvailableKernels() );
+
+            if( this->runKernel( kernel_id, st_size_t{ 1 },
+                this->lastExecWorkGroupSize( kernel_id ) ) )
+            {
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    ctx_t::status_t ctx_t::assign_addresses(
+        ctx_t::cl_argument_t& SIXTRL_RESTRICT_REF assign_items_arg,
+        ctx_t::cl_argument_t& SIXTRL_RESTRICT_REF dest_buffer_arg,
+        ctx_t::size_type const dest_buffer_id,
+        ctx_t::cl_argument_t& SIXTRL_RESTRICT_REF src_buffer_arg,
+        ctx_t::size_type const src_buffer_id )
+    {
+        using st_size_t = ctx_t::size_type;
+
+        ctx_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+        st_kernel_id_t const kernel_id =
+            this->assign_addresses_kernel_id();
+
+        if( ( kernel_id != st::ARCH_ILLEGAL_KERNEL_ID ) &&
+            ( dest_buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( src_buffer_id  != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( assign_items_arg.context() == this ) &&
+            ( assign_items_arg.usesCObjectBuffer() ) &&
+            ( assign_items_arg.ptrCObjectBuffer() != nullptr ) &&
+            ( dest_buffer_arg.context() == this ) &&
+            ( dest_buffer_arg.usesCObjectBuffer() ) &&
+            ( dest_buffer_arg.ptrCObjectBuffer() != nullptr ) &&
+            ( src_buffer_arg.context() == this ) &&
+            ( src_buffer_arg.usesCObjectBuffer() ) &&
+            ( src_buffer_arg.ptrCObjectBuffer() != nullptr ) )
+        {
+            st_size_t const num_items = ::NS(Buffer_get_num_of_objects)(
+                assign_items_arg.ptrCObjectBuffer() );
+
+            if( num_items == st_size_t{ 0 } )
+            {
+                return st::ARCH_STATUS_SUCCESS;
+            }
+
+            st_size_t const assign_slot_size = ::NS(Buffer_get_slot_size)(
+                assign_items_arg.ptrCObjectBuffer() );
+
+            st_size_t const dest_slot_size = ::NS(Buffer_get_slot_size)(
+                dest_buffer_arg.ptrCObjectBuffer() );
+
+            st_size_t const src_slot_size = ::NS(Buffer_get_slot_size)(
+                dest_buffer_arg.ptrCObjectBuffer() );
+
+            if( ( assign_slot_size > st_size_t{ 0 } ) &&
+                ( dest_slot_size > st_size_t{ 0 } ) &&
+                ( src_slot_size > st_size_t{ 0 } ) &&
+                ( this->kernelNumArgs( kernel_id ) >= st_size_t{ 8 } ) )
+            {
+                this->assignKernelArgument(
+                    kernel_id, st_size_t{ 0 }, assign_items_arg );
+
+                this->assignKernelArgumentValue(
+                    kernel_id, size_t{ 1 }, assign_slot_size );
+
+                this->assignKernelArgument(
+                    kernel_id, size_t{ 2 }, dest_buffer_arg );
+
+                this->assignKernelArgumentValue(
+                    kernel_id, size_t{ 3 }, dest_slot_size );
+
+                this->assignKernelArgumentValue(
+                    kernel_id, size_t{ 4 }, dest_buffer_id );
+
+                this->assignKernelArgument(
+                    kernel_id, size_t{ 5 }, src_buffer_arg );
+
+                this->assignKernelArgumentValue(
+                    kernel_id, size_t{ 6 }, src_slot_size );
+
+                this->assignKernelArgumentValue(
+                    kernel_id, size_t{ 7 }, src_buffer_id );
+
+                if( this->runKernel( kernel_id, num_items ) )
+                {
+                    status = st::ARCH_STATUS_SUCCESS;
+                }
+            }
+        }
+
+        return status;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    st_size_t ctx_t::selected_particle_set() const SIXTRL_NOEXCEPT
     {
         return this->m_pset_index;
     }
 
-    _size_t ClContext::num_particles_in_selected_set() const SIXTRL_NOEXCEPT
+    st_size_t ctx_t::num_particles_in_selected_set() const SIXTRL_NOEXCEPT
     {
         return this->m_num_particles_in_pset;
     }
 
     /* --------------------------------------------------------------------- */
 
-    bool ClContext::use_optimized_tracking() const SIXTRL_NOEXCEPT
+    bool ctx_t::use_optimized_tracking() const SIXTRL_NOEXCEPT
     {
         return this->m_use_optimized_tracking;
     }
 
-    void ClContext::enable_optimized_tracking()
+    void ctx_t::enable_optimized_tracking()
     {
         if( ( !this->use_optimized_tracking() ) &&
             ( !this->hasSelectedNode() ) )
@@ -1328,7 +1643,7 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    void ClContext::disable_optimized_tracking()
+    void ctx_t::disable_optimized_tracking()
     {
         if( ( this->use_optimized_tracking() ) &&
             ( !this->hasSelectedNode() ) )
@@ -1341,195 +1656,162 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    bool ClContext::is_beam_beam_tracking_enabled() const SIXTRL_NOEXCEPT
+    /* --------------------------------------------------------------------- */
+
+    bool ctx_t::is_beam_beam_tracking_enabled() const
     {
-        return this->m_enable_beam_beam;
+        return (
+            ( ( !this->has_feature_flag( "SIXTRL_TRACK_BEAMBEAM4D" ) ) ||
+              (  this->feature_flag_str( "SIXTRL_TRACK_BEAMBEAM4D" ).compare(
+                  SIXTRL_TRACK_MAP_ENABLED_STR ) == 0 ) ) &&
+            ( ( !this->has_feature_flag( "SIXTRL_TRACK_BEAMBEAM6D" ) ) ||
+              (  this->feature_flag_str( "SIXTRL_TRACK_BEAMBEAM6D" ).compare(
+                  SIXTRL_TRACK_MAP_ENABLED_STR ) == 0 ) ) );
     }
 
-    void ClContext::enable_beam_beam_tracking()
+    void ctx_t::enable_beam_beam_tracking()
     {
-        if( ( !this->is_beam_beam_tracking_enabled() ) &&
-            ( !this->hasSelectedNode() ) )
+        if( !this->hasSelectedNode() )
         {
-            this->clear();
+            this->set_feature_flag(
+                "SIXTRL_TRACK_BEAMBEAM4D", SIXTRL_TRACK_MAP_ENABLED_STR );
+            this->set_feature_flag(
+                "SIXTRL_TRACK_BEAMBEAM6D", SIXTRL_TRACK_MAP_ENABLED_STR );
 
-            this->m_enable_beam_beam = true;
-            this->doInitDefaultPrograms();
-            this->doInitDefaultKernels();
+            this->reinit_default_programs();
         }
     }
 
-    void ClContext::disable_beam_beam_tracking()
+    void ctx_t::skip_beam_beam_tracking()
     {
-        if( (  this->is_beam_beam_tracking_enabled() ) &&
-            ( !this->hasSelectedNode() ) )
+        if( !this->hasSelectedNode() )
         {
-            this->clear();
+            this->set_feature_flag(
+                "SIXTRL_TRACK_BEAMBEAM4D", SIXTRL_TRACK_MAP_SKIP_STR );
 
-            this->m_enable_beam_beam = false;
-            this->doInitDefaultPrograms();
-            this->doInitDefaultKernels();
+            this->set_feature_flag(
+                "SIXTRL_TRACK_BEAMBEAM6D", SIXTRL_TRACK_MAP_SKIP_STR );
+
+            this->reinit_default_programs();
         }
     }
 
     /* --------------------------------------------------------------------- */
 
-    std::unique_ptr< _this_t::cl_buffer_t >
-    ClContext::create_elem_by_elem_config_arg()
+    void ctx_t::disable_beam_beam_tracking()
     {
-        if( ( this->hasSelectedNode() ) &&
-            ( this->openClContext() != nullptr ) &&
-            ( this->openClQueue() != nullptr ) )
+        if( !this->hasSelectedNode() )
         {
-            _size_t const type_size = sizeof( _this_t::elem_by_elem_config_t );
+            this->set_feature_flag(
+                "SIXTRL_TRACK_BEAMBEAM4D", SIXTRL_TRACK_MAP_DISABLED_STR );
 
-            return std::unique_ptr< _this_t::cl_buffer_t >(
-                new _this_t::cl_buffer_t( *this->openClContext(),
-                    CL_MEM_READ_WRITE, type_size , nullptr ) );
-        }
+            this->set_feature_flag(
+                "SIXTRL_TRACK_BEAMBEAM6D", SIXTRL_TRACK_MAP_DISABLED_STR );
 
-        return std::unique_ptr< _this_t::cl_buffer_t >( nullptr );
+            this->reinit_default_programs();
+        }
     }
 
-    void ClContext::delete_elem_by_elem_config_arg(
-        std::unique_ptr< SIXTRL_CXX_NAMESPACE::ClContext::cl_buffer_t >&& ptr )
-    {
-        std::unique_ptr< SIXTRL_CXX_NAMESPACE::ClContext::cl_buffer_t >
-            _local_ptr = std::move( ptr );
-
-        _local_ptr.reset( nullptr );
-    }
+    /* --------------------------------------------------------------------- */
 
-    _this_t::status_t ClContext::init_elem_by_elem_config_arg(
-        _this_t::cl_buffer_t& SIXTRL_RESTRICT_REF elem_by_elem_config_arg,
-        _this_t::elem_by_elem_config_t& SIXTRL_RESTRICT_REF elem_by_elem_config,
-        const ::NS(Buffer) *const SIXTRL_RESTRICT pbuffer,
-        _this_t::size_type const num_psets,
-        _this_t::size_type const* SIXTRL_RESTRICT pset_indices_begin,
-        const ::NS(Buffer) *const SIXTRL_RESTRICT beam_elements_buffer,
-        _this_t::size_type const until_turn_elem_by_elem,
-        _this_t::particle_index_t const start_elem_id  )
+    bool ctx_t::doSelectNode( ctx_t::size_type node_index )
     {
-        _this_t::status_t status = ::st::ARCH_STATUS_GENERAL_FAILURE;
-
-        if( ( !this->hasSelectedNode() ) ||
-            (  this->openClQueue() == nullptr ) ||
-            (  this->openClContext() == nullptr ) )
-        {
-            return status;
-        }
-
-        status = ::NS(ElemByElemConfig_init_on_particle_sets)(
-            &elem_by_elem_config, pbuffer, num_psets, pset_indices_begin,
-                beam_elements_buffer, start_elem_id,
-                    until_turn_elem_by_elem );
-
-        if( status == ::NS(ARCH_STATUS_SUCCESS) )
+        /* WARNING: Workaround for AMD Heisenbug */
+        if( ( this->use_optimized_tracking() ) &&
+            ( this->isAvailableNodeAMDPlatform( node_index ) ) )
         {
-            ::NS(ElemByElemConfig_set_output_store_address)(
-                &elem_by_elem_config, uintptr_t{ 0 } );
-
-            _size_t const type_size = sizeof( _this_t::elem_by_elem_config_t );
-
-            cl_int const cl_ret = this->openClQueue()->enqueueWriteBuffer(
-                elem_by_elem_config_arg, CL_TRUE, _size_t{ 0 }, type_size,
-                    &elem_by_elem_config );
-
-            if( cl_ret != CL_SUCCESS )
-            {
-                status = ::NS(ARCH_STATUS_GENERAL_FAILURE);
-            }
+            this->disable_optimized_tracking();
         }
 
-        return status;
+        return base_ctx_t::doSelectNode( node_index );
     }
 
-    _this_t::status_t ClContext::collect_elem_by_elem_config_arg(
-        _this_t::cl_buffer_t& SIXTRL_RESTRICT_REF elem_by_elem_config_arg,
-        _this_t::elem_by_elem_config_t& SIXTRL_RESTRICT_REF
-            elem_by_elem_config )
+    st_status_t ctx_t::doInitDefaultFeatureFlags()
     {
-        _this_t::status_t status = ::st::ARCH_STATUS_GENERAL_FAILURE;
+        st_status_t status = base_ctx_t::doInitDefaultFeatureFlags();
 
-        if( ( !this->hasSelectedNode() ) ||
-            (  this->openClQueue() == nullptr ) ||
-            (  this->openClContext() == nullptr ) )
+        if( status == st::ARCH_STATUS_SUCCESS )
         {
-            return status;
+            status = this->doInitDefaultFeatureFlagsPrivImpl();
         }
 
-        _size_t const type_size = sizeof( _this_t::elem_by_elem_config_t );
-        cl_int const cl_ret = this->openClQueue()->enqueueReadBuffer(
-            elem_by_elem_config_arg, CL_TRUE, _size_t{ 0 }, type_size,
-                &elem_by_elem_config );
-
-        if( cl_ret == CL_SUCCESS ) status = st::ARCH_STATUS_SUCCESS;
-
         return status;
     }
 
-    _this_t::status_t ClContext::push_elem_by_elem_config_arg(
-        _this_t::cl_buffer_t& SIXTRL_RESTRICT_REF elem_by_elem_config_arg,
-        _this_t::elem_by_elem_config_t const& SIXTRL_RESTRICT_REF
-            elem_by_elem_config )
+    st_status_t ctx_t::doInitDefaultFeatureFlagsPrivImpl()
     {
-        _this_t::status_t status = ::st::ARCH_STATUS_GENERAL_FAILURE;
+        #if defined( SIXTRL_TRACK_BEAMBEAM4D )
+        this->set_feature_flag( "SIXTRL_TRACK_BEAMBEAM4D",
+            SIXTRL_TRACK_BEAMBEAM4D_STR );
+        #endif /* SIXTRL_TRACK_BEAMBEAM4D */
 
-        if( ( !this->hasSelectedNode() ) ||
-            (  this->openClQueue() == nullptr ) ||
-            (  this->openClContext() == nullptr ) )
-        {
-            return status;
-        }
+        #if defined( SIXTRL_TRACK_BEAMBEAM6D )
+        this->set_feature_flag( "SIXTRL_TRACK_BEAMBEAM6D",
+            SIXTRL_TRACK_BEAMBEAM6D_STR );
+        #endif /* SIXTRL_TRACK_BEAMBEAM6D */
 
-        _size_t const type_size = sizeof( _this_t::elem_by_elem_config_t );
-        cl_int const cl_ret = this->openClQueue()->enqueueWriteBuffer(
-            elem_by_elem_config_arg, CL_TRUE, _size_t{ 0 }, type_size,
-                &elem_by_elem_config );
+        #if defined( SIXTRL_TRACK_SC_COASTING )
+        this->set_feature_flag( "SIXTRL_TRACK_SC_COASTING",
+            SIXTRL_TRACK_SC_COASTING_STR );
+        #endif /* SIXTRL_TRACK_SC_COASTING */
 
-        if( cl_ret == CL_SUCCESS ) status = st::ARCH_STATUS_SUCCESS;
+        #if defined( SIXTRL_TRACK_SC_BUNCHED )
+        this->set_feature_flag( "SIXTRL_TRACK_SC_BUNCHED",
+            SIXTRL_TRACK_SC_BUNCHED_STR );
+        #endif /* SIXTRL_TRACK_SC_BUNCHED */
 
-        return status;
-    }
+        #if defined( SIXTRL_TRACK_TRICUB )
+        this->set_feature_flag( "SIXTRL_TRACK_TRICUB",
+            SIXTRL_TRACK_TRICUB_STR );
+        #endif /* SIXTRL_TRACK_TRICUB */
 
-    /* --------------------------------------------------------------------- */
+        #if defined( SIXTRL_APERTURE_CHECK_AT_DRIFT )
+        this->set_feature_flag( "SIXTRL_APERTURE_CHECK_AT_DRIFT",
+            SIXTRL_APERTURE_CHECK_AT_DRIFT_STR );
+        #endif /* defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) */
 
-    bool ClContext::doSelectNode( _this_t::size_type node_index )
-    {
-        /* WARNING: Workaround for AMD Heisenbug */
-        if( ( this->use_optimized_tracking() ) &&
-            ( this->isAvailableNodeAMDPlatform( node_index ) ) )
-        {
-            this->disable_optimized_tracking();
-        }
+        #if defined( SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH )
+        this->set_feature_flag( "SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH",
+            SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH_STR );
+        #endif /* SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH */
 
-        return _base_t::doSelectNode( node_index );
+        #if defined( SIXTRL_APERTURE_X_LIMIT )
+        this->set_feature_flag( "SIXTRL_APERTURE_X_LIMIT",
+            SIXTRL_APERTURE_X_LIMIT_STR );
+        #endif /* SIXTRL_APERTURE_X_LIMIT */
+
+        #if defined( SIXTRL_APERTURE_Y_LIMIT )
+        this->set_feature_flag( "SIXTRL_APERTURE_Y_LIMIT",
+            SIXTRL_APERTURE_Y_LIMIT_STR );
+        #endif /* SIXTRL_APERTURE_Y_LIMIT */
+
+        return st::ARCH_STATUS_SUCCESS;
     }
 
-    bool ClContext::doInitDefaultPrograms()
+    bool ctx_t::doInitDefaultPrograms()
     {
         return ( ( ClContextBase::doInitDefaultPrograms() ) &&
                  ( this->doInitDefaultProgramsPrivImpl() ) );
     }
 
-    bool ClContext::doInitDefaultKernels()
+    bool ctx_t::doInitDefaultKernels()
     {
         return ( ( ClContextBase::doInitDefaultKernels() ) &&
                  ( this->doInitDefaultKernelsPrivImpl() ) );
     }
 
-    _status_t ClContext::doAssignStatusFlagsArgPrivImpl(
-        _this_t::cl_buffer_t& SIXTRL_RESTRICT_REF status_flags_arg )
+    st_status_t ctx_t::doAssignStatusFlagsArgPrivImpl(
+        ctx_t::cl_buffer_t& SIXTRL_RESTRICT_REF status_flags_arg )
     {
-        using size_t = _size_t;
-        using kernel_id_t = _kernel_id_t;
+        using size_t = st_size_t;
+        using st_kernel_id_t = st_kernel_id_t;
 
-        _status_t status = st::ARCH_STATUS_SUCCESS;
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
         if( !this->debugMode() ) return status;
 
         constexpr size_t NUM_KERNELS = size_t{ 6 };
 
-        kernel_id_t kernel_ids[ NUM_KERNELS ];
+        st_kernel_id_t kernel_ids[ NUM_KERNELS ];
         std::fill( &kernel_ids[ 0 ], &kernel_ids[ NUM_KERNELS ],
                    st::ARCH_ILLEGAL_KERNEL_ID );
 
@@ -1542,27 +1824,27 @@ namespace SIXTRL_CXX_NAMESPACE
 
         size_t const min_num_kernel_args[ NUM_KERNELS ] =
         {
-            _this_t::MIN_NUM_TRACK_UNTIL_ARGS,
-            _this_t::MIN_NUM_TRACK_LINE_ARGS,
-            _this_t::MIN_NUM_TRACK_ELEM_ARGS,
-            _this_t::MIN_NUM_ASSIGN_BE_MON_ARGS,
-            _this_t::MIN_NUM_CLEAR_BE_MON_ARGS,
-            _this_t::MIN_NUM_ASSIGN_ELEM_ARGS
+            ctx_t::MIN_NUM_TRACK_UNTIL_ARGS,
+            ctx_t::MIN_NUM_TRACK_LINE_ARGS,
+            ctx_t::MIN_NUM_TRACK_ELEM_ARGS,
+            ctx_t::MIN_NUM_ASSIGN_BE_MON_ARGS,
+            ctx_t::MIN_NUM_CLEAR_BE_MON_ARGS,
+            ctx_t::MIN_NUM_ASSIGN_ELEM_ARGS
         };
 
         size_t const status_flags_arg_idx[ NUM_KERNELS ] =
         {
             size_t{ 5 }, // track_until
             size_t{ 7 }, // track_line
-            size_t{ 6 }, // track_elem_elem
+            size_t{ 7 }, // track_elem_elem
             size_t{ 5 }, // assign_be_mon
             size_t{ 2 }, // clear_be_mon
-            size_t{ 4 }  // assign_elem_by_elem
+            size_t{ 5 }  // assign_elem_by_elem
         };
 
         for( size_t ii = size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
         {
-            kernel_id_t const kernel_id = kernel_ids[ ii ];
+            st_kernel_id_t const kernel_id = kernel_ids[ ii ];
             size_t const min_num_args = min_num_kernel_args[ ii ];
 
             if( kernel_id == st::ARCH_ILLEGAL_KERNEL_ID ) continue;
@@ -1584,11 +1866,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::doAssignStatusFlagsArg(
-        _this_t::cl_buffer_t& SIXTRL_RESTRICT_REF status_flags_arg )
+    st_status_t ctx_t::doAssignStatusFlagsArg(
+        ctx_t::cl_buffer_t& SIXTRL_RESTRICT_REF status_flags_arg )
     {
-        _status_t status =
-            _base_t::doAssignStatusFlagsArg( status_flags_arg );
+        st_status_t status =
+            base_ctx_t::doAssignStatusFlagsArg( status_flags_arg );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
@@ -1598,15 +1880,15 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::doAssignSlotSizeArgPrivImpl( _size_t const slot_size )
+    st_status_t ctx_t::doAssignSlotSizeArgPrivImpl( st_size_t const slot_size )
     {
-        using size_t = _size_t;
-        using kernel_id_t = _kernel_id_t;
+        using size_t = st_size_t;
+        using st_kernel_id_t = st_kernel_id_t;
 
-        _status_t status = st::ARCH_STATUS_SUCCESS;
-        constexpr size_t NUM_KERNELS = size_t{ 6 };
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+        constexpr size_t NUM_KERNELS = size_t{ 7 };
 
-        kernel_id_t kernel_ids[ NUM_KERNELS ];
+        st_kernel_id_t kernel_ids[ NUM_KERNELS ];
         std::fill( &kernel_ids[ 0 ], &kernel_ids[ NUM_KERNELS ],
                    st::ARCH_ILLEGAL_KERNEL_ID );
 
@@ -1616,32 +1898,35 @@ namespace SIXTRL_CXX_NAMESPACE
         kernel_ids[ 3 ] = this->assign_beam_monitor_output_kernel_id();
         kernel_ids[ 4 ] = this->clear_beam_monitor_output_kernel_id();
         kernel_ids[ 5 ] = this->assign_elem_by_elem_output_kernel_id();
+        kernel_ids[ 6 ] = this->fetch_particles_addr_kernel_id();
 
         size_t const min_num_kernel_args[ NUM_KERNELS ] =
         {
-            _this_t::MIN_NUM_TRACK_UNTIL_ARGS,
-            _this_t::MIN_NUM_TRACK_LINE_ARGS,
-            _this_t::MIN_NUM_TRACK_ELEM_ARGS,
-            _this_t::MIN_NUM_ASSIGN_BE_MON_ARGS,
-            _this_t::MIN_NUM_CLEAR_BE_MON_ARGS,
-            _this_t::MIN_NUM_ASSIGN_ELEM_ARGS
+            ctx_t::MIN_NUM_TRACK_UNTIL_ARGS,
+            ctx_t::MIN_NUM_TRACK_LINE_ARGS,
+            ctx_t::MIN_NUM_TRACK_ELEM_ARGS,
+            ctx_t::MIN_NUM_ASSIGN_BE_MON_ARGS,
+            ctx_t::MIN_NUM_CLEAR_BE_MON_ARGS,
+            ctx_t::MIN_NUM_ASSIGN_ELEM_ARGS,
+            ctx_t::MIN_NUM_FETCH_PARTICLES_ADDR_ARGS
         };
 
         size_t const slot_size_arg_idx[ NUM_KERNELS ] =
         {
             size_t{ 4 }, // track_until
             size_t{ 6 }, // track_line
-            size_t{ 5 }, // track_elem_elem
+            size_t{ 6 }, // track_elem_elem
             size_t{ 4 }, // assign_be_mon
             size_t{ 1 }, // clear_be_mon
-            size_t{ 3 }  // assign_elem_by_elem
+            size_t{ 4 }, // assign_elem_by_elem
+            size_t{ 2 }  // fetch_particles_addr
         };
 
         uint64_t const slot_size_arg = static_cast< uint64_t >( slot_size );
 
         for( size_t ii = size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
         {
-            kernel_id_t const kernel_id = kernel_ids[ ii ];
+            st_kernel_id_t const kernel_id = kernel_ids[ ii ];
             size_t const min_num_args = min_num_kernel_args[ ii ];
 
             if( kernel_id == st::ARCH_ILLEGAL_KERNEL_ID ) continue;
@@ -1662,9 +1947,67 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    _status_t ClContext::doAssignSlotSizeArg( _size_t const slot_size )
+    st_status_t ctx_t::doAssignElemByElemConfigIndexArgPrivImpl(
+        st_size_t const elem_by_elem_config_index )
     {
-        _status_t status = _base_t::doAssignSlotSizeArg( slot_size );
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+        constexpr st_size_t NUM_KERNELS = st_size_t{ 2 };
+
+        st_kernel_id_t kernel_ids[ NUM_KERNELS ] =
+        {
+            st::ARCH_ILLEGAL_KERNEL_ID, st::ARCH_ILLEGAL_KERNEL_ID
+        };
+
+        kernel_ids[ 0 ] = this->track_elem_by_elem_kernel_id();
+        kernel_ids[ 1 ] = this->assign_elem_by_elem_output_kernel_id();
+
+        st_size_t const min_num_kernel_args[ NUM_KERNELS ] =
+        {
+            ctx_t::MIN_NUM_TRACK_ELEM_ARGS,
+            ctx_t::MIN_NUM_ASSIGN_ELEM_ARGS
+        };
+
+        st_size_t const elem_by_elem_config_index_arg_idx[ NUM_KERNELS ] =
+        {
+            st_size_t{ 4 }, // track_elem_by_elem_kernel
+            st_size_t{ 1 }, // assign_elem_by_elem_output_kernel
+        };
+
+        uint64_t const conf_idx_arg =
+            static_cast< uint64_t >( elem_by_elem_config_index );
+
+        for( st_size_t ii = st_size_t{ 0 } ; ii < NUM_KERNELS ; ++ii )
+        {
+            st_kernel_id_t const kernel_id = kernel_ids[ ii ];
+            st_size_t const min_num_args = min_num_kernel_args[ ii ];
+
+            if( kernel_id == st::ARCH_ILLEGAL_KERNEL_ID ) continue;
+            if( min_num_args == st_size_t{ 0 } ) continue;
+
+            st_size_t const num_args = this->kernelNumArgs( kernel_id );
+            st_size_t const arg_idx  = elem_by_elem_config_index_arg_idx[ ii ];
+
+            if( ( num_args <= arg_idx ) || ( num_args < min_num_args ) )
+            {
+                status |= st::ARCH_STATUS_GENERAL_FAILURE;
+                continue;
+            }
+
+            this->assignKernelArgumentValue(
+                kernel_id, arg_idx, conf_idx_arg );
+        }
+
+        if( status == st::ARCH_STATUS_SUCCESS )
+        {
+            this->m_elem_by_elem_config_index = elem_by_elem_config_index;
+        }
+
+        return status;
+    }
+
+    st_status_t ctx_t::doAssignSlotSizeArg( st_size_t const slot_size )
+    {
+        st_status_t status = base_ctx_t::doAssignSlotSizeArg( slot_size );
 
         if( status == st::ARCH_STATUS_SUCCESS )
         {
@@ -1674,17 +2017,34 @@ namespace SIXTRL_CXX_NAMESPACE
         return status;
     }
 
-    bool ClContext::doInitDefaultProgramsPrivImpl()
+    st_status_t ctx_t::doAssignElemByElemConfigIndexArg(
+        st_size_t const elem_by_elem_config_index )
+    {
+        return this->doAssignElemByElemConfigIndexArgPrivImpl(
+            elem_by_elem_config_index );
+    }
+
+    bool ctx_t::doInitDefaultProgramsPrivImpl()
     {
         bool success = false;
 
-        std::string path_to_kernel_dir( NS(PATH_TO_BASE_DIR) );
-        path_to_kernel_dir += "sixtracklib/opencl/kernels/";
+        std::string path_to_particles_track_prog =
+            this->default_path_to_kernel_dir_str();
 
-        std::string path_to_particles_track_prog          = path_to_kernel_dir;
-        std::string path_to_particles_track_opt_prog      = path_to_kernel_dir;
-        std::string path_to_assign_be_mon_out_buffer_prog = path_to_kernel_dir;
-        std::string path_to_assign_elem_out_buffer_prog   = path_to_kernel_dir;
+        std::string path_to_particles_track_opt_prog =
+            this->default_path_to_kernel_dir_str();
+
+        std::string path_to_assign_be_mon_out_buffer_prog =
+            this->default_path_to_kernel_dir_str();
+
+        std::string path_to_assign_elem_out_buffer_prog =
+            this->default_path_to_kernel_dir_str();
+
+        std::string path_to_fetch_particle_addr_prog =
+            this->default_path_to_kernel_dir_str();
+
+        std::string path_to_assign_addr_prog =
+            this->default_path_to_kernel_dir_str();
 
         if( !this->debugMode() )
         {
@@ -1713,60 +2073,99 @@ namespace SIXTRL_CXX_NAMESPACE
                 "elem_by_elem_assign_out_buffer_debug.cl";
         }
 
-        std::string track_compile_options = "-D_GPUCODE=1";
-        track_compile_options += " -DSIXTRL_BUFFER_ARGPTR_DEC=__private";
-        track_compile_options += " -DSIXTRL_BUFFER_DATAPTR_DEC=__global";
-        track_compile_options += " -DSIXTRL_PARTICLE_ARGPTR_DEC=__global";
-        track_compile_options += " -DSIXTRL_PARTICLE_DATAPTR_DEC=__global";
+        path_to_fetch_particle_addr_prog += "fetch_particles_addr.cl";
+        path_to_assign_addr_prog += "assign_address_item.cl";
+
+        std::ostringstream compile_options;
 
-        if( !this->is_beam_beam_tracking_enabled() )
+        if( ( this->defaultCompileOptions() != nullptr ) &&
+            ( std::strlen( this->defaultCompileOptions() ) > 0u ) )
         {
-            track_compile_options += " -DSIXTRL_DISABLE_BEAM_BEAM=1";
+            compile_options << this->defaultCompileOptions() << " ";
         }
 
-        track_compile_options += " -I";
-        track_compile_options += NS(PATH_TO_SIXTRL_INCLUDE_DIR);
+        compile_options << this->feature_flag_repr( "_GPUCODE" ) << " "
+            << this->feature_flag_repr( "SIXTRL_BUFFER_ARGPTR_DEC" ) << " "
+            << this->feature_flag_repr( "SIXTRL_BUFFER_DATAPTR_DEC" ) << " "
+            << "-I" << NS(PATH_TO_SIXTRL_INCLUDE_DIR);
+
+        std::string const common_compile_options( compile_options.str() );
 
-        std::string track_optimized_compile_options = "-D_GPUCODE=1";
-        track_optimized_compile_options += " -DSIXTRL_BUFFER_ARGPTR_DEC=__private";
-        track_optimized_compile_options += " -DSIXTRL_BUFFER_DATAPTR_DEC=__global";
-        track_optimized_compile_options += " -DSIXTRL_PARTICLE_ARGPTR_DEC=__private";
-        track_optimized_compile_options += " -DSIXTRL_PARTICLE_DATAPTR_DEC=__private";
+        compile_options.str( "" );
+        std::vector< std::string > const OPTIONAL_FEATURES =
+        {
+            "SIXTRL_TRACK_BEAMBEAM4D", "SIXTRL_TRACK_BEAMBEAM6D",
+            "SIXTRL_TRACK_SPACECHARGE", "SIXTRL_TRACK_TRICUB",
+            "SIXTRL_APERTURE_CHECK_AT_DRIFT",
+            "SIXTRL_APERTURE_CHECK_MIN_DRIFT_LENGTH",
+            "SIXTRL_APERTURE_X_LIMIT", "SIXTRL_APERTURE_Y_LIMIT"
+        };
 
-        if( !this->is_beam_beam_tracking_enabled() )
+        for( auto const& fkey : OPTIONAL_FEATURES )
         {
-            track_optimized_compile_options += " -DSIXTRL_DISABLE_BEAM_BEAM=1";
+            if( this->has_feature_flag( fkey ) )
+            {
+                compile_options << this->feature_flag_repr( fkey ) << " ";
+            }
         }
 
-        track_optimized_compile_options += " -I";
-        track_optimized_compile_options += NS(PATH_TO_SIXTRL_INCLUDE_DIR);
+        std::string const feature_compile_options( compile_options.str() );
+        compile_options.str( "" );
+
+        compile_options << common_compile_options << " "
+                        << feature_compile_options << " "
+                        << "-DSIXTRL_PARTICLE_ARGPTR_DEC=__private "
+                        << "-DSIXTRL_PARTICLE_DATAPTR_DEC=__private ";
+
+        std::string const track_optimized_compile_options( compile_options.str() );
+        compile_options.str( "" );
+
+        compile_options << common_compile_options  << " "
+                        << feature_compile_options << " "
+                        << "-DSIXTRL_PARTICLE_ARGPTR_DEC=__global "
+                        << "-DSIXTRL_PARTICLE_DATAPTR_DEC=__global ";
+
+        std::string const track_compile_options( compile_options.str() );
+        compile_options.str( "" );
+
+        compile_options << common_compile_options << " "
+            << "-DSIXTRL_PARTICLE_ARGPTR_DEC=__global "
+            << "-DSIXTRL_PARTICLE_DATAPTR_DEC=__global ";
+
+        std::string const fetch_paddrs_compile_options( compile_options.str() );
+        std::string const assign_out_buffer_compile_options(
+            fetch_paddrs_compile_options );
+
+
+        st_program_id_t const track_program_id = this->addProgramFile(
+            path_to_particles_track_prog, track_compile_options,
+            ctx_t::PROGRAM_PATH_ABSOLUTE );
 
-        std::string assign_out_buffer_compile_options = " -D_GPUCODE=1";
-        assign_out_buffer_compile_options += " -DSIXTRL_BUFFER_ARGPTR_DEC=__private";
-        assign_out_buffer_compile_options += " -DSIXTRL_BUFFER_DATAPTR_DEC=__global";
-        assign_out_buffer_compile_options += " -DSIXTRL_PARTICLE_ARGPTR_DEC=__global";
-        assign_out_buffer_compile_options += " -DSIXTRL_PARTICLE_DATAPTR_DEC=__global";
-        assign_out_buffer_compile_options += " -I";
-        assign_out_buffer_compile_options += NS(PATH_TO_SIXTRL_INCLUDE_DIR);
+        st_program_id_t const track_optimized_program_id = this->addProgramFile(
+            path_to_particles_track_opt_prog, track_optimized_compile_options,
+            ctx_t::PROGRAM_PATH_ABSOLUTE );
 
-        program_id_t const track_program_id = this->addProgramFile(
-            path_to_particles_track_prog, track_compile_options );
+        st_program_id_t const assign_be_mon_out_buffer_program_id =
+        this->addProgramFile( path_to_assign_be_mon_out_buffer_prog,
+            assign_out_buffer_compile_options, ctx_t::PROGRAM_PATH_ABSOLUTE );
 
-        program_id_t const track_optimized_program_id = this->addProgramFile(
-            path_to_particles_track_opt_prog, track_optimized_compile_options );
+        st_program_id_t const assign_elem_by_elem_out_buffer_program_id =
+        this->addProgramFile( path_to_assign_elem_out_buffer_prog,
+            assign_out_buffer_compile_options, ctx_t::PROGRAM_PATH_ABSOLUTE );
 
-        program_id_t const assign_be_mon_out_buffer_program_id =
-            this->addProgramFile( path_to_assign_be_mon_out_buffer_prog,
-                                  assign_out_buffer_compile_options );
+        st_program_id_t const fetch_particles_addr_program_id =
+        this->addProgramFile( path_to_fetch_particle_addr_prog,
+            fetch_paddrs_compile_options, ctx_t::PROGRAM_PATH_ABSOLUTE );
 
-        program_id_t const assign_elem_by_elem_out_buffer_program_id =
-            this->addProgramFile( path_to_assign_elem_out_buffer_prog,
-                                  assign_out_buffer_compile_options );
+        st_program_id_t const assign_addr_program_id =
+            this->addProgramFile( path_to_assign_addr_prog,
+            assign_out_buffer_compile_options, ctx_t::PROGRAM_PATH_ABSOLUTE );
 
-        if( ( track_program_id            >= program_id_t{ 0 } ) &&
-            ( track_optimized_program_id  >= program_id_t{ 0 } ) &&
-            ( assign_be_mon_out_buffer_program_id >= program_id_t{ 0 } ) &&
-            ( assign_elem_by_elem_out_buffer_program_id >= program_id_t{ 0 } ) )
+        if( ( track_program_id != st::ARCH_ILLEGAL_PROGRAM_ID ) &&
+            ( track_optimized_program_id  != st::ARCH_ILLEGAL_PROGRAM_ID ) &&
+            ( assign_be_mon_out_buffer_program_id != st::ARCH_ILLEGAL_PROGRAM_ID ) &&
+            ( assign_elem_by_elem_out_buffer_program_id != st::ARCH_ILLEGAL_PROGRAM_ID ) &&
+            ( assign_addr_program_id != st::ARCH_ILLEGAL_PROGRAM_ID ) )
         {
             if( !this->use_optimized_tracking() )
             {
@@ -1790,22 +2189,26 @@ namespace SIXTRL_CXX_NAMESPACE
             this->m_assign_elem_by_elem_out_buffer_program_id =
                 assign_elem_by_elem_out_buffer_program_id;
 
+            this->m_fetch_particles_addr_program_id =
+                fetch_particles_addr_program_id;
+
+            this->m_assign_addr_program_id = assign_addr_program_id;
             success = true;
         }
 
         return success;
     }
 
-    bool ClContext::doInitDefaultKernelsPrivImpl()
+    bool ctx_t::doInitDefaultKernelsPrivImpl()
     {
         bool success = false;
 
         if( this->hasSelectedNode() )
         {
-            program_id_t const max_program_id = static_cast< program_id_t >(
+            st_program_id_t const max_program_id = static_cast< st_program_id_t >(
                 this->numAvailablePrograms() );
 
-            if( ( this->m_track_until_turn_program_id >= program_id_t{ 0 } ) &&
+            if( ( this->m_track_until_turn_program_id >= st_program_id_t{ 0 } ) &&
                 ( this->m_track_until_turn_program_id <  max_program_id ) )
             {
                 std::string kernel_name( SIXTRL_C99_NAMESPACE_PREFIX_STR );
@@ -1823,10 +2226,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 kernel_name += "_opencl";
 
-                kernel_id_t const kernel_id = this->enableKernel(
+                st_kernel_id_t const kernel_id = this->enableKernel(
                     kernel_name.c_str(), this->m_track_until_turn_program_id );
 
-                if( kernel_id >= kernel_id_t{ 0 } )
+                if( kernel_id >= st_kernel_id_t{ 0 } )
                 {
                     success = ( this->set_track_until_kernel_id( kernel_id ) ==
                         st::ARCH_STATUS_SUCCESS );
@@ -1834,7 +2237,7 @@ namespace SIXTRL_CXX_NAMESPACE
             }
 
             if( ( success ) &&
-                ( this->m_track_elem_by_elem_program_id >= program_id_t{ 0 } ) &&
+                ( this->m_track_elem_by_elem_program_id >= st_program_id_t{ 0 } ) &&
                 ( this->m_track_elem_by_elem_program_id <  max_program_id ) )
             {
                 std::string kernel_name( SIXTRL_C99_NAMESPACE_PREFIX_STR );
@@ -1852,10 +2255,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 kernel_name += "_opencl";
 
-                kernel_id_t const kernel_id = this->enableKernel(
+                st_kernel_id_t const kernel_id = this->enableKernel(
                     kernel_name.c_str(), this->m_track_elem_by_elem_program_id );
 
-                if( kernel_id >= kernel_id_t{ 0 } )
+                if( kernel_id >= st_kernel_id_t{ 0 } )
                 {
                     success = ( this->set_track_elem_by_elem_kernel_id(
                         kernel_id ) == st::ARCH_STATUS_SUCCESS );
@@ -1863,7 +2266,7 @@ namespace SIXTRL_CXX_NAMESPACE
             }
 
             if( ( success ) &&
-                ( this->m_track_line_program_id >= program_id_t{ 0 } ) &&
+                ( this->m_track_line_program_id >= st_program_id_t{ 0 } ) &&
                 ( this->m_track_line_program_id <  max_program_id ) )
             {
                 std::string kernel_name( SIXTRL_C99_NAMESPACE_PREFIX_STR );
@@ -1881,10 +2284,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 kernel_name += "_opencl";
 
-                kernel_id_t const kernel_id = this->enableKernel(
+                st_kernel_id_t const kernel_id = this->enableKernel(
                     kernel_name.c_str(), this->m_track_line_program_id );
 
-                if( kernel_id >= kernel_id_t{ 0 } )
+                if( kernel_id >= st_kernel_id_t{ 0 } )
                 {
                     success = ( this->set_track_line_kernel_id( kernel_id ) ==
                         st::ARCH_STATUS_SUCCESS );
@@ -1892,7 +2295,7 @@ namespace SIXTRL_CXX_NAMESPACE
             }
 
             if( ( success ) &&
-                ( this->m_assign_be_mon_out_buffer_program_id >= program_id_t{ 0 } ) &&
+                ( this->m_assign_be_mon_out_buffer_program_id >= st_program_id_t{ 0 } ) &&
                 ( this->m_assign_be_mon_out_buffer_program_id <  max_program_id ) )
             {
                 std::string kernel_name( SIXTRL_C99_NAMESPACE_PREFIX_STR );
@@ -1905,10 +2308,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 kernel_name += "_opencl";
 
-                kernel_id_t const kernel_id = this->enableKernel(
+                st_kernel_id_t const kernel_id = this->enableKernel(
                     kernel_name.c_str(), this->m_assign_be_mon_out_buffer_program_id );
 
-                if( kernel_id >= kernel_id_t{ 0 } )
+                if( kernel_id >= st_kernel_id_t{ 0 } )
                 {
                     success = ( this->set_assign_beam_monitor_output_kernel_id(
                         kernel_id ) == st::ARCH_STATUS_SUCCESS );
@@ -1916,7 +2319,7 @@ namespace SIXTRL_CXX_NAMESPACE
             }
 
             if( ( success ) &&
-                ( this->m_clear_be_mon_program_id >= program_id_t{ 0 } ) &&
+                ( this->m_clear_be_mon_program_id >= st_program_id_t{ 0 } ) &&
                 ( this->m_clear_be_mon_program_id <  max_program_id ) )
             {
                 std::string kernel_name( SIXTRL_C99_NAMESPACE_PREFIX_STR );
@@ -1929,10 +2332,10 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 kernel_name += "_opencl";
 
-                kernel_id_t const kernel_id = this->enableKernel(
+                st_kernel_id_t const kernel_id = this->enableKernel(
                     kernel_name.c_str(), this->m_clear_be_mon_program_id );
 
-                if( kernel_id >= kernel_id_t{ 0 } )
+                if( kernel_id >= st_kernel_id_t{ 0 } )
                 {
                     success = ( this->set_clear_beam_monitor_output_kernel_id(
                         kernel_id ) == st::ARCH_STATUS_SUCCESS );
@@ -1941,7 +2344,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             if( ( success ) &&
                 ( this->m_assign_elem_by_elem_out_buffer_program_id >=
-                    program_id_t{ 0 } ) &&
+                    st_program_id_t{ 0 } ) &&
                 ( this->m_assign_elem_by_elem_out_buffer_program_id <
                     max_program_id ) )
             {
@@ -1955,16 +2358,52 @@ namespace SIXTRL_CXX_NAMESPACE
 
                 kernel_name += "_opencl";
 
-                kernel_id_t const kernel_id = this->enableKernel(
+                st_kernel_id_t const kernel_id = this->enableKernel(
                     kernel_name.c_str(),
                     this->m_assign_elem_by_elem_out_buffer_program_id );
 
-                if( kernel_id >= kernel_id_t{ 0 } )
+                if( kernel_id >= st_kernel_id_t{ 0 } )
                 {
                     success = ( this->set_assign_elem_by_elem_output_kernel_id(
                         kernel_id ) == st::ARCH_STATUS_SUCCESS );
                 }
             }
+
+            if( ( success ) &&
+                ( this->m_fetch_particles_addr_program_id >= st_program_id_t{ 0 } ) &&
+                ( this->m_fetch_particles_addr_program_id < max_program_id ) )
+            {
+                std::string kernel_name( SIXTRL_C99_NAMESPACE_PREFIX_STR );
+                kernel_name += "Particles_buffer_store_all_addresses";
+                kernel_name += "_opencl";
+
+                st_kernel_id_t const kernel_id = this->enableKernel(
+                    kernel_name.c_str(), this->m_fetch_particles_addr_program_id );
+
+                if( kernel_id >= st_kernel_id_t{ 0 } )
+                {
+                    success = ( this->set_fetch_particles_addr_kernel_id(
+                        kernel_id ) == st::ARCH_STATUS_SUCCESS );
+                }
+            }
+
+            if( ( success ) &&
+                ( this->m_assign_addr_program_id != st::ARCH_ILLEGAL_PROGRAM_ID ) &&
+                ( this->m_assign_addr_program_id <  this->numAvailablePrograms() ) )
+            {
+                std::string kernel_name( SIXTRL_C99_NAMESPACE_PREFIX_STR );
+                kernel_name += "AssignAddressItem_process_managed_buffer";
+                kernel_name += "_opencl";
+
+                st_kernel_id_t const kernel_id = this->enableKernel(
+                    kernel_name.c_str(), this->m_assign_addr_program_id );
+
+                if( kernel_id != st::ARCH_ILLEGAL_KERNEL_ID )
+                {
+                    success = ( this->set_assign_addresses_kernel_id(
+                        kernel_id ) == st::ARCH_STATUS_SUCCESS );
+                }
+            }
         }
 
         return success;
@@ -1977,12 +2416,12 @@ namespace SIXTRL_CXX_NAMESPACE
 
 ::NS(ClContext)* NS(ClContext_create)()
 {
-    return new st::ClContext;
+    return new SIXTRL_CXX_NAMESPACE::ClContext;
 }
 
 ::NS(ClContext)* NS(ClContext_new)( const char* node_id_str )
 {
-    return new st::ClContext( node_id_str, nullptr );
+    return new SIXTRL_CXX_NAMESPACE::ClContext( node_id_str, nullptr );
 }
 
 void NS(ClContext_delete)( ::NS(ClContext)* SIXTRL_RESTRICT ctx )
@@ -2003,7 +2442,7 @@ ::NS(ctrl_status_t) NS(ClContext_assign_particles_arg)(
 {
     return ( ( ctx != nullptr ) && ( particles_arg != nullptr ) )
         ? ctx->assign_particles_arg( *particles_arg )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(arch_status_t) NS(ClContext_assign_particle_set_arg)(
@@ -2014,7 +2453,7 @@ ::NS(arch_status_t) NS(ClContext_assign_particle_set_arg)(
     return ( ctx != nullptr )
         ? ctx->assign_particle_set_arg(
             particle_set_index, num_particles_in_selected_set )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(ctrl_status_t) NS(ClContext_assign_beam_elements_arg)(
@@ -2023,7 +2462,7 @@ ::NS(ctrl_status_t) NS(ClContext_assign_beam_elements_arg)(
 {
     return ( ( ctx != nullptr ) && ( beam_elem_arg != nullptr ) )
         ? ctx->assign_beam_elements_arg( *beam_elem_arg )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(ctrl_status_t) NS(ClContext_assign_output_buffer_arg)(
@@ -2032,17 +2471,27 @@ ::NS(ctrl_status_t) NS(ClContext_assign_output_buffer_arg)(
 {
     return ( ( ctx != nullptr ) && ( out_buffer_arg != nullptr ) )
         ? ctx->assign_output_buffer_arg( *out_buffer_arg )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
-::NS(ctrl_status_t) NS(ClContext_assign_elem_by_elem_config_arg)(
-    ::NS(ClContext)* SIXTRL_RESTRICT ctx, cl_mem elem_by_elem_config_arg  )
+::NS(ctrl_status_t) NS(ClContext_assign_elem_by_elem_config_buffer_arg)(
+    ::NS(ClContext)* SIXTRL_RESTRICT ctx,
+    ::NS(ClArgument)* SIXTRL_RESTRICT elem_by_elem_config_buffer_arg )
 {
-    cl::Buffer temp_buffer( elem_by_elem_config_arg );
+    return ( ( ctx != nullptr ) &&
+             ( elem_by_elem_config_buffer_arg != nullptr ) )
+        ? ctx->assign_elem_by_elem_config_buffer_arg(
+            *elem_by_elem_config_buffer_arg )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
 
+::NS(ctrl_status_t) NS(ClContext_assign_elem_by_elem_config_index_arg)(
+    ::NS(ClContext)* SIXTRL_RESTRICT ctx,
+    ::NS(buffer_size_t) const elem_by_elem_config_index )
+{
     return ( ctx != nullptr )
-        ? ctx->assign_elem_by_elem_config_arg( temp_buffer )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        ? ctx->assign_elem_by_elem_config_index_arg( elem_by_elem_config_index )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(ctrl_status_t) NS(ClContext_assign_slot_size_arg)(
@@ -2050,7 +2499,7 @@ ::NS(ctrl_status_t) NS(ClContext_assign_slot_size_arg)(
 {
     return ( ctx != nullptr )
         ? ctx->assign_slot_size_arg( slot_size )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(ctrl_status_t) NS(ClContext_assign_status_flags_arg)(
@@ -2060,7 +2509,7 @@ ::NS(ctrl_status_t) NS(ClContext_assign_status_flags_arg)(
 
     return ( ctx != nullptr )
         ? ctx->assign_status_flags_arg( temp_buffer )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 /* ========================================================================= */
@@ -2083,7 +2532,7 @@ ::NS(arch_status_t) NS(ClContext_set_track_until_kernel_id)(
     ::NS(arch_kernel_id_t) const kernel_id )
 {
     return ( ctx != nullptr ) ? ctx->set_track_until_kernel_id( kernel_id )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(track_status_t) NS(ClContext_track_until)(
@@ -2091,7 +2540,7 @@ ::NS(track_status_t) NS(ClContext_track_until)(
     ::NS(context_num_turns_t) const until_turn )
 {
     return ( ctx != nullptr ) ? ctx->track_until( until_turn )
-        : st::TRACK_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::TRACK_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(track_status_t) NS(ClContext_track_until_for_particle_set)(
@@ -2104,7 +2553,7 @@ ::NS(track_status_t) NS(ClContext_track_until_for_particle_set)(
     return ( ctx != nullptr )
         ? ctx->track_until( until_turn, particle_set_index,
             num_particles_in_set, restore_particle_set_index )
-        : st::TRACK_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::TRACK_STATUS_GENERAL_FAILURE;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -2119,7 +2568,7 @@ ::NS(arch_kernel_id_t) NS(ClContext_track_line_kernel_id)(
     const ::NS(ClContext) *const SIXTRL_RESTRICT ctx )
 {
     return ( ctx != nullptr ) ? ctx->track_line_kernel_id()
-        : st::ARCH_ILLEGAL_KERNEL_ID;
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_KERNEL_ID;
 }
 
 ::NS(arch_status_t) NS(ClContext_set_track_line_kernel_id)(
@@ -2128,7 +2577,7 @@ ::NS(arch_status_t) NS(ClContext_set_track_line_kernel_id)(
 {
     return ( ctx != nullptr )
         ? ctx->set_track_line_kernel_id( kernel_id )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(track_status_t) NS(ClContext_track_line)(
@@ -2152,7 +2601,7 @@ ::NS(track_status_t) NS(ClContext_track_line_for_particle_set)(
         ? ctx->track_line( line_begin_idx, line_end_idx, finish_turn,
             particle_set_index, num_particles_in_set,
             restore_particle_set_index )
-        : st::TRACK_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::TRACK_STATUS_GENERAL_FAILURE;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -2168,7 +2617,8 @@ ::NS(arch_kernel_id_t) NS(ClContext_track_elem_by_elem_kernel_id)(
     const ::NS(ClContext) *const SIXTRL_RESTRICT ctx )
 {
     return ( ctx != nullptr )
-        ? ctx->track_elem_by_elem_kernel_id() : st::ARCH_ILLEGAL_KERNEL_ID;
+        ? ctx->track_elem_by_elem_kernel_id()
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_KERNEL_ID;
 }
 
 ::NS(arch_status_t) NS(ClContext_set_track_elem_by_elem_kernel_id)(
@@ -2177,7 +2627,7 @@ ::NS(arch_status_t) NS(ClContext_set_track_elem_by_elem_kernel_id)(
 {
     return ( ctx != nullptr )
         ? ctx->set_track_elem_by_elem_kernel_id( kernel_id )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(track_status_t) NS(ClContext_track_elem_by_elem)(
@@ -2185,7 +2635,7 @@ ::NS(track_status_t) NS(ClContext_track_elem_by_elem)(
     ::NS(buffer_size_t) const until_turn )
 {
     return ( ctx != nullptr ) ? ctx->track_elem_by_elem( until_turn )
-        : st::TRACK_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::TRACK_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(track_status_t) NS(ClContext_track_elem_by_elem_for_particle_set)(
@@ -2198,7 +2648,7 @@ ::NS(track_status_t) NS(ClContext_track_elem_by_elem_for_particle_set)(
     return ( ctx != nullptr )
         ? ctx->track_elem_by_elem( until_turn, particle_set_index,
             num_particles_in_set, restore_particle_set_index )
-        : st::TRACK_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::TRACK_STATUS_GENERAL_FAILURE;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -2214,7 +2664,7 @@ ::NS(arch_kernel_id_t) NS(ClContext_assign_beam_monitor_output_kernel_id)(
     const ::NS(ClContext) *const SIXTRL_RESTRICT ctx )
 {
     return ( ctx != nullptr ) ? ctx->assign_beam_monitor_output_kernel_id()
-        : st::ARCH_ILLEGAL_KERNEL_ID;
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_KERNEL_ID;
 }
 
 ::NS(arch_status_t) NS(ClContext_set_assign_beam_monitor_output_kernel_id)(
@@ -2223,7 +2673,7 @@ ::NS(arch_status_t) NS(ClContext_set_assign_beam_monitor_output_kernel_id)(
 {
     return ( ctx != nullptr )
         ? ctx->set_assign_beam_monitor_output_kernel_id( kernel_id )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(arch_status_t) NS(ClContext_assign_beam_monitor_output)(
@@ -2234,7 +2684,7 @@ ::NS(arch_status_t) NS(ClContext_assign_beam_monitor_output)(
     return ( ctx != nullptr )
         ? ctx->assign_beam_monitor_output(
             min_turn_id, out_buffer_index_offset )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -2250,7 +2700,7 @@ ::NS(arch_kernel_id_t) NS(ClContext_assign_elem_by_elem_output_kernel_id)(
     const ::NS(ClContext) *const SIXTRL_RESTRICT ctx )
 {
     return ( ctx != nullptr ) ? ctx->assign_elem_by_elem_output_kernel_id()
-        : st::ARCH_ILLEGAL_KERNEL_ID;
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_KERNEL_ID;
 }
 
 ::NS(arch_status_t) NS(ClContext_set_assign_elem_by_elem_output_kernel_id)(
@@ -2259,7 +2709,7 @@ ::NS(arch_status_t) NS(ClContext_set_assign_elem_by_elem_output_kernel_id)(
 {
     return ( ctx != nullptr )
         ? ctx->set_assign_elem_by_elem_output_kernel_id( kernel_id )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(arch_status_t) NS(ClContext_assign_elem_by_elem_output)(
@@ -2268,7 +2718,7 @@ ::NS(arch_status_t) NS(ClContext_assign_elem_by_elem_output)(
 {
     return ( ctx != nullptr )
         ? ctx->assign_elem_by_elem_output( out_buffer_index_offset )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -2285,7 +2735,7 @@ ::NS(arch_kernel_id_t) NS(ClContext_clear_beam_monitor_output_kernel_id)(
 {
     return (ctx != nullptr )
         ? ctx->clear_beam_monitor_output_kernel_id()
-        : st::ARCH_ILLEGAL_KERNEL_ID;
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_KERNEL_ID;
 }
 
 ::NS(arch_status_t) NS(ClContext_set_clear_beam_monitor_output_kernel_id)(
@@ -2294,14 +2744,54 @@ ::NS(arch_status_t) NS(ClContext_set_clear_beam_monitor_output_kernel_id)(
 {
     return ( ctx != nullptr )
         ? ctx->set_clear_beam_monitor_output_kernel_id( kernel_id )
-        : st::ARCH_STATUS_GENERAL_FAILURE;
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 ::NS(ctrl_status_t) NS(ClContext_clear_beam_monitor_output)(
     ::NS(ClContext)*  SIXTRL_RESTRICT ctx )
 {
     return ( ctx != nullptr )
-        ? ctx->clear_beam_monitor_output() : st::ARCH_STATUS_GENERAL_FAILURE;
+        ? ctx->clear_beam_monitor_output()
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+/* ========================================================================= */
+
+bool NS(ClContext_has_assign_addresses_kernel)(
+    const ::NS(ClContext) *const SIXTRL_RESTRICT ctx )
+{
+    return ( ( ctx != nullptr ) && ( ctx->has_assign_addresses_kernel() ) );
+}
+
+::NS(ctrl_kernel_id_t) NS(ClContext_assign_addresses_kernel_id)(
+    const ::NS(ClContext) *const SIXTRL_RESTRICT ctx )
+{
+    return ( ctx != nullptr ) ? ctx->assign_addresses_kernel_id()
+        : SIXTRL_CXX_NAMESPACE::ARCH_ILLEGAL_KERNEL_ID;
+}
+
+::NS(arch_status_t) NS(ClContext_set_assign_addresses_kernel_id)(
+    ::NS(ClContext)* SIXTRL_RESTRICT ctx,
+    ::NS(ctrl_kernel_id_t) const kernel_id )
+{
+    return ( ctx != nullptr )
+        ? ctx->set_assign_addresses_kernel_id( kernel_id )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
+}
+
+NS(arch_status_t) NS(ClContext_assign_addresses)(
+    ::NS(ClContext)* SIXTRL_RESTRICT ctx,
+    ::NS(ClArgument)* SIXTRL_RESTRICT assign_items_arg,
+    ::NS(ClArgument)* SIXTRL_RESTRICT dest_buffer_arg,
+    ::NS(buffer_size_t) const dest_buffer_id,
+    ::NS(ClArgument)* SIXTRL_RESTRICT src_buffer_arg,
+    ::NS(buffer_size_t) const src_buffer_id )
+{
+    return ( ( ctx != nullptr ) && ( assign_items_arg != nullptr ) &&
+             ( dest_buffer_arg != nullptr ) && ( src_buffer_arg != nullptr ) )
+        ? ctx->assign_addresses( *assign_items_arg,
+            *dest_buffer_arg, dest_buffer_id, *src_buffer_arg, src_buffer_id )
+        : SIXTRL_CXX_NAMESPACE::ARCH_STATUS_GENERAL_FAILURE;
 }
 
 /* ========================================================================= */
@@ -2360,172 +2850,10 @@ void NS(ClContext_disable_beam_beam_tracking)(
     if( ctx != nullptr ) ctx->disable_beam_beam_tracking();
 }
 
-/* ------------------------------------------------------------------------- */
-
-cl_mem NS(ClContext_create_elem_by_elem_config_arg)(
+void NS(ClContext_skip_beam_beam_tracking)(
     ::NS(ClContext)* SIXTRL_RESTRICT ctx )
 {
-    if( ( ctx != nullptr ) && ( ctx->hasSelectedNode() ) &&
-        ( ctx->openClQueue()   != nullptr ) &&
-        ( ctx->openClContext() != nullptr ) )
-    {
-        cl_context& ocl_ctx = ( *ctx->openClContext() )();
-        cl_int cl_ret = CL_SUCCESS;
-
-        cl_mem arg_buffer = ::clCreateBuffer( ocl_ctx, CL_MEM_READ_WRITE,
-            sizeof( ::NS(ElemByElemConfig) ), nullptr, &cl_ret );
-
-        if( cl_ret == CL_SUCCESS )
-        {
-            cl_uint ref_cnt = cl_uint{ 10000 };
-            cl_ret = ::clGetMemObjectInfo( arg_buffer, CL_MEM_REFERENCE_COUNT,
-                sizeof( cl_uint ), &ref_cnt, nullptr );
-
-            if( cl_ret == CL_SUCCESS )
-            {
-                ::clRetainMemObject( arg_buffer );
-                return arg_buffer;
-            }
-        }
-    }
-
-    return cl_mem{};
-}
-
-void NS(ClContext_delete_elem_by_elem_config_arg)(
-    ::NS(ClContext)* SIXTRL_RESTRICT ctx, cl_mem elem_by_elem_config_arg )
-{
-    cl_uint ref_cnt = cl_uint{ 10000 };
-    cl_int cl_ret = ::clGetMemObjectInfo( elem_by_elem_config_arg,
-        CL_MEM_REFERENCE_COUNT, sizeof( cl_uint ), &ref_cnt, nullptr );
-
-    if( ( cl_ret == CL_SUCCESS ) && ( ref_cnt > cl_uint{ 0 } ) )
-    {
-        ::clReleaseMemObject( elem_by_elem_config_arg );
-    }
-
-    ( void )ctx;
-}
-
-::NS(arch_status_t) NS(ClContext_init_elem_by_elem_config_arg)(
-    ::NS(ClContext)* SIXTRL_RESTRICT ctx,
-    cl_mem elem_by_elem_config_arg,
-    ::NS(ElemByElemConfig)* SIXTRL_RESTRICT elem_by_elem_config,
-    const ::NS(Buffer) *const SIXTRL_RESTRICT pbuffer,
-    ::NS(buffer_size_t) const num_psets,
-    ::NS(buffer_size_t) const* SIXTRL_RESTRICT pset_indices_begin,
-    const ::NS(Buffer) *const SIXTRL_RESTRICT beam_elements_buffer,
-    ::NS(buffer_size_t) const until_turn_elem_by_elem,
-    ::NS(particle_index_t) const start_elem_id )
-{
-    ::NS(arch_status_t) status = ::NS(ARCH_STATUS_GENERAL_FAILURE);
-
-    if( ( elem_by_elem_config == nullptr ) || ( ctx == nullptr ) ||
-        ( !ctx->hasSelectedNode() ) ||
-        ( ctx->openClQueue() == nullptr ) ||
-        ( ctx->openClContext() == nullptr ) )
-    {
-        return status;
-    }
-
-    cl_int cl_ret = ::clRetainMemObject( elem_by_elem_config_arg );
-
-    if( cl_ret == CL_SUCCESS )
-    {
-        ::cl_command_queue& ocl_queue = ( *ctx->openClQueue() )();
-
-        status = ::NS(ElemByElemConfig_init_on_particle_sets)(
-            elem_by_elem_config, pbuffer, num_psets, pset_indices_begin,
-                beam_elements_buffer, start_elem_id,
-                    until_turn_elem_by_elem );
-
-        if( status == ::NS(ARCH_STATUS_SUCCESS) )
-        {
-            ::NS(ElemByElemConfig_set_output_store_address)(
-                elem_by_elem_config, uintptr_t{ 0 } );
-
-            size_t const type_size = sizeof( ::NS(ElemByElemConfig) );
-
-            cl_ret = ::clEnqueueWriteBuffer( ocl_queue, elem_by_elem_config_arg,
-                CL_TRUE, size_t { 0 }, type_size, elem_by_elem_config,
-                    cl_uint{ 0 }, nullptr, nullptr );
-
-            if( cl_ret != CL_SUCCESS )
-            {
-                status = ::NS(ARCH_STATUS_GENERAL_FAILURE);
-            }
-        }
-
-        ::clReleaseMemObject( elem_by_elem_config_arg );
-    }
-
-    return status;
-}
-
-::NS(arch_status_t) NS(ClContext_collect_elem_by_elem_config_arg)(
-    ::NS(ClContext)* SIXTRL_RESTRICT ctx, cl_mem elem_by_elem_config_arg,
-    ::NS(ElemByElemConfig)* SIXTRL_RESTRICT config )
-{
-    ::NS(arch_status_t) status = ::NS(ARCH_STATUS_GENERAL_FAILURE);
-
-    if( ( config == nullptr ) || ( ctx == nullptr ) ||
-        ( !ctx->hasSelectedNode() ) ||
-        ( ctx->openClQueue() == nullptr ) ||
-        ( ctx->openClContext() == nullptr ) )
-    {
-        return status;
-    }
-
-    cl_int cl_ret = ::clRetainMemObject( elem_by_elem_config_arg );
-
-    if( cl_ret == CL_SUCCESS )
-    {
-        ::cl_command_queue& ocl_queue = ( *ctx->openClQueue() )();
-        size_t const type_size = sizeof( ::NS(ElemByElemConfig) );
-
-        cl_ret = ::clEnqueueReadBuffer( ocl_queue,
-            elem_by_elem_config_arg, CL_TRUE, size_t{ 0 }, type_size,
-                config, cl_uint{ 0 }, nullptr, nullptr );
-
-
-        if( cl_ret != CL_SUCCESS ) status = ::NS(ARCH_STATUS_SUCCESS);
-        ::clReleaseMemObject( elem_by_elem_config_arg );
-    }
-
-    return status;
-}
-
-::NS(arch_status_t) NS(ClContext_push_elem_by_elem_config_arg)(
-    ::NS(ClContext)* SIXTRL_RESTRICT ctx, cl_mem elem_by_elem_config_arg,
-    const ::NS(ElemByElemConfig) *const SIXTRL_RESTRICT config )
-{
-    ::NS(arch_status_t) status = ::NS(ARCH_STATUS_GENERAL_FAILURE);
-
-    if( ( config == nullptr ) || ( ctx == nullptr ) ||
-        ( !ctx->hasSelectedNode() ) ||
-        ( ctx->openClQueue() == nullptr ) ||
-        ( ctx->openClContext() == nullptr ) )
-    {
-        return status;
-    }
-
-    cl_int cl_ret = ::clRetainMemObject( elem_by_elem_config_arg );
-
-    if( cl_ret == CL_SUCCESS )
-    {
-        ::cl_command_queue& ocl_queue = ( *ctx->openClQueue() )();
-        size_t const type_size = sizeof( ::NS(ElemByElemConfig) );
-
-        cl_ret = ::clEnqueueWriteBuffer( ocl_queue,
-            elem_by_elem_config_arg, CL_TRUE, size_t { 0 }, type_size,
-                config, cl_uint{ 0 }, nullptr, nullptr );
-
-        if( cl_ret != CL_SUCCESS ) status = ::NS(ARCH_STATUS_SUCCESS);
-        ::clReleaseMemObject( elem_by_elem_config_arg );
-    }
-
-    return status;
+    if( ctx != nullptr ) ctx->skip_beam_beam_tracking();
 }
 
 #endif /* !defined( __CUDACC__ ) */
-/* end: sixtracklib/opencl/internal/context.cpp */
diff --git a/sixtracklib/opencl/internal/track_job_cl.cpp b/sixtracklib/opencl/internal/track_job_cl.cpp
index 3682c1d2..9d139a2c 100644
--- a/sixtracklib/opencl/internal/track_job_cl.cpp
+++ b/sixtracklib/opencl/internal/track_job_cl.cpp
@@ -20,18 +20,17 @@
     #include "sixtracklib/opencl/argument.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
-namespace st = SIXTRL_CXX_NAMESPACE;
-
 namespace SIXTRL_CXX_NAMESPACE
 {
     namespace
     {
-        using _this_t   = st::TrackJobCl;
-        using _size_t   = _this_t::size_type;
-        using _status_t = _this_t::status_t;
+        namespace st = SIXTRL_CXX_NAMESPACE;
+        using tjob_t      = st::TrackJobCl;
+        using st_size_t   = tjob_t::size_type;
+        using st_status_t = tjob_t::status_t;
     }
 
-    TrackJobCl::TrackJobCl(
+    tjob_t::TrackJobCl(
         std::string const& SIXTRL_RESTRICT_REF device_id_str,
         std::string const& SIXTRL_RESTRICT_REF config_str ) :
         TrackJobBase( st::TRACK_JOB_CL_STR, st::TRACK_JOB_CL_ID ),
@@ -39,7 +38,8 @@ namespace SIXTRL_CXX_NAMESPACE
         m_ptr_particles_buffer_arg( nullptr ),
         m_ptr_beam_elements_buffer_arg( nullptr ),
         m_ptr_output_buffer_arg( nullptr ),
-        m_ptr_cl_elem_by_elem_config_buffer( nullptr ),
+        m_ptr_particles_addr_buffer_arg( nullptr ),
+        m_ptr_elem_by_elem_config_arg( nullptr ),
         m_total_num_particles( TrackJobBase::size_type{ 0 } )
     {
         if( !config_str.empty() )
@@ -56,7 +56,7 @@ namespace SIXTRL_CXX_NAMESPACE
             device_id_str.c_str(), this->ptrConfigStr() );
     }
 
-    TrackJobCl::TrackJobCl(
+    tjob_t::TrackJobCl(
         const char *const SIXTRL_RESTRICT device_id_str,
         const char *const SIXTRL_RESTRICT config_str ) :
         TrackJobBase( st::TRACK_JOB_CL_STR, st::TRACK_JOB_CL_ID ),
@@ -64,7 +64,8 @@ namespace SIXTRL_CXX_NAMESPACE
         m_ptr_particles_buffer_arg( nullptr ),
         m_ptr_beam_elements_buffer_arg( nullptr ),
         m_ptr_output_buffer_arg( nullptr ),
-        m_ptr_cl_elem_by_elem_config_buffer( nullptr ),
+        m_ptr_particles_addr_buffer_arg( nullptr ),
+        m_ptr_elem_by_elem_config_arg( nullptr ),
         m_total_num_particles( TrackJobBase::size_type{ 0 } )
     {
         if( config_str != nullptr )
@@ -79,19 +80,20 @@ namespace SIXTRL_CXX_NAMESPACE
         this->doPrepareContextOclImpl( device_id_str, this->ptrConfigStr() );
     }
 
-    TrackJobCl::TrackJobCl(
+    tjob_t::TrackJobCl(
         const char *const SIXTRL_RESTRICT device_id_str,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elements_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem,
         const char *const SIXTRL_RESTRICT config_str ) :
         TrackJobBase( st::TRACK_JOB_CL_STR, st::TRACK_JOB_CL_ID ),
         m_ptr_context( nullptr ),
         m_ptr_particles_buffer_arg( nullptr ),
         m_ptr_beam_elements_buffer_arg( nullptr ),
         m_ptr_output_buffer_arg( nullptr ),
-        m_ptr_cl_elem_by_elem_config_buffer( nullptr ),
+        m_ptr_particles_addr_buffer_arg( nullptr ),
+        m_ptr_elem_by_elem_config_arg( nullptr ),
         m_total_num_particles( TrackJobBase::size_type{ 0 } )
     {
         this->doInitTrackJobCl( device_id_str, particles_buffer,
@@ -100,24 +102,25 @@ namespace SIXTRL_CXX_NAMESPACE
             config_str );
     }
 
-    TrackJobCl::TrackJobCl(
+    tjob_t::TrackJobCl(
         const char *const SIXTRL_RESTRICT device_id_str,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _size_t const num_particle_sets,
-        _size_t const* SIXTRL_RESTRICT pset_begin,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belements_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        st_size_t const num_particle_sets,
+        st_size_t const* SIXTRL_RESTRICT pset_begin,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belements_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem,
         const char *const SIXTRL_RESTRICT config_str ) :
         TrackJobBase( st::TRACK_JOB_CL_STR, st::TRACK_JOB_CL_ID ),
         m_ptr_context( nullptr ),
         m_ptr_particles_buffer_arg( nullptr ),
         m_ptr_beam_elements_buffer_arg( nullptr ),
         m_ptr_output_buffer_arg( nullptr ),
-        m_ptr_cl_elem_by_elem_config_buffer( nullptr ),
+        m_ptr_particles_addr_buffer_arg( nullptr ),
+        m_ptr_elem_by_elem_config_arg( nullptr ),
         m_total_num_particles( TrackJobBase::size_type{ 0 } )
     {
-        using size_t  = _size_t;
+        using size_t  = st_size_t;
         size_t const* pset_end = pset_begin;
 
         if( ( pset_end != nullptr ) && ( num_particle_sets > size_t{ 0 } ) )
@@ -130,22 +133,23 @@ namespace SIXTRL_CXX_NAMESPACE
             until_turn_elem_by_elem, config_str );
     }
 
-    TrackJobCl::TrackJobCl(
+    tjob_t::TrackJobCl(
         std::string const& SIXTRL_RESTRICT_REF device_id_str,
-        TrackJobCl::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
-        TrackJobCl::buffer_t& SIXTRL_RESTRICT_REF belements_buffer,
-        TrackJobCl::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF particles_buffer,
+        tjob_t::buffer_t& SIXTRL_RESTRICT_REF belements_buffer,
+        tjob_t::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem,
         std::string const& config_str ) :
         TrackJobBase( st::TRACK_JOB_CL_STR, st::TRACK_JOB_CL_ID ),
         m_ptr_context( nullptr ),
         m_ptr_particles_buffer_arg( nullptr ),
         m_ptr_beam_elements_buffer_arg( nullptr ),
         m_ptr_output_buffer_arg( nullptr ),
-        m_ptr_cl_elem_by_elem_config_buffer( nullptr ),
+        m_ptr_particles_addr_buffer_arg( nullptr ),
+        m_ptr_elem_by_elem_config_arg( nullptr ),
         m_total_num_particles( TrackJobBase::size_type{ 0 } )
     {
-        using c_buffer_t = _this_t::c_buffer_t;
+        using c_buffer_t = tjob_t::c_buffer_t;
 
         c_buffer_t* ptr_part_buffer  = particles_buffer.getCApiPtr();
         c_buffer_t* ptr_belem_buffer = belements_buffer.getCApiPtr();
@@ -170,131 +174,178 @@ namespace SIXTRL_CXX_NAMESPACE
         }
     }
 
-    TrackJobCl::~TrackJobCl() SIXTRL_NOEXCEPT {}
+    tjob_t::~TrackJobCl() SIXTRL_NOEXCEPT {}
 
-    _this_t::cl_context_t& TrackJobCl::context() SIXTRL_RESTRICT
+    tjob_t::cl_context_t& tjob_t::context() SIXTRL_NOEXCEPT
     {
-        return const_cast< _this_t::cl_context_t& >(
-            static_cast< _this_t const& >( *this ).context() );
+        return const_cast< tjob_t::cl_context_t& >(
+            static_cast< tjob_t const& >( *this ).context() );
     }
 
 
-    _this_t::cl_context_t const& TrackJobCl::context() const SIXTRL_RESTRICT
+    tjob_t::cl_context_t const& tjob_t::context() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->ptrContext() != nullptr );
         return *( this->ptrContext() );
     }
 
-    ::NS(ClContext)* TrackJobCl::ptrContext() SIXTRL_RESTRICT
+    ::NS(ClContext)* tjob_t::ptrContext() SIXTRL_NOEXCEPT
     {
         return this->m_ptr_context.get();
     }
 
-    ::NS(ClContext) const* TrackJobCl::ptrContext() const SIXTRL_RESTRICT
+    ::NS(ClContext) const* tjob_t::ptrContext() const SIXTRL_NOEXCEPT
     {
         return this->m_ptr_context.get();
     }
 
-    _this_t::cl_arg_t& TrackJobCl::particlesArg() SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t& tjob_t::particlesArg() SIXTRL_NOEXCEPT
     {
-        return const_cast< _this_t::cl_arg_t& >(
-            static_cast< _this_t const& >( *this ).particlesArg() );
+        return const_cast< tjob_t::cl_arg_t& >(
+            static_cast< tjob_t const& >( *this ).particlesArg() );
     }
 
-    _this_t::cl_arg_t const& TrackJobCl::particlesArg() const SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t const& tjob_t::particlesArg() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->ptrParticlesArg() != nullptr );
         return *(this->ptrParticlesArg() );
     }
 
-    _this_t::cl_arg_t* TrackJobCl::ptrParticlesArg() SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t* tjob_t::ptrParticlesArg() SIXTRL_NOEXCEPT
     {
-        return const_cast< _this_t::cl_arg_t* >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::cl_arg_t* >( static_cast< tjob_t const& >(
             *this ).ptrParticlesArg() );
     }
 
-    _this_t::cl_arg_t const* TrackJobCl::ptrParticlesArg() const SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t const* tjob_t::ptrParticlesArg() const SIXTRL_NOEXCEPT
     {
         return this->m_ptr_particles_buffer_arg.get();
     }
 
-    _this_t::cl_arg_t& TrackJobCl::beamElementsArg() SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t& tjob_t::beamElementsArg() SIXTRL_NOEXCEPT
     {
-        return const_cast< _this_t::cl_arg_t& >( static_cast<
+        return const_cast< tjob_t::cl_arg_t& >( static_cast<
             TrackJobCl const& >( *this ).beamElementsArg() );
     }
 
-    _this_t::cl_arg_t const& TrackJobCl::beamElementsArg() const SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t const& tjob_t::beamElementsArg() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->ptrBeamElementsArg() != nullptr );
         return *( this->ptrBeamElementsArg() );
     }
 
-    _this_t::cl_arg_t* TrackJobCl::ptrBeamElementsArg() SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t* tjob_t::ptrBeamElementsArg() SIXTRL_NOEXCEPT
     {
-        return const_cast< _this_t::cl_arg_t* >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::cl_arg_t* >( static_cast< tjob_t const& >(
             *this ).ptrBeamElementsArg() );
     }
 
-    _this_t::cl_arg_t const*
-    TrackJobCl::ptrBeamElementsArg() const SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t const*
+    tjob_t::ptrBeamElementsArg() const SIXTRL_NOEXCEPT
     {
         return this->m_ptr_beam_elements_buffer_arg.get();
     }
 
-    _this_t::cl_arg_t& TrackJobCl::outputBufferArg() SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t& tjob_t::outputBufferArg() SIXTRL_NOEXCEPT
     {
-        return const_cast< _this_t::cl_arg_t& >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::cl_arg_t& >( static_cast< tjob_t const& >(
             *this ).outputBufferArg() );
     }
 
-    _this_t::cl_arg_t const& TrackJobCl::outputBufferArg() const SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t const& tjob_t::outputBufferArg() const SIXTRL_NOEXCEPT
     {
         SIXTRL_ASSERT( this->ptrOutputBufferArg() != nullptr );
         return *( this->m_ptr_output_buffer_arg );
     }
 
-    _this_t::cl_arg_t* TrackJobCl::ptrOutputBufferArg() SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t* tjob_t::ptrOutputBufferArg() SIXTRL_NOEXCEPT
     {
-        return const_cast< _this_t::cl_arg_t* >( static_cast< _this_t const& >(
+        return const_cast< tjob_t::cl_arg_t* >( static_cast< tjob_t const& >(
             *this ).ptrOutputBufferArg() );
     }
 
-    _this_t::cl_arg_t const*
-    TrackJobCl::ptrOutputBufferArg() const SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t const*
+    tjob_t::ptrOutputBufferArg() const SIXTRL_NOEXCEPT
     {
         return this->m_ptr_output_buffer_arg.get();
     }
 
+    tjob_t::cl_arg_t const&
+    tjob_t::particlesAddrBufferArg() const SIXTRL_NOEXCEPT
+    {
+        SIXTRL_ASSERT( this->ptrParticlesAddrBufferArg() != nullptr );
+        return *this->m_ptr_particles_addr_buffer_arg;
+    }
+
+    tjob_t::cl_arg_t& tjob_t::particlesAddrBufferArg() SIXTRL_NOEXCEPT
+    {
+        SIXTRL_ASSERT( this->ptrParticlesAddrBufferArg() != nullptr );
+        return *this->m_ptr_particles_addr_buffer_arg;
+    }
+
+    tjob_t::cl_arg_t const*
+    tjob_t::ptrParticlesAddrBufferArg() const SIXTRL_NOEXCEPT
+    {
+        return this->m_ptr_particles_addr_buffer_arg.get();
+    }
+
+    tjob_t::cl_arg_t* tjob_t::ptrParticlesAddrBufferArg() SIXTRL_NOEXCEPT
+    {
+        return this->m_ptr_particles_addr_buffer_arg.get();
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::cl_arg_t const&
+    tjob_t::elemByelemConfigBufferArg() const SIXTRL_NOEXCEPT
+    {
+        SIXTRL_ASSERT( this->ptrElemByElemConfigBufferArg() != nullptr );
+        return *( this->ptrElemByElemConfigBufferArg() );
+    }
+
+    tjob_t::cl_arg_t& tjob_t::elemByelemConfigBufferArg() SIXTRL_NOEXCEPT
+    {
+        using ref_t = tjob_t::cl_arg_t&;
+        return const_cast< ref_t >( static_cast< tjob_t const& >(
+                *this ).elemByelemConfigBufferArg() );
+    }
+
+    tjob_t::cl_arg_t const*
+    tjob_t::ptrElemByElemConfigBufferArg() const SIXTRL_NOEXCEPT
+    {
+        return this->m_ptr_elem_by_elem_config_arg.get();
+    }
+
+    tjob_t::cl_arg_t& tjob_t::particles_addr_arg() SIXTRL_NOEXCEPT
+    {
+        SIXTRL_ASSERT( this->m_ptr_particles_addr_buffer_arg.get() != nullptr );
+        return *( this->m_ptr_particles_addr_buffer_arg.get() );
+    }
 
-    _this_t::cl_buffer_t const&
-    TrackJobCl::clElemByElemConfigBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t const& tjob_t::particles_addr_arg() const SIXTRL_NOEXCEPT
     {
-        SIXTRL_ASSERT( this->ptrClElemByElemConfigBuffer() != nullptr );
-        return *( this->ptrClElemByElemConfigBuffer() );
+        SIXTRL_ASSERT( this->m_ptr_particles_addr_buffer_arg.get() != nullptr );
+        return *( this->m_ptr_particles_addr_buffer_arg.get() );
     }
 
-    _this_t::cl_buffer_t& TrackJobCl::clElemByElemConfigBuffer() SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t* tjob_t::ptr_particles_addr_arg() SIXTRL_NOEXCEPT
     {
-        using ref_t = _this_t::cl_buffer_t&;
-        return const_cast< ref_t >( static_cast< _this_t const& >(
-                *this ).clElemByElemConfigBuffer() );
+        return this->m_ptr_particles_addr_buffer_arg.get();
     }
 
-    _this_t::cl_buffer_t const*
-    TrackJobCl::ptrClElemByElemConfigBuffer() const SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t const*
+        tjob_t::ptr_particles_addr_arg() const SIXTRL_NOEXCEPT
     {
-        return this->m_ptr_cl_elem_by_elem_config_buffer.get();
+        return this->m_ptr_particles_addr_buffer_arg.get();
     }
 
-    _this_t::cl_buffer_t*
-    TrackJobCl::ptrClElemByElemConfigBuffer() SIXTRL_NOEXCEPT
+    tjob_t::cl_arg_t* tjob_t::ptrElemByElemConfigBufferArg() SIXTRL_NOEXCEPT
     {
-        return this->m_ptr_cl_elem_by_elem_config_buffer.get();
+        return this->m_ptr_elem_by_elem_config_arg.get();
     }
 
-    _this_t::status_t TrackJobCl::updateBeamElementsRegion(
-        _size_t const offset, _size_t const length,
+    tjob_t::status_t tjob_t::updateBeamElementsRegion(
+        st_size_t const offset, st_size_t const length,
         void const* SIXTRL_RESTRICT new_value )
     {
         return ( this->m_ptr_beam_elements_buffer_arg != nullptr )
@@ -303,10 +354,10 @@ namespace SIXTRL_CXX_NAMESPACE
             : ::NS(ARCH_STATUS_GENERAL_FAILURE);
     }
 
-    _this_t::status_t TrackJobCl::updateBeamElementsRegions(
-        _size_t const num_regions_to_update,
-        _size_t const* SIXTRL_RESTRICT offsets,
-        _size_t const* SIXTRL_RESTRICT lengths,
+    tjob_t::status_t tjob_t::updateBeamElementsRegions(
+        st_size_t const num_regions_to_update,
+        st_size_t const* SIXTRL_RESTRICT offsets,
+        st_size_t const* SIXTRL_RESTRICT lengths,
         void const* SIXTRL_RESTRICT const* SIXTRL_RESTRICT new_values )
     {
         return ( this->m_ptr_beam_elements_buffer_arg != nullptr )
@@ -315,26 +366,200 @@ namespace SIXTRL_CXX_NAMESPACE
             : ::NS(ARCH_STATUS_GENERAL_FAILURE);
     }
 
+    std::uintptr_t tjob_t::opencl_context_addr() const SIXTRL_NOEXCEPT
+    {
+        return ( this->ptrContext() != nullptr )
+            ? this->ptrContext()->openClContextAddr() : std::uintptr_t{ 0 };
+    }
+
+    std::uintptr_t tjob_t::opencl_queue_addr() const SIXTRL_NOEXCEPT
+    {
+        return ( this->ptrContext() != nullptr )
+            ? this->ptrContext()->openClQueueAddr() : std::uintptr_t{ 0 };
+    }
+
+    st_status_t tjob_t::doFetchParticleAddresses()
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( ( this->ptrContext() != nullptr ) &&
+            ( this->ptrContext()->hasSelectedNode() ) &&
+            ( this->ptrContext()->has_fetch_particles_addr_kernel() ) &&
+            ( this->ptr_particles_addr_arg() != nullptr ) )
+        {
+            status = this->ptrContext()->fetch_particles_addr();
+        }
+
+        if( status == st::ARCH_STATUS_SUCCESS )
+        {
+            status = ( this->ptr_particles_addr_arg()->read(
+                this->doGetPtrParticlesAddrBuffer() ) )
+                    ? st::ARCH_STATUS_SUCCESS : st::ARCH_STATUS_GENERAL_FAILURE;
+        }
+
+        return status;
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::cl_arg_t const* tjob_t::ptr_const_argument_by_buffer_id(
+        tjob_t::size_type const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+         tjob_t::cl_arg_t const* ptr_arg = nullptr;
+
+        switch( buffer_id )
+        {
+            case st::ARCH_PARTICLES_BUFFER_ID:
+            {
+                ptr_arg = this->ptrParticlesArg();
+                break;
+            }
+
+            case st::ARCH_BEAM_ELEMENTS_BUFFER_ID:
+            {
+                ptr_arg = this->ptrBeamElementsArg();
+                break;
+            }
+
+            case st::ARCH_OUTPUT_BUFFER_ID:
+            {
+                ptr_arg = this->ptrOutputBufferArg();
+                break;
+            }
 
-    bool TrackJobCl::doPrepareParticlesStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT pb )
+            case st::ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID:
+            {
+                ptr_arg = this->ptrElemByElemConfigBufferArg();
+                break;
+            }
+
+            case st::ARCH_PARTICLE_ADDR_BUFFER_ID:
+            {
+                ptr_arg = this->ptrParticlesAddrBufferArg();
+                break;
+            }
+
+            default:
+            {
+                ptr_arg = this->ptr_const_stored_buffer_argument( buffer_id );
+            }
+        };
+
+        return ptr_arg;
+    }
+
+    tjob_t::cl_arg_t* tjob_t::ptr_argument_by_buffer_id(
+        tjob_t::size_type const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::cl_arg_t* >(
+            this->ptr_const_argument_by_buffer_id( buffer_id ) );
+    }
+
+    tjob_t::cl_arg_t const& tjob_t::argument_by_buffer_id(
+        tjob_t::size_type const buffer_id ) const
+    {
+        tjob_t::cl_arg_t const* ptr_arg =
+            this->ptr_const_argument_by_buffer_id( buffer_id );
+
+        if( ptr_arg == nullptr )
+        {
+            std::ostringstream a2str;
+            a2str << "unable to get buffer argument for buffer_id="
+                  << buffer_id;
+
+            throw std::runtime_error( a2str.str() );
+        }
+
+        return *ptr_arg;
+    }
+
+    tjob_t::cl_arg_t& tjob_t::argument_by_buffer_id(
+        tjob_t::size_type const buffer_id )
+    {
+        return const_cast< tjob_t::cl_arg_t& >( static_cast< tjob_t const& >(
+            *this ).argument_by_buffer_id( buffer_id ) );
+    }
+
+    /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
+
+    tjob_t::cl_arg_t const* tjob_t::ptr_const_stored_buffer_argument(
+        tjob_t::size_type const buffer_id ) const SIXTRL_NOEXCEPT
+    {
+        tjob_t::cl_arg_t const* ptr_arg = nullptr;
+
+        st_size_t const min_buffer_id = this->min_stored_buffer_id();
+        st_size_t const max_buffer_id_plus_one =
+            this->max_stored_buffer_id() + st_size_t{ 1 };
+
+        if( ( min_buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_id != st::ARCH_ILLEGAL_BUFFER_ID ) &&
+            ( buffer_id >= min_buffer_id ) &&
+            ( buffer_id <  max_buffer_id_plus_one ) )
+        {
+            st_size_t const stored_buffer_id = buffer_id - min_buffer_id;
+
+            if( stored_buffer_id < this->m_stored_buffers_args.size() )
+            {
+                ptr_arg = this->m_stored_buffers_args[ stored_buffer_id ].get();
+            }
+        }
+
+        return ptr_arg;
+    }
+
+    tjob_t::cl_arg_t* tjob_t::ptr_stored_buffer_argument(
+        tjob_t::size_type const buffer_id ) SIXTRL_NOEXCEPT
+    {
+        return const_cast< tjob_t::cl_arg_t* >(
+            this->ptr_const_stored_buffer_argument( buffer_id ) );
+    }
+
+    tjob_t::cl_arg_t const& tjob_t::stored_buffer_argument(
+        tjob_t::size_type const buffer_id ) const
+    {
+        tjob_t::cl_arg_t const* ptr_arg =
+            this->ptr_const_stored_buffer_argument( buffer_id );
+
+        if( ptr_arg == nullptr )
+        {
+            std::ostringstream a2str;
+            a2str << "unable to get stored buffer argument for buffer_id="
+                  << buffer_id;
+
+            throw std::runtime_error( a2str.str() );
+        }
+
+        return *ptr_arg;
+    }
+
+    tjob_t::cl_arg_t& tjob_t::stored_buffer_argument(
+        tjob_t::size_type const buffer_id )
+    {
+        return const_cast< tjob_t::cl_arg_t& >( static_cast<
+            tjob_t const& >( *this ).stored_buffer_argument( buffer_id ) );
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    bool tjob_t::doPrepareParticlesStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pb )
     {
         return ( ( TrackJobBase::doPrepareParticlesStructures( pb ) ) &&
                  ( this->doPrepareParticlesStructuresOclImp( pb ) ) );
     }
 
-    bool TrackJobCl::doPrepareBeamElementsStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belems )
+    bool tjob_t::doPrepareBeamElementsStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems )
     {
         return ( ( TrackJobBase::doPrepareBeamElementsStructures( belems ) ) &&
             ( this->doPrepareBeamElementsStructuresOclImp( belems ) ) );
     }
 
-    bool TrackJobCl::doPrepareOutputStructures(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT part_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::doPrepareOutputStructures(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT part_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
         bool success = TrackJobBase::doPrepareOutputStructures( part_buffer,
                 belem_buffer, output_buffer, until_turn_elem_by_elem );
@@ -349,11 +574,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobCl::doAssignOutputBufferToBeamMonitors(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT out_buffer,
-        _this_t::particle_index_t const min_turn_id,
-        _this_t::size_type const output_buffer_offset_index )
+    bool tjob_t::doAssignOutputBufferToBeamMonitors(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT out_buffer,
+        tjob_t::particle_index_t const min_turn_id,
+        tjob_t::size_type const output_buffer_offset_index )
     {
         bool success = TrackJobBase::doAssignOutputBufferToBeamMonitors(
                 belem_buffer, out_buffer, min_turn_id,
@@ -369,10 +594,10 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobCl::doAssignOutputBufferToElemByElemConfig(
-        _this_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_conf,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT out_buffer,
-        _this_t::size_type const output_buffer_offset_index )
+    bool tjob_t::doAssignOutputBufferToElemByElemConfig(
+        tjob_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_conf,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT out_buffer,
+        tjob_t::size_type const output_buffer_offset_index )
     {
         bool success = TrackJobBase::doAssignOutputBufferToElemByElemConfig(
                 elem_by_elem_conf, out_buffer, output_buffer_offset_index );
@@ -386,30 +611,80 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobCl::doReset(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::doReset(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT particles_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
         return this->doResetOclImp( particles_buffer, beam_elem_buffer,
                 ptr_output_buffer, until_turn_elem_by_elem );
     }
 
-    _this_t::track_status_t TrackJobCl::doTrackUntilTurn(
-        _size_t const until_turn )
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::size_type tjob_t::doAddStoredBuffer(
+        tjob_t::buffer_store_t&& assigned_buffer_handle )
+    {
+        tjob_t::size_type buffer_id = _base_t::doAddStoredBuffer(
+            std::move( assigned_buffer_handle ) );
+
+        if( buffer_id != st::ARCH_ILLEGAL_BUFFER_ID )
+        {
+            if( st::ARCH_STATUS_SUCCESS != this->doAddStoredBufferOclImpl(
+                    buffer_id ) )
+            {
+                this->doRemoveStoredBufferOclImpl( buffer_id );
+                buffer_id = st::ARCH_ILLEGAL_BUFFER_ID;
+            }
+        }
+
+        return buffer_id;
+    }
+
+    tjob_t::status_t tjob_t::doRemoveStoredBuffer(
+        tjob_t::size_type const buffer_id )
+    {
+        tjob_t::status_t status = _base_t::doRemoveStoredBuffer( buffer_id );
+        status |= this->doRemoveStoredBufferOclImpl( buffer_id );
+
+        return status;
+    }
+
+    tjob_t::status_t tjob_t::doPushStoredBuffer(
+        tjob_t::size_type const buffer_id )
+    {
+        return this->doPushStoredBufferOclImpl( buffer_id );
+    }
+
+    tjob_t::status_t tjob_t::doCollectStoredBuffer(
+        tjob_t::size_type const buffer_id )
+    {
+        return this->doCollectStoredBufferOclImpl( buffer_id );
+    }
+
+    tjob_t::status_t tjob_t::doPerformAddressAssignments(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF assign_item_key )
+    {
+        return this->doPerformAddressAssignmentsOclImpl( assign_item_key );
+    }
+
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::track_status_t tjob_t::doTrackUntilTurn(
+        st_size_t const until_turn )
     {
         return st::track( *this, until_turn );
     }
 
-    _this_t::track_status_t TrackJobCl::doTrackElemByElem(
-        _size_t const until_turn )
+    tjob_t::track_status_t tjob_t::doTrackElemByElem(
+        st_size_t const until_turn )
     {
         return st::trackElemByElem( *this, until_turn );
     }
 
-    _this_t::track_status_t TrackJobCl::doTrackLine(
-        _size_t const line_begin_idx, _size_t const line_end_idx,
+    tjob_t::track_status_t tjob_t::doTrackLine(
+        st_size_t const line_begin_idx, st_size_t const line_end_idx,
         bool const finish_turn )
     {
         return st::trackLine(
@@ -417,74 +692,99 @@ namespace SIXTRL_CXX_NAMESPACE
     }
 
 
-    void TrackJobCl::doCollect( TrackJobCl::collect_flag_t const flags )
+    void tjob_t::doCollect( tjob_t::collect_flag_t const flags )
     {
         st::collect( *this, flags );
     }
 
-    void TrackJobCl::doPush( TrackJobCl::push_flag_t const flags )
+    void tjob_t::doPush( tjob_t::push_flag_t const flags )
     {
         st::push( *this, flags );
     }
 
-    void TrackJobCl::doParseConfigStr( const char *const SIXTRL_RESTRICT  ) {}
+    void tjob_t::doParseConfigStr( const char *const SIXTRL_RESTRICT  ) {}
 
-    void TrackJobCl::doUpdateStoredContext(
-        TrackJobCl::ptr_cl_context_t&& context )
+    void tjob_t::doUpdateStoredContext(
+        tjob_t::ptr_cl_context_t&& context )
     {
         this->m_ptr_context = std::move( context );
     }
 
-    void TrackJobCl::doUpdateStoredParticlesArg(
-        TrackJobCl::ptr_cl_arg_t&& particle_arg )
+    void tjob_t::doUpdateStoredClParticlesArg(
+        tjob_t::ptr_cl_arg_t&& particle_arg )
     {
         this->m_ptr_particles_buffer_arg = std::move( particle_arg );
     }
 
-    void TrackJobCl::doUpdateStoredBeamElementsArg(
-        TrackJobCl::ptr_cl_arg_t&& beam_elements_arg )
+    void tjob_t::doUpdateStoredClBeamElementsArg(
+        tjob_t::ptr_cl_arg_t&& beam_elements_arg )
     {
         this->m_ptr_beam_elements_buffer_arg = std::move( beam_elements_arg );
     }
 
-    void TrackJobCl::doUpdateStoredOutputArg(
-        TrackJobCl::ptr_cl_arg_t&& output_arg )
+    void tjob_t::doUpdateStoredClOutputArg(
+        tjob_t::ptr_cl_arg_t&& output_arg )
     {
         this->m_ptr_output_buffer_arg = std::move( output_arg );
     }
 
-    void TrackJobCl::doUpdateStoredClElemByElemConfigBuffer(
-            TrackJobCl::ptr_cl_buffer_t&& cl_elem_by_elem_config_buffer )
+    void tjob_t::doUpdateStoredClElemByElemConfigArg(
+            tjob_t::ptr_cl_arg_t&& cl_elem_by_elem_config_buffer )
     {
-        this->m_ptr_cl_elem_by_elem_config_buffer =
+        this->m_ptr_elem_by_elem_config_arg =
             std::move( cl_elem_by_elem_config_buffer );
     }
 
-    _size_t TrackJobCl::totalNumParticles() const SIXTRL_NOEXCEPT
+    tjob_t::status_t tjob_t::do_update_stored_particles_addr_arg(
+        tjob_t::ptr_cl_arg_t&& particles_addr_arg )
+    {
+        st_status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        this->m_ptr_particles_addr_buffer_arg =
+            std::move( particles_addr_arg );
+
+        if( ( this->ptr_particles_addr_arg() != nullptr ) &&
+            ( this->ptr_particles_addr_arg()->usesCObjectBuffer() ) &&
+            ( this->ptr_particles_addr_arg()->context() ==
+              this->ptrContext() ) &&
+            ( ( !this->context().hasSelectedNode() ) ||
+              ( ( this->context().assign_particles_addr_buffer_arg(
+                  this->particles_addr_arg() ) ==
+                  st::ARCH_STATUS_SUCCESS ) ) ) )
+        {
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    st_size_t tjob_t::totalNumParticles() const SIXTRL_NOEXCEPT
     {
         return this->m_total_num_particles;
     }
 
-    void TrackJobCl::doSetTotalNumParticles(
-        _size_t const total_num_particles ) SIXTRL_NOEXCEPT
+    void tjob_t::doSetTotalNumParticles(
+        st_size_t const total_num_particles ) SIXTRL_NOEXCEPT
     {
         this->m_total_num_particles = total_num_particles;
     }
 
-    bool TrackJobCl::doPrepareContext(
+    bool tjob_t::doPrepareContext(
         char const* SIXTRL_RESTRICT device_id_str,
         char const* SIXTRL_RESTRICT ptr_config_str )
     {
         return this->doPrepareContextOclImpl( device_id_str, ptr_config_str );
     }
 
-    bool TrackJobCl::doPrepareContextOclImpl(
+    /* --------------------------------------------------------------------- */
+
+    bool tjob_t::doPrepareContextOclImpl(
         const char *const SIXTRL_RESTRICT device_id_str,
         const char *const SIXTRL_RESTRICT ptr_config_str )
     {
-        using _this_t       = TrackJobCl;
-        using context_t     = _this_t::cl_context_t;
-        using ptr_context_t = _this_t::ptr_cl_context_t;
+        using tjob_t       = TrackJobCl;
+        using context_t     = tjob_t::cl_context_t;
+        using ptr_context_t = tjob_t::ptr_cl_context_t;
 
         bool success = false;
 
@@ -511,17 +811,17 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    void TrackJobCl::doParseConfigStrOclImpl(
+    void tjob_t::doParseConfigStrOclImpl(
         const char *const SIXTRL_RESTRICT ) {}
 
-    bool TrackJobCl::doPrepareParticlesStructuresOclImp(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT pb )
+    bool tjob_t::doPrepareParticlesStructuresOclImp(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pb )
     {
-        using _this_t = TrackJobCl;
+        using tjob_t = TrackJobCl;
 
-        using arg_t        = _this_t::cl_arg_t;
-        using ptr_arg_t    = _this_t::ptr_cl_arg_t;
-        using size_t       = _this_t::size_type;
+        using arg_t        = tjob_t::cl_arg_t;
+        using ptr_arg_t    = tjob_t::ptr_cl_arg_t;
+        using size_t       = tjob_t::size_type;
 
         bool success = false;
 
@@ -537,10 +837,19 @@ namespace SIXTRL_CXX_NAMESPACE
             this->doSetTotalNumParticles( total_num_particles );
 
             ptr_arg_t particles_arg( new arg_t( pb, this->ptrContext() ) );
-            this->doUpdateStoredParticlesArg( std::move( particles_arg ) );
+            this->doUpdateStoredClParticlesArg( std::move( particles_arg ) );
+
+            ptr_arg_t particles_addr_arg( new arg_t(
+                this->doGetPtrParticlesAddrBuffer(), this->ptrContext() ) );
+
+            success = ( st::ARCH_STATUS_SUCCESS ==
+                this->do_update_stored_particles_addr_arg(
+                    std::move( particles_addr_arg ) ) );
 
-            if( ( total_num_particles > size_t{ 0 } ) &&
+            if( ( success ) &&
+                ( total_num_particles > size_t{ 0 } ) &&
                 ( this->ptrParticlesArg() != nullptr ) &&
+                ( this->ptr_particles_addr_arg() != nullptr ) &&
                 ( this->particlesArg().usesCObjectBuffer() ) &&
                 ( this->particlesArg().context() == this->ptrContext() ) &&
                 ( this->particlesArg().ptrCObjectBuffer() == pb ) &&
@@ -559,20 +868,20 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobCl::doPrepareBeamElementsStructuresOclImp(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belems )
+    bool tjob_t::doPrepareBeamElementsStructuresOclImp(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems )
     {
-        using _this_t = TrackJobCl;
+        using tjob_t = TrackJobCl;
 
-        using arg_t     = _this_t::cl_arg_t;
-        using ptr_arg_t = _this_t::ptr_cl_arg_t;
+        using arg_t     = tjob_t::cl_arg_t;
+        using ptr_arg_t = tjob_t::ptr_cl_arg_t;
 
         bool success = false;
 
         if( ( this->ptrContext() != nullptr ) && ( belems != nullptr ) )
         {
             ptr_arg_t belems_arg( new arg_t( belems, this->ptrContext() ) );
-            this->doUpdateStoredBeamElementsArg( std::move( belems_arg ) );
+            this->doUpdateStoredClBeamElementsArg( std::move( belems_arg ) );
 
             success = (
                 ( this->ptrBeamElementsArg() != nullptr ) &&
@@ -588,25 +897,26 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobCl::doPrepareOutputStructuresOclImpl(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT pb,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belems,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT ptr_out_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::doPrepareOutputStructuresOclImpl(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pb,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belems,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT ptr_out_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        using _this_t = TrackJobCl;
+        using tjob_t = TrackJobCl;
 
-        using arg_t         = _this_t::cl_arg_t;
-        using ptr_arg_t     = _this_t::ptr_cl_arg_t;
-        using ptr_buffer_t  = _this_t::ptr_cl_buffer_t;
+        using arg_t         = tjob_t::cl_arg_t;
+        using ptr_arg_t     = tjob_t::ptr_cl_arg_t;
 
         bool success = true;
+
         ( void )until_turn_elem_by_elem;
+        ( void )belems;
 
         if( ptr_out_buffer != nullptr )
         {
             ptr_arg_t ptr( new arg_t( ptr_out_buffer, this->ptrContext() ) );
-            this->doUpdateStoredOutputArg( std::move( ptr ) );
+            this->doUpdateStoredClOutputArg( std::move( ptr ) );
 
             success &= ( this->ptrOutputBufferArg() != nullptr );
 
@@ -626,27 +936,32 @@ namespace SIXTRL_CXX_NAMESPACE
             if( ( success ) && ( this->ptrContext()   != nullptr ) &&
                 ( this->ptrElemByElemConfig() != nullptr ) )
             {
-                ptr_buffer_t ptr_buffer =
-                    this->ptrContext( )->create_elem_by_elem_config_arg();
+                ptr_arg_t ptr( new arg_t( this->ptrElemByElemConfigCBuffer(),
+                                          this->ptrContext() ) );
+
+                this->doUpdateStoredClElemByElemConfigArg( std::move( ptr ) );
 
-                this->doUpdateStoredClElemByElemConfigBuffer(
-                    std::move( ptr_buffer ) );
+                success = ( ( this->ptrElemByElemConfigCBuffer() != nullptr ) &&
+                    ( this->ptrElemByElemConfigBufferArg() != nullptr ) );
 
-                success = ( this->ptrClElemByElemConfigBuffer() != nullptr );
+                if( success )
+                {
+                    success = this->ptrElemByElemConfigBufferArg()->write(
+                        this->ptrElemByElemConfigCBuffer() );
+                }
 
                 if( success )
                 {
                     success = ( st::ARCH_STATUS_SUCCESS ==
-                        this->ptrContext()->push_elem_by_elem_config_arg(
-                            *this->ptrClElemByElemConfigBuffer(),
-                            *this->ptrElemByElemConfig() ) );
+                        this->ptrContext()->assign_elem_by_elem_config_buffer_arg(
+                            *this->ptrElemByElemConfigBufferArg() ) );
                 }
 
                 if( success )
                 {
                     success = ( st::ARCH_STATUS_SUCCESS ==
-                        this->ptrContext()->assign_elem_by_elem_config_arg(
-                            *this->ptrClElemByElemConfigBuffer() ) );
+                        this->ptrContext()->assign_elem_by_elem_config_index_arg(
+                            st_size_t{ 0 } ) );
                 }
             }
         }
@@ -654,11 +969,11 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobCl::doAssignOutputBufferToBeamMonitorsOclImp(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
-        _this_t::particle_index_t const min_turn_id,
-        _this_t::size_type const output_buffer_index_offset )
+    bool tjob_t::doAssignOutputBufferToBeamMonitorsOclImp(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT output_buffer,
+        tjob_t::particle_index_t const min_turn_id,
+        tjob_t::size_type const output_buffer_index_offset )
     {
         bool success = false;
 
@@ -695,10 +1010,10 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
-    bool TrackJobCl::doAssignOutputBufferToElemByElemConfigOclImpl(
-        _this_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_conf,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT out_buffer,
-        _this_t::size_type const output_buffer_index_offset )
+    bool tjob_t::doAssignOutputBufferToElemByElemConfigOclImpl(
+        tjob_t::elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_conf,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT out_buffer,
+        tjob_t::size_type const output_buffer_index_offset )
     {
         bool success = false;
 
@@ -706,7 +1021,7 @@ namespace SIXTRL_CXX_NAMESPACE
             ( this->context().hasSelectedNode() ) &&
             ( this->context().has_assign_elem_by_elem_output_kernel() ) &&
             ( this->hasElemByElemOutput() ) &&
-            ( this->ptrClElemByElemConfigBuffer() != nullptr ) &&
+            ( this->ptrElemByElemConfigBufferArg() != nullptr ) &&
             ( this->ptrElemByElemConfig() != nullptr ) &&
             ( this->ptrElemByElemConfig() == elem_by_elem_conf ) &&
             ( this->ptrBeamElementsArg() != nullptr ) &&
@@ -728,24 +1043,30 @@ namespace SIXTRL_CXX_NAMESPACE
 
             if( success )
             {
-                success = ( this->context().collect_elem_by_elem_config_arg(
-                    *this->ptrClElemByElemConfigBuffer(), *elem_by_elem_conf )
-                        == st::ARCH_STATUS_SUCCESS );
+                tjob_t::c_buffer_t* elem_by_elem_buffer =
+                    this->buffer_by_buffer_id(
+                        st::ARCH_ELEM_BY_ELEM_CONFIG_BUFFER_ID );
+
+                success = ( ( elem_by_elem_buffer != nullptr ) &&
+                            ( this->ptrElemByElemConfigBufferArg()->read(
+                                elem_by_elem_buffer ) ) );
             }
+
+            success = true;
         }
 
         return success;
     }
 
-    bool TrackJobCl::doResetOclImp(
-        _this_t::c_buffer_t* SIXTRL_RESTRICT pbuffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
-        _this_t::c_buffer_t* SIXTRL_RESTRICT out_buffer,
-        _size_t const until_turn_elem_by_elem )
+    bool tjob_t::doResetOclImp(
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT pbuffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT belem_buffer,
+        tjob_t::c_buffer_t* SIXTRL_RESTRICT out_buffer,
+        st_size_t const until_turn_elem_by_elem )
     {
-        using _this_t = st::TrackJobCl;
+        using tjob_t = st::TrackJobCl;
         using _base_t = st::TrackJobBase;
-        using output_buffer_flag_t = _this_t::output_buffer_flag_t;
+        using output_buffer_flag_t = tjob_t::output_buffer_flag_t;
 
         bool success = _base_t::doPrepareParticlesStructures( pbuffer );
 
@@ -845,6 +1166,200 @@ namespace SIXTRL_CXX_NAMESPACE
         return success;
     }
 
+    /* --------------------------------------------------------------------- */
+
+    tjob_t::status_t tjob_t::doAddStoredBufferOclImpl(
+        tjob_t::size_type const buffer_id )
+    {
+        tjob_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        tjob_t::buffer_store_t* ptr_stored_buffer =
+                this->doGetPtrBufferStore( buffer_id );
+
+        tjob_t::context_t* ptr_context = this->ptrContext();
+
+        if( ( ptr_context != nullptr ) && ( ptr_stored_buffer != nullptr ) &&
+            ( buffer_id >= st::ARCH_MIN_USER_DEFINED_BUFFER_ID ) )
+        {
+            tjob_t::size_type const stored_buffer_id =
+                buffer_id - st::ARCH_MIN_USER_DEFINED_BUFFER_ID;
+
+            tjob_t::size_type const nn = this->doGetStoredBufferSize();
+            tjob_t::size_type ii = this->m_stored_buffers_args.size();
+
+            for( ; ii < nn ; ++ii )
+            {
+                this->m_stored_buffers_args.emplace_back( nullptr );
+            }
+
+            SIXTRL_ASSERT( this->m_stored_buffers_args.size() >= nn );
+            SIXTRL_ASSERT( this->m_stored_buffers_args.size() >
+                           stored_buffer_id );
+
+            if( ptr_stored_buffer->ptr_cxx_buffer() != nullptr )
+            {
+                this->m_stored_buffers_args[ stored_buffer_id ].reset(
+                    new tjob_t::cl_arg_t( *ptr_stored_buffer->ptr_cxx_buffer(),
+                            ptr_context ) );
+
+                status = st::ARCH_STATUS_SUCCESS;
+
+            }
+            else if( ptr_stored_buffer->ptr_buffer() != nullptr )
+            {
+                this->m_stored_buffers_args[ stored_buffer_id ].reset(
+                    new tjob_t::cl_arg_t( ptr_stored_buffer->ptr_buffer(),
+                            ptr_context ) );
+
+                status = st::ARCH_STATUS_SUCCESS;
+            }
+        }
+
+        return status;
+    }
+
+    tjob_t::status_t tjob_t::doRemoveStoredBufferOclImpl(
+        tjob_t::size_type const buffer_id )
+    {
+        tjob_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        if( buffer_id >= st::ARCH_MIN_USER_DEFINED_BUFFER_ID )
+        {
+            tjob_t::size_type const stored_buffer_id =
+                buffer_id - st::ARCH_MIN_USER_DEFINED_BUFFER_ID;
+
+            SIXTRL_ASSERT( this->m_stored_buffers_args.size() >
+                           stored_buffer_id );
+
+            this->m_stored_buffers_args[ stored_buffer_id ].reset( nullptr );
+            status = st::ARCH_STATUS_SUCCESS;
+        }
+
+        return status;
+    }
+
+    tjob_t::status_t tjob_t::doPushStoredBufferOclImpl(
+        tjob_t::size_type const buffer_id )
+    {
+        tjob_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        tjob_t::buffer_store_t* ptr_stored_buffer =
+                this->doGetPtrBufferStore( buffer_id );
+
+        tjob_t::cl_arg_t* ptr_arg =
+            this->ptr_stored_buffer_argument( buffer_id );
+
+        if( ( ptr_stored_buffer != nullptr ) && ( ptr_arg != nullptr ) )
+        {
+            SIXTRL_ASSERT( ptr_arg->context() == this->ptrContext() );
+
+            if( ptr_stored_buffer->ptr_cxx_buffer() != nullptr )
+            {
+                status = ( ptr_arg->write(
+                    *ptr_stored_buffer->ptr_cxx_buffer() ) )
+                    ? st::ARCH_STATUS_SUCCESS
+                    : st::ARCH_STATUS_GENERAL_FAILURE;
+            }
+            else if( ptr_stored_buffer->ptr_buffer() != nullptr )
+            {
+                status = ( ptr_arg->write(
+                    ptr_stored_buffer->ptr_buffer() ) )
+                    ? st::ARCH_STATUS_SUCCESS
+                    : st::ARCH_STATUS_GENERAL_FAILURE;
+            }
+        }
+
+        return status;
+    }
+
+    tjob_t::status_t tjob_t::doCollectStoredBufferOclImpl(
+        tjob_t::size_type const buffer_id )
+    {
+        tjob_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        tjob_t::buffer_store_t* ptr_stored_buffer =
+                this->doGetPtrBufferStore( buffer_id );
+
+        tjob_t::cl_arg_t* ptr_arg =
+            this->ptr_stored_buffer_argument( buffer_id );
+
+        if( ( ptr_stored_buffer != nullptr ) && ( ptr_arg != nullptr ) )
+        {
+            SIXTRL_ASSERT( ptr_arg->context() == this->ptrContext() );
+
+            if( ptr_stored_buffer->ptr_cxx_buffer() != nullptr )
+            {
+                status = ( ptr_arg->read( *ptr_stored_buffer->ptr_cxx_buffer() ) )
+                    ? st::ARCH_STATUS_SUCCESS
+                    : st::ARCH_STATUS_GENERAL_FAILURE;
+            }
+            else if( ptr_stored_buffer->ptr_buffer() != nullptr )
+            {
+                status = ( ptr_arg->read( ptr_stored_buffer->ptr_buffer() ) )
+                    ? st::ARCH_STATUS_SUCCESS
+                    : st::ARCH_STATUS_GENERAL_FAILURE;
+            }
+        }
+
+        return status;
+    }
+
+    tjob_t::status_t tjob_t::doAddAssignAddressItemOclImpl(
+        tjob_t::assign_item_t const& SIXTRL_RESTRICT_REF assign_item,
+        tjob_t::size_type* SIXTRL_RESTRICT ptr_item_index )
+    {
+        ( void )assign_item;
+        ( void )ptr_item_index;
+
+        return st::ARCH_STATUS_SUCCESS;
+    }
+
+    tjob_t::status_t tjob_t::doPerformAddressAssignmentsOclImpl(
+        tjob_t::assign_item_key_t const& SIXTRL_RESTRICT_REF key )
+    {
+        using size_t = tjob_t::size_type;
+        using c_buffer_t = tjob_t::c_buffer_t;
+        using cl_arg_t = tjob_t::cl_arg_t;
+
+        tjob_t::status_t status = st::ARCH_STATUS_GENERAL_FAILURE;
+
+        size_t const dest_buffer_id = key.dest_buffer_id;
+        c_buffer_t* dest_buffer = this->buffer_by_buffer_id( dest_buffer_id );
+        cl_arg_t* dest_arg = this->ptr_argument_by_buffer_id( dest_buffer_id );
+
+        size_t const src_buffer_id = key.src_buffer_id;
+        c_buffer_t const* src_buffer =
+            this->buffer_by_buffer_id( src_buffer_id );
+        cl_arg_t* src_arg = this->ptr_argument_by_buffer_id( src_buffer_id );
+
+        c_buffer_t* assign_buffer =
+            this->doGetPtrAssignAddressItemsBuffer( key );
+
+        if( ( this->has_assign_items( dest_buffer_id, src_buffer_id ) ) &&
+            ( this->ptrContext() != nullptr ) && ( assign_buffer != nullptr ) &&
+            ( src_buffer != nullptr ) && ( dest_buffer != nullptr ) &&
+            ( src_arg != nullptr ) && ( src_arg->usesCObjectBuffer() ) &&
+            ( src_arg->ptrCObjectBuffer() == src_buffer ) &&
+            ( src_arg->context() == this->ptrContext() ) &&
+            ( dest_arg != nullptr ) && ( dest_arg->usesCObjectBuffer() ) &&
+            ( dest_arg->ptrCObjectBuffer() == dest_buffer ) &&
+            ( dest_arg->context() == this->ptrContext() ) )
+        {
+            status = st::ARCH_STATUS_SUCCESS;
+
+            if( ::NS(Buffer_get_num_of_objects)( assign_buffer ) > size_t{ 0 } )
+            {
+                cl_arg_t assign_items_arg( assign_buffer, this->ptrContext() );
+                status = this->ptrContext()->assign_addresses( assign_items_arg,
+                    *dest_arg, dest_buffer_id, *src_arg, src_buffer_id );
+            }
+        }
+
+        return status;
+    }
+
+    /* ********************************************************************* */
+
     void collect( TrackJobCl& SIXTRL_RESTRICT_REF job ) SIXTRL_NOEXCEPT
     {
         st::collect( job, job.collectFlags() );
@@ -853,7 +1368,7 @@ namespace SIXTRL_CXX_NAMESPACE
     void collect( TrackJobCl& SIXTRL_RESTRICT_REF job,
                   st::track_job_collect_flag_t const flags ) SIXTRL_NOEXCEPT
     {
-        if( ( TrackJobCl::IsCollectFlagSet(
+        if( ( tjob_t::IsCollectFlagSet(
                 flags, TRACK_JOB_IO_PARTICLES ) ) &&
             ( job.ptrParticlesArg() != nullptr ) &&
             ( job.ptrCParticlesBuffer() != nullptr ) )
@@ -861,7 +1376,7 @@ namespace SIXTRL_CXX_NAMESPACE
             job.particlesArg().read( job.ptrCParticlesBuffer() );
         }
 
-        if( ( TrackJobCl::IsCollectFlagSet(
+        if( ( tjob_t::IsCollectFlagSet(
                 flags, TRACK_JOB_IO_OUTPUT ) ) &&
             ( job.ptrOutputBufferArg() != nullptr ) &&
             ( job.ptrCOutputBuffer() != nullptr ) )
@@ -869,13 +1384,20 @@ namespace SIXTRL_CXX_NAMESPACE
             job.outputBufferArg().read( job.ptrCOutputBuffer() );
         }
 
-        if( ( TrackJobCl::IsCollectFlagSet(
+        if( ( tjob_t::IsCollectFlagSet(
                 flags, TRACK_JOB_IO_BEAM_ELEMENTS ) ) &&
             ( job.ptrBeamElementsArg() != nullptr ) &&
             ( job.ptrCBeamElementsBuffer() != nullptr ) )
         {
             job.beamElementsArg().read( job.ptrCBeamElementsBuffer() );
         }
+
+        if( ( tjob_t::IsCollectFlagSet(
+                flags, st::TRACK_JOB_IO_PARTICLES_ADDR ) ) &&
+            ( job.ptr_particles_addr_arg() != nullptr ) )
+        {
+            job.particles_addr_arg().read( job.ptrParticleAddressesBuffer() );
+        }
     }
 
     void push( TrackJobCl& SIXTRL_RESTRICT_REF job,
@@ -884,7 +1406,7 @@ namespace SIXTRL_CXX_NAMESPACE
         namespace st = SIXTRL_CXX_NAMESPACE;
         bool success = true;
 
-         if( ( TrackJobCl::IsCollectFlagSet(
+         if( ( tjob_t::IsCollectFlagSet(
                 flags, st::TRACK_JOB_IO_PARTICLES ) ) &&
             ( job.ptrParticlesArg() != nullptr ) &&
             ( job.ptrCParticlesBuffer() != nullptr ) )
@@ -892,7 +1414,7 @@ namespace SIXTRL_CXX_NAMESPACE
             success &= job.particlesArg().write( job.ptrCParticlesBuffer() );
         }
 
-        if( ( TrackJobCl::IsCollectFlagSet(
+        if( ( tjob_t::IsCollectFlagSet(
                 flags, st::TRACK_JOB_IO_OUTPUT ) ) &&
             ( job.ptrOutputBufferArg() != nullptr ) &&
             ( job.ptrCOutputBuffer() != nullptr ) )
@@ -900,7 +1422,7 @@ namespace SIXTRL_CXX_NAMESPACE
             success &= job.outputBufferArg().write( job.ptrCOutputBuffer() );
         }
 
-        if( ( TrackJobCl::IsCollectFlagSet(
+        if( ( tjob_t::IsCollectFlagSet(
                 flags, st::TRACK_JOB_IO_BEAM_ELEMENTS ) ) &&
             ( job.ptrBeamElementsArg() != nullptr ) &&
             ( job.ptrCBeamElementsBuffer() != nullptr ) )
@@ -909,14 +1431,22 @@ namespace SIXTRL_CXX_NAMESPACE
                 job.ptrCBeamElementsBuffer() );
         }
 
+        if( ( tjob_t::IsCollectFlagSet(
+                flags, st::TRACK_JOB_IO_PARTICLES_ADDR ) ) &&
+            ( job.ptr_particles_addr_arg() != nullptr ) )
+        {
+            success &= job.particles_addr_arg().write(
+                job.ptrParticleAddressesBuffer() );
+        }
+
         ( void )success;
     }
 
-    _this_t::track_status_t track(
+    tjob_t::track_status_t track(
         TrackJobCl& SIXTRL_RESTRICT_REF job,
-        _size_t const until_turn ) SIXTRL_NOEXCEPT
+        st_size_t const until_turn ) SIXTRL_NOEXCEPT
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        tjob_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
 
         SIXTRL_ASSERT( job.ptrContext() != nullptr );
         SIXTRL_ASSERT( job.ptrParticlesArg() != nullptr );
@@ -926,9 +1456,9 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_ASSERT( job.particleSetIndicesBegin() != nullptr );
         SIXTRL_ASSERT( job.numParticlesInSetsBegin() != nullptr );
 
-        _size_t const num_psets = job.numParticleSets();
+        st_size_t const num_psets = job.numParticleSets();
 
-        if( num_psets == _size_t{ 1 } )
+        if( num_psets == st_size_t{ 1 } )
         {
             SIXTRL_ASSERT( job.context().selected_particle_set() ==
                 *job.particleSetIndicesBegin() );
@@ -938,7 +1468,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             status = job.context().track_until( until_turn );
         }
-        else if( num_psets > _size_t{ 1 } )
+        else if( num_psets > st_size_t{ 1 } )
         {
             auto pset_it  = job.particleSetIndicesBegin();
             auto pset_end = job.particleSetIndicesEnd();
@@ -966,18 +1496,18 @@ namespace SIXTRL_CXX_NAMESPACE
                 st::ARCH_ILLEGAL_KERNEL_ID );
 
             job.context().assignKernelArgumentValue(
-                job.context().track_until_kernel_id(), _size_t{ 1 },
+                job.context().track_until_kernel_id(), st_size_t{ 1 },
                     saved_pset_idx_arg );
         }
 
         return status;
     }
 
-    _this_t::track_status_t trackElemByElem(
+    tjob_t::track_status_t trackElemByElem(
         TrackJobCl& SIXTRL_RESTRICT_REF job,
-        _size_t const until_turn ) SIXTRL_NOEXCEPT
+        st_size_t const until_turn ) SIXTRL_NOEXCEPT
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        tjob_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
 
         SIXTRL_ASSERT( job.ptrContext() != nullptr );
         SIXTRL_ASSERT( job.ptrParticlesArg() != nullptr );
@@ -986,15 +1516,15 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_ASSERT( job.ptrOutputBufferArg() != nullptr );
         SIXTRL_ASSERT( job.hasElemByElemOutput() );
         SIXTRL_ASSERT( job.ptrElemByElemConfig() != nullptr );
-        SIXTRL_ASSERT( job.ptrClElemByElemConfigBuffer() != nullptr );
+        SIXTRL_ASSERT( job.ptrElemByElemConfigBufferArg() != nullptr );
         SIXTRL_ASSERT( job.ptrContext()->hasSelectedNode() );
         SIXTRL_ASSERT( job.context().has_track_elem_by_elem_kernel() );
         SIXTRL_ASSERT( job.particleSetIndicesBegin() != nullptr );
         SIXTRL_ASSERT( job.numParticlesInSetsBegin() != nullptr );
 
-        _size_t const num_psets = job.numParticleSets();
+        st_size_t const num_psets = job.numParticleSets();
 
-        if( num_psets == _size_t{ 1 } )
+        if( num_psets == st_size_t{ 1 } )
         {
             SIXTRL_ASSERT( job.context().selected_particle_set() ==
                 *job.particleSetIndicesBegin() );
@@ -1004,7 +1534,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             status = job.context().track_elem_by_elem( until_turn );
         }
-        else if( num_psets > _size_t{ 1 } )
+        else if( num_psets > st_size_t{ 1 } )
         {
             auto pset_it  = job.particleSetIndicesBegin();
             auto pset_end = job.particleSetIndicesEnd();
@@ -1032,20 +1562,20 @@ namespace SIXTRL_CXX_NAMESPACE
                 st::ARCH_ILLEGAL_KERNEL_ID );
 
             job.context().assignKernelArgumentValue(
-                job.context().track_elem_by_elem_kernel_id(), _size_t{ 1 },
+                job.context().track_elem_by_elem_kernel_id(), st_size_t{ 1 },
                     saved_pset_idx_arg );
         }
 
         return status;
     }
 
-    _this_t::track_status_t trackLine(
+    tjob_t::track_status_t trackLine(
         TrackJobCl& SIXTRL_RESTRICT_REF job,
-        _size_t const line_begin_idx,
-        _size_t const line_end_idx,
+        st_size_t const line_begin_idx,
+        st_size_t const line_end_idx,
         bool const finish_turn ) SIXTRL_NOEXCEPT
     {
-        _this_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
+        tjob_t::track_status_t status = st::TRACK_STATUS_GENERAL_FAILURE;
 
         SIXTRL_ASSERT( job.ptrContext() != nullptr );
         SIXTRL_ASSERT( job.ptrParticlesArg() != nullptr );
@@ -1055,9 +1585,9 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_ASSERT( job.particleSetIndicesBegin() != nullptr );
         SIXTRL_ASSERT( job.numParticlesInSetsBegin() != nullptr );
 
-        _size_t const num_psets = job.numParticleSets();
+        st_size_t const num_psets = job.numParticleSets();
 
-        if( num_psets == _size_t{ 1 } )
+        if( num_psets == st_size_t{ 1 } )
         {
             SIXTRL_ASSERT( job.context().selected_particle_set() ==
                 *job.particleSetIndicesBegin() );
@@ -1068,7 +1598,7 @@ namespace SIXTRL_CXX_NAMESPACE
             status = job.context().track_line(
                 line_begin_idx, line_end_idx, finish_turn );
         }
-        else if( num_psets > _size_t{ 1 } )
+        else if( num_psets > st_size_t{ 1 } )
         {
             auto pset_it  = job.particleSetIndicesBegin();
             auto pset_end = job.particleSetIndicesEnd();
@@ -1096,7 +1626,7 @@ namespace SIXTRL_CXX_NAMESPACE
                 st::ARCH_ILLEGAL_KERNEL_ID );
 
             job.context().assignKernelArgumentValue(
-                job.context().track_line_kernel_id(), _size_t{ 1 },
+                job.context().track_line_kernel_id(), st_size_t{ 1 },
                     saved_pset_idx_arg );
         }
 
@@ -1107,7 +1637,7 @@ namespace SIXTRL_CXX_NAMESPACE
 NS(TrackJobCl)* NS(TrackJobCl_create)(
     const char *const SIXTRL_RESTRICT device_id_str )
 {
-    return new st::TrackJobCl( device_id_str, nullptr );
+    return new SIXTRL_CXX_NAMESPACE::TrackJobCl( device_id_str, nullptr );
 }
 
 NS(TrackJobCl)*
@@ -1115,7 +1645,7 @@ NS(TrackJobCl_create_from_config_str)(
     const char *const SIXTRL_RESTRICT device_id_str,
     const char *const SIXTRL_RESTRICT config_str )
 {
-    return new st::TrackJobCl( device_id_str, config_str );
+    return new SIXTRL_CXX_NAMESPACE::TrackJobCl( device_id_str, config_str );
 }
 
 NS(TrackJobCl)* NS(TrackJobCl_new)(
@@ -1123,7 +1653,7 @@ NS(TrackJobCl)* NS(TrackJobCl_new)(
     NS(Buffer)* SIXTRL_RESTRICT particles_buffer,
     NS(Buffer)* SIXTRL_RESTRICT beam_elements_buffer )
 {
-    return new st::TrackJobCl( device_id_str,
+    return new SIXTRL_CXX_NAMESPACE::TrackJobCl( device_id_str,
         particles_buffer, beam_elements_buffer );
 }
 
@@ -1134,10 +1664,10 @@ NS(TrackJobCl)* NS(TrackJobCl_new_with_output)(
     NS(Buffer)* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t) const until_turn_elem_by_elem )
 {
-    using _this_t = st::TrackJobCl;
-    return new _this_t( device_id_str, particles_buffer,
-        _this_t::DefaultNumParticleSetIndices(),
-        _this_t::DefaultParticleSetIndicesBegin(),
+    using tjob_t = SIXTRL_CXX_NAMESPACE::TrackJobCl;
+    return new tjob_t( device_id_str, particles_buffer,
+        tjob_t::DefaultNumParticleSetIndices(),
+        tjob_t::DefaultParticleSetIndicesBegin(),
         beam_elements_buffer, output_buffer, until_turn_elem_by_elem );
 }
 
@@ -1151,7 +1681,7 @@ NS(TrackJobCl)* NS(TrackJobCl_new_detailed)(
     NS(buffer_size_t) const until_turn_elem_by_elem,
     const char *const SIXTRL_RESTRICT config_str )
 {
-    return new st::TrackJobCl( device_id_str,
+    return new SIXTRL_CXX_NAMESPACE::TrackJobCl( device_id_str,
         particles_buffer, num_particle_sets, particle_set_indices_begin,
         beam_elements_buffer, output_buffer, until_turn_elem_by_elem,
         config_str );
@@ -1165,9 +1695,8 @@ SIXTRL_EXTERN bool NS(TrackJobCl_reset)(
 {
     if( job != nullptr )
     {
-        st::_size_t const
+        SIXTRL_CXX_NAMESPACE::st_size_t const
             until_turn_elem_by_elem = job->numElemByElemTurns();
-
         return job->reset( particles_buffer, beam_elements_buffer,
                            output_buffer, until_turn_elem_by_elem );
     }
@@ -1215,7 +1744,7 @@ NS(track_status_t) NS(TrackJobCl_track_until_turn)(
     NS(buffer_size_t) const until_turn )
 {
     SIXTRL_ASSERT( track_job != nullptr );
-    return st::track( *track_job, until_turn );
+    return SIXTRL_CXX_NAMESPACE::track( *track_job, until_turn );
 }
 
 NS(track_status_t) NS(TrackJobCl_track_elem_by_elem)(
@@ -1223,7 +1752,7 @@ NS(track_status_t) NS(TrackJobCl_track_elem_by_elem)(
     NS(buffer_size_t) const until_turn )
 {
     SIXTRL_ASSERT( track_job != nullptr );
-    return st::trackElemByElem( *track_job, until_turn );
+    return SIXTRL_CXX_NAMESPACE::trackElemByElem( *track_job, until_turn );
 }
 
 NS(track_status_t) NS(TrackJobCl_track_line)(
@@ -1233,7 +1762,7 @@ NS(track_status_t) NS(TrackJobCl_track_line)(
     bool const finish_turn )
 {
     SIXTRL_ASSERT( track_job != nullptr );
-    return st::trackLine(
+    return SIXTRL_CXX_NAMESPACE::trackLine(
         *track_job, line_begin_idx, line_end_idx, finish_turn );
 }
 
@@ -1309,6 +1838,25 @@ NS(TrackJobCl_get_const_output_buffer_arg)(
     return ( job != nullptr ) ? job->ptrOutputBufferArg() : nullptr;
 }
 
+bool NS(TrackJobCl_has_particles_addr_buffer_arg)(
+    const ::NS(TrackJobCl) *const SIXTRL_RESTRICT job )
+{
+    return ( ( job != nullptr ) &&
+             ( job->ptrParticlesAddrBufferArg() != nullptr ) );
+}
+
+::NS(ClArgument)* NS(TrackJobCl_get_particles_addr_buffer_arg)(
+    ::NS(TrackJobCl)* SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr ) ? job->ptrParticlesAddrBufferArg() : nullptr;
+}
+
+::NS(ClArgument) const* NS(TrackJobCl_get_const_particles_addr_arg)(
+    const ::NS(TrackJobCl) *const SIXTRL_RESTRICT job )
+{
+    return ( job != nullptr ) ? job->ptrParticlesAddrBufferArg() : nullptr;
+}
+
 ::NS(arch_status_t) NS(TrackJobCl_update_beam_elements_region)(
     ::NS(TrackJobCl)* SIXTRL_RESTRICT track_job,
     ::NS(arch_size_t) const offset, NS(arch_size_t) const length,
@@ -1331,4 +1879,48 @@ ::NS(arch_status_t) NS(TrackJobCl_update_beam_elements_regions)(
         : ::NS(ARCH_STATUS_GENERAL_FAILURE);
 }
 
-/* end: /opencl/internal/track_job_cl.cpp */
+std::uintptr_t NS(TrackJobCl_get_opencl_context_addr)(
+    const NS(TrackJobCl) *const SIXTRL_RESTRICT track_job ) SIXTRL_NOEXCEPT
+{
+    return ( track_job != nullptr )
+        ? track_job->opencl_context_addr() : std::uintptr_t{ 0 };
+}
+
+std::uintptr_t NS(TrackJobCl_get_opencl_queue_addr)(
+    const NS(TrackJobCl) *const SIXTRL_RESTRICT track_job ) SIXTRL_NOEXCEPT
+{
+    return ( track_job != nullptr )
+        ? track_job->opencl_queue_addr() : std::uintptr_t{ 0 };
+}
+
+/* ------------------------------------------------------------------------- */
+
+::NS(ClArgument) const* NS(TrackJobCl_const_argument_by_buffer_id)(
+    const ::NS(TrackJobCl) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->ptr_const_argument_by_buffer_id( buffer_id ) : nullptr;
+}
+
+::NS(ClArgument)* NS(TrackJobCl_argument_by_buffer_id)(
+    ::NS(TrackJobCl)* SIXTRL_RESTRICT job, ::NS(buffer_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->ptr_argument_by_buffer_id( buffer_id ) : nullptr;
+}
+
+::NS(ClArgument) const* NS(TrackJobCl_const_stored_buffer_argument)(
+    const ::NS(TrackJobCl) *const SIXTRL_RESTRICT job,
+    ::NS(buffer_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->ptr_const_stored_buffer_argument( buffer_id ) : nullptr;
+}
+
+::NS(ClArgument)* NS(TrackJobCl_stored_buffer_argument)(
+    ::NS(TrackJobCl)* SIXTRL_RESTRICT job, ::NS(buffer_size_t) const buffer_id )
+{
+    return ( job != nullptr )
+        ? job->ptr_stored_buffer_argument( buffer_id ) : nullptr;
+}
diff --git a/sixtracklib/opencl/kernels/assign_address_item.cl b/sixtracklib/opencl/kernels/assign_address_item.cl
new file mode 100644
index 00000000..b1ef20f9
--- /dev/null
+++ b/sixtracklib/opencl/kernels/assign_address_item.cl
@@ -0,0 +1,31 @@
+#ifndef SIXTRACKLIB_OPENCL_KERNELS_PROCESS_ASSIGN_ADDRESS_ITEMS_CL_H__
+#define SIXTRACKLIB_OPENCL_KERNELS_PROCESS_ASSIGN_ADDRESS_ITEMS_CL_H__
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/opencl/internal/default_compile_options.h"
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/buffer/assign_address_item_kernel_impl.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+__kernel void NS(AssignAddressItem_process_managed_buffer_opencl)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT assign_buffer,
+    NS(buffer_size_t) const assign_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer,
+    NS(buffer_size_t) const dest_slot_size,
+    NS(arch_size_t) const dest_buffer_id,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT src_buffer,
+    NS(buffer_size_t) const src_slot_size,
+    NS(arch_size_t) const src_buffer_id )
+{
+    NS(buffer_size_t) const start_idx = ( NS(buffer_size_t) )get_global_id( 0 );
+    NS(buffer_size_t) const stride = ( NS(buffer_size_t) )get_global_size( 0 );
+
+    NS(AssignAddressItem_perform_address_assignment_kernel_impl)(
+        assign_buffer, assign_slot_size, start_idx, stride,
+        dest_buffer, dest_slot_size, dest_buffer_id,
+        src_buffer,  src_slot_size,  src_buffer_id );
+}
+
+#endif /* SIXTRACKLIB_OPENCL_KERNELS_PROCESS_ASSIGN_ADDRESS_ITEMS_CL_H__ */
+/* end: /opencl/kernels/assign_address_item.cl */
diff --git a/sixtracklib/opencl/kernels/be_monitors_assign_out_buffer.cl b/sixtracklib/opencl/kernels/be_monitors_assign_out_buffer.cl
index 5549528e..73ad88ef 100644
--- a/sixtracklib/opencl/kernels/be_monitors_assign_out_buffer.cl
+++ b/sixtracklib/opencl/kernels/be_monitors_assign_out_buffer.cl
@@ -26,14 +26,13 @@ __kernel void NS(BeamMonitor_assign_out_buffer_from_offset_opencl)(
 }
 
 __kernel void NS(BeamMonitor_clear_all_line_obj_opencl)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT belements_buf,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
     SIXTRL_UINT64_T const slot_size )
 {
     typedef NS(buffer_size_t) buf_size_t;
-
     if( ( buf_size_t )get_global_id( 0 ) == ( buf_size_t )0u )
     {
-        NS(BeamMonitor_clear_all_on_managed_buffer)( belements_buf, slot_size );
+        NS(BeamMonitor_reset_all_in_managed_buffer)( buffer_begin, slot_size );
     }
 }
 
diff --git a/sixtracklib/opencl/kernels/be_monitors_assign_out_buffer_debug.cl b/sixtracklib/opencl/kernels/be_monitors_assign_out_buffer_debug.cl
index a7344cd3..6fd310db 100644
--- a/sixtracklib/opencl/kernels/be_monitors_assign_out_buffer_debug.cl
+++ b/sixtracklib/opencl/kernels/be_monitors_assign_out_buffer_debug.cl
@@ -34,20 +34,14 @@ __kernel void NS(BeamMonitor_assign_out_buffer_from_offset_debug_opencl)(
 }
 
 __kernel void NS(BeamMonitor_clear_all_line_obj_debug_opencl)(
-    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT beam_elements_buf,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT buffer_begin,
     SIXTRL_UINT64_T const slot_size,
     SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flag )
 {
     if( ( size_t )get_global_id( 0 ) == ( size_t )0u )
     {
         NS(arch_debugging_t) flags = SIXTRL_ARCH_DEBUGGING_GENERAL_FAILURE;
-        NS(BeamMonitor_clear_all_on_managed_buffer_debug)(
-            beam_elements_buf, slot_size, &flags );
-
-        if( ptr_status_flag != SIXTRL_NULLPTR )
-        {
-            *ptr_status_flag = flags;
-        }
+        NS(BeamMonitor_reset_all_in_managed_buffer)( buffer_begin, slot_size );
     }
 }
 
diff --git a/sixtracklib/opencl/kernels/elem_by_elem_assign_out_buffer.cl b/sixtracklib/opencl/kernels/elem_by_elem_assign_out_buffer.cl
index 4711afea..1574856a 100644
--- a/sixtracklib/opencl/kernels/elem_by_elem_assign_out_buffer.cl
+++ b/sixtracklib/opencl/kernels/elem_by_elem_assign_out_buffer.cl
@@ -14,8 +14,8 @@
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 __kernel void NS(ElemByElem_assign_out_buffer_from_offset_opencl)(
-     SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT out_buffer,
     SIXTRL_UINT64_T const out_buffer_index_offset,
     SIXTRL_UINT64_T const slot_size )
@@ -25,7 +25,8 @@ __kernel void NS(ElemByElem_assign_out_buffer_from_offset_opencl)(
     if( ( buf_size_t )get_global_id( 0 ) == ( buf_size_t )0u )
     {
         NS(ElemByElemConfig_assign_output_buffer_kernel_impl)(
-            config, out_buffer, out_buffer_index_offset, slot_size );
+            config_buffer, elem_by_elem_config_index, out_buffer,
+                out_buffer_index_offset, slot_size );
     }
 }
 
diff --git a/sixtracklib/opencl/kernels/elem_by_elem_assign_out_buffer_debug.cl b/sixtracklib/opencl/kernels/elem_by_elem_assign_out_buffer_debug.cl
index f0467fa7..bf26a32e 100644
--- a/sixtracklib/opencl/kernels/elem_by_elem_assign_out_buffer_debug.cl
+++ b/sixtracklib/opencl/kernels/elem_by_elem_assign_out_buffer_debug.cl
@@ -13,11 +13,11 @@
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 __kernel void NS(ElemByElem_assign_out_buffer_from_offset_debug_opencl)(
-     SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-        SIXTRL_RESTRICT elem_by_elem_config,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT out_buffer,
-    SIXTRL_UINT64_T const out_buffer_index_offset,
-    SIXTRL_UINT64_T const slot_size,
+    NS(buffer_size_t) const out_buffer_index_offset,
+    NS(buffer_size_t) const slot_size,
     SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flag )
 {
     typedef NS(buffer_size_t) buf_size_t;
@@ -26,8 +26,8 @@ __kernel void NS(ElemByElem_assign_out_buffer_from_offset_debug_opencl)(
     {
         NS(arch_debugging_t) dbg = SIXTRL_ARCH_DEBUGGING_GENERAL_FAILURE;
         NS(ElemByElemConfig_assign_output_buffer_debug_kernel_impl)(
-            elem_by_elem_config, out_buffer, out_buffer_index_offset,
-                slot_size, &dbg );
+            config_buffer, elem_by_elem_config_index, out_buffer,
+                out_buffer_index_offset, slot_size, &dbg );
 
         if( ptr_status_flag != SIXTRL_NULLPTR ) *ptr_status_flag = dbg;
     }
diff --git a/sixtracklib/opencl/kernels/fetch_particles_addr.cl b/sixtracklib/opencl/kernels/fetch_particles_addr.cl
new file mode 100644
index 00000000..874c312f
--- /dev/null
+++ b/sixtracklib/opencl/kernels/fetch_particles_addr.cl
@@ -0,0 +1,36 @@
+#ifndef SIXTRACKLIB_OPENCL_KERNELS_FETCH_PARTICLES_ADDR_CL__
+#define SIXTRACKLIB_OPENCL_KERNELS_FETCH_PARTICLES_ADDR_CL__
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/opencl/internal/default_compile_options.h"
+
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/buffer/managed_buffer_minimal.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/particles/definitions.h"
+    #include "sixtracklib/common/particles/particles_addr.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+__kernel void NS(Particles_buffer_store_all_addresses_opencl)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer_begin,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT paddr_buffer_begin,
+    SIXTRL_UINT64_T const slot_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+
+    buf_size_t const num_objects = NS(ManagedBuffer_get_num_objects)(
+        pbuffer_begin, slot_size );
+
+    buf_size_t ii = ( buf_size_t )get_global_id( 0 );
+    buf_size_t const stride = ( buf_size_t )get_global_size( 0 );
+
+    for( ; ii < num_objects ; ii += stride )
+    {
+        NS(Particles_managed_buffer_store_addresses)(
+            paddr_buffer_begin, pbuffer_begin, ii, slot_size );
+    }
+}
+
+#endif /* SIXTRACKLIB_OPENCL_KERNELS_FETCH_PARTICLES_ADDR_CL__ */
+
diff --git a/sixtracklib/opencl/kernels/process_assign_address_items.cl b/sixtracklib/opencl/kernels/process_assign_address_items.cl
new file mode 100644
index 00000000..dc0dba93
--- /dev/null
+++ b/sixtracklib/opencl/kernels/process_assign_address_items.cl
@@ -0,0 +1,17 @@
+#ifndef SIXTRACKLIB_OPENCL_KERNELS_PROCESS_ASSIGN_ADDRESS_ITEMS_CL_H__
+#define SIXTRACKLIB_OPENCL_KERNELS_PROCESS_ASSIGN_ADDRESS_ITEMS_CL_H__
+
+
+__kernel void NS(AssignAddressItem_process_managed_buffer_opencl)(
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT map_buffer_begin,
+    NS(buffer_size_t) const start_item_idx, NS(buffer_size_t) const item_idx_stride,
+    NS(buffer_size_t) const map_buffer_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT dest_buffer_begin,
+    SIXTRL_UINT64_T const dest_slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT src_buffer_begin,
+    NS(buffer_size_t) const src_slot_size )
+{
+
+}
+
+#endif /* SIXTRACKLIB_OPENCL_KERNELS_PROCESS_ASSIGN_ADDRESS_ITEMS_CL_H__ */
diff --git a/sixtracklib/opencl/kernels/track_particles.cl b/sixtracklib/opencl/kernels/track_particles.cl
index 286698df..1251bbb7 100644
--- a/sixtracklib/opencl/kernels/track_particles.cl
+++ b/sixtracklib/opencl/kernels/track_particles.cl
@@ -26,11 +26,12 @@ __kernel void NS(Track_particles_until_turn_opencl)(
 
 __kernel void NS(Track_particles_elem_by_elem_opencl)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    SIXTRL_UINT64_T const part_set_index,
+    NS(buffer_size_t) const part_set_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
-    SIXTRL_INT64_T const until_turn, SIXTRL_UINT64_T const slot_size )
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
+    NS(particle_num_elements_t) const until_turn,
+    NS(buffer_size_t) const slot_size )
 {
     typedef NS(particle_num_elements_t) nelements_t;
     nelements_t const part_idx = ( nelements_t )get_global_id( 0 );
@@ -38,7 +39,7 @@ __kernel void NS(Track_particles_elem_by_elem_opencl)(
 
     NS(Track_particles_elem_by_elem_until_turn_kernel_impl)( pbuffer,
         part_set_index, part_idx, part_idx_stride, belem_buffer,
-            elem_by_elem_config, until_turn, slot_size );
+            config_buffer, elem_by_elem_config_index, until_turn, slot_size );
 }
 
 __kernel void NS(Track_particles_line_opencl)(
diff --git a/sixtracklib/opencl/kernels/track_particles_debug.cl b/sixtracklib/opencl/kernels/track_particles_debug.cl
index 3ae04ff1..df3a00e3 100644
--- a/sixtracklib/opencl/kernels/track_particles_debug.cl
+++ b/sixtracklib/opencl/kernels/track_particles_debug.cl
@@ -37,11 +37,12 @@ __kernel void NS(Track_particles_until_turn_debug_opencl)(
 
 __kernel void NS(Track_particles_elem_by_elem_debug_opencl)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    SIXTRL_UINT64_T const part_set_index,
+    NS(buffer_size_t) const part_set_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
-    SIXTRL_INT64_T const until_turn, SIXTRL_UINT64_T const slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
+    NS(particle_num_elements_t) const until_turn,
+    NS(buffer_size_t) const slot_size,
     SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags )
 {
     typedef NS(particle_num_elements_t) nelements_t;
@@ -52,7 +53,8 @@ __kernel void NS(Track_particles_elem_by_elem_debug_opencl)(
 
     NS(Track_particles_elem_by_elem_until_turn_debug_kernel_impl)(
         pbuffer, part_set_index, part_idx, part_idx_stride, belem_buffer,
-            elem_by_elem_config, until_turn, slot_size, &status_flags );
+            config_buffer, elem_by_elem_config_index, until_turn, slot_size,
+                &status_flags );
 
     NS(OpenCl1x_collect_status_flag_value)( ptr_status_flags, status_flags );
 }
diff --git a/sixtracklib/opencl/kernels/track_particles_optimized_priv_particles.cl b/sixtracklib/opencl/kernels/track_particles_optimized_priv_particles.cl
index 3c47fb4d..6b33f7e5 100644
--- a/sixtracklib/opencl/kernels/track_particles_optimized_priv_particles.cl
+++ b/sixtracklib/opencl/kernels/track_particles_optimized_priv_particles.cl
@@ -28,11 +28,12 @@ __kernel void NS(Track_particles_until_turn_opt_pp_opencl)(
 
 __kernel void NS(Track_particles_elem_by_elem_opt_pp_opencl)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    SIXTRL_UINT64_T const part_set_index,
+    NS(buffer_size_t) const part_set_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
-    SIXTRL_INT64_T const until_turn, SIXTRL_UINT64_T const slot_size )
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
+    NS(particle_num_elements_t) const until_turn,
+    NS(buffer_size_t) const slot_size )
 {
     typedef NS(particle_num_elements_t) nelements_t;
     nelements_t const part_idx = ( nelements_t )get_global_id( 0 );
@@ -40,7 +41,7 @@ __kernel void NS(Track_particles_elem_by_elem_opt_pp_opencl)(
 
     NS(Track_particles_elem_by_elem_until_turn_opt_kernel_impl)( pbuffer,
         part_set_index, part_idx, part_idx_stride, belem_buffer,
-            elem_by_elem_config, until_turn, slot_size );
+            config_buffer, elem_by_elem_config_index, until_turn, slot_size );
 }
 
 __kernel void NS(Track_particles_line_opt_pp_opencl)(
diff --git a/sixtracklib/opencl/kernels/track_particles_optimized_priv_particles_debug.cl b/sixtracklib/opencl/kernels/track_particles_optimized_priv_particles_debug.cl
index 9a542d3e..ba60b2e4 100644
--- a/sixtracklib/opencl/kernels/track_particles_optimized_priv_particles_debug.cl
+++ b/sixtracklib/opencl/kernels/track_particles_optimized_priv_particles_debug.cl
@@ -37,11 +37,12 @@ __kernel void NS(Track_particles_until_turn_opt_pp_debug_opencl)(
 
 __kernel void NS(Track_particles_elem_by_elem_opt_pp_debug_opencl)(
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char* SIXTRL_RESTRICT pbuffer,
-    SIXTRL_UINT64_T const pset_index,
+    NS(buffer_size_t) const pset_index,
     SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT belem_buffer,
-    SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC const NS(ElemByElemConfig) *const
-        SIXTRL_RESTRICT elem_by_elem_config,
-    SIXTRL_INT64_T const until_turn, SIXTRL_UINT64_T const slot_size,
+    SIXTRL_BUFFER_DATAPTR_DEC unsigned char const* SIXTRL_RESTRICT config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
+    NS(particle_num_elements_t) const until_turn,
+    NS(buffer_size_t) const slot_size,
     SIXTRL_DATAPTR_DEC NS(arch_debugging_t)* SIXTRL_RESTRICT ptr_status_flags )
 {
     typedef NS(particle_num_elements_t) nelements_t;
@@ -52,7 +53,8 @@ __kernel void NS(Track_particles_elem_by_elem_opt_pp_debug_opencl)(
 
     NS(Track_particles_elem_by_elem_until_turn_debug_opt_kernel_impl)(
         pbuffer, pset_index, part_idx, part_idx_stride, belem_buffer,
-            elem_by_elem_config, until_turn, slot_size, &status_flags );
+            config_buffer, elem_by_elem_config_index, until_turn, slot_size,
+                &status_flags );
 
     NS(OpenCl1x_collect_status_flag_value)( ptr_status_flags, status_flags );
 }
diff --git a/sixtracklib/opencl/track_job_cl.h b/sixtracklib/opencl/track_job_cl.h
index f58799c9..b69a8b1f 100644
--- a/sixtracklib/opencl/track_job_cl.h
+++ b/sixtracklib/opencl/track_job_cl.h
@@ -16,6 +16,7 @@
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/buffer.h"
     #include "sixtracklib/common/particles.h"
+    #include "sixtracklib/common/particles/particles_addr.h"
     #include "sixtracklib/common/internal/track_job_base.h"
     #include "sixtracklib/common/track_job.h"
 
@@ -114,22 +115,22 @@ namespace SIXTRL_CXX_NAMESPACE
             buffer_t& SIXTRL_RESTRICT_REF beam_elements_buffer,
             buffer_t* SIXTRL_RESTRICT ptr_output_buffer = nullptr,
             size_type const until_turn_elem_by_elem = size_type{ 0 },
-            std::string SIXTRL_RESTRICT_REF config_str = std::string{} );
+            std::string const& SIXTRL_RESTRICT_REF config_str = std::string{} );
 
-        SIXTRL_HOST_FN TrackJobCl( TrackJobCl const& other ) = default;
+        SIXTRL_HOST_FN TrackJobCl( TrackJobCl const& other ) = delete;
         SIXTRL_HOST_FN TrackJobCl( TrackJobCl&& other ) = default;
 
-        SIXTRL_HOST_FN TrackJobCl& operator=( TrackJobCl const& rhs ) = default;
+        SIXTRL_HOST_FN TrackJobCl& operator=( TrackJobCl const& rhs ) = delete;
         SIXTRL_HOST_FN TrackJobCl& operator=( TrackJobCl&& rhs ) = default;
 
         SIXTRL_HOST_FN virtual ~TrackJobCl() SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN size_type totalNumParticles() const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN cl_context_t& context() SIXTRL_RESTRICT;
-        SIXTRL_HOST_FN cl_context_t const& context() const SIXTRL_RESTRICT;
-        SIXTRL_HOST_FN NS(ClContext)* ptrContext() SIXTRL_RESTRICT;
-        SIXTRL_HOST_FN NS(ClContext) const* ptrContext() const SIXTRL_RESTRICT;
+        SIXTRL_HOST_FN cl_context_t& context() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_context_t const& context() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN NS(ClContext)* ptrContext() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN NS(ClContext) const* ptrContext() const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN cl_arg_t& particlesArg() SIXTRL_NOEXCEPT;
         SIXTRL_HOST_FN cl_arg_t const& particlesArg() const SIXTRL_NOEXCEPT;
@@ -148,17 +149,29 @@ namespace SIXTRL_CXX_NAMESPACE
         SIXTRL_HOST_FN cl_arg_t* ptrOutputBufferArg() SIXTRL_NOEXCEPT;
         SIXTRL_HOST_FN cl_arg_t const* ptrOutputBufferArg() const SIXTRL_NOEXCEPT;
 
+        SIXTRL_HOST_FN cl_arg_t const&
+            particlesAddrBufferArg() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t& particlesAddrBufferArg() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t const*
+            ptrParticlesAddrBufferArg() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t* ptrParticlesAddrBufferArg() SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cl_arg_t const&
+        elemByelemConfigBufferArg() const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN cl_buffer_t const&
-        clElemByElemConfigBuffer() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t& elemByelemConfigBufferArg() SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN cl_buffer_t& clElemByElemConfigBuffer() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t const*
+        ptrElemByElemConfigBufferArg() const SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN cl_buffer_t const*
-        ptrClElemByElemConfigBuffer() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t*
+        ptrElemByElemConfigBufferArg() SIXTRL_NOEXCEPT;
 
-        SIXTRL_HOST_FN cl_buffer_t*
-        ptrClElemByElemConfigBuffer() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t& particles_addr_arg() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t const& particles_addr_arg() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t* ptr_particles_addr_arg() SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN cl_arg_t const*
+            ptr_particles_addr_arg() const SIXTRL_NOEXCEPT;
 
         SIXTRL_HOST_FN status_t updateBeamElementsRegion(
             size_type const offset, size_type const length,
@@ -170,6 +183,37 @@ namespace SIXTRL_CXX_NAMESPACE
             size_type const* SIXTRL_RESTRICT lengths,
             void const* SIXTRL_RESTRICT const* SIXTRL_RESTRICT new_values );
 
+        SIXTRL_HOST_FN std::uintptr_t opencl_context_addr() const SIXTRL_NOEXCEPT;
+        SIXTRL_HOST_FN std::uintptr_t opencl_queue_addr() const SIXTRL_NOEXCEPT;
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN cl_arg_t const* ptr_const_argument_by_buffer_id(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cl_arg_t* ptr_argument_by_buffer_id(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cl_arg_t const& argument_by_buffer_id(
+            size_type const buffer_id ) const;
+
+        SIXTRL_HOST_FN cl_arg_t& argument_by_buffer_id(
+            size_type const buffer_id );
+
+        /* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- */
+
+        SIXTRL_HOST_FN cl_arg_t const* ptr_const_stored_buffer_argument(
+            size_type const buffer_id ) const SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cl_arg_t* ptr_stored_buffer_argument(
+            size_type const buffer_id ) SIXTRL_NOEXCEPT;
+
+        SIXTRL_HOST_FN cl_arg_t const& stored_buffer_argument(
+            size_type const buffer_id ) const;
+
+        SIXTRL_HOST_FN cl_arg_t& stored_buffer_argument(
+            size_type const buffer_id );
+
         protected:
 
         using ptr_cl_context_t = std::unique_ptr< cl_context_t >;
@@ -183,67 +227,99 @@ namespace SIXTRL_CXX_NAMESPACE
             char const* SIXTRL_RESTRICT device_id_str,
             const char *const SIXTRL_RESTRICT ptr_config_str );
 
-        SIXTRL_HOST_FN virtual bool doPrepareParticlesStructures(
+        SIXTRL_HOST_FN status_t doFetchParticleAddresses() override;
+
+        SIXTRL_HOST_FN bool doPrepareParticlesStructures(
             c_buffer_t* SIXTRL_RESTRICT ptr_particles_buffer ) override;
 
-        SIXTRL_HOST_FN virtual bool doPrepareBeamElementsStructures(
+        SIXTRL_HOST_FN bool doPrepareBeamElementsStructures(
             c_buffer_t* SIXTRL_RESTRICT ptr_beam_elem_buffer ) override;
 
-        SIXTRL_HOST_FN virtual bool doPrepareOutputStructures(
+        SIXTRL_HOST_FN bool doPrepareOutputStructures(
             c_buffer_t* SIXTRL_RESTRICT particles_buffer,
             c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
             c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
             size_type const until_turn_elem_by_elem ) override;
 
-        SIXTRL_HOST_FN virtual bool doAssignOutputBufferToBeamMonitors(
+        SIXTRL_HOST_FN bool doAssignOutputBufferToBeamMonitors(
             c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
             c_buffer_t* SIXTRL_RESTRICT output_buffer,
             particle_index_t const min_turn_id,
             size_type const output_buffer_index_offset ) override;
 
-        SIXTRL_HOST_FN virtual bool doAssignOutputBufferToElemByElemConfig(
+        SIXTRL_HOST_FN bool doAssignOutputBufferToElemByElemConfig(
             elem_by_elem_config_t* SIXTRL_RESTRICT elem_by_elem_config,
             c_buffer_t* SIXTRL_RESTRICT output_buffer,
             size_type const output_buffer_offset_index ) override;
 
-        SIXTRL_HOST_FN virtual bool doReset(
+        SIXTRL_HOST_FN bool doReset(
             c_buffer_t* SIXTRL_RESTRICT particles_buffer,
             c_buffer_t* SIXTRL_RESTRICT beam_elem_buffer,
             c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
             size_type const until_turn_elem_by_elem ) override;
 
-        SIXTRL_HOST_FN virtual track_status_t doTrackUntilTurn(
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN size_type doAddStoredBuffer(
+            buffer_store_t&& assigned_buffer_handle ) override;
+
+        SIXTRL_HOST_FN status_t doRemoveStoredBuffer(
+            size_type const buffer_id ) override;
+
+        SIXTRL_HOST_FN status_t doPushStoredBuffer(
+            size_type const buffer_id ) override;
+
+        SIXTRL_HOST_FN status_t doCollectStoredBuffer(
+            size_type const buffer_id ) override;
+
+        SIXTRL_HOST_FN status_t doPerformAddressAssignments(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF
+                assign_item_key ) override;
+
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN track_status_t doTrackUntilTurn(
             size_type const until_turn ) override;
 
-        SIXTRL_HOST_FN virtual track_status_t doTrackElemByElem(
+        SIXTRL_HOST_FN track_status_t doTrackElemByElem(
             size_type const until_turn ) override;
 
-        SIXTRL_HOST_FN virtual track_status_t doTrackLine(
+        SIXTRL_HOST_FN track_status_t doTrackLine(
             size_type const line_begin_idx, size_type const line_end_idx,
-            bool const finish_turn ) override;
+                bool const finish_turn ) override;
 
-        SIXTRL_HOST_FN virtual void doCollect(
-            collect_flag_t const flags ) override;
+        SIXTRL_HOST_FN void doCollect( collect_flag_t const flags ) override;
 
-        SIXTRL_HOST_FN virtual void doPush( push_flag_t const flags ) override;
+        SIXTRL_HOST_FN void doPush( push_flag_t const flags ) override;
 
-        SIXTRL_HOST_FN virtual void doParseConfigStr(
+        SIXTRL_HOST_FN void doParseConfigStr(
             const char *const SIXTRL_RESTRICT config_str ) override;
 
+//         SIXTRL_HOST_FN status_t doRebuildAssignItemsBufferArg() override;
+
         SIXTRL_HOST_FN void doUpdateStoredContext(
             ptr_cl_context_t&& context );
 
-        SIXTRL_HOST_FN void doUpdateStoredParticlesArg(
+        SIXTRL_HOST_FN void doUpdateStoredClParticlesArg(
             ptr_cl_arg_t&& particle_arg );
 
-        SIXTRL_HOST_FN void doUpdateStoredBeamElementsArg(
+        SIXTRL_HOST_FN void doUpdateStoredClBeamElementsArg(
             ptr_cl_arg_t&& beam_elements_arg );
 
-        SIXTRL_HOST_FN void doUpdateStoredOutputArg(
+        SIXTRL_HOST_FN void doUpdateStoredClOutputArg(
             ptr_cl_arg_t&& output_arg );
 
-        SIXTRL_HOST_FN void doUpdateStoredClElemByElemConfigBuffer(
-            ptr_cl_buffer_t&& cl_elem_by_elem_config_buffer );
+        SIXTRL_HOST_FN void doUpdateStoredClElemByElemConfigArg(
+            ptr_cl_arg_t&& cl_elem_by_elem_config_arg );
+
+        SIXTRL_HOST_FN void doUpdateStoredClAssignItemsArg(
+            ptr_cl_arg_t&& cl_assign_items_buffer_arg );
+
+        SIXTRL_HOST_FN void doUpdateStoredClParticlesAddrArg(
+            ptr_cl_arg_t&& particles_addr_arg );
+
+        SIXTRL_HOST_FN status_t do_update_stored_particles_addr_arg(
+            ptr_cl_arg_t&& particles_addr_arg );
 
         private:
 
@@ -294,13 +370,36 @@ namespace SIXTRL_CXX_NAMESPACE
             c_buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
             size_type const until_turn_elem_by_elem );
 
-        std::vector< size_type > m_num_particles_in_pset;
+        /* ----------------------------------------------------------------- */
+
+        SIXTRL_HOST_FN status_t doAddStoredBufferOclImpl(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t doRemoveStoredBufferOclImpl(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t doPushStoredBufferOclImpl(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t doCollectStoredBufferOclImpl(
+            size_type const buffer_id );
+
+        SIXTRL_HOST_FN status_t doAddAssignAddressItemOclImpl(
+            assign_item_t const& SIXTRL_RESTRICT_REF assign_item,
+            size_type* SIXTRL_RESTRICT ptr_item_index );
+
+        SIXTRL_HOST_FN status_t doPerformAddressAssignmentsOclImpl(
+            assign_item_key_t const& SIXTRL_RESTRICT_REF assign_item_key );
+
+        std::vector< size_type >    m_num_particles_in_pset;
+        std::vector< ptr_cl_arg_t > m_stored_buffers_args;
 
         ptr_cl_context_t m_ptr_context;
         ptr_cl_arg_t     m_ptr_particles_buffer_arg;
         ptr_cl_arg_t     m_ptr_beam_elements_buffer_arg;
         ptr_cl_arg_t     m_ptr_output_buffer_arg;
-        ptr_cl_buffer_t  m_ptr_cl_elem_by_elem_config_buffer;
+        ptr_cl_arg_t     m_ptr_particles_addr_buffer_arg;
+        ptr_cl_arg_t     m_ptr_elem_by_elem_config_arg;
 
         size_type        m_total_num_particles;
     };
@@ -468,6 +567,17 @@ SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument) const*
 NS(TrackJobCl_get_const_output_buffer_arg)(
     const NS(TrackJobCl) *const SIXTRL_RESTRICT track_job );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN bool NS(TrackJobCl_has_particles_addr_buffer_arg)(
+    const NS(TrackJobCl) *const SIXTRL_RESTRICT track_job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument)*
+NS(TrackJobCl_get_particles_addr_buffer_arg)(
+    NS(TrackJobCl)* SIXTRL_RESTRICT track_job );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument) const*
+NS(TrackJobCl_get_const_particles_addr_arg)(
+    const NS(TrackJobCl) *const SIXTRL_RESTRICT track_job );
+
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(TrackJobCl_update_beam_elements_region)(
     NS(TrackJobCl)* SIXTRL_RESTRICT track_job,
@@ -481,6 +591,36 @@ NS(TrackJobCl_update_beam_elements_regions)(
     NS(arch_size_t) const* offsets, NS(arch_size_t) const* lengths,
     void const* SIXTRL_RESTRICT const* SIXTRL_RESTRICT new_value );
 
+SIXTRL_EXTERN SIXTRL_HOST_FN uintptr_t
+NS(TrackJobCl_get_opencl_context_addr)( const NS(TrackJobCl) *const
+    SIXTRL_RESTRICT track_job ) SIXTRL_NOEXCEPT;
+
+SIXTRL_EXTERN SIXTRL_HOST_FN uintptr_t
+NS(TrackJobCl_get_opencl_queue_addr)( const NS(TrackJobCl) *const
+    SIXTRL_RESTRICT track_job ) SIXTRL_NOEXCEPT;
+
+/* ----------------------------------------------------------------- */
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument) const*
+NS(TrackJobCl_const_argument_by_buffer_id)(
+    const NS(TrackJobCl) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument)*
+NS(TrackJobCl_argument_by_buffer_id)(
+    NS(TrackJobCl)* SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument) const*
+NS(TrackJobCl_const_stored_buffer_argument)(
+    const NS(TrackJobCl) *const SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN NS(ClArgument)*
+NS(TrackJobCl_stored_buffer_argument)(
+    NS(TrackJobCl)* SIXTRL_RESTRICT job,
+    NS(buffer_size_t) const buffer_id );
+
 #if defined( __cplusplus ) && !defined( _GPUCODE )
 }
 #endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
@@ -507,9 +647,9 @@ namespace SIXTRL_CXX_NAMESPACE
         TrackJobCl::size_type const until_turn_elem_by_elem,
         const char *const SIXTRL_RESTRICT config_str )
     {
-        using _base_t = SIXTRL_CXX_NAMESPACE::TrackJobBase;
-        using _size_t = _base_t::size_type;
-        using flags_t = ::NS(output_buffer_flag_t);
+        using base_t    = SIXTRL_CXX_NAMESPACE::TrackJobBase;
+        using st_size_t = base_t::size_type;
+        using flags_t   = ::NS(output_buffer_flag_t);
 
         bool success  = false;
         this->doSetRequiresCollectFlag( true );
@@ -517,7 +657,7 @@ namespace SIXTRL_CXX_NAMESPACE
         if( config_str != nullptr )
         {
             this->doSetConfigStr( config_str );
-            _base_t::doParseConfigStr( this->ptrConfigStr() );
+            base_t::doParseConfigStr( this->ptrConfigStr() );
             this->doParseConfigStrOclImpl( this->ptrConfigStr() );
         }
 
@@ -535,9 +675,9 @@ namespace SIXTRL_CXX_NAMESPACE
         }
         else if( success )
         {
-            _size_t const fallback_pset_indices[] =
+            st_size_t const fallback_pset_indices[] =
             {
-                _size_t{ 0 }, _size_t{ 0 }
+                st_size_t{ 0 }, st_size_t{ 0 }
             };
 
             this->doSetParticleSetIndices( &fallback_pset_indices[ 0 ],
@@ -657,7 +797,8 @@ namespace SIXTRL_CXX_NAMESPACE
         m_ptr_particles_buffer_arg( nullptr ),
         m_ptr_beam_elements_buffer_arg( nullptr ),
         m_ptr_output_buffer_arg( nullptr ),
-        m_ptr_cl_elem_by_elem_config_buffer( nullptr),
+        m_ptr_particles_addr_buffer_arg( nullptr ),
+        m_ptr_elem_by_elem_config_arg( nullptr),
         m_total_num_particles( TrackJobBase::size_type{ 0 } )
     {
         this->doInitTrackJobCl( device_id_str, particles_buffer, pset_begin,
@@ -673,14 +814,15 @@ namespace SIXTRL_CXX_NAMESPACE
         TrackJobCl::buffer_t& SIXTRL_RESTRICT_REF belements_buffer,
         TrackJobCl::buffer_t* SIXTRL_RESTRICT ptr_output_buffer,
         TrackJobCl::size_type const until_turn_elem_by_elem,
-        std::string SIXTRL_RESTRICT_REF config_str ) :
+        std::string const& SIXTRL_RESTRICT_REF config_str ) :
         TrackJobBase( SIXTRL_CXX_NAMESPACE::TRACK_JOB_CL_STR,
                       SIXTRL_CXX_NAMESPACE::TRACK_JOB_CL_ID ),
         m_ptr_context( nullptr ),
         m_ptr_particles_buffer_arg( nullptr ),
         m_ptr_beam_elements_buffer_arg( nullptr ),
         m_ptr_output_buffer_arg( nullptr ),
-        m_ptr_cl_elem_by_elem_config_buffer( nullptr),
+        m_ptr_particles_addr_buffer_arg( nullptr ),
+        m_ptr_elem_by_elem_config_arg( nullptr),
         m_total_num_particles( TrackJobBase::size_type{ 0 } )
     {
         TrackJobCl::c_buffer_t* out_buffer = ( ptr_output_buffer != nullptr )
@@ -705,7 +847,4 @@ namespace SIXTRL_CXX_NAMESPACE
 }
 
 #endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
-
 #endif /* SIXTRL_SIXTRACKLIB_OPENCL_TRACK_CL_JOB_H__ */
-
-/* end: sixtracklib/opencl/track_job.h */
diff --git a/sixtracklib/sixtracklib.h b/sixtracklib/sixtracklib.h
index 412e023c..45003b67 100644
--- a/sixtracklib/sixtracklib.h
+++ b/sixtracklib/sixtracklib.h
@@ -44,6 +44,8 @@
 #include "sixtracklib/common/be_limit/track.h"
 #include "sixtracklib/common/be_dipedge/be_dipedge.h"
 #include "sixtracklib/common/be_dipedge/track.h"
+#include "sixtracklib/common/be_tricub/be_tricub.h"
+#include "sixtracklib/common/be_tricub/track.h"
 #include "sixtracklib/common/be_rfmultipole/be_rfmultipole.h"
 #include "sixtracklib/common/be_rfmultipole/track.h"
 #include "sixtracklib/common/context/compute_arch.h"
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index ad2ead95..f99ba863 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -3,6 +3,8 @@
 message( STATUS "---- processing tests/python/CMakeLists.txt" )
 
 if( SIXTRACKL_ENABLE_PROGRAMM_TESTS )
+    set( PYTHON_TESTS_WORKDIR ${CMAKE_SOURCE_DIR}/python )
+
     add_subdirectory( beam_elements )
 
     if( SIXTRACKL_ENABLE_CUDA )
@@ -16,34 +18,56 @@ if( SIXTRACKL_ENABLE_PROGRAMM_TESTS )
     # -------------------------------------------------------------------------
     # test_cbuffer_st_buffer:
 
-    add_test( NAME Python_CBufferStBufferTests
+    add_test( NAME Python_Common_Buffer_StBuffer
         COMMAND ${PYTHON_EXECUTABLE}
                 ${CMAKE_CURRENT_SOURCE_DIR}/test_cbuffer_st_buffer.py
-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python )
+        WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
 
     # -------------------------------------------------------------------------
     # test_output_buffer:
 
-    add_test( NAME Python_OutputBufferTests
+    add_test( NAME Python_Common_Output_OutputBuffer
         COMMAND ${PYTHON_EXECUTABLE}
                 ${CMAKE_CURRENT_SOURCE_DIR}/test_output_buffer.py
-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python )
+        WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
 
     # -------------------------------------------------------------------------
     # test_track_job_setup:
 
-    add_test( NAME Python_TrackJobSetupTests
+    add_test( NAME Python_CPU_TrackJob_Setup
         COMMAND ${PYTHON_EXECUTABLE}
                 ${CMAKE_CURRENT_SOURCE_DIR}/test_track_job_setup.py
-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python )
+        WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
 
     # -------------------------------------------------------------------------
     # test_track_job_cpu:
 
-    add_test( NAME Python_TrackJobCpuTests
+    add_test( NAME Python_CPU_TrackJob_Init
         COMMAND ${PYTHON_EXECUTABLE}
                 ${CMAKE_CURRENT_SOURCE_DIR}/test_track_job_cpu.py
-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python )
+        WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
+
+    # -------------------------------------------------------------------------
+    # test_track_job_cpu_stored_buffer:
+
+    add_test( NAME Python_CPU_TrackJob_StoredBuffer
+        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_track_job_cpu_stored_buffer.py
+        WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
+
+    # -------------------------------------------------------------------------
+    # test_track_job_cpu_assign_address_items:
+
+    add_test( NAME Python_CPU_TrackJob_AssignAddressItems
+        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_track_job_cpu_assign_address_items.py
+        WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
+
+
+    # -------------------------------------------------------------------------
+    # test_qgauss:
+
+    add_test( NAME Python_Math_QGauss
+        COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_qgauss.py
+        WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
 
 endif()
 
diff --git a/tests/python/beam_elements/CMakeLists.txt b/tests/python/beam_elements/CMakeLists.txt
index a8742624..50402083 100644
--- a/tests/python/beam_elements/CMakeLists.txt
+++ b/tests/python/beam_elements/CMakeLists.txt
@@ -1,8 +1,7 @@
-# -------------------------------------------------------------------------
-# test_multipole:
-
-add_test( NAME Python_BeamElementsMultiPole
-    COMMAND ${PYTHON_EXECUTABLE}
-            ${CMAKE_CURRENT_SOURCE_DIR}/test_multipole.py
+add_test( NAME Python_BeamElements_MultiPole
+    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_multipole.py
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python )
 
+add_test( NAME Python_BeamElements_TriCub
+    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_tricub.py
+    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python )
diff --git a/tests/python/beam_elements/test_tricub.py b/tests/python/beam_elements/test_tricub.py
new file mode 100644
index 00000000..e7859e94
--- /dev/null
+++ b/tests/python/beam_elements/test_tricub.py
@@ -0,0 +1,118 @@
+import sixtracklib as st
+import sixtracklib_test as sttest
+import pysixtrack
+import cobjects
+import numpy as np
+import pickle
+import os
+
+
+def test_kicks(
+    cmp_file_name="precomputed_kicks.pickle",
+    device_str=None,
+    abs_tol=1e-15,
+    rel_tol=0.0,
+):
+
+    ####### load file with correct kicks #######
+    path_to_testdir = sttest.config.PATH_TO_TESTDATA_DIR
+    assert path_to_testdir is not None
+    assert os.path.exists(path_to_testdir)
+    assert os.path.isdir(path_to_testdir)
+
+    path_to_cmp_file = os.path.join(path_to_testdir, "tricub", cmp_file_name)
+    assert os.path.exists(path_to_cmp_file)
+
+    with open(path_to_cmp_file, "rb") as fp:
+        n_part, prng_seed, kicks = pickle.load(fp)
+
+    assert n_part > 0
+    assert prng_seed is not None
+    assert kicks is not None
+
+    np.random.seed(int(prng_seed))
+
+    lattice = st.Elements()
+    tc_index = lattice.cbuffer.n_objects
+    tc = st.TriCub(cbuffer=lattice.cbuffer)
+    tc.length = 1.0
+
+    particles_set = st.ParticlesSet()
+    particles = particles_set.Particles(num_particles=n_part)
+
+    nx = 5
+    ny = 7
+    nz = 9
+    A = np.random.rand(nx, ny, nz, 8) * 1.0e-3
+    dx = 0.001
+    dy = 0.002
+    dz = 0.003
+    x0 = -(nx // 2) * dx
+    y0 = -(ny // 2) * dy
+    z0 = -(nz // 2) * dz
+
+    test_x = x0 + (nx - 2) * dx * np.random.rand(n_part)
+    test_y = y0 + (ny - 2) * dy * np.random.rand(n_part)
+    test_z = z0 + (nz - 2) * dz * np.random.rand(n_part)
+
+    for i_part in range(n_part):
+        part = pysixtrack.Particles()
+        part.x = test_x[i_part]
+        part.y = test_y[i_part]
+        part.tau = test_z[i_part]
+
+        part.partid = i_part
+        part.state = 1
+        part.elemid = 0
+        part.turn = 0
+        particles.from_pysixtrack(part, i_part)
+
+    job = st.TrackJob(lattice, particles_set, device=device_str)
+
+    tricub_data_buffer = cobjects.CBuffer()
+    tc_data_index = tricub_data_buffer.n_objects
+    tc_data = st.TriCubData(cbuffer=tricub_data_buffer, nx=nx, ny=ny, nz=nz)
+
+    tc_data.x0 = x0
+    tc_data.y0 = y0
+    tc_data.z0 = z0
+    tc_data.dx = dx
+    tc_data.dy = dy
+    tc_data.dz = dz
+    tc_data.mirror_x = 0
+    tc_data.mirror_y = 0
+    tc_data.mirror_z = 0
+    scale = [1.0, dx, dy, dz, dx * dy, dx * dz, dy * dz, (dx * dy) * dz]
+    for ii in range(nx):
+        for jj in range(ny):
+            for kk in range(nz):
+                for ll in range(8):
+                    tc_data.table_addr[ll + 8 * (ii + nx * (jj + ny * kk))] = (
+                        A[ii, jj, kk, ll] * scale[ll]
+                    )
+
+    tricub_data_buffer_id = job.add_stored_buffer(cbuffer=tricub_data_buffer)
+
+    st.TriCub_buffer_create_assign_address_item(
+        job, tc_index, tricub_data_buffer_id, tc_data_index
+    )
+
+    job.commit_address_assignments()
+    job.assign_all_addresses()
+    job.track_until(1)
+    job.collect()
+
+    assert np.allclose(kicks[:, 0], particles.px, rel_tol, abs_tol)
+    assert np.allclose(kicks[:, 1], particles.py, rel_tol, abs_tol)
+    assert np.allclose(kicks[:, 2], particles.ptau, rel_tol, abs_tol)
+
+
+if __name__ == "__main__":
+    if st.config.TRACK_TRICUB == "enabled":
+        test_kicks(
+            cmp_file_name="precomputed_kicks.pickle",
+            rel_tol=1e-12,
+            abs_tol=1e-13,
+        )
+    else:
+        print("Disabled TriCub beam-element -> skip test")
diff --git a/tests/python/cuda/CMakeLists.txt b/tests/python/cuda/CMakeLists.txt
index 8c6e6a84..f57f8976 100644
--- a/tests/python/cuda/CMakeLists.txt
+++ b/tests/python/cuda/CMakeLists.txt
@@ -8,7 +8,7 @@ if( SIXTRACKL_ENABLE_PROGRAMM_TESTS )
     # ==========================================================================
     # test_cuda_controller.py:
 
-    add_test( NAME Python_Cuda_CudaControllerTests
+    add_test( NAME Python_Cuda_CudaController
               COMMAND ${PYTHON_EXECUTABLE} ${PRG_DIR}/test_cuda_controller.py
               WORKING_DIRECTORY ${WORK_DIR} )
 
@@ -16,14 +16,14 @@ if( SIXTRACKL_ENABLE_PROGRAMM_TESTS )
     # ==========================================================================
     # test_cuda_argument.py:
 
-    add_test( NAME Python_Cuda_CudaArgumentTests
+    add_test( NAME Python_Cuda_CudaArgument
               COMMAND ${PYTHON_EXECUTABLE} ${PRG_DIR}/test_cuda_argument.py
               WORKING_DIRECTORY ${WORK_DIR} )
 
     # ==========================================================================
     # test_track_job_track_line.py:
 
-    add_test( NAME Python_Cuda_CudaTrackJobTrackLineTests
+    add_test( NAME Python_Cuda_CudaTrackJob_TrackLine
               COMMAND ${PYTHON_EXECUTABLE} ${PRG_DIR}/test_track_job_track_line.py
               WORKING_DIRECTORY ${WORK_DIR} )
 
@@ -31,18 +31,29 @@ if( SIXTRACKL_ENABLE_PROGRAMM_TESTS )
     # ==========================================================================
     # test_track_job_fetch_particle_addr.py:
 
-    add_test( NAME Python_Cuda_CudaTrackJobFetchParticleAddrTests
+    add_test( NAME Python_Cuda_CudaTrackJob_FetchParticleAddr
               COMMAND ${PYTHON_EXECUTABLE} ${PRG_DIR}/test_track_job_fetch_particle_addr.py
               WORKING_DIRECTORY ${WORK_DIR} )
 
     # ==========================================================================
     # test_track_job_collect_and_push_cuda.py:
 
-    add_test( NAME Python_Cuda_CudaTrackJobCollectPushTests
+    add_test( NAME Python_Cuda_CudaTrackJob_CollectPush
               COMMAND ${PYTHON_EXECUTABLE}
                       ${PRG_DIR}/test_track_job_collect_and_push_cuda.py
               WORKING_DIRECTORY ${WORK_DIR} )
 
-endif()
+    # ==========================================================================
+    # test_track_job_collect_and_push_cuda.py:
 
-#end: tests/python/cuda/CMakeLists.txt
+    add_test( NAME Python_Cuda_CudaTrackJobThreadsPerBlockTests
+              COMMAND ${PYTHON_EXECUTABLE}
+                      ${PRG_DIR}/test_track_job_threads_per_block.py
+              WORKING_DIRECTORY ${WORK_DIR} )
+
+    # ==========================================================================
+    # test_cuda_assign_address_item.py:
+    add_test( NAME Python_Cuda_CudaTrackJob_AssignAddressItem
+              COMMAND ${PYTHON_EXECUTABLE} ${PRG_DIR}/test_cuda_assign_address_items.py
+              WORKING_DIRECTORY ${WORK_DIR} )
+endif()
diff --git a/tests/python/cuda/test_cuda_argument.py b/tests/python/cuda/test_cuda_argument.py
index 9ca9434f..8ed0dd07 100644
--- a/tests/python/cuda/test_cuda_argument.py
+++ b/tests/python/cuda/test_cuda_argument.py
@@ -4,7 +4,7 @@
 import sys
 import os
 from cobjects import CBuffer
-import sixtracklib as pyst
+import sixtracklib as st
 import ctypes as ct
 
 from sixtracklib.stcommon import st_NODE_UNDEFINED_INDEX, \
@@ -28,9 +28,18 @@
 from sixtracklib_test.generic_obj import GenericObj
 
 if __name__ == '__main__':
-    if not pyst.supports('cuda'):
+    if not st.supports('cuda'):
         raise SystemExit("cuda support required for this test")
 
+    try:
+        num_nodes = st.CudaController.NUM_AVAILABLE_NODES()
+    except RuntimeError as e:
+        num_nodes = 0
+
+    if num_nodes <= 0:
+        print("No CUDA nodes available -> skip test")
+        sys.exit(0)
+
     num_d_values = 10
     num_e_values = 10
     num_obj = 10
@@ -41,26 +50,26 @@
                          c=[1.0, 2.0, 3.0, 4.0],
                          num_d=num_d_values, num_e=num_e_values)
 
-    c_obj_buffer = pyst.Buffer(cbuffer=obj_buffer)
+    c_obj_buffer = st.Buffer(cbuffer=obj_buffer)
     assert c_obj_buffer.pointer != st_NullBuffer
     assert c_obj_buffer.slot_size > 0
     assert c_obj_buffer.capacity > 0
     assert c_obj_buffer.size > 0 and c_obj_buffer.size <= c_obj_buffer.capacity
     assert c_obj_buffer.num_objects == obj_buffer.n_objects
 
-    c_cpy_buffer = pyst.Buffer(size=c_obj_buffer.capacity)
+    c_cpy_buffer = st.Buffer(size=c_obj_buffer.capacity)
     assert c_cpy_buffer.pointer != st_NullBuffer
     assert c_cpy_buffer.slot_size > 0
     assert c_cpy_buffer.capacity > 0
     assert c_cpy_buffer.size <= c_obj_buffer.size
     assert c_cpy_buffer.capacity >= c_obj_buffer.capacity
 
-    ctrl = pyst.CudaController()
+    ctrl = st.CudaController()
     assert ctrl.num_nodes > 0
     assert ctrl.has_selected_node
     assert ctrl.selected_node_index != st_NODE_UNDEFINED_INDEX.value
 
-    arg1 = pyst.CudaArgument(ctrl=ctrl)
+    arg1 = st.CudaArgument(ctrl=ctrl)
     assert arg1.controller.pointer != st_NullCudaController
     assert arg1.controller.pointer == ctrl.pointer
     assert not arg1.has_argument_buffer
@@ -116,7 +125,7 @@
 
     # --------------------------------------------------------------------------
 
-    arg2 = pyst.CudaArgument(buffer=c_obj_buffer, ctrl=ctrl)
+    arg2 = st.CudaArgument(buffer=c_obj_buffer, ctrl=ctrl)
 
     assert arg2.has_argument_buffer
     assert arg2.has_cuda_arg_buffer
@@ -158,7 +167,7 @@
     assert config_orig.min_particle_id != config_copy.min_particle_id
     assert config_orig.max_particle_id != config_copy.max_particle_id
 
-    arg3 = pyst.CudaArgument(ptr_raw_arg_begin=ct.byref(config_orig),
+    arg3 = st.CudaArgument(ptr_raw_arg_begin=ct.byref(config_orig),
                              raw_arg_size=ct.sizeof(config_orig), ctrl=ctrl)
 
     assert arg3.has_argument_buffer
@@ -198,7 +207,7 @@
 
     # --------------------------------------------------------------------------
 
-    arg4 = pyst.CudaArgument(ctrl=ctrl)
+    arg4 = st.CudaArgument(ctrl=ctrl)
     assert arg4.controller.pointer != st_NullCudaController
     assert arg4.controller.pointer == ctrl.pointer
     assert not arg4.has_argument_buffer
diff --git a/tests/python/cuda/test_cuda_assign_address_items.py b/tests/python/cuda/test_cuda_assign_address_items.py
new file mode 100644
index 00000000..922b08dc
--- /dev/null
+++ b/tests/python/cuda/test_cuda_assign_address_items.py
@@ -0,0 +1,244 @@
+import cobjects
+from cobjects import CBuffer, CObject
+import sixtracklib as st
+from sixtracklib.stcommon import st_ARCH_BEAM_ELEMENTS_BUFFER_ID, \
+    st_NullAssignAddressItem, st_AssignAddressItem_p, \
+    st_buffer_size_t, st_object_type_id_t, st_arch_status_t, st_arch_size_t, \
+    st_ARCH_STATUS_SUCCESS, st_ARCH_ILLEGAL_BUFFER_ID, \
+    st_AssignAddressItem_are_equal, st_AssignAddressItem_are_not_equal, \
+    st_AssignAddressItem_compare_less
+
+import sixtracklib_test as testlib
+from sixtracklib_test.stcommon import st_AssignAddressItem_print_out
+
+if __name__ == '__main__':
+    lattice = st.Elements()
+    lattice.Drift(length=0.0)
+    lattice.Drift(length=0.1)
+    lattice.Drift(length=0.2)
+    bm0_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+    lattice.Drift(length=0.3)
+    lattice.Drift(length=0.4)
+    lattice.Drift(length=0.5)
+    bm1_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+    lattice.Drift(length=0.3)
+    lattice.Drift(length=0.4)
+    lattice.Drift(length=0.5)
+    bm2_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+
+    assert lattice.cbuffer.get_object(bm0_index).out_address == 0
+    assert lattice.cbuffer.get_object(bm1_index).out_address == 0
+    assert lattice.cbuffer.get_object(bm2_index).out_address == 0
+
+    pset = st.ParticlesSet()
+    pset.Particles(num_particles=100)
+
+    output_buffer = st.ParticlesSet()
+    out_buffer0_index = output_buffer.cbuffer.n_objects
+    output_buffer.Particles(num_particles=100)
+    out_buffer1_index = output_buffer.cbuffer.n_objects
+    output_buffer.Particles(num_particles=512)
+
+    job = st.CudaTrackJob(lattice, pset)
+
+    # hand the output_buffer over to the track job:
+    output_buffer_id = job.add_stored_buffer(cbuffer=output_buffer)
+    assert output_buffer_id != st_ARCH_ILLEGAL_BUFFER_ID.value
+
+    # use the predefined lattice_buffer_id value to refer to the
+    # beam elements buffer
+    lattice_buffer_id = st_ARCH_BEAM_ELEMENTS_BUFFER_ID.value
+
+    # use the _type_id attributes of beam monitors and particle sets to
+    # refer to these object types:
+    particle_set_type_id = output_buffer.cbuffer.get_object(
+        out_buffer0_index)._typeid
+    beam_monitor_type_id = lattice.cbuffer.get_object(bm0_index)._typeid
+
+    assert job.total_num_assign_items == 0
+    assert not job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 0
+
+    # --------------------------------------------------------------------------
+    # Create the assignment item for out_buffer0 -> bm0
+
+    out0_to_bm0_addr_assign_item = st.AssignAddressItem(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm0_index,
+        dest_pointer_offset=24,  # Magic number, offset of out_address from begin
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0  # We assign the starting address of the particle set
+    )
+
+    assert out0_to_bm0_addr_assign_item.dest_elem_type_id == \
+        beam_monitor_type_id
+    assert out0_to_bm0_addr_assign_item.dest_buffer_id == lattice_buffer_id
+    assert out0_to_bm0_addr_assign_item.dest_elem_index == bm0_index
+    assert out0_to_bm0_addr_assign_item.dest_pointer_offset == 24
+
+    assert out0_to_bm0_addr_assign_item.src_elem_type_id == \
+        particle_set_type_id
+    assert out0_to_bm0_addr_assign_item.src_buffer_id == output_buffer_id
+    assert out0_to_bm0_addr_assign_item.src_elem_index == out_buffer0_index
+    assert out0_to_bm0_addr_assign_item.src_pointer_offset == 0
+
+    # perform the assignment of assign_out0_to_bm0_item
+
+    ptr_item_0_to_0 = job.add_assign_address_item(
+        out0_to_bm0_addr_assign_item)
+
+    assert ptr_item_0_to_0 != st_NullAssignAddressItem
+    assert job.total_num_assign_items == 1
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 1
+    assert job.has_assign_item(item=ptr_item_0_to_0)
+    assert job.has_assign_item(item=out0_to_bm0_addr_assign_item)
+    assert job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm0_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm1_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer1_index,
+        src_pointer_offset=0)
+
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    item_0_to_0_index = job.index_of_assign_address_item(item=ptr_item_0_to_0)
+    assert not(item_0_to_0_index is None)
+
+    # --------------------------------------------------------------------------
+    # Create the assignment item for out_buffer1 -> bm1 at the time of
+    # passing it on to the track job:
+
+    ptr_item_1_to_1 = job.add_assign_address_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm1_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer1_index,
+        src_pointer_offset=0)
+
+    assert ptr_item_1_to_1 != st_NullAssignAddressItem
+    assert job.total_num_assign_items == 2
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 2
+    assert job.has_assign_item(item=ptr_item_1_to_1)
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    item_1_to_1_index = job.index_of_assign_address_item(ptr_item_1_to_1)
+    assert not(item_1_to_1_index is None)
+
+    # Create the assignment item for out_buffer0 -> bm2
+
+    # Create a copy of out0_to_bm0_addr_assign_item on the same buffer
+    # TODO: figure out a better way to do this?
+    out0_to_bm2_addr_assign_item = st.AssignAddressItem(
+        **{k != '_buffer' and k or 'cbuffer':
+                getattr(out0_to_bm0_addr_assign_item, k) for k in [*[f[0]
+                for f in st.AssignAddressItem.get_fields()], '_buffer']})
+
+    # out0_to_bm2_addr_assign_item is actually the same as
+    # out0_to_bm0_addr_assign_item  -> if we try to add this item unmodified,
+    # we should again effectively get ptr_item0_to_0:
+
+    ptr_item_0_to_2 = job.add_assign_address_item(
+        out0_to_bm2_addr_assign_item)
+
+    assert ptr_item_0_to_2 != st_NullAssignAddressItem
+    assert st_AssignAddressItem_are_equal(
+        ptr_item_0_to_2,
+        job.ptr_assign_address_item(
+            dest_buffer_id=lattice_buffer_id,
+            src_buffer_id=output_buffer_id,
+            index=item_0_to_0_index))
+
+    assert job.total_num_assign_items == 2
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 2
+    assert job.has_assign_item(item=ptr_item_0_to_2)
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_pointer_offset=0)
+
+    # modify out0_to_bm2_addr_assign_item to target the third beam monitor
+    # located at bm2_index:
+    out0_to_bm2_addr_assign_item.dest_elem_index = bm2_index
+
+    # try again to add -> this time it should result in a new item:
+    ptr_item_0_to_2 = job.add_assign_address_item(
+        out0_to_bm2_addr_assign_item)
+
+    assert ptr_item_0_to_2 != st_NullAssignAddressItem
+    assert st_AssignAddressItem_are_not_equal(
+        ptr_item_0_to_2,
+        job.ptr_assign_address_item(
+            dest_buffer_id=lattice_buffer_id,
+            src_buffer_id=output_buffer_id,
+            index=item_0_to_0_index))
+    assert job.total_num_assign_items == 3
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 3
+    assert job.has_assign_item(item=out0_to_bm2_addr_assign_item)
+    assert job.has_assign_item(item=ptr_item_0_to_2)
+    assert job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    # --------------------------------------------------------------------------
+    # finish assembly of assign items:
+    job.commit_address_assignments()
+
+    # perform assignment of address items:
+    job.assign_all_addresses()
+
+    job.collect_beam_elements()
+    assert lattice.cbuffer.get_object(bm0_index).out_address != 0
+    assert lattice.cbuffer.get_object(bm1_index).out_address != 0
+    assert lattice.cbuffer.get_object(bm2_index).out_address != 0
diff --git a/tests/python/cuda/test_cuda_controller.py b/tests/python/cuda/test_cuda_controller.py
index ff2028d5..f47dbdd4 100644
--- a/tests/python/cuda/test_cuda_controller.py
+++ b/tests/python/cuda/test_cuda_controller.py
@@ -4,16 +4,25 @@
 import sys
 import os
 from cobjects import CBuffer
-import sixtracklib as pyst
+import sixtracklib as st
 from sixtracklib.stcommon import st_NODE_UNDEFINED_INDEX
 import sixtracklib_test as testlib
 from sixtracklib_test.generic_obj import GenericObj
 
 if __name__ == '__main__':
-    if not pyst.supports('cuda'):
+    if not st.supports('cuda'):
         raise SystemExit("cuda support required for this test")
 
-    ctrl = pyst.CudaController()
+    try:
+        num_nodes = st.CudaController.NUM_AVAILABLE_NODES()
+    except RuntimeError as e:
+        num_nodes = 0
+
+    if num_nodes <= 0:
+        print("No CUDA nodes available -> skip test")
+        sys.exit(0)
+
+    ctrl = st.CudaController()
     assert ctrl.num_nodes > 0
     assert ctrl.has_selected_node
     assert ctrl.selected_node_index != st_NODE_UNDEFINED_INDEX.value
@@ -24,14 +33,14 @@
 
     selected_node_id = ctrl.selected_node_id
 
-    assert isinstance(selected_node_id, pyst.NodeId)
+    assert isinstance(selected_node_id, st.NodeId)
     assert selected_node_id.is_valid
 
     node_id_str = str(selected_node_id)
     print("selected node id: {0}".format(selected_node_id))
 
     selected_node_info = ctrl.selected_node_info
-    assert isinstance(selected_node_info, pyst.NodeInfoBase)
+    assert isinstance(selected_node_info, st.NodeInfoBase)
 
     print("selected node_info: ")
     print(selected_node_info)
diff --git a/tests/python/cuda/test_track_job_collect_and_push_cuda.py b/tests/python/cuda/test_track_job_collect_and_push_cuda.py
index 7a4db90a..77d8f02e 100644
--- a/tests/python/cuda/test_track_job_collect_and_push_cuda.py
+++ b/tests/python/cuda/test_track_job_collect_and_push_cuda.py
@@ -1,7 +1,7 @@
 import sys
 import os
 import numpy as np
-import sixtracklib as pyst
+import sixtracklib as st
 import sixtracklib_test as testlib
 
 from sixtracklib.stcommon import \
@@ -28,7 +28,16 @@
 if __name__ == '__main__':
     EPS = np.finfo(float).eps
 
-    line = pyst.Elements()
+    try:
+        num_nodes = st.CudaController.NUM_AVAILABLE_NODES()
+    except RuntimeError as e:
+        num_nodes = 0
+
+    if num_nodes <= 0:
+        print("No CUDA nodes available -> skip test")
+        sys.exit(0)
+
+    line = st.Elements()
     line.Drift(length=1.0)
     line.Cavity(voltage=100e3, frequency=400e6, lag=0.0)
     line.Drift(length=3.0)
@@ -44,14 +53,14 @@
                      is_turn_ordered=False)
 
     NUM_PARTICLES = 100
-    pb = pyst.ParticlesSet()
+    pb = st.ParticlesSet()
     pb.Particles(num_particles=100)
 
     ptr_pb = st_Buffer_new_mapped_on_cbuffer(pb.cbuffer)
     ptr_particles = st_Particles_cbuffer_get_particles(pb.cbuffer, 0)
     assert ptr_particles != st_NullParticles
 
-    job = pyst.CudaTrackJob(line, pb)
+    job = st.CudaTrackJob(line, pb)
     assert job.arch_str == 'cuda'
     assert job.requires_collecting
     assert job.has_output_buffer
@@ -111,37 +120,37 @@
         assert st_Particles_compare_values(ptr_init_be_mon_output,
                                            ptr_be_mon_output) != 0
 
-    drift1 = line.cbuffer.get_object(0, cls=pyst.Drift)
+    drift1 = line.cbuffer.get_object(0, cls=st.Drift)
     assert abs(drift1.length - 1.0) < EPS
     drift1.length *= 0.5
 
-    cavity2 = line.cbuffer.get_object(1, cls=pyst.Cavity)
+    cavity2 = line.cbuffer.get_object(1, cls=st.Cavity)
     assert abs(cavity2.voltage - 100e3) < EPS
     assert abs(cavity2.frequency - 400e6) < EPS
     assert abs(cavity2.lag - 0.0) < EPS
     cavity2.voltage *= 1.10
     cavity2.lag = 2.0
 
-    drift3 = line.cbuffer.get_object(2, cls=pyst.Drift)
+    drift3 = line.cbuffer.get_object(2, cls=st.Drift)
     assert abs(drift3.length - 3.0) < EPS
     drift3.length = 0.0
 
-    limit4 = line.cbuffer.get_object(3, cls=pyst.LimitRect)
+    limit4 = line.cbuffer.get_object(3, cls=st.LimitRect)
     assert abs(limit4.min_x + 1.0) < EPS
     assert abs(limit4.max_x - 1.0) < EPS
     limit4.min_x = -2.0
     limit4.max_x = 0.0
 
-    bemon6 = line.cbuffer.get_object(5, cls=pyst.BeamMonitor)
+    bemon6 = line.cbuffer.get_object(5, cls=st.BeamMonitor)
     assert bemon6.out_address != 42
     bemon6.out_address = 42
 
-    limit8 = line.cbuffer.get_object(7, cls=pyst.LimitEllipse)
+    limit8 = line.cbuffer.get_object(7, cls=st.LimitEllipse)
     assert abs(limit8.a_squ - 0.5 * 0.5) < EPS
     assert abs(limit8.b_squ - 0.35 * 0.35) < EPS
     limit8.set_half_axes(1.0, 1.0)
 
-    bemon9 = line.cbuffer.get_object(8, cls=pyst.BeamMonitor)
+    bemon9 = line.cbuffer.get_object(8, cls=st.BeamMonitor)
     assert bemon9.out_address != 137
     bemon9.out_address = 137
 
@@ -179,25 +188,25 @@
     assert st_Particles_compare_values(ptr_particles, ptr_saved_particles) != 0
     assert st_Particles_compare_values(ptr_particles, ptr_init_particles) == 0
 
-    line.cbuffer.get_object(0, cls=pyst.Drift).length = 1.0
+    line.cbuffer.get_object(0, cls=st.Drift).length = 1.0
 
-    cavity2 = line.cbuffer.get_object(1, cls=pyst.Cavity)
+    cavity2 = line.cbuffer.get_object(1, cls=st.Cavity)
     cavity2_saved_voltage = cavity2.voltage
     cavity2.voltage /= 1.10
     cavity2.lag = 0.0
 
-    line.cbuffer.get_object(2, cls=pyst.Drift).length = 3.0
+    line.cbuffer.get_object(2, cls=st.Drift).length = 3.0
 
-    limit4 = line.cbuffer.get_object(3, cls=pyst.LimitRect)
+    limit4 = line.cbuffer.get_object(3, cls=st.LimitRect)
     limit4.min_x = -1.0
     limit4.max_x = 1.0
 
-    line.cbuffer.get_object(5, cls=pyst.BeamMonitor).out_address = 0
+    line.cbuffer.get_object(5, cls=st.BeamMonitor).out_address = 0
 
     line.cbuffer.get_object(
-        7, cls=pyst.LimitEllipse).set_half_axes(0.5, 0.35)
+        7, cls=st.LimitEllipse).set_half_axes(0.5, 0.35)
 
-    line.cbuffer.get_object(8, cls=pyst.BeamMonitor).out_address = 0
+    line.cbuffer.get_object(8, cls=st.BeamMonitor).out_address = 0
 
     for ii in range(0, job.num_beam_monitors):
         ptr_be_mon_output = st_Particles_cbuffer_get_particles(
@@ -231,29 +240,29 @@
 
     job.collect_beam_elements()
 
-    drift1 = line.cbuffer.get_object(0, cls=pyst.Drift)
+    drift1 = line.cbuffer.get_object(0, cls=st.Drift)
     assert abs(drift1.length - 0.5) < EPS
 
-    cavity2 = line.cbuffer.get_object(1, cls=pyst.Cavity)
+    cavity2 = line.cbuffer.get_object(1, cls=st.Cavity)
     assert abs(cavity2.voltage - cavity2_saved_voltage) < EPS
     assert abs(cavity2.frequency - 400e6) < EPS
     assert abs(cavity2.lag - 2.0) < EPS
 
-    drift3 = line.cbuffer.get_object(2, cls=pyst.Drift)
+    drift3 = line.cbuffer.get_object(2, cls=st.Drift)
     assert abs(drift3.length) < EPS
 
-    limit4 = line.cbuffer.get_object(3, cls=pyst.LimitRect)
+    limit4 = line.cbuffer.get_object(3, cls=st.LimitRect)
     assert abs(limit4.min_x + 2.0) < EPS
     assert abs(limit4.max_x) < EPS
 
-    bemon6 = line.cbuffer.get_object(5, cls=pyst.BeamMonitor)
+    bemon6 = line.cbuffer.get_object(5, cls=st.BeamMonitor)
     assert bemon6.out_address == 42
 
-    limit8 = line.cbuffer.get_object(7, cls=pyst.LimitEllipse)
+    limit8 = line.cbuffer.get_object(7, cls=st.LimitEllipse)
     assert abs(limit8.a_squ - 1.0) < EPS
     assert abs(limit8.b_squ - 1.0) < EPS
 
-    bemon9 = line.cbuffer.get_object(8, cls=pyst.BeamMonitor)
+    bemon9 = line.cbuffer.get_object(8, cls=st.BeamMonitor)
     assert bemon9.out_address == 137
 
     job.collect_output()
diff --git a/tests/python/cuda/test_track_job_fetch_particle_addr.py b/tests/python/cuda/test_track_job_fetch_particle_addr.py
index 59dd8159..b59683e9 100644
--- a/tests/python/cuda/test_track_job_fetch_particle_addr.py
+++ b/tests/python/cuda/test_track_job_fetch_particle_addr.py
@@ -5,7 +5,7 @@
 import os
 import ctypes as ct
 from cobjects import CBuffer
-import sixtracklib as pyst
+import sixtracklib as st
 from sixtracklib.stcommon import \
     st_Particles_p, st_ParticlesAddr_p, \
     st_Particles_buffer_get_particles, st_Particles_get_num_of_particles, \
@@ -17,9 +17,18 @@
 import pdb
 
 if __name__ == '__main__':
-    if not pyst.supports('cuda'):
+    if not st.supports('cuda'):
         raise SystemExit("cuda support required for this test")
 
+    try:
+        num_nodes = st.CudaController.NUM_AVAILABLE_NODES()
+    except RuntimeError as e:
+        num_nodes = 0
+
+    if num_nodes <= 0:
+        print("No CUDA nodes available -> skip test")
+        sys.exit(0)
+
     path_to_testdir = testlib.config.PATH_TO_TESTDATA_DIR
     assert path_to_testdir is not None
     assert os.path.exists(path_to_testdir)
@@ -43,7 +52,7 @@
     # =========================================================================
     # Setup CudaTrackJob to extract device particle addresses:
 
-    track_job = pyst.CudaTrackJob(eb, pb)
+    track_job = st.CudaTrackJob(eb, pb)
 
     assert track_job.arch_str == "cuda"
     assert track_job.requires_collecting
@@ -76,7 +85,7 @@
 
     assert track_job.has_particle_addresses
 
-    pb_buffer = pyst.Buffer(cbuffer=pb)
+    pb_buffer = st.Buffer(cbuffer=pb)
     assert pb_buffer.pointer != st_NullBuffer
     assert pb_buffer.num_objects == num_particle_sets
 
diff --git a/tests/python/cuda/test_track_job_threads_per_block.py b/tests/python/cuda/test_track_job_threads_per_block.py
new file mode 100644
index 00000000..84240682
--- /dev/null
+++ b/tests/python/cuda/test_track_job_threads_per_block.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+import ctypes as ct
+from cobjects import CBuffer
+import sixtracklib as pyst
+from sixtracklib.stcommon import \
+    st_Track_all_particles_until_turn, st_Particles_buffer_get_particles, \
+    st_NullParticles, st_NullBuffer, st_buffer_size_t, st_TRACK_SUCCESS
+import sixtracklib_test as testlib
+
+if __name__ == '__main__':
+    if not pyst.supports('cuda'):
+        raise SystemExit("cuda support required for this test")
+
+    path_to_testdir = testlib.config.PATH_TO_TESTDATA_DIR
+    assert path_to_testdir is not None
+    assert os.path.exists(path_to_testdir)
+    assert os.path.isdir(path_to_testdir)
+
+    path_to_particle_data = os.path.join(
+        path_to_testdir, "beambeam", "particles_dump.bin")
+    assert os.path.exists(path_to_particle_data)
+
+    path_to_beam_elements_data = os.path.join(
+        path_to_testdir, "beambeam", "beam_elements.bin")
+    assert os.path.exists(path_to_beam_elements_data)
+
+    pb = CBuffer.fromfile(path_to_particle_data)
+    cmp_pb = CBuffer.fromfile(path_to_particle_data)
+
+    eb = CBuffer.fromfile(path_to_beam_elements_data)
+    num_beam_elements = eb.n_objects
+
+    NUM_TURNS = 10
+    PSET_INDEX = 0
+
+    # =========================================================================
+    # Setup CudaTrackJob to perform the same tracking on the same data but
+    # line by line wise:
+
+    default_threads_per_block = 256
+    default_track_threads_per_block = 512
+
+    config_str = f"""
+    cuda.threads_per_block = {default_threads_per_block}\r\n
+    cuda.track_threads_per_block = {default_track_threads_per_block}\r\n
+    """
+    track_job = pyst.CudaTrackJob(eb, pb, PSET_INDEX, config_str=config_str)
+
+    assert track_job.arch_str == "cuda"
+    assert track_job.requires_collecting
+    assert track_job.is_collecting_particles
+    assert track_job.has_controller
+    assert track_job.has_particles_arg
+    assert track_job.has_beam_elements_arg
+    assert track_job.has_particles_addr_arg
+    assert not track_job.is_in_debug_mode
+    assert not track_job.has_output_buffer
+    assert not track_job.owns_output_buffer
+    assert not track_job.has_beam_monitor_output
+    assert not track_job.has_elem_by_elem_output
+    assert track_job.num_particle_sets == 1
+    assert track_job.default_track_threads_per_block == \
+        default_track_threads_per_block
+    assert track_job.default_threads_per_block == \
+        default_threads_per_block
+
+    sys.exit(0)
diff --git a/tests/python/cuda/test_track_job_track_line.py b/tests/python/cuda/test_track_job_track_line.py
index dbb0fa5c..f3cb8fe0 100644
--- a/tests/python/cuda/test_track_job_track_line.py
+++ b/tests/python/cuda/test_track_job_track_line.py
@@ -5,16 +5,25 @@
 import os
 import ctypes as ct
 from cobjects import CBuffer
-import sixtracklib as pyst
+import sixtracklib as st
 from sixtracklib.stcommon import \
     st_Track_all_particles_until_turn, st_Particles_buffer_get_particles, \
     st_NullParticles, st_NullBuffer, st_buffer_size_t, st_TRACK_SUCCESS
 import sixtracklib_test as testlib
 
 if __name__ == '__main__':
-    if not pyst.supports('cuda'):
+    if not st.supports('cuda'):
         raise SystemExit("cuda support required for this test")
 
+    try:
+        num_nodes = st.CudaController.NUM_AVAILABLE_NODES()
+    except RuntimeError as e:
+        num_nodes = 0
+
+    if num_nodes <= 0:
+        print("No CUDA nodes available -> skip test")
+        sys.exit(0)
+
     path_to_testdir = testlib.config.PATH_TO_TESTDATA_DIR
     assert path_to_testdir is not None
     assert os.path.exists(path_to_testdir)
@@ -40,11 +49,11 @@
     # ==========================================================================
     # Perform "regular" tracking over NUM_TURNS
 
-    cmp_track_pb = pyst.Buffer(cbuffer=cmp_pb)
+    cmp_track_pb = st.Buffer(cbuffer=cmp_pb)
     assert cmp_track_pb.pointer != st_NullBuffer
     assert cmp_track_pb.num_objects == cmp_pb.n_objects
 
-    cmp_eb = pyst.Buffer(cbuffer=eb)
+    cmp_eb = st.Buffer(cbuffer=eb)
     assert cmp_eb.pointer != st_NullBuffer
     assert cmp_eb.num_objects == num_beam_elements
 
@@ -63,7 +72,7 @@
     # Setup CudaTrackJob to perform the same tracking on the same data but
     # line by line wise:
 
-    track_job = pyst.CudaTrackJob(eb, pb, PSET_INDEX)
+    track_job = st.CudaTrackJob(eb, pb, PSET_INDEX)
 
     assert track_job.arch_str == "cuda"
     assert track_job.requires_collecting
@@ -102,10 +111,10 @@
     # ==========================================================================
     # Compare Results from CPU based and CudaTrackJob based line tracking
 
-    tracked_particles = pb.get_object(PSET_INDEX, cls=pyst.Particles)
-    cmp_particles = cmp_pb.get_object(PSET_INDEX, cls=pyst.Particles)
+    tracked_particles = pb.get_object(PSET_INDEX, cls=st.Particles)
+    cmp_particles = cmp_pb.get_object(PSET_INDEX, cls=st.Particles)
 
-    assert pyst.compareParticlesDifference(
+    assert st.compareParticlesDifference(
         tracked_particles, cmp_particles, abs_treshold=2e-14) == 0
 
     sys.exit(0)
diff --git a/tests/python/opencl/CMakeLists.txt b/tests/python/opencl/CMakeLists.txt
index c0fd7f96..76ced73e 100644
--- a/tests/python/opencl/CMakeLists.txt
+++ b/tests/python/opencl/CMakeLists.txt
@@ -1,18 +1,47 @@
 # tests/python/opencl/CMakeLists.txt
 
+# ------------------------------------------------------------------------------
+# test_cl_node_id_opencl:
+
+add_test( NAME Python_OpenCL_ClNodeIdTests
+    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_cl_node_id.py
+    WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
+
+# ------------------------------------------------------------------------------
+# test_cl_controller_opencl:
+
+add_test( NAME Python_OpenCL_ClControllerTests
+    COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_cl_controller.py
+    WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
+
 # ------------------------------------------------------------------------------
 # test_track_job_opencl:
 
-add_test( NAME Python_TrackJobOpenClTests
+add_test( NAME Python_OpenCL_TrackJob_InitTests
    COMMAND ${PYTHON_EXECUTABLE}
            ${CMAKE_CURRENT_SOURCE_DIR}/test_track_job_opencl.py
-   WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python )
+   WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
 
 # ------------------------------------------------------------------------------
 # test_track_job_collect_and_push_opencl:
 
- add_test( NAME Python_TrackJobOpenClCollectAndPushTests
+ add_test( NAME Python_OpenCL_TrackJob_CollectAndPushTests
     COMMAND ${PYTHON_EXECUTABLE}
         ${CMAKE_CURRENT_SOURCE_DIR}/test_track_job_collect_and_push_opencl.py
-    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python )
+    WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
 
+# ------------------------------------------------------------------------------
+# test_track_job_cl_stored_buffer_opencl:
+
+ add_test( NAME Python_OpenCL_TrackJob_StoredBufferTests
+    COMMAND ${PYTHON_EXECUTABLE}
+        ${CMAKE_CURRENT_SOURCE_DIR}/test_track_job_cl_stored_buffer.py
+    WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
+
+# ------------------------------------------------------------------------------
+# test_track_job_cl_assign_addresses_opencl:
+
+ add_test( NAME Python_OpenCL_TrackJob_AssignAddressItemsTests
+    COMMAND ${PYTHON_EXECUTABLE}
+        ${CMAKE_CURRENT_SOURCE_DIR}/test_track_job_cl_assign_addresses.py
+    WORKING_DIRECTORY ${PYTHON_TESTS_WORKDIR} )
diff --git a/tests/python/opencl/test_cl_controller.py b/tests/python/opencl/test_cl_controller.py
new file mode 100644
index 00000000..5a33f7d7
--- /dev/null
+++ b/tests/python/opencl/test_cl_controller.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+import sixtracklib as st
+from sixtracklib.stcommon import \
+    st_ClNodeId, st_ClNodeId_p, st_NullClNodeId, \
+    st_ARCHITECTURE_OPENCL, st_NODE_ID_STR_FORMAT_ARCHSTR, \
+    st_NODE_ID_STR_FORMAT_NOARCH, st_NODE_ID_STR_FORMAT_ARCHID
+
+if __name__ == '__main__':
+    try:
+        total_num_nodes = st.ClController.NUM_ALL_NODES()
+    except RuntimeError as e:
+        total_num_nodes = 0
+
+    try:
+        num_available_nodes = st.ClController.NUM_AVAILABLE_NODES()
+    except RuntimeError as e:
+        num_available_nodes = 0
+
+    if num_available_nodes <= 0:
+        if total_num_nodes > 0:
+            print( "OpenCL nodes present, but no available for selection!" )
+            print( "--> Check SIXTRACKLIB_DEVICES environment variable!" )
+        else:
+            print( "No OpenCL nodes available, skip test case" )
+        sys.exit(0)
+
+    node_ids = st.ClController.GET_AVAILABLE_NODES()
+    assert node_ids and len( node_ids ) > 0 and \
+        len( node_ids ) <= num_available_nodes
+
+    for node_id in node_ids:
+        assert node_id.pointer != st_NullClNodeId
+        assert node_id.owns_node
+        assert node_id.arch_id == st_ARCHITECTURE_OPENCL.value
+        print( f"{node_id}\r\n" )
+
+
+
+    node_id_strs = st.ClController.GET_AVAILABLE_NODE_ID_STRS()
+    assert node_id_strs and len( node_id_strs ) == len( node_ids )
+
+    for node_id_str in node_id_strs:
+        print( f"{node_id_str}\r\n" )
+
+    sys.exit(0)
diff --git a/tests/python/opencl/test_cl_node_id.py b/tests/python/opencl/test_cl_node_id.py
new file mode 100644
index 00000000..40f552d8
--- /dev/null
+++ b/tests/python/opencl/test_cl_node_id.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sixtracklib as st
+from sixtracklib.stcommon import \
+    st_ClNodeId, st_ClNodeId_p, st_NullClNodeId, \
+    st_NODE_ID_STR_FORMAT_NOARCH, st_NODE_ID_STR_FORMAT_ARCHSTR, \
+    st_NODE_ID_STR_FORMAT_ARCHID, st_ARCHITECTURE_OPENCL
+
+if __name__ == '__main__':
+    node_a = st.ClNodeId(
+        node_id_str="opencl:1.0",
+        node_id_str_fmt=st_NODE_ID_STR_FORMAT_ARCHSTR.value)
+
+    assert node_a.pointer != st_NullClNodeId
+    assert node_a.owns_node
+    assert node_a.arch_id == st_ARCHITECTURE_OPENCL.value
+    assert node_a.platform_id == 1
+    assert node_a.device_id == 0
+
+    node_b = st.ClNodeId(platform_id=2, device_id=4)
+    assert node_b.pointer != st_NullClNodeId
+    assert node_b.owns_node
+    assert node_b.arch_id == st_ARCHITECTURE_OPENCL.value
+    assert node_b.platform_id == 2
+    assert node_b.device_id == 4
+    assert node_b.to_string(format=st_NODE_ID_STR_FORMAT_NOARCH.value) == "2.4"
+    assert node_b.to_string(format=st_NODE_ID_STR_FORMAT_ARCHSTR.value) == \
+           "opencl:2.4"
+
+    node_b_link = st.ClNodeId(ext_ptr_node_id=node_b.pointer, owns_ptr=False)
+    assert node_b_link.pointer != st_NullClNodeId
+    assert node_b_link.pointer == node_b.pointer
+    assert not node_b_link.owns_node
+    assert node_b_link.arch_id == st_ARCHITECTURE_OPENCL.value
+    assert node_b_link.platform_id == 2
+    assert node_b_link.device_id == 4
+    assert node_b_link.to_string(format=st_NODE_ID_STR_FORMAT_NOARCH.value) \
+            == "2.4"
+    assert node_b_link.to_string(format=st_NODE_ID_STR_FORMAT_ARCHSTR.value) \
+            == "opencl:2.4"
+
+    assert node_b.set_device_id( 0 )
+    assert node_b.arch_id == st_ARCHITECTURE_OPENCL.value
+    assert node_b.platform_id == 2
+    assert node_b.device_id == 0
+    assert node_b.to_string(format=st_NODE_ID_STR_FORMAT_NOARCH.value) == "2.0"
+    assert node_b.to_string(format=st_NODE_ID_STR_FORMAT_ARCHSTR.value) \
+            == "opencl:2.0"
+
+    assert node_b_link.pointer != st_NullClNodeId
+    assert node_b_link.pointer == node_b.pointer
+    assert not node_b_link.owns_node
+    assert node_b_link.arch_id == st_ARCHITECTURE_OPENCL.value
+    assert node_b_link.platform_id == 2
+    assert node_b_link.device_id == 0
+    assert node_b_link.to_string(format=st_NODE_ID_STR_FORMAT_NOARCH.value) \
+            == "2.0"
+    assert node_b_link.to_string(format=st_NODE_ID_STR_FORMAT_ARCHSTR.value) \
+            == "opencl:2.0"
+
+    del node_b_link
+    node_b_link = None
+
+    assert node_b.pointer != st_NullClNodeId
+    assert node_b.owns_node
+    assert node_b.arch_id == st_ARCHITECTURE_OPENCL.value
+    assert node_b.platform_id == 2
+    assert node_b.device_id == 0
+    assert node_b.to_string(format=st_NODE_ID_STR_FORMAT_NOARCH.value) == "2.0"
+    assert node_b.to_string(format=st_NODE_ID_STR_FORMAT_ARCHSTR.value) == \
+           "opencl:2.0"
+
+
diff --git a/tests/python/opencl/test_track_job_cl_assign_addresses.py b/tests/python/opencl/test_track_job_cl_assign_addresses.py
new file mode 100644
index 00000000..dc43150b
--- /dev/null
+++ b/tests/python/opencl/test_track_job_cl_assign_addresses.py
@@ -0,0 +1,293 @@
+import sys
+import cobjects
+from cobjects import CBuffer, CObject
+import sixtracklib as st
+from sixtracklib.stcommon import st_ARCH_BEAM_ELEMENTS_BUFFER_ID, \
+    st_NullAssignAddressItem, st_AssignAddressItem_p, \
+    st_buffer_size_t, st_object_type_id_t, st_arch_status_t, st_arch_size_t, \
+    st_ARCH_STATUS_SUCCESS, st_ARCH_ILLEGAL_BUFFER_ID, \
+    st_NODE_ID_STR_FORMAT_ARCHSTR, \
+    st_AssignAddressItem_are_equal, st_AssignAddressItem_are_not_equal, \
+    st_AssignAddressItem_compare_less
+
+import sixtracklib_test as testlib
+from sixtracklib_test.stcommon import st_AssignAddressItem_print_out
+
+if __name__ == '__main__':
+    try:
+        total_num_nodes = st.ClController.NUM_ALL_NODES()
+    except RuntimeError as e:
+        total_num_nodes = 0
+
+    try:
+        num_available_nodes = st.ClController.NUM_AVAILABLE_NODES()
+    except RuntimeError as e:
+        num_available_nodes = 0
+
+    if num_available_nodes <= 0:
+        if total_num_nodes > 0:
+            print("OpenCL nodes present, but no available for selection!")
+            print("--> Check SIXTRACKLIB_DEVICES environment variable!")
+        else:
+            print("No OpenCL nodes available, skip test case")
+        sys.exit(0)
+
+    node_id_strs = st.ClController.GET_AVAILABLE_NODE_ID_STRS(
+        node_id_str_fmt=st_NODE_ID_STR_FORMAT_ARCHSTR.value)
+
+    assert node_id_strs and len(node_id_strs) > 0
+
+    lattice = st.Elements()
+    lattice.Drift(length=0.0)
+    lattice.Drift(length=0.1)
+    lattice.Drift(length=0.2)
+    bm0_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+    lattice.Drift(length=0.3)
+    lattice.Drift(length=0.4)
+    lattice.Drift(length=0.5)
+    bm1_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+    lattice.Drift(length=0.3)
+    lattice.Drift(length=0.4)
+    lattice.Drift(length=0.5)
+    bm2_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+
+    assert lattice.cbuffer.get_object(bm0_index).out_address == 0
+    assert lattice.cbuffer.get_object(bm1_index).out_address == 0
+    assert lattice.cbuffer.get_object(bm2_index).out_address == 0
+
+    pset = st.ParticlesSet()
+    pset.Particles(num_particles=100)
+
+    output_buffer = st.ParticlesSet()
+    out_buffer0_index = output_buffer.cbuffer.n_objects
+    output_buffer.Particles(num_particles=100)
+    out_buffer1_index = output_buffer.cbuffer.n_objects
+    output_buffer.Particles(num_particles=512)
+
+    job = st.TrackJob(lattice, pset, device=node_id_strs[0])
+    controller = job.controller
+
+    assert controller.has_selected_node
+    assert controller.selected_node_id_str == node_id_strs[0]
+
+    # hand the output_buffer over to the track job:
+    output_buffer_id = job.add_stored_buffer(cbuffer=output_buffer)
+    assert output_buffer_id != st_ARCH_ILLEGAL_BUFFER_ID.value
+
+    # use the predefined lattice_buffer_id value to refer to the
+    # beam elements buffer
+    lattice_buffer_id = st_ARCH_BEAM_ELEMENTS_BUFFER_ID.value
+
+    # use the _type_id attributes of beam monitors and particle sets to
+    # refer to these object types:
+    particle_set_type_id = output_buffer.cbuffer.get_object(
+        out_buffer0_index)._typeid
+    beam_monitor_type_id = lattice.cbuffer.get_object(bm0_index)._typeid
+
+    assert job.total_num_assign_items == 0
+    assert not job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 0
+
+    # --------------------------------------------------------------------------
+    # Create the assignment item for out_buffer0 -> bm0
+
+    out0_to_bm0_addr_assign_item = st.AssignAddressItem(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm0_index,
+        dest_pointer_offset=24,  # Magic number, offset of out_address from begin
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0  # We assign the starting address of the particle set
+    )
+
+    assert out0_to_bm0_addr_assign_item.dest_elem_type_id == \
+        beam_monitor_type_id
+    assert out0_to_bm0_addr_assign_item.dest_buffer_id == lattice_buffer_id
+    assert out0_to_bm0_addr_assign_item.dest_elem_index == bm0_index
+    assert out0_to_bm0_addr_assign_item.dest_pointer_offset == 24
+
+    assert out0_to_bm0_addr_assign_item.src_elem_type_id == \
+        particle_set_type_id
+    assert out0_to_bm0_addr_assign_item.src_buffer_id == output_buffer_id
+    assert out0_to_bm0_addr_assign_item.src_elem_index == out_buffer0_index
+    assert out0_to_bm0_addr_assign_item.src_pointer_offset == 0
+
+    # perform the assignment of assign_out0_to_bm0_item
+
+    ptr_item_0_to_0 = job.add_assign_address_item(
+        out0_to_bm0_addr_assign_item)
+
+    assert ptr_item_0_to_0 != st_NullAssignAddressItem
+    assert job.total_num_assign_items == 1
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 1
+    assert job.has_assign_item(item=ptr_item_0_to_0)
+    assert job.has_assign_item(item=out0_to_bm0_addr_assign_item)
+    assert job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm0_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm1_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer1_index,
+        src_pointer_offset=0)
+
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    item_0_to_0_index = job.index_of_assign_address_item(item=ptr_item_0_to_0)
+    assert not(item_0_to_0_index is None)
+
+    # --------------------------------------------------------------------------
+    # Create the assignment item for out_buffer1 -> bm1 at the time of
+    # passing it on to the track job:
+
+    ptr_item_1_to_1 = job.add_assign_address_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm1_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer1_index,
+        src_pointer_offset=0)
+
+    assert ptr_item_1_to_1 != st_NullAssignAddressItem
+    assert job.total_num_assign_items == 2
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 2
+    assert job.has_assign_item(item=ptr_item_1_to_1)
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    item_1_to_1_index = job.index_of_assign_address_item(ptr_item_1_to_1)
+    assert not(item_1_to_1_index is None)
+
+    # Create the assignment item for out_buffer0 -> bm2
+
+    # Create a copy of out0_to_bm0_addr_assign_item on the same buffer
+    # TODO: figure out a better way to do this?
+    out0_to_bm2_addr_assign_item = st.AssignAddressItem(
+        **{k != '_buffer' and k or 'cbuffer':
+                getattr(out0_to_bm0_addr_assign_item, k) for k in [*[f[0]
+                for f in st.AssignAddressItem.get_fields()], '_buffer']})
+
+    # out0_to_bm2_addr_assign_item is actually the same as
+    # out0_to_bm0_addr_assign_item  -> if we try to add this item unmodified,
+    # we should again effectively get ptr_item0_to_0:
+
+    ptr_item_0_to_2 = job.add_assign_address_item(
+        out0_to_bm2_addr_assign_item)
+
+    assert ptr_item_0_to_2 != st_NullAssignAddressItem
+    assert st_AssignAddressItem_are_equal(
+        ptr_item_0_to_2,
+        job.ptr_assign_address_item(
+            dest_buffer_id=lattice_buffer_id,
+            src_buffer_id=output_buffer_id,
+            index=item_0_to_0_index))
+
+    assert job.total_num_assign_items == 2
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 2
+    assert job.has_assign_item(item=ptr_item_0_to_2)
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    # modify out0_to_bm2_addr_assign_item to target the third beam monitor
+    # located at bm2_index:
+    out0_to_bm2_addr_assign_item.dest_elem_index = bm2_index
+
+    # try again to add -> this time it should result in a new item:
+    ptr_item_0_to_2 = job.add_assign_address_item(
+        out0_to_bm2_addr_assign_item)
+
+    assert ptr_item_0_to_2 != st_NullAssignAddressItem
+    assert st_AssignAddressItem_are_not_equal(
+        ptr_item_0_to_2,
+        job.ptr_assign_address_item(
+            dest_buffer_id=lattice_buffer_id,
+            src_buffer_id=output_buffer_id,
+            index=item_0_to_0_index))
+    assert job.total_num_assign_items == 3
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 3
+    assert job.has_assign_item(item=out0_to_bm2_addr_assign_item)
+    assert job.has_assign_item(item=ptr_item_0_to_2)
+    assert job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    # --------------------------------------------------------------------------
+    # finish assembly of assign items:
+    job.commit_address_assignments()
+    assert job.last_status == st_ARCH_STATUS_SUCCESS.value
+
+    # perform assignment of address items:
+    job.assign_all_addresses()
+    assert job.last_status == st_ARCH_STATUS_SUCCESS.value
+
+    job.collect_beam_elements()
+    assert job.last_status == st_ARCH_STATUS_SUCCESS.value
+    assert lattice.cbuffer.get_object(bm0_index).out_address != 0
+    assert lattice.cbuffer.get_object(bm1_index).out_address != 0
+    assert lattice.cbuffer.get_object(bm2_index).out_address != 0
+
+    assert lattice.cbuffer.get_object(bm0_index).out_address == \
+        lattice.cbuffer.get_object(bm2_index).out_address
+
+    assert lattice.cbuffer.get_object(bm0_index).out_address != \
+        lattice.cbuffer.get_object(bm1_index).out_address
+
+    assert lattice.cbuffer.get_object(bm0_index).out_address < \
+        lattice.cbuffer.get_object(bm1_index).out_address
+
+    assert ((lattice.cbuffer.get_object(bm1_index).out_address -
+             lattice.cbuffer.get_object(bm0_index).out_address) ==
+            (output_buffer.cbuffer.get_object(
+                out_buffer1_index)._get_address() -
+             output_buffer.cbuffer.get_object(
+                out_buffer0_index)._get_address()))
diff --git a/tests/python/opencl/test_track_job_cl_stored_buffer.py b/tests/python/opencl/test_track_job_cl_stored_buffer.py
new file mode 100644
index 00000000..1b71f114
--- /dev/null
+++ b/tests/python/opencl/test_track_job_cl_stored_buffer.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import sys
+import os
+import sixtracklib as st
+import sixtracklib_test as testlib
+
+if __name__ == '__main__':
+    lattice = st.Elements()
+    lattice.Drift(length=1.0)
+    pset = st.ParticlesSet()
+    pset.Particles(num_particles=100)
+
+    job = st.TrackJob(lattice, pset)
+
+    assert not job.has_stored_buffers
+    assert job.num_stored_buffers == 0
+    assert job.min_stored_buffer_id == 0
+    assert job.max_stored_buffer_id == 0
+
+    data_buffer = st.ParticlesSet()
+    out_data_index = data_buffer.cbuffer.n_objects
+    out_data = data_buffer.Particles(num_particles=1000)
+    assert data_buffer.cbuffer.n_objects == 1
+    assert data_buffer.cbuffer.size > 0
+
+    data_buffer_id = job.add_stored_buffer(cbuffer=data_buffer)
+    assert data_buffer_id != st.stcommon.st_ARCH_ILLEGAL_BUFFER_ID.value
+    assert job.has_stored_buffers
+    assert job.num_stored_buffers == 1
+    assert job.min_stored_buffer_id == data_buffer_id
+    assert job.max_stored_buffer_id == data_buffer_id
+
+    st_data_buffer = job.stored_buffer(data_buffer_id)
+    assert st_data_buffer.pointer != st.stcommon.st_NullBuffer
+    assert st_data_buffer.num_objects == data_buffer.cbuffer.n_objects
+    assert st_data_buffer.size == data_buffer.cbuffer.size
+
+    ptr_data_buffer = job.ptr_stored_buffer(data_buffer_id)
+    assert ptr_data_buffer != st.stcommon.st_NullBuffer
+    assert st.stcommon.st_Buffer_get_size(
+        ptr_data_buffer) == data_buffer.cbuffer.size
+    assert st.stcommon.st_Buffer_get_num_of_objects(
+        ptr_data_buffer) == data_buffer.cbuffer.n_objects
diff --git a/tests/python/opencl/test_track_job_opencl.py b/tests/python/opencl/test_track_job_opencl.py
index bc51c1cf..c8fcab5f 100644
--- a/tests/python/opencl/test_track_job_opencl.py
+++ b/tests/python/opencl/test_track_job_opencl.py
@@ -17,7 +17,8 @@
     st_Track_all_particles_element_by_element_until_turn, st_NullBuffer, \
     st_BeamMonitor_assign_output_buffer, st_Buffer_new_mapped_on_cbuffer, \
     st_Particles_cbuffer_get_particles, \
-    st_Particles_buffer_get_particles, st_particle_index_t
+    st_Particles_buffer_get_particles, st_particle_index_t, \
+    st_TRACK_SUCCESS, st_ARCH_STATUS_SUCCESS
 
 from sixtracklib_test.stcommon import st_Particles_print_out, \
     st_Particles_compare_values_with_treshold,\
@@ -138,17 +139,15 @@
     assert job.has_elem_by_elem_output
     assert job.has_beam_monitor_output
 
-    status = job.track_elem_by_elem(until_turn_elem_by_elem)
-    assert status == 0
+    job.track_elem_by_elem(until_turn_elem_by_elem)
+    assert job.last_track_status == st_TRACK_SUCCESS.value
     print("elem by elem tracking finished")
 
-    status = job.track_until(until_turn)
-    assert status == 0
-
+    job.track_until(until_turn)
+    assert job.last_track_status == st_TRACK_SUCCESS.value
     print("tracking finished")
 
     job.collect()
-
     print("collect finished")
 
     output_buffer = job.output_buffer
@@ -161,7 +160,7 @@
     assert cmp_output_buffer.base != output_buffer.base
 
     nn = cmp_output_buffer.n_objects
-    ABS_DIFF = 2e-14
+    ABS_DIFF = 5e-11
 
     for ii in range(nn):
         _cmp_particles = cmp_output_buffer.get_object(ii, cls=st.Particles)
@@ -214,7 +213,8 @@
                 and begin_idx + num_elem_per_part \
                 or num_beam_elements
 
-            status = job.track_line(begin_idx, end_idx, is_last_in_turn)
+            job.track_line(begin_idx, end_idx, is_last_in_turn)
+            assert job.last_track_status == st_TRACK_SUCCESS.value
 
     job.collect()
 
diff --git a/tests/python/test_qgauss.py b/tests/python/test_qgauss.py
new file mode 100644
index 00000000..735562d4
--- /dev/null
+++ b/tests/python/test_qgauss.py
@@ -0,0 +1,29 @@
+import numpy as np
+import sixtracklib as st
+from sixtracklib.stcommon import Math_q_gauss, Math_sqrt_beta_from_gauss_sigma
+
+def test_qgauss_gauss_compare():
+    def gauss_distr(x, sigma, mu=0.0):
+        sigma_squ = sigma * sigma
+        arg = (x - mu) / sigma
+        return np.exp(-arg * arg / 2.0) / np.sqrt(2 * np.pi * sigma_squ)
+
+    q = 1.0
+    sigma1 = 1.0
+    abscissa = np.linspace(-4 * sigma1, 4 * sigma1, 101)
+    cmp_gauss1 = gauss_distr(abscissa, sigma1)
+
+    EPS = float(1e-16)
+    sqrt_beta1 = Math_sqrt_beta_from_gauss_sigma( sigma1 )
+    gauss1 = np.array( [ Math_q_gauss( x, q, sqrt_beta1 ) for x in abscissa ] )
+    assert np.allclose(cmp_gauss1, gauss1, EPS, EPS)
+
+    sigma2 = 2.37
+    sqrt_beta2 = Math_sqrt_beta_from_gauss_sigma( sigma2 )
+    abscissa = np.linspace(-4 * sigma2, 4 * sigma2, 101)
+    cmp_gauss2 = gauss_distr( abscissa, sigma2 )
+    gauss2 = np.array( [ Math_q_gauss( x, q, sqrt_beta2 ) for x in abscissa ] )
+    assert np.allclose(cmp_gauss2, gauss2, EPS, EPS)
+
+if __name__ == "__main__":
+    test_qgauss_gauss_compare()
diff --git a/tests/python/test_track_job_cpu.py b/tests/python/test_track_job_cpu.py
index 2a145d7b..567357b6 100644
--- a/tests/python/test_track_job_cpu.py
+++ b/tests/python/test_track_job_cpu.py
@@ -19,7 +19,7 @@
     st_Particles_buffer_get_particles, \
     st_BeamMonitor_assign_output_buffer, st_Buffer_new_mapped_on_cbuffer, \
     st_Particles_cbuffer_get_particles, st_NullBuffer, \
-    st_ARCH_STATUS_SUCCESS, st_particle_index_t
+    st_ARCH_STATUS_SUCCESS, st_TRACK_SUCCESS, st_particle_index_t
 
 from sixtracklib_test.stcommon import st_Particles_print_out, \
     st_Particles_compare_values_with_treshold,\
@@ -135,11 +135,11 @@
     assert job.has_elem_by_elem_output
     assert job.has_beam_monitor_output
 
-    status = job.track_elem_by_elem(until_turn_elem_by_elem)
-    assert status == 0
+    job.track_elem_by_elem(until_turn_elem_by_elem)
+    assert job.last_track_status == st_TRACK_SUCCESS.value
 
-    status = job.track_until(until_turn)
-    assert status == 0
+    job.track_until(until_turn)
+    assert job.last_track_status == st_TRACK_SUCCESS.value
 
     job.collect()
 
@@ -204,7 +204,8 @@
                 and begin_idx + num_elem_per_part \
                 or num_beam_elements
 
-            status = job.track_line(begin_idx, end_idx, is_last_in_turn)
+            job.track_line(begin_idx, end_idx, is_last_in_turn)
+            assert job.last_track_status == st_TRACK_SUCCESS.value
 
     job.collect()
 
diff --git a/tests/python/test_track_job_cpu_assign_address_items.py b/tests/python/test_track_job_cpu_assign_address_items.py
new file mode 100644
index 00000000..aaeba076
--- /dev/null
+++ b/tests/python/test_track_job_cpu_assign_address_items.py
@@ -0,0 +1,253 @@
+import cobjects
+from cobjects import CBuffer, CObject
+import sixtracklib as st
+from sixtracklib.stcommon import st_ARCH_BEAM_ELEMENTS_BUFFER_ID, \
+    st_NullAssignAddressItem, st_AssignAddressItem_p, \
+    st_buffer_size_t, st_object_type_id_t, st_arch_status_t, st_arch_size_t, \
+    st_ARCH_STATUS_SUCCESS, st_ARCH_ILLEGAL_BUFFER_ID, \
+    st_AssignAddressItem_are_equal, st_AssignAddressItem_are_not_equal, \
+    st_AssignAddressItem_compare_less
+
+import sixtracklib_test as testlib
+from sixtracklib_test.stcommon import st_AssignAddressItem_print_out
+
+if __name__ == '__main__':
+    lattice = st.Elements()
+    lattice.Drift(length=0.0)
+    lattice.Drift(length=0.1)
+    lattice.Drift(length=0.2)
+    bm0_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+    lattice.Drift(length=0.3)
+    lattice.Drift(length=0.4)
+    lattice.Drift(length=0.5)
+    bm1_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+    lattice.Drift(length=0.3)
+    lattice.Drift(length=0.4)
+    lattice.Drift(length=0.5)
+    bm2_index = lattice.cbuffer.n_objects
+    lattice.BeamMonitor()
+
+    assert lattice.cbuffer.get_object(bm0_index).out_address == 0
+    assert lattice.cbuffer.get_object(bm1_index).out_address == 0
+    assert lattice.cbuffer.get_object(bm2_index).out_address == 0
+
+    pset = st.ParticlesSet()
+    pset.Particles(num_particles=100)
+
+    output_buffer = st.ParticlesSet()
+    out_buffer0_index = output_buffer.cbuffer.n_objects
+    output_buffer.Particles(num_particles=100)
+    out_buffer1_index = output_buffer.cbuffer.n_objects
+    output_buffer.Particles(num_particles=512)
+
+    job = st.TrackJob(lattice, pset)
+
+    # hand the output_buffer over to the track job:
+    output_buffer_id = job.add_stored_buffer(cbuffer=output_buffer)
+    assert output_buffer_id != st_ARCH_ILLEGAL_BUFFER_ID.value
+
+    # use the predefined lattice_buffer_id value to refer to the
+    # beam elements buffer
+    lattice_buffer_id = st_ARCH_BEAM_ELEMENTS_BUFFER_ID.value
+
+    # use the _type_id attributes of beam monitors and particle sets to
+    # refer to these object types:
+    particle_set_type_id = output_buffer.cbuffer.get_object(
+        out_buffer0_index)._typeid
+    beam_monitor_type_id = lattice.cbuffer.get_object(bm0_index)._typeid
+
+    assert job.total_num_assign_items == 0
+    assert not job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 0
+
+    # --------------------------------------------------------------------------
+    # Create the assignment item for out_buffer0 -> bm0
+
+    out0_to_bm0_addr_assign_item = st.AssignAddressItem(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm0_index,
+        dest_pointer_offset=24,  # Magic number, offset of out_address from begin
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0  # We assign the starting address of the particle set
+    )
+
+    assert out0_to_bm0_addr_assign_item.dest_elem_type_id == \
+        beam_monitor_type_id
+    assert out0_to_bm0_addr_assign_item.dest_buffer_id == lattice_buffer_id
+    assert out0_to_bm0_addr_assign_item.dest_elem_index == bm0_index
+    assert out0_to_bm0_addr_assign_item.dest_pointer_offset == 24
+
+    assert out0_to_bm0_addr_assign_item.src_elem_type_id == \
+        particle_set_type_id
+    assert out0_to_bm0_addr_assign_item.src_buffer_id == output_buffer_id
+    assert out0_to_bm0_addr_assign_item.src_elem_index == out_buffer0_index
+    assert out0_to_bm0_addr_assign_item.src_pointer_offset == 0
+
+    # perform the assignment of assign_out0_to_bm0_item
+
+    ptr_item_0_to_0 = job.add_assign_address_item(
+        out0_to_bm0_addr_assign_item)
+
+    assert ptr_item_0_to_0 != st_NullAssignAddressItem
+    assert job.total_num_assign_items == 1
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 1
+    assert job.has_assign_item(item=ptr_item_0_to_0)
+    assert job.has_assign_item(item=out0_to_bm0_addr_assign_item)
+    assert job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm0_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm1_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer1_index,
+        src_pointer_offset=0)
+
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    item_0_to_0_index = job.index_of_assign_address_item(item=ptr_item_0_to_0)
+    assert not(item_0_to_0_index is None)
+
+    # --------------------------------------------------------------------------
+    # Create the assignment item for out_buffer1 -> bm1 at the time of
+    # passing it on to the track job:
+
+    ptr_item_1_to_1 = job.add_assign_address_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm1_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer1_index,
+        src_pointer_offset=0)
+
+    assert ptr_item_1_to_1 != st_NullAssignAddressItem
+    assert job.total_num_assign_items == 2
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 2
+    assert job.has_assign_item(item=ptr_item_1_to_1)
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    item_1_to_1_index = job.index_of_assign_address_item(ptr_item_1_to_1)
+    assert not(item_1_to_1_index is None)
+
+    # Create the assignment item for out_buffer0 -> bm2
+
+    # Create a copy of out0_to_bm0_addr_assign_item on the same buffer
+    # TODO: figure out a better way to do this?
+    out0_to_bm2_addr_assign_item = st.AssignAddressItem(
+        **{k != '_buffer' and k or 'cbuffer':
+                getattr(out0_to_bm0_addr_assign_item, k) for k in [*[f[0]
+                                                                     for f in st.AssignAddressItem.get_fields()], '_buffer']})
+
+    # out0_to_bm2_addr_assign_item is actually the same as
+    # out0_to_bm0_addr_assign_item  -> if we try to add this item unmodified,
+    # we should again effectively get ptr_item0_to_0:
+
+    ptr_item_0_to_2 = job.add_assign_address_item(
+        out0_to_bm2_addr_assign_item)
+
+    assert ptr_item_0_to_2 != st_NullAssignAddressItem
+    assert st_AssignAddressItem_are_equal(
+        ptr_item_0_to_2,
+        job.ptr_assign_address_item(
+            dest_buffer_id=lattice_buffer_id,
+            src_buffer_id=output_buffer_id,
+            index=item_0_to_0_index))
+
+    assert job.total_num_assign_items == 2
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 2
+    assert job.has_assign_item(item=ptr_item_0_to_2)
+    assert not job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    # modify out0_to_bm2_addr_assign_item to target the third beam monitor
+    # located at bm2_index:
+    out0_to_bm2_addr_assign_item.dest_elem_index = bm2_index
+
+    # try again to add -> this time it should result in a new item:
+    ptr_item_0_to_2 = job.add_assign_address_item(
+        out0_to_bm2_addr_assign_item)
+
+    assert ptr_item_0_to_2 != st_NullAssignAddressItem
+    assert st_AssignAddressItem_are_not_equal(
+        ptr_item_0_to_2,
+        job.ptr_assign_address_item(
+            dest_buffer_id=lattice_buffer_id,
+            src_buffer_id=output_buffer_id,
+            index=item_0_to_0_index))
+    assert job.total_num_assign_items == 3
+    assert job.has_assign_items(lattice_buffer_id, output_buffer_id)
+    assert job.num_assign_items(lattice_buffer_id, output_buffer_id) == 3
+    assert job.has_assign_item(item=out0_to_bm2_addr_assign_item)
+    assert job.has_assign_item(item=ptr_item_0_to_2)
+    assert job.has_assign_item(
+        dest_elem_type_id=beam_monitor_type_id,
+        dest_buffer_id=lattice_buffer_id,
+        dest_elem_index=bm2_index,
+        dest_pointer_offset=24,
+        src_elem_type_id=particle_set_type_id,
+        src_buffer_id=output_buffer_id,
+        src_elem_index=out_buffer0_index,
+        src_pointer_offset=0)
+
+    # --------------------------------------------------------------------------
+    # finish assembly of assign items:
+    job.commit_address_assignments()
+
+    # perform assignment of address items:
+    job.assign_all_addresses()
+
+    job.collect_beam_elements()
+    assert lattice.cbuffer.get_object(bm0_index).out_address != 0
+    assert lattice.cbuffer.get_object(bm1_index).out_address != 0
+    assert lattice.cbuffer.get_object(bm2_index).out_address != 0
+
+    # this only works on the CPU:
+    assert lattice.cbuffer.get_object(bm0_index).out_address == \
+        output_buffer.cbuffer.get_object(out_buffer0_index)._get_address()
+    assert lattice.cbuffer.get_object(bm1_index).out_address == \
+        output_buffer.cbuffer.get_object(out_buffer1_index)._get_address()
+    assert lattice.cbuffer.get_object(bm2_index).out_address == \
+        output_buffer.cbuffer.get_object(out_buffer0_index)._get_address()
diff --git a/tests/python/test_track_job_cpu_stored_buffer.py b/tests/python/test_track_job_cpu_stored_buffer.py
new file mode 100644
index 00000000..6b45e4ac
--- /dev/null
+++ b/tests/python/test_track_job_cpu_stored_buffer.py
@@ -0,0 +1,41 @@
+import cobjects
+from cobjects import CBuffer, CObject
+import sixtracklib as st
+
+if __name__ == '__main__':
+    lattice = st.Elements()
+    lattice.Drift(length=1.0)
+    pset = st.ParticlesSet()
+    pset.Particles(num_particles=100)
+
+    job = st.TrackJob(lattice, pset)
+
+    assert not job.has_stored_buffers
+    assert job.num_stored_buffers == 0
+    assert job.min_stored_buffer_id == 0
+    assert job.max_stored_buffer_id == 0
+
+    data_buffer = st.ParticlesSet()
+    out_data_index = data_buffer.cbuffer.n_objects
+    out_data = data_buffer.Particles(num_particles=1000)
+    assert data_buffer.cbuffer.n_objects == 1
+    assert data_buffer.cbuffer.size > 0
+
+    data_buffer_id = job.add_stored_buffer(cbuffer=data_buffer)
+    assert data_buffer_id != st.stcommon.st_ARCH_ILLEGAL_BUFFER_ID.value
+    assert job.has_stored_buffers
+    assert job.num_stored_buffers == 1
+    assert job.min_stored_buffer_id == data_buffer_id
+    assert job.max_stored_buffer_id == data_buffer_id
+
+    st_data_buffer = job.stored_buffer(data_buffer_id)
+    assert st_data_buffer.pointer != st.stcommon.st_NullBuffer
+    assert st_data_buffer.num_objects == data_buffer.cbuffer.n_objects
+    assert st_data_buffer.size == data_buffer.cbuffer.size
+
+    ptr_data_buffer = job.ptr_stored_buffer(data_buffer_id)
+    assert ptr_data_buffer != st.stcommon.st_NullBuffer
+    assert st.stcommon.st_Buffer_get_size(
+        ptr_data_buffer) == data_buffer.cbuffer.size
+    assert st.stcommon.st_Buffer_get_num_of_objects(
+        ptr_data_buffer) == data_buffer.cbuffer.n_objects
diff --git a/tests/sixtracklib/common/CMakeLists.txt b/tests/sixtracklib/common/CMakeLists.txt
index 314ad0b2..a6b2d0b5 100644
--- a/tests/sixtracklib/common/CMakeLists.txt
+++ b/tests/sixtracklib/common/CMakeLists.txt
@@ -1,6 +1,8 @@
 # sixtracklib/tests/sixtracklib/common/CMakeLists.txt
 
+add_subdirectory( buffer )
 add_subdirectory( control )
+add_subdirectory( math )
 add_subdirectory( beam_elements )
 add_subdirectory( track )
 
@@ -19,52 +21,7 @@ if( GTEST_FOUND )
 
     add_executable( test_tools_common_c99 test_tools_c99.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_tools_common_c99 )
-    add_test( C99_CommonToolTests test_tools_common_c99 )
-
-    # --------------------------------------------------------------------------
-    # test_managed_buffer_common_c99:
-
-    add_executable( test_managed_buffer_common_c99 test_managed_buffer_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_managed_buffer_common_c99 )
-    add_test( C99_CommonManagedBufferTest test_managed_buffer_common_c99 )
-
-    # --------------------------------------------------------------------------
-    # test_buffer_common_c99:
-
-    add_executable( test_buffer_common_c99 test_buffer_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_buffer_common_c99 )
-    add_test( C99_CommonBufferTest test_buffer_common_c99 )
-
-    # --------------------------------------------------------------------------
-    # test_buffer_common_cxx:
-
-    add_executable( test_buffer_common_cxx test_buffer_cxx.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_buffer_common_cxx )
-    add_test( CXX_CommonBufferTest test_buffer_common_cxx )
-
-    # ==========================================================================
-    # test_buffer_string_object_common_c99:
-
-    add_executable( test_buffer_string_object_common_c99
-                    test_buffer_string_object_c99.cpp )
-
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_buffer_string_object_common_c99 )
-
-    add_test( C99_CommonBufferStringObjectTests
-              test_buffer_string_object_common_c99 )
-
-    # -------------------------------------------------------------------------
-    # test_buffer_string_object_common_cxx:
-
-    add_executable( test_buffer_string_object_common_cxx
-                    test_buffer_string_object_cxx.cpp )
-
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_buffer_string_object_common_cxx )
-
-    add_test( CXX_CommonBufferStringObjectTests
-              test_buffer_string_object_common_cxx )
+    add_test( C99_Common_Tool test_tools_common_c99 )
 
     # ==========================================================================
     # test_gpu_kernel_tools_common_c99:
@@ -75,29 +32,21 @@ if( GTEST_FOUND )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
          test_gpu_kernel_tools_common_c99 )
 
-    add_test( C99_CommonGpuKernelTools
-              test_gpu_kernel_tools_common_c99 )
-
-    # --------------------------------------------------------------------------
-    # test_mem_pool_common_c99:
-
-    add_executable( test_mem_pool_common_c99      test_mem_pool_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}   test_mem_pool_common_c99 )
-    add_test( C99_CommonMemPoolTests              test_mem_pool_common_c99 )
+    add_test( C99_Common_GpuKernelTools test_gpu_kernel_tools_common_c99 )
 
     # ==========================================================================
     # test_particles_common_c99:
 
     add_executable( test_particles_common_c99     test_particles_c99.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}   test_particles_common_c99 )
-    add_test( C99_CommonParticlesTests            test_particles_common_c99 )
+    add_test( C99_Common_Particles                test_particles_common_c99 )
 
     # --------------------------------------------------------------------------
     # test_particles_common_cxx:
 
     add_executable( test_particles_common_cxx     test_particles_cxx.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}   test_particles_common_cxx )
-    add_test( CXX_CommonParticlesTests            test_particles_common_cxx )
+    add_test( CXX_Common_Particles                test_particles_common_cxx )
 
     # ==========================================================================
     # test_particles_aperture_check_enabled_common_c99:
@@ -106,14 +55,14 @@ if( GTEST_FOUND )
                     test_particles_aperture_c99.cpp )
 
     target_compile_options( test_particles_aperture_check_enabled_common_c99
-        BEFORE PRIVATE -DSIXTRL_ENABLE_APERTURE_CHECK=1
+        BEFORE PRIVATE -DSIXTRL_APERTURE_CHECK_AT_DRIFT=2
                        -DSIXTRL_APERTURE_X_LIMIT=1.0
                        -DSIXTRL_APERTURE_Y_LIMIT=1.0 )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
          test_particles_aperture_check_enabled_common_c99 )
 
-    add_test( C99_CommonParticlesApertureEnabledTests
+    add_test( C99_Common_Particles_ApertureEnabled
               test_particles_aperture_check_enabled_common_c99 )
 
     # ------------------------------------------------------------------------
@@ -123,12 +72,12 @@ if( GTEST_FOUND )
                     test_particles_aperture_c99.cpp )
 
     target_compile_options( test_particles_aperture_check_disabled_common_c99
-        BEFORE PRIVATE -DSIXTRL_ENABLE_APERTURE_CHECK=0 )
+        BEFORE PRIVATE -DSIXTRL_APERTURE_CHECK_AT_DRIFT=0 )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
          test_particles_aperture_check_disabled_common_c99 )
 
-    add_test( C99_CommonParticlesApertureDisabledTests
+    add_test( C99_Common_Particles_ApertureDisabled
               test_particles_aperture_check_disabled_common_c99 )
 
     # --------------------------------------------------------------------------
@@ -137,8 +86,8 @@ if( GTEST_FOUND )
     add_executable( test_elem_by_elem_config_c99
                     test_elem_by_elem_config_c99.cpp )
 
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_elem_by_elem_config_c99 )
-    add_test( C99_CommonElemByElemConfigTests   test_elem_by_elem_config_c99 )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}  test_elem_by_elem_config_c99 )
+    add_test( C99_Common_Output_ElemByElemConfig test_elem_by_elem_config_c99 )
 
     # --------------------------------------------------------------------------
     # test_faddeeva_errf:
@@ -166,35 +115,29 @@ if( GTEST_FOUND )
 
     add_executable( test_output_buffer_common_c99 test_output_buffer_c99.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_output_buffer_common_c99 )
-    add_test( C99_CommonOutputBufferTests test_output_buffer_common_c99 )
-
-    # ==========================================================================
-    # test_track_common_c99:
-
-    add_executable( test_track_common_c99 test_track_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_common_c99 )
-    add_test( C99_CommonTrackTests test_track_common_c99 )
+    add_test( C99_Common_Output_OutputBufferCommon
+              test_output_buffer_common_c99 )
 
     # ==========================================================================
     # test_track_line_common_c99:
 
     add_executable( test_track_line_common_c99 test_track_line_c99.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_line_common_c99 )
-    add_test( C99_CommonTrackLineTests test_track_line_common_c99 )
+    add_test( C99_Common_Track_TrackLineCommon test_track_line_common_c99 )
 
     # ==========================================================================
     # test_track_job_common_c99:
 
 #     add_executable( test_track_job_common_c99 test_track_job_c99.cpp )
 #     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_job_common_c99 )
-#     add_test( C99_CommonTrackJobTests, test_track_job_common_c99 )
+#     add_test( C99_Common_Track_TrackJobCommon, test_track_job_common_c99 )
 
     # --------------------------------------------------------------------------
     # test_track_job_common_cxx:
 
     add_executable( test_track_job_common_cxx test_track_job_cxx.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_job_common_cxx )
-    add_test( CXX_CommonTrackJobTests, test_track_job_common_cxx )
+    add_test( CXX_Common_Track_TrackJobCommon, test_track_job_common_cxx )
 
     # ==========================================================================
     # test_track_job_cpu_common_c99:
@@ -202,7 +145,7 @@ if( GTEST_FOUND )
     add_executable( test_track_job_cpu_common_c99 test_track_job_cpu_c99.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_job_cpu_common_c99 )
-    add_test( C99_CommonTrackJobCpuTests test_track_job_cpu_common_c99 )
+    add_test( C99_Common_Track_TrackJobCpu test_track_job_cpu_common_c99 )
 
     # --------------------------------------------------------------------------
     # test_track_job_cpu_cxx:
@@ -210,30 +153,58 @@ if( GTEST_FOUND )
     add_executable( test_track_job_cpu_common_cxx test_track_job_cpu_cxx.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_job_cpu_common_cxx )
-    add_test( CXX_CommonTrackJobCpuTests test_track_job_cpu_common_cxx )
+    add_test( CXX_Common_Track_TrackJobCpu test_track_job_cpu_common_cxx )
 
     # --------------------------------------------------------------------------
 
     if( SIXTRACKL_ENABLE_AUTOVECTORIZATION )
         add_executable( test_track_common_autovec_c99 test_track_c99.cpp )
-        set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_common_autovec_c99 )
-
         target_compile_options( test_track_common_autovec_c99 BEFORE PRIVATE
-            -ftree-vectorize -ftree-vectorizer-verbose=6 -fopt-info-loop
-            -fno-fast-math --param vect-max-version-for-alias-checks=150 )
+            ${SIXTRACKL_C_ENABLED_AUTOVEC_FLAGS} )
+        add_test( C99_Common_Track_AutoVec test_track_common_autovec_c99 )
 
-        add_test( C99_CommonTrackTestsAutoVec test_track_common_autovec_c99 )
+        set_target_properties( test_track_common_autovec_c99 PROPERTIES
+            POSITION_INDEPENDENT_CODE ON CXX_STANDARD 11
+            CXX_STANDARD_REQUIRED ON )
 
+        target_include_directories( test_track_common_autovec_c99 BEFORE PRIVATE
+            $<BUILD_INTERFACE:${SIXTRACKL_GTEST_INCLUDE_DIRS}>
+            $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
+            $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/tests> )
+
+        target_link_libraries( test_track_common_autovec_c99
+            ${SIXTRACKL_TEST_LIBRARIES} )
+
+        target_compile_options( test_track_common_autovec_c99
+            BEFORE PRIVATE ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+            ${SIXTRACKL_CXX_ENABLED_AUTOVEC_FLAGS} )
     endif()
 
+    # -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
+
+    add_executable( test_track_common_c99 test_track_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_common_c99 )
+    add_test( C99_Common_Track_DisabledAutoVec test_track_common_c99 )
+
+    set_target_properties( test_track_common_c99 PROPERTIES
+        POSITION_INDEPENDENT_CODE ON CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON )
+
+    target_include_directories( test_track_common_c99 BEFORE PRIVATE
+        $<BUILD_INTERFACE:${SIXTRACKL_GTEST_INCLUDE_DIRS}>
+        $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
+        $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/tests> )
+
+    target_link_libraries( test_track_common_c99 ${SIXTRACKL_TEST_LIBRARIES} )
+
+    target_compile_options( test_track_common_c99
+        BEFORE PRIVATE ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_CXX_DISABLED_AUTOVEC_FLAGS} )
+
     # *************************************************************************
     # Set all properties:
 
-    set_property(
-        TARGET ${UNIT_TEST_TARGETS}
-        APPEND PROPERTY INCLUDE_DIRECTORIES
-        $<BUILD_INTERFACE:${SIXTRACKL_GTEST_INCLUDE_DIRS}>
-    )
+    set_property( TARGET ${UNIT_TEST_TARGETS} APPEND PROPERTY
+        INCLUDE_DIRECTORIES $<BUILD_INTERFACE:${SIXTRACKL_GTEST_INCLUDE_DIRS}> )
 
     set_property( TARGET ${UNIT_TEST_TARGETS}
                   PROPERTY LINK_LIBRARIES ${SIXTRACKL_TEST_LIBRARIES} )
@@ -241,16 +212,9 @@ if( GTEST_FOUND )
     set_property( TARGET ${UNIT_TEST_TARGETS} PROPERTY CXX_STANDARD 11 )
     set_property( TARGET ${UNIT_TEST_TARGETS} PROPERTY CXX_STANDARD_REQUIRED ON )
 
-    set_property( TARGET ${UNIT_TEST_TARGETS}
-                  APPEND PROPERTY COMPILE_OPTIONS
-                  ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
-
-endif()
-
-# ------------------------------------------------------------------------------
-# --- benchmark drifts:
-
-if( SIXTRACKL_ENABLE_BENCHMARKS )
+    set_property( TARGET ${UNIT_TEST_TARGETS} APPEND PROPERTY COMPILE_OPTIONS
+        ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_CXX_AUTOVEC_FLAGS} )
 
 
 endif()
diff --git a/tests/sixtracklib/common/beam_elements/CMakeLists.txt b/tests/sixtracklib/common/beam_elements/CMakeLists.txt
index 6daeac32..5d227b95 100644
--- a/tests/sixtracklib/common/beam_elements/CMakeLists.txt
+++ b/tests/sixtracklib/common/beam_elements/CMakeLists.txt
@@ -9,23 +9,23 @@ if( GTEST_FOUND )
     # ==========================================================================
     # test_be_drift_common_c99:
 
-    add_executable( test_be_drift_common_c99      test_be_drift_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}   test_be_drift_common_c99 )
-    add_test( C99_CommonBeamElementDriftTests     test_be_drift_common_c99 )
+    add_executable( test_be_drift_common_c99    test_be_drift_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_be_drift_common_c99 )
+    add_test( C99_Common_BeamElement_Drift      test_be_drift_common_c99 )
 
     # --------------------------------------------------------------------------
     # test_be_drift_common_cxx:
 
-    add_executable( test_be_drift_common_cxx    test_be_drift_cxx.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_be_drift_common_cxx )
-    add_test( CXX_CommonBeamElementDriftTests   test_be_drift_common_cxx )
+    add_executable( test_be_drift_common_cxx      test_be_drift_cxx.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}   test_be_drift_common_cxx )
+    add_test( CXX_Common_BeamElements_Drift_Tests test_be_drift_common_cxx )
 
     # ==========================================================================
     # test_be_multipole_common_c99:
 
-    add_executable( test_be_multipole_common_c99  test_be_multipole_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}   test_be_multipole_common_c99 )
-    add_test( C99_CommonBeamElementMultiPoleTests test_be_multipole_common_c99 )
+    add_executable( test_be_multipole_common_c99 test_be_multipole_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}  test_be_multipole_common_c99 )
+    add_test( C99_Common_BeamElement_MultiPole   test_be_multipole_common_c99 )
 
     # ==========================================================================
     # test_be_rf_multipole_common_c99:
@@ -36,54 +36,50 @@ if( GTEST_FOUND )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
             test_be_rf_multipole_common_c99 )
 
-    add_test( C99_Common_BeamElements_RFMultiPoleTests
-            test_be_rf_multipole_common_c99 )
+    add_test( C99_Common_BeamElement_RFMultiPole
+        test_be_rf_multipole_common_c99 )
 
     # ==========================================================================
     # test_be_xy_shift_common_c99:
 
-    add_executable( test_be_xy_shift_common_c99   test_be_xy_shift_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}   test_be_xy_shift_common_c99 )
-    add_test( C99_CommonBeamElementXYShiftTests   test_be_xy_shift_common_c99 )
+    add_executable( test_be_xy_shift_common_c99  test_be_xy_shift_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}  test_be_xy_shift_common_c99 )
+    add_test( C99_Common_BeamElement_XYShift     test_be_xy_shift_common_c99 )
 
     # ==========================================================================
     # test_be_srotation_common_c99:
 
-    add_executable( test_be_srotation_common_c99  test_be_srotation_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}   test_be_srotation_common_c99 )
-    add_test( C99_CommonBeamElementSRotationTests test_be_srotation_common_c99 )
+    add_executable( test_be_srotation_common_c99 test_be_srotation_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}  test_be_srotation_common_c99 )
+    add_test( C99_Common_BeamElement_SRotation   test_be_srotation_common_c99 )
 
     # ==========================================================================
     # test_be_cavity_common_c99:
 
-    add_executable( test_be_cavity_common_c99   test_be_cavity_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_be_cavity_common_c99 )
-    add_test( C99_CommonBeamElementCavityTests  test_be_cavity_common_c99 )
+    add_executable( test_be_cavity_common_c99    test_be_cavity_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}  test_be_cavity_common_c99 )
+    add_test( C99_Common_BeamElement_Cavity      test_be_cavity_common_c99 )
 
     # ==========================================================================
     # test_be_monitor_common_c99:
 
     add_executable( test_be_monitor_common_c99   test_be_monitor_c99.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}  test_be_monitor_common_c99 )
-    add_test( C99_CommonBeamMonitorTests         test_be_monitor_common_c99 )
+    add_test( C99_Common_BeamElement_BeamMonitor test_be_monitor_common_c99 )
 
     # ==========================================================================
     # test_be_limit_rect_common_c99:
 
     add_executable( test_be_limit_rect_common_c99  test_be_limit_rect_c99.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_be_limit_rect_common_c99 )
-
-    add_test( C99_CommonBeamElementLimitRectTests
-              test_be_limit_rect_common_c99 )
+    add_test( C99_Common_BeamElement_LimitRect  test_be_limit_rect_common_c99 )
 
     # --------------------------------------------------------------------------
     # test_be_limit_rect_common_cxx:
 
     add_executable( test_be_limit_rect_common_cxx  test_be_limit_rect_cxx.cpp )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_be_limit_rect_common_cxx )
-
-    add_test( CXX_CommonBeamElementLimitRectTests
-              test_be_limit_rect_common_cxx )
+    add_test( CXX_Common_BeamElement_LimitRect  test_be_limit_rect_common_cxx )
 
     # ==========================================================================
     # test_be_limit_ellipse_common_c99:
@@ -94,8 +90,8 @@ if( GTEST_FOUND )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
          test_be_limit_ellipse_common_c99 )
 
-    add_test( C99_CommonBeamElementLimitEllipseTests
-              test_be_limit_ellipse_common_c99 )
+    add_test( C99_Common_BeamElement_LimitEllipse
+         test_be_limit_ellipse_common_c99 )
 
     # --------------------------------------------------------------------------
     # test_be_limit_ellipse_common_cxx:
@@ -106,30 +102,29 @@ if( GTEST_FOUND )
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
          test_be_limit_ellipse_common_cxx )
 
-    add_test( CXX_CommonBeamElementLimitEllipseTests
-              test_be_limit_ellipse_common_cxx )
+    add_test( CXX_Common_BeamElement_LimitEllipse
+         test_be_limit_ellipse_common_cxx )
 
     # ==========================================================================
     # test_be_dipedge_common_c99:
 
-    add_executable( test_be_dipedge_common_c99     test_be_dipedge_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}    test_be_dipedge_common_c99 )
-    add_test( C99_CommonBeamElementDipoleEdgeTests test_be_dipedge_common_c99 )
+    add_executable( test_be_dipedge_common_c99  test_be_dipedge_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_be_dipedge_common_c99 )
+    add_test( C99_Common_BeamElement_DipoleEdge test_be_dipedge_common_c99 )
 
     # --------------------------------------------------------------------------
     # test_be_dipedge_common_cxx:
 
-    add_executable( test_be_dipedge_common_cxx     test_be_dipedge_cxx.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}    test_be_dipedge_common_cxx )
-    add_test( CXX_CommonBeamElementDipoleEdgeTests test_be_dipedge_common_cxx )
+    add_executable( test_be_dipedge_common_cxx test_be_dipedge_cxx.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_be_dipedge_common_cxx )
+    add_test( CXX_Common_BeamElement_DipoleEdgeTests
+                test_be_dipedge_common_cxx )
 
     # *************************************************************************
     # Set all properties:
 
-    set_property( TARGET ${UNIT_TEST_TARGETS}
-        APPEND PROPERTY INCLUDE_DIRECTORIES
-        $<BUILD_INTERFACE:${SIXTRACKL_GTEST_INCLUDE_DIRS}>
-    )
+    set_property( TARGET ${UNIT_TEST_TARGETS} APPEND PROPERTY
+        INCLUDE_DIRECTORIES $<BUILD_INTERFACE:${SIXTRACKL_GTEST_INCLUDE_DIRS}> )
 
     set_property( TARGET ${UNIT_TEST_TARGETS}
                   PROPERTY LINK_LIBRARIES ${SIXTRACKL_TEST_LIBRARIES} )
diff --git a/tests/sixtracklib/common/beam_elements/test_be_cavity_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_cavity_c99.cpp
index fdef4cb7..11695024 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_cavity_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_cavity_c99.cpp
@@ -19,15 +19,15 @@
 #include "sixtracklib/common/be_cavity/be_cavity.h"
 
 /* ************************************************************************* *
- * ******  st_Cavity:
+ * ****** NS(Cavity):
  * ************************************************************************* */
 
-TEST( C99_CommonBeamElementCavityTests, MinimalAddToBufferCopyRemapRead )
+TEST( C99CommonBeamElementCavity, MinimalAddToBufferCopyRemapRead )
 {
-    using size_t   = ::st_buffer_size_t;
-    using object_t = ::st_Object;
+    using size_t   = NS(buffer_size_t);
+    using object_t = NS(Object);
     using raw_t    = unsigned char;
-    using belem_t  = ::st_Cavity;
+    using belem_t  = NS(Cavity);
     using real_t   = SIXTRL_REAL_T;
 
     static double const ZERO = double{ 0.0 };
@@ -51,10 +51,10 @@ TEST( C99_CommonBeamElementCavityTests, MinimalAddToBufferCopyRemapRead )
     static SIXTRL_CONSTEXPR_OR_CONST size_t
         NUM_BEAM_ELEMENTS = size_t{ 1000 };
 
-    ::st_object_type_id_t const BEAM_ELEMENT_TYPE_ID = ::st_OBJECT_TYPE_CAVITY;
+    NS(object_type_id_t) const BEAM_ELEMENT_TYPE_ID = NS(OBJECT_TYPE_CAVITY);
     std::vector< belem_t > orig_beam_elements( NUM_BEAM_ELEMENTS, belem_t{} );
 
-    size_t const slot_size      = ::st_BUFFER_DEFAULT_SLOT_SIZE;
+    size_t const slot_size      = NS(BUFFER_DEFAULT_SLOT_SIZE);
     size_t const num_objs       = NUM_BEAM_ELEMENTS;
     size_t const num_garbage    = size_t{ 0 };
     size_t const num_dataptrs   = size_t{ 0 };
@@ -66,31 +66,31 @@ TEST( C99_CommonBeamElementCavityTests, MinimalAddToBufferCopyRemapRead )
         real_t const frequency = frequency_dist( prng );
         real_t const lag       = lag_dist( prng );
 
-        belem_t* ptr_cav = ::st_Cavity_preset( &orig_beam_elements[ ii ] );
+        belem_t* ptr_cav = NS(Cavity_preset)( &orig_beam_elements[ ii ] );
         ASSERT_TRUE( ptr_cav != nullptr );
-        ::st_Cavity_set_voltage( ptr_cav, voltage );
-        ::st_Cavity_set_frequency( ptr_cav, frequency );
-        ::st_Cavity_set_lag( ptr_cav, lag );
+        NS(Cavity_set_voltage)( ptr_cav, voltage );
+        NS(Cavity_set_frequency)( ptr_cav, frequency );
+        NS(Cavity_set_lag)( ptr_cav, lag );
 
         ASSERT_TRUE( EPS > std::fabs(
-            voltage  - ::st_Cavity_get_voltage( ptr_cav ) ) );
+            voltage  - NS(Cavity_voltage)( ptr_cav ) ) );
 
         ASSERT_TRUE( EPS > std::fabs(
-            frequency - ::st_Cavity_get_frequency( ptr_cav ) ) );
+            frequency - NS(Cavity_frequency)( ptr_cav ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( lag - ::st_Cavity_get_lag( ptr_cav ) ) );
+        ASSERT_TRUE( EPS > std::fabs( lag - NS(Cavity_lag)( ptr_cav ) ) );
 
-        num_slots += ::st_ManagedBuffer_predict_required_num_slots( nullptr,
-            sizeof( ::st_Cavity ), ::st_Cavity_get_num_dataptrs( ptr_cav ),
+        num_slots += NS(ManagedBuffer_predict_required_num_slots)( nullptr,
+            sizeof( NS(Cavity) ), NS(Cavity_num_dataptrs)( ptr_cav ),
                 nullptr, nullptr, slot_size );
     }
 
     /* --------------------------------------------------------------------- */
 
-    size_t const requ_buffer_size = ::st_ManagedBuffer_calculate_buffer_length(
+    size_t const requ_buffer_size = NS(ManagedBuffer_calculate_buffer_length)(
         nullptr, num_objs, num_slots, num_dataptrs, num_garbage, slot_size );
 
-    ::st_Buffer* eb = ::st_Buffer_new( requ_buffer_size );
+    NS(Buffer)* eb = NS(Buffer_new)( requ_buffer_size );
     ASSERT_TRUE( eb != nullptr );
 
     /* --------------------------------------------------------------------- */
@@ -99,114 +99,114 @@ TEST( C99_CommonBeamElementCavityTests, MinimalAddToBufferCopyRemapRead )
     belem_t* ptr_orig = &orig_beam_elements[ be_index++ ];
     ASSERT_TRUE( ptr_orig != nullptr );
 
-    object_t* ptr_object = ::st_Buffer_add_object( eb, ptr_orig, sizeof( belem_t ),
-        BEAM_ELEMENT_TYPE_ID, ::st_Cavity_get_num_dataptrs( ptr_orig ),
+    object_t* ptr_object = NS(Buffer_add_object)( eb, ptr_orig, sizeof( belem_t ),
+        BEAM_ELEMENT_TYPE_ID, NS(Cavity_num_dataptrs)( ptr_orig ),
             nullptr, nullptr, nullptr );
 
     ASSERT_TRUE( ptr_object != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-    ASSERT_TRUE( ::st_Object_get_const_begin_ptr( ptr_object ) != nullptr );
-    ASSERT_TRUE( ::st_Object_get_size( ptr_object ) >= sizeof( belem_t ) );
-    ASSERT_TRUE( ::st_Object_get_type_id( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+    ASSERT_TRUE( NS(Object_get_const_begin_ptr)( ptr_object ) != nullptr );
+    ASSERT_TRUE( NS(Object_get_size)( ptr_object ) >= sizeof( belem_t ) );
+    ASSERT_TRUE( NS(Object_get_type_id)( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
 
     belem_t* ptr_cav = reinterpret_cast< belem_t* >(
-        ::st_Object_get_begin_ptr( ptr_object ) );
+        NS(Object_get_begin_ptr)( ptr_object ) );
 
     ASSERT_TRUE( ptr_cav != nullptr );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_voltage( ptr_cav ) -
-                                  ::st_Cavity_get_voltage( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_voltage)( ptr_cav ) -
+                                  NS(Cavity_voltage)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_frequency( ptr_cav ) -
-                                  ::st_Cavity_get_frequency( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_frequency)( ptr_cav ) -
+                                  NS(Cavity_frequency)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_lag( ptr_cav ) -
-                                  ::st_Cavity_get_lag( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_lag)( ptr_cav ) -
+                                  NS(Cavity_lag)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_cav = ::st_Cavity_new( eb );
+    ptr_cav = NS(Cavity_new)( eb );
 
     ASSERT_TRUE( ptr_cav != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_voltage( ptr_cav ) - ZERO ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_voltage)( ptr_cav ) - ZERO ) );
 
-    ::st_Cavity_set_voltage( ptr_cav, ::st_Cavity_get_voltage( ptr_orig ) );
-    ::st_Cavity_set_frequency( ptr_cav, ::st_Cavity_get_frequency( ptr_orig ) );
-    ::st_Cavity_set_lag( ptr_cav, ::st_Cavity_get_lag( ptr_orig ) );
+    NS(Cavity_set_voltage)( ptr_cav, NS(Cavity_voltage)( ptr_orig ) );
+    NS(Cavity_set_frequency)( ptr_cav, NS(Cavity_frequency)( ptr_orig ) );
+    NS(Cavity_set_lag)( ptr_cav, NS(Cavity_lag)( ptr_orig ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_voltage( ptr_cav ) -
-                                  ::st_Cavity_get_voltage( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_voltage)( ptr_cav ) -
+                                  NS(Cavity_voltage)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_frequency( ptr_cav ) -
-                                  ::st_Cavity_get_frequency( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_frequency)( ptr_cav ) -
+                                  NS(Cavity_frequency)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_lag( ptr_cav ) -
-                                  ::st_Cavity_get_lag( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_lag)( ptr_cav ) -
+                                  NS(Cavity_lag)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_cav = ::st_Cavity_add( eb,
-        ::st_Cavity_get_voltage( ptr_orig ),
-        ::st_Cavity_get_frequency( ptr_orig ),
-        ::st_Cavity_get_lag( ptr_orig ) );
+    ptr_cav = NS(Cavity_add)( eb,
+        NS(Cavity_voltage)( ptr_orig ),
+        NS(Cavity_frequency)( ptr_orig ),
+        NS(Cavity_lag)( ptr_orig ) );
 
     ASSERT_TRUE( ptr_cav != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_voltage( ptr_cav ) -
-                                  ::st_Cavity_get_voltage( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_voltage)( ptr_cav ) -
+                                  NS(Cavity_voltage)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_frequency( ptr_cav ) -
-                                  ::st_Cavity_get_frequency( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_frequency)( ptr_cav ) -
+                                  NS(Cavity_frequency)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_lag( ptr_cav ) -
-                                  ::st_Cavity_get_lag( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Cavity_lag)( ptr_cav ) -
+                                  NS(Cavity_lag)( ptr_orig  ) ) );
 
     for( ; be_index < NUM_BEAM_ELEMENTS ; )
     {
         ptr_orig  = &orig_beam_elements[ be_index++ ];
-        ptr_cav = ::st_Cavity_add( eb,
-            ::st_Cavity_get_voltage( ptr_orig ),
-            ::st_Cavity_get_frequency( ptr_orig ),
-            ::st_Cavity_get_lag( ptr_orig ) );
+        ptr_cav = NS(Cavity_add)( eb,
+            NS(Cavity_voltage)( ptr_orig ),
+            NS(Cavity_frequency)( ptr_orig ),
+            NS(Cavity_lag)( ptr_orig ) );
 
         ASSERT_TRUE( ptr_cav != nullptr );
-        ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+        ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_voltage( ptr_cav ) -
-                                  ::st_Cavity_get_voltage( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_voltage)( ptr_cav ) -
+                                  NS(Cavity_voltage)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_frequency( ptr_cav ) -
-                                    ::st_Cavity_get_frequency( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_frequency)( ptr_cav ) -
+                                    NS(Cavity_frequency)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_lag( ptr_cav ) -
-                                    ::st_Cavity_get_lag( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_lag)( ptr_cav ) -
+                                    NS(Cavity_lag)( ptr_orig  ) ) );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ASSERT_TRUE( ::st_Buffer_get_size( eb ) > size_t{ 0 } );
+    ASSERT_TRUE( NS(Buffer_get_size)( eb ) > size_t{ 0 } );
 
-    std::vector< raw_t > data_buffer( ::st_Buffer_get_size( eb ), raw_t{ 0 } );
-    data_buffer.assign( ::st_Buffer_get_const_data_begin( eb ),
-                        ::st_Buffer_get_const_data_end( eb ) );
+    std::vector< raw_t > data_buffer( NS(Buffer_get_size)( eb ), raw_t{ 0 } );
+    data_buffer.assign( NS(Buffer_get_const_data_begin)( eb ),
+                        NS(Buffer_get_const_data_end)( eb ) );
 
-    ::st_Buffer cmp_buffer;
-    ::st_Buffer_preset( &cmp_buffer );
-    int success = ::st_Buffer_init(
+    NS(Buffer) cmp_buffer;
+    NS(Buffer_preset)( &cmp_buffer );
+    int success = NS(Buffer_init)(
         &cmp_buffer, data_buffer.data(), data_buffer.size() );
 
     ASSERT_TRUE( success == 0 );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) ==
-                 ::st_Buffer_get_num_of_objects( &cmp_buffer ) );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) ==
+                 NS(Buffer_get_num_of_objects)( &cmp_buffer ) );
 
-    object_t const* obj_it  = ::st_Buffer_get_const_objects_begin( eb );
-    object_t const* obj_end = ::st_Buffer_get_const_objects_end( eb );
-    object_t const* cmp_it  = ::st_Buffer_get_const_objects_begin( &cmp_buffer );
+    object_t const* obj_it  = NS(Buffer_get_const_objects_begin)( eb );
+    object_t const* obj_end = NS(Buffer_get_const_objects_end)( eb );
+    object_t const* cmp_it  = NS(Buffer_get_const_objects_begin)( &cmp_buffer );
 
     be_index = size_t{ 0 };
 
@@ -214,19 +214,19 @@ TEST( C99_CommonBeamElementCavityTests, MinimalAddToBufferCopyRemapRead )
     {
         ptr_orig = &orig_beam_elements[ be_index++ ];
 
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) == BEAM_ELEMENT_TYPE_ID );
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) ==
-                     ::st_Object_get_type_id( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) == BEAM_ELEMENT_TYPE_ID );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) ==
+                     NS(Object_get_type_id)( cmp_it ) );
 
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) >= sizeof( belem_t ) );
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) ==
-                     ::st_Object_get_size( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) >= sizeof( belem_t ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) ==
+                     NS(Object_get_size)( cmp_it ) );
 
         belem_t const* elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( obj_it ) );
+            NS(Object_get_const_begin_ptr)( obj_it ) );
 
         belem_t const* cmp_elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( cmp_it ) );
+            NS(Object_get_const_begin_ptr)( cmp_it ) );
 
         ASSERT_TRUE( ptr_orig != elem );
         ASSERT_TRUE( ptr_orig != cmp_elem );
@@ -235,29 +235,27 @@ TEST( C99_CommonBeamElementCavityTests, MinimalAddToBufferCopyRemapRead )
         ASSERT_TRUE( cmp_elem != nullptr );
         ASSERT_TRUE( cmp_elem != elem    );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_voltage( elem ) -
-                                  ::st_Cavity_get_voltage( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_voltage)( elem ) -
+                                  NS(Cavity_voltage)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_frequency( elem ) -
-                                    ::st_Cavity_get_frequency( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_frequency)( elem ) -
+                                    NS(Cavity_frequency)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_lag( elem ) -
-                                    ::st_Cavity_get_lag( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_lag)( elem ) -
+                                    NS(Cavity_lag)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_voltage( cmp_elem ) -
-                                  ::st_Cavity_get_voltage( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_voltage)( cmp_elem ) -
+                                  NS(Cavity_voltage)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_frequency( cmp_elem ) -
-                                    ::st_Cavity_get_frequency( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_frequency)( cmp_elem ) -
+                                    NS(Cavity_frequency)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_Cavity_get_lag( cmp_elem ) -
-                                    ::st_Cavity_get_lag( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Cavity_lag)( cmp_elem ) -
+                                    NS(Cavity_lag)( ptr_orig  ) ) );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ::st_Buffer_delete( eb );
-    ::st_Buffer_free( &cmp_buffer );
+    NS(Buffer_delete)( eb );
+    NS(Buffer_free)( &cmp_buffer );
 }
-
-/* end: tests/sixtracklib/common/test_be_cavity_c99.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_dipedge_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_dipedge_c99.cpp
index 6cd1d024..959d9442 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_dipedge_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_dipedge_c99.cpp
@@ -14,29 +14,27 @@
 #include "sixtracklib/common/control/definitions.h"
 #include "sixtracklib/common/buffer.h"
 
-TEST( C99_CommonBeamElementDipoleEdgeTests, BasicUsage )
+TEST( C99CommonBeamElementDipoleEdge, BasicUsage )
 {
     using be_dipedge_t = ::NS(DipoleEdge);
     using buffer_t     = ::NS(Buffer);
     using size_t       = ::NS(buffer_size_t);
-    
+
     be_dipedge_t e1;
     ::NS(DipoleEdge_preset)( &e1 );
-    
+
     buffer_t* eb = ::NS(Buffer_new)( size_t{ 0 } );
     SIXTRL_ASSERT( eb != nullptr );
-    
+
     be_dipedge_t* e2 = ::NS(DipoleEdge_new)( eb );
     ASSERT_TRUE( e2 != nullptr );
-    
+
     be_dipedge_t* e3 = ::NS(DipoleEdge_add)( eb, 1.0, 2.0 );
     ASSERT_TRUE( e3 != nullptr );
-    
+
     be_dipedge_t* e4 = ::NS(DipoleEdge_add_copy)( eb, &e1 );
     ASSERT_TRUE( e4 != nullptr );
     ASSERT_TRUE( 0 == ::NS(DipoleEdge_compare_values)( e4, &e1 ) );
-    
+
     ::NS(Buffer_delete)( eb );
 }
-
-/* end: tests/sixtracklib/common/beam_elements/test_be_limit_c99.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_dipedge_cxx.cpp b/tests/sixtracklib/common/beam_elements/test_be_dipedge_cxx.cpp
index 1faee594..414f29e5 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_dipedge_cxx.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_dipedge_cxx.cpp
@@ -14,29 +14,27 @@
 #include "sixtracklib/common/control/definitions.h"
 #include "sixtracklib/common/buffer.hpp"
 
-TEST( CXX_CommonBeamElementDipoleEdgeTests, BasicUsage )
+TEST( CXXCommonBeamElementDipoleEdge, BasicUsage )
 {
     namespace st = SIXTRL_CXX_NAMESPACE;
-    
+
     using be_dipedge_t = st::DipoleEdge;
     using buffer_t     = st::Buffer;
-    
+
     be_dipedge_t e1;
     e1.preset();
-    
+
     buffer_t eb;
-        
+
     be_dipedge_t* e2 = eb.createNew< be_dipedge_t >();
     ASSERT_TRUE( e2 != nullptr );
-    
+
     be_dipedge_t* e3 = eb.add< be_dipedge_t >( 1.0, 2.0 );
     ASSERT_TRUE( e3 != nullptr );
-    
+
     be_dipedge_t* e4 = eb.addCopy( e1 );
     ASSERT_TRUE( e4 != nullptr );
-    
-    ASSERT_TRUE( 0 == ::NS(DipoleEdge_compare_values)( 
+
+    ASSERT_TRUE( 0 == ::NS(DipoleEdge_compare_values)(
         e4->getCApiPtr(), e1.getCApiPtr() ) );
 }
-
-/* end: tests/sixtracklib/common/beam_elements/test_be_limit_cxx.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_drift_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_drift_c99.cpp
index f219c8c6..36e9f2d8 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_drift_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_drift_c99.cpp
@@ -18,15 +18,15 @@
 #include "sixtracklib/common/be_drift/be_drift.h"
 
 /* ************************************************************************* *
- * ******  st_Drift:
+ * ****** NS(Drift):
  * ************************************************************************* */
 
-TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
+TEST( C99CommonBeamElementDrift, MinimalAddToBufferCopyRemapRead )
 {
-    using size_t   = ::st_buffer_size_t;
-    using object_t = ::st_Object;
+    using size_t   = NS(buffer_size_t);
+    using object_t = NS(Object);
     using raw_t    = unsigned char;
-    using belem_t  = ::st_Drift;
+    using belem_t  = NS(Drift);
     using real_t   = SIXTRL_REAL_T;
 
     static double const ZERO = double{ 0.0 };
@@ -46,10 +46,10 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
     static SIXTRL_CONSTEXPR_OR_CONST size_t
         NUM_BEAM_ELEMENTS = size_t{ 1000 };
 
-    ::st_object_type_id_t const BEAM_ELEMENT_TYPE_ID = ::st_OBJECT_TYPE_DRIFT;
+    NS(object_type_id_t) const BELEM_TYPE_ID = NS(OBJECT_TYPE_DRIFT);
     std::vector< belem_t > orig_beam_elements( NUM_BEAM_ELEMENTS, belem_t{} );
 
-    size_t const slot_size      = ::st_BUFFER_DEFAULT_SLOT_SIZE;
+    size_t const slot_size      = NS(BUFFER_DEFAULT_SLOT_SIZE);
     size_t const num_objs       = NUM_BEAM_ELEMENTS;
     size_t const num_garbage    = size_t{ 0 };
     size_t const num_dataptrs   = size_t{ 0 };
@@ -59,23 +59,23 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
     {
         real_t const length = length_dist( prng );
 
-        belem_t* ptr_drift = ::st_Drift_preset( &orig_beam_elements[ ii ] );
+        belem_t* ptr_drift = NS(Drift_preset)( &orig_beam_elements[ ii ] );
         ASSERT_TRUE( ptr_drift != nullptr );
-        ::st_Drift_set_length( ptr_drift, length );
+        NS(Drift_set_length)( ptr_drift, length );
 
-        ASSERT_TRUE( std::fabs( length - ::st_Drift_get_length( ptr_drift ) ) < EPS );
+        ASSERT_TRUE( std::fabs( length - NS(Drift_length)( ptr_drift ) ) < EPS );
 
-        num_slots += ::st_ManagedBuffer_predict_required_num_slots( nullptr,
-            sizeof( ::st_Drift ), ::st_Drift_get_num_dataptrs( ptr_drift ),
+        num_slots += NS(ManagedBuffer_predict_required_num_slots)( nullptr,
+            sizeof( NS(Drift) ), NS(Drift_num_dataptrs)( ptr_drift ),
                 nullptr, nullptr, slot_size );
     }
 
     /* --------------------------------------------------------------------- */
 
-    size_t const requ_buffer_size = ::st_ManagedBuffer_calculate_buffer_length(
+    size_t const requ_buffer_size = NS(ManagedBuffer_calculate_buffer_length)(
         nullptr, num_objs, num_slots, num_dataptrs, num_garbage, slot_size );
 
-    ::st_Buffer* eb = ::st_Buffer_new( requ_buffer_size );
+    NS(Buffer)* eb = NS(Buffer_new)( requ_buffer_size );
     ASSERT_TRUE( eb != nullptr );
 
     /* --------------------------------------------------------------------- */
@@ -84,78 +84,78 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
     belem_t* ptr_orig = &orig_beam_elements[ be_index++ ];
     ASSERT_TRUE( ptr_orig != nullptr );
 
-    object_t* ptr_object = ::st_Buffer_add_object( eb, ptr_orig, sizeof( belem_t ),
-        BEAM_ELEMENT_TYPE_ID, ::st_Drift_get_num_dataptrs( ptr_orig ),
+    object_t* ptr_object = NS(Buffer_add_object)( eb, ptr_orig, sizeof( belem_t ),
+        BELEM_TYPE_ID, NS(Drift_num_dataptrs)( ptr_orig ),
             nullptr, nullptr, nullptr );
 
     ASSERT_TRUE( ptr_object != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-    ASSERT_TRUE( ::st_Object_get_const_begin_ptr( ptr_object ) != nullptr );
-    ASSERT_TRUE( ::st_Object_get_size( ptr_object ) >= sizeof( belem_t ) );
-    ASSERT_TRUE( ::st_Object_get_type_id( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+    ASSERT_TRUE( NS(Object_get_const_begin_ptr)( ptr_object ) != nullptr );
+    ASSERT_TRUE( NS(Object_get_size)( ptr_object ) >= sizeof( belem_t ) );
+    ASSERT_TRUE( NS(Object_get_type_id)( ptr_object ) == BELEM_TYPE_ID );
 
     belem_t* ptr_drift = reinterpret_cast< belem_t* >(
-        ::st_Object_get_begin_ptr( ptr_object ) );
+        NS(Object_get_begin_ptr)( ptr_object ) );
 
     ASSERT_TRUE( ptr_drift != nullptr );
-    ASSERT_TRUE( EPS > std::fabs( ::st_Drift_get_length( ptr_drift ) -
-                                  ::st_Drift_get_length( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Drift_length)( ptr_drift ) -
+                                  NS(Drift_length)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_drift = ::st_Drift_new( eb );
+    ptr_drift = NS(Drift_new)( eb );
 
     ASSERT_TRUE( ptr_drift != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_Drift_get_length( ptr_drift ) - ZERO ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Drift_length)( ptr_drift ) - ZERO ) );
 
-    ::st_Drift_set_length( ptr_drift, ::st_Drift_get_length( ptr_orig ) );
-    ASSERT_TRUE( EPS > std::fabs( ::st_Drift_get_length( ptr_drift ) -
-                                  ::st_Drift_get_length( ptr_orig  ) ) );
+    NS(Drift_set_length)( ptr_drift, NS(Drift_length)( ptr_orig ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Drift_length)( ptr_drift ) -
+                                  NS(Drift_length)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_drift = ::st_Drift_add( eb, ::st_Drift_get_length( ptr_orig ) );
+    ptr_drift = NS(Drift_add)( eb, NS(Drift_length)( ptr_orig ) );
 
     ASSERT_TRUE( ptr_drift != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-    ASSERT_TRUE( EPS > std::fabs( ::st_Drift_get_length( ptr_drift ) -
-                                  ::st_Drift_get_length( ptr_orig  ) ) );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+    ASSERT_TRUE( EPS > std::fabs( NS(Drift_length)( ptr_drift ) -
+                                  NS(Drift_length)( ptr_orig  ) ) );
 
     for( ; be_index < NUM_BEAM_ELEMENTS ; )
     {
         ptr_orig  = &orig_beam_elements[ be_index++ ];
-        ptr_drift = ::st_Drift_add( eb, ::st_Drift_get_length( ptr_orig ) );
+        ptr_drift = NS(Drift_add)( eb, NS(Drift_length)( ptr_orig ) );
 
         ASSERT_TRUE( ptr_drift != nullptr );
-        ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-        ASSERT_TRUE( EPS > std::fabs( ::st_Drift_get_length( ptr_drift ) -
-                                      ::st_Drift_get_length( ptr_orig  ) ) );
+        ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+        ASSERT_TRUE( EPS > std::fabs( NS(Drift_length)( ptr_drift ) -
+                                      NS(Drift_length)( ptr_orig  ) ) );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ASSERT_TRUE( ::st_Buffer_get_size( eb ) > size_t{ 0 } );
+    ASSERT_TRUE( NS(Buffer_get_size)( eb ) > size_t{ 0 } );
 
-    std::vector< raw_t > data_buffer( ::st_Buffer_get_size( eb ), raw_t{ 0 } );
-    data_buffer.assign( ::st_Buffer_get_const_data_begin( eb ),
-                        ::st_Buffer_get_const_data_end( eb ) );
+    std::vector< raw_t > data_buffer( NS(Buffer_get_size)( eb ), raw_t{ 0 } );
+    data_buffer.assign( NS(Buffer_get_const_data_begin)( eb ),
+                        NS(Buffer_get_const_data_end)( eb ) );
 
-    ::st_Buffer cmp_buffer;
-    ::st_Buffer_preset( &cmp_buffer );
-    int success = ::st_Buffer_init(
+    NS(Buffer) cmp_buffer;
+    NS(Buffer_preset)( &cmp_buffer );
+    int success = NS(Buffer_init)(
         &cmp_buffer, data_buffer.data(), data_buffer.size() );
 
     ASSERT_TRUE( success == 0 );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) ==
-                 ::st_Buffer_get_num_of_objects( &cmp_buffer ) );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) ==
+                 NS(Buffer_get_num_of_objects)( &cmp_buffer ) );
 
-    object_t const* obj_it  = ::st_Buffer_get_const_objects_begin( eb );
-    object_t const* obj_end = ::st_Buffer_get_const_objects_end( eb );
-    object_t const* cmp_it  = ::st_Buffer_get_const_objects_begin( &cmp_buffer );
+    object_t const* obj_it  = NS(Buffer_get_const_objects_begin)( eb );
+    object_t const* obj_end = NS(Buffer_get_const_objects_end)( eb );
+    object_t const* cmp_it  = NS(Buffer_get_const_objects_begin)( &cmp_buffer );
 
     be_index = size_t{ 0 };
 
@@ -163,19 +163,19 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
     {
         ptr_orig = &orig_beam_elements[ be_index++ ];
 
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) == BEAM_ELEMENT_TYPE_ID );
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) ==
-                     ::st_Object_get_type_id( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) == BELEM_TYPE_ID );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) ==
+                     NS(Object_get_type_id)( cmp_it ) );
 
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) >= sizeof( belem_t ) );
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) ==
-                     ::st_Object_get_size( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) >= sizeof( belem_t ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) ==
+                     NS(Object_get_size)( cmp_it ) );
 
         belem_t const* elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( obj_it ) );
+            NS(Object_get_const_begin_ptr)( obj_it ) );
 
         belem_t const* cmp_elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( cmp_it ) );
+            NS(Object_get_const_begin_ptr)( cmp_it ) );
 
         ASSERT_TRUE( ptr_orig != elem );
         ASSERT_TRUE( ptr_orig != cmp_elem );
@@ -184,29 +184,29 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
         ASSERT_TRUE( cmp_elem != nullptr );
         ASSERT_TRUE( cmp_elem != elem    );
 
-        ASSERT_TRUE( std::fabs( ::st_Drift_get_length( elem ) -
-                                ::st_Drift_get_length( ptr_orig ) ) < EPS );
+        ASSERT_TRUE( std::fabs( NS(Drift_length)( elem ) -
+                                NS(Drift_length)( ptr_orig ) ) < EPS );
 
-        ASSERT_TRUE( std::fabs( ::st_Drift_get_length( cmp_elem ) -
-                                ::st_Drift_get_length( ptr_orig ) ) < EPS );
+        ASSERT_TRUE( std::fabs( NS(Drift_length)( cmp_elem ) -
+                                NS(Drift_length)( ptr_orig ) ) < EPS );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ::st_Buffer_delete( eb );
-    ::st_Buffer_free( &cmp_buffer );
+    NS(Buffer_delete)( eb );
+    NS(Buffer_free)( &cmp_buffer );
 }
 
 /* ************************************************************************* *
- * ******  st_DriftExact:
+ * ****** NS(DriftExact):
  * ************************************************************************* */
 
-TEST( C99_CommonBeamElementDriftExactTests, MinimalAddToBufferCopyRemapRead )
+TEST( C99CommonBeamElementDriftExact, MinimalAddToBufferCopyRemapRead )
 {
-    using size_t   = ::st_buffer_size_t;
-    using object_t = ::st_Object;
+    using size_t   = NS(buffer_size_t);
+    using object_t = NS(Object);
     using raw_t    = unsigned char;
-    using belem_t  = ::st_DriftExact;
+    using belem_t  = NS(DriftExact);
     using real_t   = SIXTRL_REAL_T;
 
     static double const ZERO = double{ 0.0 };
@@ -226,10 +226,10 @@ TEST( C99_CommonBeamElementDriftExactTests, MinimalAddToBufferCopyRemapRead )
     static SIXTRL_CONSTEXPR_OR_CONST size_t
         NUM_BEAM_ELEMENTS = size_t{ 1000 };
 
-    ::st_object_type_id_t const BEAM_ELEMENT_TYPE_ID = ::st_OBJECT_TYPE_DRIFT_EXACT;
+    NS(object_type_id_t) const BELEM_TYPE_ID = NS(OBJECT_TYPE_DRIFT_EXACT);
     std::vector< belem_t > orig_beam_elements( NUM_BEAM_ELEMENTS, belem_t{} );
 
-    size_t const slot_size      = ::st_BUFFER_DEFAULT_SLOT_SIZE;
+    size_t const slot_size      = NS(BUFFER_DEFAULT_SLOT_SIZE);
     size_t const num_objs       = NUM_BEAM_ELEMENTS;
     size_t const num_garbage    = size_t{ 0 };
     size_t const num_dataptrs   = size_t{ 0 };
@@ -239,25 +239,25 @@ TEST( C99_CommonBeamElementDriftExactTests, MinimalAddToBufferCopyRemapRead )
     {
         real_t  const length   = length_dist( prng );
 
-        belem_t* ptr_drift = ::st_DriftExact_preset( &orig_beam_elements[ ii ] );
+        belem_t* ptr_drift = NS(DriftExact_preset)( &orig_beam_elements[ ii ] );
         ASSERT_TRUE( ptr_drift != nullptr );
-        ::st_DriftExact_set_length( ptr_drift, length );
+        NS(DriftExact_set_length)( ptr_drift, length );
 
         ASSERT_TRUE( EPS > std::fabs( length -
-            ::st_DriftExact_get_length( ptr_drift ) ) );
+            NS(DriftExact_length)( ptr_drift ) ) );
 
-        num_slots += ::st_ManagedBuffer_predict_required_num_slots( nullptr,
-            sizeof( ::st_DriftExact ),
-                ::st_DriftExact_get_num_dataptrs( ptr_drift ), nullptr,
+        num_slots += NS(ManagedBuffer_predict_required_num_slots)( nullptr,
+            sizeof( NS(DriftExact) ),
+                NS(DriftExact_num_dataptrs)( ptr_drift ), nullptr,
                     nullptr, slot_size );
     }
 
     /* --------------------------------------------------------------------- */
 
-    size_t const requ_buffer_size = ::st_ManagedBuffer_calculate_buffer_length(
+    size_t const requ_buffer_size = NS(ManagedBuffer_calculate_buffer_length)(
         nullptr, num_objs, num_slots, num_dataptrs, num_garbage, slot_size );
 
-    ::st_Buffer* eb = ::st_Buffer_new( requ_buffer_size );
+    NS(Buffer)* eb = NS(Buffer_new)( requ_buffer_size );
     ASSERT_TRUE( eb != nullptr );
 
     /* --------------------------------------------------------------------- */
@@ -266,79 +266,79 @@ TEST( C99_CommonBeamElementDriftExactTests, MinimalAddToBufferCopyRemapRead )
     belem_t* ptr_orig = &orig_beam_elements[ be_index++ ];
     ASSERT_TRUE( ptr_orig != nullptr );
 
-    object_t* ptr_object = ::st_Buffer_add_object( eb, ptr_orig, sizeof( belem_t ),
-        BEAM_ELEMENT_TYPE_ID, ::st_DriftExact_get_num_dataptrs( ptr_orig ),
+    object_t* ptr_object = NS(Buffer_add_object)( eb, ptr_orig, sizeof( belem_t ),
+        BELEM_TYPE_ID, NS(DriftExact_num_dataptrs)( ptr_orig ),
             nullptr, nullptr, nullptr );
 
     ASSERT_TRUE( ptr_object != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-    ASSERT_TRUE( ::st_Object_get_const_begin_ptr( ptr_object ) != nullptr );
-    ASSERT_TRUE( ::st_Object_get_size( ptr_object ) >= sizeof( belem_t ) );
-    ASSERT_TRUE( ::st_Object_get_type_id( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+    ASSERT_TRUE( NS(Object_get_const_begin_ptr)( ptr_object ) != nullptr );
+    ASSERT_TRUE( NS(Object_get_size)( ptr_object ) >= sizeof( belem_t ) );
+    ASSERT_TRUE( NS(Object_get_type_id)( ptr_object ) == BELEM_TYPE_ID );
 
     belem_t* ptr_drift = reinterpret_cast< belem_t* >(
-        ::st_Object_get_begin_ptr( ptr_object ) );
+        NS(Object_get_begin_ptr)( ptr_object ) );
 
     ASSERT_TRUE( ptr_drift != nullptr );
-    ASSERT_TRUE( EPS > std::fabs( ::st_DriftExact_get_length( ptr_drift ) -
-                                  ::st_DriftExact_get_length( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(DriftExact_length)( ptr_drift ) -
+                                  NS(DriftExact_length)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_drift = ::st_DriftExact_new( eb );
+    ptr_drift = NS(DriftExact_new)( eb );
 
     ASSERT_TRUE( ptr_drift != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
     ASSERT_TRUE( EPS > std::fabs(
-        ::st_DriftExact_get_length( ptr_drift ) - ZERO ) );
+        NS(DriftExact_length)( ptr_drift ) - ZERO ) );
 
-    ::st_DriftExact_set_length( ptr_drift, ::st_DriftExact_get_length( ptr_orig ) );
-    ASSERT_TRUE( EPS > std::fabs( ::st_DriftExact_get_length( ptr_drift ) -
-                                  ::st_DriftExact_get_length( ptr_orig  ) ) );
+    NS(DriftExact_set_length)( ptr_drift, NS(DriftExact_length)( ptr_orig ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(DriftExact_length)( ptr_drift ) -
+                                  NS(DriftExact_length)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_drift = ::st_DriftExact_add( eb, ::st_DriftExact_get_length( ptr_orig ) );
+    ptr_drift = NS(DriftExact_add)( eb, NS(DriftExact_length)( ptr_orig ) );
 
     ASSERT_TRUE( ptr_drift != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-    ASSERT_TRUE( EPS > std::fabs( ::st_DriftExact_get_length( ptr_drift ) -
-                                  ::st_DriftExact_get_length( ptr_orig  ) ) );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+    ASSERT_TRUE( EPS > std::fabs( NS(DriftExact_length)( ptr_drift ) -
+                                  NS(DriftExact_length)( ptr_orig  ) ) );
 
     for( ; be_index < NUM_BEAM_ELEMENTS ; )
     {
         ptr_orig  = &orig_beam_elements[ be_index++ ];
-        ptr_drift = ::st_DriftExact_add( eb, ::st_DriftExact_get_length( ptr_orig ) );
+        ptr_drift = NS(DriftExact_add)( eb, NS(DriftExact_length)( ptr_orig ) );
 
         ASSERT_TRUE( ptr_drift != nullptr );
-        ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-        ASSERT_TRUE( EPS > std::fabs( ::st_DriftExact_get_length( ptr_drift ) -
-                                      ::st_DriftExact_get_length( ptr_orig  ) ) );
+        ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+        ASSERT_TRUE( EPS > std::fabs( NS(DriftExact_length)( ptr_drift ) -
+                                      NS(DriftExact_length)( ptr_orig  ) ) );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ASSERT_TRUE( ::st_Buffer_get_size( eb ) > size_t{ 0 } );
+    ASSERT_TRUE( NS(Buffer_get_size)( eb ) > size_t{ 0 } );
 
-    std::vector< raw_t > data_buffer( ::st_Buffer_get_size( eb ), raw_t{ 0 } );
-    data_buffer.assign( ::st_Buffer_get_const_data_begin( eb ),
-                        ::st_Buffer_get_const_data_end( eb ) );
+    std::vector< raw_t > data_buffer( NS(Buffer_get_size)( eb ), raw_t{ 0 } );
+    data_buffer.assign( NS(Buffer_get_const_data_begin)( eb ),
+                        NS(Buffer_get_const_data_end)( eb ) );
 
-    ::st_Buffer cmp_buffer;
-    ::st_Buffer_preset( &cmp_buffer );
-    int success = ::st_Buffer_init(
+    NS(Buffer) cmp_buffer;
+    NS(Buffer_preset)( &cmp_buffer );
+    int success = NS(Buffer_init)(
         &cmp_buffer, data_buffer.data(), data_buffer.size() );
 
     ASSERT_TRUE( success == 0 );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) ==
-                 ::st_Buffer_get_num_of_objects( &cmp_buffer ) );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) ==
+                 NS(Buffer_get_num_of_objects)( &cmp_buffer ) );
 
-    object_t const* obj_it  = ::st_Buffer_get_const_objects_begin( eb );
-    object_t const* obj_end = ::st_Buffer_get_const_objects_end( eb );
-    object_t const* cmp_it  = ::st_Buffer_get_const_objects_begin( &cmp_buffer );
+    object_t const* obj_it  = NS(Buffer_get_const_objects_begin)( eb );
+    object_t const* obj_end = NS(Buffer_get_const_objects_end)( eb );
+    object_t const* cmp_it  = NS(Buffer_get_const_objects_begin)( &cmp_buffer );
 
     be_index = size_t{ 0 };
 
@@ -346,19 +346,19 @@ TEST( C99_CommonBeamElementDriftExactTests, MinimalAddToBufferCopyRemapRead )
     {
         ptr_orig = &orig_beam_elements[ be_index++ ];
 
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) == BEAM_ELEMENT_TYPE_ID );
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) ==
-                     ::st_Object_get_type_id( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) == BELEM_TYPE_ID );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) ==
+                     NS(Object_get_type_id)( cmp_it ) );
 
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) >= sizeof( belem_t ) );
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) ==
-                     ::st_Object_get_size( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) >= sizeof( belem_t ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) ==
+                     NS(Object_get_size)( cmp_it ) );
 
         belem_t const* elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( obj_it ) );
+            NS(Object_get_const_begin_ptr)( obj_it ) );
 
         belem_t const* cmp_elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( cmp_it ) );
+            NS(Object_get_const_begin_ptr)( cmp_it ) );
 
         ASSERT_TRUE( ptr_orig != elem );
         ASSERT_TRUE( ptr_orig != cmp_elem );
@@ -367,17 +367,15 @@ TEST( C99_CommonBeamElementDriftExactTests, MinimalAddToBufferCopyRemapRead )
         ASSERT_TRUE( cmp_elem != nullptr );
         ASSERT_TRUE( cmp_elem != elem    );
 
-        ASSERT_TRUE( std::fabs( ::st_DriftExact_get_length( elem ) -
-                                ::st_DriftExact_get_length( ptr_orig ) ) < EPS );
+        ASSERT_TRUE( std::fabs( NS(DriftExact_length)( elem ) -
+                                NS(DriftExact_length)( ptr_orig ) ) < EPS );
 
-        ASSERT_TRUE( std::fabs( ::st_DriftExact_get_length( cmp_elem ) -
-                                ::st_DriftExact_get_length( ptr_orig ) ) < EPS );
+        ASSERT_TRUE( std::fabs( NS(DriftExact_length)( cmp_elem ) -
+                                NS(DriftExact_length)( ptr_orig ) ) < EPS );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ::st_Buffer_delete( eb );
-    ::st_Buffer_free( &cmp_buffer );
+    NS(Buffer_delete)( eb );
+    NS(Buffer_free)( &cmp_buffer );
 }
-
-/* end: tests/sixtracklib/common/test_be_drift_c99.cpp  */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_drift_cxx.cpp b/tests/sixtracklib/common/beam_elements/test_be_drift_cxx.cpp
index e3d753b8..7e8b13cc 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_drift_cxx.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_drift_cxx.cpp
@@ -19,7 +19,7 @@
  * ******  sixtrack::Drift:
  * ************************************************************************* */
 
-TEST( CXX_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
+TEST( CXXCommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
 {
     namespace st    = sixtrack;
 
@@ -171,7 +171,7 @@ TEST( CXX_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
  * ******  st_DriftExact:
  * ************************************************************************* */
 
-TEST( CXX_CommonBeamElementDriftExactTests, MinimalAddToBufferCopyRemapRead )
+TEST( CXXCommonBeamElementDriftExactTests, MinimalAddToBufferCopyRemapRead )
 {
     namespace st    = sixtrack;
 
diff --git a/tests/sixtracklib/common/beam_elements/test_be_limit_ellipse_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_limit_ellipse_c99.cpp
index 48824f55..852d0b5b 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_limit_ellipse_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_limit_ellipse_c99.cpp
@@ -19,85 +19,85 @@
 #include "sixtracklib/common/particles.h"
 #include "sixtracklib/common/be_limit/track.h"
 
-TEST( C99_CommonBeamElementLimitEllipseTests, BasicUsage )
+TEST( C99CommonBeamElementLimitEllipse, BasicUsage )
 {
     using be_limit_t   = ::NS(LimitEllipse);
     using buffer_t     = ::NS(Buffer);
     using size_t       = ::NS(buffer_size_t);
     using real_t       = ::NS(particle_real_t);
-    
+
     using real_limit_t = std::numeric_limits< real_t >;
     real_t const EPS   = real_limit_t::epsilon();
-    
+
     real_t const X_HALF_AXIS = real_t{ 2.0 };
     real_t const Y_HALF_AXIS = real_t{ 1.5 };
-    
-    be_limit_t limit;    
+
+    be_limit_t limit;
     ::NS(LimitEllipse_set_half_axes)( &limit, X_HALF_AXIS, Y_HALF_AXIS );
-        
+
     buffer_t* eb = ::NS(Buffer_new)( size_t{ 0 } );
-    
-    be_limit_t* l2 = ::NS(LimitEllipse_new)( eb );    
+
+    be_limit_t* l2 = ::NS(LimitEllipse_new)( eb );
     ASSERT_TRUE( l2 != nullptr );
-            
-    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_get_x_half_axis)( l2 ) - 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_x_half_axis)( l2 ) -
         ::NS(LIMIT_DEFAULT_X_HALF_AXIS) ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_get_y_half_axis)( l2 ) - 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_y_half_axis)( l2 ) -
         ::NS(LIMIT_DEFAULT_Y_HALF_AXIS) ) < EPS );
-        
-    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_get_x_half_axis_squ)( l2 ) - 
-        ::NS(LIMIT_DEFAULT_X_HALF_AXIS) * 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_x_half_axis_squ)( l2 ) -
+        ::NS(LIMIT_DEFAULT_X_HALF_AXIS) *
         ::NS(LIMIT_DEFAULT_X_HALF_AXIS) ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_get_y_half_axis_squ)( l2 ) - 
-        ::NS(LIMIT_DEFAULT_Y_HALF_AXIS) * 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_y_half_axis_squ)( l2 ) -
+        ::NS(LIMIT_DEFAULT_Y_HALF_AXIS) *
         ::NS(LIMIT_DEFAULT_Y_HALF_AXIS) ) < EPS );
-        
-    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_get_half_axes_product_squ)( l2 ) 
-        - ::NS(LIMIT_DEFAULT_X_HALF_AXIS) * ::NS(LIMIT_DEFAULT_X_HALF_AXIS) * 
-          ::NS(LIMIT_DEFAULT_Y_HALF_AXIS) * ::NS(LIMIT_DEFAULT_Y_HALF_AXIS) ) 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_half_axes_product_squ)( l2 )
+        - ::NS(LIMIT_DEFAULT_X_HALF_AXIS) * ::NS(LIMIT_DEFAULT_X_HALF_AXIS) *
+          ::NS(LIMIT_DEFAULT_Y_HALF_AXIS) * ::NS(LIMIT_DEFAULT_Y_HALF_AXIS) )
         < EPS );
-    
-    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) == 
+
+    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) ==
                  ::NS(LimitEllipse_copy)( &limit, l2 ) );
-    
+
     ASSERT_TRUE( 0 == ::NS(LimitEllipse_compare_values)( &limit, l2 ) );
-    
+
     be_limit_t* l3 = ::NS(LimitEllipse_add)( eb, X_HALF_AXIS, Y_HALF_AXIS );
     ASSERT_TRUE( l3 != nullptr );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_get_x_half_axis)( l3 ) - 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_x_half_axis)( l3 ) -
         X_HALF_AXIS ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_get_y_half_axis)( l3 ) - 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitEllipse_y_half_axis)( l3 ) -
         Y_HALF_AXIS ) < EPS );
-    
+
     be_limit_t* l4 = ::NS(LimitEllipse_add_copy)( eb, &limit );
-    
+
     ASSERT_TRUE( l4 != nullptr );
     ASSERT_TRUE( 0 == ::NS(LimitEllipse_compare_values)( l4, &limit ) );
-    
+
     real_t const TRESHOLD = real_t{ 9e-4 };
-    
-    ::NS(LimitEllipse_set_half_axes_squ)( l4, 
-        ::NS(LimitEllipse_get_x_half_axis_squ)( l4 ) + TRESHOLD, 
-        ::NS(LimitEllipse_get_y_half_axis_squ)( l4 ) );
-        
+
+    ::NS(LimitEllipse_set_half_axes_squ)( l4,
+        ::NS(LimitEllipse_x_half_axis_squ)( l4 ) + TRESHOLD,
+        ::NS(LimitEllipse_y_half_axis_squ)( l4 ) );
+
     ASSERT_TRUE( 0 != ::NS(LimitEllipse_compare_values)( l4, &limit ) );
-    
-    ASSERT_TRUE( 0 != ::NS(LimitEllipse_compare_values_with_treshold)( 
+
+    ASSERT_TRUE( 0 != ::NS(LimitEllipse_compare_values_with_treshold)(
         l4, &limit, EPS ) );
-    
-    ASSERT_TRUE( 0 == ::NS(LimitEllipse_compare_values_with_treshold)( 
+
+    ASSERT_TRUE( 0 == ::NS(LimitEllipse_compare_values_with_treshold)(
         l4, &limit, TRESHOLD ) );
-    
+
     ::NS(Buffer_delete)( eb );
     eb = nullptr;
-}    
+}
 
 
-TEST( C99_CommonBeamElementLimitRectTests, ApertureCheck )
+TEST( C99CommonBeamElementLimitRect, ApertureCheck )
 {
     using be_limit_t  = ::NS(LimitEllipse);
     using buffer_t    = ::NS(Buffer);
@@ -105,167 +105,165 @@ TEST( C99_CommonBeamElementLimitRectTests, ApertureCheck )
     using size_t      = ::NS(buffer_size_t);
     using real_t      = ::NS(particle_real_t);
     using pindex_t    = ::NS(particle_index_t);
-    
+
     size_t const NUM_PARTICLES = size_t{ 20 };
-    
+
     real_t const EPS = std::numeric_limits< real_t >::epsilon();
     pindex_t const LOST_PARTICLE = pindex_t{ 0 };
     pindex_t const NOT_LOST_PARTICLE = pindex_t{ 1 };
-    
-    std::vector< pindex_t > expected_state_after_track( 
+
+    std::vector< pindex_t > expected_state_after_track(
         NUM_PARTICLES, LOST_PARTICLE );
-    
+
     be_limit_t limit;
-    
+
     real_t const ZERO = real_t{ 0.0 };
-    
+
     real_t const X_HALF_AXIS = real_t{ +1.0 };
     real_t const Y_HALF_AXIS = real_t{ +1.0 };
-    
+
     ::NS(LimitEllipse_set_half_axes)( &limit, X_HALF_AXIS, Y_HALF_AXIS );
-    
+
     buffer_t* pb = ::NS(Buffer_new)( size_t{ 0 } );
     SIXTRL_ASSERT( pb != nullptr );
-    
+
     particles_t* particles = ::NS(Particles_new)( pb, NUM_PARTICLES );
     SIXTRL_ASSERT( particles != nullptr );
-    
+
     ::NS(Particles_set_x_value)(     particles,  0, -X_HALF_AXIS );
     ::NS(Particles_set_y_value)(     particles,  0, ZERO );
     ::NS(Particles_set_state_value)( particles,  0, NOT_LOST_PARTICLE );
     expected_state_after_track[  0 ] = NOT_LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  1, X_HALF_AXIS );
     ::NS(Particles_set_y_value)(     particles,  1, ZERO );
     ::NS(Particles_set_state_value)( particles,  1, NOT_LOST_PARTICLE );
     expected_state_after_track[  1 ] = NOT_LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  2, ZERO );
     ::NS(Particles_set_y_value)(     particles,  2, -Y_HALF_AXIS );
-    ::NS(Particles_set_state_value)( particles,  2, NOT_LOST_PARTICLE );    
+    ::NS(Particles_set_state_value)( particles,  2, NOT_LOST_PARTICLE );
     expected_state_after_track[  2 ] = NOT_LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  3, ZERO );
     ::NS(Particles_set_y_value)(     particles,  3, Y_HALF_AXIS );
     ::NS(Particles_set_state_value)( particles,  3, NOT_LOST_PARTICLE );
     expected_state_after_track[  3 ] = NOT_LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  4, -X_HALF_AXIS - EPS );
     ::NS(Particles_set_y_value)(     particles,  4, ZERO );
     ::NS(Particles_set_state_value)( particles,  4, NOT_LOST_PARTICLE );
     expected_state_after_track[  4 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  5, X_HALF_AXIS + EPS );
     ::NS(Particles_set_y_value)(     particles,  5, ZERO );
     ::NS(Particles_set_state_value)( particles,  5, NOT_LOST_PARTICLE );
     expected_state_after_track[  5 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  6, ZERO );
     ::NS(Particles_set_y_value)(     particles,  6, -Y_HALF_AXIS - EPS );
     ::NS(Particles_set_state_value)( particles,  6, NOT_LOST_PARTICLE );
     expected_state_after_track[  6 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  7, ZERO );
     ::NS(Particles_set_y_value)(     particles,  7, Y_HALF_AXIS + EPS );
     ::NS(Particles_set_state_value)( particles,  7, NOT_LOST_PARTICLE );
     expected_state_after_track[  7 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  8, -X_HALF_AXIS );
     ::NS(Particles_set_y_value)(     particles,  8, ZERO );
     ::NS(Particles_set_state_value)( particles,  8, LOST_PARTICLE );
     expected_state_after_track[  8 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  9, X_HALF_AXIS );
     ::NS(Particles_set_y_value)(     particles,  9, ZERO );
     ::NS(Particles_set_state_value)( particles,  9, LOST_PARTICLE );
     expected_state_after_track[  9 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 10, ZERO );
     ::NS(Particles_set_y_value)(     particles, 10, -Y_HALF_AXIS );
-    ::NS(Particles_set_state_value)( particles, 10, LOST_PARTICLE );    
+    ::NS(Particles_set_state_value)( particles, 10, LOST_PARTICLE );
     expected_state_after_track[ 10 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 11, ZERO );
     ::NS(Particles_set_y_value)(     particles, 11, Y_HALF_AXIS );
     ::NS(Particles_set_state_value)( particles, 11, LOST_PARTICLE );
     expected_state_after_track[ 11 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 12, -X_HALF_AXIS - EPS );
     ::NS(Particles_set_y_value)(     particles, 12, ZERO );
     ::NS(Particles_set_state_value)( particles, 12, LOST_PARTICLE );
     expected_state_after_track[ 12 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 13, X_HALF_AXIS + EPS );
     ::NS(Particles_set_y_value)(     particles, 13, ZERO );
     ::NS(Particles_set_state_value)( particles, 13, LOST_PARTICLE );
     expected_state_after_track[ 13 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 14, ZERO );
     ::NS(Particles_set_y_value)(     particles, 14, -Y_HALF_AXIS - EPS );
     ::NS(Particles_set_state_value)( particles, 14, LOST_PARTICLE );
     expected_state_after_track[ 14 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 15, ZERO );
     ::NS(Particles_set_y_value)(     particles, 15, Y_HALF_AXIS + EPS );
     ::NS(Particles_set_state_value)( particles, 15, LOST_PARTICLE );
     expected_state_after_track[ 15 ] = LOST_PARTICLE;
-    
+
     /* --------------------------------------------------------------------- */
-    
-    ::NS(Particles_set_x_value)( particles, 16, real_t{ 0.99 } * X_HALF_AXIS * 
+
+    ::NS(Particles_set_x_value)( particles, 16, real_t{ 0.99 } * X_HALF_AXIS *
         std::cos( ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
-    ::NS(Particles_set_y_value)( particles, 16, real_t{ 0.99 } * Y_HALF_AXIS * 
+
+    ::NS(Particles_set_y_value)( particles, 16, real_t{ 0.99 } * Y_HALF_AXIS *
         std::sin( ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
+
     ::NS(Particles_set_state_value)( particles, 16, NOT_LOST_PARTICLE );
     expected_state_after_track[ 16 ] = NOT_LOST_PARTICLE;
-    
-    
-    
-    ::NS(Particles_set_x_value)( particles, 17, real_t{ 1.02 } * X_HALF_AXIS * 
+
+
+
+    ::NS(Particles_set_x_value)( particles, 17, real_t{ 1.02 } * X_HALF_AXIS *
         std::cos( ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
-    ::NS(Particles_set_y_value)( particles, 17, real_t{ 1.02 } * Y_HALF_AXIS * 
+
+    ::NS(Particles_set_y_value)( particles, 17, real_t{ 1.02 } * Y_HALF_AXIS *
         std::sin( ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
+
     ::NS(Particles_set_state_value)( particles, 17, NOT_LOST_PARTICLE );
     expected_state_after_track[ 17 ] = LOST_PARTICLE;
-    
-    
-    
-    ::NS(Particles_set_x_value)( particles, 18, real_t{ 0.99 } * X_HALF_AXIS * 
+
+
+
+    ::NS(Particles_set_x_value)( particles, 18, real_t{ 0.99 } * X_HALF_AXIS *
         std::cos( ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
-    ::NS(Particles_set_y_value)( particles, 18, real_t{ 0.99 } * Y_HALF_AXIS * 
+
+    ::NS(Particles_set_y_value)( particles, 18, real_t{ 0.99 } * Y_HALF_AXIS *
         std::sin( ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
+
     ::NS(Particles_set_state_value)( particles, 18, LOST_PARTICLE );
     expected_state_after_track[ 18 ] = LOST_PARTICLE;
-    
-    
-    
-    ::NS(Particles_set_x_value)( particles, 19, real_t{ 1.02 } * X_HALF_AXIS * 
+
+
+
+    ::NS(Particles_set_x_value)( particles, 19, real_t{ 1.02 } * X_HALF_AXIS *
         std::cos( ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
-    ::NS(Particles_set_y_value)( particles, 19, real_t{ 1.02 } * Y_HALF_AXIS * 
+
+    ::NS(Particles_set_y_value)( particles, 19, real_t{ 1.02 } * Y_HALF_AXIS *
         std::sin( ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
+
     ::NS(Particles_set_state_value)( particles, 19, LOST_PARTICLE );
     expected_state_after_track[ 19 ] = LOST_PARTICLE;
-    
+
     /* --------------------------------------------------------------------- */
-    
+
     for( size_t ii = size_t{ 0 } ; ii < NUM_PARTICLES ; ++ii )
     {
         ASSERT_TRUE( ::NS(TRACK_SUCCESS) == ::NS(Track_particle_limit_ellipse)(
             particles, ii, &limit ) );
-        
+
         ASSERT_TRUE( ::NS(Particles_get_state_value)( particles, ii ) ==
                      expected_state_after_track[ ii ] );
     }
-    
+
     ::NS(Buffer_delete)( pb );
 }
-
-/* end: tests/sixtracklib/common/beam_elements/test_be_limit_c99.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_limit_ellipse_cxx.cpp b/tests/sixtracklib/common/beam_elements/test_be_limit_ellipse_cxx.cpp
index 68c46eb3..a0fa7df8 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_limit_ellipse_cxx.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_limit_ellipse_cxx.cpp
@@ -16,231 +16,228 @@
 #include "sixtracklib/common/particles.hpp"
 #include "sixtracklib/common/be_limit/track.h"
 
-TEST( C99_CommonBeamElementLimitEllipseTests, BasicUsage )
+TEST( CXXCommonBeamElementLimitEllipse, BasicUsage )
 {
     namespace st = SIXTRL_CXX_NAMESPACE;
-    
+
     using be_limit_t   = st::LimitEllipse;
     using buffer_t     = st::Buffer;
-    using real_t       = st::Particles::real_t;    
-    
+    using real_t       = st::Particles::real_t;
+
     real_t const EPS   = std::numeric_limits< real_t >::epsilon();
-    
+
     real_t const X_HALF_AXIS = real_t{ 2.0 };
     real_t const Y_HALF_AXIS = real_t{ 1.5 };
-    
+
     be_limit_t limit;
     limit.setHalfAxes( X_HALF_AXIS, Y_HALF_AXIS );
-        
+
     buffer_t eb;
-    
+
     be_limit_t* l2 = eb.createNew< be_limit_t >();
     ASSERT_TRUE( l2 != nullptr );
-    
-    ASSERT_TRUE( std::fabs( l2->getXHalfAxis() - 
+
+    ASSERT_TRUE( std::fabs( l2->getXHalfAxis() -
         st::LIMIT_DEFAULT_X_HALF_AXIS ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( l2->getYHalfAxis() - 
+
+    ASSERT_TRUE( std::fabs( l2->getYHalfAxis() -
         st::LIMIT_DEFAULT_Y_HALF_AXIS ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( l2->getXHalfAxisSqu() - 
+
+    ASSERT_TRUE( std::fabs( l2->getXHalfAxisSqu() -
         st::LIMIT_DEFAULT_X_HALF_AXIS * st::LIMIT_DEFAULT_X_HALF_AXIS ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( l2->getYHalfAxisSqu() - 
+
+    ASSERT_TRUE( std::fabs( l2->getYHalfAxisSqu() -
         st::LIMIT_DEFAULT_Y_HALF_AXIS * st::LIMIT_DEFAULT_Y_HALF_AXIS ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( l2->getHalfAxesProductSqu() - 
-        st::LIMIT_DEFAULT_X_HALF_AXIS * st::LIMIT_DEFAULT_X_HALF_AXIS * 
+
+    ASSERT_TRUE( std::fabs( l2->getHalfAxesProductSqu() -
+        st::LIMIT_DEFAULT_X_HALF_AXIS * st::LIMIT_DEFAULT_X_HALF_AXIS *
         st::LIMIT_DEFAULT_Y_HALF_AXIS * st::LIMIT_DEFAULT_Y_HALF_AXIS ) < EPS );
-    
-    
+
+
     be_limit_t* l4 = eb.addCopy< be_limit_t >( limit );
-    
+
     ASSERT_TRUE( l4 != nullptr );
-    ASSERT_TRUE( 0 == ::NS(LimitEllipse_compare_values)( 
+    ASSERT_TRUE( 0 == ::NS(LimitEllipse_compare_values)(
         l4->getCApiPtr(), limit.getCApiPtr() ) );
-    
+
     real_t const TRESHOLD = real_t{ 9e-4 };
-    
-    l4->setHalfAxesSqu( l4->getXHalfAxisSqu() + TRESHOLD, 
+
+    l4->setHalfAxesSqu( l4->getXHalfAxisSqu() + TRESHOLD,
                         l4->getYHalfAxisSqu() );
-    
-    ASSERT_TRUE( 0 != ::NS(LimitEllipse_compare_values)( 
+
+    ASSERT_TRUE( 0 != ::NS(LimitEllipse_compare_values)(
         l4->getCApiPtr(), limit.getCApiPtr() ) );
-    
-    ASSERT_TRUE( 0 != ::NS(LimitEllipse_compare_values_with_treshold)( 
-        l4->getCApiPtr(), limit.getCApiPtr(), EPS ) );    
-}
 
+    ASSERT_TRUE( 0 != ::NS(LimitEllipse_compare_values_with_treshold)(
+        l4->getCApiPtr(), limit.getCApiPtr(), EPS ) );
+}
 
-TEST( CXX_CommonBeamElementLimitRectTests, ApertureCheck )
+TEST( CXXCommonBeamElementLimitRect, ApertureCheck )
 {
     namespace st = SIXTRL_CXX_NAMESPACE;
-    
+
     using be_limit_t  = st::LimitEllipse;
     using buffer_t    = st::Buffer;
     using particles_t = st::Particles;
     using size_t      = buffer_t::size_type;
     using real_t      = particles_t::real_t;
     using pindex_t    = particles_t::index_t;
-    
+
     size_t const NUM_PARTICLES = size_t{ 20 };
-    
+
     real_t const EPS = std::numeric_limits< real_t >::epsilon();
     pindex_t const LOST_PARTICLE = pindex_t{ 0 };
     pindex_t const NOT_LOST_PARTICLE = pindex_t{ 1 };
-    
-    std::vector< pindex_t > expected_state_after_track( 
+
+    std::vector< pindex_t > expected_state_after_track(
         NUM_PARTICLES, LOST_PARTICLE );
-    
+
     be_limit_t limit;
-    
+
     real_t const ZERO = real_t{ 0.0 };
-    
+
     real_t const X_HALF_AXIS = real_t{ 1.0 };
     real_t const Y_HALF_AXIS = real_t{ 1.0 };
-    
+
     limit.setHalfAxes( X_HALF_AXIS, Y_HALF_AXIS );
-    
+
     buffer_t pb;
-    
+
     particles_t* particles = pb.createNew< particles_t >( NUM_PARTICLES );
     SIXTRL_ASSERT( particles != nullptr );
-    
+
     particles->setXValue( 0, -X_HALF_AXIS );
     particles->setYValue( 0, ZERO );
     particles->setStateValue( 0, NOT_LOST_PARTICLE );
     expected_state_after_track[  0 ] = NOT_LOST_PARTICLE;
-    
+
     particles->setXValue( 1, X_HALF_AXIS );
     particles->setYValue( 1, ZERO );
     particles->setStateValue( 1, NOT_LOST_PARTICLE );
     expected_state_after_track[  1 ] = NOT_LOST_PARTICLE;
-    
+
     particles->setXValue( 2, ZERO );
     particles->setYValue( 2, -Y_HALF_AXIS );
-    particles->setStateValue( 2, NOT_LOST_PARTICLE );    
+    particles->setStateValue( 2, NOT_LOST_PARTICLE );
     expected_state_after_track[  2 ] = NOT_LOST_PARTICLE;
-    
+
     particles->setXValue( 3, ZERO );
     particles->setYValue( 3, Y_HALF_AXIS );
     particles->setStateValue( 3, NOT_LOST_PARTICLE );
     expected_state_after_track[  3 ] = NOT_LOST_PARTICLE;
-    
+
     particles->setXValue( 4, -X_HALF_AXIS - EPS );
     particles->setYValue( 4, ZERO );
     particles->setStateValue( 4, NOT_LOST_PARTICLE );
     expected_state_after_track[  4 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 5, X_HALF_AXIS + EPS );
     particles->setYValue( 5, ZERO );
     particles->setStateValue( 5, NOT_LOST_PARTICLE );
     expected_state_after_track[  5 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 6, ZERO );
     particles->setYValue( 6, -Y_HALF_AXIS - EPS );
     particles->setStateValue( 6, NOT_LOST_PARTICLE );
     expected_state_after_track[  6 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 7, ZERO );
     particles->setYValue( 7, Y_HALF_AXIS + EPS );
     particles->setStateValue( 7, NOT_LOST_PARTICLE );
     expected_state_after_track[  7 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 8, -X_HALF_AXIS );
     particles->setYValue( 8, ZERO );
     particles->setStateValue( 8, LOST_PARTICLE );
     expected_state_after_track[  8 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 9, X_HALF_AXIS );
     particles->setYValue( 9, ZERO );
     particles->setStateValue( 9, LOST_PARTICLE );
     expected_state_after_track[  9 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 10, ZERO );
     particles->setYValue( 10, -Y_HALF_AXIS );
     particles->setStateValue( 10, LOST_PARTICLE );
     expected_state_after_track[ 10 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 11, ZERO );
     particles->setYValue( 11, Y_HALF_AXIS );
     particles->setStateValue( 11, LOST_PARTICLE );
     expected_state_after_track[ 11 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 12, -X_HALF_AXIS - EPS );
     particles->setYValue( 12, ZERO );
     particles->setStateValue( 12, LOST_PARTICLE );
     expected_state_after_track[ 12 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 13, X_HALF_AXIS + EPS );
     particles->setYValue( 13, ZERO );
     particles->setStateValue( 13, LOST_PARTICLE );
     expected_state_after_track[ 13 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 14, ZERO );
     particles->setYValue( 14, -Y_HALF_AXIS - EPS );
     particles->setStateValue( 14, LOST_PARTICLE );
     expected_state_after_track[ 14 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 15, ZERO );
     particles->setYValue( 15, Y_HALF_AXIS + EPS );
     particles->setStateValue( 15, LOST_PARTICLE );
     expected_state_after_track[ 15 ] = LOST_PARTICLE;
-    
+
     /* --------------------------------------------------------------------- */
-    
-    particles->setXValue( 16, real_t{ 0.99 } * X_HALF_AXIS * std::cos( 
+
+    particles->setXValue( 16, real_t{ 0.99 } * X_HALF_AXIS * std::cos(
         ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
-    particles->setYValue( 16, real_t{ 0.99 } * Y_HALF_AXIS * std::sin( 
+
+    particles->setYValue( 16, real_t{ 0.99 } * Y_HALF_AXIS * std::sin(
         ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
+
     particles->setStateValue( 16, NOT_LOST_PARTICLE );
     expected_state_after_track[ 16 ] = NOT_LOST_PARTICLE;
-    
-    
-    
-    particles->setXValue( 17, real_t{ 1.02 } * X_HALF_AXIS * std::cos( 
+
+
+
+    particles->setXValue( 17, real_t{ 1.02 } * X_HALF_AXIS * std::cos(
         ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
-    particles->setYValue( 17, real_t{ 1.02 } * Y_HALF_AXIS * std::sin( 
+
+    particles->setYValue( 17, real_t{ 1.02 } * Y_HALF_AXIS * std::sin(
         ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
+
     particles->setStateValue( 17, NOT_LOST_PARTICLE );
     expected_state_after_track[ 17 ] = LOST_PARTICLE;
-    
-    
-    
-    particles->setXValue( 18, real_t{ 0.99 } * X_HALF_AXIS * std::cos( 
+
+
+
+    particles->setXValue( 18, real_t{ 0.99 } * X_HALF_AXIS * std::cos(
         ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
-    particles->setYValue( 18, real_t{ 0.99 } * Y_HALF_AXIS * std::sin( 
+
+    particles->setYValue( 18, real_t{ 0.99 } * Y_HALF_AXIS * std::sin(
         ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
+
     particles->setStateValue( 18, LOST_PARTICLE );
     expected_state_after_track[ 18 ] = LOST_PARTICLE;
-    
-    
-    
-    particles->setXValue( 19, real_t{ 1.02 } * X_HALF_AXIS * std::cos( 
+
+
+
+    particles->setXValue( 19, real_t{ 1.02 } * X_HALF_AXIS * std::cos(
         ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
-    particles->setYValue( 19, real_t{ 1.02 } * Y_HALF_AXIS * std::sin( 
+
+    particles->setYValue( 19, real_t{ 1.02 } * Y_HALF_AXIS * std::sin(
         ::NS(DEG2RAD) * real_t{ 30.0 } ) );
-    
+
     particles->setStateValue( 19, LOST_PARTICLE );
     expected_state_after_track[ 19 ] = LOST_PARTICLE;
-    
+
     /* --------------------------------------------------------------------- */
-    
+
     for( size_t ii = size_t{ 0 } ; ii < NUM_PARTICLES ; ++ii )
     {
         ASSERT_TRUE( ::NS(TRACK_SUCCESS) == ::NS(Track_particle_limit_ellipse)(
             particles->getCApiPtr(), ii, limit.getCApiPtr() ) );
-        
-        ASSERT_TRUE( particles->getStateValue( ii ) == 
+
+        ASSERT_TRUE( particles->getStateValue( ii ) ==
                      expected_state_after_track[ ii ] );
     }
 }
-
-/* end: tests/sixtracklib/common/beam_elements/test_be_limit_rect_cxx.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_limit_rect_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_limit_rect_c99.cpp
index 1660f7d6..0a692d53 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_limit_rect_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_limit_rect_c99.cpp
@@ -18,99 +18,88 @@
 #include "sixtracklib/common/particles.h"
 #include "sixtracklib/common/be_limit/track.h"
 
-TEST( C99_CommonBeamElementLimitRectTests, BasicUsage )
+TEST( C99CommonBeamElementLimitRect, BasicUsage )
 {
     using be_limit_t   = ::NS(LimitRect);
     using buffer_t     = ::NS(Buffer);
     using size_t       = ::NS(buffer_size_t);
     using real_t       = ::NS(particle_real_t);
-    
+
     using real_limit_t = std::numeric_limits< real_t >;
     real_t const EPS   = real_limit_t::epsilon();
-    
+
     real_t const MIN_X_VALUE = real_t{ -2.0 };
     real_t const MAX_X_VALUE = real_t{  2.0 };
-    
+
     real_t const MIN_Y_VALUE = real_t{ -3.0 };
     real_t const MAX_Y_VALUE = real_t{  3.0 };
-    
+
     be_limit_t limit;
     ::NS(LimitRect_preset)( &limit );
     ::NS(LimitRect_set_min_x)( &limit, MIN_X_VALUE );
     ::NS(LimitRect_set_max_x)( &limit, MAX_X_VALUE );
     ::NS(LimitRect_set_min_y)( &limit, MIN_Y_VALUE );
     ::NS(LimitRect_set_max_y)( &limit, MAX_Y_VALUE );
-    
-    
+
+
     buffer_t* eb = ::NS(Buffer_new)( size_t{ 0 } );
-    
-    be_limit_t* l2 = ::NS(LimitRect_new)( eb );    
+
+    be_limit_t* l2 = ::NS(LimitRect_new)( eb );
     ASSERT_TRUE( l2 != nullptr );
-            
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_min_x)( l2 ) - 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_min_x)( l2 ) -
         ::NS(LIMIT_DEFAULT_MIN_X) ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_max_x)( l2 ) - 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_max_x)( l2 ) -
         ::NS(LIMIT_DEFAULT_MAX_X) ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_min_y)( l2 ) - 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_min_y)( l2 ) -
         ::NS(LIMIT_DEFAULT_MIN_Y) ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_max_y)( l2 ) - 
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_max_y)( l2 ) -
         ::NS(LIMIT_DEFAULT_MAX_Y) ) < EPS );
-    
-    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) == 
+
+    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) ==
                  ::NS(LimitRect_copy)( &limit, l2 ) );
     ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values)( &limit, l2 ) );
-    
-    be_limit_t* l3 = ::NS(LimitRect_add)( eb, 
+
+    be_limit_t* l3 = ::NS(LimitRect_add)( eb,
         MIN_X_VALUE, MAX_X_VALUE, MIN_Y_VALUE, MAX_Y_VALUE );
     ASSERT_TRUE( l3 != nullptr );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_min_x)( l3 ) - 
-        MIN_X_VALUE ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_max_x)( l3 ) - 
-        MAX_X_VALUE ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_min_y)( l3 ) - 
-        MIN_Y_VALUE ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_max_y)( l3 ) - 
-        MAX_Y_VALUE ) < EPS );
-    
-    ::NS(LimitRect_set_x_limit)( l3, ::NS(LimitRect_get_max_y)( l3 ) );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_max_x)( l3 ) - 
-        ::NS(LimitRect_get_max_y)( l3 ) ) < EPS );
-    
-    ASSERT_TRUE( std::fabs( ::NS(LimitRect_get_min_x)( l3 ) - 
-        ( -::NS(LimitRect_get_max_y)( l3 ) ) ) < EPS );
-    
-    
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_min_x)( l3 ) - MIN_X_VALUE ) < EPS );
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_max_x)( l3 ) - MAX_X_VALUE ) < EPS );
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_min_y)( l3 ) - MIN_Y_VALUE ) < EPS );
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_max_y)( l3 ) - MAX_Y_VALUE ) < EPS );
+
+    ::NS(LimitRect_set_x_limit)( l3, ::NS(LimitRect_max_y)( l3 ) );
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_max_x)( l3 ) -
+        ::NS(LimitRect_max_y)( l3 ) ) < EPS );
+
+    ASSERT_TRUE( std::fabs( ::NS(LimitRect_min_x)( l3 ) -
+        ( -::NS(LimitRect_max_y)( l3 ) ) ) < EPS );
+
     be_limit_t* l4 = ::NS(LimitRect_add_copy)( eb, &limit );
-    
+
     ASSERT_TRUE( l4 != nullptr );
     ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values)( l4, &limit ) );
-    
+
     real_t const TRESHOLD = real_t{ 9e-4 };
-    
-    ::NS(LimitRect_set_x_limit)( l4, 
-         ::NS(LimitRect_get_max_x)( l4 ) + TRESHOLD );
-    
+
+    ::NS(LimitRect_set_x_limit)( l4, ::NS(LimitRect_max_x)( l4 ) + TRESHOLD );
     ASSERT_TRUE( 0 != ::NS(LimitRect_compare_values)( l4, &limit ) );
-    
-    ASSERT_TRUE( 0 != ::NS(LimitRect_compare_values_with_treshold)( 
+    ASSERT_TRUE( 0 != ::NS(LimitRect_compare_values_with_treshold)(
         l4, &limit, EPS ) );
-    
-    ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values_with_treshold)( 
+
+    ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values_with_treshold)(
         l4, &limit, TRESHOLD ) );
-    
+
     ::NS(Buffer_delete)( eb );
 }
 
 
-TEST( C99_CommonBeamElementLimitRectTests, ApertureCheck )
+TEST( C99CommonBeamElementLimitRect, ApertureCheck )
 {
     using be_limit_t  = ::NS(LimitRect);
     using buffer_t    = ::NS(Buffer);
@@ -118,127 +107,125 @@ TEST( C99_CommonBeamElementLimitRectTests, ApertureCheck )
     using size_t      = ::NS(buffer_size_t);
     using real_t      = ::NS(particle_real_t);
     using pindex_t    = ::NS(particle_index_t);
-    
+
     size_t const NUM_PARTICLES = size_t{ 16 };
-    
+
     real_t const EPS = std::numeric_limits< real_t >::epsilon();
     pindex_t const LOST_PARTICLE = pindex_t{ 0 };
     pindex_t const NOT_LOST_PARTICLE = pindex_t{ 1 };
-    
-    std::vector< pindex_t > expected_state_after_track( 
+
+    std::vector< pindex_t > expected_state_after_track(
         NUM_PARTICLES, LOST_PARTICLE );
-    
+
     be_limit_t limit;
-    
+
     real_t const ZERO = real_t{ 0.0 };
-    
+
     real_t const LIMIT_MIN_X = real_t{ -1.0 };
     real_t const LIMIT_MAX_X = real_t{ +1.0 };
-    
+
     real_t const LIMIT_MIN_Y = real_t{ -1.0 };
     real_t const LIMIT_MAX_Y = real_t{ +1.0 };
-    
+
     ::NS(LimitRect_set_min_x)( &limit, LIMIT_MIN_X );
-    ::NS(LimitRect_set_max_x)( &limit, LIMIT_MAX_X );    
+    ::NS(LimitRect_set_max_x)( &limit, LIMIT_MAX_X );
     ::NS(LimitRect_set_min_y)( &limit, LIMIT_MIN_Y );
     ::NS(LimitRect_set_max_y)( &limit, LIMIT_MAX_Y );
-    
+
     buffer_t* pb = ::NS(Buffer_new)( size_t{ 0 } );
     SIXTRL_ASSERT( pb != nullptr );
-    
+
     particles_t* particles = ::NS(Particles_new)( pb, NUM_PARTICLES );
     SIXTRL_ASSERT( particles != nullptr );
-    
+
     ::NS(Particles_set_x_value)(     particles,  0, LIMIT_MIN_X );
     ::NS(Particles_set_y_value)(     particles,  0, ZERO );
     ::NS(Particles_set_state_value)( particles,  0, NOT_LOST_PARTICLE );
     expected_state_after_track[  0 ] = NOT_LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  1, LIMIT_MAX_X );
     ::NS(Particles_set_y_value)(     particles,  1, ZERO );
     ::NS(Particles_set_state_value)( particles,  1, NOT_LOST_PARTICLE );
     expected_state_after_track[  1 ] = NOT_LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  2, ZERO );
     ::NS(Particles_set_y_value)(     particles,  2, LIMIT_MIN_Y );
-    ::NS(Particles_set_state_value)( particles,  2, NOT_LOST_PARTICLE );    
+    ::NS(Particles_set_state_value)( particles,  2, NOT_LOST_PARTICLE );
     expected_state_after_track[  2 ] = NOT_LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  3, ZERO );
     ::NS(Particles_set_y_value)(     particles,  3, LIMIT_MAX_Y );
     ::NS(Particles_set_state_value)( particles,  3, NOT_LOST_PARTICLE );
     expected_state_after_track[  3 ] = NOT_LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  4, LIMIT_MIN_X - EPS );
     ::NS(Particles_set_y_value)(     particles,  4, ZERO );
     ::NS(Particles_set_state_value)( particles,  4, NOT_LOST_PARTICLE );
     expected_state_after_track[  4 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  5, LIMIT_MAX_X + EPS );
     ::NS(Particles_set_y_value)(     particles,  5, ZERO );
     ::NS(Particles_set_state_value)( particles,  5, NOT_LOST_PARTICLE );
     expected_state_after_track[  5 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  6, ZERO );
     ::NS(Particles_set_y_value)(     particles,  6, LIMIT_MIN_Y - EPS );
     ::NS(Particles_set_state_value)( particles,  6, NOT_LOST_PARTICLE );
     expected_state_after_track[  6 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  7, ZERO );
     ::NS(Particles_set_y_value)(     particles,  7, LIMIT_MAX_Y + EPS );
     ::NS(Particles_set_state_value)( particles,  7, NOT_LOST_PARTICLE );
     expected_state_after_track[  7 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  8, LIMIT_MIN_X );
     ::NS(Particles_set_y_value)(     particles,  8, ZERO );
     ::NS(Particles_set_state_value)( particles,  8, LOST_PARTICLE );
     expected_state_after_track[  8 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles,  9, LIMIT_MAX_X );
     ::NS(Particles_set_y_value)(     particles,  9, ZERO );
     ::NS(Particles_set_state_value)( particles,  9, LOST_PARTICLE );
     expected_state_after_track[  9 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 10, ZERO );
     ::NS(Particles_set_y_value)(     particles, 10, LIMIT_MIN_Y );
-    ::NS(Particles_set_state_value)( particles, 10, LOST_PARTICLE );    
+    ::NS(Particles_set_state_value)( particles, 10, LOST_PARTICLE );
     expected_state_after_track[ 10 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 11, ZERO );
     ::NS(Particles_set_y_value)(     particles, 11, LIMIT_MAX_Y );
     ::NS(Particles_set_state_value)( particles, 11, LOST_PARTICLE );
     expected_state_after_track[ 11 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 12, LIMIT_MIN_X - EPS );
     ::NS(Particles_set_y_value)(     particles, 12, ZERO );
     ::NS(Particles_set_state_value)( particles, 12, LOST_PARTICLE );
     expected_state_after_track[ 12 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 13, LIMIT_MAX_X + EPS );
     ::NS(Particles_set_y_value)(     particles, 13, ZERO );
     ::NS(Particles_set_state_value)( particles, 13, LOST_PARTICLE );
     expected_state_after_track[ 13 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 14, ZERO );
     ::NS(Particles_set_y_value)(     particles, 14, LIMIT_MIN_Y - EPS );
     ::NS(Particles_set_state_value)( particles, 14, LOST_PARTICLE );
     expected_state_after_track[ 14 ] = LOST_PARTICLE;
-    
+
     ::NS(Particles_set_x_value)(     particles, 15, ZERO );
     ::NS(Particles_set_y_value)(     particles, 15, LIMIT_MAX_Y + EPS );
     ::NS(Particles_set_state_value)( particles, 15, LOST_PARTICLE );
     expected_state_after_track[ 15 ] = LOST_PARTICLE;
-    
+
     for( size_t ii = size_t{ 0 } ; ii < NUM_PARTICLES ; ++ii )
     {
         ASSERT_TRUE( ::NS(TRACK_SUCCESS) == ::NS(Track_particle_limit_rect)(
             particles, ii, &limit ) );
-        
+
         ASSERT_TRUE( ::NS(Particles_get_state_value)( particles, ii ) ==
                      expected_state_after_track[ ii ] );
     }
-    
+
     ::NS(Buffer_delete)( pb );
 }
-
-/* end: tests/sixtracklib/common/beam_elements/test_be_limit_c99.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_limit_rect_cxx.cpp b/tests/sixtracklib/common/beam_elements/test_be_limit_rect_cxx.cpp
index 0faa92b6..38cd4dc3 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_limit_rect_cxx.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_limit_rect_cxx.cpp
@@ -16,203 +16,200 @@
 #include "sixtracklib/common/particles.hpp"
 #include "sixtracklib/common/be_limit/track.h"
 
-TEST( C99_CommonBeamElementLimitRectTests, BasicUsage )
+TEST( CXXCommonBeamElementLimitRect, BasicUsage )
 {
     namespace st = SIXTRL_CXX_NAMESPACE;
-    
+
     using be_limit_t   = st::LimitRect;
     using buffer_t     = st::Buffer;
-    using real_t       = st::Particles::real_t;    
-    
+    using real_t       = st::Particles::real_t;
+
     real_t const EPS   = std::numeric_limits< real_t >::epsilon();
-    
+
     be_limit_t limit;
     limit.setXLimit( real_t{ 0.2 } );
     limit.setYLimit( real_t{ 0.3 } );
-        
+
     buffer_t eb;
-    
+
     be_limit_t* l2 = eb.createNew< be_limit_t >();
     ASSERT_TRUE( l2 != nullptr );
-    
+
     ASSERT_TRUE( std::fabs( l2->getMinX() - be_limit_t::DEFAULT_MIN_X ) < EPS );
     ASSERT_TRUE( std::fabs( l2->getMaxX() - be_limit_t::DEFAULT_MAX_X ) < EPS );
     ASSERT_TRUE( std::fabs( l2->getMinY() - be_limit_t::DEFAULT_MIN_Y ) < EPS );
     ASSERT_TRUE( std::fabs( l2->getMaxY() - be_limit_t::DEFAULT_MAX_Y ) < EPS );
-    
-    ASSERT_TRUE( st::ARCH_STATUS_SUCCESS == ::NS(LimitRect_copy)( 
+
+    ASSERT_TRUE( st::ARCH_STATUS_SUCCESS == ::NS(LimitRect_copy)(
         limit.getCApiPtr(), l2->getCApiPtr() ) );
-    
-    ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values)( 
+
+    ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values)(
         limit.getCApiPtr(), l2->getCApiPtr() ) );
-        
-    
+
+
     real_t const MIN_X_VALUE = real_t{ -2.0 };
     real_t const MAX_X_VALUE = real_t{  2.0 };
-    
+
     real_t const MIN_Y_VALUE = real_t{ -3.0 };
     real_t const MAX_Y_VALUE = real_t{  3.0 };
-    
-    be_limit_t* l3 = eb.add< be_limit_t >(  
+
+    be_limit_t* l3 = eb.add< be_limit_t >(
         MIN_X_VALUE, MAX_X_VALUE, MIN_Y_VALUE, MAX_Y_VALUE );
-    
+
     ASSERT_TRUE( l3 != nullptr );
-    
+
     ASSERT_TRUE( std::fabs( MIN_X_VALUE - l3->getMinX() ) < EPS );
     ASSERT_TRUE( std::fabs( MAX_X_VALUE - l3->getMaxX() ) < EPS );
     ASSERT_TRUE( std::fabs( MIN_Y_VALUE - l3->getMinY() ) < EPS );
     ASSERT_TRUE( std::fabs( MAX_Y_VALUE - l3->getMaxY() ) < EPS );
-    
-    
+
+
     be_limit_t* l4 = eb.addCopy< be_limit_t >( limit );
-    
+
     ASSERT_TRUE( l4 != nullptr );
-    ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values)( 
+    ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values)(
         l4->getCApiPtr(), limit.getCApiPtr() ) );
-    
+
     real_t const TRESHOLD = real_t{ 9e-4 };
-    
+
     l4->setXLimit( l4->getMaxX() + TRESHOLD );
-    
-    ASSERT_TRUE( 0 != ::NS(LimitRect_compare_values)( 
+
+    ASSERT_TRUE( 0 != ::NS(LimitRect_compare_values)(
         l4->getCApiPtr(), limit.getCApiPtr() ) );
-    
-    ASSERT_TRUE( 0 != ::NS(LimitRect_compare_values_with_treshold)( 
+
+    ASSERT_TRUE( 0 != ::NS(LimitRect_compare_values_with_treshold)(
         l4->getCApiPtr(), limit.getCApiPtr(), EPS ) );
-    
-    ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values_with_treshold)( 
+
+    ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values_with_treshold)(
         l4->getCApiPtr(), limit.getCApiPtr(), TRESHOLD ) );
 }
 
-
-TEST( CXX_CommonBeamElementLimitRectTests, ApertureCheck )
+TEST( CXXCommonBeamElementLimitRect, ApertureCheck )
 {
     namespace st = SIXTRL_CXX_NAMESPACE;
-    
+
     using be_limit_t  = st::LimitRect;
     using buffer_t    = st::Buffer;
     using particles_t = st::Particles;
     using size_t      = buffer_t::size_type;
     using real_t      = particles_t::real_t;
     using pindex_t    = particles_t::index_t;
-    
+
     size_t const NUM_PARTICLES = size_t{ 16 };
-    
+
     real_t const EPS = std::numeric_limits< real_t >::epsilon();
     pindex_t const LOST_PARTICLE = pindex_t{ 0 };
     pindex_t const NOT_LOST_PARTICLE = pindex_t{ 1 };
-    
-    std::vector< pindex_t > expected_state_after_track( 
+
+    std::vector< pindex_t > expected_state_after_track(
         NUM_PARTICLES, LOST_PARTICLE );
-    
+
     be_limit_t limit;
-    
+
     real_t const ZERO = real_t{ 0.0 };
-    
+
     real_t const LIMIT_MIN_X = real_t{ -1.0 };
     real_t const LIMIT_MAX_X = real_t{ +1.0 };
-    
+
     real_t const LIMIT_MIN_Y = real_t{ -1.0 };
     real_t const LIMIT_MAX_Y = real_t{ +1.0 };
-    
+
     limit.setMinX( LIMIT_MIN_X );
     limit.setMaxX( LIMIT_MAX_X );
     limit.setMinY( LIMIT_MIN_Y );
     limit.setMaxY( LIMIT_MAX_Y );
-    
+
     buffer_t pb;
-    
+
     particles_t* particles = pb.createNew< particles_t >( NUM_PARTICLES );
     SIXTRL_ASSERT( particles != nullptr );
-    
+
     particles->setXValue( 0, LIMIT_MIN_X );
     particles->setYValue( 0, ZERO );
     particles->setStateValue( 0, NOT_LOST_PARTICLE );
     expected_state_after_track[  0 ] = NOT_LOST_PARTICLE;
-    
+
     particles->setXValue( 1, LIMIT_MAX_X );
     particles->setYValue( 1, ZERO );
     particles->setStateValue( 1, NOT_LOST_PARTICLE );
     expected_state_after_track[  1 ] = NOT_LOST_PARTICLE;
-    
+
     particles->setXValue( 2, ZERO );
     particles->setYValue( 2, LIMIT_MIN_Y );
-    particles->setStateValue( 2, NOT_LOST_PARTICLE );    
+    particles->setStateValue( 2, NOT_LOST_PARTICLE );
     expected_state_after_track[  2 ] = NOT_LOST_PARTICLE;
-    
+
     particles->setXValue( 3, ZERO );
     particles->setYValue( 3, LIMIT_MAX_Y );
     particles->setStateValue( 3, NOT_LOST_PARTICLE );
     expected_state_after_track[  3 ] = NOT_LOST_PARTICLE;
-    
+
     particles->setXValue( 4, LIMIT_MIN_X - EPS );
     particles->setYValue( 4, ZERO );
     particles->setStateValue( 4, NOT_LOST_PARTICLE );
     expected_state_after_track[  4 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 5, LIMIT_MAX_X + EPS );
     particles->setYValue( 5, ZERO );
     particles->setStateValue( 5, NOT_LOST_PARTICLE );
     expected_state_after_track[  5 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 6, ZERO );
     particles->setYValue( 6, LIMIT_MIN_Y - EPS );
     particles->setStateValue( 6, NOT_LOST_PARTICLE );
     expected_state_after_track[  6 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 7, ZERO );
     particles->setYValue( 7, LIMIT_MAX_Y + EPS );
     particles->setStateValue( 7, NOT_LOST_PARTICLE );
     expected_state_after_track[  7 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 8, LIMIT_MIN_X );
     particles->setYValue( 8, ZERO );
     particles->setStateValue( 8, LOST_PARTICLE );
     expected_state_after_track[  8 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 9, LIMIT_MAX_X );
     particles->setYValue( 9, ZERO );
     particles->setStateValue( 9, LOST_PARTICLE );
     expected_state_after_track[  9 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 10, ZERO );
     particles->setYValue( 10, LIMIT_MIN_Y );
     particles->setStateValue( 10, LOST_PARTICLE );
     expected_state_after_track[ 10 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 11, ZERO );
     particles->setYValue( 11, LIMIT_MAX_Y );
     particles->setStateValue( 11, LOST_PARTICLE );
     expected_state_after_track[ 11 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 12, LIMIT_MIN_X - EPS );
     particles->setYValue( 12, ZERO );
     particles->setStateValue( 12, LOST_PARTICLE );
     expected_state_after_track[ 12 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 13, LIMIT_MAX_X + EPS );
     particles->setYValue( 13, ZERO );
     particles->setStateValue( 13, LOST_PARTICLE );
     expected_state_after_track[ 13 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 14, ZERO );
     particles->setYValue( 14, LIMIT_MIN_Y - EPS );
     particles->setStateValue( 14, LOST_PARTICLE );
     expected_state_after_track[ 14 ] = LOST_PARTICLE;
-    
+
     particles->setXValue( 15, ZERO );
     particles->setYValue( 15, LIMIT_MAX_Y + EPS );
     particles->setStateValue( 15, LOST_PARTICLE );
     expected_state_after_track[ 15 ] = LOST_PARTICLE;
-    
+
     for( size_t ii = size_t{ 0 } ; ii < NUM_PARTICLES ; ++ii )
     {
         ASSERT_TRUE( ::NS(TRACK_SUCCESS) == ::NS(Track_particle_limit_rect)(
             particles->getCApiPtr(), ii, limit.getCApiPtr() ) );
-        
-        ASSERT_TRUE( particles->getStateValue( ii ) == 
+
+        ASSERT_TRUE( particles->getStateValue( ii ) ==
                      expected_state_after_track[ ii ] );
     }
 }
-
-/* end: tests/sixtracklib/common/beam_elements/test_be_limit_rect_cxx.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_monitor_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_monitor_c99.cpp
index 34ce102d..89aba462 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_monitor_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_monitor_c99.cpp
@@ -28,7 +28,7 @@
 #include "sixtracklib/common/track/track.h"
 
 
-TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
+TEST( C99CommonBeamMonitor, MinimalAddToBufferCopyRemapRead )
 {
     using size_t        = ::NS(buffer_size_t);
     using raw_t         = unsigned char;
@@ -77,14 +77,14 @@ TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
     ::NS(BeamMonitor)* be_monitor = ::NS(BeamMonitor_new)( eb );
 
     ASSERT_TRUE( be_monitor != nullptr );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_num_stores)( be_monitor ) == nturn_t{ 0 } );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_start)( be_monitor ) == nturn_t{ 0 } );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_skip)( be_monitor ) == nturn_t{ 1 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_num_stores)( be_monitor ) == nturn_t{ 0 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_start)( be_monitor ) == nturn_t{ 0 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_skip)( be_monitor ) == nturn_t{ 1 } );
     ASSERT_TRUE( !::NS(BeamMonitor_is_rolling)( be_monitor ) );
     ASSERT_TRUE(  ::NS(BeamMonitor_is_turn_ordered)( be_monitor ) );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_out_address)( be_monitor ) == addr_t{ 0 } );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) == index_t{ 0 } );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_max_particle_id)( be_monitor ) == index_t{ 0 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_out_address)( be_monitor ) == addr_t{ 0 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_min_particle_id)( be_monitor ) == index_t{ -1 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_max_particle_id)( be_monitor ) == index_t{ -1 } );
 
     ::NS(BeamMonitor_set_num_stores)( be_monitor, 10u );
     ::NS(BeamMonitor_set_start)( be_monitor, 1000u );
@@ -94,23 +94,23 @@ TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
     ::NS(BeamMonitor_set_out_address)( be_monitor, out_addr_0 );
 
     ASSERT_TRUE( be_monitor != nullptr );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_num_stores)( be_monitor ) == nturn_t{ 10 } );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_start)( be_monitor ) == nturn_t{ 1000 } );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_skip)( be_monitor ) == nturn_t{ 4 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_num_stores)( be_monitor ) == nturn_t{ 10 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_start)( be_monitor ) == nturn_t{ 1000 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_skip)( be_monitor ) == nturn_t{ 4 } );
     ASSERT_TRUE(  ::NS(BeamMonitor_is_rolling)( be_monitor ) );
     ASSERT_TRUE(  ::NS(BeamMonitor_is_turn_ordered)( be_monitor ) );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_out_address)( be_monitor ) == out_addr_0 );
+    ASSERT_TRUE(  ::NS(BeamMonitor_out_address)( be_monitor ) == out_addr_0 );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) >=
+    ASSERT_TRUE(  ::NS(BeamMonitor_min_particle_id)( be_monitor ) >=
                   index_t{ 0 } );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) <=
+    ASSERT_TRUE(  ::NS(BeamMonitor_min_particle_id)( be_monitor ) <=
                   static_cast< index_t >( min_particle_id ) );
 
-    ASSERT_TRUE( ::NS(BeamMonitor_get_max_particle_id)( be_monitor ) >=
-                 ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) );
+    ASSERT_TRUE( ::NS(BeamMonitor_max_particle_id)( be_monitor ) >=
+                 ::NS(BeamMonitor_min_particle_id)( be_monitor ) );
 
-    ASSERT_TRUE( ::NS(BeamMonitor_get_max_particle_id)( be_monitor ) >=
+    ASSERT_TRUE( ::NS(BeamMonitor_max_particle_id)( be_monitor ) >=
                  static_cast< index_t >( max_particle_id ) );
 
     cmp_beam_monitors.push_back( *be_monitor );
@@ -123,14 +123,14 @@ TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
 
     cmp_beam_monitors.push_back( *copy_be_monitor );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_num_stores)( copy_be_monitor ) ==
-                  ::NS(BeamMonitor_get_num_stores)( &cmp_beam_monitors[ 0 ] ) );
+    ASSERT_TRUE(  ::NS(BeamMonitor_num_stores)( copy_be_monitor ) ==
+                  ::NS(BeamMonitor_num_stores)( &cmp_beam_monitors[ 0 ] ) );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_start)( copy_be_monitor ) ==
-                  ::NS(BeamMonitor_get_start)( &cmp_beam_monitors[ 0 ] ) );
+    ASSERT_TRUE(  ::NS(BeamMonitor_start)( copy_be_monitor ) ==
+                  ::NS(BeamMonitor_start)( &cmp_beam_monitors[ 0 ] ) );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_skip)( copy_be_monitor ) ==
-                  ::NS(BeamMonitor_get_skip)( &cmp_beam_monitors[ 0 ] ) );
+    ASSERT_TRUE(  ::NS(BeamMonitor_skip)( copy_be_monitor ) ==
+                  ::NS(BeamMonitor_skip)( &cmp_beam_monitors[ 0 ] ) );
 
     ASSERT_TRUE(  ::NS(BeamMonitor_is_rolling)( copy_be_monitor ) ==
                   ::NS(BeamMonitor_is_rolling)( &cmp_beam_monitors[ 0 ] ) );
@@ -141,30 +141,30 @@ TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
     ASSERT_TRUE(  ::NS(BeamMonitor_is_turn_ordered)( copy_be_monitor ) ==
                   ::NS(BeamMonitor_is_turn_ordered)( &cmp_beam_monitors[ 0 ] ) );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_out_address)( copy_be_monitor ) ==
-                  ::NS(BeamMonitor_get_out_address)( &cmp_beam_monitors[ 0 ] ) );
+    ASSERT_TRUE(  ::NS(BeamMonitor_out_address)( copy_be_monitor ) ==
+                  ::NS(BeamMonitor_out_address)( &cmp_beam_monitors[ 0 ] ) );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_min_particle_id)( copy_be_monitor ) ==
-                  ::NS(BeamMonitor_get_min_particle_id)( &cmp_beam_monitors[ 0 ] ) );
+    ASSERT_TRUE(  ::NS(BeamMonitor_min_particle_id)( copy_be_monitor ) ==
+                  ::NS(BeamMonitor_min_particle_id)( &cmp_beam_monitors[ 0 ] ) );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_max_particle_id)( copy_be_monitor ) ==
-                  ::NS(BeamMonitor_get_max_particle_id)( &cmp_beam_monitors[ 0 ] ) );
+    ASSERT_TRUE(  ::NS(BeamMonitor_max_particle_id)( copy_be_monitor ) ==
+                  ::NS(BeamMonitor_max_particle_id)( &cmp_beam_monitors[ 0 ] ) );
 
     be_monitor = ::NS(BeamMonitor_add)( eb, 10u, 5000u, 1u, out_addr_1,
         min_particle_id, max_particle_id, false, true );
 
     ASSERT_TRUE( be_monitor != nullptr );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_num_stores)( be_monitor ) == nturn_t{ 10 } );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_start)( be_monitor ) == nturn_t{ 5000 } );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_skip)( be_monitor ) == nturn_t{ 1 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_num_stores)( be_monitor ) == nturn_t{ 10 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_start)( be_monitor ) == nturn_t{ 5000 } );
+    ASSERT_TRUE(  ::NS(BeamMonitor_skip)( be_monitor ) == nturn_t{ 1 } );
     ASSERT_TRUE( !::NS(BeamMonitor_is_rolling)( be_monitor ) );
     ASSERT_TRUE(  ::NS(BeamMonitor_is_turn_ordered)( be_monitor ) );
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_out_address)( be_monitor ) == out_addr_1 );
+    ASSERT_TRUE(  ::NS(BeamMonitor_out_address)( be_monitor ) == out_addr_1 );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) ==
+    ASSERT_TRUE(  ::NS(BeamMonitor_min_particle_id)( be_monitor ) ==
                   static_cast< index_t >( min_particle_id ) );
 
-    ASSERT_TRUE(  ::NS(BeamMonitor_get_max_particle_id)( be_monitor ) ==
+    ASSERT_TRUE(  ::NS(BeamMonitor_max_particle_id)( be_monitor ) ==
                   static_cast< index_t >( max_particle_id ) );
 
     cmp_beam_monitors.push_back( *be_monitor );
@@ -215,14 +215,14 @@ TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
             ::NS(Buffer_get_const_data_begin)( eb ),
             ::NS(Buffer_get_slot_size)( eb ) ) );
 
-    ASSERT_TRUE( ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) ==
+    ASSERT_TRUE( ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) ==
                  cmp_beam_monitors.size() );
 
-    ASSERT_TRUE( ::NS(BeamMonitor_get_num_of_beam_monitor_objects_from_managed_buffer)(
-        ::NS(Buffer_get_const_data_begin)( eb ), ::NS(Buffer_get_slot_size)( eb ) ) ==
-                 cmp_beam_monitors.size() );
+    ASSERT_TRUE( ::NS(BeamMonitor_num_monitors_in_managed_buffer)(
+        ::NS(Buffer_get_const_data_begin)( eb ),
+        ::NS(Buffer_get_slot_size)( eb ) ) == cmp_beam_monitors.size() );
 
-    ::NS(BeamMonitor_clear_all)( eb );
+    ::NS(BeamMonitor_reset_all_in_buffer)( eb );
 
     jj = 0;
 
@@ -240,14 +240,14 @@ TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
 
         ASSERT_TRUE( ptr_bemon != nullptr );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_num_stores)( ptr_bemon ) ==
-                     ::NS(BeamMonitor_get_num_stores)( &cmp_be_monitor ) );
+        ASSERT_TRUE( ::NS(BeamMonitor_num_stores)( ptr_bemon ) ==
+                     ::NS(BeamMonitor_num_stores)( &cmp_be_monitor ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_start)( ptr_bemon ) ==
-                     ::NS(BeamMonitor_get_start)( &cmp_be_monitor ) );
+        ASSERT_TRUE( ::NS(BeamMonitor_start)( ptr_bemon ) ==
+                     ::NS(BeamMonitor_start)( &cmp_be_monitor ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_skip)( ptr_bemon ) ==
-                     ::NS(BeamMonitor_get_skip)( &cmp_be_monitor ) );
+        ASSERT_TRUE( ::NS(BeamMonitor_skip)( ptr_bemon ) ==
+                     ::NS(BeamMonitor_skip)( &cmp_be_monitor ) );
 
         ASSERT_TRUE( ::NS(BeamMonitor_is_rolling)( ptr_bemon ) ==
                      ::NS(BeamMonitor_is_rolling)( &cmp_be_monitor ) );
@@ -255,17 +255,17 @@ TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
         ASSERT_TRUE( ::NS(BeamMonitor_is_turn_ordered)( ptr_bemon ) ==
                      ::NS(BeamMonitor_is_turn_ordered)( &cmp_be_monitor ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( ptr_bemon ) !=
-                     ::NS(BeamMonitor_get_out_address)( &cmp_be_monitor ) );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( ptr_bemon ) !=
+                     ::NS(BeamMonitor_out_address)( &cmp_be_monitor ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( ptr_bemon ) ==
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( ptr_bemon ) ==
                      addr_t{ 0 } );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)( ptr_bemon ) ==
-                     index_t{ 0 } );
+        ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)( ptr_bemon ) ==
+                     index_t{ -1 } );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_max_particle_id)( ptr_bemon ) ==
-                     index_t{ 0 } );
+        ASSERT_TRUE( ::NS(BeamMonitor_max_particle_id)( ptr_bemon ) ==
+                     index_t{ -1 } );
     }
 
     ::NS(Buffer_delete)( eb );
@@ -274,7 +274,7 @@ TEST( C99_CommonBeamMonitorTests, MinimalAddToBufferCopyRemapRead )
     ::NS(Buffer_free)( &cmp_eb );
 }
 
-TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
+TEST( C99CommonBeamMonitor, AssignIoBufferToBeamMonitors )
 {
     using real_t        = ::NS(particle_real_t);
     using size_t        = ::NS(buffer_size_t);
@@ -324,14 +324,14 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
 
         ASSERT_TRUE( be_monitor != nullptr );
 
-        sum_num_of_stores += ::NS(BeamMonitor_get_num_stores)( be_monitor );
+        sum_num_of_stores += ::NS(BeamMonitor_num_stores)( be_monitor );
         cmp_beam_monitors.push_back( *be_monitor );
     }
 
     ASSERT_TRUE( ::NS(ElemByElemConfig_get_num_elem_by_elem_objects)( eb ) ==
                  ( NUM_DRIFTS + NUM_BEAM_MONITORS ) );
 
-    ASSERT_TRUE( ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) ==
+    ASSERT_TRUE( ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) ==
                  NUM_BEAM_MONITORS );
 
     /* --------------------------------------------------------------------- */
@@ -389,7 +389,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     eb_it ) );
 
             ASSERT_TRUE( be_monitor != nullptr );
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( be_monitor ) !=
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_monitor ) !=
                          addr_t{ 0 } );
 
             addr_t const cmp_addr = static_cast< addr_t >( reinterpret_cast<
@@ -397,22 +397,22 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     out_buffer, out_particles_offset ) ) );
 
             ASSERT_TRUE( cmp_addr != addr_t{ 0 }  );
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( be_monitor ) == cmp_addr );
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_monitor ) == cmp_addr );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) >=
+            ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)( be_monitor ) >=
                          index_t{ 0 } );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) <=
+            ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)( be_monitor ) <=
                          static_cast< index_t >( min_particle_id ) );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_max_particle_id)( be_monitor ) >=
+            ASSERT_TRUE( ::NS(BeamMonitor_max_particle_id)( be_monitor ) >=
                          static_cast< index_t >( max_particle_id ) );
 
             ++out_particles_offset;
         }
     }
 
-    ::NS(BeamMonitor_clear_all)( eb );
+    ::NS(BeamMonitor_reset_all_in_buffer)( eb );
 
     eb_it = eb_begin;
 
@@ -425,7 +425,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     eb_it ) );
 
             ASSERT_TRUE( be_monitor != nullptr );
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( be_monitor ) ==
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_monitor ) ==
                          addr_t{ 0 } );
         }
     }
@@ -471,7 +471,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     eb_it ) );
 
             ASSERT_TRUE( be_monitor != nullptr );
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( be_monitor ) !=
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_monitor ) !=
                          addr_t{ 0 } );
 
             addr_t const cmp_addr = static_cast< addr_t >( reinterpret_cast<
@@ -481,16 +481,16 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
             ASSERT_TRUE( cmp_addr != addr_t{ 0 }  );
             ASSERT_TRUE( cmp_beam_monitors.size() > jj );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( be_monitor ) ==
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_monitor ) ==
                          cmp_addr );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) >=
+            ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)( be_monitor ) >=
                          index_t{ 0 } );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) <=
+            ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)( be_monitor ) <=
                          static_cast< index_t >( min_particle_id ) );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_max_particle_id)( be_monitor ) >=
+            ASSERT_TRUE( ::NS(BeamMonitor_max_particle_id)( be_monitor ) >=
                          static_cast< index_t >( max_particle_id ) );
 
             ++out_particles_offset;
@@ -498,7 +498,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
         }
     }
 
-    ::NS(BeamMonitor_clear_all)( eb );
+    ::NS(BeamMonitor_reset_all_in_buffer)( eb );
 
     eb_it = eb_begin;
 
@@ -511,7 +511,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     eb_it ) );
 
             ASSERT_TRUE( be_monitor != nullptr );
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)(
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)(
                 be_monitor ) == addr_t{ 0 } );
         }
     }
@@ -557,7 +557,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
             ASSERT_TRUE( be_monitor != nullptr );
 
             nturn_t const num_stores =
-                ::NS(BeamMonitor_get_num_stores)( be_monitor );
+                ::NS(BeamMonitor_num_stores)( be_monitor );
 
             if( num_stores > nturn_t{ 0 } )
             {
@@ -593,7 +593,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     eb_it ) );
 
             ASSERT_TRUE( be_monitor != nullptr );
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( be_monitor ) !=
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_monitor ) !=
                          addr_t{ 0 } );
 
             addr_t const cmp_addr = static_cast< addr_t >( reinterpret_cast<
@@ -603,16 +603,16 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
             ASSERT_TRUE( cmp_addr != addr_t{ 0 }  );
             ASSERT_TRUE( cmp_beam_monitors.size() > jj );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( be_monitor ) ==
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_monitor ) ==
                          cmp_addr );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) >=
+            ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)( be_monitor ) >=
                          index_t{ 0 } );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)( be_monitor ) <=
+            ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)( be_monitor ) <=
                          static_cast< index_t >( min_particle_id ) );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_max_particle_id)( be_monitor ) >=
+            ASSERT_TRUE( ::NS(BeamMonitor_max_particle_id)( be_monitor ) >=
                          static_cast< index_t >( max_particle_id ) );
 
             ++out_particles_offset;
@@ -620,7 +620,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
         }
     }
 
-    ::NS(BeamMonitor_clear_all)( eb );
+    ::NS(BeamMonitor_reset_all_in_buffer)( eb );
 
     eb_it = eb_begin;
 
@@ -633,7 +633,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     eb_it ) );
 
             ASSERT_TRUE( be_monitor != nullptr );
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)(
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)(
                 be_monitor ) == addr_t{ 0 } );
         }
     }
@@ -645,7 +645,7 @@ TEST( C99_CommonBeamMonitorTests, AssignIoBufferToBeamMonitors )
     ::NS(Buffer_delete)( out_buffer );
 }
 
-TEST( C99_CommonBeamMonitorTests, TrackingAndTurnByTurnIO )
+TEST( C99CommonBeamMonitor, TrackingAndTurnByTurnIO )
 {
     using real_t          = ::NS(particle_real_t);
     using status_t        = ::NS(arch_status_t);
@@ -700,10 +700,10 @@ TEST( C99_CommonBeamMonitorTests, TrackingAndTurnByTurnIO )
         ASSERT_TRUE( be_monitor != nullptr );
 
         nturn_t const num_stores =
-            ::NS(BeamMonitor_get_num_stores)( be_monitor );
+            ::NS(BeamMonitor_num_stores)( be_monitor );
 
-        nturn_t const skip  = ::NS(BeamMonitor_get_skip)( be_monitor );
-        nturn_t const start = ::NS(BeamMonitor_get_start)( be_monitor );
+        nturn_t const skip  = ::NS(BeamMonitor_skip)( be_monitor );
+        nturn_t const start = ::NS(BeamMonitor_start)( be_monitor );
         nturn_t const n     = num_stores * skip;
 
         ASSERT_TRUE( num_stores > nturn_t{ 0 } );
@@ -841,7 +841,7 @@ TEST( C99_CommonBeamMonitorTests, TrackingAndTurnByTurnIO )
                     ::NS(Object_get_const_begin_ptr)( obj_it ) );
 
             ASSERT_TRUE( monitor != nullptr );
-            nturn_t const num_stores = ::NS(BeamMonitor_get_num_stores)( monitor );
+            nturn_t const num_stores = ::NS(BeamMonitor_num_stores)( monitor );
 
             ASSERT_TRUE( out_particle_block_index <
                 ::NS(Buffer_get_num_of_objects)( out_buffer ) );
@@ -850,8 +850,8 @@ TEST( C99_CommonBeamMonitorTests, TrackingAndTurnByTurnIO )
                 ::NS(Particles_buffer_get_const_particles)(
                     out_buffer, out_particle_block_index );
 
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( monitor ) != addr_t{ 0 } );
-            ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( monitor ) == static_cast<
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( monitor ) != addr_t{ 0 } );
+            ASSERT_TRUE( ::NS(BeamMonitor_out_address)( monitor ) == static_cast<
                 addr_t >( reinterpret_cast< uintptr_t >( out_particles ) ) );
 
             ASSERT_TRUE( num_stores > nturn_t{ 0 } );
@@ -913,7 +913,7 @@ TEST( C99_CommonBeamMonitorTests, TrackingAndTurnByTurnIO )
                 ptr_const_mon_t mon = reinterpret_cast< ptr_const_mon_t >(
                         ::NS(Object_get_const_begin_ptr)( obj_it ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)(
+                ASSERT_TRUE( ::NS(BeamMonitor_out_address)(
                     mon ) != addr_t{ 0 } );
 
                 if( !::NS(BeamMonitor_has_turn_stored)( mon, kk, NUM_TURNS ) )
@@ -921,13 +921,13 @@ TEST( C99_CommonBeamMonitorTests, TrackingAndTurnByTurnIO )
                     continue;
                 }
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_start)( mon ) <= kk );
-                ASSERT_TRUE( ( ( kk - ::NS(BeamMonitor_get_start)( mon ) )
-                    % ::NS(BeamMonitor_get_skip)( mon ) ) == nturn_t{ 0 } );
+                ASSERT_TRUE( ::NS(BeamMonitor_start)( mon ) <= kk );
+                ASSERT_TRUE( ( ( kk - ::NS(BeamMonitor_start)( mon ) )
+                    % ::NS(BeamMonitor_skip)( mon ) ) == nturn_t{ 0 } );
 
                 ptr_particles_t out_particles = reinterpret_cast<
                     ptr_particles_t >( static_cast< uintptr_t >(
-                        ::NS(BeamMonitor_get_out_address)( mon ) ) );
+                        ::NS(BeamMonitor_out_address)( mon ) ) );
 
                 ASSERT_TRUE( elem_by_elem_particles != nullptr );
 
@@ -1004,5 +1004,3 @@ TEST( C99_CommonBeamMonitorTests, TrackingAndTurnByTurnIO )
     ::NS(Buffer_delete)( elem_by_elem_buffer );
     ::NS(Buffer_delete)( cmp_particles_buffer );
 }
-
-/* end: tests/sixtracklib/common/test_be_monitor_c99.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_multipole_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_multipole_c99.cpp
index b55a75f0..150e4566 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_multipole_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_multipole_c99.cpp
@@ -19,14 +19,14 @@
 #include "sixtracklib/common/be_multipole/be_multipole.h"
 
 /* ************************************************************************* *
- * ******  st_MultiPole:
+ * ****** NS(Multipole):
  * ************************************************************************* */
 
-TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
+TEST( C99CommonBeamElementMultipole, MinimalAddToBufferCopyRemapRead )
 {
-    using    belem_t = ::st_MultiPole;
-    using     size_t = ::st_buffer_size_t;
-    using   object_t = ::st_Object;
+    using    belem_t = NS(Multipole);
+    using     size_t = NS(buffer_size_t);
+    using   object_t = NS(Object);
     using      raw_t = unsigned char;
     using  mp_real_t = ::NS(multipole_real_t);
     using mp_order_t = ::NS(multipole_order_t);
@@ -51,20 +51,20 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
     hxl_dist_t hxl_dist(    mp_real_t{  -5.0 },  mp_real_t{  +5.0 } );
     hyl_dist_t hyl_dist(    mp_real_t{  -5.0 },  mp_real_t{  +5.0 } );
     bal_dist_t bal_dist(    mp_real_t{ -10.0 },  mp_real_t{ +10.0 } );
-    ord_dist_t ord_dist(   mp_order_t{    -1 }, mp_order_t{  20   } );
+    ord_dist_t ord_dist(   mp_order_t{     0 }, mp_order_t{  20   } );
 
     static SIXTRL_CONSTEXPR_OR_CONST size_t
         NUM_BEAM_ELEMENTS = size_t{ 1000 };
 
-    ::st_object_type_id_t const BEAM_ELEMENT_TYPE_ID =
-        ::st_OBJECT_TYPE_MULTIPOLE;
+    NS(object_type_id_t) const BEAM_ELEMENT_TYPE_ID =
+        NS(OBJECT_TYPE_MULTIPOLE);
 
     std::vector< belem_t > orig_beam_elements( NUM_BEAM_ELEMENTS, belem_t{} );
 
     std::vector< mp_order_t > orig_multipole_orders(
         NUM_BEAM_ELEMENTS, mp_order_t{ 0 } );
 
-    size_t const slot_size      = ::st_BUFFER_DEFAULT_SLOT_SIZE;
+    size_t const slot_size      = NS(BUFFER_DEFAULT_SLOT_SIZE);
     size_t const num_objs       = NUM_BEAM_ELEMENTS;
     size_t const num_garbage    = size_t{ 0 };
 
@@ -79,18 +79,18 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
         mp_real_t  const hyl      = hyl_dist( prng );
         mp_order_t const order    = ord_dist( prng );
 
-        belem_t* ptr_mp = ::st_MultiPole_preset( &orig_beam_elements[ ii ] );
+        belem_t* ptr_mp = NS(Multipole_preset)( &orig_beam_elements[ ii ] );
         ASSERT_TRUE( ptr_mp != nullptr );
 
-        ::st_MultiPole_set_length( ptr_mp, length );
-        ::st_MultiPole_set_hxl( ptr_mp, hxl );
-        ::st_MultiPole_set_hyl( ptr_mp, hyl );
+        NS(Multipole_set_length)( ptr_mp, length );
+        NS(Multipole_set_hxl)( ptr_mp, hxl );
+        NS(Multipole_set_hyl)( ptr_mp, hyl );
 
         ASSERT_TRUE( std::fabs( length -
-            ::st_MultiPole_get_length( ptr_mp ) ) < EPS );
+            NS(Multipole_length)( ptr_mp ) ) < EPS );
 
-        ASSERT_TRUE( std::fabs( hxl - ::st_MultiPole_get_hxl( ptr_mp ) ) < EPS );
-        ASSERT_TRUE( std::fabs( hyl - ::st_MultiPole_get_hyl( ptr_mp ) ) < EPS );
+        ASSERT_TRUE( std::fabs( hxl - NS(Multipole_hxl)( ptr_mp ) ) < EPS );
+        ASSERT_TRUE( std::fabs( hyl - NS(Multipole_hyl)( ptr_mp ) ) < EPS );
 
         if( order >= mp_order_t{ 0 } )
         {
@@ -135,13 +135,18 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
                 *bal_it = bal_dist( prng );
             }
 
-            ::st_MultiPole_assign_bal( ptr_mp, order, bal_begin );
-            ASSERT_TRUE( ::st_MultiPole_get_order( ptr_mp ) == order );
-            ASSERT_TRUE( ::st_MultiPole_get_bal_size( ptr_mp ) ==
+            NS(arch_status_t) status = NS(Multipole_set_order)( ptr_mp, order );
+            ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
+            ASSERT_TRUE( NS(Multipole_order)( ptr_mp ) == order );
+            ASSERT_TRUE( NS(Multipole_bal_length)( ptr_mp ) ==
                             static_cast< size_t >( 2 * order + 2 ) );
 
-            mp_real_t const* cmp_bal_it =
-                ::st_MultiPole_get_const_bal( ptr_mp );
+            status = NS(Multipole_set_bal_addr)( ptr_mp,
+                static_cast< NS(buffer_addr_t) >( reinterpret_cast<
+                    uintptr_t >( bal_begin ) ) );
+            ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
+            mp_real_t const* cmp_bal_it = NS(Multipole_const_bal_begin)(
+                ptr_mp );
 
             ASSERT_TRUE( cmp_bal_it != nullptr );
 
@@ -153,28 +158,28 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
             }
 
             size_t const obj_num_dataptrs =
-                ::st_MultiPole_get_num_dataptrs( ptr_mp );
+                NS(Multipole_num_dataptrs)( ptr_mp );
 
             size_t const sizes[]  = { sizeof( mp_real_t ) };
-            size_t const counts[] = { ::st_MultiPole_get_bal_size( ptr_mp ) };
+            size_t const counts[] = { NS(Multipole_bal_length)( ptr_mp ) };
 
             bal_begin = bal_end;
 
-            num_slots += ::st_ManagedBuffer_predict_required_num_slots( nullptr,
+            num_slots += NS(ManagedBuffer_predict_required_num_slots)( nullptr,
                 sizeof( belem_t ), obj_num_dataptrs, sizes, counts, slot_size );
 
             num_dataptrs += obj_num_dataptrs;
         }
         else
         {
-            ::st_MultiPole_set_order( ptr_mp, mp_order_t{ -1 } );
-            num_slots += ::st_ManagedBuffer_predict_required_num_slots( nullptr,
-                sizeof( belem_t ), ::st_MultiPole_get_num_dataptrs( ptr_mp ),
+            NS(Multipole_set_order)( ptr_mp, mp_order_t{ -1 } );
+            num_slots += NS(ManagedBuffer_predict_required_num_slots)( nullptr,
+                sizeof( belem_t ), NS(Multipole_num_dataptrs)( ptr_mp ),
                     nullptr, nullptr, slot_size );
 
         }
 
-        ASSERT_TRUE( order == ::st_MultiPole_get_order( ptr_mp ) );
+        ASSERT_TRUE( order == NS(Multipole_order)( ptr_mp ) );
     }
 
     /* --------------------------------------------------------------------- */
@@ -183,15 +188,15 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
     object_t*      ptr_object = nullptr;
     belem_t*       ptr_mp     = nullptr;
 
-    size_t const requ_buffer_size = ::st_ManagedBuffer_calculate_buffer_length(
+    size_t const requ_buffer_size = NS(ManagedBuffer_calculate_buffer_length)(
         nullptr, num_objs, num_slots, num_dataptrs, num_garbage, slot_size );
 
     ASSERT_TRUE( requ_buffer_size >=
-                 ::st_ManagedBuffer_get_header_length( nullptr, slot_size ) );
+                 NS(ManagedBuffer_get_header_length)( nullptr, slot_size ) );
 
     /* --------------------------------------------------------------------- */
 
-    ::st_Buffer* eb = ::st_Buffer_new( requ_buffer_size );
+    NS(Buffer)* eb = NS(Buffer_new)( requ_buffer_size );
     ASSERT_TRUE( eb != nullptr );
 
     /* --------------------------------------------------------------------- */
@@ -201,59 +206,59 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
     ptr_orig = &orig_beam_elements[ be_index++ ];
 
     ASSERT_TRUE( ptr_orig != nullptr );
-    ASSERT_TRUE( ( ( ::st_MultiPole_get_order( ptr_orig ) >= mp_order_t{ 0 } ) &&
-                   ( ::st_MultiPole_get_const_bal( ptr_orig ) != nullptr ) ) ||
-                 ( ( ::st_MultiPole_get_order( ptr_orig ) <  mp_order_t{ 0 } ) &&
-                   ( ::st_MultiPole_get_const_bal( ptr_orig ) == nullptr ) ) );
+    ASSERT_TRUE( ( ( NS(Multipole_order)( ptr_orig ) >= mp_order_t{ 0 } ) &&
+                   ( NS(Multipole_const_bal_begin)( ptr_orig ) != nullptr ) ) ||
+                 ( ( NS(Multipole_order)( ptr_orig ) <  mp_order_t{ 0 } ) &&
+                   ( NS(Multipole_const_bal_begin)( ptr_orig ) == nullptr ) ) );
 
-    if( ::st_MultiPole_get_order( ptr_orig )  >= mp_order_t{ 0 } )
+    if( NS(Multipole_order)( ptr_orig )  >= mp_order_t{ 0 } )
     {
-        size_t const offsets[] = { offsetof( belem_t, bal ) };
+        size_t const offsets[] = { offsetof( belem_t, bal_addr ) };
         size_t const sizes[]   = { sizeof( ::NS(multipole_real_t) ) };
-        size_t const counts[]  = { ::st_MultiPole_get_bal_size( ptr_orig ) };
+        size_t const counts[]  = { NS(Multipole_bal_length)( ptr_orig ) };
 
-        ptr_object = ::st_Buffer_add_object( eb, ptr_orig, sizeof( belem_t ),
-            BEAM_ELEMENT_TYPE_ID, ::st_MultiPole_get_num_dataptrs( ptr_orig ),
+        ptr_object = NS(Buffer_add_object)( eb, ptr_orig, sizeof( belem_t ),
+            BEAM_ELEMENT_TYPE_ID, NS(Multipole_num_dataptrs)( ptr_orig ),
                 offsets, sizes, counts );
     }
     else
     {
-        ptr_object = ::st_Buffer_add_object( eb, ptr_orig, sizeof( belem_t ),
-            BEAM_ELEMENT_TYPE_ID, ::st_MultiPole_get_num_dataptrs( ptr_orig ),
+        ptr_object = NS(Buffer_add_object)( eb, ptr_orig, sizeof( belem_t ),
+            BEAM_ELEMENT_TYPE_ID, NS(Multipole_num_dataptrs)( ptr_orig ),
                 nullptr, nullptr, nullptr );
     }
 
     ASSERT_TRUE( ptr_object != nullptr );
 
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-    ASSERT_TRUE( ::st_Object_get_const_begin_ptr( ptr_object ) != nullptr );
-    ASSERT_TRUE( ::st_Object_get_size( ptr_object ) >= sizeof( belem_t ) );
-    ASSERT_TRUE( ::st_Object_get_type_id( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+    ASSERT_TRUE( NS(Object_get_const_begin_ptr)( ptr_object ) != nullptr );
+    ASSERT_TRUE( NS(Object_get_size)( ptr_object ) >= sizeof( belem_t ) );
+    ASSERT_TRUE( NS(Object_get_type_id)( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
 
     ptr_mp = reinterpret_cast< belem_t* >(
-        ::st_Object_get_begin_ptr( ptr_object ) );
+        NS(Object_get_begin_ptr)( ptr_object ) );
 
     ASSERT_TRUE( ptr_mp != nullptr );
 
-    ASSERT_TRUE( std::fabs( ::st_MultiPole_get_length( ptr_mp ) -
-                            ::st_MultiPole_get_length( ptr_orig ) ) < EPS );
+    ASSERT_TRUE( std::fabs( NS(Multipole_length)( ptr_mp ) -
+                            NS(Multipole_length)( ptr_orig ) ) < EPS );
 
-    ASSERT_TRUE( std::fabs( ::st_MultiPole_get_hxl( ptr_mp ) -
-                            ::st_MultiPole_get_hxl( ptr_orig ) ) < EPS );
+    ASSERT_TRUE( std::fabs( NS(Multipole_hxl)( ptr_mp ) -
+                            NS(Multipole_hxl)( ptr_orig ) ) < EPS );
 
-    ASSERT_TRUE( std::fabs( ::st_MultiPole_get_hyl( ptr_mp ) -
-                            ::st_MultiPole_get_hyl( ptr_orig ) ) < EPS );
+    ASSERT_TRUE( std::fabs( NS(Multipole_hyl)( ptr_mp ) -
+                            NS(Multipole_hyl)( ptr_orig ) ) < EPS );
 
-    ASSERT_TRUE( ::st_MultiPole_get_order( ptr_mp ) ==
-                 ::st_MultiPole_get_order( ptr_orig ) );
+    ASSERT_TRUE( NS(Multipole_order)( ptr_mp ) ==
+                 NS(Multipole_order)( ptr_orig ) );
 
-    if( ::st_MultiPole_get_order( ptr_orig ) > mp_order_t{ 0 } )
+    if( NS(Multipole_order)( ptr_orig ) > mp_order_t{ 0 } )
     {
-        mp_real_t const* orig_bal_it  = ::st_MultiPole_get_const_bal( ptr_orig );
+        mp_real_t const* orig_bal_it  = NS(Multipole_const_bal_begin)( ptr_orig );
         mp_real_t const* orig_bal_end = orig_bal_it;
-        std::advance( orig_bal_end, ::st_MultiPole_get_bal_size( ptr_orig ) );
+        std::advance( orig_bal_end, NS(Multipole_bal_length)( ptr_orig ) );
 
-        mp_real_t const* cmp_bal_it   = ::st_MultiPole_get_const_bal( ptr_mp );
+        mp_real_t const* cmp_bal_it   = NS(Multipole_const_bal_begin)( ptr_mp );
 
         for( ; orig_bal_it != orig_bal_end ; ++orig_bal_it, ++cmp_bal_it )
         {
@@ -262,8 +267,8 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
     }
     else
     {
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_orig ) == nullptr );
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp   ) == nullptr );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_orig ) == nullptr );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp   ) == nullptr );
     }
 
     /* --------------------------------------------------------------------- */
@@ -271,70 +276,74 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
     ptr_orig = &orig_beam_elements[ be_index++ ];
     ASSERT_TRUE( ptr_orig != nullptr );
 
-    ptr_mp = ::st_MultiPole_new( eb, ::st_MultiPole_get_order( ptr_orig ) );
+    ptr_mp = NS(Multipole_new)( eb, NS(Multipole_order)( ptr_orig ) );
     ASSERT_TRUE( ptr_mp != nullptr );
 
-    ASSERT_TRUE( std::fabs( ::st_MultiPole_get_length( ptr_mp ) - ZERO ) < EPS );
-    ASSERT_TRUE( std::fabs( ::st_MultiPole_get_hxl( ptr_mp )    - ZERO ) < EPS );
-    ASSERT_TRUE( std::fabs( ::st_MultiPole_get_hyl( ptr_mp )    - ZERO ) < EPS );
+    ASSERT_TRUE( std::fabs( NS(Multipole_length)( ptr_mp ) - ZERO ) < EPS );
+    ASSERT_TRUE( std::fabs( NS(Multipole_hxl)( ptr_mp )    - ZERO ) < EPS );
+    ASSERT_TRUE( std::fabs( NS(Multipole_hyl)( ptr_mp )    - ZERO ) < EPS );
 
-    ::st_MultiPole_set_length( ptr_mp, ::st_MultiPole_get_length( ptr_orig ) );
-    ::st_MultiPole_set_hxl(    ptr_mp, ::st_MultiPole_get_hxl( ptr_orig ) );
-    ::st_MultiPole_set_hyl(    ptr_mp, ::st_MultiPole_get_hyl( ptr_orig ) );
+    NS(Multipole_set_length)( ptr_mp, NS(Multipole_length)( ptr_orig ) );
+    NS(Multipole_set_hxl)(    ptr_mp, NS(Multipole_hxl)( ptr_orig ) );
+    NS(Multipole_set_hyl)(    ptr_mp, NS(Multipole_hyl)( ptr_orig ) );
 
-    ASSERT_TRUE( ::st_MultiPole_get_order( ptr_mp ) ==
-                 ::st_MultiPole_get_order( ptr_orig ) );
+    ASSERT_TRUE( NS(Multipole_order)( ptr_mp ) ==
+                 NS(Multipole_order)( ptr_orig ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_length( ptr_orig ) -
-                                  ::st_MultiPole_get_length( ptr_mp ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Multipole_length)( ptr_orig ) -
+                                  NS(Multipole_length)( ptr_mp ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_hxl( ptr_orig ) -
-                                  ::st_MultiPole_get_hxl( ptr_mp ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Multipole_hxl)( ptr_orig ) -
+                                  NS(Multipole_hxl)( ptr_mp ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_hyl( ptr_orig ) -
-                                  ::st_MultiPole_get_hyl( ptr_mp ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Multipole_hyl)( ptr_orig ) -
+                                  NS(Multipole_hyl)( ptr_mp ) ) );
 
-    if( mp_order_t{ 0 } <= ::st_MultiPole_get_order( ptr_orig ) )
+    if( mp_order_t{ 0 } <= NS(Multipole_order)( ptr_orig ) )
     {
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp ) != nullptr );
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp ) !=
-                     ::st_MultiPole_get_const_bal( ptr_orig ) );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp ) != nullptr );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp ) !=
+                     NS(Multipole_const_bal_begin)( ptr_orig ) );
 
-        size_t const bal_size = ::st_MultiPole_get_bal_size( ptr_orig );
+        size_t const bal_size = NS(Multipole_bal_length)( ptr_orig );
 
         for( size_t ii = size_t{ 0 } ; ii < bal_size ; ++ii )
         {
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_bal_value( ptr_mp, ii ) - ZERO ) );
+                NS(Multipole_bal)( ptr_mp, ii ) - ZERO ) );
         }
 
-        ::st_MultiPole_set_bal( ptr_mp,
-            ::st_MultiPole_get_const_bal( ptr_orig ) );
+        NS(Multipole_set_bal)( ptr_mp,
+            NS(Multipole_const_bal_begin)( ptr_orig ) );
 
-        for( mp_order_t ii = ::st_MultiPole_get_order( ptr_mp ) ;
+        for( mp_order_t ii = NS(Multipole_order)( ptr_mp ) ;
              ii >= mp_order_t{ 0 } ; --ii )
         {
+            SIXTRL_ASSERT( EPS > std::fabs(
+                NS(Multipole_bal)( ptr_mp,   2u * ii      ) -
+                NS(Multipole_bal)( ptr_orig, 2u * ii      ) ) );
+
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_bal_value( ptr_mp,   2u * ii      ) -
-                ::st_MultiPole_get_bal_value( ptr_orig, 2u * ii      ) ) );
+                NS(Multipole_bal)( ptr_mp,   2u * ii      ) -
+                NS(Multipole_bal)( ptr_orig, 2u * ii      ) ) );
 
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_bal_value( ptr_mp,   2u * ii + 1u ) -
-                ::st_MultiPole_get_bal_value( ptr_orig, 2u * ii + 1u ) ) );
+                NS(Multipole_bal)( ptr_mp,   2u * ii + 1u ) -
+                NS(Multipole_bal)( ptr_orig, 2u * ii + 1u ) ) );
 
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_knl_value( ptr_mp,   ii ) -
-                ::st_MultiPole_get_knl_value( ptr_orig, ii ) ) );
+                NS(Multipole_knl)( ptr_mp,   ii ) -
+                NS(Multipole_knl)( ptr_orig, ii ) ) );
 
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_ksl_value( ptr_mp,   ii ) -
-                ::st_MultiPole_get_ksl_value( ptr_orig, ii ) ) );
+                NS(Multipole_ksl)( ptr_mp,   ii ) -
+                NS(Multipole_ksl)( ptr_orig, ii ) ) );
         }
     }
     else
     {
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp )   == nullptr );
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_orig ) == nullptr );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp )   == nullptr );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_orig ) == nullptr );
     }
 
     /* --------------------------------------------------------------------- */
@@ -342,57 +351,58 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
     ptr_orig = &orig_beam_elements[ be_index++ ];
     ASSERT_TRUE( ptr_orig != nullptr );
 
-    ptr_mp   = ::st_MultiPole_add( eb,
-        ::st_MultiPole_get_order( ptr_orig ),
-        ::st_MultiPole_get_const_bal( ptr_orig ),
-        ::st_MultiPole_get_length( ptr_orig ),
-        ::st_MultiPole_get_hxl( ptr_orig ),
-        ::st_MultiPole_get_hyl( ptr_orig ) );
+    ptr_mp   = NS(Multipole_add)( eb,
+        NS(Multipole_order)( ptr_orig ),
+        NS(Multipole_length)( ptr_orig ),
+        NS(Multipole_hxl)( ptr_orig ),
+        NS(Multipole_hyl)( ptr_orig ),
+        reinterpret_cast< uintptr_t >(
+            NS(Multipole_const_bal_begin)( ptr_orig ) ) );
 
     ASSERT_TRUE( ptr_mp != nullptr );
 
-    mp_order_t order = ::st_MultiPole_get_order( ptr_orig );
+    mp_order_t order = NS(Multipole_order)( ptr_orig );
 
-    ASSERT_TRUE( ::st_MultiPole_get_order( ptr_mp ) == order );
+    ASSERT_TRUE( NS(Multipole_order)( ptr_mp ) == order );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_length( ptr_orig ) -
-                                  ::st_MultiPole_get_length( ptr_mp ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Multipole_length)( ptr_orig ) -
+                                  NS(Multipole_length)( ptr_mp ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_hxl( ptr_orig ) -
-                                  ::st_MultiPole_get_hxl( ptr_mp ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Multipole_hxl)( ptr_orig ) -
+                                  NS(Multipole_hxl)( ptr_mp ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_hyl( ptr_orig ) -
-                                  ::st_MultiPole_get_hyl( ptr_mp ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(Multipole_hyl)( ptr_orig ) -
+                                  NS(Multipole_hyl)( ptr_mp ) ) );
 
     if( mp_order_t{ 0 } <= order )
     {
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp ) != nullptr );
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp ) !=
-                     ::st_MultiPole_get_const_bal( ptr_orig ) );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp ) != nullptr );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp ) !=
+                     NS(Multipole_const_bal_begin)( ptr_orig ) );
 
         for( mp_order_t ii = order ; ii >= mp_order_t{ 0 } ; --ii )
         {
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_bal_value( ptr_mp,   2u * ii      ) -
-                ::st_MultiPole_get_bal_value( ptr_orig, 2u * ii      ) ) );
+                NS(Multipole_bal)( ptr_mp,   2u * ii      ) -
+                NS(Multipole_bal)( ptr_orig, 2u * ii      ) ) );
 
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_bal_value( ptr_mp,   2u * ii + 1u ) -
-                ::st_MultiPole_get_bal_value( ptr_orig, 2u * ii + 1u ) ) );
+                NS(Multipole_bal)( ptr_mp,   2u * ii + 1u ) -
+                NS(Multipole_bal)( ptr_orig, 2u * ii + 1u ) ) );
 
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_knl_value( ptr_mp,   ii ) -
-                ::st_MultiPole_get_knl_value( ptr_orig, ii ) ) );
+                NS(Multipole_knl)( ptr_mp,   ii ) -
+                NS(Multipole_knl)( ptr_orig, ii ) ) );
 
             ASSERT_TRUE( EPS > std::fabs(
-                ::st_MultiPole_get_ksl_value( ptr_mp,   ii ) -
-                ::st_MultiPole_get_ksl_value( ptr_orig, ii ) ) );
+                NS(Multipole_ksl)( ptr_mp,   ii ) -
+                NS(Multipole_ksl)( ptr_orig, ii ) ) );
         }
     }
     else
     {
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp )   == nullptr );
-        ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_orig ) == nullptr );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp )   == nullptr );
+        ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_orig ) == nullptr );
     }
 
     /* --------------------------------------------------------------------- */
@@ -402,158 +412,157 @@ TEST( C99_CommonBeamElementMultiPoleTests, MinimalAddToBufferCopyRemapRead )
         ptr_orig = &orig_beam_elements[ be_index++ ];
         ASSERT_TRUE( ptr_orig != nullptr );
 
-        ptr_mp   = ::st_MultiPole_add( eb,
-            ::st_MultiPole_get_order( ptr_orig ),
-            ::st_MultiPole_get_const_bal( ptr_orig ),
-            ::st_MultiPole_get_length( ptr_orig ),
-            ::st_MultiPole_get_hxl( ptr_orig ),
-            ::st_MultiPole_get_hyl( ptr_orig ) );
+        ptr_mp   = NS(Multipole_add)( eb,
+            NS(Multipole_order)( ptr_orig ),
+            NS(Multipole_length)( ptr_orig ),
+            NS(Multipole_hxl)( ptr_orig ),
+            NS(Multipole_hyl)( ptr_orig ),
+            reinterpret_cast< uintptr_t >(
+                NS(Multipole_const_bal_begin)( ptr_orig ) ) );
 
         ASSERT_TRUE( ptr_mp != nullptr );
 
-        mp_order_t order = ::st_MultiPole_get_order( ptr_orig );
+        mp_order_t order = NS(Multipole_order)( ptr_orig );
 
-        ASSERT_TRUE( ::st_MultiPole_get_order( ptr_mp ) == order );
+        ASSERT_TRUE( NS(Multipole_order)( ptr_mp ) == order );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_length( ptr_orig ) -
-                                      ::st_MultiPole_get_length( ptr_mp ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Multipole_length)( ptr_orig ) -
+                                      NS(Multipole_length)( ptr_mp ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_hxl( ptr_orig ) -
-                                      ::st_MultiPole_get_hxl( ptr_mp ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Multipole_hxl)( ptr_orig ) -
+                                      NS(Multipole_hxl)( ptr_mp ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_hyl( ptr_orig ) -
-                                      ::st_MultiPole_get_hyl( ptr_mp ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Multipole_hyl)( ptr_orig ) -
+                                      NS(Multipole_hyl)( ptr_mp ) ) );
 
         if( mp_order_t{ 0 } <= order )
         {
-            ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp ) != nullptr );
-            ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp ) !=
-                        ::st_MultiPole_get_const_bal( ptr_orig ) );
+            ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp ) != nullptr );
+            ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp ) !=
+                        NS(Multipole_const_bal_begin)( ptr_orig ) );
 
             for( mp_order_t ii = order ; ii >= mp_order_t{ 0 } ; --ii )
             {
                 ASSERT_TRUE( EPS > std::fabs(
-                    ::st_MultiPole_get_bal_value( ptr_mp,   2u * ii      ) -
-                    ::st_MultiPole_get_bal_value( ptr_orig, 2u * ii      ) ) );
+                    NS(Multipole_bal)( ptr_mp,   2u * ii      ) -
+                    NS(Multipole_bal)( ptr_orig, 2u * ii      ) ) );
 
                 ASSERT_TRUE( EPS > std::fabs(
-                    ::st_MultiPole_get_bal_value( ptr_mp,   2u * ii + 1u ) -
-                    ::st_MultiPole_get_bal_value( ptr_orig, 2u * ii + 1u ) ) );
+                    NS(Multipole_bal)( ptr_mp,   2u * ii + 1u ) -
+                    NS(Multipole_bal)( ptr_orig, 2u * ii + 1u ) ) );
 
                 ASSERT_TRUE( EPS > std::fabs(
-                    ::st_MultiPole_get_knl_value( ptr_mp,   ii ) -
-                    ::st_MultiPole_get_knl_value( ptr_orig, ii ) ) );
+                    NS(Multipole_knl)( ptr_mp,   ii ) -
+                    NS(Multipole_knl)( ptr_orig, ii ) ) );
 
                 ASSERT_TRUE( EPS > std::fabs(
-                    ::st_MultiPole_get_ksl_value( ptr_mp,   ii ) -
-                    ::st_MultiPole_get_ksl_value( ptr_orig, ii ) ) );
+                    NS(Multipole_ksl)( ptr_mp,   ii ) -
+                    NS(Multipole_ksl)( ptr_orig, ii ) ) );
             }
         }
         else
         {
-            ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_mp )   == nullptr );
-            ASSERT_TRUE( ::st_MultiPole_get_const_bal( ptr_orig ) == nullptr );
+            ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_mp )   == nullptr );
+            ASSERT_TRUE( NS(Multipole_const_bal_begin)( ptr_orig ) == nullptr );
         }
     }
 
     /* ===================================================================== */
 
-    ASSERT_TRUE( ::st_Buffer_get_size( eb ) > size_t{ 0 } );
+    ASSERT_TRUE( NS(Buffer_get_size)( eb ) > size_t{ 0 } );
 
-    std::vector< raw_t > copy_buffer( ::st_Buffer_get_size( eb ), raw_t{ 0 } );
-    copy_buffer.assign( ::st_Buffer_get_const_data_begin( eb ),
-                        ::st_Buffer_get_const_data_end( eb ) );
+    std::vector< raw_t > copy_buffer( NS(Buffer_get_size)( eb ), raw_t{ 0 } );
+    copy_buffer.assign( NS(Buffer_get_const_data_begin)( eb ),
+                        NS(Buffer_get_const_data_end)( eb ) );
 
-    ::st_Buffer cmp_buffer;
-    ::st_Buffer_preset( &cmp_buffer );
+    NS(Buffer) cmp_buffer;
+    NS(Buffer_preset)( &cmp_buffer );
 
-    int success = ::st_Buffer_init(
+    int success = NS(Buffer_init)(
         &cmp_buffer, copy_buffer.data(), copy_buffer.size() );
 
     ASSERT_TRUE( success == 0 );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) ==
-                 ::st_Buffer_get_num_of_objects( &cmp_buffer ) );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) ==
+                 NS(Buffer_get_num_of_objects)( &cmp_buffer ) );
 
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) ==
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) ==
                  orig_beam_elements.size() );
 
-    object_t const* obj_it  = ::st_Buffer_get_const_objects_begin( eb );
-    object_t const* obj_end = ::st_Buffer_get_const_objects_end( eb );
-    object_t const* cmp_it  = ::st_Buffer_get_const_objects_begin( &cmp_buffer );
+    object_t const* obj_it  = NS(Buffer_get_const_objects_begin)( eb );
+    object_t const* obj_end = NS(Buffer_get_const_objects_end)( eb );
+    object_t const* cmp_it  = NS(Buffer_get_const_objects_begin)( &cmp_buffer );
 
     ptr_orig = &orig_beam_elements[ 0 ];
 
     for( ; obj_it != obj_end ; ++obj_it, ++cmp_it, ++ptr_orig )
     {
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) == BEAM_ELEMENT_TYPE_ID );
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) ==
-                     ::st_Object_get_type_id( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) == BEAM_ELEMENT_TYPE_ID );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) ==
+                     NS(Object_get_type_id)( cmp_it ) );
 
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) >= sizeof( belem_t ) );
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) ==
-                     ::st_Object_get_size( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) >= sizeof( belem_t ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) ==
+                     NS(Object_get_size)( cmp_it ) );
 
 
         belem_t const* elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( obj_it ) );
+            NS(Object_get_const_begin_ptr)( obj_it ) );
 
         belem_t const* cmp_elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( cmp_it ) );
+            NS(Object_get_const_begin_ptr)( cmp_it ) );
 
 
         ASSERT_TRUE( elem     != nullptr );
         ASSERT_TRUE( cmp_elem != nullptr );
         ASSERT_TRUE( cmp_elem != elem    );
 
-        mp_order_t order = ::st_MultiPole_get_order( elem );
+        mp_order_t order = NS(Multipole_order)( elem );
 
-        ASSERT_TRUE( ::st_MultiPole_get_order( cmp_elem ) == order );
+        ASSERT_TRUE( NS(Multipole_order)( cmp_elem ) == order );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_length( elem ) -
-                                      ::st_MultiPole_get_length( cmp_elem ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Multipole_length)( elem ) -
+                                      NS(Multipole_length)( cmp_elem ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_hxl( elem ) -
-                                      ::st_MultiPole_get_hxl( cmp_elem ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Multipole_hxl)( elem ) -
+                                      NS(Multipole_hxl)( cmp_elem ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_MultiPole_get_hyl( elem ) -
-                                      ::st_MultiPole_get_hyl( cmp_elem ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(Multipole_hyl)( elem ) -
+                                      NS(Multipole_hyl)( cmp_elem ) ) );
 
         if( mp_order_t{ 0 } <= order )
         {
-            ASSERT_TRUE( ::st_MultiPole_get_const_bal( cmp_elem ) != nullptr );
-            ASSERT_TRUE( ::st_MultiPole_get_const_bal( cmp_elem ) !=
-                         ::st_MultiPole_get_const_bal( elem ) );
+            ASSERT_TRUE( NS(Multipole_const_bal_begin)( cmp_elem ) != nullptr );
+            ASSERT_TRUE( NS(Multipole_const_bal_begin)( cmp_elem ) !=
+                         NS(Multipole_const_bal_begin)( elem ) );
 
             for( mp_order_t ii = order ; ii >= mp_order_t{ 0 } ; --ii )
             {
                 ASSERT_TRUE( EPS > std::fabs(
-                    ::st_MultiPole_get_bal_value( cmp_elem, 2u * ii      ) -
-                    ::st_MultiPole_get_bal_value( elem, 2u * ii      ) ) );
+                    NS(Multipole_bal)( cmp_elem, 2u * ii      ) -
+                    NS(Multipole_bal)( elem, 2u * ii      ) ) );
 
                 ASSERT_TRUE( EPS > std::fabs(
-                    ::st_MultiPole_get_bal_value( cmp_elem, 2u * ii + 1u ) -
-                    ::st_MultiPole_get_bal_value( elem, 2u * ii + 1u ) ) );
+                    NS(Multipole_bal)( cmp_elem, 2u * ii + 1u ) -
+                    NS(Multipole_bal)( elem, 2u * ii + 1u ) ) );
 
                 ASSERT_TRUE( EPS > std::fabs(
-                    ::st_MultiPole_get_knl_value( cmp_elem, ii ) -
-                    ::st_MultiPole_get_knl_value( elem, ii ) ) );
+                    NS(Multipole_knl)( cmp_elem, ii ) -
+                    NS(Multipole_knl)( elem, ii ) ) );
 
                 ASSERT_TRUE( EPS > std::fabs(
-                    ::st_MultiPole_get_ksl_value( cmp_elem, ii ) -
-                    ::st_MultiPole_get_ksl_value( elem, ii ) ) );
+                    NS(Multipole_ksl)( cmp_elem, ii ) -
+                    NS(Multipole_ksl)( elem, ii ) ) );
             }
         }
         else
         {
-            ASSERT_TRUE( ::st_MultiPole_get_const_bal( cmp_elem ) == nullptr );
-            ASSERT_TRUE( ::st_MultiPole_get_const_bal( elem ) == nullptr );
+            ASSERT_TRUE( NS(Multipole_const_bal_begin)( cmp_elem ) == nullptr );
+            ASSERT_TRUE( NS(Multipole_const_bal_begin)( elem ) == nullptr );
         }
     }
 
     /* ===================================================================== */
 
-    ::st_Buffer_delete( eb );
-    ::st_Buffer_free( &cmp_buffer );
+    NS(Buffer_delete)( eb );
+    NS(Buffer_free)( &cmp_buffer );
 }
-
-/* end: tests/sixtracklib/common/test_be_xy_shift_c99.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_rf_multipole_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_rf_multipole_c99.cpp
index 885fa24a..a310abaf 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_rf_multipole_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_rf_multipole_c99.cpp
@@ -9,11 +9,9 @@
 #include "sixtracklib/common/buffer.h"
 #include "sixtracklib/common/particles.h"
 
-
-
-TEST( C99CommonBeamElementsRFMultiPoleTests, StoreAndRestoreTests )
+TEST( C99CommonBeamElementsRFMultipole, StoreAndRestoreTests )
 {
-    using rf_multipole_t = ::NS(RFMultiPole);
+    using rf_multipole_t = ::NS(RFMultipole);
     using rf_mp_int_t = ::NS(rf_multipole_int_t);
     using rf_mp_real_t = ::NS(rf_multipole_real_t);
     using buf_size_t = ::NS(buffer_size_t);
@@ -28,29 +26,29 @@ TEST( C99CommonBeamElementsRFMultiPoleTests, StoreAndRestoreTests )
     buf_size_t const rfmp_01_idx =
         ::NS(Buffer_get_num_of_objects)( lattice );
 
-    rf_multipole_t* rfmp_01 = ::NS(RFMultiPole_new)( lattice, rfmp_01_order );
+    rf_multipole_t* rfmp_01 = ::NS(RFMultipole_new)( lattice, rfmp_01_order );
 
     ASSERT_TRUE( rfmp_01_idx < ::NS(Buffer_get_num_of_objects)( lattice ) );
     ASSERT_TRUE( rfmp_01 != nullptr );
-    ASSERT_TRUE( ::NS(RFMultiPole_order)( rfmp_01 ) == rfmp_01_order );
+    ASSERT_TRUE( ::NS(RFMultipole_order)( rfmp_01 ) == rfmp_01_order );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_num_bal_elements)( rfmp_01 ) ==
+    ASSERT_TRUE( ::NS(RFMultipole_bal_length)( rfmp_01 ) ==
         static_cast< rf_mp_int_t >( 2 * rfmp_01_order + 2 ) );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_num_phase_elements)( rfmp_01 ) ==
+    ASSERT_TRUE( ::NS(RFMultipole_phase_length)( rfmp_01 ) ==
         static_cast< rf_mp_int_t >( 2 * rfmp_01_order + 2 ) );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_voltage)( rfmp_01 ) -
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_voltage)( rfmp_01 ) -
         rf_mp_real_t{ 0.0 } ) < REAL_EPS );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_frequency)( rfmp_01 ) -
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_frequency)( rfmp_01 ) -
         rf_mp_real_t{ 0.0 } ) < REAL_EPS );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_lag)( rfmp_01 ) -
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_lag)( rfmp_01 ) -
         rf_mp_real_t{ 0.0 } ) < REAL_EPS );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_const_bal)( rfmp_01 ) != nullptr );
-    ASSERT_TRUE( ::NS(RFMultiPole_const_phase)( rfmp_01 ) != nullptr );
+    ASSERT_TRUE( ::NS(RFMultipole_const_bal_begin)( rfmp_01 ) != nullptr );
+    ASSERT_TRUE( ::NS(RFMultipole_const_phase_begin)( rfmp_01 ) != nullptr );
 
     /* --------------------------------------------------------------------- */
 
@@ -68,35 +66,36 @@ TEST( C99CommonBeamElementsRFMultiPoleTests, StoreAndRestoreTests )
 
     buf_size_t const rfmp_02_idx = ::NS(Buffer_get_num_of_objects)( lattice );
 
-    rf_multipole_t* rfmp_02 = ::NS(RFMultiPole_add)( lattice, rfmp_02_order,
-        rfmp_02_voltage, rfmp_02_frequency, rfmp_02_lag, &bal_values[ 0 ],
-            nullptr );
+    rf_multipole_t* rfmp_02 = ::NS(RFMultipole_add)( lattice, rfmp_02_order,
+        rfmp_02_voltage, rfmp_02_frequency, rfmp_02_lag,
+            reinterpret_cast< std::uintptr_t >( &bal_values[ 0 ] ),
+                std::uintptr_t{ 0 } );
 
     ASSERT_TRUE( rfmp_02_idx < ::NS(Buffer_get_num_of_objects)( lattice ) );
     ASSERT_TRUE( rfmp_02 != nullptr );
-    ASSERT_TRUE( ::NS(RFMultiPole_order)( rfmp_02 ) == rfmp_02_order );
+    ASSERT_TRUE( ::NS(RFMultipole_order)( rfmp_02 ) == rfmp_02_order );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_num_bal_elements)( rfmp_02 ) ==
+    ASSERT_TRUE( ::NS(RFMultipole_bal_length)( rfmp_02 ) ==
         static_cast< rf_mp_int_t >( 2u * rfmp_02_order + 2u ) );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_num_phase_elements)( rfmp_02 ) ==
+    ASSERT_TRUE( ::NS(RFMultipole_phase_length)( rfmp_02 ) ==
         static_cast< rf_mp_int_t >( 2u * rfmp_02_order + 2u ) );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_voltage)(
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_voltage)(
         rfmp_02 ) - rfmp_02_voltage ) < REAL_EPS );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_frequency)(
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_frequency)(
         rfmp_02 ) - rfmp_02_frequency ) < REAL_EPS );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_lag)(
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_lag)(
         rfmp_02 ) - rfmp_02_lag ) < REAL_EPS );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_const_bal)( rfmp_02 ) != nullptr );
-    ASSERT_TRUE( ::NS(RFMultiPole_const_phase)( rfmp_02 ) != nullptr );
+    ASSERT_TRUE( ::NS(RFMultipole_const_bal_begin)( rfmp_02 ) != nullptr );
+    ASSERT_TRUE( ::NS(RFMultipole_const_phase_begin)( rfmp_02 ) != nullptr );
 
-    ASSERT_TRUE( std::memcmp( &bal_values[ 0 ], ::NS(RFMultiPole_const_bal)(
-        rfmp_02 ), sizeof( rf_mp_real_t ) * ::NS(RFMultiPole_num_bal_elements)(
-            rfmp_02 ) ) == 0 );
+    ASSERT_TRUE( 0 == std::memcmp( &bal_values[ 0 ],
+        ::NS(RFMultipole_const_bal_begin)( rfmp_02 ),
+        sizeof( rf_mp_real_t ) * ::NS(RFMultipole_bal_length)( rfmp_02 ) ) );
 
     /* --------------------------------------------------------------------- */
 
@@ -104,9 +103,9 @@ TEST( C99CommonBeamElementsRFMultiPoleTests, StoreAndRestoreTests )
         ::NS(Buffer_get_num_of_objects)( lattice );
 
     rf_multipole_t* rfmp_02_copy =
-        ::NS(RFMultiPole_new)( lattice, rfmp_02_order );
+        ::NS(RFMultipole_new)( lattice, rfmp_02_order );
 
-    rfmp_02 = ::NS(RFMultiPole_from_buffer)( lattice, rfmp_02_idx );
+    rfmp_02 = ::NS(RFMultipole_from_buffer)( lattice, rfmp_02_idx );
 
     ASSERT_TRUE( rfmp_02_copy_idx > rfmp_02_idx );
     ASSERT_TRUE( rfmp_02_copy_idx <
@@ -115,54 +114,60 @@ TEST( C99CommonBeamElementsRFMultiPoleTests, StoreAndRestoreTests )
     ASSERT_TRUE( rfmp_02 != nullptr );
     ASSERT_TRUE( rfmp_02_copy != nullptr );
     ASSERT_TRUE( rfmp_02_copy != rfmp_02 );
-    ASSERT_TRUE( ::NS(RFMultiPole_order)( rfmp_02 ) ==
-                 ::NS(RFMultiPole_order)( rfmp_02_copy ) );
+    ASSERT_TRUE( ::NS(RFMultipole_order)( rfmp_02 ) ==
+                 ::NS(RFMultipole_order)( rfmp_02_copy ) );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_num_bal_elements)( rfmp_02_copy ) ==
+    ASSERT_TRUE( ::NS(RFMultipole_bal_length)( rfmp_02_copy ) ==
         static_cast< rf_mp_int_t >( 2u * rfmp_02_order + 2u ) );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_num_phase_elements)( rfmp_02_copy ) ==
+    ASSERT_TRUE( ::NS(RFMultipole_phase_length)( rfmp_02_copy ) ==
         static_cast< rf_mp_int_t >( 2u * rfmp_02_order + 2u ) );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_const_bal)( rfmp_02_copy ) != nullptr );
-    ASSERT_TRUE( ::NS(RFMultiPole_const_phase)( rfmp_02_copy ) != nullptr );
+    ASSERT_TRUE( ::NS(RFMultipole_const_bal_begin)(
+        rfmp_02_copy ) != nullptr );
+
+    ASSERT_TRUE( ::NS(RFMultipole_const_phase_begin)(
+        rfmp_02_copy ) != nullptr );
 
-    ASSERT_TRUE( ::NS(RFMultiPole_copy)( rfmp_02_copy, rfmp_02 ) ==
+    ASSERT_TRUE( ::NS(RFMultipole_copy)( rfmp_02_copy, rfmp_02 ) ==
                  ::NS(ARCH_STATUS_SUCCESS) );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_voltage)(
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_voltage)(
         rfmp_02_copy ) - rfmp_02_voltage ) < REAL_EPS );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_frequency)(
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_frequency)(
         rfmp_02_copy ) - rfmp_02_frequency ) < REAL_EPS );
 
-    ASSERT_TRUE( std::fabs( ::NS(RFMultiPole_lag)(
+    ASSERT_TRUE( std::fabs( ::NS(RFMultipole_lag)(
         rfmp_02_copy ) - rfmp_02_lag ) < REAL_EPS );
 
-    ASSERT_TRUE( std::memcmp( &bal_values[ 0 ], ::NS(RFMultiPole_const_bal)(
-        rfmp_02_copy ), sizeof( rf_mp_real_t ) *
-            ::NS(RFMultiPole_num_bal_elements)( rfmp_02_copy ) ) == 0 );
+    ASSERT_TRUE( std::memcmp( &bal_values[ 0 ],
+        ::NS(RFMultipole_const_bal_begin)( rfmp_02_copy ),
+            sizeof( rf_mp_real_t ) * ::NS(RFMultipole_bal_length)(
+                rfmp_02_copy ) ) == 0 );
 
-    ASSERT_TRUE( std::memcmp( ::NS(RFMultiPole_const_bal)( rfmp_02 ),
-        ::NS(RFMultiPole_const_bal)( rfmp_02_copy ), sizeof( rf_mp_real_t ) *
-            ::NS(RFMultiPole_num_bal_elements)( rfmp_02 ) ) == 0 );
+    ASSERT_TRUE( std::memcmp( ::NS(RFMultipole_const_bal_begin)( rfmp_02 ),
+        ::NS(RFMultipole_const_bal_begin)( rfmp_02_copy ),
+            sizeof( rf_mp_real_t ) * ::NS(RFMultipole_bal_length)(
+                rfmp_02 ) ) == 0 );
 
-    ASSERT_TRUE( std::memcmp( ::NS(RFMultiPole_const_phase)( rfmp_02 ),
-        ::NS(RFMultiPole_const_phase)( rfmp_02_copy ), sizeof( rf_mp_real_t ) *
-            ::NS(RFMultiPole_num_phase_elements)( rfmp_02 ) ) == 0 );
+    ASSERT_TRUE( std::memcmp( ::NS(RFMultipole_const_phase_begin)( rfmp_02 ),
+        ::NS(RFMultipole_const_phase_begin)( rfmp_02_copy ),
+            sizeof( rf_mp_real_t ) * ::NS(RFMultipole_phase_length)(
+                rfmp_02 ) ) == 0 );
 
     /* --------------------------------------------------------------------- */
 
-    rfmp_01 = ::NS(RFMultiPole_from_managed_buffer)(
+    rfmp_01 = ::NS(RFMultipole_from_managed_buffer)(
         ::NS(Buffer_get_data_begin)( lattice ), rfmp_01_idx,
             ::NS(Buffer_get_slot_size)( lattice ) );
 
     ASSERT_TRUE( rfmp_01 != nullptr );
 
-    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) != ::NS(RFMultiPole_copy)(
+    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) != ::NS(RFMultipole_copy)(
         rfmp_01, rfmp_02_copy) );
 
-    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) != ::NS(RFMultiPole_copy)(
+    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) != ::NS(RFMultipole_copy)(
         rfmp_02_copy, rfmp_01 ) );
 
     /* --------------------------------------------------------------------- */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_srotation_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_srotation_c99.cpp
index 4e6ee916..cb060744 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_srotation_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_srotation_c99.cpp
@@ -19,14 +19,14 @@
 #include "sixtracklib/common/be_srotation/be_srotation.h"
 
 /* ************************************************************************* *
- * ******  st_SRotation:
+ * ****** NS(SRotation):
  * ************************************************************************* */
-TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
+TEST( C99CommonBeamElementSRotation, MinimalAddToBufferCopyRemapRead )
 {
-    using size_t   = ::st_buffer_size_t;
-    using object_t = ::st_Object;
+    using size_t   = NS(buffer_size_t);
+    using object_t = NS(Object);
     using raw_t    = unsigned char;
-    using belem_t  = ::st_SRotation;
+    using belem_t  = NS(SRotation);
     using real_t   = SIXTRL_REAL_T;
 
     static real_t const ZERO = real_t{   0.0 };
@@ -47,10 +47,10 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
     static SIXTRL_CONSTEXPR_OR_CONST size_t
         NUM_BEAM_ELEMENTS = size_t{ 1000 };
 
-    ::st_object_type_id_t const BEAM_ELEMENT_TYPE_ID = ::st_OBJECT_TYPE_SROTATION;
+    NS(object_type_id_t) const BEAM_ELEMENT_TYPE_ID = NS(OBJECT_TYPE_SROTATION);
     std::vector< belem_t > orig_beam_elements( NUM_BEAM_ELEMENTS, belem_t{} );
 
-    size_t const slot_size      = ::st_BUFFER_DEFAULT_SLOT_SIZE;
+    size_t const slot_size      = NS(BUFFER_DEFAULT_SLOT_SIZE);
     size_t const num_objs       = NUM_BEAM_ELEMENTS;
     size_t const num_garbage    = size_t{ 0 };
     size_t const num_dataptrs   = size_t{ 0 };
@@ -60,17 +60,17 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
     {
         real_t const angle = angle_dist( prng );
 
-        belem_t* ptr_srot = ::st_SRotation_preset( &orig_beam_elements[ ii ] );
+        belem_t* ptr_srot = NS(SRotation_preset)( &orig_beam_elements[ ii ] );
         ASSERT_TRUE( ptr_srot != nullptr );
-        ::st_SRotation_set_angle( ptr_srot, angle );
+        NS(SRotation_set_angle)( ptr_srot, angle );
 
         ASSERT_TRUE( EPS > std::fabs(
-            std::cos( angle ) - ::st_SRotation_get_cos_angle( ptr_srot ) ) );
+            std::cos( angle ) - NS(SRotation_cos_angle)( ptr_srot ) ) );
 
         ASSERT_TRUE( EPS > std::fabs(
-            std::sin( angle ) - ::st_SRotation_get_sin_angle( ptr_srot  ) ) );
+            std::sin( angle ) - NS(SRotation_sin_angle)( ptr_srot  ) ) );
 
-        real_t const cmp_angle = ::st_SRotation_get_angle( ptr_srot );
+        real_t const cmp_angle = NS(SRotation_angle)( ptr_srot );
         real_t const delta     = std::fabs( angle - cmp_angle );
 
         if( EPS <= std::fabs( delta  ) )
@@ -79,19 +79,19 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
         }
 
         ASSERT_TRUE( EPS > std::fabs(
-            angle - ::st_SRotation_get_angle( ptr_srot ) ) );
+            angle - NS(SRotation_angle)( ptr_srot ) ) );
 
-        num_slots += ::st_ManagedBuffer_predict_required_num_slots( nullptr,
-            sizeof( ::st_SRotation ), ::st_SRotation_get_num_dataptrs( ptr_srot ),
+        num_slots += NS(ManagedBuffer_predict_required_num_slots)( nullptr,
+            sizeof( NS(SRotation) ), NS(SRotation_num_dataptrs)( ptr_srot ),
                 nullptr, nullptr, slot_size );
     }
 
     /* --------------------------------------------------------------------- */
 
-    size_t const requ_buffer_size = ::st_ManagedBuffer_calculate_buffer_length(
+    size_t const requ_buffer_size = NS(ManagedBuffer_calculate_buffer_length)(
         nullptr, num_objs, num_slots, num_dataptrs, num_garbage, slot_size );
 
-    ::st_Buffer* eb = ::st_Buffer_new( requ_buffer_size );
+    NS(Buffer)* eb = NS(Buffer_new)( requ_buffer_size );
     ASSERT_TRUE( eb != nullptr );
 
     /* --------------------------------------------------------------------- */
@@ -100,127 +100,130 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
     belem_t* ptr_orig = &orig_beam_elements[ be_index++ ];
     ASSERT_TRUE( ptr_orig != nullptr );
 
-    object_t* ptr_object = ::st_Buffer_add_object( eb, ptr_orig, sizeof( belem_t ),
-        BEAM_ELEMENT_TYPE_ID, ::st_SRotation_get_num_dataptrs( ptr_orig ),
+    object_t* ptr_object = NS(Buffer_add_object)( eb, ptr_orig, sizeof( belem_t ),
+        BEAM_ELEMENT_TYPE_ID, NS(SRotation_num_dataptrs)( ptr_orig ),
             nullptr, nullptr, nullptr );
 
     ASSERT_TRUE( ptr_object != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-    ASSERT_TRUE( ::st_Object_get_const_begin_ptr( ptr_object ) != nullptr );
-    ASSERT_TRUE( ::st_Object_get_size( ptr_object ) >= sizeof( belem_t ) );
-    ASSERT_TRUE( ::st_Object_get_type_id( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
+    ASSERT_TRUE( NS(Object_get_const_begin_ptr)( ptr_object ) != nullptr );
+    ASSERT_TRUE( NS(Object_get_size)( ptr_object ) >= sizeof( belem_t ) );
+    ASSERT_TRUE( NS(Object_get_type_id)( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
 
     belem_t* ptr_srot = reinterpret_cast< belem_t* >(
-        ::st_Object_get_begin_ptr( ptr_object ) );
+        NS(Object_get_begin_ptr)( ptr_object ) );
 
     ASSERT_TRUE( ptr_srot != nullptr );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_angle( ptr_srot ) -
-                                  ::st_SRotation_get_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_angle)( ptr_srot ) -
+                                  NS(SRotation_angle)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_cos_angle( ptr_srot ) -
-                                  ::st_SRotation_get_cos_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_cos_angle)( ptr_srot ) -
+                                  NS(SRotation_cos_angle)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_sin_angle( ptr_srot ) -
-                                  ::st_SRotation_get_sin_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_sin_angle)( ptr_srot ) -
+                                  NS(SRotation_sin_angle)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_srot = ::st_SRotation_new( eb );
+    ptr_srot = NS(SRotation_new)( eb );
 
     ASSERT_TRUE( ptr_srot != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_angle( ptr_srot ) - ZERO ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_angle)( ptr_srot ) - ZERO ) );
 
-    ::st_SRotation_set_angle( ptr_srot, ::st_SRotation_get_angle( ptr_orig ) );
+    NS(SRotation_set_angle)( ptr_srot, NS(SRotation_angle)( ptr_orig ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_angle( ptr_srot ) -
-                                  ::st_SRotation_get_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_angle)( ptr_srot ) -
+                                  NS(SRotation_angle)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_cos_angle( ptr_srot ) -
-                                  ::st_SRotation_get_cos_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_cos_angle)( ptr_srot ) -
+                                  NS(SRotation_cos_angle)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_sin_angle( ptr_srot ) -
-                                  ::st_SRotation_get_sin_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_sin_angle)( ptr_srot ) -
+                                  NS(SRotation_sin_angle)( ptr_orig  ) ) );
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_srot = ::st_SRotation_add( eb, ::st_SRotation_get_angle( ptr_orig ) );
+    ptr_srot = NS(SRotation_add)( eb,
+        NS(SRotation_cos_angle)( ptr_orig ),
+        NS(SRotation_sin_angle)( ptr_orig ) );
 
     ASSERT_TRUE( ptr_srot != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_angle( ptr_srot ) -
-                                  ::st_SRotation_get_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_angle)( ptr_srot ) -
+                                  NS(SRotation_angle)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_cos_angle( ptr_srot ) -
-                                  ::st_SRotation_get_cos_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_cos_angle)( ptr_srot ) -
+                                  NS(SRotation_cos_angle)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_sin_angle( ptr_srot ) -
-                                  ::st_SRotation_get_sin_angle( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_sin_angle)( ptr_srot ) -
+                                  NS(SRotation_sin_angle)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
 
-    ptr_srot = ::st_SRotation_add_detailed( eb,
-        std::cos( ::st_SRotation_get_angle( ptr_orig ) ),
-        std::sin( ::st_SRotation_get_angle( ptr_orig ) ) );
+    ptr_srot = NS(SRotation_add)( eb,
+        std::cos( NS(SRotation_angle)( ptr_orig ) ),
+        std::sin( NS(SRotation_angle)( ptr_orig ) ) );
 
     ASSERT_TRUE( ptr_srot != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_angle( ptr_srot ) -
-                                  ::st_SRotation_get_angle( ptr_orig ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_angle)( ptr_srot ) -
+                                  NS(SRotation_angle)( ptr_orig ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_cos_angle( ptr_srot ) -
-                                  ::st_SRotation_get_cos_angle( ptr_orig ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_cos_angle)( ptr_srot ) -
+                                  NS(SRotation_cos_angle)( ptr_orig ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_sin_angle( ptr_srot ) -
-                                  ::st_SRotation_get_sin_angle( ptr_orig ) ) );
+    ASSERT_TRUE( EPS > std::fabs( NS(SRotation_sin_angle)( ptr_srot ) -
+                                  NS(SRotation_sin_angle)( ptr_orig ) ) );
 
 
 
     for( ; be_index < NUM_BEAM_ELEMENTS ; )
     {
         ptr_orig = &orig_beam_elements[ be_index++ ];
-        ptr_srot = ::st_SRotation_add( eb, ::st_SRotation_get_angle( ptr_orig ) );
+        ptr_srot = NS(SRotation_add)( eb, NS(SRotation_cos_angle)( ptr_orig ),
+                                      NS(SRotation_sin_angle)( ptr_orig ) );
 
         ASSERT_TRUE( ptr_srot != nullptr );
-        ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+        ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_angle( ptr_srot ) -
-                                      ::st_SRotation_get_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_angle)( ptr_srot ) -
+                                      NS(SRotation_angle)( ptr_orig ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_cos_angle( ptr_srot ) -
-                                      ::st_SRotation_get_cos_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_cos_angle)( ptr_srot ) -
+                                      NS(SRotation_cos_angle)( ptr_orig ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_sin_angle( ptr_srot ) -
-                                      ::st_SRotation_get_sin_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_sin_angle)( ptr_srot ) -
+                                      NS(SRotation_sin_angle)( ptr_orig ) ) );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ASSERT_TRUE( ::st_Buffer_get_size( eb ) > size_t{ 0 } );
+    ASSERT_TRUE( NS(Buffer_get_size)( eb ) > size_t{ 0 } );
 
-    std::vector< raw_t > data_buffer( ::st_Buffer_get_size( eb ), raw_t{ 0 } );
-    data_buffer.assign( ::st_Buffer_get_const_data_begin( eb ),
-                        ::st_Buffer_get_const_data_end( eb ) );
+    std::vector< raw_t > data_buffer( NS(Buffer_get_size)( eb ), raw_t{ 0 } );
+    data_buffer.assign( NS(Buffer_get_const_data_begin)( eb ),
+                        NS(Buffer_get_const_data_end)( eb ) );
 
-    ::st_Buffer cmp_buffer;
-    ::st_Buffer_preset( &cmp_buffer );
-    int success = ::st_Buffer_init(
+    NS(Buffer) cmp_buffer;
+    NS(Buffer_preset)( &cmp_buffer );
+    int success = NS(Buffer_init)(
         &cmp_buffer, data_buffer.data(), data_buffer.size() );
 
     ASSERT_TRUE( success == 0 );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) ==
-                 ::st_Buffer_get_num_of_objects( &cmp_buffer ) );
+    ASSERT_TRUE( NS(Buffer_get_num_of_objects)( eb ) ==
+                 NS(Buffer_get_num_of_objects)( &cmp_buffer ) );
 
-    object_t const* obj_it  = ::st_Buffer_get_const_objects_begin( eb );
-    object_t const* obj_end = ::st_Buffer_get_const_objects_end( eb );
-    object_t const* cmp_it  = ::st_Buffer_get_const_objects_begin( &cmp_buffer );
+    object_t const* obj_it  = NS(Buffer_get_const_objects_begin)( eb );
+    object_t const* obj_end = NS(Buffer_get_const_objects_end)( eb );
+    object_t const* cmp_it  = NS(Buffer_get_const_objects_begin)( &cmp_buffer );
 
     be_index = size_t{ 0 };
 
@@ -228,19 +231,19 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
     {
         ptr_orig = &orig_beam_elements[ be_index++ ];
 
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) == BEAM_ELEMENT_TYPE_ID );
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) ==
-                     ::st_Object_get_type_id( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) == BEAM_ELEMENT_TYPE_ID );
+        ASSERT_TRUE( NS(Object_get_type_id)( obj_it ) ==
+                     NS(Object_get_type_id)( cmp_it ) );
 
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) >= sizeof( belem_t ) );
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) ==
-                     ::st_Object_get_size( cmp_it ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) >= sizeof( belem_t ) );
+        ASSERT_TRUE( NS(Object_get_size)( obj_it ) ==
+                     NS(Object_get_size)( cmp_it ) );
 
         belem_t const* elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( obj_it ) );
+            NS(Object_get_const_begin_ptr)( obj_it ) );
 
         belem_t const* cmp_elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( cmp_it ) );
+            NS(Object_get_const_begin_ptr)( cmp_it ) );
 
         ASSERT_TRUE( ptr_orig != elem );
         ASSERT_TRUE( ptr_orig != cmp_elem );
@@ -249,29 +252,27 @@ TEST( C99_CommonBeamElementDriftTests, MinimalAddToBufferCopyRemapRead )
         ASSERT_TRUE( cmp_elem != nullptr );
         ASSERT_TRUE( cmp_elem != elem    );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_angle( elem ) -
-                                      ::st_SRotation_get_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_angle)( elem ) -
+                                      NS(SRotation_angle)( ptr_orig ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_cos_angle( elem ) -
-                                      ::st_SRotation_get_cos_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_cos_angle)( elem ) -
+                                      NS(SRotation_cos_angle)( ptr_orig ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_sin_angle( elem ) -
-                                      ::st_SRotation_get_sin_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_sin_angle)( elem ) -
+                                      NS(SRotation_sin_angle)( ptr_orig ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_angle( cmp_elem ) -
-                                      ::st_SRotation_get_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_angle)( cmp_elem ) -
+                                      NS(SRotation_angle)( ptr_orig ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_cos_angle( cmp_elem ) -
-                                      ::st_SRotation_get_cos_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_cos_angle)( cmp_elem ) -
+                                      NS(SRotation_cos_angle)( ptr_orig ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_SRotation_get_sin_angle( cmp_elem ) -
-                                      ::st_SRotation_get_sin_angle( ptr_orig ) ) );
+        ASSERT_TRUE( EPS > std::fabs( NS(SRotation_sin_angle)( cmp_elem ) -
+                                      NS(SRotation_sin_angle)( ptr_orig ) ) );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ::st_Buffer_delete( eb );
-    ::st_Buffer_free( &cmp_buffer );
+    NS(Buffer_delete)( eb );
+    NS(Buffer_free)( &cmp_buffer );
 }
-
-/* end: tests/sixtracklib/common/test_be_srotation_c99.cpp */
diff --git a/tests/sixtracklib/common/beam_elements/test_be_xy_shift_c99.cpp b/tests/sixtracklib/common/beam_elements/test_be_xy_shift_c99.cpp
index 80580325..4d619dba 100644
--- a/tests/sixtracklib/common/beam_elements/test_be_xy_shift_c99.cpp
+++ b/tests/sixtracklib/common/beam_elements/test_be_xy_shift_c99.cpp
@@ -18,15 +18,15 @@
 #include "sixtracklib/common/be_xyshift/be_xyshift.h"
 
 /* ************************************************************************* *
- * ******  st_XYShift:
+ * ****** ::NS(XYShift):
  * ************************************************************************* */
 
-TEST( C99_CommonBeamElementXYShiftTests, MinimalAddToBufferCopyRemapRead )
+TEST( C99CommonBeamElementXYShift, MinimalAddToBufferCopyRemapRead )
 {
-    using size_t   = ::st_buffer_size_t;
-    using object_t = ::st_Object;
+    using size_t   = ::NS(buffer_size_t);
+    using object_t = ::NS(Object);
     using raw_t    = unsigned char;
-    using belem_t  = ::st_XYShift;
+    using belem_t  = ::NS(XYShift);
     using real_t   = SIXTRL_REAL_T;
 
     static double const ZERO = double{ 0.0 };
@@ -48,10 +48,10 @@ TEST( C99_CommonBeamElementXYShiftTests, MinimalAddToBufferCopyRemapRead )
     static SIXTRL_CONSTEXPR_OR_CONST size_t
         NUM_BEAM_ELEMENTS = size_t{ 1000 };
 
-    ::st_object_type_id_t const BEAM_ELEMENT_TYPE_ID = ::st_OBJECT_TYPE_XYSHIFT;
+    ::NS(object_type_id_t) const BEAM_ELEMENT_TYPE_ID = ::NS(OBJECT_TYPE_XYSHIFT);
     std::vector< belem_t > orig_beam_elements( NUM_BEAM_ELEMENTS, belem_t{} );
 
-    size_t const slot_size      = ::st_BUFFER_DEFAULT_SLOT_SIZE;
+    size_t const slot_size      = ::NS(BUFFER_DEFAULT_SLOT_SIZE);
     size_t const num_objs       = NUM_BEAM_ELEMENTS;
     size_t const num_garbage    = size_t{ 0 };
     size_t const num_dataptrs   = size_t{ 0 };
@@ -62,25 +62,25 @@ TEST( C99_CommonBeamElementXYShiftTests, MinimalAddToBufferCopyRemapRead )
         real_t const dx = dx_dist( prng );
         real_t const dy = dy_dist( prng );
 
-        belem_t* ptr_xyshift = ::st_XYShift_preset( &orig_beam_elements[ ii ] );
+        belem_t* ptr_xyshift = ::NS(XYShift_preset)( &orig_beam_elements[ ii ] );
         ASSERT_TRUE( ptr_xyshift != nullptr );
-        ::st_XYShift_set_dx( ptr_xyshift, dx );
-        ::st_XYShift_set_dy( ptr_xyshift, dy );
+        ::NS(XYShift_set_dx)( ptr_xyshift, dx );
+        ::NS(XYShift_set_dy)( ptr_xyshift, dy );
 
-        ASSERT_TRUE( std::fabs( dx - ::st_XYShift_get_dx( ptr_xyshift ) ) < EPS );
-        ASSERT_TRUE( std::fabs( dy - ::st_XYShift_get_dy( ptr_xyshift ) ) < EPS );
+        ASSERT_TRUE( std::fabs( dx - ::NS(XYShift_dx)( ptr_xyshift ) ) < EPS );
+        ASSERT_TRUE( std::fabs( dy - ::NS(XYShift_dy)( ptr_xyshift ) ) < EPS );
 
-        num_slots += ::st_ManagedBuffer_predict_required_num_slots( nullptr,
-            sizeof( ::st_XYShift ), ::st_XYShift_get_num_dataptrs( ptr_xyshift ),
+        num_slots += ::NS(ManagedBuffer_predict_required_num_slots)( nullptr,
+            sizeof( ::NS(XYShift) ), ::NS(XYShift_num_dataptrs)( ptr_xyshift ),
                 nullptr, nullptr, slot_size );
     }
 
     /* --------------------------------------------------------------------- */
 
-    size_t const requ_buffer_size = ::st_ManagedBuffer_calculate_buffer_length(
+    size_t const requ_buffer_size = ::NS(ManagedBuffer_calculate_buffer_length)(
         nullptr, num_objs, num_slots, num_dataptrs, num_garbage, slot_size );
 
-    ::st_Buffer* eb = ::st_Buffer_new( requ_buffer_size );
+    ::NS(Buffer)* eb = ::NS(Buffer_new)( requ_buffer_size );
     ASSERT_TRUE( eb != nullptr );
 
     /* --------------------------------------------------------------------- */
@@ -89,98 +89,98 @@ TEST( C99_CommonBeamElementXYShiftTests, MinimalAddToBufferCopyRemapRead )
     belem_t* ptr_orig = &orig_beam_elements[ be_index++ ];
     ASSERT_TRUE( ptr_orig != nullptr );
 
-    object_t* ptr_object = ::st_Buffer_add_object( eb, ptr_orig, sizeof( belem_t ),
-        BEAM_ELEMENT_TYPE_ID, ::st_XYShift_get_num_dataptrs( ptr_orig ),
+    object_t* ptr_object = ::NS(Buffer_add_object)( eb, ptr_orig, sizeof( belem_t ),
+        BEAM_ELEMENT_TYPE_ID, ::NS(XYShift_num_dataptrs)( ptr_orig ),
             nullptr, nullptr, nullptr );
 
     ASSERT_TRUE( ptr_object != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
-    ASSERT_TRUE( ::st_Object_get_const_begin_ptr( ptr_object ) != nullptr );
-    ASSERT_TRUE( ::st_Object_get_size( ptr_object ) >= sizeof( belem_t ) );
-    ASSERT_TRUE( ::st_Object_get_type_id( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( eb ) == be_index );
+    ASSERT_TRUE( ::NS(Object_get_const_begin_ptr)( ptr_object ) != nullptr );
+    ASSERT_TRUE( ::NS(Object_get_size)( ptr_object ) >= sizeof( belem_t ) );
+    ASSERT_TRUE( ::NS(Object_get_type_id)( ptr_object ) == BEAM_ELEMENT_TYPE_ID );
 
     belem_t* ptr_xyshift = reinterpret_cast< belem_t* >(
-        ::st_Object_get_begin_ptr( ptr_object ) );
+        ::NS(Object_get_begin_ptr)( ptr_object ) );
 
     ASSERT_TRUE( ptr_xyshift != nullptr );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dx( ptr_xyshift ) -
-                                  ::st_XYShift_get_dx( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dx)( ptr_xyshift ) -
+                                  ::NS(XYShift_dx)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dy( ptr_xyshift ) -
-                                  ::st_XYShift_get_dy( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dy)( ptr_xyshift ) -
+                                  ::NS(XYShift_dy)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_xyshift = ::st_XYShift_new( eb );
+    ptr_xyshift = ::NS(XYShift_new)( eb );
 
     ASSERT_TRUE( ptr_xyshift != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dx( ptr_xyshift ) - ZERO ) );
-    ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dy( ptr_xyshift ) - ZERO ) );
+    ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dx)( ptr_xyshift ) - ZERO ) );
+    ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dy)( ptr_xyshift ) - ZERO ) );
 
-    ::st_XYShift_set_dx( ptr_xyshift, ::st_XYShift_get_dx( ptr_orig ) );
-    ::st_XYShift_set_dy( ptr_xyshift, ::st_XYShift_get_dy( ptr_orig ) );
+    ::NS(XYShift_set_dx)( ptr_xyshift, ::NS(XYShift_dx)( ptr_orig ) );
+    ::NS(XYShift_set_dy)( ptr_xyshift, ::NS(XYShift_dy)( ptr_orig ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dx( ptr_xyshift ) -
-                                  ::st_XYShift_get_dx( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dx)( ptr_xyshift ) -
+                                  ::NS(XYShift_dx)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dy( ptr_xyshift ) -
-                                  ::st_XYShift_get_dy( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dy)( ptr_xyshift ) -
+                                  ::NS(XYShift_dy)( ptr_orig  ) ) );
 
     /* --------------------------------------------------------------------- */
 
     ptr_orig  = &orig_beam_elements[ be_index++ ];
-    ptr_xyshift = ::st_XYShift_add( eb, ::st_XYShift_get_dx( ptr_orig ),
-                                        ::st_XYShift_get_dy( ptr_orig ) );
+    ptr_xyshift = ::NS(XYShift_add)( eb, ::NS(XYShift_dx)( ptr_orig ),
+                                        ::NS(XYShift_dy)( ptr_orig ) );
 
     ASSERT_TRUE( ptr_xyshift != nullptr );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dx( ptr_xyshift ) -
-                                  ::st_XYShift_get_dx( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dx)( ptr_xyshift ) -
+                                  ::NS(XYShift_dx)( ptr_orig  ) ) );
 
-    ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dy( ptr_xyshift ) -
-                                  ::st_XYShift_get_dy( ptr_orig  ) ) );
+    ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dy)( ptr_xyshift ) -
+                                  ::NS(XYShift_dy)( ptr_orig  ) ) );
 
     for( ; be_index < NUM_BEAM_ELEMENTS ; )
     {
         ptr_orig  = &orig_beam_elements[ be_index++ ];
-        ptr_xyshift = ::st_XYShift_add( eb, ::st_XYShift_get_dx( ptr_orig ),
-                                            ::st_XYShift_get_dy( ptr_orig ) );
+        ptr_xyshift = ::NS(XYShift_add)( eb, ::NS(XYShift_dx)( ptr_orig ),
+                                            ::NS(XYShift_dy)( ptr_orig ) );
 
         ASSERT_TRUE( ptr_xyshift != nullptr );
-        ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) == be_index );
+        ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( eb ) == be_index );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dx( ptr_xyshift ) -
-                                      ::st_XYShift_get_dx( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dx)( ptr_xyshift ) -
+                                      ::NS(XYShift_dx)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dy( ptr_xyshift ) -
-                                      ::st_XYShift_get_dy( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dy)( ptr_xyshift ) -
+                                      ::NS(XYShift_dy)( ptr_orig  ) ) );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ASSERT_TRUE( ::st_Buffer_get_size( eb ) > size_t{ 0 } );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( eb ) > size_t{ 0 } );
 
-    std::vector< raw_t > data_buffer( ::st_Buffer_get_size( eb ), raw_t{ 0 } );
-    data_buffer.assign( ::st_Buffer_get_const_data_begin( eb ),
-                        ::st_Buffer_get_const_data_end( eb ) );
+    std::vector< raw_t > data_buffer( ::NS(Buffer_get_size)( eb ), raw_t{ 0 } );
+    data_buffer.assign( ::NS(Buffer_get_const_data_begin)( eb ),
+                        ::NS(Buffer_get_const_data_end)( eb ) );
 
-    ::st_Buffer cmp_buffer;
-    ::st_Buffer_preset( &cmp_buffer );
-    int success = ::st_Buffer_init(
+    ::NS(Buffer) cmp_buffer;
+    ::NS(Buffer_preset)( &cmp_buffer );
+    int success = ::NS(Buffer_init)(
         &cmp_buffer, data_buffer.data(), data_buffer.size() );
 
     ASSERT_TRUE( success == 0 );
-    ASSERT_TRUE( ::st_Buffer_get_num_of_objects( eb ) ==
-                 ::st_Buffer_get_num_of_objects( &cmp_buffer ) );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( eb ) ==
+                 ::NS(Buffer_get_num_of_objects)( &cmp_buffer ) );
 
-    object_t const* obj_it  = ::st_Buffer_get_const_objects_begin( eb );
-    object_t const* obj_end = ::st_Buffer_get_const_objects_end( eb );
-    object_t const* cmp_it  = ::st_Buffer_get_const_objects_begin( &cmp_buffer );
+    object_t const* obj_it  = ::NS(Buffer_get_const_objects_begin)( eb );
+    object_t const* obj_end = ::NS(Buffer_get_const_objects_end)( eb );
+    object_t const* cmp_it  = ::NS(Buffer_get_const_objects_begin)( &cmp_buffer );
 
     be_index = size_t{ 0 };
 
@@ -188,19 +188,19 @@ TEST( C99_CommonBeamElementXYShiftTests, MinimalAddToBufferCopyRemapRead )
     {
         ptr_orig = &orig_beam_elements[ be_index++ ];
 
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) == BEAM_ELEMENT_TYPE_ID );
-        ASSERT_TRUE( ::st_Object_get_type_id( obj_it ) ==
-                     ::st_Object_get_type_id( cmp_it ) );
+        ASSERT_TRUE( ::NS(Object_get_type_id)( obj_it ) == BEAM_ELEMENT_TYPE_ID );
+        ASSERT_TRUE( ::NS(Object_get_type_id)( obj_it ) ==
+                     ::NS(Object_get_type_id)( cmp_it ) );
 
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) >= sizeof( belem_t ) );
-        ASSERT_TRUE( ::st_Object_get_size( obj_it ) ==
-                     ::st_Object_get_size( cmp_it ) );
+        ASSERT_TRUE( ::NS(Object_get_size)( obj_it ) >= sizeof( belem_t ) );
+        ASSERT_TRUE( ::NS(Object_get_size)( obj_it ) ==
+                     ::NS(Object_get_size)( cmp_it ) );
 
         belem_t const* elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( obj_it ) );
+            ::NS(Object_get_const_begin_ptr)( obj_it ) );
 
         belem_t const* cmp_elem = reinterpret_cast< belem_t const* >(
-            ::st_Object_get_const_begin_ptr( cmp_it ) );
+            ::NS(Object_get_const_begin_ptr)( cmp_it ) );
 
         ASSERT_TRUE( ptr_orig != elem );
         ASSERT_TRUE( ptr_orig != cmp_elem );
@@ -209,23 +209,21 @@ TEST( C99_CommonBeamElementXYShiftTests, MinimalAddToBufferCopyRemapRead )
         ASSERT_TRUE( cmp_elem != nullptr );
         ASSERT_TRUE( cmp_elem != elem    );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dx( elem ) -
-                                      ::st_XYShift_get_dx( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dx)( elem ) -
+                                      ::NS(XYShift_dx)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dy( elem ) -
-                                      ::st_XYShift_get_dy( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dy)( elem ) -
+                                      ::NS(XYShift_dy)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dx( cmp_elem ) -
-                                      ::st_XYShift_get_dx( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dx)( cmp_elem ) -
+                                      ::NS(XYShift_dx)( ptr_orig  ) ) );
 
-        ASSERT_TRUE( EPS > std::fabs( ::st_XYShift_get_dy( cmp_elem ) -
-                                      ::st_XYShift_get_dy( ptr_orig  ) ) );
+        ASSERT_TRUE( EPS > std::fabs( ::NS(XYShift_dy)( cmp_elem ) -
+                                      ::NS(XYShift_dy)( ptr_orig  ) ) );
     }
 
     /* --------------------------------------------------------------------- */
 
-    ::st_Buffer_delete( eb );
-    ::st_Buffer_free( &cmp_buffer );
+    ::NS(Buffer_delete)( eb );
+    ::NS(Buffer_free)( &cmp_buffer );
 }
-
-/* end: tests/sixtracklib/common/test_be_xy_shift_c99.cpp */
diff --git a/tests/sixtracklib/common/buffer/CMakeLists.txt b/tests/sixtracklib/common/buffer/CMakeLists.txt
new file mode 100644
index 00000000..5cffc667
--- /dev/null
+++ b/tests/sixtracklib/common/buffer/CMakeLists.txt
@@ -0,0 +1,97 @@
+# sixtracklib/tests/sixtracklib/common/buffer/CMakeLists.txt
+
+if( GTEST_FOUND )
+    set( SIXTRACKL_COMMON_TESTS_DEPEND_ON_TRACKING_TESTDATA )
+
+    set( UNIT_TEST_TARGETS )
+    set( SIXTRACKL_TEST_LIBRARIES ${SIXTRACKL_TEST_LIBRARIES}
+         ${SIXTRACKL_GTEST_LIBRARIES} )
+
+    # ==========================================================================
+    # test_mem_pool_common_c99:
+
+    add_executable( test_mem_pool_common_c99 test_mem_pool_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_mem_pool_common_c99 )
+    add_test( C99_Common_Buffer_CommonMemPoolTests test_mem_pool_common_c99 )
+
+    # ==========================================================================
+    # test_assign_address_item_common_c99:
+
+    add_executable( test_assign_address_item_common_c99
+                    test_assign_address_item_c99.cpp )
+
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
+         test_assign_address_item_common_c99 )
+
+    add_test( C99_Common_Buffer_AssignAddressItemTests
+              test_assign_address_item_common_c99 )
+
+    # ==========================================================================
+    # test_managed_buffer_common_c99:
+
+    add_executable( test_managed_buffer_common_c99 test_managed_buffer_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_managed_buffer_common_c99 )
+    add_test( C99_Common_Buffer_ManagedBufferTests
+              test_managed_buffer_common_c99 )
+
+    # ==========================================================================
+    # test_buffer_common_c99:
+
+    add_executable( test_buffer_common_c99 test_buffer_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_buffer_common_c99 )
+    add_test( C99_Common_Buffer_BufferTests test_buffer_common_c99 )
+
+    # --------------------------------------------------------------------------
+    # test_buffer_common_cxx:
+
+    add_executable( test_buffer_common_cxx test_buffer_cxx.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_buffer_common_cxx )
+    add_test( CXX_Common_Buffer_BufferTests test_buffer_common_cxx )
+
+    # ==========================================================================
+    # test_buffer_string_object_common_c99:
+
+    add_executable( test_buffer_string_object_common_c99
+                    test_buffer_string_object_c99.cpp )
+
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
+         test_buffer_string_object_common_c99 )
+
+    add_test( C99_Common_Buffer_BufferStringObjectTests
+              test_buffer_string_object_common_c99 )
+
+    # -------------------------------------------------------------------------
+    # test_buffer_string_object_common_cxx:
+
+    add_executable( test_buffer_string_object_common_cxx
+                    test_buffer_string_object_cxx.cpp )
+
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
+         test_buffer_string_object_common_cxx )
+
+    add_test( CXX_Common_Buffer_BufferStringObjectTests
+              test_buffer_string_object_common_cxx )
+
+    # *************************************************************************
+    # Set all properties:
+
+    if( UNIT_TEST_TARGETS )
+        set_property( TARGET ${UNIT_TEST_TARGETS}
+            APPEND PROPERTY INCLUDE_DIRECTORIES
+            $<BUILD_INTERFACE:${SIXTRACKL_GTEST_INCLUDE_DIRS}>
+        )
+
+        set_property( TARGET ${UNIT_TEST_TARGETS}
+                      PROPERTY LINK_LIBRARIES ${SIXTRACKL_TEST_LIBRARIES} )
+
+        set_property( TARGET ${UNIT_TEST_TARGETS} PROPERTY CXX_STANDARD 11 )
+        set_property( TARGET ${UNIT_TEST_TARGETS}
+                      PROPERTY CXX_STANDARD_REQUIRED ON )
+
+        set_property( TARGET ${UNIT_TEST_TARGETS}
+                      APPEND PROPERTY COMPILE_OPTIONS
+                      ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    endif()
+endif()
+
+#end : sixtracklib/tests/sixtracklib/common/control/CMakeLists.txt
diff --git a/tests/sixtracklib/common/buffer/test_assign_address_item_c99.cpp b/tests/sixtracklib/common/buffer/test_assign_address_item_c99.cpp
new file mode 100644
index 00000000..775a3256
--- /dev/null
+++ b/tests/sixtracklib/common/buffer/test_assign_address_item_c99.cpp
@@ -0,0 +1,478 @@
+#include "sixtracklib/common/buffer/assign_address_item.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/control/definitions.h"
+#include "sixtracklib/common/internal/objects_type_id.h"
+#include "sixtracklib/common/buffer.h"
+#include "sixtracklib/common/particles.h"
+#include "sixtracklib/common/be_drift/be_drift.h"
+#include "sixtracklib/common/be_monitor/be_monitor.h"
+#include "sixtracklib/common/output/elem_by_elem_config.h"
+#include "sixtracklib/common/output/output_buffer.h"
+
+#include "sixtracklib/testlib.h"
+
+TEST( C99_Common_Buffer_AssignAddressItemTests, BeamMonitorAssignment )
+{
+    using be_monitor_t   = ::NS(BeamMonitor);
+    using buffer_t       = ::NS(Buffer);
+    using buf_size_t     = ::NS(buffer_size_t);
+    using assign_item_t  = ::NS(AssignAddressItem);
+    using particle_set_t = ::NS(Particles);
+
+    buffer_t* map_buffer    = ::NS(Buffer_new)( buf_size_t{ 0 } );
+    buffer_t* beam_elements = ::NS(Buffer_new)( buf_size_t{ 0 } );
+    buffer_t* output_buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
+
+    constexpr buf_size_t NUM_BEAM_MONITORS = buf_size_t{ 10 };
+
+    std::vector< buf_size_t > be_mon_indices(
+        NUM_BEAM_MONITORS, buf_size_t{ 0 } );
+    be_mon_indices.clear();
+
+    std::vector< buf_size_t > out_buffer_indices(
+        NUM_BEAM_MONITORS,  buf_size_t{ 0 } );
+    out_buffer_indices.clear();
+
+    particle_set_t* pset_dummy = ::NS(Particles_new)(
+        output_buffer, buf_size_t{ 100 } );
+    SIXTRL_ASSERT( pset_dummy != nullptr );
+
+    pset_dummy = ::NS(Particles_new)(
+        output_buffer, buf_size_t{ 100 } );
+    SIXTRL_ASSERT( pset_dummy != nullptr );
+    ( void )pset_dummy;
+
+    for( buf_size_t ii = buf_size_t{ 0 } ; ii < NUM_BEAM_MONITORS ; ++ii )
+    {
+        ::NS(Drift)* drift = ::NS(Drift_add)( beam_elements, 0.1 * ii );
+        SIXTRL_ASSERT( drift != nullptr );
+        ( void )drift;
+
+        be_mon_indices.push_back( ::NS(Buffer_get_num_of_objects)(
+            beam_elements ) );
+
+        ::NS(BeamMonitor)* be_mon = ::NS(BeamMonitor_new)( beam_elements );
+        SIXTRL_ASSERT( be_mon != nullptr );
+
+        ::NS(BeamMonitor_set_out_address)( be_mon, ::NS(buffer_addr_t){ 0 } );
+
+        out_buffer_indices.push_back( ::NS(Buffer_get_num_of_objects)(
+            output_buffer ) );
+
+        particle_set_t* out_pset = ::NS(Particles_new)(
+            output_buffer, buf_size_t{ 1 } );
+
+        SIXTRL_ASSERT( out_pset != nullptr );
+        ( void )out_pset;
+    }
+
+    SIXTRL_ASSERT( out_buffer_indices.size() == be_mon_indices.size() );
+
+    auto be_mon_idx_it  = be_mon_indices.cbegin();
+    auto be_mon_idx_end = be_mon_indices.cend();
+    auto out_idx_it     = out_buffer_indices.cbegin();
+
+    for( ; be_mon_idx_it != be_mon_idx_end ; ++be_mon_idx_it, ++out_idx_it )
+    {
+        buf_size_t const be_mon_idx = *be_mon_idx_it;
+        buf_size_t const out_pset_idx = *out_idx_it;
+
+        assign_item_t* assign_item = nullptr;
+
+        if( ( be_mon_idx % buf_size_t{ 2 } ) == buf_size_t{ 0 } )
+        {
+            assign_item = ::NS(AssignAddressItem_new)( map_buffer );
+            ASSERT_TRUE( assign_item != nullptr );
+
+            ::NS(AssignAddressItem_set_dest_buffer_id)(
+                assign_item, ::NS(ARCH_BEAM_ELEMENTS_BUFFER_ID) );
+
+            ::NS(AssignAddressItem_set_dest_elem_type_id)(
+                assign_item, ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+            ::NS(AssignAddressItem_set_dest_elem_index)(
+                assign_item, be_mon_idx );
+
+            ::NS(AssignAddressItem_set_dest_pointer_offset)(
+                assign_item, offsetof( NS(BeamMonitor), out_address ) );
+
+            ::NS(AssignAddressItem_set_src_buffer_id)(
+                assign_item, ::NS(ARCH_OUTPUT_BUFFER_ID) );
+
+            ::NS(AssignAddressItem_set_src_elem_type_id)(
+                assign_item, ::NS(OBJECT_TYPE_PARTICLE) );
+
+            ::NS(AssignAddressItem_set_src_elem_index)(
+                assign_item, out_pset_idx );
+
+            ::NS(AssignAddressItem_set_src_pointer_offset)(
+                assign_item, ::NS(buffer_addr_t){ 0 } );
+        }
+        else
+        {
+            assign_item = ::NS(AssignAddressItem_add)( map_buffer,
+                ::NS(OBJECT_TYPE_BEAM_MONITOR),
+                ::NS(ARCH_BEAM_ELEMENTS_BUFFER_ID), be_mon_idx,
+                offsetof( NS(BeamMonitor), out_address ),
+                ::NS(OBJECT_TYPE_PARTICLE), ::NS(ARCH_OUTPUT_BUFFER_ID),
+                out_pset_idx, ::NS(buffer_addr_t){ 0 } );
+
+            ASSERT_TRUE( assign_item != nullptr );
+        }
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_dest_elem_type_id)( assign_item ) ==
+                     ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_dest_buffer_id)( assign_item ) ==
+                     ::NS(ARCH_BEAM_ELEMENTS_BUFFER_ID) );
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_dest_elem_index)(
+            assign_item ) == be_mon_idx );
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_dest_pointer_offset)(
+            assign_item ) == offsetof( ::NS(BeamMonitor), out_address ) );
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_src_elem_type_id)(
+            assign_item ) == ::NS(OBJECT_TYPE_PARTICLE) );
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_src_buffer_id)(
+            assign_item ) == ::NS(ARCH_OUTPUT_BUFFER_ID) );
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_src_elem_index)(
+            assign_item ) == out_pset_idx );
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_src_pointer_offset)(
+            assign_item ) == ::NS(buffer_addr_t){ 0 } );
+    }
+
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)(
+        map_buffer ) == NUM_BEAM_MONITORS );
+
+    /* ********************************************************************* */
+
+    buf_size_t const dest_slot_size =
+        ::NS(Buffer_get_slot_size)( beam_elements );
+
+    for( buf_size_t ii = buf_size_t{ 0 } ; ii < NUM_BEAM_MONITORS ; ++ii )
+    {
+        assign_item_t const* assign_item =
+            ::NS(AssignAddressItem_const_from_buffer)( map_buffer, ii );
+
+        ASSERT_TRUE( assign_item != nullptr );
+
+        be_monitor_t const* be_mon = ::NS(BeamMonitor_const_from_buffer)(
+            beam_elements, ::NS(AssignAddressItem_dest_elem_index)(
+                assign_item ) );
+
+        SIXTRL_ASSERT( be_mon != nullptr );
+
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)( be_mon ) ==
+            ::NS(buffer_addr_t){ 0 } );
+
+        ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) ==
+            NS(AssignAddressItem_assign_fixed_addr)( assign_item,
+                beam_elements, static_cast< ::NS(buffer_addr_t) >(
+                    ii * dest_slot_size ) ) );
+
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_mon ) ==
+            static_cast< ::NS(buffer_addr_t) >( ii * dest_slot_size ) );
+
+        ASSERT_TRUE( ::NS(AssignAddressItem_remap_assignment)( assign_item,
+            beam_elements, ::NS(buffer_addr_t){ 192 } ) ==
+                ::NS(ARCH_STATUS_SUCCESS) );
+
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_mon ) ==
+            static_cast< ::NS(buffer_addr_t) >( ii * dest_slot_size + 192 ) );
+
+        ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) ==
+            ::NS(AssignAddressItem_remap_assignment)( assign_item,
+                beam_elements, -( static_cast< ::NS(buffer_addr_diff_t) >(
+                    ii * dest_slot_size + 192 ) ) ) );
+
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_mon ) ==
+            ::NS(buffer_addr_t){ 0 } );
+    }
+
+    for( buf_size_t ii = buf_size_t{ 0 } ; ii < NUM_BEAM_MONITORS ; ++ii )
+    {
+        assign_item_t const* assign_item =
+            ::NS(AssignAddressItem_const_from_buffer)( map_buffer, ii );
+
+        particle_set_t const* pset = ::NS(Particles_buffer_get_const_particles)(
+            output_buffer, out_buffer_indices[ ii ] );
+
+        be_monitor_t const* be_mon = ::NS(BeamMonitor_const_from_buffer)(
+            beam_elements, be_mon_indices[ ii ] );
+
+        SIXTRL_ASSERT( assign_item != nullptr );
+        SIXTRL_ASSERT( pset != nullptr );
+        SIXTRL_ASSERT( be_mon != nullptr );
+
+        ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) ==
+            ::NS(AssignAddressItem_perform_assignment)( assign_item,
+                beam_elements, output_buffer ) );
+
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( be_mon ) ==
+            static_cast< ::NS(buffer_addr_t) >( reinterpret_cast< uintptr_t >(
+                pset ) ) );
+
+        ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) ==
+            ::NS(AssignAddressItem_assign_fixed_addr)( assign_item,
+                beam_elements, ::NS(buffer_addr_t){ 0 } ) );
+    }
+
+    /* ********************************************************************* */
+
+    ::NS(Buffer_delete)( map_buffer );
+    ::NS(Buffer_delete)( beam_elements );
+    ::NS(Buffer_delete)( output_buffer );
+}
+
+TEST( C99_Common_Buffer_AssignAddressItemTests, ElemByElemConfigTest )
+{
+    using elem_config_t     = ::NS(ElemByElemConfig);
+    using buffer_t          = ::NS(Buffer);
+    using buf_size_t        = ::NS(buffer_size_t);
+    using assign_item_t     = ::NS(AssignAddressItem);
+    using particle_set_t    = ::NS(Particles);
+    using addr_t            = ::NS(buffer_addr_t);
+
+    buffer_t* map_buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
+    buffer_t* elem_by_elem_config_buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
+    buffer_t* output_buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
+
+    elem_config_t config_on_stack;
+    ::NS(ElemByElemConfig_preset)( &config_on_stack );
+    ::NS(ElemByElemConfig_set_output_store_address)(
+        &config_on_stack, addr_t{ 0 } );
+
+    elem_config_t* config_in_buffer =
+        ::NS(ElemByElemConfig_new)( elem_by_elem_config_buffer );
+
+    SIXTRL_ASSERT( config_in_buffer != nullptr );
+    ::NS(ElemByElemConfig_set_output_store_address)(
+        config_in_buffer, addr_t{ 0 } );
+
+    particle_set_t* dummy_pset = ::NS(Particles_new)(
+        output_buffer, buf_size_t{ 1 } );
+    SIXTRL_ASSERT( dummy_pset != nullptr );
+    ( void )dummy_pset;
+
+    particle_set_t* output_pset = ::NS(Particles_new)(
+        output_buffer, buf_size_t{ 1 } );
+    SIXTRL_ASSERT( output_pset != nullptr );
+
+    /* --------------------------------------------------------------------- */
+    /* Create assignment item for elem-by-elem-config on stack */
+
+    assign_item_t* assign_item_stack = ::NS(AssignAddressItem_add)( map_buffer,
+        ::NS(OBJECT_TYPE_NONE), ::NS(ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID),
+        buf_size_t{ 0 }, offsetof( ::NS(ElemByElemConfig), out_store_addr ),
+        ::NS(OBJECT_TYPE_PARTICLE), ::NS(ARCH_OUTPUT_BUFFER_ID),
+        buf_size_t{ 1 }, buf_size_t{ 0 } );
+
+    ASSERT_TRUE( assign_item_stack != nullptr );
+
+    /* --------------------------------------------------------------------- */
+    /* Create assignment item for elem-by-elem-config in buffer */
+
+    assign_item_t* assign_item_buffer =
+        ::NS(AssignAddressItem_new)( map_buffer );
+
+    ASSERT_TRUE( assign_item_buffer != nullptr );
+
+    ::NS(AssignAddressItem_set_dest_elem_type_id)(
+        assign_item_buffer, ::NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF) );
+
+    ::NS(AssignAddressItem_set_dest_buffer_id)(
+        assign_item_buffer, ::NS(ARCH_MIN_USER_DEFINED_BUFFER_ID) );
+
+    ::NS(AssignAddressItem_set_dest_elem_index)(
+        assign_item_buffer, buf_size_t{ 0 } );
+
+    ::NS(AssignAddressItem_set_dest_pointer_offset)(
+        assign_item_buffer, offsetof( ::NS(ElemByElemConfig), out_store_addr ) );
+
+    ::NS(AssignAddressItem_set_src_elem_type_id)(
+        assign_item_buffer, ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ::NS(AssignAddressItem_set_src_buffer_id)(
+        assign_item_buffer, ::NS(ARCH_OUTPUT_BUFFER_ID) );
+
+    ::NS(AssignAddressItem_set_src_elem_index)(
+        assign_item_buffer, buf_size_t{ 1 } );
+
+    ::NS(AssignAddressItem_set_src_pointer_offset)(
+        assign_item_buffer, buf_size_t{ 0 } );
+
+    /* --------------------------------------------------------------------- */
+    /* Perform assignments and remappings for elem-by-elem config on stack */
+
+    assign_item_stack = ::NS(AssignAddressItem_from_buffer)( map_buffer, 0 );
+    ASSERT_TRUE( assign_item_stack != nullptr );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_dest_buffer_id)(
+        assign_item_stack ) == ::NS(ASSIGN_ADDRESS_ITEM_NO_BUFFER_ID) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_dest_elem_type_id)(
+        assign_item_stack ) == ::NS(OBJECT_TYPE_NONE) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_dest_elem_index)(
+        assign_item_stack ) == buf_size_t{ 0 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_dest_pointer_offset)( assign_item_stack
+        ) == offsetof( ::NS(ElemByElemConfig), out_store_addr ) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_src_buffer_id)(
+        assign_item_stack ) == ::NS(ARCH_OUTPUT_BUFFER_ID) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_src_elem_type_id)(
+        assign_item_stack ) == ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_src_elem_index)(
+        assign_item_stack ) == buf_size_t{ 1 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_src_pointer_offset)(
+        assign_item_stack ) == buf_size_t{ 0 } );
+
+    unsigned char* ptr_stack_begin = reinterpret_cast< unsigned char* >(
+        reinterpret_cast< uintptr_t >( &config_on_stack ) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_assign_fixed_addr_on_raw_memory)(
+        assign_item_stack, ptr_stack_begin, addr_t{ 42 } ) ==
+            ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        &config_on_stack ) == addr_t{ 42 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_remap_assignment_on_raw_memory)(
+        assign_item_stack, ptr_stack_begin,
+            ::NS(buffer_addr_diff_t){ 214 } ) == ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        &config_on_stack ) == addr_t{ 256 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_remap_assignment_on_raw_memory)(
+        assign_item_stack, ptr_stack_begin,
+            ::NS(buffer_addr_diff_t){ -214 } ) == ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        &config_on_stack ) == addr_t{ 42 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_assign_fixed_addr_on_raw_memory)(
+        assign_item_stack, ptr_stack_begin, addr_t{ 0 } ) ==
+            ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        &config_on_stack ) == addr_t{ 0 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_assign_fixed_addr_on_raw_memory)(
+        assign_item_stack, ptr_stack_begin,
+                reinterpret_cast< uintptr_t >( output_pset ) ) ==
+                    ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        &config_on_stack ) == static_cast< addr_t >( reinterpret_cast<
+            uintptr_t >( output_pset ) ) );
+
+    /* --------------------------------------------------------------------- */
+    /* Perform assignments and remappings for elem-by-elem config in buffer  */
+
+    assign_item_buffer = ::NS(AssignAddressItem_from_buffer)(
+        map_buffer, 1 );
+
+    ASSERT_TRUE( assign_item_buffer != nullptr );
+    ASSERT_TRUE( ::NS(AssignAddressItem_dest_buffer_id)(
+        assign_item_buffer ) == ::NS(ARCH_MIN_USER_DEFINED_BUFFER_ID) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_dest_elem_type_id)(
+        assign_item_buffer ) == ::NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_dest_elem_index)(
+        assign_item_buffer ) == buf_size_t{ 0 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_dest_pointer_offset)( assign_item_buffer
+        ) == offsetof( ::NS(ElemByElemConfig), out_store_addr ) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_src_buffer_id)(
+        assign_item_buffer ) == ::NS(ARCH_OUTPUT_BUFFER_ID) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_src_elem_type_id)(
+        assign_item_buffer ) == ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_src_elem_index)(
+        assign_item_buffer ) == buf_size_t{ 1 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_src_pointer_offset)(
+        assign_item_buffer ) == buf_size_t{ 0 } );
+
+    buf_size_t const dest_slot_size =
+        ::NS(Buffer_get_slot_size)( elem_by_elem_config_buffer );
+
+    unsigned char* ptr_buffer_begin =
+        ::NS(Buffer_get_data_begin)( elem_by_elem_config_buffer );
+
+    SIXTRL_ASSERT( dest_slot_size > buf_size_t{ 0 } );
+    SIXTRL_ASSERT( ptr_buffer_begin != nullptr );
+
+    addr_t const fixed_addr = static_cast< addr_t >( dest_slot_size );
+    addr_t const remapped_fixed_addr = static_cast< addr_t >(
+        10 * dest_slot_size );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_assign_fixed_addr_on_managed_buffer)(
+        assign_item_buffer, ptr_buffer_begin, dest_slot_size, static_cast< addr_t >(
+            dest_slot_size ) ) == ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        config_in_buffer ) == static_cast< addr_t >( dest_slot_size ) );
+
+    ::NS(buffer_addr_diff_t) dist = static_cast< addr_t >(
+        9 * dest_slot_size );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_remap_assignment_on_managed_buffer)(
+        assign_item_buffer, ptr_buffer_begin, dest_slot_size, dist ) ==
+            ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        config_in_buffer ) == remapped_fixed_addr );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_remap_assignment_on_managed_buffer)(
+        assign_item_buffer, ptr_buffer_begin, dest_slot_size, -dist ) ==
+            ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        config_in_buffer ) == fixed_addr );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_assign_fixed_addr_on_managed_buffer)(
+        assign_item_buffer, ptr_buffer_begin, dest_slot_size, addr_t{ 0 } ) ==
+            ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        config_in_buffer ) == addr_t{ 0 } );
+
+    ASSERT_TRUE( ::NS(AssignAddressItem_perform_assignment_on_managed_buffer)(
+        assign_item_buffer, ptr_buffer_begin, dest_slot_size,
+            ::NS(Buffer_get_data_begin)( output_buffer ),
+                ::NS(Buffer_get_slot_size)( output_buffer ) ) ==
+                    ::NS(ARCH_STATUS_SUCCESS) );
+
+    ASSERT_TRUE( ::NS(ElemByElemConfig_get_output_store_address)(
+        config_in_buffer ) == static_cast< addr_t >( reinterpret_cast<
+            uintptr_t >( output_pset ) ) );
+
+    /* ********************************************************************* */
+
+    ::NS(Buffer_delete)( map_buffer );
+    ::NS(Buffer_delete)( elem_by_elem_config_buffer );
+    ::NS(Buffer_delete)( output_buffer );
+}
+
+/* end: tests/sixtracklib/common/buffer/test_assign_address_item_c99.cpp */
diff --git a/tests/sixtracklib/common/test_buffer_array_object_c99.cpp b/tests/sixtracklib/common/buffer/test_buffer_array_object_c99.cpp
similarity index 88%
rename from tests/sixtracklib/common/test_buffer_array_object_c99.cpp
rename to tests/sixtracklib/common/buffer/test_buffer_array_object_c99.cpp
index 1e3be635..e3da6ac5 100644
--- a/tests/sixtracklib/common/test_buffer_array_object_c99.cpp
+++ b/tests/sixtracklib/common/buffer/test_buffer_array_object_c99.cpp
@@ -15,7 +15,7 @@
 #include "sixtracklib/common/buffer.h"
 #include "sixtracklib/testlib.h"
 
-TEST( C99_CommonBufferArrayObjectTests, BasicUsage )
+TEST( C99_Common_Buffer_BufferArrayObjectTests, BasicUsage )
 {
     using buffer_t   = ::NS(Buffer)*;
     using buf_size_t = ::NS(buffer_size_t);
@@ -24,7 +24,7 @@ TEST( C99_CommonBufferArrayObjectTests, BasicUsage )
     using object_t   = ::NS(Object);
     using type_id_t  = ::NS(object_type_id_t);
 
-    buffer_t buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
+    buffer_t  buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
 
     buf_size_t const arr1_max_num_elements = buf_size_t{ 10 };
     buf_size_t const arr1_capacity = buf_size_t{ 1 << 12 };
@@ -50,4 +50,4 @@ TEST( C99_CommonBufferArrayObjectTests, BasicUsage )
     buffer = nullptr;
 }
 
-/* end: tests/sixtracklib/common/test_buffer_array_object_c99.cpp */
+/* end: tests/sixtracklib/common/buffer/test_buffer_array_object_c99.cpp */
diff --git a/tests/sixtracklib/common/test_buffer_c99.cpp b/tests/sixtracklib/common/buffer/test_buffer_c99.cpp
similarity index 97%
rename from tests/sixtracklib/common/test_buffer_c99.cpp
rename to tests/sixtracklib/common/buffer/test_buffer_c99.cpp
index 295e3e82..cf21a8ab 100644
--- a/tests/sixtracklib/common/test_buffer_c99.cpp
+++ b/tests/sixtracklib/common/buffer/test_buffer_c99.cpp
@@ -36,7 +36,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
 /* ************************************************************************* */
 
-TEST( C99_CommonBufferTests, InitOnExistingFlatMemory)
+TEST( CXX_Common_Buffer_BufferTests, InitOnExistingFlatMemory)
 {
     std::vector< unsigned char > too_small( 36u, uint8_t{ 0 } );
     std::vector< unsigned char > data_buffer( ( 1u << 20u ), uint8_t{ 0 } );
@@ -57,7 +57,7 @@ TEST( C99_CommonBufferTests, InitOnExistingFlatMemory)
     ASSERT_TRUE( success == 0 );
 }
 
-TEST( C99_CommonBufferTests, NewOnExistingFlatMemory)
+TEST( CXX_Common_Buffer_BufferTests, NewOnExistingFlatMemory)
 {
     std::vector< unsigned char > raw_buffer( 1u << 20u );
 
@@ -69,7 +69,7 @@ TEST( C99_CommonBufferTests, NewOnExistingFlatMemory)
     ASSERT_TRUE( !::NS(Buffer_owns_datastore)( buffer ) );
     ASSERT_TRUE(  ::NS(Buffer_get_num_of_dataptrs)( buffer ) == 0u );
     ASSERT_TRUE(  ::NS(Buffer_get_num_of_garbage_ranges)( buffer ) == 0u );
-    ASSERT_TRUE(  ::NS(Buffer_get_size)( buffer ) > ::st_buffer_size_t{ 0 } );
+    ASSERT_TRUE(  ::NS(Buffer_get_size)( buffer ) > ::NS(buffer_size_t){ 0 } );
 
     ::NS(Buffer_delete)( buffer );
     buffer = nullptr;
@@ -77,7 +77,7 @@ TEST( C99_CommonBufferTests, NewOnExistingFlatMemory)
 
 /* ************************************************************************* */
 
-TEST( C99_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
+TEST( CXX_Common_Buffer_BufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
 {
     namespace sixtrl = SIXTRL_CXX_NAMESPACE::tests;
 
@@ -110,8 +110,8 @@ TEST( C99_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
 
     buf_size_t attr_counts[ NUM_DATAPTRS ] =
     {
-        st_buffer_size_t{ 0 },
-        st_buffer_size_t{ 0 }
+        ::NS(buffer_size_t){ 0 },
+        ::NS(buffer_size_t){ 0 }
     };
 
     ::NS(Buffer) buffer;
@@ -584,7 +584,7 @@ TEST( C99_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
 
 /* ************************************************************************* */
 
-TEST( C99_CommonBufferTests, ReconstructFromCObjectFile )
+TEST( CXX_Common_Buffer_BufferTests, ReconstructFromCObjectFile )
 {
     namespace sixtrl = SIXTRL_CXX_NAMESPACE::tests;
 
@@ -617,8 +617,8 @@ TEST( C99_CommonBufferTests, ReconstructFromCObjectFile )
 
     buf_size_t attr_counts[ NUM_DATAPTRS ] =
     {
-        st_buffer_size_t{ 0 },
-        st_buffer_size_t{ 0 }
+        ::NS(buffer_size_t){ 0 },
+        ::NS(buffer_size_t){ 0 }
     };
 
     constexpr buf_size_t num_d_values = 4;
@@ -711,9 +711,9 @@ TEST( C99_CommonBufferTests, ReconstructFromCObjectFile )
 
         buf_size_t const cnt = std::fwrite( ( unsigned char const* )(
             uintptr_t )::NS(Buffer_get_data_begin_addr)( &buffer ),
-            ::NS(Buffer_get_size)( &buffer ), st_buffer_size_t{ 1 }, fp );
+            ::NS(Buffer_get_size)( &buffer ), ::NS(buffer_size_t){ 1 }, fp );
 
-        ASSERT_TRUE( cnt == st_buffer_size_t{ 1 } );
+        ASSERT_TRUE( cnt == ::NS(buffer_size_t){ 1 } );
 
         std::fclose( fp );
         fp = nullptr;
@@ -768,8 +768,8 @@ TEST( C99_CommonBufferTests, ReconstructFromCObjectFile )
     ASSERT_TRUE( ::NS(Buffer_get_size)( &buffer ) == buffer_size );
     ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( &buffer ) == 2u );
 
-    st_Object const* obj_it  = ::NS(Buffer_get_const_objects_begin)(&buffer);
-    st_Object const* obj_end = ::NS(Buffer_get_const_objects_end)( &buffer );
+    ::NS(Object) const* obj_it  = ::NS(Buffer_get_const_objects_begin)(&buffer);
+    ::NS(Object) const* obj_end = ::NS(Buffer_get_const_objects_end)( &buffer );
 
     my_obj_t const* cmp_obj_it = &cmp_my_obj[ 0 ];
 
@@ -791,7 +791,7 @@ TEST( C99_CommonBufferTests, ReconstructFromCObjectFile )
                      ::NS(Object_get_type_id)( obj_it ) );
 
         ASSERT_TRUE( ptr_my_obj->a == cmp_obj_it->a );
-        ASSERT_TRUE( std::abs( ( ptr_my_obj->b - cmp_obj_it->b ) < EPS ) );
+        ASSERT_TRUE( std::abs( ptr_my_obj->b - cmp_obj_it->b ) < EPS );
 
         for( std::size_t ii = 0u ; ii < 4u ; ++ii )
         {
@@ -804,8 +804,8 @@ TEST( C99_CommonBufferTests, ReconstructFromCObjectFile )
 
         for( std::size_t ii = 0u ; ii < 4u ; ++ii )
         {
-            ASSERT_TRUE( std::abs( ( ptr_my_obj->d[ ii ] -
-                cmp_obj_it->d[ ii ] ) < EPS ) );
+            ASSERT_TRUE( std::abs( ptr_my_obj->d[ ii ] -
+                cmp_obj_it->d[ ii ] ) < EPS );
         }
 
         ASSERT_TRUE( ptr_my_obj->e != nullptr );
@@ -817,7 +817,7 @@ TEST( C99_CommonBufferTests, ReconstructFromCObjectFile )
     ::NS(Buffer_free)( &buffer );
 }
 
-TEST( C99_CommonBufferTests, NewBufferAndGrowingWithinCapacity )
+TEST( CXX_Common_Buffer_BufferTests, NewBufferAndGrowingWithinCapacity )
 {
     namespace sixtrl = SIXTRL_CXX_NAMESPACE::tests;
 
@@ -1046,7 +1046,7 @@ TEST( C99_CommonBufferTests, NewBufferAndGrowingWithinCapacity )
     buffer = nullptr;
 }
 
-TEST( C99_CommonBufferTests, AddGenericObjectsTestAutoGrowingOfBuffer )
+TEST( CXX_Common_Buffer_BufferTests, AddGenericObjectsTestAutoGrowingOfBuffer )
 {
     using buf_size_t    = ::NS(buffer_size_t);
     using type_id_t     = ::NS(object_type_id_t);
@@ -1118,7 +1118,7 @@ TEST( C99_CommonBufferTests, AddGenericObjectsTestAutoGrowingOfBuffer )
     ::NS(Buffer_delete)( buffer );
 }
 
-TEST( C99_CommonBufferTests, WriteBufferNormalizedAddrRestoreVerify )
+TEST( CXX_Common_Buffer_BufferTests, WriteBufferNormalizedAddrRestoreVerify )
 {
     using prng_seed_t   = unsigned long long;
     using buf_size_t    = ::NS(buffer_size_t);
@@ -1300,7 +1300,7 @@ TEST( C99_CommonBufferTests, WriteBufferNormalizedAddrRestoreVerify )
     ::NS(Buffer_delete)( restored_buffer );
 }
 
-TEST( C99_CommonBufferTests, CreateNewOnDataAddObjects )
+TEST( CXX_Common_Buffer_BufferTests, CreateNewOnDataAddObjects )
 {
     using gen_obj_t  = ::NS(GenericObj);
     using buf_size_t = ::NS(buffer_size_t);
@@ -1684,10 +1684,8 @@ TEST( C99_CommonBufferTests, CreateNewOnDataAddObjects )
     ASSERT_TRUE( ::NS(Buffer_get_num_of_garbage_ranges)( ext_buffer ) ==
         buf_size_t{ 0 } );
 
-    ::NS(Object) const* it  =
-        ::NS(Buffer_get_const_objects_begin)( ext_buffer );
-
-    ::NS(Object) const* end  =
+    ::NS(Object) const* it = ::NS(Buffer_get_const_objects_begin)( ext_buffer );
+    ::NS(Object) const* end =
         ::NS(Buffer_get_const_objects_end)( ext_buffer );
 
     ASSERT_TRUE( ( it != nullptr ) && ( end != nullptr ) );
@@ -1732,4 +1730,4 @@ TEST( C99_CommonBufferTests, CreateNewOnDataAddObjects )
     ext_buffer = nullptr;
 }
 
-/* end: tests/sixtracklib/common/test_buffer_c99.cpp */
+/* end: tests/sixtracklib/common/buffer/test_buffer_c99.cpp */
diff --git a/tests/sixtracklib/common/test_buffer_cxx.cpp b/tests/sixtracklib/common/buffer/test_buffer_cxx.cpp
similarity index 86%
rename from tests/sixtracklib/common/test_buffer_cxx.cpp
rename to tests/sixtracklib/common/buffer/test_buffer_cxx.cpp
index 556a8ccb..2ee5608d 100644
--- a/tests/sixtracklib/common/test_buffer_cxx.cpp
+++ b/tests/sixtracklib/common/buffer/test_buffer_cxx.cpp
@@ -1,3 +1,5 @@
+#include "sixtracklib/common/buffer.hpp"
+
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
@@ -12,9 +14,8 @@
 #include <gtest/gtest.h>
 
 #include "sixtracklib/common/definitions.h"
-#include "sixtracklib/testlib/common/generic_buffer_obj.h"
+#include "sixtracklib/testlib/common/buffer/generic_buffer_obj.h"
 #include "sixtracklib/testlib/testdata/testdata_files.h"
-#include "sixtracklib/common/buffer.hpp"
 
 #include "sixtracklib/testlib.h"
 
@@ -22,15 +23,15 @@ namespace sixtrack
 {
     struct MyObj
     {
-        st_object_type_id_t      type_id  SIXTRL_ALIGN( 8u );
+        ::NS(object_type_id_t)   type_id  SIXTRL_ALIGN( 8u );
         int32_t                  a        SIXTRL_ALIGN( 8u );
         double                   b        SIXTRL_ALIGN( 8u );
         double                   c[ 4 ]   SIXTRL_ALIGN( 8u );
         uint8_t* SIXTRL_RESTRICT d        SIXTRL_ALIGN( 8u );
         double*  SIXTRL_RESTRICT e        SIXTRL_ALIGN( 8u );
 
-        void preset( st_object_type_id_t const type_id =
-            st_object_type_id_t{ 0 } ) SIXTRL_NOEXCEPT
+        void preset( ::NS(object_type_id_t) const type_id =
+            ::NS(object_type_id_t){ 0 } ) SIXTRL_NOEXCEPT
         {
             this->type_id = type_id;
             this->a       = int32_t{ 0 };
@@ -170,7 +171,7 @@ namespace sixtrack
 
 /* ************************************************************************* */
 
-TEST( CXX_CommonBufferTests, InitOnExistingFlatMemory)
+TEST( CXX_Common_Buffer_BufferTests, InitOnExistingFlatMemory)
 {
     namespace st = sixtrack;
 
@@ -194,12 +195,13 @@ TEST( CXX_CommonBufferTests, InitOnExistingFlatMemory)
 
 /* ************************************************************************* */
 
-TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
+TEST( CXX_Common_Buffer_BufferTests,
+      InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
 {
     namespace st = sixtrack;
 
     using my_obj_t  = st::MyObj;
-    using type_id_t = ::st_object_type_id_t;
+    using type_id_t = ::NS(object_type_id_t);
 
     using buffer_t  = st::Buffer;
     using obj_t     = buffer_t::object_t;
@@ -279,11 +281,11 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
 
 
     ASSERT_TRUE( ptr_object != nullptr );
-    ASSERT_TRUE( st_Object_get_type_id( ptr_object ) == obj1.type_id );
-    ASSERT_TRUE( st_Object_get_size( ptr_object ) > sizeof( obj1 ) );
+    ASSERT_TRUE( ::NS(Object_get_type_id)( ptr_object ) == obj1.type_id );
+    ASSERT_TRUE( ::NS(Object_get_size)( ptr_object ) > sizeof( obj1 ) );
 
     sixtrack::MyObj* ptr_stored_obj = reinterpret_cast< sixtrack::MyObj* >(
-       st_Object_get_begin_ptr( ptr_object ) );
+       ::NS(Object_get_begin_ptr)( ptr_object ) );
 
     ASSERT_TRUE( ptr_stored_obj != nullptr );
     ASSERT_TRUE( ptr_stored_obj != &obj1 );
@@ -293,20 +295,20 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
     ASSERT_TRUE( std::fabs( ptr_stored_obj->b - obj1.b ) <=
                  std::numeric_limits< double >::epsilon() );
 
-    for( st_buffer_size_t ii = 0u ; ii < num_c_values ; ++ii )
+    for( ::NS(buffer_size_t) ii = 0u ; ii < num_c_values ; ++ii )
     {
         ASSERT_TRUE( &ptr_stored_obj->c[ ii ] != &obj1.c[ ii ] );
         ASSERT_TRUE( std::fabs( ptr_stored_obj->c[ ii ] - obj1.c[ ii ] )
             <= std::numeric_limits< double >::epsilon() );
     }
 
-    for( st_buffer_size_t ii = 0 ; ii < num_d_values ; ++ii )
+    for( ::NS(buffer_size_t) ii = 0 ; ii < num_d_values ; ++ii )
     {
         ASSERT_TRUE( &ptr_stored_obj->d[ ii ] != &obj1.d[ ii ] );
         ASSERT_TRUE(  ptr_stored_obj->d[ ii ] ==  obj1.d[ ii ] );
     }
 
-    for( st_buffer_size_t ii = 0 ; ii < num_e_values ; ++ii )
+    for( ::NS(buffer_size_t) ii = 0 ; ii < num_e_values ; ++ii )
     {
         ASSERT_TRUE( &ptr_stored_obj->e[ ii ] != &obj1.e[ ii ] );
         ASSERT_TRUE( std::fabs( ptr_stored_obj->e[ ii ] - obj1.e[ ii ] )
@@ -380,7 +382,7 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
 
     ASSERT_TRUE( &ptr_stored_obj->c[ 0 ] != &cmp_obj.c[ 0 ] );
 
-    for( st_buffer_size_t ii = 0u ; ii < num_c_values ; ++ii )
+    for( ::NS(buffer_size_t) ii = 0u ; ii < num_c_values ; ++ii )
     {
         ASSERT_TRUE( std::fabs( ptr_stored_obj->c[ ii ] -
             cmp_obj.c[ ii ] ) <= std::numeric_limits< double >::epsilon() );
@@ -389,12 +391,12 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
     ASSERT_TRUE( ptr_stored_obj->d != nullptr );
     ASSERT_TRUE( ptr_stored_obj->e != nullptr );
 
-    for( st_buffer_size_t ii = 0 ; ii < num_d_values ; ++ii )
+    for( ::NS(buffer_size_t) ii = 0 ; ii < num_d_values ; ++ii )
     {
         ASSERT_TRUE(  ptr_stored_obj->d[ ii ] ==  uint8_t{ 0 } );
     }
 
-    for( st_buffer_size_t ii = 0 ; ii < num_e_values ; ++ii )
+    for( ::NS(buffer_size_t) ii = 0 ; ii < num_e_values ; ++ii )
     {
         ASSERT_TRUE( std::fabs( ptr_stored_obj->e[ ii ] - double{ 0.0 } )
             <= std::numeric_limits< double >::epsilon() );
@@ -475,22 +477,22 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
 
     for( ; obj_it != obj_end ; ++obj_it, ++cmp_obj_it )
     {
-        ASSERT_TRUE( st_Object_get_type_id( obj_it ) ==
-                     st_Object_get_type_id( cmp_obj_it ) );
+        ASSERT_TRUE( ::NS(Object_get_type_id)( obj_it ) ==
+                     ::NS(Object_get_type_id)( cmp_obj_it ) );
 
-        ASSERT_TRUE( st_Object_get_size( obj_it ) ==
-                     st_Object_get_size( cmp_obj_it ) );
+        ASSERT_TRUE( ::NS(Object_get_size)( obj_it ) ==
+                     ::NS(Object_get_size)( cmp_obj_it ) );
 
-        ASSERT_TRUE( st_Object_get_size( obj_it ) > sizeof( st::MyObj ) );
+        ASSERT_TRUE( ::NS(Object_get_size)( obj_it ) > sizeof( st::MyObj ) );
 
-        ASSERT_TRUE( st_Object_get_const_begin_ptr( obj_it ) !=
-                     st_Object_get_const_begin_ptr( cmp_obj_it ) );
+        ASSERT_TRUE( ::NS(Object_get_const_begin_ptr)( obj_it ) !=
+                     ::NS(Object_get_const_begin_ptr)( cmp_obj_it ) );
 
         my_obj_t const* ptr_my_obj = reinterpret_cast< my_obj_t const* >(
-            st_Object_get_const_begin_ptr( obj_it ) );
+            ::NS(Object_get_const_begin_ptr)( obj_it ) );
 
         my_obj_t const* ptr_cmp_obj = reinterpret_cast< my_obj_t const* >(
-            st_Object_get_const_begin_ptr( cmp_obj_it ) );
+            ::NS(Object_get_const_begin_ptr)( cmp_obj_it ) );
 
         ASSERT_TRUE( ptr_my_obj  != nullptr );
         ASSERT_TRUE( ptr_cmp_obj != nullptr );
@@ -501,7 +503,7 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
         ASSERT_TRUE( std::fabs( ptr_cmp_obj->b - ptr_my_obj->b ) <=
                         std::numeric_limits< double >::epsilon() );
 
-        for( st_buffer_size_t ii = 0u ; ii < num_c_values ; ++ii )
+        for( ::NS(buffer_size_t) ii = 0u ; ii < num_c_values ; ++ii )
         {
             ASSERT_TRUE( &ptr_cmp_obj->c[ ii ] != &ptr_my_obj->c[ ii ] );
             ASSERT_TRUE( std::fabs( ptr_cmp_obj->c[ ii ] - ptr_my_obj->c[ ii ] )
@@ -512,7 +514,7 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
         ASSERT_TRUE( ptr_cmp_obj->d != nullptr );
         ASSERT_TRUE( ptr_my_obj->d  != nullptr );
 
-        for( st_buffer_size_t ii = 0 ; ii < num_d_values ; ++ii )
+        for( ::NS(buffer_size_t) ii = 0 ; ii < num_d_values ; ++ii )
         {
             ASSERT_TRUE( ptr_cmp_obj->d[ ii ] == ptr_my_obj->d[ ii ] );
         }
@@ -521,7 +523,7 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
         ASSERT_TRUE( ptr_cmp_obj->e != nullptr );
         ASSERT_TRUE( ptr_my_obj->e  != nullptr );
 
-        for( st_buffer_size_t ii = 0 ; ii < num_e_values ; ++ii )
+        for( ::NS(buffer_size_t) ii = 0 ; ii < num_e_values ; ++ii )
         {
             ASSERT_TRUE( std::fabs( ptr_cmp_obj->e[ ii ] - ptr_my_obj->e[ ii ] )
                 <= std::numeric_limits< double >::epsilon() );
@@ -589,12 +591,12 @@ TEST( CXX_CommonBufferTests, InitFlatMemoryDataStoreAddObjectsRemapAndCompare )
 
 /* ************************************************************************* */
 
-TEST( CXX_CommonBufferTests, ReconstructFromCObjectFile )
+TEST( CXX_Common_Buffer_BufferTests, ReconstructFromCObjectFile )
 {
     namespace st = sixtrack;
 
     using my_obj_t  = st::MyObj;
-    using type_id_t = ::st_object_type_id_t;
+    using type_id_t = ::NS(object_type_id_t);
 
     using buffer_t  = st::Buffer;
     using obj_t     = buffer_t::object_t;
@@ -645,10 +647,10 @@ TEST( CXX_CommonBufferTests, ReconstructFromCObjectFile )
         ASSERT_TRUE( fp != nullptr );
 
         constexpr size_t NUM_DATAPTRS_PER_OBJ = size_t{ 2u };
-        constexpr size_t NUM_SLOTS            = size_t{ 48u };
-        constexpr size_t NUM_OBJECTS          = size_t{ 3u };
-        constexpr size_t NUM_DATAPTRS         = NUM_OBJECTS * NUM_DATAPTRS_PER_OBJ;
-        constexpr size_t NUM_GARBAGE_RANGES   = size_t{ 1u };
+        constexpr size_t NUM_SLOTS    = size_t{ 48u };
+        constexpr size_t NUM_OBJECTS  = size_t{ 3u };
+        constexpr size_t NUM_DATAPTRS = NUM_OBJECTS * NUM_DATAPTRS_PER_OBJ;
+        constexpr size_t NUM_GARBAGE_RANGES = size_t{ 1u };
 
         size_t const buffer_capacity = st::Buffer::CalculateBufferSize(
             NUM_OBJECTS, NUM_SLOTS, NUM_DATAPTRS, NUM_GARBAGE_RANGES );
@@ -658,7 +660,7 @@ TEST( CXX_CommonBufferTests, ReconstructFromCObjectFile )
         st::Buffer buffer( data_buffer.data(), NUM_OBJECTS, NUM_SLOTS,
                         NUM_DATAPTRS, NUM_GARBAGE_RANGES, data_buffer.size() );
 
-        /* --------------------------------------------------------------------- */
+        /* ----------------------------------------------------------------- */
 
         my_obj_t* ptr_obj1 = buffer.add< my_obj_t >( obj1_type_id,
             num_d_values, num_e_values, obj1_a, obj1_b, obj1_c, obj1_d, obj1_e );
@@ -666,7 +668,7 @@ TEST( CXX_CommonBufferTests, ReconstructFromCObjectFile )
         ASSERT_TRUE( ptr_obj1 != SIXTRL_NULLPTR );
         ASSERT_TRUE( ptr_obj1->type_id == obj1_type_id );
 
-        /* --------------------------------------------------------------------- */
+        /* ----------------------------------------------------------------- */
 
         my_obj_t* ptr_obj2 = buffer.add< my_obj_t >( obj2_type_id,
             num_d_values, num_e_values, obj2_a, obj2_b, obj2_c, obj2_d, obj2_e );
@@ -674,7 +676,7 @@ TEST( CXX_CommonBufferTests, ReconstructFromCObjectFile )
         ASSERT_TRUE( ptr_obj2 != SIXTRL_NULLPTR );
         ASSERT_TRUE( ptr_obj2->type_id == obj2_type_id );
 
-        /* --------------------------------------------------------------------- */
+        /* ----------------------------------------------------------------- */
 
         my_obj_t* ptr_obj3 = buffer.createNew< my_obj_t >(
             obj3_type_id, num_d_values, num_e_values );
@@ -682,12 +684,12 @@ TEST( CXX_CommonBufferTests, ReconstructFromCObjectFile )
         ASSERT_TRUE( ptr_obj3 != SIXTRL_NULLPTR );
         ASSERT_TRUE( ptr_obj3->type_id == obj3_type_id );
 
-        /* --------------------------------------------------------------------- */
+        /* ----------------------------------------------------------------- */
 
-        st_buffer_size_t const cnt = std::fwrite(
+        ::NS(buffer_size_t) const cnt = std::fwrite(
             buffer.dataBegin< raw_t const* >(), buffer.size(), size_t{ 1 }, fp );
 
-        ASSERT_TRUE( cnt == st_buffer_size_t{ 1 } );
+        ASSERT_TRUE( cnt == ::NS(buffer_size_t){ 1 } );
 
         std::fclose( fp );
         fp = nullptr;
@@ -769,15 +771,15 @@ TEST( CXX_CommonBufferTests, ReconstructFromCObjectFile )
 
     for( ; obj_it != obj_end ; ++obj_it, ++cmp_obj_it )
     {
-        ASSERT_TRUE( st_Object_get_type_id( obj_it ) == cmp_obj_it->type_id );
-        ASSERT_TRUE( st_Object_get_size( obj_it ) > sizeof( st::MyObj ) );
-        ASSERT_TRUE( st_Object_get_const_begin_ptr( obj_it ) != nullptr );
+        ASSERT_TRUE( ::NS(Object_get_type_id)( obj_it ) == cmp_obj_it->type_id );
+        ASSERT_TRUE( ::NS(Object_get_size)( obj_it ) > sizeof( st::MyObj ) );
+        ASSERT_TRUE( ::NS(Object_get_const_begin_ptr)( obj_it ) != nullptr );
 
         st::MyObj const* ptr_my_obj = reinterpret_cast< st::MyObj const* >(
-                st_Object_get_const_begin_ptr( obj_it ) );
+                ::NS(Object_get_const_begin_ptr)( obj_it ) );
 
         ASSERT_TRUE( ptr_my_obj != nullptr );
-        ASSERT_TRUE( ptr_my_obj->type_id == st_Object_get_type_id( obj_it ) );
+        ASSERT_TRUE( ptr_my_obj->type_id == ::NS(Object_get_type_id)( obj_it ) );
 
         ASSERT_TRUE( ptr_my_obj->a == cmp_obj_it->a );
         ASSERT_TRUE( std::fabs( ( ptr_my_obj->b - cmp_obj_it->b ) <
@@ -829,11 +831,11 @@ TEST( CXX_CommonBufferTests, ReconstructFromCObjectFile )
     }
 }
 
-TEST( CXX_CommonBufferTests, NewBufferAndGrowingWithinCapacity )
+TEST( CXX_Common_Buffer_BufferTests, NewBufferAndGrowingWithinCapacity )
 {
     namespace st = sixtrack;
 
-    using type_id_t = ::st_object_type_id_t;
+    using type_id_t = ::NS(object_type_id_t);
     using buffer_t  = st::Buffer;
     using size_t    = buffer_t::size_type;
 
@@ -908,9 +910,10 @@ TEST( CXX_CommonBufferTests, NewBufferAndGrowingWithinCapacity )
     ASSERT_TRUE( ptr_obj2->type_id == obj2_type_id );
     ASSERT_TRUE( ptr_obj2->a       == obj2_a );
 
+    ASSERT_TRUE( buffer.getNumSlots() > num_slots_after_obj1 );
     ASSERT_TRUE( buffer.getNumObjects()  == size_t{ 2 } );
-    ASSERT_TRUE( buffer.getNumDataptrs() == size_t{ 2 } * NUM_DATAPTRS_PER_OBJ );
-    ASSERT_TRUE( buffer.getNumSlots()    >  num_slots_after_obj1 );
+    ASSERT_TRUE( buffer.getNumDataptrs() == size_t{ 2 } *
+        NUM_DATAPTRS_PER_OBJ );
 
     size_t const num_slots_after_obj2 = buffer.getNumSlots();
 
@@ -924,19 +927,20 @@ TEST( CXX_CommonBufferTests, NewBufferAndGrowingWithinCapacity )
     ASSERT_TRUE( ptr_obj3 != nullptr );
     ASSERT_TRUE( ptr_obj3->type_id == obj3_type_id );
 
-    ASSERT_TRUE( buffer.getNumObjects()  == size_t{ 3 } );
-    ASSERT_TRUE( buffer.getNumDataptrs() == size_t{ 3 } * NUM_DATAPTRS_PER_OBJ );
-    ASSERT_TRUE( buffer.getNumSlots()    >  num_slots_after_obj2 );
+    ASSERT_TRUE( buffer.getNumObjects() == size_t{ 3 } );
+    ASSERT_TRUE( buffer.getNumDataptrs() ==
+                 size_t{ 3 } * NUM_DATAPTRS_PER_OBJ );
+    ASSERT_TRUE( buffer.getNumSlots() >  num_slots_after_obj2 );
 }
 
-TEST( CXX_CommonBufferTests, AddGenericObjectsTestAutoGrowingOfBuffer )
+TEST( CXX_Common_Buffer_BufferTests, AddGenericObjectsTestAutoGrowingOfBuffer )
 {
     namespace st = sixtrack;
 
     using buf_size_t    = st::Buffer::size_type;
     using type_id_t     = st::Buffer::type_id_t;
-    using generic_obj_t = ::st_GenericObj;
-    using index_obj_t   = ::st_Object;
+    using generic_obj_t = ::NS(GenericObj);
+    using index_obj_t   = ::NS(Object);
 
     st::Buffer buffer;
 
@@ -994,8 +998,8 @@ TEST( CXX_CommonBufferTests, AddGenericObjectsTestAutoGrowingOfBuffer )
                 NUM_DATAPTRS, offsets, sizes, counts );
 
         ASSERT_TRUE( index_obj != nullptr );
-        ASSERT_TRUE( ::st_Object_get_type_id( index_obj )   == temp.type_id );
-        ASSERT_TRUE( ::st_Object_get_begin_ptr( index_obj ) != nullptr );
+        ASSERT_TRUE( ::NS(Object_get_type_id)( index_obj )   == temp.type_id );
+        ASSERT_TRUE( ::NS(Object_get_begin_ptr)( index_obj ) != nullptr );
 
         buf_size_t const capacity = buffer.capacity();
         buf_size_t const size     = buffer.size();
@@ -1023,7 +1027,7 @@ TEST( CXX_CommonBufferTests, AddGenericObjectsTestAutoGrowingOfBuffer )
     ASSERT_TRUE( buffer.getNumObjects() == NUM_OBJECTS_TO_ADD );
 }
 
-TEST( CXX_CommonBufferTests, DumpToFileConstructFromDumpCompare)
+TEST( CXX_Common_Buffer_BufferTests, DumpToFileConstructFromDumpCompare)
 {
     namespace st = sixtrack;
 
@@ -1031,7 +1035,7 @@ TEST( CXX_CommonBufferTests, DumpToFileConstructFromDumpCompare)
     using prng_seed_t = unsigned long long;
 
     prng_seed_t const seed = prng_seed_t{ 20181105 };
-    ::st_Random_init_genrand64( seed );
+    ::NS(Random_init_genrand64)( seed );
 
     st::Buffer buffer;
 
@@ -1041,14 +1045,14 @@ TEST( CXX_CommonBufferTests, DumpToFileConstructFromDumpCompare)
 
     for( buf_size_t ii = buf_size_t{ 0 } ; ii < NUM_OBJECTS ; ++ii )
     {
-        ::st_object_type_id_t const type_id =
-            static_cast< ::st_object_type_id_t >( ii );
+        ::NS(object_type_id_t) const type_id =
+            static_cast< ::NS(object_type_id_t) >( ii );
 
-        ::st_GenericObj* obj = ::st_GenericObj_new(
+        ::NS(GenericObj)* obj = ::NS(GenericObj_new)(
                 &buffer, type_id, num_d_values, num_e_values );
 
         ASSERT_TRUE( obj != nullptr );
-        ::st_GenericObj_init_random( obj );
+        ::NS(GenericObj_init_random)( obj );
     }
 
     ASSERT_TRUE( buffer.size()           >  buf_size_t{ 0 } );
@@ -1072,11 +1076,12 @@ TEST( CXX_CommonBufferTests, DumpToFileConstructFromDumpCompare)
         ASSERT_TRUE( restored_ptr != nullptr );
         ASSERT_TRUE( restored_ptr != orig_ptr );
 
-        ::st_GenericObj const* orig_obj = reinterpret_cast<
-            ::st_GenericObj const* >( ::st_Object_get_const_begin_ptr( orig_ptr ) );
+        ::NS(GenericObj) const* orig_obj = reinterpret_cast<
+            ::NS(GenericObj) const* >(
+                ::NS(Object_get_const_begin_ptr)( orig_ptr ) );
 
-        ::st_GenericObj const* restored_obj = reinterpret_cast<
-            ::st_GenericObj const* >( ::st_Object_get_const_begin_ptr(
+        ::NS(GenericObj) const* restored_obj = reinterpret_cast<
+            ::NS(GenericObj) const* >( ::NS(Object_get_const_begin_ptr)(
                 restored_ptr ) );
 
         ASSERT_TRUE( orig_obj != nullptr );
@@ -1084,8 +1089,9 @@ TEST( CXX_CommonBufferTests, DumpToFileConstructFromDumpCompare)
         ASSERT_TRUE( restored_obj != orig_obj );
 
         ASSERT_TRUE(
-            ( 0 == ::st_GenericObj_compare_values( orig_obj, restored_obj ) ) ||
-            ( 0 == ::st_GenericObj_compare_values_with_treshold(
+            ( 0 == ::NS(GenericObj_compare_values)(
+                orig_obj, restored_obj ) ) ||
+            ( 0 == ::NS(GenericObj_compare_values_with_treshold)(
                 orig_obj, restored_obj, ABS_TRESHOLD ) ) );
     }
 
@@ -1093,7 +1099,7 @@ TEST( CXX_CommonBufferTests, DumpToFileConstructFromDumpCompare)
 }
 
 
-TEST( CXX_CommonBufferTests, WriteBufferNormalizedAddrRestoreVerify )
+TEST( CXX_Common_Buffer_BufferTests, WriteBufferNormalizedAddrRestoreVerify )
 {
     namespace st = sixtrack;
 
@@ -1102,7 +1108,7 @@ TEST( CXX_CommonBufferTests, WriteBufferNormalizedAddrRestoreVerify )
     using prng_seed_t = unsigned long long;
 
     prng_seed_t const seed = prng_seed_t{ 20181105 };
-    ::st_Random_init_genrand64( seed );
+    ::NS(Random_init_genrand64)( seed );
 
     st::Buffer cmp_buffer;
     st::Buffer temp_buffer;
@@ -1113,16 +1119,16 @@ TEST( CXX_CommonBufferTests, WriteBufferNormalizedAddrRestoreVerify )
 
     for( buf_size_t ii = buf_size_t{ 0 } ; ii < NUM_OBJECTS ; ++ii )
     {
-        ::st_object_type_id_t const type_id =
-            static_cast< ::st_object_type_id_t >( ii );
+        ::NS(object_type_id_t) const type_id =
+            static_cast< ::NS(object_type_id_t) >( ii );
 
-        ::st_GenericObj* obj = ::st_GenericObj_new(
+        ::NS(GenericObj)* obj = ::NS(GenericObj_new)(
                 &cmp_buffer, type_id, num_d_values, num_e_values );
 
         ASSERT_TRUE( obj != nullptr );
-        ::st_GenericObj_init_random( obj );
+        ::NS(GenericObj_init_random)( obj );
 
-        ::st_GenericObj* copy_obj = ::st_GenericObj_add_copy(
+        ::NS(GenericObj)* copy_obj = ::NS(GenericObj_add_copy)(
                 &temp_buffer, obj );
 
         ASSERT_TRUE( copy_obj != nullptr );
@@ -1144,19 +1150,21 @@ TEST( CXX_CommonBufferTests, WriteBufferNormalizedAddrRestoreVerify )
         ASSERT_TRUE( copy_ptr != nullptr );
         ASSERT_TRUE( copy_ptr != orig_ptr );
 
-        ::st_GenericObj const* orig_obj = reinterpret_cast<
-            ::st_GenericObj const* >( ::st_Object_get_const_begin_ptr( orig_ptr ) );
+        ::NS(GenericObj) const* orig_obj = reinterpret_cast<
+            ::NS(GenericObj) const* >(
+                ::NS(Object_get_const_begin_ptr)( orig_ptr ) );
 
-        ::st_GenericObj const* copy_obj = reinterpret_cast<
-            ::st_GenericObj const* >( ::st_Object_get_const_begin_ptr( copy_ptr ) );
+        ::NS(GenericObj) const* copy_obj = reinterpret_cast<
+            ::NS(GenericObj) const* >(
+                ::NS(Object_get_const_begin_ptr)( copy_ptr ) );
 
         ASSERT_TRUE( orig_obj != nullptr );
         ASSERT_TRUE( copy_obj != nullptr );
         ASSERT_TRUE( copy_obj != orig_obj );
 
         ASSERT_TRUE(
-            ( 0 == ::st_GenericObj_compare_values( orig_obj, copy_obj ) ) ||
-            ( 0 == ::st_GenericObj_compare_values_with_treshold(
+            ( 0 == ::NS(GenericObj_compare_values)( orig_obj, copy_obj ) ) ||
+            ( 0 == ::NS(GenericObj_compare_values_with_treshold)(
                 orig_obj, copy_obj, ABS_TRESHOLD ) ) );
     }
 
@@ -1188,19 +1196,21 @@ TEST( CXX_CommonBufferTests, WriteBufferNormalizedAddrRestoreVerify )
         ASSERT_TRUE( copy_ptr != nullptr );
         ASSERT_TRUE( copy_ptr != orig_ptr );
 
-        ::st_GenericObj const* orig_obj = reinterpret_cast<
-            ::st_GenericObj const* >( ::st_Object_get_const_begin_ptr( orig_ptr ) );
+        ::NS(GenericObj) const* orig_obj = reinterpret_cast<
+            ::NS(GenericObj) const* >(
+                ::NS(Object_get_const_begin_ptr)( orig_ptr ) );
 
-        ::st_GenericObj const* copy_obj = reinterpret_cast<
-            ::st_GenericObj const* >( ::st_Object_get_const_begin_ptr( copy_ptr ) );
+        ::NS(GenericObj) const* copy_obj = reinterpret_cast<
+            ::NS(GenericObj) const* >(
+                ::NS(Object_get_const_begin_ptr)( copy_ptr ) );
 
         ASSERT_TRUE( orig_obj != nullptr );
         ASSERT_TRUE( copy_obj != nullptr );
         ASSERT_TRUE( copy_obj != orig_obj );
 
         ASSERT_TRUE(
-            ( 0 == ::st_GenericObj_compare_values( orig_obj, copy_obj ) ) ||
-            ( 0 == ::st_GenericObj_compare_values_with_treshold(
+            ( 0 == ::NS(GenericObj_compare_values)( orig_obj, copy_obj ) ) ||
+            ( 0 == ::NS(GenericObj_compare_values_with_treshold)(
                 orig_obj, copy_obj, ABS_TRESHOLD ) ) );
     }
 
@@ -1240,23 +1250,25 @@ TEST( CXX_CommonBufferTests, WriteBufferNormalizedAddrRestoreVerify )
         ASSERT_TRUE( rest_ptr != nullptr );
         ASSERT_TRUE( rest_ptr != orig_ptr );
 
-        ::st_GenericObj const* orig_obj = reinterpret_cast<
-            ::st_GenericObj const* >( ::st_Object_get_const_begin_ptr( orig_ptr ) );
+        ::NS(GenericObj) const* orig_obj = reinterpret_cast<
+            ::NS(GenericObj) const* >(
+                ::NS(Object_get_const_begin_ptr)( orig_ptr ) );
 
-        ::st_GenericObj const* rest_obj = reinterpret_cast<
-            ::st_GenericObj const* >( ::st_Object_get_const_begin_ptr( rest_ptr ) );
+        ::NS(GenericObj) const* rest_obj = reinterpret_cast<
+            ::NS(GenericObj) const* >(
+                ::NS(Object_get_const_begin_ptr)( rest_ptr ) );
 
         ASSERT_TRUE( orig_obj != nullptr );
         ASSERT_TRUE( rest_obj != nullptr );
         ASSERT_TRUE( rest_obj != orig_obj );
 
         ASSERT_TRUE(
-            ( 0 == ::st_GenericObj_compare_values( orig_obj, rest_obj ) ) ||
-            ( 0 == ::st_GenericObj_compare_values_with_treshold(
+            ( 0 == ::NS(GenericObj_compare_values)( orig_obj, rest_obj ) ) ||
+            ( 0 == ::NS(GenericObj_compare_values_with_treshold)(
                 orig_obj, rest_obj, ABS_TRESHOLD ) ) );
     }
 }
 
 /* ************************************************************************* */
 
-/* end: tests/sixtracklib/common/test_buffer_cxx.cpp */
+/* end: tests/sixtracklib/common/buffer/test_buffer_cxx.cpp */
diff --git a/tests/sixtracklib/common/test_buffer_string_object_c99.cpp b/tests/sixtracklib/common/buffer/test_buffer_string_object_c99.cpp
similarity index 95%
rename from tests/sixtracklib/common/test_buffer_string_object_c99.cpp
rename to tests/sixtracklib/common/buffer/test_buffer_string_object_c99.cpp
index c524fff6..3e123b70 100644
--- a/tests/sixtracklib/common/test_buffer_string_object_c99.cpp
+++ b/tests/sixtracklib/common/buffer/test_buffer_string_object_c99.cpp
@@ -15,13 +15,13 @@
 #include "sixtracklib/common/buffer.h"
 #include "sixtracklib/testlib.h"
 
-TEST( C99_CommonBufferStringObjectTests, BasicUsage )
+TEST( C99_Common_Buffer_BufferStringObjectTests, BasicUsage )
 {
-    using buffer_t     = ::NS(Buffer)*;
-    using buf_size_t   = ::NS(buffer_size_t);
-    using addr_t       = ::NS(buffer_addr_t);
-    using strobj_t     = ::NS(BufferStringObj)*;
-    using object_t     = ::NS(Object);
+    using buffer_t   = ::NS(Buffer)*;
+    using buf_size_t = ::NS(buffer_size_t);
+    using addr_t     = ::NS(buffer_addr_t);
+    using strobj_t   = ::NS(BufferStringObj)*;
+    using object_t   = ::NS(Object);
 
     buffer_t buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
 
@@ -204,4 +204,4 @@ TEST( C99_CommonBufferStringObjectTests, BasicUsage )
     buffer = nullptr;
 }
 
-/* end: tests/sixtracklib/common/test_buffer_string_object_c99.cpp */
+/* end: tests/sixtracklib/common/buffer/test_buffer_string_object_c99.cpp */
diff --git a/tests/sixtracklib/common/test_buffer_string_object_cxx.cpp b/tests/sixtracklib/common/buffer/test_buffer_string_object_cxx.cpp
similarity index 98%
rename from tests/sixtracklib/common/test_buffer_string_object_cxx.cpp
rename to tests/sixtracklib/common/buffer/test_buffer_string_object_cxx.cpp
index 16865b9c..6cfe00ae 100644
--- a/tests/sixtracklib/common/test_buffer_string_object_cxx.cpp
+++ b/tests/sixtracklib/common/buffer/test_buffer_string_object_cxx.cpp
@@ -14,7 +14,7 @@
 #include "sixtracklib/common/buffer/buffer_string_object.hpp"
 #include "sixtracklib/testlib.h"
 
-TEST( CXX_CommonBufferStringObjectTests, BasicUsage )
+TEST( CXX_Common_Buffer_BufferStringObjectTests, BasicUsage )
 {
     namespace st = SIXTRL_CXX_NAMESPACE;
 
@@ -166,4 +166,4 @@ TEST( CXX_CommonBufferStringObjectTests, BasicUsage )
 }
 
 
-/* end: tests/sixtracklib/common/test_buffer_string_object_cxx.cpp */
+/* end: tests/sixtracklib/common/buffer/test_buffer_string_object_cxx.cpp */
diff --git a/tests/sixtracklib/common/test_managed_buffer_c99.cpp b/tests/sixtracklib/common/buffer/test_managed_buffer_c99.cpp
similarity index 64%
rename from tests/sixtracklib/common/test_managed_buffer_c99.cpp
rename to tests/sixtracklib/common/buffer/test_managed_buffer_c99.cpp
index d5b0b1f0..bc8f523a 100644
--- a/tests/sixtracklib/common/test_managed_buffer_c99.cpp
+++ b/tests/sixtracklib/common/buffer/test_managed_buffer_c99.cpp
@@ -16,9 +16,9 @@
 /* ========================================================================= */
 /* ====  Test flat-memory based minimal buffer implementation                */
 
-TEST( C99_CommonManagedBuffer, InitAndReserve )
+TEST( C99_Common_Buffer_ManagedBufferTests, InitAndReserve )
 {
-    using size_t = ::st_buffer_size_t;
+    using size_t = ::NS(buffer_size_t);
 
     std::vector< unsigned char > data_buffer( size_t{ 4096 }, uint8_t{ 0 } );
     auto begin = data_buffer.data();
@@ -27,14 +27,14 @@ TEST( C99_CommonManagedBuffer, InitAndReserve )
     constexpr size_t const OBJECTS_ID   = size_t{ 4 };
     constexpr size_t const DATAPTRS_ID  = size_t{ 5 };
     constexpr size_t const GARBAGE_ID   = size_t{ 6 };
-    constexpr size_t const slot_size    = st_BUFFER_DEFAULT_SLOT_SIZE;
+    constexpr size_t const slot_size    = ::NS(BUFFER_DEFAULT_SLOT_SIZE);
 
     size_t max_num_objects              = size_t{ 0 };
     size_t max_num_slots                = size_t{ 0 };
     size_t max_num_dataptrs             = size_t{ 0 };
     size_t max_num_garbage_range        = size_t{ 0 };
 
-    size_t predicted_size = st_ManagedBuffer_calculate_buffer_length( begin,
+    size_t predicted_size = ::NS(ManagedBuffer_calculate_buffer_length)( begin,
         max_num_objects, max_num_slots, max_num_dataptrs,
             max_num_garbage_range, slot_size );
 
@@ -42,38 +42,38 @@ TEST( C99_CommonManagedBuffer, InitAndReserve )
 
     size_t current_buffer_size  = size_t{ 0 };
 
-    int success = st_ManagedBuffer_init( begin, &current_buffer_size,
+    int success = ::NS(ManagedBuffer_init)( begin, &current_buffer_size,
         max_num_objects, max_num_slots, max_num_dataptrs,
             max_num_garbage_range, data_buffer.size(), slot_size );
 
     ASSERT_TRUE( success == 0 );
     ASSERT_TRUE( predicted_size == current_buffer_size );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, SLOTS_ID, slot_size ) == max_num_slots );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, OBJECTS_ID, slot_size ) == max_num_objects );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, DATAPTRS_ID, slot_size ) == max_num_dataptrs );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, GARBAGE_ID, slot_size ) == max_num_garbage_range );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, SLOTS_ID, slot_size ) == size_t{ 0 } );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, OBJECTS_ID, slot_size ) == size_t{ 0 } );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, DATAPTRS_ID, slot_size ) == size_t{ 0 } );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, GARBAGE_ID, slot_size ) == size_t{ 0 } );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_buffer_length( begin, slot_size ) ==
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_buffer_length)( begin, slot_size ) ==
         current_buffer_size );
 
     /* -------------------------------------------------------------------- */
@@ -83,50 +83,50 @@ TEST( C99_CommonManagedBuffer, InitAndReserve )
     max_num_dataptrs      = size_t{ 0 };
     max_num_garbage_range = size_t{ 0 };
 
-    predicted_size = st_ManagedBuffer_calculate_buffer_length( begin,
+    predicted_size = ::NS(ManagedBuffer_calculate_buffer_length)( begin,
         max_num_objects, max_num_slots, max_num_dataptrs,
             max_num_garbage_range, slot_size );
 
     ASSERT_TRUE( predicted_size > current_buffer_size );
     ASSERT_TRUE( predicted_size < data_buffer.size()  );
 
-    ASSERT_TRUE( st_ManagedBuffer_can_reserve( begin, &current_buffer_size,
+    ASSERT_TRUE( ::NS(ManagedBuffer_can_reserve)( begin, &current_buffer_size,
         max_num_objects, max_num_slots, max_num_dataptrs,
             max_num_garbage_range, data_buffer.size(), slot_size ) );
 
-    success = st_ManagedBuffer_reserve( begin, &current_buffer_size,
+    success = ::NS(ManagedBuffer_reserve)( begin, &current_buffer_size,
         max_num_objects, max_num_slots, max_num_dataptrs,
             max_num_garbage_range, data_buffer.size(), slot_size );
 
     ASSERT_TRUE( success == 0 );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, SLOTS_ID, slot_size ) == max_num_slots );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, OBJECTS_ID, slot_size ) == max_num_objects );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, DATAPTRS_ID, slot_size ) == max_num_dataptrs );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, GARBAGE_ID, slot_size ) == max_num_garbage_range );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, SLOTS_ID, slot_size ) == size_t{ 0 } );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, OBJECTS_ID, slot_size ) == size_t{ 0 } );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, DATAPTRS_ID, slot_size ) == size_t{ 0 } );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, GARBAGE_ID, slot_size ) == size_t{ 0 } );
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    using address_t     = ::st_buffer_addr_t;
+    using address_t     = ::NS(buffer_addr_t);
     using ptr_to_addr_t = address_t*;
 
     std::vector< address_t >  cmp_slot_values( max_num_slots, address_t{ 0 } );
@@ -134,7 +134,7 @@ TEST( C99_CommonManagedBuffer, InitAndReserve )
     address_t cnt = address_t{ 0 };
 
     ptr_to_addr_t slot_it = reinterpret_cast< ptr_to_addr_t >(
-        st_ManagedBuffer_get_ptr_to_section_data(
+        ::NS(ManagedBuffer_get_ptr_to_section_data)(
             begin, SLOTS_ID, slot_size ) );
 
     ptr_to_addr_t slot_end = slot_it;
@@ -148,19 +148,19 @@ TEST( C99_CommonManagedBuffer, InitAndReserve )
         *cmp_slot_it = cnt;
     }
 
-    st_ManagedBuffer_set_section_num_entities(
+    ::NS(ManagedBuffer_set_section_num_entities)(
         begin, SLOTS_ID, max_num_slots, slot_size );
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
-    using type_id_t     = ::st_object_type_id_t;
-    using object_t      = ::st_Object;
+    using type_id_t     = ::NS(object_type_id_t);
+    using object_t      = ::NS(Object);
     using ptr_to_obj_t  = object_t*;
 
     std::vector< object_t > cmp_object_values( max_num_objects, object_t{} );
 
     ptr_to_obj_t obj_it  = reinterpret_cast< ptr_to_obj_t >(
-        st_ManagedBuffer_get_ptr_to_section_data(
+        ::NS(ManagedBuffer_get_ptr_to_section_data)(
             begin, OBJECTS_ID, slot_size ) );
 
     ptr_to_obj_t  obj_end = obj_it;
@@ -173,28 +173,28 @@ TEST( C99_CommonManagedBuffer, InitAndReserve )
 
     for( ; obj_it != obj_end ; ++obj_it, ++type_id, ++cmp_obj_it )
     {
-        st_Object_preset( obj_it );
-        st_Object_set_type_id( obj_it, type_id );
-        st_Object_set_size( obj_it, size );
+        ::NS(Object_preset)( obj_it );
+        ::NS(Object_set_type_id)( obj_it, type_id );
+        ::NS(Object_set_size)( obj_it, size );
 
         *cmp_obj_it = *obj_it;
     }
 
-    st_ManagedBuffer_set_section_num_entities(
+    ::NS(ManagedBuffer_set_section_num_entities)(
         begin, OBJECTS_ID, max_num_objects, slot_size );
 
     /* -------------------------------------------------------------------- */
 
-    size_t cur_num_objects  = st_ManagedBuffer_get_section_num_entities(
+    size_t cur_num_objects  = ::NS(ManagedBuffer_get_section_num_entities)(
         begin, OBJECTS_ID, slot_size );
 
-    size_t cur_num_slots    = st_ManagedBuffer_get_section_num_entities(
+    size_t cur_num_slots    = ::NS(ManagedBuffer_get_section_num_entities)(
         begin, SLOTS_ID, slot_size );
 
-    size_t cur_num_dataptrs = st_ManagedBuffer_get_section_num_entities(
+    size_t cur_num_dataptrs = ::NS(ManagedBuffer_get_section_num_entities)(
         begin, DATAPTRS_ID, slot_size );
 
-    size_t cur_num_garbage_range = st_ManagedBuffer_get_section_num_entities(
+    size_t cur_num_garbage_range = ::NS(ManagedBuffer_get_section_num_entities)(
         begin, GARBAGE_ID, slot_size );
 
     max_num_objects       += size_t{ 2 };
@@ -202,60 +202,60 @@ TEST( C99_CommonManagedBuffer, InitAndReserve )
     max_num_dataptrs      += size_t{ 4 };
     max_num_garbage_range += size_t{ 1 };
 
-    predicted_size = st_ManagedBuffer_calculate_buffer_length( begin,
+    predicted_size = ::NS(ManagedBuffer_calculate_buffer_length)( begin,
         max_num_objects, max_num_slots, max_num_dataptrs,
             max_num_garbage_range, slot_size );
 
     ASSERT_TRUE( predicted_size > current_buffer_size );
     ASSERT_TRUE( predicted_size < data_buffer.size()  );
 
-    ASSERT_TRUE( st_ManagedBuffer_can_reserve( begin, &current_buffer_size,
+    ASSERT_TRUE( ::NS(ManagedBuffer_can_reserve)( begin, &current_buffer_size,
         max_num_objects, max_num_slots, max_num_dataptrs,
             max_num_garbage_range, data_buffer.size(), slot_size ) );
 
-    success = st_ManagedBuffer_reserve( begin, &current_buffer_size,
+    success = ::NS(ManagedBuffer_reserve)( begin, &current_buffer_size,
         max_num_objects, max_num_slots, max_num_dataptrs,
             max_num_garbage_range, data_buffer.size(), slot_size );
 
     ASSERT_TRUE( success == 0 );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, SLOTS_ID, slot_size ) == max_num_slots );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, OBJECTS_ID, slot_size ) == max_num_objects );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, DATAPTRS_ID, slot_size ) == max_num_dataptrs );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_max_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_max_num_entities)(
         begin, GARBAGE_ID, slot_size ) == max_num_garbage_range );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, SLOTS_ID, slot_size ) == cur_num_slots );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, OBJECTS_ID, slot_size ) == cur_num_objects );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, DATAPTRS_ID, slot_size ) == cur_num_dataptrs );
 
-    ASSERT_TRUE( st_ManagedBuffer_get_section_num_entities(
+    ASSERT_TRUE( ::NS(ManagedBuffer_get_section_num_entities)(
         begin, GARBAGE_ID, slot_size ) == cur_num_garbage_range );
 
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
     slot_it = reinterpret_cast< ptr_to_addr_t >(
-        st_ManagedBuffer_get_ptr_to_section_data(
+        ::NS(ManagedBuffer_get_ptr_to_section_data)(
             begin, SLOTS_ID, slot_size ) );
 
     slot_end = reinterpret_cast< ptr_to_addr_t >(
-        st_ManagedBuffer_get_ptr_to_section_end(
+        ::NS(ManagedBuffer_get_ptr_to_section_end)(
             begin, SLOTS_ID, slot_size ) );
 
     ASSERT_TRUE( std::distance( slot_it, slot_end ) ==
         static_cast< std::ptrdiff_t >(
-            st_ManagedBuffer_get_section_num_entities(
+            ::NS(ManagedBuffer_get_section_num_entities)(
                 begin, SLOTS_ID, slot_size ) ) );
 
     cmp_slot_it = cmp_slot_values.begin();
@@ -268,32 +268,32 @@ TEST( C99_CommonManagedBuffer, InitAndReserve )
     /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 
     obj_it  = reinterpret_cast< ptr_to_obj_t >(
-        st_ManagedBuffer_get_ptr_to_section_data(
+        ::NS(ManagedBuffer_get_ptr_to_section_data)(
             begin, OBJECTS_ID, slot_size ) );
 
     obj_end = reinterpret_cast< ptr_to_obj_t >(
-        st_ManagedBuffer_get_ptr_to_section_end(
+        ::NS(ManagedBuffer_get_ptr_to_section_end)(
             begin, OBJECTS_ID, slot_size ) );
 
     ASSERT_TRUE( std::distance( obj_it, obj_end ) ==
         static_cast< std::ptrdiff_t >(
-            st_ManagedBuffer_get_section_num_entities(
+            ::NS(ManagedBuffer_get_section_num_entities)(
                 begin, OBJECTS_ID, slot_size ) ) );
 
     cmp_obj_it = cmp_object_values.begin();
 
     for( ; obj_it != obj_end ; ++obj_it, ++type_id, ++cmp_obj_it )
     {
-        ASSERT_TRUE( st_Object_get_type_id( obj_it ) ==
-                     st_Object_get_type_id( &( *cmp_obj_it ) ) );
+        ASSERT_TRUE( ::NS(Object_get_type_id)( obj_it ) ==
+                     ::NS(Object_get_type_id)( &( *cmp_obj_it ) ) );
 
-        ASSERT_TRUE( st_Object_get_size( obj_it ) ==
-                     st_Object_get_size( &( *cmp_obj_it ) ) );
+        ASSERT_TRUE( ::NS(Object_get_size)( obj_it ) ==
+                     ::NS(Object_get_size)( &( *cmp_obj_it ) ) );
 
-        ASSERT_TRUE( st_Object_get_begin_addr( obj_it ) ==
-                     st_Object_get_begin_addr( &( *cmp_obj_it ) ) );
+        ASSERT_TRUE( ::NS(Object_get_begin_addr)( obj_it ) ==
+                     ::NS(Object_get_begin_addr)( &( *cmp_obj_it ) ) );
     }
 }
 
 /* ------------------------------------------------------------------------- */
-/* end: tests/sixtracklib/common/test_managed_buffer_c99.cpp */
+/* end: tests/sixtracklib/common/buffer/test_managed_buffer_c99.cpp */
diff --git a/tests/sixtracklib/common/buffer/test_mem_pool_c99.cpp b/tests/sixtracklib/common/buffer/test_mem_pool_c99.cpp
new file mode 100644
index 00000000..414bf731
--- /dev/null
+++ b/tests/sixtracklib/common/buffer/test_mem_pool_c99.cpp
@@ -0,0 +1,381 @@
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer/mem_pool.h"
+
+/* ========================================================================== */
+/* ====  Test basic usage of MemPool: init and free operations */
+
+TEST( C99_Common_Buffer_MemPoolTests, InitFreeBasic )
+{
+    ::NS(MemPool) mem_pool;
+
+    /* --------------------------------------------------------------------- */
+    /* Test the "happy path": capacity and chunk_size are compatible */
+
+    std::size_t const capacity = std::size_t{64};
+    std::size_t const chunk_size = std::size_t{8};
+
+    ::NS(MemPool_init)( &mem_pool, capacity, chunk_size );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool )  != nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool )   >= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool )       == std::size_t{0} );
+
+    ::NS(MemPool_free)( &mem_pool );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool )  == nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool )   == std::size_t{0} );
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == std::size_t{0} );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool )       == std::size_t{0} );
+}
+
+/* ========================================================================== */
+/* ====  Test handling of odd-sized but admissible capacities */
+
+TEST( C99_Common_Buffer_MemPoolTests, InitFreeNonIntegerNumChunks )
+{
+    ::NS(MemPool) mem_pool;
+
+    /* --------------------------------------------------------------------- */
+    /* Test how the MemoryPool operates if the capacity is not an integer
+     * multiple of the chunk size: */
+
+    std::size_t const capacity = std::size_t{62};
+    std::size_t const chunk_size = std::size_t{8};
+
+    static std::size_t const ZERO_SIZE = std::size_t{0};
+
+    ::NS(MemPool_init)( &mem_pool, capacity, chunk_size );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool ) != nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool ) >= capacity );
+
+    ASSERT_TRUE( ZERO_SIZE ==
+                 ( ::NS(MemPool_get_capacity)( &mem_pool ) % chunk_size ) );
+
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) == std::size_t{0} );
+
+    ::NS(MemPool_free)( &mem_pool );
+}
+
+/* ========================================================================== */
+/* ====  Test handling of pathological zero-sized capacities*/
+
+TEST( C99_Common_Buffer_MemPoolTests, InitFreeZeroCapacityNonZeroChunk )
+{
+    ::NS(MemPool) mem_pool;
+
+    /* --------------------------------------------------------------------- */
+    /* Test how the MemoryPool operates if the capacity is not an integer
+     * multiple of the chunk size: */
+
+    std::size_t const capacity = std::size_t{0};
+    std::size_t const chunk_size = std::size_t{8};
+
+    ::NS(MemPool_init)( &mem_pool, capacity, chunk_size );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool ) != nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool ) >= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool ) >= chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) == std::size_t{0} );
+
+    ::NS(MemPool_free)( &mem_pool );
+}
+
+/* ========================================================================== */
+/* ====  Happy-Path-Testing of adding blocks aligned and non-aligned */
+
+TEST( C99_Common_Buffer_MemPoolTests, AppendSuccess )
+{
+    ::NS(MemPool) mem_pool;
+
+    std::size_t const chunk_size = std::size_t{8u};
+    std::size_t const capacity = 12 * chunk_size;
+
+    ::NS(MemPool_init)( &mem_pool, capacity, chunk_size );
+
+    /* --------------------------------------------------------------------- */
+    std::size_t num_bytes_to_add = std::size_t{2} * chunk_size;
+    std::size_t expected_length = num_bytes_to_add;
+    uint64_t expected_offset = uint64_t{0};
+
+    ::NS(AllocResult)
+    result = ::NS(MemPool_append)( &mem_pool, num_bytes_to_add );
+
+    ASSERT_TRUE( ::NS(AllocResult_valid)( &result ) );
+    ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result ) == expected_offset );
+    ASSERT_TRUE( ::NS(AllocResult_get_length)( &result ) == expected_length );
+
+    /* --------------------------------------------------------------------- */
+
+    num_bytes_to_add = ( chunk_size >> 1 );
+    expected_length  =   chunk_size;
+    expected_offset  = ::NS(AllocResult_get_offset)( &result )
+                     + ::NS(AllocResult_get_length)( &result );
+
+    result = ::NS(MemPool_append)( &mem_pool, num_bytes_to_add );
+
+    ASSERT_TRUE( ::NS(AllocResult_valid)( &result ) );
+    ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result ) >= expected_offset );
+    ASSERT_TRUE( ::NS(AllocResult_get_length)( &result ) == expected_length );
+
+    /* --------------------------------------------------------------------- */
+
+    std::size_t alignment = chunk_size << 1;
+    num_bytes_to_add = chunk_size << 2;
+    expected_length  = num_bytes_to_add;
+    expected_offset  = ::NS(AllocResult_get_offset)( &result )
+                     + ::NS(AllocResult_get_length)( &result );
+
+    result = ::NS(MemPool_append_aligned)( &mem_pool, num_bytes_to_add,
+                                        alignment );
+
+    ASSERT_TRUE( ::NS(AllocResult_valid)( &result ) );
+    ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result ) >= expected_offset );
+    ASSERT_TRUE( ::NS(AllocResult_get_length)( &result ) == expected_length );
+
+    /* --------------------------------------------------------------------- */
+
+    alignment = chunk_size;
+    num_bytes_to_add = chunk_size << 1;
+    expected_length  = num_bytes_to_add;
+    expected_offset  = ::NS(AllocResult_get_offset)( &result )
+                     + ::NS(AllocResult_get_length)( &result );
+
+    result =
+        ::NS(MemPool_append_aligned)( &mem_pool, num_bytes_to_add, alignment );
+
+    ASSERT_TRUE( ::NS(AllocResult_valid)( &result ) );
+    ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result )  >= expected_offset );
+    ASSERT_TRUE( ::NS(AllocResult_get_length)( &result )  == expected_length );
+
+    /* --------------------------------------------------------------------- */
+
+    expected_offset = ::NS(AllocResult_get_offset)( &result )
+                    + ::NS(AllocResult_get_length)( &result );
+
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) >= expected_offset );
+
+    /* --------------------------------------------------------------------- */
+
+    ::NS(MemPool_clear)( &mem_pool );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool )  != nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool )   >= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool )       == std::size_t{0} );
+
+    /* --------------------------------------------------------------------- */
+
+    ::NS(MemPool_free)( &mem_pool );
+}
+
+/* ========================================================================== */
+
+TEST( C99_Common_Buffer_MemPoolTests, AppendAlignedWithPathologicalAlignment )
+{
+    ::NS(MemPool) mem_pool;
+
+    static std::uintptr_t const ZERO_ALIGN = std::uintptr_t{ 0 };
+    std::size_t const chunk_size = std::size_t{8u};
+
+    /* we will use a pathological alignment here, so make sure the buffer is
+     * large enough! */
+    std::size_t const capacity = chunk_size * chunk_size * std::size_t{ 2 };
+
+    ::NS(MemPool_init)( &mem_pool, capacity, chunk_size );
+
+    unsigned char* ptr_buffer_begin = ::NS(MemPool_get_begin_pos)( &mem_pool );
+    ASSERT_TRUE( ptr_buffer_begin != nullptr );
+
+    std::uintptr_t const buffer_begin_addr =
+        reinterpret_cast< std::uintptr_t >( ptr_buffer_begin );
+
+    ASSERT_TRUE( buffer_begin_addr > ZERO_ALIGN );
+
+    /* --------------------------------------------------------------------- */
+    /* Try to add a non-zero-length block with a "strange" alignment -
+     * it should align to the least common multiple of the provided
+     * alignment and the chunk size to be divisible by both quantities.
+     *
+     * Note that this is potentially very wasteful with memory, so be
+     * advised to avoid this! */
+
+    std::size_t const alignment = chunk_size - std::size_t{ 1 };
+    ::NS(AllocResult) const result =
+        ::NS(MemPool_append_aligned)( &mem_pool, chunk_size, alignment );
+
+    ASSERT_TRUE( ::NS(AllocResult_valid)( &result ) );
+
+    unsigned char* ptr_begin    = ::NS(AllocResult_get_pointer)( &result );
+    uint64_t const block_len    = ::NS(AllocResult_get_length)( &result );
+    uint64_t const block_offset = ::NS(AllocResult_get_offset)( &result );
+
+    ASSERT_TRUE( ptr_begin != nullptr );
+
+    std::uintptr_t const begin_addr =
+        reinterpret_cast< std::uintptr_t >( ptr_begin );
+
+    ASSERT_TRUE( ( block_offset + buffer_begin_addr ) == begin_addr );
+    ASSERT_TRUE( ( begin_addr % chunk_size ) == ZERO_ALIGN );
+    ASSERT_TRUE( ( begin_addr % alignment  ) == ZERO_ALIGN );
+
+
+    ASSERT_TRUE( block_len <= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool ) != nullptr  );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool )  >= capacity );
+
+    ::NS(MemPool_free)( &mem_pool );
+}
+
+/* ========================================================================== */
+/* ====  Test the failing of adding blocks with problematic properties        */
+
+TEST( C99_Common_Buffer_MemPoolTests, AppendFailures )
+{
+    ::NS(MemPool) mem_pool;
+
+    std::size_t const chunk_size = std::size_t{8u};
+    std::size_t const capacity = 8 * chunk_size;
+
+    static std::size_t const ZERO_SIZE = std::size_t{0};
+
+    ::NS(MemPool_init)( &mem_pool, capacity, chunk_size );
+
+    /* --------------------------------------------------------------------- */
+    /* Asked to add a block into an empty MemPool that would exceed capacity */
+
+    std::size_t num_bytes_to_add = std::size_t{10} * chunk_size;
+
+    ::NS(AllocResult)
+    result = ::NS(MemPool_append)( &mem_pool, num_bytes_to_add );
+
+    ASSERT_TRUE( !::NS(AllocResult_valid)( &result ) );
+    ASSERT_TRUE( ::NS(AllocResult_get_pointer)( &result ) == nullptr );
+    ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result ) == uint64_t{0} );
+    ASSERT_TRUE( ::NS(AllocResult_get_length)( &result ) == uint64_t{0} );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool ) != nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool )   >= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) == ZERO_SIZE );
+
+    /* --------------------------------------------------------------------- */
+    /* Add a block successfully - so we can check whether the MemPool keeps
+     * its properties if we insert a block - nonsuccessfully */
+
+    result = ::NS(MemPool_append)( &mem_pool, chunk_size );
+    ASSERT_TRUE( ::NS(AllocResult_valid)( &result ) );
+
+    std::size_t const current_size = ::NS(MemPool_get_size)( &mem_pool );
+
+    /* --------------------------------------------------------------------- */
+    /* Try to add a block with zero bytes length */
+
+    result = ::NS(MemPool_append)( &mem_pool, ZERO_SIZE );
+
+    ASSERT_TRUE( !::NS(AllocResult_valid)( &result ) );
+    ASSERT_TRUE( ::NS(AllocResult_get_pointer)( &result ) == nullptr );
+    ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result ) == uint64_t{0} );
+    ASSERT_TRUE( ::NS(AllocResult_get_length)( &result ) == uint64_t{0} );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool ) != nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool )   >= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) == current_size );
+
+    /* --------------------------------------------------------------------- */
+    /* Try to add a valid block exceeding the number of remaining bytes      */
+
+    std::size_t remaining_bytes =
+        ::NS(MemPool_get_remaining_bytes)( &mem_pool );
+
+    std::size_t const too_large = remaining_bytes + std::size_t{1};
+
+    result = ::NS(MemPool_append)( &mem_pool, too_large );
+
+    ASSERT_TRUE( !::NS(AllocResult_valid)( &result ) );
+    ASSERT_TRUE( ::NS(AllocResult_get_pointer)( &result ) == nullptr );
+    ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result ) == uint64_t{0} );
+    ASSERT_TRUE( ::NS(AllocResult_get_length)( &result ) == uint64_t{0} );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)(  &mem_pool ) != nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)(   &mem_pool ) >= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) == current_size );
+
+    /* --------------------------------------------------------------------- */
+    /* Try to add a valid block fitting in memory but exceeding the capacity
+     * due to too ambitious alignment requirements: */
+
+    /* Step one: find the "too ambitious alignment" values */
+
+    uint64_t const current_offset =
+        ::NS(MemPool_get_next_begin_offset)( &mem_pool, chunk_size );
+
+    ASSERT_TRUE( current_offset != UINT64_MAX );
+
+    std::size_t alignment = ( chunk_size << 1 );
+    std::size_t end_alignment = capacity;
+
+    bool found_alignment_for_test = false;
+
+    for( ; alignment < end_alignment; alignment += chunk_size )
+    {
+        if( ::NS(MemPool_get_next_begin_offset)( &mem_pool, alignment ) >
+            current_offset )
+        {
+            result = ::NS(MemPool_append_aligned)(
+                &mem_pool, remaining_bytes, alignment );
+
+            found_alignment_for_test = true;
+
+            break;
+        }
+    }
+
+    if( found_alignment_for_test )
+    {
+        ASSERT_TRUE( !::NS(AllocResult_valid)( &result ) );
+        ASSERT_TRUE( ::NS(AllocResult_get_pointer)( &result ) == nullptr );
+        ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result ) == uint64_t{0} );
+        ASSERT_TRUE( ::NS(AllocResult_get_length)( &result ) == uint64_t{0} );
+
+        ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool ) != nullptr );
+        ASSERT_TRUE( ::NS(MemPool_get_capacity)(  &mem_pool ) >= capacity );
+        ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+        ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) == current_size );
+    }
+
+    /* Verify that non-aligned insert would work, however: */
+
+    result = ::NS(MemPool_append)( &mem_pool, remaining_bytes );
+
+    ASSERT_TRUE( ::NS(AllocResult_valid)( &result ) );
+    ASSERT_TRUE( ::NS(AllocResult_get_pointer)( &result ) != nullptr );
+    ASSERT_TRUE( ::NS(AllocResult_get_offset)( &result ) == current_size );
+    ASSERT_TRUE( ::NS(AllocResult_get_length)( &result ) == remaining_bytes );
+
+    ASSERT_TRUE( ::NS(MemPool_get_begin_pos)( &mem_pool )!= nullptr );
+    ASSERT_TRUE( ::NS(MemPool_get_capacity)( &mem_pool ) >= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_chunk_size)( &mem_pool ) == chunk_size );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) >= capacity );
+    ASSERT_TRUE( ::NS(MemPool_get_remaining_bytes)( &mem_pool ) == ZERO_SIZE );
+    ASSERT_TRUE( ::NS(MemPool_get_size)( &mem_pool ) ==
+                 ::NS(MemPool_get_capacity)( &mem_pool ) );
+
+    /* --------------------------------------------------------------------- */
+
+    ::NS(MemPool_free)( &mem_pool );
+}
+
+/* end: tests/sixtracklib/common/buffer/test_mem_pool.cpp */
diff --git a/tests/sixtracklib/common/math/CMakeLists.txt b/tests/sixtracklib/common/math/CMakeLists.txt
new file mode 100644
index 00000000..812490c6
--- /dev/null
+++ b/tests/sixtracklib/common/math/CMakeLists.txt
@@ -0,0 +1,43 @@
+if( GTEST_FOUND )
+    set( SIXTRACKL_COMMON_TESTS_DEPEND_ON_TRACKING_TESTDATA )
+
+    set( UNIT_TEST_TARGETS )
+    set( SIXTRACKL_TEST_LIBRARIES ${SIXTRACKL_TEST_LIBRARIES}
+         ${SIXTRACKL_GTEST_LIBRARIES} )
+
+    # ==========================================================================
+    # test_interpol_1d_common_c99:
+
+    add_executable( test_interpol_1d_common_c99 test_interpol_1d_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_interpol_1d_common_c99 )
+    add_test( C99_Common_Math_Interpol1D test_interpol_1d_common_c99 )
+
+    # ==========================================================================
+    # test_qgauss_common_c99:
+
+    add_executable( test_qgauss_common_c99 test_qgauss_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_qgauss_common_c99 )
+    add_test( C99_Common_Math_QGauss test_qgauss_common_c99 )
+
+    # *************************************************************************
+    # Set all properties:
+
+    if( UNIT_TEST_TARGETS )
+        set_property(
+            TARGET ${UNIT_TEST_TARGETS}
+            APPEND PROPERTY INCLUDE_DIRECTORIES
+            $<BUILD_INTERFACE:${SIXTRACKL_GTEST_INCLUDE_DIRS}>
+        )
+
+        set_property( TARGET ${UNIT_TEST_TARGETS}
+                      PROPERTY LINK_LIBRARIES ${SIXTRACKL_TEST_LIBRARIES} )
+
+        set_property( TARGET ${UNIT_TEST_TARGETS} PROPERTY CXX_STANDARD 11 )
+        set_property( TARGET ${UNIT_TEST_TARGETS}
+                      PROPERTY CXX_STANDARD_REQUIRED ON )
+
+        set_property( TARGET ${UNIT_TEST_TARGETS}
+                      APPEND PROPERTY COMPILE_OPTIONS
+                      ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    endif()
+endif()
diff --git a/tests/sixtracklib/common/math/test_interpol_1d_c99.cpp b/tests/sixtracklib/common/math/test_interpol_1d_c99.cpp
new file mode 100644
index 00000000..8e2bbe07
--- /dev/null
+++ b/tests/sixtracklib/common/math/test_interpol_1d_c99.cpp
@@ -0,0 +1,70 @@
+#include "sixtracklib/common/internal/math_interpol.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iomanip>
+#include <cmath>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/internal/math_constants.h"
+#include "sixtracklib/testlib.h"
+
+TEST( C99MathInterpolLinear, BasicUsage )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+
+    std::size_t const NUM_PARTICLES = std::size_t{ 10 };
+    std::vector< double > phi_abscissa(  NUM_PARTICLES, double{ 0 } );
+    std::vector< double > cos_phi( NUM_PARTICLES, double{ 0 } );
+
+    double const phi0  = -( st::MathConst_pi< double >() );
+    double const d_phi = ( st::MathConst_pi< double >() - phi0 ) /
+        static_cast< double >( NUM_PARTICLES - std::size_t{ 1 } );
+
+    for( std::size_t ii = std::size_t{ 0 } ; ii < NUM_PARTICLES ; ++ii )
+    {
+        phi_abscissa[ ii ] = phi0 + d_phi * ii;
+        cos_phi[ ii ] = std::cos( phi_abscissa[ ii ] );
+    }
+
+    std::vector< double > cos_phi_derivative( NUM_PARTICLES, double{ 0 } );
+
+    ASSERT_TRUE( NS(Math_interpol_prepare_equ)( cos_phi_derivative.data(),
+        nullptr, cos_phi.data(), phi0, d_phi, phi_abscissa.size(),
+            NS(MATH_INTERPOL_LINEAR) ) == st::ARCH_STATUS_SUCCESS );
+
+    std::vector< double > temp_values( 6 * NUM_PARTICLES, double{ 0 } );
+
+    ASSERT_TRUE( NS(Math_interpol_prepare_equ)( cos_phi_derivative.data(),
+        temp_values.data(), cos_phi.data(), phi0, d_phi, phi_abscissa.size(),
+            NS(MATH_INTERPOL_CUBIC) ) == st::ARCH_STATUS_SUCCESS );
+
+    double phi = phi0;
+    double const d = double{ 1e-4 };
+
+    while( st::MathConst_pi< double >() > phi )
+    {
+        std::cout << std::setw( 20 ) << phi
+                  << std::setw( 20 )
+                  << ::NS(Math_interpol_y_equ)( phi, phi0, d_phi, cos_phi.data(),
+                        cos_phi_derivative.data(), cos_phi.size(),
+                        ::NS(MATH_INTERPOL_CUBIC) )
+                  << std::setw( 20 )
+                  << ::NS(Math_interpol_yp_equ)( phi, phi0, d_phi, cos_phi.data(),
+                        cos_phi_derivative.data(), cos_phi.size(),
+                        ::NS(MATH_INTERPOL_CUBIC) )
+                  << std::setw( 20 )
+                  << ::NS(Math_interpol_ypp_equ)( phi, phi0, d_phi, cos_phi.data(),
+                        cos_phi_derivative.data(), cos_phi.size(),
+                        ::NS(MATH_INTERPOL_CUBIC) )
+                  << "\r\n";
+
+        phi += d;
+    }
+}
+
+/* end: tests/sixtracklib/common/control/test_node_id_c99.cpp */
diff --git a/tests/sixtracklib/common/math/test_qgauss_c99.cpp b/tests/sixtracklib/common/math/test_qgauss_c99.cpp
new file mode 100644
index 00000000..73d41f65
--- /dev/null
+++ b/tests/sixtracklib/common/math/test_qgauss_c99.cpp
@@ -0,0 +1,111 @@
+#include "sixtracklib/common/internal/math_qgauss.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cmath>
+#include <iostream>
+#include <iomanip>
+#include <limits>
+
+#include <gtest/gtest.h>
+#include "sixtracklib/testlib.h"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/control/definitions.h"
+#include "sixtracklib/common/internal/math_functions.h"
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    namespace tests
+    {
+        template< class T >
+        SIXTRL_STATIC SIXTRL_INLINE SIXTRL_FN T gaussian_dist(
+            T const& x, T const& sigma, T const& mu = T{ 0 } )
+        {
+            namespace st = SIXTRL_CXX_NAMESPACE;
+            SIXTRL_ASSERT( sigma > T{ 0 } );
+            T const scaled_x = ( x - mu ) / sigma;
+            return T{ 1 } / ( sigma * st::sqrt< T >( 2 ) *
+                st::MathConst_sqrt_pi< T >() ) *
+                st::exp< T >( - T{ 0.5 } * scaled_x * scaled_x );
+        }
+    }
+}
+
+TEST( C99CommonMathQGaussian, QGaussianDist )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    using real_t = SIXTRL_REAL_T;
+
+    real_t const q0 = ( real_t )1.0;
+    real_t const sigma_0 = 2.5;
+    real_t const Cq_0 = ::NS(Math_q_gauss_cq)( q0 );
+    static real_t const ABS_TOL = std::numeric_limits< real_t >::max();
+
+    ASSERT_TRUE( Cq_0 > real_t{ 0 } );
+    ASSERT_TRUE( st::abs< real_t >( st::MathConst_sqrt_pi<
+        real_t >() - Cq_0 ) <= ABS_TOL );
+
+    real_t const sqrt_beta_0 =
+        ::NS(Math_q_gauss_sqrt_beta_from_gauss_sigma)( sigma_0 );
+
+    ASSERT_TRUE( sqrt_beta_0 > real_t{ 0 } );
+    ASSERT_TRUE( st::Type_comp_all_are_close< real_t >(
+        sqrt_beta_0 * sqrt_beta_0, real_t{ 1 } / (
+            real_t{ 2 } * sigma_0 * sigma_0 ), real_t{ 0 }, ABS_TOL ) );
+
+    real_t const xmin_0 = -real_t{ 6 } * sigma_0;
+    real_t const xmax_0 = +real_t{ 6 } * sigma_0;
+    real_t const dx_0 = ( xmax_0 - xmin_0 ) / real_t{ 1000 };
+
+    real_t x = xmin_0;
+
+    while( x < xmax_0 )
+    {
+        real_t const gaussian_x = st::tests::gaussian_dist( x, sigma_0 );
+        real_t const q_gaussian_x = ::NS(Math_q_gauss)( x, q0, sqrt_beta_0, Cq_0 );
+
+        ASSERT_TRUE( st::abs< real_t >( gaussian_x - q_gaussian_x ) < ABS_TOL );
+        x += dx_0;
+    }
+
+    /* q < 1 */
+
+    real_t const q1 = real_t{ 3 } / real_t{ 5 };
+    real_t const Cq_1 = ::NS(Math_q_gauss_cq)( q1 );
+    ASSERT_TRUE( Cq_1 > real_t{ 0 } );
+
+    real_t const sqrt_beta_1 = st::sqrt< real_t >( real_t{ 2 } );
+    real_t const xmin_1_support = real_t{ -1 } / st::sqrt< real_t >(
+        sqrt_beta_1 * sqrt_beta_1 * ( real_t{ 1 } - q1 ) );
+
+    real_t const xmax_1_support = real_t{ +1 } / st::sqrt< real_t >(
+        sqrt_beta_1 * sqrt_beta_1 * ( real_t{ 1 } - q1 ) );
+
+    real_t const xmin_1 = real_t{ 2 } * xmin_1_support;
+    real_t const xmax_1 = real_t{ 2 } * xmax_1_support;
+    real_t const dx_1 = ( xmax_1_support - xmin_1_support ) / real_t{ 100 };
+
+    x = xmin_1;
+
+    while( x < xmax_1 )
+    {
+        real_t const q_gauss_x = ::NS(Math_q_gauss)( x, q1, sqrt_beta_1, Cq_1 );
+
+        std::cout << std::setw( 20 ) << x << std::setw( 20 )
+                  << q_gauss_x << "\r\n";
+
+        if( ( x < xmin_1_support ) || ( x > xmax_1_support ) )
+        {
+            ASSERT_TRUE( st::abs< real_t >( q_gauss_x ) <= ABS_TOL );
+        }
+        else
+        {
+            ASSERT_TRUE( q_gauss_x > real_t{ 0 } );
+        }
+
+        x += dx_1;
+    }
+
+    std::cout << std::endl;
+}
diff --git a/tests/sixtracklib/common/test_mem_pool_c99.cpp b/tests/sixtracklib/common/test_mem_pool_c99.cpp
deleted file mode 100644
index dfb046c0..00000000
--- a/tests/sixtracklib/common/test_mem_pool_c99.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-#include <algorithm>
-#include <cstddef>
-#include <cstdint>
-#include <cstdlib>
-
-#include <gtest/gtest.h>
-
-#include "sixtracklib/common/definitions.h"
-#include "sixtracklib/common/buffer/mem_pool.h"
-
-/* ========================================================================== */
-/* ====  Test basic usage of MemPool: init and free operations */
-
-TEST( C99_CommonMemPoolTests, InitFreeBasic )
-{
-    st_MemPool mem_pool;
-
-    /* --------------------------------------------------------------------- */
-    /* Test the "happy path": capacity and chunk_size are compatible */
-
-    std::size_t const capacity = std::size_t{64};
-    std::size_t const chunk_size = std::size_t{8};
-
-    st_MemPool_init( &mem_pool, capacity, chunk_size );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool )  != nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool )   >= capacity );
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool )       == std::size_t{0} );
-
-    st_MemPool_free( &mem_pool );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool )  == nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool )   == std::size_t{0} );
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == std::size_t{0} );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool )       == std::size_t{0} );
-}
-
-/* ========================================================================== */
-/* ====  Test handling of odd-sized but admissible capacities */
-
-TEST( C99_CommonMemPoolTests, InitFreeNonIntegerNumChunks )
-{
-    st_MemPool mem_pool;
-
-    /* --------------------------------------------------------------------- */
-    /* Test how the MemoryPool operates if the capacity is not an integer
-     * multiple of the chunk size: */
-
-    std::size_t const capacity = std::size_t{62};
-    std::size_t const chunk_size = std::size_t{8};
-
-    static std::size_t const ZERO_SIZE = std::size_t{0};
-
-    st_MemPool_init( &mem_pool, capacity, chunk_size );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool ) != nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool ) >= capacity );
-
-    ASSERT_TRUE( ZERO_SIZE ==
-                 ( st_MemPool_get_capacity( &mem_pool ) % chunk_size ) );
-
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool ) == std::size_t{0} );
-
-    st_MemPool_free( &mem_pool );
-}
-
-/* ========================================================================== */
-/* ====  Test handling of pathological zero-sized capacities*/
-
-TEST( C99_CommonMemPoolTests, InitFreeZeroCapacityNonZeroChunk )
-{
-    st_MemPool mem_pool;
-
-    /* --------------------------------------------------------------------- */
-    /* Test how the MemoryPool operates if the capacity is not an integer
-     * multiple of the chunk size: */
-
-    std::size_t const capacity = std::size_t{0};
-    std::size_t const chunk_size = std::size_t{8};
-
-    st_MemPool_init( &mem_pool, capacity, chunk_size );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool ) != nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool ) >= capacity );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool ) >= chunk_size );
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool ) == std::size_t{0} );
-
-    st_MemPool_free( &mem_pool );
-}
-
-/* ========================================================================== */
-/* ====  Happy-Path-Testing of adding blocks aligned and non-aligned */
-
-TEST( C99_CommonMemPoolTests, AppendSuccess )
-{
-    st_MemPool mem_pool;
-
-    std::size_t const chunk_size = std::size_t{8u};
-    std::size_t const capacity = 12 * chunk_size;
-
-    st_MemPool_init( &mem_pool, capacity, chunk_size );
-
-    /* --------------------------------------------------------------------- */
-    std::size_t num_bytes_to_add = std::size_t{2} * chunk_size;
-    std::size_t expected_length = num_bytes_to_add;
-    uint64_t expected_offset = uint64_t{0};
-
-    st_AllocResult
-    result = st_MemPool_append( &mem_pool, num_bytes_to_add );
-
-    ASSERT_TRUE( st_AllocResult_valid( &result ) );
-    ASSERT_TRUE( st_AllocResult_get_offset( &result ) == expected_offset );
-    ASSERT_TRUE( st_AllocResult_get_length( &result ) == expected_length );
-
-    /* --------------------------------------------------------------------- */
-
-    num_bytes_to_add = ( chunk_size >> 1 );
-    expected_length  =   chunk_size;
-    expected_offset  = st_AllocResult_get_offset( &result )
-                     + st_AllocResult_get_length( &result );
-
-    result = st_MemPool_append( &mem_pool, num_bytes_to_add );
-
-    ASSERT_TRUE( st_AllocResult_valid( &result ) );
-    ASSERT_TRUE( st_AllocResult_get_offset( &result ) >= expected_offset );
-    ASSERT_TRUE( st_AllocResult_get_length( &result ) == expected_length );
-
-    /* --------------------------------------------------------------------- */
-
-    std::size_t alignment = chunk_size << 1;
-    num_bytes_to_add = chunk_size << 2;
-    expected_length  = num_bytes_to_add;
-    expected_offset  = st_AllocResult_get_offset( &result )
-                     + st_AllocResult_get_length( &result );
-
-    result = st_MemPool_append_aligned( &mem_pool, num_bytes_to_add,
-                                        alignment );
-
-    ASSERT_TRUE( st_AllocResult_valid( &result ) );
-    ASSERT_TRUE( st_AllocResult_get_offset( &result ) >= expected_offset );
-    ASSERT_TRUE( st_AllocResult_get_length( &result ) == expected_length );
-
-    /* --------------------------------------------------------------------- */
-
-    alignment = chunk_size;
-    num_bytes_to_add = chunk_size << 1;
-    expected_length  = num_bytes_to_add;
-    expected_offset  = st_AllocResult_get_offset( &result )
-                     + st_AllocResult_get_length( &result );
-
-    result =
-        st_MemPool_append_aligned( &mem_pool, num_bytes_to_add, alignment );
-
-    ASSERT_TRUE( st_AllocResult_valid( &result ) );
-    ASSERT_TRUE( st_AllocResult_get_offset( &result )  >= expected_offset );
-    ASSERT_TRUE( st_AllocResult_get_length( &result )  == expected_length );
-
-    /* --------------------------------------------------------------------- */
-
-    expected_offset = st_AllocResult_get_offset( &result )
-                    + st_AllocResult_get_length( &result );
-
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool ) >= expected_offset );
-
-    /* --------------------------------------------------------------------- */
-
-    st_MemPool_clear( &mem_pool );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool )  != nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool )   >= capacity );
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool )       == std::size_t{0} );
-
-    /* --------------------------------------------------------------------- */
-
-    st_MemPool_free( &mem_pool );
-}
-
-/* ========================================================================== */
-
-TEST( C99_CommonMemPoolTests, AppendAlignedWithPathologicalAlignment )
-{
-    st_MemPool mem_pool;
-
-    static std::uintptr_t const ZERO_ALIGN = std::uintptr_t{ 0 };
-    std::size_t const chunk_size = std::size_t{8u};
-
-    /* we will use a pathological alignment here, so make sure the buffer is
-     * large enough! */
-    std::size_t const capacity = chunk_size * chunk_size * std::size_t{ 2 };
-
-    st_MemPool_init( &mem_pool, capacity, chunk_size );
-
-    unsigned char* ptr_buffer_begin = st_MemPool_get_begin_pos( &mem_pool );
-    ASSERT_TRUE( ptr_buffer_begin != nullptr );
-
-    std::uintptr_t const buffer_begin_addr =
-        reinterpret_cast< std::uintptr_t >( ptr_buffer_begin );
-
-    ASSERT_TRUE( buffer_begin_addr > ZERO_ALIGN );
-
-    /* --------------------------------------------------------------------- */
-    /* Try to add a non-zero-length block with a "strange" alignment -
-     * it should align to the least common multiple of the provided
-     * alignment and the chunk size to be divisible by both quantities.
-     *
-     * Note that this is potentially very wasteful with memory, so be
-     * advised to avoid this! */
-
-    std::size_t const alignment = chunk_size - std::size_t{ 1 };
-    st_AllocResult const result =
-        st_MemPool_append_aligned( &mem_pool, chunk_size, alignment );
-
-    ASSERT_TRUE( st_AllocResult_valid( &result ) );
-
-    unsigned char* ptr_begin    = st_AllocResult_get_pointer( &result );
-    uint64_t const block_len    = st_AllocResult_get_length( &result );
-    uint64_t const block_offset = st_AllocResult_get_offset( &result );
-
-    ASSERT_TRUE( ptr_begin != nullptr );
-
-    std::uintptr_t const begin_addr =
-        reinterpret_cast< std::uintptr_t >( ptr_begin );
-
-    ASSERT_TRUE( ( block_offset + buffer_begin_addr ) == begin_addr );
-    ASSERT_TRUE( ( begin_addr % chunk_size ) == ZERO_ALIGN );
-    ASSERT_TRUE( ( begin_addr % alignment  ) == ZERO_ALIGN );
-
-
-    ASSERT_TRUE( block_len <= capacity );
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool ) != nullptr  );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool )  >= capacity );
-
-    st_MemPool_free( &mem_pool );
-}
-
-/* ========================================================================== */
-/* ====  Test the failing of adding blocks with problematic properties        */
-
-TEST( C99_CommonMemPoolTests, AppendFailures )
-{
-    st_MemPool mem_pool;
-
-    std::size_t const chunk_size = std::size_t{8u};
-    std::size_t const capacity = 8 * chunk_size;
-
-    static std::size_t const ZERO_SIZE = std::size_t{0};
-
-    st_MemPool_init( &mem_pool, capacity, chunk_size );
-
-    /* --------------------------------------------------------------------- */
-    /* Asked to add a block into an empty MemPool that would exceed capacity */
-
-    std::size_t num_bytes_to_add = std::size_t{10} * chunk_size;
-
-    st_AllocResult
-    result = st_MemPool_append( &mem_pool, num_bytes_to_add );
-
-    ASSERT_TRUE( !st_AllocResult_valid( &result ) );
-    ASSERT_TRUE( st_AllocResult_get_pointer( &result ) == nullptr );
-    ASSERT_TRUE( st_AllocResult_get_offset( &result ) == uint64_t{0} );
-    ASSERT_TRUE( st_AllocResult_get_length( &result ) == uint64_t{0} );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool ) != nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool )   >= capacity );
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool ) == ZERO_SIZE );
-
-    /* --------------------------------------------------------------------- */
-    /* Add a block successfully - so we can check whether the MemPool keeps
-     * its properties if we insert a block - nonsuccessfully */
-
-    result = st_MemPool_append( &mem_pool, chunk_size );
-    ASSERT_TRUE( st_AllocResult_valid( &result ) );
-
-    std::size_t const current_size = st_MemPool_get_size( &mem_pool );
-
-    /* --------------------------------------------------------------------- */
-    /* Try to add a block with zero bytes length */
-
-    result = st_MemPool_append( &mem_pool, ZERO_SIZE );
-
-    ASSERT_TRUE( !st_AllocResult_valid( &result ) );
-    ASSERT_TRUE( st_AllocResult_get_pointer( &result ) == nullptr );
-    ASSERT_TRUE( st_AllocResult_get_offset( &result ) == uint64_t{0} );
-    ASSERT_TRUE( st_AllocResult_get_length( &result ) == uint64_t{0} );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool ) != nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool )   >= capacity );
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool ) == current_size );
-
-    /* --------------------------------------------------------------------- */
-    /* Try to add a valid block exceeding the number of remaining bytes      */
-
-    std::size_t remaining_bytes =
-        st_MemPool_get_remaining_bytes( &mem_pool );
-
-    std::size_t const too_large = remaining_bytes + std::size_t{1};
-
-    result = st_MemPool_append( &mem_pool, too_large );
-
-    ASSERT_TRUE( !st_AllocResult_valid( &result ) );
-    ASSERT_TRUE( st_AllocResult_get_pointer( &result ) == nullptr );
-    ASSERT_TRUE( st_AllocResult_get_offset( &result ) == uint64_t{0} );
-    ASSERT_TRUE( st_AllocResult_get_length( &result ) == uint64_t{0} );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos(  &mem_pool ) != nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity(   &mem_pool ) >= capacity );
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool ) == current_size );
-
-    /* --------------------------------------------------------------------- */
-    /* Try to add a valid block fitting in memory but exceeding the capacity
-     * due to too ambitious alignment requirements: */
-
-    /* Step one: find the "too ambitious alignment" values */
-
-    uint64_t const current_offset =
-        st_MemPool_get_next_begin_offset( &mem_pool, chunk_size );
-
-    ASSERT_TRUE( current_offset != UINT64_MAX );
-
-    std::size_t alignment = ( chunk_size << 1 );
-    std::size_t end_alignment = capacity;
-
-    bool found_alignment_for_test = false;
-
-    for( ; alignment < end_alignment; alignment += chunk_size )
-    {
-        if( st_MemPool_get_next_begin_offset( &mem_pool, alignment ) >
-            current_offset )
-        {
-            result = st_MemPool_append_aligned(
-                &mem_pool, remaining_bytes, alignment );
-
-            found_alignment_for_test = true;
-
-            break;
-        }
-    }
-
-    if( found_alignment_for_test )
-    {
-        ASSERT_TRUE( !st_AllocResult_valid( &result ) );
-        ASSERT_TRUE( st_AllocResult_get_pointer( &result ) == nullptr );
-        ASSERT_TRUE( st_AllocResult_get_offset( &result )  == uint64_t{0} );
-        ASSERT_TRUE( st_AllocResult_get_length( &result )  == uint64_t{0} );
-
-        ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool )  != nullptr );
-        ASSERT_TRUE( st_MemPool_get_capacity(  &mem_pool )  >= capacity );
-        ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-        ASSERT_TRUE( st_MemPool_get_size( &mem_pool )       == current_size );
-    }
-
-    /* Verify that non-aligned insert would work, however: */
-
-    result = st_MemPool_append( &mem_pool, remaining_bytes );
-
-    ASSERT_TRUE( st_AllocResult_valid( &result ) );
-    ASSERT_TRUE( st_AllocResult_get_pointer( &result ) != nullptr );
-    ASSERT_TRUE( st_AllocResult_get_offset( &result ) == current_size );
-    ASSERT_TRUE( st_AllocResult_get_length( &result ) == remaining_bytes );
-
-    ASSERT_TRUE( st_MemPool_get_begin_pos( &mem_pool )  != nullptr );
-    ASSERT_TRUE( st_MemPool_get_capacity( &mem_pool )   >= capacity );
-    ASSERT_TRUE( st_MemPool_get_chunk_size( &mem_pool ) == chunk_size );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool )       >= capacity );
-    ASSERT_TRUE( st_MemPool_get_size( &mem_pool )       ==
-                 st_MemPool_get_capacity( &mem_pool )  );
-    ASSERT_TRUE( st_MemPool_get_remaining_bytes( &mem_pool ) == ZERO_SIZE );
-
-    /* --------------------------------------------------------------------- */
-
-    st_MemPool_free( &mem_pool );
-}
-
-/* end: tests/sixtracklib/common/test_mem_pool.cpp */
diff --git a/tests/sixtracklib/common/test_output_buffer_c99.cpp b/tests/sixtracklib/common/test_output_buffer_c99.cpp
index 43f3dea6..45f9f9dd 100644
--- a/tests/sixtracklib/common/test_output_buffer_c99.cpp
+++ b/tests/sixtracklib/common/test_output_buffer_c99.cpp
@@ -112,7 +112,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
     buf_size_t until_turn_elem_by_elem = buf_size_t{ 0 };
 
     ASSERT_TRUE( buf_size_t{ 0 } ==
-        ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) );
+        ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) );
 
     ret = NS(OutputBuffer_calculate_output_buffer_params)( eb, particles,
         until_turn_elem_by_elem, &num_objects, &num_slots, &num_dataptrs,
@@ -349,7 +349,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
             skip_turns, ::NS(Buffer_get_objects_end)( eb ) );
 
     SIXTRL_ASSERT( ret == 0 );
-    SIXTRL_ASSERT( ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) ==
+    SIXTRL_ASSERT( ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) ==
                    buf_size_t{ 2 } );
 
     SIXTRL_ASSERT( ::NS(Buffer_get_num_of_objects)( eb ) ==
@@ -368,7 +368,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
 
     ASSERT_TRUE( ret == 0 );
     ASSERT_TRUE( num_objects ==
-        ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) );
+        ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) );
 
     ASSERT_TRUE( num_slots != buf_size_t{ 0 } );
     ASSERT_TRUE( num_dataptrs != buf_size_t{ 0 } );
@@ -418,7 +418,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
                 ::NS(Object_get_begin_addr)( obj ) ) );
 
         SIXTRL_ASSERT( monitor != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_stored_num_particles)( monitor ) >
+        SIXTRL_ASSERT( ::NS(BeamMonitor_stored_num_particles)( monitor ) >
                      buf_size_t{ 0 } );
 
         out_particles = ::NS(Particles_buffer_get_const_particles)(
@@ -428,7 +428,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
 
         ASSERT_TRUE( static_cast< buf_size_t >(
             ::NS(Particles_get_num_of_particles)( out_particles ) ) >=
-                ::NS(BeamMonitor_get_stored_num_particles)( monitor ) );
+                ::NS(BeamMonitor_stored_num_particles)( monitor ) );
     }
 
     /* -------------------------------------------------------------------- */
@@ -493,7 +493,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
                 ::NS(Object_get_begin_addr)( obj ) ) );
 
         SIXTRL_ASSERT( monitor != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_stored_num_particles)( monitor ) >
+        SIXTRL_ASSERT( ::NS(BeamMonitor_stored_num_particles)( monitor ) >
                      buf_size_t{ 0 } );
 
         out_particles = ::NS(Particles_buffer_get_const_particles)(
@@ -503,7 +503,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
 
         ASSERT_TRUE( static_cast< buf_size_t >(
             ::NS(Particles_get_num_of_particles)( out_particles ) ) >=
-                ::NS(BeamMonitor_get_stored_num_particles)( monitor ) );
+                ::NS(BeamMonitor_stored_num_particles)( monitor ) );
     }
 
     /* -------------------------------------------------------------------- */
@@ -573,7 +573,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
                 ::NS(Object_get_begin_addr)( obj ) ) );
 
         SIXTRL_ASSERT( monitor != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_stored_num_particles)( monitor ) >
+        SIXTRL_ASSERT( ::NS(BeamMonitor_stored_num_particles)( monitor ) >
                      buf_size_t{ 0 } );
 
         out_particles = ::NS(Particles_buffer_get_const_particles)(
@@ -583,7 +583,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
 
         ASSERT_TRUE( static_cast< buf_size_t >(
             ::NS(Particles_get_num_of_particles)( out_particles ) ) >=
-                ::NS(BeamMonitor_get_stored_num_particles)( monitor ) );
+                ::NS(BeamMonitor_stored_num_particles)( monitor ) );
     }
 
     /* ===================================================================== */
@@ -619,7 +619,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
         target_num_turns, skip_turns, ::NS(Buffer_get_objects_end)( eb ) );
 
     SIXTRL_ASSERT( ret == 0 );
-    SIXTRL_ASSERT( ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) ==
+    SIXTRL_ASSERT( ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) ==
                    buf_size_t{ 2 } );
 
     SIXTRL_ASSERT( ::NS(Buffer_get_num_of_objects)( eb ) ==
@@ -638,7 +638,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
 
     ASSERT_TRUE( ret == 0 );
     ASSERT_TRUE( num_objects == buf_size_t{ 1 } +
-        ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) );
+        ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) );
 
     ASSERT_TRUE( num_slots != buf_size_t{ 0 } );
     ASSERT_TRUE( num_dataptrs != buf_size_t{ 0 } );
@@ -695,7 +695,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
                 ::NS(Object_get_begin_addr)( obj ) ) );
 
         SIXTRL_ASSERT( monitor != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_stored_num_particles)( monitor ) >
+        SIXTRL_ASSERT( ::NS(BeamMonitor_stored_num_particles)( monitor ) >
                      buf_size_t{ 0 } );
 
         out_particles = ::NS(Particles_buffer_get_const_particles)(
@@ -705,7 +705,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
 
         ASSERT_TRUE( static_cast< buf_size_t >(
             ::NS(Particles_get_num_of_particles)( out_particles ) ) >=
-                ::NS(BeamMonitor_get_stored_num_particles)( monitor ) );
+                ::NS(BeamMonitor_stored_num_particles)( monitor ) );
     }
 
     /* -------------------------------------------------------------------- */
@@ -777,7 +777,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
                 ::NS(Object_get_begin_addr)( obj ) ) );
 
         SIXTRL_ASSERT( monitor != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_stored_num_particles)( monitor ) >
+        SIXTRL_ASSERT( ::NS(BeamMonitor_stored_num_particles)( monitor ) >
                      buf_size_t{ 0 } );
 
         out_particles = ::NS(Particles_buffer_get_const_particles)(
@@ -787,7 +787,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
 
         ASSERT_TRUE( static_cast< buf_size_t >(
             ::NS(Particles_get_num_of_particles)( out_particles ) ) >=
-                ::NS(BeamMonitor_get_stored_num_particles)( monitor ) );
+                ::NS(BeamMonitor_stored_num_particles)( monitor ) );
     }
 
     /* -------------------------------------------------------------------- */
@@ -864,7 +864,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
                 ::NS(Object_get_begin_addr)( obj ) ) );
 
         SIXTRL_ASSERT( monitor != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_stored_num_particles)( monitor ) >
+        SIXTRL_ASSERT( ::NS(BeamMonitor_stored_num_particles)( monitor ) >
                      buf_size_t{ 0 } );
 
         out_particles = ::NS(Particles_buffer_get_const_particles)(
@@ -874,7 +874,7 @@ TEST( C99_CommonOutputBuffer, OutputBufferCalculateParameters )
 
         ASSERT_TRUE( static_cast< buf_size_t >(
             ::NS(Particles_get_num_of_particles)( out_particles ) ) >=
-                     ::NS(BeamMonitor_get_stored_num_particles)( monitor ) );
+                     ::NS(BeamMonitor_stored_num_particles)( monitor ) );
     }
 
     /* ===================================================================== */
diff --git a/tests/sixtracklib/common/test_particles_aperture_c99.cpp b/tests/sixtracklib/common/test_particles_aperture_c99.cpp
index 19b01af9..a788496a 100644
--- a/tests/sixtracklib/common/test_particles_aperture_c99.cpp
+++ b/tests/sixtracklib/common/test_particles_aperture_c99.cpp
@@ -21,8 +21,11 @@
 #include "sixtracklib/common/generated/config.h"
 #include "sixtracklib/testlib.h"
 
-#if defined( SIXTRL_ENABLE_APERTURE_CHECK ) && \
-    SIXTRL_ENABLE_APERTURE_CHECK == 1
+#if !defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) || \
+                ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                  SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS ) || \
+                ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                  SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL )
 
 TEST( C99_CommonParticlesApertureTests,
       TrackParticlesOverDriftEnabledApertureCheck )
@@ -34,7 +37,7 @@ TEST( C99_CommonParticlesApertureTests,
       TrackParticlesOverDriftDisabledApertureCheck )
 {
 
-#endif /* SIXTRL_ENABLE_APERTURE_CHECK */
+#endif /* SIXTRL_ENABLE_GLOBAL_APERTURE_CHECK */
 
     using nelem_t = ::NS(particle_num_elements_t);
     using size_t  = size_t;
@@ -79,8 +82,11 @@ TEST( C99_CommonParticlesApertureTests,
 
             ASSERT_TRUE( status == ::NS(TRACK_SUCCESS) );
 
-            #if defined( SIXTRL_ENABLE_APERTURE_CHECK ) && \
-                         SIXTRL_ENABLE_APERTURE_CHECK == 1
+            #if !defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) || \
+                ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                  SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS ) || \
+                ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                  SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL )
 
             double const x = ::NS(Particles_get_x_value)( particles, idx );
             double const y = ::NS(Particles_get_y_value)( particles, idx );
@@ -99,7 +105,7 @@ TEST( C99_CommonParticlesApertureTests,
 
             ASSERT_TRUE( ::NS(Particles_is_not_lost_value)( particles, idx ) );
 
-            #endif /* SIXTRL_ENABLE_APERTURE_CHECK */
+            #endif /* SIXTRL_ENABLE_GLOBAL_APERTURE_CHECK */
         }
     }
 
@@ -110,8 +116,9 @@ TEST( C99_CommonParticlesApertureTests,
     eb = nullptr;
 }
 
-#if defined( SIXTRL_ENABLE_APERTURE_CHECK ) && \
-             SIXTRL_ENABLE_APERTURE_CHECK == 1
+#if defined( SIXTRL_ENABLE_GLOBAL_APERTURE_CHECK ) && \
+             SIXTRL_ENABLE_GLOBAL_APERTURE_CHECK > \
+             SIXTRL_GLOBAL_APERTURE_CHECK_NEVER
 
 TEST( C99_CommonParticlesApertureTests,
       TrackParticlesOverDriftExactEnabledApertureCheck )
@@ -122,7 +129,7 @@ TEST( C99_CommonParticlesApertureTests,
 TEST( C99_CommonParticlesApertureTests,
       TrackParticlesOverDriftExactDisabledApertureCheck )
 {
-#endif /* SIXTRL_ENABLE_APERTURE_CHECK */
+#endif /* SIXTRL_ENABLE_GLOBAL_APERTURE_CHECK */
     using nelem_t = ::NS(particle_num_elements_t);
     using size_t  = size_t;
 
@@ -165,8 +172,11 @@ TEST( C99_CommonParticlesApertureTests,
 
             ASSERT_TRUE( status == ::NS(TRACK_SUCCESS) );
 
-            #if defined( SIXTRL_ENABLE_APERTURE_CHECK ) && \
-                SIXTRL_ENABLE_APERTURE_CHECK == 1
+            #if !defined( SIXTRL_APERTURE_CHECK_AT_DRIFT ) || \
+                ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                  SIXTRL_GLOBAL_APERTURE_CHECK_ALWAYS ) || \
+                ( SIXTRL_APERTURE_CHECK_AT_DRIFT == \
+                  SIXTRL_GLOBAL_APERTURE_CHECK_CONDITIONAL )
 
             double const x = ::NS(Particles_get_x_value)( particles, idx );
             double const y = ::NS(Particles_get_y_value)( particles, idx );
@@ -185,7 +195,7 @@ TEST( C99_CommonParticlesApertureTests,
 
             ASSERT_TRUE( ::NS(Particles_is_not_lost_value)( particles, idx ) );
 
-            #endif /* SIXTRL_ENABLE_APERTURE_CHECK */
+            #endif /* SIXTRL_ENABLE_GLOBAL_APERTURE_CHECK */
         }
     }
 
diff --git a/tests/sixtracklib/common/test_track_job_cpu_c99.cpp b/tests/sixtracklib/common/test_track_job_cpu_c99.cpp
index a0a306b8..779284d6 100644
--- a/tests/sixtracklib/common/test_track_job_cpu_c99.cpp
+++ b/tests/sixtracklib/common/test_track_job_cpu_c99.cpp
@@ -837,7 +837,7 @@ TEST( C99_TrackJobCpuTests, TrackParticles )
 
     SIXTRL_ASSERT( ret == 0 );
 
-    ::NS(BeamMonitor_clear_all)( eb );
+    ::NS(BeamMonitor_reset_all_in_buffer)( eb );
 
     /* -------------------------------------------------------------------- */
     /* perform tracking using a track_job: */
diff --git a/tests/sixtracklib/common/track/CMakeLists.txt b/tests/sixtracklib/common/track/CMakeLists.txt
index 0d32c3ab..4b2e302a 100644
--- a/tests/sixtracklib/common/track/CMakeLists.txt
+++ b/tests/sixtracklib/common/track/CMakeLists.txt
@@ -7,114 +7,162 @@ if( GTEST_FOUND )
          ${SIXTRACKL_GTEST_LIBRARIES} )
 
     # ==========================================================================
-    # test_track_job_setup_cpu_cxx:
+    # test_track_job_cpu_setup_cxx:
 
-    add_executable( test_track_job_setup_cpu_cxx test_track_job_setup_cxx.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_job_setup_cpu_cxx )
-    add_test( CXX_Cpu_CpuTrackJobSetupTests test_track_job_setup_cpu_cxx )
+    add_executable( test_track_job_cpu_setup_cxx test_track_job_setup_cxx.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_job_cpu_setup_cxx )
+    add_test( CXX_Cpu_CpuTrackJobSetupTests test_track_job_cpu_setup_cxx )
 
     # --------------------------------------------------------------------------
-    # test_track_job_setup_cpu_c99:
+    # test_track_job_cpu_setup_c99:
 
-    add_executable( test_track_job_setup_cpu_c99 test_track_job_setup_c99.cpp )
-    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_job_setup_cpu_c99 )
-    add_test( C99_Cpu_CpuTrackJobSetupTests test_track_job_setup_cpu_c99 )
+    add_executable( test_track_job_cpu_setup_c99 test_track_job_setup_c99.cpp )
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} test_track_job_cpu_setup_c99 )
+    add_test( C99_Cpu_CpuTrackJobSetupTests test_track_job_cpu_setup_c99 )
 
     # ==========================================================================
-    # test_track_job_fetch_particle_addr_cpu_cxx:
+    # test_track_job_cpu_stored_buffer_cxx:
 
-    add_executable( test_track_job_fetch_particle_addr_cpu_cxx
+    add_executable( test_track_job_cpu_stored_buffer_cxx
+                    test_track_job_cpu_stored_buffer_cxx.cpp )
+
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
+         test_track_job_cpu_stored_buffer_cxx )
+
+    add_test( CXX_Cpu_CpuTrackJob_StoredBufferTests
+              test_track_job_cpu_stored_buffer_cxx )
+
+    # --------------------------------------------------------------------------
+    # test_track_job_cpu_stored_buffer_c99:
+
+    add_executable( test_track_job_cpu_stored_buffer_c99
+        test_track_job_cpu_stored_buffer_c99.cpp )
+
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
+            test_track_job_cpu_stored_buffer_c99 )
+
+    add_test( C99_Cpu_CpuTrackJob_StoredBufferTests
+              test_track_job_cpu_stored_buffer_c99 )
+
+    # ==========================================================================
+    # test_track_job_cpu_assign_address_item_cxx:
+
+    add_executable( test_track_job_cpu_assign_address_item_cxx
+                    test_track_job_cpu_assign_address_item_cxx.cpp )
+
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
+         test_track_job_cpu_assign_address_item_cxx )
+
+    add_test( CXX_Cpu_CpuTrackJob_AssignAddressItemTests
+              test_track_job_cpu_assign_address_item_cxx )
+
+    # --------------------------------------------------------------------------
+    # test_track_job_cpu_assign_address_item_c99:
+
+    add_executable( test_track_job_cpu_assign_address_item_c99
+                    test_track_job_cpu_assign_address_item_c99.cpp )
+
+    set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
+            test_track_job_cpu_assign_address_item_c99 )
+
+    add_test( C99_Cpu_CpuTrackJob_AssignAddressItemTests
+              test_track_job_cpu_assign_address_item_c99 )
+
+    # ==========================================================================
+    # test_track_job_cpu_fetch_particle_addr_cxx:
+
+    add_executable( test_track_job_cpu_fetch_particle_addr_cxx
                     test_track_job_fetch_particle_addr_cxx.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_track_job_fetch_particle_addr_cpu_cxx )
+         test_track_job_cpu_fetch_particle_addr_cxx )
 
     add_test( CXX_Cpu_CpuTrackJobFetchParticleAddrTests
-              test_track_job_fetch_particle_addr_cpu_cxx )
+              test_track_job_cpu_fetch_particle_addr_cxx )
 
     # --------------------------------------------------------------------------
-    # test_track_job_fetch_particle_addr_cpu_c99:
+    # test_track_job_cpu_fetch_particle_addr_c99:
 
-    add_executable( test_track_job_fetch_particle_addr_cpu_c99
+    add_executable( test_track_job_cpu_fetch_particle_addr_c99
                     test_track_job_fetch_particle_addr_c99.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_track_job_fetch_particle_addr_cpu_c99 )
+         test_track_job_cpu_fetch_particle_addr_c99 )
 
     add_test( C99_Cpu_CpuTrackJobFetchParticleAddrTests
-              test_track_job_fetch_particle_addr_cpu_c99 )
+              test_track_job_cpu_fetch_particle_addr_c99 )
 
     # ==========================================================================
-    # test_track_job_track_until_cpu_cxx:
+    # test_track_job_cpu_track_until_cxx:
 
-    add_executable( test_track_job_track_until_cpu_cxx
+    add_executable( test_track_job_cpu_track_until_cxx
                     test_track_job_track_until_cxx.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_track_job_track_until_cpu_cxx )
+         test_track_job_cpu_track_until_cxx )
 
     add_test( CXX_Cpu_CpuTrackJobTrackUntilTests
-        test_track_job_track_until_cpu_cxx )
+        test_track_job_cpu_track_until_cxx )
 
     # --------------------------------------------------------------------------
-    # test_track_job_track_until_cpu_c99:
+    # test_track_job_cpu_track_until_c99:
 
-    add_executable( test_track_job_track_until_cpu_c99
+    add_executable( test_track_job_cpu_track_until_c99
                     test_track_job_track_until_c99.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_track_job_track_until_cpu_c99 )
+         test_track_job_cpu_track_until_c99 )
 
     add_test( C99_Cpu_CpuTrackJobTrackUntilTests
-              test_track_job_track_until_cpu_c99 )
+              test_track_job_cpu_track_until_c99 )
 
     # ==========================================================================
-    # test_track_job_track_line_cpu_cxx:
+    # test_track_job_cpu_track_line_cxx:
 
-    add_executable( test_track_job_track_line_cpu_cxx
+    add_executable( test_track_job_cpu_track_line_cxx
                     test_track_job_track_line_cxx.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_track_job_track_line_cpu_cxx )
+         test_track_job_cpu_track_line_cxx )
 
     add_test( CXX_Cpu_CpuTrackJobTrackLineTests
-              test_track_job_track_line_cpu_cxx )
+              test_track_job_cpu_track_line_cxx )
 
     # --------------------------------------------------------------------------
-    # test_track_job_track_line_cpu_c99:
+    # test_track_job_cpu_track_line_c99:
 
-    add_executable( test_track_job_track_line_cpu_c99
+    add_executable( test_track_job_cpu_track_line_c99
                     test_track_job_track_line_c99.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_track_job_track_line_cpu_c99 )
+         test_track_job_cpu_track_line_c99 )
 
     add_test( C99_Cpu_CpuTrackJobTrackLineTests
-              test_track_job_track_line_cpu_c99 )
+              test_track_job_cpu_track_line_c99 )
 
     # ==========================================================================
-    # test_track_job_track_elem_by_elem_cpu_cxx:
+    # test_track_job_cpu_track_elem_by_elem_cxx:
 
-    add_executable( test_track_job_track_elem_by_elem_cpu_cxx
+    add_executable( test_track_job_cpu_track_elem_by_elem_cxx
                     test_track_job_track_elem_by_elem_cxx.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_track_job_track_elem_by_elem_cpu_cxx )
+         test_track_job_cpu_track_elem_by_elem_cxx )
 
     add_test( CXX_Cpu_CpuTrackJobTrackElemByElemTests
-              test_track_job_track_elem_by_elem_cpu_cxx )
+              test_track_job_cpu_track_elem_by_elem_cxx )
 
     # --------------------------------------------------------------------------
-    # test_track_job_track_elem_by_elem_cpu_c99:
+    # test_track_job_cpu_track_elem_by_elem_c99:
 
-    add_executable( test_track_job_track_elem_by_elem_cpu_c99
+    add_executable( test_track_job_cpu_track_elem_by_elem_c99
                     test_track_job_track_elem_by_elem_c99.cpp )
 
     set( UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS}
-         test_track_job_track_elem_by_elem_cpu_c99 )
+         test_track_job_cpu_track_elem_by_elem_c99 )
 
     add_test( C99_Cpu_CpuTrackJobTrackElemByElemTests
-              test_track_job_track_elem_by_elem_cpu_c99 )
+              test_track_job_cpu_track_elem_by_elem_c99 )
 endif()
 
 if( UNIT_TEST_TARGETS )
diff --git a/tests/sixtracklib/common/track/test_track_job_cpu_assign_address_item_c99.cpp b/tests/sixtracklib/common/track/test_track_job_cpu_assign_address_item_c99.cpp
new file mode 100644
index 00000000..784a1c0b
--- /dev/null
+++ b/tests/sixtracklib/common/track/test_track_job_cpu_assign_address_item_c99.cpp
@@ -0,0 +1,442 @@
+#include "sixtracklib/common/track_job_cpu.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer.h"
+#include "sixtracklib/common/buffer/assign_address_item.h"
+#include "sixtracklib/common/be_drift/be_drift.h"
+#include "sixtracklib/common/be_monitor/be_monitor.h"
+#include "sixtracklib/common/particles.h"
+
+
+TEST( C99_Cpu_CpuTrackJob_AssignAddressItemTests, MinimalUsage )
+{
+    using track_job_t    = ::NS(TrackJobCpu);
+    using size_t         = ::NS(arch_size_t);
+    using assign_item_t  = ::NS(AssignAddressItem);
+    using c_buffer_t     = ::NS(Buffer);
+    using particle_set_t = ::NS(Particles);
+
+    c_buffer_t* my_lattice = ::NS(Buffer_new)( size_t{ 0 } );
+    c_buffer_t* my_output_buffer = ::NS(Buffer_new)( size_t{ 0 } );
+
+    ::NS(Drift)* dr = ::NS(Drift_add)( my_lattice, 0.0 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.1 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.2 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    size_t const bm0_elem_idx = ::NS(Buffer_get_num_of_objects)( my_lattice );
+
+    ::NS(BeamMonitor)* bm0 = ::NS(BeamMonitor_new)( my_lattice );
+    SIXTRL_ASSERT( bm0 != nullptr );
+    ( void )bm0;
+
+    dr = ::NS(Drift_add)( my_lattice, 0.0 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.1 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.2 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    size_t const bm1_elem_idx = ::NS(Buffer_get_num_of_objects)( my_lattice );
+    SIXTRL_ASSERT( bm1_elem_idx > bm0_elem_idx );
+
+    ::NS(BeamMonitor)* bm1 = ::NS(BeamMonitor_new)( my_lattice );
+    SIXTRL_ASSERT( bm1 != nullptr );
+    ( void )bm1;
+
+    dr = ::NS(Drift_add)( my_lattice, 0.3 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.4 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.5 );
+    SIXTRL_ASSERT( dr != nullptr );
+    ( void )dr;
+
+    size_t const bm2_elem_idx = ::NS(Buffer_get_num_of_objects)( my_lattice );
+    SIXTRL_ASSERT( bm2_elem_idx > bm1_elem_idx );
+
+    ::NS(BeamMonitor)* bm2 = ::NS(BeamMonitor_new)( my_lattice );
+    SIXTRL_ASSERT( bm2 != nullptr );
+    ( void )bm2;
+
+    size_t const out_buffer0_index =
+        ::NS(Buffer_get_num_of_objects)( my_output_buffer );
+
+    particle_set_t* out_buffer0 =
+        ::NS(Particles_new)( my_output_buffer, size_t{ 100 } );
+    SIXTRL_ASSERT( out_buffer0 );
+
+    size_t const out_buffer1_index =
+        ::NS(Buffer_get_num_of_objects)( my_output_buffer );
+
+    particle_set_t* out_buffer1 =
+        ::NS(Particles_new)( my_output_buffer, size_t{ 512 } );
+    SIXTRL_ASSERT( out_buffer1 );
+
+    ::NS(buffer_addr_t) const my_lattice_buffer_addr =
+        ::NS(Buffer_get_data_begin_addr)( my_lattice );
+
+    size_t const my_lattice_buffer_size =
+        ::NS(Buffer_get_size)( my_lattice );
+
+    size_t const my_lattice_buffer_capacity =
+        ::NS(Buffer_get_capacity)( my_lattice );
+
+    size_t const my_lattice_buffer_num_objects =
+        ::NS(Buffer_get_num_of_objects)( my_lattice );
+
+    ::NS(buffer_addr_t) const my_output_buffer_addr =
+        ::NS(Buffer_get_data_begin_addr)( my_output_buffer );
+
+    size_t const my_output_buffer_size =
+        ::NS(Buffer_get_size)( my_output_buffer );
+
+    size_t const my_output_buffer_capacity =
+        ::NS(Buffer_get_capacity)( my_output_buffer );
+
+    size_t const my_output_buffer_num_objects =
+        ::NS(Buffer_get_num_of_objects)( my_output_buffer );
+
+
+    out_buffer0 = ::NS(Particles_buffer_get_particles)(
+        my_output_buffer, out_buffer0_index );
+
+    out_buffer1 = ::NS(Particles_buffer_get_particles)(
+        my_output_buffer, out_buffer1_index );
+
+    track_job_t* job = ::NS(TrackJobCpu_create)();
+
+    size_t const my_lattice_buffer_id = ::NS(TrackJob_add_stored_buffer)(
+        job, my_lattice, false, false );
+
+    ASSERT_TRUE( my_lattice_buffer_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    size_t const my_output_buffer_id = ::NS(TrackJob_add_stored_buffer)(
+        job, my_output_buffer, false, false );
+
+    c_buffer_t* ptr_my_lattice_buffer = nullptr;
+    c_buffer_t* ptr_my_output_buffer  = nullptr;
+
+    ASSERT_TRUE( my_output_buffer_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+    ASSERT_TRUE( my_output_buffer_id > my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ::NS(TrackJob_is_buffer_by_buffer_id)(
+        job, my_lattice_buffer_id ) );
+
+    ASSERT_TRUE( !::NS(TrackJob_is_raw_memory_by_buffer_id)(
+        job, my_lattice_buffer_id ) );
+
+    ptr_my_lattice_buffer = ::NS(TrackJob_buffer_by_buffer_id)(
+        job, my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ptr_my_lattice_buffer != nullptr );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_addr );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_size );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_capacity );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_num_objects );
+
+    ptr_my_output_buffer = ::NS(TrackJob_buffer_by_buffer_id)(
+        job, my_output_buffer_id );
+
+    ASSERT_TRUE( ptr_my_output_buffer != nullptr );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_my_output_buffer ) ==
+                    my_output_buffer_addr );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_my_output_buffer ) ==
+                    my_output_buffer_size );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_my_output_buffer ) ==
+                    my_output_buffer_capacity );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_my_output_buffer ) ==
+                    my_output_buffer_num_objects );
+
+    ASSERT_TRUE(  ::NS(TrackJob_is_buffer_by_buffer_id)(
+        job, my_output_buffer_id ) );
+
+    ASSERT_TRUE( !::NS(TrackJob_is_raw_memory_by_buffer_id)(
+        job, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_buffer_by_buffer_id)(
+        job, my_output_buffer_id ) == ptr_my_output_buffer );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)( job, my_output_buffer_id ) ==
+        ptr_my_output_buffer );
+
+    /* --------------------------------------------------------------------- */
+
+    assign_item_t assign_item_0_to_0;
+    ::NS(AssignAddressItem_preset)( &assign_item_0_to_0 );
+
+    ::NS(AssignAddressItem_set_dest_elem_type_id)(
+        &assign_item_0_to_0, ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+    ::NS(AssignAddressItem_set_dest_buffer_id)(
+        &assign_item_0_to_0, my_lattice_buffer_id );
+
+    ::NS(AssignAddressItem_set_dest_elem_index)(
+        &assign_item_0_to_0, bm0_elem_idx );
+
+    ::NS(AssignAddressItem_set_dest_pointer_offset)(
+        &assign_item_0_to_0, offsetof( ::NS(BeamMonitor), out_address ) );
+
+    ::NS(AssignAddressItem_set_src_elem_type_id)(
+        &assign_item_0_to_0, ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ::NS(AssignAddressItem_set_src_buffer_id)(
+        &assign_item_0_to_0, my_output_buffer_id );
+
+    ::NS(AssignAddressItem_set_src_elem_index)(
+        &assign_item_0_to_0, out_buffer0_index );
+
+    ::NS(AssignAddressItem_set_src_pointer_offset)(
+        &assign_item_0_to_0, size_t{ 0 } );
+
+
+    ASSERT_TRUE(  ::NS(TrackJob_total_num_assign_items)( job ) == size_t{ 0 } );
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_address_item)(
+        job, &assign_item_0_to_0 ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 0 } );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+
+    assign_item_t* ptr_assign_item_0_to_0 =
+        ::NS(TrackJob_add_assign_address_item)( job, &assign_item_0_to_0 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0 != nullptr );
+    ASSERT_TRUE(  ::NS(AssignAddressItem_are_equal)(
+                        &assign_item_0_to_0, ptr_assign_item_0_to_0 ) );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0 != nullptr );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_elem_type_id)(
+                    ptr_assign_item_0_to_0 ) == ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_buffer_id)(
+                    ptr_assign_item_0_to_0 ) == my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_elem_index)(
+                    ptr_assign_item_0_to_0 ) == bm0_elem_idx );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_pointer_offset)(
+                    ptr_assign_item_0_to_0 ) ==
+                    offsetof( ::NS(BeamMonitor), out_address ) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_elem_type_id)(
+                    ptr_assign_item_0_to_0 ) == ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_buffer_id)(
+                    ptr_assign_item_0_to_0 ) == my_output_buffer_id );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_elem_index)(
+                    ptr_assign_item_0_to_0 ) == out_buffer0_index );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_offset)(
+                    ptr_assign_item_0_to_0 ) == size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+                        ptr_assign_item_0_to_0, ptr_my_output_buffer ) ==
+                            reinterpret_cast< uintptr_t >( out_buffer0 ) );
+
+
+    ASSERT_TRUE(  ::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 1 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_total_num_assign_items)( job ) == size_t{ 1 } );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) == size_t{ 0 } );
+
+    size_t const item_0_to_0_index = ::NS(TrackJob_index_of_assign_address_item)(
+        job, ptr_assign_item_0_to_0 );
+
+    ASSERT_TRUE( item_0_to_0_index < ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    assign_item_t assign_item_1_to_1;
+    ::NS(AssignAddressItem_preset)( &assign_item_1_to_1 );
+
+    ::NS(AssignAddressItem_set_dest_elem_type_id)(
+        &assign_item_1_to_1, ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+    ::NS(AssignAddressItem_set_dest_buffer_id)(
+        &assign_item_1_to_1, my_lattice_buffer_id );
+
+    ::NS(AssignAddressItem_set_dest_elem_index)(
+        &assign_item_1_to_1, bm1_elem_idx );
+
+    ::NS(AssignAddressItem_set_dest_pointer_offset)(
+        &assign_item_1_to_1, offsetof( ::NS(BeamMonitor), out_address ) );
+
+    ::NS(AssignAddressItem_set_src_elem_type_id)(
+        &assign_item_1_to_1, ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ::NS(AssignAddressItem_set_src_buffer_id)(
+        &assign_item_1_to_1, my_output_buffer_id );
+
+    ::NS(AssignAddressItem_set_src_elem_index)(
+        &assign_item_1_to_1, out_buffer1_index );
+
+    ::NS(AssignAddressItem_set_src_pointer_offset)(
+        &assign_item_1_to_1, size_t{ 0 } );
+
+    ASSERT_TRUE( ::NS(TrackJob_ptr_assign_address_item)(
+        job, &assign_item_1_to_1 ) == nullptr );
+
+    ASSERT_TRUE( ::NS(TrackJob_ptr_assign_address_item_detailed)(
+        job, ::NS(OBJECT_TYPE_BEAM_MONITOR), my_lattice_buffer_id,
+            bm1_elem_idx, offsetof( ::NS(BeamMonitor), out_address ),
+                ::NS(OBJECT_TYPE_PARTICLE), my_output_buffer_id,
+                    out_buffer1_index, size_t{ 0 } ) == nullptr );
+
+    /* --------------------------------------------------------------------- */
+
+    assign_item_t* ptr_assign_item_1_to_1 =
+    ::NS(TrackJob_add_assign_address_item_detailed)( job,
+        ::NS(OBJECT_TYPE_BEAM_MONITOR), my_lattice_buffer_id, bm1_elem_idx,
+            offsetof( ::NS(BeamMonitor), out_address ),
+                ::NS(OBJECT_TYPE_PARTICLE), my_output_buffer_id,
+                    out_buffer1_index, size_t{ 0 } );
+
+    ASSERT_TRUE(  ptr_assign_item_1_to_1 != nullptr );
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_elem_type_id)(
+                    ptr_assign_item_1_to_1 ) == ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_buffer_id)(
+                    ptr_assign_item_1_to_1 ) == my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_elem_index)(
+                    ptr_assign_item_1_to_1 ) == bm1_elem_idx );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_pointer_offset)(
+                    ptr_assign_item_1_to_1 ) == offsetof(
+                        ::NS(BeamMonitor), out_address ) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_elem_type_id)(
+                    ptr_assign_item_1_to_1 ) == ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_buffer_id)(
+                    ptr_assign_item_1_to_1 ) == my_output_buffer_id );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_elem_index)(
+                    ptr_assign_item_1_to_1 ) == out_buffer1_index );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_offset)(
+                    ptr_assign_item_1_to_1 ) == size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+                        ptr_assign_item_1_to_1, ptr_my_output_buffer ) ==
+                            reinterpret_cast< uintptr_t >( out_buffer1 ) );
+
+
+    ASSERT_TRUE(  ::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 2 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_total_num_assign_items)(
+        job ) == size_t{ 2 } );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) == size_t{ 0 } );
+
+    size_t const item_1_to_1_index = ::NS(TrackJob_index_of_assign_address_item)(
+        job, ptr_assign_item_1_to_1 );
+
+    ASSERT_TRUE( item_1_to_1_index < ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    /* --------------------------------------------------------------------- */
+
+    assign_item_t assign_item_0_to_2 = assign_item_0_to_0;
+
+    ::NS(AssignAddressItem_set_dest_elem_index)(
+        &assign_item_0_to_2, bm2_elem_idx );
+
+    assign_item_t* ptr_assign_item_0_to_2 =
+        ::NS(TrackJob_add_assign_address_item)( job, &assign_item_0_to_2 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_2 != nullptr );
+    ASSERT_TRUE(  ::NS(AssignAddressItem_are_equal)(
+        &assign_item_0_to_2, ptr_assign_item_0_to_2 ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 3 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_total_num_assign_items)(
+        job ) == size_t{ 3 } );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) == size_t{ 0 } );
+
+    /* --------------------------------------------------------------------- */
+
+    ::NS(arch_status_t) status =
+        ::NS(TrackJob_commit_address_assignments)( job );
+
+    ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+    status = ::NS(TrackJob_assign_all_addresses)( job );
+
+    ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+    bm0 = ::NS(BeamMonitor_from_buffer)( ptr_my_lattice_buffer, bm0_elem_idx );
+    bm1 = ::NS(BeamMonitor_from_buffer)( ptr_my_lattice_buffer, bm1_elem_idx );
+    bm2 = ::NS(BeamMonitor_from_buffer)( ptr_my_lattice_buffer, bm2_elem_idx );
+
+    SIXTRL_ASSERT( bm0 != nullptr );
+    SIXTRL_ASSERT( bm1 != nullptr );
+    SIXTRL_ASSERT( bm2 != nullptr );
+
+    ASSERT_TRUE( ::NS(BeamMonitor_out_address)( bm0 ) ==
+        reinterpret_cast< uintptr_t >( out_buffer0 ) );
+
+    ASSERT_TRUE( ::NS(BeamMonitor_out_address)( bm1 ) ==
+        reinterpret_cast< uintptr_t >( out_buffer1 ) );
+
+    ASSERT_TRUE( ::NS(BeamMonitor_out_address)( bm2 ) ==
+        reinterpret_cast< uintptr_t >( out_buffer0 ) );
+
+    /* --------------------------------------------------------------------- */
+
+    ::NS(TrackJob_delete)( job );
+    ::NS(Buffer_delete)( my_lattice );
+    ::NS(Buffer_delete)( my_output_buffer );
+}
diff --git a/tests/sixtracklib/common/track/test_track_job_cpu_assign_address_item_cxx.cpp b/tests/sixtracklib/common/track/test_track_job_cpu_assign_address_item_cxx.cpp
new file mode 100644
index 00000000..9339d14f
--- /dev/null
+++ b/tests/sixtracklib/common/track/test_track_job_cpu_assign_address_item_cxx.cpp
@@ -0,0 +1,326 @@
+#include "sixtracklib/common/track_job_cpu.h"
+
+#include <cstddef>
+#include <cstdint>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer.hpp"
+#include "sixtracklib/common/buffer/assign_address_item.h"
+#include "sixtracklib/common/be_drift/be_drift.hpp"
+#include "sixtracklib/common/be_monitor/be_monitor.hpp"
+#include "sixtracklib/common/particles.hpp"
+
+
+TEST( CXX_Cpu_CpuTrackJob_AssignAddressItemTests, MinimalUsage )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    using track_job_t    = st::TrackJobCpu;
+    using size_t         = track_job_t::size_type;
+    using assign_item_t  = track_job_t::assign_item_t;
+    using buffer_t       = track_job_t::buffer_t;
+    using c_buffer_t     = track_job_t::c_buffer_t;
+    using particle_set_t = st::Particles;
+    using be_monitor_t   = st::BeamMonitor;
+    using drift_t        = st::Drift;
+
+    buffer_t my_lattice;
+    buffer_t my_output_buffer;
+
+    st::Drift* dr = my_lattice.add< drift_t >( 0.0 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.1 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.2 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    size_t const bm0_elem_idx = my_lattice.getNumObjects();
+
+    st::BeamMonitor* bm0 = my_lattice.createNew< be_monitor_t >();
+    SIXTRL_ASSERT( bm0 != nullptr );
+    ( void )bm0;
+
+    dr = my_lattice.add< drift_t >( 0.0 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.1 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.2 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    size_t const bm1_elem_idx = my_lattice.getNumObjects();
+    SIXTRL_ASSERT( bm1_elem_idx > bm0_elem_idx );
+
+    st::BeamMonitor* bm1 = my_lattice.createNew< be_monitor_t >();
+    SIXTRL_ASSERT( bm1 != nullptr );
+    ( void )bm1;
+
+    dr = my_lattice.add< drift_t >( 0.3 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.4 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.5 );
+    SIXTRL_ASSERT( dr != nullptr );
+    ( void )dr;
+
+    size_t const bm2_elem_idx = my_lattice.getNumObjects();
+    SIXTRL_ASSERT( bm2_elem_idx > bm1_elem_idx );
+
+    st::BeamMonitor* bm2 = my_lattice.createNew< be_monitor_t >();
+    SIXTRL_ASSERT( bm2 != nullptr );
+    ( void )bm2;
+
+    size_t const out_buffer0_index = my_output_buffer.getNumObjects();
+    particle_set_t* out_buffer0 =
+        my_output_buffer.createNew< st::Particles >( size_t{ 100 } );
+    SIXTRL_ASSERT( out_buffer0 );
+
+    size_t const out_buffer1_index = my_output_buffer.getNumObjects();
+    particle_set_t* out_buffer1 =
+        my_output_buffer.createNew< st::Particles >( size_t{ 512 } );
+    SIXTRL_ASSERT( out_buffer1 );
+
+    c_buffer_t* ptr_my_lattice_buffer = my_lattice.getCApiPtr();
+    SIXTRL_ASSERT( ptr_my_lattice_buffer != nullptr );
+
+    buffer_t::address_t const my_lattice_buffer_addr =
+        my_lattice.getDataBeginAddr();
+
+    size_t const my_lattice_buffer_size = my_lattice.getSize();
+    size_t const my_lattice_buffer_capacity = my_lattice.getCapacity();
+
+    size_t const my_lattice_buffer_num_objects =
+        my_lattice.getNumObjects();
+
+    c_buffer_t* ptr_my_output_buffer  = my_output_buffer.getCApiPtr();
+    SIXTRL_ASSERT( ptr_my_output_buffer != nullptr );
+
+    buffer_t::address_t const my_output_buffer_addr =
+        my_output_buffer.getDataBeginAddr();
+
+    size_t const my_output_buffer_size = my_output_buffer.getSize();
+    size_t const my_output_buffer_capacity = my_output_buffer.getCapacity();
+
+    size_t const my_output_buffer_num_objects =
+        my_output_buffer.getNumObjects();
+
+
+    out_buffer0 = my_output_buffer.get< particle_set_t >( out_buffer0_index );
+    out_buffer1 = my_output_buffer.get< particle_set_t >( out_buffer1_index );
+
+    track_job_t job;
+
+    size_t const my_lattice_buffer_id = job.add_stored_buffer(
+        std::move( my_lattice ) );
+
+    ASSERT_TRUE( my_lattice_buffer_id != track_job_t::ILLEGAL_BUFFER_ID );
+
+    size_t const my_output_buffer_id = job.add_stored_buffer(
+        std::move( my_output_buffer ) );
+
+    ptr_my_lattice_buffer = nullptr;
+    ptr_my_output_buffer  = nullptr;
+
+    ASSERT_TRUE( my_output_buffer_id != track_job_t::ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE( my_output_buffer_id > my_lattice_buffer_id );
+
+    ASSERT_TRUE(  job.is_buffer_by_buffer_id( my_lattice_buffer_id ) );
+    ASSERT_TRUE( !job.is_raw_memory_by_buffer_id( my_lattice_buffer_id ) );
+
+    ptr_my_lattice_buffer = job.buffer_by_buffer_id( my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ptr_my_lattice_buffer != nullptr );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_addr );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_size );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_capacity );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_num_objects );
+
+    ptr_my_output_buffer = job.buffer_by_buffer_id( my_output_buffer_id );
+
+    ASSERT_TRUE( ptr_my_output_buffer != nullptr );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_my_output_buffer ) ==
+                    my_output_buffer_addr );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_my_output_buffer ) ==
+                    my_output_buffer_size );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_my_output_buffer ) ==
+                    my_output_buffer_capacity );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_my_output_buffer ) ==
+                    my_output_buffer_num_objects );
+
+    ASSERT_TRUE(  job.is_buffer_by_buffer_id( my_output_buffer_id ) );
+    ASSERT_TRUE( !job.is_raw_memory_by_buffer_id( my_output_buffer_id ) );
+    ASSERT_TRUE(  job.buffer_by_buffer_id( my_output_buffer_id ) ==
+                  ptr_my_output_buffer );
+
+    ASSERT_TRUE(  job.ptr_stored_buffer( my_output_buffer_id ) ==
+                  ptr_my_output_buffer );
+
+    assign_item_t const assign_item_0_to_0(
+        st::OBJECT_TYPE_BEAM_MONITOR, my_lattice_buffer_id, bm0_elem_idx,
+        offsetof( st::BeamMonitor, out_address ),
+        st::OBJECT_TYPE_PARTICLE, my_output_buffer_id, out_buffer0_index,
+        size_t{ 0 } );
+
+    ASSERT_TRUE(  job.total_num_assign_items() == size_t{ 0 } );
+    ASSERT_TRUE( !job.has_assign_address_item( assign_item_0_to_0 ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 0 } );
+
+    ASSERT_TRUE( !job.has_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    assign_item_t* ptr_assign_item_0_to_0 =
+        job.add_assign_address_item( assign_item_0_to_0 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0 != nullptr );
+    ASSERT_TRUE(  assign_item_0_to_0 == *ptr_assign_item_0_to_0 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0 != nullptr );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getDestElemTypeId() ==
+                  st::OBJECT_TYPE_BEAM_MONITOR );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getDestBufferId() ==
+                  my_lattice_buffer_id );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getDestElemIndex() ==
+                  bm0_elem_idx );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getDestElemPointerOffset() ==
+                  offsetof( st::BeamMonitor, out_address ) );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getSrcElemTypeId() ==
+                  st::OBJECT_TYPE_PARTICLE );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getSrcBufferId() ==
+                  my_output_buffer_id );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getSrcElemIndex() ==
+                  out_buffer0_index );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getSrcElemPointerOffset() ==
+                  size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+                    ptr_assign_item_0_to_0->getCApiPtr(),
+                        ptr_my_output_buffer ) == reinterpret_cast< uintptr_t >(
+                            out_buffer0 ) );
+
+    ASSERT_TRUE(  job.has_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 1 } );
+
+    ASSERT_TRUE(  job.total_num_assign_items() == size_t{ 1 } );
+
+    ASSERT_TRUE( !job.has_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) == size_t{ 0 } );
+
+    assign_item_t* ptr_assign_item_1_to_1 = job.add_assign_address_item(
+        st::OBJECT_TYPE_BEAM_MONITOR, my_lattice_buffer_id, bm1_elem_idx,
+        offsetof( st::BeamMonitor, out_address ),
+        st::OBJECT_TYPE_PARTICLE, my_output_buffer_id, out_buffer1_index,
+        size_t{ 0 } );
+
+    ASSERT_TRUE(  ptr_assign_item_1_to_1 != nullptr );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getDestElemTypeId() ==
+                  st::OBJECT_TYPE_BEAM_MONITOR );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getDestBufferId() ==
+                  my_lattice_buffer_id );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getDestElemIndex() ==
+                  bm1_elem_idx );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getDestElemPointerOffset() ==
+                  offsetof( st::BeamMonitor, out_address ) );
+
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getSrcElemTypeId() ==
+                  st::OBJECT_TYPE_PARTICLE );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getSrcBufferId() ==
+                  my_output_buffer_id );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getSrcElemIndex() ==
+                  out_buffer1_index );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getSrcElemPointerOffset() ==
+                  size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+                    ptr_assign_item_1_to_1->getCApiPtr(),
+                        ptr_my_output_buffer ) == reinterpret_cast< uintptr_t >(
+                            out_buffer1 ) );
+
+    ASSERT_TRUE(  job.has_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 2 } );
+
+    ASSERT_TRUE(  job.total_num_assign_items() == size_t{ 2 } );
+
+    ASSERT_TRUE( !job.has_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) == size_t{ 0 } );
+
+    assign_item_t assign_item_0_to_2( assign_item_0_to_0 );
+    assign_item_0_to_2.dest_elem_index = bm2_elem_idx;
+
+    assign_item_t* ptr_assign_item_0_to_2 =
+        job.add_assign_address_item( assign_item_0_to_2 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_2 != nullptr );
+    ASSERT_TRUE(  assign_item_0_to_2 == *ptr_assign_item_0_to_2 );
+
+    ASSERT_TRUE(  job.has_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 3 } );
+
+    ASSERT_TRUE(  job.total_num_assign_items() == size_t{ 3 } );
+
+    ASSERT_TRUE( !job.has_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) == size_t{ 0 } );
+
+    st::arch_status_t status = job.commit_address_assignments();
+    ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+
+    status = job.assign_all_addresses();
+    ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+
+    status = job.collect_stored_buffer( my_lattice_buffer_id );
+    ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+
+    bm0 = reinterpret_cast< be_monitor_t* >( ::NS(BeamMonitor_from_buffer)(
+        ptr_my_lattice_buffer, bm0_elem_idx ) );
+
+    bm1 = reinterpret_cast< be_monitor_t* >( ::NS(BeamMonitor_from_buffer)(
+        ptr_my_lattice_buffer, bm1_elem_idx ) );
+
+    bm2 = reinterpret_cast< be_monitor_t* >( ::NS(BeamMonitor_from_buffer)(
+        ptr_my_lattice_buffer, bm2_elem_idx ) );
+
+    SIXTRL_ASSERT( bm0 != nullptr );
+    SIXTRL_ASSERT( bm1 != nullptr );
+    SIXTRL_ASSERT( bm2 != nullptr );
+
+    ASSERT_TRUE( bm0->out_address == reinterpret_cast< uintptr_t >(
+        out_buffer0 ) );
+
+    ASSERT_TRUE( bm1->out_address == reinterpret_cast< uintptr_t >(
+        out_buffer1 ) );
+
+    ASSERT_TRUE( bm2->out_address == reinterpret_cast< uintptr_t >(
+        out_buffer0 ) );
+}
diff --git a/tests/sixtracklib/common/track/test_track_job_cpu_stored_buffer_c99.cpp b/tests/sixtracklib/common/track/test_track_job_cpu_stored_buffer_c99.cpp
new file mode 100644
index 00000000..d4cc3e90
--- /dev/null
+++ b/tests/sixtracklib/common/track/test_track_job_cpu_stored_buffer_c99.cpp
@@ -0,0 +1,341 @@
+#include "sixtracklib/common/track_job_cpu.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer.h"
+
+TEST( C99_Cpu_CpuTrackJob_StoredBufferTests, MinimalUsage )
+{
+    using track_job_t   = ::NS(TrackJobCpu);
+    using c_buffer_t    = ::NS(Buffer);
+    using size_t        = ::NS(buffer_size_t);
+    using buffer_addr_t = ::NS(buffer_addr_t);
+
+    /* Init track-job -> should have no ext stored buffers up front: */
+
+    track_job_t* job = ::NS(TrackJobCpu_create)();
+    SIXTRL_ASSERT( job != nullptr );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_stored_buffers)( job ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) ==
+                  size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) ==
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) ==
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    /* --------------------------------------------------------------------- */
+    /* Create a buffer that is directly managed by the job */
+
+    size_t const ext_buffer_01_capacity = size_t{ 1024 };
+    size_t const ext_buffer_01_id = ::NS(TrackJob_create_stored_buffer)(
+        job, ext_buffer_01_capacity );
+
+    ASSERT_TRUE(  ext_buffer_01_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 1 } );
+    ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ext_buffer_01_id ==
+                  ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE(  ext_buffer_01_id ==
+                  ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_owns_stored_buffer)(
+        job, ext_buffer_01_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_01_id ) != nullptr );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_01_id ) != nullptr );
+
+    ASSERT_TRUE(  ext_buffer_01_capacity == ::NS(Buffer_get_capacity)(
+        ::NS(TrackJob_stored_buffer)( job, ext_buffer_01_id ) ) );
+
+    /* --------------------------------------------------------------------- */
+    /* Create an external C99 buffer that should not be managed/owned by
+     * the track job */
+
+    size_t ext_buffer_02_capacity = size_t{ 512 };
+    c_buffer_t* ext_buffer_02 = ::NS(Buffer_new)( ext_buffer_02_capacity );
+    SIXTRL_ASSERT( ext_buffer_02 != nullptr );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( ext_buffer_02 ) >=
+                    ext_buffer_02_capacity );
+
+    size_t const ext_buffer_02_id = ::NS(TrackJob_add_stored_buffer)(
+        job, ext_buffer_02, false, false ); /* false == take no ownership */
+
+    ASSERT_TRUE(  ext_buffer_02_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+    ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 2 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ext_buffer_01_id ==
+                  ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE(  ext_buffer_02_id ==
+                  ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE( !::NS(TrackJob_owns_stored_buffer)(
+        job, ext_buffer_02_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_02_id ) != nullptr );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_02_id ) == ext_buffer_02 );
+
+    /* --------------------------------------------------------------------- */
+    /* Remove ext_buffer_02 again from the track job: */
+
+    ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) ==
+        ::NS(TrackJob_remove_stored_buffer)( job, ext_buffer_02_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 1 } );
+    ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ext_buffer_01_id ==
+                  ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE(  ext_buffer_02_id ==
+                  ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE( !::NS(TrackJob_owns_stored_buffer)(
+        job, ext_buffer_02_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_02_id ) == nullptr );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_02 again, but this time let the job take ownership: */
+
+    buffer_addr_t const ext_buffer_02_begin_addr =
+        ::NS(Buffer_get_data_begin_addr)( ext_buffer_02 );
+
+    size_t const ext_buffer_02_size =
+        ::NS(Buffer_get_size)( ext_buffer_02 );
+
+    ext_buffer_02_capacity = ::NS(Buffer_get_capacity)( ext_buffer_02 );
+
+    size_t const ext_buffer_02_id_b = ::NS(TrackJob_add_stored_buffer)(
+        job, ext_buffer_02, true, true ); /* true == takes ownership */
+
+    uintptr_t const ptr_ext_buffer_02_addr =
+        reinterpret_cast< uintptr_t >( ext_buffer_02 );
+
+    ASSERT_TRUE(  ext_buffer_02_id_b != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+    ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 2 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE( ext_buffer_01_id ==
+                 ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE(  ext_buffer_02_id_b ==
+                  ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE( ::NS(TrackJob_owns_stored_buffer)(
+        job, ext_buffer_02_id_b ) );
+
+    /* After taking ownership, the buffer is accessible also as a C++ buffer;
+       but taking ownership creates a new c99 pointer as well -> you can no
+       longer access ext_buffer_02 via it's old handle */
+
+    ext_buffer_02 = nullptr;
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_02_id_b ) != nullptr );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_02_id_b ) != nullptr );
+
+    ASSERT_TRUE(  reinterpret_cast< uintptr_t >(
+        ::NS(TrackJob_stored_buffer)( job, ext_buffer_02_id_b ) ) !=
+            ptr_ext_buffer_02_addr );
+
+    /* Transfering of ownership not only invalidates the old ext_buffer_02
+     * handle, it should also "preset" it with safe default values */
+
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ext_buffer_02 ) == size_t{ 0 } );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ext_buffer_02 ) == size_t{ 0 } );
+
+    /* The values, i.e. start address, capacity and size, should still be
+     * available via the new handle */
+
+    c_buffer_t* ext_buffer_02_b = ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_02_id_b );
+
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ext_buffer_02_b ) ==
+                 ext_buffer_02_begin_addr );
+
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ext_buffer_02_b ) ==
+                 ext_buffer_02_size );
+
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ext_buffer_02_b ) ==
+                 ext_buffer_02_capacity );
+
+    ASSERT_TRUE( ::NS(TrackJob_stored_buffer)( job, ext_buffer_02_id_b )
+                 == ext_buffer_02_b );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_03, a C99 buffer on the stack: */
+
+    size_t const ext_buffer_03_capacity = size_t{ 2048 };
+    std::vector< unsigned char > ext_buffer_03_data_store(
+        ext_buffer_03_capacity );
+
+    c_buffer_t ext_buffer_03;
+    ::NS(Buffer_preset)( &ext_buffer_03 );
+    ::NS(arch_status_t) status = ::NS(Buffer_init_on_flat_memory)(
+        &ext_buffer_03, ext_buffer_03_data_store.data(),
+            ext_buffer_03_capacity );
+
+    SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+    ( void )status;
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_const_data_begin)(
+        &ext_buffer_03 ) != nullptr );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_data_begin_addr)( &ext_buffer_03 ) ==
+        reinterpret_cast< uintptr_t >( ext_buffer_03_data_store.data() ) );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( &ext_buffer_03 ) >=
+        ext_buffer_03_capacity );
+
+    size_t const ext_buffer_03_id = ::NS(TrackJob_add_stored_buffer)(
+        job, &ext_buffer_03, false, false ); /* false == take no ownership */
+
+    ASSERT_TRUE(  ext_buffer_03_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+    ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 3 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ext_buffer_01_id ==
+                  ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE(  ext_buffer_03_id ==
+                  ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE( !::NS(TrackJob_owns_stored_buffer)(
+        job, ext_buffer_03_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_03_id ) != nullptr );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)( job, ext_buffer_03_id ) ==
+                  &ext_buffer_03 );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_04, a C99 buffer on the stack, but take ownership: */
+
+    size_t ext_buffer_04_capacity = size_t{ 4096 };
+    std::vector< unsigned char > ext_buffer_04_data_store(
+        ext_buffer_04_capacity );
+
+    c_buffer_t ext_buffer_04;
+    ::NS(Buffer_preset)( &ext_buffer_04 );
+    status = ::NS(Buffer_init_on_flat_memory)( &ext_buffer_04,
+        ext_buffer_04_data_store.data(), ext_buffer_04_capacity );
+
+    SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+    buffer_addr_t const ext_buffer_04_begin_addr =
+        ::NS(Buffer_get_data_begin_addr)( &ext_buffer_04 );
+
+    size_t const ext_buffer_04_size = ::NS(Buffer_get_size)( &ext_buffer_04 );
+    ext_buffer_04_capacity = ::NS(Buffer_get_capacity)( &ext_buffer_04 );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_const_data_begin)(
+        &ext_buffer_04 ) != nullptr );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( &ext_buffer_04 ) >=
+        ext_buffer_04_capacity );
+
+    SIXTRL_ASSERT( reinterpret_cast< uintptr_t >(
+        ext_buffer_04_data_store.data() ) == ext_buffer_04_begin_addr );
+
+    size_t const ext_buffer_04_id = ::NS(TrackJob_add_stored_buffer)(
+        job, &ext_buffer_04, true, false ); /* true: take ownership,
+            false: do not delete as ext_buffer_04 is on the stack */
+
+    ASSERT_TRUE(  ext_buffer_04_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+    ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 4 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                  ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    ASSERT_TRUE(  ext_buffer_01_id ==
+                  ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE(  ext_buffer_04_id ==
+                  ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_owns_stored_buffer)(
+        job, ext_buffer_04_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_04_id ) != nullptr );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+        job, ext_buffer_04_id ) != &ext_buffer_04 );
+
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( &ext_buffer_04 ) ==
+                  buffer_addr_t{ 0 } );
+
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( &ext_buffer_04 ) == size_t{ 0 } );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( &ext_buffer_04 ) == size_t{ 0 } );
+
+    c_buffer_t* ptr_ext_buffer_04 =
+        ::NS(TrackJob_stored_buffer)( job, ext_buffer_04_id );
+
+    ASSERT_TRUE( ptr_ext_buffer_04 != nullptr );
+
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_ext_buffer_04 ) ==
+                 ext_buffer_04_capacity );
+
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_ext_buffer_04 ) ==
+                 ext_buffer_04_size );
+
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_ext_buffer_04 ) ==
+                 ext_buffer_04_begin_addr );
+
+    ::NS(TrackJob_delete)( job );
+}
+
+/* end: tests/sixtracklib/common/track/test_track_job_cpu_stored_buffer_c99.cpp */
diff --git a/tests/sixtracklib/common/track/test_track_job_cpu_stored_buffer_cxx.cpp b/tests/sixtracklib/common/track/test_track_job_cpu_stored_buffer_cxx.cpp
new file mode 100644
index 00000000..4d3bb776
--- /dev/null
+++ b/tests/sixtracklib/common/track/test_track_job_cpu_stored_buffer_cxx.cpp
@@ -0,0 +1,405 @@
+#include "sixtracklib/common/track_job_cpu.h"
+
+#include <iomanip>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer.hpp"
+#include "sixtracklib/common/buffer.h"
+
+TEST( CXX_Cpu_CpuTrackJob_StoredBufferTests, MinimalUsage )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    using track_job_t = st::TrackJobCpu;
+    using buffer_t = track_job_t::buffer_t;
+    using c_buffer_t = track_job_t::c_buffer_t;
+    using size_t = track_job_t::size_type;
+    using buffer_addr_t = ::NS(buffer_addr_t);
+
+    /* Init track-job -> should have no ext stored buffers up front: */
+
+    track_job_t job;
+
+    ASSERT_TRUE( !job.has_stored_buffers() );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 0 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() == st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() == st::ARCH_ILLEGAL_BUFFER_ID );
+
+    /* --------------------------------------------------------------------- */
+    /* Create a buffer that is directly managed by the job */
+
+    size_t const ext_buffer_01_capacity = size_t{ 1024 };
+    size_t const ext_buffer_01_id = job.add_stored_buffer( ext_buffer_01_capacity );
+
+    ASSERT_TRUE(  ext_buffer_01_id != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 1 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_01_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_01_id ) );
+
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_01_id ) != nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_01_id ) != nullptr );
+
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_01_id )->getCApiPtr()
+                    == job.ptr_stored_buffer( ext_buffer_01_id ) );
+
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_01_id )->getCapacity()
+                    == ext_buffer_01_capacity );
+
+    /* --------------------------------------------------------------------- */
+    /* Create an external C99 buffer that should not be managed/owned by
+     * the track job */
+
+    size_t ext_buffer_02_capacity = size_t{ 512 };
+    c_buffer_t* ext_buffer_02 = ::NS(Buffer_new)( ext_buffer_02_capacity );
+    SIXTRL_ASSERT( ext_buffer_02 != nullptr );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( ext_buffer_02 ) >=
+                    ext_buffer_02_capacity );
+
+    size_t const ext_buffer_02_id = job.add_stored_buffer(
+        ext_buffer_02, false ); /* false == take no ownership */
+
+    ASSERT_TRUE(  ext_buffer_02_id != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 2 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_02_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_02_id ) );
+
+    /* This is a C99 buffer -> it is not possible to access it as a C++ buffer*/
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_02_id ) == nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id ) != nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id ) == ext_buffer_02 );
+
+    /* --------------------------------------------------------------------- */
+    /* Remove ext_buffer_02 again from the track job: */
+
+    ASSERT_TRUE( st::ARCH_STATUS_SUCCESS == job.remove_stored_buffer(
+        ext_buffer_02_id ) );
+
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 1 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_02_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_02_id ) );
+
+    /* This is a C99 buffer -> it is not possible to access it as a C++ buffer*/
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_02_id ) == nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id ) == nullptr );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_02 again, but this time let the job take ownership: */
+
+    buffer_addr_t const ext_buffer_02_begin_addr =
+        ::NS(Buffer_get_data_begin_addr)( ext_buffer_02 );
+
+    size_t const ext_buffer_02_size =
+        ::NS(Buffer_get_size)( ext_buffer_02 );
+
+    ext_buffer_02_capacity = ::NS(Buffer_get_capacity)( ext_buffer_02 );
+
+    size_t const ext_buffer_02_id_b = job.add_stored_buffer(
+        ext_buffer_02, true ); /* true == takes ownership */
+
+    uintptr_t const ptr_ext_buffer_02_addr =
+        reinterpret_cast< uintptr_t >( ext_buffer_02 );
+
+    ASSERT_TRUE(  ext_buffer_02_id_b != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 2 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id   == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_02_id_b == job.max_stored_buffer_id() );
+    ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_02_id_b ) );
+
+    /* After taking ownership, the buffer is accessible also as a C++ buffer;
+       but taking ownership creates a new c99 pointer as well -> you can no
+       longer access ext_buffer_02 via it's old handle */
+
+    ext_buffer_02 = nullptr;
+
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id_b )  != nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id_b ) != nullptr );
+    ASSERT_TRUE(  reinterpret_cast< uintptr_t >( job.ptr_stored_buffer(
+                    ext_buffer_02_id_b ) ) != ptr_ext_buffer_02_addr );
+
+    /* Transfering of ownership not only invalidates the old ext_buffer_02
+     * handle, it should also "preset" it with safe default values */
+
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ext_buffer_02 ) == size_t{ 0 } );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ext_buffer_02 ) == size_t{ 0 } );
+
+    /* The values, i.e. start address, capacity and size, should still be
+     * available via the new handle */
+
+    c_buffer_t* ext_buffer_02_b = job.ptr_stored_buffer( ext_buffer_02_id_b );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ext_buffer_02_b ) ==
+                 ext_buffer_02_begin_addr );
+
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ext_buffer_02_b ) ==
+                 ext_buffer_02_size );
+
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ext_buffer_02_b ) ==
+                 ext_buffer_02_capacity );
+
+    ASSERT_TRUE( job.ptr_stored_cxx_buffer( ext_buffer_02_id_b )->getCApiPtr()
+                 == ext_buffer_02_b );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_03, a C99 buffer on the stack: */
+
+    size_t const ext_buffer_03_capacity = size_t{ 2048 };
+    std::vector< unsigned char > ext_buffer_03_data_store(
+        ext_buffer_03_capacity );
+
+    c_buffer_t ext_buffer_03;
+    ::NS(Buffer_preset)( &ext_buffer_03 );
+    ::NS(arch_status_t) status = ::NS(Buffer_init_on_flat_memory)(
+        &ext_buffer_03, ext_buffer_03_data_store.data(),
+            ext_buffer_03_capacity );
+
+    SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+    ( void )status;
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_const_data_begin)(
+        &ext_buffer_03 ) != nullptr );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_data_begin_addr)( &ext_buffer_03 ) ==
+        reinterpret_cast< uintptr_t >( ext_buffer_03_data_store.data() ) );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( &ext_buffer_03 ) >=
+        ext_buffer_03_capacity );
+
+    size_t const ext_buffer_03_id = job.add_stored_buffer(
+        &ext_buffer_03, false ); /* false == take no ownership */
+
+    ASSERT_TRUE(  ext_buffer_03_id != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 3 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_03_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_03_id ) );
+
+    /* This is a C99 buffer -> it is not possible to access it as a C++ buffer*/
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_03_id ) == nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_03_id ) != nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_03_id ) ==
+                  &ext_buffer_03 );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_04, a C99 buffer on the stack, but take ownership: */
+
+    size_t ext_buffer_04_capacity = size_t{ 4096 };
+    std::vector< unsigned char > ext_buffer_04_data_store(
+        ext_buffer_04_capacity );
+
+    c_buffer_t ext_buffer_04;
+    ::NS(Buffer_preset)( &ext_buffer_04 );
+    status = ::NS(Buffer_init_on_flat_memory)( &ext_buffer_04,
+        ext_buffer_04_data_store.data(), ext_buffer_04_capacity );
+
+    SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+    buffer_addr_t const ext_buffer_04_begin_addr =
+        ::NS(Buffer_get_data_begin_addr)( &ext_buffer_04 );
+
+    size_t const ext_buffer_04_size = ::NS(Buffer_get_size)( &ext_buffer_04 );
+    ext_buffer_04_capacity = ::NS(Buffer_get_capacity)( &ext_buffer_04 );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_const_data_begin)(
+        &ext_buffer_04 ) != nullptr );
+
+    SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( &ext_buffer_04 ) >=
+        ext_buffer_04_capacity );
+
+    SIXTRL_ASSERT( reinterpret_cast< uintptr_t >(
+        ext_buffer_04_data_store.data() ) == ext_buffer_04_begin_addr );
+
+    size_t const ext_buffer_04_id = job.add_stored_buffer(
+        &ext_buffer_04, true, false ); /* true: take ownership,
+            false: do not delete as ext_buffer_04 is on the stack */
+
+    ASSERT_TRUE(  ext_buffer_04_id != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 4 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_04_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_04_id ) );
+
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_04_id ) != nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_04_id ) != nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_04_id ) !=
+                  &ext_buffer_04 );
+
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( &ext_buffer_04 ) ==
+                  buffer_addr_t{ 0 } );
+
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( &ext_buffer_04 ) == size_t{ 0 } );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( &ext_buffer_04 ) == size_t{ 0 } );
+
+    c_buffer_t* ptr_ext_buffer_04 =
+        job.ptr_stored_buffer( ext_buffer_04_id );
+
+    ASSERT_TRUE( ptr_ext_buffer_04 != nullptr );
+
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_ext_buffer_04 ) ==
+                 ext_buffer_04_capacity );
+
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_ext_buffer_04 ) ==
+                 ext_buffer_04_size );
+
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_ext_buffer_04 ) ==
+                 ext_buffer_04_begin_addr );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_05, a C++ buffer, not taking ownership: */
+
+    size_t ext_buffer_05_capacity = size_t{ 8192 };
+    buffer_t ext_buffer_05( ext_buffer_05_capacity );
+    c_buffer_t* ext_buffer_05_cptr = ext_buffer_05.getCApiPtr();
+    SIXTRL_ASSERT( ext_buffer_05_cptr != nullptr );
+
+    ext_buffer_05_capacity = ext_buffer_05.getCapacity();
+
+    size_t const ext_buffer_05_id = job.add_stored_buffer(
+        &ext_buffer_05, false ); /* false == take no ownership */
+
+    ASSERT_TRUE(  ext_buffer_05_id != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 5 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_05_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_05_id ) );
+
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_05_id ) ==
+                  &ext_buffer_05 );
+
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_05_id ) ==
+                  ext_buffer_05_cptr );
+
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_05_id ) ==
+                  ext_buffer_05.getCApiPtr() );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_06, a C++ buffer but adding as a C99 buffer,
+     * not taking ownership: */
+
+    size_t ext_buffer_06_capacity = size_t{ 6000 };
+    buffer_t ext_buffer_06( ext_buffer_06_capacity );
+    c_buffer_t* ext_buffer_06_cptr = ext_buffer_06.getCApiPtr();
+    SIXTRL_ASSERT( ext_buffer_06_cptr != nullptr );
+
+    ext_buffer_06_capacity = ext_buffer_06.getCapacity();
+
+    size_t const ext_buffer_06_id = job.add_stored_buffer(
+        ext_buffer_06_cptr, false ); /* false == take no ownership */
+
+    ASSERT_TRUE(  ext_buffer_06_id != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 6 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_06_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_06_id ) );
+
+    /* Added as a non-owning C99 pointer -> can not access via C++ interface */
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_06_id ) == nullptr );
+
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_06_id ) ==
+                  ext_buffer_06_cptr );
+
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_06_id ) ==
+                  ext_buffer_06.getCApiPtr() );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_07, a C++ buffer, transfering ownership by moving in */
+
+    size_t ext_buffer_07_capacity = size_t{ 14000 };
+    buffer_t ext_buffer_07( ext_buffer_07_capacity );
+
+    ext_buffer_07_capacity = ext_buffer_07.getCapacity();
+
+    size_t const ext_buffer_07_size = ext_buffer_07.getSize();
+
+    buffer_addr_t const ext_buffer_07_begin_addr =
+        ext_buffer_07.getDataBeginAddr();
+
+    size_t const ext_buffer_07_id = job.add_stored_buffer(
+        std::move( ext_buffer_07 ) );
+
+    ASSERT_TRUE(  ext_buffer_07_id != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 7 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_07_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_07_id ) );
+
+    /* Added as a non-owning C99 pointer -> can not access via C++ interface */
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_07_id ) != nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_07_id ) != nullptr );
+
+    buffer_t* ptr_ext_buffer_07 = job.ptr_stored_cxx_buffer( ext_buffer_07_id );
+    ASSERT_TRUE( ptr_ext_buffer_07 != nullptr );
+    ASSERT_TRUE( ptr_ext_buffer_07->getCapacity() == ext_buffer_07_capacity );
+    ASSERT_TRUE( ptr_ext_buffer_07->getSize() == ext_buffer_07_size );
+    ASSERT_TRUE( ptr_ext_buffer_07->getDataBeginAddr() ==
+                 ext_buffer_07_begin_addr );
+
+    /* --------------------------------------------------------------------- */
+    /* Add ext_buffer_08, a C++ buffer, transfer ownership */
+
+    size_t ext_buffer_08_capacity = size_t{ 856 };
+    buffer_t* ext_buffer_08 = new buffer_t( ext_buffer_08_capacity );
+    ASSERT_TRUE( ext_buffer_08 != nullptr );
+
+    ext_buffer_08_capacity = ext_buffer_08->getCapacity();
+
+    size_t const ext_buffer_08_id =
+        job.add_stored_buffer( ext_buffer_08, true );
+
+    ASSERT_TRUE(  ext_buffer_08_id != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 8 } );
+    ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+    ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+    ASSERT_TRUE(  ext_buffer_08_id == job.max_stored_buffer_id() );
+    ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_08_id ) );
+
+    ext_buffer_08 = nullptr;
+
+    /* Added as a non-owning C99 pointer -> can not access via C++ interface */
+    ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_08_id ) != nullptr );
+    ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_08_id ) != nullptr );
+}
+
+/* end: tests/sixtracklib/common/track/test_track_job_cpu_stored_buffer_cxx.cpp */
diff --git a/tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_c99.cpp b/tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_c99.cpp
index 192e6cd5..c23f393e 100644
--- a/tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_c99.cpp
+++ b/tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_c99.cpp
@@ -46,6 +46,7 @@ TEST( C99_Cpu_CpuTrackJobTrackElemByElemTests,
 
     buffer_t* cmp_track_pb = ::NS(Buffer_new)( buf_size_t{ 0 } );
     buffer_t* cmp_output_buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
+    buffer_t* elem_by_elem_config_buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
 
     SIXTRL_ASSERT( ::NS(Particles_buffer_get_const_particles)(
         in_particles, buf_size_t{ 0 } ) != nullptr );
@@ -54,6 +55,10 @@ TEST( C99_Cpu_CpuTrackJobTrackElemByElemTests,
         ::NS(Particles_buffer_get_const_particles)(
             in_particles, buf_size_t{ 0 } ) );
 
+    elem_by_elem_config_t* elem_by_elem_config =
+        ::NS(ElemByElemConfig_new)( elem_by_elem_config_buffer );
+    SIXTRL_ASSERT( elem_by_elem_config != nullptr );
+
     SIXTRL_ASSERT( cmp_particles != nullptr );
 
     /* --------------------------------------------------------------------- */
@@ -92,10 +97,9 @@ TEST( C99_Cpu_CpuTrackJobTrackElemByElemTests,
     SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
     SIXTRL_ASSERT( max_elem_by_elem_turn_id >= pindex_t{ 0 } );
 
-    elem_by_elem_config_t elem_by_elem_config;
-    ::NS(ElemByElemConfig_preset)( &elem_by_elem_config );
+    ::NS(ElemByElemConfig_preset)( elem_by_elem_config );
 
-    status = ::NS(ElemByElemConfig_init_detailed)( &elem_by_elem_config,
+    status = ::NS(ElemByElemConfig_init_detailed)( elem_by_elem_config,
         ::NS(ELEM_BY_ELEM_ORDER_DEFAULT), min_particle_id, max_particle_id,
         min_at_element_id, max_at_element_id, min_at_turn,
         max_elem_by_elem_turn_id, true );
@@ -103,15 +107,14 @@ TEST( C99_Cpu_CpuTrackJobTrackElemByElemTests,
     SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
 
     status = ::NS(ElemByElemConfig_assign_output_buffer)(
-        &elem_by_elem_config, cmp_output_buffer,
-            elem_by_elem_out_offset_index );
+        elem_by_elem_config, cmp_output_buffer, elem_by_elem_out_offset_index );
 
     SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
 
     track_status_t track_status =
     ::NS(TestTrackCpu_track_particles_elem_by_elem_until_turn_cpu)(
         cmp_track_pb, NUM_PSETS, &track_pset_index,
-            beam_elem_buffer, &elem_by_elem_config, UNTIL_TURN_ELEM_BY_ELEM );
+            beam_elem_buffer, elem_by_elem_config, UNTIL_TURN_ELEM_BY_ELEM );
 
     SIXTRL_ASSERT( track_status == st::TRACK_SUCCESS );
 
@@ -278,6 +281,7 @@ TEST( C99_Cpu_CpuTrackJobTrackElemByElemTests,
     ::NS(Buffer_delete)( cmp_output_buffer );
     ::NS(Buffer_delete)( beam_elem_buffer );
     ::NS(Buffer_delete)( in_particles );
+    ::NS(Buffer_delete)( elem_by_elem_config_buffer );
 }
 
 /* end: tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_c99.cpp */
diff --git a/tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_cxx.cpp b/tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_cxx.cpp
index e3bfce59..a75d5bc1 100644
--- a/tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_cxx.cpp
+++ b/tests/sixtracklib/common/track/test_track_job_track_elem_by_elem_cxx.cpp
@@ -44,6 +44,7 @@ TEST( CXX_Cpu_CpuTrackJobTrackElemByElemTests,
 
     buffer_t cmp_track_pb;
     buffer_t cmp_output_buffer;
+    buffer_t elem_by_elem_config_buffer;
 
     SIXTRL_ASSERT( in_particles.get< particles_t >(
         buf_size_t{ 0 } ) != nullptr );
@@ -53,6 +54,10 @@ TEST( CXX_Cpu_CpuTrackJobTrackElemByElemTests,
 
     SIXTRL_ASSERT( cmp_particles != nullptr );
 
+    elem_by_elem_config_t* elem_by_elem_config =
+        ::NS(ElemByElemConfig_new)( elem_by_elem_config_buffer.getCApiPtr() );
+    SIXTRL_ASSERT( elem_by_elem_config != nullptr );
+
     /* --------------------------------------------------------------------- */
     /* Perform comparison tracking over lattice: */
 
@@ -89,10 +94,9 @@ TEST( CXX_Cpu_CpuTrackJobTrackElemByElemTests,
     SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
     SIXTRL_ASSERT( max_elem_by_elem_turn_id >= pindex_t{ 0 } );
 
-    elem_by_elem_config_t elem_by_elem_config;
-    ::NS(ElemByElemConfig_preset)( &elem_by_elem_config );
+    ::NS(ElemByElemConfig_preset)( elem_by_elem_config );
 
-    status = ::NS(ElemByElemConfig_init_detailed)( &elem_by_elem_config,
+    status = ::NS(ElemByElemConfig_init_detailed)( elem_by_elem_config,
         ::NS(ELEM_BY_ELEM_ORDER_DEFAULT), min_particle_id, max_particle_id,
         min_at_element_id, max_at_element_id, min_at_turn,
         max_elem_by_elem_turn_id, true );
@@ -100,7 +104,7 @@ TEST( CXX_Cpu_CpuTrackJobTrackElemByElemTests,
     SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
 
     status = ::NS(ElemByElemConfig_assign_output_buffer)(
-        &elem_by_elem_config, cmp_output_buffer.getCApiPtr(),
+        elem_by_elem_config, cmp_output_buffer.getCApiPtr(),
             elem_by_elem_out_offset_index );
 
     SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
@@ -108,7 +112,7 @@ TEST( CXX_Cpu_CpuTrackJobTrackElemByElemTests,
     track_status_t track_status =
     ::NS(TestTrackCpu_track_particles_elem_by_elem_until_turn_cpu)(
         cmp_track_pb.getCApiPtr(), NUM_PSETS, &track_pset_index,
-            beam_elem_buffer.getCApiPtr(), &elem_by_elem_config,
+            beam_elem_buffer.getCApiPtr(), elem_by_elem_config,
                 UNTIL_TURN_ELEM_BY_ELEM );
 
     SIXTRL_ASSERT( track_status == st::TRACK_SUCCESS );
diff --git a/tests/sixtracklib/common/track/test_track_job_track_line_c99.cpp b/tests/sixtracklib/common/track/test_track_job_track_line_c99.cpp
index 15c21dc0..ae846346 100644
--- a/tests/sixtracklib/common/track/test_track_job_track_line_c99.cpp
+++ b/tests/sixtracklib/common/track/test_track_job_track_line_c99.cpp
@@ -26,7 +26,7 @@
 #include "sixtracklib/common/be_monitor/be_monitor.h"
 #include "sixtracklib/common/track/track.h"
 
-TEST( C99CpuCpuTrackJobTrackLineTests, CmpWithTrackUntilTest )
+TEST( C99CpuCpuTrackJobTrackLine, CmpWithTrackUntilTest )
 {
     namespace st = SIXTRL_CXX_NAMESPACE;
 
@@ -234,21 +234,21 @@ TEST( C99CpuCpuTrackJobTrackLineTests, CmpWithTrackUntilTest )
 }
 
 
-TEST( C99CpuCpuTrackJobTrackLineTests, LostParticleBehaviour )
+TEST( C99CpuCpuTrackJobTrackLine, LostParticleBehaviour )
 {
     using npart_t = ::NS(particle_num_elements_t);
 
     ::NS(Buffer)* elements = ::NS(Buffer_new)( ::NS(buffer_size_t){ 0 } );
 
     ::NS(DriftExact)* drift0 = ::NS(DriftExact_new)( elements );
-    ::NS(MultiPole)*  quad   = ::NS(MultiPole_new)( elements, 2 );
+    ::NS(Multipole)*  quad   = ::NS(Multipole_new)( elements, 2 );
     ::NS(LimitRect)*  limit  = ::NS(LimitRect_new)( elements );
     ::NS(DriftExact)* drift1 = ::NS(DriftExact_new)( elements );
 
-    drift0 = ::NS(BeamElements_buffer_get_drift_exact)( elements, 0 );
-    quad   = ::NS(BeamElements_buffer_get_multipole)( elements, 1 );
-    limit  = ::NS(BeamElements_buffer_get_limit_rect)( elements, 2 );
-    drift1 = ::NS(BeamElements_buffer_get_drift_exact)( elements, 3 );
+    drift0 = ::NS(DriftExact_from_buffer)( elements, 0 );
+    quad   = ::NS(Multipole_from_buffer)(  elements, 1 );
+    limit  = ::NS(LimitRect_from_buffer)(  elements, 2 );
+    drift1 = ::NS(DriftExact_from_buffer)( elements, 3 );
 
     SIXTRL_ASSERT( drift0 != nullptr );
     SIXTRL_ASSERT( quad   != nullptr );
@@ -257,9 +257,9 @@ TEST( C99CpuCpuTrackJobTrackLineTests, LostParticleBehaviour )
 
     ::NS(DriftExact_set_length)( drift0, double{ 5 } );
 
-    ::NS(MultiPole_set_knl_value)( quad, 0, double{ 0 } );
-    ::NS(MultiPole_set_knl_value)( quad, 1, double{ 1e-2 } );
-    ::NS(MultiPole_set_length)( quad, double{ 1 } );
+    ::NS(Multipole_set_knl_value)( quad, 0, double{ 0 } );
+    ::NS(Multipole_set_knl_value)( quad, 1, double{ 1e-2 } );
+    ::NS(Multipole_set_length)( quad, double{ 1 } );
 
     ::NS(LimitRect_set_min_x)( limit, double{ -0.1 } );
     ::NS(LimitRect_set_max_x)( limit, double{  0.1 } );
diff --git a/tests/sixtracklib/common/track/test_track_job_track_line_cxx.cpp b/tests/sixtracklib/common/track/test_track_job_track_line_cxx.cpp
index b55fff4f..5165ce59 100644
--- a/tests/sixtracklib/common/track/test_track_job_track_line_cxx.cpp
+++ b/tests/sixtracklib/common/track/test_track_job_track_line_cxx.cpp
@@ -223,12 +223,12 @@ TEST( CXXCpuCpuTrackJobTrackLineTests, LostParticleBehaviour )
     st::Buffer elements;
 
     elements.createNew< st::DriftExact >();
-    elements.createNew< st::MultiPole >( 2 );
+    elements.createNew< st::Multipole >( 2 );
     elements.createNew< st::LimitRect >();
     elements.createNew< st::DriftExact >();
 
     st::DriftExact*  dr0 = elements.get< st::DriftExact >( 0 );
-    st::MultiPole*  quad = elements.get< st::MultiPole >( 1 );
+    st::Multipole*  quad = elements.get< st::Multipole >( 1 );
     st::LimitRect* limit = elements.get< st::LimitRect >( 2 );
     st::DriftExact*  dr1 = elements.get< st::DriftExact >( 3 );
 
diff --git a/tests/sixtracklib/cuda/track/test_track_job_collect_push_c99.cpp b/tests/sixtracklib/cuda/track/test_track_job_collect_push_c99.cpp
index 20587def..c3d72819 100644
--- a/tests/sixtracklib/cuda/track/test_track_job_collect_push_c99.cpp
+++ b/tests/sixtracklib/cuda/track/test_track_job_collect_push_c99.cpp
@@ -140,15 +140,15 @@ TEST( C99_CudaTrackJobCollectPushTests, TestCollectAndPush )
         SIXTRL_ASSERT( particles != nullptr );
 
         buffer_t* eb = ::NS(Buffer_new_from_copy)( init_eb );
-        e01_drift  = ::NS(BeamElements_buffer_get_drift)( eb, 0 );
-        e02_cavity = ::NS(BeamElements_buffer_get_cavity)( eb, 1 );
-        e03_drift  = ::NS(BeamElements_buffer_get_drift)( eb, 2 );
-        e04_limit_rect = ::NS(BeamElements_buffer_get_limit_rect)( eb, 3 );
-        e05_drift  = ::NS(BeamElements_buffer_get_drift)( eb, 4 );
-        e06_monitor = ::NS(BeamElements_buffer_get_beam_monitor)( eb, 5 );
-        e07_drift  = ::NS(BeamElements_buffer_get_drift)( eb, 6 );
-        e08_limit_ell = ::NS(BeamElements_buffer_get_limit_ellipse)( eb, 7 );
-        e09_monitor = ::NS(BeamElements_buffer_get_beam_monitor)( eb, 8 );
+        e01_drift  = ::NS(Drift_from_buffer)( eb, 0 );
+        e02_cavity = ::NS(Cavity_from_buffer)( eb, 1 );
+        e03_drift  = ::NS(Drift_from_buffer)( eb, 2 );
+        e04_limit_rect = ::NS(LimitRect_from_buffer)( eb, 3 );
+        e05_drift  = ::NS(Drift_from_buffer)( eb, 4 );
+        e06_monitor = ::NS(BeamMonitor_from_buffer)( eb, 5 );
+        e07_drift  = ::NS(Drift_from_buffer)( eb, 6 );
+        e08_limit_ell = ::NS(LimitEllipse_from_buffer)( eb, 7 );
+        e09_monitor = ::NS(BeamMonitor_from_buffer)( eb, 8 );
 
         ASSERT_TRUE( e01_drift      != nullptr );
         ASSERT_TRUE( e02_cavity     != nullptr );
@@ -198,38 +198,38 @@ TEST( C99_CudaTrackJobCollectPushTests, TestCollectAndPush )
 
         buffer_t* copy_of_eb = ::NS(Buffer_new_from_copy)( eb );
         SIXTRL_ASSERT( ::NS(Buffer_get_num_of_objects)( copy_of_eb ) == ::NS(Buffer_get_num_of_objects)( eb ) );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) != e01_drift );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) != e02_cavity );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) != e03_drift );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) != e04_limit_rect );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 4 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 4 ) != e05_drift );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) != e06_monitor );
-
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 6 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 6 ) != e07_drift );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_limit_ellipse)( copy_of_eb, 7 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_limit_ellipse)( copy_of_eb, 7 ) != e08_limit_ell );
-
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) != e09_monitor );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 0 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 0 ) != e01_drift );
+        SIXTRL_ASSERT( ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) != e02_cavity );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 2 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 2 ) != e03_drift );
+        SIXTRL_ASSERT( ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) != e04_limit_rect );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 4 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 4 ) != e05_drift );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) != e06_monitor );
+
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 6 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 6 ) != e07_drift );
+        SIXTRL_ASSERT( ::NS(LimitEllipse_from_buffer)( copy_of_eb, 7 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(LimitEllipse_from_buffer)( copy_of_eb, 7 ) != e08_limit_ell );
+
+        SIXTRL_ASSERT( ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) != e09_monitor );
 
         /* The beam monitors on the host side should have output adddr == 0: */
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_out_address)( e06_monitor ) != be_monitor_addr_t{ 0 } );
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_out_address)( e09_monitor ) != be_monitor_addr_t{ 0 } );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)( e06_monitor ) != be_monitor_addr_t{ 0 } );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)( e09_monitor ) != be_monitor_addr_t{ 0 } );
 
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_out_address)(
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) ) ==
-                       ::NS(BeamMonitor_get_out_address)( e06_monitor ) );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)(
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) ) ==
+                       ::NS(BeamMonitor_out_address)( e06_monitor ) );
 
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_out_address)(
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) ) ==
-                       ::NS(BeamMonitor_get_out_address)( e09_monitor ) );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)(
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) ) ==
+                       ::NS(BeamMonitor_out_address)( e09_monitor ) );
 
         buffer_t* copy_of_pb = ::NS(Buffer_new_from_copy)( pb );
         SIXTRL_ASSERT( ::NS(Buffer_get_num_of_objects)( copy_of_pb ) == ::NS(Buffer_get_num_of_objects)( pb ) );
@@ -263,26 +263,30 @@ TEST( C99_CudaTrackJobCollectPushTests, TestCollectAndPush )
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* beam elements: */
         SIXTRL_ASSERT( ::NS(Drift_compare_values)( e01_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) ) == 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 0 ) ) == 0 );
         ::NS(Drift_set_length)( e01_drift,
-            double{0.5} * ::NS(Drift_get_length)( e01_drift ) );
+            double{0.5} * ::NS(Drift_length)( e01_drift ) );
 
         SIXTRL_ASSERT( ::NS(Drift_compare_values)( e01_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) ) != 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 0 ) ) != 0 );
 
         SIXTRL_ASSERT( ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) == 0 );
-        ::NS(Cavity_set_voltage)( e02_cavity, double{2.0} * ::NS(Cavity_get_voltage)( e02_cavity ) );
-        ::NS(Cavity_set_frequency)( e02_cavity, double{2.0} * ::NS(Cavity_get_frequency)( e02_cavity ) );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) == 0 );
+        ::NS(Cavity_set_voltage)( e02_cavity, double{2.0} *
+            ::NS(Cavity_voltage)( e02_cavity ) );
+
+        ::NS(Cavity_set_frequency)( e02_cavity, double{2.0} *
+            ::NS(Cavity_frequency)( e02_cavity ) );
+
         ::NS(Cavity_set_lag)( e02_cavity, double{ 1.0 } );
         SIXTRL_ASSERT( ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) != 0 );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) != 0 );
 
         SIXTRL_ASSERT( ::NS(Drift_compare_values)( e03_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) ) == 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 2 ) ) == 0 );
         ::NS(Drift_set_length)( e03_drift, double{ 0.0 } );
         SIXTRL_ASSERT( ::NS(Drift_compare_values)( e03_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) ) != 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 2 ) ) != 0 );
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* output: */
@@ -326,42 +330,42 @@ TEST( C99_CudaTrackJobCollectPushTests, TestCollectAndPush )
 
         ::NS(TrackJobNew_collect_beam_elements)( job );
 
-        ASSERT_TRUE( e01_drift == ::NS(BeamElements_buffer_get_drift)(
+        ASSERT_TRUE( e01_drift == ::NS(Drift_from_buffer)(
             ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 0 ) );
 
         ASSERT_TRUE( ::NS(Drift_compare_values)( e01_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) ) == 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 0 ) ) == 0 );
 
         ASSERT_TRUE( e02_cavity ==
-            ::NS(BeamElements_buffer_get_cavity)( ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 1 ) );
+            ::NS(Cavity_from_buffer)( ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 1 ) );
 
         ASSERT_TRUE( ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) == 0 );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) == 0 );
 
         ASSERT_TRUE( e03_drift ==
-            ::NS(BeamElements_buffer_get_drift)( ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 2 ) );
+            ::NS(Drift_from_buffer)( ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 2 ) );
 
         ASSERT_TRUE( ::NS(Drift_compare_values)( e03_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) ) == 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 2 ) ) == 0 );
 
         /* Check that the collected output has output addresses */
 
         ASSERT_TRUE( e06_monitor ==
-            ::NS(BeamElements_buffer_get_beam_monitor)( ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 5 ) );
+            ::NS(BeamMonitor_from_buffer)( ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 5 ) );
 
         ASSERT_TRUE( e09_monitor ==
-            ::NS(BeamElements_buffer_get_beam_monitor)( ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 8 ) );
+            ::NS(BeamMonitor_from_buffer)( ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 8 ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( e06_monitor ) != be_monitor_addr_t{ 0 } );
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( e09_monitor ) != be_monitor_addr_t{ 0 } );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( e06_monitor ) != be_monitor_addr_t{ 0 } );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( e09_monitor ) != be_monitor_addr_t{ 0 } );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)(
-                ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) ) !=
-            ::NS(BeamMonitor_get_out_address)( e06_monitor ) );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)(
+                ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) ) !=
+            ::NS(BeamMonitor_out_address)( e06_monitor ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)(
-                ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) ) !=
-            ::NS(BeamMonitor_get_out_address)( e09_monitor ) );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)(
+                ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) ) !=
+            ::NS(BeamMonitor_out_address)( e09_monitor ) );
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* output buffer: */
@@ -392,15 +396,15 @@ TEST( C99_CudaTrackJobCollectPushTests, TestCollectAndPush )
 
         ::NS(Cavity_set_lag)( e02_cavity, double{ 2.0 } );
         SIXTRL_ASSERT( ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) != 0 );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) != 0 );
 
         SIXTRL_ASSERT( 0 == ::NS(LimitRect_compare_values)( e04_limit_rect,
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
         ::NS(LimitRect_set_min_y)( e04_limit_rect, double{ 0.0 } );
         ::NS(LimitRect_set_max_y)( e04_limit_rect, double{ 0.5 } );
         SIXTRL_ASSERT( 0 != ::NS(LimitRect_compare_values)( e04_limit_rect,
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
         ::NS(BeamMonitor_set_out_address)(
             e06_monitor, ::NS(be_monitor_addr_t){  42u } );
@@ -445,14 +449,14 @@ TEST( C99_CudaTrackJobCollectPushTests, TestCollectAndPush )
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* beam elements: */
 
-        ::NS(Cavity_set_lag)( e02_cavity, ::NS(Cavity_get_lag)(
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) );
+        ::NS(Cavity_set_lag)( e02_cavity, ::NS(Cavity_lag)(
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) );
 
-        ::NS(LimitRect_set_min_y)( e04_limit_rect, ::NS(LimitRect_get_min_y)(
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+        ::NS(LimitRect_set_min_y)( e04_limit_rect, ::NS(LimitRect_min_y)(
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
-        ::NS(LimitRect_set_max_y)( e04_limit_rect, ::NS(LimitRect_get_max_y)(
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+        ::NS(LimitRect_set_max_y)( e04_limit_rect, ::NS(LimitRect_max_y)(
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
         ::NS(BeamMonitor_set_out_address)( e06_monitor, 0u );
         ::NS(BeamMonitor_set_out_address)( e09_monitor, 0u );
@@ -503,66 +507,66 @@ TEST( C99_CudaTrackJobCollectPushTests, TestCollectAndPush )
 
         ::NS(TrackJobNew_collect_beam_elements)( job );
 
-        ASSERT_TRUE( e02_cavity == ::NS(BeamElements_buffer_get_cavity)(
+        ASSERT_TRUE( e02_cavity == ::NS(Cavity_from_buffer)(
             ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 1 ) );
 
         ASSERT_TRUE( EPS > std::fabs(
-            ::NS(Cavity_get_lag)( e02_cavity ) - double{ 2.0 } ) );
+            ::NS(Cavity_lag)( e02_cavity ) - double{ 2.0 } ) );
 
-        ::NS(Cavity_set_lag)( ::NS(BeamElements_buffer_get_cavity)(
+        ::NS(Cavity_set_lag)( ::NS(Cavity_from_buffer)(
             copy_of_eb, 1 ), double{ 2.0 } );
 
         ASSERT_TRUE( 0 == ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) );
 
 
-        ASSERT_TRUE( e04_limit_rect == ::NS(BeamElements_buffer_get_limit_rect)(
+        ASSERT_TRUE( e04_limit_rect == ::NS(LimitRect_from_buffer)(
             ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 3 ) );
 
         ASSERT_TRUE( EPS > std::fabs(
-            ::NS(LimitRect_get_min_y)( e04_limit_rect ) - double{ 0.0 } ) );
+            ::NS(LimitRect_min_y)( e04_limit_rect ) - double{ 0.0 } ) );
 
         ASSERT_TRUE( EPS > std::fabs(
-            ::NS(LimitRect_get_max_y)( e04_limit_rect ) - double{ 0.5 } ) );
+            ::NS(LimitRect_max_y)( e04_limit_rect ) - double{ 0.5 } ) );
 
-        ::NS(LimitRect_set_min_y)( ::NS(BeamElements_buffer_get_limit_rect)(
+        ::NS(LimitRect_set_min_y)( ::NS(LimitRect_from_buffer)(
             copy_of_eb, 3 ), double{ 0.0 } );
 
-        ::NS(LimitRect_set_max_y)( ::NS(BeamElements_buffer_get_limit_rect)(
+        ::NS(LimitRect_set_max_y)( ::NS(LimitRect_from_buffer)(
             copy_of_eb, 3 ), double{ 0.5 } );
 
         ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values)( e04_limit_rect,
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
         /* Check that the collected output has output addresses */
 
-        ASSERT_TRUE( e06_monitor == ::NS(BeamElements_buffer_get_beam_monitor)(
+        ASSERT_TRUE( e06_monitor == ::NS(BeamMonitor_from_buffer)(
             ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 5 ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( e06_monitor ) ==
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( e06_monitor ) ==
             ::NS(be_monitor_addr_t){ 42 } );
 
         ::NS(BeamMonitor_set_out_address)(
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ),
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ),
             ::NS(be_monitor_addr_t){ 42 } );
 
         ASSERT_TRUE( 0 == ::NS(BeamMonitor_compare_values)(
             e06_monitor,
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) ) );
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) ) );
 
-        ASSERT_TRUE( e09_monitor == ::NS(BeamElements_buffer_get_beam_monitor)(
+        ASSERT_TRUE( e09_monitor == ::NS(BeamMonitor_from_buffer)(
             ::NS(TrackJobNew_get_beam_elements_buffer)( job ), 8 ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( e09_monitor ) ==
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( e09_monitor ) ==
             ::NS(be_monitor_addr_t){ 137 } );
 
         ::NS(BeamMonitor_set_out_address)(
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ),
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ),
             ::NS(be_monitor_addr_t){ 137 } );
 
         ASSERT_TRUE( 0 == ::NS(BeamMonitor_compare_values)(
             e09_monitor,
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) ) );
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) ) );
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* output buffer: */
diff --git a/tests/sixtracklib/cuda/track/test_track_job_setup_cxx.cpp b/tests/sixtracklib/cuda/track/test_track_job_setup_cxx.cpp
index 33730644..fb8e7f6e 100644
--- a/tests/sixtracklib/cuda/track/test_track_job_setup_cxx.cpp
+++ b/tests/sixtracklib/cuda/track/test_track_job_setup_cxx.cpp
@@ -481,4 +481,54 @@ TEST( CXX_CudaTrackJobSetupTests, CreateTrackJobBeamMonitorAndElemByElem )
             NUM_BEAM_MONITORS, NUM_TURNS,  NUM_ELEM_BY_ELEM_TURNS ) );
 }
 
+TEST( CXX_CudaTrackJobSetupTests, CreateTrackJobConfigStrParsing )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    using track_job_t = st::CudaTrackJob;
+
+    track_job_t job0;
+
+    ASSERT_TRUE( job0.default_threads_per_block() ==
+                 track_job_t::DEFAULT_THREADS_PER_BLOCK );
+
+    ASSERT_TRUE( job0.default_track_threads_per_block() ==
+                 track_job_t::DEFAULT_TRACK_THREADS_PER_BLOCK );
+
+    std::string const config_str_a(
+        "cuda.threads_per_block = 32\r\n"
+        "cuda.track_threads_per_block = 512\r\n" );
+
+    track_job_t job1( config_str_a );
+
+    ASSERT_TRUE( job1.default_threads_per_block() ==
+                 track_job_t::size_type{ 32 } );
+
+    ASSERT_TRUE( job1.default_track_threads_per_block() ==
+                 track_job_t::size_type{ 512 } );
+
+    std::string const config_str_b(
+        "cuda.threads_per_block = 16\r\n"
+        "cuda.track_threads_per_block = 80\r\n" );
+
+    track_job_t job2( config_str_b );
+
+    ASSERT_TRUE( job2.default_threads_per_block() ==
+                 track_job_t::DEFAULT_THREADS_PER_BLOCK );
+
+    ASSERT_TRUE( job2.default_track_threads_per_block() ==
+                 track_job_t::DEFAULT_TRACK_THREADS_PER_BLOCK );
+
+    std::string const config_str_c( "cuda.threads_per_block = 256" );
+
+    track_job_t job3( config_str_c );
+
+    ASSERT_TRUE( job3.default_threads_per_block() ==
+                 track_job_t::size_type{ 256 } );
+
+    ASSERT_TRUE( job3.default_track_threads_per_block() ==
+                 job3.default_threads_per_block() );
+
+
+}
+
 /* end: tests/sixtracklib/cuda/track/test_track_job_setup_cxx.cpp */
diff --git a/tests/sixtracklib/cuda/wrappers/test_beam_monitor_assign_output_c99.cpp b/tests/sixtracklib/cuda/wrappers/test_beam_monitor_assign_output_c99.cpp
index 31e66cfe..c7cc4a13 100644
--- a/tests/sixtracklib/cuda/wrappers/test_beam_monitor_assign_output_c99.cpp
+++ b/tests/sixtracklib/cuda/wrappers/test_beam_monitor_assign_output_c99.cpp
@@ -90,7 +90,7 @@ TEST( C99_CudaWrappersBeamMonitorAssignOutputTests,
 
     size_t const num_beam_monitors = size_t{ 2 };
 
-    SIXTRL_ASSERT( ::NS(BeamMonitor_get_num_of_beam_monitor_objects)(
+    SIXTRL_ASSERT( ::NS(BeamMonitor_num_monitors_in_buffer)(
         beam_elements_buffer) == num_beam_monitors );
 
     /* -------------------------------------------------------------------- */
@@ -146,7 +146,8 @@ TEST( C99_CudaWrappersBeamMonitorAssignOutputTests,
 
             status =
             ::NS(CudaKernelConfig_configure_assign_output_to_beam_monitors_kernel)(
-                ptr_kernel_config, ptr_node_info, num_beam_monitors );
+                ptr_kernel_config, ptr_node_info, num_beam_monitors,
+                    size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
diff --git a/tests/sixtracklib/cuda/wrappers/test_elem_by_elem_assign_output_c99.cpp b/tests/sixtracklib/cuda/wrappers/test_elem_by_elem_assign_output_c99.cpp
index 84ea6c38..d7ddda54 100644
--- a/tests/sixtracklib/cuda/wrappers/test_elem_by_elem_assign_output_c99.cpp
+++ b/tests/sixtracklib/cuda/wrappers/test_elem_by_elem_assign_output_c99.cpp
@@ -49,6 +49,8 @@ TEST( C99_CudaWrappersElemByElemAssignOutputTests,
     c_buffer_t* beam_elements_buffer = ::NS(Buffer_new_from_file)(
         ::NS(PATH_TO_BEAMBEAM_BEAM_ELEMENTS) );
 
+    c_buffer_t* elem_by_elem_config_buffer = ::NS(Buffer_new)( size_t{ 0 } );
+
     SIXTRL_ASSERT( beam_elements_buffer != nullptr );
     SIXTRL_ASSERT( ::NS(Buffer_get_num_of_objects)( beam_elements_buffer ) >
         size_t{ 0 } );
@@ -68,6 +70,10 @@ TEST( C99_CudaWrappersElemByElemAssignOutputTests,
 
     size_t const UNTIL_TURN_ELEM_BY_ELEM = size_t{ 5 };
 
+    elem_by_elem_config_t* elem_by_elem_conf =
+        ::NS(ElemByElemConfig_new)( elem_by_elem_config_buffer );
+    SIXTRL_ASSERT( elem_by_elem_conf != nullptr );
+
     /* -------------------------------------------------------------------- */
     /* Init the Cuda controller and arguments for the addresses
      * and the particles */
@@ -122,17 +128,17 @@ TEST( C99_CudaWrappersElemByElemAssignOutputTests,
 
             status_t status =
             ::NS(CudaKernelConfig_configure_assign_output_to_elem_by_elem_config_kernel)(
-                ptr_kernel_config, ptr_node_info );
+                ptr_kernel_config, ptr_node_info, size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
             /* ************************************************************* */
 
-            elem_by_elem_config_t elem_by_elem_conf;
-            ::NS(ElemByElemConfig_preset)( &elem_by_elem_conf );
+            ::NS(ElemByElemConfig_preset)( elem_by_elem_conf );
 
-            cuda_arg_t* elem_by_elem_conf_arg = ::NS(CudaArgument_new)( ctrl );
-            SIXTRL_ASSERT( elem_by_elem_conf_arg != nullptr );
+            cuda_arg_t* elem_by_elem_conf_buffer_arg =
+                ::NS(CudaArgument_new)( ctrl );
+            SIXTRL_ASSERT( elem_by_elem_conf_buffer_arg != nullptr );
 
             cuda_arg_t* output_arg = ::NS(CudaArgument_new)( ctrl );
             SIXTRL_ASSERT( output_arg != nullptr );
@@ -148,29 +154,31 @@ TEST( C99_CudaWrappersElemByElemAssignOutputTests,
 
             status = ::NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
                 particles_buffer, num_particle_sets, &pset_indices_begin[ 0 ],
-                beam_elements_buffer, elem_by_elem_conf_arg, &elem_by_elem_conf,
+                beam_elements_buffer, elem_by_elem_conf_buffer_arg,
+                elem_by_elem_config_buffer, size_t{ 0 },
                 output_arg, output_buffer, &output_buffer_index_offset,
                 UNTIL_TURN_ELEM_BY_ELEM, result_arg );
 
             SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
 
             ::NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
-                ptr_kernel_config, elem_by_elem_conf_arg, output_arg,
-                    output_buffer_index_offset, result_arg );
+                ptr_kernel_config, elem_by_elem_conf_buffer_arg, size_t{ 0 },
+                    output_arg, output_buffer_index_offset, result_arg );
 
             status = ::NS(TestElemByElemConfigCtrlArg_evaluate_assign_output_buffer)(
-                elem_by_elem_conf_arg, &elem_by_elem_conf, output_arg,
-                output_buffer, output_buffer_index_offset, result_arg );
+                elem_by_elem_conf_buffer_arg, elem_by_elem_config_buffer,
+                    size_t{ 0 }, output_arg, output_buffer,
+                        output_buffer_index_offset, result_arg );
 
             ASSERT_TRUE( status == NS(ARCH_STATUS_SUCCESS) );
 
             /* ************************************************************* */
 
-            ::NS(Argument_delete)( elem_by_elem_conf_arg );
+            ::NS(Argument_delete)( elem_by_elem_conf_buffer_arg );
             ::NS(Argument_delete)( output_arg );
             ::NS(Argument_delete)( result_arg );
 
-            elem_by_elem_conf_arg = nullptr;
+            elem_by_elem_conf_buffer_arg = nullptr;
             result_arg = nullptr;
             output_arg = nullptr;
 
@@ -188,6 +196,7 @@ TEST( C99_CudaWrappersElemByElemAssignOutputTests,
     ::NS(Buffer_delete)( particles_buffer );
     ::NS(Buffer_delete)( output_buffer );
     ::NS(Buffer_delete)( beam_elements_buffer );
+    ::NS(Buffer_delete)( elem_by_elem_config_buffer );
 
     ::NS(Controller_delete)( ctrl );
 }
diff --git a/tests/sixtracklib/cuda/wrappers/test_particles_store_all_addresses_c99.cpp b/tests/sixtracklib/cuda/wrappers/test_particles_store_all_addresses_c99.cpp
index 55f1f186..51f739f6 100644
--- a/tests/sixtracklib/cuda/wrappers/test_particles_store_all_addresses_c99.cpp
+++ b/tests/sixtracklib/cuda/wrappers/test_particles_store_all_addresses_c99.cpp
@@ -127,7 +127,7 @@ TEST( C99_CudaWrappersParticlesStoreAddrTests, TestSingleParticleSetPerBuffer )
 
             status =
             ::NS(CudaKernelConfig_configure_fetch_particles_addresses_kernel)(
-                ptr_kernel_config, ptr_node_info, num_psets );
+                ptr_kernel_config, ptr_node_info, num_psets, size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -290,7 +290,7 @@ TEST( C99_CudaWrappersParticlesStoreAddrTests, TestMultiParticleSetsPerBuffer )
 
             status =
             ::NS(CudaKernelConfig_configure_fetch_particles_addresses_kernel)(
-                ptr_kernel_config, ptr_node_info, num_psets );
+                ptr_kernel_config, ptr_node_info, num_psets, size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -454,7 +454,7 @@ TEST( C99_CudaWrappersParticlesStoreAddrTests,
 
             status =
             ::NS(CudaKernelConfig_configure_fetch_particles_addresses_kernel)(
-                ptr_kernel_config, ptr_node_info, num_psets );
+                ptr_kernel_config, ptr_node_info, num_psets, size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
diff --git a/tests/sixtracklib/cuda/wrappers/test_track_particles_elem_by_elem_until_turn_c99.cpp b/tests/sixtracklib/cuda/wrappers/test_track_particles_elem_by_elem_until_turn_c99.cpp
index 7ae34b59..2bcfee3e 100644
--- a/tests/sixtracklib/cuda/wrappers/test_track_particles_elem_by_elem_until_turn_c99.cpp
+++ b/tests/sixtracklib/cuda/wrappers/test_track_particles_elem_by_elem_until_turn_c99.cpp
@@ -51,6 +51,9 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
     c_buffer_t* cmp_output_buffer = ::NS(Buffer_new)( buf_size_t{ 0 } );
     c_buffer_t* cmp_track_pb      = ::NS(Buffer_new)( buf_size_t{ 0 } );
 
+    c_buffer_t* elem_by_elem_config_buffer =
+        ::NS(Buffer_new)( buf_size_t{ 0 } );
+
     particles_t* cmp_particles = ::NS(Particles_add_copy)(
         cmp_track_pb, ::NS(Particles_buffer_get_const_particles)(
             in_particles_buffer, buf_size_t{ 0 } ) );
@@ -92,12 +95,13 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
 
     SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
 
-    elem_by_elem_conf_t elem_by_elem_conf;
+    elem_by_elem_conf_t* elem_by_elem_conf =
+        ::NS(ElemByElemConfig_new)( elem_by_elem_config_buffer );
 
-    ::NS(ElemByElemConfig_preset)( &elem_by_elem_conf );
+    ::NS(ElemByElemConfig_preset)( elem_by_elem_conf );
 
     status = ::NS(ElemByElemConfig_init_detailed)(
-        &elem_by_elem_conf, ::NS(ELEM_BY_ELEM_ORDER_DEFAULT),
+        elem_by_elem_conf, ::NS(ELEM_BY_ELEM_ORDER_DEFAULT),
             min_particle_id, max_particle_id, min_at_element_id,
                 max_at_element_id, min_at_turn, max_elem_by_elem_turn_id,
                     true );
@@ -105,11 +109,11 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
     SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
 
     status = ::NS(ElemByElemConfig_assign_output_buffer)(
-        &elem_by_elem_conf, cmp_output_buffer, elem_by_elem_out_idx_offset );
+        elem_by_elem_conf, cmp_output_buffer, elem_by_elem_out_idx_offset );
 
     SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
     SIXTRL_ASSERT( ::NS(ElemByElemConfig_get_output_store_address)(
-        &elem_by_elem_conf ) != ::NS(elem_by_elem_out_addr_t){ 0 } );
+        elem_by_elem_conf ) != ::NS(elem_by_elem_out_addr_t){ 0 } );
 
     /* --------------------------------------------------------------------- */
     /* Perform comparison tracking over lattice: */
@@ -117,7 +121,7 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
     track_status_t track_status =
         ::NS(TestTrackCpu_track_particles_elem_by_elem_until_turn_cpu)(
         cmp_track_pb, NUM_PSETS, &track_pset_index, eb,
-            &elem_by_elem_conf, UNTIL_TURN_ELEM_BY_ELEM );
+            elem_by_elem_conf, UNTIL_TURN_ELEM_BY_ELEM );
 
     SIXTRL_ASSERT( track_status == ::NS(TRACK_SUCCESS) );
     ( void )track_status;
@@ -188,7 +192,7 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
 
             status =
             ::NS(CudaKernelConfig_configure_assign_output_to_elem_by_elem_config_kernel)(
-                ptr_assign_kernel_config, ptr_node_info );
+                ptr_assign_kernel_config, ptr_node_info, size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -208,7 +212,8 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
             status =
             ::NS(CudaKernelConfig_configure_track_elem_by_elem_until_turn_kernel)(
                 ptr_track_kernel_config, ptr_node_info,
-                    ::NS(Particles_get_num_of_particles)( particles ) );
+                    ::NS(Particles_get_num_of_particles)( particles ),
+                        size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -231,15 +236,15 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
 
             /* ************************************************************* */
 
-            ::NS(ElemByElemConfig_preset)( &elem_by_elem_conf );
+            ::NS(ElemByElemConfig_preset)( elem_by_elem_conf );
 
             size_t output_buffer_index_offset =
                 ::NS(Buffer_get_num_of_objects)( output_buffer ) + size_t{ 1 };
 
             status = ::NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
                 track_pb, NUM_PSETS, &track_pset_index, eb,
-                elem_by_elem_conf_arg, &elem_by_elem_conf, output_arg,
-                output_buffer, &output_buffer_index_offset,
+                elem_by_elem_conf_arg, elem_by_elem_config_buffer, size_t{ 0 },
+                output_arg, output_buffer, &output_buffer_index_offset,
                 UNTIL_TURN_ELEM_BY_ELEM, result_arg );
 
             SIXTRL_ASSERT( status == NS(ARCH_STATUS_SUCCESS) );
@@ -250,12 +255,12 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
             SIXTRL_ASSERT( status == NS(ARCH_STATUS_SUCCESS) );
 
             ::NS(ElemByElemConfig_assign_out_buffer_from_offset_cuda_wrapper)(
-                ptr_assign_kernel_config, elem_by_elem_conf_arg, output_arg,
-                    output_buffer_index_offset, result_arg );
+                ptr_assign_kernel_config, elem_by_elem_conf_arg, size_t{ 0 },
+                    output_arg, output_buffer_index_offset, result_arg );
 
             ::NS(Track_particles_elem_by_elem_until_turn_cuda_wrapper)(
                 ptr_track_kernel_config, particles_arg, track_pset_index,
-                    beam_elements_arg, elem_by_elem_conf_arg,
+                    beam_elements_arg, elem_by_elem_conf_arg, size_t{ 0 },
                         UNTIL_TURN_ELEM_BY_ELEM, result_arg );
 
             status = ::NS(TestTrackCtrlArg_evaulate_tracking)(
@@ -300,6 +305,7 @@ TEST( C99_CudaWrappersTrackParticlesElemByElemUntilTurnTests,
     ::NS(Buffer_delete)( in_particles_buffer );
     ::NS(Buffer_delete)( cmp_track_pb );
     ::NS(Buffer_delete)( cmp_output_buffer );
+    ::NS(Buffer_delete)( elem_by_elem_config_buffer );
     ::NS(Buffer_delete)( eb );
 }
 
diff --git a/tests/sixtracklib/cuda/wrappers/test_track_particles_line_c99.cpp b/tests/sixtracklib/cuda/wrappers/test_track_particles_line_c99.cpp
index 52f4b664..e55d0775 100644
--- a/tests/sixtracklib/cuda/wrappers/test_track_particles_line_c99.cpp
+++ b/tests/sixtracklib/cuda/wrappers/test_track_particles_line_c99.cpp
@@ -135,7 +135,8 @@ TEST( C99_CudaWrappersTrackParticlesLineTests,
             status_t status =
             ::NS(CudaKernelConfig_configure_track_until_turn_kernel)(
                 ptr_kernel_config, ptr_node_info,
-                    ::NS(Particles_get_num_of_particles)( particles ) );
+                    ::NS(Particles_get_num_of_particles)( particles ),
+                        size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -290,7 +291,7 @@ TEST( C99_CudaWrappersTrackParticlesLineTests,
 
     buf_size_t const num_beam_monitors = buf_size_t{ 2 };
 
-    SIXTRL_ASSERT( ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) ==
+    SIXTRL_ASSERT( ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) ==
                    num_beam_monitors );
 
     /* -------------------------------------------------------------------- */
@@ -390,7 +391,8 @@ TEST( C99_CudaWrappersTrackParticlesLineTests,
 
             status =
             ::NS(CudaKernelConfig_configure_assign_output_to_beam_monitors_kernel)(
-                ptr_assign_kernel_config, ptr_node_info, num_beam_monitors );
+                ptr_assign_kernel_config, ptr_node_info, num_beam_monitors,
+                    size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -409,7 +411,8 @@ TEST( C99_CudaWrappersTrackParticlesLineTests,
 
             status = ::NS(CudaKernelConfig_configure_track_until_turn_kernel)(
                 ptr_kernel_config, ptr_node_info,
-                    ::NS(Particles_get_num_of_particles)( particles ) );
+                    ::NS(Particles_get_num_of_particles)( particles ),
+                        size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -432,7 +435,7 @@ TEST( C99_CudaWrappersTrackParticlesLineTests,
 
             /* reset the output addresses of the eb beam monitors to prepare a
              * clean slate for the gpu tracking */
-            NS(BeamMonitor_clear_all)( eb );
+            ::NS(BeamMonitor_reset_all_in_buffer)( eb );
 
             status = ::NS(TestTrackCtrlArg_prepare_tracking)(
                 particles_arg, track_pb, beam_elements_arg, eb, result_arg );
diff --git a/tests/sixtracklib/cuda/wrappers/test_track_particles_until_turn_c99.cpp b/tests/sixtracklib/cuda/wrappers/test_track_particles_until_turn_c99.cpp
index 330fc5c7..2b2f720f 100644
--- a/tests/sixtracklib/cuda/wrappers/test_track_particles_until_turn_c99.cpp
+++ b/tests/sixtracklib/cuda/wrappers/test_track_particles_until_turn_c99.cpp
@@ -134,7 +134,8 @@ TEST( C99_CudaWrappersTrackParticlesUntilTurnTests,
             status_t status =
             ::NS(CudaKernelConfig_configure_track_until_turn_kernel)(
                 ptr_kernel_config, ptr_node_info,
-                    ::NS(Particles_get_num_of_particles)( particles ) );
+                    ::NS(Particles_get_num_of_particles)( particles ),
+                        size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -247,7 +248,7 @@ TEST( C99_CudaWrappersTrackParticlesUntilTurnTests,
 
     buf_size_t const num_beam_monitors = buf_size_t{ 2 };
 
-    SIXTRL_ASSERT( ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) ==
+    SIXTRL_ASSERT( ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) ==
                    num_beam_monitors );
 
     /* -------------------------------------------------------------------- */
@@ -347,7 +348,8 @@ TEST( C99_CudaWrappersTrackParticlesUntilTurnTests,
 
             status =
             ::NS(CudaKernelConfig_configure_assign_output_to_beam_monitors_kernel)(
-                ptr_assign_kernel_config, ptr_node_info, num_beam_monitors );
+                ptr_assign_kernel_config, ptr_node_info, num_beam_monitors,
+                    size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -366,7 +368,8 @@ TEST( C99_CudaWrappersTrackParticlesUntilTurnTests,
 
             status = ::NS(CudaKernelConfig_configure_track_until_turn_kernel)(
                 ptr_kernel_config, ptr_node_info,
-                    ::NS(Particles_get_num_of_particles)( particles ) );
+                    ::NS(Particles_get_num_of_particles)( particles ),
+                        size_t{ 128 } );
 
             ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
 
@@ -389,7 +392,7 @@ TEST( C99_CudaWrappersTrackParticlesUntilTurnTests,
 
             /* reset the output addresses of the eb beam monitors to prepare a
              * clean slate for the gpu tracking */
-            NS(BeamMonitor_clear_all)( eb );
+            ::NS(BeamMonitor_reset_all_in_buffer)( eb );
 
             status = ::NS(TestTrackCtrlArg_prepare_tracking)(
                 particles_arg, track_pb, beam_elements_arg, eb, result_arg );
diff --git a/tests/sixtracklib/opencl/CMakeLists.txt b/tests/sixtracklib/opencl/CMakeLists.txt
index 3caa6c87..e8d3e464 100644
--- a/tests/sixtracklib/opencl/CMakeLists.txt
+++ b/tests/sixtracklib/opencl/CMakeLists.txt
@@ -14,7 +14,7 @@ if( GTEST_FOUND )
     add_executable( test_context_setup_opencl_c99 test_context_setup_c99.cpp )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS}
          test_context_setup_opencl_c99 )
-    add_test( C99_OpenCL_ContextSetupTests test_context_setup_opencl_c99 )
+    add_test( C99_OpenCL_Context_Setup test_context_setup_opencl_c99 )
 
     # --------------------------------------------------------------------------
     # test_context_setup_cxx:
@@ -22,21 +22,21 @@ if( GTEST_FOUND )
     add_executable( test_context_setup_opencl_cxx test_context_setup_cxx.cpp )
     set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
          test_context_setup_opencl_cxx )
-    add_test( CXX_OpenCL_ContextSetupTests test_context_setup_opencl_cxx )
+    add_test( CXX_OpenCL_Context_Setup test_context_setup_opencl_cxx )
 
     # ==========================================================================
     # test_context_opencl_c99:
 
     add_executable( test_context_opencl_c99 test_context_opencl_c99.cpp )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS} test_context_opencl_c99 )
-    add_test( C99_OpenCL_ContextTests test_context_opencl_c99 )
+    add_test( C99_OpenCL_Context test_context_opencl_c99 )
 
     # --------------------------------------------------------------------------
     # test_context_opencl_cxx:
 
     add_executable( test_context_opencl_cxx test_context_opencl_cxx.cpp )
     set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS} test_context_opencl_cxx )
-    add_test( CXX_OpenCL_ContextTests test_context_opencl_cxx )
+    add_test( CXX_OpenCL_Context test_context_opencl_cxx )
 
     # ==========================================================================
     # test_argument_update_region_opencl_c99:
@@ -47,7 +47,7 @@ if( GTEST_FOUND )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS}
          test_argument_update_region_opencl_c99 )
 
-    add_test( C99_OpenCL_ClArgumentUpdateRegionTest
+    add_test( C99_OpenCL_ClArgument_UpdateRegion
               test_argument_update_region_opencl_c99 )
 
     # --------------------------------------------------------------------------
@@ -59,7 +59,7 @@ if( GTEST_FOUND )
     set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
          test_argument_update_region_opencl_cxx )
 
-    add_test( CXX_OpenCL_ClArgumentUpdateRegionTest
+    add_test( CXX_OpenCL_ClArgument_UpdateRegion
               test_argument_update_region_opencl_cxx )
 
     # ==========================================================================
@@ -67,21 +67,21 @@ if( GTEST_FOUND )
 
     add_executable( test_buffer_opencl_c99 test_buffer_opencl_c99.cpp )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS} test_buffer_opencl_c99 )
-    add_test( C99_OpenCL_BufferTests test_buffer_opencl_c99 )
+    add_test( C99_OpenCL_Buffer test_buffer_opencl_c99 )
 
     # ==========================================================================
     # test_particles_opencl_c99:
 
     add_executable( test_particles_opencl_c99 test_particles_opencl_c99.cpp )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS} test_particles_opencl_c99 )
-    add_test( C99_OpenCL_ParticleBufferTests test_particles_opencl_c99 )
+    add_test( C99_OpenCL_Particles_Buffer test_particles_opencl_c99 )
 
     # ==========================================================================
     # test_be_drift_opencl_c99:
 
     add_executable( test_be_drift_opencl_c99 test_be_drift_opencl_c99.cpp )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS} test_be_drift_opencl_c99 )
-    add_test( C99_OpenCL_BeamElementsDriftTests test_be_drift_opencl_c99 )
+    add_test( C99_OpenCL_BeamElements_Drift test_be_drift_opencl_c99 )
 
     # ==========================================================================
     # test_track_elem_by_elem_opencl_c99:
@@ -92,22 +92,21 @@ if( GTEST_FOUND )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS}
          test_track_elem_by_elem_opencl_c99 )
 
-    add_test( C99_OpenCL_TrackElemByElemTests
-              test_track_elem_by_elem_opencl_c99 )
+    add_test( C99_OpenCL_Track_ElemByElem test_track_elem_by_elem_opencl_c99 )
 
     # ==========================================================================
     # test_be_monitor_opencl_c99:
 
     add_executable( test_be_monitor_opencl_c99 test_be_monitor_opencl_c99.cpp )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS} test_be_monitor_opencl_c99 )
-    add_test( C99_OpenCL_BeamElementsMonitorTests test_be_monitor_opencl_c99 )
+    add_test( C99_OpenCL_BeamElements_Monitor test_be_monitor_opencl_c99 )
 
     # ==========================================================================
     # test_track_opencl_c99:
 
     add_executable( test_track_opencl_c99 test_track_opencl_c99.cpp )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS} test_track_opencl_c99 )
-    add_test( C99_OpenCL_TrackParticlesTests test_track_opencl_c99 )
+    add_test( C99_OpenCL_Track_Particles test_track_opencl_c99 )
 
     # ==========================================================================
     # test_track_job_opencl_c99:
@@ -117,7 +116,7 @@ if( GTEST_FOUND )
 
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS}
          test_track_job_cl_opencl_c99 )
-    add_test( C99_OpenCL_TrackJobClTests test_track_job_cl_opencl_c99 )
+    add_test( C99_OpenCL_Track_TrackJobCl test_track_job_cl_opencl_c99 )
 
     # --------------------------------------------------------------------------
     # test_track_job_opencl_cxx:
@@ -127,7 +126,7 @@ if( GTEST_FOUND )
 
     set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
          test_track_job_cl_opencl_cxx )
-    add_test( CXX_OpenCL_TrackJobClTests test_track_job_cl_opencl_cxx )
+    add_test( CXX_OpenCL_Track_TrackJobCl test_track_job_cl_opencl_cxx )
 
     # ==========================================================================
     # test_track_job_cl_collect_push_opencl_c99:
@@ -138,11 +137,11 @@ if( GTEST_FOUND )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS}
          test_track_job_cl_collect_push_opencl_c99 )
 
-    add_test( C99_TrackJobClCollectPushTests
+    add_test( C99_Track_TrackJobCl_CollectPush
               test_track_job_cl_collect_push_opencl_c99 )
 
-    set_property( TEST C99_TrackJobClCollectPushTests APPEND PROPERTY
-        DEPENDS C99_OpenCL_TrackJobClTests )
+    set_property( TEST C99_Track_TrackJobCl_CollectPush APPEND PROPERTY
+                  DEPENDS C99_OpenCL_Track_TrackJobCl )
 
     # --------------------------------------------------------------------------
     # test_track_job_cl_collect_push_opencl_cxx:
@@ -153,11 +152,71 @@ if( GTEST_FOUND )
     set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
          test_track_job_cl_collect_push_opencl_cxx )
 
-    add_test( CXX_TrackJobClCollectPushTests
+    add_test( CXX_Track_TrackJobCl_CollectPush
               test_track_job_cl_collect_push_opencl_cxx )
 
-    set_property( TEST CXX_TrackJobClCollectPushTests APPEND PROPERTY
-        DEPENDS CXX_OpenCL_TrackJobClTests )
+    set_property( TEST CXX_Track_TrackJobCl_CollectPush APPEND PROPERTY
+        DEPENDS CXX_OpenCL_Track_TrackJobCl )
+
+    # ==========================================================================
+    # test_track_job_cl_stored_buffer_opencl_c99:
+
+    add_executable( test_track_job_cl_stored_buffer_opencl_c99
+                    test_track_job_cl_stored_buffer_c99.cpp )
+
+    set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS}
+         test_track_job_cl_stored_buffer_opencl_c99 )
+
+    add_test( C99_OpenCL_Track_TrackJobCl_StoredBuffer
+              test_track_job_cl_stored_buffer_opencl_c99 )
+
+    set_property( TEST C99_OpenCL_Track_TrackJobCl_StoredBuffer APPEND PROPERTY
+        DEPENDS C99_OpenCL_Track_TrackJobCl )
+
+    # --------------------------------------------------------------------------
+    # test_track_job_cl_stored_buffer_opencl_cxx:
+
+    add_executable( test_track_job_cl_stored_buffer_opencl_cxx
+                    test_track_job_cl_stored_buffer_cxx.cpp )
+
+    set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
+         test_track_job_cl_stored_buffer_opencl_cxx )
+
+    add_test( CXX_OpenCL_Track_TrackJobCl_StoredBuffer
+              test_track_job_cl_stored_buffer_opencl_cxx )
+
+    set_property( TEST CXX_OpenCL_Track_TrackJobCl_StoredBuffer APPEND PROPERTY
+        DEPENDS CXX_OpenCL_Track_TrackJobCl )
+
+    # ==========================================================================
+    # test_track_job_cl_assign_address_items_opencl_c99:
+
+    add_executable( test_track_job_cl_assign_address_items_opencl_c99
+                    test_track_job_cl_assign_address_items_c99.cpp )
+
+    set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS}
+         test_track_job_cl_assign_address_items_opencl_c99 )
+
+    add_test( C99_OpenCL_Track_TrackJobCl_AssignAddressItems
+              test_track_job_cl_assign_address_items_opencl_c99 )
+
+    set_property( TEST C99_OpenCL_Track_TrackJobCl_AssignAddressItems
+        APPEND PROPERTY DEPENDS C99_OpenCL_Track_TrackJobCl )
+
+    # --------------------------------------------------------------------------
+    # test_track_job_cl_assign_address_items_opencl_cxx:
+
+    add_executable( test_track_job_cl_assign_address_items_opencl_cxx
+                    test_track_job_cl_assign_address_items_cxx.cpp )
+
+    set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
+         test_track_job_cl_assign_address_items_opencl_cxx )
+
+    add_test( CXX_OpenCL_Track_TrackJobCl_AssignAddressItems
+              test_track_job_cl_assign_address_items_opencl_cxx )
+
+    set_property( TEST CXX_OpenCL_Track_TrackJobCl_AssignAddressItems
+        APPEND PROPERTY DEPENDS CXX_OpenCL_Track_TrackJobCl )
 
     # ==========================================================================
     # test_track_job_update_region_opencl_c99:
@@ -168,7 +227,7 @@ if( GTEST_FOUND )
     set( C99_UNIT_TEST_TARGETS ${C99_UNIT_TEST_TARGETS}
          test_track_job_update_region_opencl_c99 )
 
-    add_test( C99_OpenCL_ClTrackJobUpdateBeamElementsRegionTest
+    add_test( C99_OpenCL_Track_ClTrackJob_UpdateBeamElementsRegion
               test_track_job_update_region_opencl_c99 )
 
     # --------------------------------------------------------------------------
@@ -180,9 +239,32 @@ if( GTEST_FOUND )
     set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
          test_track_job_update_region_opencl_cxx )
 
-    add_test( CXX_OpenCL_ClTrackJobUpdateBeamElementsRegionTest
+    add_test( CXX_OpenCL_Track_ClTrackJob_UpdateBeamElementsRegion
               test_track_job_update_region_opencl_cxx )
 
+    # ==========================================================================
+    # test_track_job_fetch_particle_addr_opencl_c99:
+
+    add_executable( test_track_job_fetch_particle_addr_opencl_c99
+                    test_track_job_fetch_particle_addr_c99.cpp )
+
+    set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
+         test_track_job_fetch_particle_addr_opencl_c99 )
+
+    add_test( CXX_OpenCL_Track_TrackJob_FetchParticleAddr
+              test_track_job_fetch_particle_addr_opencl_c99 )
+
+    # test_track_job_fetch_particle_addr_opencl_cxx:
+
+    add_executable( test_track_job_fetch_particle_addr_opencl_cxx
+                    test_track_job_fetch_particle_addr_cxx.cpp )
+
+    set( CXX_UNIT_TEST_TARGETS ${CXX_UNIT_TEST_TARGETS}
+         test_track_job_fetch_particle_addr_opencl_cxx )
+
+    add_test( CXX_OpenCL_Track_TrackJob_FetchParticleAddr
+              test_track_job_fetch_particle_addr_opencl_cxx )
+
     # *************************************************************************
     # Set all properties:
 
@@ -223,5 +305,4 @@ if( GTEST_FOUND )
         set_property( TARGET ${CXX_UNIT_TEST_TARGETS} PROPERTY COMPILE_OPTIONS
                       ${SIXTRACKLIB_CPU_FLAGS} -Wall -Werror -pedantic )
     endif()
-
 endif()
diff --git a/tests/sixtracklib/opencl/test_argument_update_region_c99.cpp b/tests/sixtracklib/opencl/test_argument_update_region_c99.cpp
index b4d7cbf0..0c15eb28 100644
--- a/tests/sixtracklib/opencl/test_argument_update_region_c99.cpp
+++ b/tests/sixtracklib/opencl/test_argument_update_region_c99.cpp
@@ -42,7 +42,7 @@ TEST( C99_OpenCL_ClArgumentUpdateRegionTest, BasicUsage )
     for( size_t ii = size_t{ 0 } ; ii < num_beam_elements ; ++ii )
     {
         cavity_t const* ptr_cavity =
-            ::NS(BeamElements_buffer_get_const_cavity)( lattice, ii );
+            ::NS(Cavity_const_from_buffer)( lattice, ii );
 
         if( ptr_cavity != nullptr )
         {
@@ -85,7 +85,7 @@ TEST( C99_OpenCL_ClArgumentUpdateRegionTest, BasicUsage )
         {
             size_t const idx = cavity_indices[ ii ];
             cavity_t const* ptr_orig_cavity =
-                ::NS(BeamElements_buffer_get_const_cavity)( lattice, idx );
+                ::NS(Cavity_const_from_buffer)( lattice, idx );
             ASSERT_TRUE( ptr_orig_cavity != nullptr );
 
             cavity_t* ptr_cavity = &cavities[ ii ];
@@ -115,7 +115,7 @@ TEST( C99_OpenCL_ClArgumentUpdateRegionTest, BasicUsage )
         {
             size_t const idx = cavity_indices[ ii ];
             cavity_t const* ptr_orig_cavity =
-                NS(BeamElements_buffer_get_const_cavity)( lattice, idx );
+                NS(Cavity_const_from_buffer)( lattice, idx );
             ASSERT_TRUE( ptr_orig_cavity != nullptr );
 
             cavity_t* ptr_cavity = &cavities[ ii ];
@@ -149,7 +149,7 @@ TEST( C99_OpenCL_ClArgumentUpdateRegionTest, BasicUsage )
         {
             size_t const idx = cavity_indices[ ii ];
             cavity_t const* ptr_orig_cavity =
-                ::NS(BeamElements_buffer_get_const_cavity)( lattice, idx );
+                ::NS(Cavity_const_from_buffer)( lattice, idx );
             ASSERT_TRUE( ptr_orig_cavity != nullptr );
 
             cavity_t* ptr_cavity = &cavities[ ii ];
diff --git a/tests/sixtracklib/opencl/test_be_monitor_opencl_c99.cpp b/tests/sixtracklib/opencl/test_be_monitor_opencl_c99.cpp
index d754ea5c..262c1af5 100644
--- a/tests/sixtracklib/opencl/test_be_monitor_opencl_c99.cpp
+++ b/tests/sixtracklib/opencl/test_be_monitor_opencl_c99.cpp
@@ -90,19 +90,19 @@ TEST( C99_OpenCLBeamMonitorTests, AssignIoBufferToBeamMonitors )
 
         ::NS(BeamMonitor)* be_monitor = ::NS(BeamMonitor_add)( eb,
             num_stores_dist( prng ), start_dist( prng ), skip_dist( prng ),
-            addr_t{ 0 }, part_index_t{ 0 }, part_index_t{ 0 },
+            addr_t{ 0 }, part_index_t{ -1 }, part_index_t{ -1 },
                 bool{ rolling_dist( prng ) >= 0.5 }, true );
 
         ASSERT_TRUE( be_monitor != nullptr );
 
-        sum_num_of_stores += ::NS(BeamMonitor_get_num_stores)( be_monitor );
+        sum_num_of_stores += ::NS(BeamMonitor_num_stores)( be_monitor );
         cmp_beam_monitors.push_back( *be_monitor );
     }
 
     ASSERT_TRUE( ::NS(ElemByElemConfig_get_num_elem_by_elem_objects)( eb ) ==
                  NUM_BEAM_ELEMENTS );
 
-    ASSERT_TRUE( ::NS(BeamMonitor_get_num_of_beam_monitor_objects)( eb ) ==
+    ASSERT_TRUE( ::NS(BeamMonitor_num_monitors_in_buffer)( eb ) ==
                  NUM_BEAM_MONITORS );
 
     /* --------------------------------------------------------------------- */
@@ -224,17 +224,17 @@ TEST( C99_OpenCLBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     ::NS(BeamMonitor)* >( static_cast< uintptr_t >(
                         ::NS(Object_get_begin_addr)( be_it ) ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( beam_monitor )
+                ASSERT_TRUE( ::NS(BeamMonitor_out_address)( beam_monitor )
                              == addr_t{ 0 } );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_num_stores)( beam_monitor ) ==
-                    ::NS(BeamMonitor_get_num_stores)( &cmp_beam_monitor ) );
+                ASSERT_TRUE( ::NS(BeamMonitor_num_stores)( beam_monitor ) ==
+                    ::NS(BeamMonitor_num_stores)( &cmp_beam_monitor ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_skip)( beam_monitor ) ==
-                    ::NS(BeamMonitor_get_skip)( &cmp_beam_monitor ) );
+                ASSERT_TRUE( ::NS(BeamMonitor_skip)( beam_monitor ) ==
+                    ::NS(BeamMonitor_skip)( &cmp_beam_monitor ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_start)( beam_monitor ) ==
-                    ::NS(BeamMonitor_get_start)( &cmp_beam_monitor ) );
+                ASSERT_TRUE( ::NS(BeamMonitor_start)( beam_monitor ) ==
+                    ::NS(BeamMonitor_start)( &cmp_beam_monitor ) );
 
                 ASSERT_TRUE( ::NS(BeamMonitor_is_rolling)( beam_monitor ) ==
                     ::NS(BeamMonitor_is_rolling)( &cmp_beam_monitor ) );
@@ -243,11 +243,11 @@ TEST( C99_OpenCLBeamMonitorTests, AssignIoBufferToBeamMonitors )
                     beam_monitor ) == ::NS(BeamMonitor_is_turn_ordered)(
                         &cmp_beam_monitor ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)(
+                ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)(
                     beam_monitor ) <= static_cast< mon_index_t >(
                         min_particle_id ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_max_particle_id)(
+                ASSERT_TRUE( ::NS(BeamMonitor_max_particle_id)(
                     beam_monitor ) >= static_cast< mon_index_t >(
                         max_particle_id ) );
             }
@@ -291,17 +291,17 @@ TEST( C99_OpenCLBeamMonitorTests, AssignIoBufferToBeamMonitors )
                         static_cast< uintptr_t >( ::NS(Object_get_begin_addr)(
                             be_it ) ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( beam_monitor )
+                ASSERT_TRUE( ::NS(BeamMonitor_out_address)( beam_monitor )
                              != addr_t{ 0 } );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_num_stores)( beam_monitor ) ==
-                             ::NS(BeamMonitor_get_num_stores)( &cmp_beam_monitor ) );
+                ASSERT_TRUE( ::NS(BeamMonitor_num_stores)( beam_monitor ) ==
+                             ::NS(BeamMonitor_num_stores)( &cmp_beam_monitor ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_skip)( beam_monitor ) ==
-                             ::NS(BeamMonitor_get_skip)( &cmp_beam_monitor ) );
+                ASSERT_TRUE( ::NS(BeamMonitor_skip)( beam_monitor ) ==
+                             ::NS(BeamMonitor_skip)( &cmp_beam_monitor ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_start)( beam_monitor ) ==
-                             ::NS(BeamMonitor_get_start)( &cmp_beam_monitor ) );
+                ASSERT_TRUE( ::NS(BeamMonitor_start)( beam_monitor ) ==
+                             ::NS(BeamMonitor_start)( &cmp_beam_monitor ) );
 
                 ASSERT_TRUE( ::NS(BeamMonitor_is_rolling)( beam_monitor ) ==
                              ::NS(BeamMonitor_is_rolling)( &cmp_beam_monitor ) );
@@ -309,10 +309,10 @@ TEST( C99_OpenCLBeamMonitorTests, AssignIoBufferToBeamMonitors )
                 ASSERT_TRUE( ::NS(BeamMonitor_is_turn_ordered)( beam_monitor ) ==
                              ::NS(BeamMonitor_is_turn_ordered)( &cmp_beam_monitor ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_min_particle_id)( beam_monitor ) <=
+                ASSERT_TRUE( ::NS(BeamMonitor_min_particle_id)( beam_monitor ) <=
                              static_cast< mon_index_t >( min_particle_id ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_max_particle_id)( beam_monitor ) >=
+                ASSERT_TRUE( ::NS(BeamMonitor_max_particle_id)( beam_monitor ) >=
                              static_cast< mon_index_t >( max_particle_id ) );
             }
         }
@@ -339,7 +339,7 @@ TEST( C99_OpenCLBeamMonitorTests, AssignIoBufferToBeamMonitors )
                         static_cast< uintptr_t >( ::NS(Object_get_begin_addr)(
                             be_it ) ) );
 
-                ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( beam_monitor )
+                ASSERT_TRUE( ::NS(BeamMonitor_out_address)( beam_monitor )
                              == addr_t{ 0 } );
 
                 ASSERT_TRUE( 0 == ::NS(BeamMonitor_compare_values)(
@@ -406,12 +406,12 @@ TEST( C99_OpenCLBeamMonitorTests, TrackingAndTurnByTurnIODebug )
         ASSERT_TRUE( be_monitor != nullptr );
 
         nturn_t const num_stores =
-            ::NS(BeamMonitor_get_num_stores)( be_monitor );
+            ::NS(BeamMonitor_num_stores)( be_monitor );
 
         ASSERT_TRUE( num_stores > nturn_t{ 0 } );
 
-        nturn_t const skip  = ::NS(BeamMonitor_get_skip)( be_monitor );
-        nturn_t const start = ::NS(BeamMonitor_get_start)( be_monitor );
+        nturn_t const skip  = ::NS(BeamMonitor_skip)( be_monitor );
+        nturn_t const start = ::NS(BeamMonitor_start)( be_monitor );
         nturn_t const n     = num_stores * skip;
 
         if( max_num_turns  < n     ) max_num_turns  = n;
@@ -1123,7 +1123,7 @@ namespace sixtrack
                         ptr_const_mon_t mon = reinterpret_cast< ptr_const_mon_t
                             >( ::NS(Object_get_const_begin_ptr)( obj_it ) );
 
-                        if( ::NS(BeamMonitor_get_out_address)(
+                        if( ::NS(BeamMonitor_out_address)(
                                 mon ) == addr_t{ 0 } )
                         {
                             success = false;
@@ -1136,16 +1136,16 @@ namespace sixtrack
                             continue;
                         }
 
-                        success &= ( ::NS(BeamMonitor_get_start)( mon ) <= kk );
-                        success &= ( ( ( kk - ::NS(BeamMonitor_get_start)(
-                            mon ) ) % ::NS(BeamMonitor_get_skip)( mon ) ) ==
+                        success &= ( ::NS(BeamMonitor_start)( mon ) <= kk );
+                        success &= ( ( ( kk - ::NS(BeamMonitor_start)(
+                            mon ) ) % ::NS(BeamMonitor_skip)( mon ) ) ==
                                 nturn_t{ 0 } );
 
                         if( !success ) break;
 
                         ptr_particles_t out_particles = reinterpret_cast<
                             ptr_particles_t >( static_cast< uintptr_t >(
-                                ::NS(BeamMonitor_get_out_address)( mon ) ) );
+                                ::NS(BeamMonitor_out_address)( mon ) ) );
 
                         success &= ( elem_by_elem_particles != nullptr );
                         if( !success ) break;
@@ -1277,7 +1277,7 @@ namespace sixtrack
                                 static_cast< uintptr_t >(
                                     ::NS(Object_get_begin_addr)( obj_it ) ) );
 
-                        success &= ( ::NS(BeamMonitor_get_out_address)(
+                        success &= ( ::NS(BeamMonitor_out_address)(
                             beam_monitor ) == addr_t{ 0 } );
                     }
 
diff --git a/tests/sixtracklib/opencl/test_track_elem_by_elem_opencl_c99.cpp b/tests/sixtracklib/opencl/test_track_elem_by_elem_opencl_c99.cpp
index 447daf16..4aba9d54 100644
--- a/tests/sixtracklib/opencl/test_track_elem_by_elem_opencl_c99.cpp
+++ b/tests/sixtracklib/opencl/test_track_elem_by_elem_opencl_c99.cpp
@@ -313,6 +313,7 @@ namespace SIXTRL_CXX_NAMESPACE
 
             ::NS(Buffer)* pb = ::NS(Buffer_new)( 0u );
             ::NS(Buffer)* output_buffer = ::NS(Buffer_new)( 0u );
+            ::NS(Buffer)* elem_by_elem_config_buffer = ::NS(Buffer_new)( 0u );
 
             if( ( num_elem_by_elem_objects >= size_t{ 3 } ) &&
                 ( pb != nullptr ) && ( beam_elements_buffer != nullptr ) &&
@@ -380,9 +381,10 @@ namespace SIXTRL_CXX_NAMESPACE
             /* ------------------------------------------------------------- */
             /* Create ClArguments for beam elements & the particles buffer   */
 
-            ::NS(ClArgument)* particles_buffer_arg = nullptr;
-            ::NS(ClArgument)* beam_elements_arg    = nullptr;
-            ::NS(ClArgument)* output_buffer_arg    = nullptr;
+            ::NS(ClArgument)* particles_buffer_arg    = nullptr;
+            ::NS(ClArgument)* beam_elements_arg       = nullptr;
+            ::NS(ClArgument)* output_buffer_arg       = nullptr;
+            ::NS(ClArgument)* elem_by_elem_config_arg = nullptr;
 
             if( success )
             {
@@ -410,23 +412,35 @@ namespace SIXTRL_CXX_NAMESPACE
             /* Track for num-turns without assigned beam-monitors -> should
              * not change the correctness of tracking at all */
 
-            cl_mem elem_by_elem_config_arg =
-                ::NS(ClContext_create_elem_by_elem_config_arg)( context );
+            ::NS(ElemByElemConfig)* elem_by_elem_config =
+                ::NS(ElemByElemConfig_new)( elem_by_elem_config_buffer );
 
-            size_t const pset_indices[] = { size_t{ 0 } };
+            ::NS(ElemByElemConfig_preset)( elem_by_elem_config );
 
-            ::NS(ElemByElemConfig) elem_by_elem_config;
+            size_t const pset_indices[] = { size_t{ 0 } };
 
             if( success )
             {
-                status = ::NS(ClContext_init_elem_by_elem_config_arg)(
-                    context, elem_by_elem_config_arg, &elem_by_elem_config,
-                    ::NS(ClArgument_get_ptr_cobj_buffer)( particles_buffer_arg ),
-                    size_t{ 1 }, &pset_indices[ 0 ],
-                    ::NS(ClArgument_get_ptr_cobj_buffer)( beam_elements_arg ),
-                    num_turns, 0u );
+                elem_by_elem_config_arg = ::NS(ClArgument_new_from_buffer)(
+                    elem_by_elem_config_buffer, context );
 
-                success = ( status == ::NS(ARCH_STATUS_SUCCESS) );
+                status = ::NS(ElemByElemConfig_init_on_particle_sets)(
+                    elem_by_elem_config, pb, 1u, &pset_indices[ 0 ],
+                        beam_elements_buffer, 0, num_turns );
+
+                if( ( elem_by_elem_config_arg != nullptr ) &&
+                    ( status == st::ARCH_STATUS_SUCCESS ) )
+                {
+                    ::NS(ElemByElemConfig_set_output_store_address)(
+                        elem_by_elem_config, uintptr_t{ 0 } );
+
+                    success = ::NS(ClArgument_write)(
+                        elem_by_elem_config_arg, elem_by_elem_config_buffer );
+                }
+                else
+                {
+                    success = false;
+                }
 
                 if( !success )
                 {
@@ -481,9 +495,15 @@ namespace SIXTRL_CXX_NAMESPACE
                     std::cout << "status 05e : " << status << std::endl;
                 }
 
-                status = ::NS(ClContext_assign_elem_by_elem_config_arg)(
+                status = ::NS(ClContext_assign_elem_by_elem_config_buffer_arg)(
                     context, elem_by_elem_config_arg );
 
+                if( status == st::ARCH_STATUS_SUCCESS )
+                {
+                    status = ::NS(ClContext_assign_elem_by_elem_config_index_arg)(
+                        context, size_t{ 0 } );
+                }
+
                 success &= ( status == st::ARCH_STATUS_SUCCESS );
 
                 if( !success )
@@ -597,15 +617,14 @@ namespace SIXTRL_CXX_NAMESPACE
                 }
             }
 
-            ::NS(ClContext_delete_elem_by_elem_config_arg)(
-                context, elem_by_elem_config_arg );
-
             ::NS(ClArgument_delete)( particles_buffer_arg );
             ::NS(ClArgument_delete)( beam_elements_arg );
             ::NS(ClArgument_delete)( output_buffer_arg );
+            ::NS(ClArgument_delete)( elem_by_elem_config_arg );
 
             ::NS(Buffer_delete)( pb );
             ::NS(Buffer_delete)( output_buffer );
+            ::NS(Buffer_delete)( elem_by_elem_config_buffer );
 
             return success;
         }
diff --git a/tests/sixtracklib/opencl/test_track_job_cl_assign_address_items_c99.cpp b/tests/sixtracklib/opencl/test_track_job_cl_assign_address_items_c99.cpp
new file mode 100644
index 00000000..368936cc
--- /dev/null
+++ b/tests/sixtracklib/opencl/test_track_job_cl_assign_address_items_c99.cpp
@@ -0,0 +1,501 @@
+#include "sixtracklib/opencl/track_job_cl.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iostream>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer.h"
+#include "sixtracklib/common/buffer/assign_address_item.h"
+#include "sixtracklib/common/be_drift/be_drift.h"
+#include "sixtracklib/common/be_monitor/be_monitor.h"
+#include "sixtracklib/common/particles.h"
+#include "sixtracklib/opencl/internal/base_context.h"
+
+
+TEST( C99OpenCLTrackJobClAssignAddressItemsTests, MinimalUsage )
+{
+    using track_job_t    = ::NS(TrackJobCl);
+    using size_t         = ::NS(arch_size_t);
+    using assign_item_t  = ::NS(AssignAddressItem);
+    using c_buffer_t     = ::NS(Buffer);
+    using particle_set_t = ::NS(Particles);
+    using addr_t         = ::NS(buffer_addr_t);
+    using controller_t   = ::NS(ClContextBase);
+    using node_id_t      = ::NS(ComputeNodeId);
+    using status_t       = ::NS(arch_status_t);
+
+    if( ::NS(OpenCL_num_available_nodes)( nullptr ) == 0 )
+    {
+        std::cout << "No OpenCL nodes available -> skipping test\r\n";
+        return;
+    }
+
+    c_buffer_t* my_lattice = ::NS(Buffer_new)( size_t{ 0 } );
+    c_buffer_t* my_output_buffer = ::NS(Buffer_new)( size_t{ 0 } );
+
+    ::NS(Drift)* dr = ::NS(Drift_add)( my_lattice, 0.0 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.1 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.2 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    size_t const bm0_elem_idx = ::NS(Buffer_get_num_of_objects)( my_lattice );
+
+    ::NS(BeamMonitor)* bm0 = ::NS(BeamMonitor_new)( my_lattice );
+    SIXTRL_ASSERT( bm0 != nullptr );
+    ( void )bm0;
+
+    dr = ::NS(Drift_add)( my_lattice, 0.0 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.1 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.2 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    size_t const bm1_elem_idx = ::NS(Buffer_get_num_of_objects)( my_lattice );
+    SIXTRL_ASSERT( bm1_elem_idx > bm0_elem_idx );
+
+    ::NS(BeamMonitor)* bm1 = ::NS(BeamMonitor_new)( my_lattice );
+    SIXTRL_ASSERT( bm1 != nullptr );
+    ( void )bm1;
+
+    dr = ::NS(Drift_add)( my_lattice, 0.3 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.4 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = ::NS(Drift_add)( my_lattice, 0.5 );
+    SIXTRL_ASSERT( dr != nullptr );
+    ( void )dr;
+
+    size_t const bm2_elem_idx = ::NS(Buffer_get_num_of_objects)( my_lattice );
+    SIXTRL_ASSERT( bm2_elem_idx > bm1_elem_idx );
+
+    ::NS(BeamMonitor)* bm2 = ::NS(BeamMonitor_new)( my_lattice );
+    SIXTRL_ASSERT( bm2 != nullptr );
+    ( void )bm2;
+
+    size_t const out_buffer0_index =
+        ::NS(Buffer_get_num_of_objects)( my_output_buffer );
+
+    particle_set_t* out_buffer0 =
+        ::NS(Particles_new)( my_output_buffer, size_t{ 100 } );
+    SIXTRL_ASSERT( out_buffer0 );
+
+    size_t const out_buffer1_index =
+        ::NS(Buffer_get_num_of_objects)( my_output_buffer );
+
+    particle_set_t* out_buffer1 =
+        ::NS(Particles_new)( my_output_buffer, size_t{ 512 } );
+    SIXTRL_ASSERT( out_buffer1 );
+
+    ::NS(buffer_addr_t) const my_lattice_buffer_addr =
+        ::NS(Buffer_get_data_begin_addr)( my_lattice );
+
+    size_t const my_lattice_buffer_size =
+        ::NS(Buffer_get_size)( my_lattice );
+
+    size_t const my_lattice_buffer_capacity =
+        ::NS(Buffer_get_capacity)( my_lattice );
+
+    size_t const my_lattice_buffer_num_objects =
+        ::NS(Buffer_get_num_of_objects)( my_lattice );
+
+    ::NS(buffer_addr_t) const my_output_buffer_addr =
+        ::NS(Buffer_get_data_begin_addr)( my_output_buffer );
+
+    size_t const my_output_buffer_size =
+        ::NS(Buffer_get_size)( my_output_buffer );
+
+    size_t const my_output_buffer_capacity =
+        ::NS(Buffer_get_capacity)( my_output_buffer );
+
+    size_t const my_output_buffer_num_objects =
+        ::NS(Buffer_get_num_of_objects)( my_output_buffer );
+
+
+    out_buffer0 = ::NS(Particles_buffer_get_particles)(
+        my_output_buffer, out_buffer0_index );
+
+    out_buffer1 = ::NS(Particles_buffer_get_particles)(
+        my_output_buffer, out_buffer1_index );
+
+    /* --------------------------------------------------------------------- */
+
+    node_id_t node_id;
+
+    size_t const num_nodes = ::NS(OpenCL_get_available_nodes)(
+        &node_id, size_t{ 1 } );
+
+    ASSERT_TRUE( num_nodes == size_t{ 1 } );
+
+    char NODE_ID_STR[ 32 ] =
+    {
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+    };
+
+    status_t status = ::NS(ComputeNodeId_to_string_with_format)(
+        &node_id, &NODE_ID_STR[ 0 ], size_t{ 32 }, ::NS(ARCHITECTURE_OPENCL),
+            ::NS(NODE_ID_STR_FORMAT_NOARCH) );
+
+    SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+    track_job_t* job = ::NS(TrackJobCl_create)( NODE_ID_STR );
+    controller_t* controller = ::NS(TrackJobCl_get_context)( job );
+
+    ASSERT_TRUE( controller != nullptr );
+    ASSERT_TRUE( ::NS(ClContextBase_has_selected_node)( controller ) );
+
+    char SELECTED_NODE_ID_STR[ 32 ] =
+    {
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+    };
+
+    ASSERT_TRUE( ::NS(ClContextBase_get_selected_node_id_str)( controller,
+        SELECTED_NODE_ID_STR, 32 ) );
+
+    ASSERT_TRUE( std::strcmp( NODE_ID_STR, SELECTED_NODE_ID_STR ) == 0 );
+
+    /* --------------------------------------------------------------------- */
+
+    size_t const my_lattice_buffer_id = ::NS(TrackJob_add_stored_buffer)(
+        job, my_lattice, false, false );
+
+    ASSERT_TRUE( my_lattice_buffer_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+    size_t const my_output_buffer_id = ::NS(TrackJob_add_stored_buffer)(
+        job, my_output_buffer, false, false );
+
+    c_buffer_t* ptr_my_lattice_buffer = nullptr;
+    c_buffer_t* ptr_my_output_buffer  = nullptr;
+
+    ASSERT_TRUE( my_output_buffer_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+    ASSERT_TRUE( my_output_buffer_id > my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ::NS(TrackJob_is_buffer_by_buffer_id)(
+        job, my_lattice_buffer_id ) );
+
+    ASSERT_TRUE( !::NS(TrackJob_is_raw_memory_by_buffer_id)(
+        job, my_lattice_buffer_id ) );
+
+    ptr_my_lattice_buffer = ::NS(TrackJob_buffer_by_buffer_id)(
+        job, my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ptr_my_lattice_buffer != nullptr );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_addr );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_size );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_capacity );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_num_objects );
+
+    ptr_my_output_buffer = ::NS(TrackJob_buffer_by_buffer_id)(
+        job, my_output_buffer_id );
+
+    ASSERT_TRUE( ptr_my_output_buffer != nullptr );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_my_output_buffer ) ==
+                    my_output_buffer_addr );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_my_output_buffer ) ==
+                    my_output_buffer_size );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_my_output_buffer ) ==
+                    my_output_buffer_capacity );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_my_output_buffer ) ==
+                    my_output_buffer_num_objects );
+
+    ASSERT_TRUE(  ::NS(TrackJob_is_buffer_by_buffer_id)(
+        job, my_output_buffer_id ) );
+
+    ASSERT_TRUE( !::NS(TrackJob_is_raw_memory_by_buffer_id)(
+        job, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_buffer_by_buffer_id)(
+        job, my_output_buffer_id ) == ptr_my_output_buffer );
+
+    ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)( job, my_output_buffer_id ) ==
+        ptr_my_output_buffer );
+
+    /* --------------------------------------------------------------------- */
+
+    assign_item_t assign_item_0_to_0;
+    ::NS(AssignAddressItem_preset)( &assign_item_0_to_0 );
+
+    ::NS(AssignAddressItem_set_dest_elem_type_id)(
+        &assign_item_0_to_0, ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+    ::NS(AssignAddressItem_set_dest_buffer_id)(
+        &assign_item_0_to_0, my_lattice_buffer_id );
+
+    ::NS(AssignAddressItem_set_dest_elem_index)(
+        &assign_item_0_to_0, bm0_elem_idx );
+
+    ::NS(AssignAddressItem_set_dest_pointer_offset)(
+        &assign_item_0_to_0, offsetof( ::NS(BeamMonitor), out_address ) );
+
+    ::NS(AssignAddressItem_set_src_elem_type_id)(
+        &assign_item_0_to_0, ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ::NS(AssignAddressItem_set_src_buffer_id)(
+        &assign_item_0_to_0, my_output_buffer_id );
+
+    ::NS(AssignAddressItem_set_src_elem_index)(
+        &assign_item_0_to_0, out_buffer0_index );
+
+    ::NS(AssignAddressItem_set_src_pointer_offset)(
+        &assign_item_0_to_0, size_t{ 0 } );
+
+
+    ASSERT_TRUE(  ::NS(TrackJob_total_num_assign_items)( job ) == size_t{ 0 } );
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_address_item)(
+        job, &assign_item_0_to_0 ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 0 } );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+
+    assign_item_t* ptr_assign_item_0_to_0 =
+        ::NS(TrackJob_add_assign_address_item)( job, &assign_item_0_to_0 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0 != nullptr );
+    ASSERT_TRUE(  ::NS(AssignAddressItem_are_equal)(
+                        &assign_item_0_to_0, ptr_assign_item_0_to_0 ) );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0 != nullptr );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_elem_type_id)(
+                    ptr_assign_item_0_to_0 ) == ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_buffer_id)(
+                    ptr_assign_item_0_to_0 ) == my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_elem_index)(
+                    ptr_assign_item_0_to_0 ) == bm0_elem_idx );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_pointer_offset)(
+                    ptr_assign_item_0_to_0 ) ==
+                    offsetof( ::NS(BeamMonitor), out_address ) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_elem_type_id)(
+                    ptr_assign_item_0_to_0 ) == ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_buffer_id)(
+                    ptr_assign_item_0_to_0 ) == my_output_buffer_id );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_elem_index)(
+                    ptr_assign_item_0_to_0 ) == out_buffer0_index );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_offset)(
+                    ptr_assign_item_0_to_0 ) == size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+                        ptr_assign_item_0_to_0, ptr_my_output_buffer ) ==
+                            reinterpret_cast< uintptr_t >( out_buffer0 ) );
+
+
+    ASSERT_TRUE(  ::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 1 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_total_num_assign_items)( job ) == size_t{ 1 } );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) == size_t{ 0 } );
+
+    size_t const item_0_to_0_index = ::NS(TrackJob_index_of_assign_address_item)(
+        job, ptr_assign_item_0_to_0 );
+
+    ASSERT_TRUE( item_0_to_0_index < ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    assign_item_t assign_item_1_to_1;
+    ::NS(AssignAddressItem_preset)( &assign_item_1_to_1 );
+
+    ::NS(AssignAddressItem_set_dest_elem_type_id)(
+        &assign_item_1_to_1, ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+    ::NS(AssignAddressItem_set_dest_buffer_id)(
+        &assign_item_1_to_1, my_lattice_buffer_id );
+
+    ::NS(AssignAddressItem_set_dest_elem_index)(
+        &assign_item_1_to_1, bm1_elem_idx );
+
+    ::NS(AssignAddressItem_set_dest_pointer_offset)(
+        &assign_item_1_to_1, offsetof( ::NS(BeamMonitor), out_address ) );
+
+    ::NS(AssignAddressItem_set_src_elem_type_id)(
+        &assign_item_1_to_1, ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ::NS(AssignAddressItem_set_src_buffer_id)(
+        &assign_item_1_to_1, my_output_buffer_id );
+
+    ::NS(AssignAddressItem_set_src_elem_index)(
+        &assign_item_1_to_1, out_buffer1_index );
+
+    ::NS(AssignAddressItem_set_src_pointer_offset)(
+        &assign_item_1_to_1, size_t{ 0 } );
+
+    ASSERT_TRUE( ::NS(TrackJob_ptr_assign_address_item)(
+        job, &assign_item_1_to_1 ) == nullptr );
+
+    ASSERT_TRUE( ::NS(TrackJob_ptr_assign_address_item_detailed)(
+        job, ::NS(OBJECT_TYPE_BEAM_MONITOR), my_lattice_buffer_id,
+            bm1_elem_idx, offsetof( ::NS(BeamMonitor), out_address ),
+                ::NS(OBJECT_TYPE_PARTICLE), my_output_buffer_id,
+                    out_buffer1_index, size_t{ 0 } ) == nullptr );
+
+    /* --------------------------------------------------------------------- */
+
+    assign_item_t* ptr_assign_item_1_to_1 =
+    ::NS(TrackJob_add_assign_address_item_detailed)( job,
+        ::NS(OBJECT_TYPE_BEAM_MONITOR), my_lattice_buffer_id, bm1_elem_idx,
+            offsetof( ::NS(BeamMonitor), out_address ),
+                ::NS(OBJECT_TYPE_PARTICLE), my_output_buffer_id,
+                    out_buffer1_index, size_t{ 0 } );
+
+    ASSERT_TRUE(  ptr_assign_item_1_to_1 != nullptr );
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_elem_type_id)(
+                    ptr_assign_item_1_to_1 ) == ::NS(OBJECT_TYPE_BEAM_MONITOR) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_buffer_id)(
+                    ptr_assign_item_1_to_1 ) == my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_elem_index)(
+                    ptr_assign_item_1_to_1 ) == bm1_elem_idx );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_dest_pointer_offset)(
+                    ptr_assign_item_1_to_1 ) == offsetof(
+                        ::NS(BeamMonitor), out_address ) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_elem_type_id)(
+                    ptr_assign_item_1_to_1 ) == ::NS(OBJECT_TYPE_PARTICLE) );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_buffer_id)(
+                    ptr_assign_item_1_to_1 ) == my_output_buffer_id );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_elem_index)(
+                    ptr_assign_item_1_to_1 ) == out_buffer1_index );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_offset)(
+                    ptr_assign_item_1_to_1 ) == size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+                        ptr_assign_item_1_to_1, ptr_my_output_buffer ) ==
+                            reinterpret_cast< uintptr_t >( out_buffer1 ) );
+
+
+    ASSERT_TRUE(  ::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 2 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_total_num_assign_items)(
+        job ) == size_t{ 2 } );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) == size_t{ 0 } );
+
+    size_t const item_1_to_1_index = ::NS(TrackJob_index_of_assign_address_item)(
+        job, ptr_assign_item_1_to_1 );
+
+    ASSERT_TRUE( item_1_to_1_index < ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    /* --------------------------------------------------------------------- */
+
+    assign_item_t assign_item_0_to_2 = assign_item_0_to_0;
+
+    ::NS(AssignAddressItem_set_dest_elem_index)(
+        &assign_item_0_to_2, bm2_elem_idx );
+
+    assign_item_t* ptr_assign_item_0_to_2 =
+        ::NS(TrackJob_add_assign_address_item)( job, &assign_item_0_to_2 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_2 != nullptr );
+    ASSERT_TRUE(  ::NS(AssignAddressItem_are_equal)(
+        &assign_item_0_to_2, ptr_assign_item_0_to_2 ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 3 } );
+
+    ASSERT_TRUE(  ::NS(TrackJob_total_num_assign_items)(
+        job ) == size_t{ 3 } );
+
+    ASSERT_TRUE( !::NS(TrackJob_has_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) );
+
+    ASSERT_TRUE(  ::NS(TrackJob_num_assign_items)( job,
+        my_lattice_buffer_id, ::NS(ARCH_OUTPUT_BUFFER_ID) ) == size_t{ 0 } );
+
+    /* --------------------------------------------------------------------- */
+
+    status = ::NS(TrackJob_commit_address_assignments)( job );
+    ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+    status = ::NS(TrackJob_assign_all_addresses)( job );
+    ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+    status = ::NS(TrackJob_collect_stored_buffer)( job, my_lattice_buffer_id );
+    ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+    bm0 = ::NS(BeamMonitor_from_buffer)( ptr_my_lattice_buffer, bm0_elem_idx );
+    bm1 = ::NS(BeamMonitor_from_buffer)( ptr_my_lattice_buffer, bm1_elem_idx );
+    bm2 = ::NS(BeamMonitor_from_buffer)( ptr_my_lattice_buffer, bm2_elem_idx );
+
+    SIXTRL_ASSERT( bm0 != nullptr );
+    SIXTRL_ASSERT( bm1 != nullptr );
+    SIXTRL_ASSERT( bm2 != nullptr );
+
+    ASSERT_TRUE( bm0->out_address != addr_t{ 0 } );
+    ASSERT_TRUE( bm1->out_address != addr_t{ 0 } );
+    ASSERT_TRUE( bm2->out_address != addr_t{ 0 } );
+
+    ASSERT_TRUE( bm0->out_address == bm2->out_address );
+    ASSERT_TRUE( bm1->out_address != bm0->out_address );
+    ASSERT_TRUE( bm0->out_address <  bm1->out_address );
+
+    ASSERT_TRUE( ( bm1->out_address - bm0->out_address ) ==
+        static_cast< addr_t >(
+            reinterpret_cast< uintptr_t >( out_buffer1 ) -
+            reinterpret_cast< uintptr_t >( out_buffer0 ) ) );
+
+    /* --------------------------------------------------------------------- */
+
+    ::NS(TrackJob_delete)( job );
+    ::NS(Buffer_delete)( my_lattice );
+    ::NS(Buffer_delete)( my_output_buffer );
+}
diff --git a/tests/sixtracklib/opencl/test_track_job_cl_assign_address_items_cxx.cpp b/tests/sixtracklib/opencl/test_track_job_cl_assign_address_items_cxx.cpp
new file mode 100644
index 00000000..25f6fba4
--- /dev/null
+++ b/tests/sixtracklib/opencl/test_track_job_cl_assign_address_items_cxx.cpp
@@ -0,0 +1,372 @@
+#include "sixtracklib/opencl/track_job_cl.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer.hpp"
+#include "sixtracklib/common/buffer/assign_address_item.h"
+#include "sixtracklib/common/be_drift/be_drift.hpp"
+#include "sixtracklib/common/be_monitor/be_monitor.hpp"
+#include "sixtracklib/common/particles.hpp"
+#include "sixtracklib/common/context/compute_arch.h"
+#include "sixtracklib/opencl/internal/base_context.h"
+
+TEST( CXXOpenCLTrackJobClAssignAddressItemsTests, MinimalUsage )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    using track_job_t    = st::TrackJobCl;
+    using size_t         = track_job_t::size_type;
+    using assign_item_t  = track_job_t::assign_item_t;
+    using buffer_t       = track_job_t::buffer_t;
+    using c_buffer_t     = track_job_t::c_buffer_t;
+    using controller_t   = track_job_t::context_t;
+    using node_id_t      = controller_t::node_id_t;
+    using status_t       = controller_t::status_t;
+    using particle_set_t = st::Particles;
+    using be_monitor_t   = st::BeamMonitor;
+    using drift_t        = st::Drift;
+    using addr_t         = st::buffer_addr_t;
+
+    buffer_t my_lattice;
+    buffer_t my_output_buffer;
+
+    if( controller_t::NUM_AVAILABLE_NODES() == 0u )
+    {
+        std::cout << "No OpenCL nodes available -> skipping test\r\n";
+        return;
+    }
+
+    st::Drift* dr = my_lattice.add< drift_t >( 0.0 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.1 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.2 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    size_t const bm0_elem_idx = my_lattice.getNumObjects();
+
+    st::BeamMonitor* bm0 = my_lattice.createNew< be_monitor_t >();
+    SIXTRL_ASSERT( bm0 != nullptr );
+    ( void )bm0;
+
+    dr = my_lattice.add< drift_t >( 0.0 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.1 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.2 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    size_t const bm1_elem_idx = my_lattice.getNumObjects();
+    SIXTRL_ASSERT( bm1_elem_idx > bm0_elem_idx );
+
+    st::BeamMonitor* bm1 = my_lattice.createNew< be_monitor_t >();
+    SIXTRL_ASSERT( bm1 != nullptr );
+    ( void )bm1;
+
+    dr = my_lattice.add< drift_t >( 0.3 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.4 );
+    SIXTRL_ASSERT( dr != nullptr );
+
+    dr = my_lattice.add< drift_t >( 0.5 );
+    SIXTRL_ASSERT( dr != nullptr );
+    ( void )dr;
+
+    size_t const bm2_elem_idx = my_lattice.getNumObjects();
+    SIXTRL_ASSERT( bm2_elem_idx > bm1_elem_idx );
+
+    st::BeamMonitor* bm2 = my_lattice.createNew< be_monitor_t >();
+    SIXTRL_ASSERT( bm2 != nullptr );
+    ( void )bm2;
+
+    size_t const out_buffer0_index = my_output_buffer.getNumObjects();
+    particle_set_t* out_buffer0 =
+        my_output_buffer.createNew< st::Particles >( size_t{ 100 } );
+    SIXTRL_ASSERT( out_buffer0 );
+
+    size_t const out_buffer1_index = my_output_buffer.getNumObjects();
+    particle_set_t* out_buffer1 =
+        my_output_buffer.createNew< st::Particles >( size_t{ 512 } );
+    SIXTRL_ASSERT( out_buffer1 );
+
+    c_buffer_t* ptr_my_lattice_buffer = my_lattice.getCApiPtr();
+    SIXTRL_ASSERT( ptr_my_lattice_buffer != nullptr );
+
+    buffer_t::address_t const my_lattice_buffer_addr =
+        my_lattice.getDataBeginAddr();
+
+    size_t const my_lattice_buffer_size = my_lattice.getSize();
+    size_t const my_lattice_buffer_capacity = my_lattice.getCapacity();
+
+    size_t const my_lattice_buffer_num_objects =
+        my_lattice.getNumObjects();
+
+    c_buffer_t* ptr_my_output_buffer  = my_output_buffer.getCApiPtr();
+    SIXTRL_ASSERT( ptr_my_output_buffer != nullptr );
+
+    buffer_t::address_t const my_output_buffer_addr =
+        my_output_buffer.getDataBeginAddr();
+
+    size_t const my_output_buffer_size = my_output_buffer.getSize();
+    size_t const my_output_buffer_capacity = my_output_buffer.getCapacity();
+
+    size_t const my_output_buffer_num_objects =
+        my_output_buffer.getNumObjects();
+
+
+    out_buffer0 = my_output_buffer.get< particle_set_t >( out_buffer0_index );
+    out_buffer1 = my_output_buffer.get< particle_set_t >( out_buffer1_index );
+
+    /* --------------------------------------------------------------------- */
+
+    node_id_t node_id;
+
+    size_t const num_nodes = controller_t::GET_AVAILABLE_NODES(
+        &node_id, size_t{ 1 } );
+    ASSERT_TRUE( num_nodes == size_t{ 1 } );
+
+    char NODE_ID_STR[ 32 ] =
+    {
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+        '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+    };
+
+    status_t status = ::NS(ComputeNodeId_to_string_with_format)(
+        &node_id, &NODE_ID_STR[ 0 ], size_t{ 32 }, st::ARCHITECTURE_OPENCL,
+            st::NODE_ID_STR_FORMAT_NOARCH );
+
+    SIXTRL_ASSERT( status == st::ARCH_STATUS_SUCCESS );
+
+    track_job_t job( std::string{ NODE_ID_STR } );
+
+    ASSERT_TRUE( job.ptrContext() != nullptr );
+    ASSERT_TRUE( job.ptrContext()->hasSelectedNode() );
+    ASSERT_TRUE( job.ptrContext()->selectedNodeIdStr().compare(
+        NODE_ID_STR ) == 0 );
+
+    /* -------------------------------------------------------------------- */
+
+    size_t const my_lattice_buffer_id = job.add_stored_buffer(
+        std::move( my_lattice ) );
+
+    ASSERT_TRUE( my_lattice_buffer_id != track_job_t::ILLEGAL_BUFFER_ID );
+
+    size_t const my_output_buffer_id = job.add_stored_buffer(
+        std::move( my_output_buffer ) );
+
+    ptr_my_lattice_buffer = nullptr;
+    ptr_my_output_buffer  = nullptr;
+
+    ASSERT_TRUE( my_output_buffer_id != track_job_t::ILLEGAL_BUFFER_ID );
+    ASSERT_TRUE( my_output_buffer_id > my_lattice_buffer_id );
+
+    ASSERT_TRUE(  job.is_buffer_by_buffer_id( my_lattice_buffer_id ) );
+    ASSERT_TRUE( !job.is_raw_memory_by_buffer_id( my_lattice_buffer_id ) );
+
+    ptr_my_lattice_buffer = job.buffer_by_buffer_id( my_lattice_buffer_id );
+
+    ASSERT_TRUE(  ptr_my_lattice_buffer != nullptr );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_addr );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_size );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_capacity );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_my_lattice_buffer ) ==
+                    my_lattice_buffer_num_objects );
+
+    ptr_my_output_buffer = job.buffer_by_buffer_id( my_output_buffer_id );
+
+    ASSERT_TRUE( ptr_my_output_buffer != nullptr );
+    ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_my_output_buffer ) ==
+                    my_output_buffer_addr );
+    ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_my_output_buffer ) ==
+                    my_output_buffer_size );
+    ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_my_output_buffer ) ==
+                    my_output_buffer_capacity );
+    ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_my_output_buffer ) ==
+                    my_output_buffer_num_objects );
+
+    ASSERT_TRUE(  job.is_buffer_by_buffer_id( my_output_buffer_id ) );
+    ASSERT_TRUE( !job.is_raw_memory_by_buffer_id( my_output_buffer_id ) );
+    ASSERT_TRUE(  job.buffer_by_buffer_id( my_output_buffer_id ) ==
+                  ptr_my_output_buffer );
+
+    ASSERT_TRUE(  job.ptr_stored_buffer( my_output_buffer_id ) ==
+                  ptr_my_output_buffer );
+
+    assign_item_t const assign_item_0_to_0(
+        st::OBJECT_TYPE_BEAM_MONITOR, my_lattice_buffer_id, bm0_elem_idx,
+        offsetof( st::BeamMonitor, out_address ),
+        st::OBJECT_TYPE_PARTICLE, my_output_buffer_id, out_buffer0_index,
+        size_t{ 0 } );
+
+    ASSERT_TRUE(  job.total_num_assign_items() == size_t{ 0 } );
+    ASSERT_TRUE( !job.has_assign_address_item( assign_item_0_to_0 ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 0 } );
+
+    ASSERT_TRUE( !job.has_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    assign_item_t* ptr_assign_item_0_to_0 =
+        job.add_assign_address_item( assign_item_0_to_0 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0 != nullptr );
+    ASSERT_TRUE(  assign_item_0_to_0 == *ptr_assign_item_0_to_0 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0 != nullptr );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getDestElemTypeId() ==
+                  st::OBJECT_TYPE_BEAM_MONITOR );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getDestBufferId() ==
+                  my_lattice_buffer_id );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getDestElemIndex() ==
+                  bm0_elem_idx );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getDestElemPointerOffset() ==
+                  offsetof( st::BeamMonitor, out_address ) );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getSrcElemTypeId() ==
+                  st::OBJECT_TYPE_PARTICLE );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getSrcBufferId() ==
+                  my_output_buffer_id );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getSrcElemIndex() ==
+                  out_buffer0_index );
+    ASSERT_TRUE(  ptr_assign_item_0_to_0->getSrcElemPointerOffset() ==
+                  size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+                    ptr_assign_item_0_to_0->getCApiPtr(),
+                        ptr_my_output_buffer ) == reinterpret_cast< uintptr_t >(
+                            out_buffer0 ) );
+
+    ASSERT_TRUE(  job.has_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 1 } );
+
+    ASSERT_TRUE(  job.total_num_assign_items() == size_t{ 1 } );
+
+    ASSERT_TRUE( !job.has_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) == size_t{ 0 } );
+
+    assign_item_t* ptr_assign_item_1_to_1 = job.add_assign_address_item(
+        st::OBJECT_TYPE_BEAM_MONITOR, my_lattice_buffer_id, bm1_elem_idx,
+        offsetof( st::BeamMonitor, out_address ),
+        st::OBJECT_TYPE_PARTICLE, my_output_buffer_id, out_buffer1_index,
+        size_t{ 0 } );
+
+    ASSERT_TRUE(  ptr_assign_item_1_to_1 != nullptr );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getDestElemTypeId() ==
+                  st::OBJECT_TYPE_BEAM_MONITOR );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getDestBufferId() ==
+                  my_lattice_buffer_id );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getDestElemIndex() ==
+                  bm1_elem_idx );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getDestElemPointerOffset() ==
+                  offsetof( st::BeamMonitor, out_address ) );
+
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getSrcElemTypeId() ==
+                  st::OBJECT_TYPE_PARTICLE );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getSrcBufferId() ==
+                  my_output_buffer_id );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getSrcElemIndex() ==
+                  out_buffer1_index );
+    ASSERT_TRUE(  ptr_assign_item_1_to_1->getSrcElemPointerOffset() ==
+                  size_t{ 0 } );
+
+    ASSERT_TRUE(  ::NS(AssignAddressItem_src_pointer_addr_from_buffer)(
+                    ptr_assign_item_1_to_1->getCApiPtr(),
+                        ptr_my_output_buffer ) == reinterpret_cast< uintptr_t >(
+                            out_buffer1 ) );
+
+    ASSERT_TRUE(  job.has_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 2 } );
+
+    ASSERT_TRUE(  job.total_num_assign_items() == size_t{ 2 } );
+
+    ASSERT_TRUE( !job.has_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) == size_t{ 0 } );
+
+    assign_item_t assign_item_0_to_2( assign_item_0_to_0 );
+    assign_item_0_to_2.dest_elem_index = bm2_elem_idx;
+
+    assign_item_t* ptr_assign_item_0_to_2 =
+        job.add_assign_address_item( assign_item_0_to_2 );
+
+    ASSERT_TRUE(  ptr_assign_item_0_to_2 != nullptr );
+    ASSERT_TRUE(  assign_item_0_to_2 == *ptr_assign_item_0_to_2 );
+
+    ASSERT_TRUE(  job.has_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, my_output_buffer_id ) == size_t{ 3 } );
+
+    ASSERT_TRUE(  job.total_num_assign_items() == size_t{ 3 } );
+
+    ASSERT_TRUE( !job.has_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) );
+
+    ASSERT_TRUE(  job.num_assign_items(
+        my_lattice_buffer_id, st::ARCH_OUTPUT_BUFFER_ID ) == size_t{ 0 } );
+
+    status = job.commit_address_assignments();
+    ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+
+    status = job.assign_all_addresses();
+    ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+
+    status = job.collect_stored_buffer( my_lattice_buffer_id );
+    ASSERT_TRUE(status == st::ARCH_STATUS_SUCCESS );
+
+    bm0 = reinterpret_cast< be_monitor_t* >( ::NS(BeamMonitor_from_buffer)(
+        ptr_my_lattice_buffer, bm0_elem_idx ) );
+
+    bm1 = reinterpret_cast< be_monitor_t* >( ::NS(BeamMonitor_from_buffer)(
+        ptr_my_lattice_buffer, bm1_elem_idx ) );
+
+    bm2 = reinterpret_cast< be_monitor_t* >( ::NS(BeamMonitor_from_buffer)(
+        ptr_my_lattice_buffer, bm2_elem_idx ) );
+
+    SIXTRL_ASSERT( bm0 != nullptr );
+    SIXTRL_ASSERT( bm1 != nullptr );
+    SIXTRL_ASSERT( bm2 != nullptr );
+
+    ASSERT_TRUE( bm0->out_address != addr_t{ 0 } );
+    ASSERT_TRUE( bm1->out_address != addr_t{ 0 } );
+    ASSERT_TRUE( bm2->out_address != addr_t{ 0 } );
+
+    ASSERT_TRUE( bm0->out_address == bm2->out_address );
+    ASSERT_TRUE( bm1->out_address != bm0->out_address );
+    ASSERT_TRUE( bm0->out_address <  bm1->out_address );
+
+    ASSERT_TRUE( ( bm1->out_address - bm0->out_address ) ==
+        static_cast< addr_t >(
+            reinterpret_cast< uintptr_t >( out_buffer1 ) -
+            reinterpret_cast< uintptr_t >( out_buffer0 ) ) );
+}
diff --git a/tests/sixtracklib/opencl/test_track_job_cl_collect_push_c99.cpp b/tests/sixtracklib/opencl/test_track_job_cl_collect_push_c99.cpp
index 238bf411..5093d164 100644
--- a/tests/sixtracklib/opencl/test_track_job_cl_collect_push_c99.cpp
+++ b/tests/sixtracklib/opencl/test_track_job_cl_collect_push_c99.cpp
@@ -14,7 +14,7 @@
 #include "sixtracklib/common/particles.h"
 #include "sixtracklib/common/track_job.h"
 
-TEST( C99_TrackJobClCollectPushTests, TestCollectAndPush )
+TEST( C99TrackJobClCollectPush, TestCollectAndPush )
 {
     using track_job_t        = ::NS(TrackJobCl);
     using buffer_t           = ::NS(Buffer);
@@ -154,15 +154,15 @@ TEST( C99_TrackJobClCollectPushTests, TestCollectAndPush )
         SIXTRL_ASSERT( particles != nullptr );
 
         buffer_t* eb = ::NS(Buffer_new_from_copy)( init_eb );
-        e01_drift  = ::NS(BeamElements_buffer_get_drift)( eb, 0 );
-        e02_cavity = ::NS(BeamElements_buffer_get_cavity)( eb, 1 );
-        e03_drift  = ::NS(BeamElements_buffer_get_drift)( eb, 2 );
-        e04_limit_rect = ::NS(BeamElements_buffer_get_limit_rect)( eb, 3 );
-        e05_drift  = ::NS(BeamElements_buffer_get_drift)( eb, 4 );
-        e06_monitor = ::NS(BeamElements_buffer_get_beam_monitor)( eb, 5 );
-        e07_drift  = ::NS(BeamElements_buffer_get_drift)( eb, 6 );
-        e08_limit_ell = ::NS(BeamElements_buffer_get_limit_ellipse)( eb, 7 );
-        e09_monitor = ::NS(BeamElements_buffer_get_beam_monitor)( eb, 8 );
+        e01_drift  = ::NS(Drift_from_buffer)( eb, 0 );
+        e02_cavity = ::NS(Cavity_from_buffer)( eb, 1 );
+        e03_drift  = ::NS(Drift_from_buffer)( eb, 2 );
+        e04_limit_rect = ::NS(LimitRect_from_buffer)( eb, 3 );
+        e05_drift  = ::NS(Drift_from_buffer)( eb, 4 );
+        e06_monitor = ::NS(BeamMonitor_from_buffer)( eb, 5 );
+        e07_drift  = ::NS(Drift_from_buffer)( eb, 6 );
+        e08_limit_ell = ::NS(LimitEllipse_from_buffer)( eb, 7 );
+        e09_monitor = ::NS(BeamMonitor_from_buffer)( eb, 8 );
 
         ASSERT_TRUE( e01_drift      != nullptr );
         ASSERT_TRUE( e02_cavity     != nullptr );
@@ -185,38 +185,38 @@ TEST( C99_TrackJobClCollectPushTests, TestCollectAndPush )
 
         buffer_t* copy_of_eb = ::NS(Buffer_new_from_copy)( eb );
         SIXTRL_ASSERT( ::NS(Buffer_get_num_of_objects)( copy_of_eb ) == ::NS(Buffer_get_num_of_objects)( eb ) );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) != e01_drift );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) != e02_cavity );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) != e03_drift );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) != e04_limit_rect );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 4 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 4 ) != e05_drift );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) != e06_monitor );
-
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 6 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 6 ) != e07_drift );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_limit_ellipse)( copy_of_eb, 7 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_limit_ellipse)( copy_of_eb, 7 ) != e08_limit_ell );
-
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) != nullptr );
-        SIXTRL_ASSERT( ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) != e09_monitor );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 0 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 0 ) != e01_drift );
+        SIXTRL_ASSERT( ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) != e02_cavity );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 2 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 2 ) != e03_drift );
+        SIXTRL_ASSERT( ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) != e04_limit_rect );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 4 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 4 ) != e05_drift );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) != e06_monitor );
+
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 6 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(Drift_from_buffer)( copy_of_eb, 6 ) != e07_drift );
+        SIXTRL_ASSERT( ::NS(LimitEllipse_from_buffer)( copy_of_eb, 7 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(LimitEllipse_from_buffer)( copy_of_eb, 7 ) != e08_limit_ell );
+
+        SIXTRL_ASSERT( ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) != nullptr );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) != e09_monitor );
 
         /* The beam monitors on the host side should have output adddr == 0: */
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_out_address)( e06_monitor ) != be_monitor_addr_t{ 0 } );
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_out_address)( e09_monitor ) != be_monitor_addr_t{ 0 } );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)( e06_monitor ) != be_monitor_addr_t{ 0 } );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)( e09_monitor ) != be_monitor_addr_t{ 0 } );
 
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_out_address)(
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) ) ==
-                       ::NS(BeamMonitor_get_out_address)( e06_monitor ) );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)(
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) ) ==
+                       ::NS(BeamMonitor_out_address)( e06_monitor ) );
 
-        SIXTRL_ASSERT( ::NS(BeamMonitor_get_out_address)(
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) ) ==
-                       ::NS(BeamMonitor_get_out_address)( e09_monitor ) );
+        SIXTRL_ASSERT( ::NS(BeamMonitor_out_address)(
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) ) ==
+                       ::NS(BeamMonitor_out_address)( e09_monitor ) );
 
         buffer_t* copy_of_pb = ::NS(Buffer_new_from_copy)( pb );
         SIXTRL_ASSERT( ::NS(Buffer_get_num_of_objects)( copy_of_pb ) == ::NS(Buffer_get_num_of_objects)( pb ) );
@@ -250,26 +250,26 @@ TEST( C99_TrackJobClCollectPushTests, TestCollectAndPush )
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* beam elements: */
         SIXTRL_ASSERT( ::NS(Drift_compare_values)( e01_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) ) == 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 0 ) ) == 0 );
         ::NS(Drift_set_length)( e01_drift,
-            double{0.5} * ::NS(Drift_get_length)( e01_drift ) );
+            double{0.5} * ::NS(Drift_length)( e01_drift ) );
 
         SIXTRL_ASSERT( ::NS(Drift_compare_values)( e01_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) ) != 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 0 ) ) != 0 );
 
         SIXTRL_ASSERT( ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) == 0 );
-        ::NS(Cavity_set_voltage)( e02_cavity, double{2.0} * ::NS(Cavity_get_voltage)( e02_cavity ) );
-        ::NS(Cavity_set_frequency)( e02_cavity, double{2.0} * ::NS(Cavity_get_frequency)( e02_cavity ) );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) == 0 );
+        ::NS(Cavity_set_voltage)( e02_cavity, double{2.0} * ::NS(Cavity_voltage)( e02_cavity ) );
+        ::NS(Cavity_set_frequency)( e02_cavity, double{2.0} * ::NS(Cavity_frequency)( e02_cavity ) );
         ::NS(Cavity_set_lag)( e02_cavity, double{ 1.0 } );
         SIXTRL_ASSERT( ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) != 0 );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) != 0 );
 
         SIXTRL_ASSERT( ::NS(Drift_compare_values)( e03_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) ) == 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 2 ) ) == 0 );
         ::NS(Drift_set_length)( e03_drift, double{ 0.0 } );
         SIXTRL_ASSERT( ::NS(Drift_compare_values)( e03_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) ) != 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 2 ) ) != 0 );
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* output: */
@@ -313,42 +313,42 @@ TEST( C99_TrackJobClCollectPushTests, TestCollectAndPush )
 
         ::NS(TrackJob_collect_beam_elements)( job );
 
-        ASSERT_TRUE( e01_drift == ::NS(BeamElements_buffer_get_drift)(
+        ASSERT_TRUE( e01_drift == ::NS(Drift_from_buffer)(
             ::NS(TrackJob_get_beam_elements_buffer)( job ), 0 ) );
 
         ASSERT_TRUE( ::NS(Drift_compare_values)( e01_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 0 ) ) == 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 0 ) ) == 0 );
 
         ASSERT_TRUE( e02_cavity ==
-            ::NS(BeamElements_buffer_get_cavity)( ::NS(TrackJob_get_beam_elements_buffer)( job ), 1 ) );
+            ::NS(Cavity_from_buffer)( ::NS(TrackJob_get_beam_elements_buffer)( job ), 1 ) );
 
         ASSERT_TRUE( ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) == 0 );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) == 0 );
 
         ASSERT_TRUE( e03_drift ==
-            ::NS(BeamElements_buffer_get_drift)( ::NS(TrackJob_get_beam_elements_buffer)( job ), 2 ) );
+            ::NS(Drift_from_buffer)( ::NS(TrackJob_get_beam_elements_buffer)( job ), 2 ) );
 
         ASSERT_TRUE( ::NS(Drift_compare_values)( e03_drift,
-            ::NS(BeamElements_buffer_get_drift)( copy_of_eb, 2 ) ) == 0 );
+            ::NS(Drift_from_buffer)( copy_of_eb, 2 ) ) == 0 );
 
         /* Check that the collected output has output addresses */
 
         ASSERT_TRUE( e06_monitor ==
-            ::NS(BeamElements_buffer_get_beam_monitor)( ::NS(TrackJob_get_beam_elements_buffer)( job ), 5 ) );
+            ::NS(BeamMonitor_from_buffer)( ::NS(TrackJob_get_beam_elements_buffer)( job ), 5 ) );
 
         ASSERT_TRUE( e09_monitor ==
-            ::NS(BeamElements_buffer_get_beam_monitor)( ::NS(TrackJob_get_beam_elements_buffer)( job ), 8 ) );
+            ::NS(BeamMonitor_from_buffer)( ::NS(TrackJob_get_beam_elements_buffer)( job ), 8 ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( e06_monitor ) != be_monitor_addr_t{ 0 } );
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( e09_monitor ) != be_monitor_addr_t{ 0 } );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( e06_monitor ) != be_monitor_addr_t{ 0 } );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( e09_monitor ) != be_monitor_addr_t{ 0 } );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)(
-                ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) ) ==
-            ::NS(BeamMonitor_get_out_address)( e06_monitor ) );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)(
+                ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) ) ==
+            ::NS(BeamMonitor_out_address)( e06_monitor ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)(
-                ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) ) ==
-            ::NS(BeamMonitor_get_out_address)( e09_monitor ) );
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)(
+                ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) ) ==
+            ::NS(BeamMonitor_out_address)( e09_monitor ) );
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* output buffer: */
@@ -379,15 +379,15 @@ TEST( C99_TrackJobClCollectPushTests, TestCollectAndPush )
 
         ::NS(Cavity_set_lag)( e02_cavity, double{ 2.0 } );
         SIXTRL_ASSERT( ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) != 0 );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) != 0 );
 
         SIXTRL_ASSERT( 0 == ::NS(LimitRect_compare_values)( e04_limit_rect,
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
         ::NS(LimitRect_set_min_y)( e04_limit_rect, double{ 0.0 } );
         ::NS(LimitRect_set_max_y)( e04_limit_rect, double{ 0.5 } );
         SIXTRL_ASSERT( 0 != ::NS(LimitRect_compare_values)( e04_limit_rect,
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
         ::NS(BeamMonitor_set_out_address)(
             e06_monitor, ::NS(be_monitor_addr_t){  42u } );
@@ -432,14 +432,14 @@ TEST( C99_TrackJobClCollectPushTests, TestCollectAndPush )
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* beam elements: */
 
-        ::NS(Cavity_set_lag)( e02_cavity, ::NS(Cavity_get_lag)(
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) );
+        ::NS(Cavity_set_lag)( e02_cavity, ::NS(Cavity_lag)(
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) );
 
-        ::NS(LimitRect_set_min_y)( e04_limit_rect, ::NS(LimitRect_get_min_y)(
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+        ::NS(LimitRect_set_min_y)( e04_limit_rect, ::NS(LimitRect_min_y)(
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
-        ::NS(LimitRect_set_max_y)( e04_limit_rect, ::NS(LimitRect_get_max_y)(
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+        ::NS(LimitRect_set_max_y)( e04_limit_rect, ::NS(LimitRect_max_y)(
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
         ::NS(BeamMonitor_set_out_address)( e06_monitor, 0u );
         ::NS(BeamMonitor_set_out_address)( e09_monitor, 0u );
@@ -490,66 +490,66 @@ TEST( C99_TrackJobClCollectPushTests, TestCollectAndPush )
 
         ::NS(TrackJob_collect_beam_elements)( job );
 
-        ASSERT_TRUE( e02_cavity == ::NS(BeamElements_buffer_get_cavity)(
+        ASSERT_TRUE( e02_cavity == ::NS(Cavity_from_buffer)(
             ::NS(TrackJob_get_beam_elements_buffer)( job ), 1 ) );
 
         ASSERT_TRUE( EPS > std::fabs(
-            ::NS(Cavity_get_lag)( e02_cavity ) - double{ 2.0 } ) );
+            ::NS(Cavity_lag)( e02_cavity ) - double{ 2.0 } ) );
 
-        ::NS(Cavity_set_lag)( ::NS(BeamElements_buffer_get_cavity)(
+        ::NS(Cavity_set_lag)( ::NS(Cavity_from_buffer)(
             copy_of_eb, 1 ), double{ 2.0 } );
 
         ASSERT_TRUE( 0 == ::NS(Cavity_compare_values)( e02_cavity,
-            ::NS(BeamElements_buffer_get_cavity)( copy_of_eb, 1 ) ) );
+            ::NS(Cavity_from_buffer)( copy_of_eb, 1 ) ) );
 
 
-        ASSERT_TRUE( e04_limit_rect == ::NS(BeamElements_buffer_get_limit_rect)(
+        ASSERT_TRUE( e04_limit_rect == ::NS(LimitRect_from_buffer)(
             ::NS(TrackJob_get_beam_elements_buffer)( job ), 3 ) );
 
         ASSERT_TRUE( EPS > std::fabs(
-            ::NS(LimitRect_get_min_y)( e04_limit_rect ) - double{ 0.0 } ) );
+            ::NS(LimitRect_min_y)( e04_limit_rect ) - double{ 0.0 } ) );
 
         ASSERT_TRUE( EPS > std::fabs(
-            ::NS(LimitRect_get_max_y)( e04_limit_rect ) - double{ 0.5 } ) );
+            ::NS(LimitRect_max_y)( e04_limit_rect ) - double{ 0.5 } ) );
 
-        ::NS(LimitRect_set_min_y)( ::NS(BeamElements_buffer_get_limit_rect)(
+        ::NS(LimitRect_set_min_y)( ::NS(LimitRect_from_buffer)(
             copy_of_eb, 3 ), double{ 0.0 } );
 
-        ::NS(LimitRect_set_max_y)( ::NS(BeamElements_buffer_get_limit_rect)(
+        ::NS(LimitRect_set_max_y)( ::NS(LimitRect_from_buffer)(
             copy_of_eb, 3 ), double{ 0.5 } );
 
         ASSERT_TRUE( 0 == ::NS(LimitRect_compare_values)( e04_limit_rect,
-            ::NS(BeamElements_buffer_get_limit_rect)( copy_of_eb, 3 ) ) );
+            ::NS(LimitRect_from_buffer)( copy_of_eb, 3 ) ) );
 
         /* Check that the collected output has output addresses */
 
-        ASSERT_TRUE( e06_monitor == ::NS(BeamElements_buffer_get_beam_monitor)(
+        ASSERT_TRUE( e06_monitor == ::NS(BeamMonitor_from_buffer)(
             ::NS(TrackJob_get_beam_elements_buffer)( job ), 5 ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( e06_monitor ) ==
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( e06_monitor ) ==
             ::NS(be_monitor_addr_t){ 42 } );
 
         ::NS(BeamMonitor_set_out_address)(
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ),
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ),
             ::NS(be_monitor_addr_t){ 42 } );
 
         ASSERT_TRUE( 0 == ::NS(BeamMonitor_compare_values)(
             e06_monitor,
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 5 ) ) );
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 5 ) ) );
 
-        ASSERT_TRUE( e09_monitor == ::NS(BeamElements_buffer_get_beam_monitor)(
+        ASSERT_TRUE( e09_monitor == ::NS(BeamMonitor_from_buffer)(
             ::NS(TrackJob_get_beam_elements_buffer)( job ), 8 ) );
 
-        ASSERT_TRUE( ::NS(BeamMonitor_get_out_address)( e09_monitor ) ==
+        ASSERT_TRUE( ::NS(BeamMonitor_out_address)( e09_monitor ) ==
             ::NS(be_monitor_addr_t){ 137 } );
 
         ::NS(BeamMonitor_set_out_address)(
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ),
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ),
             ::NS(be_monitor_addr_t){ 137 } );
 
         ASSERT_TRUE( 0 == ::NS(BeamMonitor_compare_values)(
             e09_monitor,
-            ::NS(BeamElements_buffer_get_beam_monitor)( copy_of_eb, 8 ) ) );
+            ::NS(BeamMonitor_from_buffer)( copy_of_eb, 8 ) ) );
 
         /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
         /* output buffer: */
diff --git a/tests/sixtracklib/opencl/test_track_job_cl_collect_push_cxx.cpp b/tests/sixtracklib/opencl/test_track_job_cl_collect_push_cxx.cpp
index cd478aa4..cf74d7af 100644
--- a/tests/sixtracklib/opencl/test_track_job_cl_collect_push_cxx.cpp
+++ b/tests/sixtracklib/opencl/test_track_job_cl_collect_push_cxx.cpp
@@ -12,7 +12,7 @@
 #include "sixtracklib/common/beam_elements.hpp"
 #include "sixtracklib/common/particles.hpp"
 
-TEST( CXX_TrackJobClCollectPushTests, TestCollectAndPush )
+TEST( CXXTrackJobClCollectPush, TestCollectAndPush )
 {
     namespace st = SIXTRL_CXX_NAMESPACE;
 
diff --git a/tests/sixtracklib/opencl/test_track_job_cl_opencl_c99.cpp b/tests/sixtracklib/opencl/test_track_job_cl_opencl_c99.cpp
index d3fa1c94..0b1f4859 100644
--- a/tests/sixtracklib/opencl/test_track_job_cl_opencl_c99.cpp
+++ b/tests/sixtracklib/opencl/test_track_job_cl_opencl_c99.cpp
@@ -901,7 +901,7 @@ TEST( C99_TrackJobClTests, CreateTrackJobTrackLineCompare )
             ::NS(Particles_buffer_get_const_particles)( pb, 0 ) );
 
         SIXTRL_ASSERT( particles != nullptr );
-        ::NS(BeamMonitor_clear_all)( eb );
+        ::NS(BeamMonitor_reset_all_in_buffer)( eb );
 
         std::cout << "node " << ( kk + size_t{ 1 } )
                   << " / " << num_nodes << "\r\n";
@@ -940,11 +940,12 @@ TEST( C99_TrackJobClTests, CreateTrackJobTrackLineCompare )
 
         ::NS(TrackJobCl_collect)( job );
 
-        double const ABS_DIFF = double{ 2e-14 };
+        /* TODO: Fix FMA / math optimization differences with Intel OpenCL Env */
+        double const ABS_ERR = double{ 5e-11 };
 
         if( ( 0 != ::NS(Particles_compare_values)( cmp_particles, particles ) ) &&
             ( 0 != ::NS(Particles_compare_values_with_treshold)(
-                cmp_particles, particles, ABS_DIFF ) ) )
+                cmp_particles, particles, ABS_ERR ) ) )
         {
             buffer_t diff_buffer  = ::NS(Buffer_new)( buf_size_t{ 0 } );
             SIXTRL_ASSERT( diff_buffer != nullptr );
@@ -969,7 +970,7 @@ TEST( C99_TrackJobClTests, CreateTrackJobTrackLineCompare )
         ASSERT_TRUE(
             ( 0 == ::NS(Particles_compare_values)( cmp_particles, particles ) ) ||
             ( 0 == ::NS(Particles_compare_values_with_treshold)(
-                cmp_particles, particles, ABS_DIFF ) ) );
+                cmp_particles, particles, ABS_ERR ) ) );
 
 
         ::NS(TrackJobCl_delete)( job );
@@ -1138,7 +1139,7 @@ TEST( C99_TrackJobClTests, TrackParticles )
 
     for( size_t kk = size_t{ 0 } ; node_it != node_end ; ++node_it, ++kk )
     {
-        ::NS(BeamMonitor_clear_all)( eb );
+        ::NS(BeamMonitor_reset_all_in_buffer)( eb );
         ::NS(Particles_copy)( particles, ::NS(Particles_buffer_get_particles)(
             in_particle_buffer, size_t{ 0 } ) );
 
@@ -1198,13 +1199,13 @@ TEST( C99_TrackJobClTests, TrackParticles )
         ASSERT_TRUE( ::NS(Buffer_get_num_of_objects)( ptr_output_buffer ) ==
                      ::NS(Buffer_get_num_of_objects)( cmp_output_buffer ) );
 
-        double const ABS_ERR = double{ 2e-14 };
+        double const ABS_TOL = double{ 5e-11 };
 
         if( ::NS(Particles_buffers_compare_values)(
                 ptr_output_buffer, cmp_output_buffer ) != 0 )
         {
             if( ::NS(Particles_buffers_compare_values_with_treshold)(
-                ptr_output_buffer, cmp_output_buffer, ABS_ERR ) != 0 )
+                ptr_output_buffer, cmp_output_buffer, ABS_TOL ) != 0 )
             {
                 size_t const nn =
                     ::NS(Buffer_get_num_of_objects)( cmp_output_buffer );
@@ -1230,7 +1231,7 @@ TEST( C99_TrackJobClTests, TrackParticles )
                             trk_particles ) ) );
 
                     if( 0 != ::NS(Particles_compare_values_with_treshold)(
-                            cmp, trk_particles, ABS_ERR ) )
+                            cmp, trk_particles, ABS_TOL ) )
                     {
                         size_t const diff_index =
                                 ::NS(Buffer_get_num_of_objects)( diff_buffer );
@@ -1303,7 +1304,7 @@ TEST( C99_TrackJobClTests, TrackParticles )
         ASSERT_TRUE( ( ::NS(Particles_buffers_compare_values)(
                             ptr_output_buffer, cmp_output_buffer ) == 0 ) ||
             ( ::NS(Particles_buffers_compare_values_with_treshold)(
-                ptr_output_buffer, cmp_output_buffer, ABS_ERR ) == 0 ) );
+                ptr_output_buffer, cmp_output_buffer, ABS_TOL ) == 0 ) );
 
         ::NS(TrackJobCl_delete)( job );
         job = nullptr;
diff --git a/tests/sixtracklib/opencl/test_track_job_cl_opencl_cxx.cpp b/tests/sixtracklib/opencl/test_track_job_cl_opencl_cxx.cpp
index c8a1283a..119149aa 100644
--- a/tests/sixtracklib/opencl/test_track_job_cl_opencl_cxx.cpp
+++ b/tests/sixtracklib/opencl/test_track_job_cl_opencl_cxx.cpp
@@ -827,7 +827,7 @@ TEST( CXXOpenCLTrackJobClTests, CreateTrackJobTrackLineCompare )
 
         SIXTRL_ASSERT( particles != nullptr );
         particles->copy( *orig_particles );
-        ::NS(BeamMonitor_clear_all)( eb.getCApiPtr() );
+        ::NS(BeamMonitor_reset_all_in_buffer)( eb.getCApiPtr() );
 
         std::cout << "node " << ( kk + size_t{ 1 } )
                   << " / " << num_nodes << "\r\n";
@@ -1142,7 +1142,8 @@ TEST( CXXOpenCLTrackJobClTests, TrackParticles )
         ASSERT_TRUE( ptr_output_buffer->getNumObjects() ==
                       cmp_output_buffer.getNumObjects() );
 
-        double const ABS_ERR = double{ 2e-14 };
+        /* TODO: Fix FMA / math optimization differences with Intel OpenCL Env */
+        double const ABS_DIFF = double{ 5e-11 };
 
         if( ::NS(Particles_buffers_compare_values)(
                 ptr_output_buffer->getCApiPtr(),
@@ -1150,7 +1151,7 @@ TEST( CXXOpenCLTrackJobClTests, TrackParticles )
         {
             if( ::NS(Particles_buffers_compare_values_with_treshold)(
                 ptr_output_buffer->getCApiPtr(),
-                cmp_output_buffer.getCApiPtr(), ABS_ERR ) != 0 )
+                cmp_output_buffer.getCApiPtr(), ABS_DIFF ) != 0 )
             {
                 size_t const nn = cmp_output_buffer.getNumObjects();
                 buffer_t diff_buffer;
@@ -1171,7 +1172,7 @@ TEST( CXXOpenCLTrackJobClTests, TrackParticles )
 
                     if( 0 != ::NS(Particles_compare_values_with_treshold)(
                             cmp->getCApiPtr(), trk_particles->getCApiPtr(),
-                                ABS_ERR ) )
+                                ABS_DIFF ) )
                     {
                         size_t const diff_index = diff_buffer.getNumObjects();
 
@@ -1246,7 +1247,7 @@ TEST( CXXOpenCLTrackJobClTests, TrackParticles )
                             cmp_output_buffer.getCApiPtr() ) == 0 ) ||
             ( ::NS(Particles_buffers_compare_values_with_treshold)(
                     ptr_output_buffer->getCApiPtr(),
-                    cmp_output_buffer.getCApiPtr(), ABS_ERR ) == 0 ) );
+                    cmp_output_buffer.getCApiPtr(), ABS_DIFF ) == 0 ) );
     }
 
     if( num_nodes == size_t{ 0 } )
diff --git a/tests/sixtracklib/opencl/test_track_job_cl_stored_buffer_c99.cpp b/tests/sixtracklib/opencl/test_track_job_cl_stored_buffer_c99.cpp
new file mode 100644
index 00000000..a0f1f1c7
--- /dev/null
+++ b/tests/sixtracklib/opencl/test_track_job_cl_stored_buffer_c99.cpp
@@ -0,0 +1,511 @@
+#include "sixtracklib/opencl/track_job_cl.h"
+
+#include <iomanip>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer.hpp"
+#include "sixtracklib/common/buffer.h"
+
+TEST( C99_OpenCL_TrackJobCl_StoredBufferTests, MinimalUsage )
+{
+    using track_job_t = ::NS(TrackJobCl);
+    using context_t = ::NS(ClContext);
+    using node_id_t = ::NS(ComputeNodeId);
+    using node_info_t = ::NS(ComputeNodeInfo);
+    using c_buffer_t = ::NS(Buffer);
+    using size_t = ::NS(arch_size_t);
+    using arg_t = ::NS(ClArgument);
+    using status_t = ::NS(arch_status_t);
+    using buffer_addr_t = ::NS(buffer_addr_t);
+
+    /* Init track-job -> should have no ext stored buffers up front: */
+
+    std::vector< node_id_t > node_ids;
+    size_t const num_available_nodes = context_t::NUM_AVAILABLE_NODES();
+    size_t num_nodes = size_t{ 0 };
+
+    if(  num_available_nodes > size_t{ 0 } )
+    {
+        node_ids.resize( num_available_nodes, node_id_t{} );
+        num_nodes = context_t::GET_AVAILABLE_NODES(
+            node_ids.data(), node_ids.size() );
+
+        ASSERT_TRUE( num_nodes <= num_available_nodes );
+    }
+
+    if( num_nodes == size_t{ 0 } )
+    {
+        std::cout << "No available OpenCL nodes -> skipping test\r\n";
+    }
+
+    bool first = true;
+
+    for( size_t idx = size_t{ 0 } ; idx < num_nodes ; ++idx )
+    {
+        char node_id_str[ 32 ] =
+        {
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+        };
+
+        node_id_t const node_id = node_ids[ idx ];
+
+        status_t status = ::NS(ComputeNodeId_to_string)(
+            &node_id, &node_id_str[ 0 ], 32 );
+        ASSERT_TRUE( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+        track_job_t* job = ::NS(TrackJobCl_create)( node_id_str );
+        SIXTRL_ASSERT( job != nullptr );
+        ASSERT_TRUE( ::NS(TrackJobCl_get_context)( job ) != nullptr );
+
+        node_info_t const* node_info =
+            ::NS(ClContextBase_get_available_node_info_by_node_id)(
+                ::NS(TrackJobCl_get_context)( job ), &node_id );
+
+        node_id_t const default_node_id =
+            ::NS(ClContextBase_get_default_node_id)(
+                ::NS(TrackJobCl_get_context)( job ) );
+
+        if( node_info == nullptr ) continue;
+
+        if( !first )
+        {
+            std::cout << "\r\n------------------------------------------------"
+                      << "-------------------------------";
+
+        }
+        else
+        {
+            first = false;
+        }
+
+        ::NS(ComputeNodeInfo_print_out)( node_info, &default_node_id );
+        std::cout << std::endl;
+
+        /* Init track-job -> should have no ext stored buffers up front: */
+
+        ASSERT_TRUE( !::NS(TrackJob_has_stored_buffers)( job ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) ==
+                    size_t{ 0 } );
+
+        ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) ==
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) ==
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        /* ----------------------------------------------------------------- */
+        /* Create a buffer that is directly managed by the job */
+
+        size_t const ext_buffer_01_capacity = size_t{ 1024 };
+        size_t const ext_buffer_01_id = ::NS(TrackJob_create_stored_buffer)(
+            job, ext_buffer_01_capacity );
+
+        ASSERT_TRUE(  ext_buffer_01_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 1 } );
+        ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ext_buffer_01_id ==
+                    ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE(  ext_buffer_01_id ==
+                    ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_owns_stored_buffer)(
+            job, ext_buffer_01_id ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_01_id ) != nullptr );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_01_id ) != nullptr );
+
+        ASSERT_TRUE(  ext_buffer_01_capacity == ::NS(Buffer_get_capacity)(
+            ::NS(TrackJob_stored_buffer)( job, ext_buffer_01_id ) ) );
+
+
+        arg_t* ext_buffer_01_arg = ::NS(TrackJobCl_argument_by_buffer_id)(
+            job, ext_buffer_01_id );
+
+        ASSERT_TRUE(  ext_buffer_01_arg != nullptr );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_to_context)(
+            ext_buffer_01_arg ) == ::NS(TrackJobCl_get_context)( job ) );
+
+        ASSERT_TRUE(  ::NS(ClArgument_uses_cobj_buffer)( ext_buffer_01_arg ) );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_cobj_buffer)(
+            ext_buffer_01_arg ) == ::NS(TrackJob_stored_buffer)(
+                job, ext_buffer_01_id ) );
+
+        ASSERT_TRUE( ::NS(ClArgument_write)( ext_buffer_01_arg,
+            ::NS(TrackJob_stored_buffer)( job, ext_buffer_01_id ) ) );
+
+        ASSERT_TRUE( ::NS(ClArgument_read)( ext_buffer_01_arg,
+            ::NS(TrackJob_stored_buffer)( job, ext_buffer_01_id ) ) );
+
+        /* ----------------------------------------------------------------- */
+        /* Create an external C99 buffer that should not be managed/owned by
+        * the track job */
+
+        size_t ext_buffer_02_capacity = size_t{ 512 };
+        c_buffer_t* ext_buffer_02 = ::NS(Buffer_new)( ext_buffer_02_capacity );
+        SIXTRL_ASSERT( ext_buffer_02 != nullptr );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( ext_buffer_02 ) >=
+                        ext_buffer_02_capacity );
+
+        size_t const ext_buffer_02_id = ::NS(TrackJob_add_stored_buffer)(
+            job, ext_buffer_02, false, false ); /* false == take no ownership */
+
+        ASSERT_TRUE(  ext_buffer_02_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+        ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 2 } );
+
+        ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ext_buffer_01_id ==
+                    ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE(  ext_buffer_02_id ==
+                    ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE( !::NS(TrackJob_owns_stored_buffer)(
+            job, ext_buffer_02_id ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_02_id ) != nullptr );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_02_id ) == ext_buffer_02 );
+
+
+        arg_t* ext_buffer_02_arg = ::NS(TrackJobCl_argument_by_buffer_id)(
+            job, ext_buffer_02_id );
+
+        ASSERT_TRUE(  ext_buffer_02_arg != nullptr );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_to_context)(
+            ext_buffer_02_arg ) == ::NS(TrackJobCl_get_context)( job ) );
+
+        ASSERT_TRUE(  ::NS(ClArgument_uses_cobj_buffer)( ext_buffer_02_arg ) );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_cobj_buffer)(
+            ext_buffer_02_arg ) == ext_buffer_02 );
+
+        ASSERT_TRUE( ::NS(ClArgument_write)(
+            ext_buffer_02_arg, ext_buffer_02 ) );
+
+        ASSERT_TRUE( ::NS(ClArgument_read)(
+            ext_buffer_02_arg, ext_buffer_02 ) );
+
+        /* ----------------------------------------------------------------- */
+        /* Remove ext_buffer_02 again from the track job: */
+
+        ASSERT_TRUE( ::NS(ARCH_STATUS_SUCCESS) ==
+            ::NS(TrackJob_remove_stored_buffer)( job, ext_buffer_02_id ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 1 } );
+        ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ext_buffer_01_id ==
+                    ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE(  ext_buffer_02_id ==
+                    ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE( !::NS(TrackJob_owns_stored_buffer)(
+            job, ext_buffer_02_id ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_02_id ) == nullptr );
+
+        ext_buffer_02_arg = ::NS(TrackJobCl_argument_by_buffer_id)(
+            job, ext_buffer_02_id );
+
+        ASSERT_TRUE( ext_buffer_02_arg == nullptr );
+
+        /* ----------------------------------------------------------------- */
+        /* Add ext_buffer_02 again, but this time let the job take ownership:*/
+
+        buffer_addr_t const ext_buffer_02_begin_addr =
+            ::NS(Buffer_get_data_begin_addr)( ext_buffer_02 );
+
+        size_t const ext_buffer_02_size =
+            ::NS(Buffer_get_size)( ext_buffer_02 );
+
+        ext_buffer_02_capacity = ::NS(Buffer_get_capacity)( ext_buffer_02 );
+
+        size_t const ext_buffer_02_id_b = ::NS(TrackJob_add_stored_buffer)(
+            job, ext_buffer_02, true, true ); /* true == takes ownership */
+
+        uintptr_t const ptr_ext_buffer_02_addr =
+            reinterpret_cast< uintptr_t >( ext_buffer_02 );
+
+        ASSERT_TRUE(  ext_buffer_02_id_b != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+        ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 2 } );
+
+        ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE( ext_buffer_01_id ==
+                    ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE(  ext_buffer_02_id_b ==
+                    ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE( ::NS(TrackJob_owns_stored_buffer)(
+            job, ext_buffer_02_id_b ) );
+
+        /* After taking ownership, the buffer is accessible also as a C++ buffer;
+        but taking ownership creates a new c99 pointer as well -> you can no
+        longer access ext_buffer_02 via it's old handle */
+
+        ext_buffer_02 = nullptr;
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_02_id_b ) != nullptr );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_02_id_b ) != nullptr );
+
+        ASSERT_TRUE(  reinterpret_cast< uintptr_t >(
+            ::NS(TrackJob_stored_buffer)( job, ext_buffer_02_id_b ) ) !=
+                ptr_ext_buffer_02_addr );
+
+        /* Transfering of ownership not only invalidates the old ext_buffer_02
+        * handle, it should also "preset" it with safe default values */
+
+        ASSERT_TRUE( ::NS(Buffer_get_size)( ext_buffer_02 ) == size_t{ 0 } );
+        ASSERT_TRUE( ::NS(Buffer_get_capacity)( ext_buffer_02 ) == size_t{ 0 } );
+
+        /* The values, i.e. start address, capacity and size, should still be
+        * available via the new handle */
+
+        c_buffer_t* ext_buffer_02_b = ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_02_id_b );
+
+        ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ext_buffer_02_b ) ==
+                    ext_buffer_02_begin_addr );
+
+        ASSERT_TRUE( ::NS(Buffer_get_size)( ext_buffer_02_b ) ==
+                    ext_buffer_02_size );
+
+        ASSERT_TRUE( ::NS(Buffer_get_capacity)( ext_buffer_02_b ) ==
+                    ext_buffer_02_capacity );
+
+        ASSERT_TRUE( ::NS(TrackJob_stored_buffer)( job, ext_buffer_02_id_b )
+                    == ext_buffer_02_b );
+
+        arg_t* ext_buffer_02_b_arg = ::NS(TrackJobCl_argument_by_buffer_id)(
+            job, ext_buffer_02_id_b );
+
+        ASSERT_TRUE(  ext_buffer_02_b_arg != nullptr );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_to_context)(
+            ext_buffer_02_b_arg ) == ::NS(TrackJobCl_get_context)( job ) );
+
+        ASSERT_TRUE(  ::NS(ClArgument_uses_cobj_buffer)( ext_buffer_02_b_arg ) );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_cobj_buffer)(
+            ext_buffer_02_b_arg ) == ext_buffer_02_b );
+
+        ASSERT_TRUE( ::NS(ClArgument_write)(
+            ext_buffer_02_b_arg, ext_buffer_02_b ) );
+
+        ASSERT_TRUE( ::NS(ClArgument_read)(
+            ext_buffer_02_b_arg, ext_buffer_02_b ) );
+
+        /* ----------------------------------------------------------------- */
+        /* Add ext_buffer_03, a C99 buffer on the stack: */
+
+        size_t const ext_buffer_03_capacity = size_t{ 2048 };
+        std::vector< unsigned char > ext_buffer_03_data_store(
+            ext_buffer_03_capacity );
+
+        c_buffer_t ext_buffer_03;
+        ::NS(Buffer_preset)( &ext_buffer_03 );
+        status = ::NS(Buffer_init_on_flat_memory)(
+            &ext_buffer_03, ext_buffer_03_data_store.data(),
+                ext_buffer_03_capacity );
+
+        SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+        ( void )status;
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_const_data_begin)(
+            &ext_buffer_03 ) != nullptr );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_data_begin_addr)( &ext_buffer_03 ) ==
+            reinterpret_cast< uintptr_t >( ext_buffer_03_data_store.data() ) );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( &ext_buffer_03 ) >=
+            ext_buffer_03_capacity );
+
+        size_t const ext_buffer_03_id = ::NS(TrackJob_add_stored_buffer)(
+            job, &ext_buffer_03, false, false ); /* false == take no ownership */
+
+        ASSERT_TRUE(  ext_buffer_03_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+        ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 3 } );
+
+        ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ext_buffer_01_id ==
+                    ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE(  ext_buffer_03_id ==
+                    ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE( !::NS(TrackJob_owns_stored_buffer)(
+            job, ext_buffer_03_id ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_03_id ) != nullptr );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)( job, ext_buffer_03_id ) ==
+                    &ext_buffer_03 );
+
+        arg_t* ext_buffer_03_arg = ::NS(TrackJobCl_argument_by_buffer_id)(
+            job, ext_buffer_03_id );
+
+        ASSERT_TRUE(  ext_buffer_03_arg != nullptr );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_to_context)(
+            ext_buffer_03_arg ) == ::NS(TrackJobCl_get_context)( job ) );
+
+        ASSERT_TRUE(  ::NS(ClArgument_uses_cobj_buffer)( ext_buffer_03_arg ) );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_cobj_buffer)(
+            ext_buffer_03_arg ) == &ext_buffer_03 );
+
+        ASSERT_TRUE( ::NS(ClArgument_write)(
+            ext_buffer_03_arg, &ext_buffer_03 ) );
+
+        ASSERT_TRUE( ::NS(ClArgument_read)(
+            ext_buffer_03_arg, &ext_buffer_03 ) );
+
+
+        /* ----------------------------------------------------------------- */
+        /* Add ext_buffer_04, a C99 buffer on the stack, but take ownership: */
+
+        size_t ext_buffer_04_capacity = size_t{ 4096 };
+        std::vector< unsigned char > ext_buffer_04_data_store(
+            ext_buffer_04_capacity );
+
+        c_buffer_t ext_buffer_04;
+        ::NS(Buffer_preset)( &ext_buffer_04 );
+        status = ::NS(Buffer_init_on_flat_memory)( &ext_buffer_04,
+            ext_buffer_04_data_store.data(), ext_buffer_04_capacity );
+
+        SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+        buffer_addr_t const ext_buffer_04_begin_addr =
+            ::NS(Buffer_get_data_begin_addr)( &ext_buffer_04 );
+
+        size_t const ext_buffer_04_size = ::NS(Buffer_get_size)( &ext_buffer_04 );
+        ext_buffer_04_capacity = ::NS(Buffer_get_capacity)( &ext_buffer_04 );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_const_data_begin)(
+            &ext_buffer_04 ) != nullptr );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( &ext_buffer_04 ) >=
+            ext_buffer_04_capacity );
+
+        SIXTRL_ASSERT( reinterpret_cast< uintptr_t >(
+            ext_buffer_04_data_store.data() ) == ext_buffer_04_begin_addr );
+
+        size_t const ext_buffer_04_id = ::NS(TrackJob_add_stored_buffer)(
+            job, &ext_buffer_04, true, false ); /* true: take ownership,
+                false: do not delete as ext_buffer_04 is on the stack */
+
+        ASSERT_TRUE(  ext_buffer_04_id != ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+        ASSERT_TRUE(  ::NS(TrackJob_num_stored_buffers)( job ) == size_t{ 4 } );
+
+        ASSERT_TRUE(  ::NS(TrackJob_min_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_max_stored_buffer_id)( job ) !=
+                    ::NS(ARCH_ILLEGAL_BUFFER_ID) );
+
+        ASSERT_TRUE(  ext_buffer_01_id ==
+                    ::NS(TrackJob_min_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE(  ext_buffer_04_id ==
+                    ::NS(TrackJob_max_stored_buffer_id)( job ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_owns_stored_buffer)(
+            job, ext_buffer_04_id ) );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_04_id ) != nullptr );
+
+        ASSERT_TRUE(  ::NS(TrackJob_stored_buffer)(
+            job, ext_buffer_04_id ) != &ext_buffer_04 );
+
+        ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( &ext_buffer_04 ) ==
+                    buffer_addr_t{ 0 } );
+
+        ASSERT_TRUE( ::NS(Buffer_get_capacity)( &ext_buffer_04 ) == size_t{ 0 } );
+        ASSERT_TRUE( ::NS(Buffer_get_size)( &ext_buffer_04 ) == size_t{ 0 } );
+
+        c_buffer_t* ptr_ext_buffer_04 =
+            ::NS(TrackJob_stored_buffer)( job, ext_buffer_04_id );
+
+        ASSERT_TRUE( ptr_ext_buffer_04 != nullptr );
+
+        ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_ext_buffer_04 ) ==
+                    ext_buffer_04_capacity );
+
+        ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_ext_buffer_04 ) ==
+                    ext_buffer_04_size );
+
+        ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_ext_buffer_04 ) ==
+                    ext_buffer_04_begin_addr );
+
+        arg_t* ext_buffer_04_arg = ::NS(TrackJobCl_argument_by_buffer_id)(
+            job, ext_buffer_04_id );
+
+        ASSERT_TRUE(  ext_buffer_04_arg != nullptr );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_to_context)(
+            ext_buffer_04_arg ) == ::NS(TrackJobCl_get_context)( job ) );
+
+        ASSERT_TRUE(  ::NS(ClArgument_uses_cobj_buffer)( ext_buffer_04_arg ) );
+        ASSERT_TRUE(  ::NS(ClArgument_get_ptr_cobj_buffer)(
+            ext_buffer_04_arg ) == ptr_ext_buffer_04 );
+
+        ASSERT_TRUE( ::NS(ClArgument_write)(
+            ext_buffer_04_arg, ptr_ext_buffer_04 ) );
+
+        ASSERT_TRUE( ::NS(ClArgument_read)(
+            ext_buffer_04_arg, ptr_ext_buffer_04 ) );
+
+        /* ----------------------------------------------------------------- */
+
+        ::NS(TrackJob_delete)( job );
+    }
+}
diff --git a/tests/sixtracklib/opencl/test_track_job_cl_stored_buffer_cxx.cpp b/tests/sixtracklib/opencl/test_track_job_cl_stored_buffer_cxx.cpp
new file mode 100644
index 00000000..bb661073
--- /dev/null
+++ b/tests/sixtracklib/opencl/test_track_job_cl_stored_buffer_cxx.cpp
@@ -0,0 +1,591 @@
+#include "sixtracklib/opencl/track_job_cl.h"
+
+#include <iomanip>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/buffer.hpp"
+#include "sixtracklib/common/buffer.h"
+
+TEST( CXX_OpenCL_TrackJobCl_StoredBufferTests, MinimalUsage )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+    using track_job_t = st::TrackJobCl;
+    using context_t = st::ClContext;
+    using node_id_t = context_t::node_id_t;
+    using node_info_t = context_t::node_info_t;
+    using buffer_t = track_job_t::buffer_t;
+    using c_buffer_t = track_job_t::c_buffer_t;
+    using size_t = track_job_t::size_type;
+    using arg_t = track_job_t::cl_arg_t;
+    using status_t = track_job_t::status_t;
+    using buffer_addr_t = ::NS(buffer_addr_t);
+
+    /* Init track-job -> should have no ext stored buffers up front: */
+
+    std::vector< node_id_t > node_ids;
+    size_t const num_available_nodes = context_t::NUM_AVAILABLE_NODES();
+    size_t num_nodes = size_t{ 0 };
+
+    if(  num_available_nodes > size_t{ 0 } )
+    {
+        node_ids.resize( num_available_nodes, node_id_t{} );
+        num_nodes = context_t::GET_AVAILABLE_NODES(
+            node_ids.data(), node_ids.size() );
+
+        ASSERT_TRUE( num_nodes <= num_available_nodes );
+    }
+
+    if( num_nodes == size_t{ 0 } )
+    {
+        std::cout << "No available OpenCL nodes -> skipping test\r\n";
+    }
+
+    bool first = true;
+
+    for( size_t idx = size_t{ 0 } ; idx < num_nodes ; ++idx )
+    {
+        char node_id_str[ 32 ] =
+        {
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+        };
+
+        node_id_t const node_id = node_ids[ idx ];
+
+        status_t status = ::NS(ComputeNodeId_to_string)(
+            &node_id, &node_id_str[ 0 ], 32 );
+        ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+
+        track_job_t job( node_id_str );
+        ASSERT_TRUE( job.ptrContext() != nullptr );
+
+        node_info_t const* node_info =
+            job.ptrContext()->ptrAvailableNodesInfo( node_id );
+
+        node_id_t const default_node_id = job.ptrContext()->defaultNodeId();
+
+        if( node_info == nullptr ) continue;
+
+        if( !first )
+        {
+            std::cout << "\r\n------------------------------------------------"
+                      << "-------------------------------";
+
+        }
+        else
+        {
+            first = false;
+        }
+
+
+       ::NS(ComputeNodeInfo_print_out)( node_info, &default_node_id );
+        std::cout << std::endl;
+
+        ASSERT_TRUE( !job.has_stored_buffers() );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 0 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() == st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() == st::ARCH_ILLEGAL_BUFFER_ID );
+
+        /* --------------------------------------------------------------------- */
+        /* Create a buffer that is directly managed by the job */
+
+        size_t const ext_buffer_01_capacity = size_t{ 1024 };
+        size_t const ext_buffer_01_id = job.add_stored_buffer(
+            ext_buffer_01_capacity );
+
+        ASSERT_TRUE(  ext_buffer_01_id != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 1 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_01_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_01_id ) );
+
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_01_id ) != nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_01_id ) != nullptr );
+
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_01_id )->getCApiPtr()
+                        == job.ptr_stored_buffer( ext_buffer_01_id ) );
+
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_01_id )->getCapacity()
+                        == ext_buffer_01_capacity );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id(
+                        ext_buffer_01_id ) != nullptr );
+
+        arg_t& ext_buffer_01_arg = job.argument_by_buffer_id( ext_buffer_01_id );
+
+        ASSERT_TRUE(  ext_buffer_01_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_01_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_01_arg.ptrCObjectBuffer() ==
+                    job.ptr_stored_cxx_buffer( ext_buffer_01_id )->getCApiPtr() );
+
+        ASSERT_TRUE(  ext_buffer_01_arg.write(
+                        job.ptr_stored_cxx_buffer( ext_buffer_01_id ) ) );
+
+        ASSERT_TRUE(  ext_buffer_01_arg.read(
+                        job.ptr_stored_cxx_buffer( ext_buffer_01_id ) ) );
+
+        /* --------------------------------------------------------------------- */
+        /* Create an external C99 buffer that should not be managed/owned by
+        * the track job */
+
+        size_t ext_buffer_02_capacity = size_t{ 512 };
+        c_buffer_t* ext_buffer_02 = ::NS(Buffer_new)( ext_buffer_02_capacity );
+        SIXTRL_ASSERT( ext_buffer_02 != nullptr );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( ext_buffer_02 ) >=
+                        ext_buffer_02_capacity );
+
+        size_t const ext_buffer_02_id = job.add_stored_buffer(
+            ext_buffer_02, false ); /* false == take no ownership */
+
+        ASSERT_TRUE(  ext_buffer_02_id != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 2 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_02_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_02_id ) );
+
+        /* This is a C99 buffer -> it is not possible to access it as a C++ buffer*/
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_02_id ) == nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id ) != nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id ) == ext_buffer_02 );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_02_id )
+                        != nullptr );
+
+        arg_t& ext_buffer_02_arg = job.argument_by_buffer_id( ext_buffer_02_id );
+
+        ASSERT_TRUE(  ext_buffer_02_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_02_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_02_arg.ptrCObjectBuffer() == ext_buffer_02 );
+
+        ASSERT_TRUE(  ext_buffer_02_arg.write( ext_buffer_02 ) );
+        ASSERT_TRUE(  ext_buffer_02_arg.read( ext_buffer_02 ) );
+
+        /* --------------------------------------------------------------------- */
+        /* Remove ext_buffer_02 again from the track job: */
+
+        ASSERT_TRUE( st::ARCH_STATUS_SUCCESS == job.remove_stored_buffer(
+            ext_buffer_02_id ) );
+
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 1 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_02_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_02_id ) );
+
+        /* This is a C99 buffer -> it is not possible to access it as a C++ buffer*/
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_02_id ) == nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id ) == nullptr );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_02_id )
+                        == nullptr );
+
+        /* --------------------------------------------------------------------- */
+        /* Add ext_buffer_02 again, but this time let the job take ownership: */
+
+        buffer_addr_t const ext_buffer_02_begin_addr =
+            ::NS(Buffer_get_data_begin_addr)( ext_buffer_02 );
+
+        size_t const ext_buffer_02_size =
+            ::NS(Buffer_get_size)( ext_buffer_02 );
+
+        ext_buffer_02_capacity = ::NS(Buffer_get_capacity)( ext_buffer_02 );
+
+        size_t const ext_buffer_02_id_b = job.add_stored_buffer(
+            ext_buffer_02, true ); /* true == takes ownership */
+
+        uintptr_t const ptr_ext_buffer_02_addr =
+            reinterpret_cast< uintptr_t >( ext_buffer_02 );
+
+        ASSERT_TRUE(  ext_buffer_02_id_b != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 2 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id   == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_02_id_b == job.max_stored_buffer_id() );
+        ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_02_id_b ) );
+
+        /* After taking ownership, the buffer is accessible also as a C++ buffer;
+        but taking ownership creates a new c99 pointer as well -> you can no
+        longer access ext_buffer_02 via it's old handle */
+
+        ext_buffer_02 = nullptr;
+
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id_b )  != nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_02_id_b ) != nullptr );
+        ASSERT_TRUE(  reinterpret_cast< uintptr_t >( job.ptr_stored_buffer(
+                        ext_buffer_02_id_b ) ) != ptr_ext_buffer_02_addr );
+
+        /* Transfering of ownership not only invalidates the old ext_buffer_02
+        * handle, it should also "preset" it with safe default values */
+
+        ASSERT_TRUE( ::NS(Buffer_get_size)( ext_buffer_02 ) == size_t{ 0 } );
+        ASSERT_TRUE( ::NS(Buffer_get_capacity)( ext_buffer_02 ) == size_t{ 0 } );
+
+        /* The values, i.e. start address, capacity and size, should still be
+        * available via the new handle */
+
+        c_buffer_t* ext_buffer_02_b = job.ptr_stored_buffer( ext_buffer_02_id_b );
+        ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ext_buffer_02_b ) ==
+                    ext_buffer_02_begin_addr );
+
+        ASSERT_TRUE( ::NS(Buffer_get_size)( ext_buffer_02_b ) ==
+                    ext_buffer_02_size );
+
+        ASSERT_TRUE( ::NS(Buffer_get_capacity)( ext_buffer_02_b ) ==
+                    ext_buffer_02_capacity );
+
+        ASSERT_TRUE( job.ptr_stored_cxx_buffer( ext_buffer_02_id_b )->getCApiPtr()
+                    == ext_buffer_02_b );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_02_id_b )
+                        != nullptr );
+
+        arg_t& ext_buffer_02_b_arg = job.argument_by_buffer_id( ext_buffer_02_id_b );
+
+        ASSERT_TRUE(  ext_buffer_02_b_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_02_b_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_02_b_arg.ptrCObjectBuffer() == ext_buffer_02_b );
+
+        ASSERT_TRUE(  ext_buffer_02_b_arg.write( ext_buffer_02_b ) );
+        ASSERT_TRUE(  ext_buffer_02_b_arg.read( ext_buffer_02_b ) );
+
+        /* --------------------------------------------------------------------- */
+        /* Add ext_buffer_03, a C99 buffer on the stack: */
+
+        size_t const ext_buffer_03_capacity = size_t{ 2048 };
+        std::vector< unsigned char > ext_buffer_03_data_store(
+            ext_buffer_03_capacity );
+
+        c_buffer_t ext_buffer_03;
+        ::NS(Buffer_preset)( &ext_buffer_03 );
+        status = ::NS(Buffer_init_on_flat_memory)( &ext_buffer_03,
+            ext_buffer_03_data_store.data(), ext_buffer_03_capacity );
+
+        SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+        ( void )status;
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_const_data_begin)(
+            &ext_buffer_03 ) != nullptr );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_data_begin_addr)( &ext_buffer_03 ) ==
+            reinterpret_cast< uintptr_t >( ext_buffer_03_data_store.data() ) );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( &ext_buffer_03 ) >=
+            ext_buffer_03_capacity );
+
+        size_t const ext_buffer_03_id = job.add_stored_buffer(
+            &ext_buffer_03, false ); /* false == take no ownership */
+
+        ASSERT_TRUE(  ext_buffer_03_id != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 3 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_03_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_03_id ) );
+
+        /* This is a C99 buffer -> it is not possible to access it as a C++ buffer*/
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_03_id ) == nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_03_id ) != nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_03_id ) ==
+                    &ext_buffer_03 );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_03_id )
+                        != nullptr );
+
+        arg_t& ext_buffer_03_arg = job.argument_by_buffer_id( ext_buffer_03_id );
+
+        ASSERT_TRUE(  ext_buffer_03_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_03_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_03_arg.ptrCObjectBuffer() == &ext_buffer_03 );
+
+        ASSERT_TRUE(  ext_buffer_03_arg.write( &ext_buffer_03 ) );
+        ASSERT_TRUE(  ext_buffer_03_arg.read( &ext_buffer_03 ) );
+
+        /* --------------------------------------------------------------------- */
+        /* Add ext_buffer_04, a C99 buffer on the stack, but take ownership: */
+
+        size_t ext_buffer_04_capacity = size_t{ 4096 };
+        std::vector< unsigned char > ext_buffer_04_data_store(
+            ext_buffer_04_capacity );
+
+        c_buffer_t ext_buffer_04;
+        ::NS(Buffer_preset)( &ext_buffer_04 );
+        status = ::NS(Buffer_init_on_flat_memory)( &ext_buffer_04,
+            ext_buffer_04_data_store.data(), ext_buffer_04_capacity );
+
+        SIXTRL_ASSERT( status == ::NS(ARCH_STATUS_SUCCESS) );
+
+        buffer_addr_t const ext_buffer_04_begin_addr =
+            ::NS(Buffer_get_data_begin_addr)( &ext_buffer_04 );
+
+        size_t const ext_buffer_04_size = ::NS(Buffer_get_size)( &ext_buffer_04 );
+        ext_buffer_04_capacity = ::NS(Buffer_get_capacity)( &ext_buffer_04 );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_const_data_begin)(
+            &ext_buffer_04 ) != nullptr );
+
+        SIXTRL_ASSERT( ::NS(Buffer_get_capacity)( &ext_buffer_04 ) >=
+            ext_buffer_04_capacity );
+
+        SIXTRL_ASSERT( reinterpret_cast< uintptr_t >(
+            ext_buffer_04_data_store.data() ) == ext_buffer_04_begin_addr );
+
+        size_t const ext_buffer_04_id = job.add_stored_buffer(
+            &ext_buffer_04, true, false ); /* true: take ownership,
+                false: do not delete as ext_buffer_04 is on the stack */
+
+        ASSERT_TRUE(  ext_buffer_04_id != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 4 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_04_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_04_id ) );
+
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_04_id ) != nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_04_id ) != nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_04_id ) !=
+                    &ext_buffer_04 );
+
+        ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( &ext_buffer_04 ) ==
+                    buffer_addr_t{ 0 } );
+
+        ASSERT_TRUE( ::NS(Buffer_get_capacity)( &ext_buffer_04 ) == size_t{ 0 } );
+        ASSERT_TRUE( ::NS(Buffer_get_size)( &ext_buffer_04 ) == size_t{ 0 } );
+
+        c_buffer_t* ptr_ext_buffer_04 =
+            job.ptr_stored_buffer( ext_buffer_04_id );
+
+        ASSERT_TRUE( ptr_ext_buffer_04 != nullptr );
+
+        ASSERT_TRUE( ::NS(Buffer_get_capacity)( ptr_ext_buffer_04 ) ==
+                    ext_buffer_04_capacity );
+
+        ASSERT_TRUE( ::NS(Buffer_get_size)( ptr_ext_buffer_04 ) ==
+                    ext_buffer_04_size );
+
+        ASSERT_TRUE( ::NS(Buffer_get_data_begin_addr)( ptr_ext_buffer_04 ) ==
+                    ext_buffer_04_begin_addr );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_04_id )
+                        != nullptr );
+
+        arg_t& ext_buffer_04_arg = job.argument_by_buffer_id( ext_buffer_04_id );
+
+        ASSERT_TRUE(  ext_buffer_04_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_04_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_04_arg.ptrCObjectBuffer() == ptr_ext_buffer_04 );
+
+        ASSERT_TRUE(  ext_buffer_04_arg.write( ptr_ext_buffer_04 ) );
+        ASSERT_TRUE(  ext_buffer_04_arg.read( ptr_ext_buffer_04 ) );
+
+        /* --------------------------------------------------------------------- */
+        /* Add ext_buffer_05, a C++ buffer, not taking ownership: */
+
+        size_t ext_buffer_05_capacity = size_t{ 8192 };
+        buffer_t ext_buffer_05( ext_buffer_05_capacity );
+        c_buffer_t* ext_buffer_05_cptr = ext_buffer_05.getCApiPtr();
+        SIXTRL_ASSERT( ext_buffer_05_cptr != nullptr );
+
+        ext_buffer_05_capacity = ext_buffer_05.getCapacity();
+
+        size_t const ext_buffer_05_id = job.add_stored_buffer(
+            &ext_buffer_05, false ); /* false == take no ownership */
+
+        ASSERT_TRUE(  ext_buffer_05_id != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 5 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_05_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_05_id ) );
+
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_05_id ) ==
+                    &ext_buffer_05 );
+
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_05_id ) ==
+                    ext_buffer_05_cptr );
+
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_05_id ) ==
+                    ext_buffer_05.getCApiPtr() );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_05_id )
+                        != nullptr );
+
+        arg_t& ext_buffer_05_arg = job.argument_by_buffer_id( ext_buffer_05_id );
+
+        ASSERT_TRUE(  ext_buffer_05_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_05_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_05_arg.ptrCObjectBuffer() ==
+                        ext_buffer_05.getCApiPtr() );
+
+        ASSERT_TRUE(  ext_buffer_05_arg.write( ext_buffer_05.getCApiPtr() ) );
+        ASSERT_TRUE(  ext_buffer_05_arg.read( ext_buffer_05.getCApiPtr() ) );
+
+        /* --------------------------------------------------------------------- */
+        /* Add ext_buffer_06, a C++ buffer but adding as a C99 buffer,
+        * not taking ownership: */
+
+        size_t ext_buffer_06_capacity = size_t{ 6000 };
+        buffer_t ext_buffer_06( ext_buffer_06_capacity );
+        c_buffer_t* ext_buffer_06_cptr = ext_buffer_06.getCApiPtr();
+        SIXTRL_ASSERT( ext_buffer_06_cptr != nullptr );
+
+        ext_buffer_06_capacity = ext_buffer_06.getCapacity();
+
+        size_t const ext_buffer_06_id = job.add_stored_buffer(
+            ext_buffer_06_cptr, false ); /* false == take no ownership */
+
+        ASSERT_TRUE(  ext_buffer_06_id != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 6 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_06_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE( !job.owns_stored_buffer( ext_buffer_06_id ) );
+
+        /* Added as a non-owning C99 pointer -> can not access via C++ interface */
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_06_id ) == nullptr );
+
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_06_id ) ==
+                    ext_buffer_06_cptr );
+
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_06_id ) ==
+                    ext_buffer_06.getCApiPtr() );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_06_id )
+                        != nullptr );
+
+        arg_t& ext_buffer_06_arg = job.argument_by_buffer_id( ext_buffer_06_id );
+
+        ASSERT_TRUE(  ext_buffer_06_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_06_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_06_arg.ptrCObjectBuffer() ==
+                        ext_buffer_06.getCApiPtr() );
+
+        ASSERT_TRUE(  ext_buffer_06_arg.write( ext_buffer_06.getCApiPtr() ) );
+        ASSERT_TRUE(  ext_buffer_06_arg.read( ext_buffer_06.getCApiPtr() ) );
+
+        /* --------------------------------------------------------------------- */
+        /* Add ext_buffer_07, a C++ buffer, transfering ownership by moving in */
+
+        size_t ext_buffer_07_capacity = size_t{ 14000 };
+        buffer_t ext_buffer_07( ext_buffer_07_capacity );
+
+        ext_buffer_07_capacity = ext_buffer_07.getCapacity();
+
+        size_t const ext_buffer_07_size = ext_buffer_07.getSize();
+
+        buffer_addr_t const ext_buffer_07_begin_addr =
+            ext_buffer_07.getDataBeginAddr();
+
+        size_t const ext_buffer_07_id = job.add_stored_buffer(
+            std::move( ext_buffer_07 ) );
+
+        ASSERT_TRUE(  ext_buffer_07_id != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 7 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_07_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_07_id ) );
+
+        /* Added as a non-owning C99 pointer -> can not access via C++ interface */
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_07_id ) != nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_07_id ) != nullptr );
+
+        buffer_t* ptr_ext_buffer_07 = job.ptr_stored_cxx_buffer( ext_buffer_07_id );
+        ASSERT_TRUE( ptr_ext_buffer_07 != nullptr );
+        ASSERT_TRUE( ptr_ext_buffer_07->getCapacity() == ext_buffer_07_capacity );
+        ASSERT_TRUE( ptr_ext_buffer_07->getSize() == ext_buffer_07_size );
+        ASSERT_TRUE( ptr_ext_buffer_07->getDataBeginAddr() ==
+                    ext_buffer_07_begin_addr );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_07_id )
+                        != nullptr );
+
+        arg_t& ext_buffer_07_arg = job.argument_by_buffer_id( ext_buffer_07_id );
+
+        ASSERT_TRUE(  ext_buffer_07_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_07_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_07_arg.ptrCObjectBuffer() == ptr_ext_buffer_07 );
+
+        ASSERT_TRUE(  ext_buffer_07_arg.write( ptr_ext_buffer_07 ) );
+        ASSERT_TRUE(  ext_buffer_07_arg.read( ptr_ext_buffer_07 ) );
+
+        /* --------------------------------------------------------------------- */
+        /* Add ext_buffer_08, a C++ buffer, transfer ownership */
+
+        size_t ext_buffer_08_capacity = size_t{ 856 };
+        buffer_t* ext_buffer_08 = new buffer_t( ext_buffer_08_capacity );
+        ASSERT_TRUE( ext_buffer_08 != nullptr );
+
+        ext_buffer_08_capacity = ext_buffer_08->getCapacity();
+
+        size_t const ext_buffer_08_id =
+            job.add_stored_buffer( ext_buffer_08, true );
+
+        ASSERT_TRUE(  ext_buffer_08_id != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.num_stored_buffers() == size_t{ 8 } );
+        ASSERT_TRUE(  job.min_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+        ASSERT_TRUE(  job.max_stored_buffer_id() != st::ARCH_ILLEGAL_BUFFER_ID );
+
+        ASSERT_TRUE(  ext_buffer_01_id == job.min_stored_buffer_id() );
+        ASSERT_TRUE(  ext_buffer_08_id == job.max_stored_buffer_id() );
+        ASSERT_TRUE(  job.owns_stored_buffer( ext_buffer_08_id ) );
+
+        ext_buffer_08 = nullptr;
+
+        /* Added as a non-owning C99 pointer -> can not access via C++ interface */
+        ASSERT_TRUE(  job.ptr_stored_cxx_buffer( ext_buffer_08_id ) != nullptr );
+        ASSERT_TRUE(  job.ptr_stored_buffer( ext_buffer_08_id ) != nullptr );
+
+        ASSERT_TRUE(  job.ptr_argument_by_buffer_id( ext_buffer_08_id )
+                        != nullptr );
+
+        arg_t& ext_buffer_08_arg = job.argument_by_buffer_id( ext_buffer_08_id );
+
+        ASSERT_TRUE(  ext_buffer_08_arg.context() == job.ptrContext() );
+        ASSERT_TRUE(  ext_buffer_08_arg.usesCObjectBuffer() );
+        ASSERT_TRUE(  ext_buffer_08_arg.ptrCObjectBuffer() ==
+                        job.ptr_stored_buffer( ext_buffer_08_id ) );
+
+        ASSERT_TRUE(  ext_buffer_08_arg.write(
+                        job.ptr_stored_buffer( ext_buffer_08_id ) ) );
+
+        ASSERT_TRUE(  ext_buffer_08_arg.read(
+                        job.ptr_stored_buffer( ext_buffer_08_id ) ) );
+    }
+}
+
+/* end: tests/sixtracklib/opencl/test_track_job_cl_stored_buffer_cxx.cpp */
diff --git a/tests/sixtracklib/opencl/test_track_job_fetch_particle_addr_c99.cpp b/tests/sixtracklib/opencl/test_track_job_fetch_particle_addr_c99.cpp
new file mode 100644
index 00000000..3c986edd
--- /dev/null
+++ b/tests/sixtracklib/opencl/test_track_job_fetch_particle_addr_c99.cpp
@@ -0,0 +1,146 @@
+#include "sixtracklib/opencl/track_job_cl.h"
+
+#include <iomanip>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/particles.h"
+#include "sixtracklib/common/particles/particles_addr.h"
+
+TEST( C99OpenCLTrackTrackJobFetchParticleAddr, BasicUsage )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+
+    using particles_t           = ::NS(Particles);
+    using particles_addr_t      = ::NS(ParticlesAddr);
+    using track_job_t           = ::NS(TrackJobCl);
+    using buffer_t              = ::NS(Buffer);
+    using st_size_t             = ::NS(buffer_size_t);
+    using st_status_t           = ::NS(arch_status_t);
+    using controller_t          = ::NS(ClContext);
+    using node_id_t             = ::NS(ComputeNodeId);
+    using node_info_t           = ::NS(ComputeNodeInfo);
+
+    buffer_t* eb = ::NS(Buffer_new_from_file)(
+        ::NS(PATH_TO_BEAMBEAM_BEAM_ELEMENTS) );
+
+    buffer_t* pb = ::NS(Buffer_new_from_file)(
+        ::NS(PATH_TO_BEAMBEAM_PARTICLES_DUMP) );
+
+    SIXTRL_ASSERT( eb != SIXTRL_NULLPTR );
+    SIXTRL_ASSERT( pb != SIXTRL_NULLPTR );
+
+    st_size_t const NUM_PARTICLE_SETS = ::NS(Buffer_get_num_of_objects)( pb );
+    st_size_t const NUM_AVAILABLE_NODES = ::NS(OpenCL_num_available_nodes)(
+        "SIXTRACKLIB_DEVICES" );
+
+    if( NUM_AVAILABLE_NODES == size_t{ 0 } )
+    {
+        std::cout << "No OpenCL nodes available -> skipping tests\r\n";
+        return;
+    }
+
+    std::vector< node_id_t > AVAILABLE_NODES(
+        NUM_AVAILABLE_NODES, node_id_t{} );
+
+    st_size_t const NUM_NODES = ::NS(OpenCL_get_available_nodes)(
+        AVAILABLE_NODES.data(), AVAILABLE_NODES.size() );
+
+    ASSERT_TRUE( NUM_NODES > size_t{ 0 } );
+
+    for( auto const& node_id : AVAILABLE_NODES )
+    {
+        char tmp_device_id_str[] =
+        {
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+        };
+
+        ASSERT_TRUE( 0 == ::NS(ComputeNodeId_to_string)(
+            &node_id, tmp_device_id_str, 16u ) );
+
+        track_job_t* track_job = NS(TrackJobCl_new)(
+            tmp_device_id_str, pb, eb );
+        ASSERT_TRUE( track_job != nullptr );
+
+        controller_t* controller = NS(TrackJobCl_get_context)( track_job );
+
+        ASSERT_TRUE( controller != nullptr );
+        ASSERT_TRUE( controller->hasSelectedNode() );
+
+        node_info_t const* selected_node_info =
+            ::NS(ClContextBase_get_selected_node_info)( controller );
+
+        node_id_t const default_node_id =
+            ::NS(ClContextBase_get_default_node_id)( controller );
+
+        ASSERT_TRUE( selected_node_info != nullptr );
+        std::cout << "[          ] [ INFO ] Selected Node \r\n";
+        ::NS(ComputeNodeInfo_print_out)( selected_node_info, &default_node_id );
+        std::cout << "\r\n";
+
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+        ASSERT_TRUE( ::NS(TrackJob_can_fetch_particles_addr)( track_job ) );
+
+        if( !::NS(TrackJob_has_particles_addr)( track_job ) )
+        {
+            status = NS(TrackJob_fetch_particle_addresses)( track_job );
+        }
+
+        ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+        ASSERT_TRUE( ::NS(TrackJob_has_particles_addr)( track_job ) );
+        ASSERT_TRUE( ::NS(TrackJob_get_const_particles_addr_buffer)(
+                        track_job ) );
+
+        st_size_t const slot_size = ::NS(Buffer_get_slot_size)(
+            ::NS(TrackJob_get_const_particles_addr_buffer)( track_job ) );
+
+        for( st_size_t ii = st_size_t{ 0 } ; ii < NUM_PARTICLE_SETS ; ++ii )
+        {
+            particles_t const* cmp_particles =
+                ::NS(Particles_buffer_get_const_particles)( pb, ii );
+            ASSERT_TRUE( cmp_particles != nullptr );
+
+            particles_addr_t const* particles_addr =
+                ::NS(TrackJob_particle_addresses)( track_job, ii );
+
+            ASSERT_TRUE( particles_addr != nullptr );
+            ASSERT_TRUE( ::NS(Particles_get_num_of_particles)(
+                cmp_particles ) == particles_addr->num_particles );
+
+            bool const are_consistent =
+                ::NS(TestParticlesAddr_are_addresses_consistent_with_particle)(
+                    particles_addr, cmp_particles, slot_size );
+
+            ASSERT_TRUE( are_consistent );
+        }
+
+        status = ::NS(TrackJob_clear_all_particle_addresses)( track_job );
+        ASSERT_TRUE(  status == st::ARCH_STATUS_SUCCESS );
+        ASSERT_TRUE(  ::NS(TrackJob_can_fetch_particles_addr)( track_job ) );
+        ASSERT_TRUE( !::NS(TrackJob_has_particles_addr)( track_job ) );
+
+        ::NS(TrackJob_delete)( track_job );
+        track_job  = nullptr;
+        controller = nullptr;
+    }
+
+    ::NS(Buffer_delete)( pb );
+    ::NS(Buffer_delete)( eb );
+
+    pb = nullptr;
+    eb = nullptr;
+}
+
+/* end: tests/sixtracklib/cuda/track/test_track_job_fetch_particle_addr_cxx.cpp */
diff --git a/tests/sixtracklib/opencl/test_track_job_fetch_particle_addr_cxx.cpp b/tests/sixtracklib/opencl/test_track_job_fetch_particle_addr_cxx.cpp
new file mode 100644
index 00000000..d1e452af
--- /dev/null
+++ b/tests/sixtracklib/opencl/test_track_job_fetch_particle_addr_cxx.cpp
@@ -0,0 +1,123 @@
+#include "sixtracklib/opencl/track_job_cl.h"
+
+#include <iomanip>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "sixtracklib/testlib.hpp"
+
+#include "sixtracklib/common/definitions.h"
+#include "sixtracklib/common/particles.hpp"
+#include "sixtracklib/common/particles/particles_addr.hpp"
+
+TEST( CXXOpenCLTrackTrackJobFetchParticleAddr, BasicUsage )
+{
+    namespace st = SIXTRL_CXX_NAMESPACE;
+
+    using particles_t           = st::Particles;
+    using particles_addr_t      = ::NS(ParticlesAddr);
+    using track_job_t           = st::TrackJobCl;
+    using buffer_t              = track_job_t::buffer_t;
+    using st_size_t             = track_job_t::size_type;
+    using st_status_t           = track_job_t::status_t;
+    using controller_t          = track_job_t::context_t;
+    using node_id_t             = controller_t::node_id_t;
+    using node_info_t           = controller_t::node_info_t;
+
+    buffer_t eb( ::NS(PATH_TO_BEAMBEAM_BEAM_ELEMENTS) );
+    buffer_t pb( ::NS(PATH_TO_BEAMBEAM_PARTICLES_DUMP) );
+
+    st_size_t const NUM_PARTICLE_SETS = pb.getNumObjects();
+    st_size_t const NUM_AVAILABLE_NODES = controller_t::NUM_AVAILABLE_NODES();
+
+    if( NUM_AVAILABLE_NODES == size_t{ 0 } )
+    {
+        std::cout << "No OpenCL nodes available -> skipping tests\r\n";
+        return;
+    }
+
+    std::vector< node_id_t > AVAILABLE_NODES(
+        NUM_AVAILABLE_NODES, node_id_t{} );
+
+    st_size_t const NUM_NODES = controller_t::GET_AVAILABLE_NODES(
+        AVAILABLE_NODES.data(), AVAILABLE_NODES.size(), st_size_t{ 0 } );
+
+    ASSERT_TRUE( NUM_NODES > size_t{ 0 } );
+
+    for( auto const& node_id : AVAILABLE_NODES )
+    {
+        char tmp_device_id_str[] =
+        {
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
+            '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
+        };
+
+        ASSERT_TRUE( 0 == ::NS(ComputeNodeId_to_string)(
+            &node_id, tmp_device_id_str, 16u ) );
+
+        track_job_t track_job( tmp_device_id_str, pb, eb );
+        controller_t* controller = track_job.ptrContext();
+
+        ASSERT_TRUE( controller != nullptr );
+        ASSERT_TRUE( controller->hasSelectedNode() );
+
+        node_info_t const* selected_node_info =
+            controller->ptrSelectedNodeInfo();
+
+        node_id_t const default_node_id = controller->defaultNodeId();
+
+        ASSERT_TRUE( selected_node_info != nullptr );
+        std::cout << "[          ] [ INFO ] Selected Node \r\n";
+        ::NS(ComputeNodeInfo_print_out)( selected_node_info, &default_node_id );
+        std::cout << "\r\n";
+
+        st_status_t status = st::ARCH_STATUS_SUCCESS;
+        ASSERT_TRUE( track_job.canFetchParticleAddresses() );
+
+        if( !track_job.hasParticleAddresses() )
+        {
+            status = track_job.fetchParticleAddresses();
+        }
+
+        ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+        ASSERT_TRUE( track_job.hasParticleAddresses() );
+        ASSERT_TRUE( track_job.ptrParticleAddressesBuffer() != nullptr );
+
+        st_size_t const slot_size =
+            track_job.ptrParticleAddressesBuffer()->getSlotSize();
+
+        for( st_size_t ii = st_size_t{ 0 } ; ii < NUM_PARTICLE_SETS ; ++ii )
+        {
+            particles_t const* cmp_particles = pb.get< particles_t >( ii );
+            ASSERT_TRUE( cmp_particles != nullptr );
+
+            particles_addr_t const* particles_addr =
+                track_job.particleAddresses( ii );
+
+            ASSERT_TRUE( particles_addr != nullptr );
+            ASSERT_TRUE( cmp_particles->getNumParticles() ==
+                         particles_addr->num_particles );
+
+            bool const are_consistent =
+                ::NS(TestParticlesAddr_are_addresses_consistent_with_particle)(
+                    particles_addr, cmp_particles->getCApiPtr(), slot_size );
+
+            ASSERT_TRUE( are_consistent );
+        }
+
+        status = track_job.clearAllParticleAddresses();
+        ASSERT_TRUE( status == st::ARCH_STATUS_SUCCESS );
+        ASSERT_TRUE( track_job.canFetchParticleAddresses() );
+        ASSERT_TRUE( !track_job.hasParticleAddresses() );
+    }
+}
+
+/* end: tests/sixtracklib/cuda/track/test_track_job_fetch_particle_addr_cxx.cpp */
diff --git a/tests/sixtracklib/opencl/test_track_job_update_region_c99.cpp b/tests/sixtracklib/opencl/test_track_job_update_region_c99.cpp
index b0522b38..3a0ccbfa 100644
--- a/tests/sixtracklib/opencl/test_track_job_update_region_c99.cpp
+++ b/tests/sixtracklib/opencl/test_track_job_update_region_c99.cpp
@@ -44,7 +44,7 @@ TEST( C99_OpenCL_ClArgumentUpdateRegionTest, BasicUsage )
     for( size_t ii = size_t{ 0 } ; ii < num_beam_elements ; ++ii )
     {
         cavity_t const* ptr_cavity =
-            ::NS(BeamElements_buffer_get_const_cavity)( lattice, ii );
+            ::NS(Cavity_const_from_buffer)( lattice, ii );
 
         if( ptr_cavity != nullptr )
         {
@@ -71,7 +71,7 @@ TEST( C99_OpenCL_ClArgumentUpdateRegionTest, BasicUsage )
     {
         size_t const idx = cavity_indices[ ii ];
         cavity_t const* ptr_orig_cavity =
-            ::NS(BeamElements_buffer_get_const_cavity)( lattice, idx );
+            ::NS(Cavity_const_from_buffer)( lattice, idx );
         ASSERT_TRUE( ptr_orig_cavity != nullptr );
 
         cavity_t* ptr_cavity = &cavities[ ii ];
@@ -101,7 +101,7 @@ TEST( C99_OpenCL_ClArgumentUpdateRegionTest, BasicUsage )
     {
         size_t const idx = cavity_indices[ ii ];
         cavity_t const* ptr_orig_cavity =
-            NS(BeamElements_buffer_get_const_cavity)( lattice, idx );
+            NS(Cavity_const_from_buffer)( lattice, idx );
         ASSERT_TRUE( ptr_orig_cavity != nullptr );
 
         cavity_t* ptr_cavity = &cavities[ ii ];
@@ -135,7 +135,7 @@ TEST( C99_OpenCL_ClArgumentUpdateRegionTest, BasicUsage )
     {
         size_t const idx = cavity_indices[ ii ];
         cavity_t const* ptr_orig_cavity =
-            ::NS(BeamElements_buffer_get_const_cavity)( lattice, idx );
+            ::NS(Cavity_const_from_buffer)( lattice, idx );
         ASSERT_TRUE( ptr_orig_cavity != nullptr );
 
         cavity_t* ptr_cavity = &cavities[ ii ];
diff --git a/tests/sixtracklib/testlib.h b/tests/sixtracklib/testlib.h
index 4276c112..bfa33a40 100644
--- a/tests/sixtracklib/testlib.h
+++ b/tests/sixtracklib/testlib.h
@@ -5,13 +5,17 @@
 #include "sixtracklib/common/definitions.h"
 #include "sixtracklib/common/generated/modules.h"
 
-#include "sixtracklib/testlib/common/generic_buffer_obj.h"
 #include "sixtracklib/testlib/common/gpu_kernel.h"
 #include "sixtracklib/testlib/common/random.h"
 #include "sixtracklib/testlib/common/time.h"
 #include "sixtracklib/testlib/common/particles/particles.h"
 #include "sixtracklib/testlib/common/particles/particles_addr.h"
 
+#include "sixtracklib/testlib/common/buffer/buffer.h"
+#include "sixtracklib/testlib/common/buffer/assign_address_item.h"
+#include "sixtracklib/testlib/common/buffer/generic_buffer_obj.h"
+// #include "sixtracklib/testlib/common/buffer/binary_array_buffer.h"
+
 #include "sixtracklib/testlib/common/output/assign_be_monitor_ctrl_arg.h"
 #include "sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.h"
 
@@ -19,7 +23,6 @@
 #include "sixtracklib/testlib/common/track/track_particles_cpu.h"
 #include "sixtracklib/testlib/common/track/track_particles_ctrl_arg.h"
 
-#include "sixtracklib/testlib/common/buffer.h"
 #include "sixtracklib/testlib/common/beam_elements/beam_elements.h"
 #include "sixtracklib/testlib/common/path.h"
 #include "sixtracklib/testlib/testdata/track_testdata.h"
diff --git a/tests/sixtracklib/testlib/CMakeLists.txt b/tests/sixtracklib/testlib/CMakeLists.txt
index 1a7606df..f5640269 100644
--- a/tests/sixtracklib/testlib/CMakeLists.txt
+++ b/tests/sixtracklib/testlib/CMakeLists.txt
@@ -57,9 +57,8 @@ set_target_properties( sixtrack_test PROPERTIES C_STANDARD 99 )
 set_target_properties( sixtrack_test PROPERTIES C_STANDARD_REQUIRED ON )
 set_target_properties( sixtrack_test PROPERTIES DEBUG_POSTFIX d )
 
-target_compile_options( sixtrack_test
-                        PRIVATE -Wall -Werror -pedantic -ansi
-                        ${SIXTRACKLIB_CPU_FLAGS} )
+target_compile_options( sixtrack_test PRIVATE ${SIXTRACKLIB_C99_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # provide a copy of the library to the python module if it is defined!
diff --git a/tests/sixtracklib/testlib/common/CMakeLists.txt b/tests/sixtracklib/testlib/common/CMakeLists.txt
index b29e2abf..e59a9a7c 100644
--- a/tests/sixtracklib/testlib/common/CMakeLists.txt
+++ b/tests/sixtracklib/testlib/common/CMakeLists.txt
@@ -12,32 +12,18 @@ set( SIXTRL_TESTLIB_COMMON_INSTALL_CXX_PATH
 # ------------------------------------------------------------------------------
 
 add_subdirectory( beam_elements )
+add_subdirectory( buffer )
 add_subdirectory( particles )
 add_subdirectory( track )
 add_subdirectory( output )
 
 # ------------------------------------------------------------------------------
 
-set( TESTLIB_COMMON_C99_HEADERS
-     buffer.h
-     generic_buffer_obj.h
-     gpu_kernel.h
-     random.h
-     time.h
-)
-
-set( TESTLIB_COMMON_C99_SOURCES
-     buffer.c
-     generic_buffer_obj.c
-     gpu_kernel.c
-     random.c
-     time.c
-)
+set( TESTLIB_COMMON_C99_HEADERS gpu_kernel.h random.h time.h )
+set( TESTLIB_COMMON_C99_SOURCES gpu_kernel.c random.c time.c )
 
 add_library( sixtrack_test_common_c99 OBJECT
-            ${TESTLIB_COMMON_C99_HEADERS}
-            ${TESTLIB_COMMON_C99_SOURCES}
-)
+    ${TESTLIB_COMMON_C99_HEADERS} ${TESTLIB_COMMON_C99_SOURCES} )
 
 target_include_directories( sixtrack_test_common_c99 PRIVATE
     PRIVATE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
@@ -48,7 +34,8 @@ set_target_properties( sixtrack_test_common_c99 PROPERTIES
     C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_test_common_c99 PRIVATE
-        -Wall -Werror -pedantic -ansi ${SIXTRACKLIB_CPU_FLAGS} )
+        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+        ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_test_common as a module for sixtrack_test:
diff --git a/tests/sixtracklib/testlib/common/beam_elements/CMakeLists.txt b/tests/sixtracklib/testlib/common/beam_elements/CMakeLists.txt
index 2dbf4c0f..05fa339d 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/CMakeLists.txt
+++ b/tests/sixtracklib/testlib/common/beam_elements/CMakeLists.txt
@@ -3,26 +3,19 @@
 
 set( SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_CXX_HEADERS )
 set( SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_C99_HEADERS
-     be_beamfields.h
-     be_limit_rect.h
-     be_limit_ellipse.h
-     be_dipedge.h
-     beam_elements.h
-)
+     be_beamfields.h be_drift.h be_cavity.h be_monitor.h be_multipole.h
+     be_limit_rect.h be_limit_ellipse.h be_limit_rect_ellipse.h be_rfmultipole.h
+     be_dipedge.h be_srotation.h be_tricub.h be_xy_shift.h beam_elements.h )
 
 set( SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_C99_SOURCES
-     be_beamfields.c
-     be_limit_rect.c
-     be_limit_ellipse.c
-     be_dipedge.c
-     beam_elements.c
-)
+     be_beamfields.c be_drift.c be_cavity.c be_monitor.c be_multipole.c
+     be_limit_rect.c be_limit_ellipse.c be_limit_rect_ellipse.c be_rfmultipole.c
+     be_dipedge.c be_srotation.c be_tricub.c be_xy_shift.c beam_elements.c )
 
 add_library( sixtrack_test_common_belems_c99 OBJECT
     ${SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_CXX_HEADERS}
     ${SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_C99_HEADERS}
-    ${SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_C99_SOURCES}
-)
+    ${SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_C99_SOURCES} )
 
 target_include_directories( sixtrack_test_common_belems_c99 PRIVATE
     PRIVATE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
@@ -33,13 +26,13 @@ set_target_properties( sixtrack_test_common_belems_c99 PROPERTIES
     C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_test_common_belems_c99 PRIVATE
-        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_test_common_belems_c99 as a module for sixtrack_test:
 
-set(  SIXTRACKL_TESTLIB_LIBRARY_MODULES
-    ${SIXTRACKL_TESTLIB_LIBRARY_MODULES}
+set(  SIXTRACKL_TESTLIB_LIBRARY_MODULES ${SIXTRACKL_TESTLIB_LIBRARY_MODULES}
     $<TARGET_OBJECTS:sixtrack_test_common_belems_c99> CACHE INTERNAL "" FORCE )
 
 # ==============================================================================
@@ -64,5 +57,3 @@ if( SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_CXX_HEADERS AND
         DESTINATION ${SIXTRL_TESTLIB_COMMON_BEAM_ELEMENTS_CXX_INSTALL_PATH} )
 
 endif()
-
-# end: tests/sixtracklib/testlib/common/beam_elements/CMakeLists.txt
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_beamfields.c b/tests/sixtracklib/testlib/common/beam_elements/be_beamfields.c
index a6c08c4f..ca2a6c59 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/be_beamfields.c
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_beamfields.c
@@ -14,14 +14,10 @@ void NS(BeamBeam4D_print)(
     SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT e )
 {
-    typedef NS(beambeam4d_real_const_ptr_t)  bb_data_ptr_t;
-    typedef SIXTRL_BE_DATAPTR_DEC NS(BB4D_data)* data_ptr_t;
+    SIXTRL_BE_DATAPTR_DEC NS(BB4D_data) const* bb4data =
+        NS(BeamBeam4D_const_data)( e );
 
-    bb_data_ptr_t data = NS(BeamBeam4D_get_const_data)( e );
-    data_ptr_t bb4ddata = ( data_ptr_t )data;
-
-    if( ( fp != SIXTRL_NULLPTR ) &&
-        ( bb4ddata != SIXTRL_NULLPTR ) )
+    if( ( fp != SIXTRL_NULLPTR ) && ( bb4data != SIXTRL_NULLPTR ) )
     {
         fprintf( fp,
                  "|beambeam4d      | q_part         = %+20e\r\n"
@@ -35,56 +31,15 @@ void NS(BeamBeam4D_print)(
                  "                 | Dpx_sub        = %+20.12f\r\n"
                  "                 | Dpy_sub        = %+20.12f\r\n"
                  "                 | enabled        = %20ld\r\n",
-                 bb4ddata->q_part,  bb4ddata->N_part,  bb4ddata->sigma_x,
-                 bb4ddata->sigma_y, bb4ddata->beta_s,  bb4ddata->min_sigma_diff,
-                 bb4ddata->Delta_x, bb4ddata->Delta_y, bb4ddata->Dpx_sub,
-                 bb4ddata->Dpy_sub, ( long int )bb4ddata->enabled );
+                 bb4data->q_part,  bb4data->N_part,  bb4data->sigma_x,
+                 bb4data->sigma_y, bb4data->beta_s,  bb4data->min_sigma_diff,
+                 bb4data->Delta_x, bb4data->Delta_y, bb4data->Dpx_sub,
+                 bb4data->Dpy_sub, ( long int )bb4data->enabled );
     }
 
     return;
 }
 
-/* ************************************************************************* */
-/* SpaceChargeCoasting:  */
-
-void NS(SpaceChargeCoasting_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT e )
-{
-    typedef NS(beambeam4d_real_const_ptr_t)  sc_data_ptr_t;
-    sc_data_ptr_t data =
-        ( sc_data_ptr_t )NS(SpaceChargeCoasting_get_const_data)( e );
-
-    if( ( data != SIXTRL_NULLPTR ) &&
-        ( fp != SIXTRL_NULLPTR ) )
-    {
-        fprintf( fp, "|sc coasting     | \r\n" );
-    }
-
-    return;
-}
-
-
-/* ************************************************************************* */
-/* SpaceChargeBunched:  */
-
-void NS(SpaceChargeBunched_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT e )
-{
-    typedef NS(beambeam4d_real_const_ptr_t)  sc_data_ptr_t;
-    sc_data_ptr_t data = NS(SpaceChargeBunched_get_const_data)( e );
-
-    if( ( data != SIXTRL_NULLPTR ) &&
-        ( fp != SIXTRL_NULLPTR ) )
-    {
-        fprintf( fp, "|sc bunched      | \r\n" );
-    }
-
-    return;
-}
-
-
 /* ************************************************************************* */
 /* BeamBeam6D:  */
 
@@ -92,15 +47,14 @@ void NS(BeamBeam6D_print)(
     SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT elem )
 {
-    typedef SIXTRL_REAL_T                               real_t;
-    typedef SIXTRL_BE_DATAPTR_DEC real_t const*         ptr_real_t;
-    typedef SIXTRL_BE_DATAPTR_DEC NS(BB6D_data) const*  data_ptr_t;
-
-    data_ptr_t bb6ddata = ( data_ptr_t )NS(BeamBeam6D_get_const_data)( elem );
+    SIXTRL_BE_DATAPTR_DEC NS(BB6D_data) const* bb6ddata =
+        NS(BeamBeam6D_const_data)( elem );
 
     if( ( bb6ddata != SIXTRL_NULLPTR ) && ( bb6ddata->enabled ) &&
         ( fp != SIXTRL_NULLPTR ) )
     {
+        typedef SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* ptr_real_t;
+
         int num_slices = (int)(bb6ddata->N_slices);
         int ii = 0;
 
@@ -154,4 +108,194 @@ void NS(BeamBeam6D_print)(
     return;
 }
 
-/*end: tests/sixtracklib/testlib/common/be_beamfields/be_beamfields.c */
+/* ************************************************************************* */
+/* SCCoasting:  */
+
+void NS(SCCoasting_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const SIXTRL_RESTRICT e )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( e != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp,
+                 "|sc coasting     | number_of_particles = %+20.12f\r\n"
+                 "                 | circumference       = %+20.12f\r\n"
+                 "                 | sigma_x             = %+20.12f\r\n"
+                 "                 | sigma_y             = %+20.12f\r\n"
+                 "                 | length              = %+20.12f\r\n"
+                 "                 | x_co                = %+20.12f\r\n"
+                 "                 | y_co                = %+20.12f\r\n"
+                 "                 | min_sigma_diff      = %+20.12f\r\n"
+                 "                 | enabled             = %20lu\r\n",
+            e->number_of_particles, e->circumference, e->sigma_x, e->sigma_y,
+            e->length, e->x_co, e->y_co, e->min_sigma_diff,
+            ( unsigned long )e->enabled );
+    }
+
+    return;
+}
+
+/* ************************************************************************* */
+/* SCQGaussProfile:  */
+
+void NS(SCQGaussProfile_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const
+        NS(SCQGaussProfile) *const SIXTRL_RESTRICT e )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( e != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp,
+                 "|sc q-gaussian   | number_of_particles = %+20.12f\r\n"
+                 "                 | circumference       = %+20.12f\r\n"
+                 "                 | sigma_x             = %+20.12f\r\n"
+                 "                 | sigma_y             = %+20.12f\r\n"
+                 "                 | length              = %+20.12f\r\n"
+                 "                 | x_co                = %+20.12f\r\n"
+                 "                 | y_co                = %+20.12f\r\n"
+                 "                 | min_sigma_diff      = %+20.12f\r\n"
+                 "                 | q_param             = %+20.12f\r\n"
+                 "                 | cq                  = %+20.12f\r\n"
+                 "                 | enabled             = %20lu\r\n",
+            e->number_of_particles, e->bunchlength_rms, e->sigma_x, e->sigma_y,
+            e->length, e->x_co, e->y_co, e->min_sigma_diff, e->q_param,
+            e->cq, ( unsigned long )e->enabled );
+    }
+
+    return;
+}
+
+/* ************************************************************************* */
+/* SCInterpolatedProfile:  */
+
+void NS(LineDensityProfileData_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(LineDensityProfileData) *const SIXTRL_RESTRICT e )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( e != SIXTRL_NULLPTR ) )
+    {
+        NS(math_abscissa_idx_t) const nvalues =
+            NS(LineDensityProfileData_num_values)( e );
+
+        fprintf( fp, "|lprof density data  | method            = " );
+
+        switch( NS(LineDensityProfileData_method)( e ) )
+        {
+            case NS(MATH_INTERPOL_LINEAR):
+            {
+                fprintf( fp, "linear" );
+                break;
+            }
+
+            case NS(MATH_INTERPOL_CUBIC):
+            {
+                fprintf( fp, "cubic" );
+                break;
+            }
+
+            default:
+            {
+                fprintf( fp, "n/a (unknown)" );
+            }
+        };
+
+        fprintf( fp, "\r\n"
+                "                     | num_values        = %21ld\r\n"
+                "                     | values_addr       = %21lx\r\n"
+                "                     | derivatives_addr  = %21lx\r\n"
+                "                     | z0                = %+20.12f\r\n"
+                "                     | dz                = %+20.12f\r\n"
+                "                     | capacity          = %21ld\r\n",
+                ( long int )NS(LineDensityProfileData_num_values)( e ),
+                ( uintptr_t )NS(LineDensityProfileData_values_addr)( e ),
+                ( uintptr_t )NS(LineDensityProfileData_derivatives_addr)( e ),
+                NS(LineDensityProfileData_z0)( e ),
+                NS(LineDensityProfileData_dz)( e ),
+                ( long int )NS(LineDensityProfileData_capacity)( e ) );
+
+        if( nvalues > ( NS(math_abscissa_idx_t ) )0 )
+        {
+            fprintf( fp, "                     |" " ii"
+                    "                     z"
+                    "                 value"
+                    "      derivative value\r\n" );
+        }
+
+        if( nvalues <= ( NS(math_abscissa_idx_t) )10 )
+        {
+            NS(math_abscissa_idx_t) ii = ( NS(math_abscissa_idx_t) )0;
+            SIXTRL_REAL_T z = NS(LineDensityProfileData_z0)( e );
+
+            for( ; ii < nvalues ; ++ii )
+            {
+                fprintf( fp, "                     |%3ld"
+                        "%+20.12f""%+20.12f""%+20.12f\r\n", ( long int )ii, z,
+                        NS(LineDensityProfileData_value_at_idx)( e, ii ),
+                        NS(LineDensityProfileData_derivatives_at_idx)( e, ii ) );
+
+                z += NS(LineDensityProfileData_dz)( e );
+            }
+        }
+        else
+        {
+            NS(math_abscissa_idx_t) ii = ( NS(math_abscissa_idx_t) )0;
+            SIXTRL_REAL_T z = NS(LineDensityProfileData_z0)( e );
+
+            for( ; ii < 5 ; ++ii )
+            {
+                fprintf( fp, "                     |%3ld"
+                        "%+20.12f""%+20.12f""%+20.12f\r\n", ( long int )ii, z,
+                        NS(LineDensityProfileData_value_at_idx)( e, ii ),
+                        NS(LineDensityProfileData_derivatives_at_idx)( e, ii ) );
+
+                z += NS(LineDensityProfileData_dz)( e );
+            }
+
+            fprintf( fp, "                         | .. ..................... "
+                    "..................... .....................\r\n" );
+
+            ii = nvalues - 6;
+            z = NS(LineDensityProfileData_z0)( e ) +
+                NS(LineDensityProfileData_dz)( e ) * ii;
+
+            for( ; ii < 5 ; ++ii )
+            {
+                fprintf( fp, "                     |%3ld"
+                        "%+20.12f""%+20.12f""%+20.12f\r\n", ( long int )ii, z,
+                        NS(LineDensityProfileData_value_at_idx)( e, ii ),
+                        NS(LineDensityProfileData_derivatives_at_idx)( e, ii ) );
+
+                z += NS(LineDensityProfileData_dz)( e );
+            }
+        }
+    }
+}
+
+/* ************************************************************************* */
+/* SCInterpolatedProfile:  */
+
+void NS(SCInterpolatedProfile_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const
+        NS(SCInterpolatedProfile) *const SIXTRL_RESTRICT e )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( e != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp,
+                 "|sc interpolated | number_of_particles   = %+20.12f\r\n"
+                 "                 | sigma_x               = %+20.12f\r\n"
+                 "                 | sigma_y               = %+20.12f\r\n"
+                 "                 | length                = %+20.12f\r\n"
+                 "                 | x_co                  = %+20.12f\r\n"
+                 "                 | y_co                  = %+20.12f\r\n"
+                 "                 | interpol_data_addr    = %21lu\r\n"
+                 "                 | line_density_fallback = %+20.12f\r\n"
+                 "                 | min_sigma_diff        = %+20.12f\r\n"
+                 "                 | enabled               = %20lu\r\n",
+            e->number_of_particles, e->sigma_x, e->sigma_y, e->length, e->x_co,
+            e->y_co, ( unsigned long )e->interpol_data_addr,
+            e->line_density_prof_fallback, e->min_sigma_diff,
+            ( unsigned long )e->enabled );
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_beamfields.h b/tests/sixtracklib/testlib/common/beam_elements/be_beamfields.h
index 368d32d8..796926a4 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/be_beamfields.h
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_beamfields.h
@@ -15,6 +15,7 @@
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/buffer/buffer_type.h"
     #include "sixtracklib/common/be_beamfields/be_beamfields.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -26,15 +27,17 @@ extern "C" {
 
 SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam4D_compare_values)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT rhs );
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam4D_compare_values_with_treshold)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT lhs,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam4D_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam4D) *const SIXTRL_RESTRICT e );
+    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT e );
 
 #if !defined( _GPUCODE )
 
@@ -45,87 +48,148 @@ SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BeamBeam4D_print)(
 #endif /* !defined( _GPUCODE ) */
 
 /* ************************************************************************** */
-/* SpaceChargeCoasting: */
+/* BeamBeam6D: */
+
+SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam6D_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN int NS(SpaceChargeCoasting_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting)
+SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam6D_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam6D_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam6D) *const SIXTRL_RESTRICT e );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BeamBeam6D_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam6D) *const SIXTRL_RESTRICT e );
+
+#endif /* !defined( _GPUCODE ) */
+
+/* ************************************************************************** */
+/* SCCoasting: */
+
+SIXTRL_STATIC SIXTRL_FN int NS(SCCoasting_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
         *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting)
-        *const SIXTRL_RESTRICT rhs );
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
+        *const SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN int NS(SpaceChargeCoasting_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting)
+SIXTRL_STATIC SIXTRL_FN int NS(SCCoasting_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
         *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting)
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
         *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeCoasting_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(SpaceChargeCoasting)
+SIXTRL_STATIC SIXTRL_FN void NS(SCCoasting_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const struct NS(SCCoasting)
         *const SIXTRL_RESTRICT e );
 
 #if !defined( _GPUCODE )
 
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(SpaceChargeCoasting_print)(
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(SCCoasting_print)(
     SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(SpaceChargeCoasting)
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting)
         *const SIXTRL_RESTRICT e );
 
 #endif /* !defined( _GPUCODE ) */
 
 /* ************************************************************************** */
-/* SpaceChargeBunched: */
+/* SCQGaussProfile: */
 
-SIXTRL_STATIC SIXTRL_FN int NS(SpaceChargeBunched_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched)
+SIXTRL_STATIC SIXTRL_FN int NS(SCQGaussProfile_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
         *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched)
-        *const SIXTRL_RESTRICT rhs );
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN int NS(SpaceChargeBunched_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched)
+SIXTRL_STATIC SIXTRL_FN int
+NS(SCQGaussProfile_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
         *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched)
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
         *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(SpaceChargeBunched_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(SpaceChargeBunched)
+SIXTRL_STATIC SIXTRL_FN void NS(SCQGaussProfile_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const struct NS(SCQGaussProfile)
         *const SIXTRL_RESTRICT e );
 
 #if !defined( _GPUCODE )
 
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(SpaceChargeBunched_print)(
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(SCQGaussProfile_print)(
     SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(SpaceChargeBunched)
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
         *const SIXTRL_RESTRICT e );
 
 #endif /* !defined( _GPUCODE ) */
 
+/* ************************************************************************** */
+/* LineDensityProfileData: */
+
+SIXTRL_STATIC SIXTRL_FN int NS(LineDensityProfileData_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int
+NS(LineDensityProfileData_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT rhs, SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN void NS(LineDensityProfileData_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const struct NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT e );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(LineDensityProfileData_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT e );
+
+#endif /* !defined( _GPUCODE ) */
+
 
 /* ************************************************************************** */
-/* BeamBeam6D: */
+/* SCInterpolatedProfile: */
 
-SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam6D_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT rhs );
+SIXTRL_STATIC SIXTRL_FN int NS(SCInterpolatedProfile_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam6D_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+SIXTRL_STATIC SIXTRL_FN int
+NS(SCInterpolatedProfile_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT rhs, SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
 
-SIXTRL_STATIC SIXTRL_FN void NS(BeamBeam6D_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam6D) *const SIXTRL_RESTRICT e );
+SIXTRL_STATIC SIXTRL_FN void NS(SCInterpolatedProfile_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT e );
 
 #if !defined( _GPUCODE )
 
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BeamBeam6D_print)(
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(SCInterpolatedProfile_print)(
     SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamBeam6D) *const SIXTRL_RESTRICT e );
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT e );
 
 #endif /* !defined( _GPUCODE ) */
 
+
 /* ************************************************************************* */
 /* Helper functions */
 
@@ -133,14 +197,14 @@ SIXTRL_STATIC SIXTRL_FN int NS(BeamBeam_compare_values_generic)(
     SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_data,
     NS(buffer_size_t) const lhs_size,
     SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT rhs_data,
-    NS(buffer_size_t) const rhs_size );
+    NS(buffer_size_t) const rhs_size ) SIXTRL_NOEXCEPT;
 
 SIXTRL_INLINE int NS(BeamBeam_compare_values_generic_with_treshold)(
     SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_data,
     NS(buffer_size_t) const lhs_size,
     SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT rhs_data,
     NS(buffer_size_t) const rhs_size,
-    SIXTRL_REAL_T const treshold );
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
@@ -157,7 +221,7 @@ SIXTRL_INLINE int NS(BeamBeam_compare_values_generic)(
     SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT lhs_data,
     NS(buffer_size_t) const lhs_size,
     SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT rhs_data,
-    NS(buffer_size_t) const rhs_size )
+    NS(buffer_size_t) const rhs_size ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
     int cmp_value = -1;
@@ -216,7 +280,7 @@ SIXTRL_INLINE int NS(BeamBeam_compare_values_generic_with_treshold)(
     NS(buffer_size_t) const lhs_size,
     SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* SIXTRL_RESTRICT rhs_data,
     NS(buffer_size_t) const rhs_size,
-    SIXTRL_REAL_T const treshold )
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT
 {
     typedef NS(buffer_size_t) buf_size_t;
     typedef SIXTRL_REAL_T real_t;
@@ -271,25 +335,29 @@ SIXTRL_INLINE int NS(BeamBeam_compare_values_generic_with_treshold)(
 
 SIXTRL_INLINE int NS(BeamBeam4D_compare_values)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT rhs )
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
 {
     return NS(BeamBeam_compare_values_generic)(
-       NS(BeamBeam4D_get_const_data)( lhs ), NS(BeamBeam4D_get_data_size)( lhs ),
-       NS(BeamBeam4D_get_const_data)( rhs ), NS(BeamBeam4D_get_data_size)( rhs ) );
+       ( SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+           )NS(BeamBeam4D_data_addr)( lhs ), NS(BeamBeam4D_data_size)( lhs ),
+       ( SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+           )NS(BeamBeam4D_data_addr)( rhs ), NS(BeamBeam4D_data_size)( rhs ) );
 }
 
 SIXTRL_INLINE int NS(BeamBeam4D_compare_values_with_treshold)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT lhs,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT
 {
     return NS(BeamBeam_compare_values_generic_with_treshold)(
-       NS(BeamBeam4D_get_const_data)( lhs ), NS(BeamBeam4D_get_data_size)( lhs ),
-       NS(BeamBeam4D_get_const_data)( rhs ), NS(BeamBeam4D_get_data_size)( rhs ),
+       ( SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+           )NS(BeamBeam4D_data_addr)( lhs ), NS(BeamBeam4D_data_size)( lhs ),
+       ( SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+           )NS(BeamBeam4D_data_addr)( rhs ), NS(BeamBeam4D_data_size)( rhs ),
        treshold );
 }
 
-
 SIXTRL_INLINE void NS(BeamBeam4D_print_out)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam4D) *const SIXTRL_RESTRICT e )
 {
@@ -298,7 +366,7 @@ SIXTRL_INLINE void NS(BeamBeam4D_print_out)(
     typedef NS(beambeam4d_real_const_ptr_t)  bb_data_ptr_t;
     typedef SIXTRL_BE_DATAPTR_DEC NS(BB4D_data)* data_ptr_t;
 
-    bb_data_ptr_t data = NS(BeamBeam4D_get_const_data)( e );
+    bb_data_ptr_t data = NS(BeamBeam4D_const_data)( e );
     data_ptr_t bb4ddata = ( NS(BB4D_data_ptr_t) )data;
 
     SIXTRL_ASSERT( bb4ddata != SIXTRL_NULLPTR );
@@ -326,120 +394,32 @@ SIXTRL_INLINE void NS(BeamBeam4D_print_out)(
     #endif /* !defined( _GPUCODE ) */
 }
 
-/* ************************************************************************* */
-/* SpaceChargeCoasting: */
-
-SIXTRL_INLINE int NS(SpaceChargeCoasting_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT rhs )
-{
-    return NS(BeamBeam_compare_values_generic)(
-       NS(SpaceChargeCoasting_get_const_data)( lhs ),
-       NS(SpaceChargeCoasting_get_data_size)( lhs ),
-       NS(SpaceChargeCoasting_get_const_data)( rhs ),
-       NS(SpaceChargeCoasting_get_data_size)( rhs ) );
-}
-
-SIXTRL_INLINE int NS(SpaceChargeCoasting_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
-{
-    return NS(BeamBeam_compare_values_generic_with_treshold)(
-       NS(SpaceChargeCoasting_get_const_data)( lhs ),
-       NS(SpaceChargeCoasting_get_data_size)( lhs ),
-       NS(SpaceChargeCoasting_get_const_data)( rhs ),
-       NS(SpaceChargeCoasting_get_data_size)( rhs ),
-       treshold );
-}
-
-SIXTRL_INLINE void NS(SpaceChargeCoasting_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeCoasting) *const SIXTRL_RESTRICT e )
-{
-    #if defined( _GPUCODE )
-
-    typedef NS(beambeam4d_real_const_ptr_t)  bb_data_ptr_t;
-    bb_data_ptr_t data = NS(SpaceChargeCoasting_get_const_data)( e );
-
-    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
-
-    printf( "|sc coasting     | \r\n" );
-    ( void )data;
-
-    #else
-
-    NS(SpaceChargeCoasting_print)( stdout, e );
-
-    #endif /* !defined( _GPUCODE ) */
-}
-
-/* ************************************************************************* */
-/* SpaceChargeBunched: */
-
-SIXTRL_INLINE int NS(SpaceChargeBunched_compare_values)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT rhs )
-{
-    return NS(BeamBeam_compare_values_generic)(
-       NS(SpaceChargeBunched_get_const_data)( lhs ),
-       NS(SpaceChargeBunched_get_data_size)( lhs ),
-       NS(SpaceChargeBunched_get_const_data)( rhs ),
-       NS(SpaceChargeBunched_get_data_size)( rhs ) );
-}
-
-SIXTRL_INLINE int NS(SpaceChargeBunched_compare_values_with_treshold)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
-{
-    return NS(BeamBeam_compare_values_generic_with_treshold)(
-       NS(SpaceChargeBunched_get_const_data)( lhs ),
-       NS(SpaceChargeBunched_get_data_size)( lhs ),
-       NS(SpaceChargeBunched_get_const_data)( rhs ),
-       NS(SpaceChargeBunched_get_data_size)( rhs ),
-       treshold );
-}
-
-SIXTRL_INLINE void NS(SpaceChargeBunched_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const NS(SpaceChargeBunched) *const SIXTRL_RESTRICT e )
-{
-    #if defined( _GPUCODE )
-
-    typedef NS(beambeam4d_real_const_ptr_t)  bb_data_ptr_t;
-    bb_data_ptr_t data = NS(SpaceChargeBunched_get_const_data)( e );
-
-    SIXTRL_ASSERT( data != SIXTRL_NULLPTR );
-
-    printf( "|sc bunched      | \r\n" );
-    ( void )data;
-
-    #else
-
-    NS(SpaceChargeBunched_print)( stdout, e );
-
-    #endif /* !defined( _GPUCODE ) */
-}
 
 /* ************************************************************************* */
 /* BeamBeam6D: */
 
 SIXTRL_INLINE int NS(BeamBeam6D_compare_values)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT rhs )
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
 {
     return NS(BeamBeam_compare_values_generic)(
-       NS(BeamBeam6D_get_const_data)( lhs ), NS(BeamBeam6D_get_data_size)( lhs ),
-       NS(BeamBeam6D_get_const_data)( rhs ), NS(BeamBeam6D_get_data_size)( rhs ) );
+       ( SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+           )NS(BeamBeam6D_data_addr)( lhs ), NS(BeamBeam6D_data_size)( lhs ),
+       ( SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+           )NS(BeamBeam6D_data_addr)( rhs ), NS(BeamBeam6D_data_size)( rhs ) );
 }
 
 SIXTRL_INLINE int NS(BeamBeam6D_compare_values_with_treshold)(
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT lhs,
     SIXTRL_BE_ARGPTR_DEC const NS(BeamBeam6D) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT
 {
     return NS(BeamBeam_compare_values_generic_with_treshold)(
-       NS(BeamBeam6D_get_const_data)( lhs ), NS(BeamBeam6D_get_data_size)( lhs ),
-       NS(BeamBeam6D_get_const_data)( rhs ), NS(BeamBeam6D_get_data_size)( rhs ),
+       ( SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+           )NS(BeamBeam6D_data_addr)( lhs ), NS(BeamBeam6D_data_size)( lhs ),
+       ( SIXTRL_BE_DATAPTR_DEC SIXTRL_REAL_T const* )( uintptr_t
+           )NS(BeamBeam6D_data_addr)( rhs ), NS(BeamBeam6D_data_size)( rhs ),
        treshold );
 }
 
@@ -454,7 +434,7 @@ SIXTRL_INLINE void NS(BeamBeam6D_print_out)(
     typedef NS(beambeam6d_real_const_ptr_t)         bb_data_ptr_t;
     typedef SIXTRL_BE_DATAPTR_DEC NS(BB6D_data)*    data_ptr_t;
 
-    data_ptr_t data = NS(BeamBeam6D_get_const_data)( elem );
+    data_ptr_t data = NS(BeamBeam6D_const_data)( elem );
     NS(BB6D_data_ptr_t) bb6ddata = ( NS(BB6D_data_ptr_t) )data;
 
     if( ( bb6ddata != SIXTRL_NULLPTR ) && ( bb6ddata->enabled ) )
@@ -515,6 +495,794 @@ SIXTRL_INLINE void NS(BeamBeam6D_print_out)(
     #endif /* !defined( _GPUCODE ) */
 }
 
-#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BEAMFIELDS_C99_H__ */
+/* ************************************************************************* */
+/* SCCoasting: */
+
+SIXTRL_INLINE int NS(SCCoasting_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = NS(Type_value_comp_result)(
+                lhs->number_of_particles, rhs->number_of_particles );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->circumference, rhs->circumference );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->sigma_x, rhs->sigma_x );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->sigma_y, rhs->sigma_y );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->length, rhs->length );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)( lhs->x_co, rhs->x_co );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(lhs->y_co, rhs->y_co );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->min_sigma_diff, rhs->min_sigma_diff );
+            }
+
+            if( ( cmp_result == 0 ) && ( lhs->enabled != rhs->enabled ) )
+            {
+                cmp_result = ( lhs->enabled > rhs->enabled ) ? +1 : -1;
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(SCCoasting_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            SIXTRL_REAL_T const REL_TOL = ( SIXTRL_REAL_T )0;
+            cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                lhs->number_of_particles, rhs->number_of_particles, REL_TOL, ABS_TOL );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->circumference, rhs->circumference, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->sigma_x, rhs->sigma_x, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->sigma_y, rhs->sigma_y, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->length, rhs->length, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->x_co, rhs->x_co, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->y_co, rhs->y_co, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->min_sigma_diff, rhs->min_sigma_diff, REL_TOL, ABS_TOL );
+            }
+
+            if( ( cmp_result == 0 ) && ( lhs->enabled != rhs->enabled ) )
+            {
+                cmp_result = ( lhs->enabled > rhs->enabled ) ? +1 : -1;
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(SCCoasting_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCCoasting) *const SIXTRL_RESTRICT e )
+{
+    #if defined( _GPUCODE )
+
+    if( != SIXTRL_NULLPTR )
+    {
+        printf( "|sc coasting     | number_of_particles = %+20.12f\r\n"
+                "                 | circumference       = %+20.12f\r\n"
+                "                 | sigma_x             = %+20.12f\r\n"
+                "                 | sigma_y             = %+20.12f\r\n"
+                "                 | length              = %+20.12f\r\n"
+                "                 | x_co                = %+20.12f\r\n"
+                "                 | y_co                = %+20.12f\r\n"
+                "                 | min_sigma_diff      = %+20.12f\r\n"
+                "                 | enabled             = %20lu\r\n",
+            e->number_of_particles, e->circumference, e->sigma_x, e->sigma_y,
+            e->length, e->x_co, e->y_co, e->min_sigma_diff,
+            ( unsigned long )e->enabled );
+    }
+
+    #else
+
+    NS(SCCoasting_print)( stdout, e );
+
+    #endif /* !defined( _GPUCODE ) */
+}
+
+/* ************************************************************************* */
+/* SCQGaussProfile: */
+
+SIXTRL_INLINE int NS(SCQGaussProfile_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = NS(Type_value_comp_result)(
+                lhs->number_of_particles, rhs->number_of_particles );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->bunchlength_rms, rhs->bunchlength_rms );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->sigma_x, rhs->sigma_x );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->sigma_y, rhs->sigma_y );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->length, rhs->length );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)( lhs->x_co, rhs->x_co );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(lhs->y_co, rhs->y_co );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->q_param, rhs->q_param );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)( lhs->cq, rhs->cq );
+            }
+
+            if( ( cmp_result == 0 ) && ( lhs->enabled != rhs->enabled ) )
+            {
+                cmp_result = ( lhs->enabled > rhs->enabled ) ? +1 : -1;
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(SCQGaussProfile_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile) *const
+        SIXTRL_RESTRICT rhs, SIXTRL_REAL_T const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            SIXTRL_REAL_T const REL_TOL = ( SIXTRL_REAL_T )0;
+            cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                lhs->number_of_particles, rhs->number_of_particles, REL_TOL, ABS_TOL );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->bunchlength_rms, rhs->bunchlength_rms,
+                        REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->sigma_x, rhs->sigma_x, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->sigma_y, rhs->sigma_y, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->length, rhs->length, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->x_co, rhs->x_co, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->y_co, rhs->y_co, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->min_sigma_diff, rhs->min_sigma_diff, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->q_param, rhs->q_param, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->cq, rhs->cq, REL_TOL, ABS_TOL );
+            }
+
+            if( ( cmp_result == 0 ) && ( lhs->enabled != rhs->enabled ) )
+            {
+                cmp_result = ( lhs->enabled > rhs->enabled ) ? +1 : -1;
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(SCQGaussProfile_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCQGaussProfile)
+        *const SIXTRL_RESTRICT e )
+{
+    #if defined( _GPUCODE )
+
+    if( ( fp != SIXTRL_NULLPTR ) && ( e != SIXTRL_NULLPTR ) )
+    {
+        printf( "|sc q-gaussian   | number_of_particles = %+20.12f\r\n"
+                "                 | circumference       = %+20.12f\r\n"
+                "                 | sigma_x             = %+20.12f\r\n"
+                "                 | sigma_y             = %+20.12f\r\n"
+                "                 | length              = %+20.12f\r\n"
+                "                 | x_co                = %+20.12f\r\n"
+                "                 | y_co                = %+20.12f\r\n"
+                "                 | min_sigma_diff      = %+20.12f\r\n"
+                "                 | q_param             = %+20.12f\r\n"
+                "                 | b_param             = %+20.12f\r\n"
+                "                 | enabled             = %20lu\r\n",
+            e->number_of_particles, e->bunchlength_rms, e->sigma_x, e->sigma_y,
+            e->length, e->x_co, e->y_co, e->min_sigma_diff, e->q_param,
+            e->b_param, ( unsigned long )e->enabled );
+    }
+
+    #else
+
+    NS(SCQGaussProfile_print)( stdout, e );
+
+    #endif /* !defined( _GPUCODE ) */
+}
+
+/* ************************************************************************* */
+/* NS(LineDensityProfileData): */
+
+SIXTRL_INLINE int NS(LineDensityProfileData_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = ( lhs->method == rhs->method )
+                ? 0 : ( ( lhs->method > rhs->method ) ? +1 : -1 );
 
-/* end: tests/sixtracklib/testlib/common/be_beamfields/be_beamfields.h */
+            if( ( cmp_result == 0 ) && ( lhs->num_values != rhs->num_values ) )
+            {
+                cmp_result = ( lhs->num_values > rhs->num_values ) ? +1 : -1;
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_for_range)(
+                    NS(LineDensityProfileData_const_values_begin)( lhs ),
+                    NS(LineDensityProfileData_const_values_end)( lhs ),
+                    NS(LineDensityProfileData_const_values_begin)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_for_range)(
+                    NS(LineDensityProfileData_const_derivatives_begin)( lhs ),
+                    NS(LineDensityProfileData_const_derivatives_end)( lhs ),
+                    NS(LineDensityProfileData_const_derivatives_begin)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)( lhs->z0, rhs->z0 );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)( lhs->dz, rhs->dz );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(LineDensityProfileData_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT rhs, SIXTRL_REAL_T const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            SIXTRL_REAL_T const REL_TOL = ( SIXTRL_REAL_T )0;
+            cmp_result = ( lhs->method == rhs->method )
+                ? 0 : ( ( lhs->method > rhs->method ) ? +1 : -1 );
+
+            if( ( cmp_result == 0 ) && ( lhs->num_values != rhs->num_values ) )
+            {
+                cmp_result = ( lhs->num_values > rhs->num_values ) ? +1 : -1;
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result =
+                NS(Type_value_comp_result_with_tolerances_for_range)(
+                    NS(LineDensityProfileData_const_values_begin)( lhs ),
+                    NS(LineDensityProfileData_const_values_end)( lhs ),
+                    NS(LineDensityProfileData_const_values_begin)( rhs ),
+                    REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result =
+                NS(Type_value_comp_result_with_tolerances_for_range)(
+                    NS(LineDensityProfileData_const_derivatives_begin)( lhs ),
+                    NS(LineDensityProfileData_const_derivatives_end)( lhs ),
+                    NS(LineDensityProfileData_const_derivatives_begin)( rhs ),
+                    REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->z0, rhs->z0, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->dz, rhs->dz, REL_TOL, ABS_TOL );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(LineDensityProfileData_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LineDensityProfileData) *const
+        SIXTRL_RESTRICT e )
+{
+    NS(math_abscissa_idx_t) const nvalues =
+        NS(LineDensityProfileData_num_values)( e );
+
+    printf( "|lprof density data  | method            = " );
+
+    switch( NS(LineDensityProfileData_method)( e ) )
+    {
+        case NS(MATH_INTERPOL_LINEAR):
+        {
+            printf( "linear" );
+            break;
+        }
+
+        case NS(MATH_INTERPOL_CUBIC):
+        {
+            printf( "cubic" );
+            break;
+        }
+
+        default:
+        {
+            printf( "n/a (unknown)" );
+        }
+    };
+
+    printf( "\r\n"
+            "                     | num_values        = %21ld\r\n"
+            "                     | values_addr       = %21lx\r\n"
+            "                     | derivatives_addr  = %21lx\r\n"
+            "                     | z0                = %+20.12f\r\n"
+            "                     | dz                = %+20.12f\r\n"
+            "                     | capacity          = %21ld\r\n",
+            ( long int )NS(LineDensityProfileData_num_values)( e ),
+            ( uintptr_t )NS(LineDensityProfileData_values_addr)( e ),
+            ( uintptr_t )NS(LineDensityProfileData_derivatives_addr)( e ),
+            NS(LineDensityProfileData_z0)( e ),
+            NS(LineDensityProfileData_dz)( e ),
+            ( long int )NS(LineDensityProfileData_capacity)( e ) );
+
+    if( nvalues > ( NS(math_abscissa_idx_t ) )0 )
+    {
+        printf( "                     |" " ii"
+                "                     z"
+                "                 value"
+                "      derivative value\r\n" );
+    }
+
+    if( nvalues <= ( NS(math_abscissa_idx_t) )10 )
+    {
+        NS(math_abscissa_idx_t) ii = ( NS(math_abscissa_idx_t) )0;
+        SIXTRL_REAL_T z = NS(LineDensityProfileData_z0)( e );
+
+        for( ; ii < nvalues ; ++ii )
+        {
+            printf( "                     |%3ld"
+                    "%+20.12f""%+20.12f""%+20.12f\r\n",
+                    ( long int )ii, z,
+                    NS(LineDensityProfileData_value_at_idx)( e, ii ),
+                    NS(LineDensityProfileData_derivatives_at_idx)( e, ii ) );
+
+            z += NS(LineDensityProfileData_dz)( e );
+        }
+    }
+    else
+    {
+        NS(math_abscissa_idx_t) ii = ( NS(math_abscissa_idx_t) )0;
+        SIXTRL_REAL_T z = NS(LineDensityProfileData_z0)( e );
+
+        for( ; ii < 5 ; ++ii )
+        {
+            printf( "                     |%3ld"
+                    "%+20.12f""%+20.12f""%+20.12f\r\n", ( long int )ii, z,
+                    NS(LineDensityProfileData_value_at_idx)( e, ii ),
+                    NS(LineDensityProfileData_derivatives_at_idx)( e, ii ) );
+
+            z += NS(LineDensityProfileData_dz)( e );
+        }
+
+        printf( "                         | .. ..................... "
+                "..................... .....................\r\n" );
+
+        ii = nvalues - 6;
+        z = NS(LineDensityProfileData_z0)( e ) +
+            NS(LineDensityProfileData_dz)( e ) * ii;
+
+        for( ; ii < 5 ; ++ii )
+        {
+            printf( "                     |%3ld"
+                    "%+20.12f""%+20.12f""%+20.12f\r\n", ( long int )ii, z,
+                    NS(LineDensityProfileData_value_at_idx)( e, ii ),
+                    NS(LineDensityProfileData_derivatives_at_idx)( e, ii ) );
+
+            z += NS(LineDensityProfileData_dz)( e );
+        }
+    }
+}
+
+/* ************************************************************************** */
+/* SCInterpolatedProfile: */
+
+SIXTRL_INLINE int NS(SCInterpolatedProfile_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = NS(Type_value_comp_result)(
+                lhs->number_of_particles, rhs->number_of_particles );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->sigma_x, rhs->sigma_x );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->sigma_y, rhs->sigma_y );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->length, rhs->length );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)( lhs->x_co, rhs->x_co );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)( lhs->y_co, rhs->y_co );
+            }
+
+            if( ( cmp_result == 0 ) &&
+                ( lhs->interpol_data_addr != rhs->interpol_data_addr ) )
+            {
+                cmp_result = NS(LineDensityProfileData_compare_values)(
+                    NS(SCInterpolatedProfile_const_line_density_profile_data)( lhs ),
+                    NS(SCInterpolatedProfile_const_line_density_profile_data)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->line_density_prof_fallback,
+                    rhs->line_density_prof_fallback );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    lhs->min_sigma_diff, rhs->min_sigma_diff );
+            }
+
+            if( ( cmp_result == 0 ) && ( lhs->enabled != rhs->enabled ) )
+            {
+                cmp_result = ( lhs->enabled > rhs->enabled ) ? +1 : -1;
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(SCInterpolatedProfile_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT rhs, SIXTRL_REAL_T const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            SIXTRL_REAL_T const REL_TOL = ( SIXTRL_REAL_T )0;
+            cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                lhs->number_of_particles, rhs->number_of_particles, REL_TOL, ABS_TOL );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->sigma_x, rhs->sigma_x, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->sigma_y, rhs->sigma_y, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->length, rhs->length, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->x_co, rhs->x_co, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->y_co, rhs->y_co, REL_TOL, ABS_TOL );
+            }
+
+            if( ( cmp_result == 0 ) &&
+                ( lhs->interpol_data_addr != rhs->interpol_data_addr ) )
+            {
+                cmp_result = NS(LineDensityProfileData_compare_values_with_treshold)(
+                    NS(SCInterpolatedProfile_const_line_density_profile_data)( lhs ),
+                    NS(SCInterpolatedProfile_const_line_density_profile_data)(
+                        rhs ), ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->line_density_prof_fallback,
+                    rhs->line_density_prof_fallback, REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->min_sigma_diff, rhs->min_sigma_diff, REL_TOL, ABS_TOL );
+            }
+
+            if( ( cmp_result == 0 ) && ( lhs->enabled != rhs->enabled ) )
+            {
+                cmp_result = ( lhs->enabled > rhs->enabled ) ? +1 : -1;
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(SCInterpolatedProfile_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const struct NS(SCInterpolatedProfile) *const
+        SIXTRL_RESTRICT e )
+{
+    SIXTRL_ASSERT( e != SIXTRL_NULLPTR );
+    printf( "|sc interpolated | number_of_particles   = %+20.12f\r\n"
+            "                 | sigma_x               = %+20.12f\r\n"
+            "                 | sigma_y               = %+20.12f\r\n"
+            "                 | length                = %+20.12f\r\n"
+            "                 | x_co                  = %+20.12f\r\n"
+            "                 | y_co                  = %+20.12f\r\n"
+            "                 | interpol_data_addr    = %21lx\r\n"
+            "                 | line_density_fallback = %+20.12f\r\n"
+            "                 | min_sigma_diff        = %+20.12f\r\n"
+            "                 | enabled               = %20lu\r\n",
+            NS(SCInterpolatedProfile_number_of_particles)( e ),
+            NS(SCInterpolatedProfile_sigma_x)( e ),
+            NS(SCInterpolatedProfile_sigma_y)( e ),
+            NS(SCInterpolatedProfile_length)( e ),
+            NS(SCInterpolatedProfile_x_co)( e ),
+            NS(SCInterpolatedProfile_y_co)( e ),
+            ( uintptr_t )NS(SCInterpolatedProfile_interpol_data_addr)(
+                e ),
+            NS(SCInterpolatedProfile_line_density_prof_fallback)( e ),
+            NS(SCInterpolatedProfile_min_sigma_diff)( e ),
+            ( unsigned long )e->enabled );
+}
+
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BEAMFIELDS_C99_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_cavity.c b/tests/sixtracklib/testlib/common/beam_elements/be_cavity.c
new file mode 100644
index 00000000..f326d86d
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_cavity.c
@@ -0,0 +1,31 @@
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_cavity/be_cavity.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+    #include "sixtracklib/testlib/common/beam_elements/be_cavity.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+void NS(Cavity_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( cavity != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp,
+            "|cavity           | voltage   = %+16.12f V   \r\n"
+            "                  | frequency = %+20.12f Hz; \r\n"
+            "                  | lag       = %+15.12f deg;\r\n",
+            NS(Cavity_voltage)( cavity ), NS(Cavity_frequency)( cavity ),
+            NS(Cavity_lag)( cavity ) );
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_cavity.h b/tests/sixtracklib/testlib/common/beam_elements/be_cavity.h
new file mode 100644
index 00000000..d577a098
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_cavity.h
@@ -0,0 +1,149 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_CAVITY_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_CAVITY_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_cavity/be_cavity.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_STATIC SIXTRL_FN void NS(Cavity_print_out)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Cavity) *const SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Cavity_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(Cavity) *const SIXTRL_RESTRICT e );
+
+#endif /* !defined( _GPUCODE ) */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN int NS(Cavity_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(Cavity_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* C++, Host */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_INLINE void NS(Cavity_print_out)( SIXTRL_ARGPTR_DEC const NS(Cavity)
+    *const SIXTRL_RESTRICT cavity ) SIXTRL_NOEXCEPT
+{
+    printf( "|cavity           | voltage   = %+16.12f V;\r\n"
+            "                  | frequency = %+20.12f Hz;\r\n"
+            "                  | lag       = %+15.12f deg;\r\n",
+            NS(Cavity_voltage)( cavity ),
+            NS(Cavity_frequency)( cavity ),
+            NS(Cavity_lag)( cavity ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE int NS(Cavity_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT
+{
+    int cmp_value = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_value = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_value = NS(Type_value_comp_result)( lhs->voltage, rhs->voltage );
+
+            if( cmp_value == 0 )
+            {
+                cmp_value = NS(Type_value_comp_result)(
+                    lhs->frequency, rhs->frequency );
+            }
+
+            if( cmp_value == 0 )
+            {
+                cmp_value = NS(Type_value_comp_result)( lhs->lag, rhs->lag );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_value = +1;
+    }
+
+    return cmp_value;
+}
+
+SIXTRL_INLINE int NS(Cavity_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT
+{
+    int cmp_value = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) &&
+        ( treshold >= ( SIXTRL_REAL_T )0 ) )
+    {
+        cmp_value = 0;
+
+        if( rhs != lhs )
+        {
+            cmp_value = NS(Type_value_comp_result_with_tolerances)(
+                lhs->voltage, rhs->voltage, ( SIXTRL_REAL_T )0, treshold );
+
+            if( cmp_value == 0 )
+            {
+                cmp_value = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->frequency, rhs->frequency, ( SIXTRL_REAL_T )0,
+                        treshold );
+            }
+
+            if( cmp_value == 0 )
+            {
+                cmp_value = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->lag, rhs->lag, ( SIXTRL_REAL_T )0, treshold );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_value = +1;
+    }
+
+    return cmp_value;
+}
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* C++, Host */
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_CAVITY_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_dipedge.c b/tests/sixtracklib/testlib/common/beam_elements/be_dipedge.c
index 9266ae0b..f0601090 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/be_dipedge.c
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_dipedge.c
@@ -1,7 +1,7 @@
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include "sixtracklib/testlib/common/beam_elements/be_dipedge.h"
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
-    
+
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <stddef.h>
     #include <stdlib.h>
@@ -29,10 +29,10 @@ void NS(DipoleEdge_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
         fprintf( fp,
                 "|dipole_edge      | r21      = %+16.12f m^-1;\r\n"
                 "                  | r43      = %+16.12f m^-1;\r\n",
-                NS(DipoleEdge_get_r21)( dipedge ),
-                NS(DipoleEdge_get_r43)( dipedge ) );
+                NS(DipoleEdge_r21)( dipedge ),
+                NS(DipoleEdge_r43)( dipedge ) );
     }
-    
+
     return;
 }
 
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_dipedge.h b/tests/sixtracklib/testlib/common/beam_elements/be_dipedge.h
index 3a04fbe7..bb66b7d7 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/be_dipedge.h
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_dipedge.h
@@ -4,11 +4,11 @@
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <stddef.h>
     #include <stdlib.h>
-    
+
     #if !defined( _GPUCODE )
     #include <stdio.h>
     #endif /* !defined( _GPUCODE ) */
-    
+
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
 
 #if !defined( SIXTRL_NO_INCLUDES )
@@ -72,21 +72,21 @@ SIXTRL_INLINE int NS(DipoleEdge_compare_values_with_treshold)(
     SIXTRL_REAL_T const treshold )
 {
     int cmp_result = -1;
-    
+
     if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
     {
         cmp_result = 0;
-        
+
         if( lhs != rhs )
         {
             cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                NS(DipoleEdge_get_r21)( lhs ), NS(DipoleEdge_get_r21)( rhs ), 
+                NS(DipoleEdge_r21)( lhs ), NS(DipoleEdge_r21)( rhs ),
                     treshold );
-            
+
             if( cmp_result == 0 )
             {
                 cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                NS(DipoleEdge_get_r43)( lhs ), NS(DipoleEdge_get_r43)( rhs ), 
+                NS(DipoleEdge_r43)( lhs ), NS(DipoleEdge_r43)( rhs ),
                     treshold );
             }
         }
@@ -95,13 +95,13 @@ SIXTRL_INLINE int NS(DipoleEdge_compare_values_with_treshold)(
     {
         cmp_result = +1;
     }
-    
+
     return cmp_result;
 }
 
 
 #if !defined( _GPUCODE )
-    
+
 SIXTRL_INLINE void NS(DipoleEdge_print_out)(
     SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge )
 {
@@ -110,25 +110,25 @@ SIXTRL_INLINE void NS(DipoleEdge_print_out)(
 
 #else /* defined( _GPUCODE ) */
 
-SIXTRL_INLINE void NS(DipoleEdge_print_out)( 
+SIXTRL_INLINE void NS(DipoleEdge_print_out)(
     SIXTRL_BE_ARGPTR_DEC const NS(DipoleEdge) *const SIXTRL_RESTRICT dipedge )
 {
     if( dipedge != SIXTRL_NULLPTR )
     {
         printf( "|dipole_edge      | r21      = %+16.12f m^-1;\r\n"
                 "                  | r43      = %+16.12f m^-1;\r\n",
-                NS(DipoleEdge_get_r21)( dipedge ),
-                NS(DipoleEdge_get_r43)( dipedge ) );
+                NS(DipoleEdge_r21)( dipedge ),
+                NS(DipoleEdge_r43)( dipedge ) );
     }
-    
+
     return;
 }
 
 #endif /* !defined( _GPUCODE ) */
-    
+
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
-#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */    
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
 #endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_DIPEDGE_C99_H__ */
 
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_drift.c b/tests/sixtracklib/testlib/common/beam_elements/be_drift.c
new file mode 100644
index 00000000..9c1ec2b5
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_drift.c
@@ -0,0 +1,21 @@
+#include "sixtracklib/testlib/common/beam_elements/be_drift.h"
+
+void NS(Drift_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT elem )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( elem != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp, "drift             | length   = %+20.18f m;\r\n",
+                 NS(Drift_length)( elem ) );
+    }
+}
+
+void NS(DriftExact_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT elem )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( elem != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp, "exact drift       | length   = %+20.18f m;\r\n",
+                 NS(DriftExact_length)( elem ) );
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_drift.h b/tests/sixtracklib/testlib/common/beam_elements/be_drift.h
new file mode 100644
index 00000000..8479f45b
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_drift.h
@@ -0,0 +1,190 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_DRIFT_C99_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_DRIFT_C99_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_drift/be_drift.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_STATIC SIXTRL_FN int NS(Drift_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(Drift_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT rhs,
+    NS(drift_real_t) const treshold ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN void NS(Drift_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT elem );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Drift_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT elem );
+
+#endif /* !defined( _GPUCODE ) */
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_STATIC SIXTRL_FN int NS(DriftExact_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(DriftExact_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT rhs,
+    NS(drift_real_t) const treshold ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN void NS(DriftExact_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT elem );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(DriftExact_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT elem );
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!  Implementation of inline functions for NS(Drift)  !!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE int NS(Drift_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT
+        rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = ( lhs != rhs )
+            ? NS(Type_value_comp_result)( lhs->length, rhs->length ) : 0;
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(Drift_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT rhs,
+    NS(drift_real_t) const treshold ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = ( lhs != rhs )
+            ? NS(Type_value_comp_result_with_tolerances)(
+                lhs->length, rhs->length, ( NS(drift_real_t) )0, treshold )
+            : 0;
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(Drift_print_out)( SIXTRL_BE_ARGPTR_DEC const
+    NS(Drift) *const SIXTRL_RESTRICT elem )
+{
+    if( elem != SIXTRL_NULLPTR )
+    {
+        printf( "drift             | length   = %+20.18f m;\r\n",
+                NS(Drift_length)( elem ) );
+    }
+}
+
+/* ------------------------------------------------------------------------- */
+
+SIXTRL_INLINE int NS(DriftExact_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT
+        rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = ( lhs != rhs )
+            ? NS(Type_value_comp_result)( lhs->length, rhs->length ) : 0;
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(DriftExact_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT rhs,
+    NS(drift_real_t) const treshold ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = ( lhs != rhs )
+            ? NS(Type_value_comp_result_with_tolerances)(
+                lhs->length, rhs->length, ( NS(drift_real_t) )0, treshold )
+            : 0;
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(DriftExact_print_out)( SIXTRL_BE_ARGPTR_DEC const
+    NS(DriftExact) *const SIXTRL_RESTRICT elem )
+{
+    if( elem != SIXTRL_NULLPTR )
+    {
+        printf( "exact drift       | length   = %+20.18f m;\r\n",
+                NS(DriftExact_length)( elem ) );
+    }
+}
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_DRIFT_C99_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.c b/tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.c
index a75f7503..cdb56e27 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.c
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.c
@@ -1,7 +1,7 @@
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include "sixtracklib/testlib/common/beam_elements/be_limit_ellipse.h"
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
-    
+
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <stddef.h>
     #include <stdlib.h>
@@ -26,13 +26,13 @@ void NS(LimitEllipse_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
 {
     if( ( fp != SIXTRL_NULLPTR ) && ( limit != SIXTRL_NULLPTR ) )
     {
-        fprintf( fp, 
+        fprintf( fp,
                 "|limit_ellipse    | half-axis x = %+16.12f m;\r\n"
-                "                  | half-axis y = %+16.12f m;\r\n",                
-                NS(LimitEllipse_get_x_half_axis)( limit ),
-                NS(LimitEllipse_get_y_half_axis)( limit ) );
+                "                  | half-axis y = %+16.12f m;\r\n",
+                NS(LimitEllipse_x_half_axis)( limit ),
+                NS(LimitEllipse_y_half_axis)( limit ) );
     }
-    
+
     return;
 }
 
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.h b/tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.h
index b654de64..6859e772 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.h
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.h
@@ -4,18 +4,18 @@
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <stddef.h>
     #include <stdlib.h>
-    
+
     #if !defined( _GPUCODE )
     #include <stdio.h>
     #endif /* !defined( _GPUCODE ) */
-    
+
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/be_limit/definitions.h"
     #include "sixtracklib/common/be_limit/be_limit_ellipse.h"
-    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -24,22 +24,23 @@ extern "C" {
 
 SIXTRL_STATIC SIXTRL_FN int NS(LimitEllipse_compare_values)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT rhs );
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN int NS(LimitEllipse_compare_values_with_treshold)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT lhs,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN void NS(LimitEllipse_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const 
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
         SIXTRL_RESTRICT limit_ellipse );
 
 #if !defined( _GPUCODE )
 
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(LimitEllipse_print)(
     SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const 
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
         SIXTRL_RESTRICT limit_ellipse );
 
 #endif /* !defined( _GPUCODE ) */
@@ -62,42 +63,73 @@ extern "C" {
 
 SIXTRL_INLINE int NS(LimitEllipse_compare_values)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT rhs )
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
 {
-    return NS(LimitEllipse_compare_values_with_treshold)( 
-        lhs, rhs, ( SIXTRL_REAL_T )0 );
+    int cmp_result = -1;
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = NS(Type_value_comp_result)(
+                NS(LimitEllipse_x_half_axis_squ)( lhs ),
+                NS(LimitEllipse_x_half_axis_squ)( rhs ) );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitEllipse_y_half_axis_squ)( lhs ),
+                    NS(LimitEllipse_y_half_axis_squ)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitEllipse_half_axes_product_squ)( lhs ),
+                    NS(LimitEllipse_half_axes_product_squ)( rhs ) );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
 }
 
 SIXTRL_INLINE int NS(LimitEllipse_compare_values_with_treshold)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT lhs,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
+    NS(particle_real_t) const ABS_TOL ) SIXTRL_NOEXCEPT
 {
     int cmp_result = -1;
-    
     if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
     {
         cmp_result = 0;
-        
         if( lhs != rhs )
         {
-            cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                NS(LimitEllipse_get_x_half_axis_squ)( lhs ), 
-                NS(LimitEllipse_get_x_half_axis_squ)( rhs ), treshold );
-            
+            NS(particle_real_t) const REL_TOL = ( NS(particle_real_t) )0;
+
+            cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                NS(LimitEllipse_x_half_axis_squ)( lhs ),
+                NS(LimitEllipse_x_half_axis_squ)( rhs ), REL_TOL, ABS_TOL );
+
             if( cmp_result == 0 )
             {
-                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                    NS(LimitEllipse_get_y_half_axis_squ)( lhs ), 
-                    NS(LimitEllipse_get_y_half_axis_squ)( rhs ), treshold );
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitEllipse_y_half_axis_squ)( lhs ),
+                    NS(LimitEllipse_y_half_axis_squ)( rhs ), REL_TOL, ABS_TOL );
             }
-            
+
             if( cmp_result == 0 )
             {
-                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                    NS(LimitEllipse_get_half_axes_product_squ)( lhs ), 
-                    NS(LimitEllipse_get_half_axes_product_squ)( rhs ), 
-                    treshold );
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitEllipse_half_axes_product_squ)( lhs ),
+                    NS(LimitEllipse_half_axes_product_squ)( rhs ),
+                    REL_TOL, ABS_TOL );
             }
         }
     }
@@ -105,12 +137,12 @@ SIXTRL_INLINE int NS(LimitEllipse_compare_values_with_treshold)(
     {
         cmp_result = +1;
     }
-    
+
     return cmp_result;
 }
 
 #if !defined( _GPUCODE )
-    
+
 SIXTRL_INLINE void NS(LimitEllipse_print_out)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitEllipse) *const SIXTRL_RESTRICT limit )
 {
@@ -126,10 +158,10 @@ SIXTRL_INLINE void NS(LimitEllipse_print_out)(
     {
         printf( "|limit_ellipse    | half-axis x = %+16.12f m;\r\n"
                 "                  | half-axis y = %+16.12f m;\r\n",
-                NS(LimitEllipse_get_x_half_axis)( limit ),
-                NS(LimitEllipse_get_y_half_axis)( limit ) );
+                NS(LimitEllipse_x_half_axis)( limit ),
+                NS(LimitEllipse_y_half_axis)( limit ) );
     }
-    
+
     return;
 }
 
@@ -138,7 +170,7 @@ SIXTRL_INLINE void NS(LimitEllipse_print_out)(
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-    
+
 #endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_LIMIT_ELLIPSE_C99_H__ */
 
 /* end: tests/sixtracklib/testlib/common/beam_elements/be_limit_ellipse.h */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.c b/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.c
index d38f57f0..150adc17 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.c
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.c
@@ -1,7 +1,7 @@
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include "sixtracklib/testlib/common/beam_elements/be_limit_rect.h"
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
-    
+
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <stddef.h>
     #include <stdlib.h>
@@ -22,21 +22,18 @@
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
 
 void NS(LimitRect_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit_rect )
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit )
 {
-    if( ( fp != SIXTRL_NULLPTR ) && ( limit_rect != SIXTRL_NULLPTR ) )
+    if( ( fp != SIXTRL_NULLPTR ) && ( limit != SIXTRL_NULLPTR ) )
     {
-        fprintf( fp,
-                 "|limit_rect       | min_x    = %+16.12f m;\r\n"
-                 "                  | max_x    = %+16.12f m;\r\n"
-                 "                  | min_y    = %+16.12f m;\r\n"
-                 "                  | max_y    = %+16.12f m;\r\n",
-                 NS(LimitRect_get_min_x)( limit_rect ),
-                 NS(LimitRect_get_max_x)( limit_rect ),
-                 NS(LimitRect_get_min_y)( limit_rect ),
-                 NS(LimitRect_get_max_y)( limit_rect ) );
+        fprintf( fp, "|limit_rect       | min_x    = %+20.12f m;\r\n"
+                "                  | max_x    = %+20.12f m;\r\n"
+                "                  | min_y    = %+20.12f m;\r\n"
+                "                  | max_y    = %+20.12f m;\r\n",
+                NS(LimitRect_min_x)( limit ), NS(LimitRect_max_x)( limit ),
+                NS(LimitRect_min_y)( limit ), NS(LimitRect_max_y)( limit ) );
     }
-    
+
     return;
 }
 
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.h b/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.h
index b4c1ba93..bddeff10 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.h
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.h
@@ -4,18 +4,18 @@
 #if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
     #include <stddef.h>
     #include <stdlib.h>
-    
+
     #if !defined( _GPUCODE )
     #include <stdio.h>
     #endif /* !defined( _GPUCODE ) */
-    
+
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
 
 #if !defined( SIXTRL_NO_INCLUDES )
     #include "sixtracklib/common/definitions.h"
     #include "sixtracklib/common/be_limit/definitions.h"
     #include "sixtracklib/common/be_limit/be_limit_rect.h"
-    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -24,12 +24,13 @@ extern "C" {
 
 SIXTRL_STATIC SIXTRL_FN int NS(LimitRect_compare_values)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT rhs );
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN int NS(LimitRect_compare_values_with_treshold)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT lhs,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold );
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
 
 SIXTRL_STATIC SIXTRL_FN void NS(LimitRect_print_out)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit );
@@ -60,48 +61,84 @@ extern "C" {
 
 SIXTRL_INLINE int NS(LimitRect_compare_values)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT lhs,
-    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT rhs )
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
 {
-    return NS(LimitRect_compare_values_with_treshold)( 
-        lhs, rhs, ( SIXTRL_REAL_T )0 );
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = NS(Type_value_comp_result)(
+                NS(LimitRect_min_x)( lhs ), NS(LimitRect_min_x)( rhs ) );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitRect_max_x)( lhs ), NS(LimitRect_max_x)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitRect_min_y)( lhs ), NS(LimitRect_min_y)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitRect_max_y)( lhs ), NS(LimitRect_max_y)( rhs ) );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
 }
 
 SIXTRL_INLINE int NS(LimitRect_compare_values_with_treshold)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT lhs,
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT rhs,
-    SIXTRL_REAL_T const treshold )
+    NS(particle_real_t) const ABS_TOL ) SIXTRL_NOEXCEPT
 {
     int cmp_result = -1;
-    
+
     if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
     {
         cmp_result = 0;
-        
+
         if( lhs != rhs )
         {
-            cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                NS(LimitRect_get_min_x)( lhs ), NS(LimitRect_get_min_x)( rhs ), 
-                    treshold );
-            
+            NS(particle_real_t) const REL_TOL = ( NS(particle_real_t) )0;
+            cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                NS(LimitRect_min_x)( lhs ), NS(LimitRect_min_x)( rhs ),
+                        REL_TOL, ABS_TOL );
+
             if( cmp_result == 0 )
             {
-                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                    NS(LimitRect_get_max_x)( lhs ), 
-                    NS(LimitRect_get_max_x)( rhs ), treshold );
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitRect_max_x)( lhs ), NS(LimitRect_max_x)( rhs ),
+                        REL_TOL, ABS_TOL );
             }
-            
+
             if( cmp_result == 0 )
             {
-                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                    NS(LimitRect_get_min_y)( lhs ), 
-                    NS(LimitRect_get_min_y)( rhs ), treshold );
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitRect_min_y)( lhs ), NS(LimitRect_min_y)( rhs ),
+                        REL_TOL, ABS_TOL );
             }
-            
+
             if( cmp_result == 0 )
             {
-                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
-                    NS(LimitRect_get_max_y)( lhs ), 
-                    NS(LimitRect_get_max_y)( rhs ), treshold );
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitRect_max_y)( lhs ), NS(LimitRect_max_y)( rhs ),
+                        REL_TOL, ABS_TOL );
             }
         }
     }
@@ -109,12 +146,12 @@ SIXTRL_INLINE int NS(LimitRect_compare_values_with_treshold)(
     {
         cmp_result = +1;
     }
-    
+
     return cmp_result;
 }
 
 #if !defined( _GPUCODE )
-    
+
 SIXTRL_INLINE void NS(LimitRect_print_out)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit )
 {
@@ -123,22 +160,18 @@ SIXTRL_INLINE void NS(LimitRect_print_out)(
 
 #else /* !defined( _GPUCODE ) */
 
-SIXTRL_INLINE void NS(LimitRect_print_out)( 
+SIXTRL_INLINE void NS(LimitRect_print_out)(
     SIXTRL_BE_ARGPTR_DEC const NS(LimitRect) *const SIXTRL_RESTRICT limit )
 {
     if( limit != SIXTRL_NULLPTR )
     {
-        printf( "|limit_rect       | min_x    = %+16.12f m;\r\n"
-                "                  | max_x    = %+16.12f m;\r\n"
-                "                  | min_y    = %+16.12f m;\r\n"
-                "                  | max_y    = %+16.12f m;\r\n",
-                NS(LimitRect_get_min_x)( limit ),
-                NS(LimitRect_get_max_x)( limit ),
-                NS(LimitRect_get_min_y)( limit ),
-                NS(LimitRect_get_max_y)( limit ) );
+        printf( "|limit_rect       | min_x    = %+20.12f m;\r\n"
+                "                  | max_x    = %+20.12f m;\r\n"
+                "                  | min_y    = %+20.12f m;\r\n"
+                "                  | max_y    = %+20.12f m;\r\n",
+                NS(LimitRect_min_x)( limit ), NS(LimitRect_max_x)( limit ),
+                NS(LimitRect_min_y)( limit ), NS(LimitRect_max_y)( limit ) );
     }
-    
-    return;
 }
 
 #endif /* !defined( _GPUCODE ) */
@@ -146,6 +179,6 @@ SIXTRL_INLINE void NS(LimitRect_print_out)(
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-    
+
 #endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_LIMIT_RECT_C99_H__ */
 /* end: tests/sixtracklib/testlib/common/beam_elements/be_limit_rect.h */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect_ellipse.c b/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect_ellipse.c
new file mode 100644
index 00000000..7071c82f
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect_ellipse.c
@@ -0,0 +1,19 @@
+#include "sixtracklib/testlib/common/beam_elements/be_limit_rect_ellipse.h"
+#include "sixtracklib/common/be_limit/be_limit_rect_ellipse.h"
+
+void NS(LimitRectEllipse_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
+        SIXTRL_RESTRICT limit )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( limit != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp, "|limit_rect_ellips| half-axis x = %+21.18f m\r\n"
+                "                  | half-axis y = %+21.18f m\r\n"
+                "                  | x limit     = %+21.18f m\r\n"
+                "                  | y limit     = %+21.18f m\r\n",
+                NS(LimitRectEllipse_a)( limit ),
+                NS(LimitRectEllipse_b)( limit ),
+                NS(LimitRectEllipse_max_x)( limit ),
+                NS(LimitRectEllipse_max_y)( limit ) );
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect_ellipse.h b/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect_ellipse.h
new file mode 100644
index 00000000..a0466322
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_limit_rect_ellipse.h
@@ -0,0 +1,205 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_LIMIT_RECT_ELLIPSE_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_LIMIT_RECT_ELLIPSE_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_limit/definitions.h"
+    #include "sixtracklib/common/be_limit/be_limit_rect_ellipse.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_STATIC SIXTRL_FN int NS(LimitRectEllipse_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(LimitRectEllipse_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN void NS(LimitRectEllipse_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
+        SIXTRL_RESTRICT limit );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(LimitRectEllipse_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const
+        SIXTRL_RESTRICT limit );
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* ========================================================================= */
+/*        Implementation of inline functions for NS(LimitEllipse)            */
+/* ========================================================================= */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/compare.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE int NS(LimitRectEllipse_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = NS(Type_value_comp_result)(
+                NS(LimitRectEllipse_max_x)( lhs ),
+                NS(LimitRectEllipse_max_x)( rhs ) );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitRectEllipse_max_y)( lhs ),
+                    NS(LimitRectEllipse_max_y)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitRectEllipse_a_squ)( lhs ),
+                    NS(LimitRectEllipse_a_squ)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitRectEllipse_b_squ)( lhs ),
+                    NS(LimitRectEllipse_b_squ)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(LimitRectEllipse_a_squ_b_squ)( lhs ),
+                    NS(LimitRectEllipse_a_squ_b_squ)( rhs ) );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(LimitRectEllipse_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(LimitRectEllipse) *const SIXTRL_RESTRICT rhs,
+    NS(particle_real_t) const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+        if( lhs != rhs )
+        {
+            NS(particle_real_t) const REL_TOL = ( NS(particle_real_t) )0;
+
+            cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                NS(LimitRectEllipse_max_x)( lhs ),
+                NS(LimitRectEllipse_max_x)( rhs ), REL_TOL, ABS_TOL );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitRectEllipse_max_y)( lhs ),
+                    NS(LimitRectEllipse_max_y)( rhs ), REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitRectEllipse_a_squ)( lhs ),
+                    NS(LimitRectEllipse_a_squ)( rhs ),
+                    REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitRectEllipse_b_squ)( lhs ),
+                    NS(LimitRectEllipse_b_squ)( rhs ),
+                    REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(LimitRectEllipse_a_squ_b_squ)( lhs ),
+                    NS(LimitRectEllipse_a_squ_b_squ)( rhs ),
+                    REL_TOL, ABS_TOL );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE void NS(LimitRectEllipse_print_out)( SIXTRL_BE_ARGPTR_DEC const
+    NS(LimitRectEllipse) *const SIXTRL_RESTRICT limit )
+{
+    NS(LimitRectEllipse_print)( stdout, limit );
+}
+
+#else /* !defined( _GPUCODE ) */
+
+SIXTRL_INLINE void NS(LimitRectEllipse_print_out)( SIXTRL_BE_ARGPTR_DEC const
+    NS(LimitRectEllipse) *const SIXTRL_RESTRICT limit )
+{
+    if( limit != SIXTRL_NULLPTR )
+    {
+        printf( "|limit_rect_ellips| half-axis x = %+21.18f m\r\n"
+                "                  | half-axis y = %+21.18f m\r\n"
+                "                  | x limit     = %+21.18f m\r\n"
+                "                  | y limit     = %+21.18f m\r\n",
+                NS(LimitRectEllipse_a)( limit ),
+                NS(LimitRectEllipse_b)( limit ),
+                NS(LimitRectEllipse_max_x)( limit ),
+                NS(LimitRectEllipse_max_y)( limit ) );
+    }
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_LIMIT_RECT_ELLIPSE_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_monitor.c b/tests/sixtracklib/testlib/common/beam_elements/be_monitor.c
new file mode 100644
index 00000000..4db2890a
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_monitor.c
@@ -0,0 +1,39 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/beam_elements/be_monitor.h"
+    #include "sixtracklib/common/be_monitor/be_monitor.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+void NS(BeamMonitor_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT elem )
+{
+    if( ( elem != SIXTRL_NULLPTR ) && ( fp != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp, "beam-monitor        | num_stores      = %21ld\r\n"
+                "                    | start           = %21ld\r\n"
+                "                    | skip            = %21ld\r\n"
+                "                    | out_address     = %21lx\r\n"
+                "                    | min_particle_id = %21ld\r\n"
+                "                    | max_particle_id = %21ld\r\n"
+                "                    | is_rolling      = %21ld\r\n"
+                "                    | is_turn_ordered = %21ld\r\n",
+                ( long int )NS(BeamMonitor_num_stores)( elem ),
+                ( long int )NS(BeamMonitor_start)( elem ),
+                ( long int )NS(BeamMonitor_skip)( elem ),
+                ( uintptr_t )NS(BeamMonitor_out_address)( elem ),
+                ( long int )NS(BeamMonitor_min_particle_id)( elem ),
+                ( long int )NS(BeamMonitor_max_particle_id)( elem ),
+                ( long int )NS(BeamMonitor_is_rolling)( elem ),
+                ( long int )NS(BeamMonitor_is_turn_ordered)( elem ) );
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_monitor.h b/tests/sixtracklib/testlib/common/beam_elements/be_monitor.h
new file mode 100644
index 00000000..4cd68872
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_monitor.h
@@ -0,0 +1,150 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_MONITOR_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_MONITOR_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_monitor/be_monitor.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_STATIC SIXTRL_FN int NS(BeamMonitor_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN void NS(BeamMonitor_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT elem );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BeamMonitor_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT elem );
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!  Implementation of inline functions for NS(BeamMonitor)  !!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE int NS(BeamMonitor_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT
+        rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = ( lhs->num_stores == rhs->num_stores )
+                ? 0 : ( ( lhs->num_stores > rhs->num_stores ) ? +1 : -1 );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = ( lhs->start == rhs->start )
+                    ? 0 : ( ( lhs->start > rhs->start ) ? +1 : -1 );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = ( lhs->skip == rhs->skip )
+                    ? 0 : ( ( lhs->skip > rhs->skip ) ? +1 : -1 );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = ( lhs->out_address == rhs->out_address )
+                    ? 0 : ( ( lhs->out_address > rhs->out_address ) ? +1 : -1 );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = ( lhs->max_particle_id == rhs->max_particle_id )
+                    ? 0 : ( ( lhs->max_particle_id > rhs->max_particle_id )
+                        ? +1 : -1 );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = ( lhs->min_particle_id == rhs->min_particle_id )
+                    ? 0 : ( ( lhs->min_particle_id > rhs->min_particle_id )
+                        ? +1 : -1 );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = ( lhs->is_rolling == rhs->is_rolling )
+                    ? 0 : ( ( lhs->is_rolling > rhs->is_rolling ) ? +1 : -1 );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = ( lhs->is_turn_ordered == rhs->is_turn_ordered )
+                    ? 0 : ( ( lhs->is_turn_ordered > rhs->is_turn_ordered )
+                        ? +1 : -1 );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(BeamMonitor_print_out)( SIXTRL_BE_ARGPTR_DEC const
+    NS(BeamMonitor) *const SIXTRL_RESTRICT elem )
+{
+    if( elem != SIXTRL_NULLPTR )
+    {
+        printf( "beam-monitor        | num_stores      = %21ld\r\n"
+                "                    | start           = %21ld\r\n"
+                "                    | skip            = %21ld\r\n"
+                "                    | out_address     = %21lx\r\n"
+                "                    | min_particle_id = %21ld\r\n"
+                "                    | max_particle_id = %21ld\r\n"
+                "                    | is_rolling      = %21ld\r\n"
+                "                    | is_turn_ordered = %21ld\r\n",
+                ( long int )NS(BeamMonitor_num_stores)( elem ),
+                ( long int )NS(BeamMonitor_start)( elem ),
+                ( long int )NS(BeamMonitor_skip)( elem ),
+                ( uintptr_t )NS(BeamMonitor_out_address)( elem ),
+                ( long int )NS(BeamMonitor_min_particle_id)( elem ),
+                ( long int )NS(BeamMonitor_max_particle_id)( elem ),
+                ( long int )NS(BeamMonitor_is_rolling)( elem ),
+                ( long int )NS(BeamMonitor_is_turn_ordered)( elem ) );
+    }
+}
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_MONITOR_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_multipole.c b/tests/sixtracklib/testlib/common/beam_elements/be_multipole.c
new file mode 100644
index 00000000..d63f9c89
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_multipole.c
@@ -0,0 +1,41 @@
+#include "sixtracklib/testlib/common/beam_elements/be_multipole.h"
+#include "sixtracklib/common/be_multipole/be_multipole.h"
+
+void NS(Multipole_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT mp )
+{
+    if( ( mp != SIXTRL_NULLPTR ) && ( fp != SIXTRL_NULLPTR ) )
+    {
+        NS(multipole_order_t) const order = NS(Multipole_order)( mp );
+
+        printf( "|multipole        | order    = %3ld;\r\n"
+                "                  | length   = %+20.12f m;\r\n"
+                "                  | hxl      = %+20.12f m;\r\n"
+                "                  | hyl      = %+20.12f m;\r\n",
+                ( long int )order, NS(Multipole_length)( mp ),
+                NS(Multipole_hxl)( mp ), NS(Multipole_hyl)( mp ) );
+
+        printf( "                  |"
+                    "    idx"
+                    "                  knl" "                  ksl\r\n" );
+
+        if( order >= ( NS(multipole_order_t) )0 )
+        {
+            NS(multipole_order_t) ii = ( NS(multipole_order_t) )0;
+            for( ; ii <= order ; ++ii )
+            {
+                printf( "                  | %6ld %+20.12f %+20.12f\r\n",
+                        ( long int )ii,
+                        NS(Multipole_knl)( mp, ii ),
+                        NS(Multipole_ksl)( mp, ii ) );
+            }
+        }
+        else
+        {
+            printf( "                  |"
+                    "    ---"
+                    "                  n/a" "                  n/a\r\n" );
+        }
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_multipole.h b/tests/sixtracklib/testlib/common/beam_elements/be_multipole.h
new file mode 100644
index 00000000..89542764
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_multipole.h
@@ -0,0 +1,205 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_MULTIPOLE_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_MULTIPOLE_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/be_multipole/be_multipole.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_STATIC SIXTRL_FN int NS(Multipole_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(Multipole_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT rhs,
+    NS(multipole_real_t) const treshold ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN void NS(Multipole_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT e );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Multipole_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT mp );
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE int NS(Multipole_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = ( lhs->order == rhs->order )
+                ? 0 : ( ( lhs->order > rhs->order ) ? +1 : -1 );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(Multipole_length)( lhs ), NS(Multipole_length)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(Multipole_hxl)( lhs ), NS(Multipole_hxl)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(Multipole_hyl)( lhs ), NS(Multipole_hyl)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_for_range)(
+                    NS(Multipole_const_bal_begin)( lhs ),
+                    NS(Multipole_const_bal_end)( lhs ),
+                    NS(Multipole_const_bal_begin)( rhs ) );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(Multipole_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT rhs,
+    NS(multipole_real_t) const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            NS(multipole_real_t) const REL_TOL = ( NS(multipole_real_t) )0;
+
+            cmp_result = ( lhs->order == rhs->order )
+                ? 0 : ( ( lhs->order > rhs->order ) ? +1 : -1 );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(Multipole_length)( lhs ), NS(Multipole_length)( rhs ),
+                        REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(Multipole_hxl)( lhs ), NS(Multipole_hxl)( rhs ),
+                        REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(Multipole_hyl)( lhs ), NS(Multipole_hyl)( rhs ),
+                        REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result =
+                NS(Type_value_comp_result_with_tolerances_for_range)(
+                    NS(Multipole_const_bal_begin)( lhs ),
+                    NS(Multipole_const_bal_end)( lhs ),
+                    NS(Multipole_const_bal_begin)( rhs ), REL_TOL, ABS_TOL );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(Multipole_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(Multipole) *const SIXTRL_RESTRICT mp )
+{
+    if( mp != SIXTRL_NULLPTR )
+    {
+        NS(multipole_order_t) const order = NS(Multipole_order)( mp );
+
+        printf( "|multipole        | order    = %3ld;\r\n"
+                "                  | length   = %+20.12f m;\r\n"
+                "                  | hxl      = %+20.12f m;\r\n"
+                "                  | hyl      = %+20.12f m;\r\n",
+                ( long int )order, NS(Multipole_length)( mp ),
+                NS(Multipole_hxl)( mp ), NS(Multipole_hyl)( mp ) );
+
+        printf( "                  |"
+                    "    idx"
+                    "                  knl" "                  ksl\r\n" );
+
+        if( order >= ( NS(multipole_order_t) )0 )
+        {
+            NS(multipole_order_t) ii = ( NS(multipole_order_t) )0;
+            for( ; ii <= order ; ++ii )
+            {
+                printf( "                  | %6ld %+20.12f %+20.12f\r\n",
+                        ( long int )ii,
+                        NS(Multipole_knl)( mp, ii ),
+                        NS(Multipole_ksl)( mp, ii ) );
+            }
+        }
+        else
+        {
+            printf( "                  |"
+                    "    ---"
+                    "                  n/a" "                  n/a\r\n" );
+        }
+    }
+}
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_MULTIPOLE_H__ */
+
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_rfmultipole.c b/tests/sixtracklib/testlib/common/beam_elements/be_rfmultipole.c
new file mode 100644
index 00000000..bc474b85
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_rfmultipole.c
@@ -0,0 +1,58 @@
+#include "sixtracklib/testlib/common/beam_elements/be_rfmultipole.h"
+#include "sixtracklib/common/be_rfmultipole/be_rfmultipole.h"
+
+void NS(RFMultipole_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mp )
+{
+    if( ( mp != SIXTRL_NULLPTR ) && ( fp != SIXTRL_NULLPTR ) )
+    {
+        NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mp );
+
+        fprintf( fp,
+                "|rf-multipole     | order      = %3ld;\r\n"
+                "                  | voltage    = %+20.12f m\r\n"
+                "                  | frequency  = %+20.12f m\r\n"
+                "                  | lag        = %+20.12f m\r\n"
+                "                  | bal_addr   = %21lx\r\n"
+                "                  | phase_addr = %21lx\r\n",
+                ( long int )order,
+                NS(RFMultipole_voltage)( mp ),
+                NS(RFMultipole_frequency)( mp ),
+                NS(RFMultipole_lag)( mp ),
+                ( uintptr_t )NS(RFMultipole_bal_addr)( mp ),
+                ( uintptr_t )NS(RFMultipole_phase_addr)( mp ) );
+
+        fprintf( fp, "                  |"
+                    "    idx"
+                    "                  knl"
+                    "                  ksl"
+                    "               phase_n"
+                    "               phase_s\r\n" );
+
+        if( order >= ( NS(rf_multipole_int_t) )0 )
+        {
+            NS(rf_multipole_int_t) ii = ( NS(rf_multipole_int_t) )0;
+            for( ; ii <= order ; ++ii )
+            {
+                fprintf( fp,
+                        "                  | %6ld %+20.12f %+20.12f "
+                        "%+20.12f %+20.12f\r\n",
+                        ( long int )ii,
+                        NS(RFMultipole_knl)( mp, ii ),
+                        NS(RFMultipole_ksl)( mp, ii ),
+                        NS(RFMultipole_phase_n)( mp, ii ),
+                        NS(RFMultipole_phase_s)( mp, ii ) );
+            }
+        }
+        else
+        {
+            fprintf( fp, "                  |"
+                    "    ---"
+                    "                  n/a"
+                    "                  n/a"
+                    "                  n/a"
+                    "                  n/a\r\n" );
+        }
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_rfmultipole.h b/tests/sixtracklib/testlib/common/beam_elements/be_rfmultipole.h
new file mode 100644
index 00000000..5e3161b1
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_rfmultipole.h
@@ -0,0 +1,241 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_RF_MULTIPOLE_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_RF_MULTIPOLE_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/be_rfmultipole/be_rfmultipole.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_STATIC SIXTRL_FN int NS(RFMultipole_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(RFMultipole_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT rhs,
+    NS(rf_multipole_real_t) const ABS_TOL ) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN void NS(RFMultipole_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT e );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(RFMultipole_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mp );
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE int NS(RFMultipole_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const
+        SIXTRL_RESTRICT rhs ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = ( lhs->order == rhs->order )
+                ? 0 : ( ( lhs->order > rhs->order ) ? +1 : -1 );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(RFMultipole_voltage)( lhs ),
+                    NS(RFMultipole_voltage)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(RFMultipole_frequency)( lhs ),
+                    NS(RFMultipole_frequency)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result)(
+                    NS(RFMultipole_lag)( lhs ),
+                    NS(RFMultipole_lag)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_for_range)(
+                    NS(RFMultipole_const_bal_begin)( lhs ),
+                    NS(RFMultipole_const_bal_end)( lhs ),
+                    NS(RFMultipole_const_bal_begin)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_for_range)(
+                    NS(RFMultipole_const_phase_begin)( lhs ),
+                    NS(RFMultipole_const_phase_end)( lhs ),
+                    NS(RFMultipole_const_phase_begin)( rhs ) );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(RFMultipole_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT rhs,
+    NS(rf_multipole_real_t) const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            NS(rf_multipole_real_t) const REL_TOL = (
+                NS(rf_multipole_real_t) )0;
+
+            cmp_result = ( lhs->order == rhs->order )
+                ? 0 : ( ( lhs->order > rhs->order ) ? +1 : -1 );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(RFMultipole_voltage)( lhs ),
+                    NS(RFMultipole_voltage)( rhs ), REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(RFMultipole_frequency)( lhs ),
+                    NS(RFMultipole_frequency)( rhs ), REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(Type_value_comp_result_with_tolerances)(
+                    NS(RFMultipole_lag)( lhs ),
+                    NS(RFMultipole_lag)( rhs ), REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result =
+                NS(Type_value_comp_result_with_tolerances_for_range)(
+                    NS(RFMultipole_const_bal_begin)( lhs ),
+                    NS(RFMultipole_const_bal_end)( lhs ),
+                    NS(RFMultipole_const_bal_begin)( rhs ), REL_TOL, ABS_TOL );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result =
+                NS(Type_value_comp_result_with_tolerances_for_range)(
+                    NS(RFMultipole_const_phase_begin)( lhs ),
+                    NS(RFMultipole_const_phase_end)( lhs ),
+                    NS(RFMultipole_const_phase_begin)( rhs ),
+                    REL_TOL, ABS_TOL );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(RFMultipole_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const NS(RFMultipole) *const SIXTRL_RESTRICT mp )
+{
+    if( mp != SIXTRL_NULLPTR )
+    {
+        NS(rf_multipole_int_t) const order = NS(RFMultipole_order)( mp );
+
+        printf( "|rf-multipole     | order      = %3ld;\r\n"
+                "                  | voltage    = %+20.12f m\r\n"
+                "                  | frequency  = %+20.12f m\r\n"
+                "                  | lag        = %+20.12f m\r\n"
+                "                  | bal_addr   = %21lx\r\n"
+                "                  | phase_addr = %21lx\r\n",
+                ( long int )order,
+                NS(RFMultipole_voltage)( mp ),
+                NS(RFMultipole_frequency)( mp ),
+                NS(RFMultipole_lag)( mp ),
+                ( uintptr_t )NS(RFMultipole_bal_addr)( mp ),
+                ( uintptr_t )NS(RFMultipole_phase_addr)( mp ) );
+
+        printf( "                  |"
+                    "    idx"
+                    "                  knl"
+                    "                  ksl"
+                    "               phase_n"
+                    "               phase_s\r\n" );
+
+        if( order >= ( NS(rf_multipole_int_t) )0 )
+        {
+            NS(rf_multipole_int_t) ii = ( NS(rf_multipole_int_t) )0;
+            for( ; ii <= order ; ++ii )
+            {
+                printf( "                  | %6ld %+20.12f %+20.12f "
+                        "%+20.12f %+20.12f\r\n",
+                        ( long int )ii,
+                        NS(RFMultipole_knl)( mp, ii ),
+                        NS(RFMultipole_ksl)( mp, ii ),
+                        NS(RFMultipole_phase_n)( mp, ii ),
+                        NS(RFMultipole_phase_s)( mp, ii ) );
+            }
+        }
+        else
+        {
+            printf( "                  |"
+                    "    ---"
+                    "                  n/a"
+                    "                  n/a"
+                    "                  n/a"
+                    "                  n/a\r\n" );
+        }
+    }
+}
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_RF_MULTIPOLE_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_srotation.c b/tests/sixtracklib/testlib/common/beam_elements/be_srotation.c
new file mode 100644
index 00000000..8ac8b5a1
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_srotation.c
@@ -0,0 +1,19 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/beam_elements/be_srotation.h"
+    #include "sixtracklib/common/be_srotation/be_srotation.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+
+void NS(SRotation_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srot )
+{
+    if( ( srot != SIXTRL_NULLPTR ) && ( fp != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp,
+            "|srotation        | angle    = %+20.16f deg  ( %+20.17f rad )\r\n"
+            "                  | cos_z    = %+20.18f;\r\n"
+            "                  | sin_z    = %+20.18f;\r\n",
+            NS(SRotation_angle_deg)( srot ), NS(SRotation_angle)( srot ),
+            NS(SRotation_cos_angle)( srot ), NS(SRotation_sin_angle)( srot ) );
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_srotation.h b/tests/sixtracklib/testlib/common/beam_elements/be_srotation.h
new file mode 100644
index 00000000..4c3069e9
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_srotation.h
@@ -0,0 +1,137 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_SROTATION_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_SROTATION_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_srotation/be_srotation.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_STATIC SIXTRL_FN void NS(SRotation_print_out)( SIXTRL_BE_ARGPTR_DEC
+    const NS(SRotation) *const SIXTRL_RESTRICT srotation );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(SRotation_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(SRotation) *const SIXTRL_RESTRICT e );
+
+#endif /* !defined( _GPUCODE ) */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN int NS(SRotation_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(SRotation_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* C++, Host */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_INLINE void NS(SRotation_print_out)( SIXTRL_ARGPTR_DEC const NS(SRotation)
+    *const SIXTRL_RESTRICT srot )
+{
+    printf( "|srotation        | angle    = %+20.16f deg  ( %+20.17f rad )\r\n"
+            "                  | cos_z    = %+20.18f;\r\n"
+            "                  | sin_z    = %+20.18f;\r\n",
+            NS(SRotation_angle_deg)( srot ), NS(SRotation_angle)( srot ),
+            NS(SRotation_cos_angle)( srot ), NS(SRotation_sin_angle)( srot ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE int NS(SRotation_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT
+{
+    int cmp_value = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_value = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_value = NS(Type_value_comp_result)( lhs->cos_z, rhs->cos_z );
+
+            if( cmp_value == 0 )
+            {
+                cmp_value = NS(Type_value_comp_result)( lhs->sin_z, rhs->sin_z );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_value = +1;
+    }
+
+    return cmp_value;
+}
+
+SIXTRL_INLINE int NS(SRotation_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_value = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) &&
+        ( ABS_TOL >= ( SIXTRL_REAL_T )0 ) )
+    {
+        cmp_value = 0;
+
+        if( rhs != lhs )
+        {
+            SIXTRL_REAL_T const REL_TOL = ( SIXTRL_REAL_T )0;
+
+            cmp_value = NS(Type_value_comp_result_with_tolerances)(
+                lhs->cos_z, rhs->cos_z, REL_TOL, ABS_TOL );
+
+            if( cmp_value == 0 )
+            {
+                cmp_value = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->sin_z, rhs->sin_z, REL_TOL, ABS_TOL );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_value = +1;
+    }
+
+    return cmp_value;
+}
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* C++, Host */
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_SROTATION_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_tricub.c b/tests/sixtracklib/testlib/common/beam_elements/be_tricub.c
new file mode 100644
index 00000000..c3b53c1a
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_tricub.c
@@ -0,0 +1,48 @@
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include "sixtracklib/testlib/common/beam_elements/be_tricub.h"
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+    #include <stdio.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_tricub/be_tricub.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE )
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stdio.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+void NS(TriCub_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT e )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( e != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp,
+            "|tricub          | x_shift             = %+20.12f\r\n"
+            "                 | y_shift             = %+20.12f\r\n"
+            "                 | tau_shift          = %+20.12f\r\n"
+            "                 | dipolar_kick_px     = %+20.12f\r\n"
+            "                 | dipolar_kick_py     = %+20.12f\r\n"
+            "                 | dipolar_kick_ptau   = %+20.12f\r\n"
+            "                 | length              = %+20.12f\r\n"
+            "                 | table_addr          = %20lu\r\n",
+            NS(TriCub_x_shift)( e ), NS(TriCub_y_shift)( e ),
+            NS(TriCub_tau_shift)( e ), NS(TriCub_dipolar_kick_px)( e ),
+            NS(TriCub_dipolar_kick_py)( e ), NS(TriCub_dipolar_kick_ptau)( e ),
+            NS(TriCub_length)( e ),
+            ( long unsigned )NS(TriCub_data_addr)( e ) );
+    }
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+/* end: /sixtracklib/testlib/common/beam_elements/be_tricub.c */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_tricub.h b/tests/sixtracklib/testlib/common/beam_elements/be_tricub.h
new file mode 100644
index 00000000..2e2278bd
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_tricub.h
@@ -0,0 +1,226 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_TRICUB_C99_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_TRICUB_C99_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/be_tricub/be_tricub.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_STATIC SIXTRL_FN int NS(TriCub_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT rhs );
+
+SIXTRL_STATIC SIXTRL_FN int NS(TriCub_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold );
+
+SIXTRL_STATIC SIXTRL_FN void NS(TriCub_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const struct NS(TriCub) *const SIXTRL_RESTRICT e );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(TriCub_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const struct NS(TriCub) *const SIXTRL_RESTRICT e );
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* ========================================================================= */
+/* =====             Implementation of inline functions                ===== */
+/* ========================================================================= */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/compare.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE int NS(TriCub_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT rhs )
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = NS(TestLibCompare_real_attribute)(
+                NS(TriCub_x_shift)( lhs ), NS(TriCub_x_shift)( rhs ) );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute)(
+                    NS(TriCub_y_shift)( lhs ), NS(TriCub_y_shift)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute)(
+                    NS(TriCub_tau_shift)( lhs ), NS(TriCub_tau_shift)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute)(
+                    NS(TriCub_dipolar_kick_px)( lhs ), NS(TriCub_dipolar_kick_px)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute)(
+                    NS(TriCub_dipolar_kick_py)( lhs ), NS(TriCub_dipolar_kick_py)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute)(
+                    NS(TriCub_dipolar_kick_ptau)( lhs ), NS(TriCub_dipolar_kick_ptau)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute)(
+                    NS(TriCub_length)( lhs ), NS(TriCub_length)( rhs ) );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_int64_attribute)(
+                    NS(TriCub_data_addr)( lhs ), NS(TriCub_data_addr)( rhs ) );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(TriCub_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(TriCub) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold )
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_result = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
+                NS(TriCub_x_shift)( lhs ), NS(TriCub_x_shift)( rhs ), treshold );
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
+                    NS(TriCub_y_shift)( lhs ), NS(TriCub_y_shift)( rhs ), treshold );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
+                    NS(TriCub_tau_shift)( lhs ), NS(TriCub_tau_shift)( rhs ), treshold );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
+                    NS(TriCub_dipolar_kick_px)( lhs ), NS(TriCub_dipolar_kick_px)( rhs ), treshold );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
+                    NS(TriCub_dipolar_kick_py)( lhs ), NS(TriCub_dipolar_kick_py)( rhs ), treshold );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
+                    NS(TriCub_dipolar_kick_ptau)( lhs ), NS(TriCub_dipolar_kick_ptau)( rhs ), treshold );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_real_attribute_with_treshold)(
+                    NS(TriCub_length)( lhs ), NS(TriCub_length)( rhs ),
+                        treshold );
+            }
+
+            if( cmp_result == 0 )
+            {
+                cmp_result = NS(TestLibCompare_int64_attribute)(
+                    NS(TriCub_data_addr)( lhs ), NS(TriCub_data_addr)( rhs ) );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE void NS(TriCub_print_out)(
+    SIXTRL_BE_ARGPTR_DEC const struct NS(TriCub) *const SIXTRL_RESTRICT e )
+{
+    #if defined( _GPUCODE )
+
+    SIXTRL_ASSERT( e != SIXTRL_NULLPTR );
+
+    printf( "|tricub          | x_shift             = %+20.12f\r\n"
+            "                 | y_shift             = %+20.12f\r\n"
+            "                 | tau_shift          = %+20.12f\r\n"
+            "                 | dipolar_kick_px     = %+20.12f\r\n"
+            "                 | dipolar_kick_py     = %+20.12f\r\n"
+            "                 | dipolar_kick_ptau   = %+20.12f\r\n"
+            "                 | length              = %+20.12f\r\n"
+            "                 | table_addr          = %20lu\r\n",
+            NS(TriCub_x_shift)( e ), NS(TriCub_y_shift)( e ),
+            NS(TriCub_tau_shift)( e ), NS(TriCub_dipolar_kick_px)( e ),
+            NS(TriCub_dipolar_kick_py)( e ), NS(TriCub_dipolar_kick_ptau)( e ),
+            NS(TriCub_length)( e ),
+            ( long unsigned )NS(TriCub_data_addr)( e ) );
+
+    #else
+
+    NS(TriCub_print)( stdout, e );
+
+    #endif /* !defined( _GPUCODE ) */
+}
+
+#if !defined(  _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_TRICUB_C99_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_xy_shift.c b/tests/sixtracklib/testlib/common/beam_elements/be_xy_shift.c
new file mode 100644
index 00000000..8380b933
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_xy_shift.c
@@ -0,0 +1,16 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/beam_elements/be_xy_shift.h"
+    #include "sixtracklib/common/be_xyshift/be_xyshift.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+void NS(XYShift_print)( SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xyshift )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( xyshift != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp,
+            "|xy_shift         | dx        = %+20.14f m\r\n"
+            "                  | dy        = %+20.14f m\r\n",
+            NS(XYShift_dx)( xyshift ), NS(XYShift_dy)( xyshift ) );
+    }
+}
diff --git a/tests/sixtracklib/testlib/common/beam_elements/be_xy_shift.h b/tests/sixtracklib/testlib/common/beam_elements/be_xy_shift.h
new file mode 100644
index 00000000..50a53758
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/beam_elements/be_xy_shift.h
@@ -0,0 +1,135 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_XY_SHIFT_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_XY_SHIFT_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdlib.h>
+
+    #if !defined( _GPUCODE )
+    #include <stdio.h>
+    #endif /* !defined( _GPUCODE ) */
+
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/be_xyshift/be_xyshift.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+    #include "sixtracklib/common/internal/type_comparison_helpers.hpp"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_STATIC SIXTRL_FN void NS(XYShift_print_out)( SIXTRL_BE_ARGPTR_DEC const
+    NS(XYShift) *const SIXTRL_RESTRICT xyshift );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(XYShift_print)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xyshift );
+
+#endif /* !defined( _GPUCODE ) */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_STATIC SIXTRL_FN int NS(XYShift_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT;
+
+SIXTRL_STATIC SIXTRL_FN int NS(XYShift_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const ABS_TOL ) SIXTRL_NOEXCEPT;
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* C++, Host */
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* C++, Host */
+
+SIXTRL_INLINE void NS(XYShift_print_out)( SIXTRL_ARGPTR_DEC const NS(XYShift)
+    *const SIXTRL_RESTRICT xyshift )
+{
+    printf( "|xy_shift         | dx        = %+20.14f m\r\n"
+            "                  | dy        = %+20.14f m\r\n",
+            NS(XYShift_dx)( xyshift ), NS(XYShift_dy)( xyshift ) );
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+SIXTRL_INLINE int NS(XYShift_compare_values)(
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT rhs
+) SIXTRL_NOEXCEPT
+{
+    int cmp_value = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        cmp_value = 0;
+
+        if( lhs != rhs )
+        {
+            cmp_value = NS(Type_value_comp_result)( lhs->dx, rhs->dx );
+
+            if( cmp_value == 0 )
+            {
+                cmp_value = NS(Type_value_comp_result)( lhs->dy, rhs->dy );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_value = +1;
+    }
+
+    return cmp_value;
+}
+
+SIXTRL_INLINE int NS(XYShift_compare_values_with_treshold)(
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT lhs,
+    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const ABS_TOL ) SIXTRL_NOEXCEPT
+{
+    int cmp_value = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) &&
+        ( ABS_TOL >= ( SIXTRL_REAL_T )0 ) )
+    {
+        cmp_value = 0;
+
+        if( rhs != lhs )
+        {
+            SIXTRL_REAL_T const REL_TOL = ( SIXTRL_REAL_T )0;
+
+            cmp_value = NS(Type_value_comp_result_with_tolerances)(
+                lhs->dx, rhs->dx, REL_TOL, ABS_TOL );
+
+            if( cmp_value == 0 )
+            {
+                cmp_value = NS(Type_value_comp_result_with_tolerances)(
+                    lhs->dy, rhs->dy, REL_TOL, ABS_TOL );
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_value = +1;
+    }
+
+    return cmp_value;
+}
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* C++, Host */
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BEAM_ELEMENTS_BE_XY_SHIFT_H__ */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/beam_elements.c b/tests/sixtracklib/testlib/common/beam_elements/beam_elements.c
index a8162296..ab56ef9f 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/beam_elements.c
+++ b/tests/sixtracklib/testlib/common/beam_elements/beam_elements.c
@@ -14,134 +14,6 @@
 /* =====           BEAM_ELEMENTS_TOOLS IMPLEMENTATION                  ===== */
 /* ========================================================================= */
 
-void NS(Drift_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift )
-{
-    SIXTRL_ASSERT( fp != SIXTRL_NULLPTR );
-    fprintf( fp, "|drift            | length   = %+16.12f m;\r\n",
-            NS(Drift_get_length)( drift ) );
-}
-
-void NS(DriftExact_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift )
-{
-    SIXTRL_ASSERT( fp != SIXTRL_NULLPTR );
-
-    fprintf( fp, "|drift exact      | length   = %+16.12f m;\r\n",
-            NS(DriftExact_get_length)( drift ) );
-}
-
-void NS(MultiPole_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT mp )
-{
-    typedef NS(multipole_order_t) mp_order_t;
-
-    mp_order_t const order = NS(MultiPole_get_order)( mp );
-    SIXTRL_ASSERT( fp != SIXTRL_NULLPTR );
-
-    fprintf( fp,
-             "|multipole        | order    = %3d;\r\n"
-             "                  | length   = %+16.12f m;\r\n"
-             "                  | hxl      = %+16.12f m;\r\n"
-             "                  | hyl      = %+16.12f m;\r\n",
-             ( int )order, NS(MultiPole_get_length)( mp ),
-             NS(MultiPole_get_hxl)( mp ), NS(MultiPole_get_hyl)( mp ) );
-
-    if( order >= ( mp_order_t )0 )
-    {
-        mp_order_t ii = ( mp_order_t )0;
-        mp_order_t const num_k_values = order + ( mp_order_t )1;
-
-        for( ; ii < num_k_values ; ++ii )
-        {
-            fprintf( fp, "                  |"
-                    "knl[ %3d ] = %+20.12f ; ksl[ %3d ] = %+20.12f \r\n",
-                    ( int )ii, NS(MultiPole_get_knl_value)( mp, ii ),
-                    ( int )ii, NS(MultiPole_get_ksl_value)( mp, ii ) );
-        }
-    }
-    else
-    {
-        fprintf( fp, "                  | knl = n/a ; ksl = n/a\r\n" );
-    }
-}
-
-void NS(XYShift_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift )
-{
-    SIXTRL_ASSERT( fp != SIXTRL_NULLPTR );
-    fprintf( fp,
-             "|xy_shift         | dx       = %+16.12f m;\r\n"
-             "                  | dy       = %+16.12f m;\r\n",
-             NS(XYShift_get_dx)( xy_shift ),
-             NS(XYShift_get_dy)( xy_shift ) );
-}
-
-void NS(SRotation_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srot )
-{
-    SIXTRL_ASSERT( fp != SIXTRL_NULLPTR );
-    fprintf( fp,
-             "|srotation        | angle    = %+16.12f deg  ( %+16.12f rad )\r\n"
-             "                  | cos_z    = %+13.12f;\r\n"
-             "                  | sin_z    = %+13.12f;\r\n",
-             NS(SRotation_get_angle_deg)( srot ),
-             NS(SRotation_get_angle)( srot ),
-             NS(SRotation_get_cos_angle)( srot ),
-             NS(SRotation_get_sin_angle)( srot ) );
-}
-
-void NS(Cavity_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cav )
-{
-    SIXTRL_ASSERT( fp != SIXTRL_NULLPTR );
-    fprintf( fp,
-             "|cavity           | voltage   = %+16.12f V   \r\n"
-             "                  | frequency = %+20.12f Hz; \r\n"
-             "                  | lag       = %+15.12f deg;\r\n",
-             NS(Cavity_get_voltage)( cav ),
-             NS(Cavity_get_frequency)( cav ),
-             NS(Cavity_get_lag)( cav ) );
-}
-
-void NS(BeamMonitor_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
-{
-    int const is_rolling =
-        NS(BeamMonitor_is_rolling)( monitor ) ? 1 : 0;
-
-    int const is_turn_ordered =
-        NS(BeamMonitor_is_turn_ordered)( monitor ) ? 1 : 0;
-
-    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
-
-    fprintf( fp,
-            "|beam-monitor     | num stores       = %20d \r\n"
-            "                  | start turn       = %20d\r\n"
-            "                  | skip turns       = %20d\r\n"
-            "                  | out_address      = %20lu;\r\n"
-            "                  | min_particle_id  = %20d\r\n"
-            "                  | max_particle_id  = %20d\r\n"
-            "                  | is_rolling       = %20d\r\n"
-            "                  | is_turn_ordered  = %20d\r\n",
-            ( int )NS(BeamMonitor_get_num_stores)( monitor ),
-            ( int )NS(BeamMonitor_get_start)( monitor ),
-            ( int )NS(BeamMonitor_get_skip)( monitor ),
-            ( unsigned long )NS(BeamMonitor_get_out_address)( monitor ),
-            ( int )NS(BeamMonitor_get_min_particle_id)( monitor ),
-            ( int )NS(BeamMonitor_get_max_particle_id)( monitor ),
-            is_rolling, is_turn_ordered );
-}
-
-/* ------------------------------------------------------------------------- */
-
 void NS(BeamElement_print)(
     SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
     SIXTRL_BE_ARGPTR_DEC const struct NS(Object) *const SIXTRL_RESTRICT
@@ -156,172 +28,132 @@ void NS(BeamElement_print)(
         {
             case NS(OBJECT_TYPE_DRIFT):
             {
-                typedef NS(Drift) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
-                NS(Drift_print)( fp, beam_element );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(Drift) const* ptr_t;
+                NS(Drift_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_DRIFT_EXACT):
             {
-                typedef NS(DriftExact) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
-                NS(DriftExact_print)( fp, beam_element );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const* ptr_t;
+                NS(DriftExact_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_MULTIPOLE):
             {
-                typedef NS(MultiPole) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(Multipole) const* ptr_t;
+                NS(Multipole_print)( fp, ( ptr_t )( uintptr_t )addr );
+                break;
+            }
 
-                NS(MultiPole_print)( fp, beam_element );
+            case NS(OBJECT_TYPE_RF_MULTIPOLE):
+            {
+                typedef SIXTRL_BE_ARGPTR_DEC NS(RFMultipole) const* ptr_t;
+                NS(RFMultipole_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_CAVITY):
             {
-                typedef NS(Cavity) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
-                NS(Cavity_print)( fp, beam_element );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(Cavity) const* ptr_t;
+                NS(Cavity_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_XYSHIFT):
             {
-                typedef NS(XYShift) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
-                NS(XYShift_print)( fp, beam_element );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(XYShift) const* ptr_t;
+                NS(XYShift_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_SROTATION):
             {
-                typedef NS(SRotation) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
-                NS(SRotation_print)( fp, beam_element );
-
+                typedef SIXTRL_BE_ARGPTR_DEC NS(SRotation) const* ptr_t;
+                NS(SRotation_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_BEAM_BEAM_4D):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(BeamBeam4D) const* ptr_to_belem_t;
-                ptr_to_belem_t beam_element = ( ptr_to_belem_t )( uintptr_t )addr;
-
-                NS(BeamBeam4D_print)( fp, beam_element );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(BeamBeam4D) const* ptr_t;
+                NS(BeamBeam4D_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(SpaceChargeCoasting) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
-
-                NS(SpaceChargeCoasting_print)( fp, beam_element );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(BeamBeam6D) const* ptr_t;
+                NS(BeamBeam6D_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+            case NS(OBJECT_TYPE_SC_COASTING):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(SpaceChargeBunched) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
-
-                NS(SpaceChargeBunched_print)( fp, beam_element );
+                typedef NS(SCCoasting) sc_elem_t;
+                typedef SIXTRL_BE_ARGPTR_DEC sc_elem_t const* ptr_t;
+                NS(SCCoasting_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
-            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+            case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(BeamBeam6D) const* ptr_to_belem_t;
-                ptr_to_belem_t beam_element = ( ptr_to_belem_t )( uintptr_t )addr;
+                typedef NS(SCQGaussProfile) sc_elem_t;
+                typedef SIXTRL_BE_ARGPTR_DEC sc_elem_t const* ptr_t;
+                NS(SCQGaussProfile_print)(
+                    fp, ( ptr_t )( uintptr_t )addr );
+                break;
+            }
 
-                NS(BeamBeam6D_print)( fp, beam_element );
+            case NS(OBJECT_TYPE_SC_INTERPOLATED_PROF):
+            {
+                typedef NS(SCInterpolatedProfile) sc_elem_t;
+                typedef SIXTRL_BE_ARGPTR_DEC sc_elem_t const* ptr_t;
+                NS(SCInterpolatedProfile_print)(
+                    fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_BEAM_MONITOR):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(BeamMonitor) const* ptr_to_belem_t;
-                ptr_to_belem_t beam_element = ( ptr_to_belem_t )( uintptr_t )addr;
-
-                NS(BeamMonitor_print)( fp, beam_element );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(BeamMonitor) const* ptr_t;
+                NS(BeamMonitor_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_LIMIT_RECT):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(LimitRect) const* ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
-
-                NS(LimitRect_print)( fp, beam_element );
+                typedef SIXTRL_BE_ARGPTR_DEC NS(LimitRect) const* ptr_t;
+                NS(LimitRect_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_LIMIT_ELLIPSE):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(LimitEllipse) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(LimitEllipse) const* ptr_t;
+                NS(LimitEllipse_print)( fp, ( ptr_t )( uintptr_t )addr );
+                break;
+            }
 
-                NS(LimitEllipse_print)( fp, beam_element );
+            case NS(OBJECT_TYPE_LIMIT_RECT_ELLIPSE):
+            {
+                typedef SIXTRL_BE_ARGPTR_DEC NS(LimitRectEllipse) const* ptr_t;
+                NS(LimitRectEllipse_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
             case NS(OBJECT_TYPE_DIPEDGE):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(DipoleEdge) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
+                typedef SIXTRL_BE_ARGPTR_DEC NS(DipoleEdge) const* ptr_t;
+                NS(DipoleEdge_print)( fp, ( ptr_t )( uintptr_t )addr );
+                break;
+            }
 
-                NS(DipoleEdge_print)( fp, beam_element );
+            case NS(OBJECT_TYPE_TRICUB):
+            {
+                typedef SIXTRL_BE_ARGPTR_DEC NS(TriCub) const* ptr_t;
+                NS(TriCub_print)( fp, ( ptr_t )( uintptr_t )addr );
                 break;
             }
 
@@ -338,5 +170,3 @@ void NS(BeamElement_print)(
 
     return;
 }
-
-/* end: tests/sixtracklib/testlib/common/beam_elements/beam_elements.c */
diff --git a/tests/sixtracklib/testlib/common/beam_elements/beam_elements.h b/tests/sixtracklib/testlib/common/beam_elements/beam_elements.h
index 95966279..70b4bc20 100644
--- a/tests/sixtracklib/testlib/common/beam_elements/beam_elements.h
+++ b/tests/sixtracklib/testlib/common/beam_elements/beam_elements.h
@@ -15,48 +15,12 @@
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-struct NS(Drift);
-struct NS(DriftExact);
-struct NS(MultiPole);
 struct NS(XYShift);
-struct NS(SRotation);
-struct NS(Cavity);
-struct NS(BeamBeam4D);
-struct NS(BeamBeam6D);
-struct NS(BeamMonitor);
-
 struct NS(Object);
 
-/* ------------------------------------------------------------------------- */
-
-SIXTRL_STATIC SIXTRL_FN void NS(Drift_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(Drift) *const SIXTRL_RESTRICT e );
-
-SIXTRL_STATIC SIXTRL_FN void NS(DriftExact_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(DriftExact) *const SIXTRL_RESTRICT e );
-
-SIXTRL_STATIC SIXTRL_FN void NS(MultiPole_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(MultiPole) *const SIXTRL_RESTRICT e );
-
-SIXTRL_STATIC SIXTRL_FN void NS(XYShift_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(XYShift) *const SIXTRL_RESTRICT e );
-
-SIXTRL_STATIC SIXTRL_FN void NS(SRotation_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(SRotation) *const SIXTRL_RESTRICT e );
-
-SIXTRL_STATIC SIXTRL_FN void NS(Cavity_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(Cavity) *const SIXTRL_RESTRICT e );
-
-SIXTRL_STATIC SIXTRL_FN void NS(BeamMonitor_print_out)(
-    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamMonitor) *const SIXTRL_RESTRICT e );
-
-/* ------------------------------------------------------------------------- */
-
 SIXTRL_STATIC SIXTRL_FN void NS(BeamElement_print_out)(
     SIXTRL_BE_ARGPTR_DEC const struct NS(Object) *const SIXTRL_RESTRICT be_info );
 
-/* ------------------------------------------------------------------------- */
-
 SIXTRL_STATIC SIXTRL_FN int NS(BeamElements_compare_objects)(
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT lhs,
     SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT rhs );
@@ -81,36 +45,6 @@ SIXTRL_STATIC SIXTRL_FN int NS(BeamElements_compare_lines_with_treshold)(
 
 #if !defined( _GPUCODE )
 
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Drift_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(Drift) *const SIXTRL_RESTRICT e );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(DriftExact_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(DriftExact) *const SIXTRL_RESTRICT e );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(MultiPole_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(MultiPole) *const SIXTRL_RESTRICT e );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(XYShift_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(XYShift) *const SIXTRL_RESTRICT e );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(SRotation_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(SRotation) *const SIXTRL_RESTRICT e );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Cavity_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(Cavity) *const SIXTRL_RESTRICT e );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BeamMonitor_print)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    SIXTRL_BE_ARGPTR_DEC const struct NS(BeamMonitor) *const SIXTRL_RESTRICT e );
-
-/* ------------------------------------------------------------------------- */
-
 SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BeamElement_print)(
     SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
     SIXTRL_BE_ARGPTR_DEC const struct NS(Object) *const SIXTRL_RESTRICT info );
@@ -130,188 +64,24 @@ SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BeamElement_print)(
     #include "sixtracklib/common/beam_elements.h"
 
     #include "sixtracklib/testlib/common/beam_elements/be_beamfields.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_cavity.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_dipedge.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_drift.h"
     #include "sixtracklib/testlib/common/beam_elements/be_limit_rect.h"
     #include "sixtracklib/testlib/common/beam_elements/be_limit_ellipse.h"
-    #include "sixtracklib/testlib/common/beam_elements/be_dipedge.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_limit_rect_ellipse.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_monitor.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_multipole.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_rfmultipole.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_srotation.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_tricub.h"
+    #include "sixtracklib/testlib/common/beam_elements/be_xy_shift.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined( _GPUCODE ) && defined( __cplusplus )
 extern "C" {
 #endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_INLINE void NS(Drift_print_out)(
-    SIXTRL_ARGPTR_DEC const NS(Drift) *const SIXTRL_RESTRICT drift )
-{
-    #if !defined( _GPUCODE )
-
-    printf( "|drift            | length   = %+16.12f m;\r\n",
-            NS(Drift_get_length)( drift ) );
-
-    #else
-
-    NS(Drift_print)( stdout, drift );
-
-    #endif /* !defined( _GPUCODE ) */
-
-    return;
-}
-
-SIXTRL_INLINE void NS(DriftExact_print_out)(
-    SIXTRL_ARGPTR_DEC const NS(DriftExact) *const SIXTRL_RESTRICT drift )
-{
-    #if !defined( _GPUCODE )
-
-    printf( "|drift exact      | length   = %+16.12f m;\r\n",
-            NS(DriftExact_get_length)( drift ) );
-    #else
-
-    NS(DriftExact_print)( stdout, drift );
-
-    #endif /* !defined( _GPUCODE ) */
-
-    return;
-}
-
-SIXTRL_INLINE void NS(MultiPole_print_out)(
-    SIXTRL_ARGPTR_DEC const NS(MultiPole) *const SIXTRL_RESTRICT mp )
-{
-    #if !defined( _GPUCODE )
-
-    typedef NS(multipole_order_t) mp_order_t;
-
-    mp_order_t const order = NS(MultiPole_get_order)( mp );
-
-    printf( "|multipole        | order    = %3d;\r\n"
-            "                  | length   = %+16.12f m;\r\n"
-            "                  | hxl      = %+16.12f m;\r\n"
-            "                  | hyl      = %+16.12f m;\r\n",
-            ( int )order, NS(MultiPole_get_length)( mp ),
-            NS(MultiPole_get_hxl)( mp ), NS(MultiPole_get_hyl)( mp ) );
-
-    if( order >= ( mp_order_t )0 )
-    {
-        mp_order_t ii = ( mp_order_t )0;
-        mp_order_t const num_k_values = order + ( mp_order_t )1;
-
-        for( ; ii < num_k_values ; ++ii )
-        {
-            printf( "                  |"
-                    "knl[ %3d ] = %+20.12f ; ksl[ %3d ] = %+20.12f \r\n",
-                    ( int )ii, NS(MultiPole_get_knl_value)( mp, ii ),
-                    ( int )ii, NS(MultiPole_get_ksl_value)( mp, ii ) );
-        }
-    }
-    else
-    {
-        printf( "                  | knl = n/a ; ksl = n/a\r\n" );
-    }
-
-    #else
-
-    NS(MultiPole_print)( stdout, mp );
-
-    #endif /* !defined( _GPUCODE ) */
-
-    return;
-}
-
-SIXTRL_INLINE void NS(XYShift_print_out)(
-    SIXTRL_ARGPTR_DEC const NS(XYShift) *const SIXTRL_RESTRICT xy_shift )
-{
-    #if !defined( _GPUCODE )
-
-    printf( "|xy_shift         | dx       = %+16.12f m;\r\n"
-            "                  | dy       = %+16.12f m;\r\n",
-            NS(XYShift_get_dx)( xy_shift ),
-            NS(XYShift_get_dy)( xy_shift ) );
-
-    #else
-
-    NS(XYShift_print)( stdout, xy_shift );
-
-    #endif /* !defined( _GPUCODE ) */
-
-    return;
-}
-
-SIXTRL_INLINE void NS(SRotation_print_out)(
-    SIXTRL_ARGPTR_DEC const NS(SRotation) *const SIXTRL_RESTRICT srot )
-{
-    #if !defined( _GPUCODE )
-
-    printf( "|srotation        | angle    = %+16.12f deg  ( %+16.12f rad )\r\n"
-            "                  | cos_z    = %+13.12f;\r\n"
-            "                  | sin_z    = %+13.12f;\r\n",
-            NS(SRotation_get_angle_deg)( srot ),
-            NS(SRotation_get_angle)( srot ),
-            NS(SRotation_get_cos_angle)( srot ),
-            NS(SRotation_get_sin_angle)( srot ) );
-
-    #else
-
-    NS(SRotation_print)( stdout, srot );
-
-    #endif /* !defined( _GPUCODE ) */
-
-    return;
-}
-
-SIXTRL_INLINE void NS(Cavity_print_out)(
-    SIXTRL_ARGPTR_DEC const NS(Cavity) *const SIXTRL_RESTRICT cavity )
-{
-    #if !defined( _GPUCODE )
-    printf( "|cavity           | voltage   = %+16.12f V   \r\n"
-            "                  | frequency = %+20.12f Hz; \r\n"
-            "                  | lag       = %+15.12f deg;\r\n",
-            NS(Cavity_get_voltage)( cavity ),
-            NS(Cavity_get_frequency)( cavity ),
-            NS(Cavity_get_lag)( cavity ) );
-
-    #else
-
-    NS(Cavity_print)( stdout, cav );
-
-    #endif /* !defined( _GPUCODE ) */
-
-    return;
-}
-
-SIXTRL_INLINE void NS(BeamMonitor_print_out)(
-    SIXTRL_ARGPTR_DEC const NS(BeamMonitor) *const SIXTRL_RESTRICT monitor )
-{
-    #if !defined( _GPUCODE )
-    int const is_rolling =
-        NS(BeamMonitor_is_rolling)( monitor ) ? 1 : 0;
-
-    int const is_turn_ordered =
-        NS(BeamMonitor_is_turn_ordered)( monitor ) ? 1 : 0;
-
-    SIXTRL_ASSERT( monitor != SIXTRL_NULLPTR );
-
-    printf( "|beam-monitor     | num stores       = %20d\r\n"
-            "                  | start turn       = %20d\r\n"
-            "                  | skip turns       = %20d\r\n"
-            "                  | out_address      = %20lu\r\n"
-            "                  | min_particle_id  = %20d\r\n"
-            "                  | max_particle_id  = %20d\r\n"
-            "                  | is_rolling       = %20d\r\n"
-            "                  | is_turn_ordered  = %20d\r\n",
-            ( int )NS(BeamMonitor_get_num_stores)( monitor ),
-            ( int )NS(BeamMonitor_get_start)( monitor ),
-            ( int )NS(BeamMonitor_get_skip)( monitor ),
-            ( unsigned long )NS(BeamMonitor_get_out_address)( monitor ),
-            ( int )NS(BeamMonitor_get_min_particle_id)( monitor ),
-            ( int )NS(BeamMonitor_get_max_particle_id)( monitor ),
-            is_rolling, is_turn_ordered );
-    #else
-
-    NS(BeamMonitor_print)( stdout, monitor );
-
-    #endif /* !defined( _GPUCODE ) */
-
-    return;
-}
-
 SIXTRL_INLINE void NS(BeamElement_print_out)(
     SIXTRL_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT be_info )
 {
@@ -326,186 +96,152 @@ SIXTRL_INLINE void NS(BeamElement_print_out)(
         {
             case NS(OBJECT_TYPE_DRIFT):
             {
-                typedef NS(Drift) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
+                typedef SIXTRL_DATAPTR_DEC NS(Drift) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
                 NS(Drift_print_out)( beam_element );
-
                 break;
             }
 
             case NS(OBJECT_TYPE_DRIFT_EXACT):
             {
-                typedef NS(DriftExact) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
+                typedef SIXTRL_DATAPTR_DEC NS(DriftExact) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
                 NS(DriftExact_print_out)( beam_element );
-
                 break;
             }
 
             case NS(OBJECT_TYPE_MULTIPOLE):
             {
-                typedef NS(MultiPole) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
-                NS(MultiPole_print_out)( beam_element );
+                typedef SIXTRL_DATAPTR_DEC NS(Multipole) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
+                NS(Multipole_print_out)( beam_element );
+                break;
+            }
 
+            case NS(OBJECT_TYPE_RF_MULTIPOLE):
+            {
+                typedef SIXTRL_DATAPTR_DEC NS(RFMultipole) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
+                NS(RFMultipole_print_out)( beam_element );
                 break;
             }
 
             case NS(OBJECT_TYPE_CAVITY):
             {
-                typedef NS(Cavity) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
+                typedef SIXTRL_DATAPTR_DEC NS(Cavity) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
                 NS(Cavity_print_out)( beam_element );
-
                 break;
             }
 
             case NS(OBJECT_TYPE_XYSHIFT):
             {
-                typedef NS(XYShift) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
+                typedef SIXTRL_DATAPTR_DEC NS(XYShift) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
                 NS(XYShift_print_out)( beam_element );
-
                 break;
             }
 
             case NS(OBJECT_TYPE_SROTATION):
             {
-                typedef NS(SRotation) beam_element_t;
-                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_belem_t;
-
-                ptr_belem_t beam_element = ( ptr_belem_t )( uintptr_t )addr;
-
-                SIXTRL_ASSERT( sizeof( beam_element_t ) <=
-                               NS(Object_get_size)( be_info ) );
-
+                typedef SIXTRL_DATAPTR_DEC NS(SRotation) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
                 NS(SRotation_print_out)( beam_element );
-
                 break;
             }
 
             case NS(OBJECT_TYPE_BEAM_BEAM_4D):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(BeamBeam4D) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
-
+                typedef SIXTRL_DATAPTR_DEC NS(BeamBeam4D) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
                 NS(BeamBeam4D_print_out)( beam_element );
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(SpaceChargeCoasting) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
-
-                NS(SpaceChargeCoasting_print_out)( beam_element );
+                typedef SIXTRL_DATAPTR_DEC NS(BeamBeam6D) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
+                NS(BeamBeam6D_print_out)( beam_element );
                 break;
             }
 
-            case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+            case NS(OBJECT_TYPE_SC_COASTING):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(SpaceChargeBunched) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
-
-                NS(SpaceChargeBunched_print_out)( beam_element );
+                typedef NS(SCCoasting) beam_element_t;
+                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
+                NS(SCCoasting_print_out)( beam_element );
                 break;
             }
 
-            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+            case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(BeamBeam6D) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
+                typedef NS(SCQGaussProfile) beam_element_t;
+                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
+                NS(SCQGaussProfile_print_out)( beam_element );
+                break;
+            }
 
-                NS(BeamBeam6D_print_out)( beam_element );
+            case NS(OBJECT_TYPE_SC_INTERPOLATED_PROF):
+            {
+                typedef NS(SCInterpolatedProfile) beam_element_t;
+                typedef SIXTRL_DATAPTR_DEC beam_element_t const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
+                NS(SCInterpolatedProfile_print_out)( beam_element );
                 break;
             }
 
             case NS(OBJECT_TYPE_BEAM_MONITOR):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(BeamMonitor) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
-
+                typedef SIXTRL_DATAPTR_DEC NS(BeamMonitor) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
                 NS(BeamMonitor_print_out)( beam_element );
                 break;
             }
 
             case NS(OBJECT_TYPE_LIMIT_RECT):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(LimitRect) const* ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
-
-                NS(LimitRect_print_out)( beam_element );
+                typedef SIXTRL_DATAPTR_DEC NS(LimitRect) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )addr;
+                NS(LimitRect_print_out)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_LIMIT_ELLIPSE):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(LimitEllipse) const*
-                        ptr_to_belem_t;
-
-                ptr_to_belem_t beam_element =
-                    ( ptr_to_belem_t )( uintptr_t )addr;
+                typedef SIXTRL_DATAPTR_DEC NS(LimitEllipse) const* ptr_elem_t;
+                ptr_elem_t elem = ( ptr_elem_t )( uintptr_t )addr;
+                NS(LimitEllipse_print_out)( elem );
+                break;
+            }
 
-                NS(LimitEllipse_print_out)( beam_element );
+            case NS(OBJECT_TYPE_LIMIT_RECT_ELLIPSE):
+            {
+                typedef SIXTRL_DATAPTR_DEC NS(LimitRectEllipse) const* ptr_t;
+                ptr_t elem = ( ptr_t )( uintptr_t )addr;
+                NS(LimitRectEllipse_print_out)( elem );
                 break;
             }
 
             case NS(OBJECT_TYPE_DIPEDGE):
             {
-                typedef SIXTRL_DATAPTR_DEC NS(DipoleEdge) const*
+                typedef SIXTRL_DATAPTR_DEC NS(DipoleEdge) const* ptr_elem_t;
+                ptr_elem_t beam_element = ( ptr_elem_t )( uintptr_t )addr;
+                NS(DipoleEdge_print_out)( beam_element );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_TRICUB):
+            {
+                typedef SIXTRL_DATAPTR_DEC NS(TriCub) const*
                     ptr_to_belem_t;
 
                 ptr_to_belem_t beam_element =
                     ( ptr_to_belem_t )( uintptr_t )addr;
 
-                NS(DipoleEdge_print_out)( beam_element );
+                NS(TriCub_print_out)( beam_element );
                 break;
             }
 
@@ -581,10 +317,22 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects)(
 
                     case NS(OBJECT_TYPE_MULTIPOLE):
                     {
-                        typedef NS(MultiPole)                       belem_t;
+                        typedef NS(Multipole)                       belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
 
-                        compare_value = NS(MultiPole_compare_values)(
+                        compare_value = NS(Multipole_compare_values)(
+                            ( ptr_belem_t )( uintptr_t )lhs_addr,
+                            ( ptr_belem_t )( uintptr_t )rhs_addr );
+
+                        break;
+                    }
+
+                    case NS(OBJECT_TYPE_RF_MULTIPOLE):
+                    {
+                        typedef NS(RFMultipole)                     belem_t;
+                        typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
+
+                        compare_value = NS(RFMultipole_compare_values)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
                             ( ptr_belem_t )( uintptr_t )rhs_addr );
 
@@ -639,36 +387,48 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects)(
                         break;
                     }
 
-                    case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+                    case NS(OBJECT_TYPE_BEAM_BEAM_6D):
                     {
-                        typedef NS(SpaceChargeCoasting) belem_t;
+                        typedef NS(BeamBeam6D)                      belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
 
-                        compare_value = NS(SpaceChargeCoasting_compare_values)(
+                        compare_value = NS(BeamBeam6D_compare_values)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
                             ( ptr_belem_t )( uintptr_t )rhs_addr );
 
                         break;
                     }
 
-                    case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+                    case NS(OBJECT_TYPE_SC_COASTING):
                     {
-                        typedef NS(SpaceChargeBunched) belem_t;
+                        typedef NS(SCCoasting) belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
 
-                        compare_value = NS(SpaceChargeBunched_compare_values)(
+                        compare_value = NS(SCCoasting_compare_values)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
                             ( ptr_belem_t )( uintptr_t )rhs_addr );
 
                         break;
                     }
 
-                    case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+                    case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
                     {
-                        typedef NS(BeamBeam6D)                      belem_t;
+                        typedef NS(SCQGaussProfile) belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
 
-                        compare_value = NS(BeamBeam6D_compare_values)(
+                        compare_value = NS(SCQGaussProfile_compare_values)(
+                            ( ptr_belem_t )( uintptr_t )lhs_addr,
+                            ( ptr_belem_t )( uintptr_t )rhs_addr );
+
+                        break;
+                    }
+
+                    case NS(OBJECT_TYPE_SC_INTERPOLATED_PROF):
+                    {
+                        typedef NS(SCInterpolatedProfile) belem_t;
+                        typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
+
+                        compare_value = NS(SCInterpolatedProfile_compare_values)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
                             ( ptr_belem_t )( uintptr_t )rhs_addr );
 
@@ -677,7 +437,7 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects)(
 
                     case NS(OBJECT_TYPE_BEAM_MONITOR):
                     {
-                        typedef NS(BeamMonitor)                      belem_t;
+                        typedef NS(BeamMonitor) belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const*  ptr_belem_t;
 
                         compare_value = NS(BeamMonitor_compare_values)(
@@ -723,6 +483,18 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects)(
                         break;
                     }
 
+                    case NS(OBJECT_TYPE_TRICUB):
+                    {
+                        typedef NS(TriCub) belem_t;
+                        typedef SIXTRL_BE_ARGPTR_DEC belem_t const*  ptr_belem_t;
+
+                        compare_value = NS(TriCub_compare_values)(
+                            ( ptr_belem_t )( uintptr_t )lhs_addr,
+                            ( ptr_belem_t )( uintptr_t )rhs_addr );
+
+                        break;
+                    }
+
                     default:
                     {
                         compare_value = -1;
@@ -780,8 +552,7 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects_with_treshold)(
 
                         compare_value = NS(Drift_compare_values_with_treshold)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
-                            ( ptr_belem_t )( uintptr_t )rhs_addr,
-                            treshold );
+                            ( ptr_belem_t )( uintptr_t )rhs_addr, treshold );
 
                         break;
                     }
@@ -793,21 +564,32 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects_with_treshold)(
 
                         compare_value = NS(DriftExact_compare_values_with_treshold)(
                             ( ptr_belem_t )( uintptr_t )rhs_addr,
-                            ( ptr_belem_t )( uintptr_t )lhs_addr,
-                            treshold  );
+                            ( ptr_belem_t )( uintptr_t )lhs_addr, treshold  );
 
                         break;
                     }
 
                     case NS(OBJECT_TYPE_MULTIPOLE):
                     {
-                        typedef NS(MultiPole)                       belem_t;
+                        typedef NS(Multipole)                       belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
 
-                        compare_value = NS(MultiPole_compare_values_with_treshold)(
+                        compare_value = NS(Multipole_compare_values_with_treshold)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
-                            ( ptr_belem_t )( uintptr_t )rhs_addr,
-                            treshold  );
+                            ( ptr_belem_t )( uintptr_t )rhs_addr, treshold  );
+
+                        break;
+                    }
+
+                    case NS(OBJECT_TYPE_RF_MULTIPOLE):
+                    {
+                        typedef NS(RFMultipole)                     belem_t;
+                        typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
+
+                        compare_value =
+                        NS(RFMultipole_compare_values_with_treshold)(
+                            ( ptr_belem_t )( uintptr_t )lhs_addr,
+                            ( ptr_belem_t )( uintptr_t )rhs_addr, treshold  );
 
                         break;
                     }
@@ -819,8 +601,7 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects_with_treshold)(
 
                         compare_value = NS(XYShift_compare_values_with_treshold)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
-                            ( ptr_belem_t )( uintptr_t )rhs_addr,
-                            treshold  );
+                            ( ptr_belem_t )( uintptr_t )rhs_addr, treshold  );
 
                         break;
                     }
@@ -832,8 +613,7 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects_with_treshold)(
 
                         compare_value = NS(SRotation_compare_values_with_treshold)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
-                            ( ptr_belem_t )( uintptr_t )rhs_addr,
-                            treshold  );
+                            ( ptr_belem_t )( uintptr_t )rhs_addr, treshold  );
 
                         break;
                     }
@@ -845,8 +625,7 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects_with_treshold)(
 
                         compare_value = NS(Cavity_compare_values_with_treshold)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
-                            ( ptr_belem_t )( uintptr_t )rhs_addr,
-                            treshold  );
+                            ( ptr_belem_t )( uintptr_t )rhs_addr, treshold  );
 
                         break;
                     }
@@ -863,24 +642,24 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects_with_treshold)(
                         break;
                     }
 
-                    case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+                    case NS(OBJECT_TYPE_SC_COASTING):
                     {
-                        typedef NS(SpaceChargeCoasting) belem_t;
+                        typedef NS(SCCoasting) belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
 
-                        compare_value = NS(SpaceChargeCoasting_compare_values)(
+                        compare_value = NS(SCCoasting_compare_values)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
                             ( ptr_belem_t )( uintptr_t )rhs_addr );
 
                         break;
                     }
 
-                    case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+                    case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
                     {
-                        typedef NS(SpaceChargeBunched) belem_t;
+                        typedef NS(SCQGaussProfile) belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
 
-                        compare_value = NS(SpaceChargeBunched_compare_values)(
+                        compare_value = NS(SCQGaussProfile_compare_values)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
                             ( ptr_belem_t )( uintptr_t )rhs_addr );
 
@@ -901,13 +680,12 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects_with_treshold)(
 
                     case NS(OBJECT_TYPE_BEAM_MONITOR):
                     {
-                        typedef NS(BeamMonitor)                          belem_t;
+                        typedef NS(BeamMonitor) belem_t;
                         typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
 
-                        compare_value = NS(BeamMonitor_compare_values_with_treshold)(
+                        compare_value = NS(BeamMonitor_compare_values)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
-                            ( ptr_belem_t )( uintptr_t )rhs_addr,
-                            treshold  );
+                            ( ptr_belem_t )( uintptr_t )rhs_addr  );
 
                         break;
                     }
@@ -946,8 +724,20 @@ SIXTRL_INLINE int NS(BeamElements_compare_objects_with_treshold)(
                         compare_value =
                         NS(DipoleEdge_compare_values_with_treshold)(
                             ( ptr_belem_t )( uintptr_t )lhs_addr,
-                            ( ptr_belem_t )( uintptr_t )rhs_addr,
-                            treshold  );
+                            ( ptr_belem_t )( uintptr_t )rhs_addr, treshold );
+
+                        break;
+                    }
+
+                    case NS(OBJECT_TYPE_TRICUB):
+                    {
+                        typedef NS(TriCub) belem_t;
+                        typedef SIXTRL_BE_ARGPTR_DEC belem_t const* ptr_belem_t;
+
+                        compare_value =
+                        NS(TriCub_compare_values_with_treshold)(
+                            ( ptr_belem_t )( uintptr_t )lhs_addr,
+                            ( ptr_belem_t )( uintptr_t )rhs_addr, treshold );
 
                         break;
                     }
diff --git a/tests/sixtracklib/testlib/common/buffer.c b/tests/sixtracklib/testlib/common/buffer.c
deleted file mode 100644
index d1148c10..00000000
--- a/tests/sixtracklib/testlib/common/buffer.c
+++ /dev/null
@@ -1,250 +0,0 @@
-#if !defined( SIXTRL_NO_INCLUDES )
-    #include "sixtracklib/testlib/common/buffer.h"
-#endif /* !defined( SIXTRL_NO_INCLUDES ) */
-
-#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
-    #include <stddef.h>
-    #include <stdint.h>
-    #include <stdio.h>
-    #include <stdlib.h>
-    #include <string.h>
-#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
-
-#if !defined( SIXTRL_NO_INCLUDES )
-    #include "sixtracklib/testlib/common/particles/particles.h"
-    #include "sixtracklib/testlib/common/beam_elements/beam_elements.h"
-    #include "sixtracklib/common/definitions.h"
-    #include "sixtracklib/common/internal/objects_type_id.h"
-    #include "sixtracklib/common/buffer.h"
-    #include "sixtracklib/common/output/elem_by_elem_config.h"
-#endif /* !defined( SIXTRL_NO_INCLUDES ) */
-
-int NS(Buffer_object_typeid_to_string)(
-    NS(object_type_id_t) const type_id, char* SIXTRL_RESTRICT type_str,
-    NS(buffer_size_t) const max_len )
-{
-    int success = -1;
-
-    typedef NS(buffer_size_t) buf_size_t;
-    buf_size_t const pref_len = strlen( SIXTRL_C99_NAMESPACE_PREFIX_STR ) + 1u;
-
-    if( ( type_str != SIXTRL_NULLPTR ) && ( max_len > pref_len ) )
-    {
-        buf_size_t const len = max_len - 1u;
-
-        memset( type_str, ( int )'\0', max_len );
-
-        success = 0;
-
-        switch( type_id )
-        {
-            case NS(OBJECT_TYPE_NONE):
-            {
-                strncpy( type_str, "None", max_len - 1u );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_PARTICLE):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "Particle", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_DRIFT):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "Drift", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_DRIFT_EXACT):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "DriftExact", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_MULTIPOLE):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "Multipole", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_CAVITY):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "Cavity", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_XYSHIFT):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "XYShift", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_SROTATION):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "SRotation", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_BEAM_BEAM_4D):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "BeamBeam4D", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "BeamBeam6D", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_BEAM_MONITOR):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "BeamMonitor", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_LINE):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "Line", max_len - pref_len );
-                break;
-            }
-
-            case NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF):
-            {
-                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
-                strncat( type_str, "ElemByElemConfig", max_len - pref_len );
-                break;
-            }
-
-            default:
-            {
-                strncpy( type_str, "n/a", max_len - 1u );
-                success = -1;
-            }
-        };
-    }
-
-    return success;
-}
-
-void NS(Buffer_object_print_typeid)( FILE* SIXTRL_RESTRICT fp,
-    NS(object_type_id_t) const type_id )
-{
-    if( fp != SIXTRL_NULLPTR )
-    {
-        char tmp_str[ 64 ];
-
-        if( 0 == NS(Buffer_object_typeid_to_string)(
-                type_id, &tmp_str[ 0 ], 64 ) )
-        {
-            fprintf( fp, "Object type: %s", tmp_str );
-        }
-        else
-        {
-            fprintf( fp, "Object type: n/a" );
-        }
-    }
-
-    return;
-}
-
-void NS(Buffer_object_print_out_typeid)( NS(object_type_id_t) const type_id )
-{
-    NS(Buffer_object_print_typeid)( stdout, type_id );
-    return;
-}
-
-
-
-void NS(Buffer_object_print)( SIXTRL_ARGPTR_DEC FILE* fp,
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj )
-{
-    typedef NS(buffer_addr_t)       address_t;
-    typedef NS(buffer_size_t)       buf_size_t;
-    typedef NS(object_type_id_t)    type_id_t;
-
-    type_id_t  const type_id = NS(Object_get_type_id)( obj );
-    address_t  const addr = NS(Object_get_begin_addr)( obj );
-    buf_size_t const size = NS(Object_get_size)( obj );
-
-    if( ( fp != SIXTRL_NULLPTR ) && ( addr != ( address_t )0u ) &&
-        ( size > ( buf_size_t )0u ) )
-    {
-        fprintf( fp, "address = %11p, size = %6lu Bytes\r\n",
-                 ( void* )( uintptr_t )addr, ( unsigned long )size );
-
-        if( type_id == NS(OBJECT_TYPE_PARTICLE) )
-        {
-            typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles) const* ptr_t;
-            NS(Particles_print)( fp, ( ptr_t )( uintptr_t )addr );
-        }
-        else if( type_id == NS(OBJECT_TYPE_NONE) )
-        {
-            fprintf( fp, "None Object\r\n" );
-        }
-        else if( type_id == NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF) )
-        {
-            typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
-                    ptr_t;
-
-            ptr_t config = ( ptr_t )( uintptr_t )addr;
-            SIXTRL_ASSERT( config != SIXTRL_NULLPTR );
-
-            fprintf( fp, "|elem_config | order            = %16ld ;\r\n"
-                         "             | nparts_to_store  = %16ld ;\r\n"
-                         "             | nelems_to_store  = %16ld ;\r\n"
-                         "             | nturns_to_store  = %16ld ;\r\n"
-                         "             | min_partid       = %16ld ;\r\n"
-                         "             | max_partid       = %16ld ;\r\n"
-                         "             | min_elemid       = %16ld ;\r\n"
-                         "             | max_elemid       = %16ld ;\r\n"
-                         "             | min_turn         = %16ld ;\r\n"
-                         "             | max_turn         = %16ld ;\r\n"
-                         "             | is_rolling       = %16ld ;\r\n"
-                         "             | out_store_addr   = %16p ;\r\n",
-                ( int64_t )NS(ElemByElemConfig_get_order)( config ),
-                ( int64_t )NS(ElemByElemConfig_get_num_particles_to_store)(
-                    config ),
-                ( int64_t )NS(ElemByElemConfig_get_num_elements_to_store)(
-                    config ),
-                ( int64_t )NS(ElemByElemConfig_get_num_turns_to_store)(
-                    config ),
-                ( int64_t )NS(ElemByElemConfig_get_min_particle_id)( config ),
-                ( int64_t )NS(ElemByElemConfig_get_max_particle_id)( config ),
-                ( int64_t )NS(ElemByElemConfig_get_min_element_id)( config ),
-                ( int64_t )NS(ElemByElemConfig_get_max_element_id)( config ),
-                ( int64_t )NS(ElemByElemConfig_get_min_turn)( config ),
-                ( int64_t )NS(ElemByElemConfig_get_max_turn)( config ),
-                config->is_rolling,
-                ( void* )( uintptr_t )config->out_store_addr );
-        }
-        else
-        {
-            NS(BeamElement_print)( fp, obj );
-        }
-    }
-
-    return;
-}
-
-void NS(Buffer_object_print_out)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj )
-{
-    NS(Buffer_object_print)( stdout, obj );
-    return;
-}
-
-
-/* end: tests/sixtracklib/testlib/common/buffer.c */
diff --git a/tests/sixtracklib/testlib/common/buffer.h b/tests/sixtracklib/testlib/common/buffer.h
deleted file mode 100644
index 9dd057e4..00000000
--- a/tests/sixtracklib/testlib/common/buffer.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef SIXTRACKLIB_TESTLIB_COMMON_BUFFER_H__
-#define SIXTRACKLIB_TESTLIB_COMMON_BUFFER_H__
-
-#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
-    #include <stdio.h>
-#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
-
-#if !defined( SIXTRL_NO_INCLUDES )
-    #include "sixtracklib/common/definitions.h"
-    #include "sixtracklib/common/internal/objects_type_id.h"
-    #include "sixtracklib/common/internal/buffer_object_defines.h"
-    #include "sixtracklib/common/buffer/buffer_type.h"
-#endif /* !defined( SIXTRL_NO_INCLUDES ) */
-
-#if !defined( _GPUCODE ) && defined( __cplusplus )
-extern "C" {
-#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
-struct NS(Object);
-
-#if !defined( _GPUCODE )
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_print_out_typeid)(
-    NS(object_type_id_t) const type_id );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN int NS(Buffer_object_typeid_to_string)(
-    NS(object_type_id_t) const type_id,
-    char* SIXTRL_RESTRICT type_str,
-    NS(buffer_size_t) const max_type_str_length );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_print_typeid)(
-    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
-    NS(object_type_id_t) const type_id );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_print)(
-    SIXTRL_ARGPTR_DEC FILE* fp,
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const struct NS(Object) *const
-        SIXTRL_RESTRICT obj );
-
-SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_print_out)(
-    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const struct NS(Object) *const
-        SIXTRL_RESTRICT obj );
-
-#endif /* !defined( _GPUCODE ) */
-
-#if !defined( _GPUCODE ) && defined( __cplusplus )
-}
-#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-
-#endif /* SIXTRACKLIB_TESTLIB_COMMON_BUFFER_H__ */
-
-/* end: tests/sixtracklib/testlib/common/buffer.h */
diff --git a/tests/sixtracklib/testlib/common/buffer/CMakeLists.txt b/tests/sixtracklib/testlib/common/buffer/CMakeLists.txt
new file mode 100644
index 00000000..a4efbbc7
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/buffer/CMakeLists.txt
@@ -0,0 +1,53 @@
+# tests/sixtracklib/testlib/common/buffer/CMakeLists.txt
+
+# -----------------------------------------------------------------------------
+# c99 object library
+
+set( SIXTRL_TESTLIB_COMMON_BUFFER_HEADERS
+     buffer.h generic_buffer_obj.h binary_array_buffer.h assign_address_item.h )
+
+set( SIXTRL_TESTLIB_COMMON_BUFFER_SOURCES
+     buffer.c generic_buffer_obj.c assign_address_item.c )
+
+add_library( sixtrack_test_common_buffer_c99 OBJECT
+             ${SIXTRL_TESTLIB_COMMON_BUFFER_HEADERS}
+             ${SIXTRL_TESTLIB_COMMON_BUFFER_SOURCES} )
+
+target_include_directories( sixtrack_test_common_buffer_c99 PRIVATE
+    PRIVATE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
+    PRIVATE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/tests> )
+
+set_target_properties( sixtrack_test_common_buffer_c99 PROPERTIES
+    LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE ON
+    C_STANDARD 99 C_STANDARD_REQUIRED ON )
+
+target_compile_options( sixtrack_test_common_buffer_c99 PRIVATE
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
+
+# -----------------------------------------------------------------------------
+# cxx object library
+
+set( SIXTRL_TESTLIB_COMMON_BUFFER_CXX_HEADERS )
+set( SIXTRL_TESTLIB_COMMON_BUFFER_CXX_SOURCES )
+
+# -----------------------------------------------------------------------------
+# pass on sixtrack_test_common as a module for sixtrack_test:
+
+set(  SIXTRACKL_TESTLIB_LIBRARY_MODULES ${SIXTRACKL_TESTLIB_LIBRARY_MODULES}
+    $<TARGET_OBJECTS:sixtrack_test_common_buffer_c99> CACHE INTERNAL "" FORCE )
+
+# =============================================================================
+# Install :
+
+if( SIXTRL_TESTLIB_COMMON_BUFFER_HEADERS )
+    install( FILES ${TESTLIB_COMMON_C99_HEADERS}
+             DESTINATION "${SIXTRL_TESTLIB_COMMON_INSTALL_C99_PATH}/buffer" )
+endif()
+
+if( ( SIXTRL_TESTLIB_COMMON_BUFFER_CXX_HEADERS ) AND ( SIXTRACKL_ENABLE_CXX ) )
+    install( FILES ${SIXTRL_TESTLIB_COMMON_BUFFER_CXX_HEADERS}
+             DESTINATION "${SIXTRL_TESTLIB_COMMON_INSTALL_CXX_PATH}/buffer" )
+endif()
+
+#end: tests/sixtracklib/testlib/common/buffer/CMakeLists.txt
diff --git a/tests/sixtracklib/testlib/common/buffer/assign_address_item.c b/tests/sixtracklib/testlib/common/buffer/assign_address_item.c
new file mode 100644
index 00000000..e8ddac12
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/buffer/assign_address_item.c
@@ -0,0 +1,47 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/buffer/assign_address_item.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <string.h>
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+void NS(AssignAddressItem_print)( FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item )
+{
+    if( ( fp != SIXTRL_NULLPTR ) && ( item != SIXTRL_NULLPTR ) )
+    {
+        fprintf( fp,
+                "|assign_address_item: | dest_elem_type_id   = %16d ;\r\n"
+                "                      | dest_buffer_id      = %16d ;\r\n"
+                "                      | dest_elem_index     = %16d ;\r\n"
+                "                      | dest_pointer_offset = %16d ;\r\n"
+                "                      | src_elem_type_id    = %16d ;\r\n"
+                "                      | src_buffer_id       = %16d ;\r\n"
+                "                      | src_elem_index      = %16d ;\r\n"
+                "                      | src_pointer_offset  = %16d ;\r\n",
+                ( int )NS(AssignAddressItem_dest_elem_type_id)( item ),
+                ( int )NS(AssignAddressItem_dest_buffer_id)( item ),
+                ( int )NS(AssignAddressItem_dest_elem_index)( item ),
+                ( int )NS(AssignAddressItem_dest_pointer_offset)( item ),
+                ( int )NS(AssignAddressItem_src_elem_type_id)( item ),
+                ( int )NS(AssignAddressItem_src_buffer_id)( item ),
+                ( int )NS(AssignAddressItem_src_elem_index)( item ),
+                ( int )NS(AssignAddressItem_src_pointer_offset)( item ) );
+    }
+}
+
+void NS(AssignAddressItem_print_out_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item )
+{
+    NS(AssignAddressItem_print)( stdout, item );
+}
diff --git a/tests/sixtracklib/testlib/common/buffer/assign_address_item.h b/tests/sixtracklib/testlib/common/buffer/assign_address_item.h
new file mode 100644
index 00000000..632d226a
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/buffer/assign_address_item.h
@@ -0,0 +1,87 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_C99_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_C99_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/buffer/assign_address_item.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+SIXTRL_STATIC SIXTRL_FN void NS(AssignAddressItem_print_out)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(AssignAddressItem_print)(
+    FILE* SIXTRL_RESTRICT fp, SIXTRL_BUFFER_DATAPTR_DEC const
+        NS(AssignAddressItem) *const SIXTRL_RESTRICT item );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(AssignAddressItem_print_out_ext)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item );
+
+#endif /* !defined( _GPUCODE ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+/* ************************************************************************* */
+/* ****              Inline function implementation                     **** */
+/* ************************************************************************* */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+extern "C" {
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+#if defined( _GPUCODE )
+
+SIXTRL_INLINE void NS(AssignAddressItem_print_out)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item )
+{
+    SIXTRL_ASSERT( item != SIXTRL_NULLPTR );
+    printf( "|assign_address_item: | dest_elem_type_id   = %16d ;\r\n"
+            "                      | dest_buffer_id      = %16d ;\r\n"
+            "                      | dest_elem_index     = %16d ;\r\n"
+            "                      | dest_pointer_offset = %16d ;\r\n"
+            "                      | src_elem_type_id    = %16d ;\r\n"
+            "                      | src_buffer_id       = %16d ;\r\n"
+            "                      | src_elem_index      = %16d ;\r\n"
+            "                      | src_pointer_offset  = %16d ;\r\n",
+            ( int )NS(AssignAddressItem_dest_elem_type_id)( item ),
+            ( int )NS(AssignAddressItem_dest_buffer_id)( item ),
+            ( int )NS(AssignAddressItem_dest_elem_index)( item ),
+            ( int )NS(AssignAddressItem_dest_pointer_offset)( item ),
+            ( int )NS(AssignAddressItem_src_elem_type_id)( item ),
+            ( int )NS(AssignAddressItem_src_buffer_id)( item ),
+            ( int )NS(AssignAddressItem_src_elem_index)( item ),
+            ( int )NS(AssignAddressItem_src_pointer_offset)( item ) );
+}
+
+#else /* defined( _GPUCODE ) */
+
+SIXTRL_INLINE void NS(AssignAddressItem_print_out)(
+    SIXTRL_BUFFER_DATAPTR_DEC const NS(AssignAddressItem)
+        *const SIXTRL_RESTRICT item )
+{
+    NS(AssignAddressItem_print)( stdout, item );
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+#if defined( __cplusplus ) && !defined( _GPUCODE )
+}
+#endif /* defined( __cplusplus ) && !defined( _GPUCODE ) */
+
+#endif /*define SIXTRACKLIB_TESTLIB_COMMON_BUFFER_ASSIGN_ADDRESS_ITEM_C99_H__*/
diff --git a/tests/sixtracklib/testlib/common/buffer/binary_array_buffer.h b/tests/sixtracklib/testlib/common/buffer/binary_array_buffer.h
new file mode 100644
index 00000000..c0c89461
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/buffer/binary_array_buffer.h
@@ -0,0 +1,72 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BUFFER_BINARY_ARRAY_BUFFER_C99_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BUFFER_BINARY_ARRAY_BUFFER_C99_H__
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/internal/binary_array_buffer.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stdbool.h>
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <limits.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_STATIC SIXTRL_FN void NS(BinaryArray_print_out)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj );
+
+#if !defined( GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(BinaryArray_print)(
+    FILE* SIXTRL_RESTRICT fp,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj );
+
+#endif /* !defined( GPUCODE ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+#if !defined( _GPUCODE )
+
+void NS(BinaryArray_print_out)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj )
+{
+    NS(BinaryArray_print)( stdout, obj );
+}
+
+#else
+
+void NS(BinaryArray_print_out)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj )
+{
+    NS(BinaryArray_print)( stdout, obj );
+}
+
+#endif /* !defined _GPUCODE */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BUFFER_BINARY_ARRAY_BUFFER_C99_H__ */
+/* end: tests/sixtracklib/testlib/common/buffer/binary_array_buffer.h */
diff --git a/tests/sixtracklib/testlib/common/buffer/buffer.c b/tests/sixtracklib/testlib/common/buffer/buffer.c
new file mode 100644
index 00000000..e369aebc
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/buffer/buffer.c
@@ -0,0 +1,370 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/buffer/buffer.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <stdio.h>
+    #include <stdlib.h>
+    #include <string.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/particles/particles.h"
+    #include "sixtracklib/testlib/common/beam_elements/beam_elements.h"
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/objects_type_id.h"
+    #include "sixtracklib/common/buffer.h"
+    #include "sixtracklib/common/output/elem_by_elem_config.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+
+void NS(Buffer_object_print_out_typeid_ext)(
+    NS(object_type_id_t) const type_id )
+{
+    NS(Buffer_object_print_out_typeid)( type_id );
+}
+
+void NS(Buffer_object_print_out_ext)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC const
+    struct NS(Object) *const SIXTRL_RESTRICT obj )
+{
+    NS(Buffer_object_print_out)( obj );
+}
+
+
+void NS(Buffer_object_typeid_to_string)( NS(object_type_id_t) const type_id,
+    char* SIXTRL_RESTRICT type_str, NS(buffer_size_t) const max_len )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+
+    buf_size_t const pref_len =
+        strlen( SIXTRL_C99_NAMESPACE_PREFIX_STR ) + 1u;
+
+    if( ( type_str != SIXTRL_NULLPTR ) && ( max_len > pref_len ) )
+    {
+        buf_size_t const len = max_len - 1u;
+        memset( type_str, ( int )'\0', max_len );
+
+        switch( type_id )
+        {
+            case NS(OBJECT_TYPE_NONE):
+            {
+                strncpy( type_str, "None", max_len - 1u );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_PARTICLE):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Particle", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_DRIFT):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Drift", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_DRIFT_EXACT):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "DriftExact", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_MULTIPOLE):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Multipole", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_CAVITY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Cavity", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_XYSHIFT):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "XYShift", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_SROTATION):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "SRotation", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_BEAM_BEAM_4D):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "BeamBeam4D", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "BeamBeam6D", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_BEAM_MONITOR):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "BeamMonitor", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_LIMIT_RECT):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "LimitRect", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_LIMIT_ELLIPSE):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "LimitEllipse", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_SC_COASTING):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "SpaceChargeCoasting", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_SC_QGAUSSIAN_PROF):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "SpaceChargeQGaussianProfile",
+                         max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_SC_INTERPOLATED_PROF):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "SpaceChargeInterpolatedProfile",
+                         max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_DIPEDGE):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "DipoleEdge", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_PARTICLES_ADDR):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "ParticlesAddr", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "AssignAddressItem", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_LINE):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Line", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_BINARY_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "BinaryArray", max_len - pref_len );
+                break;
+            }
+
+            /*
+            case NS(OBJECT_TYPE_REAL_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "RealArray", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_FLOAT32_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Float32Array", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_UINT64_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "UInt64Array", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_INT64_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Int64Array", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_UINT32_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "UInt32Array", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_INT32_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Int32Array", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_UINT16_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "UInt16Array", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_INT16_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Int16Array", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_INT8_ARRAY):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "Int8Array", max_len - pref_len );
+                break;
+            }
+            */
+
+            case NS(OBJECT_TYPE_CSTRING):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "CString", max_len - pref_len );
+                break;
+            }
+
+            case NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF):
+            {
+                strncpy( type_str, SIXTRL_C99_NAMESPACE_PREFIX_STR, len );
+                strncat( type_str, "ElemByElemConfig", max_len - pref_len );
+                break;
+            }
+
+            default:
+            {
+                strncpy( type_str, "n/a", max_len - 1u );
+            }
+        };
+    }
+}
+
+void NS(Buffer_object_print_typeid)( FILE* SIXTRL_RESTRICT fp,
+    NS(object_type_id_t) const type_id )
+{
+    if( fp != SIXTRL_NULLPTR )
+    {
+        char tmp_str[ 64 ];
+        NS(Buffer_object_typeid_to_string)( type_id, &tmp_str[ 0 ], 64 );
+        fprintf( fp, "Object type: %s", tmp_str );
+    }
+}
+
+void NS(Buffer_object_print)( SIXTRL_ARGPTR_DEC FILE* fp,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const NS(Object) *const SIXTRL_RESTRICT obj )
+{
+    typedef NS(buffer_size_t)    buf_size_t;
+    typedef NS(buffer_addr_t)    address_t;
+    typedef NS(object_type_id_t) type_id_t;
+
+    type_id_t  const type_id = NS(Object_get_type_id)( obj );
+    address_t  const addr = NS(Object_get_begin_addr)( obj );
+    buf_size_t const size = NS(Object_get_size)( obj );
+
+    if( ( fp != SIXTRL_NULLPTR ) && ( addr != ( address_t )0u ) &&
+        ( size > ( buf_size_t )0u ) )
+    {
+        fprintf( fp, "address = %11p, size = %6lu Bytes\r\n",
+                 ( void* )( uintptr_t )addr, ( unsigned long )size );
+
+        if( type_id == NS(OBJECT_TYPE_PARTICLE) )
+        {
+            typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles) const* ptr_t;
+            NS(Particles_print)( fp, ( ptr_t )( uintptr_t )addr );
+        }
+        else if( type_id == NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF) )
+        {
+            typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC
+                NS(ElemByElemConfig)* ptr_t;
+
+            ptr_t config = ( ptr_t )( uintptr_t )addr;
+            SIXTRL_ASSERT( config != SIXTRL_NULLPTR );
+
+            fprintf( fp, "|elem_config | order            = %16ld ;\r\n"
+                         "             | nparts_to_store  = %16ld ;\r\n"
+                         "             | nelems_to_store  = %16ld ;\r\n"
+                         "             | nturns_to_store  = %16ld ;\r\n"
+                         "             | min_partid       = %16ld ;\r\n"
+                         "             | max_partid       = %16ld ;\r\n"
+                         "             | min_elemid       = %16ld ;\r\n"
+                         "             | max_elemid       = %16ld ;\r\n"
+                         "             | min_turn         = %16ld ;\r\n"
+                         "             | max_turn         = %16ld ;\r\n"
+                         "             | is_rolling       = %16ld ;\r\n"
+                         "             | out_store_addr   = %16p ;\r\n",
+            ( int64_t )NS(ElemByElemConfig_get_order)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_num_particles_to_store)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_num_elements_to_store)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_num_turns_to_store)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_min_particle_id)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_max_particle_id)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_min_element_id)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_max_element_id)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_min_turn)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_max_turn)( config ),
+            config->is_rolling,
+            ( void* )( uintptr_t )config->out_store_addr );
+        }
+        else if( ( type_id >= NS(OBJECT_TYPE_BINARY_ARRAY) ) &&
+                 ( type_id <= NS(OBJECT_TYPE_CSTRING) ) )
+        {
+            printf( "TODO\r\n" );
+        }
+        else if( type_id == NS(OBJECT_TYPE_NONE) )
+        {
+            printf( "None Object\r\n" );
+        }
+        else
+        {
+            NS(BeamElement_print)( fp, obj );
+        }
+    }
+
+    return;
+}
+
+/* end: tests/sixtracklib/testlib/common/buffer/buffer.c */
diff --git a/tests/sixtracklib/testlib/common/buffer/buffer.h b/tests/sixtracklib/testlib/common/buffer/buffer.h
new file mode 100644
index 00000000..a5d82730
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/buffer/buffer.h
@@ -0,0 +1,362 @@
+#ifndef SIXTRACKLIB_TESTLIB_COMMON_BUFFER_H__
+#define SIXTRACKLIB_TESTLIB_COMMON_BUFFER_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stdio.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/control/definitions.h"
+    #include "sixtracklib/common/internal/objects_type_id.h"
+    #include "sixtracklib/common/internal/buffer_object_defines.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+struct NS(Object);
+
+SIXTRL_STATIC SIXTRL_FN void NS(Buffer_object_print_out_typeid)(
+    NS(object_type_id_t) const type_id );
+
+SIXTRL_STATIC SIXTRL_FN void NS(Buffer_object_print_out)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const struct NS(Object) *const
+        SIXTRL_RESTRICT obj );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_print_out_typeid_ext)(
+    NS(object_type_id_t) const type_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_print_out_ext)(
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const struct NS(Object) *const
+        SIXTRL_RESTRICT obj );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_print_typeid)(
+    SIXTRL_ARGPTR_DEC FILE* SIXTRL_RESTRICT fp,
+    NS(object_type_id_t) const type_id );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_typeid_to_string)(
+    NS(object_type_id_t) const type_id,
+    char* SIXTRL_RESTRICT type_str,
+    NS(buffer_size_t) const max_type_str_length );
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(Buffer_object_print)(
+    SIXTRL_ARGPTR_DEC FILE* fp,
+    SIXTRL_BUFFER_OBJ_ARGPTR_DEC const struct NS(Object) *const
+        SIXTRL_RESTRICT obj );
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+/* ************************************************************************ */
+/* ************************************************************************ */
+
+#if !defined( _GPUCODE )
+    #include <stdio.h>
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE void NS(Buffer_object_print_out_typeid)(
+    NS(object_type_id_t) const type_id )
+{
+    NS(Buffer_object_print_typeid)( stdout, type_id );
+}
+
+SIXTRL_INLINE void NS(Buffer_object_print_out)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    const struct NS(Object) *const SIXTRL_RESTRICT obj )
+{
+    NS(Buffer_object_print)( stdout, obj );
+}
+
+#else  /*  defined( _GPUCODE ) */
+
+SIXTRL_INLINE void NS(Buffer_object_print_out_typeid)(
+    NS(object_type_id_t) const type_id )
+{
+    switch( type_id )
+    {
+        case NS(OBJECT_TYPE_NONE):
+        {
+            printf( "None" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_PARTICLE):
+        {
+            printf( "ParticleSet" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_DRIFT):
+        {
+            printf( "Drift" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_DRIFT_EXACT):
+        {
+            printf( "DriftExact" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_MULTIPOLE):
+        {
+            printf( "Multipole" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_CAVITY):
+        {
+            printf( "Cavity" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_XYSHIFT):
+        {
+            printf( "XYShift" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_SROTATION):
+        {
+            printf( "SRotation" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_BEAM_BEAM_4D):
+        {
+            printf( "BeamBeam4D" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_BEAM_BEAM_6D):
+        {
+            printf( "BeamBeam6D" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_BEAM_MONITOR):
+        {
+            printf( "BeamMonitor" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_LIMIT_RECT):
+        {
+            printf( "LimitRect" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_LIMIT_ELLIPSE):
+        {
+            printf( "LimitEllipse" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_SPACE_CHARGE_COASTING):
+        {
+            printf( "SpaceChargeCoasting" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_SPACE_CHARGE_BUNCHED):
+        {
+            printf( "SpaceChargeBunched" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_DIPEDGE):
+        {
+            printf( "DipoleEdge" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_PARTICLES_ADDR):
+        {
+            printf( "ParticlesAddr" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_ASSIGN_ADDRESS_ITEM):
+        {
+            printf( "AssignAddressItem" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_LINE):
+        {
+            printf( "Line" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_BINARY_ARRAY):
+        {
+            printf( "BinaryArray" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_REAL_ARRAY):
+        {
+            printf( "RealArray" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_FLOAT32_ARRAY):
+        {
+            printf( "Float32Array" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_UINT64_ARRAY):
+        {
+            printf( "UInt64Array" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_INT64_ARRAY):
+        {
+            printf( "Int64Array" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_UINT32_ARRAY):
+        {
+            printf( "UInt32Array" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_INT32_ARRAY):
+        {
+            printf( "Int32Array" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_UINT16_ARRAY):
+        {
+            printf( "UInt16Array" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_INT16_ARRAY):
+        {
+            printf( "Int16Array" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_INT8_ARRAY):
+        {
+            printf( "Int8Array" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_CSTRING):
+        {
+            printf( "CString" );
+            break;
+        }
+
+        case NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF):
+        {
+            printf( "ElemByElemConfig" );
+            break;
+        }
+
+        default:
+        {
+            printf( "n/a" );
+        }
+    };
+}
+
+SIXTRL_INLINE void NS(Buffer_object_print_out)( SIXTRL_BUFFER_OBJ_ARGPTR_DEC
+    const struct NS(Object) *const SIXTRL_RESTRICT obj )
+{
+    typedef NS(buffer_addr_t) address_t;
+    typedef NS(buffer_size_t) buf_size_t;
+    typedef NS(object_type_id_t) type_id_t;
+
+    type_id_t  const type_id = NS(Object_get_type_id)( obj );
+    address_t  const addr    = NS(Object_get_begin_addr)( obj );
+    buf_size_t const size    = NS(Object_get_size)( obj );
+
+    if( ( addr != ( address_t )0u ) && ( size > ( buf_size_t )0u ) )
+    {
+        printf( "address = %11p, size = %6lu Bytes\r\n",
+                ( void* )( uintptr_t )addr, ( unsigned long )size );
+
+        if( type_id == NS(OBJECT_TYPE_PARTICLE) )
+        {
+            typedef SIXTRL_PARTICLE_ARGPTR_DEC NS(Particles) const* ptr_t;
+            NS(Particles_print_out)( ( ptr_t )( uintptr_t )addr );
+        }
+        else if( type_id == NS(OBJECT_TYPE_ELEM_BY_ELEM_CONF) )
+        {
+            typedef SIXTRL_ELEM_BY_ELEM_CONFIG_ARGPTR_DEC NS(ElemByElemConfig)*
+                    ptr_t;
+
+            ptr_t config = ( ptr_t )( uintptr_t )addr;
+            SIXTRL_ASSERT( config != SIXTRL_NULLPTR );
+
+            printf( "|elem_config | order            = %16ld ;\r\n"
+                    "             | nparts_to_store  = %16ld ;\r\n"
+                    "             | nelems_to_store  = %16ld ;\r\n"
+                    "             | nturns_to_store  = %16ld ;\r\n"
+                    "             | min_partid       = %16ld ;\r\n"
+                    "             | max_partid       = %16ld ;\r\n"
+                    "             | min_elemid       = %16ld ;\r\n"
+                    "             | max_elemid       = %16ld ;\r\n"
+                    "             | min_turn         = %16ld ;\r\n"
+                    "             | max_turn         = %16ld ;\r\n"
+                    "             | is_rolling       = %16ld ;\r\n"
+                    "             | out_store_addr   = %16p ;\r\n",
+            ( int64_t )NS(ElemByElemConfig_get_order)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_num_particles_to_store)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_num_elements_to_store)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_num_turns_to_store)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_min_particle_id)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_max_particle_id)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_min_element_id)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_max_element_id)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_min_turn)( config ),
+            ( int64_t )NS(ElemByElemConfig_get_max_turn)( config ),
+            config->is_rolling,
+            ( void* )( uintptr_t )config->out_store_addr );
+        }
+        else if( ( type_id >= NS(OBJECT_TYPE_BINARY_ARRAY) ) &&
+                 ( type_id <= NS(OBJECT_TYPE_CSTRING) ) )
+        {
+            printf( "TODO\r\n" );
+        }
+        else if( type_id == NS(OBJECT_TYPE_NONE) )
+        {
+            printf( "None Object\r\n" );
+        }
+        else
+        {
+            NS(BeamElement_print)( fp, obj );
+        }
+    }
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
+
+#endif /* SIXTRACKLIB_TESTLIB_COMMON_BUFFER_H__ */
+
+/* end: tests/sixtracklib/testlib/common/buffer.h */
diff --git a/tests/sixtracklib/testlib/common/buffer/generic_buffer_obj.c b/tests/sixtracklib/testlib/common/buffer/generic_buffer_obj.c
new file mode 100644
index 00000000..25538d65
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/buffer/generic_buffer_obj.c
@@ -0,0 +1,82 @@
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/testlib/common/buffer/generic_buffer_obj.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/testlib/common/random.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE )
+
+void NS(GenericObj_init_random)( SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj)* obj )
+{
+    typedef SIXTRL_UINT8_T    u8_t;
+    typedef SIXTRL_INT32_T   i32_t;
+    typedef SIXTRL_UINT64_T  u64_t;
+    typedef SIXTRL_REAL_T   real_t;
+
+    if( obj != SIXTRL_NULLPTR )
+    {
+        u64_t const num_d_elements = obj->num_d;
+        u64_t const num_e_elements = obj->num_e;
+
+        i32_t const MIN_A     = INT32_C( -131072 );
+        i32_t const MAX_A     = INT32_C( +131072 );
+        i32_t const DELTA_A   = MAX_A - MIN_A;
+
+        real_t const MIN_B    = ( real_t )-10.0;
+        real_t const MAX_B    = ( real_t )+10.0;
+        real_t const DELTA_B  = MAX_B - MIN_B;
+
+        real_t const MIN_C    = ( real_t )0.0;
+        real_t const MAX_C    = ( real_t )1.0;
+        real_t const DELTA_C  = MAX_C - MIN_C;
+
+        u8_t const MIN_D      = ( u8_t )0x01;
+        u8_t const MAX_D      = ( u8_t )0x10;
+        u8_t const DELTA_D    = MAX_D - MIN_D;
+
+        real_t const MIN_E    = ( real_t )0.0;
+        real_t const MAX_E    = ( real_t )1024.0;
+        real_t const DELTA_E  = MAX_E - MIN_E;
+
+        obj->a = MIN_A + DELTA_A * ( i32_t )NS(Random_genrand64_real1)();
+        obj->b = MIN_B + DELTA_B * NS(Random_genrand64_real1)();
+
+        obj->c[ 0 ] = MIN_C + DELTA_C * NS(Random_genrand64_real1)();
+        obj->c[ 1 ] = MIN_C + DELTA_C * NS(Random_genrand64_real1)();
+        obj->c[ 2 ] = MIN_C + DELTA_C * NS(Random_genrand64_real1)();
+        obj->c[ 3 ] = MIN_C + DELTA_C * NS(Random_genrand64_real1)();
+
+        if( ( num_d_elements > ( u64_t )0 ) && ( obj->d != SIXTRL_NULLPTR ) )
+        {
+            u64_t ii = ( u64_t )0u;
+
+            for( ; ii < num_d_elements ; ++ii )
+            {
+                obj->d[ ii ] = MIN_D +
+                    DELTA_D * ( u8_t )NS(Random_genrand64_real1)();
+            }
+        }
+
+        if( ( num_e_elements > ( u64_t )0 ) && ( obj->e != SIXTRL_NULLPTR ) )
+        {
+            u64_t ii = ( u64_t )0u;
+
+            for( ; ii < num_e_elements ; ++ii )
+            {
+                obj->e[ ii ] = MIN_E + DELTA_E * NS(Random_genrand64_real1)();
+            }
+        }
+    }
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+/* end: tests/sixtracklib/testlib/common/generic_buffer_obj.c */
diff --git a/tests/sixtracklib/testlib/common/buffer/generic_buffer_obj.h b/tests/sixtracklib/testlib/common/buffer/generic_buffer_obj.h
new file mode 100644
index 00000000..ed5faf9f
--- /dev/null
+++ b/tests/sixtracklib/testlib/common/buffer/generic_buffer_obj.h
@@ -0,0 +1,617 @@
+#ifndef SIXTRACKLIB_TESTS_TESTLIB_GENERIC_BUFFER_H__
+#define SIXTRACKLIB_TESTS_TESTLIB_GENERIC_BUFFER_H__
+
+#if !defined( SIXTRL_NO_SYSTEM_INCLUDES )
+    #include <stdbool.h>
+    #include <stddef.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <limits.h>
+#endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
+
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/definitions.h"
+    #include "sixtracklib/common/internal/buffer_main_defines.h"
+    #include "sixtracklib/common/buffer/buffer_object.h"
+    #include "sixtracklib/common/buffer/buffer_type.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+typedef struct NS(GenericObj)
+{
+    NS(object_type_id_t) type_id                         SIXTRL_ALIGN( 8u );
+    SIXTRL_INT32_T a                                     SIXTRL_ALIGN( 8u );
+    SIXTRL_REAL_T b                                      SIXTRL_ALIGN( 8u );
+    SIXTRL_REAL_T c[ 4 ]                                 SIXTRL_ALIGN( 8u );
+
+    SIXTRL_UINT64_T num_d                                SIXTRL_ALIGN( 8u );
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_UINT8_T*
+        SIXTRL_RESTRICT d                                SIXTRL_ALIGN( 8u );
+
+    SIXTRL_UINT64_T num_e                                SIXTRL_ALIGN( 8u );
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*
+        SIXTRL_RESTRICT e                                SIXTRL_ALIGN( 8u );
+}
+NS(GenericObj);
+
+SIXTRL_STATIC SIXTRL_FN int NS(GenericObj_compare_values)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* SIXTRL_RESTRICT lhs,
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* SIXTRL_RESTRICT rhs );
+
+SIXTRL_STATIC SIXTRL_FN int NS(GenericObj_compare_values_with_treshold)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* SIXTRL_RESTRICT lhs,
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(GenericObj_predict_required_num_dataptrs)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const num_d_values,
+    NS(buffer_size_t) const num_e_values );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(GenericObj_predict_required_num_slots)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const num_d_values,
+    NS(buffer_size_t) const num_e_values );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(GenericObj_predict_required_num_dataptrs_on_managed_buffer)(
+    NS(buffer_size_t) const num_d_values,
+    NS(buffer_size_t) const num_e_values, NS(buffer_size_t) const slot_size );
+
+SIXTRL_STATIC SIXTRL_FN NS(buffer_size_t)
+NS(GenericObj_predict_required_num_slots_on_managed_buffer)(
+    NS(buffer_size_t) const num_d_values,
+    NS(buffer_size_t) const num_e_values, NS(buffer_size_t) const slot_size );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj)*
+    NS(GenericObj_new)(
+    SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(object_type_id_t) const type_id,
+    NS(buffer_size_t) const num_d_values,
+    NS(buffer_size_t) const num_e_values );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj)*
+    NS(GenericObj_add)(
+    SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(object_type_id_t) const type_id,
+    NS(buffer_size_t) const num_d_values,
+    NS(buffer_size_t) const num_e_values,
+    SIXTRL_INT32_T const a_value, SIXTRL_REAL_T const b_value,
+    SIXTRL_ARGPTR_DEC  SIXTRL_REAL_T const* SIXTRL_RESTRICT c_values,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_UINT8_T* SIXTRL_RESTRICT d_values,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*  SIXTRL_RESTRICT e_values );
+
+SIXTRL_STATIC SIXTRL_FN SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj)*
+    NS(GenericObj_add_copy)(
+        SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+        SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* original );
+
+#if !defined( _GPUCODE )
+
+SIXTRL_EXTERN SIXTRL_HOST_FN void NS(GenericObj_init_random)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj)* obj );
+
+#endif /* !defined( _GPUCODE ) */
+
+
+#if defined( __cplusplus )
+
+namespace SIXTRL_CXX_NAMESPACE
+{
+    using GenericObj = ::NS(GenericObj);
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+#endif /* defined( __cplusplus ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+#if !defined( _GPUCODE )
+#if !defined( SIXTRL_NO_INCLUDES )
+    #include "sixtracklib/common/buffer.h"
+#endif /* !defined( SIXTRL_NO_INCLUDES ) */
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+extern "C" {
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+#if !defined( _GPUCODE )
+
+SIXTRL_INLINE NS(buffer_size_t) NS(GenericObj_predict_required_num_dataptrs)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const num_d_vals, NS(buffer_size_t) const num_e_vals )
+{
+    return NS(GenericObj_predict_required_num_dataptrs_on_managed_buffer)(
+        num_d_vals, num_e_vals, NS(Buffer_get_slot_size)( buffer ) );
+}
+
+SIXTRL_INLINE NS(buffer_size_t) NS(GenericObj_predict_required_num_slots)(
+    SIXTRL_BUFFER_ARGPTR_DEC const NS(Buffer) *const SIXTRL_RESTRICT buffer,
+    NS(buffer_size_t) const num_d_vals, NS(buffer_size_t) const num_e_vals )
+{
+    return NS(GenericObj_predict_required_num_slots_on_managed_buffer)(
+        num_d_vals, num_e_vals, NS(Buffer_get_slot_size)( buffer ) );
+}
+
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(GenericObj_predict_required_num_dataptrs_on_managed_buffer)(
+    NS(buffer_size_t) const num_d_vals, NS(buffer_size_t) const num_e_vals,
+    NS(buffer_size_t) const slot_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+
+    ( void )num_d_vals;
+    ( void )num_e_vals;
+    ( void )slot_size;
+
+    return ( buf_size_t )2u;
+}
+
+SIXTRL_INLINE NS(buffer_size_t)
+NS(GenericObj_predict_required_num_slots_on_managed_buffer)(
+    NS(buffer_size_t) const num_d_vals, NS(buffer_size_t) const num_e_vals,
+    NS(buffer_size_t) const slot_size )
+{
+    typedef NS(buffer_size_t) buf_size_t;
+
+    buf_size_t const num_dataptrs =
+        NS(GenericObj_predict_required_num_dataptrs_on_managed_buffer)(
+            num_d_vals, num_e_vals, slot_size );
+
+    SIXTRL_ASSERT( num_dataptrs == ( buf_size_t )2u );
+
+    buf_size_t const sizes[]  =
+    {
+        sizeof( SIXTRL_UINT8_T ), sizeof( SIXTRL_REAL_T )
+    };
+
+    buf_size_t const counts[] =
+    {
+        num_d_vals, num_e_vals
+    };
+
+    return NS(ManagedBuffer_predict_required_num_slots)(
+        SIXTRL_NULLPTR, sizeof( NS(GenericObj) ), num_dataptrs,
+            sizes, counts, slot_size );
+}
+
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj)* NS(GenericObj_new)(
+    SIXTRL_ARGPTR_DEC struct NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(object_type_id_t) const type_id,
+    NS(buffer_size_t)    const num_d_values,
+    NS(buffer_size_t)    const num_e_values )
+{
+    typedef NS(buffer_size_t)                   buf_size_t;
+    typedef SIXTRL_ARGPTR_DEC NS(GenericObj)*   ptr_gen_obj_t;
+
+    ptr_gen_obj_t ptr_gen_obj  = SIXTRL_NULLPTR;
+
+    if( ( num_d_values > ( buf_size_t )0u ) &&
+        ( num_e_values > ( buf_size_t )0u ) )
+    {
+        buf_size_t const offsets[] =
+        {
+            offsetof( NS(GenericObj), d ),
+            offsetof( NS(GenericObj), e )
+        };
+
+        buf_size_t const sizes[]  = { sizeof( SIXTRL_UINT8_T ), sizeof( SIXTRL_REAL_T ) };
+        buf_size_t const counts[] = { num_d_values, num_e_values };
+
+        NS(GenericObj) temp;
+        memset( &temp, ( int )0, sizeof( temp ) );
+
+        temp.type_id = type_id;
+        temp.a       = ( SIXTRL_INT32_T )0;
+        temp.b       = ( SIXTRL_REAL_T )0.0;
+
+        temp.c[ 0 ]  =
+        temp.c[ 1 ]  =
+        temp.c[ 2 ]  =
+        temp.c[ 3 ]  = ( SIXTRL_REAL_T )0.0;
+
+        temp.num_d = num_d_values;
+        temp.d     = SIXTRL_NULLPTR;
+
+        temp.num_e = num_e_values;
+        temp.e     = SIXTRL_NULLPTR;
+
+        ptr_gen_obj = ( ptr_gen_obj_t )( uintptr_t )NS(Object_get_begin_addr)(
+            NS(Buffer_add_object)( buffer, &temp, sizeof( temp ), temp.type_id,
+            ( buf_size_t )2u, offsets, sizes, counts ) );
+    }
+
+    return ptr_gen_obj;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj)* NS(GenericObj_add)(
+    SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+    NS(object_type_id_t) const type_id,
+    NS(buffer_size_t) const num_d_values,
+    NS(buffer_size_t) const num_e_values,
+    SIXTRL_INT32_T const a_value, SIXTRL_REAL_T const b_value,
+    SIXTRL_ARGPTR_DEC  SIXTRL_REAL_T const* SIXTRL_RESTRICT c_values,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_UINT8_T* SIXTRL_RESTRICT d_values,
+    SIXTRL_BUFFER_DATAPTR_DEC SIXTRL_REAL_T*  SIXTRL_RESTRICT e_values )
+{
+    typedef NS(buffer_size_t)                   buf_size_t;
+    typedef SIXTRL_ARGPTR_DEC NS(GenericObj)*   ptr_gen_obj_t;
+
+    ptr_gen_obj_t ptr_gen_obj  = SIXTRL_NULLPTR;
+
+    if( ( num_d_values > ( buf_size_t )0u ) &&
+        ( num_e_values > ( buf_size_t )0u ) )
+    {
+        buf_size_t const offsets[] =
+        {
+            offsetof( NS(GenericObj), d ),
+            offsetof( NS(GenericObj), e )
+        };
+
+        buf_size_t const sizes[]  =
+        {
+            sizeof( SIXTRL_UINT8_T ),
+            sizeof( SIXTRL_REAL_T )
+        };
+
+        buf_size_t const counts[] = { num_d_values, num_e_values };
+
+        NS(GenericObj) temp;
+        memset( &temp, ( int )0, sizeof( temp ) );
+
+        temp.type_id = type_id;
+        temp.a       = a_value;
+        temp.b       = b_value;
+
+        if( c_values != SIXTRL_NULLPTR )
+        {
+            memcpy( &temp.c[ 0 ], c_values, sizeof( SIXTRL_REAL_T ) * 4 );
+        }
+        else
+        {
+            temp.c[ 0 ] = temp.c[ 1 ]  =
+            temp.c[ 2 ] = temp.c[ 3 ]  = ( SIXTRL_REAL_T )0.0;
+        }
+
+        temp.num_d = num_d_values;
+        temp.d     = d_values;
+
+        temp.num_e = num_e_values;
+        temp.e     = e_values;
+
+        ptr_gen_obj = ( ptr_gen_obj_t )( uintptr_t )NS(Object_get_begin_addr)(
+            NS(Buffer_add_object)( buffer, &temp, sizeof( temp ), temp.type_id,
+            ( buf_size_t )2u, offsets, sizes, counts ) );
+    }
+
+    return ptr_gen_obj;
+}
+
+SIXTRL_INLINE SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj)* NS(GenericObj_add_copy)(
+        SIXTRL_ARGPTR_DEC NS(Buffer)* SIXTRL_RESTRICT buffer,
+        SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* original )
+{
+    if( original != SIXTRL_NULLPTR )
+    {
+        return NS(GenericObj_add)( buffer,
+            original->type_id, original->num_d, original->num_e,
+            original->a, original->b, &original->c[ 0 ],
+            original->d, original->e );
+    }
+
+    return SIXTRL_NULLPTR;
+}
+
+#endif /* !defined( _GPUCODE ) */
+
+#if !defined( _GPUCODE ) && defined( __cplusplus )
+}
+#endif /* !defined( _GPUCODE ) && defined( __cplusplus ) */
+
+SIXTRL_INLINE int NS(GenericObj_compare_values)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* SIXTRL_RESTRICT lhs,
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* SIXTRL_RESTRICT rhs )
+{
+    int cmp_result = -1;
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        if( lhs->type_id == rhs->type_id )
+        {
+            cmp_result = 0;
+        }
+        else if( lhs->type_id > rhs->type_id )
+        {
+            return -1;
+        }
+        else
+        {
+            return +1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->num_d != rhs->num_d ) )
+        {
+            if( lhs->num_d > rhs->num_d )
+            {
+                cmp_result = -1;
+            }
+            else if( lhs->num_d < rhs->num_d )
+            {
+                cmp_result = +1;
+            }
+
+            SIXTRL_ASSERT( ( cmp_result != 0 ) ||
+                ( ( lhs->d != SIXTRL_NULLPTR ) &&
+                  ( rhs->d != SIXTRL_NULLPTR ) ) );
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->num_e != rhs->num_e ) )
+        {
+            if( lhs->num_e > rhs->num_e )
+            {
+                cmp_result = -1;
+            }
+            else if( lhs->num_e < rhs->num_e )
+            {
+                cmp_result = +1;
+            }
+
+            SIXTRL_ASSERT( ( cmp_result != 0 ) ||
+                ( ( lhs->e != SIXTRL_NULLPTR ) &&
+                  ( rhs->e != SIXTRL_NULLPTR ) ) );
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->a != rhs->a ) )
+        {
+            if( lhs->a > rhs->a ) cmp_result = -1;
+            else if( lhs->a < rhs->a ) cmp_result = +1;
+        }
+
+        if( cmp_result == 0 )
+        {
+            if( lhs->b > rhs->b )
+            {
+                cmp_result = -1;
+            }
+            else if( lhs->b > rhs->b )
+            {
+                cmp_result = +1;
+            }
+        }
+
+        if( cmp_result == 0 )
+        {
+            int ii = 0;
+
+            for( ; ii < 4 ; ++ii )
+            {
+                if( lhs->c[ ii ] > rhs->c[ ii ] )
+                {
+                    cmp_result = -1;
+                }
+                else if( lhs->c[ ii ] < rhs->c[ ii ] )
+                {
+                    cmp_result = +1;
+                }
+
+                if( cmp_result != 0 ) break;
+            }
+        }
+
+        if( cmp_result == 0 )
+        {
+            SIXTRL_UINT64_T ii = 0;
+
+            SIXTRL_ASSERT( ( lhs->num_d == rhs->num_d ) &&
+                ( lhs->d != SIXTRL_NULLPTR ) &&
+                ( rhs->d != SIXTRL_NULLPTR ) );
+
+            for( ; ii < lhs->num_d ; ++ii )
+            {
+                if( lhs->d[ ii ] != rhs->d[ ii ] )
+                {
+                    if( lhs->d[ ii ] > rhs->d[ ii ] ) cmp_result = -1;
+                    else if( lhs->d[ ii ] < rhs->d[ ii ] ) cmp_result = +1;
+
+                    break;
+                }
+            }
+        }
+
+        if( cmp_result == 0 )
+        {
+            SIXTRL_UINT64_T ii = 0;
+
+            SIXTRL_ASSERT( ( lhs->num_e == rhs->num_e ) &&
+                ( lhs->e != SIXTRL_NULLPTR ) &&
+                ( rhs->e != SIXTRL_NULLPTR ) );
+
+            for( ; ii < lhs->num_e ; ++ii )
+            {
+                if( lhs->e[ ii ] > rhs->e[ ii ] )
+                {
+                    cmp_result = -1;
+                }
+                else if( lhs->e[ ii ] < rhs->e[ ii ] )
+                {
+                    cmp_result = +1;
+                }
+
+                if( cmp_result != 0 ) break;
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+SIXTRL_INLINE int NS(GenericObj_compare_values_with_treshold)(
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* SIXTRL_RESTRICT lhs,
+    SIXTRL_BUFFER_DATAPTR_DEC NS(GenericObj) const* SIXTRL_RESTRICT rhs,
+    SIXTRL_REAL_T const treshold )
+{
+    int cmp_result = -1;
+
+    SIXTRL_ASSERT( treshold >= ( SIXTRL_REAL_T )0.0 );
+
+    if( ( lhs != SIXTRL_NULLPTR ) && ( rhs != SIXTRL_NULLPTR ) )
+    {
+        if( lhs->type_id == rhs->type_id )
+        {
+            cmp_result = 0;
+        }
+        else if( lhs->type_id > rhs->type_id )
+        {
+            return -1;
+        }
+        else
+        {
+            return +1;
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->num_d != rhs->num_d ) )
+        {
+            if( lhs->num_d > rhs->num_d )
+            {
+                cmp_result = -1;
+            }
+            else if( lhs->num_d < rhs->num_d )
+            {
+                cmp_result = +1;
+            }
+
+            SIXTRL_ASSERT( ( cmp_result != 0 ) ||
+                ( ( lhs->d != SIXTRL_NULLPTR ) &&
+                  ( rhs->d != SIXTRL_NULLPTR ) ) );
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->num_e != rhs->num_e ) )
+        {
+            if( lhs->num_e > rhs->num_e )
+            {
+                cmp_result = -1;
+            }
+            else if( lhs->num_e < rhs->num_e )
+            {
+                cmp_result = +1;
+            }
+
+            SIXTRL_ASSERT( ( cmp_result != 0 ) ||
+                ( ( lhs->e != SIXTRL_NULLPTR ) &&
+                  ( rhs->e != SIXTRL_NULLPTR ) ) );
+        }
+
+        if( ( cmp_result == 0 ) && ( lhs->a != rhs->a ) )
+        {
+            if( lhs->a > rhs->a )
+            {
+                cmp_result = -1;
+            }
+            else if( lhs->a < rhs->a )
+            {
+                cmp_result = +1;
+            }
+        }
+
+        if( cmp_result == 0 )
+        {
+            SIXTRL_REAL_T const diff = ( lhs->b >= rhs->b )
+                ? ( lhs->b - rhs->b ) : ( rhs->b - lhs->b );
+
+            if( diff > treshold )
+            {
+                cmp_result = ( lhs->b > rhs->b ) ? -1 : +1;
+            }
+        }
+
+        if( cmp_result == 0 )
+        {
+            int ii = 0;
+
+            for( ; ii < 4 ; ++ii )
+            {
+                SIXTRL_REAL_T const diff = ( lhs->c[ ii ] >= rhs->c[ ii ] )
+                    ? ( lhs->c[ ii ] - rhs->c[ ii ] )
+                    : ( rhs->c[ ii ] - lhs->c[ ii ] );
+
+                if( diff > treshold )
+                {
+                    cmp_result = ( lhs->c[ ii ] > rhs->c[ ii ] ) ? -1 : +1;
+                }
+
+                if( cmp_result != 0 ) break;
+            }
+        }
+
+        if( cmp_result == 0 )
+        {
+            SIXTRL_UINT64_T ii = 0;
+
+            SIXTRL_ASSERT( ( lhs->num_d == rhs->num_d ) &&
+                ( lhs->d != SIXTRL_NULLPTR ) &&
+                ( rhs->d != SIXTRL_NULLPTR ) );
+
+            for( ; ii < lhs->num_d ; ++ii )
+            {
+                if( lhs->d[ ii ] != rhs->d[ ii ] )
+                {
+                    if( lhs->d[ ii ] > rhs->d[ ii ] ) cmp_result = -1;
+                    else if( lhs->d[ ii ] < rhs->d[ ii ] ) cmp_result = +1;
+
+                    break;
+                }
+            }
+        }
+
+        if( cmp_result == 0 )
+        {
+            SIXTRL_UINT64_T ii = 0;
+
+            SIXTRL_ASSERT( ( lhs->num_e == rhs->num_e ) &&
+                ( lhs->e != SIXTRL_NULLPTR ) &&
+                ( rhs->e != SIXTRL_NULLPTR ) );
+
+            for( ; ii < lhs->num_e ; ++ii )
+            {
+                SIXTRL_REAL_T const diff = ( lhs->e[ ii ] >= rhs->e[ ii ] )
+                    ? ( lhs->e[ ii ] - rhs->e[ ii ] )
+                    : ( rhs->e[ ii ] - lhs->e[ ii ] );
+
+                if( diff > treshold )
+                {
+                    cmp_result = ( lhs->c[ ii ] > rhs->c[ ii ] ) ? -1 : +1;
+                }
+
+                if( cmp_result != 0 ) break;
+            }
+        }
+    }
+    else if( rhs != SIXTRL_NULLPTR )
+    {
+        cmp_result = +1;
+    }
+
+    return cmp_result;
+}
+
+#endif /* SIXTRACKLIB_TESTS_TESTLIB_GENERIC_BUFFER_H__ */
+
+/* end: tests/sixtracklib/testlib/common/generic_buffer_obj.h */
diff --git a/tests/sixtracklib/testlib/common/compare.h b/tests/sixtracklib/testlib/common/compare.h
index f5e9fd14..a8349c94 100644
--- a/tests/sixtracklib/testlib/common/compare.h
+++ b/tests/sixtracklib/testlib/common/compare.h
@@ -8,20 +8,24 @@
 #endif /* !defined( SIXTRL_NO_SYSTEM_INCLUDES ) */
 
 #if !defined( SIXTRL_NO_INCLUDES )
-    #include "sixtracklib/common/definitions.h"        
+    #include "sixtracklib/common/definitions.h"
 #endif /* !defined( SIXTRL_NO_INCLUDES ) */
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
-SIXTRL_STATIC SIXTRL_FN 
+SIXTRL_STATIC SIXTRL_FN
+int NS(TestLibCompare_int64_attribute)(
+    SIXTRL_INT64_T const lhs_attribute, SIXTRL_INT64_T const rhs_attribute );
+
+SIXTRL_STATIC SIXTRL_FN
 int NS(TestLibCompare_real_attribute)(
     SIXTRL_REAL_T const lhs_attribute, SIXTRL_REAL_T const rhs_attribute );
 
-SIXTRL_STATIC SIXTRL_FN 
+SIXTRL_STATIC SIXTRL_FN
 int NS(TestLibCompare_real_attribute_with_treshold)(
-    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs, 
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
     SIXTRL_REAL_T const treshold );
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
@@ -36,6 +40,13 @@ int NS(TestLibCompare_real_attribute_with_treshold)(
 extern "C" {
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
 
+SIXTRL_INLINE int NS(TestLibCompare_int64_attribute)(
+    SIXTRL_INT64_T const lhs_attribute, SIXTRL_INT64_T const rhs_attribute )
+{
+    return ( lhs_attribute == rhs_attribute )
+        ? 0 : ( ( lhs_attribute > rhs_attribute ) ? +1 : -1 );
+}
+
 SIXTRL_INLINE int NS(TestLibCompare_real_attribute)(
     SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs )
 {
@@ -44,22 +55,22 @@ SIXTRL_INLINE int NS(TestLibCompare_real_attribute)(
 }
 
 SIXTRL_INLINE int NS(TestLibCompare_real_attribute_with_treshold)(
-    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs, 
+    SIXTRL_REAL_T const lhs, SIXTRL_REAL_T const rhs,
     SIXTRL_REAL_T const treshold )
 {
     int cmp_result = ( int )-1;
-    
+
     SIXTRL_STATIC_VAR SIXTRL_REAL_T const ZERO = ( SIXTRL_REAL_T )0.0;
     SIXTRL_REAL_T const delta = lhs - rhs;
-    
+
     if( delta == ZERO )
     {
-        cmp_result = 0;        
+        cmp_result = 0;
     }
     else if( treshold >= ZERO )
     {
         cmp_result = 0;
-        
+
         if( ( delta >= ZERO ) && ( delta > treshold ) )
         {
             cmp_result = -1;
@@ -69,13 +80,13 @@ SIXTRL_INLINE int NS(TestLibCompare_real_attribute_with_treshold)(
             cmp_result = +1;
         }
     }
-    
+
     return cmp_result;
 }
 
 #if !defined(  _GPUCODE ) && defined( __cplusplus )
 }
 #endif /* !defined(  _GPUCODE ) && defined( __cplusplus ) */
-    
+
 #endif /* SIXTRACKLIB_TESTLIB_COMMON_COMPARE_C99_H__ */
 /* end: tests/sixtracklib/testlib/common/compare.h */
diff --git a/tests/sixtracklib/testlib/common/output/CMakeLists.txt b/tests/sixtracklib/testlib/common/output/CMakeLists.txt
index fbbbb6be..c438c3c5 100644
--- a/tests/sixtracklib/testlib/common/output/CMakeLists.txt
+++ b/tests/sixtracklib/testlib/common/output/CMakeLists.txt
@@ -2,19 +2,14 @@
 # tests/sixtracklib/testlib/common/output/CMakeLists.txt
 
 set( SIXTRL_TESTLIB_COMMON_OUTPUT_C99_HEADERS
-     assign_be_monitor_ctrl_arg.h
-     assign_elem_by_elem_ctrl_arg.h
-)
+     assign_be_monitor_ctrl_arg.h assign_elem_by_elem_ctrl_arg.h )
 
 set( SIXTRL_TESTLIB_COMMON_OUTPUT_C99_SOURCES
-     assign_be_monitor_ctrl_arg.c
-     assign_elem_by_elem_ctrl_arg.c
-)
+     assign_be_monitor_ctrl_arg.c assign_elem_by_elem_ctrl_arg.c )
 
 add_library( sixtrack_test_common_output_c99 OBJECT
-             ${SIXTRL_TESTLIB_COMMON_OUTPUT_C99_HEADERS}
-             ${SIXTRL_TESTLIB_COMMON_OUTPUT_C99_SOURCES}
-)
+    ${SIXTRL_TESTLIB_COMMON_OUTPUT_C99_HEADERS}
+    ${SIXTRL_TESTLIB_COMMON_OUTPUT_C99_SOURCES} )
 
 target_include_directories( sixtrack_test_common_output_c99 PRIVATE
     PRIVATE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}>
@@ -25,7 +20,8 @@ set_target_properties( sixtrack_test_common_output_c99 PROPERTIES
     C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_test_common_output_c99 PRIVATE
-        ${SIXTRACKLIB_C99_FLAGS} ${SIXOUTPUTLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXOUTPUTLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixoutput_test_common_output_c99 and
diff --git a/tests/sixtracklib/testlib/common/output/assign_be_monitor_ctrl_arg.c b/tests/sixtracklib/testlib/common/output/assign_be_monitor_ctrl_arg.c
index ec3cc11b..1472caea 100644
--- a/tests/sixtracklib/testlib/common/output/assign_be_monitor_ctrl_arg.c
+++ b/tests/sixtracklib/testlib/common/output/assign_be_monitor_ctrl_arg.c
@@ -213,7 +213,7 @@ NS(arch_status_t) NS(TestBeamMonitorCtrlArg_evaluate_assign_output_buffer)(
                     be_monitor = ( ptr_be_monitor_t )( uintptr_t
                         )NS(Object_get_begin_addr)( be_it );
 
-                    be_out_addr = NS(BeamMonitor_get_out_address)( be_monitor );
+                    be_out_addr = NS(BeamMonitor_out_address)( be_monitor );
 
                     cmp_out_addr = ( address_t )( uintptr_t
                         )NS(Particles_buffer_get_const_particles)(
diff --git a/tests/sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.c b/tests/sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.c
index 87d7c23d..2e2a1e91 100644
--- a/tests/sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.c
+++ b/tests/sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.c
@@ -20,8 +20,9 @@ NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
     NS(buffer_size_t) const num_particle_sets,
     NS(buffer_size_t) const* SIXTRL_RESTRICT pset_indices_begin,
     NS(Buffer)* SIXTRL_RESTRICT beam_elements_buffer,
-    NS(ArgumentBase)* SIXTRL_RESTRICT elem_by_elem_config_arg,
-    NS(ElemByElemConfig)* SIXTRL_RESTRICT elem_by_elem_config,
+    NS(ArgumentBase)* SIXTRL_RESTRICT elem_by_elem_config_buffer_arg,
+    NS(Buffer)* SIXTRL_RESTRICT elem_by_elem_config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(ArgumentBase)* SIXTRL_RESTRICT output_arg,
     NS(Buffer)* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t)* SIXTRL_RESTRICT ptr_output_buffer_index_offset,
@@ -34,8 +35,12 @@ NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
         ( num_particle_sets > ( NS(buffer_size_t) )0u ) &&
         ( pset_indices_begin != SIXTRL_NULLPTR ) &&
         ( beam_elements_buffer != SIXTRL_NULLPTR ) &&
-        ( elem_by_elem_config_arg != SIXTRL_NULLPTR ) &&
-        ( elem_by_elem_config != SIXTRL_NULLPTR ) &&
+        ( elem_by_elem_config_buffer_arg != SIXTRL_NULLPTR ) &&
+        ( elem_by_elem_config_buffer != SIXTRL_NULLPTR ) &&
+        ( ( NS(Buffer_get_num_of_objects)( elem_by_elem_config_buffer ) ==
+            ( NS(buffer_size_t) )0u ) ||
+          ( NS(Buffer_get_num_of_objects)( elem_by_elem_config_buffer ) >
+            elem_by_elem_config_index ) ) &&
         ( output_arg != SIXTRL_NULLPTR ) &&
         ( output_buffer != SIXTRL_NULLPTR ) &&
         ( ( NS(Buffer_is_particles_buffer)( output_buffer ) ) ||
@@ -56,6 +61,10 @@ NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
         buf_size_t beam_monitor_output_offset = ( buf_size_t )0u;
         pindex_t   max_elem_by_elem_turn_id   = ( pindex_t )-1;
 
+        NS(ElemByElemConfig)* elem_by_elem_config =
+            NS(ElemByElemConfig_from_buffer)(
+                elem_by_elem_config_buffer, elem_by_elem_config_index );
+
         status = NS(OutputBuffer_get_min_max_attributes_on_particle_sets)(
             particles_buffer, num_particle_sets, pset_indices_begin,
             beam_elements_buffer,
@@ -79,6 +88,8 @@ NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
             *ptr_output_buffer_index_offset = output_buffer_index_offset;
         }
 
+
+
         if( status == NS(ARCH_STATUS_SUCCESS) )
         {
             status = NS(ElemByElemConfig_init_detailed)( elem_by_elem_config,
@@ -89,8 +100,8 @@ NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
 
         if( status == NS(ARCH_STATUS_SUCCESS) )
         {
-            status = NS(Argument_send_raw_argument)( elem_by_elem_config_arg,
-                elem_by_elem_config, sizeof( NS(ElemByElemConfig) ) );
+            status = NS(Argument_send_buffer)(
+                elem_by_elem_config_buffer_arg, elem_by_elem_config_buffer );
         }
 
         if( status == NS(ARCH_STATUS_SUCCESS) )
@@ -120,8 +131,9 @@ NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
 }
 
 NS(arch_status_t) NS(TestElemByElemConfigCtrlArg_evaluate_assign_output_buffer)(
-    NS(ArgumentBase)* SIXTRL_RESTRICT elem_by_elem_config_arg,
-    NS(ElemByElemConfig)* SIXTRL_RESTRICT elem_by_elem_config,
+    NS(ArgumentBase)* SIXTRL_RESTRICT elem_by_elem_config_buffer_arg,
+    NS(Buffer)* SIXTRL_RESTRICT elem_by_elem_config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(ArgumentBase)* SIXTRL_RESTRICT output_arg,
     NS(Buffer)* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t) const output_buffer_index_offset,
@@ -134,14 +146,18 @@ NS(arch_status_t) NS(TestElemByElemConfigCtrlArg_evaluate_assign_output_buffer)(
     NS(arch_status_t) status = NS(ARCH_STATUS_GENERAL_FAILURE);
     buf_size_t const nn = output_buffer_index_offset + ( buf_size_t )1u;
 
-    if( ( elem_by_elem_config_arg != SIXTRL_NULLPTR ) &&
-        ( elem_by_elem_config != SIXTRL_NULLPTR ) &&
+    if( ( elem_by_elem_config_buffer_arg != SIXTRL_NULLPTR ) &&
+        ( elem_by_elem_config_buffer != SIXTRL_NULLPTR ) &&
         ( output_arg != SIXTRL_NULLPTR ) &&
         ( output_buffer != SIXTRL_NULLPTR ) &&
+        ( NS(Buffer_get_num_of_objects)( elem_by_elem_config_buffer ) >
+            elem_by_elem_config_index ) &&
         ( NS(Buffer_get_num_of_objects)( output_buffer ) >
             output_buffer_index_offset ) &&
         ( NS(Buffer_is_particles_buffer)( output_buffer ) ) )
     {
+        NS(ElemByElemConfig)* elem_by_elem_config = SIXTRL_NULLPTR;
+
         NS(Particles) const* cmp_particles =
             NS(Particles_buffer_get_const_particles)( output_buffer,
                 output_buffer_index_offset );
@@ -157,9 +173,8 @@ NS(arch_status_t) NS(TestElemByElemConfigCtrlArg_evaluate_assign_output_buffer)(
 
         SIXTRL_ASSERT( slot_size > ( NS(buffer_size_t) )0u );
 
-        status = NS(Argument_receive_raw_argument)(
-            elem_by_elem_config_arg, elem_by_elem_config,
-                sizeof( NS(ElemByElemConfig) ) );
+        status = NS(Argument_receive_buffer)(
+            elem_by_elem_config_buffer_arg, elem_by_elem_config_buffer );
 
         if( ( result_arg != SIXTRL_NULLPTR ) &&
             ( status == NS(ARCH_STATUS_SUCCESS) ) )
@@ -167,6 +182,9 @@ NS(arch_status_t) NS(TestElemByElemConfigCtrlArg_evaluate_assign_output_buffer)(
             NS(arch_debugging_t) result_register =
                 SIXTRL_ARCH_DEBUGGING_GENERAL_FAILURE;
 
+            elem_by_elem_config = NS(ElemByElemConfig_from_buffer)(
+                    elem_by_elem_config_buffer, elem_by_elem_config_index );
+
             status = NS(Argument_receive_raw_argument)(
                 result_arg, &result_register, sizeof( result_register ) );
 
diff --git a/tests/sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.h b/tests/sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.h
index 7eaa5954..cd587666 100644
--- a/tests/sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.h
+++ b/tests/sixtracklib/testlib/common/output/assign_elem_by_elem_ctrl_arg.h
@@ -25,8 +25,9 @@ NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
     NS(buffer_size_t) const num_particle_sets,
     NS(buffer_size_t) const* SIXTRL_RESTRICT pset_indices_begin,
     NS(Buffer)* SIXTRL_RESTRICT beam_elements_buffer,
-    NS(ArgumentBase)* SIXTRL_RESTRICT elem_by_elem_config_arg,
-    NS(ElemByElemConfig)* SIXTRL_RESTRICT elem_by_elem_config,
+    NS(ArgumentBase)* SIXTRL_RESTRICT elem_by_elem_config_buffer_arg,
+    NS(Buffer)* SIXTRL_RESTRICT elem_by_elem_config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(ArgumentBase)* SIXTRL_RESTRICT output_arg,
     NS(Buffer)* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t)* SIXTRL_RESTRICT ptr_output_buffer_index_offset,
@@ -35,8 +36,9 @@ NS(TestElemByElemConfigCtrlArg_prepare_assign_output_buffer)(
 
 SIXTRL_EXTERN SIXTRL_HOST_FN NS(arch_status_t)
 NS(TestElemByElemConfigCtrlArg_evaluate_assign_output_buffer)(
-    NS(ArgumentBase)* SIXTRL_RESTRICT elem_by_elem_config_arg,
-    NS(ElemByElemConfig)* SIXTRL_RESTRICT elem_by_elem_config,
+    NS(ArgumentBase)* SIXTRL_RESTRICT elem_by_elem_config_buffer_arg,
+    NS(Buffer)* SIXTRL_RESTRICT elem_by_elem_config_buffer,
+    NS(buffer_size_t) const elem_by_elem_config_index,
     NS(ArgumentBase)* SIXTRL_RESTRICT output_arg,
     NS(Buffer)* SIXTRL_RESTRICT output_buffer,
     NS(buffer_size_t) const output_buffer_index_offset,
diff --git a/tests/sixtracklib/testlib/common/particles/CMakeLists.txt b/tests/sixtracklib/testlib/common/particles/CMakeLists.txt
index 270c1b3f..e88593f9 100644
--- a/tests/sixtracklib/testlib/common/particles/CMakeLists.txt
+++ b/tests/sixtracklib/testlib/common/particles/CMakeLists.txt
@@ -22,7 +22,8 @@ set_target_properties( sixtrack_test_common_particle_c99 PROPERTIES
     C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_test_common_particle_c99 PRIVATE
-        -Wall -Werror -pedantic -ansi ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 
@@ -46,10 +47,11 @@ set_target_properties( sixtrack_test_common_particle_cxx PROPERTIES
     CXX_STANDARD 11 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_test_common_particle_cxx PRIVATE
-        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
-# pass on sixtrack_test_common_particle_c99 and 
+# pass on sixtrack_test_common_particle_c99 and
 # sixtrack_test_common_particle_cxx as a module for sixtrack_test:
 
 set(  SIXTRACKL_TESTLIB_LIBRARY_MODULES
diff --git a/tests/sixtracklib/testlib/common/track/CMakeLists.txt b/tests/sixtracklib/testlib/common/track/CMakeLists.txt
index 88ea68ba..9625c618 100644
--- a/tests/sixtracklib/testlib/common/track/CMakeLists.txt
+++ b/tests/sixtracklib/testlib/common/track/CMakeLists.txt
@@ -27,7 +27,8 @@ set_target_properties( sixtrack_test_common_track_c99 PROPERTIES
     C_STANDARD 99 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_test_common_track_c99 PRIVATE
-        ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_C99_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_C99_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 
@@ -52,7 +53,8 @@ set_target_properties( sixtrack_test_common_track_cxx PROPERTIES
     CXX_STANDARD 11 C_STANDARD_REQUIRED ON )
 
 target_compile_options( sixtrack_test_common_track_cxx PRIVATE
-        ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS} )
+    ${SIXTRACKLIB_CXX_FLAGS} ${SIXTRACKLIB_CPU_FLAGS}
+    ${SIXTRACKL_CXX_AUTOVEC_FLAGS} )
 
 # ------------------------------------------------------------------------------
 # pass on sixtrack_test_common_track_c99 and
diff --git a/tests/sixtracklib/testlib/testdata/track_testdata.c b/tests/sixtracklib/testlib/testdata/track_testdata.c
index 97af35e9..7d2e33c4 100644
--- a/tests/sixtracklib/testlib/testdata/track_testdata.c
+++ b/tests/sixtracklib/testlib/testdata/track_testdata.c
@@ -312,7 +312,7 @@ SIXTRL_HOST_FN NS(Buffer)*
                     case NS(OBJECT_TYPE_DRIFT):
                     {
                         typedef NS(Drift) belem_t;
-                        num_dataptrs += NS(Drift_get_num_dataptrs)(
+                        num_dataptrs += NS(Drift_num_dataptrs)(
                             ( belem_t const* )( uintptr_t )beginaddr );
 
                         break;
@@ -321,7 +321,7 @@ SIXTRL_HOST_FN NS(Buffer)*
                     case NS(OBJECT_TYPE_DRIFT_EXACT):
                     {
                         typedef NS(DriftExact) belem_t;
-                        num_dataptrs += NS(DriftExact_get_num_dataptrs)(
+                        num_dataptrs += NS(DriftExact_num_dataptrs)(
                             ( belem_t const* )( uintptr_t )beginaddr );
 
                         break;
@@ -329,8 +329,8 @@ SIXTRL_HOST_FN NS(Buffer)*
 
                     case NS(OBJECT_TYPE_MULTIPOLE):
                     {
-                        typedef NS(MultiPole) belem_t;
-                        num_dataptrs += NS(MultiPole_get_num_dataptrs)(
+                        typedef NS(Multipole) belem_t;
+                        num_dataptrs += NS(Multipole_num_dataptrs)(
                             ( belem_t const* )( uintptr_t )beginaddr );
 
                         break;
@@ -338,28 +338,27 @@ SIXTRL_HOST_FN NS(Buffer)*
 
                     case NS(OBJECT_TYPE_XYSHIFT):
                     {
-                        typedef NS(XYShift) belem_t;
-                        num_dataptrs += NS(XYShift_get_num_dataptrs)(
-                            ( belem_t const* )( uintptr_t )beginaddr );
+                        typedef SIXTRL_BE_ARGPTR_DEC NS(XYShift) const* ptr_t;
+                        num_dataptrs += NS(XYShift_num_dataptrs)(
+                            ( ptr_t )( uintptr_t )beginaddr );
 
                         break;
                     }
 
                     case NS(OBJECT_TYPE_SROTATION):
                     {
-                        typedef NS(SRotation) belem_t;
-                        num_dataptrs += NS(SRotation_get_num_dataptrs)(
-                            ( belem_t const* )( uintptr_t )beginaddr );
+                        typedef SIXTRL_BE_ARGPTR_DEC NS(SRotation) const* ptr_t;
+                        num_dataptrs += NS(SRotation_num_dataptrs)(
+                            ( ptr_t )( uintptr_t )beginaddr );
 
                         break;
                     }
 
                     case NS(OBJECT_TYPE_CAVITY):
                     {
-                        typedef NS(Cavity) belem_t;
-                        num_dataptrs += NS(Cavity_get_num_dataptrs)(
-                            ( belem_t const* )( uintptr_t )beginaddr );
-
+                        typedef SIXTRL_BE_ARGPTR_DEC NS(Cavity) const* ptr_t;
+                        num_dataptrs += NS(Cavity_num_dataptrs)(
+                            ( ptr_t )( uintptr_t )beginaddr );
                         break;
                     }
 
@@ -408,99 +407,76 @@ SIXTRL_HOST_FN NS(Buffer)*
                     {
                         case NS(OBJECT_TYPE_DRIFT):
                         {
-                            typedef NS(Drift) belem_t;
-
-                            belem_t const* orig_belem =
-                                ( belem_t const* )( uintptr_t )beginaddr;
+                            SIXTRL_BE_ARGPTR_DEC NS(Drift) const* orig = (
+                                SIXTRL_BE_ARGPTR_DEC NS(Drift) const* )(
+                                    uintptr_t )beginaddr;
 
-                            belem_t* copied_belem = NS(Drift_add)(
-                                beam_elements_buffer,
-                                NS(Drift_get_length)( orig_belem ) );
+                            SIXTRL_BE_ARGPTR_DEC NS(Drift)* copied_elem =
+                                NS(Drift_add_copy)( beam_elements_buffer, orig );
 
-                            if( copied_belem == SIXTRL_NULLPTR ) success = -1;
+                            if( copied_elem == SIXTRL_NULLPTR ) success = -1;
                             break;
                         }
 
                         case NS(OBJECT_TYPE_DRIFT_EXACT):
                         {
-                            typedef NS(DriftExact) belem_t;
+                            SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const* orig = (
+                                SIXTRL_BE_ARGPTR_DEC NS(DriftExact) const* )(
+                                    uintptr_t )beginaddr;
 
-                            belem_t const* orig_belem =
-                                ( belem_t const* )( uintptr_t )beginaddr;
+                            SIXTRL_BE_ARGPTR_DEC NS(DriftExact)* copied_elem =
+                                NS(DriftExact_add_copy)(
+                                    beam_elements_buffer, orig );
 
-                            belem_t* copied_belem = NS(DriftExact_add)(
-                                beam_elements_buffer,
-                                NS(DriftExact_get_length)( orig_belem ) );
-
-                            if( copied_belem == SIXTRL_NULLPTR ) success = -1;
+                            if( copied_elem == SIXTRL_NULLPTR ) success = -1;
                             break;
                         }
 
                         case NS(OBJECT_TYPE_MULTIPOLE):
                         {
-                            typedef NS(MultiPole) belem_t;
-
-                            belem_t const* orig_belem =
-                                ( belem_t const* )( uintptr_t )beginaddr;
-
-                            belem_t* copied_belem = NS(MultiPole_add)(
-                                beam_elements_buffer,
-                                NS(MultiPole_get_order)( orig_belem ),
-                                NS(MultiPole_get_const_bal)( orig_belem ),
-                                NS(MultiPole_get_length)( orig_belem ),
-                                NS(MultiPole_get_hxl)( orig_belem ),
-                                NS(MultiPole_get_hyl)( orig_belem ) );
+                            typedef SIXTRL_BE_ARGPTR_DEC NS(Multipole) const*
+                                    ptr_elem_t;
 
+                            SIXTRL_BE_ARGPTR_DEC NS(Multipole)* copied_belem =
+                            NS(Multipole_add_copy)( beam_elements_buffer,
+                                ( ptr_elem_t )( uintptr_t )beginaddr );
                             if( copied_belem == SIXTRL_NULLPTR ) success = -1;
                             break;
                         }
 
                         case NS(OBJECT_TYPE_XYSHIFT):
                         {
-                            typedef NS(XYShift) belem_t;
-
-                            belem_t const* orig_belem =
-                                ( belem_t const* )( uintptr_t )beginaddr;
-
-                            belem_t* copied_belem = NS(XYShift_add)(
-                                beam_elements_buffer,
-                                NS(XYShift_get_dx)( orig_belem ),
-                                NS(XYShift_get_dy)( orig_belem ) );
-
+                            typedef NS(XYShift) elem_t;
+                            typedef SIXTRL_BE_ARGPTR_DEC elem_t* ptr_dest_t;
+                            typedef SIXTRL_BE_ARGPTR_DEC elem_t const* ptr_t;
+                            ptr_t orig = ( ptr_t )( uintptr_t )beginaddr;
+                            ptr_dest_t copied_belem = NS(XYShift_add_copy)(
+                                beam_elements_buffer, orig );
                             if( copied_belem == SIXTRL_NULLPTR ) success = -1;
                             break;
                         }
 
                         case NS(OBJECT_TYPE_SROTATION):
                         {
-                            typedef NS(SRotation) belem_t;
-
-                            belem_t const* orig_belem =
-                                ( belem_t const* )( uintptr_t )beginaddr;
-
-                            belem_t* copied_belem = NS(SRotation_add_detailed)(
-                                beam_elements_buffer,
-                                NS(SRotation_get_cos_angle)( orig_belem ),
-                                NS(SRotation_get_sin_angle)( orig_belem ) );
-
+                            typedef NS(SRotation) elem_t;
+                            typedef SIXTRL_BE_ARGPTR_DEC elem_t* ptr_dest_t;
+                            typedef SIXTRL_BE_ARGPTR_DEC elem_t const* ptr_t;
+                            ptr_t orig = ( ptr_t )( uintptr_t )beginaddr;
+                            ptr_dest_t copied_belem = NS(SRotation_add_copy)(
+                                beam_elements_buffer, orig );
                             if( copied_belem == SIXTRL_NULLPTR ) success = -1;
                             break;
                         }
 
                         case NS(OBJECT_TYPE_CAVITY):
                         {
-                            typedef NS(Cavity) belem_t;
-
-                            belem_t const* orig_belem =
-                                ( belem_t const* )( uintptr_t )beginaddr;
-
-                            belem_t* copied_belem = NS(Cavity_add)(
-                                beam_elements_buffer,
-                                NS(Cavity_get_voltage)( orig_belem ),
-                                NS(Cavity_get_frequency)( orig_belem ),
-                                NS(Cavity_get_lag)( orig_belem ) );
-
-                            if( copied_belem == SIXTRL_NULLPTR ) success = -1;
+                            typedef SIXTRL_BE_ARGPTR_DEC NS(Cavity) const* ptr_t;
+                            success = ( SIXTRL_NULLPTR != NS(Cavity_add_copy)(
+                                beam_elements_buffer, ( ptr_t )( uintptr_t
+                                    )beginaddr ) )
+                                ? ( NS(arch_status_t) )SIXTRL_ARCH_STATUS_SUCCESS
+                                : ( NS(arch_status_t)
+                                    )SIXTRL_ARCH_STATUS_GENERAL_FAILURE;
                             break;
                         }
 
@@ -527,5 +503,3 @@ SIXTRL_HOST_FN NS(Buffer)*
 
     return beam_elements_buffer;
 }
-
-/* end: tests/sixtracklib/testlib/testdata/track_testdata.c */
diff --git a/tests/testdata/tricub/create_testdata.py b/tests/testdata/tricub/create_testdata.py
new file mode 100644
index 00000000..26d15e03
--- /dev/null
+++ b/tests/testdata/tricub/create_testdata.py
@@ -0,0 +1,28 @@
+import numpy as np
+import pickle
+
+
+def create_testdata(path_to_txt_file, path_to_pickle_file):
+    num_lines = sum(1 for line in open(path_to_txt_file, "r"))
+    kicks = None
+    prng_seed = None
+    n_part = 0
+    if num_lines > 1:
+        n_part = num_lines - 1
+        kicks = np.empty([n_part, 3], dtype=np.float64)
+        with open(path_to_txt_file, "r") as fp:
+            for ii, line in enumerate(fp):
+                if ii < n_part:
+                    line = line.strip("\n")
+                    line = line.split(" ")
+                    line = list(map(float, line))
+                    kicks[ii] = np.array(line)
+                else:
+                    prng_seed = float(line.strip())
+
+    with open(path_to_pickle_file, "wb") as fp:
+        pickle.dump((n_part, prng_seed, kicks), fp)
+
+
+if __name__ == "__main__":
+    create_testdata("./precomputed_kicks.txt", "./precomputed_kicks.pickle")
diff --git a/tests/testdata/tricub/precomputed_kicks.pickle b/tests/testdata/tricub/precomputed_kicks.pickle
new file mode 100644
index 00000000..7bd72856
Binary files /dev/null and b/tests/testdata/tricub/precomputed_kicks.pickle differ
diff --git a/tests/testdata/tricub/precomputed_kicks.txt b/tests/testdata/tricub/precomputed_kicks.txt
new file mode 100644
index 00000000..dbf6bd2d
--- /dev/null
+++ b/tests/testdata/tricub/precomputed_kicks.txt
@@ -0,0 +1,1001 @@
+-0.723868074223315 +0.078455598757998 -0.021548912103341
+-0.016873060442879 +0.358550690016183 -0.121390273905976
+-0.428507572601246 +0.106380277031497 -0.035888409603177
++0.386088393604855 -0.116562396454870 -0.011547431203476
+-0.837695791744996 -0.017940103913146 -0.007263846245201
++0.084741294887178 +0.107037648274159 +0.036634255919948
++0.315808379300289 -0.298280419092849 -0.035478121005324
+-0.168165280864939 +0.025316699135102 -0.097171823411015
+-0.193072254708825 -0.009154573950605 -0.054860109265132
++0.073713321863936 -0.226081765971079 +0.002968226305035
+-0.913468633759351 +0.068394508136332 +0.071283670086615
+-0.178726860236247 +0.016122756845796 -0.066338992518041
++0.203982858346481 -0.030991388606069 +0.046904032273269
++0.502773962470611 +0.009270493062665 +0.002170731880958
++0.022824950612544 -0.108774823776588 +0.028791408982076
++0.023360260456836 -0.037162972779209 -0.048511065983288
++0.415355767854953 +0.045822939456164 -0.084147685702670
++0.101537518583351 -0.145022000613365 -0.039381629801400
++0.107639710327862 -0.075614959691255 -0.203492810489176
++0.368840117199920 +0.079473343749373 -0.039773200440566
++0.222931663097834 +0.234369569359660 -0.065093358827068
+-0.078482221721857 +0.162800606156940 -0.074180799578388
+-0.492481820734974 +0.301566601937252 -0.039613809219067
++0.021907052390264 -0.351805679613138 -0.078340879023796
++0.184796702994970 -0.428361832024660 +0.005520759801073
+-0.615153890034483 -0.021967115463461 +0.036174341576946
+-0.381773345468016 +0.429500709654403 -0.007392877813868
++0.163282360583760 +0.129936031901612 -0.045246103062318
+-0.241401021695364 -0.043477785508392 +0.188116177778550
++0.047829170733940 +0.205076463312576 +0.236499695789521
++0.217342594536533 -0.474718641626004 +0.006495577781316
+-0.096561897184763 -0.199981721162224 +0.033819538075563
++0.073529649675492 +0.137627703044443 -0.112686066039758
++0.711973950575217 +0.121909358857736 -0.008184311694790
++0.431223584677768 -0.007925041822451 -0.099657629956436
++0.096737094869579 -0.005528761614372 +0.148673121920841
+-0.003851721006078 +0.159544067566490 +0.086876625286716
++0.057711598751353 -0.052905563730368 +0.011478899647187
++0.851176788873493 -0.004062567707658 -0.019322086530418
++0.003871657357059 +0.305538322018420 +0.103027068153498
++0.191001382258555 +0.258481094841194 -0.054385779399432
+-0.171537403275227 -0.009635509779785 -0.183092202838707
+-0.031879197807855 -0.483532444081131 -0.010938254167592
++0.248980128161688 -0.248691395973492 -0.047378317190885
++0.232268199119948 -0.305297198537590 +0.023512702945293
+-0.332907003613980 -0.184008055639525 -0.087143400618152
++0.233597811313959 +0.148911684556550 +0.079335222141931
+-0.271439183501830 +0.129605831092738 +0.016876821132056
+-0.018240688095525 -0.285422632342162 -0.008502137316741
+-0.208120391547869 +0.044452815866171 -0.110160521459157
++0.157260676548848 -0.244572059682948 +0.002598066610792
+-0.085968901342722 +0.150446493394798 +0.033569358381573
+-0.239345875215598 -0.158701848810960 -0.052736437526201
++0.027609687660996 -0.188633827398413 +0.040167755367761
++0.114209189465731 +0.056873720379384 +0.016720585218009
++0.112386151294294 -0.223996675872755 +0.025322936464515
++0.084620869683120 -0.293798110205496 +0.042733027246950
++0.325386189238372 -0.085486092546300 +0.040753427634385
+-0.144122763660162 -0.132559415798601 -0.026624249311448
+-0.161707507757055 -0.422018592603221 +0.005099313795182
+-0.074705411994912 -0.364925061536555 +0.026721736392801
+-0.006729627000387 -0.339309271932707 -0.165121884195883
+-0.008454442214780 -0.101922402010090 +0.023762927237122
++0.298585472473677 -0.186064246944104 +0.085063991539726
++0.008254149526756 -0.107152857934582 +0.048179661108654
+-0.206521926321519 -0.400397126173766 -0.021276801895918
++0.049031430525085 -0.117636126032019 -0.066126811151245
+-0.131387809765389 +0.089539840084338 -0.039340629370608
+-0.361056742219281 +0.419471668729362 +0.097684270245937
++0.387372358954896 -0.182144698250547 -0.112176385327325
+-0.187509525529761 +0.009419371044483 +0.166769534118404
++0.228021399339005 +0.096292722347013 -0.003286423804145
+-0.093254567971469 -0.016135802300052 +0.042060444807220
++0.230565484702057 -0.452463726706136 +0.006538280420121
+-0.004937436809889 +0.011485588817562 -0.097818968721282
++1.015772858681549 +0.066949797063930 +0.021689922625031
+-0.426948351699474 +0.036993608449956 +0.053462263425299
+-0.278840675635167 -0.277318888918988 -0.087871465359980
++0.353166243960015 +0.247278443190967 +0.003451330497188
++0.061745528840867 -0.287841732338328 -0.072336130862552
++0.128730246340164 -0.011887036766552 -0.008465362670799
+-0.093699815559750 -0.152368557825066 +0.002229812243880
+-0.044576798209692 -0.012190161606571 +0.138418004512304
+-0.534562714623903 +0.159738886917402 -0.024428631990447
++0.301123121717718 -0.031474453040687 +0.008171727119293
++0.027076563027343 -0.152506811105431 -0.204222452153338
+-0.062043669067330 -0.323731533668675 +0.001805366665684
++0.053949776643974 -0.014549859958919 +0.130124852755725
+-0.196749630805227 -0.155365426460704 +0.041173238787674
+-0.075778784859226 -0.351533062196354 -0.042591389894445
+-0.060457588363936 -0.037357263311910 -0.079555526004312
+-0.057546451618853 -0.386164668186030 -0.010944576252522
+-0.067001468444907 -0.411345522185426 +0.042677849508040
++0.272129127767862 +0.198710972799455 +0.046507436865927
+-0.054709547513852 -0.126377548165375 -0.074699185014922
++0.014846481531832 -0.140643172582239 +0.132075518867154
++0.003694947404737 +0.072803578829235 -0.297001864526875
+-0.238569547824978 -0.177290048870944 -0.033553672261348
+-0.363621735632814 +0.035173038148106 +0.097359513847859
+-0.128008187806836 -0.188684767656227 -0.050456441621811
++0.084655520881346 -0.337919364079440 -0.040142192150930
+-0.286661409539366 -0.305070955781775 +0.013151210429019
++0.160336240268647 -0.062696412651580 +0.029787860207635
+-0.264860001775469 +0.109004242192130 +0.048724584768770
+-0.453520624057591 -0.237813003143748 +0.086987280604545
+-0.234972156572604 -0.219015512751799 -0.022605614908887
++0.163109039260071 +0.332219093694246 -0.000050706730077
+-0.387148151348540 +0.007706175191181 +0.010309806942509
++0.151800560113943 +0.118162786338660 -0.006473045257913
++0.173619186971021 -0.325689757471505 -0.000053220221814
++0.390246937762410 +0.404727840365523 +0.008837370666573
++0.305395657037956 +0.015109986566971 -0.019307452246986
++0.076836167771073 +0.182664852715873 +0.098515160068786
+-0.830098978149135 +0.140405957015267 -0.012582827428087
+-0.266265274904956 -0.169816078028997 +0.010711180618912
++0.267046543187358 -0.126885343671186 -0.003445344512648
+-0.073908705941973 -0.148051487497563 +0.210624242627790
+-0.734547811223574 +0.010713556758577 -0.033335776076539
+-0.064257117772051 +0.097114045162157 +0.018663800392138
++0.124980763969061 -0.051882600528647 -0.027279974866065
+-0.302553373460756 -0.033100686505470 -0.119649292679731
+-0.084209943966917 +0.196001537634847 -0.033201112046754
+-0.413444407858062 -0.155578388371505 -0.021881309318254
++0.832356521153952 +0.027576819861048 -0.054281746927361
++0.043084296517513 +0.154994651201201 +0.006623726998127
++0.120859061686193 -0.051484783745676 -0.018145642774222
++0.008768015514833 +0.161654732233363 +0.057377344384490
++0.391288617637560 +0.111806520749632 -0.156963205478091
+-0.443069972239868 +0.110148671062525 -0.005257030885166
++0.015828813823078 -0.380503860148529 -0.083756709141623
+-0.392443796643524 +0.023270077607135 +0.009726686725543
++0.118706967196335 +0.075095099942486 +0.023019673199856
+-0.029209898163985 +0.012760472672272 +0.097355320610542
++0.027031247537632 -0.135432570936734 +0.036113579073359
++0.245620990963410 +0.184000287673063 +0.046780385672875
+-0.029681932439920 -0.037317428897995 -0.127334513902544
++0.161219878387552 -0.267038450874394 -0.023535540015905
++0.250462407773988 +0.078042775222701 +0.018760610191907
++0.194123447809230 -0.094332190344942 -0.119038437216022
+-0.132888271584990 +0.304760379071534 -0.022997445413093
+-0.355207046859489 -0.180877358495975 -0.103584989500311
+-0.261601980737565 -0.137506541364753 -0.010745747029258
+-0.047319302924766 -0.037705920990747 -0.086631573927293
+-0.339986151522881 +0.119647425739732 +0.004236869094118
+-0.008881035631978 -0.213913301613363 -0.044179324655453
++0.099597979322779 +0.020977870450623 +0.192624697852983
+-0.847435899993033 -0.026530604244367 -0.016176882840873
+-0.226404271219035 -0.025235149592122 -0.043307184843012
++0.483956905861816 +0.106196784442840 -0.111754146459063
+-0.579238392368731 +0.096704983965293 +0.097615318181265
+-0.543751598977595 +0.030967981773607 +0.003204701364445
+-0.274699684357791 +0.151285886241253 +0.141215193033093
++1.016070819741009 +0.067306168664620 -0.034855336355784
++0.099547249128350 -0.013479309309404 -0.002168166437581
++0.020840091073633 -0.070922438195096 +0.113203666358840
++0.225354858152251 +0.034631085558903 -0.003511919332916
+-0.332259146284977 -0.258028954476310 -0.020900374246486
++0.397691826013088 -0.018039276605532 +0.028828103481058
+-0.053669116576157 -0.005441684102077 -0.188396642009431
+-0.338390844105198 +0.223950901082221 -0.049865011549696
++0.170252691544861 -0.361618991728359 -0.062637380819713
+-0.007131982595968 -0.524390698296863 +0.012767678209551
++0.078659550762945 +0.026153399221955 -0.008199507915816
+-0.008283278675396 +0.033012771482101 -0.173280546244580
++0.242068885194449 -0.053879288117342 -0.147091602215316
++0.061854768443233 -0.011447460357261 +0.009420032869596
++0.015263183919200 -0.295401362656214 -0.025572181377013
++0.093300759669945 +0.192616017763869 +0.029515781298532
++0.251635866109978 +0.308191040368928 +0.051354146969992
+-0.259957465318381 +0.010045637360928 -0.215706295640720
++0.016273221113174 +0.139234169633315 +0.158833215490701
++0.048597193962935 +0.118057100503120 -0.013261389706608
+-0.400074754603980 +0.118063508175681 -0.028239005529517
++0.048635596453348 -0.252011480202466 +0.001642172362280
++0.011831246525319 +0.005139099966525 -0.001107064305598
+-0.013864687150262 -0.365665148501004 -0.033205659409946
+-0.663007411344822 -0.018789853231763 +0.001027391389296
+-0.225572618321903 +0.085019078471840 -0.002384752341138
+-0.020204394014292 -0.041332793953964 +0.163106387759423
+-0.383748815125889 +0.025600419436828 -0.001488365625636
++0.054306928468516 +0.011680676965173 +0.368996355743073
++0.010363831233027 -0.158026037410813 +0.162270880067055
+-0.418949537219110 -0.005110991230433 -0.010869560228734
+-0.514104203921490 +0.124773606430912 -0.006049205205520
++0.017087325773587 +0.175062166542807 -0.016049283269000
+-0.432596130442483 -0.147009486572457 -0.000181627333135
+-0.184397528588444 +0.071344798564472 -0.000069842871498
+-0.026447740305820 +0.095324902607076 +0.236875761761601
+-0.372401146260174 -0.130107923185740 -0.086882992400013
+-0.182878746876572 -0.138630259317978 +0.013244822695775
++0.479999857898911 +0.087601057314638 +0.022774888134299
+-0.113552805055002 -0.079723794024529 -0.042523513710133
+-0.509747163145314 +0.052664892207189 -0.067990922232224
++0.036352419625593 +0.040023204564108 +0.147001438929496
++0.532530448218686 +0.029950559552267 -0.084214353531332
+-0.266015233428274 +0.269239519100382 -0.070345008829848
++0.179716917733667 -0.080823237188580 -0.034266623571449
++0.250693334990791 -0.059448860044917 -0.003860518733796
++0.109072220452676 +0.123666168129720 +0.024874839738660
++0.392500695725796 +0.047997471012815 +0.033456577350860
+-0.819663934401326 -0.128423195595269 +0.102194565166135
++0.033028501043203 -0.261425090173318 +0.026205830663722
++0.193196911696627 +0.018727009360880 -0.132232497254147
+-0.156505876406468 -0.171114434330716 +0.049993016375109
++0.184528566754692 -0.227990236294801 -0.098720859572490
++0.519899172980500 -0.057427845938241 +0.157415466817193
+-0.031361401727117 +0.044076542483753 -0.208008115695708
+-0.616169639903635 -0.008136404451900 -0.016101789880206
++0.113618687972093 +0.079096712582298 -0.069435467255076
++0.048626610782111 -0.311964937841720 -0.073172954488977
+-0.763309447051974 +0.198746799910416 +0.010267582093925
++0.225441257052084 +0.016727122334271 +0.001025154414892
+-0.217945945737710 +0.108863606874823 +0.011900464583545
++0.147067479473458 +0.189916943729750 -0.107747778948211
+-0.058786662558129 -0.287507205888341 -0.001627686681585
+-0.053630149526662 +0.242680308014305 -0.186517380361651
++0.098224566980237 -0.201059850772114 +0.010134564815632
+-0.026323718074645 -0.504113914624997 -0.015967976723720
++0.234746904157946 +0.240049849861963 -0.162612218201060
++0.095755062021689 -0.018991585804606 -0.025309073790116
+-0.100546147567097 -0.039181182372180 +0.048552936456171
++0.063488582156906 +0.126262263487814 +0.150699052849095
+-0.021256637374459 +0.172396560853326 -0.006818758382749
++0.109260158013025 +0.100866953884189 +0.045497517718042
+-0.085846673672854 -0.351061125398404 +0.023317793218562
++0.275645983314982 +0.113064777300362 -0.097742070786226
+-0.036637646335158 +0.387991827469091 +0.137380287051639
++0.186772252267016 -0.028482295755094 +0.158924601321995
+-0.064287725199701 -0.279404318681146 -0.013262116580608
+-0.273038433405104 -0.201680914701494 -0.000974569094404
++0.267116877545622 +0.093708852310664 -0.054449567637391
+-0.031835982690301 +0.050782828370246 -0.009956422894318
++0.117489646157632 -0.188373767785381 -0.000306112088283
++0.068340349138453 -0.236576531922742 +0.065677096058238
++0.505774943149565 -0.071694380249653 -0.001804869215099
++0.377960137512657 -0.057379636153761 -0.041195482735468
+-0.300476838100147 +0.126230682976297 +0.006984371627191
++0.104408165502967 -0.061167087210991 -0.026618635352185
+-0.438659537637953 -0.300531459418877 -0.014537117103340
++0.026991323113853 +0.008455090864188 +0.073582243860298
++0.092423588182547 +0.110432150006685 -0.021159680201287
++0.289938208196996 -0.141863379111299 +0.000860619465932
+-0.164498733462228 -0.020751587895963 -0.274474780263852
+-0.844812422989191 -0.014853793343732 -0.025410815607716
+-0.041736010260901 -0.075269758775498 -0.032593732198993
+-0.167593264930309 +0.003185440375981 -0.000168592185912
+-0.568685669948966 -0.044347134228831 +0.000282947863034
+-0.245697482075293 +0.097290199671812 -0.016573461119969
+-0.066290535410251 +0.158800985133925 +0.133081619078736
++0.171374379899079 -0.044001209599096 +0.004867013315411
+-0.099373376434241 -0.023990589182273 +0.131628633826859
+-0.220285123898167 +0.228676007330505 -0.005771193887062
++0.110998637525712 +0.110746492771682 -0.047694682799527
++0.014055183863230 -0.388957863660290 -0.079350946168572
+-0.042447859295812 -0.135012877418312 -0.059696359829030
++0.345826172252124 +0.104244982318525 -0.003643546218267
++0.028790553865040 -0.042316382607829 -0.039858532852112
+-0.045640984854217 -0.234699013995708 +0.008566607207860
++0.232680831282717 -0.003412987031843 -0.055573635061015
+-0.343667608371831 +0.090582320890952 +0.011526087817954
+-0.991797392190532 -0.133639615669038 +0.009152816967813
+-0.250180105560838 -0.004772362804316 +0.037207041957024
++0.035533265658995 +0.310507529495205 +0.002714886494928
+-0.551480415651552 +0.023687061495787 -0.056828630078409
++0.088055020206540 -0.164738358410577 +0.091939666757534
++0.125613454393193 +0.198701583371430 -0.087316166930732
+-0.029740308540089 -0.053523435428427 +0.053568755410582
+-0.002874444622676 -0.015561774676949 -0.110149243187549
++0.081490852236550 -0.198205200296533 -0.010227669533794
+-0.160808501342257 -0.135680576710394 -0.145250896025143
+-0.899119871759689 -0.013208303454453 +0.010225182526645
++0.024035068724032 -0.298215857731095 -0.057939442309427
+-0.254167740278424 -0.066192205072602 +0.060727661510049
++0.256811457008315 -0.060500531210284 -0.002301586763662
+-0.114576900007692 -0.323707852089724 +0.061726847080759
++0.141279647025874 +0.092772437363642 -0.174506675970683
++0.099791362579411 -0.035108311347661 -0.097017603137900
+-0.167024519060873 -0.049056760993580 -0.143361891414322
++0.537939529410552 +0.335712004603789 +0.000988856776763
+-0.030142129412248 +0.019746332247339 -0.050099699799542
++0.036735691633096 +0.037735372603731 -0.014132040208602
++0.022702505230913 +0.182083088050749 +0.071221179992479
+-0.211136632582891 -0.251727703796199 -0.049905343101766
+-0.153660471015577 +0.069604277465088 +0.048756262344701
+-0.135045755570480 +0.172903387118014 +0.115575660758976
+-0.577011431966933 +0.027999849104300 -0.003483623894763
+-0.130735898463768 -0.325943742642203 -0.000224734978739
++0.074502629961077 -0.229373810128211 +0.185400219048759
+-0.581631279962712 +0.440250595904902 -0.012185296556973
++0.006175939498966 -0.126782898352089 +0.001667360848572
++0.067755250317122 +0.244495930729657 -0.072359559687162
++0.078290923224818 +0.194972687413222 +0.001512184646841
+-0.006599558441106 -0.173072410145073 -0.049747750316433
+-0.004685632381997 -0.011015104850487 -0.213378983485859
+-0.554044677859927 +0.014901758672803 -0.182843091164577
+-0.016926322074062 -0.080102291486997 -0.036048947475668
+-0.257672703212898 +0.081264563942070 +0.263066465457927
+-0.234856085284772 +0.350375494167137 +0.120840586356982
+-0.088174890142774 +0.058831555544552 -0.089972196472268
+-0.209956583395271 +0.215510109432247 -0.090228767924634
+-0.314802630562067 -0.034805454245847 -0.028008434471569
++0.241119390633982 +0.136897704434862 +0.013198320015594
++0.048803044179915 -0.137514075230312 +0.056752039717338
++0.426957694697601 +0.000448397201330 +0.029999866394812
+-0.524601781611073 -0.293076595762746 -0.037810322498784
+-0.027756687578498 -0.280836462760700 -0.019983050241434
++0.201606885143084 +0.178178191859436 +0.009996681618678
+-0.128014235498545 +0.128446567831922 -0.132042557965820
++0.005536478347114 +0.411670420141516 +0.009902645136660
++0.148497299117115 -0.479755898739224 +0.005126474392904
+-0.229133524607037 +0.162809627314718 -0.032428059469250
++0.086688852276370 -0.320545112602874 -0.020882917485398
+-0.511004714287605 +0.013597376573762 -0.017228824293505
++0.023914087655035 -0.036565863861938 +0.009599218713412
++0.402265982748874 -0.044347599561328 -0.163222829663479
+-0.094035039765970 -0.399785908847312 +0.051682518446998
++0.076953908911971 +0.232169313869787 -0.041195354101915
++0.497832512594420 -0.077158049617479 -0.164783384770943
++0.327182040536741 -0.221723938846045 -0.029597582839161
++0.657895464484766 +0.114967879804310 -0.008803768169017
++0.115148338941179 +0.088346498639689 +0.084375203679434
+-0.509242836827464 -0.237800745494489 -0.046329481283377
+-0.706830243805058 +0.244413639363600 -0.025459418677715
+-0.238292422609873 +0.251041491042430 -0.008082567854821
+-0.013606790731997 -0.147275037426234 -0.024133961404291
+-0.165790227455981 -0.448940218869340 +0.060935630638586
+-0.766471452712713 +0.003363257411989 +0.004514650369481
+-0.000742392921359 -0.093543008775965 -0.085031953005243
++0.696934420618964 +0.132790216290481 +0.086177368991619
+-0.010241776549629 +0.187132986044626 -0.064958341535113
+-0.008479250312888 -0.038556200697616 -0.100443909186246
+-0.252966235610533 +0.309131169277290 +0.072588990485513
+-0.134735928537798 -0.066928927022839 -0.090507887607505
++0.061027517742513 -0.057383684849063 -0.174668190401003
+-0.474800937739061 +0.060574405023199 -0.086429278761448
+-0.143692056090757 +0.018328177894327 -0.004247739352231
++0.262434661219991 -0.161346805513170 +0.099216489584523
++0.103812391291682 +0.042463183426106 -0.184944409496554
+-0.442554271641042 +0.003163306539236 -0.001100802789110
+-0.306146101919233 +0.098865953011236 -0.044195543672574
+-0.118147322535853 +0.183449877868305 -0.043299845357027
+-0.118045689568295 +0.084042620795043 -0.144802891332030
++0.008295397902235 +0.185760083381444 +0.138411551183483
+-0.142448923760498 -0.077204418951632 +0.012997922820304
++0.296613265676320 +0.069319435383445 -0.117773398078309
++0.269949415305383 +0.013540781388566 +0.033308083006124
+-0.639483826537211 +0.075003900321367 +0.000852473681999
++0.051572623353513 -0.031005606622728 -0.293089535959851
+-0.040524006335039 +0.039334609665762 -0.084037993133495
++0.055742169868399 -0.074664747201656 +0.223712498632455
++0.104531006751989 +0.012737473978820 +0.232252931351854
++0.284620283271767 -0.054094447786143 +0.090500783582102
+-0.396853399839036 +0.071855494157081 -0.011317913733325
+-0.831447870538021 +0.064927144814939 +0.009326447507717
+-0.360979535681926 +0.135147018875795 -0.032086296024145
+-0.192940576669607 +0.083972148320808 -0.119611593418240
+-0.010406403229875 +0.293548171230790 +0.001700932161760
+-0.040446761159478 -0.027374343100788 -0.147326588099697
++0.255512671302703 +0.005942459112591 +0.058134617064546
+-0.638702691783973 -0.091306599880722 +0.050646438125172
++0.120370763176019 +0.098489575720762 -0.020859403949387
++0.015570894348364 +0.030634413497800 +0.185893901267553
++0.322405679327833 +0.051071540256545 -0.049842207834955
+-0.547791917725199 -0.236328753337608 -0.075039317377263
+-0.183197317542995 +0.215602214875590 -0.091383850374706
+-0.623527374480331 +0.122766424781216 +0.141185316483948
+-0.208407072272604 -0.300473252794162 +0.139622357609730
+-0.015012631033304 -0.147109450195197 +0.026949911161031
++0.086456032972542 +0.146880791565958 +0.169940133702991
+-0.028730016528416 +0.147998343715932 +0.006020348111524
++0.259260906800441 -0.102460028465977 +0.250458727283402
+-0.301185869470998 -0.071095034334584 -0.014913324054987
+-0.017384958367362 -0.124578818098580 -0.002040000512108
+-0.201492575429543 -0.356863320483180 -0.070577934532444
+-0.090548182293119 +0.094046083121716 -0.123085740388406
+-0.014405881174577 +0.025453696402564 -0.113803221671898
++0.006764226474877 +0.306421830774935 -0.058892710079315
+-0.293888549871719 -0.103664157487121 -0.075443677634378
+-0.211934248312241 -0.291761183698988 -0.003895356325750
++0.246273041487774 +0.038150812968963 +0.034431290883686
++0.071693059554258 -0.025853066752971 -0.096225126040177
++0.442259881550741 +0.122934256399839 -0.040695361036668
++0.056719003590168 +0.001852756733900 -0.125559774503803
+-0.073451660667417 +0.298991898448746 -0.134714385151005
+-0.093869277411053 -0.193414674564815 -0.042370407731420
++0.039961536152099 +0.018457045495611 +0.027199932160553
+-0.682095190896183 +0.000476129964077 +0.058594262059633
+-0.097582563333257 +0.080426915131439 -0.000006425966368
++0.706854569107711 +0.007741426466549 -0.176864081647538
+-0.736456920964589 -0.152827220297218 -0.006879850685827
+-0.163264103826273 +0.172702561382118 -0.014642906046026
+-0.047216553354535 -0.123082465068350 -0.037186823209795
+-0.544787826953914 -0.147192059504908 -0.024133937424221
++0.074533645372642 +0.013120314383180 -0.178752696696078
+-0.114200061826484 +0.031093759496669 -0.006957384709660
++0.059276877230717 +0.285092131139698 -0.011182454907102
++0.750938942265044 +0.056960951516877 -0.025661949820986
++0.199782410251556 +0.231962236828228 -0.190647187443986
++0.259721342378100 +0.324640297442265 -0.045842777677341
+-0.282567284680475 +0.110316993595422 -0.027827968919844
++0.039334204688332 -0.343393743087946 +0.052617928439274
+-0.927003225704875 -0.080744029213843 -0.114459657943521
+-0.900279953199026 +0.112775455529641 -0.055531747388300
++0.120057603354582 -0.099222724897414 -0.064043390794174
+-0.015082765879020 -0.004007433770312 -0.308263028050484
+-0.156968211689613 -0.150145675837665 +0.022152565598134
+-0.086232572851062 -0.302759000879832 -0.029457876345895
+-0.526652760256934 +0.079765404771697 -0.058814568171927
+-0.066676805328156 -0.071658044066929 +0.130709034061945
++0.174664797053845 +0.143530274961113 +0.012149596276744
+-0.046428641306685 +0.046659598145527 +0.206854085316942
+-0.004159295772110 -0.140287510731915 -0.037435793282871
++0.040488730815330 -0.050920781082506 -0.154341142342447
+-0.602463669367704 +0.029192349629403 -0.179184238573810
+-0.513544577808099 -0.114494084768034 +0.013628819775637
+-0.002071378802150 -0.465218902796000 -0.033983244526217
+-0.053555101064769 +0.339803308200305 +0.137828910027017
++0.223940847133647 -0.016997094503834 -0.157038647571038
++0.121060597893139 +0.101615474904366 -0.039252781455597
+-0.079330588104690 +0.196284219880256 +0.030323722020131
+-0.060566701380152 -0.245838461363116 -0.065618672839212
++0.868355001176325 -0.091068613227555 +0.021722375214246
+-0.314878843822825 -0.208698985925377 -0.007881420150154
+-0.105049543392086 +0.071960011682062 -0.196989601374073
+-0.140646386367151 +0.203159746716562 -0.036005050554508
++0.057482444364116 +0.086002134259176 +0.052142645240877
+-0.158812808642463 -0.174396808243790 -0.035553917486882
++0.929311409361996 -0.013092691226606 +0.004103403155511
++0.513305701725372 +0.033881659124784 -0.128693214587335
+-0.078126531273832 +0.038566946362504 -0.157307493652740
+-0.609586923235082 +0.010375373575145 -0.008061750230881
+-0.274292195172538 -0.092863124955634 -0.080600562232735
+-0.063616814539736 -0.166182119233658 +0.003301125549896
+-0.080747587471681 -0.231579092652678 -0.056275303411623
+-0.268531139725405 -0.178533244376684 -0.067325314504155
++0.030947605989163 -0.151203840990334 -0.103957408472229
++0.016818515956904 +0.236823979565667 +0.015317873491493
+-0.015144072156275 +0.124780728535233 +0.170375820988571
+-0.377991790654827 +0.001942166288659 +0.015816590933787
+-0.149758758681911 +0.346613468460271 +0.060974843683104
++0.184662614295380 -0.307972270542066 -0.018749042355115
+-0.612066246136997 +0.080286733047230 +0.006465095390459
+-0.037715045359248 +0.082186739586205 -0.048068245751859
++0.433805689423704 -0.236815437333478 +0.091238153101355
+-0.324168826086055 +0.014630557599395 +0.208304940254683
++0.138727200052437 -0.265422209265395 -0.051200111094104
++0.045431037859455 +0.071655630553282 -0.070169425367006
+-0.116748028151841 -0.027886516999223 +0.153714381205079
+-0.037455631802334 +0.071431292167987 +0.104910105717947
++0.036176060573738 -0.469847330534906 -0.003850032817861
+-0.739996163834585 -0.054171296898890 +0.096134094078979
++0.426423010752497 +0.012489722626254 +0.004320662160855
++0.312366985058311 +0.147709956217269 -0.148083853537797
+-0.483653628414981 +0.093431437471704 -0.023657147216010
+-0.105199486856218 -0.514943666568910 +0.005870081950628
++0.124363929321216 -0.043730193092732 -0.050920803145188
++0.110642470345905 +0.316052504449562 +0.001242035836593
++0.029131282089618 -0.501169276173387 -0.000411342665184
+-0.289502324066162 -0.021642728868526 +0.001638587756109
+-0.226498208408650 -0.210199812197582 -0.042870649640308
+-0.119481568311128 +0.056365588394814 +0.091300639204135
++0.352194914845057 +0.084923999010935 +0.166709554028583
+-0.450015776757213 -0.189125076533604 +0.000537222586178
+-0.342400953535300 +0.075644005486684 -0.104027713819726
++0.349231806666387 -0.029396814201224 +0.184571188407011
++0.201027968198953 -0.107425294332570 -0.054620895880672
+-0.200875751764645 +0.143660499128564 +0.146782110136786
+-0.499502294745433 +0.152307903108882 -0.076350085407685
++0.347023666487707 +0.185482632587722 +0.025966125083205
++0.045696234515441 +0.235884560956417 +0.004386696834564
+-0.093736702750861 +0.070834970911905 -0.016440921051257
+-0.005988337956902 +0.088821382227684 +0.237280416902170
+-0.366314955718136 +0.038589616721054 -0.043300431472345
+-0.501534843979837 +0.131669429464797 -0.010720681405454
+-0.432030643164210 +0.156384760219558 +0.068328629407082
++0.011998787299438 +0.502085953914903 +0.007980866700662
++0.012735265391033 -0.469138799606852 -0.042549281448711
+-0.828416780352719 -0.045048456110822 -0.185550532042674
++0.124591407069817 -0.105927502198579 +0.027324564779533
++0.158992101081730 +0.018238680867460 +0.014778911575722
+-0.119955482423457 +0.038939110192845 -0.110502636260958
+-0.221550999601124 +0.243598512921886 -0.067517849422293
+-0.213359723870008 +0.083870241342779 -0.048271593643930
++0.155343013395293 -0.465240208412274 +0.047313831775077
+-0.965192033157041 -0.017725731803437 -0.044954579915127
++0.261034508635631 +0.000878787805152 +0.023737943304679
+-0.182564655233723 -0.384676255597585 +0.065419738689219
++0.125530685204555 -0.456567135212631 +0.042454670747754
++0.003101006144246 +0.204105163990288 +0.011404668080556
++0.014809927861608 +0.130334756075735 +0.083663949775541
+-0.409960131241954 +0.184421398509556 +0.001886728215170
+-0.264025941152570 +0.257036553291497 +0.167953386484670
++0.099787262754252 -0.308307140131653 +0.063167393122236
+-0.727322713733805 +0.006672025070354 -0.120493147603528
+-0.254000329077643 -0.017288046220475 +0.265434192225857
++0.078436953284139 -0.391006925373121 -0.027333818828893
++0.224258540728921 +0.014289232357317 -0.016096120923538
+-0.058116175097364 +0.199706584312916 +0.272458308301538
++0.250917646617864 +0.545297111062064 +0.002462001143384
+-0.006856325853570 -0.103090914655000 -0.037152320290095
++0.030464283971086 +0.070574900631691 +0.048354286436786
++0.008861479932583 -0.180766904638040 +0.005187546165558
+-0.231291261956382 +0.313360463848205 -0.003043008559209
+-0.371223504925709 -0.124353070464881 -0.047098082450568
+-0.048131945252929 -0.043620629432597 -0.100558505073862
++0.557355163462429 -0.012853992316194 -0.088300880568540
+-0.117116486654453 +0.134928244592440 +0.102697588066142
++0.004512870713201 +0.005840782307534 -0.179549843207152
++0.185856125663011 +0.013757399689536 -0.154472480390404
++0.371520600196871 -0.288160432003990 +0.001948677444767
+-0.340634179166450 +0.252375756288407 -0.030823203916947
++0.202235280502008 +0.077560155477550 -0.021267889116675
+-0.157400471045774 +0.263561410973284 +0.078685776996592
+-0.583503031599238 +0.030091599196278 +0.134195137325893
++0.055703499715986 -0.032024681852599 -0.069655851666565
+-0.118281317536679 -0.002896760888138 -0.046735941701868
++0.068331538293116 +0.112434700138173 -0.043643028195165
++0.436470626162909 +0.010191447582563 +0.002197915093858
+-0.073958236493862 -0.219816485055721 -0.031902858076918
+-0.502389022457299 -0.100418904602312 -0.054942368664405
+-0.069608695397508 -0.015603299849529 +0.043785543664507
+-0.613405458412364 +0.081674985541601 +0.090519480992139
+-0.559051925076665 +0.178573698466338 -0.028154569559671
++0.252850051532922 +0.134934797123601 +0.072059846607498
+-0.687076769529799 -0.255372578821065 +0.028418121155486
++0.079207874248902 +0.305312565267078 -0.014388284094208
++0.106671053009276 +0.172642938075833 +0.045595497409570
+-0.036894426281417 +0.232497082372700 -0.010461680623318
++0.062642111068701 +0.043853983211583 +0.301615911016879
++0.197993951306887 +0.524345818107805 -0.005512755241949
+-0.251305229117820 +0.089846711831570 -0.159646866175352
++0.598383638269536 -0.003160653860043 -0.153087360617810
+-0.725243671516690 +0.153528585667888 -0.007198199641613
++0.291296932724895 +0.012513897018718 -0.037401079219036
+-0.045895439007587 -0.133537766429145 -0.197059228696930
++0.118772525505912 +0.184789876965122 -0.006931480300858
++0.171038543064646 -0.327124264062575 -0.048109094945798
+-0.234182497335614 +0.112131601681329 +0.141947310213501
+-0.294324290830902 +0.417593049282110 -0.020556840904453
+-0.101129011712908 -0.097865255752287 +0.031654609826296
+-0.409271927905000 +0.197632934363608 -0.078979702210482
+-0.001391562683807 -0.335989656021490 +0.042927406861607
+-0.362577457751238 +0.171072446831065 +0.013992088848735
++0.159310119329960 -0.169269942164035 +0.040407945370164
+-0.342473693908578 -0.211861250781546 -0.111636206386728
+-0.154726095450670 -0.008004220789959 -0.016629227061216
+-0.470704491639427 -0.102167248831934 -0.108251794135706
+-0.118222002672259 -0.019561629302158 -0.115401418455709
++0.080125645465674 +0.104445574679314 -0.048466499881605
++0.013968253763315 +0.152145285681174 +0.001567133560934
++0.575780628487678 -0.051532371445010 -0.083437440964868
+-0.378335511444970 -0.163114492575318 -0.108041594191072
+-0.022666706947887 -0.015020871216237 +0.002098547704424
+-0.058930591429364 +0.027448114870401 -0.038645772822695
+-0.440787531065254 -0.239196710827489 +0.022157182972948
+-0.667906910453254 +0.124510212529352 -0.028254902410309
++0.142204540090283 +0.215835998415983 -0.031327252730441
++0.152968433440898 -0.173174133293170 -0.029227347678298
+-0.295518387989495 +0.191191564212455 -0.027023596702743
+-0.345960094849269 -0.002377680472783 -0.053195474595761
+-0.014941370407678 -0.056179747986674 +0.092810873271827
++0.217295645263685 -0.319139583491271 -0.037323103212281
++0.353293684580502 +0.002971443577915 +0.023724037384833
++0.082169254011811 -0.141519606655889 -0.019236182417189
++0.317194646815410 +0.129161609958658 -0.090180812370035
++0.050726479556737 +0.029720649437396 -0.280373354522186
++0.548889972209257 +0.189946355681670 +0.002705264647036
++0.271077264386130 +0.028865275580398 -0.044223256399454
+-0.312641071965167 -0.056215107039283 +0.004283965784408
+-0.232495141256836 -0.007437185204174 -0.058930746248019
+-0.411882100651819 -0.020684354307521 -0.054256761625470
+-0.417209292982392 -0.268979814980259 -0.023213142924538
++0.159329692351519 +0.274484869430918 -0.029918145694609
+-0.485213877743053 +0.036293384508252 -0.205001259486777
+-0.064229706554584 -0.033595504594315 -0.010763872462738
+-0.109196960017459 -0.067192359195230 -0.036390023894745
+-0.015336786510635 +0.035976656895079 +0.015383252889940
+-0.353273583596274 -0.129811517075720 -0.055632039843650
++0.029567342076167 +0.157181332035308 +0.129846317873012
++0.020963160348747 +0.024128394864117 -0.047230035960588
+-0.222096161181902 +0.055684320440607 -0.035536484654644
+-0.073369394573193 +0.049673338278463 -0.028855555399384
+-0.636920298318053 +0.080239119131748 +0.000862598506822
+-0.370894116896358 -0.041026698921270 -0.026058423398817
+-0.456919363230395 +0.001486591931437 -0.032879535015518
++0.093852984120236 -0.104328471847336 -0.028158792799346
+-0.170941451916732 -0.148066405163696 +0.150401330300942
++0.147923997621238 -0.364405985685684 +0.111457001363833
++0.526216508149200 +0.107921815412704 -0.037951697411792
+-0.157740232272368 +0.056389000715088 -0.043132686052409
++0.317785340585990 +0.126594244569778 -0.060141699643805
+-0.277092352297929 -0.079923228294528 +0.211900985511143
+-0.221889800371270 -0.061456829197476 -0.024805088233982
++0.556399752841031 +0.002818981763712 +0.139384088183072
++0.016759787425243 -0.121716586356635 +0.110137988844072
++0.537950728794777 +0.215216848271652 +0.002130508030519
+-0.281280364878457 +0.028790709902867 -0.008993576944094
++0.171892661984256 -0.250294964256480 +0.006104203759820
+-0.894354098520726 -0.005822386017233 -0.017975490276183
+-0.036029843148626 +0.208024782713875 -0.191517845144261
++0.019780164080904 -0.084366642240799 +0.318933041328097
+-0.210037914973248 -0.116745560393853 -0.014082968177707
++0.419916514819640 +0.056011482428381 -0.115996179267036
+-0.560860997800187 -0.026965005823637 -0.014769826747211
++0.011045243636879 +0.181230309133664 +0.035570900752734
+-0.425057151622011 -0.106808147677004 -0.153286143032552
++0.242412939141691 -0.102432575414209 +0.149399299756263
++0.182796946310256 -0.048622844193171 +0.238799379545818
+-0.063927021752180 +0.202994355638396 +0.073835527875492
+-0.483496900279532 -0.239332364555913 +0.074416226821172
++0.085602189888867 -0.127108604696113 -0.010793068515786
+-0.022071460351141 +0.130745785564997 +0.360804637894654
++0.066119124573878 -0.014798629058339 +0.076785553874137
+-0.058727194488249 -0.226681686285565 -0.001899103207336
++0.028884392465922 +0.119215850905408 +0.087416778343629
+-0.193583910489030 -0.386003833480023 +0.021990277131364
++0.673813503458268 -0.069908187759977 -0.022402966205186
++0.185831681783585 -0.105323175818839 -0.018479773649246
+-0.220454722349769 +0.170244334973572 -0.018354073716883
++0.045737023921898 +0.060785754620485 -0.018914652181466
++0.000878999708831 +0.071885139866992 +0.072861917356980
++0.425013497533871 +0.073559848604211 -0.070029055554516
++0.045214831753995 +0.097434291572672 -0.021770855948222
+-0.224602055226104 -0.011730039801631 -0.074901326894593
++0.053757135283886 +0.016660873655336 -0.030088062300517
++0.094486132811829 -0.091073871964948 -0.025477653775392
++0.274049042163695 +0.127250349337372 -0.038078582276846
++0.300863559097880 -0.016424614268713 -0.015414761541598
+-0.246784522890658 -0.307994030353878 -0.101493369440822
++0.139275160076316 -0.389316830540257 -0.000255615318494
+-0.106659643119429 -0.202190385800130 +0.036312968582529
+-0.017629945802591 +0.109311321040759 +0.054021447582872
++0.424190410844513 +0.001452301202245 -0.014061164167356
++0.403738067017334 +0.012737209177775 +0.000901265939755
++0.411513201915992 -0.263463485801715 -0.006886698284416
++0.405612262262291 +0.178649459767235 -0.124832028609615
++0.773751662539612 -0.046195417329307 +0.018871138706139
+-0.127104040831748 -0.239948825442744 -0.029578193203223
+-0.137480726689922 +0.066897220885460 +0.235335720630258
++0.034381924916538 -0.143895840523954 -0.016549256662856
++0.432225283674056 +0.058490778177409 -0.173259053440746
+-0.224146965681035 +0.271454464816945 +0.072268807742536
+-0.150825530845099 -0.186378562681977 -0.089466016406505
++0.078572819374175 +0.081917149640947 -0.051446884914596
+-0.043155499491400 +0.051521855597894 -0.100833458321420
++0.270916983137711 +0.149573711451602 -0.077801636978510
++0.203956977554149 +0.054878431185026 +0.020756629283201
++0.814894288549234 -0.048898231982685 -0.006956983912525
+-0.423435000306772 -0.022934430141635 -0.009524649541704
+-0.176709676088506 -0.034279199605751 -0.109772145558402
++0.264274037080178 +0.381487697366083 -0.136434115858306
+-0.412281675756144 +0.123490748562618 -0.087149205068247
+-0.463153795170111 -0.184036439927920 -0.235240770652677
+-0.324591284949303 -0.121097695178322 +0.008228869159481
+-0.039578160067860 +0.032789821651196 +0.100272682296235
+-0.086472921830812 +0.094591261225961 +0.071306339875428
++0.024308479584775 +0.083998405312319 +0.207713692865078
++0.187128841722988 -0.102511287713232 -0.050264153701149
+-0.243205104259989 -0.005183832772267 -0.054084914595252
+-0.006670292575183 -0.174386456642054 +0.086829055657727
+-0.268899444608086 +0.054867153594836 +0.049785998739248
++0.135126837160896 -0.307008215485775 -0.000654068703216
+-0.257905189179258 -0.148357848975946 +0.193258589575836
++0.273176849117906 +0.039201616707163 -0.007949892054934
+-0.266009249499450 -0.051460290836389 -0.055991905734501
++0.181547499984032 -0.078005406895264 -0.005308582221715
++0.253627509146201 +0.049176254845768 -0.025157854456700
++0.080316750707888 -0.229107404646464 +0.070547089486064
++0.344360387180163 -0.028838242185000 -0.036300110766030
+-0.756566163779815 -0.031638813901892 -0.004532139712003
++0.657279650498367 +0.164197428180576 -0.011932238531965
++0.144644935803199 -0.004830783419559 -0.014281917138185
+-0.021428845768806 +0.007706918536251 -0.068269352212480
++0.054217232839539 -0.073291879301503 +0.024703288952277
+-0.038996407116548 -0.309974813511479 +0.086306937621623
+-0.100019137864718 -0.049096222899768 -0.042161411244879
++0.057876578561827 +0.012827347511830 +0.060337362560130
+-0.003541117924488 -0.137142604914921 +0.154706820424152
++0.060923634337156 +0.005425540590712 -0.142475337138507
+-0.262558867587489 +0.331452169746188 -0.048776929006927
++0.062946632383236 -0.104614400151826 -0.052641842506273
++0.116501522667138 +0.319169837331167 +0.024485303327204
+-0.230929799894058 -0.113164042349635 +0.059438064975927
+-0.223304404917167 +0.123066698880367 -0.046061327623838
++0.059717491347369 -0.013809539240471 -0.012129724630420
++0.386616542819304 +0.156010053150954 -0.166760004956240
++0.323999590786770 +0.013508275962268 -0.003674121078224
+-0.293827749242176 +0.060455355939692 -0.313889919601418
++0.002998334857380 -0.201411458102297 +0.106205387556003
++0.002732617867191 -0.265093500365297 +0.036103831142998
++0.045378706016809 -0.027552478417705 -0.065174839710138
++0.261514894047590 +0.049323281594819 +0.302696714962219
++0.735309797131247 -0.077046330122311 -0.001911377493477
+-0.500270796879026 -0.081433994181416 -0.106668972748018
+-0.352553350249844 +0.138525121083369 -0.114929695825876
++0.150056556011775 -0.299455984639074 +0.034435862006659
+-0.207512828287791 +0.048071146865052 +0.042683015534364
+-0.522714231156500 -0.015996344350123 +0.003944549111573
+-0.005812251930025 +0.260626681440037 +0.263309412155407
+-0.296413583744094 +0.000971478129105 +0.276038429284472
+-1.161044218545410 +0.040912545379735 -0.015273369439142
+-0.011862366051030 -0.355018905690052 +0.078107923846407
+-0.210388631047390 -0.161583438417888 -0.175841801762590
+-0.332039220932471 +0.211447076419458 -0.095964689244701
+-0.578704899286281 -0.012200195750349 +0.007829818261199
+-0.085214797929388 +0.051013867674724 -0.049338398985607
+-0.380075732022014 +0.066090236235382 -0.148674024132824
+-0.096752017596439 +0.062870780886253 +0.159733832482168
+-0.025553077882969 +0.044575124692870 +0.028007157501263
++0.083934216159323 -0.180948266908263 -0.002399926278488
++0.012323413569048 -0.045019412990928 -0.160268972245644
+-0.825296740159534 -0.201371626082139 +0.007710710945137
+-0.013826697035652 -0.175888230885711 +0.009108256662837
++0.182472014908354 +0.177676018227151 +0.071954153891324
++0.085982616443984 -0.340035738690630 -0.069162768413001
++0.153629781792871 +0.233631132639657 +0.038591411407654
++0.138114889592277 -0.050821174662028 -0.013057953814225
+-0.032667503859360 +0.278135000417629 -0.039797405618838
+-0.076726350311853 +0.192590422222574 +0.141424588879026
++0.171461991793196 +0.200088726990056 -0.040182718416706
+-0.294904640367256 +0.027315292035292 +0.002546528685888
+-0.122509218084539 -0.274242735505705 -0.055329892682101
+-0.033236047062799 +0.089975561923694 -0.072607750527254
++0.040114349392391 +0.086199053051972 +0.235745097048428
++0.396361852274446 +0.085609867388421 -0.062865232701573
+-0.054155320687601 -0.227714071572183 -0.012013293601678
+-0.189214190246110 -0.344445646054511 +0.005159618078592
++0.100430306163415 +0.397691610491289 +0.036009906239780
++0.464311606267021 +0.059331243307876 -0.086098187443796
+-0.125047469369781 +0.221257571060639 +0.146922595226565
+-0.567564906220752 +0.047326556897735 -0.086242777073471
+-0.138622142409721 -0.151711017935686 -0.031447786828469
++0.168503048094828 -0.227627095862226 -0.014290632799880
++0.003560637601608 +0.005872119868329 -0.044193050018124
++0.260635921351285 -0.068628517484952 -0.079046935841747
+-0.077799048904400 -0.162100976042575 +0.105824599926001
++0.282816633992382 -0.069449280100839 +0.011462726599629
++0.103640102276238 +0.088275226135427 -0.000896663760230
++0.156475810658740 -0.147232392685153 +0.014997260216388
+-0.264105486276404 +0.159861359533046 -0.046611003456292
+-0.073274839221168 +0.136365509762934 -0.025883236564576
+-0.472392810888397 +0.280603987515899 -0.005002060958109
++0.204957210901274 +0.059348232382609 +0.273822189123857
++0.202243351392114 -0.074946385535914 -0.052098204436860
++0.072456757448570 -0.035275460551109 -0.049199333310220
+-0.382375231620416 +0.413595550846206 -0.008611396660609
+-0.173759013277618 -0.234811598718518 -0.084363321969584
+-0.337072374399401 +0.155237651955106 +0.038920140359319
+-0.052827118430860 +0.009479434915537 +0.002909321024338
++0.027682427312927 -0.053939383161786 +0.251670290952871
+-0.340497875390561 +0.083556949408469 +0.079517376131028
+-0.329136793976358 -0.116531727680987 -0.007084256600142
+-0.553880571215108 +0.137017886803605 -0.006978085129461
++0.171388411142796 +0.137101150043678 +0.070815423033408
+-0.134648666432263 -0.021270796081686 -0.031984734901421
++0.065943132119144 +0.046921295591956 -0.114145806446746
+-0.270544770160556 -0.006741159643500 -0.052487361939751
+-0.028480885768938 -0.252570334642795 +0.109680726778321
+-0.024356490816467 +0.220477015988814 +0.144621899897799
+-0.085137415692994 -0.491201553620348 +0.005645907373875
+-0.221715518330471 -0.057929583984079 -0.048413082119152
++0.277159843639453 -0.115205484982318 +0.233160190694388
++0.185809768249169 +0.132791382630811 -0.116157983336280
++0.145372626802738 -0.003049536550543 +0.057484786340038
++0.197468897360371 -0.254415040366531 -0.076811665147566
++0.187071335553099 -0.016602823979010 +0.195133434841862
+-0.510827036513650 -0.220829114331985 -0.076354099469730
+-0.434592019861384 +0.021196897038596 -0.175112024389575
++0.242999529092930 +0.304089492092243 -0.021600041549195
++0.024654908158065 -0.043168486657517 -0.006376173826106
+-0.179811372339188 +0.215716203253382 -0.022326612332988
++0.274226576501502 -0.013347407056056 +0.149373457404179
+-0.563099668707361 -0.176153101545452 +0.024473014202071
++0.129526236995052 -0.021640432241372 -0.070318782996545
++0.735229244006141 -0.105943812619067 -0.007189871814059
++0.430260351321558 +0.253211569269551 -0.035165524084479
+-0.071057532320629 +0.270720469735109 -0.072271578617406
+-0.783219941543754 -0.005302900997304 -0.111437959640031
+-0.662023913727161 +0.203145527977060 -0.012550812405809
+-0.126443726871563 +0.451966505908077 +0.005163375379687
++0.048109484611832 -0.189046246387032 -0.012683407255268
++0.239380430747548 -0.292816520926742 -0.083727703493744
+-0.535635080259132 +0.003898364324837 +0.022970357285860
++0.231612858659823 +0.143070749149633 -0.274081814121206
+-0.182459611920424 +0.164791958462355 +0.025708297497479
++0.107033942905879 +0.159781231887353 +0.075979463906239
+-0.001270642917921 -0.166268313027383 -0.016657467656474
++0.111614788285316 -0.200703933447279 -0.079272913473789
+-0.054016510404329 -0.135277540902629 -0.111087886250660
++0.347323659840901 +0.012402371561693 +0.095183420561167
++0.016400504710816 -0.090258051899284 +0.070395384507882
+-0.467395342048347 -0.005398204440878 -0.092734649185299
++0.149077835171075 -0.090072276525632 -0.005870372809503
+-0.025218929731044 -0.179104972821433 +0.093074431437436
+-0.466570308105246 +0.022110586953743 -0.090610291549515
+-0.007183284217993 -0.042405118176912 +0.128532109077774
+-0.312778180778919 -0.162522150966117 +0.163546909586671
++0.178560383863511 +0.134214841878500 +0.167976870173682
++0.695326617742266 -0.038480142875976 -0.081608041921759
+-0.224926015937157 +0.189069631976348 -0.060452330887153
++0.342789985078392 +0.124171866714110 -0.215681700945073
+-0.234914005974163 +0.391176277611994 -0.038686422233715
+-0.071800530440146 -0.366956423598116 -0.002423347507952
++0.095052313256293 -0.392693351600493 +0.080602674978117
++0.003278525590588 +0.007679579601555 -0.297097987814990
+-0.097498250332690 -0.091068585341662 -0.118296822260259
++0.015976973833461 +0.031001385590870 -0.226000640638729
+-0.071577223232658 -0.193018423812336 -0.009368997485194
+-0.081051346252674 +0.297825731528811 -0.002757986042542
++0.094735139914529 +0.087878994441518 -0.021133192515979
++0.008304691978877 -0.100264902202444 +0.096528630389040
++0.188832122908433 +0.169938936530512 -0.005880545849787
++0.239806403599668 +0.029958923660383 +0.109644441251767
++0.080491579831459 +0.045189195792702 -0.020729402791175
+-0.363974971418780 +0.037926948441624 +0.003981215852172
+-0.065582463374749 -0.001887616994991 +0.039739421566453
++0.148401180379440 +0.226522456721575 +0.068098308427438
+-0.276146366123536 -0.040068305486256 +0.000702471724688
++0.235654942155816 -0.003819215688357 +0.040511535544973
++0.131181649272618 +0.084576156103983 -0.041127625716313
+-0.904474462976493 +0.024242792775222 -0.010937777321143
+-0.300640108811024 +0.130085954340135 +0.192246787586341
+-0.000028542157950 +0.192587937243127 -0.114205170880677
+-0.162694432760360 +0.056352957354942 -0.123692268610674
++0.130735684000834 -0.025480950397311 -0.063598826636674
++0.024607375678238 +0.010138113686651 +0.125499163569408
+-0.127823919470513 +0.023435425608948 -0.073869504368503
++0.015704081039673 +0.036550489209007 -0.393097741954416
+-0.282100436319746 -0.288510874963269 -0.039206967395426
++0.052127283158309 +0.076720379991462 -0.094488675016474
+-0.236410948142831 -0.091527060062866 +0.305185111337941
++0.133611351883953 -0.050020690659449 -0.067135564578626
+-0.432429948820302 -0.046521378545076 -0.079543751262235
+-0.504372951698694 -0.000480468824412 -0.035966228867500
+-0.619067939036726 -0.001145632340303 -0.095661865089979
+-0.779837515979347 -0.048728821760276 +0.037845607884523
++0.336748736254773 -0.354699963174956 +0.024670457906018
+-0.355847913673226 +0.105332375383365 -0.001352108813923
++0.068422392342008 +0.001827101410932 -0.187296571439715
++0.219016683885903 +0.008985800841300 -0.182141391746802
++0.642889957703262 +0.007952777296440 -0.022489197967932
++0.020371758527134 +0.047577046817192 +0.017905959785719
+-0.517499821083211 -0.203664052003304 +0.052781486179645
+-0.057380227766412 +0.031458099395698 +0.002922691782973
+-0.816991870563423 +0.111725048626546 -0.033703421675107
+-0.176363461686778 -0.002166661462578 +0.020833631718454
++0.567811419813490 -0.105278208585539 -0.002793878870881
++0.186054145483072 -0.013235124293635 +0.020320950444960
++0.055505920592537 +0.057448346036590 -0.033376913491522
++0.085896828521766 +0.156860563020284 -0.089208960432234
+-0.132711646592164 +0.265400978078222 +0.034725193656972
+-0.324730002174443 -0.034067648080764 -0.055425669052127
+-0.296322951978072 -0.126494856152486 -0.003253660489169
+-0.301689400505900 +0.147670978948833 -0.055398037430902
++0.025764763209148 +0.049570865989398 -0.057688080863241
++0.090802037792437 +0.124972502822476 +0.123342967051300
++0.059038432487723 -0.054880631143881 +0.196141994837098
+-0.042450032270522 +0.080910028270428 -0.073244779380374
+-0.060076345109675 +0.043765889873844 +0.110247064494708
+-0.058719065940829 -0.184943451898282 +0.051086278633231
+-0.032234961503318 +0.003134944448758 +0.109465717069202
+-0.273617780488066 -0.115985145787816 -0.024994158440078
++0.009249759901534 -0.216831444259360 +0.006686451380521
++0.022447706956079 +0.060915592455377 -0.047095849199087
+-0.324108258323784 +0.011550163970115 -0.061560100659394
++0.336728042315705 +0.318030697212546 -0.021472790534425
++0.031828024183365 -0.072188472320295 -0.021133297447420
++0.428882877823111 +0.141479443095415 -0.009384469943244
+-0.230221860220794 +0.169583551929499 -0.039449766251944
++0.163410642392525 -0.156027420867813 +0.083922271417633
+-0.357017719492039 -0.029591714250147 -0.187037812611329
+-0.371230186258824 -0.001469416135648 -0.030027400020826
+-0.858967471547883 -0.026818888472088 -0.017984306661750
+-0.005209329212237 +0.145458358770612 -0.001378317381134
+-0.534232462126347 +0.024378558918725 +0.108553322974810
++0.016584355482336 -0.053586009858372 -0.054108960284839
++0.125547522092977 +0.183873368690911 +0.033336624139887
++0.352254819215459 -0.005864587756072 -0.117577452889220
++0.003871789771750 -0.153408300466241 +0.067812070779116
+-0.224202779636651 +0.179029646132558 +0.008138666470157
++0.326296801097099 -0.253049165248960 -0.084448718722810
++0.084637441685923 -0.004782994405042 -0.116508533741225
++0.102173236975690 -0.055523289035784 -0.053106620504266
+-0.049666604334607 +0.213058645709584 -0.012258011969809
++0.053585892579708 +0.134441273265027 +0.154030887103886
+-0.205950923016619 -0.331209988255579 -0.083752363229736
++0.505905278168061 -0.040358874592229 +0.162610521425768
+-0.085341235388068 +0.378323753730632 -0.017440712264897
++0.176544060933760 +0.003957376595986 +0.003687664076300
+-0.056254444290068 -0.191068252733696 -0.053197258476539
+-0.397842846380725 -0.232155887962585 -0.008762782970287
+-0.376398010632342 -0.156520738360040 -0.000481283001720
++0.214531335964504 -0.035677111767271 +0.075484712280081
++0.224910679049030 +0.015319088339567 -0.054966763763811
+-0.186311086325385 +0.050177208115372 -0.027335021736086
++0.148328504821869 -0.142918472698433 -0.028373197496301
+-0.385482604001206 +0.073027769589289 -0.009819573850287
+-0.077800438724897 +0.028304796706274 +0.418801452686525
++0.207573932494668 +0.015361831505545 +0.111086166343934
+-0.311754701049249 -0.200800457828994 -0.176401835236880
++0.062334336822366 -0.031495051136414 -0.148644645401261
++0.197355445379473 +0.009030253046124 -0.028582274238871
++0.112055013317388 -0.221331508492375 +0.063682866689031
+-0.007771966317474 -0.344533947438234 +0.005975311227784
++0.439916750689965 +0.074141550202205 +0.001909861120861
+-0.094681761896387 -0.332154176797292 -0.059135248300224
+-0.111900929233158 +0.012285659734841 +0.110292307230888
+-0.046376024864987 +0.306832471465620 -0.023662558245152
+-0.740513011733433 -0.000855177511579 -0.013807813387607
+-0.000149350078206 -0.144091353092417 +0.198532788060624
+-0.571730874934782 -0.014341461099986 -0.013904908375038
+-0.100715349698244 +0.246855081095151 -0.028671672623400
+-0.031273432242684 +0.038017569053828 -0.251872546654841
++0.766728134550305 -0.128398273929749 +0.024345658028022
+-0.363552629276877 +0.167081956835051 -0.005458151929367
+-0.019100736286716 +0.074735878444227 -0.003608788575538
+-0.124658270999572 -0.016090693654427 -0.203654972546549
+-0.295788284503572 +0.058112430900700 -0.097165674390747
+-0.012988321744161 +0.066880012587466 +0.076725515713611
++0.439885587899885 +0.322088867772629 -0.022283590056405
++0.056260401201406 -0.115459050527143 -0.022643890865046
++0.074151775525108 -0.451948858606506 -0.004664276112383
++0.210579137179064 -0.187299203538662 +0.018460207262639
+-0.171031644865640 +0.044447567965259 -0.004013629464991
++0.067387254018817 -0.099998114074636 -0.001578545634356
+-0.513347905485675 -0.196066723431753 -0.016037062639579
++0.207674141444625 +0.210441226341106 -0.072798710491440
++0.086123874199987 -0.218904586828645 -0.001047832902139
+-0.364519940593780 +0.041280180985794 -0.025488184304024
+-0.716909416447065 +0.016735889053926 +0.163082505305123
+-0.720684766982309 -0.023473234398051 +0.056243472736286
++0.109849147127981 -0.047230974221772 -0.004456436464991
+-0.044249285473488 +0.150364027052729 -0.136152251221739
+-0.449705249611733 -0.027809596427876 -0.000251388725381
+-0.037667293264888 -0.121834391152166 +0.374339053466073
+-0.272207327363336 -0.213684963888856 -0.006075212900449
+-0.026245764516384 -0.008304548971253 +0.059304463389540
++0.248829834945644 +0.028063828450023 +0.076463151171974
++0.044788638258332 +0.132955206513087 +0.008139330525869
++0.064171001917827 -0.307389040774479 -0.002204796471339
++0.021156620203668 -0.015436261765566 -0.266755849757402
++0.198317932318319 -0.010295162527497 -0.164578804437330
+-0.032695540238535 -0.118357253162590 +0.329210322841371
+-0.273276152771419 +0.069583439587142 +0.005733450136346
++0.039403164129709 +0.151174208048962 -0.079941131547506
+-0.628240074861476 -0.031986933480469 -0.007055429456465
+-0.009714758594901 -0.003768595749866 -0.101609846062381
+-0.271867064901944 +0.041193975845459 -0.035505533828844
+-0.187740220110112 -0.248370288039113 -0.062881383847810
++0.125912902779689 -0.004441330621028 +0.015374721783973
+-0.460339840946028 +0.055024153529852 -0.004518729853290
++0.074913704333005 -0.100941383364758 +0.152386429343086
++0.092908591089076 +0.057883937996206 -0.091659078387188
+-0.002992041673758 +0.129107599007214 -0.070158134676269
+-0.416186782327417 +0.135045975865297 -0.092601436088845
++0.235456185154831 -0.251904139612489 +0.230676765545888
++0.162682006019889 +0.036053552472132 +0.120414195940534
+-0.110875162391152 +0.063566644874780 -0.037097740137337
++0.171357296184676 -0.020300008744931 -0.014679566618294
+-0.373353534328056 +0.093658123146904 +0.010685751364453
++0.116435227451657 -0.093464918787414 +0.020582421968829
++0.344336222570148 -0.089613472124130 -0.055367399058762
+-0.335408079915309 -0.092001539822727 -0.049162527753831
+-0.031947680442232 +0.000965424847991 +0.042650108254608
++0.108993643114660 -0.116559273618539 +0.047482356281843
+-0.321487701169480 -0.056399140750337 +0.022944811992080
+-0.041629819965635 -0.318127917989601 -0.023190162211199
++0.065241475322277 -0.018901740902846 -0.186420487757531
+-0.593545566834790 -0.161251843719063 -0.000871399356027
+-0.584213758209950 +0.137319087239845 -0.051544362834602
++0.087044521329586 -0.053004055491136 +0.207220291792629
++0.358613564959432 +0.018826390718043 -0.138800278503036
+-0.207792166820913 +0.002201987759713 -0.096178500190727
+-0.365502145777875 -0.061309927831265 -0.079205750793235
++0.119336475077229 +0.016298533232945 -0.016132300497943
++0.185902263004146 -0.142400823743830 -0.114224034889187
+-0.052702651971941 -0.284862613433627 +0.028800916331545
++0.129823832631535 -0.199305981071719 -0.020775603780361
+-0.079863584943981 +0.064894449185526 -0.091072531931338
+-0.315586018930566 -0.054708148019179 +0.011464565913293
+-0.042453573646784 -0.314553547198861 -0.001237669261269
+-0.173247915494097 -0.035364592623672 +0.071413829164276
++0.798640657998853 -0.041051866629724 +0.001956985490555
+-0.067931887956905 +0.004923838948389 +0.022924462032258
++0.039573154643230 +0.182499003940546 -0.027399990952735
+-0.636781147072271 +0.002453296873542 +0.021434440455829
++0.268106617532487 -0.013242650394906 -0.133901901144749
+-0.525395499198998 -0.060630041249370 -0.019735547526729
+-0.164683928381662 -0.322000817136769 -0.059295276530966
++0.140199429787841 +0.176275362185926 +0.008590048917531
+-0.137278118184342 +0.158928939794725 -0.171928215947468
+-0.013238583159609 +0.008904531178354 +0.147890725201095
+-0.086392073725742 -0.022088821791991 +0.002882196728879
+-0.088598912532618 +0.460735864599342 +0.000188315946834
++0.074713475544337 +0.005283075872863 -0.017236231359845
+-0.115137340370272 +0.013048333763878 -0.128527933016751
++0.425057738619904 -0.060756811852297 -0.142973291830913
++0.004058939625730 -0.255058778004041 -0.039043492426601
+-0.415854718056840 -0.303584043372968 -0.022003226508279
+-0.196107281181374 -0.405237166635975 -0.027407184769190
+6969 
diff --git a/tools/dump_cbuffer.c b/tools/dump_cbuffer.c
index f7c6858e..6673bac4 100644
--- a/tools/dump_cbuffer.c
+++ b/tools/dump_cbuffer.c
@@ -8,7 +8,7 @@
 
 int main( int argc, char* argv[] )
 {
-    st_Buffer* buffer = SIXTRL_NULLPTR;
+    NS(Buffer)* buffer = SIXTRL_NULLPTR;
 
     if( argc < 2 )
     {
@@ -16,35 +16,35 @@ int main( int argc, char* argv[] )
         return 0;
     }
 
-    buffer = st_Buffer_new_from_file( argv[ 1 ] );
+    buffer = NS(Buffer_new_from_file)( argv[ 1 ] );
 
     if( buffer != SIXTRL_NULLPTR )
     {
-        st_buffer_size_t ii = ( st_buffer_size_t )0u;
+        NS(buffer_size_t) ii = ( NS(buffer_size_t) )0u;
 
-        st_buffer_size_t const num_objects =
-            st_Buffer_get_num_of_objects( buffer );
+        NS(buffer_size_t) const num_objects =
+            NS(Buffer_get_num_of_objects)( buffer );
 
-        st_buffer_size_t const num_slots =
-            st_Buffer_get_num_of_slots( buffer );
+        NS(buffer_size_t) const num_slots =
+            NS(Buffer_get_num_of_slots)( buffer );
 
-        st_buffer_size_t const num_dataptrs =
-            st_Buffer_get_num_of_dataptrs( buffer );
+        NS(buffer_size_t) const num_dataptrs =
+            NS(Buffer_get_num_of_dataptrs)( buffer );
 
-        st_buffer_size_t const num_garbage =
-            st_Buffer_get_num_of_garbage_ranges( buffer );
+        NS(buffer_size_t) const num_garbage =
+            NS(Buffer_get_num_of_garbage_ranges)( buffer );
 
-        st_buffer_size_t const buffer_size =
-            st_Buffer_get_size( buffer );
+        NS(buffer_size_t) const buffer_size =
+            NS(Buffer_get_size)( buffer );
 
-        st_buffer_size_t const buffer_capacity =
-            st_Buffer_get_capacity( buffer );
+        NS(buffer_size_t) const buffer_capacity =
+            NS(Buffer_get_capacity)( buffer );
 
-        st_buffer_addr_t const addr =
-            st_Buffer_get_data_begin_addr( buffer );
+        NS(buffer_addr_t) const addr =
+            NS(Buffer_get_data_begin_addr)( buffer );
 
-        st_Object const* it  = st_Buffer_get_const_objects_begin( buffer );
-        st_Object const* end = st_Buffer_get_const_objects_end( buffer );
+        NS(Object) const* it  = NS(Buffer_get_const_objects_begin)( buffer );
+        NS(Object) const* end = NS(Buffer_get_const_objects_end)( buffer );
 
         printf( "Contents of %s\r\n", argv[ 1 ] );
         printf( "  num_objects  = %16lu\r\n"
@@ -64,15 +64,15 @@ int main( int argc, char* argv[] )
             printf( "Object %9lu / %9lu:\r\n",
                     ( uint64_t )ii, ( uint64_t )num_objects );
 
-            st_Buffer_object_print_out_typeid( st_Object_get_type_id( it ) );
+            NS(Buffer_object_print_out_typeid)( NS(Object_get_type_id)( it ) );
             printf( "\r\n" );
 
-            st_Buffer_object_print_out( it );
+            NS(Buffer_object_print_out)( it );
             printf( "\r\n" );
         }
     }
 
-    st_Buffer_delete( buffer );
+    NS(Buffer_delete)( buffer );
     buffer = SIXTRL_NULLPTR;
 
     return 0;