def __init__(self, mesh): self.mesh = mesh self.S1 = df.FunctionSpace(mesh, 'CG', 1) self.S3 = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3) #zero = df.Expression('0.3') m_init = df.Constant([1, 1, 1.0]) self.m = df.interpolate(m_init, self.S3) self.field = df.interpolate(m_init, self.S3) self.dmdt = df.interpolate(m_init, self.S3) self.spin = self.m.vector().array() self.t = 0 #It seems it's not safe to specify rank in df.interpolate??? self._alpha = df.interpolate(df.Constant("0.001"), self.S1) self._alpha.vector().set_local(self._alpha.vector().array()) print 'dolfin', self._alpha.vector().array() self.llg = LLG(self.S1, self.S3, unit_length=1e-9) #normalise doesn't work due to the wrong order self.llg.set_m(m_init, normalise=True) parameters = { 'absolute_tolerance': 1e-10, 'relative_tolerance': 1e-10, 'maximum_iterations': int(1e5) } demag = Demag() demag.parameters['phi_1'] = parameters demag.parameters['phi_2'] = parameters self.exchange = Exchange(13e-12) self.zeeman = Zeeman([0, 0, 1e5]) self.llg.effective_field.add(self.exchange) #self.llg.effective_field.add(demag) self.llg.effective_field.add(self.zeeman) self.m_petsc = df.as_backend_type(self.llg.m_field.f.vector()).vec() self.h_petsc = df.as_backend_type(self.field.vector()).vec() self.alpha_petsc = df.as_backend_type(self._alpha.vector()).vec() self.dmdt_petsc = df.as_backend_type(self.dmdt.vector()).vec() alpha = 0.001 gamma = 2.21e5 LLG1 = -gamma / (1 + alpha * alpha) * df.cross( self.m, self.field) - alpha * gamma / (1 + alpha * alpha) * df.cross( self.m, df.cross(self.m, self.field)) self.L = df.dot(LLG1, df.TestFunction(self.S3)) * df.dP
def test_method_of_computing_the_average_matters(): length = 20e-9 # m simplices = 10 mesh = df.IntervalMesh(simplices, 0, length) S1 = df.FunctionSpace(mesh, "Lagrange", 1) S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3) llg = LLG(S1, S3) llg.set_m(( '(2*x[0]-L)/L', 'sqrt(1 - ((2*x[0]-L)/L)*((2*x[0]-L)/L))', '0'), L=length) average1 = llg.m_average average2 = np.mean(components(llg.m_numpy), axis=1) diff = np.abs(average1 - average2) assert diff.max() > 5e-2
def test_dmdt_computation_with_oommf(): # set up finmag llg = LLG(S1, S3) llg.set_m((-3, -2, 1)) Ms = llg.Ms.vector().array()[0] Ms = float(Ms) h = Ms / 2 H_app = (h / np.sqrt(3), h / np.sqrt(3), h / np.sqrt(3)) zeeman = Zeeman(H_app) zeeman.setup(llg.m_field, llg.Ms, 1) llg.effective_field.add(zeeman) dmdt_finmag = df.Function(llg.S3) dmdt_finmag.vector()[:] = llg.solve(0) # set up oommf msh = mesh.Mesh((nL, nW, nH), size=(L, W, H)) m0 = msh.new_field(3) m0.flat[0] += -3 m0.flat[1] += -2 m0.flat[2] += 1 m0.flat /= np.sqrt(m0.flat[0] * m0.flat[0] + m0.flat[1] * m0.flat[1] + m0.flat[2] * m0.flat[2]) dmdt_oommf = oommf_dmdt(m0, Ms, A=0, H=H_app, alpha=0.5, gamma_G=llg.gamma).flat # extract finmag data for comparison with oommf dmdt_finmag_like_oommf = msh.new_field(3) for i, (x, y, z) in enumerate(msh.iter_coords()): dmdt_x, dmdt_y, dmdt_z = dmdt_finmag(x, y, z) dmdt_finmag_like_oommf.flat[0, i] = dmdt_x dmdt_finmag_like_oommf.flat[1, i] = dmdt_y dmdt_finmag_like_oommf.flat[2, i] = dmdt_z # compare difference = np.abs(dmdt_finmag_like_oommf.flat - dmdt_oommf) relative_difference = difference / np.max( np.sqrt(dmdt_oommf[0]**2 + dmdt_oommf[1]**2 + dmdt_oommf[2]**2)) print "comparison with oommf, dm/dt, relative difference:" print stats(relative_difference) assert np.max(relative_difference) < TOLERANCE return difference, relative_difference
def test_spatially_varying_alpha_using_LLG_class(): """ no property magic here - llg.alpha is a df.Function at heart and can be set with any type using llg.set_alpha() """ length = 20 simplices = 10 mesh = df.IntervalMesh(simplices, 0, length) S1 = df.FunctionSpace(mesh, "Lagrange", 1) S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, 3) llg = LLG(S1, S3) llg.set_alpha(1) expected_alpha = np.ones(simplices + 1) print "Got:\n", llg.alpha.vector().array() print "Expected:\n", expected_alpha assert np.array_equal(llg.alpha.vector().array(), expected_alpha)
def setup_domain_wall_cobalt(node_count=NODE_COUNT, A=A_Co, Ms=Ms_Co, K1=K1_Co, length=LENGTH, do_precession=True): mesh = df.IntervalMesh(node_count - 1, 0, length) S1 = df.FunctionSpace(mesh, "Lagrange", 1) S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3) llg = LLG(S1, S3) llg.set_m( np.array([initial_m(xi, node_count) for xi in xrange(node_count)]).T.reshape((-1, ))) exchange = Exchange(A) llg.effective_field.add(exchange) anis = UniaxialAnisotropy(K1, (0, 0, 1)) llg.effective_field.add(anis) llg.pins = [0, node_count - 1] return llg
def test_external_field_depends_on_t(): tfinal = 0.3 * 1e-9 dt = 0.001e-9 simplices = 2 L = 10e-9 mesh = df.IntervalMesh(simplices, 0, L) S1 = df.FunctionSpace(mesh, "Lagrange", 1) S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3) GHz = 1e9 omega = 100 * GHz llg = LLG(S1, S3) llg.set_m(df.Constant((1, 0, 0))) #This is the time dependent field H_app_expr = df.Expression(("0.0", "0.0", "H0*sin(omega*t)"), H0=1e5, omega=omega, t=0.0, degree=1) H_app = TimeZeeman(H_app_expr) Ms_field = Field(df.FunctionSpace(mesh, 'DG', 0), 8.6e5) H_app.setup(llg.m_field, Ms=Ms_field) #define function that updates that expression, and the field object def update_H_ext(t): print "update_H_ext being called for t=%g" % t H_app.update(t) llg.effective_field.add(H_app, with_time_update=update_H_ext) #nothing special from here, just setting up time integration integrator = llg_integrator(llg, llg.m_field) #to gather data for later analysis mlist = [] tlist = [] hext = [] #time loop times = np.linspace(0, tfinal, tfinal / dt + 1) for t in times: integrator.advance_time(t) print "Integrating time: %g" % t mlist.append(llg.m_average) tlist.append(t) hext.append(H_app.H((0))) #only plotting and data analysis from here on mx = [tmp[0] for tmp in mlist] my = [tmp[1] for tmp in mlist] mz = [tmp[2] for tmp in mlist] pylab.plot(tlist, mx, label='m_x') pylab.plot(tlist, my, label='m_y') pylab.plot(tlist, mz, label='m_z') pylab.xlabel('time [s]') pylab.legend() pylab.savefig(os.path.join(MODULE_DIR, 'results.png')) pylab.close() #if max_step is not provided, or chosen too large, #the external field appears not smooth in this plot. #What seems to happen is that the ode integrator #returns the solution without calling the rhs side again #if we request very small time steps. #This is only for debugging. pylab.plot(tlist, hext, '-x') pylab.ylabel('external field [A/m]') pylab.xlabel('time [s]') pylab.savefig(os.path.join(MODULE_DIR, 'hext.png')) pylab.close() #Then try to fit sinusoidal curve through results def sinusoidalfit(t, omega, phi, A, B): return A * np.cos(omega * t + phi) + B #if scipy available try: import scipy.optimize except ImportError: print "Couldn't import scipy.optimize, skipping test" else: popt, pcov = scipy.optimize.curve_fit(sinusoidalfit, np.array(tlist), np.array(my), p0=(omega * 1.04, 0., 0.1, 0.2)) #p0 is the set of parameters with which the fitting #routine starts print "popt=", popt fittedomega, fittedphi, fittedA, fittedB = popt f = open(os.path.join(MODULE_DIR, "fittedresults.txt"), "w") print >> f, "Fitted omega : %9g" % (fittedomega) print >> f, "Rel error in omega fit : %9g" % ( (fittedomega - omega) / omega) print >> f, "Fitted phi : %9f" % (fittedphi) print >> f, "Fitted Amplitude (A) : %9f" % (fittedA) print >> f, "Fitted Amp-offset (B) : %9f" % (fittedB) pylab.plot(tlist, my, label='my - simulated') pylab.plot(tlist, sinusoidalfit(np.array(tlist), *popt), '-x', label='m_y - fit') pylab.xlabel('time [s]') pylab.legend() pylab.savefig(os.path.join(MODULE_DIR, 'fit.png')) deviation = np.sqrt( sum((sinusoidalfit(np.array(tlist), *popt) - my)**2)) / len(tlist) print >> f, "stddev=%g" % deviation f.close() assert (fittedomega - omega) / omega < 1e-4 assert deviation < 5e-4
class Test(object): def __init__(self, mesh): self.mesh = mesh self.S1 = df.FunctionSpace(mesh, 'CG', 1) self.S3 = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3) #zero = df.Expression('0.3') m_init = df.Constant([1, 1, 1.0]) self.m = df.interpolate(m_init, self.S3) self.field = df.interpolate(m_init, self.S3) self.dmdt = df.interpolate(m_init, self.S3) self.spin = self.m.vector().array() self.t = 0 #It seems it's not safe to specify rank in df.interpolate??? self._alpha = df.interpolate(df.Constant("0.001"), self.S1) self._alpha.vector().set_local(self._alpha.vector().array()) print 'dolfin', self._alpha.vector().array() self.llg = LLG(self.S1, self.S3, unit_length=1e-9) #normalise doesn't work due to the wrong order self.llg.set_m(m_init, normalise=True) parameters = { 'absolute_tolerance': 1e-10, 'relative_tolerance': 1e-10, 'maximum_iterations': int(1e5) } demag = Demag() demag.parameters['phi_1'] = parameters demag.parameters['phi_2'] = parameters self.exchange = Exchange(13e-12) self.zeeman = Zeeman([0, 0, 1e5]) self.llg.effective_field.add(self.exchange) #self.llg.effective_field.add(demag) self.llg.effective_field.add(self.zeeman) self.m_petsc = df.as_backend_type(self.llg.m_field.f.vector()).vec() self.h_petsc = df.as_backend_type(self.field.vector()).vec() self.alpha_petsc = df.as_backend_type(self._alpha.vector()).vec() self.dmdt_petsc = df.as_backend_type(self.dmdt.vector()).vec() alpha = 0.001 gamma = 2.21e5 LLG1 = -gamma / (1 + alpha * alpha) * df.cross( self.m, self.field) - alpha * gamma / (1 + alpha * alpha) * df.cross( self.m, df.cross(self.m, self.field)) self.L = df.dot(LLG1, df.TestFunction(self.S3)) * df.dP def set_up_solver(self, rtol=1e-8, atol=1e-8): self.ode = cvode2.CvodeSolver(self.sundials_rhs, 0, self.m_petsc, rtol, atol) def sundials_rhs(self, t, y, ydot): self.llg.effective_field.update(t) self.field.vector().set_local(self.llg.effective_field.H_eff) #print y, self.h_petsc, self.m_petsc y.copy(self.m_petsc) df.assemble(self.L, tensor=self.dmdt.vector()) self.dmdt_petsc.copy(ydot) """ #llg_petsc.compute_dm_dt(y, self.h_petsc, ydot, self.alpha_petsc, self.llg.gamma, self.llg.do_precession, self.llg.c) """ return 0 def run_until(self, t): if t <= self.t: ode = self.ode self.spin = self.m.vector().array() return ode = self.ode flag = ode.run_until(t) if flag < 0: raise Exception("Run cython run_until failed!!!") self.m.vector().set_local(ode.y_np) self.spin = self.m.vector().array()
def run_simulation(): """ Translation of the nmag code. Mesh generated on the fly. """ x0 = 0 x1 = 15e-9 nx = 30 y0 = -4.5e-9 y1 = 4.5e-9 ny = 18 z0 = -0.1e-9 z1 = 0.1e-9 nz = 1 mesh = df.BoxMesh(df.Point(x0, y0, z0), df.Point(x1, y1, z1), nx, ny, nz) S1 = df.FunctionSpace(mesh, "Lagrange", 1) S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3) nb_nodes = len(mesh.coordinates()) llg = LLG(S1, S3) llg.Ms = 1e6 llg.set_alpha(0.02) exchange = Exchange(1.3e-11) llg.effective_field.add(exchange) llg.set_m(("1", "5 * pow(cos(pi * (x[0] * pow(10, 9) - 11) / 6), 3) \ * pow(cos(pi * x[1] * pow(10, 9) / 6), 3)", "0")) m = llg.m_numpy for i in xrange(nb_nodes): x, y, z = mesh.coordinates()[i] mx = 1 my = 0 mz = 0 if 8e-9 < x < 14e-9 and -3e-9 < y < 3e-9: pass else: m[i] = mx m[i + nb_nodes] = my m[i + 2 * nb_nodes] = mz llg.m_field.set_with_numpy_array_debug(m) llg_wrap = lambda t, y: llg.solve_for(y, t) t0 = 0 dt = 0.05e-12 t1 = 10e-12 r = ode(llg_wrap).set_integrator( "vode", method="bdf", rtol=1e-5, atol=1e-5) r.set_initial_value(llg.m_numpy, t0) fh = open(os.path.join(MODULE_DIR, "averages.txt"), "w") while r.successful() and r.t <= t1: mx, my, mz = llg.m_average fh.write( str(r.t) + " " + str(mx) + " " + str(my) + " " + str(mz) + "\n") r.integrate(r.t + dt) fh.close()
def __init__(self, S1, S3): LLG.__init__(self, S1, S3) self.alpha = 0.5 self.p = Constant(self.gamma / (1 + self.alpha ** 2))
import dolfin import numpy from scipy.integrate import odeint from finmag.physics.llg import LLG """ Compute the behaviour of a one-dimensional strip of magnetic material, with exchange interaction. """ length = 40e-9 # in meters simplexes = 10 mesh = dolfin.Interval(simplexes, 0, length) llg = LLG(mesh) llg.H_app = (0, 0, llg.Ms) llg.set_alpha(0.1) llg.set_m(('1', '0', '0')) llg.setup() #llg.pins = [0, 10] print "Solving problem..." import visual y = llg.m[:] y.shape = (3, len(llg.m) / 3) arrows = [] coordinates = (mesh.coordinates() / length - 0.5) * len( mesh.coordinates()) * 0.4 for i in range(y.shape[1]):
import dolfin as df from finmag.physics.llg import LLG x0 = 0 x1 = 100e-9 xn = 50 y0 = 0 y1 = 10e-9 yn = 5 nanowire = df.RectangleMesh(df.Point(x0, y0), df.Point(x1, y1), xn, yn, "left/right") S1 = df.FunctionSpace(nanowire, "Lagrange", 1) S3 = df.VectorFunctionSpace(nanowire, "Lagrange", 1, dim=3) llg = LLG(S1, S3) """ We want to increase the damping at the boundary of the object. It is convenient to channel the power of dolfin expressions for this task. """ alpha_expression = df.Expression("(x[0] > x_limit) ? 1.0 : 0.5", x_limit=80e-9, degree=1) llg.set_alpha(alpha_expression) print "alpha vector:\n", llg.alpha.vector().array() df.plot(llg.alpha, interactive=True)
""" Compute the behaviour of a one-dimensional strip of magnetic material, with exchange interaction. """ A = 1.3e-11 Ms = 8.6e5 length = 20e-9 # in meters simplexes = 10 mesh = dolfin.Interval(simplexes, 0, length) S1 = dolfin.FunctionSpace(mesh, "Lagrange", 1) S3 = dolfin.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3) llg = LLG(S1, S3) llg.set_m(('2*x[0]/L - 1', 'sqrt(1 - (2*x[0]/L - 1)*(2*x[0]/L - 1))', '0'), L=length) llg.pins = [0, 10] exchange = Exchange(A) llg.effective_field.add(exchange) print "Solving problem..." ts = numpy.linspace(0, 1e-9, 10) ys, infodict = odeint(llg.solve_for, llg.m, ts, full_output=True) print "Used", infodict["nfe"][-1], "function evaluations." print "Saving data..." numpy.savetxt("1d_times.txt", ts)