diff --git a/core/include/Spirit/Parameters_GNEB.h b/core/include/Spirit/Parameters_GNEB.h index 9b930e7cc..ff25fd0a2 100644 --- a/core/include/Spirit/Parameters_GNEB.h +++ b/core/include/Spirit/Parameters_GNEB.h @@ -111,6 +111,15 @@ PREFIX void Parameters_GNEB_Set_Spring_Force_Ratio( State * state, float ratio, PREFIX void Parameters_GNEB_Set_Path_Shortening_Constant( State * state, float path_shortening_constant, int idx_chain = -1 ) SUFFIX; +// Set if moving endpoints should be used +PREFIX void Parameters_GNEB_Set_Moving_Endpoints( State * state, bool moving_endpoints, int idx_chain = -1 ) SUFFIX; + +// Set if attracting endpoints should be used +PREFIX void Parameters_GNEB_Set_Translating_Endpoints( State * state, bool translating_endpoints, int idx_chain = -1 ) SUFFIX; + +// Set equilibrium Rx, used for the moving endpoints method +PREFIX void Parameters_GNEB_Set_Equilibrium_Delta_Rx( State * state, float delta_Rx_left, float delta_Rx_right, int idx_chain = -1 ) SUFFIX; + // Set the GNEB image type (see the integers defined above). PREFIX void Parameters_GNEB_Set_Climbing_Falling( State * state, int image_type, int idx_image = -1, int idx_chain = -1 ) SUFFIX; @@ -169,6 +178,15 @@ PREFIX float Parameters_GNEB_Get_Spring_Force_Ratio( State * state, int idx_chai // Return the path shortening constant. PREFIX float Parameters_GNEB_Get_Path_Shortening_Constant( State * state, int idx_chain = -1 ) SUFFIX; +// Return if moving endpoints are used +PREFIX bool Parameters_GNEB_Get_Moving_Endpoints( State * state, int idx_chain = -1 ) SUFFIX; + +// Set if translating endpoints are used +PREFIX bool Parameters_GNEB_Get_Translating_Endpoints( State * state, int idx_chain = -1 ) SUFFIX; + +// Get the equilibrium Rx, used for the moving endpoints method +PREFIX void Parameters_GNEB_Get_Equilibrium_Delta_Rx( State * state, float * delta_Rx_left, float * delta_Rx_right, int idx_chain = -1 ) SUFFIX; + /* Returns the integer of whether an image is regular, climbing, falling, or stationary. diff --git a/core/include/data/Parameters_Method_GNEB.hpp b/core/include/data/Parameters_Method_GNEB.hpp index b80a06883..6b4b0165b 100644 --- a/core/include/data/Parameters_Method_GNEB.hpp +++ b/core/include/data/Parameters_Method_GNEB.hpp @@ -33,6 +33,14 @@ struct Parameters_Method_GNEB : Parameters_Method_Solver // Mersenne twister PRNG std::mt19937 prng = std::mt19937( rng_seed ); + bool moving_endpoints = false; + bool translating_endpoints = false; + + scalar equilibrium_delta_Rx_left = 1.0; + scalar equilibrium_delta_Rx_right = 1.0; + + bool escape_first = false; + // ----------------- Output -------------- bool output_energies_step = false; bool output_energies_divide_by_nspins = true; diff --git a/core/include/engine/Method_GNEB.hpp b/core/include/engine/Method_GNEB.hpp index 5509b2c7d..572fe383b 100644 --- a/core/include/engine/Method_GNEB.hpp +++ b/core/include/engine/Method_GNEB.hpp @@ -75,8 +75,15 @@ class Method_GNEB : public Method_Solver std::vector F_gradient; std::vector F_spring; vectorfield f_shrink; + + vectorfield F_translation_left; + vectorfield F_translation_right; + // Last calculated tangents std::vector tangents; + + vectorfield tangent_endpoints_left; + vectorfield tangent_endpoints_right; }; } // namespace Engine diff --git a/core/python/spirit/parameters/gneb.py b/core/python/spirit/parameters/gneb.py index bbe549498..1c46dc60d 100644 --- a/core/python/spirit/parameters/gneb.py +++ b/core/python/spirit/parameters/gneb.py @@ -135,6 +135,27 @@ def set_path_shortening_constant(p_state, shortening_constant, idx_image=-1, idx _GNEB_Set_Path_Shortening_Constant(ctypes.c_void_p(p_state), ctypes.c_float(shortening_constant), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) +_GNEB_Set_Moving_Endpoints = _spirit.Parameters_GNEB_Set_Moving_Endpoints +_GNEB_Set_Moving_Endpoints.argtypes = [ctypes.c_void_p, ctypes.c_bool, ctypes.c_int] +_GNEB_Set_Moving_Endpoints.restype = None +def set_moving_endpoints(p_state, moving_endpoints, idx_chain=-1): + """Set if moving endpoints should be used.""" + _GNEB_Set_Moving_Endpoints(ctypes.c_void_p(p_state), ctypes.c_bool(moving_endpoints), ctypes.c_int(idx_chain)) + +_GNEB_Set_Translating_Endpoints = _spirit.Parameters_GNEB_Set_Translating_Endpoints +_GNEB_Set_Translating_Endpoints.argtypes = [ctypes.c_void_p, ctypes.c_bool, ctypes.c_int] +_GNEB_Set_Translating_Endpoints.restype = None +def set_translating_endpoints(p_state, translating_endpoints, idx_chain=-1): + """Set if attracting endpoints should be used.""" + _GNEB_Set_Translating_Endpoints(ctypes.c_void_p(p_state), ctypes.c_bool(translating_endpoints), ctypes.c_int(idx_chain)) + +_GNEB_Set_Equilibrium_Delta_Rx = _spirit.Parameters_GNEB_Set_Equilibrium_Delta_Rx +_GNEB_Set_Equilibrium_Delta_Rx.argtypes = [ctypes.c_void_p, ctypes.c_float, ctypes.c_float, ctypes.c_int] +_GNEB_Set_Equilibrium_Delta_Rx.restype = None +def set_equilibrium_delta_Rx(p_state, delta_Rx_left, delta_Rx_right, idx_chain=-1): + """Set if moving endpoints should be used.""" + _GNEB_Set_Equilibrium_Delta_Rx(ctypes.c_void_p(p_state), ctypes.c_float(delta_Rx_left), ctypes.c_float(delta_Rx_right), ctypes.c_int(idx_chain)) + _GNEB_Set_Climbing_Falling = _spirit.Parameters_GNEB_Set_Climbing_Falling _GNEB_Set_Climbing_Falling.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int] _GNEB_Set_Climbing_Falling.restype = None @@ -198,6 +219,34 @@ def get_path_shortening_constant(p_state, idx_image=-1, idx_chain=-1): return float( _GNEB_Get_Path_Shortening_Constant(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))) +_GNEB_Get_Moving_Endpoints = _spirit.Parameters_GNEB_Get_Moving_Endpoints +_GNEB_Get_Moving_Endpoints.argtypes = [ctypes.c_void_p, ctypes.c_int] +_GNEB_Get_Moving_Endpoints.restype = ctypes.c_bool +def get_moving_endpoints(p_state, idx_chain=-1): + """Return if moving endpoints are used.""" + return bool( _GNEB_Get_Moving_Endpoints(ctypes.c_void_p(p_state), + ctypes.c_int(idx_chain)) ) + +_GNEB_Get_Translating_Endpoints = _spirit.Parameters_GNEB_Get_Translating_Endpoints +_GNEB_Get_Translating_Endpoints.argtypes = [ctypes.c_void_p, ctypes.c_int] +_GNEB_Get_Translating_Endpoints.restype = ctypes.c_bool +def get_translating_endpoints(p_state, idx_chain=-1): + """Return if translating endpoints are used.""" + return bool( _GNEB_Get_Translating_Endpoints(ctypes.c_void_p(p_state), + ctypes.c_int(idx_chain)) ) + +_GNEB_Get_Equilibrium_Delta_Rx = _spirit.Parameters_GNEB_Get_Equilibrium_Delta_Rx +_GNEB_Get_Equilibrium_Delta_Rx.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int] +_GNEB_Get_Equilibrium_Delta_Rx.restype = None +def get_equilibrium_delta_Rx(p_state, idx_chain=-1): + """Return the equilibrium delta_Rx for the moving endpoints.""" + delta_Rx_left = ctypes.c_float() + delta_Rx_right = ctypes.c_float() + + _GNEB_Get_Equilibrium_Delta_Rx(ctypes.c_void_p(p_state), ctypes.byref(delta_Rx_left), ctypes.byref(delta_Rx_right), ctypes.c_int(idx_chain)) + + return [float(delta_Rx_left.value), float(delta_Rx_right.value)] + _GNEB_Get_Climbing_Falling = _spirit.Parameters_GNEB_Get_Climbing_Falling _GNEB_Get_Climbing_Falling.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _GNEB_Get_Climbing_Falling.restype = ctypes.c_int diff --git a/core/src/Spirit/Parameters_GNEB.cpp b/core/src/Spirit/Parameters_GNEB.cpp index d2e22118b..27e9a500b 100644 --- a/core/src/Spirit/Parameters_GNEB.cpp +++ b/core/src/Spirit/Parameters_GNEB.cpp @@ -237,6 +237,80 @@ catch( ... ) spirit_handle_exception_api( -1, idx_chain ); } +// Set if moving endpoints should be used +void Parameters_GNEB_Set_Moving_Endpoints( State * state, bool moving_endpoints, int idx_chain ) noexcept +try +{ + int idx_image = -1; + std::shared_ptr image; + std::shared_ptr chain; + + // Fetch correct indices and pointers + from_indices( state, idx_image, idx_chain, image, chain ); + + chain->Lock(); + auto p = chain->gneb_parameters; + p->moving_endpoints = moving_endpoints; + chain->Unlock(); + + Log( Utility::Log_Level::Parameter, Utility::Log_Sender::API, + fmt::format( "Set GNEB moving endpoints = {}", moving_endpoints ), idx_image, idx_chain ); +} +catch( ... ) +{ + spirit_handle_exception_api( -1, idx_chain ); +} + +// Set if translating endpoints should be used +void Parameters_GNEB_Set_Translating_Endpoints( State * state, bool translating_endpoints, int idx_chain ) noexcept +try +{ + int idx_image = -1; + std::shared_ptr image; + std::shared_ptr chain; + + // Fetch correct indices and pointers + from_indices( state, idx_image, idx_chain, image, chain ); + + chain->Lock(); + auto p = chain->gneb_parameters; + p->translating_endpoints = translating_endpoints; + chain->Unlock(); + + Log( Utility::Log_Level::Parameter, Utility::Log_Sender::API, + fmt::format( "Set GNEB translating endpoints = {}", translating_endpoints ), idx_image, idx_chain ); +} +catch( ... ) +{ + spirit_handle_exception_api( -1, idx_chain ); +} + +void Parameters_GNEB_Set_Equilibrium_Delta_Rx( State * state, float delta_Rx_left, float delta_Rx_right, int idx_chain ) noexcept +try +{ + int idx_image = -1; + std::shared_ptr image; + std::shared_ptr chain; + + // Fetch correct indices and pointers + from_indices( state, idx_image, idx_chain, image, chain ); + + chain->Lock(); + auto p = chain->gneb_parameters; + p->equilibrium_delta_Rx_left = delta_Rx_left; + p->equilibrium_delta_Rx_right = delta_Rx_right; + + chain->Unlock(); + + Log( Utility::Log_Level::Parameter, Utility::Log_Sender::API, + fmt::format( "Set equilibrium delta Rx for GNEB with moving endpoints. delta_Rx_left = {}, delta_Rx_right = {}", delta_Rx_left, delta_Rx_right ), idx_image, idx_chain ); +} +catch( ... ) +{ + spirit_handle_exception_api( -1, idx_chain ); +} + + void Parameters_GNEB_Set_Climbing_Falling( State * state, int image_type, int idx_image, int idx_chain ) noexcept try { @@ -507,6 +581,63 @@ catch( ... ) return 0; } +bool Parameters_GNEB_Get_Moving_Endpoints( State * state, int idx_chain ) noexcept +try +{ + int idx_image = -1; + std::shared_ptr image; + std::shared_ptr chain; + + // Fetch correct indices and pointers + from_indices( state, idx_image, idx_chain, image, chain ); + + auto p = chain->gneb_parameters; + return static_cast( p->moving_endpoints ); +} +catch( ... ) +{ + spirit_handle_exception_api( -1, idx_chain ); + return 0; +} + +bool Parameters_GNEB_Get_Translating_Endpoints( State * state, int idx_chain ) noexcept +try +{ + int idx_image = -1; + std::shared_ptr image; + std::shared_ptr chain; + + // Fetch correct indices and pointers + from_indices( state, idx_image, idx_chain, image, chain ); + + auto p = chain->gneb_parameters; + return static_cast( p->translating_endpoints ); +} +catch( ... ) +{ + spirit_handle_exception_api( -1, idx_chain ); + return 0; +} + +void Parameters_GNEB_Get_Equilibrium_Delta_Rx( State * state, float * delta_Rx_left, float * delta_Rx_right, int idx_chain) noexcept +try +{ + int idx_image = -1; + std::shared_ptr image; + std::shared_ptr chain; + + // Fetch correct indices and pointers + from_indices( state, idx_image, idx_chain, image, chain ); + + auto p = chain->gneb_parameters; + *delta_Rx_left = float(p->equilibrium_delta_Rx_left); + *delta_Rx_right = float(p->equilibrium_delta_Rx_right); +} +catch( ... ) +{ + spirit_handle_exception_api( -1, idx_chain ); +} + int Parameters_GNEB_Get_Climbing_Falling( State * state, int idx_image, int idx_chain ) noexcept try { diff --git a/core/src/Spirit/Simulation.cpp b/core/src/Spirit/Simulation.cpp index 18012e279..c6e68d7c6 100644 --- a/core/src/Spirit/Simulation.cpp +++ b/core/src/Spirit/Simulation.cpp @@ -255,10 +255,10 @@ try std::string( "There are still one or more simulations running on the specified chain!" ) + std::string( " Please stop them before starting a GNEB calculation." ) ); } - else if( Chain_Get_NOI( state, idx_chain ) < 3 ) + else if( Chain_Get_NOI( state, idx_chain ) < 2 ) { Log( Utility::Log_Level::Error, Utility::Log_Sender::API, - std::string( "There are less than 3 images in the specified chain!" ) + std::string( "There are less than 2 images in the specified chain!" ) + std::string( " Please insert more before starting a GNEB calculation." ) ); } else diff --git a/core/src/engine/Manifoldmath.cpp b/core/src/engine/Manifoldmath.cpp index 18447c7a3..9ecad2461 100644 --- a/core/src/engine/Manifoldmath.cpp +++ b/core/src/engine/Manifoldmath.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -21,12 +22,12 @@ namespace Manifoldmath { void project_parallel( vectorfield & vf1, const vectorfield & vf2 ) { - vectorfield vf3 = vf1; - project_orthogonal( vf3, vf2 ); -// TODO: replace the loop with Vectormath Kernel -#pragma omp parallel for - for( unsigned int i = 0; i < vf1.size(); ++i ) - vf1[i] -= vf3[i]; + scalar proj = Vectormath::dot(vf1, vf2); + Backend::par::apply( vf1.size(), [vf1 = vf1.data(), vf2 = vf2.data(), proj] SPIRIT_LAMBDA (int idx) + { + vf1[idx] = proj * vf2[idx]; + } + ); } void project_orthogonal( vectorfield & vf1, const vectorfield & vf2 ) @@ -73,6 +74,42 @@ scalar dist_geodesic( const vectorfield & v1, const vectorfield & v2 ) return sqrt( dist ); } +/* + Helper function for a more accurate tangent +*/ +void Geodesic_Tangent( vectorfield & tangent, const vectorfield & image_1, const vectorfield & image_2, const vectorfield & image_mid ) +{ + // clang-format off + Backend::par::apply( + image_1.size(), + [ + image_minus = image_1.data(), + image_plus = image_2.data(), + image_mid = image_mid.data(), + tangent = tangent.data() + ] SPIRIT_LAMBDA (int idx) + { + const Vector3 ex = { 1, 0, 0 }; + const Vector3 ey = { 0, 1, 0 }; + scalar epsilon = 1e-15; + + Vector3 axis = image_plus[idx].cross( image_minus[idx] ); + + // If the spins are anti-parallel, we choose an arbitrary axis + if( std::abs(image_minus[idx].dot(image_plus[idx]) + 1) < epsilon ) // Check if anti-parallel + { + if( std::abs( image_mid[idx].dot( ex ) - 1 ) > epsilon ) // Check if parallel to ex + axis = ex; + else + axis = ey; + } + tangent[idx] = image_mid[idx].cross( axis ); + } + ); + Manifoldmath::normalize(tangent); + // clang-format on +}; + /* Calculates the 'tangent' vectors, i.e.in crudest approximation the difference between an image and the neighbouring */ @@ -91,15 +128,13 @@ void Tangents( if( idx_img == 0 ) { auto & image_plus = *configurations[idx_img + 1]; - Vectormath::set_c_a( 1, image_plus, tangents[idx_img] ); - Vectormath::add_c_a( -1, image, tangents[idx_img] ); + Geodesic_Tangent( tangents[idx_img], image, image_plus, image ); // Use the accurate tangent at the endpoints, useful for the dimer method } // Last Image else if( idx_img == noi - 1 ) { auto & image_minus = *configurations[idx_img - 1]; - Vectormath::set_c_a( 1, image, tangents[idx_img] ); - Vectormath::add_c_a( -1, image_minus, tangents[idx_img] ); + Geodesic_Tangent( tangents[idx_img], image_minus, image, image ); // Use the accurate tangent at the endpoints, useful for the dimer method } // Images Inbetween else @@ -161,14 +196,12 @@ void Tangents( Vectormath::set_c_a( 1, t_plus, tangents[idx_img] ); Vectormath::add_c_a( 1, t_minus, tangents[idx_img] ); } - } - - // Project tangents into tangent planes of spin vectors to make them actual tangents - project_tangential( tangents[idx_img], image ); - - // Normalise in 3N - dimensional space - Manifoldmath::normalize( tangents[idx_img] ); + // Project tangents into tangent planes of spin vectors to make them actual tangents + project_tangential( tangents[idx_img], image ); + // Normalise in 3N - dimensional space + Manifoldmath::normalize( tangents[idx_img] ); + } } // end for idx_img } // end Tangents } // namespace Manifoldmath diff --git a/core/src/engine/Manifoldmath.cu b/core/src/engine/Manifoldmath.cu index 7a20cf7c0..3bdd1299a 100644 --- a/core/src/engine/Manifoldmath.cu +++ b/core/src/engine/Manifoldmath.cu @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -18,9 +19,12 @@ namespace Engine { void project_parallel(vectorfield & vf1, const vectorfield & vf2) { - vectorfield vf3 = vf1; - project_orthogonal(vf3, vf2); - Vectormath::add_c_a(-1, vf3, vf1); + scalar proj = Vectormath::dot(vf1, vf2); + Backend::par::apply( vf1.size(), [vf1 = vf1.data(), vf2 = vf2.data(), proj] SPIRIT_LAMBDA (int idx) + { + vf1[idx] = proj * vf2[idx]; + } + ); } __global__ void cu_project_orthogonal(Vector3 *vf1, const Vector3 *vf2, scalar proj, size_t N) diff --git a/core/src/engine/Method_GNEB.cpp b/core/src/engine/Method_GNEB.cpp index d416197b0..5d410bc09 100644 --- a/core/src/engine/Method_GNEB.cpp +++ b/core/src/engine/Method_GNEB.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -6,13 +8,11 @@ #include #include #include +#include #include #include #include -#include -#include - #include using namespace Utility; @@ -40,10 +40,15 @@ Method_GNEB::Method_GNEB( std::shared_ptr chain this->F_gradient = std::vector( this->noi, vectorfield( this->nos, { 0, 0, 0 } ) ); // [noi][nos] this->F_spring = std::vector( this->noi, vectorfield( this->nos, { 0, 0, 0 } ) ); // [noi][nos] this->f_shrink = vectorfield( this->nos, { 0, 0, 0 } ); // [nos] - this->xi = vectorfield( this->nos, { 0, 0, 0 } ); // [nos] + this->xi = vectorfield( this->nos, { 0, 0, 0 } ); + + this->F_translation_left = vectorfield( this->nos, { 0, 0, 0 } ); + this->F_translation_right = vectorfield( this->nos, { 0, 0, 0 } ); // Tangents this->tangents = std::vector( this->noi, vectorfield( this->nos, { 0, 0, 0 } ) ); // [noi][nos] + this->tangent_endpoints_left = vectorfield( this->nos, { 0, 0, 0 } ); // [nos] + this->tangent_endpoints_right = vectorfield( this->nos, { 0, 0, 0 } ); // [nos] // We assume that the chain is not converged before the first iteration this->max_torque = this->chain->gneb_parameters->force_convergence + 1.0; @@ -100,13 +105,10 @@ void Method_GNEB::Calculate_Force( // while the gradient force is manipulated (e.g. projected) auto eff_field = this->chain->images[img]->effective_field.data(); auto f_grad = F_gradient[img].data(); - Backend::par::apply( - image.size(), - [eff_field, f_grad] SPIRIT_LAMBDA( int idx ) - { - eff_field[idx] *= -1; - f_grad[idx] = eff_field[idx]; - } ); + Backend::par::apply( image.size(), [eff_field, f_grad] SPIRIT_LAMBDA( int idx ) { + eff_field[idx] *= -1; + f_grad[idx] = eff_field[idx]; + } ); if( img > 0 ) { @@ -145,11 +147,11 @@ void Method_GNEB::Calculate_Force( scalar range_Rx = interp[0].at( std::distance( interp[0].begin(), std::max_element( interp[0].begin(), interp[0].end() ) ) ) - interp[0].at( - std::distance( interp[0].begin(), std::min_element( interp[0].begin(), interp[0].end() ) ) ); + std::distance( interp[0].begin(), std::min_element( interp[0].begin(), interp[0].end() ) ) ); scalar range_E = interp[1].at( std::distance( interp[1].begin(), std::max_element( interp[1].begin(), interp[1].end() ) ) ) - interp[1].at( - std::distance( interp[1].begin(), std::min_element( interp[1].begin(), interp[1].end() ) ) ); + std::distance( interp[1].begin(), std::min_element( interp[1].begin(), interp[1].end() ) ) ); for( int idx_image = 1; idx_image < this->chain->noi; ++idx_image ) { @@ -251,6 +253,104 @@ void Method_GNEB::Calculate_Force( // Copy out Vectormath::set_c_a( 1, F_total[img], forces[img] ); } // end for img=1..noi-1 + + // Moving endpoints + if( chain->gneb_parameters->moving_endpoints ) + { + int noi = chain->noi; + Manifoldmath::project_tangential( F_gradient[0], *configurations[0] ); + Manifoldmath::project_tangential( F_gradient[noi - 1], *configurations[noi - 1] ); + + // Overall translational force + if( chain->gneb_parameters->translating_endpoints ) + { + // clang-format off + Backend::par::apply(nos, + [ + F_translation_left = F_translation_left.data(), + F_translation_right = F_translation_right.data(), + F_gradient_left = F_gradient[0].data(), + F_gradient_right = F_gradient[noi-1].data(), + spins_left = this->chain->images[0]->spins->data(), + spins_right = this->chain->images[noi-1]->spins->data() + ] SPIRIT_LAMBDA ( int idx) + { + const Vector3 axis = spins_left[idx].cross(spins_right[idx]); + const scalar angle = acos(spins_left[idx].dot(spins_right[idx])); + + // Rotation matrix that rotates spin_left to spin_right + Matrix3 rotation_matrix = Eigen::AngleAxis(angle, axis.normalized()).toRotationMatrix(); + + if ( abs(spins_left[idx].dot(spins_right[idx])) >= 1.0 ) // Angle can become nan for collinear spins + rotation_matrix = Matrix3::Identity(); + + const Vector3 F_gradient_right_rotated = rotation_matrix * F_gradient_right[idx]; + F_translation_left[idx] = -0.5 * (F_gradient_left[idx] + F_gradient_right_rotated); + + const Vector3 F_gradient_left_rotated = rotation_matrix.transpose() * F_gradient_left[idx]; + F_translation_right[idx] = -0.5 * (F_gradient_left_rotated + F_gradient_right[idx]); + } + ); + // clang-format on + + Manifoldmath::project_parallel( F_translation_left, tangents[0] ); + Manifoldmath::project_parallel( F_translation_right, tangents[chain->noi - 1] ); + } + + scalar rotational_coeff = 1.0; + if(chain->gneb_parameters->escape_first) + { + // Estimate the curvature along the tangent and only activate the rotational force, if it is negative + scalar proj_left = Vectormath::dot( F_gradient[0], tangents[0] ); + scalar proj_right = Vectormath::dot( F_gradient[chain->noi-1], tangents[chain->noi-1] ); + if (proj_left > proj_right) + { + rotational_coeff = 0.0; + } + } + + for( int img : { 0, chain->noi - 1 } ) + { + scalar delta_Rx0 = ( img == 0 ) ? chain->gneb_parameters->equilibrium_delta_Rx_left : + chain->gneb_parameters->equilibrium_delta_Rx_right; + scalar delta_Rx = ( img == 0 ) ? Rx[1] - Rx[0] : Rx[chain->noi - 1] - Rx[chain->noi - 2]; + + auto spring_constant = ( ( img == 0 ) ? 1.0 : -1.0 ) * this->chain->gneb_parameters->spring_constant; + auto projection = Vectormath::dot( F_gradient[img], tangents[img] ); + + auto F_translation = ( img == 0 ) ? F_translation_left.data() : F_translation_right.data(); + + // std::cout << " === " << img << " ===\n"; + // fmt::print( "tangent_coeff = {}\n", spring_constant * (delta_Rx - delta_Rx0) ); + // fmt::print( "delta_Rx {}\n", delta_Rx ); + // fmt::print( "delta_Rx0 {}\n", delta_Rx0 ); + + // clang-format off + Backend::par::apply( + nos, + [ + F_total = F_total[img].data(), + F_gradient = F_gradient[img].data(), + forces = forces[img].data(), + tangents = tangents[img].data(), + tangent_coeff = spring_constant * (delta_Rx - delta_Rx0), + F_translation, + projection, + rotational_coeff + ] SPIRIT_LAMBDA ( int idx ) + { + forces[idx] = rotational_coeff * (F_gradient[idx] - projection * tangents[idx]) + + tangent_coeff * tangents[idx] + + F_translation[idx]; + + // std::cout << F_translation[idx].transpose() << "\n"; + F_total[idx] = forces[idx]; + } + ); + // clang-format on + } + } + } // end Calculate template @@ -261,8 +361,14 @@ void Method_GNEB::Calculate_Force_Virtual( using namespace Utility; // Calculate the cross product with the spin configuration to get direct minimization - for( std::size_t i = 1; i < configurations.size() - 1; ++i ) + for( std::size_t i = 0; i < configurations.size(); ++i ) { + + if( !chain->gneb_parameters->moving_endpoints && ( i == 0 || i == configurations.size() - 1 ) ) + { + continue; + } + auto & image = *configurations[i]; auto & force = forces[i]; auto & force_virtual = forces_virtual[i]; @@ -305,7 +411,7 @@ void Method_GNEB::Hook_Post_Iteration() this->max_torque = 0; std::fill( this->max_torque_all.begin(), this->max_torque_all.end(), 0 ); - for( int img = 1; img < chain->noi - 1; ++img ) + for( int img = 0; img < chain->noi; ++img ) { scalar fmax = this->MaxTorque_on_Image( *( this->systems[img]->spins ), F_total[img] ); // Set maximum per image @@ -338,7 +444,7 @@ void Method_GNEB::Hook_Post_Iteration() // Rx chain->Rx = this->Rx; // E - for( int img = 1; img < chain->noi; ++img ) + for( int img = 0; img < chain->noi; ++img ) chain->images[img]->E = this->energies[img]; // Rx interpolated chain->Rx_interpolated = interp[0]; @@ -516,8 +622,8 @@ void Method_GNEB::Save_Current( std::string starttime, int iteration, bo preEnergiesFile = this->parameters->output_folder + "/" + fileTag + "Chain_Energies"; // Function to write or append image and energy files - auto writeOutputChain = [this, preChainFile, preEnergiesFile, iteration]( const std::string& suffix, bool append ) - { + auto writeOutputChain = [this, preChainFile, preEnergiesFile, + iteration]( const std::string & suffix, bool append ) { try { // File name @@ -561,8 +667,7 @@ void Method_GNEB::Save_Current( std::string starttime, int iteration, bo }; Calculate_Interpolated_Energy_Contributions(); - auto writeOutputEnergies = [this, preChainFile, preEnergiesFile, iteration]( const std::string & suffix ) - { + auto writeOutputEnergies = [this, preChainFile, preEnergiesFile, iteration]( const std::string & suffix ) { bool normalize = this->chain->gneb_parameters->output_energies_divide_by_nspins; bool readability = this->chain->gneb_parameters->output_energies_add_readability_lines; diff --git a/core/src/io/Configparser.cpp b/core/src/io/Configparser.cpp index b09ad94ba..588749b33 100644 --- a/core/src/io/Configparser.cpp +++ b/core/src/io/Configparser.cpp @@ -1052,6 +1052,10 @@ std::unique_ptr Parameters_Method_GNEB_from_Config config_file_handle.Read_Single( parameters->n_iterations_log, "gneb_n_iterations_log" ); config_file_handle.Read_Single( parameters->n_iterations_amortize, "gneb_n_iterations_amortize" ); config_file_handle.Read_Single( parameters->n_E_interpolations, "gneb_n_energy_interpolations" ); + config_file_handle.Read_Single( parameters->moving_endpoints, "gneb_moving_endpoints" ); + config_file_handle.Read_Single( parameters->equilibrium_delta_Rx_left, "gneb_equilibrium_delta_Rx_left" ); + config_file_handle.Read_Single( parameters->equilibrium_delta_Rx_right, "gneb_equilibrium_delta_Rx_right" ); + config_file_handle.Read_Single( parameters->translating_endpoints, "gneb_translating_endpoints" ); } catch( ... ) { @@ -1074,6 +1078,10 @@ std::unique_ptr Parameters_Method_GNEB_from_Config parameter_log.emplace_back( fmt::format( " {:<18} = {}", "n_iterations", parameters->n_iterations ) ); parameter_log.emplace_back( fmt::format( " {:<18} = {}", "n_iterations_log", parameters->n_iterations_log ) ); parameter_log.emplace_back( fmt::format( " {:<18} = {}", "n_iterations_amortize", parameters->n_iterations_amortize ) ); + parameter_log.emplace_back( fmt::format( " {:<18} = {}", "moving_endpoints", parameters->moving_endpoints ) ); + parameter_log.emplace_back( fmt::format( " {:<18} = {}", "equilibrium_delta_Rx_left", parameters->equilibrium_delta_Rx_left ) ); + parameter_log.emplace_back( fmt::format( " {:<18} = {}", "equilibrium_delta_Rx_right", parameters->equilibrium_delta_Rx_right ) ); + parameter_log.emplace_back( fmt::format( " {:<18} = {}", "translating_endpoints", parameters->translating_endpoints ) ); parameter_log.emplace_back( fmt::format( " {:<18} = \"{}\"", "output_folder", parameters->output_folder ) ); parameter_log.emplace_back( fmt::format( " {:<18} = {}", "output_any", parameters->output_any ) ); parameter_log.emplace_back( fmt::format( " {:<18} = {}", "output_initial", parameters->output_initial ) ); diff --git a/ui-cpp/ui-imgui/include/parameters_widget.hpp b/ui-cpp/ui-imgui/include/parameters_widget.hpp index eb9f295a7..ea7bcc578 100644 --- a/ui-cpp/ui-imgui/include/parameters_widget.hpp +++ b/ui-cpp/ui-imgui/include/parameters_widget.hpp @@ -140,6 +140,12 @@ struct Parameters // Seed for RNG int rng_seed = 2006; + bool moving_endpoints = false; + bool translating_endpoints = false; + + float delta_Rx_left = 1.0; + float delta_Rx_right = 1.0; + // ----------------- Output -------------- bool output_energies_step = false; bool output_energies_divide_by_nspins = true; diff --git a/ui-cpp/ui-imgui/src/parameters_widget.cpp b/ui-cpp/ui-imgui/src/parameters_widget.cpp index 9d706513f..33203fe30 100644 --- a/ui-cpp/ui-imgui/src/parameters_widget.cpp +++ b/ui-cpp/ui-imgui/src/parameters_widget.cpp @@ -550,6 +550,41 @@ void ParametersWidget::show_content() { Parameters_GNEB_Set_Path_Shortening_Constant( state.get(), parameters_gneb.path_shortening_constant ); } + + ImGui::BeginTable( "MovingEndpointsTable", 2 ); + ImGui::TableNextColumn(); + ImGui::TextUnformatted( "Moving endpoints" ); + ImGui::TableNextColumn(); + if( ImGui::Checkbox( "##gneb_moving_endpoints", ¶meters_gneb.moving_endpoints ) ) + { + Parameters_GNEB_Set_Moving_Endpoints( state.get(), parameters_gneb.moving_endpoints ); + } + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex( 0 ); + ImGui::TextUnformatted( "Translating endpoints" ); + ImGui::TableNextColumn(); + if( ImGui::Checkbox( "##gneb_translating_endpoints", ¶meters_gneb.translating_endpoints ) ) + { + Parameters_GNEB_Set_Translating_Endpoints( state.get(), parameters_gneb.translating_endpoints ); + } + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex( 0 ); + ImGui::TextUnformatted( "Delta Rx left" ); + ImGui::TableNextColumn(); + if( ImGui::InputFloat( "##gneb_delta_Rx_left", ¶meters_gneb.delta_Rx_left ) ) + { + Parameters_GNEB_Set_Equilibrium_Delta_Rx( + state.get(), parameters_gneb.delta_Rx_left, parameters_gneb.delta_Rx_right ); + } + ImGui::TableNextColumn(); + ImGui::TextUnformatted( "Delta Rx right" ); + ImGui::TableNextColumn(); + if( ImGui::InputFloat( "##gneb_delta_Rx_right", ¶meters_gneb.delta_Rx_right ) ) + { + Parameters_GNEB_Set_Equilibrium_Delta_Rx( + state.get(), parameters_gneb.delta_Rx_left, parameters_gneb.delta_Rx_right ); + } + ImGui::EndTable(); } else if( ui_shared_state.selected_mode == GUI_Mode::MMF ) { @@ -768,6 +803,11 @@ void ParametersWidget::update_data() state.get(), ¶meters_gneb.output_energies_step, ¶meters_gneb.output_energies_interpolated, ¶meters_gneb.output_energies_divide_by_nspins, ¶meters_gneb.output_energies_add_readability_lines ); + parameters_gneb.moving_endpoints = Parameters_GNEB_Get_Moving_Endpoints( state.get() ); + parameters_gneb.translating_endpoints = Parameters_GNEB_Get_Translating_Endpoints( state.get() ); + Parameters_GNEB_Get_Equilibrium_Delta_Rx( + state.get(), ¶meters_gneb.delta_Rx_left, ¶meters_gneb.delta_Rx_right ); + // ----------------- MMF Parameters_MMF_Get_N_Iterations( state.get(), ¶meters_mmf.n_iterations, ¶meters_mmf.n_iterations_log ); // Output diff --git a/ui-cpp/ui-qt/include/PlotWidget.hpp b/ui-cpp/ui-qt/include/PlotWidget.hpp index feb62159b..23e6a161a 100644 --- a/ui-cpp/ui-qt/include/PlotWidget.hpp +++ b/ui-cpp/ui-qt/include/PlotWidget.hpp @@ -20,6 +20,8 @@ class PlotWidget : public QtCharts::QChartView bool plot_image_energies; bool plot_interpolated; int plot_interpolated_n; + bool divide_by_nos; + bool renormalize_Rx; private: std::shared_ptr state; diff --git a/ui-cpp/ui-qt/src/ParametersWidget.cpp b/ui-cpp/ui-qt/src/ParametersWidget.cpp index 9495f01b3..4bfd2e3e0 100644 --- a/ui-cpp/ui-qt/src/ParametersWidget.cpp +++ b/ui-cpp/ui-qt/src/ParametersWidget.cpp @@ -189,6 +189,16 @@ void ParametersWidget::Load_Parameters_Contents() else if( image_type == 3 ) this->radioButton_Stationary->setChecked( true ); + // Moving endpoints + bool moving_endpoints = Parameters_GNEB_Get_Moving_Endpoints( state.get() ); + this->checkBox_moving_endpoints->setChecked( moving_endpoints ); + bool translating_endpoints = Parameters_GNEB_Get_Translating_Endpoints( state.get() ); + this->checkBox_translating_endpoints->setChecked( translating_endpoints ); + float delta_Rx_left, delta_Rx_right; + Parameters_GNEB_Get_Equilibrium_Delta_Rx( state.get(), &delta_Rx_left, &delta_Rx_right); + this->doubleSpinBox_delta_Rx_left->setValue( delta_Rx_left ); + this->doubleSpinBox_delta_Rx_right->setValue( delta_Rx_right ); + // EMA // modes to calculate and visualize i1 = Parameters_EMA_Get_N_Modes( state.get() ); @@ -445,6 +455,16 @@ void ParametersWidget::set_parameters_gneb() Parameters_GNEB_Set_N_Iterations( state.get(), i1, i2 ); std::string folder = this->lineEdit_gneb_output_folder->text().toStdString(); Parameters_GNEB_Set_Output_Folder( state.get(), folder.c_str() ); + + // Moving endpoints + bool moving_endpoints = this->checkBox_moving_endpoints->isChecked(); + bool translating_endpoints = this->checkBox_translating_endpoints->isChecked(); + float delta_Rx_left = this->doubleSpinBox_delta_Rx_left->value(); + float delta_Rx_right = this->doubleSpinBox_delta_Rx_right->value(); + + Parameters_GNEB_Set_Moving_Endpoints(state.get(), moving_endpoints); + Parameters_GNEB_Set_Translating_Endpoints(state.get(), translating_endpoints); + Parameters_GNEB_Set_Equilibrium_Delta_Rx(state.get(), delta_Rx_left, delta_Rx_right); } void ParametersWidget::set_gneb_auto_image_type() @@ -691,6 +711,7 @@ void ParametersWidget::Setup_Parameters_Slots() connect( this->checkBox_gneb_output_any, SIGNAL( stateChanged( int ) ), this, SLOT( set_parameters_gneb() ) ); connect( this->checkBox_gneb_output_initial, SIGNAL( stateChanged( int ) ), this, SLOT( set_parameters_gneb() ) ); connect( this->checkBox_gneb_output_final, SIGNAL( stateChanged( int ) ), this, SLOT( set_parameters_gneb() ) ); + connect( this->checkBox_gneb_output_energies_step, SIGNAL( stateChanged( int ) ), this, SLOT( set_parameters_gneb() ) ); connect( @@ -699,6 +720,12 @@ void ParametersWidget::Setup_Parameters_Slots() connect( this->checkBox_gneb_output_chain_step, SIGNAL( stateChanged( int ) ), this, SLOT( set_parameters_gneb() ) ); + // Endpoints + connect( this->checkBox_moving_endpoints, SIGNAL( stateChanged( int ) ), this, SLOT( set_parameters_gneb() ) ); + connect( this->checkBox_translating_endpoints, SIGNAL( stateChanged( int ) ), this, SLOT( set_parameters_gneb() ) ); + connect( this->doubleSpinBox_delta_Rx_left, SIGNAL( editingFinished() ), this, SLOT( set_parameters_gneb() ) ); + connect( this->doubleSpinBox_delta_Rx_right, SIGNAL( editingFinished() ), this, SLOT( set_parameters_gneb() ) ); + // EMA connect( this->spinBox_ema_n_modes, SIGNAL( editingFinished() ), this, SLOT( set_parameters_ema() ) ); connect( this->spinBox_ema_n_mode_follow, SIGNAL( editingFinished() ), this, SLOT( set_parameters_ema() ) ); diff --git a/ui-cpp/ui-qt/src/PlotWidget.cpp b/ui-cpp/ui-qt/src/PlotWidget.cpp index 323a55258..8ce4d45cd 100644 --- a/ui-cpp/ui-qt/src/PlotWidget.cpp +++ b/ui-cpp/ui-qt/src/PlotWidget.cpp @@ -177,14 +177,30 @@ void PlotWidget::plotEnergies() // Add data to series int idx_current = System_Get_Index( state.get() ); - current.push_back( QPointF( Rx[idx_current] / Rx_tot, energies[idx_current] / nos ) ); + + scalar Rx_cur = Rx[idx_current]; + if (renormalize_Rx && Rx_tot > 0) + Rx_cur /= Rx_tot; + + scalar E_cur = energies[idx_current]; + if (divide_by_nos) + E_cur /= nos; + + current.push_back( QPointF( Rx_cur, E_cur) ); + if( this->plot_image_energies ) { for( int i = 0; i < noi; ++i ) { if( i > 0 && Rx_tot > 0 ) - Rx[i] = Rx[i] / Rx_tot; - energies[i] = energies[i] / nos; + Rx[i] = Rx[i]; + energies[i] = energies[i]; + + if (renormalize_Rx && Rx_tot > 0) + Rx[i] /= Rx_tot; + + if (divide_by_nos) + energies[i] /= nos; if( Parameters_GNEB_Get_Climbing_Falling( state.get(), i ) == 0 ) normal.push_back( QPointF( Rx[i], energies[i] ) ); @@ -206,8 +222,14 @@ void PlotWidget::plotEnergies() for( int i = 0; i < size_interp; ++i ) { if( i > 0 && Rx_tot > 0 ) - Rx_interp[i] = Rx_interp[i] / Rx_tot; - energies_interp[i] = energies_interp[i] / nos; + Rx_interp[i] = Rx_interp[i]; + energies_interp[i] = energies_interp[i]; + + if (renormalize_Rx && Rx_tot > 0) + Rx_interp[i] /= Rx_tot; + + if (divide_by_nos) + energies_interp[i] /= nos; interp.push_back( QPointF( Rx_interp[i], energies_interp[i] ) ); @@ -268,6 +290,21 @@ void PlotWidget::plotEnergies() float delta = 0.1 * ( ymax - ymin ); if( delta < 1e-6 ) delta = 0.1; + this->chart->axisY()->setMin( ymin - delta ); this->chart->axisY()->setMax( ymax + delta ); + + // Rescale x axis + if (!renormalize_Rx && Rx_tot > 0) + { + delta = 0.04 * Rx_tot; + this->chart->axisX()->setMin( Rx[0] - delta ); + this->chart->axisX()->setMax( Rx[noi-1] + delta ); + } else if(Rx_tot > 0) { + this->chart->axisX()->setMin( -0.04 ); + this->chart->axisX()->setMax( 1.04 ); + } else { + this->chart->axisX()->setMin( -0.04 ); + this->chart->axisX()->setMax( 0.04 ); + } } \ No newline at end of file diff --git a/ui-cpp/ui-qt/src/PlotsWidget.cpp b/ui-cpp/ui-qt/src/PlotsWidget.cpp index 753efe9a9..0546dcaa3 100644 --- a/ui-cpp/ui-qt/src/PlotsWidget.cpp +++ b/ui-cpp/ui-qt/src/PlotsWidget.cpp @@ -24,6 +24,8 @@ PlotsWidget::PlotsWidget( std::shared_ptr state ) connect( this->checkBox_ImageEnergies, SIGNAL( stateChanged( int ) ), this, SLOT( updatePlotSettings() ) ); connect( this->checkBox_InterpolateEnergies, SIGNAL( stateChanged( int ) ), this, SLOT( updatePlotSettings() ) ); connect( this->spinBox_InterpolateEnergies_N, SIGNAL( editingFinished() ), this, SLOT( updatePlotSettings() ) ); + connect( this->checkBox_divide_by_NOS, SIGNAL( stateChanged( int ) ), this, SLOT( updatePlotSettings() ) ); + connect( this->checkBox_normalize_Rx, SIGNAL( stateChanged( int ) ), this, SLOT( updatePlotSettings() ) ); // Update Timer auto timer = new QTimer( this ); @@ -46,5 +48,9 @@ void PlotsWidget::updatePlotSettings() { this->energyPlot->plot_image_energies = this->checkBox_ImageEnergies->isChecked(); this->energyPlot->plot_interpolated = this->checkBox_InterpolateEnergies->isChecked(); + + this->energyPlot->divide_by_nos = this->checkBox_divide_by_NOS->isChecked(); + this->energyPlot->renormalize_Rx = this->checkBox_normalize_Rx->isChecked(); + this->energyPlot->plot_interpolated_n = this->spinBox_InterpolateEnergies_N->value(); } \ No newline at end of file diff --git a/ui-cpp/ui-qt/ui/ParametersWidget.ui b/ui-cpp/ui-qt/ui/ParametersWidget.ui index 1983806fb..892f8f6ce 100644 --- a/ui-cpp/ui-qt/ui/ParametersWidget.ui +++ b/ui-cpp/ui-qt/ui/ParametersWidget.ui @@ -83,15 +83,15 @@ - 0 + 2 0 0 - 513 - 670 + 533 + 684 @@ -110,22 +110,6 @@ LLG - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 30 - - - - @@ -138,42 +122,26 @@ Parameters - - - - - - - 60 - 16777215 - - - - Inclination - - - - - - - - 60 - 16777215 - - + + + + - 0 + Polarisation (x y z) - - + + Qt::Horizontal + + QSizePolicy::Minimum + - 40 + 15 20 @@ -181,6 +149,13 @@ + + + + Temperature + + + @@ -250,6 +225,107 @@ + + + + Convergence at + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Time Step + + + + + + + + + + 45 + 16777215 + + + + 3 + + + -100.000000000000000 + + + 100.000000000000000 + + + + + + + + 45 + 16777215 + + + + 3 + + + -100.000000000000000 + + + 100.000000000000000 + + + + + + + + 45 + 16777215 + + + + 3 + + + -100.000000000000000 + + + 100.000000000000000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -285,6 +361,22 @@ + + + + + 40 + 0 + + + + + 50 + 16777215 + + + + @@ -325,62 +417,6 @@ - - - - Convergence at - - - - - - - - - - 15 - 16777215 - - - - 1E - - - - - - - - 60 - 0 - - - - -20 - - - 20 - - - -8 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -442,74 +478,36 @@ - - - - Time Step - - - - - - - - - - 45 - 16777215 - - - - 3 - - - -100.000000000000000 - - - 100.000000000000000 - - - - - + + + + - 45 + 60 16777215 - - 3 - - - -100.000000000000000 - - - 100.000000000000000 + + Inclination - - + + - 45 + 60 16777215 - - 3 - - - -100.000000000000000 - - - 100.000000000000000 + + 0 - - + + Qt::Horizontal @@ -523,55 +521,48 @@ - - - - - 40 - 0 - - - - - 50 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - + + + + + + + 15 + 16777215 + + - Polarisation (x y z) + 1E - - + + + + + 60 + 0 + + + + -20 + + + 20 + + + -8 + + + + + Qt::Horizontal - - QSizePolicy::Minimum - - 15 + 40 20 @@ -579,13 +570,6 @@ - - - - Temperature - - - @@ -601,7 +585,7 @@ Output - + @@ -626,7 +610,7 @@ - + @@ -660,7 +644,7 @@ - + @@ -706,7 +690,7 @@ - + Qt::Horizontal @@ -719,7 +703,7 @@ - + @@ -763,6 +747,22 @@ + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 30 + + + + @@ -842,7 +842,7 @@ 0 0 483 - 637 + 652 @@ -1193,8 +1193,8 @@ 0 0 - 483 - 715 + 469 + 848 @@ -1213,7 +1213,7 @@ GNEB - + Qt::Vertical @@ -1226,23 +1226,7 @@ - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 30 - - - - - + @@ -1303,31 +1287,31 @@ - - + + - Energies Step + Chain Step - - + + - Energies divide by NOS + Energies Step - - + + - Chain Step + Energies Interpolated - - + + - Energies Interpolated + Energies divide by NOS @@ -1405,65 +1389,57 @@ - - - - - 0 - 0 - + + + + Qt::Vertical - + - 16777215 - 16777215 + 20 + 40 - - GNEB Parameters - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Temperature - - - - - - - 4 - - - 1000.000000000000000 - - - - - - - + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 30 + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + GNEB Parameters + + + + - + Qt::Horizontal @@ -1476,28 +1452,41 @@ - - - false - - + + 60 - 16777215 + 0 + + -20 + + + 20 + + + -8 + - + - Time Step + Convergence at 1E - + + + + Moving endpoints + + + + @@ -1563,10 +1552,10 @@ - - + + - + Qt::Horizontal @@ -1579,63 +1568,57 @@ - + - 60 + 40 0 - - -20 - - - 20 + + + 50 + 16777215 + - - -8 + + 0.5 - + - Convergence at 1E + Spring force ratio - - + + - + - Spring Constant + Path shortening constant 1E - - - - 40 - 0 - + + + -1000 - - - 50 - 16777215 - + + 1000 - - 1.0 + + -3 - + Qt::Horizontal @@ -1649,30 +1632,80 @@ - - + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Temperature + + + + + + + 4 + + + 1000.000000000000000 + + + + + + + + + Translating endpoints + + + + + - + - Path shortening constant 1E + Spring Constant - - - -1000 + + + + 40 + 0 + - - 1000 + + + 50 + 16777215 + - - -3 + + 1.0 - + Qt::Horizontal @@ -1686,10 +1719,10 @@ - - + + - + Qt::Horizontal @@ -1702,33 +1735,73 @@ - - - - 40 - 0 - + + + false - 50 + 60 16777215 - - 0.5 - - + - Spring force ratio + Time Step + + + + Equilibrium Delta_Rx (right) + + + + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + + + + + Equilibrium Delta_Rx (left) + + + @@ -1740,7 +1813,7 @@ 0 0 483 - 637 + 652 @@ -2055,7 +2128,7 @@ 0 0 483 - 637 + 652 @@ -2463,7 +2536,7 @@ - + diff --git a/ui-cpp/ui-qt/ui/PlotsWidget.ui b/ui-cpp/ui-qt/ui/PlotsWidget.ui index 775ab7276..1e2d45549 100644 --- a/ui-cpp/ui-qt/ui/PlotsWidget.ui +++ b/ui-cpp/ui-qt/ui/PlotsWidget.ui @@ -110,28 +110,18 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Refresh - - - + + + + 1 + + + 10000 + + + @@ -142,6 +132,13 @@ + + + + Normalize Rx + + + @@ -149,18 +146,35 @@ - - - - 1 - - - 10000 + + + + Divide by NOS + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Refresh + + +