From 1fdf20386073f667097866d677c2518644045bf3 Mon Sep 17 00:00:00 2001 From: Marijan Beg Date: Mon, 12 Mar 2018 14:37:17 +0100 Subject: [PATCH] Initial commit. --- .travis.yml | 10 + Dockerfile | 25 +++ LICENSE | 11 + Makefile | 14 ++ README.md | 59 ++++++ examples/isolated_sk_DMI_D2d.mif | 105 ++++++++++ examples/sk_lattice_DMI_D2d_PBCs.mif | 115 +++++++++++ src/DMI_D2d.cc | 297 +++++++++++++++++++++++++++ src/DMI_D2d.h | 61 ++++++ 9 files changed, 697 insertions(+) create mode 100644 .travis.yml create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 examples/isolated_sk_DMI_D2d.mif create mode 100644 examples/sk_lattice_DMI_D2d_PBCs.mif create mode 100644 src/DMI_D2d.cc create mode 100644 src/DMI_D2d.h diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0877f19 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +sudo: required + +services: + - docker + +script: + - make travis-build + +notifications: + slack: joommf:eqKxGPXuUP3LxnOfxg7GWgDF diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bf7ec09 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +FROM ubuntu:16.04 + +RUN apt-get -y update +RUN apt-get install -y git tk-dev tcl-dev + +# Clone OOMMF repository. +WORKDIR /usr/local +RUN git clone http://github.com/fangohr/oommf.git + +# Copy OOMMF extension repository. +COPY . /usr/local/oommf-extension-dmi-d2d/ +WORKDIR /usr/local/oommf-extension-dmi-d2d/ + +# Copy OOMMF extension to OOMMF directory. +RUN cp src/* /usr/local/oommf/oommf/app/oxs/local/ + +# Compile OOMMF. +WORKDIR /usr/local/oommf +RUN make + +# Create OOMMFTCL environment variable +ENV OOMMFTCL /usr/local/oommf/oommf/oommf.tcl + +# Change working directory. +WORKDIR /usr/local/oommf-extension-dmi-d2d \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..22ee297 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +Copyright <2018> David Cortés-Ortuño, Marijan Beg, Vanessa Nehruji, Ryan A. Pepper, and Hans Fangohr, European XFEL GmbH and University of Southampton + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7d351c9 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +test-all: + ls -lh examples + tclsh $(OOMMFTCL) boxsi +fg examples/isolated_sk_DMI_D2d.mif -exitondone 1 + ls -lh examples + tclsh $(OOMMFTCL) boxsi +fg examples/sk_lattice_DMI_D2d_PBCs.mif -exitondone 1 + ls -lh examples + +travis-build: SHELL:=/bin/bash +travis-build: + docker build --no-cache -t dockertestimage . + docker run -ti -d --name testcontainer dockertestimage + docker exec testcontainer make test-all + docker stop testcontainer + docker rm testcontainer diff --git a/README.md b/README.md new file mode 100644 index 0000000..637c3b0 --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +[![Build Status](https://travis-ci.org/joommf/oommf-extension-dmi-d2d.svg?branch=master)](https://travis-ci.org/joommf/oommf-extension-dmi-d2d) +[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) + +# [OOMMF](https://math.nist.gov/oommf/) extension: Dzyaloshinskii-Moriya interaction (DMI) for the crystallographic class D2d + +David Cortés-Ortuño1, Marijan Beg1,2, Vanessa Nehruji3, Ryan A. Pepper1, and Hans Fangohr1,2 + +1 Faculty of Engineering and the Environment, University of Southampton, Southampton SO17 1BJ, United Kingdom +2 European XFEL GmbH, Holzkoppel 4, 22869 Schenefeld, Germany +3 Department of Physics, University of Durham, Durham DH1 3LE, United Kingdom + +## Introduction + +Different Dzyaloshinskii-Moriya interaction forms can be written as different combinations of Lifshitz invariants depending on the crystallographic class of the magnetic material [1]. + +## Energy density + +The DMI energy density for the crystallographic class D2d as a sum of Lifshitz invariants [1] is + + + +where is the DMI constant and is the normalised magnetisation field. + +## Periodic boundary conditions + +This OOMMF extension works both with and without periodic boundary conditions (PBC). Therefore, it is possible to use the same class in either kind of mesh (`Oxs_RectangularMesh` or `Oxs_PeriodicRectangularMesh`). + +## Installation + +To install this extension: +1. Copy `DMI_D2d.cc` and `DMI_D2d.h` files from the `src` directory in this repository into the `app/oxs/local` directory in the OOMMF main directory. +2. Recompile OOMMF, usually by running +``` +tclsh oommf.tcl pimake distclean && tclsh oommf.tcl pimake upgrade && tclsh oommf.tcl pimake +``` + +## Examples + +Examples are provided in `.mif` files for the stabilisation of an isolated skyrmion in a confined cuboid (no periodic boundary conditions) and for the stabilisation of a skyrmion lattice in a unit cell of an infinite system (with periodic boundary conditions). + +## Support + +If you require support on installation or usage of this OOMMF extension as well as if you want to report a problem, you are welcome to raise an issue in our [joommf/help](https://github.com/joommf/help) repository. + +## How to cite + +If you use this OOMMF extension in your research, please cite it as: + +## License + +This extension is licensed under the BSD 3-Clause "New" or "Revised" License. For details, please refer to the [LICENSE](LICENSE) file. + +## Acknowledgements + +This extension was developed as a part of [OpenDreamKit](http://opendreamkit.org/) – Horizon 2020 European Research Infrastructure project (676541) and the [EPSRC Programme grant on Skyrmionics (EP/N032128/1)](https://www.skyrmions.ac.uk/). + +## References + +[1] A. Bogdanov and D. Yablonskii. Thermodynamically stable "vortices" in magnetically ordered crystals. The mixed state of magnets. [Zh. Eksp. Teor. Fiz 95, 178 (1989)](http://www.jetp.ac.ru/cgi-bin/e/index/e/68/1/p101?a=list). \ No newline at end of file diff --git a/examples/isolated_sk_DMI_D2d.mif b/examples/isolated_sk_DMI_D2d.mif new file mode 100644 index 0000000..265da0a --- /dev/null +++ b/examples/isolated_sk_DMI_D2d.mif @@ -0,0 +1,105 @@ +# MIF 2.1 --------------------------------------------------------------------- + +# Generate an isolated skyrmion with interfacial (C_nv) DMI +# +# Authors: D. Cortes, M. Beg, H.Fangohr (2018) + +set PI [expr {4 * atan(1.)}] +set MU0 [expr {4 * $PI * 1e-7}] + +# ----------------------------------------------------------------------------- +# PdFe on Ir(111) [PRL, 114(17):1-5, 2015] +# This is an interfacial system but the parameters should work similarly for +# the D2d symmetry. Spins only change the sense of rotation +set Ms [expr {1.1e6}] +set A [expr {2e-12}] +set D [expr {3.9e-3}] +set KU [expr {2.5e6}] +set BZ [expr {1.0}] + +set XL [expr {15e-9}] +set YL [expr {$XL}] +set ZL [expr {2e-9}] + +set xcell [expr {$XL / 20}] +set ycell [expr {$YL / 20}] +set zcell [expr {2e-9}] + +# ----------------------------------------------------------------------------- + +# BoxAtlas +Specify Oxs_BoxAtlas:atlas [subst { + xrange {0 $XL} + yrange {0 $YL} + zrange {0 $ZL} + name atlas +}] + +# RectangularMesh +Specify Oxs_RectangularMesh:mesh [subst { + cellsize {$xcell $ycell $zcell} + atlas Oxs_BoxAtlas:atlas +}] + +# UniformExchange +Specify Oxs_UniformExchange [subst { + A $A +}] + +# Uniaxial Anisotropy +Specify Oxs_UniaxialAnisotropy:Anisotropy [subst { + axis { 0 0 1 } + K1 $KU +}] + +# D_2d DMI +Specify Oxs_DMI_D2d [subst { + default_D $D + atlas :atlas + D { + atlas atlas $D + } +}] + +Specify Oxs_FixedZeeman:Bfield [subst { + comment {Field values in Tesla; scale to A/m} + multiplier [expr {1 / $MU0}] + field {0.0 0.0 $BZ} +}] + +# CGEvolver +Specify Oxs_CGEvolve {} + +# MinDriver +Specify Oxs_MinDriver [subst { + evolver Oxs_CGEvolve + stopping_mxHxm 0.01 + mesh :mesh + Ms $Ms + m0 { Oxs_ScriptVectorField { + atlas :atlas + script { dot } + norm 1.0 + script_args { relpt } + }} + + basename isolated_sk_D2d + scalar_field_output_format {text %\#.15g} + vector_field_output_format {text %\#.15g} +}] + +Destination table mmArchive +Destination mags mmArchive + +Schedule DataTable table Stage 1 +Schedule Oxs_MinDriver::Magnetization mags Stage 1 + +# ============================================================================= + +proc dot { x y z } { + set xnorm [expr {(2 * $x - 1)}] + set ynorm [expr {(2 * $y - 1)}] + set radius [expr {sqrt($xnorm * $xnorm + $ynorm * $ynorm)}] + if {$radius < 0.2} { return [list 0 0 -1] } + return [list 0 0 1] +} diff --git a/examples/sk_lattice_DMI_D2d_PBCs.mif b/examples/sk_lattice_DMI_D2d_PBCs.mif new file mode 100644 index 0000000..f67fa06 --- /dev/null +++ b/examples/sk_lattice_DMI_D2d_PBCs.mif @@ -0,0 +1,115 @@ +# MIF 2.1 --------------------------------------------------------------------- + +# Generate a skyrmion lattice in a "unit cell" with Periodic Boundaries +# +# Authors: D. Cortes, M. Beg, H.Fangohr (2018) + +set PI [expr {4 * atan(1.)}] +set MU0 [expr {4 * $PI * 1e-7}] + +# ----------------------------------------------------------------------------- +# PdFe on Ir(111) [PRL, 114(17):1-5, 2015] +# This is an interfacial system but parameters should work similarly for D2d +# symmetry. Spins only change the sense of rotation for the skyrmion +set Ms [expr {1.1e6}] +set A [expr {2e-12}] +set D [expr {3.9e-3}] +set KU [expr {2.5e6}] +set BZ [expr {1.0}] + +set XL [expr {15e-9}] +set YL [expr {$XL / sqrt(3)}] +set ZL [expr {2e-9}] + +set xcell [expr {$XL / 64}] +set ycell [expr {$YL / 32}] +set zcell [expr {2e-9}] + +# ----------------------------------------------------------------------------- + +# BoxAtlas +Specify Oxs_BoxAtlas:atlas [subst { + xrange {0 $XL} + yrange {0 $YL} + zrange {0 $ZL} + name atlas +}] + +# RectangularMesh +Specify Oxs_PeriodicRectangularMesh:mesh [subst { + cellsize {$xcell $ycell $zcell} + atlas Oxs_BoxAtlas:atlas + periodic "xy" +}] + +# UniformExchange +Specify Oxs_UniformExchange [subst { + A $A +}] + +# Uniaxial Anisotropy +Specify Oxs_UniaxialAnisotropy:Anisotropy [subst { + axis { 0 0 1 } + K1 $KU +}] + +# D_2d DMI +Specify Oxs_DMI_D2d [subst { + default_D $D + atlas :atlas + D { + atlas atlas $D + } +}] + +Specify Oxs_FixedZeeman:Bfield [subst { + comment {Field values in Tesla; scale to A/m} + multiplier [expr {1 / $MU0}] + field {0.0 0.0 $BZ} +}] + +# CGEvolver +Specify Oxs_CGEvolve {} + +# MinDriver +Specify Oxs_MinDriver [subst { + evolver Oxs_CGEvolve + stopping_mxHxm 0.01 + mesh :mesh + Ms $Ms + m0 { Oxs_ScriptVectorField { + atlas :atlas + script { skX } + norm 1.0 + script_args { relpt } + }} + + basename skL_D2d_PBCs + scalar_field_output_format {text %\#.15g} + vector_field_output_format {text %\#.15g} +}] + +Destination table mmArchive +Destination mags mmArchive + +Schedule DataTable table Stage 1 +Schedule Oxs_MinDriver::Magnetization mags Stage 1 + +# ============================================================================= + +proc skX { x y z } { + set xnorm [expr {(2 * $x - 1)}] + set ynorm [expr {(2 * $y - 1)}] + + foreach xsk [list -1.0 1.0 -1.0 1.0 0.0] ysk [list -1.0 -1.0 1.0 1.0 0.0] { + + set xrel [expr {$xnorm - $xsk}] + set yrel [expr {$ynorm - $ysk}] + set radius [expr {sqrt($xrel * $xrel + $yrel * $yrel)}] + + if {$radius < 0.3} { return [list 0 0 -1] } + + } + + return [list 0 0 1] +} diff --git a/src/DMI_D2d.cc b/src/DMI_D2d.cc new file mode 100644 index 0000000..1829986 --- /dev/null +++ b/src/DMI_D2d.cc @@ -0,0 +1,297 @@ +/* FILE: DMI_D2d.cc -*-Mode: c++-*- + * + * Dzyaloshinskii-Moriya energy for the D2d crystallographic class [1]: + * + * $w_\text{dmi} = D ( L_{xz}^{(y)} + L_{yz}^{(x)} ) + * + * This extension works both with and without periodic boundary conditions. + * + * Written by David Cortes-Ortuno, Marijan Beg and Hans Fangohr (University of Southampton and European XFEL GmbH). + * + * Developed as a part of OpenDreamKit Horizon 2020 European Research Infrastructure + * project (676541), and the EPSRC Programme grant on Skyrmionics (EP/N032128/1). + * + * [1] A. N. Bogdanov and D. A. Yablonskii. Zh. Eksp. Teor. Fiz. 95, 178-182 (1989). + * + */ + +#include + +#include "atlas.h" +#include "nb.h" +#include "key.h" +#include "director.h" +#include "mesh.h" +#include "meshvalue.h" +#include "simstate.h" +#include "threevector.h" +#include "rectangularmesh.h" +#include "DMI_D2d.h" +#include "energy.h" // Needed to make MSVC++ 5 happy + +OC_USE_STRING; + +// Oxs_Ext registration support +OXS_EXT_REGISTER(Oxs_DMI_D2d); + +/* End includes */ + + +// Constructor +Oxs_DMI_D2d::Oxs_DMI_D2d( + const char* name, // Child instance id + Oxs_Director* newdtr, // App director + const char* argstr) // MIF input block parameters + : Oxs_Energy(name,newdtr,argstr), + A_size(0), D(NULL), + xperiodic(0),yperiodic(0),zperiodic(0), + mesh_id(0) +{ + // Process arguments + OXS_GET_INIT_EXT_OBJECT("atlas",Oxs_Atlas,atlas); + atlaskey.Set(atlas.GetPtr()); + /// Dependency lock is held until *this is deleted. + + // Check for optional default_D parameter; default is 0. + OC_REAL8m default_D = GetRealInitValue("default_D",0.0); + + // Allocate A matrix. Because raw pointers are used, a memory + // leak will occur if an exception is thrown inside this constructor. + A_size = atlas->GetRegionCount(); + if(A_size<1) { + String msg = String("Oxs_Atlas object ") + + atlas->InstanceName() + + String(" must contain at least one region."); + + throw Oxs_Ext::Error(msg.c_str()); + } + D = new OC_REAL8m*[A_size]; + D[0] = new OC_REAL8m[A_size*A_size]; + OC_INDEX i; + for(i=1;i params; + FindRequiredInitValue("D",params); + if(params.empty()) { + throw Oxs_Ext::Error(this,"Empty parameter list for key \"D\""); + } + if(params.size()%3!=0) { + char buf[512]; + Oc_Snprintf(buf,sizeof(buf), + "Number of elements in D sub-list must be" + " divisible by 3" + " (actual sub-list size: %u)", + (unsigned int)params.size()); + throw Oxs_Ext::Error(this,buf); + } + for(i=0;iGetRegionId(params[i]); + OC_INT4m i2 = atlas->GetRegionId(params[i+1]); + if(i1<0 || i2<0) { + char buf[4096]; + char* cptr=buf; + if(i1<0) { + Oc_Snprintf(buf,sizeof(buf), + "First entry in D[%u] sub-list, \"%s\"," + " is not a known region in atlas \"%s\". ", + i/3,params[i].c_str(),atlas->InstanceName()); + cptr += strlen(buf); + } + if(i2<0) { + Oc_Snprintf(cptr,sizeof(buf)-(cptr-buf), + "Second entry in D[%u] sub-list, \"%s\"," + " is not a known region in atlas \"%s\". ", + i/3,params[i+1].c_str(),atlas->InstanceName()); + } + String msg = String(buf); + msg += String("Known regions:"); + vector regions; + atlas->GetRegionList(regions); + for(unsigned int j=0;j0 && D!=NULL) { + delete[] D[0]; + delete[] D; + } +} + +OC_BOOL Oxs_DMI_D2d::Init() +{ + mesh_id = 0; + region_id.Release(); + return Oxs_Energy::Init(); +} + +void Oxs_DMI_D2d::GetEnergy +(const Oxs_SimState& state, + Oxs_EnergyData& oed + ) const +{ + // See if mesh and/or atlas has changed. + if(mesh_id != state.mesh->Id() || !atlaskey.SameState()) { + // Setup region mapping + mesh_id = 0; // Safety + OC_INDEX size = state.mesh->Size(); + region_id.AdjustSize(state.mesh); + ThreeVector location; + for(OC_INDEX i=0;iCenter(i,location); + if((region_id[i] = atlas->GetRegionId(location))<0) { + String msg = String("Import mesh to Oxs_DMI_D2d::GetEnergy()" + " routine of object ") + + String(InstanceName()) + + String(" has points outside atlas ") + + String(atlas->InstanceName()); + throw Oxs_Ext::Error(msg.c_str()); + } + } + mesh_id = state.mesh->Id(); + } + const Oxs_MeshValue& spin = state.spin; + const Oxs_MeshValue& Ms_inverse = *(state.Ms_inverse); + + // Use supplied buffer space, and reflect that use in oed. + oed.energy = oed.energy_buffer; + oed.field = oed.field_buffer; + Oxs_MeshValue& energy = *oed.energy_buffer; + Oxs_MeshValue& field = *oed.field_buffer; + + // Check periodicity -------------------------------------------------------- + const Oxs_CommonRectangularMesh* mesh + = dynamic_cast(state.mesh); + if(mesh==NULL) { + String msg=String("Object ") + + String(state.mesh->InstanceName()) + + String(" is not a rectangular mesh."); + throw Oxs_ExtError(this,msg); + } + + const Oxs_RectangularMesh* rmesh + = dynamic_cast(mesh); + const Oxs_PeriodicRectangularMesh* pmesh + = dynamic_cast(mesh); + if(pmesh!=NULL) { + // Rectangular, periodic mesh + xperiodic = pmesh->IsPeriodicX(); + yperiodic = pmesh->IsPeriodicY(); + zperiodic = pmesh->IsPeriodicZ(); + } else if (rmesh!=NULL) { + xperiodic=0; yperiodic=0; zperiodic=0; + } else { + String msg=String("Unknown mesh type: \"") + + String(ClassName()) + + String("\"."); + throw Oxs_ExtError(this,msg.c_str()); + } + // -------------------------------------------------------------------------- + + OC_INDEX xdim = mesh->DimX(); + OC_INDEX ydim = mesh->DimY(); + OC_INDEX zdim = mesh->DimZ(); + OC_INDEX xydim = xdim*ydim; + + OC_REAL8m wgtx = 1.0/(mesh->EdgeLengthX()); + OC_REAL8m wgty = 1.0/(mesh->EdgeLengthY()); + //OC_REAL8m wgtz = -1.0/(mesh->EdgeLengthZ()*mesh->EdgeLengthZ()); + + OC_REAL8m hcoef = -2/MU0; + + for(OC_INDEX z=0;zIndex(x,y,z); // Get base linear address + ThreeVector base = spin[i]; + OC_REAL8m Msii = Ms_inverse[i]; + if(Msii == 0.0) { + energy[i]=0.0; + field[i].Set(0.,0.,0.); + continue; + } + OC_REAL8m* Drow = D[region_id[i]]; + ThreeVector sum(0.,0.,0.); + OC_INDEX j; + + if(y > 0 || yperiodic) { // y- direction + if(y > 0) { + j = i - xdim; + } else if (yperiodic) { + j = i - xdim + xydim; + } + if(Ms_inverse[j] != 0.0) { + OC_REAL8m Dpair = Drow[region_id[j]]; + ThreeVector Dij(0.,-1.,0); + sum += 0.5 * Dpair * wgty * (Dij ^ spin[j]); + } + } + + if(x > 0 || xperiodic) { // x- direction + if(x > 0) { + j = i - 1; + } else if (xperiodic) { + j = i - 1 + xdim; + } + if(Ms_inverse[j] != 0.0) { + OC_REAL8m Dpair = Drow[region_id[j]]; + ThreeVector Dij(1.,0.,0); + sum += 0.5 * Dpair * wgtx * (Dij ^ spin[j]); + } + } + + if(y < ydim - 1 || yperiodic) { // y+ direction + if (y < ydim-1) { + j = i + xdim; + } else if (yperiodic) { + j = i + xdim - xydim; + } + if(Ms_inverse[j] != 0.0) { + OC_REAL8m Dpair = Drow[region_id[j]]; + ThreeVector Dij(0.,1.,0); + sum += 0.5 * Dpair * wgty * (Dij ^ spin[j]); + } + } + + if(x < xdim-1 || xperiodic) { // x+ direction + if (x < xdim-1) { + j = i + 1; + } else if (xperiodic) { + j = i + 1 - xdim; + } + if (Ms_inverse[j] != 0.0) { + OC_REAL8m Dpair = Drow[region_id[j]]; + ThreeVector Dij(-1.,0.,0); + sum += 0.5 * Dpair * wgtx * (Dij ^ spin[j]); + } + } + + field[i] = (hcoef * Msii) * sum; + energy[i] = (sum * base); + } + } + } +} diff --git a/src/DMI_D2d.h b/src/DMI_D2d.h new file mode 100644 index 0000000..03e671d --- /dev/null +++ b/src/DMI_D2d.h @@ -0,0 +1,61 @@ +/* FILE: DMI_D2d.cc -*-Mode: c++-*- + * + * Dzyaloshinskii-Moriya energy for the D2d crystallographic class [1]: + * + * $w_\text{dmi} = D ( L_{xz}^{(y)} + L_{yz}^{(x)} ) + * + * This extension works both with and without periodic boundary conditions. + * + * Written by David Cortes-Ortuno, Marijan Beg and Hans Fangohr (University of Southampton and European XFEL GmbH). + * + * Developed as a part of OpenDreamKit Horizon 2020 European Research Infrastructure + * project (676541), and the EPSRC Programme grant on Skyrmionics (EP/N032128/1). + * + * [1] A. N. Bogdanov and D. A. Yablonskii. Zh. Eksp. Teor. Fiz. 95, 178-182 (1989). + * + */ + +#ifndef _OXS_DMI_D2D +#define _OXS_DMI_D2D + +#include "atlas.h" +#include "key.h" +#include "energy.h" +#include "mesh.h" +#include "meshvalue.h" +#include "simstate.h" +#include "threevector.h" +#include "rectangularmesh.h" + +/* End includes */ + +class Oxs_DMI_D2d:public Oxs_Energy { +private: + OC_INT4m A_size; + OC_REAL8m** D; + Oxs_Key atlaskey; + Oxs_OwnedPointer atlas; + mutable OC_INT4m mesh_id; + mutable Oxs_MeshValue region_id; + + // Periodic boundaries? + mutable int xperiodic; + mutable int yperiodic; + mutable int zperiodic; + +protected: + virtual void GetEnergy(const Oxs_SimState& state, + Oxs_EnergyData& oed) const; + +public: + virtual const char* ClassName() const; // ClassName() is + /// automatically generated by the OXS_EXT_REGISTER macro. + Oxs_DMI_D2d(const char* name, // Child instance id + Oxs_Director* newdtr, // App director + const char* argstr); // MIF input block parameters + virtual ~Oxs_DMI_D2d(); + virtual OC_BOOL Init(); +}; + + +#endif // _OXS_DMI_D2D