Multiple energy terms of the same class#

Here we demonstrate how to define multiple energy terms of the same class in the energy equation. For the sample, we choose a one-dimensional chain of magnetic moments.

[1]:
import random
import oommfc as mc
import discretisedfield as df
import micromagneticmodel as mm

p1 = (-10e-9, 0, 0)
p2 = (10e-9, 1e-9, 1e-9)
cell = (1e-9, 1e-9, 1e-9)
region = df.Region(p1=p1, p2=p2)
mesh = df.Mesh(region=region, cell=cell)

The mesh is

[2]:
mesh.mpl(box_aspect=(10, 4, 4), figsize=(8, 8))
../../_images/examples_notebooks_multiple-terms_3_0.png

Let us say that the system has an energy equation, which consists of two Zeeman energy terms.

[3]:
H1 = (0, 0, 1e6)
H2 = (1e6, 0, 0)

system = mm.System(name="multiple_terms")

Now, if we try to add two Zeeman energy terms, we get an exception raised.

[4]:
system.energy = mm.Zeeman(H=(0, 0, 1e5)) + mm.Zeeman(H=(0, 1e5, 0))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[4], line 1
----> 1 system.energy = mm.Zeeman(H=(0, 0, 1e5)) + mm.Zeeman(H=(0, 1e5, 0))

File ~/repos/ubermag-devtools/repos/micromagneticmodel/micromagneticmodel/abstract/term.py:115, in Term.__add__(self, other)
    113 result = getattr(mm, self._container_class)()
    114 result += self
--> 115 result += other
    116 return result

File ~/repos/ubermag-devtools/repos/micromagneticmodel/micromagneticmodel/abstract/container.py:378, in Container.__add__(self, other)
    369 if any(
    370     isinstance(other, term.__class__) and other.name == term.name
    371     for term in self._terms
    372 ):
    373     msg = (
    374         f"There is already a term of type {other.__class__} with  name "
    375         f"'{other.name}' in {self.__class__}. Please provide a different "
    376         f"name for {other}."
    377     )
--> 378     raise ValueError(msg)
    379 else:
    380     result._terms.append(other)

ValueError: There is already a term of type <class 'micromagneticmodel.energy.zeeman.Zeeman'> with  name 'zeeman' in <class 'micromagneticmodel.energy.energy.Energy'>. Please provide a different name for Zeeman(H=(0, 100000.0, 0)).

This is because different energy terms must have different names, so they can be uniquely identified. So, we have to give names to our energy terms:

[5]:
system.energy = mm.Zeeman(H=H1, name="zeeman1") + mm.Zeeman(H=H2, name="zeeman2")

We need to define the system’s magnetisation (system.m). We are going to make it random with \(M_\text{s}=8\times10^{5} \,\text{Am}^{-1}\)

[6]:
random.seed(1)

Ms = 8e5  # saturation magnetisation (A/m)


def m_fun(pos):
    return [2 * random.random() - 1 for i in range(3)]


system.m = df.Field(mesh, nvdim=3, value=m_fun, norm=Ms)

Now, we can minimise the system’s energy:

[7]:
md = mc.MinDriver()
md.drive(system)
Running OOMMF (ExeOOMMFRunner)[2023/10/23 16:08]... (0.4 s)

We expect that now all magnetic moments are aligned parallel or antiparallel to the anisotropy axis (in the \(z\)-direction).

[8]:
system.m.sel("y").mpl(
    figsize=(10, 3), scalar_kw={"clim": [-0.1, 0.1], "colorbar_label": "$m_y$"}
)
../../_images/examples_notebooks_multiple-terms_15_0.png

We can see that magnetisation is aligned with the sum of fields H1+H2. Finally, let us have a look at the table:

[9]:
system.table.data
[9]:
max_mxHxm E delta_E bracket_count line_min_count conjugate_cycle_count cycle_count cycle_sub_count energy_calc_count E_zeeman_zeeman1 E_zeeman_zeeman2 iteration stage_iteration stage mx my mz
0 0.003228 -2.843445e-20 -7.222237e-35 27.0 5.0 21.0 23.0 2.0 33.0 -1.421723e-20 -1.421723e-20 30.0 30.0 0.0 0.707107 9.445158e-11 0.707107

We can see that energy terms are marked with the names we gave to energy terms when we defined the energy equation.