Beispiel #1
0
def test_coordinates_y():
    r"""
       /\ /\
      |  |  |
      | 2| 3|
     /\ /\ /
    |  |  |    Hexagon size 1.
    | 0| 1|    Cells 2 x 2.
     \/ \/

    """
    size = 1
    mesh = HexagonalMesh(size, 2, 1)
    width = size * 2.0
    # height refers to the y-distance between two hexagons
    # centres in consecutive rows
    height = sqrt(3) * size
    # This is the total hexagon height that we use as the base
    hex_height = 2.0 * width / sqrt(3)
    mesh = HexagonalMesh(size, 2, 2)
    assert allclose(mesh.coordinates, np.array((
        (width / 2.0, hex_height / 2.0, 0),
        (width * 3.0 / 2.0, hex_height / 2.0, 0),
        (width, height + hex_height / 2.0, 0),
        (width * 2, height + hex_height / 2.0, 0))))
Beispiel #2
0
def test_nearest_neighbours_multiple():
    r"""
         /\ /\ /\
        |  |  |  |
        | 6| 7| 8|
       /\ /\ /\ /
      |  |  |  |
      | 3| 4| 5|
     /\ /\ /\ /
    |  |  |  |    Hexagon size 1.
    | 0| 1| 2|    Cells 3 x 3.
     \/ \/ \/

    """
    mesh = HexagonalMesh(1, 3, 3)
    print(mesh.neighbours)
    # assert to_sets(mesh.neighbours) == [{1, 3}, {0, 2, 3, 4},  # cells 0, 1
    #                                     {1, 4, 5}, {0, 1, 4, 6},  # cells 2, 3
    #                                     {1, 2, 3, 5, 6, 7}, {2, 4, 7, 8},  # cells 4, 5
    #                                     {3, 4, 7}, {4, 5, 6, 8},  # cells 6, 7
    #                                     {5, 7}]  # cell 8
    assert (mesh.neighbours == [[1, -1, 3, -1, -1, -1],  # cell 0
                                [2, 0, 4, -1, 3, -1],    # cell 1
                                [-1, 1, 5, -1, 4, -1],   # cell 2
                                [4, -1, 6, 0, -1, 1],    # cell 3
                                [5, 3, 7, 1, 6, 2],      # cell 4
                                [-1, 4, 8, 2, 7, -1],    # cell 5
                                [7, -1, -1, 3, -1, 4],   # ...
                                [8, 6, -1, 4, -1, 5],
                                [-1, 7, -1, 5, -1, -1]
                                ]
            ).all()
Beispiel #3
0
def test_nearest_neighbours_multiple_square():
    r"""

       /\ /\ /\
      |  |  |  |
      | 6| 7| 8|
     /\ /\ /\ /
    |  |  |  |
    | 3| 4| 5|
     \ /\ /\ /\
      |  |  |  |
      | 0| 1| 2|   Hexagon size 1.
       \/ \/ \/    Cells 3 x 3.

    """
    mesh = HexagonalMesh(1, 3, 3, alignment='square')
    print(mesh.neighbours)
    assert (mesh.neighbours == [[1, -1, 4, -1, 3, -1],   # cell 0
                                [2, 0, 5, -1, 4, -1],    # cell 1
                                [-1, 1, -1, -1, 5, -1],  # cell 2
                                [4, -1, 6, -1, -1, 0],   # ...
                                [5, 3, 7, 0, 6, 1],
                                [-1, 4, 8, 1, 7, 2],
                                [7, -1, -1, 3, -1, 4],
                                [8, 6, -1, 4, -1, 5],
                                [-1, 7, -1, 5, -1, -1]
                                ]
            ).all()
Beispiel #4
0
    def generate_mesh(self):

        nx = int(np.around(2 * self.R / self.lattice_a)) + 1
        ny = int(np.around(2 * self.R * np.cos(np.pi / 6)
                           / (self.lattice_a * np.sqrt(3) * 0.5)
                           )) + 1

        self.mesh = HexagonalMesh(self.lattice_a * 0.5, nx, ny,
                                  alignment='square', unit_length=1e-9,
                                  shells=self.shells
                                  )
Beispiel #5
0
def test_neighbours_x_periodic():
    r"""

     /\ /\
    |  |  |  Hexagon size 1.
    | 0| 1|  Cells 2 x 1.
     \/ \/

    """
    mesh = HexagonalMesh(1, 2, 1, periodicity=(True, False))
    assert (mesh.neighbours == [[1, 1, -1, -1, -1, -1],
                                [0, 0, -1, -1, -1, -1]]).all()
Beispiel #6
0
def test_neighbours_x():
    r"""

     /\ /\
    |  |  |  Hexagon size 1.
    | 0| 1|  Cells 2 x 1.
     \/ \/

    """
    mesh = HexagonalMesh(1, 2, 1)
    # assert to_sets(mesh.neighbours) == [{1}, {0}]
    assert (mesh.neighbours == [[1, -1, -1, -1, -1, -1],
                                [-1, 0, -1, -1, -1, -1]]).all()
Beispiel #7
0
def test_neighbours_y_square():
    r"""
    /\
   |  |
   | 1|
    \/\
    |  |    Hexagon size 1.
    | 0|    Cells 1 x 2.
     \/

    """
    mesh = HexagonalMesh(1, 1, 2, alignment='square')
    assert (mesh.neighbours == [[-1, -1, -1, -1, 1, -1],
                                [-1, -1, -1, -1, -1, 0]]).all()
Beispiel #8
0
def test_neighbours_y_periodic():
    r"""
       /\
      |  |
      | 1|
     /\ /
    |  |    Hexagon size 1.
    | 0|    Cells 1 x 2.
     \/

    """
    mesh = HexagonalMesh(1, 1, 2, periodicity=(False, True))
    assert (mesh.neighbours == [[-1, -1, 1, 1, -1, -1],
                                [-1, -1, 0, 0, -1, -1]]).all()
Beispiel #9
0
def test_neighbours_y():
    r"""
       /\
      |  |
      | 1|
     /\ /
    |  |    Hexagon size 1.
    | 0|    Cells 1 x 2.
     \/

    """
    mesh = HexagonalMesh(1, 1, 2)
    # assert to_sets(mesh.neighbours) == [{1}, {0}]
    assert (mesh.neighbours == [[-1, -1, 1, -1, -1, -1],
                                [-1, -1, -1, 0, -1, -1]]).all()
Beispiel #10
0
def test_hexagonal_demags_2D():
    """
    Comparison of the FFT approach for hexagonal meshes, named
    DemagHexagonal, where it is used a system with the double number
    of nodes along the x direction (i.e. a mesh with twice the number
    of nodes of the original mesh), against the full calculation
    of the Demag field
    """
    # Number of atoms
    N = 15
    a = 0.4
    mesh = HexagonalMesh(a * 0.5, N, N,
                         unit_length=1e-9,
                         alignment='square')

    # Centre
    xc = (mesh.Lx * 0.5)
    yc = (mesh.Ly * 0.5)

    mu_s = 2 * const.mu_B

    sim = Sim(mesh)
    sim.mu_s = mu_s

    sim.set_m(lambda pos: m_init_2Dvortex(pos, (xc, yc)))
    # Brute force demag calculation
    sim.add(DemagFull())

    sim.get_interaction('DemagFull').compute_field()
    sim.get_interaction('DemagFull').field
    DemagFull_energy = sim.compute_energy() / const.meV

    # Demag using the FFT approach and a larger mesh
    sim2 = Sim(mesh)
    sim2.mu_s = mu_s

    sim2.set_m(lambda pos: m_init_2Dvortex(pos, (xc, yc)))

    sim2.add(DemagHexagonal())
    sim2.get_interaction('DemagHexagonal').compute_field()
    sim2.compute_energy()

    demag_2fft_energy = sim2.compute_energy() / const.meV

    # We compare both energies scaled in meV
    assert (DemagFull_energy - demag_2fft_energy) < 1e-10
Beispiel #11
0
def test_coordinates_x():
    r"""

     /\ /\
    |  |  |  Hexagon size 1.
    |  |  |  Cells 2 x 1.
     \/ \/


    """
    size = 1
    mesh = HexagonalMesh(size, 2, 1)
    width = size * 2.0
    height = 2.0 * width / sqrt(3)
    assert allclose(mesh.coordinates,
                    np.array(((width / 2.0, height / 2.0, 0),
                              (width * 3.0 / 2.0, height / 2.0, 0))))
Beispiel #12
0
    def generate_mesh(self):

        # The width of the mesh will be the width of the triangle less
        # the offsets (that's why we shifted the material to the left)
        # We add 2 to avoid cropping the mesh if the integer approximation
        # is not optimal
        nx = int(np.around((self.L - (self.offsets[0] + self.offsets[2]) * 0.5)
                           / self.lattice_a)) + 2

        # Height of the triangle divided by the lattice hexagons height
        # +1 is to avoid cropping the triangle
        ny = int(np.around((self.L - self.offsets[1]) * np.sin(np.pi / 3)
                           / (self.lattice_a * np.sqrt(3) * 0.5))
                 ) + 1

        self.mesh = HexagonalMesh(self.lattice_a * 0.5, nx, ny,
                                  alignment='square', unit_length=1e-9,
                                  shells=self.shells
                                  )
Beispiel #13
0
def test_neighbours_9shells_square_even_row():
    """
    Just as test_neighbours_9shells_square_odd_row but checking a site in an
    even row in a 12x12 hexagonal lattice
    """
    mesh = HexagonalMesh(1, 12, 12, alignment='square', shells=9)
    assert (mesh.neighbours[77] == [78, 76, 90, 65, 89, 66,    # 1st shell
                                    91, 64, 101, 53, 88, 67,   # 2nd shell
                                    79, 75, 102, 52, 100, 54,  # 3rd shell
                                    92, 63, 103, 51, 114, 41,  # 4th shell
                                    113, 42, 99, 55, 87, 68,
                                    80, 74, 115, 40, 112, 43,  # 5th shell
                                    104, 50, 125, 29, 98, 56,  # 6th shell
                                    93, 62, 116, 39, 126, 28,  # 7th shell
                                    124, 30, 111, 44, 86, 69,
                                    81, 73, 127, 27, 123, 31,  # 8th shell
                                    105, 49, 117, 38, 138, 17, # 9th shell
                                    137, 18, 110, 45, 97, 57
                                    ]
            ).all()
Beispiel #14
0
sk_npy_path = glob.glob(args.sk_folder + '*.npy')[0]
fm_npy_path = glob.glob(args.fm_folder + '*.npy')[0]

# Number of images to be generated
number_images = 19

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

mu_s = 0.846 * const.mu_B

a = 0.125
nx = 320
ny = 185

# MESH
mesh = HexagonalMesh(a, nx, ny, alignment='square', unit_length=1e-9)

vtk_saver = SaveVTK(mesh, name='sk_displ')

centre_x = (np.max(mesh.coordinates[:, 0]) +
            np.min(mesh.coordinates[:, 0])) * 0.5

centre_y = (np.max(mesh.coordinates[:, 1]) +
            np.min(mesh.coordinates[:, 1])) * 0.5

lx = (np.max(mesh.coordinates[:, 0]) - np.min(mesh.coordinates[:, 0]))
ly = (np.max(mesh.coordinates[:, 1]) - np.min(mesh.coordinates[:, 1]))

# Create a simulation for the FM state and one for the skyrmion
sim = Sim(mesh, name='sk_displ')
sim.mu_s = mu_s
Beispiel #15
0
    'blue':
    ((0.0, 0.0, 0.0), (0.5, 0.753402, 0.753402), (1.0, 73 / 255., 73 / 255.))
}

# Transform to colormaps
BlOr = mpl.colors.LinearSegmentedColormap('BlOr', cdict_BlOr, 256)
BlOr_r = cm.revcmap(BlOr._segmentdata)
BlOr_r = mpl.colors.LinearSegmentedColormap('BlOr', BlOr_r, 256)

# mesh = CuboidMesh(nx=21, ny=21,
#                   dx=0.5, dy=0.5,
#                   unit_length=1e-9,
#                   periodicity=(True, True, False)
#                   )

mesh = HexagonalMesh(.5, 41, 41, periodicity=(True, True))

# Initialise a simulation object and load the skyrmion
# or ferromagnetic states
sim = Sim(mesh, name='neb_21x21-spins_fm-sk_atomic')

sk = '../hexagonal_system/relaxation/npys/2Dhex_41x41_FePd-Ir_B-15e-1_J588e-2_sk-up_npys/m_689.npy'
fm = '../../npys/neb_21x21-spins_fm-sk_atomic_k1e10_216/image_17.npy'
ds = '../../npys/neb_21x21-spins_fm-sk_atomic_k1e10_216/image_11.npy'

# For now we will just generate a skyrmion
states = {
    'skyrmion': sk,
    # 'ferromagnetic': fm,
    # 'destruction': ds
}
Beispiel #16
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 #17
0
def test_hexagonal_mesh_creation_periodic_square_y():
    mesh = HexagonalMesh(1, 2, 2, alignment='square', periodicity=(False, True, False))
Beispiel #18
0
def test_iterate_over_cells_and_neighbours():
    mesh = HexagonalMesh(1, 2, 2)
    for c_i in mesh.cells():
        print("I am cell #{}.".format(c_i))
        for c_j in mesh.neighbours[c_i]:
            print("\tAnd I am its neighbour, cell #{}!".format(c_j))
Beispiel #19
0
def test_iterate_over_cells():
    mesh = HexagonalMesh(1, 2, 2)
    for c_i in mesh.cells():
        print("This is cell #{}, I have neighbours {}.".format(c_i, mesh.neighbours[c_i]))
Beispiel #20
0
def test_save_scalar_field_hexagonal_mesh():
    mesh = HexagonalMesh(1, 3, 3)
    s = scalar_field(mesh, lambda r: r[0] + r[1])
    vtk = VTK(mesh, directory=OUTPUT_DIR, filename="scalar_hexagonal")
    vtk.save_scalar(s, name="s")
Beispiel #21
0
def test_neighbours_9shells_square_odd_row():
    r"""

    Testing neighbour indexes manually, for a 11x11 hexagonal mesh with square
    alignment. In this test we check the neighbours of the 60th lattice site,
    which is in an even row (we could check an odd row as well in the future)

       /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\
      |  |  |  |  |..|..|  |  |  |  |  |
      |  |  |  |  |14|15|  |  |  |  |  |
     /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /
    |  |  |  |;;|~~|``|~~|;;|  |  |  |
    |  |  |  |02|03|04|05|06|  |  |  |
     \ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\
      |  |..|~~|##|@@|@@|##|~~|..|  |  |
      |  |89|90|91|92|93|94|95|96|  |  |
     /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /
    |  |..|``|@@|**|--|**|@@|``|..|  |
    |  |78|79|80|81|82|83|84|85|86|  |
     \ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\
      |  |~~|@@|--|xx|xx|--|@@|~~|  |  |          OO i-th site
      |  |67|68|69|70|71|72|73|74|  |  |          xx 1st neighbours (nearest)
     /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /           -- 2nd neighbours (next nearest)
    |  |;;|##|**|xx|  |xx|**|##|;;|  |            ** 3rd neighbours
    |  |56|57|58|59|60|61|62|63|64|  |            @@ 4th neighbours
     \ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\           ## 5th neighnbours
      |  |~~|@@|--|xx|xx|--|@@|~~|  |  |          `` 6th neighbours
      |  |45|46|47|48|49|50|51|52|  |  |          ~~ 7th neighbours
     /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /           ;; 8th neighbours
    |  |..|``|@@|**|--|**|@@|``|..|  |
    |  |34|35|36|37|38|39|40|41|42|  |
     \ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\
      |  |..|~~|##|@@|@@|##|~~|..|  |  |
      |22|23|24|25|26|27|28|29|30|  |  |
     /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /
    |  |  |  |;;|~~|``|~~|;;|  |  |  |
    |11|  |13|14|15|16|17|18|  |  |  |
     \ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\
      |  |  |  |  |..|..|  |  |  |  |  |
      | 0|  | 2|  | 4| 5|  |  |  |  |  |         Hexagon size 1.
       \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/          Cells 9 x 6.


    """
    mesh = HexagonalMesh(1, 11, 11, alignment='square', shells=9)
    print(mesh.neighbours)
    assert (mesh.neighbours[60] == [61, 59, 71, 48, 70, 49,    # 1st shell
                                    72, 47, 82, 38, 69, 50,    # 2nd shell
                                    62, 58, 83, 37, 81, 39,    # 3rd shell
                                    73, 46, 84, 36, 93, 26,    # 4th shell
                                    92, 27, 80, 40, 68, 51,
                                    63, 57, 94, 25, 91, 28,    # 5th shell
                                    85, 35, 104, 16, 79, 41,   # 6th shell
                                    74, 45, 95, 24, 105, 15,   # 7th shell
                                    103, 17, 90, 29, 67, 52,
                                    64, 56, 106, 14, 102, 18,  # 8th shell
                                    86, 34, 96, 23, 115, 4,    # 9th shell
                                    114, 5, 89, 30, 78, 42
                                    ]
            ).all()

    # Second neighbours of the 0th position:
    assert (mesh.neighbours[0][6:12] == [13, -1, 22, -1, -1, -1]  # 2nd shell
            ).all()
Beispiel #22
0
def test_save_scalar_field_hexagonal_mesh(tmpdir):
    mesh = HexagonalMesh(1, 3, 3)
    s = scalar_field(mesh, lambda r: r[0] + r[1])
    vtk = VTK(mesh, directory=str(tmpdir), filename="scalar_hexagonal")
    vtk.save_scalar(s, name="s")
    assert same_as_ref(vtk.write_file(), REF_DIR)
Beispiel #23
0
nebm_data = {}


# Return a simulation folder according to the specified method
def methods(method, D):
    if method == 'boundary':
        return base_folder_ba(D)
    elif method == 'linear_interpolations':
        return base_folder(D)
    elif method == 'climbing':
        return base_folder_ci(D, climbing_image[D])


# Data ------------------------------------------------------------------------

mesh = HexagonalMesh(0.125, 320, 185, unit_length=1e-9, alignment='square')

# Generate the linear interpolations of the NEBM band from every DMI value from
# the arguments
for D in args.D_list:

    sim = Sim(mesh)
    sim.set_mu_s(0.846 * const.mu_B)
    sim.add(DemagHexagonal())
    sim.add(UniformExchange(J=27.026 * const.meV))
    sim.add(DMI(DMIc[D] * const.meV, dmi_type='interfacial'))
    sim.add(Anisotropy(0.0676 * const.meV, axis=[0, 0, 1]))

    images = [
        np.load(os.path.join(methods(args.method, D), _file))
        for _file in sorted(os.listdir(methods(args.method, D)),
Beispiel #24
0
# Mesh and Simulation ---------------------------------------------------------

# Check if multiple exchange constants were passed and set the number of
# neighbour shells according to the number of constants
if len(args.J) > 1:
    shells = len(args.J)
else:
    shells = 1

if args.hexagonal_mesh:
    if not args.PBC_2D:
        mesh = HexagonalMesh(args.hexagonal_mesh[2] * 0.5,
                             int(args.hexagonal_mesh[0]),
                             int(args.hexagonal_mesh[1]),
                             alignment=args.alignment,
                             unit_length=args.unit_length,
                             shells=shells
                             )
    else:
        mesh = HexagonalMesh(args.hex_a, args.hex_nx, args.hex_ny,
                             periodicity=(True, True),
                             alignment=args.alignment,
                             unit_length=args.unit_length,
                             shells=shells
                             )
    sim = Sim(mesh, name=args.sim_name, driver=args.driver)

elif args.mesh_from_image:
    sim_from_image = sfi.sim_from_image(args.mesh_from_image[0],
                                        image_range=[float(args.mesh_from_image[1]),
Beispiel #25
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 #26
0
from fidimag.common.nebm_spherical import NEBM_Spherical as NEBM_Spherical

import os
import re
import glob

mu0 = 4 * np.pi * 1e-7

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

if not args.PBC_2D:
    mesh = HexagonalMesh(args.hex_a,
                         args.hex_nx,
                         args.hex_ny,
                         alignment=args.alignment,
                         unit_length=args.unit_length)
else:
    mesh = HexagonalMesh(args.hex_a,
                         args.hex_nx,
                         args.hex_ny,
                         periodicity=(True, True),
                         alignment=args.alignment,
                         unit_length=args.unit_length)

# Initiate Fidimag simulation -------------------------------------------------
sim = Sim(mesh, name=args.sim_name)

# sim.set_tols(rtol=1e-10, atol=1e-14)
if args.alpha:
Beispiel #27
0
    def __init__(self,
                 image_path,
                 image_range=[0, 21.03, 0, 17.79],
                 mesh_a=0.2715,
                 shells=1,
                 # mesh_nx=79,
                 # mesh_ny=78
                 sim_name='unnamed',
                 bg_colour=(1., 1., 1.),
                 driver='llg'
                 ):

        """

        Generate an object on top of the fidimag simulation class, to generate
        an atomistic simulation using a hexagonal mesh, where the magnetic
        moments are populated in the mesh according to the pixels in a PNG
        image, located in *image_path* The mesh size is generated automatically
        from the dimensions provided for the image (the *image_range* array),
        so that the mesh covers the whole picture. It is recommended that the
        image has white borders since mesh points away from the picture range
        will take the values from the closest boundary point (see the
        populate_mesh function)

        image_range  :: An array [xmin, xmax, ymin, ymax] with the ranges
                        of the image, given in nm

        """

        # print 'Mesh spacings are: nx = {}, ny = {}'.format(mesh_a,
        #                                                    mesh_a * np.sqrt(3) * 0.5)

        self.image_path = image_path
        self.image_range = image_range

        mesh_nx = int(np.around(np.abs(image_range[1] - image_range[0]) / mesh_a))
        mesh_ny = int(np.around(
            np.abs(image_range[3] - image_range[2]) / (mesh_a * np.sqrt(3) * 0.5)
            ))

        self.mesh = HexagonalMesh(mesh_a * 0.5, mesh_nx, mesh_ny,
                                  # periodicity=(True, True),
                                  alignment='square',
                                  unit_length=1e-9,
                                  shells=shells
                                  )

        self.sim = Sim(self.mesh, name=sim_name, driver=driver)

        # Generate the 2D matrix with the image
        # If the image is B/W, every entry will have either [1., 1., 1.]
        # or [0., 0., 0.] representing the RGB data from every pixel
        self.image_data = mpl.image.imread(self.image_path)

        # We will create two new matrices, with the X and Y coordinates
        # of every point in the image matrix, using the range
        # provided in the arguments. For doing this, we use a meshgrid, which
        # automatically generates a 2D mesh of coordinates. The range
        # in the Y coordinates matrix is reversed since the image matrix
        # starts from top to bottom to generate the picture.
        # The shape is [n_rows, n_columns]  --> (ny, nx)
        self.image_coords_x = np.linspace(self.image_range[0],
                                          self.image_range[1],
                                          self.image_data.shape[1])

        self.image_coords_y = np.linspace(self.image_range[3],
                                          self.image_range[2],
                                          self.image_data.shape[0])

        (self.image_coords_x,
         self.image_coords_y) = np.meshgrid(self.image_coords_x,
                                            self.image_coords_y)

        self.bg_colour = bg_colour
Beispiel #28
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()