forked from lijiext/lammps
Implementation of SeqNei V1 (Real)
Still both Seq and SeqNei versions In SeqNei, loop on Neighb not working yet
This commit is contained in:
parent
bf5b3f96e9
commit
b934621651
|
@ -0,0 +1,951 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "atom_vec_spin.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "domain.h"
|
||||
#include "modify.h"
|
||||
#include "fix.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
AtomVecSpin::AtomVecSpin(LAMMPS *lmp) : AtomVec(lmp)
|
||||
{
|
||||
molecular = 0;
|
||||
mass_type = 1; //check why
|
||||
|
||||
//comm_x_only = 0;
|
||||
comm_x_only = 1;
|
||||
//comm_f_only = 1;
|
||||
comm_f_only = 0;
|
||||
size_forward = 7;
|
||||
size_reverse = 6;
|
||||
size_border = 11;
|
||||
size_velocity = 3;
|
||||
size_data_atom = 9; //to check later
|
||||
size_data_vel = 4;
|
||||
xcol_data = 4;
|
||||
|
||||
forceclearflag = 1;
|
||||
atom->mumag_flag = atom->sp_flag = 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
grow atom arrays
|
||||
n = 0 grows arrays by a chunk
|
||||
n > 0 allocates arrays to size n
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::grow(int n)
|
||||
{
|
||||
if (n == 0) grow_nmax();
|
||||
else nmax = n;
|
||||
atom->nmax = nmax;
|
||||
if (nmax < 0 || nmax > MAXSMALLINT)
|
||||
error->one(FLERR,"Per-processor system is too big");
|
||||
|
||||
tag = memory->grow(atom->tag,nmax,"atom:tag");
|
||||
type = memory->grow(atom->type,nmax,"atom:type");
|
||||
mask = memory->grow(atom->mask,nmax,"atom:mask");
|
||||
image = memory->grow(atom->image,nmax,"atom:image");
|
||||
x = memory->grow(atom->x,nmax,3,"atom:x");
|
||||
v = memory->grow(atom->v,nmax,3,"atom:v");
|
||||
f = memory->grow(atom->f,nmax*comm->nthreads,3,"atom:f");
|
||||
//Allocating mag. quantities
|
||||
mumag = memory->grow(atom->mumag,nmax,"atom:mumag");
|
||||
sp = memory->grow(atom->sp,nmax,4,"atom:sp");
|
||||
fm = memory->grow(atom->fm,nmax*comm->nthreads,3,"atom:fm");
|
||||
|
||||
if (atom->nextra_grow)
|
||||
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
|
||||
modify->fix[atom->extra_grow[iextra]]->grow_arrays(nmax);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
reset local array ptrs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::grow_reset()
|
||||
{
|
||||
tag = atom->tag; type = atom->type;
|
||||
mask = atom->mask; image = atom->image;
|
||||
x = atom->x; v = atom->v; f = atom->f;
|
||||
mumag = atom->mumag; sp = atom->sp; fm = atom->fm;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
copy atom I info to atom J
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::copy(int i, int j, int delflag)
|
||||
{
|
||||
tag[j] = tag[i];
|
||||
type[j] = type[i];
|
||||
mask[j] = mask[i];
|
||||
image[j] = image[i];
|
||||
x[j][0] = x[i][0];
|
||||
x[j][1] = x[i][1];
|
||||
x[j][2] = x[i][2];
|
||||
v[j][0] = v[i][0];
|
||||
v[j][1] = v[i][1];
|
||||
v[j][2] = v[i][2];
|
||||
|
||||
mumag[j] = mumag[i];
|
||||
sp[j][0] = sp[i][0];
|
||||
sp[j][1] = sp[i][1];
|
||||
sp[j][2] = sp[i][2];
|
||||
sp[j][3] = sp[i][3];
|
||||
|
||||
if (atom->nextra_grow)
|
||||
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
|
||||
modify->fix[atom->extra_grow[iextra]]->copy_arrays(i,j,delflag);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_comm(int n, int *list, double *buf,
|
||||
int pbc_flag, int *pbc)
|
||||
{
|
||||
int i,j,m;
|
||||
double dx,dy,dz;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flag == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
}
|
||||
} else {
|
||||
if (domain->triclinic == 0) {
|
||||
dx = pbc[0]*domain->xprd;
|
||||
dy = pbc[1]*domain->yprd;
|
||||
dz = pbc[2]*domain->zprd;
|
||||
} else {
|
||||
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
|
||||
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
|
||||
dz = pbc[2]*domain->zprd;
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + dx;
|
||||
buf[m++] = x[j][1] + dy;
|
||||
buf[m++] = x[j][2] + dz;
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_comm_vel(int n, int *list, double *buf,
|
||||
int pbc_flag, int *pbc)
|
||||
{
|
||||
int i,j,m;
|
||||
double dx,dy,dz,dvx,dvy,dvz;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flag == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
buf[m++] = v[j][0];
|
||||
buf[m++] = v[j][1];
|
||||
buf[m++] = v[j][2];
|
||||
}
|
||||
} else {
|
||||
if (domain->triclinic == 0) {
|
||||
dx = pbc[0]*domain->xprd;
|
||||
dy = pbc[1]*domain->yprd;
|
||||
dz = pbc[2]*domain->zprd;
|
||||
} else {
|
||||
dx = pbc[0]*domain->xprd + pbc[5]*domain->xy + pbc[4]*domain->xz;
|
||||
dy = pbc[1]*domain->yprd + pbc[3]*domain->yz;
|
||||
dz = pbc[2]*domain->zprd;
|
||||
}
|
||||
if (!deform_vremap) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + dx;
|
||||
buf[m++] = x[j][1] + dy;
|
||||
buf[m++] = x[j][2] + dz;
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
buf[m++] = v[j][0];
|
||||
buf[m++] = v[j][1];
|
||||
buf[m++] = v[j][2];
|
||||
}
|
||||
} else {
|
||||
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
|
||||
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
|
||||
dvz = pbc[2]*h_rate[2];
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + dx;
|
||||
buf[m++] = x[j][1] + dy;
|
||||
buf[m++] = x[j][2] + dz;
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
if (mask[i] & deform_groupbit) {
|
||||
buf[m++] = v[j][0] + dvx;
|
||||
buf[m++] = v[j][1] + dvy;
|
||||
buf[m++] = v[j][2] + dvz;
|
||||
} else {
|
||||
buf[m++] = v[j][0];
|
||||
buf[m++] = v[j][1];
|
||||
buf[m++] = v[j][2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_comm_hybrid(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::unpack_comm(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
sp[i][0] = buf[m++];
|
||||
sp[i][1] = buf[m++];
|
||||
sp[i][2] = buf[m++];
|
||||
sp[i][3] = buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::unpack_comm_vel(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
sp[i][0] = buf[m++];
|
||||
sp[i][1] = buf[m++];
|
||||
sp[i][2] = buf[m++];
|
||||
sp[i][3] = buf[m++];
|
||||
v[i][0] = buf[m++];
|
||||
v[i][1] = buf[m++];
|
||||
v[i][2] = buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::unpack_comm_hybrid(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
sp[i][0] = buf[m++];
|
||||
sp[i][1] = buf[m++];
|
||||
sp[i][2] = buf[m++];
|
||||
sp[i][3] = buf[m++];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_reverse(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
buf[m++] = f[i][0];
|
||||
buf[m++] = f[i][1];
|
||||
buf[m++] = f[i][2];
|
||||
buf[m++] = fm[i][0];
|
||||
buf[m++] = fm[i][1];
|
||||
buf[m++] = fm[i][2];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::unpack_reverse(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
f[j][0] += buf[m++];
|
||||
f[j][1] += buf[m++];
|
||||
f[j][2] += buf[m++];
|
||||
fm[j][0] += buf[m++];
|
||||
fm[j][1] += buf[m++];
|
||||
fm[j][2] += buf[m++];
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_border(int n, int *list, double *buf,
|
||||
int pbc_flag, int *pbc)
|
||||
{
|
||||
int i,j,m;
|
||||
double dx,dy,dz;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flag == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
buf[m++] = ubuf(tag[j]).d;
|
||||
buf[m++] = ubuf(type[j]).d;
|
||||
buf[m++] = ubuf(mask[j]).d;
|
||||
buf[m++] = mumag[j];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
}
|
||||
} else {
|
||||
if (domain->triclinic == 0) {
|
||||
dx = pbc[0]*domain->xprd;
|
||||
dy = pbc[1]*domain->yprd;
|
||||
dz = pbc[2]*domain->zprd;
|
||||
} else {
|
||||
dx = pbc[0];
|
||||
dy = pbc[1];
|
||||
dz = pbc[2];
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + dx;
|
||||
buf[m++] = x[j][1] + dy;
|
||||
buf[m++] = x[j][2] + dz;
|
||||
buf[m++] = ubuf(tag[j]).d;
|
||||
buf[m++] = ubuf(type[j]).d;
|
||||
buf[m++] = ubuf(mask[j]).d;
|
||||
buf[m++] = mumag[j];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
}
|
||||
}
|
||||
|
||||
if (atom->nextra_border)
|
||||
for (int iextra = 0; iextra < atom->nextra_border; iextra++)
|
||||
m += modify->fix[atom->extra_border[iextra]]->pack_border(n,list,&buf[m]);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_border_vel(int n, int *list, double *buf,
|
||||
int pbc_flag, int *pbc)
|
||||
{
|
||||
int i,j,m;
|
||||
double dx,dy,dz,dvx,dvy,dvz;
|
||||
|
||||
m = 0;
|
||||
if (pbc_flag == 0) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0];
|
||||
buf[m++] = x[j][1];
|
||||
buf[m++] = x[j][2];
|
||||
buf[m++] = ubuf(tag[j]).d;
|
||||
buf[m++] = ubuf(type[j]).d;
|
||||
buf[m++] = ubuf(mask[j]).d;
|
||||
buf[m++] = mumag[j];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
buf[m++] = v[j][0];
|
||||
buf[m++] = v[j][1];
|
||||
buf[m++] = v[j][2];
|
||||
}
|
||||
} else {
|
||||
if (domain->triclinic == 0) {
|
||||
dx = pbc[0]*domain->xprd;
|
||||
dy = pbc[1]*domain->yprd;
|
||||
dz = pbc[2]*domain->zprd;
|
||||
} else {
|
||||
dx = pbc[0];
|
||||
dy = pbc[1];
|
||||
dz = pbc[2];
|
||||
}
|
||||
if (!deform_vremap) {
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + dx;
|
||||
buf[m++] = x[j][1] + dy;
|
||||
buf[m++] = x[j][2] + dz;
|
||||
buf[m++] = ubuf(tag[j]).d;
|
||||
buf[m++] = ubuf(type[j]).d;
|
||||
buf[m++] = ubuf(mask[j]).d;
|
||||
buf[m++] = mumag[j];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
buf[m++] = v[j][0];
|
||||
buf[m++] = v[j][1];
|
||||
buf[m++] = v[j][2];
|
||||
}
|
||||
} else {
|
||||
dvx = pbc[0]*h_rate[0] + pbc[5]*h_rate[5] + pbc[4]*h_rate[4];
|
||||
dvy = pbc[1]*h_rate[1] + pbc[3]*h_rate[3];
|
||||
dvz = pbc[2]*h_rate[2];
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = x[j][0] + dx;
|
||||
buf[m++] = x[j][1] + dy;
|
||||
buf[m++] = x[j][2] + dz;
|
||||
buf[m++] = ubuf(tag[j]).d;
|
||||
buf[m++] = ubuf(type[j]).d;
|
||||
buf[m++] = ubuf(mask[j]).d;
|
||||
buf[m++] = mumag[j];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
if (mask[i] & deform_groupbit) {
|
||||
buf[m++] = v[j][0] + dvx;
|
||||
buf[m++] = v[j][1] + dvy;
|
||||
buf[m++] = v[j][2] + dvz;
|
||||
} else {
|
||||
buf[m++] = v[j][0];
|
||||
buf[m++] = v[j][1];
|
||||
buf[m++] = v[j][2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (atom->nextra_border)
|
||||
for (int iextra = 0; iextra < atom->nextra_border; iextra++)
|
||||
m += modify->fix[atom->extra_border[iextra]]->pack_border(n,list,&buf[m]);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_border_hybrid(int n, int *list, double *buf)
|
||||
{
|
||||
int i,j,m;
|
||||
|
||||
m = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
j = list[i];
|
||||
buf[m++] = mumag[j];
|
||||
buf[m++] = sp[j][0];
|
||||
buf[m++] = sp[j][1];
|
||||
buf[m++] = sp[j][2];
|
||||
buf[m++] = sp[j][3];
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::unpack_border(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
if (i == nmax) grow(0);
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
tag[i] = (tagint) ubuf(buf[m++]).i;
|
||||
type[i] = (int) ubuf(buf[m++]).i;
|
||||
mask[i] = (int) ubuf(buf[m++]).i;
|
||||
mumag[i] = buf[m++];
|
||||
sp[i][0] = buf[m++];
|
||||
sp[i][1] = buf[m++];
|
||||
sp[i][2] = buf[m++];
|
||||
sp[i][3] = buf[m++];
|
||||
}
|
||||
|
||||
if (atom->nextra_border)
|
||||
for (int iextra = 0; iextra < atom->nextra_border; iextra++)
|
||||
m += modify->fix[atom->extra_border[iextra]]->
|
||||
unpack_border(n,first,&buf[m]);
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::unpack_border_vel(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
if (i == nmax) grow(0);
|
||||
x[i][0] = buf[m++];
|
||||
x[i][1] = buf[m++];
|
||||
x[i][2] = buf[m++];
|
||||
tag[i] = (tagint) ubuf(buf[m++]).i;
|
||||
type[i] = (int) ubuf(buf[m++]).i;
|
||||
mask[i] = (int) ubuf(buf[m++]).i;
|
||||
mumag[i] = buf[m++];
|
||||
sp[i][0] = buf[m++];
|
||||
sp[i][1] = buf[m++];
|
||||
sp[i][2] = buf[m++];
|
||||
sp[i][3] = buf[m++];
|
||||
v[i][0] = buf[m++];
|
||||
v[i][1] = buf[m++];
|
||||
v[i][2] = buf[m++];
|
||||
}
|
||||
|
||||
if (atom->nextra_border)
|
||||
for (int iextra = 0; iextra < atom->nextra_border; iextra++)
|
||||
m += modify->fix[atom->extra_border[iextra]]->
|
||||
unpack_border(n,first,&buf[m]);
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::unpack_border_hybrid(int n, int first, double *buf)
|
||||
{
|
||||
int i,m,last;
|
||||
|
||||
m = 0;
|
||||
last = first + n;
|
||||
for (i = first; i < last; i++) {
|
||||
mumag[i] = buf[m++];
|
||||
sp[i][0] = buf[m++];
|
||||
sp[i][1] = buf[m++];
|
||||
sp[i][2] = buf[m++];
|
||||
sp[i][3] = buf[m++];
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack all atom quantities for shipping to another proc
|
||||
xyz must be 1st 3 values, so that comm::exchange can test on them
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_exchange(int i, double *buf)
|
||||
{
|
||||
int m = 1;
|
||||
buf[m++] = x[i][0];
|
||||
buf[m++] = x[i][1];
|
||||
buf[m++] = x[i][2];
|
||||
buf[m++] = v[i][0];
|
||||
buf[m++] = v[i][1];
|
||||
buf[m++] = v[i][2];
|
||||
buf[m++] = ubuf(tag[i]).d;
|
||||
buf[m++] = ubuf(type[i]).d;
|
||||
buf[m++] = ubuf(mask[i]).d;
|
||||
buf[m++] = ubuf(image[i]).d;
|
||||
|
||||
buf[m++] = mumag[i];
|
||||
buf[m++] = sp[i][0];
|
||||
buf[m++] = sp[i][1];
|
||||
buf[m++] = sp[i][2];
|
||||
buf[m++] = sp[i][3];
|
||||
|
||||
if (atom->nextra_grow)
|
||||
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
|
||||
m += modify->fix[atom->extra_grow[iextra]]->pack_exchange(i,&buf[m]);
|
||||
|
||||
buf[0] = m;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::unpack_exchange(double *buf)
|
||||
{
|
||||
int nlocal = atom->nlocal;
|
||||
if (nlocal == nmax) grow(0);
|
||||
|
||||
int m = 1;
|
||||
x[nlocal][0] = buf[m++];
|
||||
x[nlocal][1] = buf[m++];
|
||||
x[nlocal][2] = buf[m++];
|
||||
v[nlocal][0] = buf[m++];
|
||||
v[nlocal][1] = buf[m++];
|
||||
v[nlocal][2] = buf[m++];
|
||||
tag[nlocal] = (tagint) ubuf(buf[m++]).i;
|
||||
type[nlocal] = (int) ubuf(buf[m++]).i;
|
||||
mask[nlocal] = (int) ubuf(buf[m++]).i;
|
||||
image[nlocal] = (imageint) ubuf(buf[m++]).i;
|
||||
|
||||
mumag[nlocal] = buf[m++];
|
||||
sp[nlocal][0] = buf[m++];
|
||||
sp[nlocal][1] = buf[m++];
|
||||
sp[nlocal][2] = buf[m++];
|
||||
sp[nlocal][3] = buf[m++];
|
||||
|
||||
if (atom->nextra_grow)
|
||||
for (int iextra = 0; iextra < atom->nextra_grow; iextra++)
|
||||
m += modify->fix[atom->extra_grow[iextra]]->
|
||||
unpack_exchange(nlocal,&buf[m]);
|
||||
|
||||
atom->nlocal++;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
size of restart data for all atoms owned by this proc
|
||||
include extra data stored by fixes
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::size_restart()
|
||||
{
|
||||
int i;
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
int n = 16 * nlocal;
|
||||
|
||||
if (atom->nextra_restart)
|
||||
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
|
||||
for (i = 0; i < nlocal; i++)
|
||||
n += modify->fix[atom->extra_restart[iextra]]->size_restart(i);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack atom I's data for restart file including extra quantities
|
||||
xyz must be 1st 3 values, so that read_restart can test on them
|
||||
molecular types may be negative, but write as positive
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_restart(int i, double *buf)
|
||||
{
|
||||
int m = 1;
|
||||
|
||||
buf[m++] = x[i][0];
|
||||
buf[m++] = x[i][1];
|
||||
buf[m++] = x[i][2];
|
||||
buf[m++] = ubuf(tag[i]).d;
|
||||
buf[m++] = ubuf(type[i]).d;
|
||||
buf[m++] = ubuf(mask[i]).d;
|
||||
buf[m++] = ubuf(image[i]).d;
|
||||
buf[m++] = v[i][0];
|
||||
buf[m++] = v[i][1];
|
||||
buf[m++] = v[i][2];
|
||||
|
||||
buf[m++] = mumag[i];
|
||||
buf[m++] = sp[i][0];
|
||||
buf[m++] = sp[i][1];
|
||||
buf[m++] = sp[i][2];
|
||||
buf[m++] = sp[i][3];
|
||||
|
||||
if (atom->nextra_restart)
|
||||
for (int iextra = 0; iextra < atom->nextra_restart; iextra++)
|
||||
m += modify->fix[atom->extra_restart[iextra]]->pack_restart(i,&buf[m]);
|
||||
|
||||
buf[0] = m;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
unpack data for one atom from restart file including extra quantities
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::unpack_restart(double *buf)
|
||||
{
|
||||
int nlocal = atom->nlocal;
|
||||
if (nlocal == nmax) {
|
||||
grow(0);
|
||||
if (atom->nextra_store)
|
||||
memory->grow(atom->extra,nmax,atom->nextra_store,"atom:extra");
|
||||
}
|
||||
|
||||
int m = 1;
|
||||
x[nlocal][0] = buf[m++];
|
||||
x[nlocal][1] = buf[m++];
|
||||
x[nlocal][2] = buf[m++];
|
||||
tag[nlocal] = (tagint) ubuf(buf[m++]).i;
|
||||
type[nlocal] = (int) ubuf(buf[m++]).i;
|
||||
mask[nlocal] = (int) ubuf(buf[m++]).i;
|
||||
image[nlocal] = (imageint) ubuf(buf[m++]).i;
|
||||
v[nlocal][0] = buf[m++];
|
||||
v[nlocal][1] = buf[m++];
|
||||
v[nlocal][2] = buf[m++];
|
||||
|
||||
mumag[nlocal] = buf[m++];
|
||||
sp[nlocal][0] = buf[m++];
|
||||
sp[nlocal][1] = buf[m++];
|
||||
sp[nlocal][2] = buf[m++];
|
||||
sp[nlocal][3] = buf[m++];
|
||||
|
||||
double **extra = atom->extra;
|
||||
if (atom->nextra_store) {
|
||||
int size = static_cast<int> (buf[0]) - m;
|
||||
for (int i = 0; i < size; i++) extra[nlocal][i] = buf[m++];
|
||||
}
|
||||
|
||||
atom->nlocal++;
|
||||
return m;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
create one atom of itype at coord
|
||||
set other values to defaults
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::create_atom(int itype, double *coord)
|
||||
{
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
if (nlocal == nmax) grow(0);
|
||||
|
||||
tag[nlocal] = 0;
|
||||
type[nlocal] = itype;
|
||||
x[nlocal][0] = coord[0];
|
||||
x[nlocal][1] = coord[1];
|
||||
x[nlocal][2] = coord[2];
|
||||
mask[nlocal] = 1;
|
||||
image[nlocal] = ((imageint) IMGMAX << IMG2BITS) |
|
||||
((imageint) IMGMAX << IMGBITS) | IMGMAX;
|
||||
v[nlocal][0] = 0.0;
|
||||
v[nlocal][1] = 0.0;
|
||||
v[nlocal][2] = 0.0;
|
||||
|
||||
mumag[nlocal] = 0.0;
|
||||
sp[nlocal][0] = 0.0;
|
||||
sp[nlocal][1] = 0.0;
|
||||
sp[nlocal][2] = 0.0;
|
||||
sp[nlocal][3] = 0.0;
|
||||
|
||||
atom->nlocal++;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
unpack one line from Atoms section of data file
|
||||
initialize other atom quantities
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::data_atom(double *coord, imageint imagetmp, char **values)
|
||||
{
|
||||
int nlocal = atom->nlocal;
|
||||
if (nlocal == nmax) grow(0);
|
||||
|
||||
tag[nlocal] = ATOTAGINT(values[0]);
|
||||
type[nlocal] = atoi(values[1]);
|
||||
if (type[nlocal] <= 0 || type[nlocal] > atom->ntypes)
|
||||
error->one(FLERR,"Invalid atom type in Atoms section of data file");
|
||||
|
||||
mumag[nlocal] = atof(values[2]);
|
||||
|
||||
x[nlocal][0] = coord[0];
|
||||
x[nlocal][1] = coord[1];
|
||||
x[nlocal][2] = coord[2];
|
||||
|
||||
sp[nlocal][0] = atof(values[6]);
|
||||
sp[nlocal][1] = atof(values[7]);
|
||||
sp[nlocal][2] = atof(values[8]);
|
||||
sp[nlocal][3] = sqrt(sp[nlocal][0]*sp[nlocal][0] +
|
||||
sp[nlocal][1]*sp[nlocal][1] +
|
||||
sp[nlocal][2]*sp[nlocal][2]);
|
||||
|
||||
image[nlocal] = imagetmp;
|
||||
|
||||
mask[nlocal] = 1;
|
||||
v[nlocal][0] = 0.0;
|
||||
v[nlocal][1] = 0.0;
|
||||
v[nlocal][2] = 0.0;
|
||||
|
||||
atom->nlocal++;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
unpack hybrid quantities from one line in Atoms section of data file
|
||||
initialize other atom quantities for this sub-style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::data_atom_hybrid(int nlocal, char **values)
|
||||
{
|
||||
mumag[nlocal] = atof(values[0]);
|
||||
sp[nlocal][0] = atof(values[1]);
|
||||
sp[nlocal][1] = atof(values[2]);
|
||||
sp[nlocal][2] = atof(values[3]);
|
||||
sp[nlocal][3] = sqrt(sp[nlocal][0]*sp[nlocal][0] +
|
||||
sp[nlocal][1]*sp[nlocal][1] +
|
||||
sp[nlocal][2]*sp[nlocal][2]);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack atom info for data file including 3 image flags
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::pack_data(double **buf)
|
||||
{
|
||||
int nlocal = atom->nlocal;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
buf[i][0] = ubuf(tag[i]).d;
|
||||
buf[i][1] = ubuf(type[i]).d;
|
||||
buf[i][2] = mumag[i];
|
||||
buf[i][3] = x[i][0];
|
||||
buf[i][4] = x[i][1];
|
||||
buf[i][5] = x[i][2];
|
||||
buf[i][6] = sp[i][0];
|
||||
buf[i][7] = sp[i][1];
|
||||
buf[i][8] = sp[i][2];
|
||||
buf[i][9] = sp[i][3];
|
||||
buf[i][10] = ubuf((image[i] & IMGMASK) - IMGMAX).d;
|
||||
buf[i][11] = ubuf((image[i] >> IMGBITS & IMGMASK) - IMGMAX).d;
|
||||
buf[i][12] = ubuf((image[i] >> IMG2BITS) - IMGMAX).d;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
pack hybrid atom info for data file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::pack_data_hybrid(int i, double *buf)
|
||||
{
|
||||
buf[0] = mumag[i];
|
||||
buf[1] = sp[i][0];
|
||||
buf[2] = sp[i][1];
|
||||
buf[3] = sp[i][2];
|
||||
buf[4] = sp[i][3];
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
write atom info to data file including 3 image flags
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void AtomVecSpin::write_data(FILE *fp, int n, double **buf)
|
||||
{
|
||||
for (int i = 0; i < n; i++)
|
||||
fprintf(fp,TAGINT_FORMAT \
|
||||
" %d %-1.16e %-1.16e %-1.16e %-1.16e %-1.16e %-1.16e "
|
||||
"%-1.16e %d %d %d\n",
|
||||
(tagint) ubuf(buf[i][0]).i,(int) ubuf(buf[i][1]).i,
|
||||
buf[i][2],buf[i][3],buf[i][4],
|
||||
buf[i][5],buf[i][6],buf[i][7],buf[i][8],buf[i][9],
|
||||
(int) ubuf(buf[i][10]).i,(int) ubuf(buf[i][11]).i,
|
||||
(int) ubuf(buf[i][12]).i);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
write hybrid atom info to data file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int AtomVecSpin::write_data_hybrid(FILE *fp, double *buf)
|
||||
{
|
||||
fprintf(fp," %-1.16e %-1.16e %-1.16e %-1.16e %-1.16e",buf[0],buf[1],buf[2],buf[3],buf[4]);
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return # of bytes of allocated memory
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
bigint AtomVecSpin::memory_usage()
|
||||
{
|
||||
bigint bytes = 0;
|
||||
|
||||
if (atom->memcheck("tag")) bytes += memory->usage(tag,nmax);
|
||||
if (atom->memcheck("type")) bytes += memory->usage(type,nmax);
|
||||
if (atom->memcheck("mask")) bytes += memory->usage(mask,nmax);
|
||||
if (atom->memcheck("image")) bytes += memory->usage(image,nmax);
|
||||
if (atom->memcheck("x")) bytes += memory->usage(x,nmax,3);
|
||||
if (atom->memcheck("v")) bytes += memory->usage(v,nmax,3);
|
||||
if (atom->memcheck("f")) bytes += memory->usage(f,nmax*comm->nthreads,3);
|
||||
|
||||
if (atom->memcheck("fm")) bytes += memory->usage(fm,nmax*comm->nthreads,3);
|
||||
if (atom->memcheck("mumag")) bytes += memory->usage(mumag,nmax);
|
||||
if (atom->memcheck("sp")) bytes += memory->usage(sp,nmax,4);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void AtomVecSpin::force_clear(int n, size_t nbytes)
|
||||
{
|
||||
memset(&atom->f[0][0],0,3*nbytes);
|
||||
memset(&atom->fm[0][0],0,3*nbytes);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef ATOM_CLASS
|
||||
|
||||
AtomStyle(spin,AtomVecSpin)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_ATOM_VEC_SPIN_H
|
||||
#define LMP_ATOM_VEC_SPIN_H
|
||||
|
||||
#include "atom_vec.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class AtomVecSpin : public AtomVec {
|
||||
public:
|
||||
AtomVecSpin(class LAMMPS *);
|
||||
void grow(int);
|
||||
void grow_reset();
|
||||
void copy(int, int, int);
|
||||
int pack_comm(int, int *, double *, int, int *);
|
||||
int pack_comm_vel(int, int *, double *, int, int *);
|
||||
int pack_comm_hybrid(int, int *, double *);
|
||||
void unpack_comm(int, int, double *);
|
||||
void unpack_comm_vel(int, int, double *);
|
||||
int unpack_comm_hybrid(int, int, double *);
|
||||
int pack_reverse(int, int, double *);
|
||||
void unpack_reverse(int, int *, double *);
|
||||
int pack_border(int, int *, double *, int, int *);
|
||||
int pack_border_vel(int, int *, double *, int, int *);
|
||||
int pack_border_hybrid(int, int *, double *);
|
||||
void unpack_border(int, int, double *);
|
||||
void unpack_border_vel(int, int, double *);
|
||||
int unpack_border_hybrid(int, int, double *);
|
||||
int pack_exchange(int, double *);
|
||||
int unpack_exchange(double *);
|
||||
int size_restart();
|
||||
int pack_restart(int, double *);
|
||||
int unpack_restart(double *);
|
||||
void create_atom(int, double *);
|
||||
void data_atom(double *, imageint, char **);
|
||||
int data_atom_hybrid(int, char **);
|
||||
void pack_data(double **);
|
||||
int pack_data_hybrid(int, double *);
|
||||
void write_data(FILE *, int, double **);
|
||||
int write_data_hybrid(FILE *, double *);
|
||||
bigint memory_usage();
|
||||
|
||||
//Test force clear
|
||||
void force_clear(int, size_t);
|
||||
|
||||
|
||||
private:
|
||||
tagint *tag;
|
||||
int *type,*mask;
|
||||
imageint *image;
|
||||
double **x,**v,**f; //MD quantities: position, velocity and force
|
||||
double *mumag,**sp, **fm; //Magnetic quantities: mu, spin direction, magnetic force
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Per-processor system is too big
|
||||
|
||||
The number of owned atoms plus ghost atoms on a single
|
||||
processor must fit in 32-bit integer.
|
||||
|
||||
E: Invalid atom type in Atoms section of data file
|
||||
|
||||
Atom types must range from 1 to specified # of types.
|
||||
|
||||
*/
|
|
@ -0,0 +1,145 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <string.h>
|
||||
#include "compute_spin.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
#include "modify.h"
|
||||
#include "domain.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
#include "math_special.h"
|
||||
#include "math_const.h"
|
||||
#include "force.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathSpecial;
|
||||
using namespace MathConst;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeSpin::ComputeSpin(LAMMPS *lmp, int narg, char **arg) :
|
||||
Compute(lmp, narg, arg), mag(NULL)
|
||||
{
|
||||
if ((narg != 3) && (narg != 4)) error->all(FLERR,"Illegal compute compute/spin command");
|
||||
|
||||
vector_flag = 1;
|
||||
size_vector = 7;
|
||||
extvector = 0;
|
||||
|
||||
init();
|
||||
|
||||
allocate();
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeSpin::~ComputeSpin()
|
||||
{
|
||||
memory->destroy(mag);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeSpin::init()
|
||||
{
|
||||
hbar = force->hplanck/MY_2PI;
|
||||
kb = force->boltz;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeSpin::compute_vector()
|
||||
{
|
||||
int i, index;
|
||||
|
||||
invoked_vector = update->ntimestep;
|
||||
|
||||
countsp = countsptot = 0.0;
|
||||
mag[0] = mag[1] = mag[2] = mag[3] = 0.0;
|
||||
magtot[0] = magtot[1] = magtot[2] = magtot[3] = 0.0;
|
||||
magenergy = magenergytot = 0.0;
|
||||
tempnum = tempnumtot = 0.0;
|
||||
tempdenom = tempdenomtot = 0.0;
|
||||
spintemperature = 0.0;
|
||||
|
||||
double **x = atom->x;
|
||||
int *mask = atom->mask;
|
||||
int *type = atom->type;
|
||||
imageint *image = atom->image;
|
||||
double *mumag = atom->mumag;
|
||||
double **sp = atom->sp;
|
||||
double **fm = atom->fm;
|
||||
double tx,ty,tz;
|
||||
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
// compute total magnetization and magnetic energy
|
||||
// compute spin temperature; See Nurdin et al., Phys. Rev. E 61, 2000
|
||||
for (i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) {
|
||||
if (atom->mumag_flag && atom->sp_flag) {
|
||||
mag[0] += sp[i][0];
|
||||
mag[1] += sp[i][1];
|
||||
mag[2] += sp[i][2];
|
||||
magenergy += mumag[i]*sp[i][0]*fm[i][0];
|
||||
magenergy += mumag[i]*sp[i][1]*fm[i][1];
|
||||
magenergy += mumag[i]*sp[i][2]*fm[i][2];
|
||||
tx = sp[i][1]*fm[i][2]-sp[i][2]*fm[i][1];
|
||||
ty = sp[i][2]*fm[i][0]-sp[i][0]*fm[i][2];
|
||||
tz = sp[i][0]*fm[i][1]-sp[i][1]*fm[i][0];
|
||||
tempnum += tx*tx+ty*ty+tz*tz;
|
||||
tempdenom += sp[i][0]*sp[i][0]+sp[i][1]*sp[i][1]+sp[i][2]*sp[i][2];
|
||||
countsp++;
|
||||
}
|
||||
}
|
||||
else error->all(FLERR,"Compute spin/compute declared magnetic quantities (sp and mumag flags)");
|
||||
}
|
||||
|
||||
MPI_Allreduce(mag,magtot,4,MPI_DOUBLE,MPI_SUM,world);
|
||||
MPI_Allreduce(&magenergy,&magenergytot,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
MPI_Allreduce(&tempnum,&tempnumtot,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
MPI_Allreduce(&tempdenom,&tempdenomtot,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
MPI_Allreduce(&countsp,&countsptot,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
|
||||
double scale = 1.0/countsptot;
|
||||
magtot[0] *= scale;
|
||||
magtot[1] *= scale;
|
||||
magtot[2] *= scale;
|
||||
magtot[3] = sqrt(square(magtot[0])+square(magtot[1])+square(magtot[2]));
|
||||
spintemperature = hbar*tempnumtot/2.0/kb/tempdenomtot;
|
||||
|
||||
vector[0] = invoked_vector*update->dt;
|
||||
vector[1] = magtot[0];
|
||||
vector[2] = magtot[1];
|
||||
vector[3] = magtot[2];
|
||||
vector[4] = magtot[3];
|
||||
vector[5] = -0.5*magenergytot*hbar;
|
||||
vector[6] = spintemperature;
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
free and reallocate arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ComputeSpin::allocate()
|
||||
{
|
||||
memory->destroy(mag);
|
||||
memory->create(mag,4,"compute/spin:mag");
|
||||
memory->create(magtot,5,"compute/spin:mag");
|
||||
memory->create(vector,7,"compute/spin:vector");
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef COMPUTE_CLASS
|
||||
|
||||
ComputeStyle(compute/spin,ComputeSpin)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_COMPUTE_SPIN_H
|
||||
#define LMP_COMPUTE_SPIN_H
|
||||
|
||||
#include "compute.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ComputeSpin : public Compute {
|
||||
public:
|
||||
ComputeSpin(class LAMMPS *, int, char **);
|
||||
~ComputeSpin();
|
||||
void init();
|
||||
void compute_vector();
|
||||
|
||||
private:
|
||||
double *mag;
|
||||
double *magtot;
|
||||
double magenergy;
|
||||
double magenergytot;
|
||||
double tempnum,tempnumtot;
|
||||
double tempdenom,tempdenomtot;
|
||||
double spintemperature;
|
||||
double kb,hbar;
|
||||
int countsp;
|
||||
int countsptot;
|
||||
int usecenter;
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
E: Chunk/atom compute does not exist for compute compute/spin
|
||||
|
||||
Self-explanatory.
|
||||
|
||||
E: Compute compute/spin does not use chunk/atom compute
|
||||
|
||||
The style of the specified compute is not chunk/atom.
|
||||
|
||||
*/
|
|
@ -0,0 +1,255 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "fix_force_spin.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
#include "domain.h"
|
||||
#include "respa.h"
|
||||
#include "modify.h"
|
||||
#include "input.h"
|
||||
#include "variable.h"
|
||||
#include "math_const.h"
|
||||
#include "error.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
using namespace MathConst;
|
||||
|
||||
enum{ZEEMAN,ANISOTROPY};
|
||||
enum{CONSTANT,EQUAL};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixForceSpin::FixForceSpin(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg)
|
||||
{
|
||||
|
||||
if (narg < 7) error->all(FLERR,"Illegal fix spin command");
|
||||
// 7 arguments for a force/spin fix command:
|
||||
//(fix ID group force/spin magnitude (T or eV) style (zeeman or anisotropy) direction (3 cartesian coordinates)
|
||||
|
||||
//Magnetic interactions only coded for cartesian coordinates
|
||||
|
||||
dynamic_group_allow = 1;
|
||||
scalar_flag = 1;
|
||||
global_freq = 1;
|
||||
extscalar = 1;
|
||||
respa_level_support = 1;
|
||||
ilevel_respa = 0;
|
||||
|
||||
magstr = NULL;
|
||||
magfieldstyle = CONSTANT;
|
||||
|
||||
H_field = 0.0;
|
||||
Hx = Hy = Hz = 0.0;
|
||||
Ka = 0.0;
|
||||
Kax = Kay = Kaz = 0.0;
|
||||
|
||||
zeeman_flag = aniso_flag = 0;
|
||||
|
||||
if (strcmp(arg[3],"zeeman") == 0) {
|
||||
if (narg != 8) error->all(FLERR,"Illegal fix zeeman command");
|
||||
style = ZEEMAN;
|
||||
zeeman_flag = 1;
|
||||
H_field = force->numeric(FLERR,arg[4]);
|
||||
Hx = force->numeric(FLERR,arg[5]);
|
||||
Hy = force->numeric(FLERR,arg[6]);
|
||||
Hz = force->numeric(FLERR,arg[7]);
|
||||
magfieldstyle = CONSTANT;
|
||||
} else if (strcmp(arg[3],"anisotropy") == 0) {
|
||||
if (narg != 8) error->all(FLERR,"Illegal fix anisotropy command");
|
||||
style = ANISOTROPY;
|
||||
aniso_flag = 1;
|
||||
Ka = force->numeric(FLERR,arg[4]);
|
||||
Kax = force->numeric(FLERR,arg[5]);
|
||||
Kay = force->numeric(FLERR,arg[6]);
|
||||
Kaz = force->numeric(FLERR,arg[7]);
|
||||
} else error->all(FLERR,"Illegal fix force/spin command");
|
||||
|
||||
degree2rad = MY_PI/180.0;
|
||||
time_origin = update->ntimestep;
|
||||
|
||||
eflag = 0;
|
||||
emag = 0.0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixForceSpin::~FixForceSpin()
|
||||
{
|
||||
memory->destroy(spi);
|
||||
memory->destroy(fmi);
|
||||
delete [] magstr;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int FixForceSpin::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= POST_FORCE;
|
||||
mask |= THERMO_ENERGY;
|
||||
mask |= POST_FORCE_RESPA;
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixForceSpin::init()
|
||||
{
|
||||
double hbar = force->hplanck/MY_2PI; //eV/(rad.THz)
|
||||
double mub = 5.78901e-5; //in eV/T
|
||||
double gyro = mub/hbar; //in rad.THz/T
|
||||
|
||||
H_field *= gyro; //in rad.THz
|
||||
Ka /= hbar; //in rad.THz
|
||||
|
||||
if (strstr(update->integrate_style,"respa")) {
|
||||
ilevel_respa = ((Respa *) update->integrate)->nlevels-1;
|
||||
if (respa_level >= 0) ilevel_respa = MIN(respa_level,ilevel_respa);
|
||||
}
|
||||
|
||||
// check variables
|
||||
if (magstr) {
|
||||
magvar = input->variable->find(magstr);
|
||||
if (magvar < 0)
|
||||
error->all(FLERR,"Variable name for fix magnetic field does not exist");
|
||||
if (!input->variable->equalstyle(magvar))
|
||||
error->all(FLERR,"Variable for fix magnetic field is invalid style");
|
||||
}
|
||||
|
||||
varflag = CONSTANT;
|
||||
if (magfieldstyle != CONSTANT) varflag = EQUAL;
|
||||
|
||||
// set magnetic field components once and for all
|
||||
if (varflag == CONSTANT) set_magneticforce();
|
||||
|
||||
memory->create(spi,3,"forcespin:spi");
|
||||
memory->create(fmi,3,"forcespin:fmi");
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixForceSpin::setup(int vflag)
|
||||
{
|
||||
if (strstr(update->integrate_style,"verlet"))
|
||||
post_force(vflag);
|
||||
else {
|
||||
((Respa *) update->integrate)->copy_flevel_f(ilevel_respa);
|
||||
post_force_respa(vflag,ilevel_respa,0);
|
||||
((Respa *) update->integrate)->copy_f_flevel(ilevel_respa);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixForceSpin::post_force(int vflag)
|
||||
{
|
||||
// update gravity due to variables
|
||||
if (varflag != CONSTANT) {
|
||||
modify->clearstep_compute();
|
||||
modify->addstep_compute(update->ntimestep + 1);
|
||||
set_magneticforce(); //Update value of the mag. field if time-dependent
|
||||
}
|
||||
|
||||
// double **x = atom->x;
|
||||
double **sp = atom->sp;
|
||||
double *mumag = atom->mumag;
|
||||
double **fm = atom->fm;
|
||||
int nlocal = atom->nlocal;
|
||||
double scalar;
|
||||
|
||||
eflag = 0;
|
||||
emag = 0.0;
|
||||
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
fmi[0] = fmi[1] = fmi[2] = 0.0;
|
||||
//if (style == ZEEMAN) {
|
||||
if (zeeman_flag) {
|
||||
compute_zeeman(i,fmi);
|
||||
}
|
||||
//if (style == ANISOTROPY) {
|
||||
if (aniso_flag) {
|
||||
spi[0] = sp[i][0];
|
||||
spi[1] = sp[i][1];
|
||||
spi[2] = sp[i][2];
|
||||
compute_anisotropy(i,spi,fmi);
|
||||
}
|
||||
fm[i][0] += fmi[0];
|
||||
fm[i][1] += fmi[1];
|
||||
fm[i][2] += fmi[2];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void FixForceSpin::compute_zeeman(int i, double *fmi)
|
||||
{
|
||||
double *mumag = atom->mumag;
|
||||
fmi[0] += mumag[i]*xmag;
|
||||
fmi[1] += mumag[i]*ymag;
|
||||
fmi[2] += mumag[i]*zmag;
|
||||
}
|
||||
|
||||
void FixForceSpin::compute_anisotropy(int i, double * spi, double *fmi)
|
||||
{
|
||||
double scalar = Kax*spi[0] + Kay*spi[1] + Kaz*spi[2];
|
||||
fmi[0] += scalar*xmag;
|
||||
fmi[1] += scalar*ymag;
|
||||
fmi[2] += scalar*zmag;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixForceSpin::post_force_respa(int vflag, int ilevel, int iloop)
|
||||
{
|
||||
if (ilevel == ilevel_respa) post_force(vflag);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
//No acceleration for magnetic EOM, only a "magnetic force"
|
||||
void FixForceSpin::set_magneticforce()
|
||||
{
|
||||
if (style == ZEEMAN) {
|
||||
xmag = H_field*Hx;
|
||||
ymag = H_field*Hy;
|
||||
zmag = H_field*Hz;
|
||||
}
|
||||
if (style == ANISOTROPY) {
|
||||
xmag = 2.0*Ka*Kax;
|
||||
ymag = 2.0*Ka*Kay;
|
||||
zmag = 2.0*Ka*Kaz;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
potential energy in magnetic field
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double FixForceSpin::compute_scalar()
|
||||
{
|
||||
// only sum across procs one time
|
||||
if (eflag == 0) {
|
||||
MPI_Allreduce(&emag,&emag_all,1,MPI_DOUBLE,MPI_SUM,world);
|
||||
eflag = 1;
|
||||
}
|
||||
return emag_all;
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
|
||||
FixStyle(force/spin,FixForceSpin)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_FORCE_SPIN_H
|
||||
#define LMP_FIX_FORCE_SPIN_H
|
||||
|
||||
#include "fix.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixForceSpin : public Fix {
|
||||
friend class FixPour;
|
||||
|
||||
public:
|
||||
FixForceSpin(class LAMMPS *, int, char **);
|
||||
~FixForceSpin();
|
||||
int setmask();
|
||||
void init();
|
||||
void setup(int);
|
||||
virtual void post_force(int);
|
||||
virtual void post_force_respa(int, int, int);
|
||||
double compute_scalar();
|
||||
|
||||
int zeeman_flag, aniso_flag;
|
||||
void compute_zeeman(int, double *);
|
||||
void compute_anisotropy(int, double *, double *);
|
||||
|
||||
protected:
|
||||
int style;
|
||||
|
||||
double xmag, ymag, zmag; //Magnetic force
|
||||
double degree2rad;
|
||||
int ilevel_respa;
|
||||
int time_origin;
|
||||
int eflag;
|
||||
double emag, emag_all;
|
||||
|
||||
int varflag;
|
||||
int magfieldstyle;
|
||||
int magvar;
|
||||
char *magstr;
|
||||
|
||||
double H_field; //Zeeman field intensity and direction
|
||||
double Hx, Hy, Hz;
|
||||
|
||||
double Ka; //Magnetic anisotropy intensity and direction
|
||||
double Kax, Kay, Kaz;
|
||||
|
||||
double *spi, *fmi; //Temp var. in compute
|
||||
|
||||
void set_magneticforce();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
E: Variable name for fix force/spin does not exist
|
||||
|
||||
Self-explanatory.
|
||||
|
||||
E: Variable for fix force/spin is invalid style
|
||||
|
||||
Only equal-style variables can be used.
|
||||
|
||||
*/
|
|
@ -0,0 +1,200 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Contributing authors: Carolyn Phillips (U Mich), reservoir energy tally
|
||||
Aidan Thompson (SNL) GJF formulation
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <mpi.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "fix_langevin_spin.h"
|
||||
#include "math_extra.h"
|
||||
#include "atom.h"
|
||||
#include "atom_vec_ellipsoid.h"
|
||||
#include "force.h"
|
||||
#include "update.h"
|
||||
#include "modify.h"
|
||||
#include "compute.h"
|
||||
#include "domain.h"
|
||||
#include "region.h"
|
||||
#include "respa.h"
|
||||
#include "comm.h"
|
||||
#include "input.h"
|
||||
#include "variable.h"
|
||||
#include "random_mars.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
#include "group.h"
|
||||
#include "math_const.h"
|
||||
#include "random_park.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
using namespace MathConst;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixLangevinSpin::FixLangevinSpin(LAMMPS *lmp, int narg, char **arg) :
|
||||
Fix(lmp, narg, arg), id_temp(NULL), random(NULL)
|
||||
{
|
||||
if (narg != 7) error->all(FLERR,"Illegal fix langevin/spin command");
|
||||
|
||||
dynamic_group_allow = 1;
|
||||
scalar_flag = 1;
|
||||
global_freq = 1;
|
||||
extscalar = 1;
|
||||
nevery = 1;
|
||||
|
||||
temp = force->numeric(FLERR,arg[3]);
|
||||
alpha_t = force->numeric(FLERR,arg[4]);
|
||||
alpha_l = force->numeric(FLERR,arg[5]);
|
||||
seed = force->inumeric(FLERR,arg[6]);
|
||||
|
||||
if (alpha_t < 0.0) error->all(FLERR,"Fix langevin/spin transverse damping must be >= 0.0");
|
||||
if (alpha_l < 0.0) error->all(FLERR,"Fix langevin/spin transverse damping must be >= 0.0");
|
||||
if (seed <= 0) error->all(FLERR,"Illegal fix langevin/spin seed must be > 0");
|
||||
|
||||
// initialize Marsaglia RNG with processor-unique seed
|
||||
//random = new RanMars(lmp,seed + comm->me);
|
||||
random = new RanPark(lmp,seed + comm->me);
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixLangevinSpin::~FixLangevinSpin()
|
||||
{
|
||||
delete random;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int FixLangevinSpin::setmask()
|
||||
{
|
||||
int mask = 0;
|
||||
mask |= POST_FORCE;
|
||||
mask |= POST_FORCE_RESPA;
|
||||
mask |= END_OF_STEP;
|
||||
mask |= THERMO_ENERGY;
|
||||
return mask;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLangevinSpin::init()
|
||||
{
|
||||
// warn if any fix comes after this one
|
||||
int after = 0;
|
||||
int flag_force = 0;
|
||||
int flag_lang = 0;
|
||||
for (int i = 0; i < modify->nfix; i++) {
|
||||
if (strcmp("force/spin",modify->fix[i]->style)==0) flag_force = MAX(flag_force,i);
|
||||
if (strcmp("langevin/spin",modify->fix[i]->style)==0) flag_lang = i;
|
||||
}
|
||||
if (flag_force >= flag_lang) error->all(FLERR,"Fix langevin/spin should come after all other spin fixes");
|
||||
|
||||
dts = update->dt;
|
||||
Gil_factor = 1.0/(1.0+(alpha_t)*(alpha_t));
|
||||
|
||||
double hbar = force->hplanck/MY_2PI; //eV/(rad.THz)
|
||||
double kb = force->boltz;
|
||||
D = (MY_2PI*Gil_factor*kb*temp)/hbar/dts;
|
||||
sigma = sqrt(D);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLangevinSpin::setup(int vflag)
|
||||
{
|
||||
if (strstr(update->integrate_style,"verlet"))
|
||||
post_force(vflag);
|
||||
else {
|
||||
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
|
||||
post_force_respa(vflag,nlevels_respa-1,0);
|
||||
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLangevinSpin::post_force(int vflag)
|
||||
{
|
||||
double **sp = atom->sp;
|
||||
double **fm = atom->fm;
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
double sx, sy, sz;
|
||||
double fmx, fmy, fmz;
|
||||
double cpx, cpy, cpz;
|
||||
double rx, ry, rz;
|
||||
|
||||
// add the damping to the effective field of each spin
|
||||
for (int i = 0; i < nlocal; i++)
|
||||
if (mask[i] & groupbit) {
|
||||
sx = sp[i][0];
|
||||
sy = sp[i][1];
|
||||
sz = sp[i][2];
|
||||
|
||||
fmx = fm[i][0];
|
||||
fmy = fm[i][1];
|
||||
fmz = fm[i][2];
|
||||
|
||||
cpx = fmy*sz - fmz*sy;//Computing cross product
|
||||
cpy = fmz*sx - fmx*sz;
|
||||
cpz = fmx*sy - fmy*sx;
|
||||
|
||||
fmx -= alpha_t*cpx;//Taking the damping value away
|
||||
fmy -= alpha_t*cpy;
|
||||
fmz -= alpha_t*cpz;
|
||||
|
||||
fm[i][0] = fmx;
|
||||
fm[i][1] = fmy;
|
||||
fm[i][2] = fmz;
|
||||
}
|
||||
|
||||
//apply thermal effects adding random fields to fm
|
||||
for (int i = 0; i < nlocal; i++)
|
||||
if (mask[i] & groupbit) {
|
||||
#define GAUSSIAN_R
|
||||
#if defined GAUSSIAN_R
|
||||
rx = sigma*random->gaussian();//Drawing random distributions
|
||||
ry = sigma*random->gaussian();
|
||||
rz = sigma*random->gaussian();
|
||||
#else
|
||||
rx = sigma*(random->uniform() - 0.5);
|
||||
ry = sigma*(random->uniform() - 0.5);
|
||||
rz = sigma*(random->uniform() - 0.5);
|
||||
#endif
|
||||
|
||||
fm[i][0] += rx;//Adding random field
|
||||
fm[i][1] += ry;
|
||||
fm[i][2] += rz;
|
||||
|
||||
fm[i][0] *= Gil_factor;//Multiplying by Gilbert's prefactor
|
||||
fm[i][1] *= Gil_factor;
|
||||
fm[i][2] *= Gil_factor;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixLangevinSpin::post_force_respa(int vflag, int ilevel, int iloop)
|
||||
{
|
||||
if (ilevel == nlevels_respa-1) post_force(vflag);
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
|
||||
FixStyle(langevin/spin,FixLangevinSpin)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_LANGEVIN_SPIN_H
|
||||
#define LMP_FIX_LANGEVIN_SPIN_H
|
||||
|
||||
#include "fix.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixLangevinSpin : public Fix {
|
||||
public:
|
||||
FixLangevinSpin(class LAMMPS *, int, char **);
|
||||
virtual ~FixLangevinSpin();
|
||||
int setmask();
|
||||
void init();
|
||||
void setup(int);
|
||||
virtual void post_force(int);
|
||||
void post_force_respa(int, int, int);
|
||||
|
||||
protected:
|
||||
//First mag. quantities
|
||||
int transv_damp_flag, long_damp_flag; //Flags for transverse or longitudinal mag. dampings
|
||||
double alpha_t, alpha_l; //Transverse and long. damping value
|
||||
double dts,temp,D,sigma;//timestep, temp, noise
|
||||
double Gil_factor;//Gilbert's prefactor
|
||||
|
||||
char *id_temp;
|
||||
class Compute *temperature;
|
||||
|
||||
int nlevels_respa;
|
||||
//class RanMars *random;
|
||||
class RanPark *random;
|
||||
int seed;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
E: Fix langevin period must be > 0.0
|
||||
|
||||
The time window for temperature relaxation must be > 0
|
||||
|
||||
W: Energy tally does not account for 'zero yes'
|
||||
|
||||
The energy removed by using the 'zero yes' flag is not accounted
|
||||
for in the energy tally and thus energy conservation cannot be
|
||||
monitored in this case.
|
||||
|
||||
|
||||
E: Variable for fix langevin is invalid style
|
||||
|
||||
It must be an equal-style variable.
|
||||
|
||||
|
||||
E: Cannot zero Langevin force of 0 atoms
|
||||
|
||||
The group has zero atoms, so you cannot request its force
|
||||
be zeroed.
|
||||
|
||||
E: Fix langevin variable returned negative temperature
|
||||
|
||||
Self-explanatory.
|
||||
|
||||
E: Could not find fix_modify temperature ID
|
||||
|
||||
The compute ID for computing temperature does not exist.
|
||||
|
||||
E: Fix_modify temperature ID does not compute temperature
|
||||
|
||||
The compute ID assigned to the fix must compute temperature.
|
||||
|
||||
W: Group for fix_modify temp != fix group
|
||||
|
||||
The fix_modify command is specifying a temperature computation that
|
||||
computes a temperature on a different group of atoms than the fix
|
||||
itself operates on. This is probably not what you want to do.
|
||||
|
||||
*/
|
|
@ -0,0 +1,562 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "fix_nve_spin.h"
|
||||
#include "atom.h"
|
||||
#include "atom_vec.h"
|
||||
#include "update.h"
|
||||
#include "respa.h"
|
||||
#include "force.h"
|
||||
#include "error.h"
|
||||
#include "math_vector.h"
|
||||
#include "math_extra.h"
|
||||
#include "math_const.h"
|
||||
#include "modify.h"
|
||||
|
||||
//Add headers (see delete later)
|
||||
#include "pair.h"
|
||||
#include "timer.h"
|
||||
#include "integrate.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_list.h"
|
||||
#include "pair_spin.h"
|
||||
#include "memory.h"
|
||||
#include "fix_force_spin.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace FixConst;
|
||||
using namespace MathConst;
|
||||
using namespace MathExtra;
|
||||
|
||||
enum{NONE,SPIN};
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
FixNVESpin::FixNVESpin(LAMMPS *lmp, int narg, char **arg) :
|
||||
FixNVE(lmp, narg, arg)
|
||||
{
|
||||
|
||||
if (narg < 3) error->all(FLERR,"Illegal fix nve/spin command");
|
||||
|
||||
time_integrate = 1;
|
||||
|
||||
extra = NONE;
|
||||
|
||||
int iarg = 2;
|
||||
if (strcmp(arg[iarg],"nve/spin") == 0) {
|
||||
if (iarg+1 > narg) error->all(FLERR,"Illegal fix nve/spin command");
|
||||
extra = SPIN;
|
||||
}
|
||||
|
||||
// error checks
|
||||
if (extra == SPIN && !atom->mumag_flag)
|
||||
error->all(FLERR,"Fix nve/spin requires spin attribute mumag");
|
||||
|
||||
#if defined SEQNEI
|
||||
lockpairspin = NULL;
|
||||
lockforcespin = NULL;
|
||||
exch_flag = dmi_flag = me_flag = 0;
|
||||
zeeman_flag = aniso_flag = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
FixNVESpin::~FixNVESpin(){
|
||||
#if defined SEQNEI
|
||||
//delete lockpairspin;
|
||||
//delete lockforcespin;
|
||||
memory->destroy(spi);
|
||||
memory->destroy(fmi);
|
||||
memory->destroy(fmj);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixNVESpin::init()
|
||||
{
|
||||
FixNVE::init();
|
||||
|
||||
dts = update->dt;
|
||||
|
||||
#if defined SEQNEI
|
||||
lockpairspin = (PairSpin *) force->pair;
|
||||
|
||||
memory->create(spi,3,"nves:spi");
|
||||
memory->create(fmi,3,"nves:fmi");
|
||||
memory->create(fmj,3,"nves:fmj");
|
||||
|
||||
int iforce;
|
||||
for (iforce = 0; iforce < modify->nfix; iforce++)
|
||||
if (strstr(modify->fix[iforce]->style,"force/spin")) break;
|
||||
lockforcespin = (FixForceSpin *) modify->fix[iforce];
|
||||
|
||||
exch_flag = lockpairspin->exch_flag;
|
||||
dmi_flag = lockpairspin->dmi_flag;
|
||||
me_flag = lockpairspin->me_flag;
|
||||
|
||||
zeeman_flag = lockforcespin->zeeman_flag;
|
||||
aniso_flag = lockforcespin->aniso_flag;
|
||||
#endif
|
||||
|
||||
/*int idamp;
|
||||
for (idamp = 0; idamp < modify->nfix; idamp++)
|
||||
if (strstr(modify->fix[idamp]->style,"damping/spin")) break;
|
||||
if (idamp == modify->nfix)
|
||||
error->all(FLERR,"Integration of spin systems requires use of fix damping (set damping to 0.0 for NVE)");
|
||||
|
||||
lockspindamping = (FixSpinDamping *) modify->fix[idamp];
|
||||
alpha_t = lockspindamping->get_damping(0);
|
||||
*/
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixNVESpin::initial_integrate(int vflag)
|
||||
{
|
||||
double dtfm,msq,scale,fm2,fmsq,sp2,spsq,energy;
|
||||
double cp[3],g[3];
|
||||
|
||||
double **x = atom->x;
|
||||
double **v = atom->v;
|
||||
double **f = atom->f;
|
||||
double **sp = atom->sp;
|
||||
double **fm = atom->fm;
|
||||
double *rmass = atom->rmass;
|
||||
double *mass = atom->mass;
|
||||
int nlocal = atom->nlocal;
|
||||
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
|
||||
// Advance half spins all particles
|
||||
//See Omelyan et al., PRL 86, 2001 and P.W. Ma et al, PRB 83, 2011
|
||||
if (extra == SPIN) {
|
||||
#if defined SEQNEI
|
||||
for (int i = 0; i < nlocal; i++){
|
||||
ComputeSpinInteractionsNei(i);
|
||||
AdvanceSingleSpin(i,0.5*dts,sp,fm);
|
||||
}
|
||||
#endif
|
||||
#if defined SEQ
|
||||
for (int i = 0; i < nlocal; i++){
|
||||
AdvanceSingleSpin(i,0.5*dts,sp,fm);
|
||||
ComputeSpinInteractions();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// update half v all particles
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) {
|
||||
if (rmass) dtfm = dtf / rmass[i];
|
||||
else dtfm = dtf / mass[type[i]];
|
||||
v[i][0] += dtfm * f[i][0];
|
||||
v[i][1] += dtfm * f[i][1];
|
||||
v[i][2] += dtfm * f[i][2];
|
||||
}
|
||||
}
|
||||
|
||||
// update x for all particles
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) {
|
||||
x[i][0] += 0.5 * dtv * v[i][0];
|
||||
x[i][1] += 0.5 * dtv * v[i][1];
|
||||
x[i][2] += 0.5 * dtv * v[i][2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined SEQNEI
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void FixNVESpin::ComputeSpinInteractionsNei(int ii)
|
||||
{
|
||||
int nflag,sortflag;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
int n_post_integrate = modify->n_post_integrate;
|
||||
int n_pre_exchange = modify->n_pre_exchange;
|
||||
int n_pre_neighbor = modify->n_pre_neighbor;
|
||||
int n_pre_force = modify->n_pre_force;
|
||||
int n_pre_reverse = modify->n_pre_reverse;
|
||||
int n_post_force = modify->n_post_force;
|
||||
int n_end_of_step = modify->n_end_of_step;
|
||||
|
||||
bigint ntimestep;
|
||||
ntimestep = update->ntimestep;
|
||||
|
||||
//Force compute quantities
|
||||
int i,j,jj,inum,jnum,itype,jtype;
|
||||
int *ilist,*jlist,*numneigh,**firstneigh;
|
||||
double **x = atom->x;
|
||||
double **sp = atom->sp;
|
||||
double **fm = atom->fm;
|
||||
int *type = atom->type;
|
||||
int newton_pair = force->newton_pair;
|
||||
|
||||
inum = lockpairspin->list->inum;
|
||||
ilist = lockpairspin->list->ilist;
|
||||
numneigh = lockpairspin->list->numneigh;
|
||||
firstneigh = lockpairspin->list->firstneigh;
|
||||
|
||||
double xtmp,ytmp,ztmp;
|
||||
double rsq,rd,delx,dely,delz;
|
||||
double cut_ex_2, cut_dmi_2, cut_me_2;
|
||||
cut_ex_2 = cut_dmi_2 = cut_me_2 = 0.0;
|
||||
|
||||
int eflag = 1;
|
||||
int vflag = 0;
|
||||
int pair_compute_flag = 1;
|
||||
|
||||
if (atom->sortfreq > 0) sortflag = 1;
|
||||
else sortflag = 0;
|
||||
if (n_post_integrate) modify->post_integrate();
|
||||
timer->stamp(Timer::MODIFY);
|
||||
|
||||
// regular communication vs neighbor list rebuild
|
||||
nflag = neighbor->decide();
|
||||
if (nflag == 0) {
|
||||
timer->stamp();
|
||||
comm->forward_comm();
|
||||
timer->stamp(Timer::COMM);
|
||||
} else {
|
||||
if (n_pre_exchange) {
|
||||
timer->stamp();
|
||||
modify->pre_exchange();
|
||||
timer->stamp(Timer::MODIFY);
|
||||
}
|
||||
//if (triclinic) domain->x2lamda(atom->nlocal);
|
||||
domain->pbc();
|
||||
if (domain->box_change) {
|
||||
domain->reset_box();
|
||||
comm->setup();
|
||||
if (neighbor->style) neighbor->setup_bins();
|
||||
}
|
||||
timer->stamp();
|
||||
comm->exchange();
|
||||
if (sortflag && ntimestep >= atom->nextsort) atom->sort();
|
||||
comm->borders();
|
||||
//if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
|
||||
timer->stamp(Timer::COMM);
|
||||
if (n_pre_neighbor) {
|
||||
modify->pre_neighbor();
|
||||
timer->stamp(Timer::MODIFY);
|
||||
}
|
||||
neighbor->build();
|
||||
timer->stamp(Timer::NEIGH);
|
||||
}
|
||||
|
||||
///////Force computation for spin i/////////////
|
||||
i = ilist[ii];
|
||||
//Clear atom i
|
||||
fm[i][0] = fm[i][1] = fm[i][2] = 0.0;
|
||||
|
||||
timer->stamp();
|
||||
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
fmi[0] = fmi[1] = fmi[2] = 0.0;
|
||||
fmj[0] = fmj[1] = fmj[2] = 0.0;
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
// printf("Test inum: %g \n",inum);
|
||||
/*
|
||||
//Pair interaction
|
||||
for (int jj = 0; jj < inum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
itype = type[ii];
|
||||
jtype = type[j];
|
||||
|
||||
if (exch_flag) {
|
||||
cut_ex_2 = (lockpairspin->cut_spin_exchange[itype][jtype])*(lockpairspin->cut_spin_exchange[itype][jtype]);
|
||||
if (rsq <= cut_ex_2) {
|
||||
lockpairspin->compute_exchange(i,j,rsq,fmi,fmj);
|
||||
}
|
||||
}
|
||||
if (dmi_flag) {
|
||||
cut_dmi_2 = (lockpairspin->cut_spin_dmi[itype][jtype])*(lockpairspin->cut_spin_dmi[itype][jtype]);
|
||||
if (rsq <= cut_dmi_2) {
|
||||
lockpairspin->compute_dmi(i,j,fmi,fmj);
|
||||
}
|
||||
}
|
||||
if (me_flag) {
|
||||
cut_me_2 = (lockpairspin->cut_spin_me[itype][jtype])*(lockpairspin->cut_spin_me[itype][jtype]);
|
||||
if (rsq <= cut_me_2) {
|
||||
lockpairspin->compute_me(i,j,fmi,fmj);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//Pair interaction
|
||||
int natom = nlocal + atom->nghost;
|
||||
for (int k = 0; k < natom; k++) {
|
||||
delx = xtmp - x[k][0];
|
||||
dely = ytmp - x[k][1];
|
||||
delz = ztmp - x[k][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz;
|
||||
itype = type[ii];
|
||||
jtype = type[k];
|
||||
|
||||
if (exch_flag) {
|
||||
cut_ex_2 = (lockpairspin->cut_spin_exchange[itype][jtype])*(lockpairspin->cut_spin_exchange[itype][jtype]);
|
||||
if (rsq <= cut_ex_2) {
|
||||
lockpairspin->compute_exchange(i,k,rsq,fmi,fmj);
|
||||
}
|
||||
}
|
||||
if (dmi_flag) {
|
||||
cut_dmi_2 = (lockpairspin->cut_spin_dmi[itype][jtype])*(lockpairspin->cut_spin_dmi[itype][jtype]);
|
||||
if (rsq <= cut_dmi_2) {
|
||||
lockpairspin->compute_dmi(i,k,fmi,fmj);
|
||||
}
|
||||
}
|
||||
if (me_flag) {
|
||||
cut_me_2 = (lockpairspin->cut_spin_me[itype][jtype])*(lockpairspin->cut_spin_me[itype][jtype]);
|
||||
if (rsq <= cut_me_2) {
|
||||
lockpairspin->compute_me(i,k,fmi,fmj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//post force
|
||||
if (zeeman_flag) {
|
||||
lockforcespin->compute_zeeman(i,fmi);
|
||||
}
|
||||
if (aniso_flag) {
|
||||
spi[0] = sp[i][0];
|
||||
spi[1] = sp[i][1];
|
||||
spi[2] = sp[i][2];
|
||||
lockforcespin->compute_anisotropy(i,spi,fmi);
|
||||
}
|
||||
|
||||
//Replace the force by its new value
|
||||
fm[i][0] = fmi[0];
|
||||
fm[i][1] = fmi[1];
|
||||
fm[i][2] = fmi[2];
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void FixNVESpin::ComputeSpinInteractions()
|
||||
{
|
||||
int nflag,sortflag;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
int n_post_integrate = modify->n_post_integrate;
|
||||
int n_pre_exchange = modify->n_pre_exchange;
|
||||
int n_pre_neighbor = modify->n_pre_neighbor;
|
||||
int n_pre_force = modify->n_pre_force;
|
||||
int n_pre_reverse = modify->n_pre_reverse;
|
||||
int n_post_force = modify->n_post_force;
|
||||
int n_end_of_step = modify->n_end_of_step;
|
||||
|
||||
bigint ntimestep;
|
||||
ntimestep = update->ntimestep;
|
||||
|
||||
//int eflag = update->integrate->eflag;
|
||||
//int vflag = update->integrate->vflag;
|
||||
int eflag = 1;
|
||||
int vflag = 0;
|
||||
int pair_compute_flag = 1;
|
||||
|
||||
if (atom->sortfreq > 0) sortflag = 1;
|
||||
else sortflag = 0;
|
||||
if (n_post_integrate) modify->post_integrate();
|
||||
timer->stamp(Timer::MODIFY);
|
||||
|
||||
// regular communication vs neighbor list rebuild
|
||||
nflag = neighbor->decide();
|
||||
if (nflag == 0) {
|
||||
timer->stamp();
|
||||
comm->forward_comm();
|
||||
timer->stamp(Timer::COMM);
|
||||
} else {
|
||||
if (n_pre_exchange) {
|
||||
timer->stamp();
|
||||
modify->pre_exchange();
|
||||
timer->stamp(Timer::MODIFY);
|
||||
}
|
||||
//if (triclinic) domain->x2lamda(atom->nlocal);
|
||||
domain->pbc();
|
||||
if (domain->box_change) {
|
||||
domain->reset_box();
|
||||
comm->setup();
|
||||
if (neighbor->style) neighbor->setup_bins();
|
||||
}
|
||||
timer->stamp();
|
||||
comm->exchange();
|
||||
if (sortflag && ntimestep >= atom->nextsort) atom->sort();
|
||||
comm->borders();
|
||||
//if (triclinic) domain->lamda2x(atom->nlocal+atom->nghost);
|
||||
timer->stamp(Timer::COMM);
|
||||
if (n_pre_neighbor) {
|
||||
modify->pre_neighbor();
|
||||
timer->stamp(Timer::MODIFY);
|
||||
}
|
||||
neighbor->build();
|
||||
timer->stamp(Timer::NEIGH);
|
||||
}
|
||||
|
||||
// force computations
|
||||
// important for pair to come before bonded contributions
|
||||
// since some bonded potentials tally pairwise energy/virial
|
||||
// and Pair:ev_tally() needs to be called before any tallying
|
||||
|
||||
size_t nbytes;
|
||||
nbytes = sizeof(double) * nlocal;
|
||||
if (force->newton) nbytes += sizeof(double) * atom->nghost;
|
||||
|
||||
atom->avec->force_clear(0,nbytes);
|
||||
|
||||
timer->stamp();
|
||||
|
||||
if (n_pre_force) {
|
||||
modify->pre_force(vflag);
|
||||
timer->stamp(Timer::MODIFY);
|
||||
}
|
||||
|
||||
if (pair_compute_flag) {
|
||||
force->pair->compute(eflag,vflag);
|
||||
timer->stamp(Timer::PAIR);
|
||||
}
|
||||
|
||||
/*if (kspace_compute_flag) {
|
||||
force->kspace->compute(eflag,vflag);
|
||||
timer->stamp(Timer::KSPACE);
|
||||
}*/
|
||||
|
||||
if (n_pre_reverse) {
|
||||
modify->pre_reverse(eflag,vflag);
|
||||
timer->stamp(Timer::MODIFY);
|
||||
}
|
||||
|
||||
// reverse communication of forces
|
||||
|
||||
if (force->newton) {
|
||||
comm->reverse_comm();
|
||||
timer->stamp(Timer::COMM);
|
||||
}
|
||||
|
||||
// force modifications
|
||||
|
||||
if (n_post_force) modify->post_force(vflag);
|
||||
timer->stamp(Timer::MODIFY);
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixNVESpin::AdvanceSingleSpin(int i, double dts, double **sp, double **fm)
|
||||
{
|
||||
int nlocal = atom->nlocal;
|
||||
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
|
||||
double dtfm,msq,scale,fm2,fmsq,sp2,spsq,energy;
|
||||
double cp[3],g[3];
|
||||
|
||||
cp[0] = cp[1] = cp[2] = 0.0;
|
||||
g[0] = g[1] = g[2] = 0.0;
|
||||
fm2 = (fm[i][0]*fm[i][0])+(fm[i][1]*fm[i][1])+(fm[i][2]*fm[i][2]);
|
||||
fmsq = sqrt(fm2);
|
||||
energy = (sp[i][0]*fm[i][0])+(sp[i][1]*fm[i][1])+(sp[i][2]*fm[i][2]);
|
||||
|
||||
cp[0] = fm[i][1]*sp[i][2]-fm[i][2]*sp[i][1];
|
||||
cp[1] = fm[i][2]*sp[i][0]-fm[i][0]*sp[i][2];
|
||||
cp[2] = fm[i][0]*sp[i][1]-fm[i][1]*sp[i][0];
|
||||
|
||||
g[0] = sp[i][0]+cp[0]*dts;
|
||||
g[1] = sp[i][1]+cp[1]*dts;
|
||||
g[2] = sp[i][2]+cp[2]*dts;
|
||||
|
||||
g[0] += (fm[i][0]*energy-0.5*sp[i][0]*fm2)*0.5*dts*dts;
|
||||
g[1] += (fm[i][1]*energy-0.5*sp[i][1]*fm2)*0.5*dts*dts;
|
||||
g[2] += (fm[i][2]*energy-0.5*sp[i][2]*fm2)*0.5*dts*dts;
|
||||
|
||||
g[0] /= (1+0.25*fm2*dts*dts);
|
||||
g[1] /= (1+0.25*fm2*dts*dts);
|
||||
g[2] /= (1+0.25*fm2*dts*dts);
|
||||
|
||||
sp[i][0] = g[0];
|
||||
sp[i][1] = g[1];
|
||||
sp[i][2] = g[2];
|
||||
|
||||
//Renormalization (may not be necessary)
|
||||
msq = g[0]*g[0] + g[1]*g[1] + g[2]*g[2];
|
||||
scale = 1.0/sqrt(msq);
|
||||
sp[i][0] *= scale;
|
||||
sp[i][1] *= scale;
|
||||
sp[i][2] *= scale;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void FixNVESpin::final_integrate()
|
||||
{
|
||||
double dtfm,msq,scale,fm2,fmsq,energy;
|
||||
double cp[3],g[3];
|
||||
|
||||
double **x = atom->x;
|
||||
double **v = atom->v;
|
||||
double **f = atom->f;
|
||||
double **sp = atom->sp;
|
||||
double **fm = atom->fm;
|
||||
double *rmass = atom->rmass;
|
||||
double *mass = atom->mass;
|
||||
int nlocal = atom->nlocal;
|
||||
if (igroup == atom->firstgroup) nlocal = atom->nfirst;
|
||||
int *type = atom->type;
|
||||
int *mask = atom->mask;
|
||||
|
||||
// update half v for all particles
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (mask[i] & groupbit) {
|
||||
if (rmass) dtfm = dtf / rmass[i];
|
||||
else dtfm = dtf / mass[type[i]];
|
||||
v[i][0] += dtfm * f[i][0];
|
||||
v[i][1] += dtfm * f[i][1];
|
||||
v[i][2] += dtfm * f[i][2];
|
||||
}
|
||||
}
|
||||
|
||||
// Advance half spins all particles
|
||||
//See Omelyan et al., PRL 86, 2001 and P.W. Ma et al, PRB 83, 2011
|
||||
if (extra == SPIN) {
|
||||
#if defined SEQNEI
|
||||
for (int i = nlocal-1; i >= 0; i--){
|
||||
ComputeSpinInteractionsNei(i);
|
||||
AdvanceSingleSpin(i,0.5*dts,sp,fm);
|
||||
}
|
||||
#endif
|
||||
#if defined SEQ
|
||||
for (int i = nlocal-1; i >= 0; i--){
|
||||
AdvanceSingleSpin(i,0.5*dts,sp,fm);
|
||||
ComputeSpinInteractions();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef FIX_CLASS
|
||||
|
||||
FixStyle(nve/spin,FixNVESpin)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_FIX_NVE_SPIN_H
|
||||
#define LMP_FIX_NVE_SPIN_H
|
||||
|
||||
#include "fix_nve.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class FixNVESpin : public FixNVE {
|
||||
|
||||
public:
|
||||
FixNVESpin(class LAMMPS *, int, char **);
|
||||
virtual ~FixNVESpin();
|
||||
void init();
|
||||
virtual void initial_integrate(int);
|
||||
void AdvanceSingleSpin(int, double, double **, double **);
|
||||
virtual void final_integrate();
|
||||
|
||||
//#define SEQ
|
||||
#define SEQNEI
|
||||
void ComputeSpinInteractions();
|
||||
void ComputeSpinInteractionsNei(int);
|
||||
|
||||
protected:
|
||||
int extra;
|
||||
double dts;
|
||||
//double alpha_t;
|
||||
|
||||
#if defined SEQNEI
|
||||
private:
|
||||
int exch_flag, dmi_flag, me_flag;
|
||||
int zeeman_flag, aniso_flag;
|
||||
class PairSpin *lockpairspin;
|
||||
double *spi, *fmi, *fmj; //Temp var. for compute
|
||||
class FixForceSpin *lockforcespin;
|
||||
#endif
|
||||
|
||||
//private:
|
||||
//class FixSpinDamping *lockspindamping;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
E: Fix nve/sphere requires atom style sphere
|
||||
|
||||
Self-explanatory.
|
||||
|
||||
E: Fix nve/sphere update dipole requires atom attribute mu
|
||||
|
||||
An atom style with this attribute is needed.
|
||||
|
||||
E: Fix nve/sphere requires extended particles
|
||||
|
||||
This fix can only be used for particles of a finite size.
|
||||
|
||||
E: Fix nve/sphere dlm must be used with update dipole
|
||||
|
||||
The DLM algorithm can only be used in conjunction with update dipole.
|
||||
|
||||
|
||||
*/
|
|
@ -0,0 +1,558 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "pair_spin.h"
|
||||
#include "atom.h"
|
||||
#include "neighbor.h"
|
||||
#include "neigh_list.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "memory.h"
|
||||
#include "math_const.h"
|
||||
#include "error.h"
|
||||
#include "update.h"
|
||||
#include <string.h>
|
||||
|
||||
//Add. lib. for full neighb. list
|
||||
#include "neigh_request.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
using namespace MathConst;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairSpin::PairSpin(LAMMPS *lmp) : Pair(lmp)
|
||||
{
|
||||
single_enable = 0;
|
||||
exch_flag = 0;
|
||||
dmi_flag = 0;
|
||||
me_flag = 0;
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
PairSpin::~PairSpin()
|
||||
{
|
||||
if (allocated) {
|
||||
memory->destroy(setflag);
|
||||
|
||||
memory->destroy(cut_spin_exchange);
|
||||
memory->destroy(J_1);
|
||||
memory->destroy(J_2);
|
||||
memory->destroy(J_2);
|
||||
|
||||
memory->destroy(cut_spin_dmi);
|
||||
memory->destroy(DM);
|
||||
memory->destroy(v_dmx);
|
||||
memory->destroy(v_dmy);
|
||||
memory->destroy(v_dmz);
|
||||
|
||||
memory->destroy(cut_spin_me);
|
||||
memory->destroy(ME);
|
||||
memory->destroy(v_mex);
|
||||
memory->destroy(v_mey);
|
||||
memory->destroy(v_mez);
|
||||
|
||||
memory->destroy(fmi);
|
||||
memory->destroy(fmj);
|
||||
|
||||
memory->destroy(cutsq);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::compute(int eflag, int vflag)
|
||||
{
|
||||
int i,j,ii,jj,inum,jnum,itype,jtype;
|
||||
double evdwl,ecoul;
|
||||
double xtmp,ytmp,ztmp;
|
||||
double fmix,fmiy,fmiz,fmjx,fmjy,fmjz;
|
||||
double cut_ex_2,cut_dmi_2,cut_me_2;
|
||||
double rsq,rd,delx,dely,delz;
|
||||
int *ilist,*jlist,*numneigh,**firstneigh;
|
||||
|
||||
evdwl = ecoul = 0.0;
|
||||
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||
else evflag = vflag_fdotr = 0;
|
||||
|
||||
double **x = atom->x;
|
||||
double **fm = atom->fm;
|
||||
double *mumag = atom->mumag;
|
||||
double **sp = atom->sp;
|
||||
int *type = atom->type;
|
||||
int nlocal = atom->nlocal;
|
||||
int newton_pair = force->newton_pair;
|
||||
|
||||
inum = list->inum;
|
||||
ilist = list->ilist;
|
||||
numneigh = list->numneigh;
|
||||
firstneigh = list->firstneigh;
|
||||
|
||||
// Pair spin computations
|
||||
// Loop over neighbors of my itoms
|
||||
|
||||
for (ii = 0; ii < inum; ii++) {
|
||||
i = ilist[ii];
|
||||
xtmp = x[i][0];
|
||||
ytmp = x[i][1];
|
||||
ztmp = x[i][2];
|
||||
jlist = firstneigh[i];
|
||||
jnum = numneigh[i];
|
||||
|
||||
//Loop on Neighbors
|
||||
for (jj = 0; jj < jnum; jj++) {
|
||||
j = jlist[jj];
|
||||
j &= NEIGHMASK;
|
||||
|
||||
fmi[0] = fmi[1] = fmi[2] = 0.0;
|
||||
fmj[0] = fmj[1] = fmj[2] = 0.0;
|
||||
|
||||
delx = xtmp - x[j][0];
|
||||
dely = ytmp - x[j][1];
|
||||
delz = ztmp - x[j][2];
|
||||
rsq = delx*delx + dely*dely + delz*delz; //square or inter-atomic distance
|
||||
itype = type[i];
|
||||
jtype = type[j];
|
||||
|
||||
//Exchange interaction
|
||||
if (exch_flag) {
|
||||
cut_ex_2 = cut_spin_exchange[itype][jtype]*cut_spin_exchange[itype][jtype];
|
||||
if (rsq <= cut_ex_2) {
|
||||
compute_exchange(i,j,rsq,fmi,fmj);
|
||||
}
|
||||
}
|
||||
//DM interaction
|
||||
if (dmi_flag){
|
||||
cut_dmi_2 = cut_spin_dmi[itype][jtype]*cut_spin_dmi[itype][jtype];
|
||||
if (rsq <= cut_dmi_2){
|
||||
compute_dmi(i,j,fmi,fmj);
|
||||
}
|
||||
}
|
||||
//ME interaction
|
||||
if (me_flag){
|
||||
cut_me_2 = cut_spin_me[itype][jtype]*cut_spin_me[itype][jtype];
|
||||
if (rsq <= cut_me_2){
|
||||
compute_me(i,j,fmi,fmj);
|
||||
}
|
||||
}
|
||||
|
||||
fm[i][0] += fmi[0];
|
||||
fm[i][1] += fmi[1];
|
||||
fm[i][2] += fmi[2];
|
||||
|
||||
if (newton_pair || j < nlocal) {
|
||||
fm[j][0] += fmj[0];
|
||||
fm[j][1] += fmj[1];
|
||||
fm[j][2] += fmj[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vflag_fdotr) virial_fdotr_compute();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void PairSpin::compute_exchange(int i, int j, double rsq, double *fmi, double *fmj)
|
||||
{
|
||||
int *type = atom->type;
|
||||
int itype, jtype;
|
||||
double **sp = atom->sp;
|
||||
double dmix,dmiy,dmiz;
|
||||
double Jex, ra;
|
||||
itype = type[i];
|
||||
jtype = type[j];
|
||||
|
||||
ra = rsq/J_3[itype][jtype]/J_3[itype][jtype];
|
||||
Jex = 4.0*J_1[itype][jtype]*ra;
|
||||
Jex *= (1.0-J_2[itype][jtype]*ra);
|
||||
Jex *= exp(-ra);
|
||||
|
||||
fmi[0] += Jex*sp[j][0];
|
||||
fmi[1] += Jex*sp[j][1];
|
||||
fmi[2] += Jex*sp[j][2];
|
||||
|
||||
fmj[0] += Jex*sp[i][0];
|
||||
fmj[1] += Jex*sp[i][1];
|
||||
fmj[2] += Jex*sp[i][2];
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void PairSpin::compute_dmi(int i, int j, double *fmi, double *fmj)
|
||||
{
|
||||
int *type = atom->type;
|
||||
int itype, jtype;
|
||||
double **sp = atom->sp;
|
||||
double dmix,dmiy,dmiz;
|
||||
itype = type[i];
|
||||
jtype = type[j];
|
||||
|
||||
dmix = DM[itype][jtype]*v_dmx[itype][jtype];
|
||||
dmiy = DM[itype][jtype]*v_dmy[itype][jtype];
|
||||
dmiz = DM[itype][jtype]*v_dmz[itype][jtype];
|
||||
|
||||
fmi[0] += sp[j][1]*dmiz-sp[j][2]*dmiy;
|
||||
fmi[1] += sp[j][2]*dmix-sp[j][0]*dmiz;
|
||||
fmi[2] += sp[j][0]*dmiy-sp[j][1]*dmix;
|
||||
|
||||
fmj[0] -= sp[i][1]*dmiz-sp[i][2]*dmiy;
|
||||
fmj[1] -= sp[i][2]*dmix-sp[i][0]*dmiz;
|
||||
fmj[2] -= sp[i][0]*dmiy-sp[i][1]*dmix;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
void PairSpin::compute_me(int i, int j, double *fmi, double *fmj)
|
||||
{
|
||||
int *type = atom->type;
|
||||
int itype, jtype;
|
||||
itype = type[i];
|
||||
jtype = type[j];
|
||||
double **sp = atom->sp;
|
||||
double **x = atom->x;
|
||||
double meix,meiy,meiz;
|
||||
double rx, ry, rz, inorm;
|
||||
|
||||
rx = x[j][0] - x[i][0];
|
||||
ry = x[j][1] - x[i][1];
|
||||
rz = x[j][2] - x[i][2];
|
||||
inorm = 1.0/sqrt(rx*rx+ry*ry+rz*rz);
|
||||
rx *= inorm;
|
||||
ry *= inorm;
|
||||
rz *= inorm;
|
||||
|
||||
meix = v_mey[itype][jtype]*rz - v_mez[itype][jtype]*ry;
|
||||
meiy = v_mez[itype][jtype]*rx - v_mex[itype][jtype]*rz;
|
||||
meiz = v_mex[itype][jtype]*ry - v_mey[itype][jtype]*rx;
|
||||
|
||||
meix *= ME[itype][jtype];
|
||||
meiy *= ME[itype][jtype];
|
||||
meiz *= ME[itype][jtype];
|
||||
|
||||
fmi[0] += sp[j][1]*meiz - sp[j][2]*meiy;
|
||||
fmi[1] += sp[j][2]*meix - sp[j][0]*meiz;
|
||||
fmi[2] += sp[j][0]*meiy - sp[j][1]*meix;
|
||||
|
||||
fmj[0] -= sp[i][1]*meiz - sp[i][2]*meiy;
|
||||
fmj[1] -= sp[i][2]*meix - sp[i][0]*meiz;
|
||||
fmj[2] -= sp[i][0]*meiy - sp[i][1]*meix;
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
allocate all arrays
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::allocate()
|
||||
{
|
||||
allocated = 1;
|
||||
int n = atom->ntypes;
|
||||
|
||||
memory->create(setflag,n+1,n+1,"pair:setflag");
|
||||
for (int i = 1; i <= n; i++)
|
||||
for (int j = i; j <= n; j++)
|
||||
setflag[i][j] = 0;
|
||||
|
||||
memory->create(cut_spin_exchange,n+1,n+1,"pair:cut_spin_exchange");
|
||||
memory->create(J_1,n+1,n+1,"pair:J_1");
|
||||
memory->create(J_2,n+1,n+1,"pair:J_2");
|
||||
memory->create(J_3,n+1,n+1,"pair:J_3");
|
||||
|
||||
memory->create(cut_spin_dmi,n+1,n+1,"pair:cut_spin_dmi");
|
||||
memory->create(DM,n+1,n+1,"pair:DM");
|
||||
memory->create(v_dmx,n+1,n+1,"pair:DM_vector_x");
|
||||
memory->create(v_dmy,n+1,n+1,"pair:DM_vector_y");
|
||||
memory->create(v_dmz,n+1,n+1,"pair:DM_vector_z");
|
||||
|
||||
memory->create(cut_spin_me,n+1,n+1,"pair:cut_spin_me");
|
||||
memory->create(ME,n+1,n+1,"pair:ME");
|
||||
memory->create(v_mex,n+1,n+1,"pair:ME_vector_x");
|
||||
memory->create(v_mey,n+1,n+1,"pair:ME_vector_y");
|
||||
memory->create(v_mez,n+1,n+1,"pair:ME_vector_z");
|
||||
|
||||
memory->create(fmi,3,"pair:fmi");
|
||||
memory->create(fmj,3,"pair:fmj");
|
||||
|
||||
memory->create(cutsq,n+1,n+1,"pair:cutsq");
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
global settings
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::settings(int narg, char **arg)
|
||||
{
|
||||
if (narg < 1 || narg > 2)
|
||||
error->all(FLERR,"Incorrect number of args in pair_style pair/spin command");
|
||||
|
||||
if (strcmp(update->unit_style,"metal") != 0)
|
||||
error->all(FLERR,"Spin simulations require metal unit style");
|
||||
|
||||
cut_spin_pair_global = force->numeric(FLERR,arg[0]);
|
||||
|
||||
// reset cutoffs that have been explicitly set
|
||||
|
||||
if (allocated) {
|
||||
int i,j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i+1; j <= atom->ntypes; j++)
|
||||
if (setflag[i][j]) {
|
||||
cut_spin_exchange[i][j] = cut_spin_pair_global;
|
||||
cut_spin_dmi[i][j] = cut_spin_pair_global;
|
||||
cut_spin_me[i][j] = cut_spin_pair_global;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set coeffs for one or more type spin pairs (only one for now)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::coeff(int narg, char **arg)
|
||||
{
|
||||
|
||||
if (!allocated) allocate();
|
||||
|
||||
if (strcmp(arg[2],"exchange")==0){
|
||||
if (narg != 7) error->all(FLERR,"Incorrect args in pair_style command");
|
||||
exch_flag = 1;
|
||||
|
||||
int ilo,ihi,jlo,jhi;
|
||||
force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi);
|
||||
force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi);
|
||||
|
||||
double rij = force->numeric(FLERR,arg[3]);
|
||||
double J1 = force->numeric(FLERR,arg[4]);
|
||||
double J2 = force->numeric(FLERR,arg[5]);
|
||||
double J3 = force->numeric(FLERR,arg[6]);
|
||||
|
||||
double hbar = force->hplanck/MY_2PI;
|
||||
J1 /= hbar;
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
cut_spin_exchange[i][j] = rij;
|
||||
J_1[i][j] = J1;
|
||||
J_2[i][j] = J2;
|
||||
J_3[i][j] = J3;
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0) error->all(FLERR,"Incorrect args in pair_style command");
|
||||
} else if (strcmp(arg[2],"dmi")==0) {
|
||||
if (narg != 8) error->all(FLERR,"Incorrect args in pair_style command");
|
||||
dmi_flag = 1;
|
||||
int ilo,ihi,jlo,jhi;
|
||||
force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi);
|
||||
force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi);
|
||||
|
||||
double rij = force->numeric(FLERR,arg[3]);
|
||||
double dm = force->numeric(FLERR,arg[4]);
|
||||
double dmx = force->numeric(FLERR,arg[5]);
|
||||
double dmy = force->numeric(FLERR,arg[6]);
|
||||
double dmz = force->numeric(FLERR,arg[7]);
|
||||
|
||||
double inorm = 1.0/(dmx*dmx+dmy*dmy+dmz*dmz);
|
||||
dmx *= inorm;
|
||||
dmy *= inorm;
|
||||
dmz *= inorm;
|
||||
|
||||
double hbar = force->hplanck/MY_2PI;
|
||||
dm /= hbar;
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
cut_spin_dmi[i][j] = rij;
|
||||
DM[i][j] = dm;
|
||||
v_dmx[i][j] = dmx;
|
||||
v_dmy[i][j] = dmy;
|
||||
v_dmz[i][j] = dmz;
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0) error->all(FLERR,"Incorrect args in pair_style command");
|
||||
} else if (strcmp(arg[2],"me")==0) {
|
||||
if (narg != 8) error->all(FLERR,"Incorrect args in pair_style command");
|
||||
me_flag = 1;
|
||||
int ilo,ihi,jlo,jhi;
|
||||
force->bounds(FLERR,arg[0],atom->ntypes,ilo,ihi);
|
||||
force->bounds(FLERR,arg[1],atom->ntypes,jlo,jhi);
|
||||
|
||||
double rij = force->numeric(FLERR,arg[3]);
|
||||
double me = force->numeric(FLERR,arg[4]);
|
||||
double mex = force->numeric(FLERR,arg[5]);
|
||||
double mey = force->numeric(FLERR,arg[6]);
|
||||
double mez = force->numeric(FLERR,arg[7]);
|
||||
|
||||
double inorm = 1.0/(mex*mex+mey*mey+mez*mez);
|
||||
mex *= inorm;
|
||||
mey *= inorm;
|
||||
mez *= inorm;
|
||||
|
||||
double hbar = force->hplanck/MY_2PI;
|
||||
me /= hbar;
|
||||
|
||||
int count = 0;
|
||||
for (int i = ilo; i <= ihi; i++) {
|
||||
for (int j = MAX(jlo,i); j <= jhi; j++) {
|
||||
cut_spin_me[i][j] = rij;
|
||||
DM[i][j] = me;
|
||||
v_mex[i][j] = mex;
|
||||
v_mey[i][j] = mey;
|
||||
v_mez[i][j] = mez;
|
||||
setflag[i][j] = 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0) error->all(FLERR,"Incorrect args in pair_style command");
|
||||
} else error->all(FLERR,"Incorrect args in pair_style command");
|
||||
|
||||
//Check if Jex [][] still works for Ferrimagnetic exchange
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init specific to this pair style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::init_style()
|
||||
{
|
||||
if (!atom->sp_flag || !atom->mumag_flag)
|
||||
error->all(FLERR,"Pair spin requires atom attributes sp, mumag");
|
||||
|
||||
neighbor->request(this,instance_me);
|
||||
|
||||
#define FULLNEI
|
||||
#if defined FULLNEI
|
||||
int irequest = neighbor->request(this,instance_me);
|
||||
neighbor->requests[irequest]->half = 0;
|
||||
neighbor->requests[irequest]->full = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
init for one type pair i,j and corresponding j,i
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double PairSpin::init_one(int i, int j)
|
||||
{
|
||||
|
||||
if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
|
||||
|
||||
return cut_spin_pair_global;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::write_restart(FILE *fp)
|
||||
{
|
||||
write_restart_settings(fp);
|
||||
|
||||
int i,j;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
fwrite(&setflag[i][j],sizeof(int),1,fp);
|
||||
if (setflag[i][j]) {
|
||||
if (exch_flag){
|
||||
fwrite(&J_1[i][j],sizeof(double),1,fp);
|
||||
fwrite(&J_2[i][j],sizeof(double),1,fp);
|
||||
fwrite(&J_3[i][j],sizeof(double),1,fp);
|
||||
fwrite(&cut_spin_exchange[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
if (dmi_flag) {
|
||||
fwrite(&DM[i][j],sizeof(double),1,fp);
|
||||
fwrite(&v_dmx[i][j],sizeof(double),1,fp);
|
||||
fwrite(&v_dmy[i][j],sizeof(double),1,fp);
|
||||
fwrite(&v_dmz[i][j],sizeof(double),1,fp);
|
||||
fwrite(&cut_spin_dmi[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
if (me_flag) {
|
||||
fwrite(&ME[i][j],sizeof(double),1,fp);
|
||||
fwrite(&v_mex[i][j],sizeof(double),1,fp);
|
||||
fwrite(&v_mey[i][j],sizeof(double),1,fp);
|
||||
fwrite(&v_mez[i][j],sizeof(double),1,fp);
|
||||
fwrite(&cut_spin_me[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::read_restart(FILE *fp)
|
||||
{
|
||||
read_restart_settings(fp);
|
||||
|
||||
allocate();
|
||||
|
||||
int i,j;
|
||||
int me = comm->me;
|
||||
for (i = 1; i <= atom->ntypes; i++)
|
||||
for (j = i; j <= atom->ntypes; j++) {
|
||||
if (me == 0) fread(&setflag[i][j],sizeof(int),1,fp);
|
||||
MPI_Bcast(&setflag[i][j],1,MPI_INT,0,world);
|
||||
if (setflag[i][j]) {
|
||||
if (me == 0) {
|
||||
fread(&J_1[i][j],sizeof(double),1,fp);
|
||||
fread(&J_2[i][j],sizeof(double),1,fp);
|
||||
fread(&J_2[i][j],sizeof(double),1,fp);
|
||||
fread(&cut_spin_exchange[i][j],sizeof(double),1,fp);
|
||||
}
|
||||
MPI_Bcast(&J_1[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&J_2[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&J_3[i][j],1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&cut_spin_exchange[i][j],1,MPI_DOUBLE,0,world);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 writes to restart file
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::write_restart_settings(FILE *fp)
|
||||
{
|
||||
fwrite(&cut_spin_pair_global,sizeof(double),1,fp);
|
||||
fwrite(&offset_flag,sizeof(int),1,fp);
|
||||
fwrite(&mix_flag,sizeof(int),1,fp);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
proc 0 reads from restart file, bcasts
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void PairSpin::read_restart_settings(FILE *fp)
|
||||
{
|
||||
if (comm->me == 0) {
|
||||
fread(&cut_spin_pair_global,sizeof(double),1,fp);
|
||||
fread(&offset_flag,sizeof(int),1,fp);
|
||||
fread(&mix_flag,sizeof(int),1,fp);
|
||||
}
|
||||
MPI_Bcast(&cut_spin_pair_global,1,MPI_DOUBLE,0,world);
|
||||
MPI_Bcast(&offset_flag,1,MPI_INT,0,world);
|
||||
MPI_Bcast(&mix_flag,1,MPI_INT,0,world);
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef PAIR_CLASS
|
||||
|
||||
PairStyle(pair/spin,PairSpin)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_PAIR_SPIN_H
|
||||
#define LMP_PAIR_SPIN_H
|
||||
|
||||
#include "pair.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PairSpin : public Pair {
|
||||
public:
|
||||
PairSpin(class LAMMPS *);
|
||||
virtual ~PairSpin();
|
||||
virtual void compute(int, int);
|
||||
void settings(int, char **);
|
||||
void coeff(int, char **);
|
||||
void init_style();
|
||||
double init_one(int, int);
|
||||
|
||||
void write_restart(FILE *);
|
||||
void read_restart(FILE *);
|
||||
void write_restart_settings(FILE *);
|
||||
void read_restart_settings(FILE *);
|
||||
|
||||
void compute_exchange(int, int, double, double *, double *);
|
||||
void compute_dmi(int, int, double *, double *);
|
||||
void compute_me(int, int, double *, double *);
|
||||
|
||||
//Test for seq. integ.
|
||||
//protected:
|
||||
int exch_flag,dmi_flag,me_flag;
|
||||
double cut_spin_pair_global;
|
||||
double cut_spin_dipolar_global;
|
||||
|
||||
double **cut_spin_exchange; //cutting distance exchange
|
||||
double **cut_spin_dmi; //cutting distance dmi
|
||||
double **cut_spin_me; //cutting distance me
|
||||
|
||||
//Test for seq. integ.
|
||||
protected:
|
||||
double **J_1, **J_2, **J_3; //exchange coeffs Jij
|
||||
//J1 in eV, J2 adim and J3 in Ang
|
||||
double **DM;
|
||||
double **v_dmx, **v_dmy, **v_dmz;//DMI coeffs
|
||||
//DM int. in eV, v direction
|
||||
|
||||
double **ME;
|
||||
double **v_mex, **v_mey, **v_mez;//ME coeffs
|
||||
//ME in eV, v direction
|
||||
|
||||
double *fmi, *fmj; //Temp var. in compute
|
||||
|
||||
void allocate();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Incorrect args in pair_style command
|
||||
|
||||
Self-explanatory.
|
||||
|
||||
E: Spin simulations require metal unit style
|
||||
|
||||
Self-explanatory.
|
||||
|
||||
E: Incorrect args for pair coefficients
|
||||
|
||||
Self-explanatory. Check the input script or data file.
|
||||
|
||||
E: Pair spin requires atom attributes sp, mumag
|
||||
|
||||
The atom style defined does not have these attributes.
|
||||
|
||||
*/
|
Loading…
Reference in New Issue