# MIF 2.2

Parameter seed 1
Parameter thickness 6e-9
Parameter stop 1e-2

RandomSeed $seed


### ROGUE GRAIN:                             ###
###   if $Rogue= -1, no rogue grain is used  ###
###   for $Rogue>= 0, Kc of grain number     ###
###     designated by $Rogue may be adjusted ###
################################################
set Rogue -1
Parameter phideg 10;        #phideg in degrees, from 0 to 90, 0 is all z.

#######################
###### CONSTANTS #####
#######################

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

###################
###### PROCS ######
###################

### This Proc makes ellipses and circles  ###
#############################################
proc Ellipse { Ms x y z} {
   set x [expr {2*$x-1.}]
   set y [expr {2*$y-1.}]
   if {$x*$x+$y*$y<=1.0} {
      return $Ms
   }
   return 0.0
}

#######################
###### MATERIALS ######
#######################

### for Ni ###

set Ms 490e3
set Ku -5.7e3
set A  6.9e-12

##########################
###### ATLAS & MESH ######
##########################


set xsize 400e-9
set ysize 400e-9

set xycellsize 1.0e-9
set zcellsize  3.0e-9

### Atlas ####
##############

set grain_count 260
set grain_map polycrystal-map-mif.ppm

set colormap {}
for {set i 0} {$i<$grain_count} {incr i} {
   lappend colormap [format "#%06x" $i]
   lappend colormap $i
}

Specify Oxs_ImageAtlas:world [subst {
  xrange {0 $xsize}
  yrange {0 $ysize}
  zrange {0 $thickness}
  viewplane xy
  image $grain_map
  colormap {
     $colormap
  }
  matcherror 0.0
}]

### Mesh ###
############

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


##############################
###### CUBIC ANISOTROPY ######
##############################

### This Proc generates TEXTURED random unit vector  ###
########################################################

set phirange [expr {1-cos($phideg*$pi/180.)}]
proc Texture {} {
   global pi phirange

   set theta [expr {(2.*rand()-1.)*$pi}]
   set costheta [expr {cos($theta)}]
   set sintheta [expr {sin($theta)}]

   set cosphi [expr {1.-$phirange*rand()}]
   set sinphi [expr {1.0-$cosphi*$cosphi}]
   if {$sinphi>0.0} { set sinphi [expr {sqrt($sinphi)}] }

   set x [expr {$sinphi*$costheta}]
   set y [expr {$sinphi*$sintheta}]
   set z [expr {$cosphi}]

   return [list $x $y $z]
}


### This Proc generates a second random unit vector  ###
########################################################

proc RandomUnitVec {} {
   global pi

   set theta [expr {(2.*rand()-1.)*$pi}]
   set costheta [expr {cos($theta)}]
   set sintheta [expr {sin($theta)}]

   set cosphi [expr {1.0 - 2.*rand()}]
   set sinphi [expr {1.0-$cosphi*$cosphi}]
   if {$sinphi>0.0} { set sinphi [expr {sqrt($sinphi)}] }

   set x [expr {$sinphi*$costheta}]
   set y [expr {$sinphi*$sintheta}]
   set z [expr {$cosphi}]

   return [list $x $y $z]
}


### This sets two vectors for each grain region ###
############################################################

set A_axes {}
for {set i 0} {$i<$grain_count} {incr i} {
   lappend A_axes $i
   lappend A_axes [Texture]
}

set B_axes {}
for {set i 0} {$i<$grain_count} {incr i} {

   lappend B_axes $i
   set B_temp [RandomUnitVec]

   set Ax [lindex [lindex $A_axes [expr {2*$i+1}]] 0]
   set Ay [lindex [lindex $A_axes [expr {2*$i+1}]] 1]
   set Az [lindex [lindex $A_axes [expr {2*$i+1}]] 2]

   set Bxtemp [lindex $B_temp 0]
   set Bytemp [lindex $B_temp 1]
   set Bztemp [lindex $B_temp 2]

   while {[expr abs($Ax*$Bxtemp + $Ay*$Bytemp + $Az*$Bztemp) > 0.9] } {
      set B_temp [RandomUnitVec]
      set Bxtemp [lindex $B_temp 0]
      set Bytemp [lindex $B_temp 1]
      set Bztemp [lindex $B_temp 2]
   }
   set Bx [expr {$Ay*$Bztemp-$Az*$Bytemp}]
   set By [expr {$Az*$Bxtemp-$Ax*$Bztemp}]
   set Bz [expr {$Ax*$Bytemp-$Ay*$Bxtemp}]

   #set norm [expr {sqrt($Bx*$Bx+$By*$By+$Bz*$Bz)}]
   lappend B_axes [list $Bx $By $Bz]

}

### This sets the rogue grain ($Rogue < $grain_count) ###
#########################################################

if {$Rogue != -1} {
   set item_number [expr {2*$Rogue+1}]
   set A_axes [lreplace $A_axes $item_number $item_number {1 0 0}]
   set B_axes [lreplace $B_axes $item_number $item_number {0 1 0}]
}


Specify Oxs_AtlasVectorField:A_axes [subst {
   atlas :world
   norm 1.0
   values [list $A_axes]
}]

Specify Oxs_AtlasVectorField:B_axes [subst {
   atlas :world
   norm 1.0
   values [list $B_axes]
}]

Specify Oxs_CubicAnisotropy [subst {
   K1 $Ku
   axis1 :A_axes
   axis2 :B_axes
}]


######################
###### EXCHANGE ######
######################

set A_list {}
for {set i 0} {$i<$grain_count} {incr i} {
   lappend A_list $i $i $A
}

Specify Oxs_Exchange6Ngbr [subst {
   default_A $A
   atlas world
   A   [list $A_list]
}]


######################################
###### ZEEMAN ( applied field ) ######
######################################


set field 10000         ;# Maximum field (in Oe)

Specify Oxs_UZeeman [subst {
   multiplier [expr {(1./($mu0*1e4))*$field}]
   Hrange  {
      { 0 0 0   0 0 1   10}
   }
}]


##############################
###### DRIVER & EVOLVER ######
##############################

### File Handling ###
#####################

SetOptions [subst {
   basename "polycubic_phi_$phideg"
}]

### Evolver ###
###############

Specify Oxs_CGEvolve:evolve {}

### Driver ###
##############

Specify Oxs_MinDriver [subst {
   evolver evolve
   stopping_mxHxm $stop
   mesh :mesh
   Ms { Oxs_ScriptScalarField {
      atlas :world
      script_args {relpt}
      script {Ellipse $Ms}
   } }
   m0 { 1 0 0 }
}]
