Beispiel #1
0
def relax_system(mesh):

    sim = Sim(mesh, name='relax')
    sim.set_default_options(gamma=const.gamma)
    sim.alpha = 0.5
    sim.mu_s = const.mu_s_1

    sim.set_m(init_m)

    J = 50.0 * const.k_B
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.5 * J
    dmi = DMI(D)
    sim.add(dmi)

    Hz = 0.2 * J / const.mu_s_1
    zeeman = Zeeman([0, 0, Hz])
    sim.add(zeeman)

    ONE_DEGREE_PER_NS = 17453292.52

    sim.relax(dt=1e-13, stopping_dmdt=0.01 * ONE_DEGREE_PER_NS,
              max_steps=1000, save_m_steps=100, save_vtk_steps=50)

    np.save('m0.npy', sim.spin)
Beispiel #2
0
def relax_system(mesh):

    sim = Sim(mesh, name='relax')
    # sim.set_options(rtol=1e-10,atol=1e-14)
    sim.driver.alpha = 1.0
    sim.driver.gamma = 1.0
    sim.mu_s = 1.0

    sim.set_m(init_m)
    # sim.set_m(random_m)
    # sim.set_m(np.load('m_10000.npy'))

    J = 1.0
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.09
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman([0, 0, 3.75e-3])
    sim.add(zeeman)

    sim.relax(dt=2.0,
              stopping_dmdt=1e-6,
              max_steps=1000,
              save_m_steps=100,
              save_vtk_steps=50)

    np.save('m0.npy', sim.spin)
Beispiel #3
0
def excite_system(mesh):

    sim = Sim(mesh, name='dyn', driver='sllg')
    sim.set_options(dt=1e-14, gamma=const.gamma, k_B=const.k_B)
    sim.alpha = 0.1
    sim.mu_s = const.mu_s_1
    sim.T = temperature_gradient

    sim.set_m(np.load("m0.npy"))

    J = 50.0 * const.k_B
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.5 * J
    dmi = DMI(D)
    sim.add(dmi)

    Hz = 0.2 * J / const.mu_s_1
    zeeman = Zeeman([0, 0, Hz])
    sim.add(zeeman)

    dt = 2e-14 * 50  # 1e-12
    ts = np.linspace(0, 1000 * dt, 501)
    for t in ts:
        sim.run_until(t)
        sim.save_vtk()
        sim.save_m()
        print 'sim t=%g' % t
Beispiel #4
0
def relax_system(mesh):

    sim = Sim(mesh, name='relax')
    sim.set_options(rtol=1e-12, atol=1e-14)
    sim.do_procession = False
    sim.alpha = 0.5
    sim.gamma = 1.0
    sim.mu_s = 1.0

    sim.set_m(init_m)

    J = 1.0
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.18
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman([0, 0e-3, 2e-2], name='H')
    sim.add(zeeman)

    sim.relax(dt=2.0,
              stopping_dmdt=1e-8,
              max_steps=10000,
              save_m_steps=None,
              save_vtk_steps=100)

    np.save('m0.npy', sim.spin)
Beispiel #5
0
def relax_system(mesh, Hy=0):

    sim = Sim(mesh, name='relax')
    sim.driver.set_tols(rtol=1e-10, atol=1e-12)
    sim.driver.alpha = 0.5
    sim.driver.gamma = 1.0
    sim.mu_s = 1.0

    sim.do_precession = False

    sim.set_m(init_m)
    #sim.set_m(random_m)
    #sim.set_m(np.load('m_10000.npy'))

    J = 1.0
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.18
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman([0, Hy, 2e-2], name='H')
    sim.add(zeeman)

    sim.relax(dt=2.0,
              stopping_dmdt=1e-7,
              max_steps=10000,
              save_m_steps=100,
              save_vtk_steps=50)

    np.save('m0.npy', sim.spin)
Beispiel #6
0
def excite_system(mesh, Hy=0):

    sim = Sim(mesh, name='dyn')

    sim.driver.set_tols(rtol=1e-10, atol=1e-12)
    sim.driver.alpha = 0.04
    sim.driver.gamma = 1.0
    sim.mu_s = 1.0

    sim.set_m(np.load('m0.npy'))

    J = 1.0
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.18
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman([0, Hy, 2e-2], name='H')
    sim.add(zeeman)

    hx = TimeZeeman([0, 0, 1e-5], sinc_fun, name='h')
    sim.add(hx, save_field=True)

    dt = 5
    steps = 2001
    for i in range(steps):
        sim.run_until(i * dt)
        sim.save_m()
        print("step {}/{}".format(i, steps))
Beispiel #7
0
def relax_system_stage2():

    mesh = CuboidMesh(nx=140 , ny=140, nz=1)

    sim = Sim(mesh, name='dyn', driver='llg')
    sim.alpha = 0.1
    sim.do_precession = True
    sim.gamma = const.gamma
    sim.mu_s = spatial_mu

    sim.set_m(np.load('skx.npy'))

    J = 50 * const.k_B
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.27 * J
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman(spatial_H)
    sim.add(zeeman)

    ts = np.linspace(0, 2e-9, 201)
    for t in ts:
        sim.run_until(t)
        sim.save_vtk()
        sim.save_m()
        print(t)
Beispiel #8
0
def relax_system_stage1():

    mesh = CuboidMesh(nx=140 , ny=140, nz=1)

    sim = Sim(mesh, name='relax', driver='llg')
    #sim.set_options(dt=1e-14, gamma=const.gamma, k_B=const.k_B)
    sim.alpha = 0.5
    sim.do_precession = False
    sim.gamma = const.gamma
    sim.mu_s = spatial_mu

    sim.set_m(init_m)

    J = 50 * const.k_B
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.27 * J
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman(spatial_H)
    sim.add(zeeman)

    sim.relax(dt=1e-14, stopping_dmdt=1e10, max_steps=1000,
              save_m_steps=100, save_vtk_steps=10)

    np.save('skx.npy', sim.spin)
    plot_m(mesh, 'skx.npy', comp='z')
Beispiel #9
0
def test_skx_num():

    mesh = CuboidMesh(nx=120, ny=120, nz=1, periodicity=(True, True, False))

    sim = Sim(mesh, name='skx_num')
    sim.set_tols(rtol=1e-6, atol=1e-6)
    sim.alpha = 1.0
    sim.gamma = 1.0
    sim.mu_s = 1.0

    sim.set_m(init_m)

    sim.do_procession = False

    J = 1.0
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.09
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman([0, 0, 5e-3])
    sim.add(zeeman)

    sim.relax(dt=2.0,
              stopping_dmdt=1e-2,
              max_steps=1000,
              save_m_steps=None,
              save_vtk_steps=None)

    skn = sim.skyrmion_number()
    print 'skx_number', skn
    assert skn > -1 and skn < -0.99
Beispiel #10
0
def excite_system(mesh):

    sim = Sim(mesh, name='dyn')

    # sim.set_options(rtol=1e-10,atol=1e-14)
    sim.alpha = 0.04
    sim.gamma = 1.0
    sim.mu_s = 1.0

    sim.set_m(np.load('m0.npy'))

    J = 1.0
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.09
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman([0, 0, 3.75e-3], name='H')
    sim.add(zeeman)

    w0 = 0.02

    def time_fun(t):
        return np.exp(-w0 * t)

    hx = TimeZeeman([0, 0, 1e-5], sinc_fun, name='h')
    sim.add(hx, save_field=True)

    ts = np.linspace(0, 20000, 5001)
    for t in ts:
        sim.run_until(t)
        print 'sim t=%g' % t
Beispiel #11
0
def excite_system(T=0.1, H=0.15):

    mesh = CuboidMesh(nx=28 * 3, ny=16 * 5, nz=1, pbc='2d')

    sim = Sim(mesh, name='dyn', driver='sllg')
    sim.set_options(dt=1e-14, gamma=const.gamma, k_B=const.k_B)
    sim.alpha = 0.1
    sim.mu_s = const.mu_s_1

    sim.set_m(random_m)

    J = 50 * const.k_B
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.5 * J
    dmi = DMI(D)
    sim.add(dmi)

    Hz = H * J / const.mu_s_1
    zeeman = Zeeman([0, 0, Hz])
    sim.add(zeeman)

    sim.T = J / const.k_B * T

    ts = np.linspace(0, 5e-11, 51)
    for t in ts:
        sim.run_until(t)
        # sim.save_vtk()

    np.save('m.npy', sim.spin)
    plot_m(mesh, 'm.npy', comp='z')
Beispiel #12
0
def test_sim_spins(do_plot=False):

    mesh = CuboidMesh(nx=10, ny=5, nz=1)

    sim = Sim(mesh, name='10spin')

    alpha = 0.1
    gamma = 2.21e5
    sim.alpha = alpha
    sim.gamma = gamma
    sim.mu_s = 1.0

    sim.set_m((1, 0, 0))
    print(sim.spin)

    H0 = 1e5
    sim.add(Zeeman((0, 0, H0)))

    ts = np.linspace(0, 1e-9, 101)

    mx = []
    my = []
    mz = []
    real_ts = []

    for t in ts:
        sim.run_until(t)
        real_ts.append(sim.t)
        #print sim.t, abs(sim.spin_length()[0] - 1)
        av = sim.compute_average()
        mx.append(av[0])
        my.append(av[1])
        mz.append(av[2])

        #sim.save_vtk()

    mz = np.array(mz)
    # print mz
    a_mx, a_my, a_mz = single_spin(alpha, gamma, H0, ts)

    print(sim.stat())

    if do_plot:
        plot(real_ts,
             mx,
             my,
             mz,
             a_mx,
             a_my,
             a_mz,
             name='spins.pdf',
             title='integrating spins')

    print(("Max Deviation = {0}".format(np.max(np.abs(mz - a_mz)))))

    assert np.max(np.abs(mz - a_mz)) < 5e-7
Beispiel #13
0
def test_skx_num_atomistic():
    """
    Test the *finite spin chirality* or skyrmion number for
    a discrete spins simulation in a two dimensional lattice

    The expression is (PRL 108, 017601 (2012)) :

    Q =     S_i \dot ( S_{i+1}  X  S_{j+1} )
         +  S_i \dot ( S_{i-1}  X  S_{j-1} )

    which measures the chirality taking two triangles of spins
    per lattice site i:
        S_{i} , S_{i + x} , S_{i + y}    and
        S_{i} , S_{i - x} , S_{i - y}

    The area of the two triangles cover a unit cell, thus the sum
    cover the whole area of the atomic lattice

    This test generate a skyrmion pointing down with unrealistic
    paremeters.

    """

    mesh = CuboidMesh(nx=120, ny=120, nz=1,
                      periodicity=(True, True, False))

    sim = Sim(mesh, name='skx_num')
    sim.set_tols(rtol=1e-6, atol=1e-6)
    sim.alpha = 1.0
    sim.gamma = 1.0
    sim.mu_s = 1.0

    sim.set_m(lambda pos: init_m(pos, 60, 60, 20))

    sim.do_precession = False

    J = 1.0
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.09
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman([0, 0, 5e-3])
    sim.add(zeeman)

    sim.relax(dt=2.0, stopping_dmdt=1e-2, max_steps=1000,
              save_m_steps=None, save_vtk_steps=None)

    skn = sim.skyrmion_number()
    print('skx_number', skn)
    assert skn > -1 and skn < -0.99
def test_zeeman():
    """
    Test the x and y component of the zeeman field
    for the 2nd spin

        6  7  8  9  10 11
        0  1  2  3  4  5
              ^
    """

    mesh = CuboidMesh(nx=5, ny=2, nz=1)

    sim = Sim(mesh)
    sim.set_m((1, 0, 0))

    zeeman = Zeeman(varying_field)
    sim.add(zeeman)

    field = zeeman.compute_field()

    assert field[2 * 3] == 1.2 * (2 + 0.5)
    assert field[2 * 3 + 1] == 2.3 * 0.5
Beispiel #15
0
def test_zeeman():
    """
    Test the x and y component of the zeeman field
    for the 2nd spin

        6  7  8  9  10 11
        0  1  2  3  4  5
              ^
    """

    mesh = CuboidMesh(nx=5, ny=2, nz=1)

    sim = Sim(mesh)
    sim.set_m((1, 0, 0))

    zeeman = Zeeman(varying_field)
    sim.add(zeeman)

    field = zeeman.compute_field()

    assert field[2 * 3] == 1.2 * (2 + 0.5)
    assert field[2 * 3 + 1] == 2.3 * 0.5
Beispiel #16
0
def test_sim_single_spin_sllg(do_plot=False):

    mesh = CuboidMesh(nx=1, ny=1, nz=1)

    sim = Sim(mesh, name='spin', driver='sllg')

    alpha = 0.1
    gamma = 2.21e5

    sim.set_options(dt=5e-15, gamma=gamma)

    sim.alpha = alpha
    sim.mu_s = 1.0

    sim.set_m((1, 0, 0))

    H0 = 1e5
    sim.add(Zeeman((0, 0, H0)))

    ts = np.linspace(0, 1e-10, 101)

    mx = []
    my = []
    mz = []
    real_ts = []
    for t in ts:
        sim.run_until(t)
        real_ts.append(sim.t)
        print(sim.t, abs(sim.spin_length()[0] - 1))
        mx.append(sim.spin[0])
        my.append(sim.spin[1])
        mz.append(sim.spin[2])

    mz = np.array(mz)

    a_mx, a_my, a_mz = single_spin(alpha, gamma, H0, ts)

    if do_plot:
        plot(real_ts,
             mx,
             my,
             mz,
             a_mx,
             a_my,
             a_mz,
             name='spin_sllg.pdf',
             title='integrating a spin')

    print(("Max Deviation = {0}".format(np.max(np.abs(mz - a_mz)))))

    assert np.max(np.abs(mz - a_mz)) < 1e-8
Beispiel #17
0
def relax_system(rtol=1e-10, atol=1e-12):
    """numerical solution"""
    mesh = CuboidMesh(nx=1, ny=1, nz=1)
    sim = Sim(mesh, name='relax')
    sim.driver.set_tols(rtol=rtol, atol=atol)
    sim.driver.alpha = 0.5
    sim.driver.gamma = 2.21e5
    sim.mu_s = 1.0

    sim.set_m((1.0, 0, 0))

    sim.add(Zeeman((0, 0, 1e5)))

    ts = np.linspace(0, 1e-9, 1001)

    for t in ts:
        sim.driver.run_until(t)
Beispiel #18
0
def disable_test_sim_single_spin_llg_stt(do_plot=False):
    ni = Nickel()
    mesh = CuboidMesh(nx=1, ny=1, nz=1)
    mesh.set_material(ni)

    ni.alpha = 0.1
    sim = Sim(mesh, driver='llg_stt')
    sim.set_m((1, 0, 0))

    H0 = 1
    sim.add(Zeeman((0, 0, H0)))

    dt = 1e-12
    ts = np.linspace(0, 200 * dt, 101)

    precession = ni.gamma / (1 + ni.alpha**2)

    mz_ref = []
    mxyz = []
    real_ts = []

    for t in ts:
        sim.run_until(t)
        real_ts.append(sim.t)
        print(sim.t, abs(sim.spin_length()[0] - 1), sim.spin)
        mz_ref.append(np.tanh(precession * ni.alpha * H0 * sim.t))
        mxyz.append(np.copy(sim.spin))

    mxyz = np.array(mxyz)

    if do_plot:
        ts_ns = np.array(real_ts) * 1e9

        plt.plot(ts_ns, mxyz[:, 0], ".-", label="mx")
        plt.plot(ts_ns, mxyz[:, 1], ".-", label="my")
        plt.plot(ts_ns, mxyz[:, 2], ".-", label="mz")
        plt.plot(ts_ns, mz_ref, "-", label="analytical")
        plt.xlabel("time (ns)")
        plt.ylabel("mz")
        plt.title("integrating a macrospin")
        plt.legend()
        plt.savefig("test_llg_stt.png")

        print(("Deviation = {0}".format(np.max(np.abs(mxyz[:, 2] - mz_ref)))))

    assert np.max(np.abs(mxyz[:, 2] - mz_ref)) < 1e-9
Beispiel #19
0
def create_simulation(R, B):
    mu_s = 3
    sim_hexagon = HexagonSim(
        R,  # R
        0.2715,  # a
        mu_s,  # mu_s
        name='unnamed')
    sim = sim_hexagon.sim

    # mask = (sim.mu_s / C.mu_B) > 1e-5
    exch = UniformExchange(5.881 * C.meV)
    sim.add(exch)
    dmi = DMI(D=1.557 * C.meV, dmi_type='interfacial')
    sim.add(dmi)
    sim.add(Zeeman([0., 0., B]))
    sim.add(Anisotropy(0.406 * C.meV, axis=[0, 0, 1]))

    return sim
Beispiel #20
0
def test_sim_single_spin_vode(do_plot=False):

    mesh = CuboidMesh(nx=1, ny=1, nz=1)

    sim = Sim(mesh, name='spin')

    alpha = 0.1
    gamma = 2.21e5
    sim.driver.alpha = alpha
    sim.driver.gamma = gamma
    sim.mu_s = 1.0

    sim.set_m((1, 0, 0))

    H0 = 1e5
    sim.add(Zeeman((0, 0, H0)))

    ts = np.linspace(0, 1e-9, 101)

    mx = []
    my = []
    mz = []
    real_ts = []
    for t in ts:
        sim.driver.run_until(t)
        real_ts.append(sim.driver.t)
        #print sim.driver.t, abs(sim.spin_length()[0] - 1)
        mx.append(sim.spin[0])
        my.append(sim.spin[1])
        mz.append(sim.spin[2])

    mz = np.array(mz)
    a_mx, a_my, a_mz = single_spin(alpha, gamma, H0, ts)

    print(sim.driver.stat())

    if do_plot:
        plot(real_ts, mx, my, mz, a_mx, a_my, a_mz)

    print(("Max Deviation = {0}".format(
        np.max(np.abs(mz - a_mz)))))

    assert np.max(np.abs(mz - a_mz)) < 5e-7
Beispiel #21
0
def test_skx_num_atomistic():
    """
    Test the *finite spin chirality* or skyrmion number for
    a discrete spins simulation in a two dimensional lattice

    The expression is (PRL 108, 017601 (2012)) :

    Q =     S_i \dot ( S_{i+1}  X  S_{j+1} )
         +  S_i \dot ( S_{i-1}  X  S_{j-1} )

    which measures the chirality taking two triangles of spins
    per lattice site i:
        S_{i} , S_{i + x} , S_{i + y}    and
        S_{i} , S_{i - x} , S_{i - y}

    The area of the two triangles cover a unit cell, thus the sum
    cover the whole area of the atomic lattice

    We also test the Berg and Luscher definition for a topological
    charge (see the hexagonal mesh test for details) in a
    square lattice.

    This test generate a skyrmion pointing down with unrealistic
    paremeters.

    """

    mesh = CuboidMesh(nx=120, ny=120, nz=1, periodicity=(True, True, False))

    sim = Sim(mesh, name='skx_num')
    sim.driver.set_tols(rtol=1e-6, atol=1e-6)
    sim.driver.alpha = 1.0
    sim.driver.gamma = 1.0
    sim.mu_s = 1.0

    sim.set_m(lambda pos: init_m(pos, 60, 60, 20))

    sim.do_precession = False

    J = 1.0
    exch = UniformExchange(J)
    sim.add(exch)

    D = 0.09
    dmi = DMI(D)
    sim.add(dmi)

    zeeman = Zeeman([0, 0, 5e-3])
    sim.add(zeeman)

    sim.relax(dt=2.0,
              stopping_dmdt=1e-2,
              max_steps=1000,
              save_m_steps=None,
              save_vtk_steps=None)

    skn = sim.skyrmion_number()
    print('skx_number', skn)

    skn_BL = sim.skyrmion_number(method='BergLuscher')
    print('skx_number_BergLuscher', skn_BL)

    # Test the finite chirality method
    assert skn > -1 and skn < -0.99

    # Test the Berg-Luscher method
    assert np.abs(skn_BL - (-1)) < 1e-4 and np.sign(skn_BL) < 0

    # Test guiding center
    Rx, Ry = compute_RxRy(mesh, sim.spin)
    print('Rx=%g, Ry=%g' % (Rx, Ry))
    assert Rx < 60 and Rx > 58
    assert Ry < 60 and Ry > 58
Beispiel #22
0
def test_skx_num_atomistic_hexagonal():
    """

    Test the topological charge or skyrmion number for a discrete spins
    simulation in a two dimensional hexagonal lattice, using Berg and Luscher
    definition in [Nucl Phys B 190, 412 (1981)] and simplified in [PRB 93,
    174403 (2016)], which maps a triangulated lattice (using triangles of
    neighbouring spins) area into a unit sphere.

    The areas of two triangles per lattice site cover a unit cell, thus the sum
    cover the whole area of the atomic lattice

    This test generates a skyrmion pointing down and two skyrmions pointing up
    in a PdFe sample using magnetic parameters from: PRL 114, 177203 (2015)

    """

    mesh = HexagonalMesh(0.2715, 41, 41, periodicity=(True, True))

    sim = Sim(mesh, name='skx_number_hexagonal')
    sim.driver.set_tols(rtol=1e-6, atol=1e-6)
    sim.driver.alpha = 1.0
    sim.driver.gamma = 1.0
    sim.mu_s = 3 * const.mu_B

    sim.set_m(lambda pos: init_m(pos, 16.1, 10, 2))

    sim.driver.do_precession = False

    J = 5.881 * const.meV
    exch = UniformExchange(J)
    sim.add(exch)

    D = 1.557 * const.meV
    dmi = DMI(D, dmi_type='interfacial')
    sim.add(dmi)

    sim.add(Anisotropy(0.406 * const.meV, axis=[0, 0, 1]))

    zeeman = Zeeman([0, 0, 2.5])
    sim.add(zeeman)

    sim.relax(dt=1e-13,
              stopping_dmdt=1e-2,
              max_steps=2000,
              save_m_steps=None,
              save_vtk_steps=100)

    skn_single = sim.skyrmion_number(method='BergLuscher')
    print('skx_number_hexagonal', skn_single)

    # Now we generate two skyrmions pointing up
    sim.driver.reset_integrator()
    sim.set_m(
        lambda pos: init_m_multiple_sks(pos, 1, sk_pos=[(9, 6), (18, 12)]))
    sim.get_interaction('Zeeman').update_field([0, 0, -2.5])
    sim.relax(dt=1e-13,
              stopping_dmdt=1e-2,
              max_steps=2000,
              save_m_steps=None,
              save_vtk_steps=None)

    skn_two = sim.skyrmion_number(method='BergLuscher')
    print('skx_number_hexagonal_two', skn_two)

    # Check that we get a right sk number
    assert np.abs(skn_single - (-1)) < 1e-4 and np.sign(skn_single) < 0
    assert np.abs(skn_two - (2)) < 1e-4 and np.sign(skn_two) > 0
Beispiel #23
0
from fidimag.atomistic import Sim
from fidimag.common.cuboid_mesh import CuboidMesh
from fidimag.atomistic import UniformExchange, Zeeman
import fidimag.common.constant as const

mesh = CuboidMesh(nx=1, ny=1, dx=1, dy=1)

sim = Sim(mesh, name='relax_sk')
sim.gamma = const.gamma
sim.set_m((1, 0, 0))
sim.add(Zeeman((0, 0, 25.)))

sim.run_until(1e-11)
sim.set_tols(rtol=1e-10, atol=1e-12)
sim.run_until(2e-11)
Beispiel #24
0
                      dy=dy,
                      dz=dz,
                      x0=-nx * 0.5,
                      y0=-ny * 0.5,
                      z0=-nz * 0.5,
                      unit_length=1.,
                      periodicity=(True, True, False))

    sim_name = 'sk_helix'
    sim = Sim(mesh, name=sim_name, integrator='sundials_openmp')

    sim.mu_s = 1
    sim.add(Exchange(1))
    sim.add(DMI(0.727, dmi_type='bulk'))
    bz_min = FIELD
    sim.add(Zeeman((0.0, 0.0, bz_min * 1e-3)), save_field=True)
    kc = -0.05
    if np.abs(kc) > 0.0:
        sim.add(CubicAnisotropy(kc))

    # .........................................................................

    sim.driver.alpha = 0.9
    sim.driver.do_precession = False

    # Zeeman_int = sim.get_interaction('Zeeman')
    # Zeeman_int.update_field((0.0, 0.0, B_sweep * 1e-3))

    H_BG = np.load(
        f'../npys/helix-y_kc-5e-2_L10/m_helix-y_kc-5e-2_L10_Bz_{FIELD:06d}.npy'
    )
Beispiel #25
0
    def generate_simulation(self,
                            do_precession=False,
                            gamma=1.76e11,
                            load_mu_s=False):
        """

        Generates a simulation according to the self.simulation option

        gamma       :: Default is the free electron gyromagnetic ratio
        load_mu_s   :: A file path to a NPY file with the mu_s information
                       (only for the experimental_sample option)

        """

        # Mesh ----------------------------------------------------------------

        if self.simulation == 'experimental_sample':
            self.sim_from_image = sfi.sim_from_image(sfi.default_image)

            if not load_mu_s:
                self.sim_from_image.generate_magnetic_moments(mu_s=self.mu_s)
            else:
                self.sim_from_image.generate_magnetic_moments(
                    load_file=load_mu_s)

            self.sim = self.sim_from_image.sim

        elif self.simulation == '2D_square':
            # A square sized hexagonal mesh
            mesh = HexagonalMesh(
                self.mesh_a * 0.5,
                self.mesh_nx,
                self.mesh_ny,
                # periodicity=(True, True),
                alignment='square',
                unit_length=1e-9)
            self.sim = Sim(mesh)

            # If we use polygon mesh tools, we can use a hexagon shaped mesh
            # self.sim.mu_s = self.mu_s_in_hexagon

            self.sim.mu_s = self.mu_s

        elif self.simulation == '1D_chain':
            # A 1D chain using a cuboid mesh
            mesh = CuboidMesh(
                dx=self.mesh_a,
                nx=self.mesh_nx,
                ny=1,
                nz=1,
                # periodicity=(True, True),
                unit_length=1e-9)
            self.sim = Sim(mesh)

            # If we use polygon mesh tools, we can use a hexagon shaped mesh
            # self.sim.mu_s = self.mu_s_in_hexagon

            self.sim.mu_s = self.mu_s

        self.sim.driver.do_precession = do_precession
        self.sim.driver.gamma = gamma

        # Interactions --------------------------------------------------------

        exch = UniformExchange(self.J)
        self.sim.add(exch)

        dmi = DMI(D=(self.D), dmi_type='interfacial')
        self.sim.add(dmi)

        zeeman = Zeeman((self.B[0], self.B[1], self.B[2]))
        self.sim.add(zeeman, save_field=True)

        if self.ku:
            # Uniaxial anisotropy along + z-axis
            self.sim.add(Anisotropy(self.ku, axis=[0, 0, 1]))

        if self.Demag:
            print('Using Demag!')
            self.sim.add(DemagHexagonal())

        # ---------------------------------------------------------------------

        self.hls = np.ones_like(self.sim.spin.reshape(-1, 3))
        self.rgbs = np.ones((self.sim.spin.reshape(-1, 3).shape[0], 4))
Beispiel #26
0
def simulation(nx,
               ny,
               nz,
               dx,
               dy,
               dz,
               j,
               d,
               kc,
               mu_s,
               sim_name,
               bz_min,
               bz_max,
               bz_steps,
               bz_hysteresis=False,
               initial_state_one_bobber=None,
               initial_state_two_bobbers=None,
               initial_state_two_bobbers_asymm=None,
               initial_state_sk_tube=None,
               initial_state_one_dim_mod=None,
               initial_state_helix_angle_x=(None, None),
               stopping_dmdt=1e-5,
               max_steps=4000,
               save_initial_state=None):

    mesh = CuboidMesh(nx=nx,
                      ny=ny,
                      nz=nz,
                      dx=dx,
                      dy=dy,
                      dz=dz,
                      x0=-nx * 0.5,
                      y0=-ny * 0.5,
                      z0=-nz * 0.5,
                      unit_length=1.,
                      periodicity=(True, True, False))

    # J = 1.
    # D = 0.628  # L_D = 2 PI a J / D = 10 * a => D / J = 2 PI / 10.
    # Bz = 0.2   # B_z == (B_z mu_s / J)
    # mu_s = 1.

    sim = Sim(mesh, name=sim_name, integrator='sundials_openmp')

    sim.mu_s = mu_s
    sim.add(Exchange(j))
    sim.add(DMI(d, dmi_type='bulk'))
    sim.add(Zeeman((0.0, 0.0, bz_min * 1e-3)), save_field=True)
    if np.abs(kc) > 0.0:
        sim.add(CubicAnisotropy(kc))

    # .........................................................................

    sim.driver.alpha = 0.9
    sim.driver.do_precession = False

    if not os.path.exists('npys/{}'.format(sim_name)):
        os.makedirs('npys/{}'.format(sim_name))

    if not os.path.exists('txts'):
        os.makedirs('txts')

    for i, B_sweep in enumerate(np.linspace(bz_min, bz_max, bz_steps)):

        print('Bz = {:.0f} mT '.format(B_sweep).ljust(80, '-'))

        Zeeman_int = sim.get_interaction('Zeeman')
        Zeeman_int.update_field((0.0, 0.0, B_sweep * 1e-3))

        if (not bz_hysteresis) or (bz_hysteresis and i < 1):

            if initial_state_one_dim_mod:
                sim.set_m(lambda r: one_dim_mod(r, B_sweep * 1e-3, d))
            elif initial_state_helix_angle_x[0]:
                angle = initial_state_helix_angle_x[0] * np.pi / 180.
                periodic = initial_state_helix_angle_x[1]
                sim.set_m(lambda r: helix_angle_x(r, angle, periodic))
            elif initial_state_sk_tube:
                sk_rad = initial_state_sk_tube
                sim.set_m(
                    lambda r: sk_tube(r, B_sweep * 1e-3, d, sk_rad=sk_rad))
            elif initial_state_two_bobbers:
                bobber_length = initial_state_two_bobbers
                sim.set_m(lambda r: two_bobbers(r,
                                                B_sweep * 1e-3,
                                                d,
                                                mesh.Lz,
                                                bobber_rad=3.,
                                                bobber_length=bobber_length))
            elif initial_state_two_bobbers_asymm:
                bobber_length = initial_state_two_bobbers_asymm
                sim.set_m(
                    lambda r: two_bobbers_asymm(r,
                                                B_sweep * 1e-3,
                                                d,
                                                mesh.Lz,
                                                bobber_rad=3.,
                                                bobber_length=bobber_length))
            elif initial_state_one_bobber:
                bobber_length = initial_state_one_bobber
                sim.set_m(lambda r: one_bobber(r,
                                               B_sweep * 1e-3,
                                               d,
                                               mesh.Lz,
                                               bobber_rad=3.,
                                               bobber_length=bobber_length))
            else:
                raise Exception('Not a valid initial state')

        if save_initial_state:
            save_vtk(sim, sim_name + '_INITIAL', field_mT=B_sweep)
            name = 'npys/{}/m_{}_INITIAL_Bz_{:06d}.npy'.format(
                sim.driver.name, sim_name, int(B_sweep))
            np.save(name, sim.spin)

        # .....................................................................

        sim.relax(stopping_dmdt=stopping_dmdt,
                  max_steps=max_steps,
                  save_m_steps=None,
                  save_vtk_steps=None)

        # .....................................................................

        save_vtk(sim, sim_name, field_mT=B_sweep)
        name = 'npys/{}/m_{}_Bz_{:06d}.npy'.format(sim.driver.name, sim_name,
                                                   int(B_sweep))
        np.save(name, sim.spin)

        sim.driver.reset_integrator()

    shutil.move(sim_name + '.txt', 'txts/{}.txt'.format(sim_name))
Beispiel #27
0
def simulation(nx,
               ny,
               nz,
               dx,
               dy,
               dz,
               j,
               d,
               kc,
               bz,
               mu_s,
               sim_name,
               add_image=None,
               add_interpolations=None,
               add_images_folder=None,
               spring_constant=None,
               stopping_dydt=None,
               max_steps=None,
               keep_sim_climbing_image_steps=None,
               save_m_every=None,
               climbing_image=None,
               keep_sim_climbing_image=None,
               keep_sim_climbing_image_again=None,
               integrator='sundials',
               integrator_stepsize=1e-3,
               interpolation_method='rotation',
               variable_spring_forces=None,
               interpolation_energy='polynomial'):

    if add_interpolations:
        if (len(add_image) - 1) != len(add_interpolations):
            raise Exception('(N interpolations) != (N images - 1)')

    mesh = CuboidMesh(nx=nx,
                      ny=ny,
                      nz=nz,
                      dx=dx,
                      dy=dy,
                      dz=dz,
                      x0=-nx * 0.5,
                      y0=-ny * 0.5,
                      z0=-nz * 0.5,
                      unit_length=1.,
                      periodicity=(True, True, False))

    # Simulation
    sim = Sim(mesh, name=sim_name)
    sim.mu_s = mu_s
    sim.add(Exchange(j))
    sim.add(DMI(d, dmi_type='bulk'))
    sim.add(Zeeman((0.0, 0.0, bz * 1e-3)))
    if np.abs(kc) > 0.0:
        sim.add(CubicAnisotropy(kc))

    # GNEBM simulation ........................................................

    if add_interpolations:
        # Set the initial images from the list
        init_images = [np.load(image) for image in add_image]
        interpolations = [i for i in add_interpolations]
    elif add_images_folder:
        if add_images_folder.endswith('_LAST'):
            dir_list = glob.glob(add_images_folder[:-5] + '*')
            dir_list = sorted(
                dir_list,
                key=lambda f: int(re.search(r'(?<=_)[0-9]+$', f).group(0)))
            add_images_folder = dir_list[-1]

        flist = sorted(os.listdir(add_images_folder))
        init_images = [
            np.load(os.path.join(add_images_folder, image)) for image in flist
        ]
        interpolations = []
    else:
        raise Exception('Specify an option to add images')

    if climbing_image:
        if climbing_image.isdigit():
            climbing_image = int(climbing_image)
        else:
            try:
                energies = np.loadtxt(climbing_image)[-1][1:]
                energies = energies - energies[0]
                climbing_image = np.where(energies == np.max(energies))[0][0]
            except OSError:
                raise Exception('Err trying to compute climb image from file')

        print('Using climbing image: {}'.format(climbing_image))

    # Start a NEB simulation passing the Simulation object and all the NEB
    # parameters
    neb = NEBM_Geodesic(sim,
                        init_images,
                        interpolations=interpolations,
                        spring_constant=spring_constant,
                        name=sim_name,
                        openmp=True,
                        climbing_image=climbing_image,
                        integrator=integrator,
                        interpolation_method=interpolation_method)

    if integrator == 'verlet':
        neb.integrator.mass = 1
        neb.integrator.stepsize = integrator_stepsize
        dt = integrator_stepsize * 10
    else:
        dt = integrator_stepsize

    # .........................................................................

    for fdir in ['interpolations', 'ndts']:
        if not os.path.exists(fdir):
            os.makedirs(fdir)

    # Finally start the energy band relaxation
    neb.relax(max_iterations=max_steps,
              save_vtks_every=save_m_every,
              save_npys_every=save_m_every,
              stopping_dYdt=stopping_dydt,
              dt=dt)

    if variable_spring_forces:
        neb.variable_k = True
        neb.dk = spring_constant * 0.9

        neb.relax(max_iterations=max_steps,
                  save_vtks_every=save_m_every,
                  save_npys_every=save_m_every,
                  stopping_dYdt=stopping_dydt,
                  dt=dt,
                  save_initial_state=False)

    # Continue with climbing image if specified
    if keep_sim_climbing_image:

        if not keep_sim_climbing_image_steps:
            keep_sim_climbing_image_steps = max_steps

        # Find all local maxima
        largest_E_im_idx = []
        for i in range(2, neb.n_images - 2):
            if (neb.energies[i] > neb.energies[i - 1]
                    and neb.energies[i - 1] > neb.energies[i - 2]
                    and neb.energies[i] > neb.energies[i + 1]
                    and neb.energies[i + 1] > neb.energies[i + 2]):

                largest_E_im_idx.append(i)
            elif (neb.energies[i] < neb.energies[i - 1]
                  and neb.energies[i - 1] < neb.energies[i - 2]
                  and neb.energies[i] < neb.energies[i + 1]
                  and neb.energies[i + 1] < neb.energies[i + 2]):

                largest_E_im_idx.append(-i)

        neb.climbing_image = largest_E_im_idx

        print('Continuing simulation with CI = {}'.format(largest_E_im_idx))

        neb.name += '_CI'
        # Data will be appended to the initial NDT file, at least we create a
        # new one with the CI appended to the sim name:
        # neb.create_tablewriter()
        # last_step_relax = neb.iterations

        # Variable dk for better resolution around saddle points
        # neb.variable_k = True
        # neb.dk = spring_constant

        neb.relax(max_iterations=keep_sim_climbing_image_steps,
                  save_vtks_every=save_m_every,
                  save_npys_every=save_m_every,
                  stopping_dYdt=keep_sim_climbing_image,
                  dt=dt,
                  save_initial_state=False)

        # Remove initial state (same as final state from the prev relaxation)
        # shutil.rmtree('vtks/{}_{}'.format(neb.name, last_step_relax))

    # Continue with climbing image if specified
    if keep_sim_climbing_image_again:

        if not keep_sim_climbing_image_steps:
            keep_sim_climbing_image_steps = max_steps

        # Find all local maxima
        largest_E_im_idx = []
        for i in range(2, neb.n_images - 2):
            if (neb.energies[i] > neb.energies[i - 1]
                    and neb.energies[i - 1] > neb.energies[i - 2]
                    and neb.energies[i] > neb.energies[i + 1]
                    and neb.energies[i + 1] > neb.energies[i + 2]):

                largest_E_im_idx.append(i)
            elif (neb.energies[i] < neb.energies[i - 1]
                  and neb.energies[i - 1] < neb.energies[i - 2]
                  and neb.energies[i] < neb.energies[i + 1]
                  and neb.energies[i + 1] < neb.energies[i + 2]):

                largest_E_im_idx.append(-i)

        neb.climbing_image = largest_E_im_idx
        print('Continuing simulation with CI = {}'.format(largest_E_im_idx))
        neb.name += '_CI'
        neb.relax(max_iterations=keep_sim_climbing_image_steps,
                  save_vtks_every=save_m_every,
                  save_npys_every=save_m_every,
                  stopping_dYdt=keep_sim_climbing_image_again,
                  dt=dt,
                  save_initial_state=False)

    # Produce a file with the data from a cubic interpolation for the band
    interp_data = np.zeros((200, 2))
    if interpolation_energy == 'polynomial':
        neb.compute_polynomial_factors()
        (interp_data[:, 0],
         interp_data[:, 1]) = neb.compute_polynomial_approximation_energy(200)
    elif interpolation_energy == 'Bernstein':
        neb.compute_Bernstein_polynomials()
        (interp_data[:, 0],
         interp_data[:, 1]) = neb.compute_Bernstein_approximation_energy(200)
    else:
        raise Exception('No valid interpolation method')

    np.savetxt('interpolations/{}_interpolation.dat'.format(sim_name),
               interp_data)

    # Clean files
    shutil.move(sim_name + '_energy.ndt',
                'ndts/{}_energy.ndt'.format(sim_name))
    shutil.move(sim_name + '_dYs.ndt', 'ndts/{}_dYs.ndt'.format(sim_name))
Beispiel #28
0
if args.alpha:
    sim.driver.alpha = args.alpha
# sim.gamma = 2.211e5

# Material parameters ---------------------------------------------------------

sim.mu_s = args.mu_s * const.mu_B

exch = UniformExchange(args.J * const.meV)
sim.add(exch)

dmi = DMI(D=(args.D * const.meV), dmi_type='interfacial')
sim.add(dmi)

if args.B:
    zeeman = Zeeman((0, 0, args.B))
    sim.add(zeeman, save_field=True)

if args.k_u:
    # Uniaxial anisotropy along + z-axis
    sim.add(Anisotropy(args.k_u * const.meV, axis=[0, 0, 1]))

if args.Demag:
    sim.add(DemagHexagonal())

# -----------------------------------------------------------------------------

# Debug Information -----------------------------------------------------------

print('Saturation Magnetisation: {} mu_B'.format(args.mu_s))
print('Exchange constant: {}  meV'.format(args.J))
Beispiel #29
0
def simulation(nx,
               ny,
               nz,
               dx,
               dy,
               dz,
               j,
               d,
               kc,
               bz,
               mu_s,
               sim_name,
               add_image=None,
               add_interpolations=None,
               add_images_folder=None,
               stopping_dydt=None,
               max_steps=None,
               save_m_every=None,
               integrator='sundials',
               integrator_stepsize=1e-3,
               interpolation_method='rotation',
               variable_spring_forces=None,
               interpolation_energy='polynomial'):

    if add_interpolations:
        if (len(add_image) - 1) != len(add_interpolations):
            raise Exception('(N interpolations) != (N images - 1)')

    mesh = CuboidMesh(nx=nx,
                      ny=ny,
                      nz=nz,
                      dx=dx,
                      dy=dy,
                      dz=dz,
                      x0=-nx * 0.5,
                      y0=-ny * 0.5,
                      z0=-nz * 0.5,
                      unit_length=1.,
                      periodicity=(True, True, False))

    # Simulation
    sim = Sim(mesh, name=sim_name)
    sim.mu_s = mu_s
    sim.add(Exchange(j))
    sim.add(DMI(d, dmi_type='bulk'))
    sim.add(Zeeman((0.0, 0.0, bz * 1e-3)))
    if np.abs(kc) > 0.0:
        sim.add(CubicAnisotropy(kc))

    # GNEBM simulation ........................................................

    if add_interpolations:
        # Set the initial images from the list
        init_images = [np.load(image) for image in add_image]
        interpolations = [i for i in add_interpolations]
    elif add_images_folder:
        if add_images_folder.endswith('_LAST'):
            dir_list = glob.glob(add_images_folder[:-5] + '*')
            dir_list = sorted(
                dir_list,
                key=lambda f: int(re.search(r'(?<=_)[0-9]+$', f).group(0)))
            add_images_folder = dir_list[-1]

        flist = sorted(os.listdir(add_images_folder))
        init_images = [
            np.load(os.path.join(add_images_folder, image)) for image in flist
        ]
        interpolations = []
    else:
        raise Exception('Specify an option to add images')

    # Start a NEB simulation passing the Simulation object and all the NEB
    # parameters
    string = StringMethod(sim,
                          init_images,
                          interpolations=interpolations,
                          name=sim_name,
                          openmp=True,
                          integrator=integrator,
                          interpolation_method=interpolation_method)

    if integrator == 'verlet':
        string.integrator.mass = 1
        string.integrator.stepsize = integrator_stepsize
        dt = integrator_stepsize * 10
    else:
        dt = integrator_stepsize

    # .........................................................................

    for fdir in ['interpolations', 'ndts']:
        if not os.path.exists(fdir):
            os.makedirs(fdir)

    # Finally start the energy band relaxation
    string.relax(max_iterations=max_steps,
                 save_vtks_every=save_m_every,
                 save_npys_every=save_m_every,
                 stopping_dYdt=stopping_dydt,
                 dt=dt)

    # Produce a file with the data from a cubic interpolation for the band
    interp_data = np.zeros((200, 2))
    if interpolation_energy == 'polynomial':
        string.compute_polynomial_factors()
        (interp_data[:, 0],
         interp_data[:,
                     1]) = string.compute_polynomial_approximation_energy(200)
    elif interpolation_energy == 'Bernstein':
        string.compute_Bernstein_polynomials()
        (interp_data[:, 0],
         interp_data[:,
                     1]) = string.compute_Bernstein_approximation_energy(200)
    else:
        raise Exception('No valid interpolation method')

    np.savetxt('interpolations/{}_interpolation.dat'.format(sim_name),
               interp_data)

    # Clean files
    shutil.move(sim_name + '_energy.ndt',
                'ndts/{}_energy.ndt'.format(sim_name))
    shutil.move(sim_name + '_dYs.ndt', 'ndts/{}_dYs.ndt'.format(sim_name))
Beispiel #30
0
def hysteresis_loop(config_file,
                    D=1.56, J=5.88, k_u=0.41, mu_s=3, B=(0, 0, 0), Demag=None,
                    ):
    """
    The config file must have the following parameters:
        D
        J
        k_u
        mu_s                :: Magnitude in Bohr magneton units. A file path
                               can be specified to load a NPY file with the
                               mu_s values, when using the mesh_from_image
                               option
        Demag               :: Set to True for Demag
        sim_name            :: Simulation name
        initial_state       :: A function or a npy file
        hysteresis_steps    ::
        mesh_from_image     :: [IMAGE_PATH, xmin, xmax, ymin, ymax]
        hexagonal_mesh      :: [nx, ny, a]
        PBC_2D              :: Set to True for Periodic boundaries
        pin_boundaries      :: Set to True to pin the spins at the boundaries.
                               Their orientations are already given from the
                               initial_state NPY file
        llg_dt              ::
        llg_stopping_dmdt   ::
        llg_max_steps       ::
        llg_do_precession   :: False as default
        llg_alpha           :: 0.01 as default

    """

    # Parameters --------------------------------------------------------------

    cf = {}
    # execfile(config_file, cf)
    # Python3:
    exec(open(config_file).read(), cf)

    D = cf["D"] * const.meV
    J = cf["J"] * const.meV
    k_u = cf["k_u"] * const.meV

    if isinstance(cf["mu_s"], int) or isinstance(cf["mu_s"], float):
        mu_s = cf["mu_s"] * const.mu_B

    if isinstance(cf["initial_state"], str):
        init_state = np.load(cf["initial_state"])
    elif isinstance(cf["initial_state"], types.FunctionType):
        init_state = cf["initial_state"]

    # Set up default arguments
    default_args = {"mesh_alignment": 'diagonal',
                    "mesh_unit_length": 1e-9,
                    "llg_dt": 1e-11,
                    "llg_stopping_dmdt": 1e-2,
                    "llg_max_steps": 4000,
                    "llg_do_precession": False,
                    "llg_alpha": 0.01
                    }

    for key in default_args.keys():
        if not cf.get(key):
            print(default_args[key])
            cf[key] = default_args[key]

    # Simulation object -------------------------------------------------------

    if cf.get("hexagonal_mesh"):
        if not cf["PBC_2D"]:
            mesh = HexagonalMesh(cf["hexagonal_mesh"][2] * 0.5,
                                 int(cf["hexagonal_mesh"][0]),
                                 int(cf["hexagonal_mesh"][1]),
                                 alignment=cf["mesh_alignment"],
                                 unit_length=cf["mesh_unit_length"]
                                 )

        else:
            mesh = HexagonalMesh(cf["hexagonal_mesh"][2] * 0.5,
                                 int(cf["hexagonal_mesh"][0]),
                                 int(cf["hexagonal_mesh"][1]),
                                 periodicity=(True, True),
                                 alignment=cf["mesh_alignment"],
                                 unit_length=cf["mesh_unit_length"]
                                 )

        sim = Sim(mesh, name=cf["sim_name"])

    elif cf.get("mesh_from_image"):
        sim_from_image = sfi.sim_from_image(
            cf["mesh_from_image"][0],
            image_range=[float(cf["mesh_from_image"][1]),
                         float(cf["mesh_from_image"][2]),
                         float(cf["mesh_from_image"][3]),
                         float(cf["mesh_from_image"][4])
                         ],
            sim_name=cf["sim_name"]
            )

        if isinstance(cf["mu_s"], str):
            sim_from_image.generate_magnetic_moments(load_file=cf["mu_s"])
        else:
            sim_from_image.generate_magnetic_moments(mu_s=(mu_s))

        sim = sim_from_image.sim

    elif cf.get("truncated_triangle"):
        if len(cf["truncated_triangle"]) == 3:
            sim_triangle = TruncatedTriangleSim(
                cf["truncated_triangle"][0],  # L
                cf["truncated_triangle"][1],  # offset
                cf["truncated_triangle"][2],  # a
                cf["mu_s"],                   # mu_s
                name=cf["sim_name"]
                )
        elif len(cf["truncated_triangle"]) == 5:
            sim_triangle = TruncatedTriangleSim(
                cf["truncated_triangle"][0],    # L
                [float(offs) for offs in cf["truncated_triangle"][1:4]],  # offsets
                cf["truncated_triangle"][4],    # a
                cf["mu_s"],                     # mu_s
                name=cf["sim_name"]
                )

        sim = sim_triangle.sim

    elif cf.get("hexagon"):
        sim_hexagon = HexagonSim(cf["hexagon"][0],    # R
                                 cf["hexagon"][1],    # a
                                 cf["mu_s"],          # mu_s
                                 name=cf["sim_name"]
                                 )
        sim = sim_hexagon.sim

    # Initial state
    sim.set_m(init_state)

    sim.driver.do_precession = cf["llg_do_precession"]
    sim.driver.alpha = cf["llg_alpha"]

    # Material parameters -----------------------------------------------------

    if cf.get("hexagonal_mesh"):
        sim.mu_s = mu_s

    exch = UniformExchange(J)
    sim.add(exch)

    dmi = DMI(D=(D), dmi_type='interfacial')
    sim.add(dmi)

    zeeman = Zeeman((0, 0, 0))
    sim.add(zeeman, save_field=True)

    if k_u:
        # Uniaxial anisotropy along + z-axis
        sim.add(Anisotropy(k_u, axis=[0, 0, 1]))

    if cf.get("Demag"):
        print('Using Demag!')
        sim.add(DemagHexagonal())

    # Pin boundaries ----------------------------------------------------------

    # We will correct the spin directions according to the specified argument,
    # in case the spins at the boundaries are pinned
    if cf.get('pin_boundaries'):
        ngbs_filter = np.zeros(sim.pins.shape[0])
        # Filter rows by checking if any of the elements is less than zero
        # This means that if any of the neighbours of the i-th lattice site is
        # -1, we pin the spin direction at that site
        ngbs_filter = np.any(sim.mesh.neighbours < 0, axis=1, out=ngbs_filter)

        sim.set_pins(ngbs_filter)

    # Hysteresis --------------------------------------------------------------

    for ext in ['npys', 'vtks']:
        if not os.path.exists('{}/{}'.format(ext, cf["sim_name"])):
            os.makedirs('{}/{}'.format(ext, cf["sim_name"]))

    for ext in ['txts', 'dats']:
        if not os.path.exists('{}/'.format(ext)):
            os.makedirs('{}'.format(ext))

    Brange = cf["hysteresis_steps"]
    print('Computing for Fields:', Brange)

    # We will save the hysteresis steps on this file with every row as:
    # step_number field_in_Tesla
    hystfile = '{}_hyst_steps.dat'.format(cf["sim_name"])
    # If the file already exists, we will append the new steps, otherwise
    # we just create a new file (useful for restarting simulations)
    if not os.path.exists(hystfile):
        nsteps = 0
        fstate = 'w'
    else:
        # Move old txt file from the previous simulation, appending an _r
        # everytime a simulation with the same name is started
        txtfile = [f for f in os.listdir('.') if f.endswith('txt')][0]
        txtfile = re.search(r'.*(?=\.txt)', txtfile).group(0)
        shutil.move(txtfile + '.txt', txtfile + '_r.txt')

        nsteps = len(np.loadtxt(hystfile))
        fstate = 'a'

    f = open(hystfile, fstate)

    for i, B in enumerate(Brange):
        sim.get_interaction('Zeeman').update_field(B)

        sim.driver.relax(dt=cf["llg_dt"],
                         stopping_dmdt=cf["llg_stopping_dmdt"],
                         max_steps=cf["llg_max_steps"],
                         save_m_steps=None,
                         save_vtk_steps=None
                         )

        print('Saving NPY for B = {}'.format(B))
        np.save('npys/{0}/step_{1}.npy'.format(cf["sim_name"], i + nsteps),
                sim.spin)

        sim.driver.save_vtk()
        shutil.move('{}_vtks/m_{}.vtk'.format(cf["sim_name"],
                                              str(sim.driver.step).zfill(6)
                                              ),
                    'vtks/{0}/step_{1}.vtk'.format(cf["sim_name"], i + nsteps)
                    )

        f.write('{} {} {} {}\n'.format(i + nsteps,
                                       B[0], B[1], B[2],
                                       )
                )
        f.flush()
        sim.driver.reset_integrator()

    os.rmdir('{}_vtks'.format(cf["sim_name"]))
    shutil.move('{}.txt'.format(cf["sim_name"]), 'txts/')
    shutil.move(hystfile, 'dats/')

    f.close()