def test_anisotropy_energy_analytical(fixt): """ Compare one UniaxialAnisotropy energy with the corresponding analytical result. The magnetisation is m = (0, sqrt(1 - x^2), x) and the easy axis still a = (0, 0, 1). The squared dot product in the energy integral thus gives dot(a, m)^2 = x^2. Integrating x^2 gives (x^3)/3 and the analytical result with the constants we have chosen is 1 - 1/3 = 2/3. """ mesh = df.UnitCubeMesh(1, 1, 1) functionspace = df.VectorFunctionSpace(mesh, "Lagrange", 1) K1 = 1 Ms = Field(df.FunctionSpace(mesh, 'DG', 0), 1) a = df.Constant((0, 0, 1)) m = Field(functionspace) m.set(df.Expression(("0", "sqrt(1 - pow(x[0], 2))", "x[0]"), degree=1)) anis = UniaxialAnisotropy(K1, a) anis.setup(m, Ms) E = anis.compute_energy() expected_E = float(2) / 3 print "With m = (0, sqrt(1-x^2), x), expecting E = {}. Got E = {}.".format( expected_E, E) #assert abs(E - expected_E) < TOLERANCE assert np.allclose(E, expected_E, atol=1e-14, rtol=TOLERANCE)
def test_anisotropy_field_supported_methods(fixt): """ Check that all supported methods give the same results as the default method. """ TOLERANCE = 1e-13 fixt["m"].set(df.Constant((1 / np.sqrt(2), 0, 1 / np.sqrt(2)))) H_default = fixt["anis"].compute_field() supported_methods = list(UniaxialAnisotropy._supported_methods) # No need to compare default method with itself. supported_methods.remove(fixt["anis"].method) for method in supported_methods: anis = UniaxialAnisotropy(fixt["K1"], fixt["a"], method=method) anis.setup(fixt["m"], fixt["Ms"]) H = anis.compute_field() print( textwrap.dedent(""" With method '{}', expecting: H = {}, got: H = {}. """.format(method, H_default.reshape((3, -1)).mean(axis=1), H.reshape((3, -1)).mean(axis=1)))) assert np.allclose(H, H_default, atol=0, rtol=TOLERANCE)
def compute_finmag_anis(m_gen, Ms, K1, axis, dolfin_mesh): S3 = df.VectorFunctionSpace(dolfin_mesh, "Lagrange", 1, dim=3) coords = np.array(zip(*dolfin_mesh.coordinates())) m0 = m_gen(coords).flatten() m = Field(S3) m.set_with_numpy_array_debug(m0) anis = UniaxialAnisotropy(K1, axis) anis.setup(m, Field(df.FunctionSpace(dolfin_mesh, 'DG', 0), Ms)) anis_field = df.Function(S3) anis_field.vector()[:] = anis.compute_field() return anis_field
def fixt(): """ Create an UniaxialAnisotropy object that will be re-used during testing. """ mesh = df.UnitCubeMesh(1, 1, 1) functionspace = df.VectorFunctionSpace(mesh, "Lagrange", 1) K1 = 1 Ms = Field(df.FunctionSpace(mesh, 'DG', 0), 1) a = df.Constant((0, 0, 1)) m = Field(functionspace) anis = UniaxialAnisotropy(K1, a) anis.setup(m, Ms) return {"anis": anis, "m": m, "a": a, "Ms": Ms, "K1": K1}
def setup(K2=K2): print "Running finmag..." mesh = from_geofile(os.path.join(MODULE_DIR, "bar.geo")) coords = np.array(zip(*mesh.coordinates())) S3 = df.VectorFunctionSpace(mesh, "Lagrange", 1, dim=3) m = Field(S3) m.set_with_numpy_array_debug(m_gen(coords).flatten()) S1 = df.FunctionSpace(mesh, "Lagrange", 1) Ms_cg = Field(df.FunctionSpace(mesh, 'CG', 1), Ms) anisotropy = UniaxialAnisotropy(K1, u1, K2=K2) anisotropy.setup(m, Ms_cg, unit_length=1e-9) H_anis = df.Function(S3) H_anis.vector()[:] = anisotropy.compute_field() return dict(m=m, H=H_anis, S3=S3, table=start_table())
def test_anisotropy_energy_simple_configurations(fixt, m, expected_E): """ Test some parallel and orthogonal configurations of m and a. """ mesh = df.UnitCubeMesh(1, 1, 1) functionspace = df.VectorFunctionSpace(mesh, "Lagrange", 1) K1 = 1 Ms = Field(df.FunctionSpace(mesh, 'DG', 0), 1) a = df.Constant((0, 0, 1)) m_field = Field(functionspace) m_field.set(df.Constant(m)) anis = UniaxialAnisotropy(K1, a) anis.setup(m_field, Ms) E = anis.compute_energy() print "With m = {}, expecting E = {}. Got E = {}.".format(m, expected_E, E) #assert abs(E - expected_E) < TOLERANCE assert np.allclose(E, expected_E, atol=1e-14, rtol=TOLERANCE)
def test_anisotropy_energy_density(): """ Written in sperical coordinates, the equation for the anisotropy energy density reads E/V = K*sin^2(theta), where theta is the angle between the magnetisation and the easy axis. With a magnetisation pointing 45 degrees between the x- and z-axis, and using the z-axis as the easy axis, theta becomes pi/4. sin^2(pi/4) evaluates to 1/2, and with K set to 1 in this simple test case, we expect the energy density to be 1/2 at every node. """ # 5 simplices between 0 and 1 nm. mesh = df.IntervalMesh(5, 0, 1e-9) V = df.VectorFunctionSpace(mesh, "CG", 1, dim=3) # Initial magnetisation 45 degress between x- and z-axis. m_vec = df.Constant((1 / np.sqrt(2), 0, 1 / np.sqrt(2))) m = Field(V, value=m_vec) # Easy axis in z-direction. a = df.Constant((0, 0, 1)) # These are 1 just to simplify the analytical solution. K = 1 Ms = 1 anis = UniaxialAnisotropy(K, a) anis.setup(m, Field(df.FunctionSpace(mesh, 'DG', 0), Ms)) density = anis.energy_density() deviation = np.abs(density - 0.5) print "Anisotropy energy density (expect array of 0.5):" print density print "Max deviation: %g" % np.max(deviation) assert np.all(deviation < TOL), \ "Max deviation %g, should be zero." % np.max(deviation)