def recompute_alpha(sph_start, sph_end, t_start, t_end, mag_params): """ From a change in energy we can calculate what the effective damping was. For more details see [Albuquerque2001, http://dx.doi.org/10.1063/1.1355322]. alpha' = - (1/(M**2)) *( dE/dt / spaceintegral( (dm/dt**2 ))) No space integral is needed because we are working with 0D LLG. """ Ms = mag_params.Ms dt = t_end - t_start # Estimate dEnergy / dTime dEdt = (llg_state_energy(sph_end, mag_params, t_end) - llg_state_energy(sph_start, mag_params, t_start) )/dt # Estimate dMagnetisation / dTime then take sum of squares dmdt = [(m2 - m1)/dt for m1, m2 in zip(utils.sph2cart(sph_start), utils.sph2cart(sph_end))] dmdt_sq = sp.dot(dmdt, dmdt) # dE should be negative so the result should be positive. return - (1/(Ms**2)) * (dEdt / dmdt_sq)
def test_dfdm(): ms = [utils.sph2cart([1.0, 0.0, pi/18]), utils.sph2cart([1.0, 0.0, 0.0001*pi]), utils.sph2cart([1.0, 0.0, 0.999*pi]), utils.sph2cart([1.0, 0.3*2*pi, 0.5*pi]), utils.sph2cart([1.0, 2*pi, pi/18]), ] for m in ms: yield check_dfdm, m
def test_dfdm(): ms = [ utils.sph2cart([1.0, 0.0, pi / 18]), utils.sph2cart([1.0, 0.0, 0.0001 * pi]), utils.sph2cart([1.0, 0.0, 0.999 * pi]), utils.sph2cart([1.0, 0.3 * 2 * pi, 0.5 * pi]), utils.sph2cart([1.0, 2 * pi, pi / 18]), ] for m in ms: yield check_dfdm, m
def zeeman_energy(sph, mag_params, t=None): """ Ez = - mu0 * (M.Happ(t)), t can be None if the field is not time dependant. """ Ms = mag_params.Ms Happ = mag_params.Hvec(t) mu0 = mag_params.mu0 m = utils.sph2cart(sph) return -1 * mu0 * Ms * sp.dot(m, Happ)
def recompute_alpha_varying_fields_at_midpoint(sph_start, sph_end, t_start, t_end, mag_params): """ Compute effective damping from change in magnetisation and change in applied field. See notes 30/7/13 pg 5. Derivatives are estimated using midpoint method finite differences, all values are computed at the midpoint (m = (m_n + m_n-1)/2, similarly for t). """ # Only for normalised problems! assert(mag_params.Ms == 1) # Get some values dt = t_end - t_start t = (t_end + t_start)/2 m = (sp.array(utils.sph2cart(sph_end)) + sp.array(utils.sph2cart(sph_start)))/2 h_eff = heff(mag_params, t, m) mxh = sp.cross(m, h_eff) # Finite difference derivatives dhadt = (mag_params.Hvec(t_end) - mag_params.Hvec(t_start))/dt dedt = (llg_state_energy(sph_end, mag_params, t_end) - llg_state_energy(sph_start, mag_params, t_start) )/dt dmdt = (sp.array(utils.sph2cart(sph_end)) - sp.array(utils.sph2cart(sph_start)))/dt # utils.assert_almost_equal(dedt, sp.dot(m_cart_end, dhadt) # + sp.dot(dmdt, h_eff_end), 1e-2) # print(sp.dot(m_cart_end, dhadt), dedt) # Calculate alpha itself using the forumla derived in notes alpha = -((dedt + sp.dot(m, dhadt)) / (sp.dot(h_eff, sp.cross(m, dmdt)))) return alpha
def test_llg_residuals(): m0_sph = [0.0, pi/18] m0_cart = utils.sph2cart(tuple([1.0] + m0_sph)) # m0_constrained = list(m0_cart) + [None] # ??ds residuals = [(llg.llg_cartesian_residual, m0_cart), (llg.ll_residual, m0_cart), # (llg_constrained_cartesian_residual, m0_constrained), ] for r, i in residuals: yield check_residual, r, i
def test_llg_residuals(): m0_sph = [0.0, pi / 18] m0_cart = utils.sph2cart(tuple([1.0] + m0_sph)) # m0_constrained = list(m0_cart) + [None] # ??ds residuals = [ (llg.llg_cartesian_residual, m0_cart), (llg.ll_residual, m0_cart), # (llg_constrained_cartesian_residual, m0_constrained), ] for r, i in residuals: yield check_residual, r, i
def recompute_alpha_varying_fields( sph_start, sph_end, t_start, t_end, mag_params): """ Compute effective damping from change in magnetisation and change in applied field. See notes 30/7/13 pg 5. Derivatives are estimated using BDF1 finite differences. """ # Only for normalised problems! assert(mag_params.Ms == 1) # Get some values dt = t_end - t_start m_cart_end = utils.sph2cart(sph_end) h_eff_end = heff(mag_params, t_end, m_cart_end) mxh = sp.cross(m_cart_end, h_eff_end) # Finite difference derivatives dhadt = (mag_params.Hvec(t_start) - mag_params.Hvec(t_end))/dt dedt = (llg_state_energy(sph_end, mag_params, t_end) - llg_state_energy(sph_start, mag_params, t_start) )/dt dmdt = (sp.array(utils.sph2cart(sph_start)) - sp.array(m_cart_end))/dt utils.assert_almost_equal(dedt, sp.dot(m_cart_end, dhadt) + sp.dot(dmdt, h_eff_end), 1e-2) # print(sp.dot(m_cart_end, dhadt), dedt) # Calculate alpha itself using the forumla derived in notes alpha = ((dedt - sp.dot(m_cart_end, dhadt)) / (sp.dot(h_eff_end, sp.cross(m_cart_end, dmdt)))) return alpha
def low_accuracy_recompute_alpha_varying_fields( sph_start, sph_end, t_start, t_end, mag_params): """ Compute effective damping from change in magnetisation and change in applied field. From Nonlinear magnetization dynamics in nanosystems eqn (2.15). See notes 30/7/13. Derivatives are estimated using BDF1 finite differences. """ # Only for normalised problems! assert(mag_params.Ms == 1) # Get some values dt = t_end - t_start m_cart_end = utils.sph2cart(sph_end) h_eff_end = heff(mag_params, t_end, m_cart_end) mxh = sp.cross(m_cart_end, h_eff_end) # Finite difference derivatives dhadt = (mag_params.Hvec(t_start) - mag_params.Hvec(t_end))/dt assert(all(dhadt == 0)) # no field for now dedt = (llg_state_energy(sph_end, mag_params, t_end) - llg_state_energy(sph_start, mag_params, t_start) )/dt sigma = sp.dot(mxh, mxh) / (dedt + sp.dot(m_cart_end, dhadt)) possible_alphas = sp.roots([1, sigma, 1]) a = (-sigma + sqrt(sigma**2 - 4))/2 b = (-sigma - sqrt(sigma**2 - 4))/2 possible_alphas2 = [a, b] utils.assert_list_almost_equal(possible_alphas, possible_alphas2) print(sigma, possible_alphas) def real_and_positive(x): return sp.isreal(x) and x > 0 alphas = filter(real_and_positive, possible_alphas) assert(len(alphas) == 1) return sp.real(alphas[0])
def ramping_field_llg_initial(*_): return utils.sph2cart([1.0, 0.0, sp.pi/18])
def simple_llg_initial(*_): return utils.sph2cart([1.0, 0.0, sp.pi/18])
def magnetocrystalline_anisotropy_energy(sph, mag_params): """ Eca = K1 (m.e)^2""" K1 = mag_params.K1 m_cart = utils.sph2cart(sph) return K1 * (1 - sp.dot(m_cart, mag_params.easy_axis)**2)
def ramping_field_llg_initial(*_): return utils.sph2cart([1.0, 0.0, sp.pi / 18])
def simple_llg_initial(*_): return utils.sph2cart([1.0, 0.0, sp.pi / 18])