# MIF 2.1
# MIF Example File: h2h.mif
# Description: Head-to-head domain wall in an infinite strip.
#
# This example requires the pre-computation of an appropriate edge
# field OVF file.  The steps to build the edge field file are:
#  
#  A) Run
#         tclsh ../../../oommf.tcl boxsi h2h_edgefield.mif \
#            -parameters "cellsize 5e-9"
#     where "5e-9" should be replaced with the desired cellsize.
#     This will create the output file
#         h2h_edgefield-Oxs_Demag-Field-00-0000000.ohf
#
#  B) Truncate the demag output file create in the previous step
#     to the simulation dimensions in this file:
#
#         tclsh ../../../oommf.tcl avf2ovf -format b8 -grid reg \
#            -clip 0 0 0 1600e-9 - - \
#            h2h_edgefield-Oxs_Demag-Field-00-0000000.ohf \
#            h2h_leftedge_80x8.ohf
#
#     The "80x8" in the last line must be adjust to match the number
#     cells across the y and z dimensions in this simulation,
#     respectively.  For width = 400e-9 and thickness = 40e-9 with
#     cellsize = 5e-9, we get 400e-9/5e-9 = 80 and 40e-9/5e-9 = 8.
#
#  C) Delete the file h2h_edgefield-Oxs_Demag-Field-00-0000000.ohf
#

set pi [expr {4*atan(1.0)}]
set mu0 [expr {4*$pi*1e-7}]
RandomSeed 10

# Strip geometry.
# NB: The cross dimensions must match the edge field (see below).
set thickness       40e-9
set width          400e-9
Parameter length  1600e-9

# Simulation cellsize
Parameter cellsize        10e-9

# Saturation magnetization
Parameter Ms 8e5         ;# In A/m

# Main atlas
Specify Oxs_BoxAtlas:atlas [subst {
   xrange {0 $length}
   yrange {0 $width}
   zrange {0 $thickness}
}]

# Supplemental atlas, used to specify fixed spins
Specify Oxs_MultiAtlas:Edges [subst {
   atlas {Oxs_BoxAtlas:left_edge {
      xrange {0 $cellsize}
      yrange {0 $width}
      zrange {0 $thickness}
   }}
   atlas {Oxs_BoxAtlas:right_edge {
      xrange {[expr {$length-$cellsize}] $length}
      yrange {0 $width}
      zrange {0 $thickness}
   }}
}]

Specify Oxs_RectangularMesh:mesh [subst {
  cellsize {$cellsize $cellsize $cellsize}
  atlas :atlas
}]

# Exchange
Specify Oxs_UniformExchange {
  A   1.3e-11
}

# Demag
Parameter asymptotic_radius 32  ;# Units are (max) cell width
Specify Oxs_Demag [subst {
  asymptotic_radius $asymptotic_radius
}]

# Field to offset edge demag.  This field is pre-computed using the
# h2h_edgefield.mif problem description, and stored in an *.ohf file.
set widthcells [expr {int(round($width/$cellsize))}]
set thickcells [expr {int(round($thickness/$cellsize))}]
Specify Oxs_FileVectorField:leftedge [subst {
   file h2h_leftedge_${widthcells}x${thickcells}.ohf
   spatial_scaling {1 1 1}
   spatial_offset  {0 0 0}
}]

# Field from the left edge
Specify Oxs_FixedZeeman:leftadj { 
   field :leftedge
   multiplier -1
}

# Field from the right edge.  This is the same as the left edge field,
# but rotated about the origin via the 'M -1' entry (the *.ohf fields
# are located in the first octant), and translated into position with
# the offset entry.
Specify Oxs_FixedZeeman:rightadj [subst { 
   field { Oxs_AffineOrientVectorField {
      field :leftedge
      M -1
      offset { $length $width $thickness }
   }}
}]


#####################################################################
### Evolver and driver for energy minimization
# Evolver
Specify Oxs_CGEvolve:evolve {
   fixed_spins {
      :Edges left_edge right_edge
   }
}

proc HeadToHead { x y z } {
   # (x,y,z) are relative components, each in range [0,1]
   set centerpt 0.5
   set edgerange 0.05
   if {$x<$edgerange}   { return [list  1. 0. 0.] }
   if {1-$edgerange<$x} { return [list -1. 0. 0.] }
   set mx [expr {-1*tanh(12.0*($x-$centerpt)/double($centerpt))}]
   set my [expr {sqrt(1.0-$mx*$mx)}]
   set mz 0.01 ;# Just to break xy-plane symmetry
   return [list $mx $my $mz]
}

# Driver
Specify Oxs_MinDriver [subst {
   evolver :evolve
   mesh :mesh
   Ms $Ms
   m0 { Oxs_ScriptVectorField {
      script HeadToHead
      atlas :atlas
      norm 1.0
   } }
   stopping_mxHxm 0.001
   basename h2h
}]

# Output
Destination archive mmArchive
Schedule Oxs_MinDriver::Spin archive stage 1
