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
Google Colab Link
The demo can be run on Google Colab without any local installation. Use the following link to try it out.
[10]:
!pip install -q magnumnp numpy==1.22.4
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")