Skip to content

Commit

Permalink
Added 'normal' parameter to Configuration_Hopfion.
Browse files Browse the repository at this point in the history
Controls the plane in which the toroidal Hopfion is constructed.
  • Loading branch information
Moritz Sallermann committed Oct 25, 2021
1 parent 15eae12 commit c33c8d4
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 11 deletions.
7 changes: 6 additions & 1 deletion core/include/Spirit/Configurations.h
Expand Up @@ -27,6 +27,11 @@ The default rectangular condition: none
*/
float const defaultRect[3] = {-1,-1,-1};

/*
The default normal for planar configurations. For now only used in the toroidal Hopfion.
*/
float const defaultNormal[3] = {0,0,1};

/*
Clipboard
--------------------------------------------------------------------
Expand Down Expand Up @@ -88,7 +93,7 @@ PREFIX void Configuration_Skyrmion(State *state, float r, float order, float pha
PREFIX void Configuration_DW_Skyrmion(State *state, float dw_radius, float dw_width, float order, float phase, bool upDown, bool achiral, bool rl, const float position[3]=defaultPos, const float r_cut_rectangular[3]=defaultRect, float r_cut_cylindrical=-1, float r_cut_spherical=-1, bool inverted=false, int idx_image=-1, int idx_chain=-1) SUFFIX;

// Create a toroidal Hopfion
PREFIX void Configuration_Hopfion(State *state, float r, int order=1, const float position[3]=defaultPos, const float r_cut_rectangular[3]=defaultRect, float r_cut_cylindrical=-1, float r_cut_spherical=-1, bool inverted=false, int idx_image=-1, int idx_chain=-1) SUFFIX;
PREFIX void Configuration_Hopfion(State *state, float r, int order=1, const float position[3]=defaultPos, const float r_cut_rectangular[3]=defaultRect, float r_cut_cylindrical=-1, float r_cut_spherical=-1, bool inverted=false, const float normal[3] = defaultNormal, int idx_image=-1, int idx_chain=-1) SUFFIX;

/*
Pinning and atom types
Expand Down
23 changes: 23 additions & 0 deletions core/include/engine/Vectormath.hpp
Expand Up @@ -18,6 +18,29 @@ namespace Engine
/////////////////////////////////////////////////////////////////
//////// Single Vector Math

// A "rotated view" into a vectorfield, with optional shifts applied before and after rotation.
template<class vectorfield_t, class vector_t>
class Rotated_View
{
private:
const vectorfield_t & field;
const Matrix3 & rotation_matrix;
const vector_t & shift_pre;
const vector_t & shift_post;

public:
Rotated_View(const vectorfield_t & field, const Matrix3 & rotation_matrix, const vector_t & shift_pre = vector_t{0,0,0}, const vector_t & shift_post = vector_t{0,0,0}) : field(field), rotation_matrix(rotation_matrix), shift_pre(shift_pre), shift_post(shift_post)
{}

const vector_t operator[] (int idx)
{
return rotation_matrix * (field[idx] - shift_pre) + shift_post;
}
};

// Constructs a rotation matrix that rotates to a frame with "normal" as the z-axis
Matrix3 dreibein(const Vector3 & normal);

// Angle between two vectors, assuming both are normalized
scalar angle(const Vector3 & v1, const Vector3 & v2);
// Rotate a vector around an axis by a certain degree (Implemented with Rodrigue's formula)
Expand Down
2 changes: 1 addition & 1 deletion core/include/utility/Configurations.hpp
Expand Up @@ -38,7 +38,7 @@ void Add_Noise_Temperature(
Data::Spin_System & s, scalar temperature, int delta_seed = 0, filterfunction filter = defaultfilter );

// Creates a toroid
void Hopfion( Data::Spin_System & s, Vector3 pos, scalar r, int order = 1, filterfunction filter = defaultfilter );
void Hopfion( Data::Spin_System & s, Vector3 pos, scalar r, int order = 1, Vector3 normal = {0,0,1}, filterfunction filter = defaultfilter );

// Creates a Skyrmion
void Skyrmion(
Expand Down
6 changes: 3 additions & 3 deletions core/python/spirit/configuration.py
Expand Up @@ -152,11 +152,11 @@ def dw_skyrmion(p_state, dw_radius, dw_width, order=1, phase=1, up_down=False, a

_Hopfion = _spirit.Configuration_Hopfion
_Hopfion.argtypes = [ctypes.c_void_p, ctypes.c_float, ctypes.c_int, ctypes.POINTER(ctypes.c_float),
ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, ctypes.c_bool,
ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, ctypes.c_bool, ctypes.POINTER(ctypes.c_float),
ctypes.c_int, ctypes.c_int]
_Hopfion.restype = None
def hopfion(p_state, radius, order=1, pos=[0,0,0], border_rectangular=[-1,-1,-1],
border_cylindrical=-1, border_spherical=-1, inverted=False, idx_image=-1, idx_chain=-1):
border_cylindrical=-1, border_spherical=-1, inverted=False, normal=[0,0,1], idx_image=-1, idx_chain=-1):
"""Set a Hopfion configuration.
Arguments:
Expand All @@ -172,7 +172,7 @@ def hopfion(p_state, radius, order=1, pos=[0,0,0], border_rectangular=[-1,-1,-1]
vec3 = ctypes.c_float * 3
_Hopfion(ctypes.c_void_p(p_state), ctypes.c_float(radius), ctypes.c_int(order),
vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical),
ctypes.c_float(border_spherical), ctypes.c_bool(inverted),
ctypes.c_float(border_spherical), ctypes.c_bool(inverted), vec3(*normal),
ctypes.c_int(idx_image), ctypes.c_int(idx_chain))

_SpinSpiral = _spirit.Configuration_SpinSpiral
Expand Down
4 changes: 2 additions & 2 deletions core/src/Spirit/Configurations.cpp
Expand Up @@ -466,7 +466,7 @@ catch( ... )

void Configuration_Hopfion( State *state, float r, int order, const float position[3],
const float r_cut_rectangular[3], float r_cut_cylindrical,
float r_cut_spherical, bool inverted, int idx_image, int idx_chain ) noexcept
float r_cut_spherical, bool inverted, const float normal[3], int idx_image, int idx_chain ) noexcept
try
{
std::shared_ptr<Data::Spin_System> image;
Expand All @@ -487,7 +487,7 @@ try

// Apply configuration
image->Lock();
Utility::Configurations::Hopfion(*image, vpos, r, order, filter);
Utility::Configurations::Hopfion(*image, vpos, r, order, {normal[0],normal[1],normal[2]}, filter);
image->geometry->Apply_Pinning(*image->spins);
image->Unlock();

Expand Down
22 changes: 22 additions & 0 deletions core/src/engine/Vectormath.cpp
Expand Up @@ -442,6 +442,28 @@ namespace Vectormath
return solid_angle;
}

// Constructs a rotation matrix that rotates to a frame with "normal" as the z-axis
Matrix3 dreibein(const Vector3 & normal)
{
const Vector3 ex = {1,0,0};
const Vector3 ey = {0,1,0};

Vector3 x_hat;
if( std::abs(normal.dot(ex)-1) > 1e-1) // Make sure not to take the cross product with a parallel vector
{
x_hat = normal.cross(ex);
} else {
x_hat = normal.cross(ey);
}

Vector3 y_hat = normal.cross(x_hat);

Matrix3 dreibein;
dreibein.row(0) = x_hat.normalized();
dreibein.row(1) = y_hat.normalized();
dreibein.row(2) = normal.normalized();
return dreibein;
}

void rotate(const Vector3 & v, const Vector3 & axis, const scalar & angle, Vector3 & v_out)
{
Expand Down
11 changes: 7 additions & 4 deletions core/src/utility/Configurations.cpp
@@ -1,3 +1,4 @@
#include "engine/Vectormath_Defines.hpp"
#include <data/Spin_System.hpp>
#include <engine/Vectormath.hpp>
#include <utility/Configurations.hpp>
Expand Down Expand Up @@ -152,8 +153,13 @@ void Add_Noise_Temperature( Data::Spin_System & s, scalar temperature, int delta
Engine::Vectormath::normalize_vectors( *s.spins );
}

void Hopfion( Data::Spin_System & s, Vector3 pos, scalar r, int order, filterfunction filter )
void Hopfion( Data::Spin_System & s, Vector3 pos, scalar r, int order, Vector3 normal, filterfunction filter )
{

auto dreibein = Engine::Vectormath::dreibein(normal);
auto & spins = *s.spins;
auto positions = Engine::Vectormath::Rotated_View<vectorfield, Vector3>(s.geometry->positions, dreibein, pos, pos);

using std::acos;
using std::atan;
using std::atan2;
Expand All @@ -162,9 +168,6 @@ void Hopfion( Data::Spin_System & s, Vector3 pos, scalar r, int order, filterfun
using std::sin;
using std::sqrt;

auto & spins = *s.spins;
auto & positions = s.geometry->positions;

if( r != 0.0 )
{
scalar tmp;
Expand Down

0 comments on commit c33c8d4

Please sign in to comment.