Exemple #1
0
def test_exchange_field_supported_methods(fixt):
    """
    Check that all supported methods give the same results
    as the default method.

    """
    A = 1
    REL_TOLERANCE = 1e-12
    mesh = df.UnitCubeMesh(10, 10, 10)
    Ms = Field(df.FunctionSpace(mesh, 'DG', 0), 1)
    functionspace = df.VectorFunctionSpace(mesh, "CG", 1, 3)
    m = Field(functionspace)
    m.set(df.Expression(("0", "sin(x[0])", "cos(x[0])"), degree=1))
    exch = Exchange(A)
    exch.setup(m, Ms)
    H_default = exch.compute_field()

    supported_methods = list(Exchange._supported_methods)
    # no need to compare default method with itself
    supported_methods.remove(exch.method)
    # the project method for the exchange is too bad
    supported_methods.remove("project")

    for method in supported_methods:
        exch = Exchange(A, method=method)
        exch.setup(m, Ms)
        H = exch.compute_field()
        print "With method '{}', expecting H =\n{}\n, got H =\n{}.".format(
            method,
            H_default.reshape((3, -1)).mean(1),
            H.reshape((3, -1)).mean(1))

        rel_diff = np.abs((H - H_default) / H_default)
        assert np.nanmax(rel_diff) < REL_TOLERANCE
Exemple #2
0
def test_exchange_energy_analytical_2():
    """
    Compare one Exchange energy with the corresponding analytical result.

    """
    REL_TOLERANCE = 5e-5
    lx = 6
    ly = 3
    lz = 2
    nx = 300
    ny = nz = 1
    mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(lx, ly, lz), nx, ny, nz)
    unit_length = 1e-9
    functionspace = df.VectorFunctionSpace(mesh, "CG", 1, 3)
    Ms = Ms = Field(df.FunctionSpace(mesh, 'DG', 0), 8e5)
    A = 13e-12
    m = Field(functionspace)
    m.set(
        df.Expression(['0', 'sin(2*pi*x[0]/l_x)', 'cos(2*pi*x[0]/l_x)'],
                      l_x=lx,
                      degree=1))
    exch = Exchange(A)
    exch.setup(m, Ms, unit_length=unit_length)
    E_expected = A * 4 * pi ** 2 * \
        (ly * unit_length) * (lz * unit_length) / (lx * unit_length)
    E = exch.compute_energy()
    print "expected energy: {}".format(E)
    print "computed energy: {}".format(E_expected)
    assert abs((E - E_expected) / E_expected) < REL_TOLERANCE
Exemple #3
0
def test_exchange_periodic_boundary_conditions():

    mesh1 = df.BoxMesh(df.Point(0, 0, 0), df.Point(1, 1, 0.1), 2, 2, 1)
    mesh2 = df.UnitCubeMesh(10, 10, 10)

    print("""
    # for debugging, to make sense of output
    # testrun 0, 1 : mesh1
    # testrun 2,3 : mesh2
    # testrun 0, 2 : normal
    # testrun 1,3 : pbc
    """)
    testrun = 0

    for mesh in [mesh1, mesh2]:
        pbc = PeriodicBoundary2D(mesh)
        S3_normal = df.VectorFunctionSpace(mesh, "Lagrange", 1)
        S3_pbc = df.VectorFunctionSpace(mesh,
                                        "Lagrange",
                                        1,
                                        constrained_domain=pbc)

        for S3 in [S3_normal, S3_pbc]:
            print("Running test {}".format(testrun))
            testrun += 1

            FIELD_TOLERANCE = 6e-7
            ENERGY_TOLERANCE = 0.0

            m_expr = df.Expression(("0", "0", "1"), degree=1)

            m = Field(S3, m_expr, name='m')

            exch = Exchange(1)
            exch.setup(m, Field(df.FunctionSpace(mesh, 'DG', 0), 1))
            field = exch.compute_field()
            energy = exch.compute_energy()
            print("m.shape={}".format(m.vector().array().shape))
            print("m=")
            print(m.vector().array())
            print("energy=")
            print(energy)
            print("shape=")
            print(field.shape)
            print("field=")
            print(field)

            H = field
            print "Asserted zero exchange field for uniform m = (1, 0, 0) " + \
                  "got H =\n{}.".format(H.reshape((3, -1)))
            print "np.max(np.abs(H)) =", np.max(np.abs(H))
            assert np.max(np.abs(H)) < FIELD_TOLERANCE

            E = energy
            print "Asserted zero exchange energy for uniform m = (1, 0, 0), " + \
                  "Got E = {:g}.".format(E)
            assert abs(E) <= ENERGY_TOLERANCE
Exemple #4
0
def compute_finmag_exc(dolfin_mesh, m_gen, Ms, A):
    S3 = df.VectorFunctionSpace(dolfin_mesh, "Lagrange", 1, dim=3)
    coords = np.array(zip(*dolfin_mesh.coordinates()))
    m0 = m_gen(coords).flatten()
    m = Field(S3)
    m.set_with_numpy_array_debug(m0)

    exchange = Exchange(A)
    exchange.setup(m, Field(df.FunctionSpace(dolfin_mesh, 'DG', 0), Ms))

    finmag_exc_field = df.Function(S3)
    finmag_exc_field.vector()[:] = exchange.compute_field()
    return finmag_exc_field
Exemple #5
0
def fixt():
    """
    Create an Exchange object that will be re-used during testing.

    """
    mesh = df.UnitCubeMesh(10, 10, 10)
    functionspace = df.VectorFunctionSpace(mesh, "CG", 1, 3)
    Ms = Field(df.FunctionSpace(mesh, 'DG', 0), 1)
    A = 1
    m = Field(functionspace)
    exch = Exchange(A)
    exch.setup(m, Ms)
    return {"exch": exch, "m": m, "A": A, "Ms": Ms}
Exemple #6
0
    def H_eff(self):
        """Very temporary function to make things simple."""
        H_app = project((Constant((0, 1e5, 0))), self.S3)
        H_ex = Function(self.S3)

        # Comment out these two lines if you don't want exchange.
        exch = Exchange(1.3e-11)
        print "About to call setup"
        exch.setup(self._m_field, self.Ms)
        H_ex.vector().array()[:] = exch.compute_field()

        H_eff = H_ex + H_app
        return H_eff
Exemple #7
0
def exchange(mesh, unit_length):
    S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1)
    m = Field(S3,
              value=df.Expression(("x[1]*u", "0", "sqrt(1-pow(x[1]*u, 2))"),
                                  u=unit_length,
                                  degree=1))
    exch = Exchange(A)
    exch.setup(m,
               Field(df.FunctionSpace(mesh, 'DG', 0), Ms),
               unit_length=unit_length)
    H = exch.compute_field()
    E = exch.compute_energy()
    return m.get_numpy_array_debug(), H, E
def three_dimensional_problem():
    x_max = 10e-9
    y_max = 1e-9
    z_max = 1e-9
    mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(x_max, y_max, z_max), 40, 2,
                      2)

    V = df.VectorFunctionSpace(mesh, 'Lagrange', 1)

    Ms = 8.6e5

    m0_x = "pow(sin(0.2*x[0]*1e9), 2)"
    m0_y = "0"
    m0_z = "pow(cos(0.2*x[0]*1e9), 2)"
    m = Field(V,
              value=vector_valued_function((m0_x, m0_y, m0_z),
                                           V,
                                           normalise=True))

    C = 1.3e-11

    u_exch = Exchange(C)
    u_exch.setup(m, Field(df.FunctionSpace(mesh, 'DG', 0), Ms))
    finmag_exch = u_exch.compute_field()

    magpar_result = os.path.join(MODULE_DIR, 'magpar_result', 'test_exch')
    nodes, magpar_exch = magpar.get_field(magpar_result, 'exch')

    ## Uncomment the line below to invoke magpar to compute the results,
    ## rather than using our previously saved results.
    # nodes, magpar_exch = magpar.compute_exch_magpar(m, A=C, Ms=Ms)

    print magpar_exch

    # Because magpar have changed the order of the nodes!!!

    tmp = df.Function(V)
    tmp_c = mesh.coordinates()
    mesh.coordinates()[:] = tmp_c * 1e9

    finmag_exch, magpar_exch, \
        diff, rel_diff = magpar.compare_field(
            mesh.coordinates(), finmag_exch,
            nodes, magpar_exch)

    return dict(m0=m.get_numpy_array_debug(),
                mesh=mesh,
                exch=finmag_exch,
                magpar_exch=magpar_exch,
                diff=diff,
                rel_diff=rel_diff)
Exemple #9
0
def setup_finmag():
    mesh = df.IntervalMesh(xn, x0, x1)
    coords = np.array(zip(*mesh.coordinates()))

    S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3)
    m = Field(S3)
    m.set_with_numpy_array_debug(m_gen(coords).flatten())

    exchange = Exchange(A)
    exchange.setup(m, Field(df.FunctionSpace(mesh, 'DG', 0), Ms))

    H_exc = df.Function(S3)
    H_exc.vector()[:] = exchange.compute_field()
    return dict(m=m, H=H_exc, table=start_table())
Exemple #10
0
def test_exchange_energy_analytical(fixt):
    """
    Compare one Exchange energy with the corresponding analytical result.

    """
    REL_TOLERANCE = 1e-7

    A = 1
    mesh = df.UnitCubeMesh(10, 10, 10)
    Ms = Field(df.FunctionSpace(mesh, 'DG', 0), 1)
    functionspace = df.VectorFunctionSpace(mesh, "CG", 1, 3)
    m = Field(functionspace)
    m.set(df.Expression(("x[0]", "x[2]", "-x[1]"), degree=1))
    exch = Exchange(A)
    exch.setup(m, Ms)
    E = exch.compute_energy()
    # integrating the vector laplacian, the latter gives 3 already
    expected_E = 3

    print "With m = (0, sqrt(1-x^2), x), " + \
        "expecting E = {}. Got E = {}.".format(expected_E, E)
    assert abs(E - expected_E) / expected_E < REL_TOLERANCE
Exemple #11
0
def test_exchange_energy_density():
    """
    Compare solution with nmag for now. Should derive the
    analytical solution here as well.

    Our initial magnetisation looks like this:

    ^   ~
    |  /  --->  \   |       (Hahahaha! :-D)
                 ~  v

    """
    TOL = 1e-7  # Should be lower when comparing with analytical solution
    MODULE_DIR = os.path.dirname(os.path.abspath(__file__))

    # run nmag
    cmd = "nsim %s --clean" % os.path.join(MODULE_DIR, "run_nmag_Eexch.py")
    status, output = commands.getstatusoutput(cmd)
    if status != 0:
        print output
        sys.exit("Error %d: Running %s failed." % (status, cmd))
    nmag_data = np.loadtxt(
        os.path.join(MODULE_DIR, "nmag_exchange_energy_density.txt"))

    # run finmag
    mesh = df.IntervalMesh(100, 0, 10e-9)
    S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3)
    Ms = 42
    m = Field(S3,
              value=df.Expression(
                  ("cos(x[0]*pi/10e-9)", "sin(x[0]*pi/10e-9)", "0"), degree=1))

    exch = Exchange(1.3e-11)
    Ms_field = Field(df.FunctionSpace(mesh, 'DG', 0), Ms)
    exch.setup(m, Ms_field)

    finmag_data = exch.energy_density()
    rel_err = np.abs(nmag_data - finmag_data) / np.linalg.norm(nmag_data)

    print("Nmag data   = %g" % nmag_data[0])
    print("Finmag data = %g" % finmag_data[0])
    print "Relative error from nmag data (expect array of 0):"
    print rel_err
    print "Max relative error:", np.max(rel_err)
    assert np.max(rel_err) < TOL, \
        "Max relative error is %g, should be zero." % np.max(rel_err)

    print("Work out average energy density and energy")
    S1 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=1)
    # only approximative -- using assemble would be better
    average_energy_density = np.average(finmag_data)
    w = df.TestFunction(S1)
    vol = sum(df.assemble(df.dot(df.Constant([1]), w) * df.dx))
    # finmag 'manually' computed, based on node values of energy density:
    energy1 = average_energy_density * vol
    # finmag computed by energy class
    energy2 = exch.compute_energy()
    # comparison with Nmag
    energy3 = np.average(nmag_data) * vol
    print energy1, energy2, energy3

    assert abs(energy1 - energy2) < 1e-12  # actual value is 0, but
    # that must be pure luck.
    assert abs(energy1 - energy3) < 5e-8  # actual value
Exemple #12
0
    x, y, z = mesh.coordinates()[i]
    mx = 1
    my = 0
    mz = 0
    if 8e-9 < x < 14e-9 and -3e-9 < y < 3e-9:
        pass
    else:
        m_arr[i] = mx
        m_arr[i + nb_nodes] = my
        m_arr[i + 2 * nb_nodes] = mz

M.vector()[:] = m_arr

# LLG setup
exchange = Exchange(C)
exchange.setup(V, M, Ms)

H_eff = Function(V)
H_eff.vector()[:] = exchange.compute_field()

p = gamma / (1 + alpha * alpha)
q = alpha * p
u = TrialFunction(V)
v = TestFunction(V)

a = inner(u, v) * dx
L = inner(
    -p * cross(M, H_eff) - q * cross(M, cross(M, H_eff)) - c *
    (inner(M, M) - 1) * M, v) * dx

dm = Function(V)
Exemple #13
0
    os.path.join(MODULE_DIR, "simple_1D_nmag.py")),
                shell=True)

nd = np.load(os.path.join(MODULE_DIR, "nmag_hansconf.npy"))

# run finmag
mesh = df.IntervalMesh(100, 0, 10e-9)
S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3)
DG0 = df.FunctionSpace(mesh, "DG", 0)
m = Field(
    S3,
    df.Expression(("cos(x[0]*pi/10e-9)", "sin(x[0]*pi/10e-9)", "0"), degree=1))
Ms = Field(DG0, 1.0)

exchange = Exchange(1.3e-11)
exchange.setup(m, Ms)

fd = exchange.energy_density()

# draw an ASCII table of the findings
table_border = "+" + "-" * 8 + "+" + "-" * 64 + "+"
table_entries = "| {:<6} | {:<20} {:<20} {:<20} |"
table_entries_f = "| {:<6} | {:<20.8f} {:<20.8f} {:<20g} |"
print table_border
print table_entries.format(" ", "min", "max", "delta")
print table_border
print table_entries_f.format("finmag", min(fd), max(fd), max(fd) - min(fd))
print table_entries_f.format("nmag", min(nd), max(nd), max(nd) - min(nd))
print table_border

# draw a plot of the two exchange energy densities
Exemple #14
0
                  "got H =\n{}.".format(H.reshape((3, -1)))
            print "np.max(np.abs(H)) =", np.max(np.abs(H))
            assert np.max(np.abs(H)) < FIELD_TOLERANCE

            E = energy
            print "Asserted zero exchange energy for uniform m = (1, 0, 0), " + \
                  "Got E = {:g}.".format(E)
            assert abs(E) <= ENERGY_TOLERANCE


if __name__ == "__main__":
    mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(2 * np.pi, 1, 1), 10, 1, 1)

    S = df.FunctionSpace(mesh, "Lagrange", 1)
    S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1)

    expr = df.Expression(("0", "cos(x[0])", "sin(x[0])"), degree=1)

    m = df.interpolate(expr, S3)

    exch = Exchange(1, pbc2d=True)
    exch.setup(S3, m, 1)
    print exch.compute_field()

    field = df.Function(S3)
    field.vector().set_local(exch.compute_field())

    df.plot(m)
    df.plot(field)
    df.interactive()
Exemple #15
0
    x, y, z = mesh.coordinates()[i]
    mx = 1
    my = 0
    mz = 0
    if 8e-9 < x < 14e-9 and -3e-9 < y < 3e-9:
        pass
    else:
        m_arr[i] = mx
        m_arr[i + nb_nodes] = my
        m_arr[i + 2 * nb_nodes] = mz

m_func.vector()[:] = m_arr

# LLG setup
exchange = Exchange(C)
exchange.setup(V, m_func, Ms)


# LLG solve_for
def solve_for(t, y):
    m_func.vector()[:] = y
    H_ex = exchange.compute_field()
    H_eff = H_ex + H_app.vector().array()

    status, dMdt = csolve(alpha, gamma, c,
                          m_func.vector().array(), H_eff,
                          m_func.vector().array().shape[0], pins)
    if status == 0:
        return dMdt

Exemple #16
0
class Nanostrip1dEigenproblemFinmag(AbstractEigenproblem):
    """
    Eigenproblem of the form

       A*v = omega*v

    where A is a matrix that represents the right-hand side of the
    action of the linearised LLG equation (without damping):

       dv/dt = -gamma * m_0 x H_exchange(v)

    """
    def __init__(self,
                 A_ex,
                 Ms,
                 xmin,
                 xmax,
                 unit_length=1e-9,
                 regular_mesh=True):
        """
        *Arguments*

        A_ex:  float

            Exchange coupling constant (in J/m).

        Ms:  float

            Saturation magnetisation (in A/m).

        xmin, xmax:  float

            The bounds of the interval on which the 1D system is
            defined.

        regular_mesh:  bool

            If True (the default), the mesh nodes will be equally
            spaced in the interval [xmin, xmax]. Otherwise they will
            be randomly chosen.

        """
        self.A_ex = A_ex
        self.Ms = Ms
        self.xmin = xmin
        self.xmax = xmax
        self.unit_length = unit_length
        self.regular_mesh = regular_mesh
        self.L = (self.xmax - self.xmin) * self.unit_length

    def compute_exchange_field(self, v):
        """
        Compute the exchange field for the given input vector `v`
        (which should be a `numpy.array`).

        """
        self.exch.m.set_with_numpy_array_debug(v)
        return self.exch.compute_field()

    def compute_action_rhs_linearised_LLG(self, m0, v):
        """
        This function computes the action of the right hand side of
        the linearised LLG on the vector `v` and returns the result.
        Explicitly, it computes

           -gamma * (m0 x H_ex(v))

        where `m0` is the equilibrium configuration around which the
        LLG was linearised.

        """
        H = self.compute_exchange_field(v).reshape(3, -1)
        return -gamma * m0_cross(m0, H)

    def compute_action_rhs_linearised_LLG_2K(self, v):
        """
        Compute the action of the right hand side of the linearised
        LLg equation on the vector `v`, which should have a shape
        compatible with (2, N). This function assumes that the
        equilibrium configuration around which the LLG equation was
        linearised is `m0 = (0, 0, 1)^T`.

        """
        K = self.K
        m0 = np.array([0, 0, 1])
        v_3K = np.zeros(3 * K)
        v_3K[:2 * K] = v
        #v_3K.shape = (3, -1)
        res_3K = self.compute_action_rhs_linearised_LLG(m0, v_3K).ravel()
        res = res_3K[:2 * K]
        return res

    def instantiate(self, N, dtype, regular_mesh=None):
        """
        Return a pair (A, None), where A is a matrix representing the
        action on a vector v given by the right-hand side of the
        linearised LLG equation (without damping):

            A*v = dv/dt = -gamma * m_0 x H_exchange(v)

        """
        if not iseven(N):
            raise ValueError("N must be even. Got: {}".format(N))
        # XXX TODO: Actually, we shouldn't store these values in 'self'
        #           because we can always re-instantiate the problem,
        #           right?
        self.N = N
        self.dtype = dtype
        if regular_mesh == None:
            regular_mesh = self.regular_mesh
        self.K = N // 2

        if regular_mesh:
            mesh = df.IntervalMesh(self.K - 1, self.xmin, self.xmax)
        else:
            mesh = irregular_interval_mesh(self.xmin, self.xmax, self.K)
            #raise NotImplementedError()

        V = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3)
        v = Field(V)
        self.exch = Exchange(A=self.A_ex)
        Ms_field = Field(df.FunctionSpace(mesh, 'DG', 0), self.Ms)
        self.exch.setup(v, Ms_field, unit_length=self.unit_length)

        C_2Kx2K = LinearOperator(
            shape=(N, N),
            matvec=self.compute_action_rhs_linearised_LLG_2K,
            dtype=dtype)
        C_2Kx2K_dense = as_dense_array(C_2Kx2K)
        return C_2Kx2K_dense, None

    def get_kth_analytical_eigenvalue(self, k, size=None):
        i = k // 2
        return 1j * (-1)**k * (2 * self.A_ex *
                               gamma) / (mu0 * self.Ms) * (i * pi / self.L)**2

    def get_kth_analytical_eigenvector(self, k, size):
        assert (iseven(size))
        i = k // 2
        xs = np.linspace(self.xmin * self.unit_length,
                         self.xmax * self.unit_length, size // 2)
        v1 = np.cos(i * pi / self.L * xs)
        v2 = np.cos(i * pi / self.L * xs) * 1j * (-1)**i
        return np.concatenate([v1, v2])

    def _set_plot_title(self, fig, title):
        fig.suptitle(title, fontsize=16, verticalalignment='bottom')
        # fig.subplots_adjust(top=0.55)
        # fig.tight_layout()

    def plot(self, w, fig, label, fmt=None):
        """
        This function plots the real and imaginary parts of the solutions separately,
        and in addition splits each soluton eigenvector into two halves (which represent
        the x- and y-component of the magnetisation, respectively).

        """
        if fig.axes == []:
            fig.add_subplot(2, 2, 1)
            fig.add_subplot(2, 2, 2)
            fig.add_subplot(2, 2, 3)
            fig.add_subplot(2, 2, 4)
        assert (len(fig.axes) == 4)
        ax1, ax2, ax3, ax4 = fig.axes

        N = len(w)
        K = N // 2
        assert (N == 2 * K)

        # Scale the vector so that its maximum entry is 1.0
        w_max = abs(w).max()
        if w_max != 0.0:
            w = w / w_max

        fmt = fmt or ''
        ax1.plot(w[:K].real, fmt, label=label)
        ax3.plot(w[:K].imag, fmt, label=label)
        ax2.plot(w[K:].real, fmt, label=label)
        ax4.plot(w[K:].imag, fmt, label=label)
        ax1.set_ylim(-1.1, 1.1)
        ax2.set_ylim(-1.1, 1.1)
        ax3.set_ylim(-1.1, 1.1)
        ax4.set_ylim(-1.1, 1.1)