/
engine.go
131 lines (110 loc) · 2.91 KB
/
engine.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package engine
import (
"github.com/mumax/3/cuda"
"github.com/mumax/3/data"
"github.com/mumax/3/mag"
"log"
"runtime"
)
const VERSION = "mumax3.0.11 α "
var UNAME = VERSION + runtime.GOOS + "_" + runtime.GOARCH + " " + runtime.Version() + "(" + runtime.Compiler + ")"
var (
globalmesh data.Mesh // mesh for m and everything that has the same size
M magnetization // reduced magnetization (unit length)
B_eff, Torque setter
)
func init() {
DeclFunc("setgridsize", setGridSize, `Sets the number of cells for X,Y,Z`)
DeclFunc("setcellsize", setCellSize, `Sets the X,Y,Z cell size in meters`)
// magnetization
M.init(3, "m", "", `Reduced magnetization (unit length)`, &globalmesh)
// effective field
B_eff.init(3, &globalmesh, "B_eff", "T", "Effective field", func(dst *data.Slice) {
B_demag.set(dst)
B_exch.addTo(dst)
B_anis.addTo(dst)
B_ext.addTo(dst)
})
// torque inited in torque.go
}
func Mesh() *data.Mesh {
checkMesh()
return &globalmesh
}
func WorldSize() [3]float64 {
w := Mesh().WorldSize()
return [3]float64{w[2], w[1], w[0]} // swaps XYZ
}
// Set the simulation mesh to Nx x Ny x Nz cells of given size.
// Can be set only once at the beginning of the simulation.
func SetMesh(Nx, Ny, Nz int, cellSizeX, cellSizeY, cellSizeZ float64) {
if Nx <= 1 {
log.Fatal("mesh size X should be > 1, have: ", Nx)
}
globalmesh = *data.NewMesh(Nz, Ny, Nx, cellSizeZ, cellSizeY, cellSizeX)
log.Println("set mesh:", Mesh().UserString())
alloc()
}
// allocate m and regions buffer (after mesh is set)
func alloc() {
M.alloc()
regions.alloc()
Solver = *cuda.NewHeun(M.buffer, Torque.set, normalize, 1e-15, mag.Gamma0, &Time)
Table.Add(&M)
vol = data.NilSlice(1, Mesh())
}
func normalize(m *data.Slice) {
cuda.Normalize(m, nil)
}
// for lazy setmesh: set gridsize and cellsize in separate calls
var (
gridsize []int
cellsize []float64
)
func setGridSize(Nx, Ny, Nz int) {
gridsize = []int{Nx, Ny, Nz}
if cellsize != nil {
SetMesh(Nx, Ny, Nz, cellsize[0], cellsize[1], cellsize[2])
}
}
func setCellSize(cx, cy, cz float64) {
cellsize = []float64{cx, cy, cz}
if gridsize != nil {
SetMesh(gridsize[0], gridsize[1], gridsize[2], cx, cy, cz)
}
}
// check if mesh is set
func checkMesh() {
if globalmesh.Size() == [3]int{0, 0, 0} {
log.Panic("need to set mesh first")
}
}
// check if m is set
func checkM() {
checkMesh()
if M.buffer.DevPtr(0) == nil {
log.Fatal("need to initialize magnetization first")
}
if cuda.MaxVecNorm(M.buffer) == 0 {
log.Fatal("need to initialize magnetization first")
}
}
// Cleanly exits the simulation, assuring all output is flushed.
func Close() {
log.Println("shutting down")
drainOutput()
Table.flush()
// debug. TODO: rm
for n, p := range params {
if u, ok := p.(interface {
NUpload() int
}); ok {
log.Println(n, "\t:\t", u.NUpload(), "uploads")
}
}
}
//func sanitycheck() {
// if Msat() == 0 {
// log.Fatal("Msat should be nonzero")
// }
//}