示例#1
0
def test_hysteresis(tmpdir):
    os.chdir(str(tmpdir))
    sim = barmini()
    mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(1, 1, 1), 1, 1, 1)
    H_ext_list = [(1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0)]
    N = len(H_ext_list)

    # Run a relaxation and save a vtk snapshot at the end of each stage;
    # this should result in three .vtu files (one for each stage).
    sim1 = sim_with(mesh,
                    Ms=1e6,
                    m_init=(0.8, 0.2, 0),
                    alpha=1.0,
                    unit_length=1e-9,
                    A=None,
                    demag_solver=None)
    sim1.schedule('save_vtk', at_end=True, filename='barmini_hysteresis.pvd')
    res1 = sim1.hysteresis(H_ext_list=H_ext_list)
    assert (len(glob('barmini_hysteresis*.vtu')) == N)
    assert (res1 == None)

    # Run a relaxation with a non-trivial `fun` argument and check
    # that we get a list of return values.
    sim2 = sim_with(mesh,
                    Ms=1e6,
                    m_init=(0.8, 0.2, 0),
                    alpha=1.0,
                    unit_length=1e-9,
                    A=None,
                    demag_solver=None)
    res2 = sim2.hysteresis(H_ext_list=H_ext_list,
                           fun=lambda sim: sim.m_average[0])
    assert (len(res2) == N)
示例#2
0
def demo1():
    # create example simulation
    import finmag
    import dolfin as df
    xmin, ymin, zmin = 0, 0, 0  # one corner of cuboid
    xmax, ymax, zmax = 6, 6, 11  # other corner of cuboid
    nx, ny, nz = 3, 3, 6  # number of subdivisions (use ~2nm edgelength)
    mesh = df.BoxMesh(df.Point(xmin, ymin, zmin), df.Point(xmax, ymax, zmax),
                      nx, ny, nz)
    # standard Py parameters
    sim = finmag.sim_with(mesh,
                          Ms=0.86e6,
                          alpha=0.5,
                          unit_length=1e-9,
                          A=13e-12,
                          m_init=(1, 0, 1))
    filename = 'data.txt'
    ndt = Tablewriter(filename, sim, override=True)
    times = np.linspace(0, 3.0e-11, 6 + 1)
    for i, time in enumerate(times):
        print("In iteration {}, computing up to time {}".format(i, time))
        sim.run_until(time)
        ndt.save()

    # now open file for reading
    f = Tablereader(filename)
    print f.timesteps()
    print f['m_x']
示例#3
0
def bar(name='bar', demag_solver_type=None):
    """Py bar with dimensions 30x30x100nm, initial field
    pointing in (1,0,1) direction.

    Same as example 2 in Nmag manual.

    This function returns a simulation object that is 'ready to go'.

    Useful commands to run this for a minute::

        times = numpy.linspace(0, 3.0e-11, 6 + 1)
        for t in times:
            # Integrate
            sim.run_until(t)
    """

    xmin, ymin, zmin = 0, 0, 0  # one corner of cuboid
    xmax, ymax, zmax = 30, 30, 100  # other corner of cuboid
    # number of subdivisions (use ~2nm edgelength)
    nx, ny, nz = 15, 15, 50
    mesh = df.BoxMesh(df.Point(xmin, ymin, zmin), df.Point(xmax, ymax, zmax),
                      nx, ny, nz)

    sim = finmag.sim_with(mesh,
                          Ms=0.86e6,
                          alpha=0.5,
                          unit_length=1e-9,
                          A=13e-12,
                          m_init=(1, 0, 1),
                          name=name,
                          demag_solver_type=demag_solver_type)

    return sim
示例#4
0
def macrospin_box(Ms=0.86e6,
                  m_init=(1, 0, 0),
                  H_ext=(0, 0, 1e6),
                  alpha=0.1,
                  name='macrospin'):
    """
    Cubic mesh of length 1 nm along each edge, with eight vertices
    located in the corners of the cube.

    No anisotropy, exchange coupling or demag is present so that
    magnetic moments at the vertices behave identical under the
    influence of the external field.


    Default values for the arguments:

        Ms = 0.86e6  (saturation magnetisation in A/m)

        m_init = (1, 0, 0)  (initial magnetisation pointing along the x-axis)

        H_ext = (0, 0, 1e6)  (external field in A/m)

        alpha = 0.1  (Gilbert damping coefficient)

    """
    mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(1, 1, 1), 1, 1, 1)
    sim = sim_with(mesh,
                   Ms=0.86e6,
                   alpha=alpha,
                   unit_length=1e-9,
                   A=None,
                   H_ext=H_ext,
                   m_init=(1, 0, 0),
                   name=name)
    return sim
示例#5
0
def test_Table_writer_and_reader(tmpdir):
    os.chdir(str(tmpdir))
    import finmag
    import dolfin as df

    xmin, ymin, zmin = 0, 0, 0  # one corner of cuboid
    xmax, ymax, zmax = 6, 6, 11  # other corner of cuboid
    nx, ny, nz = 3, 3, 6  # number of subdivisions (use ~2nm edgelength)
    mesh = df.BoxMesh(df.Point(xmin, ymin, zmin), df.Point(xmax, ymax, zmax),
                      nx, ny, nz)
    # standard Py parameters
    sim = finmag.sim_with(mesh,
                          Ms=0.86e6,
                          alpha=0.5,
                          unit_length=1e-9,
                          A=13e-12,
                          m_init=(1, 0, 1))

    filename = 'test-save_averages-data.ndt'
    ndt = Tablewriter(filename, sim)
    times = np.linspace(0, 3.0e-11, 6 + 1)
    for i, time in enumerate(times):
        print("In iteration {}, computing up to time {}".format(i, time))
        sim.run_until(time)
        ndt.save()

    # now open file for reading
    data = Tablereader(filename)
    print data.timesteps() - times
    print("III")
    assert np.all(np.abs(data.timesteps() - times)) < 1e-25
    mx, my, mz = sim.m_average
    assert abs(data['m_x'][-1] - mx) < 1e-11
    assert abs(data['m_y'][-1] - my) < 1e-11
    assert abs(data['m_z'][-1] - mz) < 1e-11

    # Try reading multiple columns at once by indexing 'data'
    # with multiple indices (in the assert statement).
    dmx = data['m_x']
    dmy = data['m_y']
    dmz = data['m_z']
    dm = np.vstack([dmx, dmy, dmz]).T  # stack the arrays together
    assert np.allclose(dm, np.array(data['m_x', 'm_y', 'm_z']).T)

    # Reading an incomplete dataset should raise a runtime error
    with pytest.raises(RuntimeError):
        Tablereader(os.path.join(MODULE_DIR, 'test-incomplete-data.ndt'))
示例#6
0
def test_get_interaction_list():
    # has bar mini example Demag and Exchange?
    s = finmag.example.barmini()
    lst = s.get_interaction_list()
    assert 'Exchange' in lst
    assert 'Demag' in lst
    assert len(lst) == 2

    # Let's remove one and ceck again
    s.remove_interaction('Exchange')
    assert s.get_interaction_list() == ['Demag']

    # test simulation with no interaction
    s2 = finmag.sim_with(mesh=dolfin.IntervalMesh(10, 0, 1),
                         m_init=(1, 0, 0),
                         Ms=1,
                         demag_solver=None,
                         unit_length=1e-8)
    assert s2.get_interaction_list() == []
示例#7
0
def barmini(name='barmini', mark_regions=False, demag_solver_type=None):
    """Py bar with dimensions 3x3x10nm, initial field
    pointing in (1,0,1) direction.

    Same as example 2 in Nmag manual, but much smaller (and faster).

    This function returns a simulation object that is 'ready to go'.

    If `mark_regions` is True, the mesh will be subdivided vertically
    into two regions which are markes as 'top' and 'bottom'.

    Useful commands to run this for a couple of seconds:

        times = numpy.linspace(0, 3.0e-11, 6 + 1)
        for t in times:
            # Integrate
            sim.run_until(t)
    """

    xmin, ymin, zmin = 0, 0, 0  # one corner of cuboid
    xmax, ymax, zmax = 3, 3, 10  # other corner of cuboid
    # number of subdivisions (use ~2nm edgelength)
    nx, ny, nz = 2, 2, 4
    mesh = df.BoxMesh(df.Point(xmin, ymin, zmin), df.Point(xmax, ymax, zmax),
                      nx, ny, nz)

    sim = finmag.sim_with(mesh,
                          Ms=0.86e6,
                          alpha=0.5,
                          unit_length=1e-9,
                          A=13e-12,
                          m_init=(1, 0, 1),
                          name=name,
                          demag_solver_type=demag_solver_type)

    if mark_regions:

        def fun_regions(pt):
            return 'bottom' if (pt[2] <= 5.0) else 'top'

        sim.mark_regions(fun_regions)

    return sim
示例#8
0
    def setup_class(cls):
        """
        Create a box mesh and a simulation object on this mesh which
        will be used to compute Zeeman energies in the individual tests.

        """
        # The mesh and simulation are only created once for the entire
        # test class and are re-used in each test method for efficiency.
        cls.Lx, cls.Ly, cls.Lz = 100, 30, 10
        nx, ny, nz = 30, 10, 5
        mesh = df.BoxMesh(0, 0, 0, cls.Lx, cls.Ly, cls.Lz, nx, ny, nz)
        unit_length = 1e-9
        cls.mesh_vol = cls.Lx * cls.Ly * cls.Lz  * unit_length**3
        cls.S3 = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3)

        # The values for Ms and m_init are arbitrary as they will be
        # ovewritten in the tests.
        cls.sim = sim_with(mesh, Ms=1, m_init=(1, 0, 0), demag_solver=None,
                           unit_length=unit_length)
示例#9
0
def test_hysteresis_loop_and_plotting(tmpdir):
    """
    Call the hysteresis loop with various combinations for saving
    snapshots and check that the correct number of vtk files have been
    produced. Also check that calling the plotting function works
    (although the output image isn't verified).

    """
    os.chdir(str(tmpdir))

    mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(1, 1, 1), 1, 1, 1)
    sim = sim_with(mesh,
                   Ms=1e6,
                   m_init=(0.8, 0.2, 0),
                   alpha=1.0,
                   unit_length=1e-9,
                   A=None,
                   demag_solver=None)
    H_vals, m_vals = \
        sim.hysteresis_loop(H, initial_direction, N, stopping_dmdt=10)

    # Check that the magnetisation values are as trivial as we expect
    # them to be ;-)
    assert (np.allclose(m_vals, [1.0 for _ in xrange(2 * N)], atol=1e-4))

    # This only tests whether the plotting function works without
    # errors. It currently does *not* check that it produces
    # meaningful results (and the plot is quite boring for the system
    # above anyway).
    plot_hysteresis_loop(H_vals,
                         m_vals,
                         infobox=["param_A = 23", ("param_B", 42)],
                         title="Hysteresis plot test",
                         xlabel="H_ext",
                         ylabel="m_avg",
                         figsize=(5, 4),
                         infobox_loc="bottom left",
                         filename='test_plot.pdf')

    # Test multiple filenames, too
    plot_hysteresis_loop(H_vals,
                         m_vals,
                         filename=['test_plot.pdf', 'test_plot.png'])
示例#10
0
def nanowire(lx=100, ly=10, lz=3, nx=30, ny=3, nz=1, name='nanowire'):
    """
    Permalloy nanowire with head-to-head domain wall. The nanowire
    has dimensions lx, ly, lz and discretization nx, ny, nz along
    the three coordinate axes.

    """
    A = 13e-12
    Ms = 8e5

    mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(lx, ly, lz), nx, ny, nz)
    S1 = df.FunctionSpace(mesh, 'CG', 1)
    S3 = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3)

    def m_init_fun(pt):
        x, y, z = pt
        return [cos(x*pi/lx), sin(x*pi/lx), 0]

    sim = finmag.sim_with(mesh, Ms=Ms, m_init=m_init_fun, unit_length=1e-9, A=A)
    return sim
示例#11
0
def test_airbox_method():
    """
    Define a mesh with two regions (Permalloy and 'air'), where
    the Permalloy region is e.g. a sphere of radius 1.0 and the 'air'
    region is a cube with sides of length 10. Next set Ms in both
    regions, where Ms in the 'air' region is either zero or has a
    very low value.  Then run the simulation and and check that the
    value of the external field in the 'air' region coincides with the
    field of a dipole.
    """
    mesh = from_geofile("mesh.geo")
    mesh_region = df.MeshFunction("uint", mesh, "mesh_mat.xml")

    # Visualise mesh regions to check they look right (this will be
    # removed in the final test).
    #plot_mesh_regions(mesh_region, regions=[1, 2], colors=["green", "red"],
    #                  alphas=[1.0, 0.25])
    #plt.show()

    # Define different values for Ms on each subdomain
    Ms_vals = (8.6e5, 0)
    Ms = piecewise_on_subdomains(mesh, mesh_region, Ms_vals)

    sim = sim_with(mesh,
                   Ms=Ms,
                   m_init=(1.0, 0.0, 0),
                   alpha=1.0,
                   unit_length=1e-9,
                   A=13.0e-12,
                   demag_solver='FK')

    print "Computing effective field..."
    H_eff = sim.effective_field()
    print "Computed field: {}".format(H_eff)

    sim.relax(save_snapshots=True,
              save_every=1e-11,
              filename="snapshots/snapshot.pvd")
示例#12
0
def macrospin_interval(Ms=0.86e6,
                       m_init=(1, 0, 0),
                       H_ext=(0, 0, 1e6),
                       alpha=0.1,
                       name='macrospin'):
    """
    1d mesh (= interval) with two vertices which are 1 nm apart.

    No anisotropy, exchange coupling or demag is present so that
    magnetic moments at the vertices behave identical under the
    influence of the external field. The damping constant has the
    value alpha=0.1.


    Default values for the arguments:

        Ms = 0.86e6  (saturation magnetisation in A/m)

        m_init = (1, 0, 0)  (initial magnetisation pointing along the x-axis)

        H_ext = (0, 0, 1e6)  (external field in A/m)

        alpha = 0.1  (Gilbert damping coefficient)

    """
    mesh = df.UnitIntervalMesh()
    sim = sim_with(mesh,
                   Ms=1e6,
                   m_init=(1, 0, 0),
                   alpha=alpha,
                   unit_length=1e-9,
                   H_ext=H_ext,
                   A=None,
                   demag_solver=None,
                   name=name)
    return sim
示例#13
0
def test_check_Kittel_mode_for_single_sphere(tmpdir, debug=False):
    """
    Compute the eigenmodes of a perfect sphere and check that the
    frequency of the base mode equals the analytical value from the
    Kittel equation (see Charles Kittel, "Introduction to solid state
    physics", 7th edition, Ch. 16, p.505):

       omega_0 = gamma * B_0

    Here omega_0 is the angular frequency, so the actual frequency is
    equal to omega_0 / (2*pi).

    """
    os.chdir(str(tmpdir))

    sphere = Sphere(r=11)
    mesh = sphere.create_mesh(maxh=2.0)
    print "[DDD] mesh: {}".format(mesh)
    print mesh_info(mesh)
    if debug:
        plot_mesh_with_paraview(mesh, outfile='mesh_sphere.png')

    H_z = 4.42e5  # slightly odd value to make the test a bit more reliable
    frequency_unit = 1e9

    sim = sim_with(mesh, Ms=1e6, m_init=[
                   0, 0, 1], A=13e-12, H_ext=[0, 0, H_z], unit_length=1e-9, demag_solver='FK')
    sim.relax()

    A, M, _, _ = compute_generalised_eigenproblem_matrices(
        sim, alpha=0.0, frequency_unit=1e9)

    RTOL = 1e-3
    n_values = 2
    n_values_export = 0
    omega, w = compute_normal_modes_generalised(
        A, M, n_values=n_values, discard_negative_frequencies=False)
    assert(len(omega) == n_values)

    # Check that the frequency of the base mode equals the analytical value from the Kittel equation
    # (see Charles Kittel, "Introduction to solid state physics", 7th edition, Ch. 16, p.505):
    #
    #    omega_0 = gamma * B_0
    #
    # The frequency is equal to omega_0 / (2*pi).
    #
    freq_expected = sim.gamma * H_z / (2 * pi * frequency_unit)
    assert(np.allclose(omega[0], +freq_expected, atol=0, rtol=RTOL))
    assert(np.allclose(omega[1], -freq_expected, atol=0, rtol=RTOL))
    logger.debug("Computed eigenfrequencies: {}".format(omega))
    logger.debug(
        "Expected frequency of the Kittel mode: {}".format(freq_expected))

    # Perform the same test when negative frequencies are discarded
    omega_positive, _ = compute_normal_modes_generalised(
        A, M, n_values=n_values, discard_negative_frequencies=True)
    logger.debug("[DDD] omega_positive: {}".format(omega_positive))
    assert(len(omega_positive) == n_values)
    assert(np.allclose(omega_positive[0], freq_expected, atol=0, rtol=RTOL))

    # Ensure that the frequencies are all positive and sorted by absolute value
    assert((np.array(omega_positive) > 0).all())
    assert(np.allclose(omega_positive, sorted(omega_positive, key=abs)))

    omega_positive_first_half = omega_positive[:(n_values // 2)]
    assert(np.allclose(sorted(np.concatenate([omega_positive_first_half, -omega_positive_first_half])),
                       sorted(omega)))

    # Export normal mode animations for debugging
    for i in xrange(n_values_export):
        freq = omega_positive[i]
        export_normal_mode_animation(
            sim, freq, w[i], filename='normal_mode_{:02d}__{:.3f}_GHz.pvd'.format(i, freq))

    ##
    # Perform the same test as above but without demag, wich should improve the accuracy.
    ##
    sim = sim_with(mesh, Ms=1e6, m_init=[
                   0, 0, 1], A=13e-12, H_ext=[0, 0, H_z], unit_length=1e-9, demag_solver=None)
    sim.relax()

    A, M, _, _ = compute_generalised_eigenproblem_matrices(
        sim, alpha=0.0, frequency_unit=1e9)

    RTOL = 1e-9
    omega, _ = compute_normal_modes_generalised(
        A, M, n_values=1, discard_negative_frequencies=True)

    logger.debug("Computed eigenfrequencies (without demag): {}".format(omega))
    logger.debug(
        "Expected frequency of the Kittel mode: {}".format(freq_expected))
    assert(np.allclose(omega[0], freq_expected, atol=0, rtol=RTOL))
示例#14
0
import dolfin as df
from numpy import linspace
from math import cos, sin, pi
from finmag import sim_with
from finmag.util.meshes import ellipsoid

r1 = 30.0
r2 = 10.0
r3 = 10.0
maxh = 3.0

Ms = 1e6         # A/m
A = 13.0e-12     # J/m
alpha = 1.0      # large damping for quick convergence
H = 1e6          # external field strength in A/m
m_init = (1, 0, 0)

# Create a few external field values (at 45 degree angles
# to each other, sweeping a half-circle).
H_ext_list = [(cos(t)*H, sin(t)*H, 0.01*H) for t in linspace(0, pi, 5)]

mesh = ellipsoid(r1, r2, r3, maxh)
sim = sim_with(mesh, Ms, m_init, alpha=alpha, unit_length=1e-9, A=A, demag_solver='FK')

sim.hysteresis(H_ext_list[1:3], filename="snapshots/hysteresis_example/hysteresis_ellipsoid.pvd", save_snapshots=True, save_every=10e-12, force_overwrite=True)