Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F91044677
fix_rigid_nh_omp.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
Thu, Nov 7, 06:36
Size
29 KB
Mime Type
text/x-c
Expires
Sat, Nov 9, 06:36 (1 d, 22 h)
Engine
blob
Format
Raw Data
Handle
22184818
Attached To
rLAMMPS lammps
fix_rigid_nh_omp.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 author: Axel Kohlmeyer (Temple U)
------------------------------------------------------------------------- */
#include "fix_rigid_nh_omp.h"
#include "atom.h"
#include "atom_vec_ellipsoid.h"
#include "atom_vec_line.h"
#include "atom_vec_tri.h"
#include "comm.h"
#include "compute.h"
#include "domain.h"
#include "force.h"
#include "kspace.h"
#include "modify.h"
#include "update.h"
#include <string.h>
#if defined(_OPENMP)
#include <omp.h>
#endif
#include "math_extra.h"
#include "math_const.h"
using
namespace
LAMMPS_NS
;
using
namespace
FixConst
;
using
namespace
MathConst
;
enum
{
SINGLE
,
MOLECULE
,
GROUP
};
// same as in FixRigid
enum
{
ISO
,
ANISO
,
TRICLINIC
};
// same as in FixRigid
#define EINERTIA 0.4
// moment of inertia prefactor for ellipsoid
typedef
struct
{
double
x
,
y
,
z
;
}
dbl3_t
;
/* ----------------------------------------------------------------------
perform preforce velocity Verlet integration
see Kamberaj paper for step references
------------------------------------------------------------------------- */
void
FixRigidNHOMP
::
initial_integrate
(
int
vflag
)
{
double
scale_r
,
scale_t
[
3
],
scale_v
[
3
];
// compute scale variables
scale_t
[
0
]
=
scale_t
[
1
]
=
scale_t
[
2
]
=
1.0
;
scale_v
[
0
]
=
scale_v
[
1
]
=
scale_v
[
2
]
=
1.0
;
scale_r
=
1.0
;
if
(
tstat_flag
)
{
akin_t
=
akin_r
=
0.0
;
double
tmp
=
exp
(
-
dtq
*
eta_dot_t
[
0
]);
scale_t
[
0
]
=
scale_t
[
1
]
=
scale_t
[
2
]
=
tmp
;
tmp
=
exp
(
-
dtq
*
eta_dot_r
[
0
]);
scale_r
=
tmp
;
}
if
(
pstat_flag
)
{
akin_t
=
akin_r
=
0.0
;
scale_t
[
0
]
*=
exp
(
-
dtq
*
(
epsilon_dot
[
0
]
+
mtk_term2
));
scale_t
[
1
]
*=
exp
(
-
dtq
*
(
epsilon_dot
[
1
]
+
mtk_term2
));
scale_t
[
2
]
*=
exp
(
-
dtq
*
(
epsilon_dot
[
2
]
+
mtk_term2
));
scale_r
*=
exp
(
-
dtq
*
(
pdim
*
mtk_term2
));
double
tmp
=
dtq
*
epsilon_dot
[
0
];
scale_v
[
0
]
=
dtv
*
exp
(
tmp
)
*
maclaurin_series
(
tmp
);
tmp
=
dtq
*
epsilon_dot
[
1
];
scale_v
[
1
]
=
dtv
*
exp
(
tmp
)
*
maclaurin_series
(
tmp
);
tmp
=
dtq
*
epsilon_dot
[
2
];
scale_v
[
2
]
=
dtv
*
exp
(
tmp
)
*
maclaurin_series
(
tmp
);
}
// update xcm, vcm, quat, conjqm and angmom
double
akt
=
0.0
,
akr
=
0.0
;
int
ibody
;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(ibody) shared(scale_r,scale_t,scale_v) schedule(static) reduction(+:akt,akr)
#endif
for
(
ibody
=
0
;
ibody
<
nbody
;
ibody
++
)
{
double
mbody
[
3
],
tbody
[
3
],
fquat
[
4
];
const
double
dtf2
=
dtf
*
2.0
;
// step 1.1 - update vcm by 1/2 step
const
double
dtfm
=
dtf
/
masstotal
[
ibody
];
vcm
[
ibody
][
0
]
+=
dtfm
*
fcm
[
ibody
][
0
]
*
fflag
[
ibody
][
0
];
vcm
[
ibody
][
1
]
+=
dtfm
*
fcm
[
ibody
][
1
]
*
fflag
[
ibody
][
1
];
vcm
[
ibody
][
2
]
+=
dtfm
*
fcm
[
ibody
][
2
]
*
fflag
[
ibody
][
2
];
if
(
tstat_flag
||
pstat_flag
)
{
vcm
[
ibody
][
0
]
*=
scale_t
[
0
];
vcm
[
ibody
][
1
]
*=
scale_t
[
1
];
vcm
[
ibody
][
2
]
*=
scale_t
[
2
];
double
tmp
=
vcm
[
ibody
][
0
]
*
vcm
[
ibody
][
0
]
+
vcm
[
ibody
][
1
]
*
vcm
[
ibody
][
1
]
+
vcm
[
ibody
][
2
]
*
vcm
[
ibody
][
2
];
akt
+=
masstotal
[
ibody
]
*
tmp
;
}
// step 1.2 - update xcm by full step
if
(
!
pstat_flag
)
{
xcm
[
ibody
][
0
]
+=
dtv
*
vcm
[
ibody
][
0
];
xcm
[
ibody
][
1
]
+=
dtv
*
vcm
[
ibody
][
1
];
xcm
[
ibody
][
2
]
+=
dtv
*
vcm
[
ibody
][
2
];
}
else
{
xcm
[
ibody
][
0
]
+=
scale_v
[
0
]
*
vcm
[
ibody
][
0
];
xcm
[
ibody
][
1
]
+=
scale_v
[
1
]
*
vcm
[
ibody
][
1
];
xcm
[
ibody
][
2
]
+=
scale_v
[
2
]
*
vcm
[
ibody
][
2
];
}
// step 1.3 - apply torque (body coords) to quaternion momentum
torque
[
ibody
][
0
]
*=
tflag
[
ibody
][
0
];
torque
[
ibody
][
1
]
*=
tflag
[
ibody
][
1
];
torque
[
ibody
][
2
]
*=
tflag
[
ibody
][
2
];
MathExtra
::
transpose_matvec
(
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
],
torque
[
ibody
],
tbody
);
MathExtra
::
quatvec
(
quat
[
ibody
],
tbody
,
fquat
);
conjqm
[
ibody
][
0
]
+=
dtf2
*
fquat
[
0
];
conjqm
[
ibody
][
1
]
+=
dtf2
*
fquat
[
1
];
conjqm
[
ibody
][
2
]
+=
dtf2
*
fquat
[
2
];
conjqm
[
ibody
][
3
]
+=
dtf2
*
fquat
[
3
];
if
(
tstat_flag
||
pstat_flag
)
{
conjqm
[
ibody
][
0
]
*=
scale_r
;
conjqm
[
ibody
][
1
]
*=
scale_r
;
conjqm
[
ibody
][
2
]
*=
scale_r
;
conjqm
[
ibody
][
3
]
*=
scale_r
;
}
// step 1.4 to 1.13 - use no_squish rotate to update p and q
MathExtra
::
no_squish_rotate
(
3
,
conjqm
[
ibody
],
quat
[
ibody
],
inertia
[
ibody
],
dtq
);
MathExtra
::
no_squish_rotate
(
2
,
conjqm
[
ibody
],
quat
[
ibody
],
inertia
[
ibody
],
dtq
);
MathExtra
::
no_squish_rotate
(
1
,
conjqm
[
ibody
],
quat
[
ibody
],
inertia
[
ibody
],
dtv
);
MathExtra
::
no_squish_rotate
(
2
,
conjqm
[
ibody
],
quat
[
ibody
],
inertia
[
ibody
],
dtq
);
MathExtra
::
no_squish_rotate
(
3
,
conjqm
[
ibody
],
quat
[
ibody
],
inertia
[
ibody
],
dtq
);
// update exyz_space
// transform p back to angmom
// update angular velocity
MathExtra
::
q_to_exyz
(
quat
[
ibody
],
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
]);
MathExtra
::
invquatvec
(
quat
[
ibody
],
conjqm
[
ibody
],
mbody
);
MathExtra
::
matvec
(
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
],
mbody
,
angmom
[
ibody
]);
angmom
[
ibody
][
0
]
*=
0.5
;
angmom
[
ibody
][
1
]
*=
0.5
;
angmom
[
ibody
][
2
]
*=
0.5
;
MathExtra
::
angmom_to_omega
(
angmom
[
ibody
],
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
],
inertia
[
ibody
],
omega
[
ibody
]);
if
(
tstat_flag
||
pstat_flag
)
{
akr
+=
angmom
[
ibody
][
0
]
*
omega
[
ibody
][
0
]
+
angmom
[
ibody
][
1
]
*
omega
[
ibody
][
1
]
+
angmom
[
ibody
][
2
]
*
omega
[
ibody
][
2
];
}
}
// end of parallel for
if
(
pstat_flag
||
tstat_flag
)
{
akin_t
=
akt
;
akin_r
=
akr
;
}
// compute target temperature
// update thermostat chains using akin_t and akin_r
// refer to update_nhcp() in Kamberaj et al.
if
(
tstat_flag
)
{
compute_temp_target
();
nhc_temp_integrate
();
}
// update thermostat chains coupled with barostat
// refer to update_nhcb() in Kamberaj et al.
if
(
pstat_flag
)
{
nhc_press_integrate
();
}
// virial setup before call to set_xv
if
(
vflag
)
v_setup
(
vflag
);
else
evflag
=
0
;
// remap simulation box by 1/2 step
if
(
pstat_flag
)
remap
();
// set coords/orient and velocity/rotation of atoms in rigid bodies
// from quarternion and omega
if
(
triclinic
)
if
(
evflag
)
set_xv_thr
<
1
,
1
>
();
else
set_xv_thr
<
1
,
0
>
();
else
if
(
evflag
)
set_xv_thr
<
0
,
1
>
();
else
set_xv_thr
<
0
,
0
>
();
// remap simulation box by full step
// redo KSpace coeffs since volume has changed
if
(
pstat_flag
)
{
remap
();
if
(
kspace_flag
)
force
->
kspace
->
setup
();
}
}
/* ---------------------------------------------------------------------- */
void
FixRigidNHOMP
::
final_integrate
()
{
double
scale_t
[
3
],
scale_r
;
// compute scale variables
scale_t
[
0
]
=
scale_t
[
1
]
=
scale_t
[
2
]
=
1.0
;
scale_r
=
1.0
;
if
(
tstat_flag
)
{
double
tmp
=
exp
(
-
1.0
*
dtq
*
eta_dot_t
[
0
]);
scale_t
[
0
]
=
scale_t
[
1
]
=
scale_t
[
2
]
=
tmp
;
scale_r
=
exp
(
-
1.0
*
dtq
*
eta_dot_r
[
0
]);
}
if
(
pstat_flag
)
{
scale_t
[
0
]
*=
exp
(
-
dtq
*
(
epsilon_dot
[
0
]
+
mtk_term2
));
scale_t
[
1
]
*=
exp
(
-
dtq
*
(
epsilon_dot
[
1
]
+
mtk_term2
));
scale_t
[
2
]
*=
exp
(
-
dtq
*
(
epsilon_dot
[
2
]
+
mtk_term2
));
scale_r
*=
exp
(
-
dtq
*
(
pdim
*
mtk_term2
));
akin_t
=
akin_r
=
0.0
;
}
double
*
const
*
_noalias
const
x
=
atom
->
x
;
const
dbl3_t
*
_noalias
const
f
=
(
dbl3_t
*
)
atom
->
f
[
0
];
const
double
*
const
*
const
torque_one
=
atom
->
torque
;
const
int
nlocal
=
atom
->
nlocal
;
// sum over atoms to get force and torque on rigid body
// we have 3 different strategies for multi-threading this.
if
(
rstyle
==
SINGLE
)
{
// we have just one rigid body. use OpenMP reduction to get sum[]
double
s0
=
0.0
,
s1
=
0.0
,
s2
=
0.0
,
s3
=
0.0
,
s4
=
0.0
,
s5
=
0.0
;
int
i
;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(i) reduction(+:s0,s1,s2,s3,s4,s5)
#endif
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
const
int
ibody
=
body
[
i
];
if
(
ibody
<
0
)
continue
;
double
unwrap
[
3
];
domain
->
unmap
(
x
[
i
],
xcmimage
[
i
],
unwrap
);
const
double
dx
=
unwrap
[
0
]
-
xcm
[
0
][
0
];
const
double
dy
=
unwrap
[
1
]
-
xcm
[
0
][
1
];
const
double
dz
=
unwrap
[
2
]
-
xcm
[
0
][
2
];
s0
+=
f
[
i
].
x
;
s1
+=
f
[
i
].
y
;
s2
+=
f
[
i
].
z
;
s3
+=
dy
*
f
[
i
].
z
-
dz
*
f
[
i
].
y
;
s4
+=
dz
*
f
[
i
].
x
-
dx
*
f
[
i
].
z
;
s5
+=
dx
*
f
[
i
].
y
-
dy
*
f
[
i
].
x
;
if
(
extended
&&
(
eflags
[
i
]
&
TORQUE
))
{
s3
+=
torque_one
[
i
][
0
];
s4
+=
torque_one
[
i
][
1
];
s5
+=
torque_one
[
i
][
2
];
}
}
sum
[
0
][
0
]
=
s0
;
sum
[
0
][
1
]
=
s1
;
sum
[
0
][
2
]
=
s2
;
sum
[
0
][
3
]
=
s3
;
sum
[
0
][
4
]
=
s4
;
sum
[
0
][
5
]
=
s5
;
}
else
if
(
rstyle
==
GROUP
)
{
// we likely have only a rather number of groups so we loops
// over bodies and thread over all atoms for each of them.
for
(
int
ib
=
0
;
ib
<
nbody
;
++
ib
)
{
double
s0
=
0.0
,
s1
=
0.0
,
s2
=
0.0
,
s3
=
0.0
,
s4
=
0.0
,
s5
=
0.0
;
int
i
;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(i) shared(ib) reduction(+:s0,s1,s2,s3,s4,s5)
#endif
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
const
int
ibody
=
body
[
i
];
if
(
ibody
!=
ib
)
continue
;
s0
+=
f
[
i
].
x
;
s1
+=
f
[
i
].
y
;
s2
+=
f
[
i
].
z
;
double
unwrap
[
3
];
domain
->
unmap
(
x
[
i
],
xcmimage
[
i
],
unwrap
);
const
double
dx
=
unwrap
[
0
]
-
xcm
[
ibody
][
0
];
const
double
dy
=
unwrap
[
1
]
-
xcm
[
ibody
][
1
];
const
double
dz
=
unwrap
[
2
]
-
xcm
[
ibody
][
2
];
s3
+=
dy
*
f
[
i
].
z
-
dz
*
f
[
i
].
y
;
s4
+=
dz
*
f
[
i
].
x
-
dx
*
f
[
i
].
z
;
s5
+=
dx
*
f
[
i
].
y
-
dy
*
f
[
i
].
x
;
if
(
extended
&&
(
eflags
[
i
]
&
TORQUE
))
{
s3
+=
torque_one
[
i
][
0
];
s4
+=
torque_one
[
i
][
1
];
s5
+=
torque_one
[
i
][
2
];
}
}
sum
[
ib
][
0
]
=
s0
;
sum
[
ib
][
1
]
=
s1
;
sum
[
ib
][
2
]
=
s2
;
sum
[
ib
][
3
]
=
s3
;
sum
[
ib
][
4
]
=
s4
;
sum
[
ib
][
5
]
=
s5
;
}
}
else
if
(
rstyle
==
MOLECULE
)
{
// we likely have a large number of rigid objects with only a
// a few atoms each. so we loop over all atoms for all threads
// and then each thread only processes some bodies.
const
int
nthreads
=
comm
->
nthreads
;
memset
(
&
sum
[
0
][
0
],
0
,
6
*
nbody
*
sizeof
(
double
));
#if defined(_OPENMP)
#pragma omp parallel default(none)
#endif
{
#if defined(_OPENMP)
const
int
tid
=
omp_get_thread_num
();
#else
const
int
tid
=
0
;
#endif
for
(
int
i
=
0
;
i
<
nlocal
;
i
++
)
{
const
int
ibody
=
body
[
i
];
if
((
ibody
<
0
)
||
(
ibody
%
nthreads
!=
tid
))
continue
;
double
unwrap
[
3
];
domain
->
unmap
(
x
[
i
],
xcmimage
[
i
],
unwrap
);
const
double
dx
=
unwrap
[
0
]
-
xcm
[
ibody
][
0
];
const
double
dy
=
unwrap
[
1
]
-
xcm
[
ibody
][
1
];
const
double
dz
=
unwrap
[
2
]
-
xcm
[
ibody
][
2
];
const
double
s0
=
f
[
i
].
x
;
const
double
s1
=
f
[
i
].
y
;
const
double
s2
=
f
[
i
].
z
;
double
s3
=
dy
*
s2
-
dz
*
s1
;
double
s4
=
dz
*
s0
-
dx
*
s2
;
double
s5
=
dx
*
s1
-
dy
*
s0
;
if
(
extended
&&
(
eflags
[
i
]
&
TORQUE
))
{
s3
+=
torque_one
[
i
][
0
];
s4
+=
torque_one
[
i
][
1
];
s5
+=
torque_one
[
i
][
2
];
}
sum
[
ibody
][
0
]
+=
s0
;
sum
[
ibody
][
1
]
+=
s1
;
sum
[
ibody
][
2
]
+=
s2
;
sum
[
ibody
][
3
]
+=
s3
;
sum
[
ibody
][
4
]
+=
s4
;
sum
[
ibody
][
5
]
+=
s5
;
}
}
}
else
error
->
all
(
FLERR
,
"rigid style is unsupported by fix rigid/omp"
);
MPI_Allreduce
(
sum
[
0
],
all
[
0
],
6
*
nbody
,
MPI_DOUBLE
,
MPI_SUM
,
world
);
// update vcm and angmom
// include Langevin thermostat forces
// fflag,tflag = 0 for some dimensions in 2d
double
akt
=
0.0
,
akr
=
0.0
;
const
double
dtf2
=
dtf
*
2.0
;
int
ibody
;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(ibody) shared(scale_t,scale_r) schedule(static) reduction(+:akt,akr)
#endif
for
(
ibody
=
0
;
ibody
<
nbody
;
ibody
++
)
{
double
mbody
[
3
],
tbody
[
3
],
fquat
[
4
];
fcm
[
ibody
][
0
]
=
all
[
ibody
][
0
]
+
langextra
[
ibody
][
0
];
fcm
[
ibody
][
1
]
=
all
[
ibody
][
1
]
+
langextra
[
ibody
][
1
];
fcm
[
ibody
][
2
]
=
all
[
ibody
][
2
]
+
langextra
[
ibody
][
2
];
torque
[
ibody
][
0
]
=
all
[
ibody
][
3
]
+
langextra
[
ibody
][
3
];
torque
[
ibody
][
1
]
=
all
[
ibody
][
4
]
+
langextra
[
ibody
][
4
];
torque
[
ibody
][
2
]
=
all
[
ibody
][
5
]
+
langextra
[
ibody
][
5
];
// update vcm by 1/2 step
const
double
dtfm
=
dtf
/
masstotal
[
ibody
];
if
(
tstat_flag
||
pstat_flag
)
{
vcm
[
ibody
][
0
]
*=
scale_t
[
0
];
vcm
[
ibody
][
1
]
*=
scale_t
[
1
];
vcm
[
ibody
][
2
]
*=
scale_t
[
2
];
}
vcm
[
ibody
][
0
]
+=
dtfm
*
fcm
[
ibody
][
0
]
*
fflag
[
ibody
][
0
];
vcm
[
ibody
][
1
]
+=
dtfm
*
fcm
[
ibody
][
1
]
*
fflag
[
ibody
][
1
];
vcm
[
ibody
][
2
]
+=
dtfm
*
fcm
[
ibody
][
2
]
*
fflag
[
ibody
][
2
];
if
(
pstat_flag
)
{
double
tmp
=
vcm
[
ibody
][
0
]
*
vcm
[
ibody
][
0
]
+
vcm
[
ibody
][
1
]
*
vcm
[
ibody
][
1
]
+
vcm
[
ibody
][
2
]
*
vcm
[
ibody
][
2
];
akt
+=
masstotal
[
ibody
]
*
tmp
;
}
// update conjqm, then transform to angmom, set velocity again
// virial is already setup from initial_integrate
torque
[
ibody
][
0
]
*=
tflag
[
ibody
][
0
];
torque
[
ibody
][
1
]
*=
tflag
[
ibody
][
1
];
torque
[
ibody
][
2
]
*=
tflag
[
ibody
][
2
];
MathExtra
::
transpose_matvec
(
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
],
torque
[
ibody
],
tbody
);
MathExtra
::
quatvec
(
quat
[
ibody
],
tbody
,
fquat
);
if
(
tstat_flag
||
pstat_flag
)
{
conjqm
[
ibody
][
0
]
=
scale_r
*
conjqm
[
ibody
][
0
]
+
dtf2
*
fquat
[
0
];
conjqm
[
ibody
][
1
]
=
scale_r
*
conjqm
[
ibody
][
1
]
+
dtf2
*
fquat
[
1
];
conjqm
[
ibody
][
2
]
=
scale_r
*
conjqm
[
ibody
][
2
]
+
dtf2
*
fquat
[
2
];
conjqm
[
ibody
][
3
]
=
scale_r
*
conjqm
[
ibody
][
3
]
+
dtf2
*
fquat
[
3
];
}
else
{
conjqm
[
ibody
][
0
]
+=
dtf2
*
fquat
[
0
];
conjqm
[
ibody
][
1
]
+=
dtf2
*
fquat
[
1
];
conjqm
[
ibody
][
2
]
+=
dtf2
*
fquat
[
2
];
conjqm
[
ibody
][
3
]
+=
dtf2
*
fquat
[
3
];
}
MathExtra
::
invquatvec
(
quat
[
ibody
],
conjqm
[
ibody
],
mbody
);
MathExtra
::
matvec
(
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
],
mbody
,
angmom
[
ibody
]);
angmom
[
ibody
][
0
]
*=
0.5
;
angmom
[
ibody
][
1
]
*=
0.5
;
angmom
[
ibody
][
2
]
*=
0.5
;
MathExtra
::
angmom_to_omega
(
angmom
[
ibody
],
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
],
inertia
[
ibody
],
omega
[
ibody
]);
if
(
pstat_flag
)
{
akr
+=
angmom
[
ibody
][
0
]
*
omega
[
ibody
][
0
]
+
angmom
[
ibody
][
1
]
*
omega
[
ibody
][
1
]
+
angmom
[
ibody
][
2
]
*
omega
[
ibody
][
2
];
}
}
// end of parallel for
if
(
pstat_flag
)
{
akin_t
+=
akt
;
akin_r
+=
akr
;
}
// set velocity/rotation of atoms in rigid bodies
// virial is already setup from initial_integrate
// triclinic only matters for virial calculation.
if
(
evflag
)
if
(
triclinic
)
set_v_thr
<
1
,
1
>
();
else
set_v_thr
<
0
,
1
>
();
else
set_v_thr
<
0
,
0
>
();
// compute current temperature
if
(
tcomputeflag
)
t_current
=
temperature
->
compute_scalar
();
// compute current and target pressures
// update epsilon dot using akin_t and akin_r
if
(
pstat_flag
)
{
if
(
pstyle
==
ISO
)
{
temperature
->
compute_scalar
();
pressure
->
compute_scalar
();
}
else
{
temperature
->
compute_vector
();
pressure
->
compute_vector
();
}
couple
();
pressure
->
addstep
(
update
->
ntimestep
+
1
);
compute_press_target
();
nh_epsilon_dot
();
}
}
/* ---------------------------------------------------------------------- */
void
FixRigidNHOMP
::
remap
()
{
double
*
const
*
_noalias
const
x
=
atom
->
x
;
const
int
*
_noalias
const
mask
=
atom
->
mask
;
const
int
nlocal
=
atom
->
nlocal
;
// epsilon is not used, except for book-keeping
for
(
int
i
=
0
;
i
<
3
;
i
++
)
epsilon
[
i
]
+=
dtq
*
epsilon_dot
[
i
];
// convert pertinent atoms and rigid bodies to lamda coords
if
(
allremap
)
domain
->
x2lamda
(
nlocal
);
else
{
int
i
;
#if defined (_OPENMP)
#pragma omp parallel for private(i) default(none) schedule(static)
#endif
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
if
(
mask
[
i
]
&
dilate_group_bit
)
domain
->
x2lamda
(
x
[
i
],
x
[
i
]);
}
if
(
nrigid
)
for
(
int
i
=
0
;
i
<
nrigidfix
;
i
++
)
modify
->
fix
[
rfix
[
i
]]
->
deform
(
0
);
// reset global and local box to new size/shape
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
if
(
p_flag
[
i
])
{
const
double
oldlo
=
domain
->
boxlo
[
i
];
const
double
oldhi
=
domain
->
boxhi
[
i
];
const
double
ctr
=
0.5
*
(
oldlo
+
oldhi
);
const
double
expfac
=
exp
(
dtq
*
epsilon_dot
[
i
]);
domain
->
boxlo
[
i
]
=
(
oldlo
-
ctr
)
*
expfac
+
ctr
;
domain
->
boxhi
[
i
]
=
(
oldhi
-
ctr
)
*
expfac
+
ctr
;
}
}
domain
->
set_global_box
();
domain
->
set_local_box
();
// convert pertinent atoms and rigid bodies back to box coords
if
(
allremap
)
domain
->
lamda2x
(
nlocal
);
else
{
int
i
;
#if defined (_OPENMP)
#pragma omp parallel for private(i) default(none) schedule(static)
#endif
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
if
(
mask
[
i
]
&
dilate_group_bit
)
domain
->
lamda2x
(
x
[
i
],
x
[
i
]);
}
if
(
nrigid
)
for
(
int
i
=
0
;
i
<
nrigidfix
;
i
++
)
modify
->
fix
[
rfix
[
i
]]
->
deform
(
1
);
}
/* ----------------------------------------------------------------------
set space-frame coords and velocity of each atom in each rigid body
set orientation and rotation of extended particles
x = Q displace + Xcm, mapped back to periodic box
v = Vcm + (W cross (x - Xcm))
NOTE: this needs to be kept in sync with FixRigidOMP
------------------------------------------------------------------------- */
template
<
int
TRICLINIC
,
int
EVFLAG
>
void
FixRigidNHOMP
::
set_xv_thr
()
{
dbl3_t
*
_noalias
const
x
=
(
dbl3_t
*
)
atom
->
x
[
0
];
dbl3_t
*
_noalias
const
v
=
(
dbl3_t
*
)
atom
->
v
[
0
];
const
dbl3_t
*
_noalias
const
f
=
(
dbl3_t
*
)
atom
->
f
[
0
];
const
double
*
_noalias
const
rmass
=
atom
->
rmass
;
const
double
*
_noalias
const
mass
=
atom
->
mass
;
const
int
*
_noalias
const
type
=
atom
->
type
;
double
v0
=
0.0
,
v1
=
0.0
,
v2
=
0.0
,
v3
=
0.0
,
v4
=
0.0
,
v5
=
0.0
;
const
double
xprd
=
domain
->
xprd
;
const
double
yprd
=
domain
->
yprd
;
const
double
zprd
=
domain
->
zprd
;
const
double
xy
=
domain
->
xy
;
const
double
xz
=
domain
->
xz
;
const
double
yz
=
domain
->
yz
;
// set x and v of each atom
const
int
nlocal
=
atom
->
nlocal
;
int
i
;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(i) reduction(+:v0,v1,v2,v3,v4,v5)
#endif
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
const
int
ibody
=
body
[
i
];
if
(
ibody
<
0
)
continue
;
const
dbl3_t
&
xcmi
=
*
((
dbl3_t
*
)
xcm
[
ibody
]);
const
dbl3_t
&
vcmi
=
*
((
dbl3_t
*
)
vcm
[
ibody
]);
const
dbl3_t
&
omegai
=
*
((
dbl3_t
*
)
omega
[
ibody
]);
const
int
xbox
=
(
xcmimage
[
i
]
&
IMGMASK
)
-
IMGMAX
;
const
int
ybox
=
(
xcmimage
[
i
]
>>
IMGBITS
&
IMGMASK
)
-
IMGMAX
;
const
int
zbox
=
(
xcmimage
[
i
]
>>
IMG2BITS
)
-
IMGMAX
;
const
double
deltax
=
xbox
*
xprd
+
(
TRICLINIC
?
ybox
*
xy
+
zbox
*
xz
:
0.0
);
const
double
deltay
=
ybox
*
yprd
+
(
TRICLINIC
?
zbox
*
yz
:
0.0
);
const
double
deltaz
=
zbox
*
zprd
;
// save old positions and velocities for virial
double
x0
,
x1
,
x2
,
vx
,
vy
,
vz
;
if
(
EVFLAG
)
{
x0
=
x
[
i
].
x
+
deltax
;
x1
=
x
[
i
].
y
+
deltay
;
x2
=
x
[
i
].
z
+
deltaz
;
vx
=
v
[
i
].
x
;
vy
=
v
[
i
].
y
;
vz
=
v
[
i
].
z
;
}
// x = displacement from center-of-mass, based on body orientation
// v = vcm + omega around center-of-mass
MathExtra
::
matvec
(
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
],
displace
[
i
],
&
x
[
i
].
x
);
v
[
i
].
x
=
omegai
.
y
*
x
[
i
].
z
-
omegai
.
z
*
x
[
i
].
y
+
vcmi
.
x
;
v
[
i
].
y
=
omegai
.
z
*
x
[
i
].
x
-
omegai
.
x
*
x
[
i
].
z
+
vcmi
.
y
;
v
[
i
].
z
=
omegai
.
x
*
x
[
i
].
y
-
omegai
.
y
*
x
[
i
].
x
+
vcmi
.
z
;
// add center of mass to displacement
// map back into periodic box via xbox,ybox,zbox
// for triclinic, add in box tilt factors as well
x
[
i
].
x
+=
xcmi
.
x
-
deltax
;
x
[
i
].
y
+=
xcmi
.
y
-
deltay
;
x
[
i
].
z
+=
xcmi
.
z
-
deltaz
;
// virial = unwrapped coords dotted into body constraint force
// body constraint force = implied force due to v change minus f external
// assume f does not include forces internal to body
// 1/2 factor b/c final_integrate contributes other half
// assume per-atom contribution is due to constraint force on that atom
if
(
EVFLAG
)
{
double
massone
,
vr
[
6
];
if
(
rmass
)
massone
=
rmass
[
i
];
else
massone
=
mass
[
type
[
i
]];
const
double
fc0
=
0.5
*
(
massone
*
(
v
[
i
].
x
-
vx
)
/
dtf
-
f
[
i
].
x
);
const
double
fc1
=
0.5
*
(
massone
*
(
v
[
i
].
y
-
vy
)
/
dtf
-
f
[
i
].
y
);
const
double
fc2
=
0.5
*
(
massone
*
(
v
[
i
].
z
-
vz
)
/
dtf
-
f
[
i
].
z
);
vr
[
0
]
=
x0
*
fc0
;
vr
[
1
]
=
x1
*
fc1
;
vr
[
2
]
=
x2
*
fc2
;
vr
[
3
]
=
x0
*
fc1
;
vr
[
4
]
=
x0
*
fc2
;
vr
[
5
]
=
x1
*
fc2
;
// Fix::v_tally() is not thread safe, so we do this manually here
// accumulate global virial into thread-local variables for reduction
if
(
vflag_global
)
{
v0
+=
vr
[
0
];
v1
+=
vr
[
1
];
v2
+=
vr
[
2
];
v3
+=
vr
[
3
];
v4
+=
vr
[
4
];
v5
+=
vr
[
5
];
}
// accumulate per atom virial directly since we parallelize over atoms.
if
(
vflag_atom
)
{
vatom
[
i
][
0
]
+=
vr
[
0
];
vatom
[
i
][
1
]
+=
vr
[
1
];
vatom
[
i
][
2
]
+=
vr
[
2
];
vatom
[
i
][
3
]
+=
vr
[
3
];
vatom
[
i
][
4
]
+=
vr
[
4
];
vatom
[
i
][
5
]
+=
vr
[
5
];
}
}
}
// second part of thread safe virial accumulation
// add global virial component after it was reduced across all threads
if
(
EVFLAG
)
{
if
(
vflag_global
)
{
virial
[
0
]
+=
v0
;
virial
[
1
]
+=
v1
;
virial
[
2
]
+=
v2
;
virial
[
3
]
+=
v3
;
virial
[
4
]
+=
v4
;
virial
[
5
]
+=
v5
;
}
}
// set orientation, omega, angmom of each extended particle
// XXX: extended particle info not yet multi-threaded
if
(
extended
)
{
double
*
shape
,
*
quatatom
,
*
inertiaatom
;
double
theta_body
,
theta
;
double
ione
[
3
],
exone
[
3
],
eyone
[
3
],
ezone
[
3
],
p
[
3
][
3
];
AtomVecEllipsoid
::
Bonus
*
ebonus
;
if
(
avec_ellipsoid
)
ebonus
=
avec_ellipsoid
->
bonus
;
AtomVecLine
::
Bonus
*
lbonus
;
if
(
avec_line
)
lbonus
=
avec_line
->
bonus
;
AtomVecTri
::
Bonus
*
tbonus
;
if
(
avec_tri
)
tbonus
=
avec_tri
->
bonus
;
double
**
omega_one
=
atom
->
omega
;
double
**
angmom_one
=
atom
->
angmom
;
double
**
mu
=
atom
->
mu
;
int
*
ellipsoid
=
atom
->
ellipsoid
;
int
*
line
=
atom
->
line
;
int
*
tri
=
atom
->
tri
;
for
(
int
i
=
0
;
i
<
nlocal
;
i
++
)
{
const
int
ibody
=
body
[
i
];
if
(
ibody
<
0
)
continue
;
if
(
eflags
[
i
]
&
SPHERE
)
{
omega_one
[
i
][
0
]
=
omega
[
ibody
][
0
];
omega_one
[
i
][
1
]
=
omega
[
ibody
][
1
];
omega_one
[
i
][
2
]
=
omega
[
ibody
][
2
];
}
else
if
(
eflags
[
i
]
&
ELLIPSOID
)
{
shape
=
ebonus
[
ellipsoid
[
i
]].
shape
;
quatatom
=
ebonus
[
ellipsoid
[
i
]].
quat
;
MathExtra
::
quatquat
(
quat
[
ibody
],
orient
[
i
],
quatatom
);
MathExtra
::
qnormalize
(
quatatom
);
ione
[
0
]
=
EINERTIA
*
rmass
[
i
]
*
(
shape
[
1
]
*
shape
[
1
]
+
shape
[
2
]
*
shape
[
2
]);
ione
[
1
]
=
EINERTIA
*
rmass
[
i
]
*
(
shape
[
0
]
*
shape
[
0
]
+
shape
[
2
]
*
shape
[
2
]);
ione
[
2
]
=
EINERTIA
*
rmass
[
i
]
*
(
shape
[
0
]
*
shape
[
0
]
+
shape
[
1
]
*
shape
[
1
]);
MathExtra
::
q_to_exyz
(
quatatom
,
exone
,
eyone
,
ezone
);
MathExtra
::
omega_to_angmom
(
omega
[
ibody
],
exone
,
eyone
,
ezone
,
ione
,
angmom_one
[
i
]);
}
else
if
(
eflags
[
i
]
&
LINE
)
{
if
(
quat
[
ibody
][
3
]
>=
0.0
)
theta_body
=
2.0
*
acos
(
quat
[
ibody
][
0
]);
else
theta_body
=
-
2.0
*
acos
(
quat
[
ibody
][
0
]);
theta
=
orient
[
i
][
0
]
+
theta_body
;
while
(
theta
<=
MINUSPI
)
theta
+=
TWOPI
;
while
(
theta
>
MY_PI
)
theta
-=
TWOPI
;
lbonus
[
line
[
i
]].
theta
=
theta
;
omega_one
[
i
][
0
]
=
omega
[
ibody
][
0
];
omega_one
[
i
][
1
]
=
omega
[
ibody
][
1
];
omega_one
[
i
][
2
]
=
omega
[
ibody
][
2
];
}
else
if
(
eflags
[
i
]
&
TRIANGLE
)
{
inertiaatom
=
tbonus
[
tri
[
i
]].
inertia
;
quatatom
=
tbonus
[
tri
[
i
]].
quat
;
MathExtra
::
quatquat
(
quat
[
ibody
],
orient
[
i
],
quatatom
);
MathExtra
::
qnormalize
(
quatatom
);
MathExtra
::
q_to_exyz
(
quatatom
,
exone
,
eyone
,
ezone
);
MathExtra
::
omega_to_angmom
(
omega
[
ibody
],
exone
,
eyone
,
ezone
,
inertiaatom
,
angmom_one
[
i
]);
}
if
(
eflags
[
i
]
&
DIPOLE
)
{
MathExtra
::
quat_to_mat
(
quat
[
ibody
],
p
);
MathExtra
::
matvec
(
p
,
dorient
[
i
],
mu
[
i
]);
MathExtra
::
snormalize3
(
mu
[
i
][
3
],
mu
[
i
],
mu
[
i
]);
}
}
}
}
/* ----------------------------------------------------------------------
set space-frame velocity of each atom in a rigid body
set omega and angmom of extended particles
v = Vcm + (W cross (x - Xcm))
NOTE: this needs to be kept in sync with FixRigidOMP
------------------------------------------------------------------------- */
template
<
int
TRICLINIC
,
int
EVFLAG
>
void
FixRigidNHOMP
::
set_v_thr
()
{
dbl3_t
*
_noalias
const
x
=
(
dbl3_t
*
)
atom
->
x
[
0
];
dbl3_t
*
_noalias
const
v
=
(
dbl3_t
*
)
atom
->
v
[
0
];
const
dbl3_t
*
_noalias
const
f
=
(
dbl3_t
*
)
atom
->
f
[
0
];
const
double
*
_noalias
const
rmass
=
atom
->
rmass
;
const
double
*
_noalias
const
mass
=
atom
->
mass
;
const
int
*
_noalias
const
type
=
atom
->
type
;
const
double
xprd
=
domain
->
xprd
;
const
double
yprd
=
domain
->
yprd
;
const
double
zprd
=
domain
->
zprd
;
const
double
xy
=
domain
->
xy
;
const
double
xz
=
domain
->
xz
;
const
double
yz
=
domain
->
yz
;
double
v0
=
0.0
,
v1
=
0.0
,
v2
=
0.0
,
v3
=
0.0
,
v4
=
0.0
,
v5
=
0.0
;
// set v of each atom
const
int
nlocal
=
atom
->
nlocal
;
int
i
;
#if defined(_OPENMP)
#pragma omp parallel for default(none) private(i) reduction(+:v0,v1,v2,v3,v4,v5)
#endif
for
(
i
=
0
;
i
<
nlocal
;
i
++
)
{
const
int
ibody
=
body
[
i
];
if
(
ibody
<
0
)
continue
;
const
dbl3_t
&
vcmi
=
*
((
dbl3_t
*
)
vcm
[
ibody
]);
const
dbl3_t
&
omegai
=
*
((
dbl3_t
*
)
omega
[
ibody
]);
double
delta
[
3
],
vx
,
vy
,
vz
;
MathExtra
::
matvec
(
ex_space
[
ibody
],
ey_space
[
ibody
],
ez_space
[
ibody
],
displace
[
i
],
delta
);
// save old velocities for virial
if
(
EVFLAG
)
{
vx
=
v
[
i
].
x
;
vy
=
v
[
i
].
y
;
vz
=
v
[
i
].
z
;
}
v
[
i
].
x
=
omegai
.
y
*
delta
[
2
]
-
omegai
.
z
*
delta
[
1
]
+
vcmi
.
x
;
v
[
i
].
y
=
omegai
.
z
*
delta
[
0
]
-
omegai
.
x
*
delta
[
2
]
+
vcmi
.
y
;
v
[
i
].
z
=
omegai
.
x
*
delta
[
1
]
-
omegai
.
y
*
delta
[
0
]
+
vcmi
.
z
;
// virial = unwrapped coords dotted into body constraint force
// body constraint force = implied force due to v change minus f external
// assume f does not include forces internal to body
// 1/2 factor b/c initial_integrate contributes other half
// assume per-atom contribution is due to constraint force on that atom
if
(
EVFLAG
)
{
double
massone
,
vr
[
6
];
if
(
rmass
)
massone
=
rmass
[
i
];
else
massone
=
mass
[
type
[
i
]];
const
int
xbox
=
(
xcmimage
[
i
]
&
IMGMASK
)
-
IMGMAX
;
const
int
ybox
=
(
xcmimage
[
i
]
>>
IMGBITS
&
IMGMASK
)
-
IMGMAX
;
const
int
zbox
=
(
xcmimage
[
i
]
>>
IMG2BITS
)
-
IMGMAX
;
const
double
deltax
=
xbox
*
xprd
+
(
TRICLINIC
?
ybox
*
xy
+
zbox
*
xz
:
0.0
);
const
double
deltay
=
ybox
*
yprd
+
(
TRICLINIC
?
zbox
*
yz
:
0.0
);
const
double
deltaz
=
zbox
*
zprd
;
const
double
fc0
=
0.5
*
(
massone
*
(
v
[
i
].
x
-
vx
)
/
dtf
-
f
[
i
].
x
);
const
double
fc1
=
0.5
*
(
massone
*
(
v
[
i
].
y
-
vy
)
/
dtf
-
f
[
i
].
y
);
const
double
fc2
=
0.5
*
(
massone
*
(
v
[
i
].
z
-
vz
)
/
dtf
-
f
[
i
].
z
);
const
double
x0
=
x
[
i
].
x
+
deltax
;
const
double
x1
=
x
[
i
].
y
+
deltay
;
const
double
x2
=
x
[
i
].
z
+
deltaz
;
vr
[
0
]
=
x0
*
fc0
;
vr
[
1
]
=
x1
*
fc1
;
vr
[
2
]
=
x2
*
fc2
;
vr
[
3
]
=
x0
*
fc1
;
vr
[
4
]
=
x0
*
fc2
;
vr
[
5
]
=
x1
*
fc2
;
// Fix::v_tally() is not thread safe, so we do this manually here
// accumulate global virial into thread-local variables and reduce them later
if
(
vflag_global
)
{
v0
+=
vr
[
0
];
v1
+=
vr
[
1
];
v2
+=
vr
[
2
];
v3
+=
vr
[
3
];
v4
+=
vr
[
4
];
v5
+=
vr
[
5
];
}
// accumulate per atom virial directly since we parallelize over atoms.
if
(
vflag_atom
)
{
vatom
[
i
][
0
]
+=
vr
[
0
];
vatom
[
i
][
1
]
+=
vr
[
1
];
vatom
[
i
][
2
]
+=
vr
[
2
];
vatom
[
i
][
3
]
+=
vr
[
3
];
vatom
[
i
][
4
]
+=
vr
[
4
];
vatom
[
i
][
5
]
+=
vr
[
5
];
}
}
}
// end of parallel for
// second part of thread safe virial accumulation
// add global virial component after it was reduced across all threads
if
(
EVFLAG
)
{
if
(
vflag_global
)
{
virial
[
0
]
+=
v0
;
virial
[
1
]
+=
v1
;
virial
[
2
]
+=
v2
;
virial
[
3
]
+=
v3
;
virial
[
4
]
+=
v4
;
virial
[
5
]
+=
v5
;
}
}
// set omega, angmom of each extended particle
// XXX: extended particle info not yet multi-threaded
if
(
extended
)
{
double
*
shape
,
*
quatatom
,
*
inertiaatom
;
double
ione
[
3
],
exone
[
3
],
eyone
[
3
],
ezone
[
3
];
AtomVecEllipsoid
::
Bonus
*
ebonus
;
if
(
avec_ellipsoid
)
ebonus
=
avec_ellipsoid
->
bonus
;
AtomVecTri
::
Bonus
*
tbonus
;
if
(
avec_tri
)
tbonus
=
avec_tri
->
bonus
;
double
**
omega_one
=
atom
->
omega
;
double
**
angmom_one
=
atom
->
angmom
;
int
*
ellipsoid
=
atom
->
ellipsoid
;
int
*
tri
=
atom
->
tri
;
for
(
int
i
=
0
;
i
<
nlocal
;
i
++
)
{
const
int
ibody
=
body
[
i
];
if
(
ibody
<
0
)
continue
;
if
(
eflags
[
i
]
&
SPHERE
)
{
omega_one
[
i
][
0
]
=
omega
[
ibody
][
0
];
omega_one
[
i
][
1
]
=
omega
[
ibody
][
1
];
omega_one
[
i
][
2
]
=
omega
[
ibody
][
2
];
}
else
if
(
eflags
[
i
]
&
ELLIPSOID
)
{
shape
=
ebonus
[
ellipsoid
[
i
]].
shape
;
quatatom
=
ebonus
[
ellipsoid
[
i
]].
quat
;
ione
[
0
]
=
EINERTIA
*
rmass
[
i
]
*
(
shape
[
1
]
*
shape
[
1
]
+
shape
[
2
]
*
shape
[
2
]);
ione
[
1
]
=
EINERTIA
*
rmass
[
i
]
*
(
shape
[
0
]
*
shape
[
0
]
+
shape
[
2
]
*
shape
[
2
]);
ione
[
2
]
=
EINERTIA
*
rmass
[
i
]
*
(
shape
[
0
]
*
shape
[
0
]
+
shape
[
1
]
*
shape
[
1
]);
MathExtra
::
q_to_exyz
(
quatatom
,
exone
,
eyone
,
ezone
);
MathExtra
::
omega_to_angmom
(
omega
[
ibody
],
exone
,
eyone
,
ezone
,
ione
,
angmom_one
[
i
]);
}
else
if
(
eflags
[
i
]
&
LINE
)
{
omega_one
[
i
][
0
]
=
omega
[
ibody
][
0
];
omega_one
[
i
][
1
]
=
omega
[
ibody
][
1
];
omega_one
[
i
][
2
]
=
omega
[
ibody
][
2
];
}
else
if
(
eflags
[
i
]
&
TRIANGLE
)
{
inertiaatom
=
tbonus
[
tri
[
i
]].
inertia
;
quatatom
=
tbonus
[
tri
[
i
]].
quat
;
MathExtra
::
q_to_exyz
(
quatatom
,
exone
,
eyone
,
ezone
);
MathExtra
::
omega_to_angmom
(
omega
[
ibody
],
exone
,
eyone
,
ezone
,
inertiaatom
,
angmom_one
[
i
]);
}
}
}
}
Event Timeline
Log In to Comment