-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.go
118 lines (104 loc) · 3.01 KB
/
run.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
package engine
import (
"fmt"
"github.com/mumax/3/mag"
"github.com/mumax/3/util"
"time"
)
func init() {
DeclFunc("Run", Run, "Run the simulation for a time in seconds")
DeclFunc("Steps", Steps, "Run the simulation for a number of time steps")
DeclFunc("RunWhile", RunWhile, "Run while condition function is true")
DeclFunc("SetSolver", SetSolver, "Set solver type. 1:Euler, 2:Heun")
DeclVar("t", &Time, "Total simulated time (s)")
DeclROnly("dt", &Solver.Dt_si, "Last solver time step (s)")
DeclVar("MinDt", &Solver.MinDt, "Minimum time step the solver can take (s)")
DeclVar("MaxDt", &Solver.MaxDt, "Maximum time step the solver can take (s)")
DeclVar("MaxErr", &Solver.MaxErr, "Maximum error per step the solver can tolerate")
DeclVar("Headroom", &Solver.Headroom, "Solver headroom")
DeclVar("FixDt", &Solver.FixDt, "Set a fixed time step. 0 disables fixed step.")
SetSolver(HEUN)
}
var (
Solver = NewSolver(Torque.Set, M.normalize, 1e-15, mag.Gamma0, HeunStep)
Time float64 // time in seconds
pause = true // set pause at any time to stop running after the current step
postStep []func() // called on after every time step
Inject = make(chan func()) // injects code in between time steps. Used by web interface.
solvertype int
)
func SetSolver(typ int) {
switch typ {
default:
util.Fatalf("SetSolver: unknown solver type: %v", typ)
case 1:
Solver.step = EulerStep
case 2:
Solver.step = HeunStep
}
solvertype = typ
}
const (
EULER = 1
HEUN = 2
)
// Run the simulation for a number of seconds.
func Run(seconds float64) {
GUI.Set("runtime", seconds)
stop := Time + seconds
RunWhile(func() bool { return Time < stop })
}
// Run the simulation for a number of steps.
func Steps(n int) {
GUI.Set("runsteps", n)
stop := Solver.NSteps + n
RunWhile(func() bool { return Solver.NSteps < stop })
}
// Runs as long as condition returns true.
func RunWhile(condition func() bool) {
GUI.Set("maxtorque", "--") // only updated on page refresh, avoid showing out-of-date value
pause = false
for condition() && !pause {
select {
default:
step()
// accept tasks form Inject channel
case f := <-Inject:
f()
}
}
pause = true
}
func break_() {
pause = true
}
// exit finished simulation this long after browser was closed
var Timeout = 3 * time.Second
// Enter interactive mode. Simulation is now exclusively controlled by web GUI
func RunInteractive() {
updateKeepAlive()
fmt.Println("entering interactive mode")
for time.Since(KeepAlive()) < Timeout {
f := <-Inject
f()
}
fmt.Println("browser disconnected, exiting")
}
func step() {
Solver.Step(M.Buffer())
for _, f := range postStep {
f()
}
DoOutput()
}
// Register function f to be called after every time step.
// Typically used, e.g., to manipulate the magnetization.
func PostStep(f func()) {
postStep = append(postStep, f)
}
// inject code into engine and wait for it to complete.
func InjectAndWait(task func()) {
ready := make(chan int)
Inject <- func() { task(); ready <- 1 }
<-ready
}