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
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
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,
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
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
Force-gradient detection#
The force-gradient produced by a single spin is
with \(G_{zxx} = \partial^2 B_z / \partial x^2\). For a single spin directly below the tip at \((0,0,z)\),
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
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
Testing Lists#
- class tests.test_experiment.test_cermitesr.TestCERMITESR[source]#
Bases:
object
Test cermitesr experiment.
- class tests.test_experiment.test_cermitarp.TestCERMITARP[source]#
Bases:
object
Test cermitarp experiments.
grid = GridObject( L = [0.5E-3,0.5E-3,0.5E-3], dL= [0.5E-3,0.5E-3,0.5E-3], o=[0.0, 0.0, 0.0])
The resulting grid is
centered at zero,
contains \(2 \times 2 \times 2 = 8\) grid points, and
runs from
-0.5e-3
to+0.5e-3
nm in each direction.
So that the grid contains 1 spin total, we need to fudge the spin density to be \(1.0 \times 10^{9} \: \mathrm{spins} \: \mathrm{nm}^{3}\). Other notable features of the calculations:
We work at 10 millikelvin and 10.0 tesla so that the electron spin is nearly fully polarized
In the ARP experiment, we set the irradiation frequency to be in resonance with spins directly below the tip. These spins experience a total field of 10437.318 mT. The assumed \(B_1\) is 10 mT, and the FM sweep is ten times that (in field units). In setting up
expt1
below, we must take care to setB_0_start
to 10000.0 mT and not 10437.318 mT.
We check to see that the single-spin signal and the pulse time agree with expected values to be within a 2 percent (relative) error.
- class tests.test_experiment.test_cermitarp.TestCERMITESRSmallTip[source]#
Bases:
object
Compare different limits between experiment settings.
Test the group of CERMIT ESR experiments.
- class tests.test_experiment.test_cermitsinglespin.TestCermitSinglespin[source]#
Bases:
object
Test the CERMIT ESR experiment with a single spin.
See test_misc.py for the test of the numerical solution. Here, we test that the approximated solution is similar to the exact solution.
- class tests.test_experiment.test_ibmcyclic.TestIBMCyclic[source]#
Bases:
object
Test IBMCyclic Experimental method.
- 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 the 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 Trapezoid 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.
- tests.test_formula.test_field.test_field_func()[source]#
Test field.
Test the field calculation against ogrid and mgrid.
- tests.test_formula.test_field.test_field_func_singularity()[source]#
Test field when the grid has one point in one direction.
In this example, the z direction has only one point. The resulting grid is effectively a 2d plane.
- 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_slice_matrix()[source]#
Test slice matrix cuts the matrix in the center.
- tests.test_formula.test_magnetization.test_mz2_eq_H()[source]#
Test proton magnetization variance at equilibrium.
- tests.test_formula.test_magnetization.test_mz_eq_high_susceptibility(Gamma, J, temperature, mz_eq_true)[source]#
Test mz_eq function on different types of samples at low temperature. The total field is set to 100 T
- tests.test_formula.test_magnetization.test_mz_eq_low_susceptibility(B_tot)[source]#
Test mz_eq on 71Ga at high temperature.
- 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_formula.test_misc.test_sum_of_product()[source]#
Test sum_of_product.
Make sure the final value is an int and is the floor value.
Test the relative change in polarization.
- tests.test_formula.test_polarization.test_rel_dol_sat_td_smallsteps(sample_e)[source]#
Test rel_dol_sat_td_smallsteps.
Small steps approximation should have the same result as regular when Bzx stays the same, given that delta_B_offset has the same sign as Bzx.
- tests.test_formula.test_polarization.test_rel_dpol_arp(sample_h)[source]#
Test rel_dpol_arp.
if f_fm is close to infinity, the relative change in polarization is -2.0 if b1 and the modulation frequency is small and b_offset is large the spin does not flip therefore the relative change in polarization is close to 0.0 (off-resonance case)
- tests.test_formula.test_polarization.test_rel_dpol_ibm_cyclic(sample_h)[source]#
Test rpol_arp_ibm.
Sample -> proton spin -> rpol_arp_ibm() limiting cases Sample -> h -> proton spin
- tests.test_formula.test_polarization.test_rel_dpol_multipulse_long(sample_e)[source]#
Test rel_dpol_multipulse when the time between pulses is long.
In this case, the final polarization should be relaxed to 1 and the chang in polarization is 0.
- tests.test_formula.test_polarization.test_rel_dpol_multipulse_no_pol(sample_e)[source]#
Test rel_dpol_multipulse when relative polarization is 0.
- tests.test_formula.test_polarization.test_rel_dpol_multipulse_short(sample_e)[source]#
Test rel_dpol_multipulse when the pulse time difference is short.
Because the time between pulses is short and the equation ignores relaxation during pulses,
- tests.test_formula.test_polarization.test_rel_dpol_nut(sample_h)[source]#
Test rel_dpol_nut.
Sample -> proton spin -> rpol_nut(), on resonance pulses Sample -> h -> proton spin
- tests.test_formula.test_polarization.test_rel_dpol_periodic_irrad_cont(sample_e)[source]#
Test rel_dpol_periodic_irrad in the continuous case.
When the if t_off is 0, the intermittent irradiation becomes continuous irradiation. This should be the same as rel_dpol_sat When t_on is 0, the signal should vanish
- tests.test_formula.test_polarization.test_rel_dpol_periodic_irrad_no_irrad(sample_e)[source]#
Test rel_dpol_periodic_irrad in no irradiation case.
When t_on is 0, the signal should vanish
- tests.test_formula.test_polarization.test_rel_dpol_periodic_irrad_off_res(sample_e)[source]#
Test rel_dpol_periodic_irrad off-resonance case.
When is it off-resonance (B_offset is large), the signal is 0
- tests.test_formula.test_polarization.test_rel_dpol_sat_steadystate(sample_e)[source]#
Test the rel_dpol_sat absolute tolerance.
Sample -> e -> electron spin, J = 1/2, high field limit
- tests.test_formula.test_polarization.test_rel_dpol_sat_td(sample_e)[source]#
Test rel_dpol_sat_td when offset is 0.
When the offset is 0, the result should be 0
Here we construct a 1D grid size of 3, and extended grid size of 5