Commit JT 082318

- corrected memory errors in pppm_dipole and pppm_dipole_spin
- created fm_long in atom_vec_spin
- fm_long added to fm in initial_integrate (in ComputeInteractionsSpin)
This commit is contained in:
julient31
2018-08-23 15:18:30 -06:00
parent 8d79db03d3
commit cf1d421e10
17 changed files with 288 additions and 101 deletions

View File

@ -0,0 +1 @@
../cobalt_fcc/Co_PurjaPun_2012.eam.alloy

View File

@ -0,0 +1,32 @@
#Program fitting the exchange interaction
#Model curve: Bethe-Slater function
import numpy as np, pylab, tkinter
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from decimal import *
print("Loop begin")
#Definition of the Bethe-Slater function
def func(x,a,b,c):
return 4*a*((x/c)**2)*(1-b*(x/c)**2)*np.exp(-(x/c)**2)
#Exchange coeff table (data to fit)
rdata, Jdata = np.loadtxt('exchange_hcp_co.dat', usecols=(0,1), unpack=True)
plt.plot(rdata, Jdata, 'b-', label='data')
#Perform the fit
popt, pcov = curve_fit(func, rdata, Jdata, bounds=(0, [500.,5.,5.]))
plt.plot(rdata, func(rdata, *popt), 'r--', label='fit')
#Print the fitted params
print("Parameters: a={:.10} (in meV), b={:.10} (adim), c={:.10} (in Ang)".format(*popt))
#Ploting the result
plt.xlabel('r_ij')
pylab.xlim([0,6.5])
plt.ylabel('J_ij')
plt.legend()
plt.show()
print("Loop end")

View File

@ -0,0 +1,9 @@
2.25569176882662 73.37931034482759
2.3817863397548162 47.99999999999999
2.4518388791593697 34.39080459770115
2.507880910683012 31.816091954022987
2.5359019264448337 28.137931034482747
2.5779334500875657 25.011494252873554
2.6339754816112086 19.126436781609186
2.760070052539404 13.241379310344826
3.5446584938704033 6.068965517241367

View File

@ -0,0 +1,55 @@
# 3d Lennard-Jones melt
units lj
#atom_style charge
atom_style hybrid sphere dipole
processors * 1 1
lattice fcc 0.8442
#region box block 0 10 0 10 0 10
region box block 0 5 0 5 0 5
create_box 3 box
create_atoms 1 box
mass * 1.0
region long block 3 6 0 10 0 10
set region long type 2
set group all dipole/random 98934 0.75
#set type 1:2 charge 0.0
velocity all create 1.0 87287
#pair_style lj/long/coul/long long off 2.5
#pair_coeff * * 1.0 1.0 2.5
#pair_coeff * 2 1.0 1.0 5.0
pair_style lj/cut/dipole/long 3.0
pair_coeff * * 1.0 1.0
#kspace_style pppm/disp 1.0e-4
kspace_style pppm/dipole 1.0e-4
kspace_modify gewald/disp 0.1
neighbor 0.3 bin
neigh_modify every 2 delay 4 check yes
group fast type 1
group slow type 2
fix 0 all balance 20 1.0 shift x 5 1.0 &
weight group 2 fast 1.0 slow 2.0 weight time 0.66
fix 1 all nve
#dump id all atom 50 dump.melt
#dump 2 all image 25 image.*.jpg type type &
# axes yes 0.8 0.02 view 60 -30
#dump_modify 2 pad 3
#dump 3 all movie 25 movie.mpg type type &
# axes yes 0.8 0.02 view 60 -30
#dump_modify 3 pad 3
#thermo 50
thermo 1
#run 500
run 5

View File

@ -0,0 +1,61 @@
# hcp cobalt in a 3d periodic box
clear
units metal
atom_style spin
dimension 3
boundary p p p
# necessary for the serial algorithm (sametag)
atom_modify map array
lattice hcp 2.5071
region box block 0.0 20.0 0.0 20.0 0.0 8.0
create_box 1 box
create_atoms 1 box
# setting mass, mag. moments, and interactions for hcp cobalt
mass 1 58.93
#set group all spin/random 31 1.72
set group all spin 1.72 0.0 0.0 1.0
velocity all create 100 4928459 rot yes dist gaussian
pair_style hybrid/overlay eam/alloy spin/exchange 4.0 spin/long 8.0
#pair_style hybrid/overlay eam/alloy spin/exchange 4.0
pair_coeff * * eam/alloy ../examples/SPIN/pppm_spin/Co_PurjaPun_2012.eam.alloy Co
pair_coeff * * spin/exchange exchange 4.0 0.3593 1.135028015e-05 1.064568567
pair_coeff * * spin/long long 8.0
neighbor 0.1 bin
neigh_modify every 10 check yes delay 20
kspace_style pppm/dipole/spin 1.0e-4
#fix 1 all precession/spin zeeman 1.0 0.0 0.0 1.0
fix 1 all precession/spin zeeman 0.0 0.0 0.0 1.0
fix 2 all langevin/spin 0.0 0.0 21
fix 3 all nve/spin lattice yes
timestep 0.0001
compute out_mag all compute/spin
compute out_pe all pe
compute out_ke all ke
compute out_temp all temp
variable magz equal c_out_mag[3]
variable magnorm equal c_out_mag[4]
variable emag equal c_out_mag[5]
variable tmag equal c_out_mag[6]
thermo_style custom step time v_magnorm v_emag temp etotal
thermo 10
compute outsp all property/atom spx spy spz sp fmx fmy fmz
dump 100 all custom 1 dump_cobalt_hcp.lammpstrj type x y z c_outsp[1] c_outsp[2] c_outsp[3]
run 20000

View File

@ -100,6 +100,9 @@ PPPM::PPPM(LAMMPS *lmp, int narg, char **arg) : KSpace(lmp, narg, arg),
nyhi_in = nylo_in = nyhi_out = nylo_out = 0; nyhi_in = nylo_in = nyhi_out = nylo_out = 0;
nzhi_in = nzlo_in = nzhi_out = nzlo_out = 0; nzhi_in = nzlo_in = nzhi_out = nzlo_out = 0;
// test
nlower = nupper = 0;
density_brick = vdx_brick = vdy_brick = vdz_brick = NULL; density_brick = vdx_brick = vdy_brick = vdz_brick = NULL;
density_fft = NULL; density_fft = NULL;
u_brick = NULL; u_brick = NULL;
@ -1428,12 +1431,13 @@ void PPPM::set_grid_local()
double zprd = prd[2]; double zprd = prd[2];
double zprd_slab = zprd*slab_volfactor; double zprd_slab = zprd*slab_volfactor;
double dist[3]; double dist[3] = {0.0,0.0,0.0};
double cuthalf = 0.5*neighbor->skin + qdist; double cuthalf = 0.5*neighbor->skin + qdist;
if (triclinic == 0) dist[0] = dist[1] = dist[2] = cuthalf; if (triclinic == 0) dist[0] = dist[1] = dist[2] = cuthalf;
else kspacebbox(cuthalf,&dist[0]); else kspacebbox(cuthalf,&dist[0]);
int nlo,nhi; int nlo,nhi;
nlo = nhi = 0;
nlo = static_cast<int> ((sublo[0]-dist[0]-boxlo[0]) * nlo = static_cast<int> ((sublo[0]-dist[0]-boxlo[0]) *
nx_pppm/xprd + shift) - OFFSET; nx_pppm/xprd + shift) - OFFSET;

View File

@ -116,9 +116,10 @@ void PPPMDipole::init()
// error check // error check
dipoleflag = atom->mu?1:0; dipoleflag = atom->mu?1:0;
qsum_qsq(0); qsum_qsq(0); // q[i] might not be declared ?
if (dipoleflag && q2) if (dipoleflag && q2)
error->all(FLERR,"Cannot (yet) uses charges with Kspace style PPPMDipole"); error->all(FLERR,"Cannot (yet) use charges with Kspace style PPPMDipole");
triclinic_check(); triclinic_check();
@ -168,7 +169,9 @@ void PPPMDipole::init()
cutoff = *p_cutoff; cutoff = *p_cutoff;
// kspace TIP4P not yet supported // kspace TIP4P not yet supported
// qdist = offset only for TIP4P fictitious charge
qdist = 0.0;
if (tip4pflag) if (tip4pflag)
error->all(FLERR,"Cannot yet use TIP4P with PPPMDipole"); error->all(FLERR,"Cannot yet use TIP4P with PPPMDipole");
@ -206,7 +209,7 @@ void PPPMDipole::init()
"beyond nearest neighbor processor"); "beyond nearest neighbor processor");
compute_gf_denom(); compute_gf_denom();
set_grid_global(mu2); set_grid_global();
set_grid_local(); set_grid_local();
if (overlap_allowed) break; if (overlap_allowed) break;
@ -235,7 +238,7 @@ void PPPMDipole::init()
// calculate the final accuracy // calculate the final accuracy
double estimated_accuracy = final_accuracy_dipole(mu2); double estimated_accuracy = final_accuracy_dipole();
// print stats // print stats
@ -607,7 +610,7 @@ void PPPMDipole::allocate()
// summation coeffs // summation coeffs
order_allocated = order; order_allocated = order;
memory->create(gf_b,order,"pppm_dipole:gf_b"); if (!gf_b) memory->create(gf_b,order,"pppm_dipole:gf_b");
memory->create2d_offset(rho1d,3,-order/2,order/2,"pppm_dipole:rho1d"); memory->create2d_offset(rho1d,3,-order/2,order/2,"pppm_dipole:rho1d");
memory->create2d_offset(drho1d,3,-order/2,order/2,"pppm_dipole:drho1d"); memory->create2d_offset(drho1d,3,-order/2,order/2,"pppm_dipole:drho1d");
memory->create2d_offset(rho_coeff,order,(1-order)/2,order/2,"pppm_dipole:rho_coeff"); memory->create2d_offset(rho_coeff,order,(1-order)/2,order/2,"pppm_dipole:rho_coeff");
@ -791,7 +794,8 @@ void PPPMDipole::deallocate_peratom()
used for charge accumulation, FFTs, and electric field interpolation used for charge accumulation, FFTs, and electric field interpolation
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
void PPPMDipole::set_grid_global(double dipole2) //void PPPMDipole::set_grid_global(double dipole2)
void PPPMDipole::set_grid_global()
{ {
// use xprd,yprd,zprd // use xprd,yprd,zprd
// adjust z dimension for 2d slab PPPMDipole // adjust z dimension for 2d slab PPPMDipole
@ -813,14 +817,11 @@ void PPPMDipole::set_grid_global(double dipole2)
if (!gewaldflag) { if (!gewaldflag) {
if (accuracy <= 0.0) if (accuracy <= 0.0)
error->all(FLERR,"KSpace accuracy must be > 0"); error->all(FLERR,"KSpace accuracy must be > 0");
//if (mu2 == 0.0) if (mu2 == 0.0)
if (dipole2 == 0.0)
error->all(FLERR,"Must use kspace_modify gewald for systems with no dipoles"); error->all(FLERR,"Must use kspace_modify gewald for systems with no dipoles");
g_ewald = (1.35 - 0.15*log(accuracy))/cutoff; g_ewald = (1.35 - 0.15*log(accuracy))/cutoff;
//Try Newton Solver
double g_ewald_new = double g_ewald_new =
find_gewald_dipole(g_ewald,cutoff,natoms,xprd*yprd*zprd,dipole2); find_gewald_dipole(g_ewald,cutoff,natoms,xprd*yprd*zprd,mu2);
//find_gewald_dipole(g_ewald,cutoff,natoms,xprd*yprd*zprd,mu2);
if (g_ewald_new > 0.0) g_ewald = g_ewald_new; if (g_ewald_new > 0.0) g_ewald = g_ewald_new;
else error->warning(FLERR,"PPPMDipole dipole Newton solver failed, " else error->warning(FLERR,"PPPMDipole dipole Newton solver failed, "
"using old method to estimate g_ewald"); "using old method to estimate g_ewald");
@ -837,6 +838,7 @@ void PPPMDipole::set_grid_global(double dipole2)
while (1) { while (1) {
// set grid dimension // set grid dimension
nx_pppm = static_cast<int> (xprd/h_x); nx_pppm = static_cast<int> (xprd/h_x);
ny_pppm = static_cast<int> (yprd/h_y); ny_pppm = static_cast<int> (yprd/h_y);
nz_pppm = static_cast<int> (zprd_slab/h_z); nz_pppm = static_cast<int> (zprd_slab/h_z);
@ -845,7 +847,8 @@ void PPPMDipole::set_grid_global(double dipole2)
if (ny_pppm <= 1) ny_pppm = 2; if (ny_pppm <= 1) ny_pppm = 2;
if (nz_pppm <= 1) nz_pppm = 2; if (nz_pppm <= 1) nz_pppm = 2;
//set local grid dimension // set local grid dimension
int npey_fft,npez_fft; int npey_fft,npez_fft;
if (nz_pppm >= nprocs) { if (nz_pppm >= nprocs) {
npey_fft = 1; npey_fft = 1;
@ -862,7 +865,7 @@ void PPPMDipole::set_grid_global(double dipole2)
nzlo_fft = me_z*nz_pppm/npez_fft; nzlo_fft = me_z*nz_pppm/npez_fft;
nzhi_fft = (me_z+1)*nz_pppm/npez_fft - 1; nzhi_fft = (me_z+1)*nz_pppm/npez_fft - 1;
double df_kspace = compute_df_kspace_dipole(dipole2); double df_kspace = compute_df_kspace_dipole();
count++; count++;
@ -895,7 +898,7 @@ void PPPMDipole::set_grid_global(double dipole2)
compute estimated kspace force error for dipoles compute estimated kspace force error for dipoles
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
double PPPMDipole::compute_df_kspace_dipole(double dipole2) double PPPMDipole::compute_df_kspace_dipole()
{ {
double xprd = domain->xprd; double xprd = domain->xprd;
double yprd = domain->yprd; double yprd = domain->yprd;
@ -903,8 +906,7 @@ double PPPMDipole::compute_df_kspace_dipole(double dipole2)
double zprd_slab = zprd*slab_volfactor; double zprd_slab = zprd*slab_volfactor;
bigint natoms = atom->natoms; bigint natoms = atom->natoms;
double qopt = compute_qopt_dipole(); double qopt = compute_qopt_dipole();
//double df_kspace = sqrt(qopt/natoms)*mu2/(3.0*xprd*yprd*zprd_slab); double df_kspace = sqrt(qopt/natoms)*mu2/(3.0*xprd*yprd*zprd_slab);
double df_kspace = sqrt(qopt/natoms)*dipole2/(3.0*xprd*yprd*zprd_slab);
return df_kspace; return df_kspace;
} }
@ -1101,27 +1103,27 @@ void PPPMDipole::compute_gf_dipole()
calculate f(x) for use in Newton-Raphson solver calculate f(x) for use in Newton-Raphson solver
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
//double PPPMDipole::newton_raphson_f() double PPPMDipole::newton_raphson_f()
//{ {
// double xprd = domain->xprd; double xprd = domain->xprd;
// double yprd = domain->yprd; double yprd = domain->yprd;
// double zprd = domain->zprd; double zprd = domain->zprd;
// bigint natoms = atom->natoms; bigint natoms = atom->natoms;
//
// double df_rspace,df_kspace; double df_rspace,df_kspace;
// double vol = xprd*yprd*zprd; double vol = xprd*yprd*zprd;
// double a = cutoff*g_ewald; double a = cutoff*g_ewald;
// double rg2 = a*a; double rg2 = a*a;
// double rg4 = rg2*rg2; double rg4 = rg2*rg2;
// double rg6 = rg4*rg2; double rg6 = rg4*rg2;
// double Cc = 4.0*rg4 + 6.0*rg2 + 3.0; double Cc = 4.0*rg4 + 6.0*rg2 + 3.0;
// double Dc = 8.0*rg6 + 20.0*rg4 + 30.0*rg2 + 15.0; double Dc = 8.0*rg6 + 20.0*rg4 + 30.0*rg2 + 15.0;
// df_rspace = (mu2/(sqrt(vol*powint(g_ewald,4)*powint(cutoff,9)*natoms)) * df_rspace = (mu2/(sqrt(vol*powint(g_ewald,4)*powint(cutoff,9)*natoms)) *
// sqrt(13.0/6.0*Cc*Cc + 2.0/15.0*Dc*Dc - 13.0/15.0*Cc*Dc) * exp(-rg2)); sqrt(13.0/6.0*Cc*Cc + 2.0/15.0*Dc*Dc - 13.0/15.0*Cc*Dc) * exp(-rg2));
// df_kspace = compute_df_kspace_dipole(); df_kspace = compute_df_kspace_dipole();
//
// return df_rspace - df_kspace; return df_rspace - df_kspace;
//} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
find g_ewald parameter for dipoles based on desired accuracy find g_ewald parameter for dipoles based on desired accuracy
@ -1184,7 +1186,7 @@ double PPPMDipole::derivf_dipole(double x, double Rc,
calculate the final estimate of the accuracy calculate the final estimate of the accuracy
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
double PPPMDipole::final_accuracy_dipole(double dipole2) double PPPMDipole::final_accuracy_dipole()
{ {
double xprd = domain->xprd; double xprd = domain->xprd;
double yprd = domain->yprd; double yprd = domain->yprd;
@ -1193,7 +1195,7 @@ double PPPMDipole::final_accuracy_dipole(double dipole2)
bigint natoms = atom->natoms; bigint natoms = atom->natoms;
if (natoms == 0) natoms = 1; // avoid division by zero if (natoms == 0) natoms = 1; // avoid division by zero
double df_kspace = compute_df_kspace_dipole(mu2); double df_kspace = compute_df_kspace_dipole();
double a = cutoff*g_ewald; double a = cutoff*g_ewald;
double rg2 = a*a; double rg2 = a*a;
@ -1201,10 +1203,7 @@ double PPPMDipole::final_accuracy_dipole(double dipole2)
double rg6 = rg4*rg2; double rg6 = rg4*rg2;
double Cc = 4.0*rg4 + 6.0*rg2 + 3.0; double Cc = 4.0*rg4 + 6.0*rg2 + 3.0;
double Dc = 8.0*rg6 + 20.0*rg4 + 30.0*rg2 + 15.0; double Dc = 8.0*rg6 + 20.0*rg4 + 30.0*rg2 + 15.0;
//double df_rspace = (mu2/(sqrt(vol*powint(g_ewald,4)*powint(cutoff,9)*natoms)) * double df_rspace = (mu2/(sqrt(vol*powint(g_ewald,4)*powint(cutoff,9)*natoms)) *
// sqrt(13.0/6.0*Cc*Cc + 2.0/15.0*Dc*Dc - 13.0/15.0*Cc*Dc) *
// exp(-rg2));
double df_rspace = (dipole2/(sqrt(vol*powint(g_ewald,4)*powint(cutoff,9)*natoms)) *
sqrt(13.0/6.0*Cc*Cc + 2.0/15.0*Dc*Dc - 13.0/15.0*Cc*Dc) * sqrt(13.0/6.0*Cc*Cc + 2.0/15.0*Dc*Dc - 13.0/15.0*Cc*Dc) *
exp(-rg2)); exp(-rg2));
@ -2521,11 +2520,11 @@ double PPPMDipole::memory_usage()
double bytes = nmax*3 * sizeof(double); double bytes = nmax*3 * sizeof(double);
int nbrick = (nxhi_out-nxlo_out+1) * (nyhi_out-nylo_out+1) * int nbrick = (nxhi_out-nxlo_out+1) * (nyhi_out-nylo_out+1) *
(nzhi_out-nzlo_out+1); (nzhi_out-nzlo_out+1);
bytes += 6 * nfft_both * sizeof(double); // vg bytes += 6 * nfft_both * sizeof(double); // vg
bytes += nfft_both * sizeof(double); // greensfn bytes += nfft_both * sizeof(double); // greensfn
bytes += nfft_both*5 * sizeof(FFT_SCALAR); // work*2*2 bytes += nfft_both*5 * sizeof(FFT_SCALAR); // work*2*2
bytes += 9 * nbrick * sizeof(FFT_SCALAR); // ubrick*3 + vdbrick*6 bytes += 9 * nbrick * sizeof(FFT_SCALAR); // ubrick*3 + vdbrick*6
bytes += nfft_both*7 * sizeof(FFT_SCALAR); //density_ffx*3 + work*2*2 bytes += nfft_both*7 * sizeof(FFT_SCALAR); // density_ffx*3 + work*2*2
if (peratom_allocate_flag) if (peratom_allocate_flag)
bytes += 21 * nbrick * sizeof(FFT_SCALAR); bytes += 21 * nbrick * sizeof(FFT_SCALAR);

View File

@ -37,8 +37,8 @@ class PPPMDipole : public PPPM {
double memory_usage(); double memory_usage();
protected: protected:
void set_grid_global(double); void set_grid_global();
//double newton_raphson_f(); double newton_raphson_f();
void allocate(); void allocate();
void allocate_peratom(); void allocate_peratom();
@ -76,7 +76,7 @@ class PPPMDipole : public PPPM {
double find_gewald_dipole(double, double, bigint, double, double); double find_gewald_dipole(double, double, bigint, double, double);
double newton_raphson_f_dipole(double, double, bigint, double, double); double newton_raphson_f_dipole(double, double, bigint, double, double);
double derivf_dipole(double, double, bigint, double, double); double derivf_dipole(double, double, bigint, double, double);
double compute_df_kspace_dipole(double); double compute_df_kspace_dipole();
double compute_qopt_dipole(); double compute_qopt_dipole();
void compute_gf_dipole(); void compute_gf_dipole();
void make_rho_dipole(); void make_rho_dipole();
@ -85,7 +85,7 @@ class PPPMDipole : public PPPM {
void poisson_peratom_dipole(); void poisson_peratom_dipole();
void fieldforce_ik_dipole(); void fieldforce_ik_dipole();
void fieldforce_peratom_dipole(); void fieldforce_peratom_dipole();
double final_accuracy_dipole(double dipole2); double final_accuracy_dipole();
void musum_musq(); void musum_musq();
}; };

View File

@ -50,8 +50,8 @@ using namespace MathSpecial;
#define SMALL 0.00001 #define SMALL 0.00001
#define EPS_HOC 1.0e-7 #define EPS_HOC 1.0e-7
enum{REVERSE_SP}; enum{REVERSE_MU};
enum{FORWARD_SP,FORWARD_SP_PERATOM}; enum{FORWARD_MU,FORWARD_MU_PERATOM};
#ifdef FFT_SINGLE #ifdef FFT_SINGLE
#define ZEROF 0.0f #define ZEROF 0.0f
@ -68,10 +68,12 @@ PPPMDipoleSpin::PPPMDipoleSpin(LAMMPS *lmp, int narg, char **arg) :
{ {
dipoleflag = 0; dipoleflag = 0;
spinflag = 1; spinflag = 1;
group_group_enable = 0;
hbar = force->hplanck/MY_2PI; // eV/(rad.THz)
cg_dipole = NULL; mub = 5.78901e-5; // in eV/T
cg_peratom_dipole = NULL; mu_0 = 1.2566370614e-6; // in T.m/A
mub2mu0 = mub * mub * mu_0; // in eV
mub2mu0hbinv = mub2mu0 / hbar; // in rad.THz
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -104,7 +106,10 @@ void PPPMDipoleSpin::init()
// error check // error check
spinflag = atom->sp?1:0; spinflag = atom->sp?1:0;
//qsum_qsq(0); // q[i] is probably not declared ?
//if (spinflag && q2)
// error->all(FLERR,"Cannot use charges with Kspace style PPPMDipoleSpin");
triclinic_check(); triclinic_check();
if (triclinic != domain->triclinic) if (triclinic != domain->triclinic)
@ -118,8 +123,8 @@ void PPPMDipoleSpin::init()
if (!atom->sp) error->all(FLERR,"Kspace style requires atom attribute sp"); if (!atom->sp) error->all(FLERR,"Kspace style requires atom attribute sp");
if (atom->sp && differentiation_flag == 1) error->all(FLERR,"Cannot (yet) use kspace_modify diff" if (atom->sp && differentiation_flag == 1) error->all(FLERR,"Cannot (yet) use"
" ad with spins"); " kspace_modify diff ad with spins");
if (spinflag && strcmp(update->unit_style,"metal") != 0) if (spinflag && strcmp(update->unit_style,"metal") != 0)
error->all(FLERR,"'metal' units have to be used with spins"); error->all(FLERR,"'metal' units have to be used with spins");
@ -148,21 +153,19 @@ void PPPMDipoleSpin::init()
int itmp = 0; int itmp = 0;
double *p_cutoff = (double *) force->pair->extract("cut_coul",itmp); double *p_cutoff = (double *) force->pair->extract("cut_coul",itmp);
// probably not the correct extract here
if (p_cutoff == NULL) if (p_cutoff == NULL)
error->all(FLERR,"KSpace style is incompatible with Pair style"); error->all(FLERR,"KSpace style is incompatible with Pair style");
cutoff = *p_cutoff; cutoff = *p_cutoff;
// kspace TIP4P not yet supported // kspace TIP4P not yet supported
// qdist = offset only for TIP4P fictitious charge
qdist = 0.0;
if (tip4pflag) if (tip4pflag)
error->all(FLERR,"Cannot yet use TIP4P with PPPMDipoleSpin"); error->all(FLERR,"Cannot yet use TIP4P with PPPMDipoleSpin");
scale = 1.0; scale = 1.0;
hbar = force->hplanck/MY_2PI; // eV/(rad.THz)
mub = 5.78901e-5; // in eV/T
mu_0 = 1.2566370614e-6; // in T.m/A
mub2mu0 = mub * mub * mu_0; // in eV
mub2mu0hbinv = mub2mu0 / hbar; // in rad.THz
spsum_spsq(); spsum_spsq();
natoms_original = atom->natoms; natoms_original = atom->natoms;
@ -188,14 +191,14 @@ void PPPMDipoleSpin::init()
GridComm *cgtmp = NULL; GridComm *cgtmp = NULL;
int iteration = 0; int iteration = 0;
while (order >= minorder) { while (order >= minorder) {
if (iteration && me == 0) if (iteration && me == 0)
error->warning(FLERR,"Reducing PPPMDipoleSpin order b/c stencil extends " error->warning(FLERR,"Reducing PPPMDipoleSpin order b/c stencil extends "
"beyond nearest neighbor processor"); "beyond nearest neighbor processor");
compute_gf_denom(); compute_gf_denom();
set_grid_global(sp2); set_grid_global();
set_grid_local(); set_grid_local();
if (overlap_allowed) break; if (overlap_allowed) break;
@ -224,7 +227,7 @@ void PPPMDipoleSpin::init()
// calculate the final accuracy // calculate the final accuracy
double estimated_accuracy = final_accuracy_dipole(sp2); double estimated_accuracy = final_accuracy_dipole();
// print stats // print stats
@ -310,7 +313,7 @@ void PPPMDipoleSpin::compute(int eflag, int vflag)
// return if there are no spins // return if there are no spins
if (spsqsum == 0.0) return; if (musqsum == 0.0) return;
// convert atoms from box to lamda coords // convert atoms from box to lamda coords
@ -334,7 +337,7 @@ void PPPMDipoleSpin::compute(int eflag, int vflag)
// to fully sum contribution in their 3d bricks // to fully sum contribution in their 3d bricks
// remap from 3d decomposition to FFT decomposition // remap from 3d decomposition to FFT decomposition
cg_dipole->reverse_comm(this,REVERSE_SP); cg_dipole->reverse_comm(this,REVERSE_MU);
brick2fft_dipole(); brick2fft_dipole();
// compute potential gradient on my FFT grid and // compute potential gradient on my FFT grid and
@ -347,12 +350,12 @@ void PPPMDipoleSpin::compute(int eflag, int vflag)
// all procs communicate E-field values // all procs communicate E-field values
// to fill ghost cells surrounding their 3d bricks // to fill ghost cells surrounding their 3d bricks
cg_dipole->forward_comm(this,FORWARD_SP); cg_dipole->forward_comm(this,FORWARD_MU);
// extra per-atom energy/virial communication // extra per-atom energy/virial communication
if (evflag_atom) { if (evflag_atom) {
cg_peratom_dipole->forward_comm(this,FORWARD_SP_PERATOM); cg_peratom_dipole->forward_comm(this,FORWARD_MU_PERATOM);
} }
// calculate the force on my particles // calculate the force on my particles
@ -374,7 +377,7 @@ void PPPMDipoleSpin::compute(int eflag, int vflag)
energy = energy_all; energy = energy_all;
energy *= 0.5*volume; energy *= 0.5*volume;
energy -= spsqsum*2.0*g3/3.0/MY_PIS; energy -= musqsum*2.0*g3/3.0/MY_PIS;
energy *= spscale; energy *= spscale;
} }
@ -510,7 +513,7 @@ void PPPMDipoleSpin::fieldforce_ik_spin()
double spx,spy,spz; double spx,spy,spz;
double **x = atom->x; double **x = atom->x;
double **f = atom->f; double **f = atom->f;
double **fm = atom->fm; double **fm_long = atom->fm_long;
int nlocal = atom->nlocal; int nlocal = atom->nlocal;
@ -548,7 +551,7 @@ void PPPMDipoleSpin::fieldforce_ik_spin()
} }
} }
// convert M-field to mech. and mag. forces // convert M-field and store mech. forces
const double spfactor = mub2mu0 * scale; const double spfactor = mub2mu0 * scale;
spx = sp[i][0]*sp[i][3]; spx = sp[i][0]*sp[i][3];
@ -558,13 +561,12 @@ void PPPMDipoleSpin::fieldforce_ik_spin()
f[i][1] += spfactor*(vxy*spx + vyy*spy + vyz*spz); f[i][1] += spfactor*(vxy*spx + vyy*spy + vyz*spz);
f[i][2] += spfactor*(vxz*spx + vyz*spy + vzz*spz); f[i][2] += spfactor*(vxz*spx + vyz*spy + vzz*spz);
// store long-range mag. precessions
const double spfactorh = mub2mu0hbinv * scale; const double spfactorh = mub2mu0hbinv * scale;
fm[i][0] += spfactorh*ex; fm_long[i][0] += spfactorh*ex;
fm[i][1] += spfactorh*ey; fm_long[i][1] += spfactorh*ey;
fm[i][2] += spfactorh*ez; fm_long[i][2] += spfactorh*ez;
// create a new vector (in atom_spin style ?) to store long-range fm tables
} }
} }
@ -708,9 +710,11 @@ void PPPMDipoleSpin::slabcorr()
// add on mag. force corrections // add on mag. force corrections
double ffact = spscale * (-4.0*MY_PI/volume); double ffact = spscale * (-4.0*MY_PI/volume);
double **fm = atom->fm; //double **fm = atom->fm;
double **fm_long = atom->fm_long;
for (int i = 0; i < nlocal; i++) { for (int i = 0; i < nlocal; i++) {
fm[i][2] += ffact * spin_all; //fm[i][2] += ffact * spin_all;
fm_long[i][2] += ffact * spin_all;
} }
} }
@ -723,13 +727,13 @@ void PPPMDipoleSpin::spsum_spsq()
{ {
const int nlocal = atom->nlocal; const int nlocal = atom->nlocal;
spsum = spsqsum = sp2 = 0.0; musum = musqsum = mu2 = 0.0;
if (atom->sp_flag) { if (atom->sp_flag) {
double **sp = atom->sp; double **sp = atom->sp;
double spx, spy, spz; double spx, spy, spz;
double spsum_local(0.0), spsqsum_local(0.0); double spsum_local(0.0), spsqsum_local(0.0);
// not exactly the good loop: need to add norm of spins // sum (direction x norm) of all spins
for (int i = 0; i < nlocal; i++) { for (int i = 0; i < nlocal; i++) {
spx = sp[i][0]*sp[i][3]; spx = sp[i][0]*sp[i][3];
@ -739,12 +743,14 @@ void PPPMDipoleSpin::spsum_spsq()
spsqsum_local += spx*spx + spy*spy + spz*spz; spsqsum_local += spx*spx + spy*spy + spz*spz;
} }
MPI_Allreduce(&spsum_local,&spsum,1,MPI_DOUBLE,MPI_SUM,world); // store results into pppm_dipole quantities
MPI_Allreduce(&spsqsum_local,&spsqsum,1,MPI_DOUBLE,MPI_SUM,world);
sp2 = spsqsum * mub2mu0; MPI_Allreduce(&spsum_local,&musum,1,MPI_DOUBLE,MPI_SUM,world);
MPI_Allreduce(&spsqsum_local,&musqsum,1,MPI_DOUBLE,MPI_SUM,world);
mu2 = musqsum * mub2mu0;
} }
if (sp2 == 0 && comm->me == 0) if (mu2 == 0 && comm->me == 0)
error->all(FLERR,"Using kspace solver PPPMDipoleSpin on system with no spins"); error->all(FLERR,"Using kspace solver PPPMDipoleSpin on system with no spins");
} }

View File

@ -42,7 +42,6 @@ class PPPMDipoleSpin : public PPPMDipole {
// spin // spin
double spsum,spsqsum,sp2;
void make_rho_spin(); void make_rho_spin();
void fieldforce_ik_spin(); void fieldforce_ik_spin();
void fieldforce_peratom_spin(); void fieldforce_peratom_spin();

View File

@ -106,7 +106,6 @@ void AtomVecSpin::grow_reset()
sp = atom->sp; fm = atom->fm; fm_long = atom->fm_long; sp = atom->sp; fm = atom->fm; fm_long = atom->fm_long;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
copy atom I info to atom J copy atom I info to atom J
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */

View File

@ -126,6 +126,7 @@ FixNVESpin::FixNVESpin(LAMMPS *lmp, int narg, char **arg) :
// initialize the magnetic interaction flags // initialize the magnetic interaction flags
pair_spin_flag = 0; pair_spin_flag = 0;
long_spin_flag = 0;
precession_spin_flag = 0; precession_spin_flag = 0;
maglangevin_flag = 0; maglangevin_flag = 0;
tdamp_flag = temp_flag = 0; tdamp_flag = temp_flag = 0;
@ -209,8 +210,16 @@ void FixNVESpin::init()
if (count != npairspin) if (count != npairspin)
error->all(FLERR,"Incorrect number of spin pairs"); error->all(FLERR,"Incorrect number of spin pairs");
// set pair/spin and long/spin flags
if (npairspin >= 1) pair_spin_flag = 1; if (npairspin >= 1) pair_spin_flag = 1;
for (int i = 0; i<npairs; i++) {
if (force->pair_match("spin/long",0,i)) {
long_spin_flag = 1;
}
}
// ptrs FixPrecessionSpin classes // ptrs FixPrecessionSpin classes
int iforce; int iforce;
@ -425,6 +434,7 @@ void FixNVESpin::ComputeInteractionsSpin(int i)
double **sp = atom->sp; double **sp = atom->sp;
double **fm = atom->fm; double **fm = atom->fm;
double **fm_long = atom->fm_long;
// force computation for spin i // force computation for spin i
@ -442,6 +452,14 @@ void FixNVESpin::ComputeInteractionsSpin(int i)
} }
} }
// update magnetic long-range components
if (long_spin_flag) {
fmi[0] += fm_long[i][0];
fmi[1] += fm_long[i][1];
fmi[2] += fm_long[i][2];
}
// update magnetic precession interactions // update magnetic precession interactions
if (precession_spin_flag) { if (precession_spin_flag) {

View File

@ -58,7 +58,8 @@ friend class PairSpin;
int nlocal_max; // max value of nlocal (for lists size) int nlocal_max; // max value of nlocal (for lists size)
int pair_spin_flag; // magnetic pair flags int pair_spin_flag; // magnetic pair flags
int precession_spin_flag; // magnetic precession flags int long_spin_flag; // magnetic long-range flag
int precession_spin_flag; // magnetic precession flags
int maglangevin_flag; // magnetic langevin flags int maglangevin_flag; // magnetic langevin flags
int tdamp_flag, temp_flag; int tdamp_flag, temp_flag;

View File

@ -81,6 +81,7 @@ PairSpinLong::~PairSpinLong()
if (allocated) { if (allocated) {
memory->destroy(setflag); memory->destroy(setflag);
memory->destroy(cut_spin_long); memory->destroy(cut_spin_long);
memory->destroy(cutsq);
} }
} }
@ -97,7 +98,6 @@ void PairSpinLong::settings(int narg, char **arg)
error->all(FLERR,"Spin simulations require metal unit style"); error->all(FLERR,"Spin simulations require metal unit style");
cut_spin_long_global = force->numeric(FLERR,arg[0]); cut_spin_long_global = force->numeric(FLERR,arg[0]);
//cut_spin = force->numeric(FLERR,arg[0]);
// reset cutoffs that have been explicitly set // reset cutoffs that have been explicitly set
@ -126,7 +126,7 @@ void PairSpinLong::coeff(int narg, char **arg)
if (strcmp(arg[2],"long") != 0) if (strcmp(arg[2],"long") != 0)
error->all(FLERR,"Incorrect args in pair_style command"); error->all(FLERR,"Incorrect args in pair_style command");
if (narg != 3) if (narg < 1 || narg > 4)
error->all(FLERR,"Incorrect args in pair_style command"); error->all(FLERR,"Incorrect args in pair_style command");
int ilo,ihi,jlo,jhi; int ilo,ihi,jlo,jhi;
@ -197,9 +197,9 @@ void PairSpinLong::init_style()
double PairSpinLong::init_one(int i, int j) double PairSpinLong::init_one(int i, int j)
{ {
if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set"); if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set");
cut_spin_long[j][i] = cut_spin_long[i][j]; cut_spin_long[j][i] = cut_spin_long[i][j];
return cut_spin_long_global; return cut_spin_long_global;
} }
@ -505,7 +505,8 @@ void PairSpinLong::allocate()
for (int j = i; j <= n; j++) for (int j = i; j <= n; j++)
setflag[i][j] = 0; setflag[i][j] = 0;
memory->create(cut_spin_long,n+1,n+1,"pair:cut_spin_long"); memory->create(cut_spin_long,n+1,n+1,"pair/spin/long:cut_spin_long");
memory->create(cutsq,n+1,n+1,"pair/spin/long:cutsq");
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------

View File

@ -98,7 +98,7 @@ Atom::Atom(LAMMPS *lmp) : Pointers(lmp)
// SPIN package // SPIN package
sp = fm = NULL; sp = fm = fm_long = NULL;
// USER-DPD // USER-DPD
@ -277,6 +277,7 @@ Atom::~Atom()
memory->destroy(sp); memory->destroy(sp);
memory->destroy(fm); memory->destroy(fm);
memory->destroy(fm_long);
memory->destroy(vfrac); memory->destroy(vfrac);
memory->destroy(s0); memory->destroy(s0);

View File

@ -65,6 +65,7 @@ class Atom : protected Pointers {
double **sp; double **sp;
double **fm; double **fm;
double **fm_long;
// PERI package // PERI package

View File

@ -61,7 +61,7 @@ class Pair : protected Pointers {
int dispersionflag; // 1 if compatible with LJ/dispersion solver int dispersionflag; // 1 if compatible with LJ/dispersion solver
int tip4pflag; // 1 if compatible with TIP4P solver int tip4pflag; // 1 if compatible with TIP4P solver
int dipoleflag; // 1 if compatible with dipole solver int dipoleflag; // 1 if compatible with dipole solver
int spinflag; // 1 if compatible with spin long solver int spinflag; // 1 if compatible with spin solver
int reinitflag; // 1 if compatible with fix adapt and alike int reinitflag; // 1 if compatible with fix adapt and alike
int tail_flag; // pair_modify flag for LJ tail correction int tail_flag; // pair_modify flag for LJ tail correction