# MIF 2.1
# MIF Example File: manyregions-scriptatlas.mif
# Description: Example with a large number of regions defined using an
#              Oxs_ScriptAtlas.  This example is otherwise identical to
#              manyregions-multiatlas.mif.

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

# Use a Tcl for-loop to construct a string representing region names.
for {set i 0} {$i<$region_count} {incr i} {
     lappend region_names "region_$i"
}

proc regions_proc { x y z } {
   global region_width region_period
   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 "0" to indicate "universe" region.
      return 0
   }
   # Otherwise, return offset number plus one.  The plus one is
   # necessary to skip over the 0-numbered "universe" region.
   return [expr {$index+1}]
}

Specify Oxs_ScriptAtlas:atlas [subst {
  xrange {0 $xmax}
  yrange {0 $ymax}
  zrange {0 $zmax}
  regions { $region_names }
  script_args rawpt
  script regions_proc
}]

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

# Define an Oxs_AtlasVectorField object to define anisotropy directions.
# Again, a Tcl for-loop is used to construct a string that is imported
# into the Specify block.
for {set i 0} {$i<$region_count} {incr i} {
   set theta [expr {$pi*$i/$region_count}]
   set value_string [list 0 [expr {cos($theta)}] [expr {sin($theta)}]]
   lappend anisaxis_value_list "region_$i" $value_string
}
Specify Oxs_AtlasVectorField:anisotropy_directions [subst {
   atlas :atlas
   norm 1.0
   default_value {1 0 0}  comment {Dummy value for non-magnetic matrix}
   values { $anisaxis_value_list }
}]

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 {}

# Define an Oxs_AtlasVectorField object to define initial magnetization.
for {set i 0} {$i<$region_count} {incr i} {
   set value_string [list 0 [expr {1 - 2*($i%2)}] 0]
   lappend m0_value_list "region_$i" $value_string
}
Specify Oxs_AtlasVectorField:m0 [subst {
   atlas :atlas
   norm 1.0
   default_value {1 0 0}
   values { $m0_value_list }
}]


Specify Oxs_MinDriver [subst {
 evolver :evolve
 stopping_mxHxm 0.1
 mesh :mesh
 Ms { Oxs_AtlasScalarField {
    atlas :atlas
    default_value 8e5
    values {
       universe 0.0
    }
 }}
 m0 :m0
}]
