Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F66066259
create_atoms.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
Sat, Jun 8, 01:15
Size
23 KB
Mime Type
text/x-c
Expires
Mon, Jun 10, 01:15 (2 d)
Engine
blob
Format
Raw Data
Handle
18168039
Attached To
rLAMMPS lammps
create_atoms.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.
------------------------------------------------------------------------- */
#include "math.h"
#include "stdlib.h"
#include "string.h"
#include "create_atoms.h"
#include "atom.h"
#include "atom_vec.h"
#include "molecule.h"
#include "comm.h"
#include "irregular.h"
#include "modify.h"
#include "force.h"
#include "special.h"
#include "fix.h"
#include "domain.h"
#include "lattice.h"
#include "region.h"
#include "random_park.h"
#include "random_mars.h"
#include "math_extra.h"
#include "math_const.h"
#include "error.h"
using
namespace
LAMMPS_NS
;
using
namespace
MathConst
;
#define BIG 1.0e30
#define EPSILON 1.0e-6
enum
{
BOX
,
REGION
,
SINGLE
,
RANDOM
};
enum
{
ATOM
,
MOLECULE
};
/* ---------------------------------------------------------------------- */
CreateAtoms
::
CreateAtoms
(
LAMMPS
*
lmp
)
:
Pointers
(
lmp
)
{}
/* ---------------------------------------------------------------------- */
void
CreateAtoms
::
command
(
int
narg
,
char
**
arg
)
{
if
(
domain
->
box_exist
==
0
)
error
->
all
(
FLERR
,
"Create_atoms command before simulation box is defined"
);
if
(
modify
->
nfix_restart_peratom
)
error
->
all
(
FLERR
,
"Cannot create_atoms after "
"reading restart file with per-atom info"
);
// parse arguments
if
(
narg
<
2
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
ntype
=
force
->
inumeric
(
FLERR
,
arg
[
0
]);
int
iarg
;
if
(
strcmp
(
arg
[
1
],
"box"
)
==
0
)
{
style
=
BOX
;
iarg
=
2
;
}
else
if
(
strcmp
(
arg
[
1
],
"region"
)
==
0
)
{
style
=
REGION
;
if
(
narg
<
3
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
nregion
=
domain
->
find_region
(
arg
[
2
]);
if
(
nregion
==
-
1
)
error
->
all
(
FLERR
,
"Create_atoms region ID does not exist"
);
domain
->
regions
[
nregion
]
->
init
();
iarg
=
3
;;
}
else
if
(
strcmp
(
arg
[
1
],
"single"
)
==
0
)
{
style
=
SINGLE
;
if
(
narg
<
5
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
xone
[
0
]
=
force
->
numeric
(
FLERR
,
arg
[
2
]);
xone
[
1
]
=
force
->
numeric
(
FLERR
,
arg
[
3
]);
xone
[
2
]
=
force
->
numeric
(
FLERR
,
arg
[
4
]);
iarg
=
5
;
}
else
if
(
strcmp
(
arg
[
1
],
"random"
)
==
0
)
{
style
=
RANDOM
;
if
(
narg
<
5
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
nrandom
=
force
->
inumeric
(
FLERR
,
arg
[
2
]);
seed
=
force
->
inumeric
(
FLERR
,
arg
[
3
]);
if
(
strcmp
(
arg
[
4
],
"NULL"
)
==
0
)
nregion
=
-
1
;
else
{
nregion
=
domain
->
find_region
(
arg
[
4
]);
if
(
nregion
==
-
1
)
error
->
all
(
FLERR
,
"Create_atoms region ID does not exist"
);
domain
->
regions
[
nregion
]
->
init
();
}
iarg
=
5
;
}
else
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
// process optional keywords
int
scaleflag
=
1
;
remapflag
=
0
;
mode
=
ATOM
;
int
molseed
;
nbasis
=
domain
->
lattice
->
nbasis
;
basistype
=
new
int
[
nbasis
];
for
(
int
i
=
0
;
i
<
nbasis
;
i
++
)
basistype
[
i
]
=
ntype
;
while
(
iarg
<
narg
)
{
if
(
strcmp
(
arg
[
iarg
],
"basis"
)
==
0
)
{
if
(
iarg
+
3
>
narg
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
int
ibasis
=
force
->
inumeric
(
FLERR
,
arg
[
iarg
+
1
]);
int
itype
=
force
->
inumeric
(
FLERR
,
arg
[
iarg
+
2
]);
if
(
ibasis
<=
0
||
ibasis
>
nbasis
||
itype
<=
0
||
itype
>
atom
->
ntypes
)
error
->
all
(
FLERR
,
"Invalid basis setting in create_atoms command"
);
basistype
[
ibasis
-
1
]
=
itype
;
iarg
+=
3
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"remap"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
if
(
strcmp
(
arg
[
iarg
+
1
],
"yes"
)
==
0
)
remapflag
=
1
;
else
if
(
strcmp
(
arg
[
iarg
+
1
],
"no"
)
==
0
)
remapflag
=
0
;
else
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
iarg
+=
2
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"mol"
)
==
0
)
{
if
(
iarg
+
3
>
narg
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
int
imol
=
atom
->
find_molecule
(
arg
[
iarg
+
1
]);
if
(
imol
==
-
1
)
error
->
all
(
FLERR
,
"Molecule template ID for "
"create_atoms does not exist"
);
if
(
atom
->
molecules
[
imol
]
->
nset
>
1
&&
comm
->
me
==
0
)
error
->
warning
(
FLERR
,
"Molecule template for "
"create_atoms has multiple molecules"
);
mode
=
MOLECULE
;
onemol
=
atom
->
molecules
[
imol
];
molseed
=
force
->
inumeric
(
FLERR
,
arg
[
iarg
+
2
]);
iarg
+=
3
;
}
else
if
(
strcmp
(
arg
[
iarg
],
"units"
)
==
0
)
{
if
(
iarg
+
2
>
narg
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
if
(
strcmp
(
arg
[
iarg
+
1
],
"box"
)
==
0
)
scaleflag
=
0
;
else
if
(
strcmp
(
arg
[
iarg
+
1
],
"lattice"
)
==
0
)
scaleflag
=
1
;
else
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
iarg
+=
2
;
}
else
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
}
// error checks
if
(
mode
==
ATOM
&&
(
ntype
<=
0
||
ntype
>
atom
->
ntypes
))
error
->
all
(
FLERR
,
"Invalid atom type in create_atoms command"
);
if
(
style
==
RANDOM
)
{
if
(
nrandom
<
0
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
if
(
seed
<=
0
)
error
->
all
(
FLERR
,
"Illegal create_atoms command"
);
}
// error check and further setup for mode = MOLECULE
ranmol
=
NULL
;
if
(
mode
==
MOLECULE
)
{
if
(
onemol
->
xflag
==
0
)
error
->
all
(
FLERR
,
"Create_atoms molecule must have coordinates"
);
if
(
onemol
->
typeflag
==
0
)
error
->
all
(
FLERR
,
"Create_atoms molecule must have atom types"
);
if
(
ntype
+
onemol
->
maxtype
<=
0
||
ntype
+
onemol
->
maxtype
>
atom
->
ntypes
)
error
->
all
(
FLERR
,
"Invalid atom type in create_atoms mol command"
);
if
(
onemol
->
tag_require
&&
!
atom
->
tag_enable
)
error
->
all
(
FLERR
,
"Create_atoms molecule has atom IDs, but system does not"
);
// create_atoms uses geoemetric center of molecule for insertion
onemol
->
compute_center
();
// molecule random number generator, different for each proc
ranmol
=
new
RanMars
(
lmp
,
molseed
+
comm
->
me
);
}
// demand non-none lattice be defined for BOX and REGION
// else setup scaling for SINGLE and RANDOM
// could use domain->lattice->lattice2box() to do conversion of
// lattice to box, but not consistent with other uses of units=lattice
// triclinic remapping occurs in add_single()
if
(
style
==
BOX
||
style
==
REGION
)
{
if
(
nbasis
==
0
)
error
->
all
(
FLERR
,
"Cannot create atoms with undefined lattice"
);
}
else
if
(
scaleflag
==
1
)
{
xone
[
0
]
*=
domain
->
lattice
->
xlattice
;
xone
[
1
]
*=
domain
->
lattice
->
ylattice
;
xone
[
2
]
*=
domain
->
lattice
->
zlattice
;
}
// set bounds for my proc in sublo[3] & subhi[3]
// if periodic and style = BOX or REGION, i.e. using lattice:
// should create exactly 1 atom when 2 images are both "on" the boundary
// either image may be slightly inside/outside true box due to round-off
// if I am lo proc, decrement lower bound by EPSILON
// this will insure lo image is created
// if I am hi proc, decrement upper bound by 2.0*EPSILON
// this will insure hi image is not created
// thus insertion box is EPSILON smaller than true box
// and is shifted away from true boundary
// which is where atoms are likely to be generated
triclinic
=
domain
->
triclinic
;
double
epsilon
[
3
];
if
(
triclinic
)
epsilon
[
0
]
=
epsilon
[
1
]
=
epsilon
[
2
]
=
EPSILON
;
else
{
epsilon
[
0
]
=
domain
->
prd
[
0
]
*
EPSILON
;
epsilon
[
1
]
=
domain
->
prd
[
1
]
*
EPSILON
;
epsilon
[
2
]
=
domain
->
prd
[
2
]
*
EPSILON
;
}
if
(
triclinic
==
0
)
{
sublo
[
0
]
=
domain
->
sublo
[
0
];
subhi
[
0
]
=
domain
->
subhi
[
0
];
sublo
[
1
]
=
domain
->
sublo
[
1
];
subhi
[
1
]
=
domain
->
subhi
[
1
];
sublo
[
2
]
=
domain
->
sublo
[
2
];
subhi
[
2
]
=
domain
->
subhi
[
2
];
}
else
{
sublo
[
0
]
=
domain
->
sublo_lamda
[
0
];
subhi
[
0
]
=
domain
->
subhi_lamda
[
0
];
sublo
[
1
]
=
domain
->
sublo_lamda
[
1
];
subhi
[
1
]
=
domain
->
subhi_lamda
[
1
];
sublo
[
2
]
=
domain
->
sublo_lamda
[
2
];
subhi
[
2
]
=
domain
->
subhi_lamda
[
2
];
}
if
(
style
==
BOX
||
style
==
REGION
)
{
if
(
domain
->
xperiodic
)
{
if
(
comm
->
myloc
[
0
]
==
0
)
sublo
[
0
]
-=
epsilon
[
0
];
if
(
comm
->
myloc
[
0
]
==
comm
->
procgrid
[
0
]
-
1
)
subhi
[
0
]
-=
2.0
*
epsilon
[
0
];
}
if
(
domain
->
yperiodic
)
{
if
(
comm
->
myloc
[
1
]
==
0
)
sublo
[
1
]
-=
epsilon
[
1
];
if
(
comm
->
myloc
[
1
]
==
comm
->
procgrid
[
1
]
-
1
)
subhi
[
1
]
-=
2.0
*
epsilon
[
1
];
}
if
(
domain
->
zperiodic
)
{
if
(
comm
->
myloc
[
2
]
==
0
)
sublo
[
2
]
-=
epsilon
[
2
];
if
(
comm
->
myloc
[
2
]
==
comm
->
procgrid
[
2
]
-
1
)
subhi
[
2
]
-=
2.0
*
epsilon
[
2
];
}
}
// add atoms/molecules in one of 3 ways
bigint
natoms_previous
=
atom
->
natoms
;
int
nlocal_previous
=
atom
->
nlocal
;
if
(
style
==
SINGLE
)
add_single
();
else
if
(
style
==
RANDOM
)
add_random
();
else
add_lattice
();
// invoke set_arrays() for fixes that need initialization of new atoms
int
nlocal
=
atom
->
nlocal
;
for
(
int
m
=
0
;
m
<
modify
->
nfix
;
m
++
)
{
Fix
*
fix
=
modify
->
fix
[
m
];
if
(
fix
->
create_attribute
)
for
(
int
i
=
nlocal_previous
;
i
<
nlocal
;
i
++
)
fix
->
set_arrays
(
i
);
}
// set new total # of atoms and error check
bigint
nblocal
=
atom
->
nlocal
;
MPI_Allreduce
(
&
nblocal
,
&
atom
->
natoms
,
1
,
MPI_LMP_BIGINT
,
MPI_SUM
,
world
);
if
(
atom
->
natoms
<
0
||
atom
->
natoms
>=
MAXBIGINT
)
error
->
all
(
FLERR
,
"Too many total atoms"
);
// add IDs for newly created atoms
// check that atom IDs are valid
if
(
atom
->
tag_enable
)
atom
->
tag_extend
();
atom
->
tag_check
();
// if molecular system or user-requested, create global mapping of atoms
// zero nghost in case are adding new atoms to existing atoms
if
(
atom
->
molecular
||
atom
->
map_user
)
{
atom
->
nghost
=
0
;
atom
->
map_init
();
atom
->
map_set
();
}
// for MOLECULE mode:
// set molecule IDs for created atoms if used
// reset new molecule bond,angle,etc and special values
// send atoms to new owning procs via irregular comm
// since not all atoms I created will be within my sub-domain
// perform special list build if needed
if
(
mode
==
MOLECULE
)
{
// molcreate = # of molecules I created
int
molcreate
=
(
atom
->
nlocal
-
nlocal_previous
)
/
onemol
->
natoms
;
// maxmol = max molecule ID across all procs, for previous atoms
// moloffset = max molecule ID for all molecules owned by previous procs
// including molecules existing before this creation
tagint
moloffset
;
tagint
*
molecule
=
atom
->
molecule
;
if
(
molecule
)
{
tagint
max
=
0
;
for
(
int
i
=
0
;
i
<
nlocal_previous
;
i
++
)
max
=
MAX
(
max
,
molecule
[
i
]);
tagint
maxmol
;
MPI_Allreduce
(
&
max
,
&
maxmol
,
1
,
MPI_LMP_TAGINT
,
MPI_MAX
,
world
);
MPI_Scan
(
&
molcreate
,
&
moloffset
,
1
,
MPI_INT
,
MPI_SUM
,
world
);
moloffset
=
moloffset
-
molcreate
+
maxmol
;
}
// loop over molecules I created
// set their molecule ID
// reset their bond,angle,etc and special values
int
natoms
=
onemol
->
natoms
;
tagint
offset
=
0
;
tagint
*
tag
=
atom
->
tag
;
int
*
num_bond
=
atom
->
num_bond
;
int
*
num_angle
=
atom
->
num_angle
;
int
*
num_dihedral
=
atom
->
num_dihedral
;
int
*
num_improper
=
atom
->
num_improper
;
tagint
**
bond_atom
=
atom
->
bond_atom
;
tagint
**
angle_atom1
=
atom
->
angle_atom1
;
tagint
**
angle_atom2
=
atom
->
angle_atom2
;
tagint
**
angle_atom3
=
atom
->
angle_atom3
;
tagint
**
dihedral_atom1
=
atom
->
dihedral_atom1
;
tagint
**
dihedral_atom2
=
atom
->
dihedral_atom2
;
tagint
**
dihedral_atom3
=
atom
->
dihedral_atom3
;
tagint
**
dihedral_atom4
=
atom
->
dihedral_atom4
;
tagint
**
improper_atom1
=
atom
->
improper_atom1
;
tagint
**
improper_atom2
=
atom
->
improper_atom2
;
tagint
**
improper_atom3
=
atom
->
improper_atom3
;
tagint
**
improper_atom4
=
atom
->
improper_atom4
;
int
**
nspecial
=
atom
->
nspecial
;
tagint
**
special
=
atom
->
special
;
int
ilocal
=
nlocal_previous
;
for
(
int
i
=
0
;
i
<
molcreate
;
i
++
)
{
if
(
tag
)
offset
=
tag
[
ilocal
]
-
1
;
for
(
int
m
=
0
;
m
<
natoms
;
m
++
)
{
if
(
molecule
)
molecule
[
ilocal
]
=
moloffset
+
i
+
1
;
if
(
onemol
->
bondflag
)
for
(
int
j
=
0
;
j
<
num_bond
[
ilocal
];
j
++
)
bond_atom
[
ilocal
][
j
]
+=
offset
;
if
(
onemol
->
angleflag
)
for
(
int
j
=
0
;
j
<
num_angle
[
ilocal
];
j
++
)
{
angle_atom1
[
ilocal
][
j
]
+=
offset
;
angle_atom2
[
ilocal
][
j
]
+=
offset
;
angle_atom3
[
ilocal
][
j
]
+=
offset
;
}
if
(
onemol
->
dihedralflag
)
for
(
int
j
=
0
;
j
<
num_dihedral
[
ilocal
];
j
++
)
{
dihedral_atom1
[
ilocal
][
j
]
+=
offset
;
dihedral_atom2
[
ilocal
][
j
]
+=
offset
;
dihedral_atom3
[
ilocal
][
j
]
+=
offset
;
dihedral_atom4
[
ilocal
][
j
]
+=
offset
;
}
if
(
onemol
->
improperflag
)
for
(
int
j
=
0
;
j
<
num_improper
[
ilocal
];
j
++
)
{
improper_atom1
[
ilocal
][
j
]
+=
offset
;
improper_atom2
[
ilocal
][
j
]
+=
offset
;
improper_atom3
[
ilocal
][
j
]
+=
offset
;
improper_atom4
[
ilocal
][
j
]
+=
offset
;
}
if
(
onemol
->
specialflag
)
for
(
int
j
=
0
;
j
<
nspecial
[
ilocal
][
2
];
j
++
)
special
[
ilocal
][
j
]
+=
offset
;
ilocal
++
;
}
}
// perform irregular comm to migrate atoms to new owning procs
double
**
x
=
atom
->
x
;
imageint
*
image
=
atom
->
image
;
int
nlocal
=
atom
->
nlocal
;
for
(
int
i
=
0
;
i
<
nlocal
;
i
++
)
domain
->
remap
(
x
[
i
],
image
[
i
]);
if
(
domain
->
triclinic
)
domain
->
x2lamda
(
atom
->
nlocal
);
domain
->
reset_box
();
Irregular
*
irregular
=
new
Irregular
(
lmp
);
irregular
->
migrate_atoms
();
delete
irregular
;
if
(
domain
->
triclinic
)
domain
->
lamda2x
(
atom
->
nlocal
);
}
// clean up
delete
ranmol
;
if
(
domain
->
lattice
)
delete
[]
basistype
;
// print status
if
(
comm
->
me
==
0
)
{
if
(
screen
)
fprintf
(
screen
,
"Created "
BIGINT_FORMAT
" atoms
\n
"
,
atom
->
natoms
-
natoms_previous
);
if
(
logfile
)
fprintf
(
logfile
,
"Created "
BIGINT_FORMAT
" atoms
\n
"
,
atom
->
natoms
-
natoms_previous
);
}
// for MOLECULE mode:
// create special bond lists for molecular systems
// only if onemol added bonds but not special info
if
(
mode
==
MOLECULE
)
{
if
(
atom
->
molecular
&&
onemol
->
bondflag
&&
!
onemol
->
specialflag
)
{
Special
special
(
lmp
);
special
.
build
();
}
}
}
/* ----------------------------------------------------------------------
add single atom with coords at xone if it's in my sub-box
if triclinic, xone is in lamda coords
------------------------------------------------------------------------- */
void
CreateAtoms
::
add_single
()
{
// remap atom if requested
if
(
remapflag
)
{
imageint
imagetmp
=
((
imageint
)
IMGMAX
<<
IMG2BITS
)
|
((
imageint
)
IMGMAX
<<
IMGBITS
)
|
IMGMAX
;
domain
->
remap
(
xone
,
imagetmp
);
}
// if triclinic, convert to lamda coords (0-1)
double
lamda
[
3
],
*
coord
;
if
(
triclinic
)
{
domain
->
x2lamda
(
xone
,
lamda
);
coord
=
lamda
;
}
else
coord
=
xone
;
// if atom/molecule is in my subbox, create it
if
(
coord
[
0
]
>=
sublo
[
0
]
&&
coord
[
0
]
<
subhi
[
0
]
&&
coord
[
1
]
>=
sublo
[
1
]
&&
coord
[
1
]
<
subhi
[
1
]
&&
coord
[
2
]
>=
sublo
[
2
]
&&
coord
[
2
]
<
subhi
[
2
])
{
if
(
mode
==
ATOM
)
atom
->
avec
->
create_atom
(
ntype
,
xone
);
else
add_molecule
(
xone
);
}
}
/* ----------------------------------------------------------------------
add Nrandom atoms at random locations
------------------------------------------------------------------------- */
void
CreateAtoms
::
add_random
()
{
double
xlo
,
ylo
,
zlo
,
xhi
,
yhi
,
zhi
,
zmid
;
double
lamda
[
3
],
*
coord
;
double
*
boxlo
,
*
boxhi
;
// random number generator, same for all procs
RanPark
*
random
=
new
RanPark
(
lmp
,
seed
);
// bounding box for atom creation
// in real units, even if triclinic
// only limit bbox by region if its bboxflag is set (interior region)
if
(
triclinic
==
0
)
{
xlo
=
domain
->
boxlo
[
0
];
xhi
=
domain
->
boxhi
[
0
];
ylo
=
domain
->
boxlo
[
1
];
yhi
=
domain
->
boxhi
[
1
];
zlo
=
domain
->
boxlo
[
2
];
zhi
=
domain
->
boxhi
[
2
];
zmid
=
zlo
+
0.5
*
(
zhi
-
zlo
);
}
else
{
xlo
=
domain
->
boxlo_bound
[
0
];
xhi
=
domain
->
boxhi_bound
[
0
];
ylo
=
domain
->
boxlo_bound
[
1
];
yhi
=
domain
->
boxhi_bound
[
1
];
zlo
=
domain
->
boxlo_bound
[
2
];
zhi
=
domain
->
boxhi_bound
[
2
];
zmid
=
zlo
+
0.5
*
(
zhi
-
zlo
);
boxlo
=
domain
->
boxlo_lamda
;
boxhi
=
domain
->
boxhi_lamda
;
}
if
(
nregion
>=
0
&&
domain
->
regions
[
nregion
]
->
bboxflag
)
{
xlo
=
MAX
(
xlo
,
domain
->
regions
[
nregion
]
->
extent_xlo
);
xhi
=
MIN
(
xhi
,
domain
->
regions
[
nregion
]
->
extent_xhi
);
ylo
=
MAX
(
ylo
,
domain
->
regions
[
nregion
]
->
extent_ylo
);
yhi
=
MIN
(
yhi
,
domain
->
regions
[
nregion
]
->
extent_yhi
);
zlo
=
MAX
(
zlo
,
domain
->
regions
[
nregion
]
->
extent_zlo
);
zhi
=
MIN
(
zhi
,
domain
->
regions
[
nregion
]
->
extent_zhi
);
}
// generate random positions for each new atom/molecule within bounding box
// iterate until atom is within region and triclinic simulation box
// if final atom position is in my subbox, create it
if
(
xlo
>
xhi
||
ylo
>
yhi
||
zlo
>
zhi
)
error
->
all
(
FLERR
,
"No overlap of box and region for create_atoms"
);
int
valid
;
for
(
int
i
=
0
;
i
<
nrandom
;
i
++
)
{
while
(
1
)
{
xone
[
0
]
=
xlo
+
random
->
uniform
()
*
(
xhi
-
xlo
);
xone
[
1
]
=
ylo
+
random
->
uniform
()
*
(
yhi
-
ylo
);
xone
[
2
]
=
zlo
+
random
->
uniform
()
*
(
zhi
-
zlo
);
if
(
domain
->
dimension
==
2
)
xone
[
2
]
=
zmid
;
valid
=
1
;
if
(
nregion
>=
0
&&
domain
->
regions
[
nregion
]
->
match
(
xone
[
0
],
xone
[
1
],
xone
[
2
])
==
0
)
valid
=
0
;
if
(
triclinic
)
{
domain
->
x2lamda
(
xone
,
lamda
);
coord
=
lamda
;
if
(
coord
[
0
]
<
boxlo
[
0
]
||
coord
[
0
]
>=
boxhi
[
0
]
||
coord
[
1
]
<
boxlo
[
1
]
||
coord
[
1
]
>=
boxhi
[
1
]
||
coord
[
2
]
<
boxlo
[
2
]
||
coord
[
2
]
>=
boxhi
[
2
])
valid
=
0
;
}
else
coord
=
xone
;
if
(
valid
)
break
;
}
// if triclinic, coord is now in lamda units
if
(
coord
[
0
]
>=
sublo
[
0
]
&&
coord
[
0
]
<
subhi
[
0
]
&&
coord
[
1
]
>=
sublo
[
1
]
&&
coord
[
1
]
<
subhi
[
1
]
&&
coord
[
2
]
>=
sublo
[
2
]
&&
coord
[
2
]
<
subhi
[
2
])
{
if
(
mode
==
ATOM
)
atom
->
avec
->
create_atom
(
ntype
,
xone
);
else
add_molecule
(
xone
);
}
}
// clean-up
delete
random
;
}
/* ----------------------------------------------------------------------
add many atoms by looping over lattice
------------------------------------------------------------------------- */
void
CreateAtoms
::
add_lattice
()
{
// convert 8 corners of my subdomain from box coords to lattice coords
// for orthogonal, use corner pts of my subbox
// for triclinic, use bounding box of my subbox
// xyz min to max = bounding box around the domain corners in lattice space
double
bboxlo
[
3
],
bboxhi
[
3
];
if
(
triclinic
==
0
)
{
bboxlo
[
0
]
=
domain
->
sublo
[
0
];
bboxhi
[
0
]
=
domain
->
subhi
[
0
];
bboxlo
[
1
]
=
domain
->
sublo
[
1
];
bboxhi
[
1
]
=
domain
->
subhi
[
1
];
bboxlo
[
2
]
=
domain
->
sublo
[
2
];
bboxhi
[
2
]
=
domain
->
subhi
[
2
];
}
else
domain
->
bbox
(
domain
->
sublo_lamda
,
domain
->
subhi_lamda
,
bboxlo
,
bboxhi
);
double
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
;
xmin
=
ymin
=
zmin
=
BIG
;
xmax
=
ymax
=
zmax
=
-
BIG
;
domain
->
lattice
->
bbox
(
1
,
bboxlo
[
0
],
bboxlo
[
1
],
bboxlo
[
2
],
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
);
domain
->
lattice
->
bbox
(
1
,
bboxhi
[
0
],
bboxlo
[
1
],
bboxlo
[
2
],
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
);
domain
->
lattice
->
bbox
(
1
,
bboxlo
[
0
],
bboxhi
[
1
],
bboxlo
[
2
],
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
);
domain
->
lattice
->
bbox
(
1
,
bboxhi
[
0
],
bboxhi
[
1
],
bboxlo
[
2
],
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
);
domain
->
lattice
->
bbox
(
1
,
bboxlo
[
0
],
bboxlo
[
1
],
bboxhi
[
2
],
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
);
domain
->
lattice
->
bbox
(
1
,
bboxhi
[
0
],
bboxlo
[
1
],
bboxhi
[
2
],
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
);
domain
->
lattice
->
bbox
(
1
,
bboxlo
[
0
],
bboxhi
[
1
],
bboxhi
[
2
],
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
);
domain
->
lattice
->
bbox
(
1
,
bboxhi
[
0
],
bboxhi
[
1
],
bboxhi
[
2
],
xmin
,
ymin
,
zmin
,
xmax
,
ymax
,
zmax
);
// ilo:ihi,jlo:jhi,klo:khi = loop bounds for lattice overlap of my subbox
// overlap = any part of a unit cell (face,edge,pt) in common with my subbox
// in lattice space, subbox is a tilted box
// but bbox of subbox is aligned with lattice axes
// so ilo:khi unit cells should completely tile bounding box
// decrement lo, increment hi to avoid round-off issues in lattice->bbox(),
// which can lead to missing atoms in rare cases
// extra decrement of lo if min < 0, since static_cast(-1.5) = -1
int
ilo
,
ihi
,
jlo
,
jhi
,
klo
,
khi
;
ilo
=
static_cast
<
int
>
(
xmin
)
-
1
;
jlo
=
static_cast
<
int
>
(
ymin
)
-
1
;
klo
=
static_cast
<
int
>
(
zmin
)
-
1
;
ihi
=
static_cast
<
int
>
(
xmax
)
+
1
;
jhi
=
static_cast
<
int
>
(
ymax
)
+
1
;
khi
=
static_cast
<
int
>
(
zmax
)
+
1
;
if
(
xmin
<
0.0
)
ilo
--
;
if
(
ymin
<
0.0
)
jlo
--
;
if
(
zmin
<
0.0
)
klo
--
;
// iterate on 3d periodic lattice of unit cells using loop bounds
// iterate on nbasis atoms in each unit cell
// convert lattice coords to box coords
// add atom or molecule (on each basis point) if it meets all criteria
double
**
basis
=
domain
->
lattice
->
basis
;
double
x
[
3
],
lamda
[
3
];
double
*
coord
;
int
i
,
j
,
k
,
m
;
for
(
k
=
klo
;
k
<=
khi
;
k
++
)
for
(
j
=
jlo
;
j
<=
jhi
;
j
++
)
for
(
i
=
ilo
;
i
<=
ihi
;
i
++
)
for
(
m
=
0
;
m
<
nbasis
;
m
++
)
{
x
[
0
]
=
i
+
basis
[
m
][
0
];
x
[
1
]
=
j
+
basis
[
m
][
1
];
x
[
2
]
=
k
+
basis
[
m
][
2
];
// convert from lattice coords to box coords
domain
->
lattice
->
lattice2box
(
x
[
0
],
x
[
1
],
x
[
2
]);
// if a region was specified, test if atom is in it
if
(
style
==
REGION
)
if
(
!
domain
->
regions
[
nregion
]
->
match
(
x
[
0
],
x
[
1
],
x
[
2
]))
continue
;
// test if atom/molecule position is in my subbox
if
(
triclinic
)
{
domain
->
x2lamda
(
x
,
lamda
);
coord
=
lamda
;
}
else
coord
=
x
;
if
(
coord
[
0
]
<
sublo
[
0
]
||
coord
[
0
]
>=
subhi
[
0
]
||
coord
[
1
]
<
sublo
[
1
]
||
coord
[
1
]
>=
subhi
[
1
]
||
coord
[
2
]
<
sublo
[
2
]
||
coord
[
2
]
>=
subhi
[
2
])
continue
;
// add the atom or entire molecule to my list of atoms
if
(
mode
==
ATOM
)
atom
->
avec
->
create_atom
(
basistype
[
m
],
x
);
else
add_molecule
(
x
);
}
}
/* ----------------------------------------------------------------------
add a randomly rotated molecule with its center at center
------------------------------------------------------------------------- */
void
CreateAtoms
::
add_molecule
(
double
*
center
)
{
int
n
;
double
r
[
3
],
rotmat
[
3
][
3
],
quat
[
4
],
xnew
[
3
];
if
(
domain
->
dimension
==
3
)
{
r
[
0
]
=
ranmol
->
uniform
()
-
0.5
;
r
[
1
]
=
ranmol
->
uniform
()
-
0.5
;
r
[
2
]
=
ranmol
->
uniform
()
-
0.5
;
}
else
{
r
[
0
]
=
r
[
1
]
=
0.0
;
r
[
2
]
=
1.0
;
}
double
theta
=
ranmol
->
uniform
()
*
MY_2PI
;
MathExtra
::
norm3
(
r
);
MathExtra
::
axisangle_to_quat
(
r
,
theta
,
quat
);
MathExtra
::
quat_to_mat
(
quat
,
rotmat
);
// create atoms in molecule with atom ID = 0 and mol ID = 0
// reset in caller after all moleclues created by all procs
// pass add_molecule_atom an offset of 0 since don't know
// max tag of atoms in previous molecules at this point
int
natoms
=
onemol
->
natoms
;
for
(
int
m
=
0
;
m
<
natoms
;
m
++
)
{
MathExtra
::
matvec
(
rotmat
,
onemol
->
dx
[
m
],
xnew
);
MathExtra
::
add3
(
xnew
,
center
,
xnew
);
atom
->
avec
->
create_atom
(
ntype
+
onemol
->
type
[
m
],
xnew
);
n
=
atom
->
nlocal
-
1
;
atom
->
add_molecule_atom
(
onemol
,
m
,
n
,
0
);
}
}
Event Timeline
Log In to Comment