void fdm_zhangli_cpu( int dim_x, int dim_y, int dim_z, double delta_x, double delta_y, double delta_z, bool do_precess, const Matrix &P, const Matrix &xi, const Matrix &Ms, const Matrix &alpha, const VectorMatrix &j, const VectorMatrix &M, VectorMatrix &dM) { VectorMatrix::const_accessor M_acc(M), j_acc(j); Matrix::ro_accessor Ms_acc(Ms), alpha_acc(alpha), P_acc(P), xi_acc(xi); VectorMatrix::accessor dM_acc(dM); for (int z=0; z<dim_z; ++z) for (int y=0; y<dim_y; ++y) for (int x=0; x<dim_x; ++x) { const int k = z*dim_x*dim_y + y*dim_x + x; const double Ms = Ms_acc.at(k); const double alpha = alpha_acc.at(k); const double P = P_acc.at(k); const double xi = xi_acc.at(k); const Vector3d j = j_acc.get(k); dM_acc.set(k, zhangli_dMdt(x, y, z, dim_x, dim_y, dim_z, delta_x, delta_y, delta_z, do_precess, P, xi, Ms, alpha, j, M_acc)); } }
void fdm_slonchewski( int dim_x, int dim_y, int dim_z, double delta_x, double delta_y, double delta_z, double a_j, const VectorMatrix &p, // spin polarization const Matrix &Ms, const Matrix &alpha, const VectorMatrix &M, VectorMatrix &dM) { // Calculate: // c1*(M x (M x p)) + c2*(M x p) // // c1(theta): damping factor // c2(theta): precession factor // Ms*cos(theta) = M*p Matrix::ro_accessor Ms_acc(Ms), alpha_acc(alpha); VectorMatrix::const_accessor p_acc(p); VectorMatrix::const_accessor M_acc(M); VectorMatrix::accessor dM_acc(dM); const int N = dim_x * dim_y * dim_z; for (int n=0; n<N; ++n) { const double alpha = alpha_acc.at(n); const double Ms = Ms_acc.at(n); const Vector3d p = p_acc.get(n); const Vector3d M = M_acc.get(n); if (p == Vector3d(0.0, 0.0, 0.0)) continue; if (Ms == 0.0) continue; // Calculate precession and damping terms const Vector3d Mxp = cross(M, p); // precession: u=mxp const Vector3d MxMxp = cross(M, Mxp); // damping: t=mxu=mx(mxp) // add both terms to dm/dt in LLGE const double gamma_pr = GYROMAGNETIC_RATIO / (1.0 + alpha*alpha); Vector3d dM_n; dM_n.x = gamma_pr * a_j * (-MxMxp.x/Ms + Mxp.x*alpha); dM_n.y = gamma_pr * a_j * (-MxMxp.y/Ms + Mxp.y*alpha); dM_n.z = gamma_pr * a_j * (-MxMxp.z/Ms + Mxp.z*alpha); dM_acc.set(n, dM_n); } }
static double fdm_exchange_cpu_nonperiodic( int dim_x, int dim_y, int dim_z, double delta_x, double delta_y, double delta_z, const Matrix &Ms, const Matrix &A, const VectorMatrix &M, VectorMatrix &H) { const int dim_xy = dim_x * dim_y; const double wx = 1.0 / (delta_x * delta_x); const double wy = 1.0 / (delta_y * delta_y); const double wz = 1.0 / (delta_z * delta_z); VectorMatrix::const_accessor M_acc(M); VectorMatrix::accessor H_acc(H); Matrix::ro_accessor Ms_acc(Ms), A_acc(A); double energy = 0.0; for (int z=0; z<dim_z; ++z) { for (int y=0; y<dim_y; ++y) { for (int x=0; x<dim_x; ++x) { const int i = z*dim_xy + y*dim_x + x; // linear index of (x,y,z) const double Ms = Ms_acc.at(i); if (Ms == 0.0) { H_acc.set(i, Vector3d(0.0, 0.0, 0.0)); continue; } const int idx_l = i- 1; const int idx_r = i+ 1; const int idx_u = i- dim_x; const int idx_d = i+ dim_x; const int idx_f = i-dim_xy; const int idx_b = i+dim_xy; const Vector3d M_i = M_acc.get(i) / Ms; // magnetization at (x,y,z) Vector3d sum(0.0, 0.0, 0.0); // left / right (X) if (x > 0) { const double Ms_l = Ms_acc.at(idx_l); if (Ms_l != 0.0) sum += ((M_acc.get(idx_l) / Ms_l) - M_i) * wx; } if (x < dim_x-1) { const double Ms_r = Ms_acc.at(idx_r); if (Ms_r != 0.0) sum += ((M_acc.get(idx_r) / Ms_r) - M_i) * wx; } // up / down (Y) if (y > 0) { const double Ms_u = Ms_acc.at(idx_u); if (Ms_u != 0.0) sum += ((M_acc.get(idx_u) / Ms_u) - M_i) * wy; } if (y < dim_y-1) { const double Ms_d = Ms_acc.at(idx_d); if (Ms_d != 0.0) sum += ((M_acc.get(idx_d) / Ms_d) - M_i) * wy; } // forward / backward (Z) if (z > 0) { const double Ms_f = Ms_acc.at(idx_f); if (Ms_f != 0.0) sum += ((M_acc.get(idx_f) / Ms_f) - M_i) * wz; } if (z < dim_z-1) { const double Ms_b = Ms_acc.at(idx_b); if (Ms_b != 0.0) sum += ((M_acc.get(idx_b) / Ms_b) - M_i) * wz; } // Exchange field at (x,y,z) const Vector3d H_i = (2/MU0) * A_acc.at(i) * sum / Ms; H_acc.set(i, H_i); // Exchange energy sum energy += dot(M_i, H_i); } } } energy *= -MU0/2.0 * delta_x * delta_y * delta_z; return energy; }