@@ -9,189 +9,26 @@ double Energy::compute_energy() {
9
9
return sum * (dx * dy * dz * std::pow (unit_length, 3 ));
10
10
}
11
11
12
+ void Energy::_setup (MicroSim * sim) {
12
13
13
- void Energy::setup (int nx, int ny, int nz, double dx, double dy, double dz,
14
- double unit_length, double *spin, double *Ms, double *Ms_inv,
15
- double *coordinates, int *ngbs,
16
- double *energy, double *field
17
- ) {
18
-
19
- this ->nx = nx;
20
- this ->ny = ny;
21
- this ->nz = nz;
22
- this ->n = nx * ny * nz;
23
- this ->dx = dx;
24
- this ->dy = dy;
25
- this ->dz = dz;
26
- this ->unit_length = unit_length;
14
+ this ->nx = sim->nx ;
15
+ this ->ny = sim->ny ;
16
+ this ->nz = sim->nz ;
17
+ this ->n = sim->nx * ny * nz;
18
+ this ->dx = sim->dx ;
19
+ this ->dy = sim->dy ;
20
+ this ->dz = sim->dz ;
21
+ this ->unit_length = sim->unit_length ;
27
22
28
23
// Arrays
29
- this ->spin = spin;
30
- this ->Ms = Ms;
31
- this ->Ms_inv = Ms_inv;
32
- this ->coordinates = coordinates;
33
- this ->ngbs = ngbs;
34
- this ->energy = energy;
35
- this ->field = field;
24
+ this ->spin = sim->spin ;
25
+ this ->Ms = sim->Ms ;
26
+ this ->Ms_inv = sim->Ms_inv ;
27
+ this ->coordinates = sim->coordinates ;
28
+ this ->ngbs = sim->ngbs ;
29
+ this ->energy = sim->energy ;
30
+ this ->field = sim->field ;
31
+ // this->pins = sim->pins;
36
32
37
33
set_up = true ;
38
34
}
39
-
40
- void ExchangeEnergy::compute_field (double t) {
41
- /* Compute the micromagnetic exchange field and energy using the
42
- * matrix of neighbouring spins and a second order approximation
43
- * for the derivative
44
- *
45
- * Ms_inv :: Array with the (1 / Ms) values for every mesh node.
46
- * The values are zero for points with Ms = 0 (no material)
47
- *
48
- * A :: Exchange constant
49
- *
50
- * dx, dy, dz :: Mesh spacings in the corresponding directions
51
- *
52
- * n :: Number of mesh nodes
53
- *
54
- * ngbs :: The array of neighbouring spins, which has (6 * n)
55
- * entries. Specifically, it contains the indexes of
56
- * the neighbours of every mesh node, in the following order:
57
- * -x, +x, -y, +y, -z, +z
58
- *
59
- * Thus, the array is like:
60
- * | 0-x, 0+x, 0-y, 0+y, 0-z, 0+z, 1-x, 1+x, 1-y, ... |
61
- * i=0 i=1 ...
62
- *
63
- * where 0-y is the index of the neighbour of the 0th spin,
64
- * in the -y direction, for example. The index value for a
65
- * neighbour where Ms = 0, is evaluated as -1. The array
66
- * automatically gives periodic boundaries.
67
- *
68
- * A basic example is a 3 x 3 two dimensional mesh with PBCs
69
- * in the X and Y direction:
70
- *
71
- * +-----------+
72
- * | 6 | 7 | 8 |
73
- * +-----------+
74
- * | 3 | 4 | 5 |
75
- * +-----------+
76
- * | 0 | 1 | 2 |
77
- * +-----------+
78
- *
79
- * so, the first 6 entries (neighbours of the 0th mesh node)
80
- * of the array would be: [ 2 1 6 3 -1 -1 ... ]
81
- * (-1 since there is no material in +-z, and a '2' first,
82
- * since it is the left neighbour which is the PBC in x, etc..)
83
- *
84
- * For the exchange computation, the field is defined as:
85
- * H_ex = (2 * A / (mu0 * Ms)) * nabla^2 (mx, my, mz)
86
- *
87
- * Therefore, for the i-th mesh node (spin), we approximate the
88
- * derivatives as:
89
- * nabla^2 mx = (1 / dx^2) * ( spin[i-x] - 2 * spin[i] + spin[i+x] ) +
90
- * (1 / dy^2) * ( spin[i-y] - 2 * spin[i] + spin[i+y] ) +
91
- * (1 / dz^2) * ( spin[i-z] - 2 * spin[i] + spin[i+z] )
92
- *
93
- * Where i-x is the neighbour in the -x direction. This is similar
94
- * for my and mz.
95
- * We can notice that the sum is the same if we do:
96
- * ( spin[i-x] - spin[i] ) + ( spin[i+x] - spin[i] )
97
- * so we can iterate through the neighbours and perform the sum with the
98
- * corresponding coefficient 1 /dx, 1/dy or 1/dz
99
- *
100
- * The *m array contains the spins as:
101
- * [mx0, my0, mz0, mx1, my1, mz1, mx2, ...]
102
- * so if we want the starting position of the magnetisation for the
103
- * i-th spin, we only have to do (3 * i) for mx, (3 * i + 1) for my
104
- * and (3 * i + 2) for mz
105
- *
106
- *
107
- * IMPORTANT: The ex field usually has the structure:
108
- * 2 * A / (mu0 Ms ) * (Second derivative of M)
109
- * When discretising the derivative, it carries a "2" in the
110
- * denominator which we "cancel" with the "2" in the prefactor,
111
- * hence we do not put it explicitly in the calculations
112
- *
113
- * So, when computing the energy: (-1/2) * mu * Ms * H_ex
114
- * we only put the 0.5 factor and don't worry about the "2"s in the
115
- * field
116
- *
117
- */
118
-
119
- /* Here we iterate through every mesh node */
120
- for (int i = 0 ; i < n; i++) {
121
- /* Define the coefficients */
122
- double ax = 2 * A[i] / (dx * dx);
123
- double ay = 2 * A[i] / (dy * dy);
124
- double az = 2 * A[i] / (dz * dz);
125
-
126
- double fx = 0 , fy = 0 , fz = 0 ;
127
- int idnm = 0 ; // Index for the magnetisation matrix
128
- int idn = 6 * i; // index for the neighbours
129
-
130
- /* Set a zero field for sites without magnetic material */
131
- if (Ms_inv[i] == 0.0 ){
132
- field[3 * i] = 0 ;
133
- field[3 * i + 1 ] = 0 ;
134
- field[3 * i + 2 ] = 0 ;
135
- continue ;
136
- }
137
-
138
- /* Here we iterate through the neighbours */
139
- for (int j = 0 ; j < 6 ; j++) {
140
- /* Remember that index=-1 is for sites without material */
141
- if (ngbs[idn + j] >= 0 ) {
142
- /* Magnetisation of the neighbouring spin since ngbs gives
143
- * the neighbour's index */
144
- idnm = 3 * ngbs[idn + j];
145
-
146
- /* Check that the magnetisation of the neighbouring spin
147
- * is larger than zero */
148
- if (Ms_inv[ngbs[idn + j]] > 0 ){
149
-
150
- /* Neighbours in the -x and +x directions
151
- * giving: ( spin[i-x] - spin[i] ) + ( spin[i+x] - spin[i] )
152
- * when ngbs[idn + j] > 0 for j = 0 and j=1
153
- * If, for example, there is no
154
- * neighbour at -x (j=0) in the 0th node (no PBCs),
155
- * the second derivative would only be avaluated as:
156
- * (1 / dx * dx) * ( spin[i+x] - spin[i] )
157
- * which, according to
158
- * [M.J. Donahue and D.G. Porter; Physica B, 343, 177-183 (2004)]
159
- * when performing the integration of the energy, we still
160
- * have error of the order O(dx^2)
161
- * This same applies for the other directions
162
- */
163
- if (j == 0 || j == 1 ) {
164
- fx += ax * (spin[idnm] - spin[3 * i]);
165
- fy += ax * (spin[idnm + 1 ] - spin[3 * i + 1 ]);
166
- fz += ax * (spin[idnm + 2 ] - spin[3 * i + 2 ]);
167
- }
168
- /* Neighbours in the -y and +y directions */
169
- else if (j == 2 || j == 3 ) {
170
- fx += ay * (spin[idnm] - spin[3 * i]);
171
- fy += ay * (spin[idnm + 1 ] - spin[3 * i + 1 ]);
172
- fz += ay * (spin[idnm + 2 ] - spin[3 * i + 2 ]);
173
- }
174
- /* Neighbours in the -z and +z directions */
175
- else if (j == 4 || j == 5 ) {
176
- fx += az * (spin[idnm] - spin[3 * i]);
177
- fy += az * (spin[idnm + 1 ] - spin[3 * i + 1 ]);
178
- fz += az * (spin[idnm + 2 ] - spin[3 * i + 2 ]);
179
- }
180
- else {
181
- continue ;
182
- }
183
- }
184
- }
185
- }
186
-
187
- /* Energy as: (-mu0 * Ms / 2) * [ H_ex * m ] */
188
- energy[i] = -0.5 * (fx * spin[3 * i] + fy * spin[3 * i + 1 ]
189
- + fz * spin[3 * i + 2 ]);
190
-
191
- /* Update the field H_ex which has the same structure than *m */
192
- field[3 * i] = fx * Ms_inv[i] * MU_0_INV;
193
- field[3 * i + 1 ] = fy * Ms_inv[i] * MU_0_INV;
194
- field[3 * i + 2 ] = fz * Ms_inv[i] * MU_0_INV;
195
-
196
- }
197
- }
0 commit comments