RKKY

Example and benchmark problem according to “Accurate finite-difference micromagnetics of magnets including RKKY interaction”, Suess, Dieter, et al., arXiv preprint arXiv:2206.11063 (2022).

The analytical saturation field Hx = 5*Hk

Run Demo:

[12]:
from magnumnp import *
import torch
import numpy as np

Timer.enable()
A = 1e-11
Js = 1.0
Ms = Js/constants.mu_0
Ku = 1e5
tfinal = 20e-9
J_rkky = -2.0e-3
Hxmin = 4.8 * 2*Ku/Js
Hxmax = 5.0 * 2*Ku/Js

# initialize mesh
n  = (1, 1, 400)
dx = (2e-9, 2e-9, 2e-9)
mesh = Mesh(n, dx)
state = State(mesh)

state.material = {
        "Ms": Ms,
        "A": A,
        "Ku": Ku,
        "Ku_axis": state.Tensor([0,1,0]),
        "alpha": 1.0
        }

domain1 = state._zeros(n, dtype=torch.bool)
domain1[:,:,n[2]//2:] = True

domain2 = state._zeros(n, dtype=torch.bool)
domain2[:,:,:-n[2]//2] = True

# Set initial magnetization
state.m = state.Constant([0, 0, 0])
state.m[domain1] = state.Tensor([0, -1, 0])
state.m[domain2] = state.Tensor([0, 1, 0])

# define field terms
exchange1 = ExchangeField(domain1) # Two seperate exchange regions are required,
exchange2 = ExchangeField(domain2) # so that at the RKKY interface the bulk exchange is zero
rkky      = RKKYField(J_rkky, "z", n[2]//2-1, n[2]//2, order=2)
aniso     = UniaxialAnisotropyField()
zeeman    = ExternalField(TimeInterpolator(state, {0e-0:   [0, 0, Hxmin],
                                                   tfinal: [0, 0, Hxmax]}))

# integrate
llg = LLGSolver([aniso, exchange1, exchange2, rkky, zeeman], atol = 1e-6)
logger = Logger("data", ['t', 'm', zeeman.h], ['m'], fields_every = 100)
while state.t < tfinal:
    logger << state
    llg.step(state, 1e-9)

Timer.print_report()
2023-05-08 12:26:30  magnum.np:INFO [State] running on device: cpu (dtype = float64)
2023-05-08 12:26:30  magnum.np:INFO [Mesh] 1x1x400 (size= 2e-09 x 2e-09 x 2e-09)
2023-05-08 12:26:30  magnum.np:INFO [LLGSolver] using RKF45 solver (atol = 1e-06)
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
File ~/git/magnum.np/magnumnp/common/timer.py:236, in timedmethod.<locals>.timed(*args, **kwargs)
    235 with Timer("%s.%s" % (args[0].__class__.__name__, method.__name__)):
--> 236     return method(*args, **kwargs)

File ~/git/magnum.np/magnumnp/field_terms/external.py:51, in ExternalField.h(self, state)
     49 @timedmethod
     50 def h(self, state):
---> 51     h = state.Tensor(self._h)(state.t)
     52     if len(h.shape) == 1:

File ~/git/magnum.np/magnumnp/common/state.py:115, in State.Tensor.<locals>.<lambda>(t)
    114 elif callable(data):
--> 115     return lambda t: self.Tensor(data(t))
    116 else:

File ~/git/magnum.np/magnumnp/common/time_interpolator.py:36, in TimeInterpolator.__call__(self, t)
     35 fp = self._fp
---> 36 return fp[i-1] + (t-tp[i-1]) / (tp[i]-tp[i-1]) * (fp[i] - fp[i-1])

File ~/git/magnum.np/magnumnp/common/decorated_tensor.py:62, in DecoratedTensor.__getitem__(self, idx)
     61 else: # apply fancy indexing
---> 62     item._cell_volumes = self._cell_volumes.__getitem__(idx)
     64 return item

File ~/git/magnum.np/venv/lib/python3.8/site-packages/torch/_tensor.py:1295, in Tensor.__torch_function__(cls, func, types, args, kwargs)
   1294 with _C.DisableTorchFunctionSubclass():
-> 1295     ret = func(*args, **kwargs)
   1296     if func in get_default_nowrap_functions():

IndexError: index 1 is out of bounds for dimension 0 with size 1

The above exception was the direct cause of the following exception:

IndexError                                Traceback (most recent call last)
Cell In[12], line 52
     50 logger = Logger("data", ['t', 'm', zeeman.h], ['m'], fields_every = 100)
     51 while state.t < tfinal:
---> 52     logger << state
     53     llg.step(state, 1e-9)
     55 Timer.print_report()

File ~/git/magnum.np/magnumnp/loggers/logger.py:71, in Logger.__lshift__(self, state)
     70 def __lshift__(self, state):
---> 71     self.log(state)

File ~/git/magnum.np/magnumnp/loggers/logger.py:68, in Logger.log(self, state)
     66     return
     67 for logger in self.loggers.values():
---> 68     logger << state

File ~/git/magnum.np/magnumnp/loggers/scalar_logger.py:113, in ScalarLogger.__lshift__(self, state)
    112 def __lshift__(self, state):
--> 113     self.log(state)

File ~/git/magnum.np/magnumnp/loggers/scalar_logger.py:92, in ScalarLogger.log(self, state)
     90     except:
     91         name = 'unnamed'
---> 92     raw_value = column(state)
     93 elif isinstance(column, tuple) or isinstance(column, list):
     94     name = column[0]

File ~/git/magnum.np/magnumnp/common/timer.py:236, in timedmethod.<locals>.timed(*args, **kwargs)
    233 @wraps(method)
    234 def timed(*args, **kwargs):
    235     with Timer("%s.%s" % (args[0].__class__.__name__, method.__name__)):
--> 236         return method(*args, **kwargs)

File ~/git/magnum.np/magnumnp/common/timer.py:103, in Timer.__exit__(self, e_typ, e_val, trcbak)
    101 def __exit__(self, e_typ, e_val, trcbak):
    102     if all((e_typ, e_val, trcbak)):
--> 103         raise e_typ from e_val
    105     if not Timer._options['active']: return self
    107     if Timer._options['skip'] <= self._data['calls']:

IndexError:

Plot Results:

[ ]:
from os import path
if not path.isfile("ref/log.dat"):
    !mkdir ref
    !wget -P ref https://gitlab.com/magnum.np/magnum.np/raw/main/demos/rkky/ref/log.dat
[ ]:
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

data = np.loadtxt("data/log.dat")
ref = np.loadtxt("ref/log.dat")

Hk = 2 * 1e5 / 1.

fig, ax = plt.subplots(figsize=(10,5))
cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']

ax.plot(data[:,6]/Hk, data[:,3], '-', color = cycle[2], label = "magnum.np")
ax.plot(ref[:,6]/Hk, ref[:,3], '-', color = cycle[2], linewidth = 6, alpha = 0.4, label = "reference")

ax.set_xlim([4.82,5.0])
ax.set_ylim([0.99994,1.0])
ax.set_yticklabels(['0.99994', '0.99995', '0.99996', '0.99997', '0.99998', '0.99999', '1.00000'])
ax.set_title("RKKY Standard Problem")
ax.set_xlabel("External Field H$_{ext}$ / H$_k$ [1]")
ax.set_ylabel("Magnetization m")
ax.legend(ncol=3)
ax.grid()
fig.savefig("data/results.png")