├── fidimag
├── extensions
│ ├── __init__.py
│ └── user
│ │ └── __init__.py
├── atomistic
│ ├── test.txt
│ ├── lib
│ │ ├── fmmlib
│ │ │ ├── utils.hpp
│ │ │ ├── utils.cpp
│ │ │ ├── tree.hpp
│ │ │ ├── fmmlib.pyx
│ │ │ └── calculate.hpp
│ │ ├── fidimag_random.h
│ │ └── sllg.c
│ ├── __init__.py
│ ├── fmmlib
│ │ ├── example.py
│ │ ├── utils.cpp
│ │ ├── utils.hpp
│ │ └── calculate.hpp
│ ├── field.py
│ ├── materials.py
│ ├── exchange_new.py
│ ├── energy.py
│ ├── demag_full.py
│ └── llg.py
├── user
│ ├── example
│ │ ├── __init__.py
│ │ └── example.pyx
│ └── README.md
├── common
│ ├── __init__.py
│ ├── constant.py
│ ├── neb_method
│ │ ├── nebm_spherical_lib.h
│ │ ├── nebm_integrators.h
│ │ ├── nebm_geodesic_lib.h
│ │ └── nebm_integrators.c
│ ├── citation.py
│ ├── sim2fdfield.py
│ ├── field.py
│ ├── helper.py
│ ├── save_vtk.py
│ ├── vtk.py
│ └── dipolar
│ │ └── license.txt
├── micro
│ ├── __init__.py
│ ├── simple_demag.py
│ ├── lib
│ │ ├── baryakhtar
│ │ │ └── baryakhtar_clib.h
│ │ └── micro_clib.h
│ ├── energy.py
│ ├── exchange.py
│ ├── relax.py
│ └── exchange_rkky.py
└── __init__.py
├── bin
├── install-python-packages.sh
├── install-ubuntu-packages.sh
├── install-scikit-odes.sh
├── ubuntu_install_script.sh
├── fix_load_path_mac.py
├── install-fftw.sh
└── install-sundials.sh
├── pytest.ini
├── doc
├── images
│ ├── nebm.png
│ ├── nebm_classes.png
│ ├── bobber_toron_vis.png
│ └── 2d-lattice-triagonal.pdf
├── user_guide
│ ├── ipynb
│ │ ├── sanitize_file
│ │ └── runtimes.org
│ └── index.rst
├── environment.yml
├── _templates
│ └── custom-template.html
├── physics_num_methods
│ ├── index.rst
│ └── monte_carlo.rst
├── index.rst
└── todo.org
├── examples
├── micromagnetic
│ ├── std4
│ │ └── res.pdf
│ ├── skyrmion_stt
│ │ ├── m0.npy
│ │ └── main.py
│ ├── nmag_example_2_box
│ │ ├── sim.py
│ │ └── plot.py
│ ├── pbc_2d
│ │ ├── single_cube.py
│ │ ├── rod.py
│ │ └── main.py
│ ├── PRB_88_184422
│ │ ├── oommf
│ │ │ └── dmi.mif
│ │ └── plot.py
│ ├── baryakhtar
│ │ └── relax_system.py
│ ├── spatial_dmi
│ │ └── main.py
│ ├── skyrmion
│ │ ├── main.py
│ │ └── Ku_H
│ │ │ └── main.py
│ ├── vortex_oommf
│ │ ├── relax.mif
│ │ └── dyn
│ │ │ └── dyn.mif
│ ├── std4_oommf
│ │ └── stdprob4.mif
│ └── single_spin
│ │ └── single_spin.py
├── atomistic
│ ├── skyrmion
│ │ └── skx_rotation
│ │ │ ├── m_z_backup.png
│ │ │ └── deal_m.py
│ ├── dmi
│ │ ├── dmi_1d.py
│ │ ├── dmi_2d.py
│ │ └── interfacial_dmi_dw
│ │ │ └── dw.py
│ ├── PRL_111_067203
│ │ └── phase_res
│ │ │ └── plot.py
│ ├── heat
│ │ ├── macrospin.py
│ │ ├── compute_energy.py
│ │ ├── dw-heat.py
│ │ └── temperature.py
│ ├── dynamic_spectrum
│ │ └── plot_results.py
│ ├── PRL_108_017601
│ │ ├── figure1.py
│ │ └── figure2.py
│ ├── dw_demag
│ │ └── dw_demag.py
│ ├── dw_field
│ │ └── dw-field.py
│ ├── stt
│ │ ├── single_spin_stt.py
│ │ └── stt.py
│ ├── skyrmion_demag
│ │ └── single_ku.py
│ ├── demag_field
│ │ └── demag_field.py
│ └── sw.py
├── neb_micromagnetic
│ ├── skyrmion
│ │ ├── results
│ │ │ └── energy_167.pdf
│ │ ├── plot.py
│ │ └── relaxation
│ │ │ ├── skyrmion_down_relax.py
│ │ │ └── skyrmion_relax.py
│ └── domain_wall
│ │ └── dw.py
├── mc
│ └── skx.py
├── eigen
│ └── skx.py
└── nebm_atomistic
│ ├── 1D_spin_chain
│ └── relaxation
│ │ ├── 1D_spin_chain_fm.py
│ │ └── 1D_spin_chain.py
│ └── skyrmion_reduced
│ └── relax.py
├── tests
├── omfs
│ ├── test_dmi_field_oommf.ohf
│ ├── test_exch_field_oommf.ohf
│ ├── test_with_oommf_spatial_Ms_Demag.ohf
│ ├── test_demag_field_oommf_large_Demag.ohf
│ ├── test_with_oommf_spatial_Ms_Exchange.ohf
│ ├── test_demag_field_oommf_large_Exchange.ohf
│ └── dmi-Oxs_TimeDriver-Magnetization-00-0000963.omf
├── mini_test.py
├── __init__.py
├── conftest.py
├── test_citation.py
├── test_imports.py
├── field_test.py
├── vtk_refs
│ ├── save_scalar_000000.vtk
│ ├── save_vector_000000.vtk
│ └── scalar_hexagonal_000000.vtk
├── test_init_scalar.py
├── test_mesh.py
├── test_llg_raises_error.py
├── test_init_vector.py
├── test_atomistic_zeeman.py
├── test_regression_init_scalar.py
├── test_time_zeeman.py
├── test_add_remove_interaction.py
├── test_2dpbc_cube.py
├── test_anis.py
├── test_check_ms_inv_sensible.py
├── test_spatial_exch.py
├── test_stt_slonczewski.py
├── test_demag.py
├── test_monte_carlo.py
├── test_vtk_writing.py
├── test_exch_rkky.py
├── test_dw_dmi.py
├── test_hubert_minimiser.py
└── test_micromagnetic_zeeman.py
├── sandbox
├── parallel-cvode
│ ├── run_multiple.sh
│ ├── test_cvode_serial.py
│ ├── test_cvode_parallel.py
│ └── test.py
├── relaxation_test
│ └── skyrmion.py
├── more-dmi
│ ├── dmi-test.py
│ ├── isolated_sk_T-Oxs_DMI_T-Field-00-0000000.ohf
│ ├── isolated_sk_sim.py
│ └── test_dmi.mif
└── memory_leak
│ └── fidimag_memory_issue_example.py
├── docker
├── minimal-py2
│ ├── Dockerfile.org
│ ├── Makefile
│ ├── Readme.md
│ └── Dockerfile
├── notebook
│ ├── Makefile
│ ├── Dockerfile
│ └── Readme.md
├── minimal-py3
│ ├── Makefile
│ ├── Readme.md
│ └── Dockerfile
└── testing
│ └── Dockerfile
├── .readthedocs.yml
├── .travis.yml
├── .gitignore
├── .github
└── workflows
│ ├── superlinter.yml
│ └── build.yml
├── pyproject.toml
├── LICENSE.txt
└── Dockerfile
/fidimag/extensions/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fidimag/extensions/user/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fidimag/atomistic/test.txt:
--------------------------------------------------------------------------------
1 | this is a test file.
2 |
--------------------------------------------------------------------------------
/bin/install-python-packages.sh:
--------------------------------------------------------------------------------
1 | pip install --upgrade cython psutil ipywidgets
2 |
--------------------------------------------------------------------------------
/fidimag/user/example/__init__.py:
--------------------------------------------------------------------------------
1 | from fidimag.extensions.user.example import *
2 |
--------------------------------------------------------------------------------
/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | markers =
3 | slow: Mark tests that will take long time to finish
4 |
--------------------------------------------------------------------------------
/doc/images/nebm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/doc/images/nebm.png
--------------------------------------------------------------------------------
/doc/images/nebm_classes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/doc/images/nebm_classes.png
--------------------------------------------------------------------------------
/doc/images/bobber_toron_vis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/doc/images/bobber_toron_vis.png
--------------------------------------------------------------------------------
/doc/images/2d-lattice-triagonal.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/doc/images/2d-lattice-triagonal.pdf
--------------------------------------------------------------------------------
/doc/user_guide/ipynb/sanitize_file:
--------------------------------------------------------------------------------
1 | [matplotlib_text_output]
2 | regex: \<(matplotlib|Figure).*
3 | replace: MATPLOTLIB-FIGURE
4 |
5 |
--------------------------------------------------------------------------------
/examples/micromagnetic/std4/res.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/examples/micromagnetic/std4/res.pdf
--------------------------------------------------------------------------------
/tests/omfs/test_dmi_field_oommf.ohf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/tests/omfs/test_dmi_field_oommf.ohf
--------------------------------------------------------------------------------
/tests/omfs/test_exch_field_oommf.ohf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/tests/omfs/test_exch_field_oommf.ohf
--------------------------------------------------------------------------------
/examples/micromagnetic/skyrmion_stt/m0.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/examples/micromagnetic/skyrmion_stt/m0.npy
--------------------------------------------------------------------------------
/tests/mini_test.py:
--------------------------------------------------------------------------------
1 | import fidimag as f
2 |
3 | mesh = f.common.CuboidMesh(nx=5, ny=1, nz=1)
4 | sim = f.micro.Sim(mesh)
5 |
6 | sim.set_m([0., 0., 1.])
7 |
--------------------------------------------------------------------------------
/tests/omfs/test_with_oommf_spatial_Ms_Demag.ohf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/tests/omfs/test_with_oommf_spatial_Ms_Demag.ohf
--------------------------------------------------------------------------------
/tests/omfs/test_demag_field_oommf_large_Demag.ohf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/tests/omfs/test_demag_field_oommf_large_Demag.ohf
--------------------------------------------------------------------------------
/tests/omfs/test_with_oommf_spatial_Ms_Exchange.ohf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/tests/omfs/test_with_oommf_spatial_Ms_Exchange.ohf
--------------------------------------------------------------------------------
/tests/omfs/test_demag_field_oommf_large_Exchange.ohf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/tests/omfs/test_demag_field_oommf_large_Exchange.ohf
--------------------------------------------------------------------------------
/examples/atomistic/skyrmion/skx_rotation/m_z_backup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/examples/atomistic/skyrmion/skx_rotation/m_z_backup.png
--------------------------------------------------------------------------------
/examples/neb_micromagnetic/skyrmion/results/energy_167.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/examples/neb_micromagnetic/skyrmion/results/energy_167.pdf
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | from numpy import allclose
2 |
3 |
4 | def very_close(a, b):
5 | """ close to machine precision """
6 | return allclose(a, b, rtol=1e-14, atol=1e-14)
7 |
--------------------------------------------------------------------------------
/tests/omfs/dmi-Oxs_TimeDriver-Magnetization-00-0000963.omf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/computationalmodelling/fidimag/HEAD/tests/omfs/dmi-Oxs_TimeDriver-Magnetization-00-0000963.omf
--------------------------------------------------------------------------------
/sandbox/parallel-cvode/run_multiple.sh:
--------------------------------------------------------------------------------
1 | for ((i = 1; i <= 16; i++)); do
2 | export OMP_NUM_THREADS=$i
3 | echo $OMP_NUM_THREADS
4 | python test_cvode_serial.py
5 | python test_cvode_parallel.py
6 | done
7 |
--------------------------------------------------------------------------------
/fidimag/atomistic/lib/fmmlib/utils.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FMMLIB_UTILS_HPP
2 | #define FMMLIB_UTILS_HPP
3 |
4 | unsigned int TriangleNumbers(unsigned int n);
5 |
6 | unsigned int Nterms(unsigned int p);
7 |
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pytest
3 | import tempfile
4 |
5 | @pytest.fixture(scope="session", autouse=True)
6 | def config():
7 | tmpdir = tempfile.mkdtemp(suffix='fidimag-tests')
8 | os.chdir(tmpdir)
9 |
--------------------------------------------------------------------------------
/doc/environment.yml:
--------------------------------------------------------------------------------
1 | # name of the conda environment
2 | name: fidimag_docs
3 |
4 | dependencies:
5 | - pandoc
6 | - nbformat
7 | - pip:
8 | - ipython
9 | - nbsphinx
10 | - pydata-sphinx-theme
11 |
--------------------------------------------------------------------------------
/examples/neb_micromagnetic/skyrmion/plot.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | from util.helper import plot_energy_2d, plot_energy_3d
4 |
5 | plot_energy_2d('neb_nanodisk_d50nm_k1e10')
6 | plot_energy_3d('neb_nanodisk_d50nm_k1e10')
7 |
--------------------------------------------------------------------------------
/docker/minimal-py2/Dockerfile.org:
--------------------------------------------------------------------------------
1 | * How to use
2 |
3 | ** Linux
4 |
5 | $> sudo docker pull fangohr/fidimag
6 |
7 | $> docker run -ci fangohr/fidimag ipython
8 |
9 | then try 'import fidimag'.
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | build:
4 | os: "ubuntu-20.04"
5 | tools:
6 | python: "mambaforge-22.9"
7 |
8 | conda:
9 | environment: doc/environment.yml
10 |
11 | sphinx:
12 | # Path to your Sphinx configuration file.
13 | configuration: doc/conf.py
14 |
--------------------------------------------------------------------------------
/doc/_templates/custom-template.html:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/doc/physics_num_methods/index.rst:
--------------------------------------------------------------------------------
1 | ===============================
2 | Magnetism and Numerical Methods
3 | ===============================
4 |
5 | .. toctree::
6 | :maxdepth: 2
7 | :caption: Micromagnetics and Discrete Spin Model
8 |
9 | core_eqs
10 | extended_eqs
11 | monte_carlo
12 | nebm
13 |
--------------------------------------------------------------------------------
/fidimag/atomistic/lib/fmmlib/utils.cpp:
--------------------------------------------------------------------------------
1 | unsigned int TriangleNumbers(unsigned int n) {
2 | return (n * (n + 1)) / 2;
3 | }
4 |
5 | unsigned int Nterms(unsigned int p) {
6 | unsigned int result = 0;
7 | for(unsigned int i = 0; i < p + 2; i++) {
8 | result += TriangleNumbers(i);
9 | }
10 | return result;
11 | }
12 |
--------------------------------------------------------------------------------
/bin/install-ubuntu-packages.sh:
--------------------------------------------------------------------------------
1 | # required to compile fidimag
2 | deps_compilation="python-pip python-numpy python-dev python-scipy cmake liblapack-dev libblas-dev"
3 |
4 | # required for tests and running fidimag
5 | deps_live="python-pytest python-pyvtk ipython python-matplotlib"
6 |
7 | apt-get install $deps_compilation $deps_live
8 |
--------------------------------------------------------------------------------
/tests/test_citation.py:
--------------------------------------------------------------------------------
1 | import fidimag
2 |
3 |
4 | def test_citation():
5 | s = fidimag.citation()
6 | assert type(s) == str
7 | assert 'fidimag' in s.lower()
8 |
9 | sb = fidimag.citation(bibtex=True)
10 | assert sb[0] == '@'
11 | assert len(sb.split()) > 1
12 | assert 'fidimag' in sb.lower()
13 |
14 |
--------------------------------------------------------------------------------
/fidimag/common/__init__.py:
--------------------------------------------------------------------------------
1 | from .fileio import DataSaver
2 | from .fileio import DataReader
3 | from .batch_task import BatchTasks
4 | from .citation import citation
5 | from .cuboid_mesh import CuboidMesh
6 | #from .neb_cartesian import NEB_Sundials
7 | from .helper import init_scalar, init_vector
8 | from .plot import plot, plot_micro, plot_atom_cub, plot_atom_hex
9 |
--------------------------------------------------------------------------------
/tests/test_imports.py:
--------------------------------------------------------------------------------
1 | def test_has_pyvtk_installed():
2 | # use 'pip install pyvtk' if this fails
3 | import pyvtk
4 |
5 | def test_has_fidimag_installed():
6 | # fix PYTHONPATH if this fails
7 | import fidimag
8 |
9 | def test_has_pytest_installed():
10 | # install pytest if this fails (via conda, apt-get, ...)
11 | import pytest
12 |
--------------------------------------------------------------------------------
/fidimag/micro/__init__.py:
--------------------------------------------------------------------------------
1 | from .sim import Sim
2 | from .demag import Demag
3 | from .exchange import UniformExchange
4 | from .exchange_rkky import ExchangeRKKY
5 | from .zeeman import Zeeman, TimeZeeman
6 | from .anisotropy import UniaxialAnisotropy, UniaxialAnisotropy4
7 | from .dmi import DMI
8 | from .baryakhtar import LLBar, LLBarFull
9 | from .simple_demag import SimpleDemag
10 |
--------------------------------------------------------------------------------
/fidimag/common/constant.py:
--------------------------------------------------------------------------------
1 | from math import pi
2 |
3 | mu_0 = 4 * pi * 1e-7
4 | mu_B = 9.27400949e-24
5 | k_B = 1.3806505e-23
6 | c_e = 1.602176565e-19
7 | eV = 1.602176565e-19
8 | meV = 1.602176565e-22
9 | m_e = 9.10938291e-31
10 | g_e = 2.0023193043737
11 | h_bar = 1.05457172647e-34
12 | h = h_bar * 2. * pi
13 | gamma = g_e * mu_B / h_bar
14 | mu_s_1 = g_e * mu_B * 1.0 # for S=1, 1.856952823077189e-23
15 | h_bar_gamma = h_bar * gamma
16 |
--------------------------------------------------------------------------------
/docker/notebook/Makefile:
--------------------------------------------------------------------------------
1 | # to build a new docker image
2 | build:
3 | time docker build -t fidimag/notebook:latest .
4 |
5 | # to run new image
6 | run: build
7 | docker run -v `pwd`:/io -d -p 30008:8888 fidimag/notebook
8 |
9 | # to push the new docker image to dockerhub (need to login first)
10 | push: build
11 | docker push fidimag/notebook:latest
12 |
13 | # to fetch image to local machine
14 | pull:
15 | docker pull fidimag/notebook:latest
16 |
--------------------------------------------------------------------------------
/fidimag/common/neb_method/nebm_spherical_lib.h:
--------------------------------------------------------------------------------
1 | #include "math.h"
2 | #define WIDE_PI 3.1415926535897932384626433832795L
3 |
4 | void normalise_spherical(double *restrict a, int n);
5 |
6 | void normalise_images_spherical_C(double *restrict y, int n_images,
7 | int n_dofs_image);
8 |
9 | double compute_distance_spherical(double *restrict A, double *B, int n,
10 | int *restrict material, int n_dofs_image_material);
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 |
3 | dist: trusty
4 | group: deprecated-2017Q4
5 |
6 | services:
7 | - docker
8 |
9 | before_install:
10 | - travis_wait 90 docker build -t fidimag -f ./docker/travis/Dockerfile .
11 | - docker run -ti -d --name fidimag fidimag
12 |
13 | jobs:
14 | include:
15 | - stage: Tests
16 | script: make test-docker
17 | - stage: Notebooks
18 | script: make ipynb-docker
19 |
20 | notifications:
21 | email:
22 | on_failure: always
23 |
--------------------------------------------------------------------------------
/docker/minimal-py2/Makefile:
--------------------------------------------------------------------------------
1 | # to build a new docker image
2 | build:
3 | time docker build -t fidimag/minimal-py2:latest .
4 |
5 | # to run new image
6 | run: build
7 | docker run -v `pwd`:/io -ti fidimag/minimal-py2
8 | # try 'ipython' and then 'import fidimag'
9 |
10 | # to push the new docker image to dockerhub (need to login first)
11 | push: build
12 | docker push fidimag/minimal-py2:latest
13 |
14 | # to fetch image to local machine
15 | pull:
16 | docker pull fidimag/minimal-py2:latest
17 |
--------------------------------------------------------------------------------
/docker/minimal-py3/Makefile:
--------------------------------------------------------------------------------
1 | # to build a new docker image
2 | build:
3 | time docker build -t fidimag/minimal-py3:latest .
4 |
5 | # to run new image
6 | run: build
7 | docker run -v `pwd`:/io -ti fidimag/minimal-py3
8 | # try 'ipython3' and then 'import fidimag'
9 |
10 | # to push the new docker image to dockerhub (need to login first)
11 | push: build
12 | docker push fidimag/minimal-py3:latest
13 |
14 | # to fetch image to local machine
15 | pull:
16 | docker pull fidimag/minimal-py3:latest
17 |
--------------------------------------------------------------------------------
/sandbox/relaxation_test/skyrmion.py:
--------------------------------------------------------------------------------
1 | from fidimag.atomistic import Sim
2 | from fidimag.common.cuboid_mesh import CuboidMesh
3 | from fidimag.atomistic import UniformExchange, Zeeman
4 | import fidimag.common.constant as const
5 |
6 | mesh = CuboidMesh(nx=1, ny=1, dx=1, dy=1)
7 |
8 | sim = Sim(mesh, name='relax_sk')
9 | sim.gamma = const.gamma
10 | sim.set_m((1, 0, 0))
11 | sim.add(Zeeman((0, 0, 25.)))
12 |
13 | sim.run_until(1e-11)
14 | sim.set_tols(rtol=1e-10, atol=1e-12)
15 | sim.run_until(2e-11)
16 |
--------------------------------------------------------------------------------
/fidimag/atomistic/__init__.py:
--------------------------------------------------------------------------------
1 | from .sim import Sim
2 | from .exchange import UniformExchange, Exchange
3 | from .anisotropy import Anisotropy, CubicAnisotropy
4 | from .zeeman import Zeeman, TimeZeeman
5 | from .demag import Demag, DemagFMM
6 | from .demag_hexagonal import DemagHexagonal
7 | from .hexagonal_mesh import HexagonalMesh
8 | from .demag_full import DemagFull
9 | from .dmi import DMI
10 | from .monte_carlo import MonteCarlo
11 | import fidimag.common.constant as const
12 | from .materials import UnitMaterial, Nickel
13 |
--------------------------------------------------------------------------------
/fidimag/atomistic/fmmlib/example.py:
--------------------------------------------------------------------------------
1 | import fmmgen
2 |
3 | order = 8
4 | source_order = 1
5 | cse = True
6 | atomic = True
7 | precision='double'
8 | fmmgen.generate_code(order, "operators",
9 | precision=precision,
10 | CSE=cse,
11 | cython=False,
12 | harmonic_derivs=True,
13 | potential=False,
14 | field=True,
15 | source_order=source_order,
16 | atomic=atomic)
17 |
--------------------------------------------------------------------------------
/fidimag/common/neb_method/nebm_integrators.h:
--------------------------------------------------------------------------------
1 | double step_Verlet_C(double *restrict forces,
2 | double *restrict forces_prev,
3 | double *restrict velocities,
4 | double *restrict velocities_new,
5 | double *restrict y,
6 | double t,
7 | double h,
8 | double mass,
9 | int n_images,
10 | int n_dofs_image,
11 | double (*update_field)(double, double *));
12 |
--------------------------------------------------------------------------------
/tests/field_test.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.common.field import scalar_field, vector_field
3 | from fidimag.common import CuboidMesh
4 | from . import very_close
5 |
6 |
7 | def test_initialise_scalar():
8 | mesh = CuboidMesh(1, 1, 1, 1, 1, 1)
9 | f = scalar_field(mesh, lambda r: r[0] + r[1] + r[2])
10 | assert very_close(f, np.array((1.5)))
11 |
12 |
13 | def test_initialise_vector():
14 | mesh = CuboidMesh(1, 1, 1, 1, 1, 1)
15 | v = vector_field(mesh, lambda r: 2 * r)
16 | assert very_close(v, np.array((1, 1, 1)))
17 |
--------------------------------------------------------------------------------
/tests/vtk_refs/save_scalar_000000.vtk:
--------------------------------------------------------------------------------
1 | # vtk DataFile Version 2.0
2 |
3 | ASCII
4 | DATASET RECTILINEAR_GRID
5 | DIMENSIONS 5 4 3
6 | X_COORDINATES 5 double
7 | 0.0 4.0 8.0 12.0 16.0
8 | Y_COORDINATES 4 double
9 | 0.0 3.0 6.0 9.0
10 | Z_COORDINATES 3 double
11 | 0.0 2.0 4.0
12 | CELL_DATA 24
13 | SCALARS s double 1
14 | LOOKUP_TABLE default
15 | 4.5
16 | 8.5
17 | 12.5
18 | 16.5
19 | 7.5
20 | 11.5
21 | 15.5
22 | 19.5
23 | 10.5
24 | 14.5
25 | 18.5
26 | 22.5
27 | 6.5
28 | 10.5
29 | 14.5
30 | 18.5
31 | 9.5
32 | 13.5
33 | 17.5
34 | 21.5
35 | 12.5
36 | 16.5
37 | 20.5
38 | 24.5
--------------------------------------------------------------------------------
/fidimag/user/example/example.pyx:
--------------------------------------------------------------------------------
1 | from libc.math cimport cos, sin
2 |
3 | def fast_sin_init(mesh, double[:] field, *params):
4 | t, axis, Bmax, fc = params
5 | for i in range(mesh.n):
6 | field[3*i+0] = Bmax * axis[0] * sin(fc*t)
7 | field[3*i+1] = Bmax * axis[1] * sin(fc*t)
8 | field[3*i+2] = Bmax * axis[2] * sin(fc*t)
9 |
10 | def TimeZeemanFast_test_time_fun(mesh, double[:] field, *params):
11 | cdef int i
12 | t, frequency = params
13 | for i in range(mesh.n):
14 | field[3*i+0] = 0
15 | field[3*i+1] = 0
16 | field[3*i+2] = 10 * cos(frequency * t)
17 |
--------------------------------------------------------------------------------
/fidimag/atomistic/fmmlib/utils.cpp:
--------------------------------------------------------------------------------
1 | #include "utils.hpp"
2 |
3 | size_t TriangleNumbers(size_t n) {
4 | return (n * (n + 1)) / 2;
5 | }
6 |
7 | size_t Nterms(size_t p) {
8 | if (p < 0) {
9 | return 0;
10 | }
11 | size_t result = 0;
12 | for(size_t i = 0; i < p + 2; i++) {
13 | result += TriangleNumbers(i);
14 | }
15 | return result;
16 | }
17 |
18 | size_t Msize(size_t order, size_t source_order) {
19 | if (source_order == 0) {
20 | return Nterms(order);
21 | }
22 | return Nterms(order) - Nterms(source_order-1);
23 | }
24 |
25 | size_t Lsize(size_t order, size_t source_order) {
26 | return Nterms(order - source_order);
27 | }
--------------------------------------------------------------------------------
/fidimag/common/neb_method/nebm_geodesic_lib.h:
--------------------------------------------------------------------------------
1 | #include "math.h"
2 | #define WIDE_PI 3.1415926535897932384626433832795L
3 |
4 | double compute_geodesic_GreatCircle(double *restrict A, double *restrict B,
5 | int n_dofs_image,
6 | int *restrict material,
7 | int n_dofs_image_material);
8 |
9 | double compute_geodesic_Vincenty(double *restrict A, double *restrict B,
10 | int n_dofs_image,
11 | int *restrict material,
12 | int n_dofs_image_material);
13 |
--------------------------------------------------------------------------------
/doc/user_guide/index.rst:
--------------------------------------------------------------------------------
1 | ==========
2 | User Guide
3 | ==========
4 |
5 | .. toctree::
6 | :maxdepth: 2
7 | :caption: Tutorials
8 |
9 | ipynb/tutorial-docker-container
10 | ipynb/tutorial-basics
11 | ipynb/1d_domain_wall
12 | ipynb/anisotropic-grain-structure
13 | ipynb/current-driven-domain-wall
14 | ipynb/ferromagnetic-resonance-stdprob
15 | ipynb/isolated_skyrmion
16 | ipynb/Simulating an Anisotropic Grain Structure
17 | ipynb/skyrmions-applied-field-gradient
18 | ipynb/spin-polarised-current-driven-skyrmion
19 | ipynb/spin-waves-in-periodic-system
20 | ipynb/standard_problem_4
21 | ipynb/steepest_descent_atomistic
22 |
--------------------------------------------------------------------------------
/tests/test_init_scalar.py:
--------------------------------------------------------------------------------
1 | import fidimag
2 | from fidimag.common import init_scalar
3 | import numpy as np
4 | import unittest
5 |
6 | def m_init(pos, t):
7 | x, y, z = pos
8 | return np.sin(t)
9 |
10 | def test_init_scalar_function():
11 | import fidimag
12 | import numpy as np
13 | # Create simulation
14 | nx = ny = nz = 2
15 | mesh = fidimag.common.CuboidMesh(nx=nx, ny=ny, nz=nz,
16 | dx=1, dy=1, dz=1)
17 |
18 | test_vec = np.zeros(nx * ny * nz)
19 | test_vec[:] = init_scalar(m_init, mesh, 0)
20 | assert test_vec[0] == 0.0
21 | test_vec[:] = init_scalar(m_init, mesh, np.pi/2.0)
22 | assert test_vec[0] == 1.0
23 |
--------------------------------------------------------------------------------
/sandbox/more-dmi/dmi-test.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import fidimag
3 | # PdFe on Ir(111) [PRL, 114(17):1-5, 2015]
4 | Ms = 1.1e6
5 | D = -3.9e-3
6 |
7 |
8 | XL = 15e-9
9 | YL = XL
10 | ZL = XL
11 |
12 | nx = 2
13 | ny = 1
14 | nz = 1
15 |
16 | def set_D(pos):
17 | x, y, z = pos
18 | if x < XL/2:
19 | return 0
20 | else:
21 | return -D
22 |
23 | mesh = fidimag.common.CuboidMesh(nx=nx,ny=ny,nz=nz, dx=XL/nx, dy=YL/ny, dz=ZL/nz)
24 |
25 | sim = fidimag.micro.Sim(mesh)
26 | sim.set_Ms(Ms)
27 |
28 |
29 | sim.add(fidimag.micro.DMI(set_D))
30 | m0 = np.array([0, 0, 1])
31 | sim.set_m(m0)
32 |
33 | sim.compute_effective_field(0)
34 | print(sim.driver.field.reshape(-1, 3))
35 |
--------------------------------------------------------------------------------
/fidimag/common/citation.py:
--------------------------------------------------------------------------------
1 | def citation(bibtex=False):
2 | """Return citation string. Use bibtex=True to get
3 | a bibtex-formatted entry.
4 |
5 | Print the return value to see line breaks."""
6 |
7 | s = """Fidimag - FInite DIfference microMAGnetic simulator.
8 | https://github.com/fangohr/fidimag
9 | (C) University of Southampton, 2012 - 2015"""
10 |
11 | s_bib = """@Misc{Fidimag,
12 | author = {University of Southampton},
13 | title = {Fidimag - FInite DIfference microMAGnetic simulator},
14 | year = {2015},
15 | note = {https://github.com/fangohr/fidimag}
16 | }"""
17 |
18 | if bibtex:
19 | return s_bib
20 | else:
21 | return s
22 |
23 |
24 |
--------------------------------------------------------------------------------
/tests/vtk_refs/save_vector_000000.vtk:
--------------------------------------------------------------------------------
1 | # vtk DataFile Version 2.0
2 |
3 | ASCII
4 | DATASET RECTILINEAR_GRID
5 | DIMENSIONS 5 4 3
6 | X_COORDINATES 5 double
7 | 0.0 4.0 8.0 12.0 16.0
8 | Y_COORDINATES 4 double
9 | 0.0 3.0 6.0 9.0
10 | Z_COORDINATES 3 double
11 | 0.0 2.0 4.0
12 | CELL_DATA 24
13 | VECTORS s double
14 | 2.0 1.5 1.0
15 | 6.0 1.5 1.0
16 | 10.0 1.5 1.0
17 | 14.0 1.5 1.0
18 | 2.0 4.5 1.0
19 | 6.0 4.5 1.0
20 | 10.0 4.5 1.0
21 | 14.0 4.5 1.0
22 | 2.0 7.5 1.0
23 | 6.0 7.5 1.0
24 | 10.0 7.5 1.0
25 | 14.0 7.5 1.0
26 | 2.0 1.5 3.0
27 | 6.0 1.5 3.0
28 | 10.0 1.5 3.0
29 | 14.0 1.5 3.0
30 | 2.0 4.5 3.0
31 | 6.0 4.5 3.0
32 | 10.0 4.5 3.0
33 | 14.0 4.5 3.0
34 | 2.0 7.5 3.0
35 | 6.0 7.5 3.0
36 | 10.0 7.5 3.0
37 | 14.0 7.5 3.0
--------------------------------------------------------------------------------
/examples/mc/skx.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from fidimag.atomistic import MonteCarlo
7 | from fidimag.common import DataReader, CuboidMesh
8 | import fidimag.common.constant as const
9 |
10 | def random_m(pos):
11 | return np.random.random(3) - 0.5
12 |
13 | def run(mesh):
14 | mc = MonteCarlo(mesh, name='test1')
15 | mc.set_m(random_m)
16 | J = 50*const.k_B
17 | mc.set_options(H=[0,0,1.0], J=J, D=0.27*J, T=4.0)
18 | mc.run(steps=int(1e8), save_m_steps=None, save_vtk_steps=50000, save_data_steps=50000)
19 |
20 | if __name__=='__main__':
21 | mesh = CuboidMesh(nx=58, ny=33, nz=1, periodicity = (True, True, False))
22 | run(mesh)
23 |
--------------------------------------------------------------------------------
/fidimag/atomistic/fmmlib/utils.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | size_t TriangleNumbers(size_t n);
6 | size_t Nterms(size_t p);
7 | size_t Msize(size_t order, size_t source_order);
8 | size_t Lsize(size_t order, size_t source_order);
9 |
10 | class Timer {
11 | private:
12 | // Type aliases to make accessing nested type easier
13 | using clock_t = std::chrono::high_resolution_clock;
14 | using second_t = std::chrono::duration>;
15 | std::chrono::time_point t;
16 |
17 | public:
18 | Timer() : t(clock_t::now()) {}
19 | void reset() { t = clock_t::now(); }
20 | double elapsed() const {
21 | return std::chrono::duration_cast(clock_t::now() - t).count();
22 | }
23 | };
--------------------------------------------------------------------------------
/tests/test_mesh.py:
--------------------------------------------------------------------------------
1 | from fidimag.common import CuboidMesh
2 | import unittest
3 |
4 | def test_mesh1():
5 | mesh = CuboidMesh(nx=5, ny=3, nz=2, dx=0.23, dy=0.41)
6 | assert len(mesh.coordinates) == 5 * 3 * 2
7 | assert mesh.ny * mesh.nz == 6
8 | assert tuple(mesh.coordinates[mesh.index(0, 0, 0)]) == (0.23 / 2, 0.41 / 2, 0.5)
9 | assert tuple(mesh.coordinates[mesh.index(3, 2, 1)]) == (
10 | (3 + 0.5) * 0.23, (2 + 0.5) * 0.41, 1 + 0.5)
11 |
12 |
13 | class Mesh_TestCase(unittest.TestCase):
14 | def test_mesh_input_args(self):
15 | self.assertRaises(ValueError, CuboidMesh, 1, 1, 0, 1, 1, 1)
16 | self.assertRaises(ValueError, CuboidMesh, 1, 1, 1, 0, 1, 1)
17 |
18 | if __name__ == '__main__':
19 | test_mesh1()
20 |
--------------------------------------------------------------------------------
/tests/test_llg_raises_error.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | from fidimag.common import CuboidMesh
3 | from fidimag.micro import Sim
4 | from fidimag.micro import Zeeman
5 | from fidimag.micro import UniaxialAnisotropy
6 | import numpy as np
7 | import unittest
8 |
9 | def run_sim():
10 | mesh = CuboidMesh()
11 | sim = Sim(mesh, name='spin')
12 | alpha = 0.1
13 | gamma = 2.21e5
14 | sim.alpha = alpha
15 | sim.driver.gamma = gamma
16 | sim.mu_s = 1.0
17 |
18 | sim.set_m((1, 0, 0))
19 | H0 = 1e5
20 | sim.add(Zeeman((0, 0, H0)))
21 | sim.driver.run_until(1e-10)
22 | sim.driver.run_until(0.5e-10)
23 |
24 | class mytest(unittest.TestCase):
25 | def test_raises_valueerror_time_integration(self):
26 | self.assertRaises(ValueError, run_sim)
27 |
--------------------------------------------------------------------------------
/tests/test_init_vector.py:
--------------------------------------------------------------------------------
1 | import fidimag
2 | from fidimag.common import init_vector
3 | import numpy as np
4 | import unittest
5 |
6 | def m_init(pos, t):
7 | x, y, z = pos
8 | return (np.sin(t), np.cos(t), 0.0)
9 |
10 | def test_init_vector_function():
11 | import fidimag
12 | import numpy as np
13 | # Create simulation
14 | nx = ny = nz = 2
15 | mesh = fidimag.common.CuboidMesh(nx=nx, ny=ny, nz=nz,
16 | dx=1, dy=1, dz=1)
17 |
18 | test_vec = np.zeros(3 * nx * ny * nz)
19 | test_vec[:] = init_vector(m_init, mesh, 3, False, 0)
20 | assert test_vec[0] < 1e-15
21 | assert test_vec[1] - 1.0 < 1e-15
22 | test_vec[:] = init_vector(m_init, mesh, 3, False, np.pi/2.0)
23 | assert test_vec[0] - 1.0 < 1e-15
24 | assert test_vec[1] < 1e-15
25 |
--------------------------------------------------------------------------------
/tests/test_atomistic_zeeman.py:
--------------------------------------------------------------------------------
1 | from fidimag.atomistic import Zeeman
2 | from fidimag.common import CuboidMesh
3 | from fidimag.atomistic import Sim
4 | import numpy as np
5 |
6 |
7 | def varying_field(pos):
8 | return (1.2 * pos[0], 2.3 * pos[1], 0)
9 |
10 |
11 | def test_zeeman():
12 | """
13 | Test the x and y component of the zeeman field
14 | for the 2nd spin
15 |
16 | 6 7 8 9 10 11
17 | 0 1 2 3 4 5
18 | ^
19 | """
20 |
21 | mesh = CuboidMesh(nx=5, ny=2, nz=1)
22 |
23 | sim = Sim(mesh)
24 | sim.set_m((1, 0, 0))
25 |
26 | zeeman = Zeeman(varying_field)
27 | sim.add(zeeman)
28 |
29 | field = zeeman.compute_field()
30 |
31 | assert field[2 * 3] == 1.2 * (2 + 0.5)
32 | assert field[2 * 3 + 1] == 2.3 * 0.5
33 |
34 |
35 | if __name__ == '__main__':
36 | test_zeeman()
37 |
--------------------------------------------------------------------------------
/docker/minimal-py2/Readme.md:
--------------------------------------------------------------------------------
1 | # Docker
2 |
3 | Run fidimag with Python 2 under Docker.
4 |
5 | ## Using the docker container
6 |
7 | There is a fidimag container available under `fidimag/minimal-py2`.
8 |
9 | To use it, you can try this:
10 |
11 | 1. Install docker
12 |
13 | 2. Pull the container onto your machine using
14 |
15 | docker pull fidimag/minimal-py2
16 |
17 | 3. Start the container using
18 |
19 | docker run -ti fidimag/minimal-py2
20 |
21 | This command should show a bash prompt inside the docker container:
22 |
23 |
24 | bin:docker fangohr$ docker run -v `pwd`:/io -ti fidimag/minimal-py2
25 | fidimag@38fdd2a0feb4:/io$
26 |
27 |
28 | ## Creating the docker container
29 |
30 | The `Makefile` in this directory shows the relevant targets (build, login, push)
31 | to create a new container and push it to the the cloud.
32 |
--------------------------------------------------------------------------------
/docker/minimal-py3/Readme.md:
--------------------------------------------------------------------------------
1 | # Docker
2 |
3 | Run fidimag with Python 3 under Docker.
4 |
5 | ## Using the docker container
6 |
7 | There is a fidimag container available under `fidimag/minimal-py3`.
8 |
9 | To use it, you can try this:
10 |
11 | 1. Install docker
12 |
13 | 2. Pull the container onto your machine using
14 |
15 | docker pull fidimag/minimal-py3
16 |
17 | 3. Start the container using
18 |
19 | docker run -ti fidimag/minimal-py3
20 |
21 | This command should show a bash prompt inside the docker container:
22 |
23 |
24 | bin:docker fangohr$ docker run -v `pwd`:/io -ti fidimag/minimal-py3
25 | fidimag@38fdd2a0feb4:/io$
26 |
27 |
28 | ## Creating the docker container
29 |
30 | The `Makefile` in this directory shows the relevant targets (build, login, push)
31 | to create a new container and push it to the the cloud.
32 |
--------------------------------------------------------------------------------
/fidimag/common/sim2fdfield.py:
--------------------------------------------------------------------------------
1 | import finitedifferencefield
2 | from fidimag.common import CuboidMesh
3 |
4 | def fidimag_to_finitedifferencefield(sim):
5 | """
6 | fidimag_to_finitedifferencefield(sim)
7 |
8 | This function takes a Fidimag simulation object, and constructs a
9 | Finite Difference Field object which has the magnetisation configuration
10 | from the simulation at the last time step.
11 | """
12 | cmin = np.array([sim.mesh.x0, sim.mesh.y0, sim.mesh.z0])*sim.mesh.unit_length
13 | cmax = tuple(cmin +np.array([mesh.Lx, mesh.Ly, mesh.Lz])*sim.mesh.unit_length)
14 | cmin = tuple(cmin)
15 | d = tuple(np.array([sim.mesh.dx, sim.mesh.dy, sim.mesh.dz])*sim.mesh.unit_length)
16 | field = finitedifferencefield.Field(cmin, cmax, d)
17 | numpyfield = sim.spin.copy().reshape((mesh.nx, mesh.ny, mesh.nz, 3))
18 | field.f = numpyfield
19 | return field
20 |
21 |
--------------------------------------------------------------------------------
/doc/user_guide/ipynb/runtimes.org:
--------------------------------------------------------------------------------
1 | * <2016-05-01 Sun>
2 |
3 | To see which tests run long:
4 |
5 | cd doc/ipynb && py.test . -v --nbval --duration=10 --sanitize-with sanitize_file
6 |
7 | ========================== slowest 10 test durations ===========================
8 | 17209.34s call doc/ipynb/isolated_skyrmion.ipynb::Cell 13
9 | 4098.12s call doc/ipynb/standard_problem_4.ipynb::Cell 19
10 | 967.73s call doc/ipynb/spin-polarised-current-driven-skyrmion.ipynb::Cell 14
11 | 703.63s call doc/ipynb/standard_problem_4.ipynb::Cell 15
12 | 20.86s call doc/ipynb/tutorial-basics.ipynb::Cell 21
13 | 6.32s call doc/ipynb/spin-waves-in-periodic-system.ipynb::Cell 13
14 | 6.16s call doc/ipynb/isolated_skyrmion.ipynb::Cell 11
15 | 5.76s call doc/ipynb/current-driven-domain-wall.ipynb::Cell 24
16 | 1.95s call doc/ipynb/current-driven-domain-wall.ipynb::Cell 18
17 | 1.67s call doc/ipynb/spin-polarised-current-driven-skyrmion.ipynb::Cell 11
18 |
--------------------------------------------------------------------------------
/tests/test_regression_init_scalar.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 |
4 | def regression_helper_init_scalar():
5 | import fidimag
6 | import numpy as np
7 | # Create simulation
8 | mesh = fidimag.common.CuboidMesh(nx=10, ny=2, nz=1,
9 | dx=1, dy=1, dz=1)
10 | sim = fidimag.atomistic.Sim(mesh)
11 | # Set the magnetisation and save it to mu_s.npy
12 | sim.mu_s = 3
13 | np.save('mu_s.npy', sim.mu_s)
14 |
15 | # Create another simulation with less elements in the x direction
16 | mesh2 = fidimag.common.CuboidMesh(nx=5, ny=2, nz=1,
17 | dx=1, dy=1, dz=1)
18 | sim2 = fidimag.atomistic.Sim(mesh2)
19 | # Set the magnetisation loading the other simulation file
20 | sim2.mu_s = np.load('mu_s.npy')
21 |
22 |
23 | class regression_test(unittest.TestCase):
24 |
25 | def test_init_scalar(self):
26 | self.assertRaises(ValueError, regression_helper_init_scalar)
27 |
--------------------------------------------------------------------------------
/docker/testing/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:20.04
2 |
3 | # To build this image `docker build -t fidimag .`
4 | # Then you can drop into a live bash shell with `docker run -it fidimag`.
5 | ENTRYPOINT ["/bin/bash"]
6 | SHELL ["/bin/bash", "-c"]
7 |
8 | ARG DEBIAN_FRONTEND=noninteractive
9 |
10 | RUN apt-get update -y -qq
11 | RUN apt-get install -y -qq build-essential cmake cython3 python3-dev python3-pip \
12 | liblapack-dev libopenblas-dev \
13 | wget curl git
14 |
15 | RUN pip3 install --upgrade setuptools
16 | RUN pip3 install numpy matplotlib ipywidgets nbval pyvtk six psutil pytest pytest-cov pluggy scipy -U
17 |
18 | WORKDIR /fidimag
19 | ADD . /fidimag
20 | RUN ./bin/install-sundials.sh
21 | RUN ./bin/install-fftw.sh
22 | RUN make build
23 |
24 | ENV PYTHONPATH=/fidimag \
25 | LD_LIBRARY_PATH=/fidimag/local/lib LD_RUN_PATH=/fidimag/local/lib \
26 | OMP_NUM_THREADS=1 MPLBACKEND=Agg QT_API=pyqt
27 |
28 |
29 | RUN make test-docker
30 | RUN make ipynb-docker
31 |
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | .. pccp documentation master file, created by
2 | sphinx-quickstart on Tue Aug 27 19:41:06 2013.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to Fidimag's documentation!
7 | ===================================
8 |
9 | .. image:: ./images/bobber_toron_vis.png
10 |
11 | Fidimag is a micromagnetic and atomistic simulation package, which can be used
12 | to simulate the magnetisation of nanoscale samples of materials.
13 |
14 | The code for Fidimag is available under an open source license on `GitHub
15 | `_.
16 |
17 | Contents:
18 |
19 | .. toctree::
20 | :maxdepth: 2
21 | :caption: Installation Instructions
22 |
23 | install
24 |
25 | .. toctree::
26 | :caption: User Guide
27 | :maxdepth: 2
28 |
29 | user_guide/index
30 |
31 | .. toctree::
32 | :maxdepth: 2
33 | :caption: Physics
34 |
35 | physics_num_methods/index
36 |
--------------------------------------------------------------------------------
/fidimag/atomistic/lib/fidimag_random.h:
--------------------------------------------------------------------------------
1 | #ifndef __FIDIMAG_RANDOM__
2 | #define __FIDIMAG_RANDOM__
3 |
4 |
5 |
6 | //#include
7 |
8 | #define WIDE_PI 3.1415926535897932384626433832795L
9 |
10 | //=================================================
11 | //random number, mt19937
12 | typedef struct {
13 | unsigned int MT[624];
14 | unsigned int matrix[2];// = { 0, 0x9908b0dfU};
15 | int index_t;
16 | int seed;
17 |
18 | } mt19937_state;
19 |
20 | #define MT19973_RAND_MAX 4294967295u
21 |
22 | mt19937_state *create_mt19937_state(void);
23 | void finalize_mt19937_state(mt19937_state *state);
24 |
25 | void initial_rng_mt19973(mt19937_state *state, int seed);
26 | //inline unsigned int rand_int(mt19937_state *state);
27 | double random_double_half_open(mt19937_state *state);
28 | int rand_int_n(mt19937_state *state, int n);
29 | void gauss_random_vector(mt19937_state *state, double *x, int n);
30 |
31 | void uniform_random_sphere(mt19937_state *state, double *spin, int n);
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/fidimag/common/field.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def vector_field(mesh, v):
5 | """
6 | Returns a np.array with values specified by `v`, where `v` should
7 | be a iterable of length 3, or a function that returns an iterable of
8 | length 3 when getting the coordinates of a cell of `mesh`.
9 |
10 | """
11 | return field(mesh, v, dim=3)
12 |
13 |
14 | def scalar_field(mesh, s):
15 | """
16 | Returns a np.array with values specified by `s`, where `s` should be
17 | a scalar, or a function that returns a scalar when getting the coordinates
18 | of a cell of `mesh`.
19 |
20 | """
21 | return field(mesh, s, dim=1)
22 |
23 |
24 | def field(mesh, val, dim):
25 | values = np.zeros(mesh.vector_shape()) if dim == 3 else np.zeros(mesh.scalar_shape())
26 |
27 | if hasattr(val, '__call__'):
28 | f = val
29 | else:
30 | f = lambda r: val
31 |
32 | for i, r in enumerate(mesh.coordinates):
33 | values[i] = f(r)
34 | return values
35 |
--------------------------------------------------------------------------------
/fidimag/atomistic/field.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def vector_field(mesh, v):
5 | """
6 | Returns a np.array with values specified by `v`, where `v` should
7 | be a iterable of length 3, or a function that returns an iterable of
8 | length 3 when getting the coordinates of a cell of `mesh`.
9 |
10 | """
11 | return field(mesh, v, dim=3)
12 |
13 |
14 | def scalar_field(mesh, s):
15 | """
16 | Returns a np.array with values specified by `s`, where `s` should be
17 | a scalar, or a function that returns a scalar when getting the coordinates
18 | of a cell of `mesh`.
19 |
20 | """
21 | return field(mesh, s, dim=1)
22 |
23 |
24 | def field(mesh, val, dim):
25 | values = np.zeros(mesh.vector_shape()) if dim == 3 else np.zeros(mesh.scalar_shape())
26 |
27 | if hasattr(val, '__call__'):
28 | f = val
29 | else:
30 | f = lambda r: val
31 |
32 | for i, r in enumerate(mesh.coordinates):
33 | values[i] = f(r)
34 | return values
35 |
--------------------------------------------------------------------------------
/bin/install-scikit-odes.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | # This script installs the python bindings to SUNDIALS called scikit ODES.
5 | # It requires SUNDIALS 2.6.2 to be installed.
6 |
7 | echo "Installing dependencies."
8 | sudo apt-get install python-dev
9 | sudo pip install scipy numpy cython enum34
10 |
11 | HERE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
12 | FIDIMAG_DIR="$(dirname "$HERE_DIR")"
13 | LIBS_DIR=${FIDIMAG_DIR}/local
14 |
15 | echo "Downloading ODES to "${LIBS_DIR}"."
16 | mkdir -p ${LIBS_DIR}
17 | cd ${LIBS_DIR}
18 |
19 | git clone git://github.com/bmcage/odes.git odes
20 | cd odes
21 |
22 | # Paths to SUNDIALS are hardcoded in odes/scikits/odes/sundials/setup.py.
23 | # The README recommends to edit that file if you want to change the paths...
24 |
25 | sed -i \
26 | "s|LIB_DIRS_SUNDIALS = \[base_path\,|LIB_DIRS_SUNDIALS = [base_path, '${LIBS_DIR}\/lib',|g" \
27 | scikits/odes/sundials/setup.py
28 |
29 | python setup.py build
30 | sudo python setup.py install
31 |
32 | cd ${HERE_DIR}
33 |
--------------------------------------------------------------------------------
/examples/atomistic/dmi/dmi_1d.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim, DMI, UniformExchange
3 | from fidimag.common import CuboidMesh
4 |
5 | def init_m(pos):
6 | x, y, z = pos
7 | if x < 50:
8 | return (0, 0, 1)
9 | elif x > 50 - 1:
10 | return (0, 1, -1)
11 | else:
12 | return (0, 1, 0)
13 |
14 |
15 | def relax_system(mesh):
16 |
17 | sim = Sim(mesh, name='relax')
18 | sim.driver.alpha = 0.1
19 |
20 | sim.set_m(init_m)
21 |
22 | J = 1
23 | exch = UniformExchange(J)
24 | sim.add(exch)
25 |
26 | dmi = DMI(0.05 * J)
27 | sim.add(dmi)
28 |
29 | ts = np.linspace(0, 1, 11)
30 | for t in ts:
31 | print t, sim.spin_length() - 1
32 | sim.run_until(t)
33 |
34 | sim.save_vtk()
35 |
36 | return sim.spin
37 |
38 |
39 | if __name__ == '__main__':
40 |
41 | mesh = CuboidMesh(nx=20, ny=1, nz=1, pbc=None)
42 |
43 | m0 = relax_system(mesh)
44 | print 'relax system done'
45 | # spin_wave(mesh,m0)
46 |
--------------------------------------------------------------------------------
/docker/notebook/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM jupyter/scipy-notebook
2 | # where to install source
3 | USER root
4 | RUN mkdir -p /io
5 | RUN chown $NB_USER /io
6 | RUN apt update && apt install -y cmake
7 | USER $NB_USER
8 | ENV FIDIMAG_DIR /io
9 | WORKDIR /io
10 | RUN git clone https://github.com/rpep/fidimag.git
11 | WORKDIR /io/fidimag
12 | # install third party libraries from source
13 | RUN bash bin/install-fftw.sh
14 | RUN bash bin/install-sundials.sh
15 |
16 | # install pyvtk
17 | RUN pip install pyvtk
18 | # install cython
19 | RUN pip install cython --upgrade
20 |
21 | # compile fidimag
22 | RUN python3 setup.py build_ext --inplace
23 | RUN pip install psutil
24 | ENV PYTHONPATH=$FIDIMAG_DIR
25 | ENV LD_LIBRARY_PATH=$FIDIMAG_DIR/local/lib
26 | WORKDIR $FIDIMAG_DIR/tests
27 |
28 | # https://github.com/conda-forge/matplotlib-feedstock/issues/36
29 | RUN conda install --quiet --yes icu
30 |
31 | # check that tests run okay
32 | RUN conda install --quiet --yes pytest
33 |
34 | # /io will be mounted from the host system
35 | WORKDIR /io
36 |
37 |
--------------------------------------------------------------------------------
/examples/micromagnetic/nmag_example_2_box/sim.py:
--------------------------------------------------------------------------------
1 | """
2 | example 2 in the nmag manual
3 | from http://nmag.soton.ac.uk/nmag/0.2/manual/html/example2/doc.html
4 |
5 | """
6 | import numpy as np
7 | from fidimag.common import CuboidMesh
8 | from fidimag.micro import Sim, UniformExchange, Demag
9 |
10 | mesh = CuboidMesh(3, 3, 10/3.0, 10, 10, 30, unit_length=1e-9)
11 |
12 |
13 | def run(integrator, jacobian):
14 | name = "sim_" + integrator
15 | if integrator == "sundials":
16 | name += "_J1" if jacobian else "_J0"
17 | sim = Sim(mesh, name, integrator=integrator, driver='llg', use_jac=jacobian)
18 | sim.Ms = 0.86e6
19 | sim.driver.alpha = 0.5
20 | sim.set_m((1, 0, 1))
21 | sim.add(UniformExchange(A=13e-12))
22 | sim.add(Demag())
23 |
24 | ts = np.linspace(0, 3e-10, 61)
25 | for t in ts:
26 | print(f'Running until t = {t}')
27 | sim.driver.run_until(t)
28 |
29 | if __name__ == "__main__":
30 | run("sundials", False)
31 | run("sundials_diag", False)
32 | run("sundials", True)
33 |
--------------------------------------------------------------------------------
/examples/atomistic/PRL_111_067203/phase_res/plot.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 | import matplotlib.cm as cm
5 |
6 | import numpy as np
7 |
8 |
9 | def plot_res(Ts, Hs, res):
10 | mesh_x, mesh_y = np.meshgrid(Ts, Hs)
11 | res.shape = (len(Ts), len(Hs))
12 |
13 | fig = plt.figure(figsize=(6, 4))
14 |
15 | im = plt.imshow(np.transpose(res), cmap=cm.RdBu, extent=[
16 | Ts[0], Ts[-1], Hs[0], Hs[-1]], origin='lower', aspect='auto')
17 | plt.colorbar(im)
18 |
19 | plt.text(0.25, 0.4, 'FM')
20 | plt.text(0.05, 0.15, 'SkX')
21 | plt.text(0.1, 0.005, 'HL')
22 |
23 | plt.xlabel(r'$k_B T/J$')
24 | plt.ylabel('H')
25 | plt.title('Skyrmion number')
26 | plt.tight_layout()
27 |
28 | fig.savefig('phase.pdf')
29 |
30 |
31 | if __name__ == '__main__':
32 | # np.random.seed(125)
33 |
34 | Ts = np.linspace(0, 0.5, 11)
35 | Hs = np.linspace(0, 0.5, 11)
36 |
37 | res = np.load('res.npy')
38 |
39 | plot_res(Ts, Hs, res)
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.txt
2 | *.pyc
3 | *.ndt
4 | *.gch
5 | *.swp
6 | *.pdf
7 | *.tmp
8 | *.so
9 | *.o
10 |
11 | local/
12 | *~
13 | *.bak
14 | .DS_Store
15 | .pytest_cache/
16 | # ignore automatically generated cython files
17 | fidimag/atomistic/lib/clib.c
18 | fidimag/common/lib/common_clib.c
19 | fidimag/common/dipolar/dipolar.c
20 | fidimag/common/neb/neb_clib.c
21 | fidimag/common/neb_method/*clib.c
22 | fidimag/common/sundials/cvode.c
23 | fidimag/micro/lib/baryakhtar/baryakhtar_clib.c
24 | fidimag/micro/lib/micro_clib.c
25 | fidimag/user/example/example.c
26 |
27 | # ignore .cache from pytest
28 | .cache
29 |
30 | # ignore simulation data
31 | *_npys
32 | *_vtks
33 |
34 | # ignore output files from NEB method
35 | npys
36 | vtks
37 |
38 | /build/
39 | /doc/build/
40 |
41 |
42 | # ignore *.so created by cython
43 | fidimag/extensions/*.so
44 |
45 | # ignore output from coverage
46 | htmlcov
47 |
48 | # ignore junit test output
49 | test-reports
50 |
51 | # ignore notebook checkpoint directory
52 | .ipynb_checkpoints/
53 |
54 | *.npz
55 | *.npy
56 | fmm.cpp
--------------------------------------------------------------------------------
/bin/ubuntu_install_script.sh:
--------------------------------------------------------------------------------
1 | echo "Super user authentication required to add packages (you will be \
2 | prompted for confirmation)."
3 | sudo bash install-ubuntu-packages.sh
4 | sudo bash install-python-packages.sh
5 | bash install-fftw.sh
6 | bash install-sundials.sh
7 | pushd .. > /dev/null
8 | make
9 |
10 | # Adds fidimag environment variables to profile.d, if they're not already there.
11 | FIDIMAG_PROFILE_PATH=/etc/profile.d/fidimag.sh
12 | if [ ! -e "$FIDIMAG_PROFILE_PATH" ]; then
13 | echo "Warning: Adding Fidimag to path at $FIDIMAG_PROFILE_PATH."
14 | echo "Super user authentication required to add paths."
15 | sudo mkdir --parents "$(dirname $FIDIMAG_PROFILE_PATH)"
16 | sudo bash -c "echo \"export PYTHONPATH=$PWD/:\\\$PYTHONPATH\"\
17 | > $FIDIMAG_PROFILE_PATH"
18 | sudo bash -c "echo \"export LD_LIBRARY_PATH=$PWD/local/lib:\
19 | \\\$LD_LIBRARY_PATH\" >> $FIDIMAG_PROFILE_PATH"
20 | sudo chmod 0644 "$FIDIMAG_PROFILE_PATH"
21 | echo "Path written to $FIDIMAG_PROFILE_PATH."
22 | else
23 | echo "Path added previously. Skipping."
24 | fi
25 |
--------------------------------------------------------------------------------
/tests/test_time_zeeman.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.common import CuboidMesh
3 | from fidimag.micro import TimeZeeman
4 |
5 | def time_fun(t, frequency):
6 | return 10*np.cos(frequency*t)
7 |
8 | def fixture_setup(nx, ny, nz):
9 | """
10 | Fixtures for the tests
11 | """
12 | dx = 10.0/nx
13 | spin = np.zeros(3*nx*ny*nz)
14 | Ms = np.zeros(nx*ny*nz)
15 | Ms_inv = np.zeros(nx*ny*nz)
16 | mesh = CuboidMesh(nx=nx, ny=ny, nz=nz, dx=dx, dy=1, dz=1, unit_length=1e-9)
17 | frequency = 10e9
18 | return mesh, frequency, spin, Ms, Ms_inv
19 |
20 | def test_TimeZeeman():
21 | mesh, frequency, spin, Ms, Ms_inv = fixture_setup(10, 10, 10)
22 | zee = TimeZeeman(np.array([0.0, 0.0, 1.0]), time_fun, extra_args=[frequency])
23 | zee.setup(mesh, spin, Ms, Ms_inv)
24 | field1 = zee.compute_field(t=0)
25 | assert field1[0] == 0
26 | assert field1[1] == 0
27 | assert field1[2] == 10
28 | field2 = zee.compute_field(t=1)
29 | assert field2[0] == 0
30 | assert field2[1] == 0
31 | assert field2[2] == 10*np.cos(frequency)
32 |
--------------------------------------------------------------------------------
/tests/test_add_remove_interaction.py:
--------------------------------------------------------------------------------
1 | from fidimag.common import CuboidMesh, constant
2 | from fidimag.micro import UniformExchange, Sim, Zeeman
3 | import numpy as np
4 |
5 | def test_add_remove_interaction_simple():
6 | mesh = CuboidMesh(nx=10, ny=10, nz=10, unit_length=1e-9)
7 | name = 'test_add_remove_intn_simple'
8 | sim = Sim(mesh, name=name)
9 | sim.set_m(lambda pos: (0, 0, 1))
10 | sim.set_Ms(5.8e5)
11 | exch = UniformExchange(A=1e-11, name='Exchange')
12 | zee = Zeeman((0, 0, 0.05 / constant.mu_0), name='Zeeman')
13 | sim.add(exch)
14 | sim.add(zee)
15 | sim.driver.run_until(1e-9)
16 | sim.remove('Zeeman')
17 | sim.driver.run_until(2e-9)
18 | f = open(name + '.txt')
19 | lines = f.read().split('\n')
20 | headers = lines[0].split()
21 | first_data = lines[2].split()
22 | last_data = lines[2].split()
23 | # Find the position in the data table
24 | position = headers.index('E_Zeeman')
25 | assert np.abs(float(last_data[position])) < 1e-15
26 |
27 | if __name__ == '__main__':
28 | test_add_remove_interaction_simple()
--------------------------------------------------------------------------------
/sandbox/memory_leak/fidimag_memory_issue_example.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python2
2 |
3 | # This script creates multiple fidimag simulation objects and shows how much
4 | # memory (maybe) the simulation objects claim in memory.
5 |
6 | import fidimag
7 | import gc
8 | import resource
9 | import sys
10 |
11 |
12 | def create_simulation():
13 | return fidimag.micro.Sim(fidimag.micro.CuboidMesh(x0=-200, dx=1, nx=400,
14 | y0=-200, dy=1, ny=400,
15 | unit_length=1e-9, pbc="xy"),
16 | name="resource_test")
17 |
18 | def measure_memory():
19 | return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
20 |
21 |
22 | print("Initial memory before simulation creation: {}MB?".format(measure_memory()/1024.**2))
23 | for zI in range(30):
24 | sim = create_simulation()
25 | gc.collect()
26 | print("Memory after creation of simulation {:02d}: {}MB?"\
27 | .format(zI + 1, measure_memory()/1024.**2))
28 | print("\tReference count: {}".format(sys.getrefcount(sim)))
29 |
--------------------------------------------------------------------------------
/examples/atomistic/dmi/dmi_2d.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim, DMI, UniformExchange
3 | from fidimag.common import CuboidMesh
4 |
5 | import time
6 |
7 |
8 | def init_m(pos):
9 |
10 | x, y, z = pos
11 | if x < 50:
12 | return (0, 0, 1)
13 | elif x > 50:
14 | return (0, 0, -1)
15 | else:
16 | return (0, 1, 0)
17 |
18 |
19 | def relax_system(mesh):
20 |
21 | sim = Sim(mesh, name='dmi_2d')
22 | sim.driver.alpha = 0.1
23 | sim.driver.gamma=1.76e11
24 | sim.mu_s = 1e-22
25 |
26 | J = 1e-20
27 | exch = UniformExchange(J)
28 | sim.add(exch)
29 |
30 | dmi = DMI(0.1 * J)
31 | sim.add(dmi)
32 |
33 | sim.set_m(init_m)
34 |
35 | ts = np.linspace(0, 5e-10, 101)
36 | for t in ts:
37 | print(t)
38 | sim.run_until(t)
39 | #sim.save_vtk()
40 |
41 | return sim.spin
42 |
43 | if __name__ == '__main__':
44 |
45 | mesh = CuboidMesh(
46 | nx=1000, ny=1000, nz=1, dx=0.5, dy=0.5, dz=0.5, unit_length=1e-10)
47 |
48 | m0 = relax_system(mesh)
49 | print 'relax system done'
50 |
--------------------------------------------------------------------------------
/examples/atomistic/skyrmion/skx_rotation/deal_m.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | from moviepy.video.io.bindings import mplfig_to_npimage
4 | from moviepy.editor import VideoClip
5 | import moviepy.editor as mpy
6 | import matplotlib.cm as cm
7 |
8 | duration = 10
9 |
10 | def read_data(i):
11 | m = np.load('dyn_npys/m_%d.npy'%i)
12 | m.shape = (-1,3)
13 | mx = m[:,2]
14 | mx.shape=(140,140)
15 | return mx
16 |
17 | fig_mpl, ax = plt.subplots(1,figsize=(5,5), facecolor='white')
18 |
19 | mx = read_data(0)
20 | myobj = ax.imshow(np.transpose(mx),origin='lower',cmap=cm.rainbow)
21 | ax.set_title('t= 0 ns')
22 |
23 |
24 | # ANIMATE WITH MOVIEPY (UPDATE THE CURVE FOR EACH t). MAKE A GIF.
25 |
26 | def make_frame_mpl(t):
27 | myobj.set_data(read_data(int(t*20)))
28 | ax.set_title('t= %0.2f ns'%(t*40*0.01))
29 | #fig_mpl.savefig('test.png')
30 | #line.set_ydata() # <= Update the curve
31 | return mplfig_to_npimage(fig_mpl) # RGB image of the figure
32 |
33 | animation = mpy.VideoClip(make_frame_mpl, duration=duration)
34 | animation.write_gif("skx.gif", fps=20)
35 |
--------------------------------------------------------------------------------
/.github/workflows/superlinter.yml:
--------------------------------------------------------------------------------
1 | name: Super-Linter
2 |
3 | # Run this workflow every time a new commit pushed to your repository
4 | on: push
5 |
6 | jobs:
7 | # Set the job key. The key is displayed as the job name
8 | # when a job name is not provided
9 | super-lint:
10 | # Name the Job
11 | name: Lint code base
12 | # Set the type of machine to run on
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | ##########################
17 | # Checkout the code base #
18 | ##########################
19 | - name: Checkout Code
20 | uses: actions/checkout@v2
21 | with:
22 | # Full git history is needed to get a proper list of changed files within `super-linter`
23 | fetch-depth: 0
24 |
25 | # Runs the Super-Linter action
26 | - name: Run Super-Linter
27 | uses: github/super-linter@v4
28 | env:
29 | VALIDATE_ALL_CODEBASE: true
30 | DEFAULT_BRANCH: master
31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32 | FILTER_REGEX_EXCLUDE: .*fidimag/atomistic/fmmlib/*.*
33 | FILTER_REGEX_EXCLUDE: .*fidimag/atomistic/lib/fmmlib/*.*
34 |
--------------------------------------------------------------------------------
/tests/test_2dpbc_cube.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | import numpy as np
3 | from fidimag.micro import Sim
4 | from fidimag.common import CuboidMesh
5 | from fidimag.micro import Demag
6 |
7 | mu0 = 4 * np.pi * 1e-7
8 |
9 |
10 | def test_compute_field():
11 | """In an infinite film, we expect the demag tensor to be (0, 0, -1), and thus the
12 | magnetisation, if aligned in 0, 0, 1 direction, to create a demag field pointing
13 | with equal strength in the opposite direction.
14 | """
15 |
16 | mesh = CuboidMesh(nx=1, ny=1, nz=1, dx=2.0, dy=2.0, dz=2.0,
17 | unit_length=1e-9, periodicity=(True, True, False))
18 |
19 | sim = Sim(mesh, name='relax')
20 |
21 | sim.driver.set_tols(rtol=1e-10, atol=1e-14)
22 | sim.alpha = 0.5
23 | sim.gamma = 2.211e5
24 | sim.Ms = 8.6e5
25 | sim.do_precession = False
26 |
27 | sim.set_m((0, 0, 1))
28 |
29 | demag = Demag(pbc_2d=True)
30 | sim.add(demag)
31 | field = demag.compute_field()
32 | print((1 + field[2] / 8.6e5))
33 | assert abs(1 + field[2] / 8.6e5) < 1e-10
34 |
35 |
36 | if __name__ == '__main__':
37 | test_compute_field()
38 |
--------------------------------------------------------------------------------
/docker/notebook/Readme.md:
--------------------------------------------------------------------------------
1 | # Docker
2 |
3 | First steps towards running fidimag through Docker.
4 |
5 | ## Using the docker container
6 |
7 | There is a fidimag container available under `fangohr/fidimag`.
8 |
9 | To use it, you can try this:
10 |
11 | 1. Install docker
12 |
13 | 2. Pull the container onto your machine using
14 |
15 | docker pull fidimag/notebook
16 |
17 | 3. Start the container using
18 |
19 | docker run -v `pwd`:/io -p 30008:8888 fidimag/notebook
20 |
21 | This will start a notebook server. You can see it in your browser at
22 | http://localhost:30008/ on Linux and Mac (you may
23 | need to change this IP address if your docker VM is at a different address).
24 |
25 | You will need to
26 | To run a shell instead of the notebook server, run:
27 |
28 | docker run -v `pwd`:/io -ti fidimag/notebook bash
29 |
30 | ## Shortcomings
31 |
32 | - need to share directory between host and container (MOUNT or VOLUME)
33 |
34 |
35 | ## Creating the docker container
36 |
37 | The `Makefile` in this directory shows the relevant targets (build, login, push)
38 | to create a new container and push it to the the cloud.
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "fidimag"
3 | dynamic = ["version"]
4 | description = "Atomistic and Finite-DIfference microMAGnetic code, based on Python, Cython and C "
5 | readme = "README.md"
6 | # Not fully supported:
7 | # license-files = ["LICENSE.txt"]
8 | # license = "BSD-2-Clause"
9 | requires-python = ">= 3.10"
10 | dependencies = [
11 | 'numpy',
12 | 'scipy',
13 | 'cython>=3.0.0',
14 | 'pytest',
15 | 'matplotlib',
16 | 'ipywidgets',
17 | 'pyvtk',
18 | 'ipython',
19 | 'psutil'
20 | ]
21 | authors = [
22 | { name = "Weiwei Wang" },
23 | { name = "David Cortes Ortuno" },
24 | { name = "Ryan Pepper" },
25 | { name = "Hans Fangohr" },
26 | { name = "Marc-Antonio Bisotti" },
27 | { name = "Thomas Kluyver" },
28 | { name = "Mark Vousden" },
29 | { name = "Oliver Laslett" },
30 | { name = "Rebecca Carey" },
31 | ]
32 |
33 | maintainers = [
34 | {name = "David Cortes Ortuno", email = "david.cortes.o@gmail.com"},
35 | {name = "Ryan Pepper"}
36 | ]
37 |
38 | [build-system]
39 | build-backend = "setuptools.build_meta"
40 | requires = [
41 | "setuptools",
42 | "numpy",
43 | "cython>=3.0.0",
44 | ]
45 |
--------------------------------------------------------------------------------
/tests/test_anis.py:
--------------------------------------------------------------------------------
1 | from fidimag.atomistic import Anisotropy, CubicAnisotropy
2 | from fidimag.common import CuboidMesh
3 | from fidimag.atomistic import Sim
4 | import numpy as np
5 |
6 |
7 | def test_anis():
8 | mesh = CuboidMesh(nx=5, ny=3, nz=2)
9 | spin = np.zeros(90)
10 | anis = Anisotropy(Ku=1, axis=[1, 0, 0])
11 | mu_s = np.ones(90)
12 | mu_s_inv = np.ones(90)
13 | anis.setup(mesh, spin, mu_s, mu_s_inv)
14 | field = anis.compute_field()
15 | assert len(mesh.coordinates) == 5 * 3 * 2
16 | assert np.max(field) == 0
17 | spin[0] = 99
18 | field = anis.compute_field()
19 | assert field[0] == 2 * 99
20 |
21 | def test_anis_cubic():
22 | mesh = CuboidMesh(nx=1, ny=1, nz=1)
23 | spin = np.array([0.6,0.8,0])
24 | anis = CubicAnisotropy(Kc=1.23)
25 | mu_s = np.ones(3)
26 | mu_s_inv = np.ones(3)
27 | anis.setup(mesh, spin, mu_s, mu_s_inv)
28 | field = anis.compute_field()
29 | assert np.max(field-np.array([-1.06272,-2.51904, -0.]))<1e-6
30 | energy = anis.compute_energy()
31 | assert abs(energy-0.663216)<1e-5
32 |
33 |
34 | if __name__ == '__main__':
35 | test_anis()
36 | test_anis_cubic()
37 |
--------------------------------------------------------------------------------
/doc/todo.org:
--------------------------------------------------------------------------------
1 | * TODO [0/1]
2 | 1) [ ] Documentation
3 | - [ ] Add docstrings to the Cythonised functions which are exposed to the user; e.g fidimag.micro.sim.Sim
4 |
5 | 2) [1/2] Update dependencies
6 | - [X] FFTW 3.3.3 -> 3.3.4
7 | - [1/1] Sundials ->
8 | - [X] Get it to build
9 | - cmake -DCMAKE_INSTALL_PREFIX=$PWD CC=gcc-5 OPENMP_ENABLE=ON sundials-2.6.2
10 | - make install
11 | - [ ] Get Fidimag to link with it
12 | - Not sure what the problem is here - failed to load library with error:
13 |
14 | fidimag/atomistic/llg.py:5: in
15 | import fidimag.extensions.clib as clib
16 | ImportError: dlopen(/Users/ryan/Git/fidimag/fidimag/extensions/clib.so, 2):
17 | Library not loaded: libsundials_cvodes.2.dylib │
18 | Referenced from: /Users/ryan/Git/fidimag/fidimag/extensions/clib.so │
19 | Reason: image not found
20 |
21 |
22 |
--------------------------------------------------------------------------------
/fidimag/micro/simple_demag.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from .energy import Energy
3 |
4 |
5 | class SimpleDemag(Energy):
6 | """
7 | Demagnetising field for thin films in the i-direction.
8 | Hj = Hk = 0 and Hi = - Mi.
9 |
10 | """
11 | def __init__(self, Nx=0, Ny=0.5, Nz=0.5, name='SimpleDemag'):
12 | """
13 | field_strength is Ms by default
14 |
15 | """
16 |
17 | self.Nx = Nx
18 | self.Ny = Ny
19 | self.Nz = Nz
20 | self.name = name
21 |
22 |
23 | def compute_field(self, t=0):
24 | self.spin.shape = (3,-1)
25 | self.field.shape = (3,-1)
26 | self.field[0][:] = -self.Nx*self.spin[0][:]*self.Ms[:]
27 | self.field[1][:] = -self.Ny*self.spin[1][:]*self.Ms[:]
28 | self.field[2][:] = -self.Nz*self.spin[2][:]*self.Ms[:]
29 | self.spin.shape = (-1,)
30 | self.field.shape = (-1,)
31 | return self.field
32 |
33 | def compute_energy(self):
34 |
35 | mu_0 = 4*np.pi*1e-7
36 | sf = -0.5 * self.field * self.spin * mu_0
37 | energy = np.sum(sf.reshape(-1, 3), axis=1) * self.Ms
38 |
39 | return energy * self.mesh.cellsize
40 |
--------------------------------------------------------------------------------
/examples/micromagnetic/pbc_2d/single_cube.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from fidimag.micro import Sim
7 | from fidimag.common import CuboidMesh
8 | from fidimag.micro import UniformExchange, Demag, DMI
9 | from fidimag.micro import Zeeman, TimeZeeman
10 | from fidimag.common.fileio import DataReader
11 |
12 | mu0 = 4 * np.pi * 1e-7
13 |
14 |
15 | def compute_field():
16 |
17 | mesh = CuboidMesh(nx=1, ny=1, nz=1, dx=2.0, dy=2.0, dz=2.0, unit_length=1e-9, periodicity=(True, True, False))
18 |
19 | sim = Sim(mesh, name='relax')
20 |
21 | sim.driver.set_tols(rtol=1e-10, atol=1e-14)
22 | sim.driver.alpha = 0.5
23 | sim.driver.gamma = 2.211e5
24 | sim.Ms = 8.6e5
25 | sim.do_precession = False
26 |
27 | sim.set_m((0,0,1))
28 | # sim.set_m(np.load('m0.npy'))
29 |
30 | A = 1.3e-11
31 | exch = UniformExchange(A=A)
32 | sim.add(exch)
33 |
34 | demag = Demag(pbc_2d=True)
35 | sim.add(demag)
36 | field=demag.compute_field()
37 | print(field)
38 |
39 | np.save('m0.npy', sim.spin)
40 |
41 |
42 | if __name__ == '__main__':
43 |
44 | compute_field()
45 |
--------------------------------------------------------------------------------
/tests/test_check_ms_inv_sensible.py:
--------------------------------------------------------------------------------
1 | import fidimag
2 | import numpy as np
3 |
4 | def setup_fixture_micro(driver='llg'):
5 | mesh = fidimag.common.CuboidMesh(nx=3, ny=3, nz=3,
6 | dx=1, dy=1, dz=1,
7 | unit_length=1e-9)
8 | sim = fidimag.micro.Sim(mesh, driver=driver)
9 | return mesh, sim
10 |
11 |
12 | def setup_fixture_atomistic(driver='llg'):
13 | mesh = fidimag.common.CuboidMesh(nx=3, ny=3, nz=3,
14 | dx=1, dy=1, dz=1,
15 | unit_length=1e-9)
16 | sim = fidimag.atomistic.Sim(mesh, driver=driver)
17 | return mesh, sim
18 |
19 | def set_Ms(pos):
20 | if pos[0] < 2:
21 | return 0
22 | else:
23 | return 5e8
24 |
25 | def test_llg_Ms_inv():
26 | mesh, sim = setup_fixture_micro()
27 | sim.set_Ms(set_Ms)
28 | assert np.isnan(np.dot(sim._magnetisation_inv, sim._magnetisation_inv)) == False
29 |
30 | def test_llg_atomistic_mu_s_inv():
31 | mesh, sim = setup_fixture_atomistic()
32 | sim.set_mu_s(set_Ms)
33 | assert np.isnan(np.dot(sim._magnetisation_inv, sim._magnetisation_inv)) == False
34 |
--------------------------------------------------------------------------------
/tests/test_spatial_exch.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim
3 | from fidimag.common import CuboidMesh
4 | from fidimag.atomistic import Exchange
5 |
6 |
7 | def init_m(pos):
8 | x, y, z = pos
9 | return (x - 0.5, y - 0.5, z - 0.5)
10 |
11 |
12 | def spatial_J(pos):
13 | x, y, z = pos
14 | if x < 5:
15 | return (-1.0, -1.0, -1.0, -1.0, -1.0, -1.0)
16 | elif x < 6:
17 | return (-1.0, 0.3, -1.0, -1.0, -1.0, -1.0)
18 | elif x > 7:
19 | return (1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
20 | elif x > 6:
21 | return (0.3, 1.0, 1.0, 1.0, 1.0, 1.0)
22 |
23 |
24 | def test_exch_1d_spatial():
25 | """
26 | Test the x component of the exchange field
27 | in a 1D mesh, with the spin ordering:
28 |
29 | 0 1 2 3 4 5
30 |
31 | """
32 | mesh = CuboidMesh(nx=12, ny=1, nz=1)
33 | sim = Sim(mesh)
34 | exch = Exchange(spatial_J)
35 | sim.add(exch)
36 |
37 | sim.set_m(init_m, normalise=False)
38 |
39 | field = exch.compute_field()
40 |
41 | assert exch._J[3, 3] == -1.0
42 | assert exch._J[5, 1] == 0.3
43 | assert exch._J[6, 0] == 0.3
44 | assert exch._J[8, 5] == 1.0
45 |
46 |
47 | if __name__ == '__main__':
48 | test_exch_1d_spatial()
49 |
--------------------------------------------------------------------------------
/sandbox/more-dmi/isolated_sk_T-Oxs_DMI_T-Field-00-0000000.ohf:
--------------------------------------------------------------------------------
1 | # OOMMF OVF 2.0
2 | #
3 | # Segment count: 1
4 | #
5 | # Begin: Segment
6 | # Begin: Header
7 | #
8 | # Title: Oxs_DMI_T::Field
9 | # Desc: Oxs vector field output
10 | # Desc: MIF source file: /Users/ryan/git/fidimag/sandbox/more-dmi/test_dmi_multi.mif
11 | # Desc: Iteration: 0, State id: 179
12 | # Desc: Stage: 0, Stage iteration: 0
13 | # Desc: Stage simulation time: -1 s
14 | # Desc: Total simulation time: -2 s
15 | # meshunit: m
16 | # meshtype: rectangular
17 | # xbase: 3.7499999999999997e-09
18 | # ybase: 7.4999999999999993e-09
19 | # zbase: 7.4999999999999993e-09
20 | # xnodes: 2
21 | # ynodes: 1
22 | # znodes: 1
23 | # xstepsize: 7.4999999999999993e-09
24 | # ystepsize: 1.4999999999999999e-08
25 | # zstepsize: 1.4999999999999999e-08
26 | # xmin: 0
27 | # ymin: 0
28 | # zmin: 0
29 | # xmax: 1.4999999999999999e-08
30 | # ymax: 1.4999999999999999e-08
31 | # zmax: 1.4999999999999999e-08
32 | # valuedim: 3
33 | # valuelabels: Field_x Field_y Field_z
34 | # valueunits: A/m A/m A/m
35 | #
36 | # End: Header
37 | #
38 | # Begin: Data Text
39 | -0.00000000000000 -376184.410944480 -0.00000000000000
40 | -0.00000000000000 376184.410944480 -0.00000000000000
41 | # End: Data Text
42 | # End: Segment
43 |
--------------------------------------------------------------------------------
/examples/micromagnetic/PRB_88_184422/oommf/dmi.mif:
--------------------------------------------------------------------------------
1 | # MIF 2.1
2 |
3 | Specify Oxs_MultiAtlas:atlas {
4 | atlas { Oxs_BoxAtlas:world {
5 | xrange {0 100e-09}
6 | yrange {0 1e-09}
7 | zrange {0 1e-09}
8 | name world
9 | } }
10 | }
11 |
12 | Specify Oxs_RectangularMesh:mesh [subst {
13 | cellsize {1e-9 1e-09 1e-09}
14 | atlas :atlas
15 | }]
16 |
17 | Specify Oxs_UniformExchange {
18 | A 16e-12
19 | }
20 |
21 | Specify Oxs_DMExchange6Ngbr [subst {
22 | default_D 3.6e-3
23 | atlas :atlas
24 | D {
25 | world world 3.6e-3
26 | }
27 | }]
28 |
29 | Specify Oxs_UniaxialAnisotropy {
30 | axis {0 0 1}
31 | K1 510e3
32 | }
33 |
34 | Specify Oxs_RungeKuttaEvolve:evolve {
35 | alpha 0.5
36 | }
37 |
38 | Specify Oxs_TimeDriver [subst {
39 | basename dmi
40 | evolver :evolve
41 | stage_count 1
42 | stopping_dm_dt 0.01
43 | mesh :mesh
44 |
45 | Ms 8.6e5
46 |
47 | m0 { Oxs_ScriptVectorField {
48 | atlas :atlas
49 | script_args {rawpt}
50 | script init_m0
51 | norm 1
52 | } }
53 | }]
54 |
55 | proc init_m0 { x y z} {
56 | return [list 0 0 1]
57 | }
58 |
59 | Destination archive mmArchive
60 | Schedule DataTable archive Stage 1
61 | Schedule Oxs_TimeDriver::Magnetization archive Stage 1
62 |
--------------------------------------------------------------------------------
/tests/test_stt_slonczewski.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 |
3 | import numpy as np
4 | from fidimag.atomistic import Sim, DMI, UniformExchange, Zeeman, Anisotropy
5 | from fidimag.common import CuboidMesh, DataReader
6 |
7 |
8 | def test_dynamic():
9 |
10 | mesh = CuboidMesh(nx=1, ny=1, nz=1)
11 |
12 | sim = Sim(mesh, name='dyn_spin', driver='llg_stt_cpp')
13 | # sim.set_options(rtol=1e-10,atol=1e-14)
14 | sim.driver.gamma = 1.0
15 | sim.mu_s = 1.0
16 |
17 | sim.set_m((0.8,0,-1))
18 |
19 | Kx = Anisotropy(Ku=-0.05, axis=(0, 0, 1), name='Kz')
20 | sim.add(Kx)
21 |
22 | sim.p = (0,0,1)
23 |
24 | sim.a_J = 0.0052
25 | sim.alpha = 0.1
26 |
27 | ts = np.linspace(0, 1200, 401)
28 | for t in ts:
29 | sim.driver.run_until(t)
30 |
31 |
32 | mz = sim.spin[2]
33 | alpha, K, u = 0.1, 0.05, 0.0052
34 | print(mz, u/(2*alpha*K))
35 |
36 | #########################################################
37 | # The system used in this test can be solved analytically, which gives that mz = u/(2*alpha*K),
38 | # where K represents the easy-plane anisotropy.
39 | ###
40 | assert abs(mz - u/(2*alpha*K))/mz< 5e-4
41 |
42 |
43 |
44 |
45 | if __name__ == '__main__':
46 |
47 | test_dynamic()
48 |
--------------------------------------------------------------------------------
/bin/fix_load_path_mac.py:
--------------------------------------------------------------------------------
1 | """
2 | Creates working dylibs on Mac OS X by adding the full path to referenced libraries.
3 | This fixes ImportErrors that may appear starting with SUNDIALS 2.6.
4 |
5 | """
6 | import os
7 | import glob
8 | import re
9 | import subprocess
10 |
11 | THIS_FILE = os.path.dirname(os.path.abspath(__file__))
12 | MODULE_DIR = os.path.abspath(os.path.join(THIS_FILE, os.pardir))
13 | LIB_DIR = os.path.join(MODULE_DIR, "local", "lib")
14 |
15 | EXTENSION_DIR = os.path.join(MODULE_DIR, "fidimag", "extensions")
16 |
17 | sos = glob.glob(os.path.join(EXTENSION_DIR, "*.so"))
18 |
19 | patten = re.compile(r'libsundials[\w.]+\.dylib')
20 | def extract_library(so_file):
21 | cmd = ('otool', '-L', so_file)
22 | output = subprocess.check_output(cmd)
23 | for line in output.decode().split('\t'):
24 | m = patten.match(line)
25 | print(m, line)
26 | if m:
27 | lib_name = m.group()
28 | full_name = os.path.join(LIB_DIR, lib_name)
29 | print(lib_name, full_name)
30 | cmd = ('install_name_tool', '-change',
31 | lib_name, full_name, so_file
32 | )
33 | os.system(' '.join(cmd))
34 |
35 | for so in sos:
36 | extract_library(so)
37 | print("Done for %s!"%so)
38 |
--------------------------------------------------------------------------------
/fidimag/micro/lib/baryakhtar/baryakhtar_clib.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | //#include
4 |
5 | #define WIDE_PI 3.1415926535897932384626433832795L
6 | #define MU0 1.25663706143591728850e-6
7 |
8 | inline double cross_x(double a0, double a1, double a2, double b0, double b1, double b2) { return a1*b2 - a2*b1; }
9 | inline double cross_y(double a0, double a1, double a2, double b0, double b1, double b2) { return a2*b0 - a0*b2; }
10 | inline double cross_z(double a0, double a1, double a2, double b0, double b1, double b2) { return a0*b1 - a1*b0; }
11 |
12 | void compute_laplace_m(double *m, double *field, double *Ms, double dx, double dy, double dz,
13 | int nx, int ny, int nz);
14 |
15 | void compute_relaxation_field_c(double *m, double *field, double *Ms, double chi_inv, int n);
16 |
17 | void compute_perp_field_c(double *m, double *field, double *field_p, int n);
18 |
19 | void llg_rhs_baryakhtar(double *dm_dt, double *m, double *h, double *delta_h,
20 | double *alpha, double beta, int *pins,
21 | double gamma, int nxyz, int do_precession);
22 |
23 |
24 | void llg_rhs_baryakhtar_reduced(double *dm_dt, double *m, double *hp, double *delta_hp,
25 | double *alpha, double beta, int *pins,
26 | double gamma, int nxyz, int do_precession, double default_c);
27 |
--------------------------------------------------------------------------------
/fidimag/user/README.md:
--------------------------------------------------------------------------------
1 | # User Extensions
2 |
3 | The user extensions directory is here to allow for
4 | the user to be able to straightforwardly run compiled
5 | code within Fidimag for performance reasons. We
6 | consider this an advanced feature and do not recommend
7 | trying this unless you have experience writing and
8 | building C/Cython programs.
9 |
10 | Some of the energy classes perform callbacks to
11 | user-supplied functions. Performance for this
12 | is generally poor, as there is an overhead to
13 | calling Python functions repeatedly. Hence,
14 | we place this folder here to allow you to expose
15 | functions written in Cython/C conveniently.
16 |
17 | An example has been supplied. We suggest copying
18 | the folder and modifying each of the files in
19 | this. Please note that we have automated the
20 | building of the extensions, but you can only
21 | have a single Cython .pyx file per directory,
22 | because a single Cython module is created in
23 | each folder. The module that is created will have
24 | the name of this file.
25 |
26 | You do not explicitly need to write an __init__.py file;
27 | your extension will be importable immediately from
28 | fidimag.extensions.user.$FOLDERNAME
29 |
30 | The __init__.py file lets you do the slightly shorter:
31 | from fidimag.user.$FOLDERNAME import *
32 |
33 |
--------------------------------------------------------------------------------
/bin/install-fftw.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This script installs FFTW locally. It may need to environment
4 | # variables to work, like 'export CC=gcc' in ARCHER.
5 |
6 | FFTW=fftw-3.3.8
7 |
8 | set -e
9 |
10 | # Create target directory if needed.
11 |
12 |
13 | HERE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
14 | FIDIMAG_DIR="$(dirname "$HERE_DIR")"
15 |
16 | if [ -z $LIBS_DIR ]; then LIBS_DIR=${FIDIMAG_DIR}/local; fi
17 |
18 | mkdir -p $LIBS_DIR
19 | cd ${LIBS_DIR}
20 | echo "Installing FFTW to "$LIBS_DIR"."
21 | echo "Using CC="$CC" "
22 |
23 | download_and_install() {
24 | # $1 name of the package
25 | # $2 URL where ${1}.tar.gz can be obtained
26 | # $3 configure options
27 | if [ ! -e ${1}.tar.gz ]; then
28 | echo "Downloading "${1}"."
29 | wget -q ${2}/${1}.tar.gz
30 | fi;
31 |
32 | if [ ! -e ${1} ]; then
33 | tar -xzf ${1}.tar.gz
34 | cd ${1}
35 | echo "Configuring "${1}"."
36 | ./configure --quiet --enable-shared --enable-openmp --prefix=${LIBS_DIR}
37 | echo "Compiling and installing "${1}"."
38 | {
39 | make -j2
40 | make install
41 | } > /dev/null
42 | echo "Done."
43 | cd ${LIBS_DIR}
44 | fi;
45 | }
46 |
47 | download_and_install ${FFTW} http://www.fftw.org
48 |
49 | echo "Installation succesful."
50 |
--------------------------------------------------------------------------------
/fidimag/micro/energy.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | class Energy(object):
5 |
6 | """
7 | An abstract class to implement the basic functions such as setup in micromagnetics.
8 | """
9 |
10 | def setup(self, mesh, spin, Ms, Ms_inv):
11 | self.mesh = mesh
12 | self.dx = mesh.dx * mesh.unit_length
13 | self.dy = mesh.dy * mesh.unit_length
14 | self.dz = mesh.dz * mesh.unit_length
15 | self.dxyz = self.dx * self.dy * self.dz
16 | self.nx = mesh.nx
17 | self.ny = mesh.ny
18 | self.nz = mesh.nz
19 | self.spin = spin
20 | self.n = mesh.n
21 |
22 | self.field = np.zeros(3 * mesh.n)
23 | self.energy = np.zeros(mesh.n)
24 | self.total_energy = 0
25 | self.Ms = Ms
26 | self.Ms_inv = Ms_inv
27 |
28 | # For old code compatibility
29 | self.xperiodic, self.yperiodic, self.zperiodic = mesh.periodicity
30 |
31 | self.neighbours = mesh.neighbours
32 |
33 | def compute_field(self, t=0):
34 |
35 | return 0
36 |
37 | def compute_energy(self):
38 |
39 | # since we are not always calling this function, so it's okay to call
40 | # compute_field again
41 | self.compute_field()
42 |
43 | self.total_energy = np.sum(self.energy) * self.dxyz
44 |
45 | return self.total_energy
46 |
--------------------------------------------------------------------------------
/examples/micromagnetic/baryakhtar/relax_system.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 |
6 | from fidimag.common import CuboidMesh
7 | from fidimag.micro import Sim
8 | from fidimag.micro import Demag
9 | from fidimag.micro import Zeeman
10 | from fidimag.micro import UniformExchange
11 |
12 |
13 | def relax_system(mesh):
14 |
15 | sim = Sim(mesh, name='relax', driver='llbar_full')
16 |
17 | sim.driver.chi = 1e-3
18 | sim.driver.set_tols(rtol=1e-7, atol=1e-7)
19 | sim.Ms = 8.0e5
20 | sim.driver.alpha = 0.1
21 | sim.beta = 0
22 | sim.driver.gamma = 2.211e5
23 |
24 | sim.set_m((1, 0.25, 0.1))
25 | # sim.set_m(np.load('m0.npy'))
26 |
27 | A = 1.3e-11
28 | exch = UniformExchange(A=A)
29 | sim.add(exch)
30 |
31 | mT = 795.7747154594767
32 | zeeman = Zeeman([-100 * mT, 4.3 * mT, 0], name='H')
33 | sim.add(zeeman, save_field=True)
34 |
35 | demag = Demag()
36 | sim.add(demag)
37 |
38 | ONE_DEGREE_PER_NS = 17453292.52
39 |
40 | sim.relax(dt=1e-12, stopping_dmdt=0.01,
41 | max_steps=5000, save_m_steps=100, save_vtk_steps=50)
42 |
43 | np.save('m0.npy', sim.spin)
44 |
45 | if __name__ == "__main__":
46 |
47 | mesh = CuboidMesh(nx=20, ny=20, nz=1, dx=2.5, dy=2.5, dz=3, unit_length=1e-9)
48 | relax_system(mesh)
49 |
--------------------------------------------------------------------------------
/fidimag/common/helper.py:
--------------------------------------------------------------------------------
1 | from fidimag.extensions.common_clib import normalise
2 | from fidimag.extensions.common_clib import init_scalar
3 | from fidimag.extensions.common_clib import init_vector
4 | from fidimag.extensions.common_clib import init_vector_func_fast
5 | import fidimag.extensions.clib as clib
6 | import numpy as np
7 |
8 |
9 | def extract_data(mesh, npys, pos, comp='x'):
10 | """
11 | extract data of special positions for given npy data
12 |
13 | npys:
14 | the names of npys
15 |
16 | pos:
17 | something like [(1,0,0),...,(2,3,4)]
18 | """
19 | ids = []
20 | for p in pos:
21 | ids.append(mesh.index(p[0], p[1], p[2]))
22 |
23 | ids = np.array(ids)
24 |
25 | if comp == 'x':
26 | cmpi = 0
27 | elif comp == 'y':
28 | cmpi = 1
29 | elif comp == 'z':
30 | cmpi = 2
31 | else:
32 | raise Exception('Seems given component is wrong!!!')
33 |
34 | ids += cmpi * mesh.n
35 |
36 | all_data = []
37 |
38 | for ny in npys:
39 |
40 | all_data.append(np.load(ny)[ids])
41 |
42 | return np.array(all_data)
43 |
44 |
45 | def compute_RxRy(mesh, spin, nx_start=0, nx_stop=-1, ny_start=0, ny_stop=-1):
46 | res = clib.compute_RxRy(spin, mesh.nx, mesh.ny,
47 | mesh.nz, nx_start, nx_stop, ny_start, ny_stop)
48 | return res
49 |
--------------------------------------------------------------------------------
/fidimag/atomistic/materials.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | import numpy as np
3 |
4 |
5 | class UnitMaterial(object):
6 |
7 | def __init__(self):
8 | self.a = 1
9 | self.b = 1
10 | self.c = 1
11 | self.J = 1
12 | self.D = 0.5
13 | self.mu_s = 1
14 | self.gamma = 1
15 | self.alpha = 0.01
16 | self.unit_length = 1
17 |
18 |
19 | class Nickel(object):
20 |
21 | def __init__(self):
22 | self.mu_0 = 4 * np.pi * 1e-7
23 | self.mu_B = 9.27400949e-24
24 | self.k_B = 1.3806505e-23
25 | self.mu_s = 0.617 * self.mu_B
26 | self.S = 1.0 / 2
27 | self.unit_length = 1e-10
28 | # the real length should be a*unit_length
29 | self.a = 3.524
30 | self.b = self.a
31 | self.c = self.a
32 | self.K = 4.8e3
33 | self.D = self.K * self.a**3
34 | self.Tc = 630
35 | self.J = self.k_B * self.Tc / 3.0
36 | self.gamma = 2.210173e5 / self.mu_0
37 | self.Ms = 4.9e5
38 |
39 | self.alpha = 0.5
40 |
41 | if __name__ == '__main__':
42 | ni = Nickel()
43 | print(ni.K)
44 | print('gamma', ni.gamma)
45 | print('mu_s', ni.mu_s)
46 | print('J', ni.J)
47 | print('D', ni.D)
48 | print('D/J:', ni.D / ni.J)
49 |
50 | K = 1e5 * ni.a**3
51 | print(K)
52 | print((ni.J / K)**0.5)
53 |
--------------------------------------------------------------------------------
/examples/micromagnetic/pbc_2d/rod.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from fidimag.micro import Sim
7 | from fidimag.common import CuboidMesh
8 | from fidimag.micro import UniformExchange, Demag, DMI
9 | from fidimag.micro import Zeeman, TimeZeeman
10 | from fidimag.common.fileio import DataReader
11 |
12 | mu0 = 4 * np.pi * 1e-7
13 |
14 |
15 | def relax_system(mesh):
16 |
17 | sim = Sim(mesh, name='relax')
18 |
19 | sim.driver.set_tols(rtol=1e-10, atol=1e-14)
20 | sim.driver.alpha = 0.5
21 | sim.driver.gamma = 2.211e5
22 | sim.Ms = 8.6e5
23 | sim.do_precession = False
24 |
25 | sim.set_m((1,1,1))
26 | # sim.set_m(np.load('m0.npy'))
27 |
28 | A = 1.3e-11
29 | exch = UniformExchange(A=A)
30 | sim.add(exch)
31 |
32 | dmi = DMI(D=1e-3)
33 | sim.add(dmi)
34 |
35 | zeeman = Zeeman((0, 0, 2e4))
36 | sim.add(zeeman, save_field=True)
37 |
38 | sim.relax(dt=1e-13, stopping_dmdt=0.01, max_steps=5000,
39 | save_m_steps=None, save_vtk_steps=50)
40 |
41 | np.save('m0.npy', sim.spin)
42 |
43 |
44 | if __name__ == '__main__':
45 |
46 | mesh = CuboidMesh(
47 | nx=2, ny=2, nz=10, dx=1, dy=1, dz=2.0, unit_length=1e-9, periodicity=(True, True, False))
48 |
49 | relax_system(mesh)
50 |
51 | # apply_field1(mesh)
52 | # deal_plot()
53 |
--------------------------------------------------------------------------------
/examples/micromagnetic/PRB_88_184422/plot.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from micro import Sim
7 | from common import CuboidMesh
8 | from micro import Zeeman
9 | from fidimag.common.fileio import DataReader
10 |
11 | from util.omf import OMF2
12 |
13 | mesh = CuboidMesh(nx=100, dx=1, unit_length=1e-9)
14 |
15 |
16 | def plot_all():
17 |
18 | font = {'family': 'serif',
19 | 'weight': 'normal',
20 | 'size': 12,
21 | }
22 |
23 | plt.rc('font', **font)
24 |
25 | Ms = 8.6e5
26 | omf = OMF2('oommf/dmi-Oxs_TimeDriver-Magnetization-00-0000963.omf')
27 | mx = omf.get_all_mag(comp='x') / Ms
28 | my = omf.get_all_mag(comp='y') / Ms
29 | mz = omf.get_all_mag(comp='z') / Ms
30 | xs = np.linspace(0.5, 100 - 0.5, 100)
31 |
32 | fig = plt.figure(figsize=(5, 4))
33 | plt.plot(xs, mx, '--', label='m_x', dashes=(2.0, 2.0))
34 | plt.plot(xs, my, '--', label='m_y', dashes=(2.0, 2.0))
35 | plt.plot(xs, mz, '--', label='m_z', dashes=(2.0, 2.0))
36 |
37 | l1 = plt.legend(bbox_to_anchor=[0.8, 0.8], shadow=True, frameon=True)
38 | # custom_legend(l1)
39 |
40 | plt.xlabel('xs (nm)')
41 | plt.ylabel('m')
42 | plt.title('OOMMF')
43 | plt.tight_layout()
44 | fig.savefig('m_oommf.pdf')
45 |
46 |
47 | if __name__ == '__main__':
48 |
49 | # relax_system()
50 | plot_all()
51 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015, Weiwei Wang, David Cortes, Marc-Antonio, Hans Fangohr
2 | University of Southampton,
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 |
8 | * Redistributions of source code must retain the above copyright notice, this
9 | list of conditions and the following disclaimer.
10 |
11 | * Redistributions in binary form must reproduce the above copyright notice,
12 | this list of conditions and the following disclaimer in the documentation
13 | and/or other materials provided with the distribution.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/examples/atomistic/heat/macrospin.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | from fidimag.atomistic import Anisotropy, Sim, Zeeman
6 | from fidimag.common import CuboidMesh
7 | import numpy as np
8 |
9 |
10 | class Material():
11 |
12 | def __init__(self):
13 | self.mu_0 = 4 * np.pi * 1e-7
14 | self.mu_s = 1.12e-17
15 | self.K = 3.36e-18
16 | self.unit_length = 1e-10
17 | self.gamma = 2.210173e5 / self.mu_0
18 |
19 |
20 | def single_spin(alpha=0.01):
21 |
22 | mat = Material()
23 |
24 | mesh = CuboidMesh(nx=1, ny=1, nz=1)
25 |
26 | sim = Sim(mesh, driver='sllg')
27 | sim.driver.alpha = alpha
28 | sim.driver.gamma = mat.gamma
29 | sim.mu_s = mat.mu_s
30 | sim.T = 10000
31 |
32 | sim.set_m((1, 1, 1))
33 |
34 | #sim.add(Zeeman(1,(0, 0, 1)))
35 |
36 | anis = Anisotropy(mat.K, direction=(0, 0, 1))
37 | sim.add(anis)
38 |
39 | dt = 0.5e-12
40 | ts = np.linspace(0, 1000 * dt, 1001)
41 |
42 | sx = []
43 | sy = []
44 | for t in ts:
45 | sim.run_until(t)
46 | sx.append(sim.spin[0])
47 | sy.append(sim.spin[1])
48 | print(t)
49 |
50 | plt.plot(sx, sy)
51 | plt.xlabel("$S_x$")
52 | plt.ylabel("$S_y$")
53 | plt.grid()
54 | plt.axis((-0.9, 0.9, -0.9, 0.9))
55 | plt.axes().set_aspect('equal')
56 |
57 | plt.savefig("macrospin.pdf")
58 |
59 |
60 | if __name__ == '__main__':
61 | single_spin()
62 |
--------------------------------------------------------------------------------
/fidimag/atomistic/lib/fmmlib/tree.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FMMLIB_TREE_HPP
2 | #define FMMLIB_TREE_HPP
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include "utils.hpp"
9 |
10 | class Particle {
11 | public:
12 | double x, y, z;
13 | double mux, muy, muz;
14 | Particle(double x, double y, double z, double mux, double muy, double muz) : x(x), y(y), z(z), mux(mux), muy(muy), muz(muz) {}
15 | };
16 |
17 | struct Cell {
18 | public:
19 | unsigned int nleaf;
20 | unsigned int nchild;
21 | unsigned int level;
22 | std::array child;
23 | std::vector Mx;
24 | std::vector My;
25 | std::vector Mz;
26 | std::vector Lx;
27 | std::vector Ly;
28 | std::vector Lz;
29 | std::vector leaf;
30 | double x, y, z, r;
31 | unsigned int parent;
32 | Cell(double x, double y, double z, double r, unsigned int parent, unsigned int order, unsigned int level, unsigned int ncrit);
33 | };
34 |
35 | void printTreeParticles(std::vector &cells, unsigned int cell, unsigned int depth);
36 |
37 | void add_child(std::vector &cells, int octant, unsigned int p, unsigned int ncrit, unsigned int order);
38 |
39 |
40 | void split_cell(std::vector &cells, std::vector &particles, unsigned int p, unsigned int ncrit, unsigned int order);
41 |
42 | std::vector build_tree(std::vector &particles, Cell &root, unsigned int ncrit, unsigned int order);
43 |
44 | #endif
--------------------------------------------------------------------------------
/fidimag/micro/exchange.py:
--------------------------------------------------------------------------------
1 | import fidimag.extensions.micro_clib as micro_clib
2 | from .energy import Energy
3 | #from constant import mu_0
4 |
5 |
6 | class UniformExchange(Energy):
7 |
8 | """
9 | UniformExchange(A, name='UniformExchange')
10 |
11 | Compute the exchange field in micromagnetics.
12 |
13 | Inputs:
14 | A: float
15 | A is the exchange stiffness constant measured in
16 | Joules / Meter (J / M)
17 |
18 | """
19 |
20 | def __init__(self, A, name='UniformExchange'):
21 | self.A = A
22 | self.name = name
23 | self.jac = True
24 |
25 | def compute_field(self, t=0, spin=None):
26 | if spin is not None:
27 | m = spin
28 | else:
29 | m = self.spin
30 |
31 | micro_clib.compute_exchange_field_micro(m,
32 | self.field,
33 | self.energy,
34 | self.Ms_inv,
35 | self.A,
36 | self.dx,
37 | self.dy,
38 | self.dz,
39 | self.n,
40 | self.neighbours
41 | )
42 |
43 | return self.field
44 |
--------------------------------------------------------------------------------
/examples/atomistic/dynamic_spectrum/plot_results.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib as mpl
3 | mpl.use("Agg")
4 |
5 | import matplotlib.pyplot as plt
6 | from fidimag.atomistic import Sim, DMI, UniformExchange, Zeeman, TimeZeeman
7 | from fidimag.common import DataReader, BatchTasks, CuboidMesh
8 |
9 | def deal_plot(Hy=0):
10 |
11 | data = DataReader('dyn.txt')
12 | ts = data['time']
13 | N = len(ts)
14 | #N = 8000
15 |
16 | dt = ts[1] - ts[0]
17 | print('dt=',dt)
18 |
19 | freq = np.fft.fftshift(np.fft.fftfreq(N, dt))
20 |
21 | H = data['h_z'][0:N]
22 | M = data['m_z'][0:N]
23 |
24 | fH = np.fft.fftshift(np.fft.fft(H))
25 | fM = np.fft.fftshift(np.fft.fft(M))
26 |
27 | a = fH.real
28 | b = fH.imag
29 | c = fM.real
30 | d = fM.imag
31 |
32 | rx = (a*c+b*d)/(a*a+b*b)
33 | ix = (b*c-a*d)/(a*a+b*b)
34 |
35 | ind = np.argmax(ix)
36 | print(ind, freq[ind]*2*np.pi)
37 | w_ix = np.array([freq*2*np.pi, ix])
38 | #np.savetxt('w_ix.txt',np.transpose(w_ix))
39 |
40 | plt.plot(freq*2*np.pi, ix, '.-')
41 | #plt.legend()
42 | plt.xlim([0, 0.06])
43 | #plt.ylim([-5, 100])
44 | plt.xlabel(r'$w$')
45 | plt.ylabel('Susceptibility')
46 | plt.savefig('res.pdf')
47 |
48 | def plot_v(x,y,filename):
49 | fig=plt.figure()
50 | plt.plot(x,y,'^-',markersize=3)
51 | fig.savefig(filename)
52 |
53 | if __name__=='__main__':
54 |
55 | deal_plot()
56 |
57 |
--------------------------------------------------------------------------------
/tests/vtk_refs/scalar_hexagonal_000000.vtk:
--------------------------------------------------------------------------------
1 | # vtk DataFile Version 2.0
2 |
3 | ASCII
4 | DATASET POLYDATA
5 | POINTS 30 double
6 | 2.0 1.7320508075688774 0.0
7 | 1.0 2.3094010767585034 0.0
8 | -2.220446049250313e-16 1.7320508075688774 0.0
9 | 0.0 0.5773502691896257 0.0
10 | 0.9999999999999998 0.0 0.0
11 | 1.9999999999999998 0.5773502691896253 0.0
12 | 4.0 1.7320508075688774 0.0
13 | 3.0 2.3094010767585034 0.0
14 | 3.0 0.0 0.0
15 | 4.0 0.5773502691896253 0.0
16 | 6.0 1.7320508075688774 0.0
17 | 5.0 2.3094010767585034 0.0
18 | 5.0 0.0 0.0
19 | 6.0 0.5773502691896253 0.0
20 | 3.0 3.464101615137755 0.0
21 | 2.0 4.041451884327381 0.0
22 | 0.9999999999999998 3.464101615137755 0.0
23 | 5.0 3.464101615137755 0.0
24 | 4.0 4.041451884327381 0.0
25 | 7.0 3.464101615137755 0.0
26 | 6.0 4.041451884327381 0.0
27 | 7.0 2.309401076758503 0.0
28 | 4.0 5.196152422706632 0.0
29 | 3.0 5.773502691896257 0.0
30 | 1.9999999999999998 5.196152422706632 0.0
31 | 6.0 5.196152422706632 0.0
32 | 5.0 5.773502691896257 0.0
33 | 8.0 5.196152422706632 0.0
34 | 7.0 5.773502691896257 0.0
35 | 8.0 4.04145188432738 0.0
36 | POLYGONS 9 63
37 | 6 0 1 2 3 4 5
38 | 6 6 7 0 5 8 9
39 | 6 10 11 6 9 12 13
40 | 6 14 15 16 1 0 7
41 | 6 17 18 14 7 6 11
42 | 6 19 20 17 11 10 21
43 | 6 22 23 24 15 14 18
44 | 6 25 26 22 18 17 20
45 | 6 27 28 25 20 19 29
46 | CELL_DATA 9
47 | SCALARS s double 1
48 | LOOKUP_TABLE default
49 | 2.1547005383792515
50 | 4.1547005383792515
51 | 6.1547005383792515
52 | 4.886751345948129
53 | 6.886751345948129
54 | 8.886751345948129
55 | 7.618802153517006
56 | 9.618802153517006
57 | 11.618802153517006
--------------------------------------------------------------------------------
/examples/micromagnetic/pbc_2d/main.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from fidimag.micro import Sim
7 | from fidimag.common import CuboidMesh
8 | from fidimag.micro import UniformExchange, Demag, DMI
9 | from fidimag.micro import Zeeman, TimeZeeman
10 | from fidimag.common.fileio import DataReader
11 |
12 | mu0 = 4 * np.pi * 1e-7
13 |
14 |
15 | def init_m(pos):
16 |
17 | x, y = pos[0] - 500, pos[1] - 500
18 |
19 | if x**2 + y**2 < 50**2:
20 | return (0, 0, -1)
21 | else:
22 | return (0, 0, 1)
23 |
24 |
25 | def relax_system(mesh):
26 |
27 | sim = Sim(mesh, name='relax')
28 |
29 | sim.driver.set_tols(rtol=1e-10, atol=1e-14)
30 | sim.driver.alpha = 0.5
31 | sim.driver.gamma = 2.211e5
32 | sim.Ms = 8.6e5
33 | sim.do_precession = False
34 |
35 | sim.set_m(init_m)
36 | # sim.set_m(np.load('m0.npy'))
37 |
38 | A = 1.3e-11
39 | exch = UniformExchange(A=A)
40 | sim.add(exch)
41 |
42 | dmi = DMI(D=1e-3)
43 | sim.add(dmi)
44 |
45 | zeeman = Zeeman((0, 0, 2e4))
46 | sim.add(zeeman, save_field=True)
47 |
48 | sim.relax(dt=1e-13, stopping_dmdt=0.01, max_steps=5000,
49 | save_m_steps=None, save_vtk_steps=50)
50 |
51 | np.save('m0.npy', sim.spin)
52 |
53 |
54 | if __name__ == '__main__':
55 |
56 | mesh = CuboidMesh(
57 | nx=1001, ny=1001, nz=1, dx=1, dy=1, dz=2.0, unit_length=1e-9, periodicity=(True, True, False))
58 |
59 | relax_system(mesh)
60 |
61 | # apply_field1(mesh)
62 | # deal_plot()
63 |
--------------------------------------------------------------------------------
/examples/micromagnetic/spatial_dmi/main.py:
--------------------------------------------------------------------------------
1 | import fidimag.micro
2 | import numpy as np
3 |
4 | xMax = 50. # Upper bound of the domain, centred about zero. Domain only varies
5 | # in x.
6 | D = 4e-3 # DMI coefficient, [Jm-2].
7 |
8 | def m_init(pos):
9 | """Define magnetisation texture corresponding to +Mz at the edges, -Mz at
10 | centre, and rotating through My. Encourages helices that change chirality
11 | at the centre.."""
12 | Mz = abs(pos[0]) * 2. / xMax - 1
13 | My = (1 - Mz ** 2.) ** 0.5
14 | My *= 1 if pos[0] < 0 else -1 # Change direction! Could be the wrong way
15 | # though...
16 | return [0., My, Mz]
17 |
18 | def dmi_variance(pos):
19 | """Define how the DMI is defined on the simulation domain. Is basically:
20 |
21 | ----------|----------
22 | D -D
23 |
24 | """
25 | return D if pos[0] < 0 else -D
26 |
27 | # Create a mesh that looks like this: ------------------
28 | mesh = fidimag.micro.CuboidMesh(nx=100, dx=1, x0=-50, unit_length=1e-9)
29 | sim = fidimag.micro.Sim(mesh)
30 |
31 | # Dynamics parameters.
32 | sim.driver.set_tols(rtol=1e-6, atol=1e-6)
33 | sim.driver.alpha = 0.5
34 | sim.driver.gamma = 2.211e5
35 | sim.Ms = 8.6e5
36 | sim.do_precession = False
37 |
38 | # Set magnetisation and add energies.
39 | sim.set_m(m_init)
40 | sim.add(fidimag.micro.UniformExchange(A=1.3e-11))
41 | sim.add(fidimag.micro.DMI(D=dmi_variance))
42 |
43 | # Relax and save.
44 | sim.relax(dt=1e-13, stopping_dmdt=1e-2, save_m_steps=None, save_vtk_steps=50)
45 | np.save('m0.npy', sim.spin)
46 |
--------------------------------------------------------------------------------
/examples/micromagnetic/skyrmion/main.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from fidimag.micro import Sim
7 | from fidimag.common import CuboidMesh
8 | from fidimag.micro import UniformExchange, Demag, DMI
9 | from fidimag.micro import Zeeman, TimeZeeman
10 | from fidimag.common.fileio import DataReader
11 |
12 | mu0 = 4 * np.pi * 1e-7
13 |
14 |
15 | def init_m(pos):
16 |
17 | x, y = pos[0] - 500, pos[1] - 500
18 |
19 | if x**2 + y**2 < 50**2:
20 | return (0, 0, -1)
21 | else:
22 | return (0, 0, 1)
23 |
24 |
25 | def relax_system(mesh):
26 |
27 | sim = Sim(mesh, name='relax')
28 |
29 | sim.driver.set_tols(rtol=1e-10, atol=1e-14)
30 | sim.driver.alpha = 0.5
31 | sim.driver.gamma = 2.211e5
32 | sim.Ms = 8.6e5
33 | sim.do_precession = False
34 |
35 | sim.set_m(init_m)
36 | # sim.set_m(np.load('m0.npy'))
37 |
38 | A = 1.3e-11
39 | exch = UniformExchange(A=A)
40 | sim.add(exch)
41 |
42 | dmi = DMI(D=1e-3)
43 | sim.add(dmi)
44 |
45 | zeeman = Zeeman((0, 0, 2e4))
46 | sim.add(zeeman, save_field=True)
47 |
48 | sim.relax(dt=1e-13, stopping_dmdt=0.01, max_steps=5000,
49 | save_m_steps=None, save_vtk_steps=50)
50 |
51 | np.save('m0.npy', sim.spin)
52 |
53 |
54 | if __name__ == '__main__':
55 |
56 | mesh = CuboidMesh(
57 | nx=1001, ny=1001, nz=1, dx=1, dy=1, dz=2.0, unit_length=1e-9, periodicity=(True, True, False))
58 |
59 | relax_system(mesh)
60 |
61 | # apply_field1(mesh)
62 | # deal_plot()
63 |
--------------------------------------------------------------------------------
/examples/atomistic/heat/compute_energy.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import scipy.integrate as integrate
3 | import matplotlib as mpl
4 | mpl.use("Agg")
5 | import matplotlib.pyplot as plt
6 | import fidimag.common.constant as const
7 | """
8 | compute the figure 2 in the paper at dx.doi.org/10.1063/1.2169472
9 | Note: it seems that the volume given in the paper is not correct,
10 | since v=28e-27 generates the correct figures.
11 | """
12 |
13 |
14 | def compute_energy(mx):
15 | Ms = 1.42e6
16 | a, b, c = 4, 2, 2
17 | v = 4.0 / 3 * np.pi * a * b * c * 1e-27
18 |
19 | v = 28e-27
20 |
21 | alpha = 0.005
22 | T = 300
23 | nu2 = alpha * 2 * const.k_B * T / (const.mu_0 * Ms**2 * v)
24 | mu = 2 * alpha / nu2
25 |
26 | Dx = 0.0946
27 | Dy = 0.4132
28 |
29 | fun = lambda t: np.exp(-mu / 2.0 *
30 | (Dx * np.cos(t)**2 + Dy * np.sin(t)**2)) * np.sin(t)
31 | res = integrate.quad(fun, 0, np.pi)
32 | Z = res[0]
33 |
34 | print 'mu=', mu, 'Z=', Z
35 |
36 | gl = (Dx * mx**2 + Dy * (1 - mx**2)) / 2.0
37 |
38 | p = 1 / Z * np.exp(-mu * gl)
39 |
40 | return p
41 |
42 |
43 | def plot_energy(name='out.pdf'):
44 | fig = plt.figure()
45 | mxs = np.linspace(-1, 1, 21)
46 | energy = []
47 | for x in mxs:
48 | en = compute_energy(x)
49 | energy.append(en)
50 |
51 | plt.plot(mxs, energy, '.-')
52 | plt.xlabel('m_x')
53 | plt.ylabel('Energy')
54 | #plt.ylim([0, 2])
55 | fig.savefig(name)
56 |
57 |
58 | if __name__ == '__main__':
59 | print compute_energy(0)
60 | plot_energy()
61 |
--------------------------------------------------------------------------------
/doc/physics_num_methods/monte_carlo.rst:
--------------------------------------------------------------------------------
1 | Monte Carlo Simulation
2 | =======================
3 |
4 | In the atomistic part of Fidimag, Monte Carlo based on Metropolis algorithm is integrated.
5 | The supported interactions include the exchange interaction, the bulk DMI, the external field and
6 | cubic anisotropy. The total Hamiltonian of the system is therefore given by
7 |
8 | .. math::
9 | \mathcal{H} = \mathcal{H}_{ex} + \mathcal{H}_{dmi} + \mathcal{H}_{ext} + \mathcal{H}_{c}
10 |
11 | where :math:`\mathcal{H}_{ex}` is the nearest-neighbor exchange interaction,
12 |
13 | .. math::
14 | \mathcal{H}_{ex} = -J \sum_{}\vec{m}_i \cdot \vec{m}_j
15 |
16 | Note that the summation is taken only once for each pair and :math:`\vec{m}_i` is the unit vector of spin :math:`\vec{S}` at site :math:`i`.
17 |
18 | The Hamiltonian of bulk DMI can be expressed as,
19 |
20 | .. math::
21 | \mathcal{H}_{dmi}= \sum_{} \vec{D}_{ij}\cdot [\vec{m}_i \times \vec{m}_j]
22 |
23 | where :math:`\vec{D}_{ij} = D \vec{e}_{ij}` with :math:`\vec{e}_{ij}` is the unit vector between :math:`\vec{S}_{i}` and :math:`\vec{S}_{j}`.
24 |
25 | The Hamiltonian of external field is
26 |
27 | .. math::
28 | \mathcal{H}_{dmi}= - \sum_{i} \mu_s \vec{H}\cdot \vec{m}_i
29 |
30 | where :math:`\mu_s = g \mu_B S`.
31 |
32 | The cubic anisotropy implemented in Fidimag is,
33 |
34 | .. math::
35 | \mathcal{H}_{c}= - \sum_{i} (K_c/2) (m_{i,x}^4 + m_{i,y}^4 + m_{i,z}^4)
36 |
37 | which is equivalent to the form
38 |
39 | .. math::
40 | \mathcal{H}_{c}= \sum_{i} K_c (m_{i,x}^2 m_{i,y}^2 + m_{i,y}^2 m_{i,z}^2 + m_{i,z}^2 m_{i,x}^2)
41 |
42 |
43 |
--------------------------------------------------------------------------------
/fidimag/common/save_vtk.py:
--------------------------------------------------------------------------------
1 | import os
2 | import numpy as np
3 | from fidimag.common.vtk import VTK
4 |
5 |
6 | class SaveVTK():
7 |
8 | def __init__(self, mesh, name='unnamed', directory=None):
9 | self.name = name
10 |
11 | if directory is None:
12 | self.directory = '{}_vtks'.format(name)
13 | else:
14 | self.directory = directory
15 |
16 | # Initiate a VTK object
17 | self.VTK = VTK(mesh,
18 | directory=self.directory,
19 | filename=name
20 | )
21 |
22 | def save_vtk(self, m1, Ms, step=0, vtkname='m'):
23 | self.VTK.reset_data()
24 | # Here we save both Ms and spins as cell data
25 | self.VTK.save_scalar(Ms, name='Ms')
26 | self.VTK.save_vector(m1, name='spins')
27 |
28 | # Now we set the name of the file to start with m_ as default
29 | self.VTK.filename = vtkname
30 | self.VTK.write_file(step=step)
31 |
32 | def save_vtk_scalar(self, scalar_data_array, step=0, vtkname='skx'):
33 | # This saves the skyrmion number or any scalar data
34 | # CHECK: that the array skx_num is being passed with the correct shape
35 | # TODO: put more generic names as default names
36 | self.VTK.save_scalar(scalar_data_array, name='skx_num')
37 |
38 | # These files will be saved starting with: skx_ or other name
39 | # and saved to a different folder instead of {}_vtks
40 | self.VTK.filename = vtkname
41 | self.VTK.directory = self.name + '_' + vtkname
42 | self.VTK.write_file(step=step)
43 |
--------------------------------------------------------------------------------
/examples/micromagnetic/nmag_example_2_box/plot.py:
--------------------------------------------------------------------------------
1 | import matplotlib
2 | matplotlib.use('Agg')
3 | import matplotlib.pyplot as plt
4 | from fidimag.common.fileio import DataReader
5 |
6 | # labels on plot
7 | mathmode = lambda txt: "$" + txt + "$"
8 | rm = lambda txt: "\mathrm{" + txt + "}"
9 | label = lambda name, mi: mathmode(rm(rm(name) + "\; m_" + rm(mi)))
10 | fidi = mathmode(rm("fidimag"))
11 | m = lambda i: label("fidimag", i)
12 |
13 | for datafile, descr in (
14 | ("sim_sundials_J0", "w/o Jacobian"),
15 | ("sim_sundials_diag", "Jacobian approx."),
16 | ("sim_sundials_J1", "with Jacobian")):
17 | data = DataReader(datafile + ".txt")
18 | total_wall_time = (data["real_time"][-1] - data["real_time"][0]) / 60.0
19 |
20 | fig, axes = plt.subplots(2, figsize=(10, 8), sharex=True)
21 |
22 | # magnetisation dynamics
23 | axes[0].plot(data["time"] * 1e9, data["m_x"], "bx", label=m("x"))
24 | axes[0].plot(data["time"] * 1e9, data["m_y"], "gx", label=m("y"))
25 | axes[0].plot(data["time"] * 1e9, data["m_z"], "rx", label=m("z"))
26 | axes[0].set_ylim((-0.3, 1.1))
27 | axes[0].set_ylabel("unit magnetisation (1)")
28 | axes[0].legend()
29 | axes[0].set_title("{}, wall time {:.2} minutes".format(descr, total_wall_time))
30 |
31 | # number of RHS evaluations
32 | axes[1].plot(data["time"] * 1e9, data["rhs_evals"], label=fidi)
33 | axes[1].legend(loc=0)
34 | axes[1].set_ylabel("# of RHS evaluations")
35 | axes[1].set_xlabel("time (ns)")
36 | axes[1].set_xlim((0, 0.3))
37 |
38 | fig.tight_layout()
39 | fig.savefig(datafile + ".png")
40 | plt.close(fig)
41 |
--------------------------------------------------------------------------------
/fidimag/atomistic/lib/fmmlib/fmmlib.pyx:
--------------------------------------------------------------------------------
1 | from libcpp.vector cimport vector
2 |
3 | cdef extern from "tree.hpp":
4 | cdef cppclass Particle:
5 | Particle(double x, double y, double z, double mux, double muy, double muz)
6 | double x, y, z, mux, muy, muz
7 |
8 | cdef cppclass Cell:
9 | Cell(double x, double y, double z, double r, unsigned int parent, unsigned int order,
10 | unsigned int level, unsigned int ncrit)
11 | unsigned int nleaf, nchild, level
12 | double x, y, z, r
13 | unsigned int parent
14 | vector[double] Mx
15 | vector[double] My
16 | vector[double] Mz
17 | vector[double] Lx
18 | vector[double] Ly
19 | vector[double] Lz
20 | vector[int] leaf
21 |
22 | cdef vector[Cell] build_tree(vector[Particle]& particles,
23 | Cell &root,
24 | unsigned int ncrit,
25 | unsigned int order)
26 |
27 |
28 | cdef vector[Particle] sim_to_particles(mesh, mu_s):
29 | """
30 | Convert the positions of the lattice spins to C++ Particle objects
31 | for the building of the trees.
32 | """
33 | ids = []
34 | for k in range(mesh.nz):
35 | for j in range(mesh.ny):
36 | for i in range(mesh.nx):
37 | id = k * mesh.nx * mesh.ny + j * mesh.nx + i
38 | # Check that the spin is not a 'ghost' spin
39 | if mu_s[id] != 0:
40 | ids.append(id)
41 |
42 |
43 |
44 |
45 |
46 | def build_tree(mesh, mus):
47 | pass
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/fidimag/atomistic/lib/fmmlib/calculate.hpp:
--------------------------------------------------------------------------------
1 | //############################################
2 | //#
3 | //# Functions for running the Barnes-Hut
4 | //# method for gravitational source particles.
5 | //#
6 | //# (C) Ryan Pepper, 2018
7 | //# University of Southampton, UK
8 | //#
9 | //#
10 | //###########################################
11 |
12 | #include
13 | #include "expansions.hpp"
14 | #include "tree.hpp"
15 | #include "utils.hpp"
16 | #include
17 |
18 | #ifndef FMMLIB_CALCULATE_HPP
19 | #define FMMLIB_CALCULATE_HPP
20 |
21 |
22 | void evaluate_P2M(std::vector &particles, std::vector &cells, unsigned int cell, unsigned int ncrit, unsigned int exporder);
23 |
24 | void evaluate_M2M(std::vector &particles, std::vector &cells, unsigned int exporder);
25 |
26 | void evaluate_M2P_and_P2P(std::vector &particles, unsigned int p,
27 | unsigned int i, std::vector &cells, std::vector &Bx,
28 | std::vector &By, std::vector &Bz, unsigned int n_crit,
29 | double theta, unsigned int exporder, std::vector> &mempool);
30 |
31 | void evaluate_approx(std::vector &particles, std::vector &cells, std::vector &Bx,
32 | std::vector &By, std::vector &Bz, unsigned int n_crit, double theta,
33 | unsigned int exp_order);
34 |
35 | void evaluate_direct(std::vector &particles, std::vector &Bx, std::vector &By,
36 | std::vector &Bz);
37 |
38 |
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/examples/atomistic/PRL_108_017601/figure1.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim, DMI, UniformExchange, Zeeman
3 | from fidimag.common import CuboidMesh
4 |
5 | def init_m(pos):
6 | x, y, z = pos
7 |
8 | x0, y0, r = 166, 96, 25
9 |
10 | x1 = x % x0
11 | y1 = y % y0
12 |
13 | m1 = (0.05, 0.01, -1)
14 | m2 = (0, 0, 1)
15 |
16 | if (x1 - r)**2 + (y1 - r)**2 < r**2:
17 | return m1
18 | elif (x1 - x0 / 2. - r)**2 + (y1 - y0 / 2. - r)**2 < r**2:
19 | return m1
20 | else:
21 | return m2
22 |
23 |
24 | def random_m(pos):
25 | return np.random.random(3) - 0.5
26 |
27 |
28 | def relax_system(mesh):
29 |
30 | sim = Sim(mesh, name='relax')
31 | # sim.set_options(rtol=1e-10,atol=1e-14)
32 | sim.driver.alpha = 1.0
33 | sim.driver.gamma = 1.0
34 | sim.mu_s = 1.0
35 |
36 | sim.set_m(init_m)
37 | # sim.set_m(random_m)
38 | # sim.set_m(np.load('m_10000.npy'))
39 |
40 | J = 1.0
41 | exch = UniformExchange(J)
42 | sim.add(exch)
43 |
44 | D = 0.09
45 | dmi = DMI(D)
46 | sim.add(dmi)
47 |
48 | zeeman = Zeeman([0, 0, 3.75e-3])
49 | sim.add(zeeman)
50 |
51 | sim.relax(dt=2.0, stopping_dmdt=1e-6, max_steps=1000,
52 | save_m_steps=100, save_vtk_steps=50)
53 |
54 | np.save('m0.npy', sim.spin)
55 |
56 |
57 | if __name__ == '__main__':
58 |
59 | np.random.seed(11)
60 |
61 | #mesh = CuboidMesh(nx=288,ny=288,nz=1)
62 | mesh = CuboidMesh(nx=166, ny=96 * 2, nz=1, periodicity=(True, True, False))
63 |
64 | relax_system(mesh)
65 |
66 | print 'relax system done'
67 | # spin_wave(mesh,m0)
68 |
--------------------------------------------------------------------------------
/examples/atomistic/dw_demag/dw_demag.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 | from fidimag.atomistic import Sim
6 | from fidimag.atomistic import DMI, Demag, UniformExchange
7 | from fidimag.common import CuboidMesh
8 |
9 |
10 | def init_m(pos):
11 | x, y, z = pos
12 | if x < 140 * 0.5:
13 | return (1, 0, 0.1)
14 | elif x > 160 * 0.5:
15 | return (-1, 0, 0.1)
16 | else:
17 | return (0, 1, 0.1)
18 |
19 |
20 | def relax_system(mesh):
21 |
22 | sim = Sim(mesh, name='relax')
23 | sim.mu_s=1e-23
24 | sim.driver.gamma=1.76e11
25 | sim.driver.alpha = 1.0
26 | J = 1e-22
27 | exch = UniformExchange(J)
28 | sim.add(exch)
29 | demag = Demag()
30 | sim.add(demag)
31 | sim.set_m(init_m)
32 |
33 | ts = np.linspace(0, 5e-10, 101)
34 | for t in ts:
35 | sim.driver.run_until(t)
36 | sim.save_vtk()
37 | np.save('m0.npy', sim.spin)
38 |
39 |
40 | def save_plot():
41 | fig = plt.figure()
42 | data = np.load('m0.npy')
43 | data.shape = (-1, 3)
44 | print(data)
45 |
46 | plt.plot(data[:, 0], '-', label='Sx')
47 | plt.plot(data[:, 1], '-', label='Sy')
48 | plt.plot(data[:, 2], '-', label='Sz')
49 |
50 | plt.ylim([-1.2, 1.2])
51 | plt.ylabel('S')
52 | plt.xlabel('x/a')
53 | plt.legend(loc=1)
54 | plt.grid()
55 | fig.savefig('mxyz.pdf')
56 |
57 | if __name__ == '__main__':
58 |
59 | mesh = CuboidMesh(nx=300, dx=0.5, dy=1, dz=1, unit_length=1e-9)
60 |
61 | relax_system(mesh)
62 | print('relax system done')
63 | save_plot()
64 | # spin_wave(mesh,m0)
65 |
--------------------------------------------------------------------------------
/examples/atomistic/dw_field/dw-field.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from pc import *
3 | import time
4 |
5 |
6 | def init_m(pos):
7 | x, y, z = pos
8 | if x < 8:
9 | return (1, 0, 0)
10 | elif x > 12:
11 | return (-1, 0, 0)
12 | else:
13 | return (0, 1, 0)
14 |
15 |
16 | def relax_system(mesh, mat):
17 | sim = Sim(mesh, T=0, mat=mat, name='relax')
18 | sim.c = 2
19 |
20 | exch = UniformExchange(mat.J)
21 | sim.add(exch)
22 |
23 | anis = Anisotropy(mat.D)
24 | sim.add(anis)
25 |
26 | sim.set_m(init_m)
27 |
28 | ts = np.linspace(0, 100, 2001)
29 | sim.save_vtk()
30 |
31 | for t in ts:
32 | sim.run_until(t)
33 |
34 | sim.save_vtk()
35 |
36 | return sim.spin
37 |
38 |
39 | def dw_motion(mesh, m0, mat, H0=1):
40 | sim = Sim(mesh, T=0, mat=mat)
41 | sim.c = 3
42 |
43 | exch = UniformExchange(mat.J)
44 | sim.add(exch)
45 |
46 | anis = Anisotropy(mat.D)
47 | sim.add(anis)
48 |
49 | zeeman = Zeeman(H0, (1, 0, 0))
50 | sim.add(zeeman)
51 |
52 | sim.set_m(m0)
53 |
54 | ts = np.linspace(0, 200, 2001)
55 | for t in ts:
56 | sim.run_until(t)
57 | sim.save_vtk()
58 |
59 |
60 | if __name__ == '__main__':
61 |
62 | ni = Nickel()
63 | ni.alpha = 0.5
64 | ni.a = 1
65 | ni.b = 1
66 | ni.c = 1
67 | ni.unit_length = 1
68 | ni.mu_s = 1
69 | ni.D = 1
70 | ni.J = 2
71 | ni.gamma = 1
72 |
73 | mesh = CuboidMesh(nx=20, ny=5, nz=2)
74 | mesh.set_material(ni)
75 |
76 | m0 = relax_system(mesh, ni)
77 | print 'relax system done'
78 | ni.alpha = 0.05
79 | dw_motion(mesh, m0, ni)
80 |
--------------------------------------------------------------------------------
/fidimag/atomistic/exchange_new.py:
--------------------------------------------------------------------------------
1 | from .field import scalar_field, vector_field
2 |
3 | class Exchange(object):
4 | """
5 | Uniform exchange interaction.
6 |
7 | """
8 | def __init__(self, mesh, J, name="exchange"):
9 | self.mesh = mesh
10 | # J is a scalar field, because that's good enough for uniform
11 | # exchange. Could be changed trivially by making J a vector field
12 | # and changing the J = self.J[c_i] line in the compute method.
13 | self.J = scalar_field(mesh, J)
14 | # field and energy are just np.arrays. In principle, they could be
15 | # created in the scope of the compute method, but we want to avoid
16 | # re-creating the objects in memory unnecessarily.
17 | self.field = vector_field(mesh, 0)
18 | self.energy = scalar_field(mesh, 0)
19 | self.in_jacobian = True
20 |
21 | def compute(self, spins):
22 | """
23 | Compute the exchange field and the exchange energy.
24 |
25 | """
26 | for c_i in mesh.cells():
27 | #TODO: cythonise this loop fiercely
28 | # like shown at http://docs.cython.org/src/tutorial/numpy.html
29 | fx = 0
30 | fy = 0
31 | fz = 0
32 | J = self.J[c_i]
33 | for c_j in mesh.neighbours[c_i]:
34 | fx += J * spins[c_j, 0]
35 | fy += J * spins[c_j, 1]
36 | fz += J * spins[c_j, 2]
37 | self.field[c_i] = (fx, fy, fz)
38 | self.energy[c_i] = -0.5 * ( fx * spins[c_i, 0]
39 | + fy * spins[c_i, 1]
40 | + fz * spins[c_i, 2])
41 |
--------------------------------------------------------------------------------
/fidimag/atomistic/energy.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | #from constant import mu_0
4 |
5 |
6 | class Energy(object):
7 |
8 | """
9 |
10 | An abstract class to implement the basic functions such as setup for atomic
11 | dynamics.
12 |
13 | """
14 |
15 | def setup(self, mesh, spin, mu_s, mu_s_inv):
16 | self.mesh = mesh
17 | self.dx = mesh.dx * mesh.unit_length
18 | self.dy = mesh.dy * mesh.unit_length
19 | self.dz = mesh.dz * mesh.unit_length
20 | self.nx = mesh.nx
21 | self.ny = mesh.ny
22 | self.nz = mesh.nz
23 | self.spin = spin
24 | self.n = mesh.n
25 | self.n_ngbs = mesh.n_ngbs
26 | self.mesh_type = mesh.mesh_type
27 |
28 | self.total_energy = 0
29 | self.mu_s = mu_s
30 |
31 | self.field = np.zeros(3 * self.n, dtype=np.float64)
32 | self.energy = np.zeros(mesh.n, dtype=np.float64)
33 | self.total_energy = 0.0
34 |
35 | self.mu_s_inv = mu_s_inv
36 |
37 | self.xperiodic, self.yperiodic = (mesh.periodicity[0],
38 | mesh.periodicity[1])
39 | self.neighbours = mesh.neighbours
40 |
41 | try:
42 | self.coordinates = self.mesh.coordinates
43 | except:
44 | self.coordinates = np.array(self.mesh.pos)
45 |
46 | def compute_field(self, t=0):
47 |
48 | return 0
49 |
50 | def compute_energy(self):
51 |
52 | # since we are not always calling this function, so it's okay to call
53 | # compute_field again
54 | self.compute_field()
55 |
56 | self.total_energy = np.sum(self.energy)
57 |
58 | return self.total_energy
59 |
--------------------------------------------------------------------------------
/examples/atomistic/stt/single_spin_stt.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim, DMI, UniformExchange, Zeeman, Anisotropy
3 | from fidimag.common import CuboidMesh, DataReader
4 | import matplotlib.pyplot as plt
5 |
6 | def dynamic(mesh):
7 |
8 | sim = Sim(mesh, name='dyn_spin', driver='slonczewski')
9 | # sim.set_options(rtol=1e-10,atol=1e-14)
10 | sim.driver.gamma = 1.0
11 | sim.mu_s = 1.0
12 |
13 | sim.set_m((0.8,0,-1))
14 |
15 | Kx = Anisotropy(Ku=-0.05, axis=(0, 0, 1), name='Kz')
16 | sim.add(Kx)
17 |
18 | sim.p = (0,0,1)
19 |
20 | sim.u0 = 0.005
21 | sim.driver.alpha = 0.1
22 |
23 | ts = np.linspace(0, 1200, 401)
24 | for t in ts:
25 | sim.run_until(t)
26 | #sim.save_vtk()
27 | print t
28 |
29 | def plot_all():
30 |
31 | font = {'family': 'serif',
32 | 'weight': 'normal',
33 | 'size': 12,
34 | }
35 |
36 | plt.rc('font', **font)
37 |
38 | data = DataReader('dyn_spin.txt')
39 | ts = data['time']
40 |
41 | fig = plt.figure(figsize=(5, 4))
42 |
43 | mx = data['m_x']
44 | my = data['m_y']
45 | mz = data['m_z']
46 | plt.plot(ts, mx, '-', label='mx', color='b')
47 | plt.plot(ts, my, '-', label='my', color='g')
48 | plt.plot(ts[::6], mz[::6],'.-', label='mz', color='r')
49 |
50 | plt.legend(bbox_to_anchor=[0.8, 0.8], shadow=True, frameon=True)
51 | #plt.xlim([0, 1.01])
52 |
53 | plt.legend()
54 |
55 | plt.xlabel('Time')
56 | plt.ylabel('m')
57 | plt.tight_layout()
58 | fig.savefig('m_ts.pdf')
59 |
60 | if __name__ == '__main__':
61 | mesh = CuboidMesh(nx=1, ny=1, nz=1)
62 | dynamic(mesh)
63 | plot_all()
64 |
--------------------------------------------------------------------------------
/examples/micromagnetic/skyrmion/Ku_H/main.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from fidimag.micro import Sim
7 | from fidimag.common import CuboidMesh
8 | from fidimag.micro import UniformExchange, Demag, DMI, UniaxialAnisotropy
9 | from fidimag.micro import Zeeman, TimeZeeman
10 | from fidimag.common.fileio import DataReader
11 |
12 | mu0 = 4 * np.pi * 1e-7
13 |
14 |
15 | def init_m(pos):
16 |
17 | x, y = pos[0] - 500, pos[1] - 500
18 |
19 | if x**2 + y**2 < 60**2:
20 | return (0, 0, -1)
21 | else:
22 | return (0, 0, 1)
23 |
24 |
25 | def relax_system(mesh):
26 |
27 | sim = Sim(mesh, name='relax')
28 |
29 | sim.driver.set_tols(rtol=1e-6, atol=1e-6)
30 | sim.driver.alpha = 0.5
31 | sim.driver.gamma = 2.211e5
32 | sim.Ms = 8.6e5
33 | sim.do_precession = False
34 |
35 | sim.set_m(init_m)
36 | # sim.set_m(np.load('m0.npy'))
37 |
38 | A = 1.3e-11
39 | exch = UniformExchange(A=A)
40 | sim.add(exch)
41 |
42 | dmi = DMI(D=1.3e-3)
43 | sim.add(dmi)
44 |
45 | anis = UniaxialAnisotropy(-3.25e4, axis=(0, 0, 1))
46 | sim.add(anis)
47 |
48 | zeeman = Zeeman((0, 0, 6.014576e4))
49 | sim.add(zeeman, save_field=True)
50 |
51 | sim.relax(dt=1e-13, stopping_dmdt=1e-2, max_steps=5000,
52 | save_m_steps=None, save_vtk_steps=50)
53 |
54 | np.save('m0.npy', sim.spin)
55 |
56 |
57 | if __name__ == '__main__':
58 |
59 | mesh = CuboidMesh(
60 | nx=501, ny=501, nz=1, dx=2.0, dy=2.0, dz=2.0, unit_length=1e-9, periodicity=(True, True, False))
61 |
62 | relax_system(mesh)
63 |
64 | # apply_field1(mesh)
65 | # deal_plot()
66 |
--------------------------------------------------------------------------------
/sandbox/parallel-cvode/test_cvode_serial.py:
--------------------------------------------------------------------------------
1 | import fidimag
2 | import time
3 | d = 100
4 | t = 10
5 | dx = dy = 2.5
6 |
7 | dz = 5
8 | mesh = fidimag.common.CuboidMesh(nx=int(d/dx), ny=int(d/dy), nz=int(t/dz), dx=dx, dy=dy, dz=dz, unit_length=1e-9)
9 |
10 | def Ms_function(Ms):
11 | def wrapped_function(pos):
12 | x, y, z = pos[0], pos[1], pos[2]
13 |
14 | r = ((x-d/2.)**2 + (y-d/2.)**2)**0.5 # distance from the centre
15 |
16 | if r <= d/2:
17 | # Mesh point is inside the disk.
18 | return Ms
19 | else:
20 | # Mesh point is outside the disk.
21 | return 0
22 | return wrapped_function
23 |
24 | def init_m(pos):
25 | x,y,z = pos
26 | x0, y0 = d/2., d/2.
27 | r = ((x-x0)**2 + (y-y0)**2)**0.5
28 |
29 | if r<10:
30 | return (0,0, 1)
31 | elif r<30:
32 | return (0,0, -1)
33 | elif r<60:
34 | return (0, 0, 1)
35 | else:
36 | return (0, 0, -1)
37 |
38 | # FeGe material paremeters.
39 | Ms = 3.84e5 # saturation magnetisation (A/m)
40 | A = 8.78e-12 # exchange energy constant (J/m)
41 | D = 1.58e-3 # Dzyaloshinkii-Moriya energy constant (J/m**2)
42 | alpha = 1 # Gilbert damping
43 | gamma = 2.211e5 # gyromagnetic ration (m/As)
44 |
45 | # Create simulation object.
46 | sim = fidimag.micro.Sim(mesh)
47 | sim.Ms = Ms_function(Ms)
48 | sim.alpha = alpha
49 | sim.driver.gamma = gamma
50 |
51 | # Add energies.
52 | sim.add(fidimag.micro.UniformExchange(A=A))
53 | sim.add(fidimag.micro.DMI(D=D))
54 | #sim.add(Demag())
55 |
56 | # Initialise the system.
57 | sim.set_m(init_m)
58 | a = time.time()
59 | sim.driver.run_until(5e-9)
60 | b = time.time()
61 | print('elpased time: %g'%(b - a))
62 |
--------------------------------------------------------------------------------
/examples/atomistic/heat/dw-heat.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import fidimag
3 | from fidimag.atomistic import *
4 | from fidimag.common import CuboidMesh
5 | import time
6 |
7 |
8 | def init_T(pos):
9 | return 0.001 * pos[0]
10 |
11 |
12 | def init_m(pos):
13 | x, y, z = pos
14 | if x < 300:
15 | return (1, 0, 0)
16 | elif x > 350:
17 | return (-1, 0, 0)
18 | else:
19 | return (0, 1, 0)
20 |
21 |
22 | def relax_system(mesh, mat):
23 | sim = Sim(mesh, name='relax')
24 | sim.set_mu_s(mat.mu_B)
25 | exch = UniformExchange(mat.J)
26 | sim.add(exch)
27 |
28 | anis = Anisotropy(mat.D)
29 | sim.add(anis)
30 |
31 | sim.set_m(init_m)
32 |
33 | ts = np.linspace(0, 5e-10, 21)
34 | sim.save_vtk()
35 |
36 | for t in ts:
37 | sim.driver.run_until(t)
38 | sim.save_vtk()
39 |
40 | return sim.spin
41 |
42 |
43 | def dw_motion(mesh, m0, mat, H0=1):
44 | sim = Sim(mesh, driver='sllg')
45 | sim.driver.set_T(init_T)
46 |
47 | exch = UniformExchange(mat.J)
48 | sim.add(exch)
49 |
50 | anis = Anisotropy(mat.D)
51 | sim.add(anis)
52 |
53 | # zeeman=Zeeman(H0,(1,0,0))
54 | # sim.add(zeeman)
55 |
56 | sim.set_m(m0)
57 |
58 | ts = np.linspace(0, 5e-10, 1001)
59 | for t in ts:
60 | sim.driver.run_until(t)
61 | print(t)
62 | sim.save_vtk()
63 |
64 |
65 | if __name__ == '__main__':
66 |
67 | ni = Nickel()
68 | ni.J *= 0.05
69 |
70 | dl = dx=ni.a*ni.unit_length
71 | mesh = fidimag.common.CuboidMesh(nx=200, ny=1, nz=1, dx=dl, dy=dl, dz=dl)
72 |
73 | m0 = relax_system(mesh, ni)
74 | print('relax system done')
75 | ni.alpha = 0.05
76 | dw_motion(mesh, m0, ni)
77 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.04
2 |
3 | # Avoid user interaction dialog
4 | ENV DEBIAN_FRONTEND=noninteractive
5 |
6 | RUN apt -y update
7 | # Binder fails with Cython from pip -> use apt cython3
8 | RUN apt install -y git python3 python3-pip gcc psutils cmake wget make cython3
9 | RUN apt install -y gfortran libblas-dev liblapack-dev python3-tk sudo fonts-lato
10 | RUN pip3 install pip -U
11 | RUN pip3 install matplotlib pytest scipy psutil pyvtk ipywidgets -U
12 | RUN pip3 install --no-cache-dir notebook
13 |
14 | RUN ln -s /usr/bin/python3 /usr/bin/python
15 |
16 | WORKDIR /usr/local
17 | RUN git clone https://github.com/computationalmodelling/fidimag.git
18 | WORKDIR /usr/local/fidimag
19 | # Work with stable release
20 | RUN git checkout tags/v3.0a2
21 | # Install CVODE and FFTW libraries
22 | WORKDIR /usr/local/fidimag/bin
23 | RUN bash install-fftw.sh
24 | RUN bash install-sundials.sh
25 |
26 | ENV PYTHONPATH="/usr/local/fidimag:$PYTHONPATH"
27 | ENV LD_LIBRARY_PATH="/usr/local/fidimag/local/lib:$LD_LIBRARY_PATH"
28 |
29 | WORKDIR /usr/local/fidimag
30 | RUN python3 setup.py build_ext --inplace
31 | RUN python3 -c "import matplotlib"
32 | # Headless Matplotlib:
33 | ENV MPLBACKEND=Agg
34 |
35 | # Headless Matplotlib:
36 | ENV MPLBACKEND=Agg
37 |
38 | # Set threads for OpenMP:
39 | ENV OMP_NUM_THREADS=2
40 | # WORKDIR /io
41 |
42 | # User to make Binder happy
43 | ENV NB_USER magnetism
44 | ENV NB_UID 1000
45 | ENV HOME /home/${NB_USER}
46 |
47 | RUN adduser --disabled-password \
48 | --gecos "Default user" \
49 | --uid ${NB_UID} \
50 | ${NB_USER}
51 |
52 | # Make sure the contents of our repo are in ${HOME}
53 | COPY . ${HOME}
54 | USER root
55 | RUN chown -R ${NB_UID} ${HOME}
56 | USER ${NB_USER}
57 |
58 | WORKDIR /home/${USER}/magnetism/doc/ipynb
59 |
--------------------------------------------------------------------------------
/fidimag/atomistic/lib/sllg.c:
--------------------------------------------------------------------------------
1 | #include "clib.h"
2 |
3 | /*
4 | * n is the spin number
5 | * eta is the random number array
6 | */
7 | void llg_rhs_dw_c(double *restrict m, double *restrict h, double *restrict dm, double *restrict T, double *restrict alpha,
8 | double *restrict mu_s_inv, int *restrict pins, double *restrict eta, int n, double gamma, double dt) {
9 |
10 | double k_B = 1.3806505e-23;
11 | double Q = 2 * k_B * dt / gamma;
12 |
13 | //#pragma omp parallel for
14 | for (int id = 0; id < n; id++) {
15 | int i = 3*id;
16 | int j = i+1;
17 | int k = j+1;
18 |
19 | if (pins[id]>0){
20 | dm[i] = 0;
21 | dm[j] = 0;
22 | dm[k] = 0;
23 | continue;
24 | }
25 |
26 |
27 | double coeff = -gamma/ (1.0 + alpha[id] * alpha[id]);
28 | double q = sqrt(Q * alpha[id] * T[id] * mu_s_inv[id]);
29 |
30 | double hi = h[i]*dt + eta[i]*q;
31 | double hj = h[j]*dt + eta[j]*q;
32 | double hk = h[k]*dt + eta[k]*q;
33 |
34 | double mth0 = coeff * (m[j] * hk - m[k] * hj);
35 | double mth1 = coeff * (m[k] * hi - m[i] * hk);
36 | double mth2 = coeff * (m[i] * hj - m[j] * hi);
37 |
38 | dm[i] = mth0 + alpha[id] * (m[j] * mth2 - m[k] * mth1);
39 | dm[j] = mth1 + alpha[id] * (m[k] * mth0 - m[i] * mth2);
40 | dm[k] = mth2 + alpha[id] * (m[i] * mth1 - m[j] * mth0);
41 |
42 | }
43 | }
44 |
45 | void normalise(double *restrict m, int *restrict pins, int n){
46 | int i, j, k;
47 | double mm;
48 | for (int id = 0; id < n; id++) {
49 | i = 3*id;
50 | j = i + 1;
51 | k = j + 1;
52 |
53 | if (pins[id]>0) continue;
54 |
55 |
56 | mm = 1.0 / sqrt(m[i] * m[i] + m[j] * m[j] + m[k] * m[k]);
57 | m[i] *= mm;
58 | m[j] *= mm;
59 | m[k] *= mm;
60 |
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/sandbox/parallel-cvode/test_cvode_parallel.py:
--------------------------------------------------------------------------------
1 | import fidimag
2 | import time
3 | d = 100
4 | t = 10
5 | dx = dy = 2.5
6 |
7 | dz = 5
8 | mesh = fidimag.common.CuboidMesh(nx=int(d/dx), ny=int(d/dy), nz=int(t/dz), dx=dx, dy=dy, dz=dz, unit_length=1e-9)
9 |
10 | def Ms_function(Ms):
11 | def wrapped_function(pos):
12 | x, y, z = pos[0], pos[1], pos[2]
13 |
14 | r = ((x-d/2.)**2 + (y-d/2.)**2)**0.5 # distance from the centre
15 |
16 | if r <= d/2:
17 | # Mesh point is inside the disk.
18 | return Ms
19 | else:
20 | # Mesh point is outside the disk.
21 | return 0
22 | return wrapped_function
23 |
24 | def init_m(pos):
25 | x,y,z = pos
26 | x0, y0 = d/2., d/2.
27 | r = ((x-x0)**2 + (y-y0)**2)**0.5
28 |
29 | if r<10:
30 | return (0,0, 1)
31 | elif r<30:
32 | return (0,0, -1)
33 | elif r<60:
34 | return (0, 0, 1)
35 | else:
36 | return (0, 0, -1)
37 |
38 | # FeGe material paremeters.
39 | Ms = 3.84e5 # saturation magnetisation (A/m)
40 | A = 8.78e-12 # exchange energy constant (J/m)
41 | D = 1.58e-3 # Dzyaloshinkii-Moriya energy constant (J/m**2)
42 | alpha = 1 # Gilbert damping
43 | gamma = 2.211e5 # gyromagnetic ration (m/As)
44 |
45 | # Create simulation object.
46 | sim = fidimag.micro.Sim(mesh, integrator='sundials_openmp')
47 | sim.Ms = Ms_function(Ms)
48 | sim.alpha = alpha
49 | sim.driver.gamma = gamma
50 |
51 | # Add energies.
52 | sim.add(fidimag.micro.UniformExchange(A=A))
53 | sim.add(fidimag.micro.DMI(D=D))
54 | #sim.add(Demag())
55 |
56 | # Initialise the system.
57 | sim.set_m(init_m)
58 | a = time.time()
59 | sim.driver.run_until(5e-9)
60 | b = time.time()
61 | print('elpased time: %g'%(b - a))
62 |
--------------------------------------------------------------------------------
/examples/atomistic/skyrmion_demag/single_ku.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim
3 | from fidimag.common import CuboidMesh
4 | from fidimag.atomistic import DMI, UniformExchange, Demag, Anisotropy
5 | import fidimag.common.constant as const
6 |
7 | def mu_s(pos):
8 | x, y, z = pos
9 | x0, y0, r = 60 * 0.5, 60 * 0.5, 60.5 * 0.5
10 |
11 | if (x - x0)**2 + (y - y0)**2 <= r**2:
12 | return const.mu_s_1
13 | else:
14 | return 0
15 |
16 |
17 | def init_m(pos):
18 | x, y, z = pos
19 |
20 | x0, y0, r = 60 * 0.5, 60 * 0.5, 25 * 0.5
21 |
22 | m1 = (0.05, 0.01, -1)
23 | m2 = (0, 0, 1)
24 |
25 | if (x - x0)**2 + (y - y0)**2 < r**2:
26 | return m1
27 | else:
28 | return m2
29 |
30 |
31 | def random_m(pos):
32 | return np.random.random(3) - 0.5
33 |
34 |
35 | def relax_system():
36 |
37 | mesh = CuboidMesh(nx=121, ny=121, dx=0.5, dy=0.5, unit_length=1e-9)
38 |
39 | sim = Sim(mesh, name='relax_skx')
40 | sim.driver.gamma=const.gamma
41 |
42 | sim.driver.alpha = 1.0
43 |
44 | sim.mu_s = mu_s
45 |
46 | sim.set_m(init_m)
47 |
48 | J = 50.0 * const.k_B
49 | exch = UniformExchange(J)
50 | sim.add(exch)
51 |
52 | D = 0.09 * J
53 | dmi = DMI(D)
54 | sim.add(dmi)
55 |
56 | K = 5e-3 * J
57 | anis = Anisotropy(K, axis=(0, 0, 1), name='Ku')
58 | sim.add(anis)
59 |
60 | sim.add(Demag(calc_every=100))
61 |
62 | ONE_DEGREE_PER_NS = 17453292.52
63 |
64 | sim.relax(dt=1e-12, stopping_dmdt=0.1,
65 | max_steps=5000, save_m_steps=100, save_vtk_steps=100)
66 |
67 | # np.save('m0.npy',sim.spin)
68 | sim.save_vtk()
69 |
70 | if __name__ == '__main__':
71 |
72 | np.random.seed(3)
73 | relax_system()
74 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Fidimag test
2 |
3 | on: [push]
4 |
5 | jobs:
6 | unit-tests:
7 |
8 | strategy:
9 | fail-fast: false
10 | matrix:
11 | python-version: ['3.10']
12 |
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: "Checkout"
17 | uses: actions/checkout@v2
18 |
19 | - name: Set up Python ${{ matrix.python-version }}
20 | uses: actions/setup-python@v2
21 | with:
22 | python-version: ${{ matrix.python-version }}
23 |
24 | - name: "Update apt and install cmake"
25 | run: |
26 | sudo apt-get -y update
27 | sudo apt-get install -y cmake
28 | sudo apt-get install -y libatlas-base-dev libatlas3-base
29 |
30 | - name: "Install sundials and fftw"
31 | working-directory: ./bin
32 | run: |
33 | bash install-fftw.sh
34 | bash install-sundials.sh
35 |
36 | - name: "Install pip and packages"
37 | working-directory: ./
38 | run: |
39 | python3 -m ensurepip
40 | python3 -m pip install --upgrade pip
41 | python3 -m pip install --user scipy numpy pytest matplotlib
42 | python3 -m pip install --user setuptools pyvtk cython psutil
43 |
44 | - name: "Install FIDIMAG"
45 | run: |
46 | python3 setup.py build_ext --inplace
47 | PWD=$(pwd)
48 | export PYTHONPATH=$PWD:$PYTHONPATH
49 | echo "PYTHONPATH=$PYTHONPATH"
50 | echo "PYTHONPATH=$PYTHONPATH" >> $GITHUB_ENV
51 | echo "LD_LIBRARY_PATH=$PWD/local/lib" >> $GITHUB_ENV
52 |
53 | - name: "Run test"
54 | working-directory: ./tests
55 | run: |
56 | python3 -m pytest -v
57 | # env:
58 | # PYTHONPATH: $PWD
59 |
--------------------------------------------------------------------------------
/examples/atomistic/stt/stt.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim, DMI, UniformExchange, Zeeman, Anisotropy
3 | from fidimag.common import CuboidMesh
4 |
5 |
6 | def init_m(pos):
7 | x, y, z = pos
8 | if x < 250:
9 | return (1, 0, 0)
10 | elif x > 270:
11 | return (-1, 0, 0)
12 | else:
13 | return (0, 1, 0)
14 |
15 |
16 | def relax_system(mesh):
17 |
18 | sim = Sim(mesh, name='relax')
19 | # sim.set_options(rtol=1e-10,atol=1e-14)
20 | sim.driver.alpha = 1.0
21 | sim.driver.gamma = 1.0
22 | sim.mu_s = 1.0
23 |
24 | sim.set_m(init_m)
25 | # sim.set_m(random_m)
26 | # sim.set_m(np.load('m_10000.npy'))
27 |
28 | J = 1.0
29 | exch = UniformExchange(J)
30 | sim.add(exch)
31 |
32 | Kx = Anisotropy(Ku=0.005, axis=(1, 0, 0), name='Kx')
33 | sim.add(Kx)
34 |
35 | sim.relax(dt=2.0, stopping_dmdt=1e-6, max_steps=1000,
36 | save_m_steps=100, save_vtk_steps=50)
37 |
38 | np.save('m0.npy', sim.spin)
39 |
40 |
41 | def dynamic(mesh):
42 |
43 | sim = Sim(mesh, name='dyn', driver='slonczewski')
44 | # sim.set_options(rtol=1e-10,atol=1e-14)
45 | sim.driver.gamma = 1.0
46 | sim.mu_s = 1.0
47 |
48 | sim.set_m(np.load('m0.npy'))
49 |
50 | J = 1.0
51 | exch = UniformExchange(J)
52 | sim.add(exch)
53 |
54 | Kx = Anisotropy(Ku=0.005, axis=(1, 0, 0), name='Kx')
55 | sim.add(Kx)
56 |
57 | sim.p = (0,0,1)
58 |
59 | sim.u0 = 0.03
60 | sim.driver.alpha = 0.1
61 |
62 | ts = np.linspace(0, 1e3, 101)
63 | for t in ts:
64 | sim.run_until(t)
65 | sim.save_vtk()
66 | print t
67 |
68 |
69 | if __name__ == '__main__':
70 | mesh = CuboidMesh(nx=500, ny=1, nz=1)
71 | relax_system(mesh)
72 | dynamic(mesh)
73 |
--------------------------------------------------------------------------------
/tests/test_demag.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | from fidimag.common import CuboidMesh
3 | from fidimag.atomistic import Sim
4 | from fidimag.atomistic import Demag
5 | import numpy as np
6 |
7 |
8 | def test_demag_fft_exact():
9 | mesh = CuboidMesh(nx=5, ny=3, nz=4, unit_length=1e-9)
10 | sim = Sim(mesh)
11 |
12 | demag = Demag()
13 | sim.add(demag)
14 |
15 | def init_m(pos):
16 | x = pos[0]
17 | if x <= 2:
18 | return (1, 0, 0)
19 | elif x >= 4:
20 | return (0, 0, 1)
21 | else:
22 | return (0, 1, 0)
23 |
24 | sim.set_m(init_m)
25 | fft = demag.compute_field()
26 | exact = demag.compute_exact()
27 |
28 | np.testing.assert_allclose(fft, exact, rtol=1e-10)
29 |
30 |
31 |
32 |
33 | def test_demag_fft_exact_oommf():
34 | mesh = CuboidMesh(nx=5, ny=3, nz=2, unit_length=1e-9)
35 | sim = Sim(mesh)
36 | demag = Demag()
37 | sim.add(demag)
38 |
39 | def init_m(pos):
40 | x = pos[0]
41 | if x <= 2:
42 | return (1, 0, 0)
43 | elif x >= 4:
44 | return (0, 0, 1)
45 | else:
46 | return (0, 1, 0)
47 | sim.set_m(init_m)
48 | fft = demag.compute_field()
49 | exact = demag.compute_exact()
50 | np.testing.assert_allclose(fft, exact, rtol=1e-10)
51 |
52 |
53 |
54 | def test_demag_two_spin_xx():
55 | mesh = CuboidMesh(nx=2, ny=1, nz=1)
56 | sim = Sim(mesh)
57 | demag = Demag()
58 | sim.add(demag)
59 | sim.set_m((1, 0, 0))
60 | field = demag.compute_field()
61 | print(field)
62 | assert(field[0] == 2e-7)
63 | assert(field[3] == 2e-7)
64 |
65 |
66 | if __name__ == '__main__':
67 | test_demag_fft_exact()
68 | test_demag_two_spin_xx()
69 | test_demag_fft_exact_oommf()
70 |
--------------------------------------------------------------------------------
/sandbox/parallel-cvode/test.py:
--------------------------------------------------------------------------------
1 | import fidimag
2 | d = 300
3 | t = 10
4 | dx = dy = 2.5
5 |
6 | dz = 5
7 | mesh = fidimag.common.CuboidMesh(nx=int(d/dx), ny=int(d/dy), nz=int(t/dz), dx=dx, dy=dy, dz=dz, unit_length=1e-9)
8 |
9 | def Ms_function(Ms):
10 | def wrapped_function(pos):
11 | x, y, z = pos[0], pos[1], pos[2]
12 |
13 | r = ((x-d/2.)**2 + (y-d/2.)**2)**0.5 # distance from the centre
14 |
15 | if r <= d/2:
16 | # Mesh point is inside the disk.
17 | return Ms
18 | else:
19 | # Mesh point is outside the disk.
20 | return 0
21 | return wrapped_function
22 |
23 | def init_m(pos):
24 | x,y,z = pos
25 | x0, y0 = d/2., d/2.
26 | r = ((x-x0)**2 + (y-y0)**2)**0.5
27 |
28 | if r<10:
29 | return (0,0, 1)
30 | elif r<30:
31 | return (0,0, -1)
32 | elif r<60:
33 | return (0, 0, 1)
34 | else:
35 | return (0, 0, -1)
36 |
37 | # FeGe material paremeters.
38 | Ms = 3.84e5 # saturation magnetisation (A/m)
39 | A = 8.78e-12 # exchange energy constant (J/m)
40 | D = 1.58e-3 # Dzyaloshinkii-Moriya energy constant (J/m**2)
41 | alpha = 1 # Gilbert damping
42 | gamma = 2.211e5 # gyromagnetic ration (m/As)
43 |
44 | # Create simulation object.
45 | sim = fidimag.micro.Sim(mesh, integrator='sundials')
46 | sim.Ms = Ms_function(Ms)
47 | sim.alpha = alpha
48 | sim.gamma = gamma
49 |
50 | # Add energies.
51 | sim.add(fidimag.micro.UniformExchange(A=A))
52 | sim.add(fidimag.micro.DMI(D=D))
53 | #sim.add(Demag())
54 |
55 | # Since the magnetisation dynamics is not important in this stage,
56 | # the precession term in LLG equation can be set to artificially zero.
57 | sim.do_precession = False
58 |
59 | # Initialise the system.
60 | sim.set_m(init_m)
61 |
62 | sim.run_until(5e-9)
63 |
--------------------------------------------------------------------------------
/sandbox/more-dmi/isolated_sk_sim.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import fidimag
3 | from fidimag.micro import Sim
4 | from fidimag.common import CuboidMesh
5 | import fidimag.common.constant as C
6 |
7 |
8 | def init_m(r):
9 | """
10 | Initial magnetisation profile; a dot to obtain a skyrmion
11 | """
12 | R_sk = 2
13 | rho = np.sqrt(r[0] ** 2 + r[1] ** 2)
14 | if rho < R_sk:
15 | return (0, 0, -1)
16 | else:
17 | return (0, 0, 1)
18 |
19 |
20 | dx, dy, dz = 0.25, 0.25, 1
21 | Lx, Ly, Lz = 20, 20, 1
22 | mesh = CuboidMesh(nx=int(Lx/dx), ny=int(Ly/dy), nz=int(Lz/dz),
23 | dx=dx, dy=dy, dz=dz,
24 | x0=-Lx/2, y0=-Ly/2, z0=-Lz/2,
25 | unit_length=1e-9)
26 |
27 | sim = Sim(mesh)
28 |
29 | Ms = 1.1e6
30 | A = 2e-12
31 | D = 3.9e-3
32 | Ku = 2.5e6
33 | Bz = 1.
34 |
35 | sim.set_Ms(Ms)
36 | sim.add(fidimag.micro.UniformExchange(A))
37 | sim.add(fidimag.micro.UniaxialAnisotropy(Ku, axis=(0, 0, 1)))
38 | sim.add(fidimag.micro.Zeeman((0, 0, Bz / C.mu_0)))
39 |
40 | # sim.add(fidimag.micro.DMI(D, dmi_type='interfacial'))
41 |
42 | # For a C_n material, there is a kind of instability when one of the DM
43 | # constants is larger than approx 0.7 times the other DM constant
44 | sim.add(fidimag.micro.DMI([D, 0.6 * D], dmi_type='C_n'))
45 |
46 | sim.set_m(init_m)
47 |
48 | sim.driver.do_precession = False
49 | sim.driver.alpha = 0.9
50 |
51 | sim.relax()
52 |
53 | # ----------------------------------------------------------------------------
54 | # Plot the 2D system
55 |
56 | import matplotlib.pyplot as plt
57 |
58 | m = sim.spin.reshape(-1, 3)
59 | plt.figure(figsize=(8, 8))
60 | plt.quiver(mesh.coordinates[:, 0], mesh.coordinates[:, 1],
61 | m[:, 0], m[:, 1],
62 | m[:, 2], cmap='RdYlBu'
63 | )
64 | plt.show()
65 |
--------------------------------------------------------------------------------
/docker/minimal-py2/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:14.04
2 |
3 | # packages we need to run fidimag
4 | RUN apt-get -y update
5 | RUN apt-get -y install python-numpy python-dev python-scipy
6 | RUN apt-get -y install python-pytest python-pyvtk ipython python-matplotlib mayavi2
7 | # standard tools for compilation
8 | RUN apt-get -y install wget make git
9 |
10 | # where to install source
11 | ENV FIDIMAG_HOME /home/fidimag
12 |
13 | RUN mkdir -p $FIDIMAG_HOME
14 | WORKDIR $FIDIMAG_HOME
15 | RUN git clone https://github.com/computationalmodelling/fidimag.git
16 | WORKDIR $FIDIMAG_HOME/fidimag/bin
17 |
18 | # install third party libraries from source
19 | RUN bash install-ubuntu-packages.sh
20 | RUN bash install-fftw.sh
21 | RUN bash install-sundials-2.5.sh
22 |
23 | # for pip
24 | RUN apt-get -y install python-pip
25 | # install cython
26 | RUN pip install cython --upgrade
27 | WORKDIR $FIDIMAG_HOME/fidimag
28 |
29 | # compile fidimag
30 | RUN make
31 | env PYTHONPATH=$FIDIMAG_HOME/fidimag
32 | env LD_LIBRARY_PATH=$FIDIMAG_HOME/fidimag/local/lib
33 | WORKDIR $FIDIMAG_HOME/fidimag/tests
34 |
35 | # check that tests run okay
36 | RUN py.test -v
37 |
38 |
39 | # install Jupyter, port exposing doesn't work yet
40 | #RUN pip install jupyter
41 |
42 | # expose jupyter port - not working yet
43 | #EXPOSE 8888 8888
44 |
45 |
46 | # Set up user so that we do not run as root
47 | RUN useradd -m -s /bin/bash -G sudo fidimag && \
48 | echo "fidimag:docker" | chpasswd && \
49 | echo "fidimag ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
50 | RUN chown -R fidimag $FIDIMAG_HOME
51 |
52 | # For bind mounts from host
53 | RUN mkdir /io
54 | RUN chown -R fidimag /io
55 |
56 | USER fidimag
57 | RUN touch $FIDIMAG_HOME/.sudo_as_admin_successful
58 |
59 | # Print something nice on entry.
60 | #COPY WELCOME $FIDIMAG_HOME/WELCOME
61 |
62 |
63 | WORKDIR /io
64 | CMD ["/bin/bash","-i"]
65 |
--------------------------------------------------------------------------------
/examples/atomistic/heat/temperature.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from pc import *
3 |
4 | import time
5 |
6 | import matplotlib as mpl
7 | mpl.use("Agg")
8 | import matplotlib.pyplot as plt
9 |
10 |
11 | def plot_mxyz(ts, mx, my, mz, me, name):
12 | fig = plt.figure()
13 | plt.plot(ts, mx, '^-', label='mx')
14 | plt.plot(ts, my, '.-', label='my')
15 | plt.plot(ts, mz, 'o-', label='mz')
16 | plt.plot(ts, me, '>-', label='me')
17 | plt.legend()
18 | fig.savefig(name)
19 |
20 |
21 | def temperature_test(T):
22 | ni = Nickel()
23 | ni.alpha = 0.1
24 | ni.D = 1.35e-26
25 | ni.mu_s = 2.16e-23
26 | ni.J = 6.16e-21
27 |
28 | (nx, ny, nz) = (24, 24, 24)
29 |
30 | mesh = CuboidMesh(nx=nx, ny=ny, nz=nz)
31 |
32 | sim = Sim(mesh, T=T, driver='sllg')
33 | sim.set_options(dt=1e-15, gamma=ni.gamma, k_B=ni.k_B)
34 | sim.mu_s = ni.mu_s
35 |
36 | exch = UniformExchange(ni.J)
37 | sim.add(exch)
38 |
39 | anis = Anisotropy(ni.D)
40 | sim.add(anis)
41 |
42 | # zeeman=Zeeman(1e2,(0,0,1))
43 | # sim.add(zeeman)
44 |
45 | # demag=Demag(mu_s=ni.mu_s)
46 | # sim.add(demag)
47 |
48 | sim.set_m((0, 0.6, 0.99))
49 |
50 | # vs=VisualSpin(sim)
51 | # vs.init()
52 |
53 | ts = np.linspace(0, 1e-11, 101)
54 | me = []
55 | mx = []
56 | my = []
57 | mz = []
58 | for t in ts:
59 | sim.run_until(t)
60 | # vs.update()
61 | av = sim.compute_average()
62 | mx.append(av[0])
63 | my.append(av[1])
64 | mz.append(av[2])
65 | me.append(np.sqrt(np.sum(av * av)))
66 | # time.sleep(0.001)
67 | #print av, me[-1]
68 | sim.save_vtk()
69 | name = 'nx%d_ny%d_nz%d_T%g.png' % (nx, ny, nz, T)
70 | plot_mxyz(ts, mx, my, mz, me, name)
71 |
72 |
73 | if __name__ == '__main__':
74 | temperature_test(100)
75 |
--------------------------------------------------------------------------------
/sandbox/more-dmi/test_dmi.mif:
--------------------------------------------------------------------------------
1 | # MIF 2.1 ---------------------------------------------------------------------
2 |
3 | # Generate an isolated skyrmion with bulk (T) DMI
4 | #
5 | # Authors: D. Cortes, M. Beg, H.Fangohr (2018)
6 |
7 | set PI [expr {4 * atan(1.)}]
8 | set MU0 [expr {4 * $PI * 1e-7}]
9 |
10 | # -----------------------------------------------------------------------------
11 | # PdFe on Ir(111) [PRL, 114(17):1-5, 2015]
12 | set Ms [expr {1.1e6}]
13 | set A [expr {2e-12}]
14 | set D [expr {-3.9e-3}]
15 | set KU [expr {2.5e6}]
16 | set BZ [expr {1.0}]
17 |
18 | set XL [expr {15e-9}]
19 | set YL [expr {$XL}]
20 | set ZL [expr {$XL}]
21 |
22 | set xcell [expr {$XL / 2}]
23 | set ycell [expr {$YL / 2}]
24 | set zcell [expr {$XL / 2}]
25 |
26 | # -----------------------------------------------------------------------------
27 |
28 | # BoxAtlas
29 | Specify Oxs_BoxAtlas:atlas [subst {
30 | xrange {0 $XL}
31 | yrange {0 $YL}
32 | zrange {0 $ZL}
33 | name atlas
34 | }]
35 |
36 | # RectangularMesh
37 | Specify Oxs_RectangularMesh:mesh [subst {
38 | cellsize {$xcell $ycell $zcell}
39 | atlas Oxs_BoxAtlas:atlas
40 | }]
41 |
42 | # T DMI
43 | Specify Oxs_DMI_T [subst {
44 | default_D $D
45 | atlas :atlas
46 | D {
47 | atlas atlas $D
48 | }
49 | }]
50 |
51 |
52 | # CGEvolver
53 | Specify Oxs_CGEvolve {}
54 |
55 | # MinDriver
56 | Specify Oxs_MinDriver [subst {
57 | evolver Oxs_CGEvolve
58 | stopping_mxHxm 0.01
59 | mesh :mesh
60 | Ms $Ms
61 | m0 { 0 0 1 }
62 | basename isolated_sk_T
63 | scalar_field_output_format {text %\#.15g}
64 | vector_field_output_format {text %\#.15g}
65 | }]
66 |
67 | Destination table mmArchive
68 | Destination mags mmArchive
69 | Schedule DataTable table Stage 1
70 | Schedule Oxs_MinDriver::Magnetization mags Stage 1
71 |
72 |
73 | # =============================================================================
74 |
75 |
--------------------------------------------------------------------------------
/examples/eigen/skx.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 |
4 | import numpy as np
5 | from fidimag.atomistic import Sim, DMI, UniformExchange, Zeeman, TimeZeeman
6 | from fidimag.common import DataReader, CuboidMesh
7 |
8 | from fidimag.atomistic.eigen import EigenProblem
9 |
10 | import matplotlib.pyplot as plt
11 |
12 | def init_m(pos):
13 | x,y,z = pos
14 |
15 | Rx, Ry, r = 87, 50, 12
16 |
17 | x = x%Rx + 20
18 | y = y%Ry
19 |
20 | m1 = (0.05,0.01,-1)
21 | m2 = (0,0,1)
22 |
23 | if x**2 + y**2 < r**2:
24 | return m1
25 | elif x**2 + (y-Ry)**2 < r**2:
26 | return m1
27 | elif (x-Rx)**2 + y**2 < r**2:
28 | return m1
29 | elif (x-Rx)**2 + (y-Ry)**2 < r**2:
30 | return m1
31 | elif (x-Rx/2.0)**2 + (y-Ry/2.0)**2 < r**2:
32 | return m1
33 | else:
34 | return m2
35 |
36 |
37 | def relax_system(mesh):
38 |
39 | sim=Sim(mesh,name='relax')
40 | sim.set_options(rtol=1e-12,atol=1e-14)
41 | sim.do_precession = False
42 | sim.driver.alpha = 0.5
43 | sim.driver.gamma = 1.0
44 | sim.mu_s = 1.0
45 |
46 | sim.set_m(init_m)
47 |
48 | J = 1.0
49 | exch = UniformExchange(J)
50 | sim.add(exch)
51 |
52 | D = 0.18
53 | dmi = DMI(D)
54 | sim.add(dmi)
55 |
56 | zeeman = Zeeman([0,0e-3,2e-2],name='H')
57 | sim.add(zeeman)
58 |
59 | sim.relax(dt=2.0, stopping_dmdt=1e-8, max_steps=10000, save_m_steps=None, save_vtk_steps=100)
60 |
61 | np.save('m0.npy',sim.spin)
62 |
63 |
64 | def eigen(mesh):
65 | m0 = np.load('m0.npy')
66 | ep = EigenProblem(mesh, m0, H=[0,0,2e-2], J=1.0, D=0.18)
67 | ep.solve_sparse()
68 |
69 |
70 | if __name__=='__main__':
71 |
72 | #mesh = CuboidMesh(nx=174,ny=150, nz=1, pbc='2d')
73 | mesh = CuboidMesh(nx=87,ny=100, nz=1, pbc='2d')
74 |
75 | relax_system(mesh)
76 |
77 | eigen(mesh)
78 |
--------------------------------------------------------------------------------
/fidimag/atomistic/demag_full.py:
--------------------------------------------------------------------------------
1 | import fidimag.extensions.clib as clib
2 | import numpy as np
3 | from .energy import Energy
4 |
5 |
6 | class DemagFull(Energy):
7 | """
8 | Calculation of the demag field using a brute-force approach,
9 | summing the dipolar contributions of the whole system for
10 | every lattice point.
11 | Since we can obtain the field directly, the energy is calculated
12 | in this process, thus we inherit from the Energy class
13 | as in the Exchange field, to calculate the total energy summing up
14 | the energy density.
15 | """
16 |
17 | def __init__(self, name='DemagFull'):
18 | self.name = name
19 | self.jac = True
20 |
21 | def setup(self, mesh, spin, mu_s, mu_s_inv):
22 | super(DemagFull, self).setup(mesh, spin, mu_s, mu_s_inv)
23 |
24 | unit_length = mesh.unit_length
25 | self.mu_s_scale = np.zeros(mesh.n, dtype=np.float64)
26 |
27 | # note that the 1e-7 comes from \frac{\mu_0}{4\pi}
28 | self.scale = 1e-7 / (unit_length ** 3)
29 |
30 | # could be wrong, needs carefully tests!!!
31 | self.mu_s_scale = self.mu_s * self.scale
32 |
33 | def compute_field(self, t=0, spin=None):
34 | if spin is not None:
35 | m = spin
36 | else:
37 | m = self.spin
38 |
39 | clib.compute_demag_full(m, self.field,
40 | self.energy,
41 | self.mesh.coordinates,
42 | self.mu_s,
43 | self.mu_s_scale,
44 | self.n
45 | )
46 |
47 | return self.field
48 |
49 | # def compute_energy(self):
50 | # energy = self.demag.compute_energy(
51 | # self.spin, self.mu_s_scale, self.field)
52 | # return energy / self.scale
53 |
--------------------------------------------------------------------------------
/examples/atomistic/demag_field/demag_field.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from fidimag.atomistic import Sim, Demag
7 | from fidimag.common import CuboidMesh
8 | import fidimag.common.constant as const
9 | from fidimag.common.save_vtk import SaveVTK
10 |
11 |
12 | def mu_s(pos):
13 | x, y, z = pos
14 | x0, y0, r = 60 * 0.5, 60 * 0.5, 30 * 0.5
15 |
16 | if (x - x0)**2 + (y - y0)**2 <= r**2:
17 | return const.mu_s_1
18 | else:
19 | return 0
20 |
21 |
22 | def init_m(pos):
23 | x, y, z = pos
24 |
25 | return (0, 0, 1)
26 |
27 |
28 | def random_m(pos):
29 | return np.random.random(3) - 0.5
30 |
31 |
32 | def plot_f(mesh, field, mu_s_inv):
33 | fig = plt.figure(figsize=(6, 4))
34 |
35 | field.shape = (3, -1)
36 |
37 | xs = range(121)
38 | fz = []
39 | for i in xs:
40 | j = mesh.index(i, 60, 0)
41 | if mu_s_inv[j] > 0:
42 | fz.append(0)
43 | else:
44 | fz.append(field[2][j])
45 |
46 | plt.plot(xs, fz)
47 | plt.savefig('f.pdf')
48 |
49 |
50 | def relax_system():
51 |
52 | mesh = CuboidMesh(nx=121, ny=121, nz=1, dx=0.5, dy=0.5, unit_length=1e-9)
53 |
54 | sim = Sim(mesh, name='relax_skx')
55 |
56 | sim.driver.gamma = const.gamma
57 | #sim.set_default_options(gamma=const.gamma)
58 |
59 | sim.driver.alpha = 1.0
60 |
61 | sim.mu_s = mu_s
62 |
63 | sim.set_m(init_m)
64 |
65 | demag = Demag()
66 |
67 | sim.add(demag)
68 |
69 | field = demag.compute_field()
70 |
71 | print(field)
72 |
73 | #vtk = SaveVTK(mesh, name='demag')
74 | #vtk.save_vtk(field)
75 |
76 | #sim.save_vtk()
77 |
78 | plot_f(mesh, field, sim._mu_s_inv)
79 |
80 | # np.save('m0.npy',sim.spin)
81 |
82 |
83 | if __name__ == '__main__':
84 |
85 | np.random.seed(3)
86 |
87 | relax_system()
88 |
--------------------------------------------------------------------------------
/examples/micromagnetic/vortex_oommf/relax.mif:
--------------------------------------------------------------------------------
1 | # MIF 2.1
2 |
3 | set pi [expr 4*atan(1.0)]
4 | set mu0 [expr 4*$pi*1e-7]
5 |
6 | RandomSeed 1
7 |
8 | Parameter cellsize_x 2.5e-9
9 | Parameter cellsize_y 2.5e-9
10 | Parameter cellsize_z 5e-9
11 |
12 |
13 | Specify Oxs_MultiAtlas:atlas {
14 | atlas { Oxs_BoxAtlas:left {
15 | xrange {0 200e-9}
16 | yrange {0 200e-9}
17 | zrange {0 20e-9}
18 | } }
19 | }
20 |
21 |
22 | Specify Oxs_RectangularMesh:mesh [subst {
23 | cellsize {$cellsize_x $cellsize_y $cellsize_z}
24 | atlas :atlas
25 | }]
26 |
27 |
28 | Specify Oxs_UniformExchange {
29 | A 1.3e-11
30 | }
31 |
32 | Specify Oxs_Demag {}
33 |
34 | Specify Oxs_RungeKuttaEvolve:evolve {
35 | alpha 1.0
36 | }
37 |
38 | Specify Oxs_TimeDriver [subst {
39 | basename ./plus
40 | evolver :evolve
41 | stopping_dm_dt 0.05
42 | mesh :mesh
43 |
44 | Ms { Oxs_ScriptScalarField {
45 | atlas :atlas
46 | script_args {rawpt}
47 | script {plus 8.6e5}
48 | } }
49 |
50 | m0 { Oxs_ScriptVectorField {
51 | atlas :atlas
52 | script_args {rawpt}
53 | script init_m0
54 | norm 1
55 | } }
56 |
57 | }]
58 |
59 |
60 | proc plus { Ms x y z } {
61 |
62 | set r 100e-9
63 |
64 | if { ($x-100e-9)*($x-100e-9) + ($y-100e-9)*($y-100e-9) > $r*$r} {
65 | return 0
66 | }
67 |
68 | return $Ms
69 | }
70 |
71 |
72 | proc init_m0 { x y z} {
73 | if { $x < $y } {
74 | if { $x + $y < 200e-9 } {
75 | return "0 -1 0"
76 | } else {
77 | return "-1 0 0"
78 | }
79 |
80 | } else {
81 | if { $x + $y < 200e-9 } {
82 | return "1 0 0"
83 | } else {
84 | return "0 1 0"
85 | }
86 | }
87 |
88 | }
89 |
90 | Destination archive mmArchive
91 |
92 | Schedule DataTable archive Step 20
93 | Schedule DataTable archive Stage 1
94 | Schedule Oxs_TimeDriver::Magnetization archive Stage 1
95 | Schedule Oxs_TimeDriver::Magnetization archive Step 50
96 |
--------------------------------------------------------------------------------
/examples/micromagnetic/vortex_oommf/dyn/dyn.mif:
--------------------------------------------------------------------------------
1 | # MIF 2.1
2 |
3 | set pi [expr 4*atan(1.0)]
4 | set mu0 [expr 4*$pi*1e-7]
5 |
6 | RandomSeed 1
7 |
8 | Parameter cellsize_x 2.5e-9
9 | Parameter cellsize_y 2.5e-9
10 | Parameter cellsize_z 5e-9
11 |
12 |
13 | Specify Oxs_MultiAtlas:atlas {
14 | atlas { Oxs_BoxAtlas:left {
15 | xrange {0 200e-9}
16 | yrange {0 200e-9}
17 | zrange {0 20e-9}
18 | } }
19 | }
20 |
21 |
22 | Specify Oxs_RectangularMesh:mesh [subst {
23 | cellsize {$cellsize_x $cellsize_y $cellsize_z}
24 | atlas :atlas
25 | }]
26 |
27 |
28 | Specify Oxs_UniformExchange {
29 | A 1.3e-11
30 | }
31 |
32 | Specify Oxs_Demag {}
33 |
34 | Specify Oxs_RungeKuttaEvolve:evolve {
35 | alpha 0.01
36 | }
37 |
38 | Specify Oxs_TimeDriver [subst {
39 | basename ./dyn
40 | evolver :evolve
41 | stopping_time 2e-12
42 | stage_count 1000
43 | mesh :mesh
44 |
45 | Ms { Oxs_ScriptScalarField {
46 | atlas :atlas
47 | script_args {rawpt}
48 | script {plus 8.6e5}
49 | } }
50 |
51 | m0 { Oxs_FileVectorField {
52 | atlas :atlas
53 | norm 1
54 | file ../plus-Oxs_TimeDriver-Magnetization-00-0001827.omf
55 | } }
56 |
57 | }]
58 |
59 |
60 | proc plus { Ms x y z } {
61 |
62 | set r 100e-9
63 |
64 | if { ($x-100e-9)*($x-100e-9) + ($y-100e-9)*($y-100e-9) > $r*$r} {
65 | return 0
66 | }
67 |
68 | return $Ms
69 | }
70 |
71 | Specify Oxs_ScriptUZeeman {
72 | script_args total_time
73 | script ExpField
74 | }
75 |
76 | proc ExpField { total_time } {
77 | set Hx [expr {79577*exp(-0.5*($total_time/0.1e-9)*($total_time/0.1e-9))}]
78 | set dHx [expr {-$Hx*$total_time/(0.1e-9)/(0.1e-9)}]
79 | return [list $Hx 0 0 $dHx 0 0]
80 | }
81 |
82 | Destination archive mmArchive
83 |
84 | #Schedule DataTable archive Step 20
85 | Schedule DataTable archive Stage 1
86 | #Schedule Oxs_TimeDriver::Magnetization archive Stage 1
87 | #Schedule Oxs_TimeDriver::Magnetization archive Step 50
88 |
--------------------------------------------------------------------------------
/examples/atomistic/sw.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from pccp.pc import *
3 | import time
4 |
5 |
6 | def init_m(pos):
7 | x, y, z = pos
8 | if x < 10:
9 | return (1, 0, 0)
10 | elif x > 10:
11 | return (-1, 0, 0)
12 | else:
13 | return (0, 1, 0)
14 |
15 |
16 | def pin_fun(t, mesh, spin):
17 | n = mesh.nxyz
18 | h0 = 0.1
19 | omega = 3
20 |
21 | t1 = h0 * np.cos(omega * t)
22 | t2 = h0 * np.sin(omega * t)
23 | t0 = np.sqrt(1 - t1 * t1 - t2 * t2)
24 |
25 | if t >= 1000 and t < 500:
26 | t0 = 1
27 | t1 = 0
28 | t2 = 0
29 |
30 | spin[0] = t0
31 | spin[n] = t1
32 | spin[n + n] = t2
33 |
34 |
35 | def relax_system(mesh):
36 | sim = Sim(mesh, name='relax')
37 | sim.driver.alpha = 0.5
38 | sim.driver.gamma = 5
39 | sim.c = 2
40 |
41 | exch = UniformExchange(1)
42 | sim.add(exch)
43 |
44 | anis = Anisotropy(0.3)
45 | sim.add(anis)
46 |
47 | sim.set_m(init_m)
48 |
49 | ts = np.linspace(0, 50, 101)
50 | for t in ts:
51 | sim.run_until(t)
52 |
53 | # sim.save_vtk()
54 | return sim.spin
55 |
56 |
57 | def spin_wave(mesh, m0, H0=10):
58 | sim = Sim(mesh, name='sw')
59 | sim.driver.alpha = 0.01
60 | sim.driver.gamma = 5
61 | sim.c = 2
62 | sim.pin_fun = pin_fun
63 |
64 | exch = UniformExchange(1)
65 | sim.add(exch)
66 |
67 | anis = Anisotropy(0.3)
68 | sim.add(anis)
69 |
70 | # zeeman=Zeeman(H0,(-1,0,0))
71 | # sim.add(zeeman)
72 |
73 | sim.set_m(m0)
74 | # vs=VisualSpin(sim)
75 | # vs.init()
76 |
77 | ts = np.linspace(0, 500, 501)
78 | for t in ts:
79 | sim.run_until(t)
80 | sim.save_vtk()
81 | # vs.update()
82 | # time.sleep(0.001)
83 |
84 |
85 | if __name__ == '__main__':
86 |
87 | mesh = CuboidMesh(nx=20)
88 |
89 | m0 = relax_system(mesh)
90 | print 'relax system done'
91 | # spin_wave(mesh,m0)
92 |
--------------------------------------------------------------------------------
/fidimag/common/neb_method/nebm_integrators.c:
--------------------------------------------------------------------------------
1 | #include "math.h"
2 | #include "nebm_lib.h"
3 | #include
4 | #include
5 |
6 | double step_Verlet_C(double *restrict forces,
7 | double *restrict forces_prev,
8 | double *restrict velocities,
9 | double *restrict velocities_new,
10 | double *restrict y,
11 | double t,
12 | double h,
13 | double mass,
14 | int n_images,
15 | int n_dofs_image,
16 | double (*update_field)(double, double *)
17 |
18 | ) {
19 |
20 | printf("Hellooooooo\n");
21 |
22 | update_field(t, y);
23 |
24 | int im_idx;
25 | for (int i = 1; i < n_images - 1; i++) {
26 |
27 | im_idx = n_dofs_image * i;
28 | double *force = &forces[im_idx];
29 | double *force_prev = &forces_prev[im_idx];
30 | double *velocity = &velocities[im_idx];
31 | double *velocity_new = &velocities_new[im_idx];
32 |
33 | double v_dot_f = 0;
34 | double f_dot_f = 0;
35 |
36 | for (int j = 0; i < n_dofs_image; j++) {
37 | y[im_idx + j] += h * (velocity[j] + (h / (2 * mass)) * force[j]);
38 |
39 | velocity[j] = velocity_new[j] + (h / (2 * mass)) * (force_prev[j] + force[j]);
40 |
41 | v_dot_f += velocity[j] * force[j];
42 | f_dot_f += force[j] * force[j];
43 |
44 | force_prev[j] = force[j];
45 | }
46 |
47 | if (v_dot_f <= 0) {
48 | for (int j = 0; i < n_dofs_image; j++) {
49 | velocity_new[j] = 0.0;
50 | }
51 | } else {
52 | for (int j = 0; i < n_dofs_image; j++) {
53 | velocity_new[j] = v_dot_f * force[j] / f_dot_f;
54 | }
55 | }
56 | }
57 |
58 | normalise_spins_C(y, n_images, n_dofs_image);
59 |
60 | return t + h;
61 | }
62 |
--------------------------------------------------------------------------------
/examples/micromagnetic/skyrmion_stt/main.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.micro import Sim
3 | from fidimag.common import CuboidMesh
4 | from fidimag.micro import UniformExchange, DMI, Zeeman
5 |
6 | mu0 = 4 * np.pi * 1e-7
7 |
8 |
9 | def init_m(pos):
10 |
11 | x, y = pos[0] - 100, pos[1] - 100
12 |
13 | if x**2 + y**2 > 20**2:
14 | return (0, 0, 1)
15 | else:
16 | return (0, 0, -1)
17 |
18 |
19 | def relax_system(mesh):
20 |
21 | sim = Sim(mesh, name='relax')
22 |
23 | sim.driver.set_tols(rtol=1e-6, atol=1e-6)
24 | sim.driver.alpha = 0.5
25 | sim.driver.gamma = 2.211e5
26 | sim.Ms = 8.6e5
27 | sim.do_precession = False
28 |
29 | sim.set_m(init_m)
30 |
31 | exch = UniformExchange(A=1.3e-11)
32 | sim.add(exch)
33 |
34 | dmi = DMI(D=-4e-3)
35 | sim.add(dmi)
36 |
37 | zeeman = Zeeman((0, 0, 4e5))
38 | sim.add(zeeman, save_field=True)
39 |
40 | sim.relax(dt=1e-13, stopping_dmdt=1e-2,
41 | save_m_steps=None, save_vtk_steps=50)
42 |
43 | np.save('m0.npy', sim.spin)
44 |
45 |
46 | def excite_system(mesh):
47 | sim = Sim(mesh, name='dyn', driver='llg_stt')
48 | sim.driver.set_tols(rtol=1e-8, atol=1e-10)
49 | sim.driver.alpha = 0.5
50 | sim.driver.gamma = 2.211e5
51 | sim.Ms = 8.6e5
52 |
53 | sim.set_m(np.load('m0.npy'))
54 |
55 | exch = UniformExchange(A=1.3e-11)
56 | sim.add(exch)
57 | dmi = DMI(D=-4e-3)
58 | sim.add(dmi)
59 | zeeman = Zeeman((0, 0, 4e5))
60 | sim.add(zeeman, save_field=True)
61 |
62 | sim.jx = -5e12
63 | sim.beta = 0
64 |
65 | ts = np.linspace(0, 0.5e-9, 101)
66 | for t in ts:
67 | print('time', t)
68 | sim.run_until(t)
69 | sim.save_vtk()
70 | #sim.save_m()
71 |
72 | if __name__ == '__main__':
73 |
74 | mesh = CuboidMesh(nx=101, ny=101, nz=1, dx=2.0, dy=2.0, dz=2.0, unit_length=1e-9, periodicity=(True, True, False))
75 |
76 | relax_system(mesh)
77 |
78 | excite_system(mesh)
79 |
--------------------------------------------------------------------------------
/examples/nebm_atomistic/1D_spin_chain/relaxation/1D_spin_chain_fm.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | from fidimag.atomistic import Sim
4 | from fidimag.common import CuboidMesh
5 | from fidimag.atomistic import DMI
6 | from fidimag.atomistic import UniformExchange
7 | from fidimag.atomistic import Zeeman
8 | from fidimag.atomistic import Anisotropy
9 | import fidimag.common.constant as const
10 |
11 | # Number of spins and lattice spacing (see mesh)
12 | nx = 50
13 | dx = 0.27
14 |
15 | sim_name = 'relax_spin_chain_fm'
16 |
17 |
18 | def relax_system():
19 |
20 | # 1D chain of 50 spins with a lattice constant of 0.27 A
21 | mesh = CuboidMesh(nx=nx,
22 | dx=dx,
23 | unit_length=1e-9,
24 | # pbc='1d'
25 | )
26 |
27 | # Initiate the simulation. PBCs are specified in the mesh
28 | sim = Sim(mesh, name=sim_name)
29 | sim.driver.gamma = const.gamma
30 |
31 | # magnetisation in units of Bohr's magneton
32 | sim.mu_s = 2. * const.mu_B
33 |
34 | # sim.set_options(gamma=const.gamma, k_B=const.k_B)
35 |
36 | # Initial magnetisation profile
37 | sim.set_m((0, 0, 1))
38 |
39 | # Exchange constant in Joules: E = Sum J_{ij} S_i S_j
40 | J = 12. * const.meV
41 | exch = UniformExchange(J)
42 | sim.add(exch)
43 |
44 | # DMI constant in Joules: E = Sum D_{ij} S_i x S_j
45 | D = 2. * const.meV
46 | dmi = DMI(D, dmi_type='interfacial')
47 | sim.add(dmi)
48 |
49 | # Anisotropy along +z axis
50 | ku = Anisotropy(Ku=0.5 * const.meV,
51 | axis=[0, 0, 1],
52 | name='ku')
53 | sim.add(ku)
54 |
55 | # Faster convergence
56 | sim.driver.alpha = 0.5
57 | sim.do_precession = False
58 |
59 | sim.relax(dt=1e-13, stopping_dmdt=0.05,
60 | max_steps=700,
61 | save_m_steps=1000, save_vtk_steps=1000)
62 |
63 | # Save the last relaxed state
64 | np.save(sim_name + '.npy', sim.spin)
65 |
66 |
67 | relax_system()
68 |
--------------------------------------------------------------------------------
/fidimag/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import platform
4 |
5 | try:
6 | from . import extensions
7 | from . import atomistic
8 | from . import micro
9 | from . import common
10 | citation = common.citation
11 | except ImportError as e:
12 | # cwd = os.getcwd()
13 | FIDIMAG_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
14 | # os.chdir(FIDIMAG_DIR)
15 | message = """
16 | Could not load the Fidimag extensions. This could be due to a few things:
17 | 1) The extensions are not built. Try running 'make' from the root directory.
18 |
19 | 2) FIDIMAG loads comon libraries dynamically. Currently, FIDIMAG requires
20 | * Sundials 6.6.1
21 | * FFTW 3.3.8
22 | If you are using Linux, you may be able to download these through a
23 | package manager such as apt or yum. However, convenience scripts
24 | are provided in the folder bin to install these locally for Ubuntu.
25 |
26 | 3) If you've run the scripts to install the dynamic libaries,
27 | you may still need to export the LD_LIBRARY_PATH environment
28 | variable. You can do this from the shell with:
29 | export LD_LIBRARY_PATH={}/local/lib:$LD_LIBRARY_PATH
30 |
31 | 4) If after trying *all* of the above, you still can't get Fidimag to install,
32 | please create an issue on the following website:
33 |
34 | https://github.com/computationalmodelling/fidimag/issues
35 |
36 | Copy and paste *all* of the information below which will help
37 | us to diagnose your problem:
38 |
39 |
40 | Exception Error message
41 | -----------------------
42 | {}
43 |
44 | System Info
45 | -----------------------
46 | Architecture: {}
47 | Platform: {}
48 | Processor: {}
49 | """
50 | print(message.format(FIDIMAG_DIR, e, platform.machine(), platform.platform(), platform.processor()))
51 |
52 |
53 | __version__ = '3.0'
54 |
--------------------------------------------------------------------------------
/fidimag/micro/lib/micro_clib.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | #define WIDE_PI 3.1415926535897932384626433832795L
6 | #define MU0 1.25663706143591728850e-6
7 | #define MU0_INV 795774.71545947669074
8 |
9 | inline double cross_x(double a0, double a1, double a2,
10 | double b0, double b1, double b2) { return a1 * b2 - a2 * b1; }
11 | inline double cross_y(double a0, double a1, double a2,
12 | double b0, double b1, double b2) { return a2 * b0 - a0 * b2; }
13 | inline double cross_z(double a0, double a1, double a2,
14 | double b0, double b1, double b2) { return a0 * b1 - a1 * b0; }
15 |
16 | void compute_exch_field_micro(double *restrict m, double *restrict field, double *restrict energy, double *restrict Ms_inv,
17 | double A, double dx, double dy, double dz, int n, int *ngbs);
18 |
19 | void dmi_field(double *restrict m, double *restrict field,
20 | double *restrict energy, double *restrict Ms_inv,
21 | double *restrict D, int n_DMIs,
22 | double *dmi_vector,
23 | double dx, double dy, double dz, int n, int *ngbs);
24 |
25 | void compute_exch_field_rkky_micro(double *m, double *field, double *energy, double *Ms_inv,
26 | double sigma, int nx, double ny, double nz, int z_bottom, int z_top);
27 |
28 | void compute_uniaxial_anis(double *restrict m, double *restrict field, double *restrict energy, double *restrict Ms_inv,
29 | double *restrict Ku, double *restrict axis, int nx, int ny, int nz);
30 |
31 | void compute_uniaxial4_anis(double *restrict m, double *restrict field, double *restrict energy, double *restrict Ms_inv,
32 | double *restrict K1, double *restrict K2, double *restrict axis, int nx, int ny, int nz);
33 |
34 | double skyrmion_number(double *restrict spin, double *restrict charge,
35 | int nx, int ny, int nz, int *restrict ngbs);
36 |
--------------------------------------------------------------------------------
/docker/minimal-py3/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:14.04
2 |
3 | # packages we need to run fidimag
4 | RUN apt-get -y update
5 | RUN apt-get -y install python3-numpy python3-dev python3-scipy cmake
6 | RUN apt-get -y install python3-pytest ipython3 python3-matplotlib python3-pip
7 | # standard tools for compilation
8 | RUN apt-get -y install wget make git
9 |
10 | # where to install source
11 | ENV FIDIMAG_HOME /home/fidimag
12 |
13 | RUN mkdir -p $FIDIMAG_HOME
14 | WORKDIR $FIDIMAG_HOME
15 | RUN git clone https://github.com/computationalmodelling/fidimag.git
16 | WORKDIR $FIDIMAG_HOME/fidimag/bin
17 |
18 | # install third party libraries from source
19 | RUN bash install-fftw.sh
20 | RUN bash install-sundials.sh
21 |
22 | # for pip
23 | RUN python3 -m pip install --user --upgrade setuptools pip
24 | # install pyvtk
25 | RUN python3 -m pip install pyvtk
26 | # install cython
27 | RUN python3 -m pip install cython --upgrade
28 | WORKDIR $FIDIMAG_HOME/fidimag
29 | RUN apt-get -y install libatlas-base-dev libatlas3-base libatlas3gf-base
30 | # compile fidimag
31 | RUN python3 setup.py build_ext --inplace
32 | env PYTHONPATH=$FIDIMAG_HOME/fidimag
33 | env LD_LIBRARY_PATH=$FIDIMAG_HOME/fidimag/local/lib
34 | WORKDIR $FIDIMAG_HOME/fidimag/tests
35 |
36 | # check that tests run okay
37 | RUN py.test-3 -v
38 |
39 |
40 | # install Jupyter, port exposing doesn't work yet
41 | #RUN pip install jupyter
42 |
43 | # expose jupyter port - not working yet
44 | #EXPOSE 8888 8888
45 |
46 |
47 | # Set up user so that we do not run as root
48 | RUN useradd -m -s /bin/bash -G sudo fidimag && \
49 | echo "fidimag:docker" | chpasswd && \
50 | echo "fidimag ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
51 | RUN chown -R fidimag $FIDIMAG_HOME
52 |
53 | # For bind mounts from host
54 | RUN mkdir /io
55 | RUN chown -R fidimag /io
56 |
57 | USER fidimag
58 | RUN touch $FIDIMAG_HOME/.sudo_as_admin_successful
59 |
60 | RUN cd fidimag
61 | RUN py.test -v
62 | # Print something nice on entry.
63 | #COPY WELCOME $FIDIMAG_HOME/WELCOME
64 |
65 | WORKDIR /io
66 | CMD ["/bin/bash","-i"]
67 |
--------------------------------------------------------------------------------
/examples/neb_micromagnetic/domain_wall/dw.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import numpy as np
6 | from fidimag.micro import Sim, UniformExchange, Demag, UniaxialAnisotropy
7 | from fidimag.common import CuboidMesh
8 | from fidimag.common.nebm_cartesian import NEBM_Cartesian
9 | # TODO: FIX the plotting functions
10 | # from fidimag.common.helper import plot_energy_2d, plot_energy_3d
11 | #from finmag.sim.neb import plot_energy_2d, plot_energy_3d
12 |
13 |
14 | def init_dw(pos):
15 | x = pos[0]
16 |
17 | if x < 200:
18 | return (-1, 0, 0)
19 | elif x > 300:
20 | return (1, 0, 0)
21 | else:
22 | return (0, 1, 0)
23 |
24 |
25 | def create_simulation(mesh):
26 |
27 | sim = Sim(mesh)
28 | sim.Ms = 8.6e5
29 |
30 | sim.set_m((1, 0, 0))
31 | sim.add(UniformExchange(A=1.3e-11))
32 | # sim.add(Demag())
33 | #sim.add(UniaxialAnisotropy(Kx, (1, 0, 0), name='Kx'))
34 | anis = UniaxialAnisotropy(1e5, axis=(1, 0, 0))
35 | sim.add(anis)
36 |
37 | return sim
38 |
39 |
40 | def relax_system(sim):
41 |
42 | # init_images=[np.load('m_init.npy')]
43 | """
44 | n=20
45 | for i in range(1,n):
46 | theta = i*np.pi/n
47 | mx = -np.cos(theta)
48 | my = np.sin(theta)
49 | init_images.append((mx,my,0))
50 | """
51 |
52 | # init_images.append(np.load('m_final.npy'))
53 |
54 | init_images = [(-1, 0, 0), init_dw, (1, 0, 0)]
55 |
56 | neb = NEBM_Cartesian(
57 | sim, init_images, interpolations=[6, 6], name='neb',
58 | spring_constant=1e8)
59 |
60 | # neb.add_noise(0.1)
61 |
62 | neb.relax(dt=1e-8, max_iterations=5000, save_vtks_every=500,
63 | save_npys_every=500, stopping_dYdt=100)
64 |
65 | if __name__ == "__main__":
66 |
67 | mesh = CuboidMesh(nx=160, ny=1, nz=1, dx=4.0, dy=4.0, dz=4.0, unit_length=1e-9)
68 |
69 | sim = create_simulation(mesh)
70 | # relax_two_state(mesh)
71 | relax_system(sim)
72 | # plot_energy_2d('neb')
73 | # plot_energy_3d('neb')
74 |
--------------------------------------------------------------------------------
/fidimag/common/vtk.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pyvtk
3 | from fidimag.common import CuboidMesh
4 | from fidimag.atomistic.hexagonal_mesh import HexagonalMesh
5 | import sys
6 |
7 | log = pyvtk.logging.getLogger(pyvtk.__name__)
8 | log.setLevel(pyvtk.logging.ERROR)
9 |
10 |
11 | class VTK(object):
12 | def __init__(self, mesh, header="", directory=".", filename="unnamed"):
13 | self.mesh = mesh
14 | self.directory = directory
15 | self.filename = filename
16 |
17 | if isinstance(mesh, HexagonalMesh):
18 | structure = pyvtk.PolyData(points=mesh.vertices,
19 | polygons=mesh.hexagons)
20 | elif isinstance(mesh, CuboidMesh):
21 | # for keyword argument dimensions: if the mesh is made up of
22 | # nx * ny * nz cells, it has (nx + 1) * (ny + 1) * (nz + 1)
23 | # vertices.
24 | structure = pyvtk.RectilinearGrid(* mesh.grid)
25 | else:
26 | raise NotImplementedError(
27 | "Mesh should be CuboidMesh or HexagonalMesh, is {}.".format(
28 | mesh.__class__.__name__))
29 | self.structure = structure
30 | self.header = header
31 |
32 | self.init_VtkData(structure, header)
33 |
34 | def init_VtkData(self, structure, header):
35 | self.vtk_data = pyvtk.VtkData(structure, header)
36 |
37 | def reset_data(self):
38 | self.vtk_data = pyvtk.VtkData(self.structure, self.header)
39 |
40 | def save_scalar(self, s, name="my_field", step=0):
41 | self.vtk_data.cell_data.append(pyvtk.Scalars(s, name))
42 |
43 | def save_vector(self, v, name="my_field", step=0):
44 | self.vtk_data.cell_data.append(pyvtk.Vectors(v, name))
45 |
46 | def write_file(self, step=0):
47 | if not os.path.isdir(self.directory):
48 | os.makedirs(self.directory)
49 |
50 | filename = "{}_{:06}".format(self.filename, step) + ".vtk"
51 | path = os.path.join(self.directory, filename)
52 | self.vtk_data.tofile(path)
53 | return path
54 |
--------------------------------------------------------------------------------
/bin/install-sundials.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | # This script installs any SUNDIALS version starting with version 2.6.0
5 | # when SUNDIALS moved to a CMake-based installation. Will install locally.
6 | # It may need environment variables to work, like `export CC=gcc` in ARCHER.
7 |
8 | # Github release from Sundials repository
9 | # https://github.com/LLNL/sundials
10 | SUNDIALS_TAG=v6.6.1
11 | SUNDIALS=sundials-6.6.1
12 |
13 | # Make sure CMake is installed, since SUNDIALS requires it.
14 | type cmake >/dev/null 2>&1 || { printf "CMake required to build SUNDIALS. You can install it by typing: \nsudo apt install cmake\n"; exit 1;}
15 |
16 |
17 | HERE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
18 | FIDIMAG_DIR="$(dirname "$HERE_DIR")"
19 |
20 | if [ -z $LIBS_DIR ]; then LIBS_DIR=${FIDIMAG_DIR}/local; fi
21 |
22 | echo "Will install SUNDIALS to "${LIBS_DIR}" using CC="${CC}"."
23 | mkdir -p ${LIBS_DIR}
24 | cd ${LIBS_DIR}
25 |
26 | download_and_cmake_install() {
27 | # $1 tag of the package
28 | # $2 name of the package
29 | # $3 URL where ${1}.tar.gz can be obtained
30 | # $4 configure options
31 | if [ ! -e ${1}/${2}.tar.gz ]; then
32 | echo "Downloading "${3}/${1}/${2}.tar.gz"."
33 | wget -q -O ${2}.tar.gz ${3}/${1}/${2}.tar.gz
34 | fi;
35 |
36 | if [ ! -e ${2} ]; then
37 | tar -xzf ${2}.tar.gz
38 |
39 | echo "Configuring "${2}"."
40 | mkdir ${2}_build
41 | cd ${2}_build
42 | cmake ${4} ../${2}
43 |
44 | echo "Compiling and installing "${2}"."
45 | {
46 | make -j2
47 | make install
48 | } > /dev/null
49 |
50 | echo "Cleaning up."
51 | cd ..
52 | rm -rf ${2}
53 | rm -rf ${2}_build
54 |
55 | cd ${HERE_DIR}
56 | echo "Done."
57 | fi;
58 | }
59 |
60 | download_and_cmake_install \
61 | ${SUNDIALS_TAG} \
62 | ${SUNDIALS} \
63 | https://github.com/LLNL/sundials/releases/download \
64 | "-DBUILD_STATIC_LIBS=OFF -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX="${LIBS_DIR}" -DEXAMPLES_ENABLE=OFF -DENABLE_LAPACK=ON -DENABLE_OPENMP=ON"
65 |
--------------------------------------------------------------------------------
/tests/test_monte_carlo.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 |
5 | import fidimag.extensions.clib as clib
6 | import numpy as np
7 | from fidimag.atomistic import MonteCarlo, HexagonalMesh
8 | import fidimag.common.constant as const
9 |
10 | def test_random_sphere(do_plot=False):
11 | """
12 | test whether spins are uniformly distributed on the surface of a sphere.
13 | """
14 | mt19937 = clib.rng_mt19937()
15 | mt19937.set_seed(123)
16 | spin = np.zeros(3 * 10000, dtype=np.float64)
17 | mt19937.fill_vector_uniform_sphere(spin, 10000)
18 | spin.shape = (-1,3)
19 | n = spin.shape[0]
20 | x = np.average([spin[i,0] for i in range(n) if spin[i,0]>0])
21 | y = np.average([spin[i,1] for i in range(n) if spin[i,1]>0])
22 | z = np.average([spin[i,2] for i in range(n) if spin[i,2]>0])
23 | print(x,y,z)
24 | print(abs(x-y), abs(x-z), abs(y-z))
25 | assert(abs(x-y)<4e-3)
26 | assert(abs(x-z)<4e-3)
27 | assert(abs(y-z)<4e-3)
28 |
29 | if do_plot:
30 | fig = plt.figure()
31 | ax3D = fig.add_subplot(111, projection='3d')
32 | ax3D.scatter(spin[:1000,0], spin[:1000,1], spin[:1000,2], s=30, marker='.')
33 | plt.savefig('test_random_sphere.png')
34 |
35 | def random_m(pos):
36 | return np.random.random(3) - 0.5
37 |
38 | def test_mc_run(Hz=6.0, T=5.0):
39 | #This fast test just shows whether mc can be run or not.
40 | np.random.seed(100)
41 | #mesh = CuboidMesh(nx=28*2, ny=16*3, nz=1, periodicity = (True, True, False))
42 | mesh = HexagonalMesh(1, 28, 16*2, periodicity=(True, True))
43 | mc = MonteCarlo(mesh, name='test_mc')
44 | mc.set_m(random_m)
45 | J = 50*const.k_B
46 | mc.set_options(H=[0,0,Hz], J=J, D=0.5*J, T=T)
47 | mc.run(steps=5000, save_m_steps=None, save_vtk_steps=None, save_data_steps=1000)
48 | skx_number = mc.skyrmion_number()
49 | assert(skx_number<-2.5)
50 | assert(skx_number>-3.5)
51 | #np.save('m.npy', mc.spin)
52 | #plot_m(mesh, 'm.npy', comp='z')
53 |
54 | if __name__ == '__main__':
55 | test_random_sphere(do_plot=True)
56 | test_mc_run()
57 |
--------------------------------------------------------------------------------
/examples/micromagnetic/std4_oommf/stdprob4.mif:
--------------------------------------------------------------------------------
1 | # MIF 2.1
2 | #
3 | # muMAG Standard Problem 4.
4 | #
5 | set pi [expr 4*atan(1.0)]
6 | set mu0 [expr 4*$pi*1e-7]
7 |
8 | Parameter solver rkf54 ;# One of rk2, rk2heun, rk4,
9 | ## rkf54, rkf54m, or rkf54s
10 |
11 | Parameter subproblem 1 ;# Should be either 1 or 2
12 |
13 | Parameter initproblem 1 ;# Use 1 to generate initial state,
14 | ## or 0 to run using previously generated state.
15 |
16 | if {1 == $subproblem} {
17 | set basename stdprob4a
18 | set Hx -24.6 ;# Applied field in mT
19 | set Hy 4.3
20 | } elseif {2 == $subproblem} {
21 | set basename stdprob4b
22 | set Hx -35.5 ;# Applied field in mT
23 | set Hy -6.3
24 | } else {
25 | error "Unrecognized subproblem request: $subproblem\
26 | (should be 1 or 2)"
27 | }
28 | set Hz 0.0
29 |
30 | Specify Oxs_BoxAtlas:atlas {
31 | xrange {0 500e-9}
32 | yrange {0 125e-9}
33 | zrange {0 3e-9}
34 | }
35 |
36 | Specify Oxs_RectangularMesh:mesh {
37 | cellsize {2.5e-9 2.5e-9 3e-9}
38 | atlas Oxs_BoxAtlas:atlas
39 | }
40 |
41 | Specify Oxs_UniformExchange {
42 | A 13E-12
43 | }
44 |
45 | Specify Oxs_Demag {}
46 |
47 | if {$initproblem} {
48 | Specify Oxs_CGEvolve {}
49 | Specify Oxs_MinDriver [subst {
50 | basename stdprob4
51 | evolver Oxs_CGEvolve
52 | mesh :mesh
53 | stopping_mxHxm 1e-6
54 | Ms 8e5
55 | m0 { 1 0.25 0.1 }
56 | }]
57 | } else {
58 | Specify Oxs_FixedZeeman [subst {
59 | multiplier [expr 0.001/$mu0]
60 | field {$Hx $Hy $Hz}
61 | }]
62 | Specify Oxs_RungeKuttaEvolve:evolver [subst {
63 | gamma_G 2.211e5
64 | alpha 0.02
65 | method $solver
66 | }]
67 | Specify Oxs_TimeDriver [subst {
68 | basename $basename
69 | evolver :evolver
70 | mesh :mesh
71 | stopping_time 1e-12
72 | stage_count 3000
73 | Ms 8e5
74 | m0 { Oxs_FileVectorField {
75 | atlas :atlas
76 | norm 1.0
77 | file stdprob4-start.omf
78 | }}
79 | }]
80 | }
81 |
82 |
83 | Destination archive mmArchive Stage 1
84 | Schedule DataTable archive Stage 1
85 | #Schedule Oxs_TimeDriver::Magnetization archive Stage 100
86 |
--------------------------------------------------------------------------------
/examples/atomistic/PRL_108_017601/figure2.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim, DMI, UniformExchange, Zeeman, TimeZeeman
3 | from fidimag.common import CuboidMesh, DataReader
4 | import matplotlib as mpl
5 | mpl.use("Agg")
6 | import matplotlib.pyplot as plt
7 |
8 |
9 | def sinc_fun(t):
10 |
11 | w0 = 0.01
12 |
13 | return np.sinc(w0 * t)
14 |
15 |
16 | def excite_system(mesh):
17 |
18 | sim = Sim(mesh, name='dyn')
19 |
20 | # sim.set_options(rtol=1e-10,atol=1e-14)
21 | sim.driver.alpha = 0.04
22 | sim.driver.gamma = 1.0
23 | sim.mu_s = 1.0
24 |
25 | sim.set_m(np.load('m0.npy'))
26 |
27 | J = 1.0
28 | exch = UniformExchange(J)
29 | sim.add(exch)
30 |
31 | D = 0.09
32 | dmi = DMI(D)
33 | sim.add(dmi)
34 |
35 | zeeman = Zeeman([0, 0, 3.75e-3], name='H')
36 | sim.add(zeeman)
37 |
38 | w0 = 0.02
39 |
40 | def time_fun(t):
41 | return np.exp(-w0 * t)
42 |
43 | hx = TimeZeeman([0, 0, 1e-5], sinc_fun, name='h')
44 | sim.add(hx, save_field=True)
45 |
46 | ts = np.linspace(0, 20000, 5001)
47 | for t in ts:
48 | sim.run_until(t)
49 | print 'sim t=%g' % t
50 |
51 |
52 | def deal_plot():
53 | data = DataReader('dyn.txt')
54 | ts = data['time']
55 | N = len(ts)
56 | dt = ts[1] - ts[0]
57 | print 'dt=', dt
58 |
59 | freq = np.fft.fftshift(np.fft.fftfreq(N, dt))
60 |
61 | H = data['h_z']
62 | M = data['m_z']
63 |
64 | fH = np.fft.fftshift(np.fft.fft(H))
65 | fM = np.fft.fftshift(np.fft.fft(M))
66 |
67 | a = fH.real
68 | b = fH.imag
69 | c = fM.real
70 | d = fM.imag
71 |
72 | rx = (a * c + b * d) / (a * a + b * b)
73 | ix = (b * c - a * d) / (a * a + b * b)
74 |
75 | plt.plot(freq * 2 * np.pi, ix, '.-')
76 | # plt.legend()
77 | plt.xlim([0, 0.012])
78 | #plt.ylim([-5, 100])
79 | plt.xlabel(r'$w$')
80 | plt.ylabel('Susceptibility')
81 | plt.savefig('res.pdf')
82 |
83 |
84 | if __name__ == '__main__':
85 |
86 | #mesh = CuboidMesh(nx=288,ny=288,nz=1)
87 | mesh = CuboidMesh(nx=166, ny=96 * 2, nz=1, periodicity=(True, True, False))
88 |
89 | excite_system(mesh)
90 |
91 | deal_plot()
92 |
--------------------------------------------------------------------------------
/fidimag/micro/relax.py:
--------------------------------------------------------------------------------
1 | import fidimag.extensions.baryakhtar_clib as clib
2 | import numpy as np
3 |
4 |
5 | class Relaxation(object):
6 |
7 | """
8 | compute the relaxation field related to exchange field.
9 | """
10 |
11 | def __init__(self, chi, name='relax'):
12 | self.chi = chi
13 | self.name = name
14 |
15 | def setup(self, mesh, m, Ms):
16 | self.mesh = mesh
17 | self.dx = mesh.dx * mesh.unit_length
18 | self.dy = mesh.dy * mesh.unit_length
19 | self.dz = mesh.dz * mesh.unit_length
20 | self.nx = mesh.nx
21 | self.ny = mesh.ny
22 | self.nz = mesh.nz
23 | self.spin = m
24 | self.Ms = Ms
25 | self.field = np.zeros(3 * mesh.n)
26 |
27 | if self.chi == 0.0:
28 | self.chi_inv = 0
29 | else:
30 | self.chi_inv = 1.0 / self.chi
31 |
32 | def compute_field(self, t=0):
33 |
34 | clib.compute_relaxation_field(self.spin,
35 | self.field,
36 | self.Ms,
37 | self.chi_inv,
38 | self.mesh.n)
39 |
40 | return self.field
41 |
42 | def compute_energy(self):
43 |
44 | return 0.0
45 |
46 |
47 | class Laplace(object):
48 |
49 | """
50 | compute the laplace for given field.
51 | """
52 |
53 | def __init__(self, mesh):
54 | self.dx = mesh.dx * mesh.unit_length
55 | self.dy = mesh.dy * mesh.unit_length
56 | self.dz = mesh.dz * mesh.unit_length
57 | self.nx = mesh.nx
58 | self.ny = mesh.ny
59 | self.nz = mesh.nz
60 | self.field = np.zeros(3 * mesh.n)
61 |
62 | def compute_laplace_field(self, h, Ms):
63 |
64 | clib.compute_laplace_field(h, self.field,
65 | Ms,
66 | self.dx,
67 | self.dy,
68 | self.dz,
69 | self.nx,
70 | self.ny,
71 | self.nz)
72 |
73 | return self.field
74 |
--------------------------------------------------------------------------------
/tests/test_vtk_writing.py:
--------------------------------------------------------------------------------
1 | import os
2 | import subprocess
3 | from fidimag.common import CuboidMesh
4 | from fidimag.atomistic.hexagonal_mesh import HexagonalMesh
5 | from fidimag.common.field import scalar_field, vector_field
6 | from fidimag.common.vtk import VTK
7 | import pyvtk
8 | import pytest
9 |
10 | MODULE_DIR = os.path.realpath(os.path.dirname(__file__))
11 | REF_DIR = os.path.dirname(__file__) + '/vtk_refs/'
12 |
13 | def same_as_ref(filepath, ref_dir):
14 | """
15 | Looks for file with the same filename as `filepath` in `ref_dir`
16 | and compares the two.
17 |
18 | """
19 | filename = os.path.basename(filepath)
20 | reference = os.path.join(ref_dir, filename)
21 | ret = subprocess.call(["diff", filepath, reference])
22 | f = open(filepath, 'r').read()
23 | print('new\n', f)
24 | f = open(reference, 'r').read()
25 | print('ref\n', f)
26 |
27 | return ret == 0 # 0 means files are the same, c.f. man diff exit codes
28 |
29 | @pytest.mark.skip(reason="Need a better way to test; precision means comparing diffs does not work.")
30 | def test_save_scalar_field(tmpdir):
31 | mesh = CuboidMesh(4, 3, 2, 4, 3, 2)
32 | s = scalar_field(mesh, lambda r: r[0] + r[1] + r[2])
33 | vtk = VTK(mesh, directory=str(tmpdir), filename="save_scalar")
34 | vtk.save_scalar(s, name="s")
35 | assert same_as_ref(vtk.write_file(), REF_DIR)
36 |
37 | @pytest.mark.skip(reason="Need a better way to test; precision means comparing diffs does not work.")
38 | def test_save_vector_field(tmpdir):
39 | mesh = CuboidMesh(4, 3, 2, 4, 3, 2)
40 | s = vector_field(mesh, lambda r: (r[0], r[1], r[2]))
41 | vtk = VTK(mesh, directory=str(tmpdir), filename="save_vector")
42 | vtk.save_vector(s, name="s")
43 | assert same_as_ref(vtk.write_file(), REF_DIR)
44 |
45 | @pytest.mark.skip(reason="Need a better way to test; precision means comparing diffs does not work.")
46 | def test_save_scalar_field_hexagonal_mesh(tmpdir):
47 | mesh = HexagonalMesh(1, 3, 3)
48 | s = scalar_field(mesh, lambda r: r[0] + r[1])
49 | vtk = VTK(mesh, directory=str(tmpdir), filename="scalar_hexagonal")
50 | vtk.save_scalar(s, name="s")
51 | assert same_as_ref(vtk.write_file(), REF_DIR)
52 |
--------------------------------------------------------------------------------
/fidimag/common/dipolar/license.txt:
--------------------------------------------------------------------------------
1 | The files demag_oommf.c and demagcoef.h are from the OOMMF project
2 | (http://math.nist.gov/oommf/) and are distributed under this license:
3 |
4 | --------------
5 |
6 | OOMMF - Object Oriented MicroMagnetic Framework
7 |
8 | The research software provided in this release (“software”) is provided by
9 | NIST as a public service. You may use, copy and distribute copies of the
10 | software in any medium, provided that you keep intact this entire notice.
11 | You may improve, modify and create derivative works of the software or any
12 | portion of the software, and you may copy and distribute such modifications
13 | or works. Modified works should carry a notice stating that you changed the
14 | software and should note the date and nature of any such change. Please
15 | explicitly acknowledge the National Institute of Standards and Technology
16 | as the source of the software.
17 |
18 | The software is expressly provided “AS IS.” NIST MAKES NO WARRANTY OF ANY
19 | KIND, EXPRESS, IMPLIED, IN FACT OR ARISING BY OPERATION OF LAW, INCLUDING,
20 | WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
21 | PARTICULAR PURPOSE, NON-INFRINGEMENT AND DATA ACCURACY. NIST NEITHER
22 | REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE
23 | UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST
24 | DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE
25 | SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE
26 | CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE.
27 |
28 | You are solely responsible for determining the appropriateness of using
29 | and distributing the software and you assume all risks associated with
30 | its use, including but not limited to the risks and costs of program
31 | errors, compliance with applicable laws, damage to or loss of data,
32 | programs or equipment, and the unavailability or interruption of operation.
33 | This software is not intended to be used in any situation where a failure
34 | could cause risk of injury or damage to property. The software was
35 | developed by NIST employees. NIST employee contributions are not subject
36 | to copyright protection within the United States.
37 |
38 |
--------------------------------------------------------------------------------
/tests/test_exch_rkky.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | import matplotlib as mpl
3 | mpl.use("Agg")
4 | import matplotlib.pyplot as plt
5 |
6 | from fidimag.common import CuboidMesh
7 | from fidimag.micro import Sim
8 | from fidimag.micro import Zeeman
9 | from fidimag.micro import UniaxialAnisotropy, ExchangeRKKY
10 | import numpy as np
11 |
12 |
13 | def init_m(pos):
14 | x, y, z = pos
15 | if z<1:
16 | return (0,0.01,-1)
17 | else:
18 | return (0.01, 0, 1)
19 |
20 |
21 | def spatial_Ms(pos):
22 | x, y, z = pos
23 | if z<2 and z>1:
24 | return 0
25 | else:
26 | return 8.6e5
27 |
28 |
29 | def test_excahnge_rkky(do_plot=False):
30 |
31 | mesh = CuboidMesh(nx=1, ny=1, nz=3, dz=1.0, unit_length=1e-9)
32 |
33 | sim = Sim(mesh, name='spin')
34 | sim.driver.alpha = 0.001
35 | sim.driver.gamma = 2.211e5
36 | sim.Ms = spatial_Ms
37 |
38 | sim.set_m(init_m)
39 |
40 | anis = UniaxialAnisotropy(5e4, axis=(0,0,1))
41 | sim.add(anis)
42 |
43 | exch = ExchangeRKKY(sigma=-1e-4)
44 | sim.add(exch)
45 |
46 | ts = np.linspace(0, 3e-9, 1001)
47 |
48 | mx = []
49 |
50 | mxt = []
51 |
52 | real_ts = []
53 | for t in ts:
54 | sim.driver.run_until(t)
55 | real_ts.append(sim.driver.t)
56 | print(sim.driver.t, abs(sim.spin_length()[0] - 1))
57 | mx.append(sim.spin[0])
58 | mxt.append(sim.spin[6])
59 |
60 |
61 | id = np.argmax(abs(np.fft.fft(mx)))
62 | freqs = np.fft.fftfreq(len(mx), ts[1]-ts[0])
63 |
64 | mu0 = 4*np.pi*1e-7
65 | Ms = 8.6e5
66 | K = 2*5e4/(mu0*Ms)
67 | sigma = 1e-4/1e-9/(mu0*Ms)
68 | expected = 2.211e5*(K*(K+2*sigma))**0.5/(2*np.pi)
69 |
70 | if do_plot:
71 | ts_ns = np.array(real_ts) * 1e9
72 | plt.plot(ts_ns, mx, label="mx", color='darkslateblue')
73 | plt.plot(ts_ns, mxt, label="mxt", color='m')
74 |
75 | plt.xlabel("time (ns)")
76 | plt.ylabel("m")
77 | plt.legend()
78 | plt.savefig("test_rkky.pdf")
79 |
80 | print((freqs[id]-expected)/expected)
81 | print((freqs[id]-expected)/expected<0.01)
82 |
83 |
84 |
85 | if __name__ == '__main__':
86 | test_excahnge_rkky(do_plot=True)
87 |
--------------------------------------------------------------------------------
/examples/nebm_atomistic/skyrmion_reduced/relax.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.atomistic import Sim, DMI, UniformExchange, Anisotropy
3 | from fidimag.common import CuboidMesh
4 | from fidimag.atomistic import NEB_Sundials
5 |
6 | def mu_s(pos):
7 | x,y,z = pos
8 | x0,y0,r = 60,60,60.5
9 |
10 | if (x-x0)**2 + (y-y0)**2 <= r**2:
11 | return 1
12 | else:
13 | return 0
14 |
15 | def init_m(pos):
16 | x,y,z = pos
17 |
18 | x0,y0,r = 60,60,25
19 |
20 | m1 = (0.05,0.01,-1)
21 | m2 = (0,0,1)
22 |
23 | if (x-x0)**2 + (y-y0)**2 < r**2:
24 | return m1
25 | else:
26 | return m2
27 |
28 | def init_m_down(pos):
29 | x,y,z = pos
30 |
31 | x0,y0,r = 60,60,25
32 |
33 | m1 = (0.05,0.01,1)
34 | m2 = (0,0,-1)
35 |
36 | if (x-x0)**2 + (y-y0)**2 < r**2:
37 | return m1
38 | else:
39 | return m2
40 |
41 | def create_sim():
42 |
43 | mesh = CuboidMesh(nx=121,ny=121,nz=1)
44 | sim=Sim(mesh,name='relax')
45 |
46 | sim.driver.alpha = 1.0
47 | sim.driver.gamma = 0.5
48 | sim.mu_s = mu_s
49 |
50 | sim.set_m(init_m)
51 |
52 | J = 1.0
53 | exch = UniformExchange(J)
54 | sim.add(exch)
55 |
56 | D = 0.08
57 | dmi = DMI(D)
58 | sim.add(dmi)
59 |
60 | K = 4e-3
61 | anis=Anisotropy(K, direction=(0,0,1),name='Ku')
62 | sim.add(anis)
63 |
64 | return sim
65 |
66 |
67 | def relax_system():
68 |
69 | sim = create_sim()
70 |
71 | sim.do_precession = False
72 |
73 | sim.relax(dt=2.0, stopping_dmdt=1e-6, max_steps=5000, save_m_steps=100, save_vtk_steps=100)
74 |
75 | np.save('m_up.npy',sim.spin)
76 |
77 | sim.set_m(init_m_down)
78 |
79 | sim.relax(dt=2.0, stopping_dmdt=1e-6, max_steps=5000, save_m_steps=100, save_vtk_steps=100)
80 |
81 | np.save('m_down.npy',sim.spin)
82 |
83 | def run_neb():
84 |
85 | sim = create_sim()
86 |
87 | init_images = [np.load('m_up.npy'), np.load('m_down.npy')]
88 |
89 | neb = NEB_Sundials(sim, init_images, interpolations=[10], name='neb', spring=1.0)
90 |
91 | neb.relax(dt=1, max_steps=5000, save_vtk_steps=500, save_npy_steps=500, stopping_dmdt=1e-5)
92 |
93 |
94 |
95 | if __name__=='__main__':
96 |
97 | #relax_system()
98 | run_neb()
99 |
--------------------------------------------------------------------------------
/fidimag/micro/exchange_rkky.py:
--------------------------------------------------------------------------------
1 | import fidimag.extensions.micro_clib as micro_clib
2 | from .energy import Energy
3 | #from constant import mu_0
4 |
5 |
6 | class ExchangeRKKY(Energy):
7 |
8 | """
9 | RKKYExchange(sigma, Delta, z_bottom=0, z_top = -1, name='RKKYExchange')
10 |
11 | Compute the RKKY-style exchange interaction defined by
12 |
13 | E = sigma/Delta *(1-m_t * m_b)
14 |
15 | where E is the energy density, sigma is the surface exchange coefficient between the two surfaces,
16 | Delata is the space thickness. m_t and m_b are the unit vectors of the top and bottom layers, respectively.
17 |
18 | Inputs:
19 | sigma: float
20 | sigma is the surface exchange stiffness constant.
21 | Delta: float
22 | Delta is the the space thickness in Meter.
23 | z_bottom: int
24 | z_bottom is the index of the bottom layer
25 | z_top: int
26 | z_top is the index of the top layer.
27 |
28 | """
29 |
30 | def __init__(self, sigma, Delta=1e-9, z_bottom=0, z_top = -1, name='RKKYExchange'):
31 | self.sigma = sigma/Delta
32 | self.name = name
33 | self.z_bottom = z_bottom
34 | self.z_top = z_top
35 | self.jac = True
36 |
37 | def setup(self, mesh, spin, Ms, Ms_inv):
38 | super(ExchangeRKKY, self).setup(mesh, spin, Ms, Ms_inv)
39 | if self.z_top<0:
40 | self.z_top+= self.nz
41 |
42 |
43 | def compute_field(self, t=0, spin=None):
44 | if spin is not None:
45 | m = spin
46 | else:
47 | m = self.spin
48 |
49 | micro_clib.compute_exchange_field_micro_rkky(m,
50 | self.field,
51 | self.energy,
52 | self.Ms_inv,
53 | self.sigma,
54 | self.nx,
55 | self.ny,
56 | self.nz,
57 | self.z_bottom,
58 | self.z_top
59 | )
60 |
61 | return self.field
62 |
--------------------------------------------------------------------------------
/fidimag/atomistic/llg.py:
--------------------------------------------------------------------------------
1 | from __future__ import division
2 | from __future__ import print_function
3 |
4 | # Use the common C library for the LLG equation in the atomistic case
5 | import fidimag.extensions.common_clib as clib
6 |
7 | from .atomistic_driver import AtomisticDriver
8 |
9 |
10 | class LLG(AtomisticDriver):
11 |
12 | """
13 |
14 | This class is the driver to solve the Landau Lifshitz Gilbert equation
15 | which has the form:
16 |
17 |
18 | ds -gamma
19 | ---- = -------- ( s X H_eff + a * s X ( s X H_eff ) )
20 | dt 2
21 | ( 1 + a )
22 |
23 | by using the Sundials library with CVODE.
24 |
25 | This class inherits common methods to evolve the system using CVODE, from
26 | the micro_driver.MicroDriver class. Arrays with the system information
27 | are taken as references from the main micromagnetic Simulation class
28 |
29 | """
30 |
31 | def __init__(self, mesh, spin, mu_s, mu_s_inv, field, pins,
32 | interactions,
33 | name,
34 | data_saver,
35 | use_jac,
36 | integrator='sundials'
37 | ):
38 |
39 | # Inherit from the driver class
40 | super(LLG, self).__init__(mesh, spin, mu_s, mu_s_inv, field,
41 | pins, interactions, name,
42 | data_saver,
43 | use_jac,
44 | integrator=integrator
45 | )
46 |
47 | def sundials_rhs(self, t, y, ydot):
48 |
49 | self.t = t
50 |
51 | # already synchronized when call this funciton
52 | # self.spin[:]=y[:]
53 |
54 | self.compute_effective_field(t)
55 |
56 | clib.compute_llg_rhs(ydot,
57 | self.spin,
58 | self.field,
59 | self._alpha,
60 | self._pins,
61 | self.gamma,
62 | self.n,
63 | self.do_precession,
64 | self.default_c)
65 |
66 | #ydot[:] = self.dm_dt[:]
67 |
68 | return 0
69 |
70 | if __name__ == '__main__':
71 | pass
72 |
--------------------------------------------------------------------------------
/examples/nebm_atomistic/1D_spin_chain/relaxation/1D_spin_chain.py:
--------------------------------------------------------------------------------
1 |
2 | import numpy as np
3 | from fidimag.atomistic import Sim
4 | from fidimag.common import CuboidMesh
5 | from fidimag.atomistic import DMI
6 | from fidimag.atomistic import UniformExchange
7 | from fidimag.atomistic import Zeeman
8 | from fidimag.atomistic import Anisotropy
9 | import fidimag.common.constant as const
10 |
11 | # Number of spins and lattice spacing (see mesh)
12 | nx = 50
13 | dx = 0.27
14 |
15 |
16 | # ^ ^ ^
17 | # An irregular initial state | | | | | | | | |
18 | # v v v v v v
19 | def init_m(pos):
20 |
21 | chain_third = nx * dx / 3.
22 |
23 | x = pos[0]
24 |
25 | if x < chain_third or x > 2 * chain_third:
26 | return (0, 0, -1)
27 | else:
28 | return (0, 0, 1)
29 |
30 | sim_name = 'relax_spin_chain'
31 |
32 |
33 | def relax_system():
34 |
35 | # 1D chain of 50 spins with a lattice constant of 0.27 A
36 | mesh = CuboidMesh(nx=nx,
37 | dx=dx,
38 | unit_length=1e-9,
39 | # pbc='1d'
40 | )
41 |
42 | # Initiate the simulation
43 | sim = Sim(mesh, name=sim_name)
44 | sim.driver.gamma = const.gamma
45 |
46 | # magnetisation in units of Bohr's magneton
47 | sim.mu_s = 2 * const.mu_B
48 |
49 | # sim.set_options(gamma=const.gamma, k_B=const.k_B)
50 |
51 | # Initial magnetisation profile
52 | sim.set_m(init_m)
53 |
54 | # Exchange constant in Joules: E = Sum J_{ij} S_i S_j
55 | J = 12. * const.meV
56 | exch = UniformExchange(J)
57 | sim.add(exch)
58 |
59 | # DMI constant in Joules: E = Sum D_{ij} S_i x S_j
60 | D = 2. * const.meV
61 | dmi = DMI(D, dmi_type='interfacial')
62 | sim.add(dmi)
63 |
64 | # Anisotropy along +z axis
65 | ku = Anisotropy(Ku=0.5 * const.meV,
66 | axis=[0, 0, 1],
67 | name='ku')
68 | sim.add(ku)
69 |
70 | # Faster convergence
71 | sim.driver.alpha = 0.5
72 | sim.do_precession = False
73 |
74 | sim.relax(dt=1e-13, stopping_dmdt=0.05,
75 | max_steps=700,
76 | save_m_steps=1000, save_vtk_steps=1000)
77 |
78 | # Save the last relaxed state
79 | np.save(sim_name + '.npy', sim.spin)
80 |
81 | relax_system()
82 |
--------------------------------------------------------------------------------
/examples/neb_micromagnetic/skyrmion/relaxation/skyrmion_down_relax.py:
--------------------------------------------------------------------------------
1 | """
2 |
3 | Script to generate a skyrmion pointing DOWN in a 50 nm wide
4 | and 5 nm thick FeGe disk
5 |
6 | The skyrmion is stabilised due to the finite system (border
7 | effects) and without Demag, external magnetic fields or
8 | anisotropies
9 |
10 | """
11 |
12 | # FIDIMAG:
13 | from fidimag.micro import Sim, UniformExchange, Demag, DMI
14 | from fidimag.common import CuboidMesh
15 | import numpy as np
16 |
17 |
18 | # Material Parameters for FeGe
19 | A = 8.78e-12
20 | D = 1.58e-3
21 | Ms = 3.84e5
22 |
23 | # Radius of the nanodisk
24 | radius = 25
25 |
26 | # MESH
27 | # We pass this function to the Ms property
28 | # of the simulation, so spins outside the desired
29 | # radius will have Ms = 0
30 | def cylinder(pos):
31 |
32 | # Relative position
33 | x, y = pos[0] - radius, pos[1] - radius
34 |
35 | if x ** 2 + y ** 2 < radius ** 2:
36 | return Ms
37 | else:
38 | return 0
39 |
40 | # We will generate a 50 nm wide and 5nm thick disk The finite difference
41 | # elements are 2nmx2nm cubes along the disk plane and they have a thickness of
42 | # 1 nm
43 | # Finite differences mesh
44 | mesh = CuboidMesh(nx=25, ny=25, nz=5,
45 | dx=2, dy=2, dz=1,
46 | unit_length=1e-9
47 | )
48 |
49 |
50 | # Initial magnetisation profile to get the skyrmion
51 | # We create a small core pointing in the -z direction
52 | def init_m(pos):
53 |
54 | x, y = pos[0] - radius, pos[1] - radius
55 |
56 | if x ** 2 + y ** 2 < radius ** 2:
57 | return (0, 0, -1)
58 | else:
59 | return (0, 0, 1)
60 |
61 | # Prepare simulation
62 | # We define the cylinder with the Magnetisation function
63 | sim = Sim(mesh, name='skyrmion_down')
64 | sim.Ms = cylinder
65 |
66 | # To get a faster relaxation, we tune the LLG equation parameters
67 | sim.do_precession = False
68 | sim.driver.alpha = 0.5
69 |
70 | # Initial magnetisation:
71 | sim.set_m(init_m)
72 |
73 | # Energies:
74 |
75 | # Exchange
76 | sim.add(UniformExchange(A=A))
77 |
78 | # Bulk DMI
79 | sim.add(DMI(D=D))
80 |
81 | # Relax the system
82 | sim.relax(dt=1e-12, stopping_dmdt=0.0001, max_steps=5000,
83 | save_m_steps=None,
84 | save_vtk_steps=None
85 | )
86 |
87 | # Save the final state and a vtk file
88 | np.save('sk_down.npy', sim.spin)
89 | sim.save_vtk()
90 |
--------------------------------------------------------------------------------
/examples/neb_micromagnetic/skyrmion/relaxation/skyrmion_relax.py:
--------------------------------------------------------------------------------
1 | """
2 |
3 | Script to generate a skyrmion pointing up in a 50 nm wide
4 | and 5 nm thick FeGe disk
5 |
6 | The skyrmion is stabilised due to the finite system (border
7 | effects) and without Demag, external magnetic fields or
8 | anisotropies
9 |
10 | """
11 |
12 | # FIDIMAG:
13 | from fidimag.micro import Sim, UniformExchange, Demag, DMI
14 | from fidimag.common import CuboidMesh
15 | import numpy as np
16 |
17 |
18 | # Material Parameters for FeGe
19 | A = 8.78e-12
20 | D = 1.58e-3
21 | Ms = 3.84e5
22 |
23 | # Radius of the nanodisk
24 | radius = 25
25 |
26 | # MESH
27 | # We pass this function to the Ms property
28 | # of the simulation, so spins outside the desired
29 | # radius will have Ms = 0
30 | def cylinder(pos):
31 |
32 | # Relative position
33 | x, y = pos[0] - radius, pos[1] - radius
34 |
35 | if x ** 2 + y ** 2 < radius ** 2:
36 | return Ms
37 | else:
38 | return 0
39 |
40 | # We will generate a 50 nm wide and 5nm thick disk The finite difference
41 | # elements are 2nmx2nm cubes along the disk plane and they have a thickness of
42 | # 1 nm
43 | # Finite differences mesh
44 | mesh = CuboidMesh(nx=25, ny=25, nz=5,
45 | dx=2, dy=2, dz=1,
46 | unit_length=1e-9
47 | )
48 |
49 |
50 | # Initial magnetisation profile to get the skyrmion
51 | # We create a small core pointing in the +z direction
52 | def init_m(pos):
53 |
54 | x, y = pos[0] - radius, pos[1] - radius
55 |
56 | if x ** 2 + y ** 2 < radius ** 2:
57 | return (0, 0, 1)
58 | else:
59 | return (0, 0, -1)
60 |
61 | # Prepare simulation
62 |
63 | # We define the cylinder with the Magnetisation function
64 | sim = Sim(mesh, name='skyrmion')
65 | sim.Ms = cylinder
66 |
67 | # To get a faster relaxation, we tune the LLG equation parameters
68 | sim.do_precession = False
69 | sim.driver.alpha = 0.5
70 |
71 | # Initial magnetisation:
72 | sim.set_m(init_m)
73 |
74 | # Energies:
75 |
76 | # Exchange
77 | sim.add(UniformExchange(A=A))
78 |
79 | # Bulk DMI
80 | sim.add(DMI(D=D))
81 |
82 | # Relax the system
83 | sim.relax(dt=1e-12, stopping_dmdt=0.0001, max_steps=5000,
84 | save_m_steps=None,
85 | save_vtk_steps=None
86 | )
87 |
88 | # Save the final relaxed state and a vtk file
89 | np.save('sk_up.npy', sim.spin)
90 | sim.save_vtk()
91 |
--------------------------------------------------------------------------------
/examples/atomistic/dmi/interfacial_dmi_dw/dw.py:
--------------------------------------------------------------------------------
1 | import matplotlib as mpl
2 | mpl.use("Agg")
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 | from fidimag.atomistic import Sim, DMI, UniformExchange, Anisotropy
6 | from fidimag.common import constant, CuboidMesh
7 |
8 |
9 | def m_init_dw(pos):
10 |
11 | x = pos[0]
12 |
13 | if x < 140:
14 | return (0, 0, 1)
15 | elif x > 160:
16 | return (0, 0, -1)
17 | else:
18 | return (0, 1, 1)
19 |
20 |
21 | def analytical(xs, A=1.3e-11, D=4e-4, K=8e4):
22 |
23 | delta = np.sqrt(A / (K - D * D / (4 * A)))
24 |
25 | phi = D / (2 * A) * xs
26 |
27 | mx = - np.tanh(xs / delta)
28 | my = 1.0 / np.cosh(xs / delta) * np.cos(phi)
29 | mz = 1.0 / np.cosh(xs / delta) * np.sin(phi)
30 | return mx, my, mz
31 |
32 |
33 | def relax_system(mesh):
34 |
35 | sim = Sim(mesh, name='relax')
36 | sim.driver.gamma = constant.gamma
37 | sim.driver.alpha = 0.5
38 | sim.mu_s = constant.mu_s_1
39 | sim.do_precession = False
40 |
41 | sim.set_m(m_init_dw)
42 |
43 | J = 50.0 * constant.k_B
44 | exch = UniformExchange(J)
45 | sim.add(exch)
46 |
47 | D = 0.1 * J
48 | dmi = DMI(D, dmi_type='interfacial')
49 | sim.add(dmi)
50 |
51 | K = 0.02 * J
52 | anis = Anisotropy(K, axis=[0, 0, 1])
53 | sim.add(anis)
54 |
55 | ONE_DEGREE_PER_NS = 17453292.52
56 |
57 | sim.relax(dt=1e-13, stopping_dmdt=0.01 * ONE_DEGREE_PER_NS,
58 | max_steps=1000, save_m_steps=100, save_vtk_steps=50)
59 |
60 | np.save('m0.npy', sim.spin)
61 |
62 | xs = np.array([p[0] for p in mesh.coordinates]) - 150
63 |
64 | mx, my, mz = analytical(xs, A=J/2.0, D=-D, K=K)
65 | mxyz = sim.spin.copy()
66 | mxyz.shape = (3, -1)
67 |
68 | save_plot(xs, mxyz, mx, my, mz)
69 |
70 |
71 | def save_plot(xs, mxyz, mx, my, mz):
72 | fig = plt.figure()
73 | mxyz.shape = (3, -1)
74 | plt.plot(xs, mxyz[0], '.', label='mx')
75 | plt.plot(xs, mxyz[1], '.', label='my')
76 | plt.plot(xs, mxyz[2], '.', label='mz')
77 |
78 | plt.plot(xs, mx, '-')
79 | plt.plot(xs, my, '-')
80 | plt.plot(xs, mz, '-')
81 |
82 | plt.ylabel('mxyz')
83 | plt.xlabel('x/a')
84 | plt.legend(loc=1)
85 | plt.grid()
86 | #plt.xlim([-150, 150])
87 | plt.ylim([-1.2, 1.2])
88 | fig.savefig('dw_dmi.pdf')
89 |
90 |
91 | if __name__ == '__main__':
92 | mesh = CuboidMesh(nx=300, ny=40, nz=1)
93 | relax_system(mesh)
94 | #excite_system(mesh)
95 |
--------------------------------------------------------------------------------
/examples/micromagnetic/single_spin/single_spin.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from fidimag.micro import Sim, Zeeman
3 | from fidimag.common import CuboidMesh
4 | from fidimag.common.fileio import DataReader
5 | import matplotlib.pyplot as plt
6 |
7 |
8 | def single_spin(alpha, gamma, H0, ts):
9 | """
10 | compute single spin under the external field H
11 | """
12 |
13 | precession = gamma / (1 + alpha**2)
14 | beta = precession * H0 * ts
15 |
16 | mx = np.cos(beta) / np.cosh(alpha * beta)
17 | my = np.sin(beta) / np.cosh(alpha * beta)
18 | mz = np.tanh(alpha * beta)
19 |
20 | return mx, my, mz
21 |
22 |
23 | def relax_system():
24 | mesh = CuboidMesh(nx=1, ny=1, nz=1)
25 | sim = Sim(mesh, name='relax')
26 | sim.driver.set_tols(rtol=1e-10, atol=1e-10)
27 | sim.driver.alpha = 0.5
28 |
29 | sim.set_m((1.0, 0, 0))
30 |
31 | sim.add(Zeeman((0, 0, 1e5)))
32 |
33 | ts = np.linspace(0, 1e-9, 1001)
34 |
35 | for t in ts:
36 | sim.run_until(t)
37 |
38 |
39 | def custom_legend(legend):
40 | frame = legend.get_frame()
41 | frame.set_facecolor('0.90')
42 |
43 | # Set the fontsize
44 | for label in legend.get_texts():
45 | label.set_fontsize(11)
46 |
47 | for label in legend.get_lines():
48 | label.set_linewidth(1.5) # the legend line width
49 |
50 |
51 | def plot_all():
52 |
53 | font = {'family': 'serif',
54 | 'weight': 'normal',
55 | 'size': 12,
56 | }
57 |
58 | plt.rc('font', **font)
59 |
60 | data = DataReader('relax.txt')
61 | ts = data['time']
62 |
63 | mx, my, mz = single_spin(0.5, 2.21e5, 1e5, ts)
64 |
65 | ts = ts * 1e9
66 | fig = plt.figure(figsize=(5, 4))
67 | plt.plot(ts, mx, '--', label='m_x', dashes=(2.0, 2.0))
68 | plt.plot(ts, my, '--', label='m_y', dashes=(2.0, 2.0))
69 | plt.plot(ts, mz, '--', label='m_z', dashes=(2.0, 2.0))
70 |
71 | ts = ts[::10]
72 | mx = data['m_x'][::10]
73 | my = data['m_y'][::10]
74 | mz = data['m_z'][::10]
75 | plt.plot(ts, mx, '.', color='b')
76 | plt.plot(ts, my, '.', color='g')
77 | plt.plot(ts[::2], mz[::2], '.', color='r')
78 | plt.xlim([0, 1.01])
79 |
80 | l1 = plt.legend(bbox_to_anchor=[0.8, 0.8], shadow=True, frameon=True)
81 | custom_legend(l1)
82 |
83 | plt.xlabel('Time (ns)')
84 | plt.ylabel('m')
85 | plt.tight_layout()
86 | fig.savefig('m_ts.pdf')
87 |
88 |
89 | if __name__ == '__main__':
90 |
91 | relax_system()
92 | plot_all()
93 |
--------------------------------------------------------------------------------
/tests/test_dw_dmi.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | from fidimag.common import CuboidMesh
4 | from fidimag.micro import Sim
5 | from fidimag.micro import UniformExchange
6 | from fidimag.micro import UniaxialAnisotropy
7 | from fidimag.micro import DMI
8 |
9 | import matplotlib.pyplot as plt
10 |
11 | mesh = CuboidMesh(dx=2, nx=150, x0=-150, unit_length=1e-9)
12 |
13 |
14 | def m_init_dw(pos):
15 |
16 | x = pos[0]
17 |
18 | if x < -10:
19 | return (1, 0, 0)
20 | elif x > 10:
21 | return (-1, 0, 0)
22 | else:
23 | return (0, 1, 0)
24 |
25 |
26 | def analytical(xs, A=1.3e-11, D=4e-4, K=8e4):
27 |
28 | delta = np.sqrt(A / (K - D * D / (4 * A))) * 1e9
29 |
30 | phi = D / (2 * A) * xs * 1e-9
31 |
32 | mx = - np.tanh(xs / delta)
33 | my = 1.0 / np.cosh(xs / delta) * np.cos(phi)
34 | mz = 1.0 / np.cosh(xs / delta) * np.sin(phi)
35 | return mx, my, mz
36 |
37 |
38 | def save_plot(mxyz, mx, my, mz):
39 | fig = plt.figure()
40 | mxyz.shape = (-1, 3)
41 | xs = np.array([p[0] for p in mesh.pos])
42 | plt.plot(xs, mxyz[:, 0], '.', label='mx')
43 | plt.plot(xs, mxyz[:, 1], '.', label='my')
44 | plt.plot(xs, mxyz[:, 2], '.', label='mz')
45 |
46 | plt.plot(xs, mx, '-')
47 | plt.plot(xs, my, '-')
48 | plt.plot(xs, mz, '-')
49 |
50 | plt.ylabel('mxyz')
51 | plt.xlabel('x (nm)')
52 | plt.legend(loc=1)
53 | plt.grid()
54 | plt.xlim([-150, 150])
55 | plt.ylim([-1.2, 1.2])
56 | fig.savefig('dw_dmi.pdf')
57 |
58 |
59 | def test_dw_dmi(mesh=mesh, do_plot=False):
60 |
61 | Ms = 8.0e5
62 | sim = Sim(mesh, name='relax')
63 |
64 | sim.set_m(m_init_dw)
65 |
66 | sim.driver.set_tols(rtol=1e-8, atol=1e-12)
67 | sim.Ms = Ms
68 | sim.alpha = 0.5
69 | sim.do_precession = False
70 |
71 | A = 1.3e-11
72 | D = 4e-4
73 | Kx = 8e4
74 | Kp = -6e5
75 |
76 | sim.add(UniformExchange(A))
77 | sim.add(DMI(D))
78 | sim.add(UniaxialAnisotropy(Kx, axis=[1, 0, 0], name='Kx'))
79 |
80 | sim.driver.relax(stopping_dmdt=0.01)
81 |
82 | xs = np.array([p[0] for p in mesh.coordinates])
83 | mx, my, mz = analytical(xs, A=A, D=D, K=Kx)
84 | mxyz = sim.spin.copy()
85 | mxyz = mxyz.reshape(-1, 3)
86 |
87 | assert max(abs(mxyz[:, 0] - mx)) < 0.002
88 | assert max(abs(mxyz[:, 1] - my)) < 0.002
89 | assert max(abs(mxyz[:, 2] - mz)) < 0.0006
90 |
91 | if do_plot:
92 |
93 | save_plot(mxyz, mx, my, mz)
94 |
95 | if __name__ == '__main__':
96 |
97 | test_dw_dmi(do_plot=True)
98 |
--------------------------------------------------------------------------------
/fidimag/atomistic/fmmlib/calculate.hpp:
--------------------------------------------------------------------------------
1 | //############################################
2 | //#
3 | //# Functions for running the Barnes-Hut
4 | //# method for gravitational source particles.
5 | //#
6 | //# (C) Ryan Pepper, 2018
7 | //# University of Southampton, UK
8 | //#
9 | //#
10 | //###########################################
11 | #pragma once
12 | #include "tree.hpp"
13 | #include "utils.hpp"
14 | #include
15 | #include
16 |
17 | void M_sanity_check(const std::vector &cells);
18 |
19 | void evaluate_P2M(std::vector &particles, std::vector &cells,
20 | size_t cell, size_t ncrit, size_t exporder);
21 |
22 | void evaluate_M2M(std::vector &particles, std::vector &cells,
23 | size_t exporder);
24 |
25 |
26 | void evaluate_L2L(std::vector &cells, size_t exporder);
27 |
28 | void evaluate_L2P(std::vector &particles, std::vector &cells,
29 | double *F, size_t ncrit, size_t exporder);
30 |
31 | void evaluate_direct(std::vector &particles, double *F, size_t Nparticles);
32 |
33 | void interact_dehnen(size_t A, size_t B, std::vector &cells, std::vector &particles, double theta, size_t order, size_t ncrit, double *F);
34 |
35 | void interact_dehnen_lazy(const size_t A, const size_t B, const std::vector &cells, const std::vector &particles,
36 | const double theta, const size_t order, const size_t ncrit,
37 | std::vector> &M2L_list,
38 | std::vector> &P2P_list);
39 |
40 | void P2P_Cells(size_t A, size_t B, std::vector &cells,
41 | std::vector &particles, double *F);
42 |
43 | void evaluate_P2P_lazy(std::vector &cells,
44 | std::vector> &P2P_list);
45 |
46 | void evaluate_M2L_lazy(std::vector &cells,
47 | std::vector> &M2L_list,
48 | std::vector &M2L_locks);
49 |
50 | void evaluate_M2L_lazy(std::vector &cells,
51 | std::vector> &M2L_list, size_t order);
52 |
53 | void evaluate_P2P_lazy(std::vector &cells, std::vector &particles,
54 | std::vector> &P2P_list, double *F);
55 |
56 | void evaluate_M2P_and_P2P(std::vector &particles, unsigned int p, unsigned int i,
57 | std::vector| &cells, double *F, unsigned int n_crit, double theta,
58 | unsigned int exporder);
59 |
--------------------------------------------------------------------------------
/tests/test_hubert_minimiser.py:
--------------------------------------------------------------------------------
1 | import fidimag
2 | import fidimag.common.constant as C
3 | import numpy as np
4 |
5 |
6 | def test_hubert_minimiser_1D_DW():
7 |
8 | nx, ny, nz = 100, 1, 1
9 | dx, dy, dz = 1, 1, 1
10 |
11 | mesh = fidimag.common.CuboidMesh(nx=nx, ny=ny, nz=nz, dx=dx, dy=dy, dz=dz,
12 | periodicity=(False, False, False),
13 | unit_length=1e-9)
14 |
15 | sim = fidimag.micro.Sim(mesh, name='1Dmicro', driver='hubert_minimiser')
16 |
17 | Ms = 0.86e6
18 | A = 13e-12
19 | Ku = 0.4e6
20 |
21 | # Define the magnetisation
22 | sim.set_Ms(Ms)
23 |
24 | # Add the magnetic interactions
25 | sim.add(fidimag.micro.UniformExchange(A))
26 | sim.add(fidimag.micro.UniaxialAnisotropy(Ku, axis=(0, 0, 1)))
27 | # sim.add(fidimag.atomistic.DMI(D, dmi_type='interfacial'))
28 | # sim.add(fidimag.micro.Zeeman((0, 0, B)))
29 |
30 | xs = mesh.coordinates[:, 0]
31 | centre_x = (xs.max() + xs.min()) * 0.5 + xs.min()
32 |
33 | def m_initial(r):
34 | x, y, z = r[0], r[1], r[2]
35 | if x < centre_x:
36 | return (0, 0.1, -.9)
37 | else:
38 | return (0, 0.1, .9)
39 | sim.set_m(m_initial)
40 |
41 | mesh_vol = mesh.n * mesh.dx * mesh.dy * mesh.dz * 1e-27
42 | Kd = C.mu_0 * (Ms ** 2) * 0.5 * mesh_vol
43 | # Scale the energy for the minimiser
44 | sim.driver.energyScale = Kd
45 |
46 | sim.driver.minimise(stopping_dE=1e-6, maxCreep=6,
47 | eta_scale=1e-6, log_steps=10)
48 | mz = sim.spin.reshape(-1, 3)[:, 2]
49 |
50 | # ANALYSIS
51 |
52 | def mz_dw_analyt(x, xc):
53 | """Analytical DW function using DW width param"""
54 | # DW width from theory
55 | deltaB = np.sqrt(A / Ku)
56 | return np.tanh((x - xc) / deltaB)
57 |
58 | # Analytical model in nm units
59 | x = sim.mesh.coordinates[:, 0]
60 | y = mz_dw_analyt(x * 1e-9, 50 * 1e-9)
61 |
62 | # Mean absolute error at points within the DW width:
63 | # The maximum "deviation" a spin might have from the curve is 2, since
64 | # the spin-z is in the [-1, 1] range
65 | deltaB = np.sqrt(A / Ku) * 1e9
66 | xc = 50 # sample centre
67 | ftr = np.logical_and(x <= xc + deltaB, x >= xc - deltaB)
68 |
69 | MAE_dw = np.mean(np.abs(y[ftr] - mz[ftr]))
70 | print('Domain wall MAE', MAE_dw)
71 | # This is at least 1% the max deviation
72 | assert MAE_dw < 0.02
73 |
74 |
75 | if __name__ == "__main__":
76 | test_hubert_minimiser_1D_DW()
77 |
--------------------------------------------------------------------------------
/tests/test_micromagnetic_zeeman.py:
--------------------------------------------------------------------------------
1 | from fidimag.micro import Zeeman
2 | from fidimag.common import CuboidMesh
3 | from fidimag.micro import Sim
4 | import numpy as np
5 |
6 |
7 | def varying_field(pos):
8 | return (1.2 * pos[0], 2.3 * pos[1], 0)
9 |
10 |
11 | def test_H0_is_indexable_or_callable():
12 | """
13 | Test that an exception is raised if H0 is not indexable, and that an
14 | exception is not raised if H0 is indexable.
15 | """
16 | # Test for some different accepted types.
17 | inputSuccess = ([0., 0., 1.],
18 | np.array([0., 0., 1.]),
19 | lambda x: x + 0.1)
20 | for zS in inputSuccess:
21 | Zeeman(zS)
22 |
23 | # Test for different failing types. Should perhaps use a unittest.TestCase
24 | # for testing to make this more elegant, but there's probably a reason why
25 | # it's not used elsewhere.
26 | inputFailures = [5., -7]
27 | for zS in inputFailures:
28 | try:
29 | Zeeman(zS)
30 | except ValueError:
31 | pass
32 | else:
33 | raise Exception("Zeeman argument \"{}\" was expected to raise an "
34 | "exception, but did not!."
35 | .format(zS))
36 |
37 | def test_zeeman():
38 |
39 | mesh = CuboidMesh(nx=5, ny=2, nz=1)
40 |
41 | sim = Sim(mesh)
42 | sim.set_m((1, 0, 0))
43 |
44 | zeeman = Zeeman(varying_field)
45 | sim.add(zeeman)
46 |
47 | field = zeeman.compute_field()
48 |
49 | assert field[6] == 1.2 * (2 + 0.5)
50 | assert field[7] == 2.3 * 0.5
51 |
52 |
53 | def test_zeeman_energy():
54 |
55 | mu0 = 4 * np.pi * 1e-7
56 | # A system of 8 cells ( not using nm units)
57 | mesh = CuboidMesh(dx=2, dy=2, dz=2,
58 | nx=2, ny=2, nz=2
59 | )
60 |
61 | sim = Sim(mesh)
62 | Ms = 1e5
63 | sim.set_Ms(Ms)
64 |
65 | sim.set_m((0, 0, 1))
66 |
67 | H = 0.1 / mu0
68 | zeeman = Zeeman((0, 0, H))
69 | sim.add(zeeman)
70 |
71 | field = zeeman.compute_field()
72 | zf = sim.get_interaction('Zeeman')
73 |
74 | # -> ->
75 | # Expected energy: Int ( -mu0 M * H ) dV
76 | # Since we have 8 cells with the same M, we just sum their contrib
77 | exp_energy = 8 * (-mu0 * H * Ms * mesh.dx * mesh.dy * mesh.dz)
78 |
79 | assert np.abs(zf.compute_energy() - exp_energy) < 1e-10
80 |
81 |
82 | if __name__ == "__main__":
83 | test_zeeman()
84 | test_H0_is_indexable_or_callable()
85 | test_zeeman_energy()
86 |
--------------------------------------------------------------------------------
| | | | | | | | | | | | | | | | | | | | |