Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F102275099
fix_qbmsst.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Feb 19, 00:18
Size
37 KB
Mime Type
text/x-c
Expires
Fri, Feb 21, 00:18 (2 d)
Engine
blob
Format
Raw Data
Handle
24305198
Attached To
rLAMMPS lammps
fix_qbmsst.cpp
View Options
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Shen,Yuan, Qi,Tingting, and Reed,Evan
Implementation of the Multi-Scale Shock Method with quantum nuclear effects
------------------------------------------------------------------------- */
#include <mpi.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "fix_qbmsst.h"
#include "math_extra.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "force.h"
#include "update.h"
#include "modify.h"
#include "compute.h"
#include "domain.h"
#include "region.h"
#include "respa.h"
#include "comm.h"
#include "input.h"
#include "output.h"
#include "variable.h"
#include "random_mars.h"
#include "memory.h"
#include "error.h"
#include "group.h"
#include "kspace.h"
#include "thermo.h"
using
namespace
LAMMPS_NS
;
using
namespace
FixConst
;
/* ----------------------------------------------------------------------
read parameters
------------------------------------------------------------------------- */
FixQBMSST
::
FixQBMSST
(
LAMMPS
*
lmp
,
int
narg
,
char
**
arg
)
:
Fix
(
lmp
,
narg
,
arg
)
{
if
(
narg
<
5
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
if
(
strcmp
(
arg
[
3
],
"x"
)
==
0
)
direction
=
0
;
else
if
(
strcmp
(
arg
[
3
],
"y"
)
==
0
)
direction
=
1
;
else
if
(
strcmp
(
arg
[
3
],
"z"
)
==
0
)
direction
=
2
;
else
{
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
}
velocity
=
atof
(
arg
[
4
]);
if
(
velocity
<
0
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
// default parameters
global_freq
=
1
;
extscalar
=
1
;
extvector
=
0
;
nevery
=
1
;
restart_global
=
1
;
box_change_size
=
1
;
time_integrate
=
1
;
scalar_flag
=
1
;
vector_flag
=
1
;
size_vector
=
5
;
qmass
=
1.0e1
;
mu
=
0.0
;
p0
=
0.0
;
v0
=
1.0
;
e0
=
0.0
;
p0_set
=
0
;
v0_set
=
0
;
e0_set
=
0
;
tscale
=
0.01
;
t_period
=
1.0
;
fric_coef
=
1
/
t_period
;
seed
=
880302
;
f_max
=
200.0
;
N_f
=
100
;
eta
=
1.0
;
beta
=
100
;
t_init
=
300.0
;
qtb_set
=
0
;
// reading parameters
int
iarg
=
5
;
while
(
iarg
<
narg
)
{
if
(
strcmp
(
arg
[
iarg
],
"q"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
qmass
=
atof
(
arg
[
iarg
+
1
]);
if
(
qmass
<
0.0
)
error
->
all
(
FLERR
,
"Fix qbmsst qmass must be >= 0.0"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"mu"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
mu
=
atof
(
arg
[
iarg
+
1
]);
if
(
mu
<
0.0
)
error
->
all
(
FLERR
,
"Fix qbmsst mu must be >= 0.0"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"p0"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
p0
=
atof
(
arg
[
iarg
+
1
]);
if
(
p0
<
0.0
)
error
->
all
(
FLERR
,
"Fix qbmsst p0 must be >= 0.0"
);
p0_set
=
1
;
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"v0"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
v0
=
atof
(
arg
[
iarg
+
1
]);
if
(
v0
<
0.0
)
error
->
all
(
FLERR
,
"Fix qbmsst v0 must be >= 0.0"
);
v0_set
=
1
;
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"e0"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
e0
=
atof
(
arg
[
iarg
+
1
]);
e0_set
=
1
;
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"tscale"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
tscale
=
atof
(
arg
[
iarg
+
1
]);
if
(
tscale
<
0.0
||
tscale
>
1.0
)
error
->
all
(
FLERR
,
"Fix qbmsst tscale must satisfy 0 <= tscale < 1"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"damp"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
t_period
=
atof
(
arg
[
iarg
+
1
]);
if
(
t_period
<=
0.0
)
error
->
all
(
FLERR
,
"Fix qbmsst damp must be > 0.0"
);
fric_coef
=
1
/
t_period
;
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"seed"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
seed
=
atof
(
arg
[
iarg
+
1
]);
if
(
seed
<=
0
)
error
->
all
(
FLERR
,
"Fix qbmsst seed must be a positive integer"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"f_max"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
f_max
=
atof
(
arg
[
iarg
+
1
]);
if
(
f_max
<=
0
)
error
->
all
(
FLERR
,
"Fix qbmsst f_max must be > 0.0"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"N_f"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
N_f
=
atof
(
arg
[
iarg
+
1
]);
if
(
N_f
<=
0
)
error
->
all
(
FLERR
,
"Fix qbmsst N_f must be a positive integer"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"eta"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
eta
=
atof
(
arg
[
iarg
+
1
]);
if
(
eta
<=
0
)
error
->
all
(
FLERR
,
"Fix qbmsst eta must be >= 0.0"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"beta"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
beta
=
atof
(
arg
[
iarg
+
1
]);
if
(
beta
<=
0
)
error
->
all
(
FLERR
,
"Fix qbmsst beta must be a positive integer"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"T_init"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
t_init
=
atof
(
arg
[
iarg
+
1
]);
if
(
t_init
<=
0
)
error
->
all
(
FLERR
,
"Fix qbmsst T_init must be >= 0.0"
);
iarg
+=
2
;
}
else
error
->
all
(
FLERR
,
"Illegal fix qbmsst command"
);
}
// check for periodicity in controlled dimensions
if
(
domain
->
nonperiodic
)
error
->
all
(
FLERR
,
"Fix qbmsst requires a periodic box"
);
// comments
if
(
comm
->
me
==
0
)
{
if
(
screen
)
{
fprintf
(
screen
,
"QBMSST parameters:
\n
"
);
if
(
direction
==
0
)
fprintf
(
screen
,
" Shock in x direction
\n
"
);
else
if
(
direction
==
1
)
fprintf
(
screen
,
" Shock in y direction
\n
"
);
else
if
(
direction
==
2
)
fprintf
(
screen
,
" Shock in z direction
\n
"
);
fprintf
(
screen
,
" Cell mass-like parameter qmass (units of mass^2/length^4) = %12.5e
\n
"
,
qmass
);
fprintf
(
screen
,
" Shock velocity = %12.5e
\n
"
,
velocity
);
fprintf
(
screen
,
" Artificial viscosity (units of mass/length/time) = %12.5e
\n
"
,
mu
);
if
(
p0_set
)
fprintf
(
screen
,
" Initial pressure specified to be %12.5e
\n
"
,
p0
);
else
fprintf
(
screen
,
" Initial pressure calculated on first step
\n
"
);
if
(
v0_set
)
fprintf
(
screen
,
" Initial volume specified to be %12.5e
\n
"
,
v0
);
else
fprintf
(
screen
,
" Initial volume calculated on first step
\n
"
);
if
(
e0_set
)
fprintf
(
screen
,
" Initial energy specified to be %12.5e
\n
"
,
e0
);
else
fprintf
(
screen
,
" Initial energy calculated on first step
\n
"
);
}
if
(
logfile
)
{
fprintf
(
logfile
,
"QBMSST parameters:
\n
"
);
if
(
direction
==
0
)
fprintf
(
logfile
,
" Shock in x direction
\n
"
);
else
if
(
direction
==
1
)
fprintf
(
logfile
,
" Shock in y direction
\n
"
);
else
if
(
direction
==
2
)
fprintf
(
logfile
,
" Shock in z direction
\n
"
);
fprintf
(
logfile
,
" Cell mass-like parameter qmass (units of mass^2/length^4) = %12.5e
\n
"
,
qmass
);
fprintf
(
logfile
,
" Shock velocity = %12.5e
\n
"
,
velocity
);
fprintf
(
logfile
,
" Artificial viscosity (units of mass/length/time) = %12.5e
\n
"
,
mu
);
if
(
p0_set
)
fprintf
(
logfile
,
" Initial pressure specified to be %12.5e
\n
"
,
p0
);
else
fprintf
(
logfile
,
" Initial pressure calculated on first step
\n
"
);
if
(
v0_set
)
fprintf
(
logfile
,
" Initial volume specified to be %12.5e
\n
"
,
v0
);
else
fprintf
(
logfile
,
" Initial volume calculated on first step
\n
"
);
if
(
e0_set
)
fprintf
(
logfile
,
" Initial energy specified to be %12.5e
\n
"
,
e0
);
else
fprintf
(
logfile
,
" Initial energy calculated on first step
\n
"
);
}
}
// create a new compute temp style
// id = fix-ID + temp
// compute group = all since pressure is always global (group all)
// and thus its KE/temperature contribution should use group all
int
n
=
strlen
(
id
)
+
6
;
id_temp
=
new
char
[
n
];
strcpy
(
id_temp
,
id
);
strcat
(
id_temp
,
"_temp"
);
char
**
newarg
=
new
char
*
[
3
];
newarg
[
0
]
=
id_temp
;
newarg
[
1
]
=
const_cast
<
char
*>
(
"all"
);
newarg
[
2
]
=
const_cast
<
char
*>
(
"temp"
);
modify
->
add_compute
(
3
,
newarg
);
delete
[]
newarg
;
tflag
=
1
;
// create a new compute pressure style
// id = fix-ID + press, compute group = all
// pass id_temp as 4th arg to pressure constructor
n
=
strlen
(
id
)
+
7
;
id_press
=
new
char
[
n
];
strcpy
(
id_press
,
id
);
strcat
(
id_press
,
"_press"
);
newarg
=
new
char
*
[
4
];
newarg
[
0
]
=
id_press
;
newarg
[
1
]
=
const_cast
<
char
*>
(
"all"
);
newarg
[
2
]
=
const_cast
<
char
*>
(
"pressure"
);
newarg
[
3
]
=
id_temp
;
modify
->
add_compute
(
4
,
newarg
);
delete
[]
newarg
;
pflag
=
1
;
// create a new compute potential energy compute
n
=
strlen
(
id
)
+
3
;
id_pe
=
new
char
[
n
];
strcpy
(
id_pe
,
id
);
strcat
(
id_pe
,
"_pe"
);
newarg
=
new
char
*
[
3
];
newarg
[
0
]
=
id_pe
;
newarg
[
1
]
=
(
char
*
)
"all"
;
newarg
[
2
]
=
(
char
*
)
"pe"
;
modify
->
add_compute
(
3
,
newarg
);
delete
[]
newarg
;
peflag
=
1
;
// allocate qbmsst
temperature
=
NULL
;
pressure
=
NULL
;
pe
=
NULL
;
old_velocity
=
NULL
;
rfix
=
NULL
;
gfactor
=
NULL
;
random
=
NULL
;
omega_H
=
NULL
;
time_H
=
NULL
;
random_array_0
=
NULL
;
random_array_1
=
NULL
;
random_array_2
=
NULL
;
fran
=
NULL
;
// initialize Marsagxlia RNG with processor-unique seed
random
=
new
RanMars
(
lmp
,
seed
+
comm
->
me
);
// allocate per-type arrays for force prefactors
gfactor
=
new
double
[
atom
->
ntypes
+
1
];
// allocate random-arrays and fran
grow_arrays
(
atom
->
nmax
);
atom
->
add_callback
(
0
);
// allocate omega_H and time_H
memory
->
create
(
omega_H
,
2
*
N_f
,
"qbmsst:omega_H"
);
memory
->
create
(
time_H
,
2
*
N_f
,
"qbmsst:time_H"
);
// initiate velocity record array
memory
->
create
(
old_velocity
,
atom
->
nlocal
,
3
,
"qbmsst:old_velocity"
);
atoms_allocated
=
atom
->
nlocal
;
}
/* ----------------------------------------------------------------------
release memories
------------------------------------------------------------------------- */
FixQBMSST
::~
FixQBMSST
()
{
delete
[]
rfix
;
delete
[]
gfactor
;
delete
random
;
// delete temperature and pressure if fix created them
if
(
tflag
)
modify
->
delete_compute
(
id_temp
);
if
(
pflag
)
modify
->
delete_compute
(
id_press
);
if
(
peflag
)
modify
->
delete_compute
(
id_pe
);
delete
[]
id_temp
;
delete
[]
id_press
;
delete
[]
id_pe
;
memory
->
destroy
(
old_velocity
);
memory
->
destroy
(
fran
);
memory
->
destroy
(
random_array_0
);
memory
->
destroy
(
random_array_1
);
memory
->
destroy
(
random_array_2
);
memory
->
destroy
(
omega_H
);
memory
->
destroy
(
time_H
);
atom
->
delete_callback
(
id
,
0
);
}
/* ----------------------------------------------------------------------
setmask
------------------------------------------------------------------------- */
int
FixQBMSST
::
setmask
()
{
int
mask
=
0
;
mask
|=
INITIAL_INTEGRATE
;
mask
|=
FINAL_INTEGRATE
;
mask
|=
THERMO_ENERGY
;
return
mask
;
}
/* ----------------------------------------------------------------------
fix initiation
------------------------------------------------------------------------- */
void
FixQBMSST
::
init
()
{
// copy parameters from other classes
dtv
=
update
->
dt
;
dthalf
=
0.5
*
update
->
dt
;
dtf
=
0.5
*
update
->
dt
*
force
->
ftm2v
;
ntotal
=
atom
->
natoms
;
boltz
=
force
->
boltz
;
nktv2p
=
force
->
nktv2p
;
mvv2e
=
force
->
mvv2e
;
if
(
atom
->
mass
==
NULL
)
error
->
all
(
FLERR
,
"Cannot use fix qbmsst without per-type mass defined"
);
// set compute ptrs
int
itemp
=
modify
->
find_compute
(
id_temp
);
int
ipress
=
modify
->
find_compute
(
id_press
);
int
ipe
=
modify
->
find_compute
(
id_pe
);
if
(
itemp
<
0
||
ipress
<
0
||
ipe
<
0
)
error
->
all
(
FLERR
,
"Could not find fix qbmsst compute ID"
);
if
(
modify
->
compute
[
itemp
]
->
tempflag
==
0
)
error
->
all
(
FLERR
,
"Fix qbmsst compute ID does not compute temperature"
);
if
(
modify
->
compute
[
ipress
]
->
pressflag
==
0
)
error
->
all
(
FLERR
,
"Fix qbmsst compute ID does not compute pressure"
);
if
(
modify
->
compute
[
ipe
]
->
peflag
==
0
)
error
->
all
(
FLERR
,
"Fix qbmsst compute ID does not compute potential energy"
);
temperature
=
modify
->
compute
[
itemp
];
pressure
=
modify
->
compute
[
ipress
];
pe
=
modify
->
compute
[
ipe
];
// initiate the counter l and \mu
counter_l
=
0
;
counter_mu
=
0
;
// initiate qtb temperature
if
(
!
qtb_set
)
{
t_current
=
t_init
;
qtb_set
=
1
;
}
old_eavg
=
e0
;
//set up the h time step for updating the random force \delta{}h=\frac{\pi}{\Omega_{max}}
if
(
int
(
1.0
/
(
2
*
f_max
*
dtv
))
==
0
)
{
if
(
comm
->
me
==
0
)
printf
(
"Warning: Either f_max is too high or the time step is too big, setting f_max to be 1/timestep!
\n
"
);
h_timestep
=
dtv
;
alpha
=
1
;
}
else
{
alpha
=
int
(
1.0
/
(
2
*
f_max
*
dtv
));
h_timestep
=
alpha
*
dtv
;
}
if
(
comm
->
me
==
0
)
printf
(
"The effective maximum frequncy is now %f inverse time unit with alpha value as %d!
\n
"
,
0.5
/
h_timestep
,
alpha
);
//gfactor is the random force \sqrt{\frac{2\gamma{}m_{i}}{\alpha*\delta{}t}}, \sqrt{12} makes the random array variance equal to unit.
for
(
int
i
=
1
;
i
<=
atom
->
ntypes
;
i
++
)
{
gfactor
[
i
]
=
sqrt
(
2
*
fric_coef
*
atom
->
mass
[
i
])
*
sqrt
(
force
->
mvv2e
)
*
sqrt
(
12
/
h_timestep
);
//this still leaves a square energy term from the power spectrum H.
}
// generate random number array with zero mean and variance equal 1/12.
int
nlocal
=
atom
->
nlocal
;
for
(
int
i
=
0
;
i
<
nlocal
;
i
++
)
{
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
{
random_array_0
[
i
][
m
]
=
random
->
uniform
()
-
0.5
;
random_array_1
[
i
][
m
]
=
random
->
uniform
()
-
0.5
;
random_array_2
[
i
][
m
]
=
random
->
uniform
()
-
0.5
;
}
}
// initiate dilations
dilation
[
0
]
=
dilation
[
1
]
=
dilation
[
2
]
=
1.0
;
// initialize the time derivative of the volume.
omega
[
0
]
=
omega
[
1
]
=
omega
[
2
]
=
0.0
;
// compute total mass
double
mass
=
0.0
;
for
(
int
i
=
0
;
i
<
atom
->
nlocal
;
i
++
)
mass
+=
atom
->
mass
[
atom
->
type
[
i
]];
MPI_Allreduce
(
&
mass
,
&
total_mass
,
1
,
MPI_DOUBLE
,
MPI_SUM
,
world
);
// enable kspace summation of long range forces
if
(
force
->
kspace
)
kspace_flag
=
1
;
else
kspace_flag
=
0
;
// detect if any fix rigid exist so rigid bodies move when box is dilated
// rfix[] = indices to each fix rigid
nrigid
=
0
;
for
(
int
i
=
0
;
i
<
modify
->
nfix
;
i
++
)
if
(
strcmp
(
modify
->
fix
[
i
]
->
style
,
"rigid"
)
==
0
||
strcmp
(
modify
->
fix
[
i
]
->
style
,
"poems"
)
==
0
)
nrigid
++
;
if
(
nrigid
)
{
rfix
=
new
int
[
nrigid
];
nrigid
=
0
;
for
(
int
i
=
0
;
i
<
modify
->
nfix
;
i
++
)
if
(
strcmp
(
modify
->
fix
[
i
]
->
style
,
"rigid"
)
==
0
||
strcmp
(
modify
->
fix
[
i
]
->
style
,
"poems"
)
==
0
)
rfix
[
nrigid
++
]
=
i
;
}
}
/* ----------------------------------------------------------------------
compute T,P before integrator starts
------------------------------------------------------------------------- */
void
FixQBMSST
::
setup
(
int
vflag
)
{
lagrangian_position
=
0.0
;
temperature
->
compute_vector
();
pressure
->
compute_vector
();
couple
();
velocity_sum
=
compute_vsum
();
if
(
v0_set
==
0
)
{
v0
=
compute_vol
();
v0_set
=
1
;
if
(
comm
->
me
==
0
)
{
if
(
screen
)
fprintf
(
screen
,
"Fix QBMSST v0 = %12.5e
\n
"
,
v0
);
if
(
logfile
)
fprintf
(
logfile
,
"Fix QBMSST v0 = %12.5e
\n
"
,
v0
);
}
}
if
(
p0_set
==
0
)
{
p0
=
p_current
[
direction
];
p0_set
=
1
;
if
(
comm
->
me
==
0
)
{
if
(
screen
)
fprintf
(
screen
,
"Fix QBMSST p0 = %12.5e
\n
"
,
p0
);
if
(
logfile
)
fprintf
(
logfile
,
"Fix QBMSST p0 = %12.5e
\n
"
,
p0
);
}
}
if
(
e0_set
==
0
)
{
e0
=
compute_etotal
();
e0_set
=
1
;
old_eavg
=
e0
;
if
(
comm
->
me
==
0
)
{
if
(
screen
)
fprintf
(
screen
,
"Fix QBMSST e0 = to be %12.5e
\n
"
,
e0
);
if
(
logfile
)
fprintf
(
logfile
,
"Fix QBMSST e0 = to be %12.5e
\n
"
,
e0
);
}
}
temperature
->
compute_vector
();
double
*
ke_tensor
=
temperature
->
vector
;
double
ke_temp
=
ke_tensor
[
0
]
+
ke_tensor
[
1
]
+
ke_tensor
[
2
];
if
(
ke_temp
>
0.0
&&
tscale
>
0.0
)
{
// transfer energy from atom velocities to cell volume motion
// to bias initial compression
double
**
v
=
atom
->
v
;
int
*
mask
=
atom
->
mask
;
double
sqrt_initial_temperature_scaling
=
sqrt
(
1.0
-
tscale
);
double
fac1
=
tscale
*
total_mass
/
qmass
*
ke_temp
/
force
->
mvv2e
;
omega
[
direction
]
=-
1
*
sqrt
(
fac1
);
double
fac2
=
omega
[
direction
]
/
v0
;
if
(
comm
->
me
==
0
&&
tscale
!=
1.0
)
{
if
(
screen
)
fprintf
(
screen
,
"Fix QBMSST initial strain rate of %12.5e established "
"by reducing temperature by factor of %12.5e
\n
"
,
fac2
,
tscale
);
if
(
logfile
)
fprintf
(
logfile
,
"Fix QBMSST initial strain rate of %12.5e established "
"by reducing temperature by factor of %12.5e
\n
"
,
fac2
,
tscale
);
}
for
(
int
i
=
0
;
i
<
atom
->
nlocal
;
i
++
)
{
if
(
mask
[
i
]
&
groupbit
)
{
for
(
int
k
=
0
;
k
<
3
;
k
++
)
{
v
[
i
][
k
]
*=
sqrt_initial_temperature_scaling
;
}
}
}
}
// trigger virial computation on next timestep
pressure
->
addstep
(
update
->
ntimestep
+
1
);
pe
->
addstep
(
update
->
ntimestep
+
1
);
}
/* ----------------------------------------------------------------------
1st half of Verlet update
------------------------------------------------------------------------- */
void
FixQBMSST
::
initial_integrate
(
int
vflag
)
{
int
sd
;
sd
=
direction
;
double
p_qbmsst
;
// QBMSST driving pressure.
int
i
,
k
;
double
vol
;
int
nlocal
=
atom
->
nlocal
;
int
*
mask
=
atom
->
mask
;
double
**
v
=
atom
->
v
;
double
**
f
=
atom
->
f
;
double
*
mass
=
atom
->
mass
;
int
*
type
=
atom
->
type
;
double
**
x
=
atom
->
x
;
double
boltz
=
force
->
boltz
;
// check to see if old_velocity is correctly allocated
check_alloc
(
nlocal
);
// compute new pressure and volume.
temperature
->
compute_vector
();
pressure
->
compute_vector
();
couple
();
vol
=
compute_vol
();
// decide if the qtb temperature need to be updated or not
if
(
counter_l
==
0
)
{
t_current
-=
dtv
*
fric_coef
*
eta
*
beta
*
(
old_eavg
-
e0
)
/
(
3
*
ntotal
*
boltz
);
old_eavg
=
0
;
//clear old energy average
if
(
t_current
<
0.0
)
t_current
=
0
;
// load omega_H with calculated spectrum at a specific temperature (corrected spectrum), omega_H is the Fourier transformation of time_H
for
(
int
k
=
0
;
k
<
2
*
N_f
;
k
++
)
{
double
f_k
=
(
k
-
N_f
)
/
(
2
*
N_f
*
h_timestep
);
//\omega_k=\frac{2\pi}{\delta{}h}\frac{k}{2N_f} for k from -N_f to N_f-1
if
(
k
==
N_f
)
{
omega_H
[
k
]
=
sqrt
(
force
->
boltz
*
t_current
);
}
else
{
double
energy_k
=
force
->
hplanck
*
fabs
(
f_k
);
omega_H
[
k
]
=
sqrt
(
energy_k
*
(
0.5
+
1.0
/
(
exp
(
energy_k
/
(
force
->
boltz
*
t_current
))
-
1.0
))
);
omega_H
[
k
]
*=
alpha
*
sin
((
k
-
N_f
)
*
M_PI
/
(
2
*
alpha
*
N_f
))
/
sin
((
k
-
N_f
)
*
M_PI
/
(
2
*
N_f
));
}
}
// construct the signal filter H, filter has the unit of of sqrt(energy) \sqrt{2N_f}^{-1}H\left(t_n\right)
for
(
int
n
=
0
;
n
<
2
*
N_f
;
n
++
)
{
time_H
[
n
]
=
0
;
double
t_n
=
(
n
-
N_f
);
for
(
int
k
=
0
;
k
<
2
*
N_f
;
k
++
)
{
double
omega_k
=
(
k
-
N_f
)
*
M_PI
/
N_f
;
time_H
[
n
]
+=
omega_H
[
k
]
*
(
cos
(
omega_k
*
t_n
));
}
time_H
[
n
]
/=
(
2.0
*
N_f
);
}
}
//update the colored random force every alpha MD steps
if
(
counter_mu
==
0
)
{
//propagate h_timestep ahead
for
(
int
j
=
0
;
j
<
nlocal
;
j
++
)
{
//update random array
for
(
int
m
=
0
;
m
<
2
*
N_f
-
1
;
m
++
)
{
random_array_0
[
j
][
m
]
=
random_array_0
[
j
][
m
+
1
];
random_array_1
[
j
][
m
]
=
random_array_1
[
j
][
m
+
1
];
random_array_2
[
j
][
m
]
=
random_array_2
[
j
][
m
+
1
];
}
random_array_0
[
j
][
2
*
N_f
-
1
]
=
random
->
uniform
()
-
0.5
;
random_array_1
[
j
][
2
*
N_f
-
1
]
=
random
->
uniform
()
-
0.5
;
random_array_2
[
j
][
2
*
N_f
-
1
]
=
random
->
uniform
()
-
0.5
;
//reset random force
fran
[
j
][
0
]
=
0.0
;
fran
[
j
][
1
]
=
0.0
;
fran
[
j
][
2
]
=
0.0
;
if
(
mask
[
j
]
&
groupbit
)
{
double
gamma3
=
gfactor
[
type
[
j
]];
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
{
fran
[
j
][
0
]
+=
time_H
[
m
]
*
random_array_0
[
j
][
2
*
N_f
-
m
-
1
];
fran
[
j
][
1
]
+=
time_H
[
m
]
*
random_array_1
[
j
][
2
*
N_f
-
m
-
1
];
fran
[
j
][
2
]
+=
time_H
[
m
]
*
random_array_2
[
j
][
2
*
N_f
-
m
-
1
];
}
fran
[
j
][
0
]
=
fran
[
j
][
0
]
*
gamma3
;
fran
[
j
][
1
]
=
fran
[
j
][
1
]
*
gamma3
;
fran
[
j
][
2
]
=
fran
[
j
][
2
]
*
gamma3
;
}
}
}
// estimate old energy average in this step
old_eavg
=
old_eavg
+
compute_egrand
()
/
beta
;
counter_l
=
(
counter_l
+
1
)
%
beta
;
counter_mu
=
(
counter_mu
+
1
)
%
alpha
;
// propagate the time derivative of
// the volume 1/2 step at fixed vol, r, rdot.
p_qbmsst
=
nktv2p
*
mvv2e
*
velocity
*
velocity
*
total_mass
*
(
v0
-
vol
)
/
(
v0
*
v0
);
double
A
=
total_mass
*
(
p_current
[
sd
]
-
p0
-
p_qbmsst
)
/
(
qmass
*
nktv2p
*
mvv2e
);
double
B
=
total_mass
*
mu
/
(
qmass
*
vol
);
// prevent blow-up of the volume.
if
(
vol
>
v0
&&
A
>
0.0
)
{
A
=
-
A
;
}
// use taylor expansion to avoid singularity at B == 0.
if
(
B
*
dthalf
>
1.0e-06
)
{
omega
[
sd
]
=
(
omega
[
sd
]
+
A
*
(
exp
(
B
*
dthalf
)
-
1.0
)
/
B
)
*
exp
(
-
B
*
dthalf
);
}
else
{
omega
[
sd
]
=
omega
[
sd
]
+
(
A
-
B
*
omega
[
sd
])
*
dthalf
+
0.5
*
(
B
*
B
*
omega
[
sd
]
-
A
*
B
)
*
dthalf
*
dthalf
;
}
// propagate velocity sum 1/2 step by
// temporarily propagating the velocities.
velocity_sum
=
compute_vsum
();
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
if
(
mask
[
i
]
&
groupbit
)
{
for
(
k
=
0
;
k
<
3
;
k
++
)
{
double
C
=
(
f
[
i
][
k
]
+
fran
[
i
][
k
])
*
force
->
ftm2v
/
mass
[
type
[
i
]];
// this term now has a random force part
double
D
=
mu
*
omega
[
sd
]
*
omega
[
sd
]
/
(
velocity_sum
*
mass
[
type
[
i
]]
*
vol
)
-
fric_coef
;
old_velocity
[
i
][
k
]
=
v
[
i
][
k
];
if
(
k
==
direction
)
{
D
=
D
-
2.0
*
omega
[
sd
]
/
vol
;
}
if
(
fabs
(
dthalf
*
D
)
>
1.0e-06
)
{
double
expd
=
exp
(
D
*
dthalf
);
v
[
i
][
k
]
=
expd
*
(
C
+
D
*
v
[
i
][
k
]
-
C
/
expd
)
/
D
;
}
else
{
v
[
i
][
k
]
=
v
[
i
][
k
]
+
(
C
+
D
*
v
[
i
][
k
]
)
*
dthalf
+
0.5
*
(
D
*
D
*
v
[
i
][
k
]
+
C
*
D
)
*
dthalf
*
dthalf
;
}
}
}
}
velocity_sum
=
compute_vsum
();
// reset the velocities.
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
if
(
mask
[
i
]
&
groupbit
)
{
for
(
k
=
0
;
k
<
3
;
k
++
)
{
v
[
i
][
k
]
=
old_velocity
[
i
][
k
];
}
}
}
// propagate velocities 1/2 step using the new velocity sum.
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
if
(
mask
[
i
]
&
groupbit
)
{
for
(
k
=
0
;
k
<
3
;
k
++
)
{
double
C
=
(
f
[
i
][
k
]
+
fran
[
i
][
k
])
*
force
->
ftm2v
/
mass
[
type
[
i
]];
// this term now has a random force part
double
D
=
mu
*
omega
[
sd
]
*
omega
[
sd
]
/
(
velocity_sum
*
mass
[
type
[
i
]]
*
vol
)
-
fric_coef
;
if
(
k
==
direction
)
{
D
=
D
-
2.0
*
omega
[
sd
]
/
vol
;
}
if
(
fabs
(
dthalf
*
D
)
>
1.0e-06
)
{
double
expd
=
exp
(
D
*
dthalf
);
v
[
i
][
k
]
=
expd
*
(
C
+
D
*
v
[
i
][
k
]
-
C
/
expd
)
/
D
;
}
else
{
v
[
i
][
k
]
=
v
[
i
][
k
]
+
(
C
+
D
*
v
[
i
][
k
]
)
*
dthalf
+
0.5
*
(
D
*
D
*
v
[
i
][
k
]
+
C
*
D
)
*
dthalf
*
dthalf
;
}
}
}
}
// propagate the volume 1/2 step.
double
vol1
=
vol
+
omega
[
sd
]
*
dthalf
;
// rescale positions and change box size.
dilation
[
sd
]
=
vol1
/
vol
;
remap
(
0
);
// propagate particle positions 1 time step.
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
if
(
mask
[
i
]
&
groupbit
)
{
x
[
i
][
0
]
+=
dtv
*
v
[
i
][
0
];
x
[
i
][
1
]
+=
dtv
*
v
[
i
][
1
];
x
[
i
][
2
]
+=
dtv
*
v
[
i
][
2
];
}
}
// propagate the volume 1/2 step.
double
vol2
=
vol1
+
omega
[
sd
]
*
dthalf
;
// rescale positions and change box size.
dilation
[
sd
]
=
vol2
/
vol1
;
remap
(
0
);
if
(
kspace_flag
)
force
->
kspace
->
setup
();
}
/* ----------------------------------------------------------------------
2nd half of Verlet update
------------------------------------------------------------------------- */
void
FixQBMSST
::
final_integrate
()
{
int
i
;
// v update only for atoms in QBMSST group
double
**
v
=
atom
->
v
;
double
**
f
=
atom
->
f
;
double
*
mass
=
atom
->
mass
;
int
*
type
=
atom
->
type
;
int
*
mask
=
atom
->
mask
;
int
nlocal
=
atom
->
nlocal
;
double
vol
=
compute_vol
();
double
p_qbmsst
;
int
sd
=
direction
;
// propagate particle velocities 1/2 step.
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
if
(
mask
[
i
]
&
groupbit
)
{
for
(
int
k
=
0
;
k
<
3
;
k
++
)
{
double
C
=
(
f
[
i
][
k
]
+
fran
[
i
][
k
])
*
force
->
ftm2v
/
mass
[
type
[
i
]];
// this term now has a random force part
double
D
=
mu
*
omega
[
sd
]
*
omega
[
sd
]
/
(
velocity_sum
*
mass
[
type
[
i
]]
*
vol
)
-
fric_coef
;
if
(
k
==
direction
)
{
D
=
D
-
2.0
*
omega
[
sd
]
/
vol
;
}
if
(
fabs
(
dthalf
*
D
)
>
1.0e-06
)
{
double
expd
=
exp
(
D
*
dthalf
);
v
[
i
][
k
]
=
expd
*
(
C
+
D
*
v
[
i
][
k
]
-
C
/
expd
)
/
D
;
}
else
{
v
[
i
][
k
]
=
v
[
i
][
k
]
+
(
C
+
D
*
v
[
i
][
k
]
)
*
dthalf
+
0.5
*
(
D
*
D
*
v
[
i
][
k
]
+
C
*
D
)
*
dthalf
*
dthalf
;
}
}
}
}
// compute new pressure and volume.
temperature
->
compute_vector
();
pressure
->
compute_vector
();
couple
();
velocity_sum
=
compute_vsum
();
vol
=
compute_vol
();
// propagate the time derivative of the volume 1/2 step at fixed V, r, rdot.
p_qbmsst
=
nktv2p
*
mvv2e
*
velocity
*
velocity
*
total_mass
*
(
v0
-
vol
)
/
(
v0
*
v0
);
double
A
=
total_mass
*
(
p_current
[
sd
]
-
p0
-
p_qbmsst
)
/
(
qmass
*
nktv2p
*
mvv2e
);
double
B
=
total_mass
*
mu
/
(
qmass
*
vol
);
// prevent blow-up of the volume.
if
(
vol
>
v0
&&
A
>
0.0
)
{
A
=
-
A
;
}
// use taylor expansion to avoid singularity at B == 0.
if
(
B
*
dthalf
>
1.0e-06
)
{
omega
[
sd
]
=
(
omega
[
sd
]
+
A
*
(
exp
(
B
*
dthalf
)
-
1.0
)
/
B
)
*
exp
(
-
B
*
dthalf
);
}
else
{
omega
[
sd
]
=
omega
[
sd
]
+
(
A
-
B
*
omega
[
sd
])
*
dthalf
+
0.5
*
(
B
*
B
*
omega
[
sd
]
-
A
*
B
)
*
dthalf
*
dthalf
;
}
// calculate Lagrangian position of computational cell
lagrangian_position
-=
velocity
*
vol
/
v0
*
update
->
dt
;
// trigger virial computation on next timestep
pressure
->
addstep
(
update
->
ntimestep
+
1
);
pe
->
addstep
(
update
->
ntimestep
+
1
);
}
/* ----------------------------------------------------------------------
couple
------------------------------------------------------------------------- */
void
FixQBMSST
::
couple
()
{
double
*
tensor
=
pressure
->
vector
;
p_current
[
0
]
=
tensor
[
0
];
p_current
[
1
]
=
tensor
[
1
];
p_current
[
2
]
=
tensor
[
2
];
}
/* ----------------------------------------------------------------------
change box size
remap owned or owned+ghost atoms depending on flag
if rigid bodies exist, scale rigid body centers-of-mass
------------------------------------------------------------------------- */
void
FixQBMSST
::
remap
(
int
flag
)
{
int
i
,
n
;
double
oldlo
,
oldhi
,
ctr
;
double
**
v
=
atom
->
v
;
if
(
flag
)
n
=
atom
->
nlocal
+
atom
->
nghost
;
else
n
=
atom
->
nlocal
;
// convert pertinent atoms and rigid bodies to lamda coords
domain
->
x2lamda
(
n
);
if
(
nrigid
)
for
(
i
=
0
;
i
<
nrigid
;
i
++
)
modify
->
fix
[
rfix
[
i
]]
->
deform
(
0
);
// reset global and local box to new size/shape
for
(
i
=
0
;
i
<
3
;
i
++
)
{
if
(
direction
==
i
)
{
oldlo
=
domain
->
boxlo
[
i
];
oldhi
=
domain
->
boxhi
[
i
];
ctr
=
0.5
*
(
oldlo
+
oldhi
);
domain
->
boxlo
[
i
]
=
(
oldlo
-
ctr
)
*
dilation
[
i
]
+
ctr
;
domain
->
boxhi
[
i
]
=
(
oldhi
-
ctr
)
*
dilation
[
i
]
+
ctr
;
}
}
domain
->
set_global_box
();
domain
->
set_local_box
();
// convert pertinent atoms and rigid bodies back to box coords
domain
->
lamda2x
(
n
);
if
(
nrigid
)
for
(
i
=
0
;
i
<
nrigid
;
i
++
)
modify
->
fix
[
rfix
[
i
]]
->
deform
(
1
);
for
(
i
=
0
;
i
<
n
;
i
++
)
{
v
[
i
][
direction
]
=
v
[
i
][
direction
]
*
dilation
[
direction
];
}
}
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void
FixQBMSST
::
write_restart
(
FILE
*
fp
)
{
int
n
=
0
;
double
list
[
5
];
list
[
n
++
]
=
omega
[
direction
];
list
[
n
++
]
=
e0
;
list
[
n
++
]
=
v0
;
list
[
n
++
]
=
p0
;
list
[
n
++
]
=
t_current
;
if
(
comm
->
me
==
0
)
{
int
size
=
n
*
sizeof
(
double
);
fwrite
(
&
size
,
sizeof
(
int
),
1
,
fp
);
fwrite
(
&
list
,
sizeof
(
double
),
n
,
fp
);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void
FixQBMSST
::
restart
(
char
*
buf
)
{
int
n
=
0
;
double
*
list
=
(
double
*
)
buf
;
omega
[
direction
]
=
list
[
n
++
];
e0
=
list
[
n
++
];
v0
=
list
[
n
++
];
p0
=
list
[
n
++
];
t_current
=
list
[
n
++
];
e0_set
=
1
;
v0_set
=
1
;
p0_set
=
1
;
qtb_set
=
1
;
}
/* ----------------------------------------------------------------------
modify parameters
------------------------------------------------------------------------- */
int
FixQBMSST
::
modify_param
(
int
narg
,
char
**
arg
)
{
if
(
strcmp
(
arg
[
0
],
"temp"
)
==
0
)
{
if
(
narg
<
2
)
error
->
all
(
FLERR
,
"Illegal fix_modify command"
);
if
(
tflag
)
{
modify
->
delete_compute
(
id_temp
);
tflag
=
0
;
}
delete
[]
id_temp
;
int
n
=
strlen
(
arg
[
1
])
+
1
;
id_temp
=
new
char
[
n
];
strcpy
(
id_temp
,
arg
[
1
]);
int
icompute
=
modify
->
find_compute
(
id_temp
);
if
(
icompute
<
0
)
error
->
all
(
FLERR
,
"Could not find fix_modify temperature ID"
);
temperature
=
modify
->
compute
[
icompute
];
if
(
temperature
->
tempflag
==
0
)
error
->
all
(
FLERR
,
"Fix_modify temperature ID does not compute temperature"
);
if
(
temperature
->
igroup
!=
0
&&
comm
->
me
==
0
)
error
->
warning
(
FLERR
,
"Temperature for QBMSST is not for group all"
);
return
2
;
}
else
if
(
strcmp
(
arg
[
0
],
"press"
)
==
0
)
{
if
(
narg
<
2
)
error
->
all
(
FLERR
,
"Illegal fix_modify command"
);
if
(
pflag
)
{
modify
->
delete_compute
(
id_press
);
pflag
=
0
;
}
delete
[]
id_press
;
int
n
=
strlen
(
arg
[
1
])
+
1
;
id_press
=
new
char
[
n
];
strcpy
(
id_press
,
arg
[
1
]);
int
icompute
=
modify
->
find_compute
(
id_press
);
if
(
icompute
<
0
)
error
->
all
(
FLERR
,
"Could not find fix_modify pressure ID"
);
pressure
=
modify
->
compute
[
icompute
];
if
(
pressure
->
pressflag
==
0
)
error
->
all
(
FLERR
,
"Fix_modify pressure ID does not compute pressure"
);
return
2
;
}
return
0
;
}
/* ----------------------------------------------------------------------
compute scalar
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_scalar
()
{
// compute new pressure and volume.
temperature
->
compute_vector
();
pressure
->
compute_vector
();
couple
();
double
volume
=
compute_vol
();
double
energy
=
0.0
;
int
i
;
i
=
direction
;
energy
=
qmass
*
omega
[
i
]
*
omega
[
i
]
/
(
2.0
*
total_mass
)
*
mvv2e
;
energy
-=
0.5
*
total_mass
*
velocity
*
velocity
*
(
1.0
-
volume
/
v0
)
*
(
1.0
-
volume
/
v0
)
*
mvv2e
;
energy
-=
p0
*
(
v0
-
volume
)
/
nktv2p
;
return
energy
;
}
/* ----------------------------------------------------------------------
return a single element from the following vector,
[dhug,dray,lgr_vel,lgr_pos,T_qm]
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_vector
(
int
n
)
{
if
(
n
==
0
)
{
return
compute_hugoniot
();
}
else
if
(
n
==
1
)
{
return
compute_rayleigh
();
}
else
if
(
n
==
2
)
{
return
compute_lagrangian_speed
();
}
else
if
(
n
==
3
)
{
return
compute_lagrangian_position
();
}
else
if
(
n
==
4
)
{
return
t_current
;
}
return
0.0
;
}
/* ----------------------------------------------------------------------
Computes the deviation of the current point
from the Hugoniot in Kelvin for the QBMSST.
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_hugoniot
()
{
double
v
,
e
,
p
;
double
dhugo
;
e
=
compute_etotal
();
temperature
->
compute_vector
();
pressure
->
compute_vector
();
p
=
pressure
->
vector
[
direction
];
v
=
compute_vol
();
dhugo
=
(
0.5
*
(
p
+
p0
)
*
(
v0
-
v
))
/
force
->
nktv2p
+
e0
-
e
;
dhugo
/=
temperature
->
dof
*
force
->
boltz
;
return
dhugo
;
}
/* ----------------------------------------------------------------------
Computes the deviation of the current point from the Rayleigh
in pressure units for the QBMSST.
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_rayleigh
()
{
double
v
,
p
;
double
drayleigh
;
temperature
->
compute_vector
();
pressure
->
compute_vector
();
p
=
pressure
->
vector
[
direction
];
v
=
compute_vol
();
drayleigh
=
p
-
p0
-
total_mass
*
velocity
*
velocity
*
force
->
mvv2e
*
(
1.0
-
v
/
v0
)
*
force
->
nktv2p
/
v0
;
return
drayleigh
;
}
/* ----------------------------------------------------------------------
Computes the speed of the QBMSST computational cell in the
unshocked material rest-frame
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_lagrangian_speed
()
{
double
v
=
compute_vol
();
return
velocity
*
(
1.0
-
v
/
v0
);
}
/* ----------------------------------------------------------------------
Computes the distance behind the
shock front of the QBMSST computational cell.
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_lagrangian_position
()
{
return
lagrangian_position
;
}
/* ----------------------------------------------------------------------
Computes the atomic kinetic + atomic potential energy. This excludes the QBMSST
external potential terms in the QBMSST Lagrangian.
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_etotal
()
{
double
epot
,
ekin
,
etot
;
epot
=
pe
->
compute_scalar
();
if
(
thermo_energy
)
epot
-=
compute_scalar
();
ekin
=
temperature
->
compute_scalar
();
ekin
*=
0.5
*
temperature
->
dof
*
force
->
boltz
;
etot
=
epot
+
ekin
;
return
etot
;
}
/* ----------------------------------------------------------------------
Computes the atomic kinetic + atomic potential energy + QBMSST external potential.
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_egrand
()
{
double
epot
,
ekin
,
etot
;
epot
=
pe
->
compute_scalar
();
if
(
!
thermo_energy
)
epot
+=
compute_scalar
();
ekin
=
temperature
->
compute_scalar
();
ekin
*=
0.5
*
temperature
->
dof
*
force
->
boltz
;
etot
=
epot
+
ekin
;
return
etot
;
}
/* ----------------------------------------------------------------------
Computes the atomic kinetic + atomic potential energy. This excludes the QBMSST
external potential terms in the QBMSST Lagrangian.
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_vol
()
{
if
(
domain
->
dimension
==
3
)
return
domain
->
xprd
*
domain
->
yprd
*
domain
->
zprd
;
else
return
domain
->
xprd
*
domain
->
yprd
;
}
/* ----------------------------------------------------------------------
Checks to see if the allocated size of old_velocity is >= n
The number of local atoms can change during a parallel run.
------------------------------------------------------------------------- */
void
FixQBMSST
::
check_alloc
(
int
n
)
{
if
(
atoms_allocated
<
n
)
{
memory
->
destroy
(
old_velocity
);
memory
->
create
(
old_velocity
,
n
,
3
,
"qbmsst:old_velocity"
);
atoms_allocated
=
n
;
}
}
/* ----------------------------------------------------------------------
Computes the atomic kinetic + atomic potential energy. This excludes the QBMSST
external potential terms in the QBMSST Lagrangian.
------------------------------------------------------------------------- */
double
FixQBMSST
::
compute_vsum
()
{
double
vsum
;
double
**
v
=
atom
->
v
;
int
*
mask
=
atom
->
mask
;
int
nlocal
=
atom
->
nlocal
;
double
t
=
0.0
;
for
(
int
i
=
0
;
i
<
nlocal
;
i
++
)
{
if
(
mask
[
i
]
&
groupbit
)
{
t
+=
(
v
[
i
][
0
]
*
v
[
i
][
0
]
+
v
[
i
][
1
]
*
v
[
i
][
1
]
+
v
[
i
][
2
]
*
v
[
i
][
2
])
;
}
}
MPI_Allreduce
(
&
t
,
&
vsum
,
1
,
MPI_DOUBLE
,
MPI_SUM
,
world
);
return
vsum
;
}
/* ----------------------------------------------------------------------
memory usage of fix qbmsst
------------------------------------------------------------------------- */
double
FixQBMSST
::
memory_usage
()
{
double
bytes
=
0.0
;
// random_arrays memory usage
bytes
+=
(
atom
->
nmax
*
6
*
N_f
*
sizeof
(
double
));
// fran memory usage
bytes
+=
(
atom
->
nmax
*
3
*
sizeof
(
double
));
bytes
+=
(
4
*
N_f
*
sizeof
(
double
));
return
bytes
;
}
/* ----------------------------------------------------------------------
allocate atom-based array for fran and random_array
------------------------------------------------------------------------- */
void
FixQBMSST
::
grow_arrays
(
int
nmax
)
{
memory
->
grow
(
random_array_0
,
nmax
,
2
*
N_f
,
"qbmsst:random_array_0"
);
memory
->
grow
(
random_array_1
,
nmax
,
2
*
N_f
,
"qbmsst:random_array_1"
);
memory
->
grow
(
random_array_2
,
nmax
,
2
*
N_f
,
"qbmsst:random_array_2"
);
memory
->
grow
(
fran
,
nmax
,
3
,
"qbmsst:fran"
);
}
/* ----------------------------------------------------------------------
copy values within local atom-based array
------------------------------------------------------------------------- */
void
FixQBMSST
::
copy_arrays
(
int
i
,
int
j
,
int
delflag
)
{
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
{
random_array_0
[
j
][
m
]
=
random_array_0
[
i
][
m
];
random_array_1
[
j
][
m
]
=
random_array_1
[
i
][
m
];
random_array_2
[
j
][
m
]
=
random_array_2
[
i
][
m
];
}
for
(
int
m
=
0
;
m
<
3
;
m
++
)
fran
[
j
][
m
]
=
fran
[
i
][
m
];
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int
FixQBMSST
::
pack_exchange
(
int
i
,
double
*
buf
)
{
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
buf
[
m
]
=
random_array_0
[
i
][
m
];
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
buf
[
m
+
2
*
N_f
]
=
random_array_1
[
i
][
m
];
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
buf
[
m
+
4
*
N_f
]
=
random_array_2
[
i
][
m
];
for
(
int
m
=
0
;
m
<
3
;
m
++
)
buf
[
m
+
6
*
N_f
]
=
fran
[
i
][
m
];
return
6
*
N_f
+
3
;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int
FixQBMSST
::
unpack_exchange
(
int
nlocal
,
double
*
buf
)
{
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
random_array_0
[
nlocal
][
m
]
=
buf
[
m
];
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
random_array_1
[
nlocal
][
m
]
=
buf
[
m
+
2
*
N_f
];
for
(
int
m
=
0
;
m
<
2
*
N_f
;
m
++
)
random_array_2
[
nlocal
][
m
]
=
buf
[
m
+
4
*
N_f
];
for
(
int
m
=
0
;
m
<
3
;
m
++
)
fran
[
nlocal
][
m
]
=
buf
[
m
+
6
*
N_f
];
return
6
*
N_f
+
3
;
}
Event Timeline
Log In to Comment