# MIF 2.1
# MIF Example File: manyregions-scriptfields.mif
# Description: Example with multiple magnetically active segments,
#    defined using Oxs_ScriptScalarField and Oxs_ScriptVectorField
#    objects and a single Oxs_BoxAtlas, instead of an Oxs_MultiAtlas (as
#    in manyregions-multatlas.mif, q.v.) or an Oxs_ScriptAtlas (as in
#    manyregions-scriptatlas.mif, q.v.).


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

RandomSeed 1

Parameter cellsize 5e-9
Parameter region_width   60e-9
Parameter region_period  70e-9
Parameter region_count   20

set xmax [expr {($region_count-1)*$region_period + $region_width}]
set ymax 60e-9
set zmax 10e-9

Specify Oxs_BoxAtlas:atlas [subst {
  xrange {0 $xmax}
  yrange {0 $ymax}
  zrange {0 $zmax}
}]

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

# Define an Oxs_ScriptVectorField object to define anisotropy directions.
proc anisaxis_proc { x y z } {
   global region_width region_period region_count pi
   set index [expr {int(floor($x/$region_period))}]
   set offset [expr {$x - $index*$region_period}]
   if {$offset>$region_width} {
      # Point is in space between magnetic bits;
      # Return {1 0 0} as dummy value.
      return {1 0 0}
   }
   set theta [expr {$pi*$index/$region_count}]
   set result [list 0 [expr {cos($theta)}] [expr {sin($theta)}]]
   return $result
}
Specify Oxs_ScriptVectorField:anisotropy_directions [subst {
   atlas :atlas
   norm 1.0
   script_args rawpt
   script anisaxis_proc
}]
Specify Oxs_UniaxialAnisotropy {
  K1  1.5e3
  axis :anisotropy_directions
}

# Exchange is automatically 0 at locations where Ms=0.
# Oxs_UniformExchange does not allow more general variation of A.  If
# more control is needed, use Oxs_Exchange6Ngbr.
Specify Oxs_UniformExchange {
   A  13e-12  comment {A here is a single scalar, not a scalar field}
}

Specify Oxs_UZeeman [subst {
  multiplier [expr {0.001/$mu0}]
  Hrange {
     {   0   0   0   100   1   0   2 }
     { 100   1   0  -100   0   0   2 }
     {   0   0   0     0 100   0   4 }
     {  10  10  10    50  50  50   1 }
     {   0   0   0     0   0   0   0 }
  }
}]

Specify Oxs_Demag {}

Specify Oxs_CGEvolve:evolve {}

# Initial magnetization.
proc m0_proc { x y z } {
   global region_period
   set index [expr {int(floor($x/$region_period))}]
   return [list 0 [expr {1 - 2*($index%2)}] 0]
}
Specify Oxs_ScriptVectorField:m0 [subst {
   atlas :atlas
   norm 1.0
   script_args rawpt
   script m0_proc
}]

# Saturation magnetization
proc Ms_proc { x y z } {
   global region_width region_period
   set offset [expr {fmod($x,$region_period)}]
   if {$offset>$region_width} {
      # Point is in space between magnetic bits
      return 0.0
   }
   return 8e5
}
Specify Oxs_ScriptScalarField:Ms [subst {
   atlas :atlas
   script_args rawpt
   script Ms_proc
}]

Specify Oxs_MinDriver [subst {
 evolver :evolve
 stopping_mxHxm 0.1
 mesh :mesh
 Ms :Ms
 m0 :m0
}]
