@@ -10,22 +10,22 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
1010 *
1111 * Ms_inv :: Array with the (1 / Ms) values for every mesh node.
1212 * The values are zero for points with Ms = 0 (no material)
13- *
13+ *
1414 * A :: Exchange constant
15- *
15+ *
1616 * dx, dy, dz :: Mesh spacings in the corresponding directions
17- *
17+ *
1818 * n :: Number of mesh nodes
1919 *
2020 * ngbs :: The array of neighbouring spins, which has (6 * n)
21- * entries. Specifically, it contains the indexes of
21+ * entries. Specifically, it contains the indexes of
2222 * the neighbours of every mesh node, in the following order:
2323 * -x, +x, -y, +y, -z, +z
24- *
24+ *
2525 * Thus, the array is like:
2626 * | 0-x, 0+x, 0-y, 0+y, 0-z, 0+z, 1-x, 1+x, 1-y, ... |
2727 * i=0 i=1 ...
28- *
28+ *
2929 * where 0-y is the index of the neighbour of the 0th spin,
3030 * in the -y direction, for example. The index value for a
3131 * neighbour where Ms = 0, is evaluated as -1. The array
@@ -48,15 +48,15 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
4848 * since it is the left neighbour which is the PBC in x, etc..)
4949 *
5050 * For the exchange computation, the field is defined as:
51- * H_ex = (2 * A / (mu0 * Ms)) * nabla^2 (mx, my, mz)
51+ * H_ex = (2 * A / (mu0 * Ms)) * nabla^2 (mx, my, mz)
5252 *
5353 * Therefore, for the i-th mesh node (spin), we approximate the
5454 * derivatives as:
55- * nabla^2 mx = (1 / dx^2) * ( m[i-x] - 2 * m[i] + m[i+x] ) +
56- * (1 / dy^2) * ( m[i-y] - 2 * m[i] + m[i+y] ) +
55+ * nabla^2 mx = (1 / dx^2) * ( m[i-x] - 2 * m[i] + m[i+x] ) +
56+ * (1 / dy^2) * ( m[i-y] - 2 * m[i] + m[i+y] ) +
5757 * (1 / dz^2) * ( m[i-z] - 2 * m[i] + m[i+z] )
58- *
59- * Where i-x is the neighbour in the -x direction. This is similar
58+ *
59+ * Where i-x is the neighbour in the -x direction. This is similar
6060 * for my and mz.
6161 * We can notice that the sum is the same if we do:
6262 * ( m[i-x] - m[i] ) + ( m[i+x] - m[i] )
@@ -101,7 +101,7 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
101101 field [3 * i + 2 ] = 0 ;
102102 continue ;
103103 }
104-
104+
105105 /* Here we iterate through the neighbours */
106106 for (int j = 0 ; j < 6 ; j ++ ) {
107107 /* Remember that index=-1 is for sites without material */
@@ -113,15 +113,15 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
113113 /* Check that the magnetisation of the neighbouring spin
114114 * is larger than zero */
115115 if (Ms_inv [ngbs [idn + j ]] > 0 ){
116-
117- /* Neighbours in the -x and +x directions
116+
117+ /* Neighbours in the -x and +x directions
118118 * giving: ( m[i-x] - m[i] ) + ( m[i+x] - m[i] )
119119 * when ngbs[idn + j] > 0 for j = 0 and j=1
120120 * If, for example, there is no
121121 * neighbour at -x (j=0) in the 0th node (no PBCs),
122122 * the second derivative would only be avaluated as:
123123 * (1 / dx * dx) * ( m[i+x] - m[i] )
124- * which, according to
124+ * which, according to
125125 * [M.J. Donahue and D.G. Porter; Physica B, 343, 177-183 (2004)]
126126 * when performing the integration of the energy, we still
127127 * have error of the order O(dx^2)
@@ -160,3 +160,77 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
160160 field [3 * i + 2 ] = fz * Ms_inv [i ] * MU0_INV ;
161161 }
162162}
163+
164+ inline int get_index (int nx , int ny , int i , int j , int k ){
165+ return k * nx * ny + j * nx + i ;
166+ }
167+
168+ void compute_exch_field_rkky_micro (double * m , double * field , double * energy , double * Ms_inv ,
169+ double sigma , int nx , double ny , double nz , int z_bottom , int z_top ){
170+
171+ /* Compute the micromagnetic exchange field and energy using the
172+ * matrix of neighbouring spins and a second order approximation
173+ * for the derivative
174+ *
175+ * Ms_inv :: Array with the (1 / Ms) values for every mesh node.
176+ * The values are zero for points with Ms = 0 (no material)
177+ *
178+ * sigma :: Exchange constant
179+ *
180+ * nx, ny, nz :: Mesh dimensions.
181+ * The exchange field at the top (bottom) layer can be computed as:
182+ *
183+ * H_top = (sigma / (mu0 * Ms)) * m_bottom
184+ * H_bottom = (sigma / (mu0 * Ms)) * m_top
185+ *
186+ * The *m array contains the spins as:
187+ * [mx0, my0, mz0, mx1, my1, mz1, mx2, ...]
188+ * so if we want the starting position of the magnetisation for the
189+ * i-th spin, we only have to do (3 * i) for mx, (3 * i + 1) for my
190+ * and (3 * i + 2) for mz
191+ *
192+ *
193+ *
194+ */
195+
196+ int n = nx * ny * nz ;
197+ for (int i = 0 ; i < n ; i ++ ){
198+ energy [i ] = 0 ;
199+ field [3 * i ]= 0 ;
200+ field [3 * i + 1 ]= 0 ;
201+ field [3 * i + 2 ]= 0 ;
202+ }
203+
204+ #pragma omp parallel for
205+ for (int i = 0 ; i < nx ; i ++ ) {
206+ for (int j = 0 ; j < ny ; j ++ ){
207+ double mtx = 0 , mty = 0 , mtz = 0 ;
208+ double mbx = 0 , mby = 0 , mbz = 0 ;
209+ int id1 = get_index (nx ,ny , i , j , z_bottom );
210+ int id2 = get_index (nx ,ny , i , j , z_top );
211+ mtx = m [3 * id2 ];
212+ mty = m [3 * id2 + 1 ];
213+ mtz = m [3 * id2 + 2 ];
214+
215+ mbx = m [3 * id1 ];
216+ mby = m [3 * id1 + 1 ];
217+ mbz = m [3 * id1 + 2 ];
218+
219+ if (Ms_inv [id1 ] != 0.0 ){
220+ energy [id1 ] = sigma * (1 - mtx * mbx - mty * mby - mtz * mbz );
221+ field [3 * id1 ] = sigma * mtx * Ms_inv [id1 ] * MU0_INV ;
222+ field [3 * id1 + 1 ] = sigma * mty * Ms_inv [id1 ] * MU0_INV ;
223+ field [3 * id1 + 2 ] = sigma * mtz * Ms_inv [id1 ] * MU0_INV ;
224+ }
225+
226+ if (Ms_inv [id2 ] != 0.0 ){
227+ energy [id2 ] = sigma * (1 - mtx * mbx - mty * mby - mtz * mbz );
228+ field [3 * id2 ] = sigma * mbx * Ms_inv [id2 ] * MU0_INV ;
229+ field [3 * id2 + 1 ] = sigma * mby * Ms_inv [id2 ] * MU0_INV ;
230+ field [3 * id2 + 2 ] = sigma * mbz * Ms_inv [id2 ] * MU0_INV ;
231+ }
232+ }
233+ }
234+
235+
236+ }
0 commit comments