forked from lijiext/lammps
git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@10130 f3b2605a-c512-4ea7-a41b-209d697bcdaa
This commit is contained in:
parent
1e4b3bcf87
commit
440d389779
6784
src/KSPACE/pppm.cpp
6784
src/KSPACE/pppm.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,335 +1,335 @@
|
|||
/* -*- 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 KSPACE_CLASS
|
||||
|
||||
KSpaceStyle(pppm,PPPM)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_PPPM_H
|
||||
#define LMP_PPPM_H
|
||||
|
||||
#include "lmptype.h"
|
||||
#include "mpi.h"
|
||||
|
||||
#ifdef FFT_SINGLE
|
||||
typedef float FFT_SCALAR;
|
||||
#define MPI_FFT_SCALAR MPI_FLOAT
|
||||
#else
|
||||
typedef double FFT_SCALAR;
|
||||
#define MPI_FFT_SCALAR MPI_DOUBLE
|
||||
#endif
|
||||
|
||||
#include "kspace.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PPPM : public KSpace {
|
||||
public:
|
||||
PPPM(class LAMMPS *, int, char **);
|
||||
virtual ~PPPM();
|
||||
virtual void init();
|
||||
virtual void setup();
|
||||
void setup_grid();
|
||||
virtual void compute(int, int);
|
||||
virtual int timing_1d(int, double &);
|
||||
virtual int timing_3d(int, double &);
|
||||
virtual double memory_usage();
|
||||
|
||||
virtual void compute_group_group(int, int, int);
|
||||
|
||||
protected:
|
||||
int me,nprocs;
|
||||
int nfactors;
|
||||
int *factors;
|
||||
double qsum,qsqsum,q2;
|
||||
double cutoff;
|
||||
double volume;
|
||||
double delxinv,delyinv,delzinv,delvolinv;
|
||||
double h_x,h_y,h_z;
|
||||
double shift,shiftone;
|
||||
int peratom_allocate_flag;
|
||||
|
||||
int nxlo_in,nylo_in,nzlo_in,nxhi_in,nyhi_in,nzhi_in;
|
||||
int nxlo_out,nylo_out,nzlo_out,nxhi_out,nyhi_out,nzhi_out;
|
||||
int nxlo_ghost,nxhi_ghost,nylo_ghost,nyhi_ghost,nzlo_ghost,nzhi_ghost;
|
||||
int nxlo_fft,nylo_fft,nzlo_fft,nxhi_fft,nyhi_fft,nzhi_fft;
|
||||
int nlower,nupper;
|
||||
int ngrid,nfft,nfft_both;
|
||||
|
||||
FFT_SCALAR ***density_brick;
|
||||
FFT_SCALAR ***vdx_brick,***vdy_brick,***vdz_brick;
|
||||
FFT_SCALAR ***u_brick;
|
||||
FFT_SCALAR ***v0_brick,***v1_brick,***v2_brick;
|
||||
FFT_SCALAR ***v3_brick,***v4_brick,***v5_brick;
|
||||
double *greensfn;
|
||||
double **vg;
|
||||
double *fkx,*fky,*fkz;
|
||||
FFT_SCALAR *density_fft;
|
||||
FFT_SCALAR *work1,*work2;
|
||||
|
||||
double *gf_b;
|
||||
FFT_SCALAR **rho1d,**rho_coeff,**drho1d,**drho_coeff;
|
||||
double *sf_precoeff1, *sf_precoeff2, *sf_precoeff3;
|
||||
double *sf_precoeff4, *sf_precoeff5, *sf_precoeff6;
|
||||
double sf_coeff[6]; // coefficients for calculating ad self-forces
|
||||
double **acons;
|
||||
|
||||
// group-group interactions
|
||||
|
||||
int group_allocate_flag;
|
||||
FFT_SCALAR ***density_A_brick,***density_B_brick;
|
||||
FFT_SCALAR *density_A_fft,*density_B_fft;
|
||||
|
||||
class FFT3d *fft1,*fft2;
|
||||
class Remap *remap;
|
||||
class CommGrid *cg;
|
||||
class CommGrid *cg_peratom;
|
||||
|
||||
int **part2grid; // storage for particle -> grid mapping
|
||||
int nmax;
|
||||
|
||||
double *boxlo;
|
||||
// TIP4P settings
|
||||
int typeH,typeO; // atom types of TIP4P water H and O atoms
|
||||
double qdist; // distance from O site to negative charge
|
||||
double alpha; // geometric factor
|
||||
|
||||
void set_grid_global();
|
||||
void set_grid_local();
|
||||
void adjust_gewald();
|
||||
double newton_raphson_f();
|
||||
double derivf();
|
||||
double final_accuracy();
|
||||
|
||||
virtual void allocate();
|
||||
virtual void allocate_peratom();
|
||||
virtual void deallocate();
|
||||
virtual void deallocate_peratom();
|
||||
int factorable(int);
|
||||
double compute_df_kspace();
|
||||
double estimate_ik_error(double, double, bigint);
|
||||
double compute_qopt();
|
||||
void compute_gf_denom();
|
||||
virtual void compute_gf_ik();
|
||||
virtual void compute_gf_ad();
|
||||
void compute_sf_precoeff();
|
||||
|
||||
virtual void particle_map();
|
||||
virtual void make_rho();
|
||||
virtual void brick2fft();
|
||||
|
||||
virtual void poisson();
|
||||
virtual void poisson_ik();
|
||||
virtual void poisson_ad();
|
||||
|
||||
virtual void fieldforce();
|
||||
virtual void fieldforce_ik();
|
||||
virtual void fieldforce_ad();
|
||||
|
||||
virtual void poisson_peratom();
|
||||
virtual void fieldforce_peratom();
|
||||
void procs2grid2d(int,int,int,int *, int*);
|
||||
void compute_rho1d(const FFT_SCALAR &, const FFT_SCALAR &,
|
||||
const FFT_SCALAR &);
|
||||
void compute_drho1d(const FFT_SCALAR &, const FFT_SCALAR &,
|
||||
const FFT_SCALAR &);
|
||||
void compute_rho_coeff();
|
||||
void slabcorr();
|
||||
|
||||
// grid communication
|
||||
|
||||
virtual void pack_forward(int, FFT_SCALAR *, int, int *);
|
||||
virtual void unpack_forward(int, FFT_SCALAR *, int, int *);
|
||||
virtual void pack_reverse(int, FFT_SCALAR *, int, int *);
|
||||
virtual void unpack_reverse(int, FFT_SCALAR *, int, int *);
|
||||
|
||||
// triclinic
|
||||
|
||||
int triclinic; // domain settings, orthog or triclinic
|
||||
void setup_triclinic();
|
||||
void compute_gf_ik_triclinic();
|
||||
void poisson_ik_triclinic();
|
||||
void poisson_groups_triclinic();
|
||||
|
||||
// group-group interactions
|
||||
|
||||
virtual void allocate_groups();
|
||||
virtual void deallocate_groups();
|
||||
virtual void make_rho_groups(int, int, int);
|
||||
virtual void poisson_groups(int);
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
denominator for Hockney-Eastwood Green's function
|
||||
of x,y,z = sin(kx*deltax/2), etc
|
||||
|
||||
inf n-1
|
||||
S(n,k) = Sum W(k+pi*j)**2 = Sum b(l)*(z*z)**l
|
||||
j=-inf l=0
|
||||
|
||||
= -(z*z)**n /(2n-1)! * (d/dx)**(2n-1) cot(x) at z = sin(x)
|
||||
gf_b = denominator expansion coeffs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
inline double gf_denom(const double &x, const double &y,
|
||||
const double &z) const {
|
||||
double sx,sy,sz;
|
||||
sz = sy = sx = 0.0;
|
||||
for (int l = order-1; l >= 0; l--) {
|
||||
sx = gf_b[l] + sx*x;
|
||||
sy = gf_b[l] + sy*y;
|
||||
sz = gf_b[l] + sz*z;
|
||||
}
|
||||
double s = sx*sy*sz;
|
||||
return s*s;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#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: Cannot (yet) use PPPM with triclinic box and 'kspace_modify diff ad'
|
||||
|
||||
This feature is not yet supported.
|
||||
|
||||
E: Cannot (yet) use PPPM with triclinic box and slab correction
|
||||
|
||||
This feature is not yet supported.
|
||||
|
||||
E: Cannot use PPPM with 2d simulation
|
||||
|
||||
The kspace style pppm cannot be used in 2d simulations. You can use
|
||||
2d PPPM in a 3d simulation; see the kspace_modify command.
|
||||
|
||||
E: Kspace style requires atom attribute q
|
||||
|
||||
The atom style defined does not have these attributes.
|
||||
|
||||
E: Cannot use nonperiodic boundaries with PPPM
|
||||
|
||||
For kspace style pppm, all 3 dimensions must have periodic boundaries
|
||||
unless you use the kspace_modify command to define a 2d slab with a
|
||||
non-periodic z dimension.
|
||||
|
||||
E: Incorrect boundaries with slab PPPM
|
||||
|
||||
Must have periodic x,y dimensions and non-periodic z dimension to use
|
||||
2d slab option with PPPM.
|
||||
|
||||
E: PPPM order cannot be < 2 or > than %d
|
||||
|
||||
This is a limitation of the PPPM implementation in LAMMPS.
|
||||
|
||||
E: KSpace style is incompatible with Pair style
|
||||
|
||||
Setting a kspace style requires that a pair style with a long-range
|
||||
Coulombic or dispersion component be used.
|
||||
|
||||
E: Bond and angle potentials must be defined for TIP4P
|
||||
|
||||
Cannot use TIP4P pair potential unless bond and angle potentials
|
||||
are defined.
|
||||
|
||||
E: Bad TIP4P angle type for PPPM/TIP4P
|
||||
|
||||
Specified angle type is not valid.
|
||||
|
||||
E: Bad TIP4P bond type for PPPM/TIP4P
|
||||
|
||||
Specified bond type is not valid.
|
||||
|
||||
E: Cannot (yet) use PPPM with triclinic box and TIP4P
|
||||
|
||||
This feature is not yet supported.
|
||||
|
||||
E: Cannot use kspace solver on system with no charge
|
||||
|
||||
No atoms in system have a non-zero charge.
|
||||
|
||||
W: System is not charge neutral, net charge = %g
|
||||
|
||||
The total charge on all atoms on the system is not 0.0, which
|
||||
is not valid for the long-range Coulombic solvers.
|
||||
|
||||
W: Reducing PPPM order b/c stencil extends beyond nearest neighbor processor
|
||||
|
||||
This may lead to a larger grid than desired. See the kspace_modify overlap
|
||||
command to prevent changing of the PPPM order.
|
||||
|
||||
E: PPPM order < minimum allowed order
|
||||
|
||||
The default minimum order is 2. This can be reset by the
|
||||
kspace_modify minorder command.
|
||||
|
||||
E: PPPM grid stencil extends beyond nearest neighbor processor
|
||||
|
||||
This is not allowed if the kspace_modify overlap setting is no.
|
||||
|
||||
E: KSpace accuracy must be > 0
|
||||
|
||||
The kspace accuracy designated in the input must be greater than zero.
|
||||
|
||||
E: Could not compute grid size
|
||||
|
||||
The code is unable to compute a grid size consistent with the desired
|
||||
accuracy. This error should not occur for typical problems. Please
|
||||
send an email to the developers.
|
||||
|
||||
E: PPPM grid is too large
|
||||
|
||||
The global PPPM grid is larger than OFFSET in one or more dimensions.
|
||||
OFFSET is currently set to 4096. You likely need to decrease the
|
||||
requested accuracy.
|
||||
|
||||
E: Could not compute g_ewald
|
||||
|
||||
The Newton-Raphson solver failed to converge to a good value for
|
||||
g_ewald. This error should not occur for typical problems. Please
|
||||
send an email to the developers.
|
||||
|
||||
E: Out of range atoms - cannot compute PPPM
|
||||
|
||||
One or more atoms are attempting to map their charge to a PPPM grid
|
||||
point that is not owned by a processor. This is likely for one of two
|
||||
reasons, both of them bad. First, it may mean that an atom near the
|
||||
boundary of a processor's sub-domain has moved more than 1/2 the
|
||||
"neighbor skin distance"_neighbor.html without neighbor lists being
|
||||
rebuilt and atoms being migrated to new processors. This also means
|
||||
you may be missing pairwise interactions that need to be computed.
|
||||
The solution is to change the re-neighboring criteria via the
|
||||
"neigh_modify"_neigh_modify command. The safest settings are "delay 0
|
||||
every 1 check yes". Second, it may mean that an atom has moved far
|
||||
outside a processor's sub-domain or even the entire simulation box.
|
||||
This indicates bad physics, e.g. due to highly overlapping atoms, too
|
||||
large a timestep, etc.
|
||||
|
||||
E: Cannot (yet) use K-space slab correction with compute group/group
|
||||
|
||||
This option is not yet supported.
|
||||
|
||||
E: Cannot (yet) use 'kspace_modify diff ad' with compute group/group
|
||||
|
||||
This option is not yet supported.
|
||||
|
||||
*/
|
||||
/* -*- 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 KSPACE_CLASS
|
||||
|
||||
KSpaceStyle(pppm,PPPM)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_PPPM_H
|
||||
#define LMP_PPPM_H
|
||||
|
||||
#include "lmptype.h"
|
||||
#include "mpi.h"
|
||||
|
||||
#ifdef FFT_SINGLE
|
||||
typedef float FFT_SCALAR;
|
||||
#define MPI_FFT_SCALAR MPI_FLOAT
|
||||
#else
|
||||
typedef double FFT_SCALAR;
|
||||
#define MPI_FFT_SCALAR MPI_DOUBLE
|
||||
#endif
|
||||
|
||||
#include "kspace.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class PPPM : public KSpace {
|
||||
public:
|
||||
PPPM(class LAMMPS *, int, char **);
|
||||
virtual ~PPPM();
|
||||
virtual void init();
|
||||
virtual void setup();
|
||||
void setup_grid();
|
||||
virtual void compute(int, int);
|
||||
virtual int timing_1d(int, double &);
|
||||
virtual int timing_3d(int, double &);
|
||||
virtual double memory_usage();
|
||||
|
||||
virtual void compute_group_group(int, int, int);
|
||||
|
||||
protected:
|
||||
int me,nprocs;
|
||||
int nfactors;
|
||||
int *factors;
|
||||
double qsum,qsqsum,q2;
|
||||
double cutoff;
|
||||
double volume;
|
||||
double delxinv,delyinv,delzinv,delvolinv;
|
||||
double h_x,h_y,h_z;
|
||||
double shift,shiftone;
|
||||
int peratom_allocate_flag;
|
||||
|
||||
int nxlo_in,nylo_in,nzlo_in,nxhi_in,nyhi_in,nzhi_in;
|
||||
int nxlo_out,nylo_out,nzlo_out,nxhi_out,nyhi_out,nzhi_out;
|
||||
int nxlo_ghost,nxhi_ghost,nylo_ghost,nyhi_ghost,nzlo_ghost,nzhi_ghost;
|
||||
int nxlo_fft,nylo_fft,nzlo_fft,nxhi_fft,nyhi_fft,nzhi_fft;
|
||||
int nlower,nupper;
|
||||
int ngrid,nfft,nfft_both;
|
||||
|
||||
FFT_SCALAR ***density_brick;
|
||||
FFT_SCALAR ***vdx_brick,***vdy_brick,***vdz_brick;
|
||||
FFT_SCALAR ***u_brick;
|
||||
FFT_SCALAR ***v0_brick,***v1_brick,***v2_brick;
|
||||
FFT_SCALAR ***v3_brick,***v4_brick,***v5_brick;
|
||||
double *greensfn;
|
||||
double **vg;
|
||||
double *fkx,*fky,*fkz;
|
||||
FFT_SCALAR *density_fft;
|
||||
FFT_SCALAR *work1,*work2;
|
||||
|
||||
double *gf_b;
|
||||
FFT_SCALAR **rho1d,**rho_coeff,**drho1d,**drho_coeff;
|
||||
double *sf_precoeff1, *sf_precoeff2, *sf_precoeff3;
|
||||
double *sf_precoeff4, *sf_precoeff5, *sf_precoeff6;
|
||||
double sf_coeff[6]; // coefficients for calculating ad self-forces
|
||||
double **acons;
|
||||
|
||||
// group-group interactions
|
||||
|
||||
int group_allocate_flag;
|
||||
FFT_SCALAR ***density_A_brick,***density_B_brick;
|
||||
FFT_SCALAR *density_A_fft,*density_B_fft;
|
||||
|
||||
class FFT3d *fft1,*fft2;
|
||||
class Remap *remap;
|
||||
class CommGrid *cg;
|
||||
class CommGrid *cg_peratom;
|
||||
|
||||
int **part2grid; // storage for particle -> grid mapping
|
||||
int nmax;
|
||||
|
||||
double *boxlo;
|
||||
// TIP4P settings
|
||||
int typeH,typeO; // atom types of TIP4P water H and O atoms
|
||||
double qdist; // distance from O site to negative charge
|
||||
double alpha; // geometric factor
|
||||
|
||||
void set_grid_global();
|
||||
void set_grid_local();
|
||||
void adjust_gewald();
|
||||
double newton_raphson_f();
|
||||
double derivf();
|
||||
double final_accuracy();
|
||||
|
||||
virtual void allocate();
|
||||
virtual void allocate_peratom();
|
||||
virtual void deallocate();
|
||||
virtual void deallocate_peratom();
|
||||
int factorable(int);
|
||||
double compute_df_kspace();
|
||||
double estimate_ik_error(double, double, bigint);
|
||||
virtual double compute_qopt();
|
||||
virtual void compute_gf_denom();
|
||||
virtual void compute_gf_ik();
|
||||
virtual void compute_gf_ad();
|
||||
void compute_sf_precoeff();
|
||||
|
||||
virtual void particle_map();
|
||||
virtual void make_rho();
|
||||
virtual void brick2fft();
|
||||
|
||||
virtual void poisson();
|
||||
virtual void poisson_ik();
|
||||
virtual void poisson_ad();
|
||||
|
||||
virtual void fieldforce();
|
||||
virtual void fieldforce_ik();
|
||||
virtual void fieldforce_ad();
|
||||
|
||||
virtual void poisson_peratom();
|
||||
virtual void fieldforce_peratom();
|
||||
void procs2grid2d(int,int,int,int *, int*);
|
||||
void compute_rho1d(const FFT_SCALAR &, const FFT_SCALAR &,
|
||||
const FFT_SCALAR &);
|
||||
void compute_drho1d(const FFT_SCALAR &, const FFT_SCALAR &,
|
||||
const FFT_SCALAR &);
|
||||
void compute_rho_coeff();
|
||||
void slabcorr();
|
||||
|
||||
// grid communication
|
||||
|
||||
virtual void pack_forward(int, FFT_SCALAR *, int, int *);
|
||||
virtual void unpack_forward(int, FFT_SCALAR *, int, int *);
|
||||
virtual void pack_reverse(int, FFT_SCALAR *, int, int *);
|
||||
virtual void unpack_reverse(int, FFT_SCALAR *, int, int *);
|
||||
|
||||
// triclinic
|
||||
|
||||
int triclinic; // domain settings, orthog or triclinic
|
||||
void setup_triclinic();
|
||||
void compute_gf_ik_triclinic();
|
||||
void poisson_ik_triclinic();
|
||||
void poisson_groups_triclinic();
|
||||
|
||||
// group-group interactions
|
||||
|
||||
virtual void allocate_groups();
|
||||
virtual void deallocate_groups();
|
||||
virtual void make_rho_groups(int, int, int);
|
||||
virtual void poisson_groups(int);
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
denominator for Hockney-Eastwood Green's function
|
||||
of x,y,z = sin(kx*deltax/2), etc
|
||||
|
||||
inf n-1
|
||||
S(n,k) = Sum W(k+pi*j)**2 = Sum b(l)*(z*z)**l
|
||||
j=-inf l=0
|
||||
|
||||
= -(z*z)**n /(2n-1)! * (d/dx)**(2n-1) cot(x) at z = sin(x)
|
||||
gf_b = denominator expansion coeffs
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
inline double gf_denom(const double &x, const double &y,
|
||||
const double &z) const {
|
||||
double sx,sy,sz;
|
||||
sz = sy = sx = 0.0;
|
||||
for (int l = order-1; l >= 0; l--) {
|
||||
sx = gf_b[l] + sx*x;
|
||||
sy = gf_b[l] + sy*y;
|
||||
sz = gf_b[l] + sz*z;
|
||||
}
|
||||
double s = sx*sy*sz;
|
||||
return s*s;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#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: Cannot (yet) use PPPM with triclinic box and 'kspace_modify diff ad'
|
||||
|
||||
This feature is not yet supported.
|
||||
|
||||
E: Cannot (yet) use PPPM with triclinic box and slab correction
|
||||
|
||||
This feature is not yet supported.
|
||||
|
||||
E: Cannot use PPPM with 2d simulation
|
||||
|
||||
The kspace style pppm cannot be used in 2d simulations. You can use
|
||||
2d PPPM in a 3d simulation; see the kspace_modify command.
|
||||
|
||||
E: Kspace style requires atom attribute q
|
||||
|
||||
The atom style defined does not have these attributes.
|
||||
|
||||
E: Cannot use nonperiodic boundaries with PPPM
|
||||
|
||||
For kspace style pppm, all 3 dimensions must have periodic boundaries
|
||||
unless you use the kspace_modify command to define a 2d slab with a
|
||||
non-periodic z dimension.
|
||||
|
||||
E: Incorrect boundaries with slab PPPM
|
||||
|
||||
Must have periodic x,y dimensions and non-periodic z dimension to use
|
||||
2d slab option with PPPM.
|
||||
|
||||
E: PPPM order cannot be < 2 or > than %d
|
||||
|
||||
This is a limitation of the PPPM implementation in LAMMPS.
|
||||
|
||||
E: KSpace style is incompatible with Pair style
|
||||
|
||||
Setting a kspace style requires that a pair style with a long-range
|
||||
Coulombic or dispersion component be used.
|
||||
|
||||
E: Bond and angle potentials must be defined for TIP4P
|
||||
|
||||
Cannot use TIP4P pair potential unless bond and angle potentials
|
||||
are defined.
|
||||
|
||||
E: Bad TIP4P angle type for PPPM/TIP4P
|
||||
|
||||
Specified angle type is not valid.
|
||||
|
||||
E: Bad TIP4P bond type for PPPM/TIP4P
|
||||
|
||||
Specified bond type is not valid.
|
||||
|
||||
E: Cannot (yet) use PPPM with triclinic box and TIP4P
|
||||
|
||||
This feature is not yet supported.
|
||||
|
||||
E: Cannot use kspace solver on system with no charge
|
||||
|
||||
No atoms in system have a non-zero charge.
|
||||
|
||||
W: System is not charge neutral, net charge = %g
|
||||
|
||||
The total charge on all atoms on the system is not 0.0, which
|
||||
is not valid for the long-range Coulombic solvers.
|
||||
|
||||
W: Reducing PPPM order b/c stencil extends beyond nearest neighbor processor
|
||||
|
||||
This may lead to a larger grid than desired. See the kspace_modify overlap
|
||||
command to prevent changing of the PPPM order.
|
||||
|
||||
E: PPPM order < minimum allowed order
|
||||
|
||||
The default minimum order is 2. This can be reset by the
|
||||
kspace_modify minorder command.
|
||||
|
||||
E: PPPM grid stencil extends beyond nearest neighbor processor
|
||||
|
||||
This is not allowed if the kspace_modify overlap setting is no.
|
||||
|
||||
E: KSpace accuracy must be > 0
|
||||
|
||||
The kspace accuracy designated in the input must be greater than zero.
|
||||
|
||||
E: Could not compute grid size
|
||||
|
||||
The code is unable to compute a grid size consistent with the desired
|
||||
accuracy. This error should not occur for typical problems. Please
|
||||
send an email to the developers.
|
||||
|
||||
E: PPPM grid is too large
|
||||
|
||||
The global PPPM grid is larger than OFFSET in one or more dimensions.
|
||||
OFFSET is currently set to 4096. You likely need to decrease the
|
||||
requested accuracy.
|
||||
|
||||
E: Could not compute g_ewald
|
||||
|
||||
The Newton-Raphson solver failed to converge to a good value for
|
||||
g_ewald. This error should not occur for typical problems. Please
|
||||
send an email to the developers.
|
||||
|
||||
E: Out of range atoms - cannot compute PPPM
|
||||
|
||||
One or more atoms are attempting to map their charge to a PPPM grid
|
||||
point that is not owned by a processor. This is likely for one of two
|
||||
reasons, both of them bad. First, it may mean that an atom near the
|
||||
boundary of a processor's sub-domain has moved more than 1/2 the
|
||||
"neighbor skin distance"_neighbor.html without neighbor lists being
|
||||
rebuilt and atoms being migrated to new processors. This also means
|
||||
you may be missing pairwise interactions that need to be computed.
|
||||
The solution is to change the re-neighboring criteria via the
|
||||
"neigh_modify"_neigh_modify command. The safest settings are "delay 0
|
||||
every 1 check yes". Second, it may mean that an atom has moved far
|
||||
outside a processor's sub-domain or even the entire simulation box.
|
||||
This indicates bad physics, e.g. due to highly overlapping atoms, too
|
||||
large a timestep, etc.
|
||||
|
||||
E: Cannot (yet) use K-space slab correction with compute group/group
|
||||
|
||||
This option is not yet supported.
|
||||
|
||||
E: Cannot (yet) use 'kspace_modify diff ad' with compute group/group
|
||||
|
||||
This option is not yet supported.
|
||||
|
||||
*/
|
||||
|
|
893
src/kspace.cpp
893
src/kspace.cpp
|
@ -1,446 +1,447 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
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 "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "kspace.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "pair.h"
|
||||
#include "memory.h"
|
||||
#include "atom_masks.h"
|
||||
#include "error.h"
|
||||
#include "suffix.h"
|
||||
#include "domain.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
KSpace::KSpace(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
||||
{
|
||||
energy = 0.0;
|
||||
virial[0] = virial[1] = virial[2] = virial[3] = virial[4] = virial[5] = 0.0;
|
||||
|
||||
triclinic_support = 1;
|
||||
ewaldflag = pppmflag = msmflag = dispersionflag = tip4pflag = dipoleflag = 0;
|
||||
compute_flag = 1;
|
||||
group_group_enable = 0;
|
||||
|
||||
order = 5;
|
||||
gridflag = 0;
|
||||
gewaldflag = 0;
|
||||
minorder = 2;
|
||||
overlap_allowed = 1;
|
||||
fftbench = 1;
|
||||
|
||||
order_6 = 5;
|
||||
gridflag_6 = 0;
|
||||
gewaldflag_6 = 0;
|
||||
|
||||
slabflag = 0;
|
||||
differentiation_flag = 0;
|
||||
slab_volfactor = 1;
|
||||
suffix_flag = Suffix::NONE;
|
||||
adjust_cutoff_flag = 1;
|
||||
|
||||
accuracy_absolute = -1.0;
|
||||
two_charge_force = force->qqr2e *
|
||||
(force->qelectron * force->qelectron) /
|
||||
(force->angstrom * force->angstrom);
|
||||
|
||||
maxeatom = maxvatom = 0;
|
||||
eatom = NULL;
|
||||
vatom = NULL;
|
||||
|
||||
datamask = ALL_MASK;
|
||||
datamask_ext = ALL_MASK;
|
||||
|
||||
memory->create(gcons,7,7,"kspace:gcons");
|
||||
gcons[2][0] = 15.0 / 8.0;
|
||||
gcons[2][1] = -5.0 / 4.0;
|
||||
gcons[2][2] = 3.0 / 8.0;
|
||||
gcons[3][0] = 35.0 / 16.0;
|
||||
gcons[3][1] = -35.0 / 16.0;
|
||||
gcons[3][2] = 21.0 / 16.0;
|
||||
gcons[3][3] = -5.0 / 16.0;
|
||||
gcons[4][0] = 315.0 / 128.0;
|
||||
gcons[4][1] = -105.0 / 32.0;
|
||||
gcons[4][2] = 189.0 / 64.0;
|
||||
gcons[4][3] = -45.0 / 32.0;
|
||||
gcons[4][4] = 35.0 / 128.0;
|
||||
gcons[5][0] = 693.0 / 256.0;
|
||||
gcons[5][1] = -1155.0 / 256.0;
|
||||
gcons[5][2] = 693.0 / 128.0;
|
||||
gcons[5][3] = -495.0 / 128.0;
|
||||
gcons[5][4] = 385.0 / 256.0;
|
||||
gcons[5][5] = -63.0 / 256.0;
|
||||
gcons[6][0] = 3003.0 / 1024.0;
|
||||
gcons[6][1] = -3003.0 / 512.0;
|
||||
gcons[6][2] = 9009.0 / 1024.0;
|
||||
gcons[6][3] = -2145.0 / 256.0;
|
||||
gcons[6][4] = 5005.0 / 1024.0;
|
||||
gcons[6][5] = -819.0 / 512.0;
|
||||
gcons[6][6] = 231.0 / 1024.0;
|
||||
|
||||
memory->create(dgcons,7,6,"kspace:dgcons");
|
||||
dgcons[2][0] = -5.0 / 2.0;
|
||||
dgcons[2][1] = 3.0 / 2.0;
|
||||
dgcons[3][0] = -35.0 / 8.0;
|
||||
dgcons[3][1] = 21.0 / 4.0;
|
||||
dgcons[3][2] = -15.0 / 8.0;
|
||||
dgcons[4][0] = -105.0 / 16.0;
|
||||
dgcons[4][1] = 189.0 / 16.0;
|
||||
dgcons[4][2] = -135.0 / 16.0;
|
||||
dgcons[4][3] = 35.0 / 16.0;
|
||||
dgcons[5][0] = -1155.0 / 128.0;
|
||||
dgcons[5][1] = 693.0 / 32.0;
|
||||
dgcons[5][2] = -1485.0 / 64.0;
|
||||
dgcons[5][3] = 385.0 / 32.0;
|
||||
dgcons[5][4] = -315.0 / 128.0;
|
||||
dgcons[6][0] = -3003.0 / 256.0;
|
||||
dgcons[6][1] = 9009.0 / 256.0;
|
||||
dgcons[6][2] = -6435.0 / 128.0;
|
||||
dgcons[6][3] = 5005.0 / 128.0;
|
||||
dgcons[6][4] = -4095.0 / 256.0;
|
||||
dgcons[6][5] = 693.0 / 256.0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
KSpace::~KSpace()
|
||||
{
|
||||
memory->destroy(eatom);
|
||||
memory->destroy(vatom);
|
||||
memory->destroy(gcons);
|
||||
memory->destroy(dgcons);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::triclinic_check()
|
||||
{
|
||||
if (domain->triclinic && triclinic_support != 1)
|
||||
error->all(FLERR,"KSpace style does not yet support triclinic geometries");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::compute_dummy(int eflag, int vflag)
|
||||
{
|
||||
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||
else evflag = evflag_atom = eflag_global = vflag_global =
|
||||
eflag_atom = vflag_atom = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check that pair style is compatible with long-range solver
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::pair_check()
|
||||
{
|
||||
if (force->pair == NULL)
|
||||
error->all(FLERR,"KSpace solver requires a pair style");
|
||||
if (ewaldflag && force->pair->ewaldflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (pppmflag && force->pair->pppmflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (msmflag && force->pair->msmflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (dispersionflag && force->pair->dispersionflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (tip4pflag && force->pair->tip4pflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (dipoleflag && force->pair->dipoleflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
setup for energy, virial computation
|
||||
see integrate::ev_set() for values of eflag (0-3) and vflag (0-6)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::ev_setup(int eflag, int vflag)
|
||||
{
|
||||
int i,n;
|
||||
|
||||
evflag = 1;
|
||||
|
||||
eflag_either = eflag;
|
||||
eflag_global = eflag % 2;
|
||||
eflag_atom = eflag / 2;
|
||||
|
||||
vflag_either = vflag;
|
||||
vflag_global = vflag % 4;
|
||||
vflag_atom = vflag / 4;
|
||||
|
||||
if (eflag_atom || vflag_atom) evflag_atom = 1;
|
||||
else evflag_atom = 0;
|
||||
|
||||
// reallocate per-atom arrays if necessary
|
||||
|
||||
if (eflag_atom && atom->nmax > maxeatom) {
|
||||
maxeatom = atom->nmax;
|
||||
memory->destroy(eatom);
|
||||
memory->create(eatom,maxeatom,"kspace:eatom");
|
||||
}
|
||||
if (vflag_atom && atom->nmax > maxvatom) {
|
||||
maxvatom = atom->nmax;
|
||||
memory->destroy(vatom);
|
||||
memory->create(vatom,maxvatom,6,"kspace:vatom");
|
||||
}
|
||||
|
||||
// zero accumulators
|
||||
|
||||
if (eflag_global) energy = 0.0;
|
||||
if (vflag_global) for (i = 0; i < 6; i++) virial[i] = 0.0;
|
||||
if (eflag_atom) {
|
||||
n = atom->nlocal;
|
||||
if (tip4pflag) n += atom->nghost;
|
||||
for (i = 0; i < n; i++) eatom[i] = 0.0;
|
||||
}
|
||||
if (vflag_atom) {
|
||||
n = atom->nlocal;
|
||||
if (tip4pflag) n += atom->nghost;
|
||||
for (i = 0; i < n; i++) {
|
||||
vatom[i][0] = 0.0;
|
||||
vatom[i][1] = 0.0;
|
||||
vatom[i][2] = 0.0;
|
||||
vatom[i][3] = 0.0;
|
||||
vatom[i][4] = 0.0;
|
||||
vatom[i][5] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
estimate the accuracy of the short-range coulomb tables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double KSpace::estimate_table_accuracy(double q2_over_sqrt, double spr)
|
||||
{
|
||||
double table_accuracy = 0.0;
|
||||
int nctb = force->pair->ncoultablebits;
|
||||
if (nctb) {
|
||||
double empirical_precision[17];
|
||||
empirical_precision[6] = 6.99E-03;
|
||||
empirical_precision[7] = 1.78E-03;
|
||||
empirical_precision[8] = 4.72E-04;
|
||||
empirical_precision[9] = 1.17E-04;
|
||||
empirical_precision[10] = 2.95E-05;
|
||||
empirical_precision[11] = 7.41E-06;
|
||||
empirical_precision[12] = 1.76E-06;
|
||||
empirical_precision[13] = 9.28E-07;
|
||||
empirical_precision[14] = 7.46E-07;
|
||||
empirical_precision[15] = 7.32E-07;
|
||||
empirical_precision[16] = 7.30E-07;
|
||||
if (nctb <= 6) table_accuracy = empirical_precision[6];
|
||||
else if (nctb <= 16) table_accuracy = empirical_precision[nctb];
|
||||
else table_accuracy = empirical_precision[16];
|
||||
table_accuracy *= q2_over_sqrt;
|
||||
if ((table_accuracy > spr) && (comm->me == 0))
|
||||
error->warning(FLERR,"For better accuracy use 'pair_modify table 0'");
|
||||
}
|
||||
|
||||
return table_accuracy;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert box coords vector to transposed triclinic lamda (0-1) coords
|
||||
vector, lamda = [(H^-1)^T] * v, does not preserve vector magnitude
|
||||
v and lamda can point to same 3-vector
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::x2lamdaT(double *v, double *lamda)
|
||||
{
|
||||
double *h_inv = domain->h_inv;
|
||||
double lamda_tmp[3];
|
||||
|
||||
lamda_tmp[0] = h_inv[0]*v[0];
|
||||
lamda_tmp[1] = h_inv[5]*v[0] + h_inv[1]*v[1];
|
||||
lamda_tmp[2] = h_inv[4]*v[0] + h_inv[3]*v[1] + h_inv[2]*v[2];
|
||||
|
||||
lamda[0] = lamda_tmp[0];
|
||||
lamda[1] = lamda_tmp[1];
|
||||
lamda[2] = lamda_tmp[2];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert lamda (0-1) coords vector to transposed box coords vector
|
||||
lamda = (H^T) * v, does not preserve vector magnitude
|
||||
v and lamda can point to same 3-vector
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::lamda2xT(double *lamda, double *v)
|
||||
{
|
||||
double *h = domain->h;
|
||||
double v_tmp[3];
|
||||
|
||||
v_tmp[0] = h[0]*lamda[0];
|
||||
v_tmp[1] = h[5]*lamda[0] + h[1]*lamda[1];
|
||||
v_tmp[2] = h[4]*lamda[0] + h[3]*lamda[1] + h[2]*lamda[2];
|
||||
|
||||
v[0] = v_tmp[0];
|
||||
v[1] = v_tmp[1];
|
||||
v[2] = v_tmp[2];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert triclinic lamda (0-1) coords vector to box coords vector
|
||||
v = H * lamda, does not preserve vector magnitude
|
||||
lamda and v can point to same 3-vector
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::lamda2xvector(double *lamda, double *v)
|
||||
{
|
||||
double *h = domain->h;
|
||||
|
||||
v[0] = h[0]*lamda[0] + h[5]*lamda[1] + h[4]*lamda[2];
|
||||
v[1] = h[1]*lamda[1] + h[3]*lamda[2];
|
||||
v[2] = h[2]*lamda[2];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert a sphere in box coords to an ellipsoid in lamda (0-1)
|
||||
coords and return the tight (axis-aligned) bounding box, does not
|
||||
preserve vector magnitude
|
||||
see http://www.loria.fr/~shornus/ellipsoid-bbox.html and
|
||||
http://yiningkarlli.blogspot.com/2013/02/bounding-boxes-for-ellipsoidsfigure.html
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::kspacebbox(double r, double *b)
|
||||
{
|
||||
double *h = domain->h;
|
||||
double lx,ly,lz,xy,xz,yz;
|
||||
lx = h[0];
|
||||
ly = h[1];
|
||||
lz = h[2];
|
||||
yz = h[3];
|
||||
xz = h[4];
|
||||
xy = h[5];
|
||||
|
||||
b[0] = r*sqrt(ly*ly*lz*lz + ly*ly*xz*xz - 2.0*ly*xy*xz*yz + lz*lz*xy*xy +
|
||||
xy*xy*yz*yz)/(lx*ly*lz);
|
||||
b[1] = r*sqrt(lz*lz + yz*yz)/(ly*lz);
|
||||
b[2] = r/lz;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
modify parameters of the KSpace style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::modify_params(int narg, char **arg)
|
||||
{
|
||||
int iarg = 0;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg],"mesh") == 0) {
|
||||
if (iarg+4 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
nx_pppm = nx_msm_max = atoi(arg[iarg+1]);
|
||||
ny_pppm = ny_msm_max = atoi(arg[iarg+2]);
|
||||
nz_pppm = nz_msm_max = atoi(arg[iarg+3]);
|
||||
if (nx_pppm == 0 && ny_pppm == 0 && nz_pppm == 0) gridflag = 0;
|
||||
else gridflag = 1;
|
||||
iarg += 4;
|
||||
} else if (strcmp(arg[iarg],"mesh/disp") == 0) {
|
||||
if (iarg+4 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
nx_pppm_6 = atoi(arg[iarg+1]);
|
||||
ny_pppm_6 = atoi(arg[iarg+2]);
|
||||
nz_pppm_6 = atoi(arg[iarg+3]);
|
||||
if (nx_pppm_6 == 0 || ny_pppm_6 == 0 || nz_pppm_6 == 0) gridflag_6 = 0;
|
||||
else gridflag_6 = 1;
|
||||
iarg += 4;
|
||||
} else if (strcmp(arg[iarg],"order") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
order = atoi(arg[iarg+1]);
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"order/disp") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
order_6 = atoi(arg[iarg+1]);
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"minorder") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
minorder = atoi(arg[iarg+1]);
|
||||
if (minorder < 2) error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"overlap") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) overlap_allowed = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) overlap_allowed = 0;
|
||||
else error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"force") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
accuracy_absolute = atof(arg[iarg+1]);
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"gewald") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
g_ewald = atof(arg[iarg+1]);
|
||||
if (g_ewald == 0.0) gewaldflag = 0;
|
||||
else gewaldflag = 1;
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"gewald/disp") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
g_ewald_6 = atof(arg[iarg+1]);
|
||||
if (g_ewald_6 == 0.0) gewaldflag_6 = 0;
|
||||
else gewaldflag_6 = 1;
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"slab") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"nozforce") == 0) {
|
||||
slabflag = 2;
|
||||
} else {
|
||||
slabflag = 1;
|
||||
slab_volfactor = atof(arg[iarg+1]);
|
||||
if (slab_volfactor <= 1.0)
|
||||
error->all(FLERR,"Bad kspace_modify slab parameter");
|
||||
if (slab_volfactor < 2.0 && comm->me == 0)
|
||||
error->warning(FLERR,"Kspace_modify slab param < 2.0 may "
|
||||
"cause unphysical behavior");
|
||||
}
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"compute") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) compute_flag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) compute_flag = 0;
|
||||
else error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"fftbench") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) fftbench = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) fftbench = 0;
|
||||
else error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"diff") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"ad") == 0) differentiation_flag = 1;
|
||||
else if (strcmp(arg[iarg+1],"ik") == 0) differentiation_flag = 0;
|
||||
else error->all(FLERR, "Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"cutoff/adjust") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) adjust_cutoff_flag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) adjust_cutoff_flag = 0;
|
||||
else error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else error->all(FLERR,"Illegal kspace_modify command");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void *KSpace::extract(const char *str)
|
||||
{
|
||||
if (strcmp(str,"scale") == 0) return (void *) &scale;
|
||||
return NULL;
|
||||
}
|
||||
/* ----------------------------------------------------------------------
|
||||
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 "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "kspace.h"
|
||||
#include "atom.h"
|
||||
#include "comm.h"
|
||||
#include "force.h"
|
||||
#include "pair.h"
|
||||
#include "memory.h"
|
||||
#include "atom_masks.h"
|
||||
#include "error.h"
|
||||
#include "suffix.h"
|
||||
#include "domain.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
KSpace::KSpace(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp)
|
||||
{
|
||||
energy = 0.0;
|
||||
virial[0] = virial[1] = virial[2] = virial[3] = virial[4] = virial[5] = 0.0;
|
||||
|
||||
triclinic_support = 1;
|
||||
ewaldflag = pppmflag = msmflag = dispersionflag = tip4pflag = dipoleflag = 0;
|
||||
compute_flag = 1;
|
||||
group_group_enable = 0;
|
||||
stagger_flag = 0;
|
||||
|
||||
order = 5;
|
||||
gridflag = 0;
|
||||
gewaldflag = 0;
|
||||
minorder = 2;
|
||||
overlap_allowed = 1;
|
||||
fftbench = 1;
|
||||
|
||||
order_6 = 5;
|
||||
gridflag_6 = 0;
|
||||
gewaldflag_6 = 0;
|
||||
|
||||
slabflag = 0;
|
||||
differentiation_flag = 0;
|
||||
slab_volfactor = 1;
|
||||
suffix_flag = Suffix::NONE;
|
||||
adjust_cutoff_flag = 1;
|
||||
|
||||
accuracy_absolute = -1.0;
|
||||
two_charge_force = force->qqr2e *
|
||||
(force->qelectron * force->qelectron) /
|
||||
(force->angstrom * force->angstrom);
|
||||
|
||||
maxeatom = maxvatom = 0;
|
||||
eatom = NULL;
|
||||
vatom = NULL;
|
||||
|
||||
datamask = ALL_MASK;
|
||||
datamask_ext = ALL_MASK;
|
||||
|
||||
memory->create(gcons,7,7,"kspace:gcons");
|
||||
gcons[2][0] = 15.0 / 8.0;
|
||||
gcons[2][1] = -5.0 / 4.0;
|
||||
gcons[2][2] = 3.0 / 8.0;
|
||||
gcons[3][0] = 35.0 / 16.0;
|
||||
gcons[3][1] = -35.0 / 16.0;
|
||||
gcons[3][2] = 21.0 / 16.0;
|
||||
gcons[3][3] = -5.0 / 16.0;
|
||||
gcons[4][0] = 315.0 / 128.0;
|
||||
gcons[4][1] = -105.0 / 32.0;
|
||||
gcons[4][2] = 189.0 / 64.0;
|
||||
gcons[4][3] = -45.0 / 32.0;
|
||||
gcons[4][4] = 35.0 / 128.0;
|
||||
gcons[5][0] = 693.0 / 256.0;
|
||||
gcons[5][1] = -1155.0 / 256.0;
|
||||
gcons[5][2] = 693.0 / 128.0;
|
||||
gcons[5][3] = -495.0 / 128.0;
|
||||
gcons[5][4] = 385.0 / 256.0;
|
||||
gcons[5][5] = -63.0 / 256.0;
|
||||
gcons[6][0] = 3003.0 / 1024.0;
|
||||
gcons[6][1] = -3003.0 / 512.0;
|
||||
gcons[6][2] = 9009.0 / 1024.0;
|
||||
gcons[6][3] = -2145.0 / 256.0;
|
||||
gcons[6][4] = 5005.0 / 1024.0;
|
||||
gcons[6][5] = -819.0 / 512.0;
|
||||
gcons[6][6] = 231.0 / 1024.0;
|
||||
|
||||
memory->create(dgcons,7,6,"kspace:dgcons");
|
||||
dgcons[2][0] = -5.0 / 2.0;
|
||||
dgcons[2][1] = 3.0 / 2.0;
|
||||
dgcons[3][0] = -35.0 / 8.0;
|
||||
dgcons[3][1] = 21.0 / 4.0;
|
||||
dgcons[3][2] = -15.0 / 8.0;
|
||||
dgcons[4][0] = -105.0 / 16.0;
|
||||
dgcons[4][1] = 189.0 / 16.0;
|
||||
dgcons[4][2] = -135.0 / 16.0;
|
||||
dgcons[4][3] = 35.0 / 16.0;
|
||||
dgcons[5][0] = -1155.0 / 128.0;
|
||||
dgcons[5][1] = 693.0 / 32.0;
|
||||
dgcons[5][2] = -1485.0 / 64.0;
|
||||
dgcons[5][3] = 385.0 / 32.0;
|
||||
dgcons[5][4] = -315.0 / 128.0;
|
||||
dgcons[6][0] = -3003.0 / 256.0;
|
||||
dgcons[6][1] = 9009.0 / 256.0;
|
||||
dgcons[6][2] = -6435.0 / 128.0;
|
||||
dgcons[6][3] = 5005.0 / 128.0;
|
||||
dgcons[6][4] = -4095.0 / 256.0;
|
||||
dgcons[6][5] = 693.0 / 256.0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
KSpace::~KSpace()
|
||||
{
|
||||
memory->destroy(eatom);
|
||||
memory->destroy(vatom);
|
||||
memory->destroy(gcons);
|
||||
memory->destroy(dgcons);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::triclinic_check()
|
||||
{
|
||||
if (domain->triclinic && triclinic_support != 1)
|
||||
error->all(FLERR,"KSpace style does not yet support triclinic geometries");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::compute_dummy(int eflag, int vflag)
|
||||
{
|
||||
if (eflag || vflag) ev_setup(eflag,vflag);
|
||||
else evflag = evflag_atom = eflag_global = vflag_global =
|
||||
eflag_atom = vflag_atom = 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check that pair style is compatible with long-range solver
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::pair_check()
|
||||
{
|
||||
if (force->pair == NULL)
|
||||
error->all(FLERR,"KSpace solver requires a pair style");
|
||||
if (ewaldflag && force->pair->ewaldflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (pppmflag && force->pair->pppmflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (msmflag && force->pair->msmflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (dispersionflag && force->pair->dispersionflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (tip4pflag && force->pair->tip4pflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
if (dipoleflag && force->pair->dipoleflag == 0)
|
||||
error->all(FLERR,"KSpace style is incompatible with Pair style");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
setup for energy, virial computation
|
||||
see integrate::ev_set() for values of eflag (0-3) and vflag (0-6)
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::ev_setup(int eflag, int vflag)
|
||||
{
|
||||
int i,n;
|
||||
|
||||
evflag = 1;
|
||||
|
||||
eflag_either = eflag;
|
||||
eflag_global = eflag % 2;
|
||||
eflag_atom = eflag / 2;
|
||||
|
||||
vflag_either = vflag;
|
||||
vflag_global = vflag % 4;
|
||||
vflag_atom = vflag / 4;
|
||||
|
||||
if (eflag_atom || vflag_atom) evflag_atom = 1;
|
||||
else evflag_atom = 0;
|
||||
|
||||
// reallocate per-atom arrays if necessary
|
||||
|
||||
if (eflag_atom && atom->nmax > maxeatom) {
|
||||
maxeatom = atom->nmax;
|
||||
memory->destroy(eatom);
|
||||
memory->create(eatom,maxeatom,"kspace:eatom");
|
||||
}
|
||||
if (vflag_atom && atom->nmax > maxvatom) {
|
||||
maxvatom = atom->nmax;
|
||||
memory->destroy(vatom);
|
||||
memory->create(vatom,maxvatom,6,"kspace:vatom");
|
||||
}
|
||||
|
||||
// zero accumulators
|
||||
|
||||
if (eflag_global) energy = 0.0;
|
||||
if (vflag_global) for (i = 0; i < 6; i++) virial[i] = 0.0;
|
||||
if (eflag_atom) {
|
||||
n = atom->nlocal;
|
||||
if (tip4pflag) n += atom->nghost;
|
||||
for (i = 0; i < n; i++) eatom[i] = 0.0;
|
||||
}
|
||||
if (vflag_atom) {
|
||||
n = atom->nlocal;
|
||||
if (tip4pflag) n += atom->nghost;
|
||||
for (i = 0; i < n; i++) {
|
||||
vatom[i][0] = 0.0;
|
||||
vatom[i][1] = 0.0;
|
||||
vatom[i][2] = 0.0;
|
||||
vatom[i][3] = 0.0;
|
||||
vatom[i][4] = 0.0;
|
||||
vatom[i][5] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
estimate the accuracy of the short-range coulomb tables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double KSpace::estimate_table_accuracy(double q2_over_sqrt, double spr)
|
||||
{
|
||||
double table_accuracy = 0.0;
|
||||
int nctb = force->pair->ncoultablebits;
|
||||
if (nctb) {
|
||||
double empirical_precision[17];
|
||||
empirical_precision[6] = 6.99E-03;
|
||||
empirical_precision[7] = 1.78E-03;
|
||||
empirical_precision[8] = 4.72E-04;
|
||||
empirical_precision[9] = 1.17E-04;
|
||||
empirical_precision[10] = 2.95E-05;
|
||||
empirical_precision[11] = 7.41E-06;
|
||||
empirical_precision[12] = 1.76E-06;
|
||||
empirical_precision[13] = 9.28E-07;
|
||||
empirical_precision[14] = 7.46E-07;
|
||||
empirical_precision[15] = 7.32E-07;
|
||||
empirical_precision[16] = 7.30E-07;
|
||||
if (nctb <= 6) table_accuracy = empirical_precision[6];
|
||||
else if (nctb <= 16) table_accuracy = empirical_precision[nctb];
|
||||
else table_accuracy = empirical_precision[16];
|
||||
table_accuracy *= q2_over_sqrt;
|
||||
if ((table_accuracy > spr) && (comm->me == 0))
|
||||
error->warning(FLERR,"For better accuracy use 'pair_modify table 0'");
|
||||
}
|
||||
|
||||
return table_accuracy;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert box coords vector to transposed triclinic lamda (0-1) coords
|
||||
vector, lamda = [(H^-1)^T] * v, does not preserve vector magnitude
|
||||
v and lamda can point to same 3-vector
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::x2lamdaT(double *v, double *lamda)
|
||||
{
|
||||
double *h_inv = domain->h_inv;
|
||||
double lamda_tmp[3];
|
||||
|
||||
lamda_tmp[0] = h_inv[0]*v[0];
|
||||
lamda_tmp[1] = h_inv[5]*v[0] + h_inv[1]*v[1];
|
||||
lamda_tmp[2] = h_inv[4]*v[0] + h_inv[3]*v[1] + h_inv[2]*v[2];
|
||||
|
||||
lamda[0] = lamda_tmp[0];
|
||||
lamda[1] = lamda_tmp[1];
|
||||
lamda[2] = lamda_tmp[2];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert lamda (0-1) coords vector to transposed box coords vector
|
||||
lamda = (H^T) * v, does not preserve vector magnitude
|
||||
v and lamda can point to same 3-vector
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::lamda2xT(double *lamda, double *v)
|
||||
{
|
||||
double *h = domain->h;
|
||||
double v_tmp[3];
|
||||
|
||||
v_tmp[0] = h[0]*lamda[0];
|
||||
v_tmp[1] = h[5]*lamda[0] + h[1]*lamda[1];
|
||||
v_tmp[2] = h[4]*lamda[0] + h[3]*lamda[1] + h[2]*lamda[2];
|
||||
|
||||
v[0] = v_tmp[0];
|
||||
v[1] = v_tmp[1];
|
||||
v[2] = v_tmp[2];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert triclinic lamda (0-1) coords vector to box coords vector
|
||||
v = H * lamda, does not preserve vector magnitude
|
||||
lamda and v can point to same 3-vector
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::lamda2xvector(double *lamda, double *v)
|
||||
{
|
||||
double *h = domain->h;
|
||||
|
||||
v[0] = h[0]*lamda[0] + h[5]*lamda[1] + h[4]*lamda[2];
|
||||
v[1] = h[1]*lamda[1] + h[3]*lamda[2];
|
||||
v[2] = h[2]*lamda[2];
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
convert a sphere in box coords to an ellipsoid in lamda (0-1)
|
||||
coords and return the tight (axis-aligned) bounding box, does not
|
||||
preserve vector magnitude
|
||||
see http://www.loria.fr/~shornus/ellipsoid-bbox.html and
|
||||
http://yiningkarlli.blogspot.com/2013/02/bounding-boxes-for-ellipsoidsfigure.html
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::kspacebbox(double r, double *b)
|
||||
{
|
||||
double *h = domain->h;
|
||||
double lx,ly,lz,xy,xz,yz;
|
||||
lx = h[0];
|
||||
ly = h[1];
|
||||
lz = h[2];
|
||||
yz = h[3];
|
||||
xz = h[4];
|
||||
xy = h[5];
|
||||
|
||||
b[0] = r*sqrt(ly*ly*lz*lz + ly*ly*xz*xz - 2.0*ly*xy*xz*yz + lz*lz*xy*xy +
|
||||
xy*xy*yz*yz)/(lx*ly*lz);
|
||||
b[1] = r*sqrt(lz*lz + yz*yz)/(ly*lz);
|
||||
b[2] = r/lz;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
modify parameters of the KSpace style
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void KSpace::modify_params(int narg, char **arg)
|
||||
{
|
||||
int iarg = 0;
|
||||
while (iarg < narg) {
|
||||
if (strcmp(arg[iarg],"mesh") == 0) {
|
||||
if (iarg+4 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
nx_pppm = nx_msm_max = atoi(arg[iarg+1]);
|
||||
ny_pppm = ny_msm_max = atoi(arg[iarg+2]);
|
||||
nz_pppm = nz_msm_max = atoi(arg[iarg+3]);
|
||||
if (nx_pppm == 0 && ny_pppm == 0 && nz_pppm == 0) gridflag = 0;
|
||||
else gridflag = 1;
|
||||
iarg += 4;
|
||||
} else if (strcmp(arg[iarg],"mesh/disp") == 0) {
|
||||
if (iarg+4 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
nx_pppm_6 = atoi(arg[iarg+1]);
|
||||
ny_pppm_6 = atoi(arg[iarg+2]);
|
||||
nz_pppm_6 = atoi(arg[iarg+3]);
|
||||
if (nx_pppm_6 == 0 || ny_pppm_6 == 0 || nz_pppm_6 == 0) gridflag_6 = 0;
|
||||
else gridflag_6 = 1;
|
||||
iarg += 4;
|
||||
} else if (strcmp(arg[iarg],"order") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
order = atoi(arg[iarg+1]);
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"order/disp") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
order_6 = atoi(arg[iarg+1]);
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"minorder") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
minorder = atoi(arg[iarg+1]);
|
||||
if (minorder < 2) error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"overlap") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) overlap_allowed = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) overlap_allowed = 0;
|
||||
else error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"force") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
accuracy_absolute = atof(arg[iarg+1]);
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"gewald") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
g_ewald = atof(arg[iarg+1]);
|
||||
if (g_ewald == 0.0) gewaldflag = 0;
|
||||
else gewaldflag = 1;
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"gewald/disp") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
g_ewald_6 = atof(arg[iarg+1]);
|
||||
if (g_ewald_6 == 0.0) gewaldflag_6 = 0;
|
||||
else gewaldflag_6 = 1;
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"slab") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"nozforce") == 0) {
|
||||
slabflag = 2;
|
||||
} else {
|
||||
slabflag = 1;
|
||||
slab_volfactor = atof(arg[iarg+1]);
|
||||
if (slab_volfactor <= 1.0)
|
||||
error->all(FLERR,"Bad kspace_modify slab parameter");
|
||||
if (slab_volfactor < 2.0 && comm->me == 0)
|
||||
error->warning(FLERR,"Kspace_modify slab param < 2.0 may "
|
||||
"cause unphysical behavior");
|
||||
}
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"compute") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) compute_flag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) compute_flag = 0;
|
||||
else error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"fftbench") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) fftbench = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) fftbench = 0;
|
||||
else error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"diff") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"ad") == 0) differentiation_flag = 1;
|
||||
else if (strcmp(arg[iarg+1],"ik") == 0) differentiation_flag = 0;
|
||||
else error->all(FLERR, "Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"cutoff/adjust") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal kspace_modify command");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) adjust_cutoff_flag = 1;
|
||||
else if (strcmp(arg[iarg+1],"no") == 0) adjust_cutoff_flag = 0;
|
||||
else error->all(FLERR,"Illegal kspace_modify command");
|
||||
iarg += 2;
|
||||
} else error->all(FLERR,"Illegal kspace_modify command");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void *KSpace::extract(const char *str)
|
||||
{
|
||||
if (strcmp(str,"scale") == 0) return (void *) &scale;
|
||||
return NULL;
|
||||
}
|
||||
|
|
398
src/kspace.h
398
src/kspace.h
|
@ -1,198 +1,200 @@
|
|||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LMP_KSPACE_H
|
||||
#define LMP_KSPACE_H
|
||||
|
||||
#include "pointers.h"
|
||||
|
||||
#ifdef FFT_SINGLE
|
||||
typedef float FFT_SCALAR;
|
||||
#define MPI_FFT_SCALAR MPI_FLOAT
|
||||
#else
|
||||
typedef double FFT_SCALAR;
|
||||
#define MPI_FFT_SCALAR MPI_DOUBLE
|
||||
#endif
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class KSpace : protected Pointers {
|
||||
friend class ThrOMP;
|
||||
friend class FixOMP;
|
||||
public:
|
||||
double energy; // accumulated energies
|
||||
double energy_1,energy_6;
|
||||
double virial[6]; // accumlated virial
|
||||
double *eatom,**vatom; // accumulated per-atom energy/virial
|
||||
double e2group; // accumulated group-group energy
|
||||
double f2group[3]; // accumulated group-group force
|
||||
int triclinic_support; // 1 if supports triclinic geometries
|
||||
|
||||
int ewaldflag; // 1 if a Ewald solver
|
||||
int pppmflag; // 1 if a PPPM solver
|
||||
int msmflag; // 1 if a MSM solver
|
||||
int dispersionflag; // 1 if a LJ/dispersion solver
|
||||
int tip4pflag; // 1 if a TIP4P solver
|
||||
int dipoleflag; // 1 if a dipole solver
|
||||
int differentiation_flag;
|
||||
int slabflag;
|
||||
double slab_volfactor;
|
||||
|
||||
int order,order_6;
|
||||
double accuracy; // accuracy of KSpace solver (force units)
|
||||
double accuracy_absolute; // user-specifed accuracy in force units
|
||||
double accuracy_relative; // user-specified dimensionless accuracy
|
||||
// accurary = acc_rel * two_charge_force
|
||||
double two_charge_force; // force in user units of two point
|
||||
// charges separated by 1 Angstrom
|
||||
|
||||
double g_ewald,g_ewald_6;
|
||||
int nx_pppm,ny_pppm,nz_pppm; // global FFT grid for Coulombics
|
||||
int nx_pppm_6,ny_pppm_6,nz_pppm_6; // global FFT grid for dispersion
|
||||
int nx_msm_max,ny_msm_max,nz_msm_max;
|
||||
|
||||
int group_group_enable; // 1 if style supports group/group calculation
|
||||
|
||||
unsigned int datamask;
|
||||
unsigned int datamask_ext;
|
||||
|
||||
int compute_flag; // 0 if skip compute()
|
||||
int fftbench; // 0 if skip FFT timing
|
||||
|
||||
KSpace(class LAMMPS *, int, char **);
|
||||
virtual ~KSpace();
|
||||
void triclinic_check();
|
||||
void modify_params(int, char **);
|
||||
void *extract(const char *);
|
||||
void compute_dummy(int, int);
|
||||
|
||||
// triclinic
|
||||
|
||||
void x2lamdaT(double *, double *);
|
||||
void lamda2xT(double *, double *);
|
||||
void lamda2xvector(double *, double *);
|
||||
void kspacebbox(double, double *);
|
||||
|
||||
// general child-class methods
|
||||
|
||||
virtual void init() = 0;
|
||||
virtual void setup() = 0;
|
||||
virtual void setup_grid() {};
|
||||
virtual void compute(int, int) = 0;
|
||||
virtual void compute_group_group(int, int, int) {};
|
||||
|
||||
virtual void pack_forward(int, FFT_SCALAR *, int, int *) {};
|
||||
virtual void unpack_forward(int, FFT_SCALAR *, int, int *) {};
|
||||
virtual void pack_reverse(int, FFT_SCALAR *, int, int *) {};
|
||||
virtual void unpack_reverse(int, FFT_SCALAR *, int, int *) {};
|
||||
|
||||
virtual int timing(int, double &, double &) {return 0;}
|
||||
virtual int timing_1d(int, double &) {return 0;}
|
||||
virtual int timing_3d(int, double &) {return 0;}
|
||||
virtual double memory_usage() {return 0.0;}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compute gamma for MSM and pair styles
|
||||
see Eq 4 from Parallel Computing 35 (2009) 164177
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double gamma(const double &rho) const {
|
||||
if (rho <= 1.0) {
|
||||
const int split_order = order/2;
|
||||
const double rho2 = rho*rho;
|
||||
double g = gcons[split_order][0];
|
||||
double rho_n = rho2;
|
||||
for (int n=1; n<=split_order; n++) {
|
||||
g += gcons[split_order][n]*rho_n;
|
||||
rho_n *= rho2;
|
||||
}
|
||||
return g;
|
||||
} else
|
||||
return (1.0/rho);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compute the derivative of gamma for MSM and pair styles
|
||||
see Eq 4 from Parallel Computing 35 (2009) 164-177
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double dgamma(const double &rho) const {
|
||||
if (rho <= 1.0) {
|
||||
const int split_order = order/2;
|
||||
const double rho2 = rho*rho;
|
||||
double dg = dgcons[split_order][0]*rho;
|
||||
double rho_n = rho*rho2;
|
||||
for (int n=1; n<split_order; n++) {
|
||||
dg += dgcons[split_order][n]*rho_n;
|
||||
rho_n *= rho2;
|
||||
}
|
||||
return dg;
|
||||
} else
|
||||
return (-1.0/rho/rho);
|
||||
}
|
||||
|
||||
protected:
|
||||
int gridflag,gridflag_6;
|
||||
int gewaldflag,gewaldflag_6;
|
||||
int minorder,overlap_allowed;
|
||||
int adjust_cutoff_flag;
|
||||
int suffix_flag; // suffix compatibility flag
|
||||
double scale;
|
||||
double **gcons,**dgcons; // accumulated per-atom energy/virial
|
||||
|
||||
int evflag,evflag_atom;
|
||||
int eflag_either,eflag_global,eflag_atom;
|
||||
int vflag_either,vflag_global,vflag_atom;
|
||||
int maxeatom,maxvatom;
|
||||
|
||||
void pair_check();
|
||||
void ev_setup(int, int);
|
||||
double estimate_table_accuracy(double, double);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: KSpace solver requires a pair style
|
||||
|
||||
No pair style is defined.
|
||||
|
||||
E: KSpace style is incompatible with Pair style
|
||||
|
||||
Setting a kspace style requires that a pair style with a long-range
|
||||
Coulombic or dispersion component be used.
|
||||
|
||||
W: For better accuracy use 'pair_modify table 0'
|
||||
|
||||
The user-specified force accuracy cannot be achieved unless the table
|
||||
feature is disabled by using 'pair_modify table 0'.
|
||||
|
||||
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: Bad kspace_modify slab parameter
|
||||
|
||||
Kspace_modify value for the slab/volume keyword must be >= 2.0.
|
||||
|
||||
W: Kspace_modify slab param < 2.0 may cause unphysical behavior
|
||||
|
||||
The kspace_modify slab parameter should be larger to insure periodic
|
||||
grids padded with empty space do not overlap.
|
||||
|
||||
*/
|
||||
/* -*- 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.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LMP_KSPACE_H
|
||||
#define LMP_KSPACE_H
|
||||
|
||||
#include "pointers.h"
|
||||
|
||||
#ifdef FFT_SINGLE
|
||||
typedef float FFT_SCALAR;
|
||||
#define MPI_FFT_SCALAR MPI_FLOAT
|
||||
#else
|
||||
typedef double FFT_SCALAR;
|
||||
#define MPI_FFT_SCALAR MPI_DOUBLE
|
||||
#endif
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class KSpace : protected Pointers {
|
||||
friend class ThrOMP;
|
||||
friend class FixOMP;
|
||||
public:
|
||||
double energy; // accumulated energies
|
||||
double energy_1,energy_6;
|
||||
double virial[6]; // accumlated virial
|
||||
double *eatom,**vatom; // accumulated per-atom energy/virial
|
||||
double e2group; // accumulated group-group energy
|
||||
double f2group[3]; // accumulated group-group force
|
||||
int triclinic_support; // 1 if supports triclinic geometries
|
||||
|
||||
int ewaldflag; // 1 if a Ewald solver
|
||||
int pppmflag; // 1 if a PPPM solver
|
||||
int msmflag; // 1 if a MSM solver
|
||||
int dispersionflag; // 1 if a LJ/dispersion solver
|
||||
int tip4pflag; // 1 if a TIP4P solver
|
||||
int dipoleflag; // 1 if a dipole solver
|
||||
int differentiation_flag;
|
||||
int slabflag;
|
||||
double slab_volfactor;
|
||||
|
||||
int order,order_6;
|
||||
double accuracy; // accuracy of KSpace solver (force units)
|
||||
double accuracy_absolute; // user-specifed accuracy in force units
|
||||
double accuracy_relative; // user-specified dimensionless accuracy
|
||||
// accurary = acc_rel * two_charge_force
|
||||
double two_charge_force; // force in user units of two point
|
||||
// charges separated by 1 Angstrom
|
||||
|
||||
double g_ewald,g_ewald_6;
|
||||
int nx_pppm,ny_pppm,nz_pppm; // global FFT grid for Coulombics
|
||||
int nx_pppm_6,ny_pppm_6,nz_pppm_6; // global FFT grid for dispersion
|
||||
int nx_msm_max,ny_msm_max,nz_msm_max;
|
||||
|
||||
int group_group_enable; // 1 if style supports group/group calculation
|
||||
|
||||
unsigned int datamask;
|
||||
unsigned int datamask_ext;
|
||||
|
||||
int compute_flag; // 0 if skip compute()
|
||||
int fftbench; // 0 if skip FFT timing
|
||||
|
||||
int stagger_flag; // 1 if using staggered PPPM grids
|
||||
|
||||
KSpace(class LAMMPS *, int, char **);
|
||||
virtual ~KSpace();
|
||||
void triclinic_check();
|
||||
void modify_params(int, char **);
|
||||
void *extract(const char *);
|
||||
void compute_dummy(int, int);
|
||||
|
||||
// triclinic
|
||||
|
||||
void x2lamdaT(double *, double *);
|
||||
void lamda2xT(double *, double *);
|
||||
void lamda2xvector(double *, double *);
|
||||
void kspacebbox(double, double *);
|
||||
|
||||
// general child-class methods
|
||||
|
||||
virtual void init() = 0;
|
||||
virtual void setup() = 0;
|
||||
virtual void setup_grid() {};
|
||||
virtual void compute(int, int) = 0;
|
||||
virtual void compute_group_group(int, int, int) {};
|
||||
|
||||
virtual void pack_forward(int, FFT_SCALAR *, int, int *) {};
|
||||
virtual void unpack_forward(int, FFT_SCALAR *, int, int *) {};
|
||||
virtual void pack_reverse(int, FFT_SCALAR *, int, int *) {};
|
||||
virtual void unpack_reverse(int, FFT_SCALAR *, int, int *) {};
|
||||
|
||||
virtual int timing(int, double &, double &) {return 0;}
|
||||
virtual int timing_1d(int, double &) {return 0;}
|
||||
virtual int timing_3d(int, double &) {return 0;}
|
||||
virtual double memory_usage() {return 0.0;}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compute gamma for MSM and pair styles
|
||||
see Eq 4 from Parallel Computing 35 (2009) 164177
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double gamma(const double &rho) const {
|
||||
if (rho <= 1.0) {
|
||||
const int split_order = order/2;
|
||||
const double rho2 = rho*rho;
|
||||
double g = gcons[split_order][0];
|
||||
double rho_n = rho2;
|
||||
for (int n=1; n<=split_order; n++) {
|
||||
g += gcons[split_order][n]*rho_n;
|
||||
rho_n *= rho2;
|
||||
}
|
||||
return g;
|
||||
} else
|
||||
return (1.0/rho);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
compute the derivative of gamma for MSM and pair styles
|
||||
see Eq 4 from Parallel Computing 35 (2009) 164-177
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double dgamma(const double &rho) const {
|
||||
if (rho <= 1.0) {
|
||||
const int split_order = order/2;
|
||||
const double rho2 = rho*rho;
|
||||
double dg = dgcons[split_order][0]*rho;
|
||||
double rho_n = rho*rho2;
|
||||
for (int n=1; n<split_order; n++) {
|
||||
dg += dgcons[split_order][n]*rho_n;
|
||||
rho_n *= rho2;
|
||||
}
|
||||
return dg;
|
||||
} else
|
||||
return (-1.0/rho/rho);
|
||||
}
|
||||
|
||||
protected:
|
||||
int gridflag,gridflag_6;
|
||||
int gewaldflag,gewaldflag_6;
|
||||
int minorder,overlap_allowed;
|
||||
int adjust_cutoff_flag;
|
||||
int suffix_flag; // suffix compatibility flag
|
||||
double scale;
|
||||
double **gcons,**dgcons; // accumulated per-atom energy/virial
|
||||
|
||||
int evflag,evflag_atom;
|
||||
int eflag_either,eflag_global,eflag_atom;
|
||||
int vflag_either,vflag_global,vflag_atom;
|
||||
int maxeatom,maxvatom;
|
||||
|
||||
void pair_check();
|
||||
void ev_setup(int, int);
|
||||
double estimate_table_accuracy(double, double);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: KSpace solver requires a pair style
|
||||
|
||||
No pair style is defined.
|
||||
|
||||
E: KSpace style is incompatible with Pair style
|
||||
|
||||
Setting a kspace style requires that a pair style with a long-range
|
||||
Coulombic or dispersion component be used.
|
||||
|
||||
W: For better accuracy use 'pair_modify table 0'
|
||||
|
||||
The user-specified force accuracy cannot be achieved unless the table
|
||||
feature is disabled by using 'pair_modify table 0'.
|
||||
|
||||
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: Bad kspace_modify slab parameter
|
||||
|
||||
Kspace_modify value for the slab/volume keyword must be >= 2.0.
|
||||
|
||||
W: Kspace_modify slab param < 2.0 may cause unphysical behavior
|
||||
|
||||
The kspace_modify slab parameter should be larger to insure periodic
|
||||
grids padded with empty space do not overlap.
|
||||
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue