Source code for mrfmsim.formula.misc

import math
import numpy as np
import scipy.special
from functools import reduce

HBAR = 1.054571628e-7  # aN nm s - reduced Planck constant


[docs] def convert_grid_pts(distance, grid_step): """Convert distance to ext points. :param int distance: distance in the x direction. """ return math.floor(distance / grid_step[0])
[docs] def singlespin_analytical( Gamma, geometry, J, magnet_spin_dist, magnet_origin, magnet_radius, mu0_Ms, x_0p ): r"""The analytical calculation for a single spin. The analytical solution to the exact equations for the delta k without any approximations as derived below: :math:`\Delta f = - \frac{f}{k x_{pk}^2} \langle F_{ts} x \rangle` where :math:`x_{pk}` is the zero-to-peak amplitude of the cantilever. This equation can be expressed as an integral over an angle :math:`\theta` For the *hangdown* geometry, .. math:: F_{ts} = \mu_z \mu_0 M r^3 \dfrac{x^3 - 4z^2x}{(z^2 + x^2)^{7/2}} For the *SPAM* geometry, :math:`F_{ts} = \dfrac{\mu_z \mu_0 M r^3 x}{(x^2 + y^2)^{5/2}}` where :math:`\mu_z` is the spin magnetic moment, :math:`\mu_0 M` is the saturation magnetization of the tip, and r is the tip radius. .. math:: \Delta f = \frac{f}{2 \pi k x_{pk}^2} \int_{-\pi}^{\pi} \mu(x,y,z,\theta) \times \frac{\partial B_{z}^{\mathrm{tip}} (x-x_{pk}\cos \theta, y, z)}{\partial x} x_{pk}\cos \theta d\theta Substituting into the integral and introducing a unitless variable :math:`\hat{z} = z/x_{peak}` for the *hangdown* geometry and :math:`\hat{y}/x_{peak}` for the SPAM geometry, we obtain the following integrals: .. math:: \Delta f = \frac{f}{2 k x_{pk}}\frac{\mu_z \mu_0 M}{a} (\frac{a}{z})^4 \times \frac{\bar{z}^4}{\pi} \int_0^{2\pi} \frac{\cos^4 \theta - 4\hat{z}^2\cos^2\theta} {(\hat{z}^2 + \cos^2\theta)^{7/2}} d\theta This integral (along with the :math:`\frac{\hat{z}^4}{\pi}` prefactor) can be solved exactly in Mathematica to give a solution in terms of Elliptic Integrals .. math:: \frac{\hat{z}^3}{3\pi(\hat{z}^2 +1)}(4(2\hat{z}^4 - 7\hat{z}^2 -1)E(-1/\hat{z}^2) -8(\hat{z}^4 - 1)K(-1/\hat{z}^2)) where :math:`K(m)` and :math:`E(m)` are, respectively, the complete elliptic integrals of the first and second kind. For the *SPAM* geometry, .. math:: \Delta f = \frac{f}{2 k x_{pk}} \frac{\mu_z \mu_0 M} {z} \left(\frac{a}{y}\right)^4 \times \frac{\hat{z}^4}{\pi} \int_0^{2\pi}\frac{\cos^2 \theta}{(\cos^2 \theta + \hat{y}^2)^{5/2}}d\theta This integral (along with the :math:`\frac{\hat{y}^4}{\pi}` prefactor can be solved exactly in terms of Elliptic integrals: .. math:: \frac{4\hat{y}^3}{3\pi(1+\hat{y}^2)^2}[(1+\hat{y}^2)E(-1/\hat{y}^2) - (\hat{y}^2 -1)K(-1/\hat{y}^2) :param float Gamma: the gyromagnetic ratio :param float J: the spin angular momentum :param array magnet_origin: the origin of the magnet :param float magnet_radius: the radius of the magnet :param float mu0_Ms: the saturation magnetization of the magnet :param float mu_z: the spin magnetic moment :param float magnet_spin_distance: magnet-spin distance :return: The analytical solution for a single spin (effective force). The spin constant shift is the effective force divided by the 0 to peak amplitude. """ mu_z = HBAR * Gamma * J if geometry.lower() == "spam": origin_sample_distance = magnet_origin[1] + magnet_spin_dist Y = origin_sample_distance / x_0p val = -1.0 / Y**2 ek = scipy.special.ellipk(val) ee = scipy.special.ellipe(val) I_term = ( 4.0 * Y**3 / (3.0 * np.pi * (1.0 + Y**2) ** 2) * ((1.0 + Y**2) * ek - (Y**2 - 1.0) * ee) ) elif geometry.lower() == "hangdown": origin_sample_distance = magnet_origin[2] + magnet_spin_dist Z = origin_sample_distance / x_0p val = -1.0 / Z**2 ek = scipy.special.ellipk(val) ee = scipy.special.ellipe(val) I_term = ( Z**3 / (3.0 * np.pi * (1 + Z**2) ** 3) * (4.0 * (2.0 * Z**4 - 7.0 * Z**2 - 1.0) * ee - 8.0 * (Z**4 - 1.0) * ek) ) else: raise ValueError("Invalid geometry") const_term = -( mu0_Ms * mu_z / magnet_radius * (magnet_radius / origin_sample_distance) ** 4 ) # Assuming the spin is completely saturated, from 1 to 0 # polarization change is -1, hence the negative sign. dF_spin = -const_term * I_term return dF_spin
[docs] def sum_of_product(*args): """Calculate the sum of the product input values. The args can be a list of values since NumPy multiple can calculate the value. """ return np.sum(reduce(np.multiply, args))
[docs] def neg_sum_of_product(*args): """Calculate the negative sum of the product input values. The args can be a list of values, since numpy multiple can calculate the value. The function is used to simplify the definition in some of the experiments. The approximation of the signal results in a negative sign at the front. """ return -np.sum(reduce(np.multiply, args))