def test_dmi_field(): """ Simulation 1 is computing H_dmi=dE_dM via assemble. Simulation 2 is computing H_dmi=g*M with a suitable pre-computed matrix g. Simulation 3 is computing g using a petsc matrix. We show that the three methods give equivalent results (this relies on H_dmi being linear in M). """ m_initial = df.Expression( ('(2*x[0]-L)/L', 'sqrt(1 - ((2*x[0]-L)/L)*((2*x[0]-L)/L))', '0'), L=length, degree=1) m = Field(V) m.set(m_initial) dmi1 = DMI(D=5e-3, method="box-assemble") dmi1.setup(m, Field(df.FunctionSpace(mesh, 'DG', 0), 8.6e5)) dmi2 = DMI(D=5e-3, method="box-matrix-numpy") dmi2.setup(m, Field(df.FunctionSpace(mesh, 'DG', 0), 8.6e5)) dmi3 = DMI(D=5e-3, method="box-matrix-petsc") dmi3.setup(m, Field(df.FunctionSpace(mesh, 'DG', 0), 8.6e5)) H_dmi1 = dmi1.compute_field() H_dmi2 = dmi2.compute_field() H_dmi3 = dmi3.compute_field() diff12 = np.max(np.abs(H_dmi1 - H_dmi2)) diff13 = np.max(np.abs(H_dmi1 - H_dmi3)) print "Difference between H_dmi1 and H_dmi2: max(abs(H_dmi1-H_dmi2))=%g" % diff12 print "Max value = %g, relative error = %g " % (max(H_dmi1), diff12 / max(H_dmi1)) print "Difference between H_dmi1 and H_dmi3: max(abs(H_dmi1-H_dmi3))=%g" % diff13 print "Max value = %g, relative error = %g " % (max(H_dmi1), diff13 / max(H_dmi1)) assert diff12 < 5e-8 assert diff13 < 5e-8 assert diff12 / max(H_dmi1) < 1e-14 assert diff13 / max(H_dmi1) < 1e-14
def test_dmi_uses_unit_length_2dmesh(): """ Set up a helical state in two meshes (one expressed in SI units the other expressed in nanometers) and compute energies and fields. """ A = 8.78e-12 # J/m D = 1.58e-3 # J/m^2 Ms = 3.84e5 # A/m energies = [] # unit_lengths 1e-9 and 1 are common, let's throw in an intermediate length # just to challenge the system a little: for unit_length in (1, 1e-4, 1e-9): radius = 200e-9 / unit_length maxh = 5e-9 / unit_length helical_period = (4 * pi * A / D) / unit_length k = 2 * pi / helical_period # HF 27 April 2014: The next command fails in dolfin 1.3 # mesh = df.CircleMesh(df.Point(0, 0), radius, maxh) # The actual shape of the domain shouldn't matter for the test, # so let's use a Rectangular mesh which should work the same: nx = ny = int(round(radius / maxh)) mesh = df.RectangleMesh(df.Point(0, 0), df.Point(radius, radius), nx, ny) S3 = df.VectorFunctionSpace(mesh, "CG", 1, dim=3) m_expr = df.Expression(("0", "cos(k * x[0])", "sin(k * x[0])"), k=k, degree=1) m = Field(S3, m_expr, name='m') dmi = DMI(D) Ms_dg = Field(df.FunctionSpace(mesh, 'DG', 0), Ms) dmi.setup(m, Ms_dg, unit_length=unit_length) energies.append(dmi.compute_energy()) H = df.Function(S3) H.vector()[:] = dmi.compute_field() print H(0.0, 0.0) print "Using unit_length = {}.".format(unit_length) print "Helical period {}.".format(helical_period) print "Energy {}.".format(dmi.compute_energy()) rel_diff_energies = abs(energies[0] - energies[1]) / abs(energies[1]) print "Relative difference of energy {}.".format(rel_diff_energies) assert rel_diff_energies < 1e-13 rel_diff_energies2 = abs(energies[0] - energies[2]) / abs(energies[2]) print "Relative difference2 of energy {}.".format(rel_diff_energies2) assert rel_diff_energies2 < 1e-13
def test_dmi_pbc2d(): mesh = df.BoxMesh(df.Point(0, 0, 0), df.Point(1, 1, 0.1), 2, 2, 1) pbc = PeriodicBoundary2D(mesh) S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, constrained_domain=pbc) m_expr = df.Expression(("0", "0", "1"), degree=1) m = Field(S3, m_expr, name='m') dmi = DMI(1) dmi.setup(m, Field(df.FunctionSpace(mesh, 'DG', 0), 1)) field = dmi.compute_field() assert np.max(field) < 1e-15
def run_finmag(): sim = Sim(mesh, Ms, unit_length=unit_length) sim.alpha = 0.5 sim.set_m(init_m) exchange = Exchange(13.0e-12) sim.add(exchange) dmi = DMI(4e-3) sim.add(dmi) dmi_direct = DMI(4e-3, method='direct', name='dmi_direct') sim.add(dmi_direct) df.plot(sim.m_field.f, title='m') fun = df.interpolate(HelperExpression(), sim.S3) df.plot(fun, title='exact') df.plot(Field(sim.S3, dmi.compute_field()).f, title='dmi_petsc') df.plot(Field(sim.S3, dmi_direct.compute_field()).f, title='dmi_direct', interactive=True)