Tests#

Overview#

This module is a collection of files that test the functions in the MrfmSim package. To run the unit tests, open up a terminal in the MrfmSim directory and run the following command:

python -m pytest

Signal verification#

We can test the signal-calculation modules by computing the signal from a single spin. Consider a magnet-tipped cantilever operated in the hangdown geometry:

  • a magnetic field is applied along the \(z\) direction to polarize the cantilever’s magnet and to define the quantization axis of the sample’s spins;

  • the cantilever oscillates in the \(x\) direction;

  • the long axis of the cantilever is parallel to the \(z\) direction;

  • the magnet at the tip of the cantilever is a sphere of radius \(r\), polarized along the \(z\) direction, with saturation magnetization \(M_s\) and saturation field \(\mu_0 M_s\);

  • the center of the spherical magnet lies at the origin, \((0,0,0)\);

  • the sample lies in the \(xy\) plane; for simplicity, we further assume that the spin lies along the \(y = 0\) line;

  • the distance between the center of the magnet and the sample plane is \(z\).

Some notes on the additional tests

Magnet Test#

The RectMagnet is tested through its symmetry factors: it is symmetric in the \(z\) direction when x and y are 0. The gradient functions are tested against a numerical derivative calculation from the field. \(B_z\) is an even function in the \(x\) direction, \(B_{zx}\) is an odd function in the x-direction and :math: B_{zxx} is an even function in the \(x\) direction.

Polarization Test#

The polarization test for irrad_periodic function is taken from John’s notebook

Experiment Test#

Some of the tests are calculated against some of the old notebook examples from John and Corinne. Note to see the notebook and examples go to the MrfmSim-archived package’s git commit (c74d504).

  • IBMCyclic dF_spin -> test_experiment from John Marohn.

  • IBMCyclic dF2_spin -> value taken from test-ibmexpt-1.ipynb simulation 1, #4 - 9, matching with relative 5e-5 precision.

  • CermitARP is taken from “test_cornellexptobject.py”

  • CermitESR is tested against value from “test-cornellexpt-4.ipynb” (Moore experiment - local peak, # 0 - 5, Issac Experiment, # 24 - 28) the difference in value is expected because the min_abs_offset function fixed a previous issue.

  • CermitARP_SmallTip is tested against “test-cornellexpt-8-Hickman_nanomagnet_simulations.ipynb”, first simulation.

  • CermitARP_SmallTip is compared with CermitARP, in two cases using a rectangular magnet, one is when the amplitude is small, they should be the same, and when tip_sep is large, the effect of amplitude is also small (There is a comparison in “test-micrometertip_smallampapprox_vs_exactsol.ipynb” on small amplitude, however, the result is unchecked).

  • CmeritSingleSpinESR_Approx is compared with CermitARP_SmallTip.

  • SingleSpinESR
    • The approximation is tested against both SPAM and hangdown geometry of the analytical solution

Force detection#

The force produced by a single spin is

\[\delta F_{\mathrm{spin}} = \mu_{\mathrm{spin}} \: G_{zx}(r_{\mathrm{spin}})\]

with \(\mu_{\mathrm{spin}}\) the spin magnetic moment and \(G_{zx} = \partial B_z / \partial x\) and \(r_{\mathrm{spin}}\) the location of the spin. The gradient experienced by a spin located in the \(y = 0\) plane is

\[G_{zx}(x,0,z) = 4 \mu_0 M_s r^3 \: \frac{x \: (x^2 - 4 z^2)}{(x^2 + z^2)^{7/2}}\]

We see that the gradient \(G_{zx}\) is zero for a spin directly below the tip at \((0,0,z)\). For the single-spin force experiment, we must therefore place the spin “off to the side”, at a location \((x,0,z)\). The gradient is maximized at (approximately) \(x_{\mathrm{opt}} = \pm 0.389295 \: z\). For a spin placed at this optimal location,

\[G_{zx}(x_{\mathrm{opt}}, 0, z) \approx 0.914269 \: \frac{\mu_0 M_s}{r} \left( \frac{r}{z} \right)^{4}\]

In the hangdown-geometry experiment delineated above, the force acting on a magnet-tipped cantilever from a single spin placed at an optimal location “off to the side” of the cantilever tip is

\[\delta F_{\mathrm{spin}} \approx 0.914269 \: \mu_{\mathrm{spin}} \: \frac{\mu_0 M_s}{r} \left( \frac{r}{z} \right)^{4}\]

With

  • tip magnetization \(\mu_0 M_s = 1800 \: \mathrm{mT}\) (cobalt)

  • tip radius \(r = 50 \: \mathrm{nm}\)

  • tip-sample separation \(20 \: \mathrm{nm}\), that is, \(z = 70 \: \mathrm{nm}\)

  • a single (fully polarized) electron spin placed at \((27.2507, 0.0000, 70.0000) \: \mathrm{nm}\)

the force is

\[\delta F_{\mathrm{spin}} = -79.231 \: \mathrm{aN}\]

Force-gradient detection#

The force-gradient produced by a single spin is

\[\delta k_{\mathrm{spin}} = \mu_{\mathrm{spin}} \: G_{zxx}(r_{\mathrm{spin}})\]

with \(G_{zxx} = \partial^2 B_z / \partial x^2\). For a single spin directly below the tip at \((0,0,z)\),

\[G_{zxx}(0,0,z) = - \frac{4 \mu_0 M_s r^3}{z^5} = - \frac{4 \mu_0 M_s}{r^2} \left( \frac{r}{z} \right)^{5}\]

In the hangdown-geometry experiment delineated above, the force gradient acting on a magnet-tipped cantilever from a single spin placed directly below the cantilever tip is

\[\delta k_{\mathrm{spin}} = - \mu_{\mathrm{spin}} \: \frac{4 \mu_0 M_s}{r^2} \left( \frac{r}{z} \right)^{5}\]

With

  • tip magnetization \(\mu_0 M_s = 1800 \: \mathrm{mT}\) (cobalt)

  • tip radius \(r = 50 \: \mathrm{nm}\)

  • tip-sample separation \(20 \: \mathrm{nm}\), that is, \(z = 70 \: \mathrm{nm}\)

  • a single (fully polarized) electron spin placed at \((0.0, 0.0, 70.0) \: \mathrm{nm}\)

the force gradient is

\[\delta k_{\mathrm{spin}} = 4.95203 \: \mathrm{aN} \: \mathrm{nm}^{-1} = 4.95203 \: \mathrm{nN} \: \mathrm{m}^{-1}\]

Testing Lists#

class tests.test_experiment.test_ibmcyclic.TestIBMCyclic[source]#

Bases: object

Test IBMCyclic Experimental method.

test_IBMCyclic_dF2_spin()[source]#

Test IBM cyclic force variance signal for nucleus.

Values are taken from “test-ibmexpt-1.ipynb” simulation 1 #4- #9 based on John’s calculation.

test_IBMCyclic_dF_spin()[source]#

Test IBM curie law signal.

class tests.test_formula.test_field.TestXTrapzFieldGradient[source]#

Bases: object

Test trapz field gradient.

test_xtrapz_field_gradient_large_distance()[source]#

Test gradient against a large tip-sample separation.

When the distance is very large, the change of Bzx in between grid points are small.

test_xtrapz_field_gradient_smallamp()[source]#

Test gradient against a small x0p.

When the 0 to the peak is very small compared to the magnet, the field is equivalent to Bzxx. Here we “fake” a small grid step for the x direction, because the grid step here is only used to calculate x_0p. The cantilever is 150 nm away from the sample.

class tests.test_formula.test_field.TestXTrapzFxDtheta[source]#

Bases: object

Test xtrapz_fxdtheta.

test_xtrapz_fxdtheta_cos()[source]#

Test xtrapz_fxdtheta against :math: cos{x}dx

Let’s consider the field method returns 1, the trapz integral should return the value of

\[\int_{-\pi}^{\pi}{x_0 \cos\theta d\theta}\]

The results: (-pi/2 -> 0): x0 (-pi -> 0): 0

test_xtrapz_fxdtheta_multidim()[source]#

Test xtrapz_fxdtheta against :math: x cos{x} for multi-dimensions.

test_xtrapz_xtrapz_fxdtheta_x2cos()[source]#

Test xtrapz_fxdtheta against :math: x2cos{x}.

Let’s consider a case where the field f(x) = x

\[\int_{-\pi}^{\pi}{(x-x_0 \cos\theta)x_0 \cos\theta d\theta}\]

The results: (-pi/2 -> 0): x^2*x0 - pi/2*x*x0^2 + 2/3 * x0^3 (-pi -> 0): - pi*x*x0^2

test_xtrapz_xtrapz_fxdtheta_xcos()[source]#

Test xtrapz_fxdtheta against :math: x cos{x}.

Let’s consider a case where the field f(x) = x

\[\int_{-\pi}^{\pi}{(x-x_0 \cos\theta)x_0 \cos\theta d\theta}\]

The results: (-pi/2 -> 0): x*x0 - x0^2*pi/4 (-pi -> 0): - x0^2 * pi/2

tests.test_formula.test_field.test_B_offset()[source]#

Test B_offset.

Test the nucleus.

tests.test_formula.test_field.test_min_abs_offset()[source]#

Test min_abs_x.

tests.test_formula.test_field.test_min_abs_offset_symmetry()[source]#

Test if min_abs_x result is symmetric. If a matrix is flipped, the result should also be flipped

tests.test_formula.test_math.test_as_strided_x()[source]#

Testing if as_strided_x maximum matches running max.

tests.test_formula.test_math.test_ogrid_sub()[source]#

Test ogrid_sub.

The sub results in a iterable mapping. Here tests if the dimension and values are correct.

tests.test_formula.test_math.test_slice_matrix()[source]#

Test slice matrix cuts the matrix in the center.

tests.test_formula.test_misc.test_convert_grid_pts()[source]#

Test convert_grid_pts.

Make sure the final value is an int and is the floor value.

tests.test_units.test_units()[source]#

Test if units are loaded correctly.