<jupyter_start><jupyter_text>Relaxation of two coupled nanodisks **Author**: <NAME>**Date**: Jan 2013**Purpose**: This notebook illustrates a typical relaxation. It uses a mesh consisting of two separated nanodisks and also shows how such a mesh can be produced by writing a `.geo` file directly from the code. --- In this simulation we explore the relaxation behaviour of two nanodisks which are separated by a small distance. The initial magnetisation in each disk is uniform, but with a different (random) direction for each of them. We hope to see some kind of interaction so that ideally in the final relaxed state the magnetisation in the two disks is aligned along the common axis (due to the magnetostatic interaction). First we import all the relevant modules and functions. We also change the logging level from the default 'DEBUG' to 'INFO' to avoid cluttering the notebook with lots of debugging message.<jupyter_code>from paraview import servermanager
from finmag.util.meshes import from_geofile, plot_mesh, plot_mesh_with_paraview
from finmag import sim_with
from finmag.util.helpers import vector_valued_function
from finmag.util.visualization import render_paraview_scene
import finmag
import numpy as np
finmag.set_logging_level("INFO")<jupyter_output>[2014-06-09 18:43:58] INFO: Finmag logging output will be appended to file: '/home/albert/.finmag/global.log'
[2014-06-09 18:43:58] DEBUG: Building modules in 'native'...
[2014-06-09 18:43:59] DEBUG: FinMag          5047:e8225c1b7a79ea431efa470d26532258c63bb6ef
[2014-06-09 18:43:59] DEBUG: Dolfin          1.4.0                Matplotlib      1.3.1               
[2014-06-09 18:43:59] DEBUG: Numpy           1.8.1                Scipy           0.12.0              
[2014-06-09 18:43:59] DEBUG: IPython         2.1.0                Python          2.7.5+              
[2014-06-09 18:43:59] DEBUG: Paraview        4.0.1-1              Sundials        2.5.0               
[2014-06-09 18:43:59] DEBUG: Boost-Python    <unknown>            Linux           Linux Mint 16 Petra 
[2014-06-09 18:43:59] DEBUG: Registering debug signal handler. Press Ctrl-Z at any time to stop execution and jump into the debugger.<jupyter_text>First we set the parameters which define the geometry, such as the disk radius/height and their separation. The two disks are put on the positive and negative x-axis with equal distances to the origin.<jupyter_code># Geometry parameters:

r = 25      # disk radius
h = 10      # disk height
s = 30      # distance from the origin to the center of each disk
maxh = 3.0  # mesh discretisation
unit_length = 1e-9  # the mesh units are given in nm

assert(s > r)  # Disk separation should be greater than the radius<jupyter_output><empty_output><jupyter_text>Next we set the material parameters for Permalloy and define the initial magnetisations for each disk.<jupyter_code># Material parameters
Ms = 8.6e5
A = 13.0e-12
alpha = 1.0
m_init_1 = np.array([-0.7, 0.1, 0.1])  # m_init for first disk
m_init_2 = np.array([0.6, 0.2, -0.2])  # m_init for second disk
demag_solver = 'FK'<jupyter_output><empty_output><jupyter_text>We also define some helper strings used in filename, directory names etc., which make it easier to distinguish between simulations with different parameters.<jupyter_code>geom_descr = "r_{:05.1f}__h_{:05.1f}__s_{:05.1f}__maxh_{:04.1f}".format(r, h, s, maxh)
sim_descr = "sim_{}__m_init_1_{:03.1f}_{:03.1f}_{:03.1f}__m_init_2_{:03.1f}_{:03.1f}_{:03.1f}".format(
                geom_descr, m_init_1[0], m_init_1[1], m_init_1[2], m_init_2[0], m_init_2[1], m_init_2[2])
print "geom_descr: {}".format(geom_descr)
print "sim_descr: {}".format(sim_descr)<jupyter_output>geom_descr: r_025.0__h_010.0__s_030.0__maxh_03.0
sim_descr: sim_r_025.0__h_010.0__s_030.0__maxh_03.0__m_init_1_-0.7_0.1_0.1__m_init_2_0.6_0.2_-0.2<jupyter_text>Now we create the mesh and load it. Since we would like to be able to change parameters, we write a CSG description of the mesh geometry here interactively and write it to a .geo file, which is then loaded.<jupyter_code>import textwrap
import os

meshfilename = os.path.join("meshes", "mesh__{}.geo".format(geom_descr))
if not os.path.exists(meshfilename):
    # Interactively write the mesh file from here so that we
    # can adapt the geometry parameters from this notebook.

    if not os.path.exists("meshes"):
        os.mkdir('meshes')

    csg = textwrap.dedent("""\
        algebraic3d

        solid disk1 = cylinder (-{s}, 0, 1; -{s}, 0, -1; {r} )
              and plane (0, 0, 0; 0, 0, -1)
              and plane (0, 0, {h}; 0, 0, 1) -maxh = {maxh};

        solid disk2 = cylinder ({s}, 0, 1; {s}, 0, -1; {r} )
              and plane (0, 0, 0; 0, 0, -1)
              and plane (0, 0, {h}; 0, 0, 1) -maxh = {maxh};

        tlo disk1;
        tlo disk2;
        """.format(s=s, r=r, h=h, maxh=maxh))

    with open(meshfilename, "w") as f:
        f.write(csg)

mesh = from_geofile(meshfilename)<jupyter_output>[2014-06-09 18:44:11] WARNING: Warning: Ignoring netgen's output status of 34304.<jupyter_text>Plot the mesh to be sure that it looks ok. Unfortunately, matplotlib doesn't support equal aspect ratios for 3D plots (yet), but the axes labels indicate that the disks have the correct proportions.<jupyter_code>plot_mesh(mesh, figsize=(10, 5))<jupyter_output><empty_output><jupyter_text>Alternatively, we can plot the mesh using Paraview.<jupyter_code>plot_mesh_with_paraview(mesh)<jupyter_output><empty_output><jupyter_text>Now we actually set the initial magnetisation in the two disks. Since m_init is different in each of the disks, this is done via a function that distinguishes the mesh points in each disk according to their x-coordinate.<jupyter_code>def fun_m_init(pt):
    if pt[0] < 0:
        return m_init_1
    else:
        return m_init_2

m_init = vector_valued_function(fun_m_init, mesh)<jupyter_output><empty_output><jupyter_text>Now create the Simulation object (with the mesh and material parameters defined above).<jupyter_code>sim = sim_with(mesh, Ms=Ms, m_init=m_init, alpha=alpha,
               unit_length=unit_length, A=A,
               demag_solver=demag_solver,
               name="sim_01__relaxation_of_two_nanodisks")<jupyter_output>[2014-06-09 18:44:54] INFO: Finmag logging output will be written to file: '/home/albert/work/code/finmag/doc/ipython_notebooks_src/sim_01__relaxation_of_two_nanodisks.log' (any old content will be overwritten).
[2014-06-09 18:44:54] INFO: Creating Sim object 'sim_01__relaxation_of_two_nanodisks' (rank=0/1).
[2014-06-09 18:44:54] INFO: <Mesh of topological dimension 3 (tetrahedra) with 1973 vertices and 7295 cells, ordered><jupyter_text>... and relax the configuration. While doing so, we save vtk snapshots of the magnetisation configuration every 50 ps for later analysis. Since the simulation takes a few mintes to finish, we also print a message every 0.5 ns (of simulation time) to keep us informed about the progress (note that this would not be necessary if we had used the 'DEBUG' logging level above, but it is also a nice illustration of how to use the scheduler for these purposes).<jupyter_code>def print_simulation_time(sim):
    finmag.logger.info("Reached simulation time: {} ns".format(sim.t * 1e9))

sim.schedule(print_simulation_time, every=0.5e-9)
sim.schedule('save_vtk', filename='snapshots/{}/relaxation.pvd'.format(sim_descr), every=5e-11, overwrite=True)
sim.relax()<jupyter_output>[2014-06-09 18:45:00] INFO: Create integrator sundials with kwargs={}
[2014-06-09 18:45:00] INFO: Simulation will run until relaxation of the magnetisation.
[2014-06-09 18:45:00] INFO: Reached simulation time: 0.0 ns
[2014-06-09 18:45:13] INFO: Reached simulation time: 0.5 ns
[2014-06-09 18:45:20] INFO: Reached simulation time: 1.0 ns
[2014-06-09 18:45:26] INFO: Reached simulation time: 1.5 ns
[2014-06-09 18:45:32] INFO: Reached simulation time: 2.0 ns
[2014-06-09 18:45:38] INFO: Reached simulation time: 2.5 ns
[2014-06-09 18:45:41] INFO: Relaxation finished at time t = 2.8e-09.<jupyter_text>Here is an image of the initial state. It shows that each disk has uniform magnetisation but they point in different directions, as specified by `m_init_1` and `m_init_2`.<jupyter_code>render_paraview_scene('snapshots/{}/relaxation.pvd'.format(sim_descr),
                      timesteps=0, color_by_axis='X', view_size=(1000, 800))<jupyter_output><empty_output><jupyter_text>And this is an image of the relaxed state. It clearly shows how the magnetisation in the two disks is now aligned due the magnetostatic interaction.<jupyter_code>render_paraview_scene('snapshots/{}/relaxation.pvd'.format(sim_descr),
                      timesteps=42, color_by_axis='Y', view_size=(1000, 800))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10135984458918981, 'fraction_numerical': 0.06890641069592046, 'mean_word_length': 4.026995979322229, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '621858', 'license': 'BSL-1.0', 'n_tokens_mistral': 3305, 'n_tokens_neox': 2898, 'n_words': 948, 'path': 'doc/ipython_notebooks_src/tutorial-coupled-relaxation-of-two-nanodisks.ipynb', 'repo_name': 'davidcortesortuno/finmag', 'size': '8762'}