1
1
from __future__ import division
2
2
import numpy as np
3
3
import fidimag .extensions .clib as clib
4
- import fidimag .common .helper as helper
5
- import fidimag .common .constant as const
4
+ # import fidimag.common.constant as const
6
5
7
- from .atomistic_driver import AtomisticDriver
6
+ from .minimiser_base import MinimiserBase
8
7
9
8
10
- class Minimiser ( AtomisticDriver ):
9
+ class SimpleMinimiser ( MinimiserBase ):
11
10
"""
11
+ A simple minimisation algorithm, where the evolution of the magnetisation
12
+ follows the system's torque
12
13
13
- A simple minimisation algorithm
14
-
15
- This class inherits common methods to evolve the system using CVODE, from
16
- the micro_driver.AtomisticDriver class. Arrays with the system information
17
- are taken as references from the main micromagnetic Simulation class
14
+ CHECK:
18
15
16
+ h = (m_i + H) / || (m_i + H) ||
17
+ m_i+1 = m_i + alpha * (h_i - m_i)
19
18
"""
20
19
21
- def __init__ (self , mesh , spin , mu_s , mu_s_inv , field , pins ,
20
+ def __init__ (self , mesh , spin ,
21
+ magnetisation , magnetisation_inv , field , pins ,
22
22
interactions ,
23
23
name ,
24
24
data_saver ,
25
25
use_jac = False ,
26
26
integrator = None
27
27
):
28
28
29
- # self.mesh = mesh
30
- # self.spin = spin
31
- # self.mu_s mu_s
32
- # self._mu_s_inv = mu_s_inv
33
- # self.field = field
34
- # self.pins = pins
35
- # self.interactions = interactions
36
- # self.name = name
37
- # self.data_saver = data_saver
38
-
39
- # Inherit from the driver class
40
- super (Minimiser , self ).__init__ (mesh , spin , mu_s , mu_s_inv , field ,
41
- pins , interactions , name ,
42
- data_saver ,
43
- use_jac = use_jac ,
44
- integrator = integrator
45
- )
29
+ # Inherit from the base minimiser class
30
+ super (SimpleMinimiser , self ).__init__ (mesh , spin ,
31
+ magnetisation , magnetisation_inv ,
32
+ field ,
33
+ pins ,
34
+ interactions ,
35
+ name ,
36
+ data_saver
37
+ )
46
38
47
39
self .t = 1e-4
48
- self .alpha = 0.1
40
+ self ._alpha = 0.1
41
+ self ._alpha_field = self ._alpha * np .ones_like (self .spin )
49
42
self .spin_last = np .zeros_like (spin )
50
43
self ._new_spin = np .zeros_like (spin )
51
44
52
- # self.set_options()
45
+ @property
46
+ def alpha (self ):
47
+ """
48
+ Returns the array with the spatially dependent Gilbert damping
49
+ per mesh/lattice site
50
+ """
51
+ return self ._alpha
52
+
53
+ @alpha .setter
54
+ def set_alpha (self , value ):
55
+ """
56
+ """
57
+ self ._alpha = value
58
+ self ._alpha_field = value * np .ones_like (self .spin )
53
59
54
60
def run_step (self ):
55
61
@@ -60,48 +66,56 @@ def run_step(self):
60
66
clib .normalise_spin (self ._new_spin , self ._pins , self .n )
61
67
62
68
self ._new_spin [self ._material ] = (self .spin_last +
63
- self .alpha_field * (self ._new_spin - self .spin_last ))[self ._material ]
69
+ self ._alpha_field * (self ._new_spin - self .spin_last ))[self ._material ]
64
70
self .spin [:] = self ._new_spin [:]
65
71
clib .normalise_spin (self .spin , self ._pins , self .n )
66
72
67
- def update_effective_field (self ):
68
-
69
- self .field [:] = 0
70
- for obj in self .interactions :
71
- self .field += obj .compute_field (t = 0 , spin = self .spin )
72
-
73
- def minimise (self , stopping_dm = 1e-2 , max_steps = 2000 , save_data_steps = 10 ):
73
+ def minimise (self , stopping_dm = 1e-2 , max_steps = 2000 ,
74
+ save_data_steps = 10 , save_m_steps = None , save_vtk_steps = None ,
75
+ log_steps = 1000
76
+ ):
74
77
"""
75
78
76
79
"""
77
80
78
81
self .step = 0
79
82
80
- self .alpha_field = np .repeat (self .alpha , 3 )
81
-
82
- # Only update site with mu_s > 0 which are not pinned
83
- self ._material = np .logical_and (np .repeat (self ._mu_s / const .mu_B , 3 ) > 1e-10 ,
83
+ # Only update site with magnetisation > 0 which are not pinned
84
+ self ._material = np .logical_and (np .repeat (self ._magnetisation , 3 ) > 0.0 ,
84
85
np .repeat (1 - self ._pins , 3 ).astype (np .bool ))
85
86
86
87
self .spin_last [:] = self .spin [:]
87
- self .update_effective_field ()
88
+ self .compute_effective_field ()
88
89
while self .step < max_steps :
89
90
90
91
self .run_step ()
91
92
92
93
max_dm = (self .spin - self .spin_last ).reshape (- 1 , 3 ) ** 2
93
94
max_dm = np .max (np .sqrt (np .sum (max_dm , axis = 1 )))
94
- print ("#max_dm={:<10.3g} step={}" .format (max_dm , self .step ))
95
+
96
+ if self .step % log_steps == 0 :
97
+ print ("#max_tau={:<8.3g} max_dm={:<10.3g} counter={}" .format (
98
+ np .max (np .abs (self .tau )),
99
+ max_dm , self .step ))
95
100
96
101
if max_dm < stopping_dm and self .step > 0 :
102
+ print ("FINISHED AT: max_tau={:<8.3g} max_dm={:<10.3g} counter={}" .format (
103
+ np .max (np .abs (self .tau )),
104
+ max_dm , self .step ))
105
+
106
+ self .compute_effective_field ()
107
+ self .data_saver .save ()
108
+
97
109
break
98
110
99
111
if self .step % save_data_steps == 0 :
100
112
# update field before saving data
101
- self .update_effective_field ()
113
+ self .compute_effective_field ()
102
114
self .data_saver .save ()
103
115
104
- self .step += 1
116
+ if (save_vtk_steps is not None ) and (self .step % save_vtk_steps == 0 ):
117
+ self .save_vtk ()
118
+ if (save_m_steps is not None ) and (self .step % save_m_steps == 0 ):
119
+ self .save_m ()
105
120
106
- def relax (self ):
107
- print ('Not implemented for the minimizer' )
121
+ self .step += 1
0 commit comments