2 new computes: chunk/spread/atom and reduce/chunk
This commit is contained in:
@ -35,6 +35,7 @@ KOKKOS, o = USER-OMP, t = OPT.
|
||||
"bond/local"_compute_bond_local.html,
|
||||
"centro/atom"_compute_centro_atom.html,
|
||||
"chunk/atom"_compute_chunk_atom.html,
|
||||
"chunk/spread/atom"_compute_chunk_spread_atom.html,
|
||||
"cluster/atom"_compute_cluster_atom.html,
|
||||
"cna/atom"_compute_cna_atom.html,
|
||||
"cnp/atom"_compute_cnp_atom.html,
|
||||
@ -97,6 +98,7 @@ KOKKOS, o = USER-OMP, t = OPT.
|
||||
"property/local"_compute_property_local.html,
|
||||
"rdf"_compute_rdf.html,
|
||||
"reduce"_compute_reduce.html,
|
||||
"reduce/chunk"_compute_reduce_chunk.html,
|
||||
"reduce/region"_compute_reduce.html,
|
||||
"rigid/local"_compute_rigid_local.html,
|
||||
"saed"_compute_saed.html,
|
||||
|
||||
@ -22,7 +22,7 @@ commands, to calculate various properties of a system:
|
||||
"fix ave/chunk"_fix_ave_chunk.html
|
||||
any of the "compute */chunk"_compute.html commands :ul
|
||||
|
||||
Here, each of the 3 kinds of chunk-related commands is briefly
|
||||
Here, each of the 4 kinds of chunk-related commands is briefly
|
||||
overviewed. Then some examples are given of how to compute different
|
||||
properties with chunk commands.
|
||||
|
||||
@ -83,8 +83,9 @@ chunk.
|
||||
|
||||
Compute */chunk commands: :h4
|
||||
|
||||
Currently the following computes operate on chunks of atoms to produce
|
||||
per-chunk values.
|
||||
The following computes operate on chunks of atoms to produce per-chunk
|
||||
values. Any compute whose style name ends in "/chunk" is in this
|
||||
category:
|
||||
|
||||
"compute com/chunk"_compute_com_chunk.html
|
||||
"compute gyration/chunk"_compute_gyration_chunk.html
|
||||
@ -111,8 +112,8 @@ of a center of mass, which requires summing mass*position over the
|
||||
atoms and then dividing by summed mass.
|
||||
|
||||
All of these computes produce a global vector or global array as
|
||||
output, wih one or more values per chunk. They can be used
|
||||
in various ways:
|
||||
output, wih one or more values per chunk. The output can be used in
|
||||
various ways:
|
||||
|
||||
As input to the "fix ave/time"_fix_ave_time.html command, which can
|
||||
write the values to a file and optionally time average them. :ulb,l
|
||||
@ -122,9 +123,27 @@ histogram values across chunks. E.g. a histogram of cluster sizes or
|
||||
molecule diffusion rates. :l
|
||||
|
||||
As input to special functions of "equal-style
|
||||
variables"_variable.html, like sum() and max(). E.g. to find the
|
||||
largest cluster or fastest diffusing molecule. :l
|
||||
:ule
|
||||
variables"_variable.html, like sum() and max() and ave(). E.g. to
|
||||
find the largest cluster or fastest diffusing molecule or average
|
||||
radius-of-gyration of a set of molecules (chunks). :l :ule
|
||||
|
||||
Other chunk commands: :h4
|
||||
|
||||
"compute chunk/spread/atom"_compute_chunk_spread_atom.html
|
||||
"compute reduce/chunk"_compute_reduce_chunk.html :ul
|
||||
|
||||
The "compute chunk/spread/atom"_compute_chunk_spread_atom.html command
|
||||
spreads per-chunk values to each atom in the chunk, producing per-atom
|
||||
values as its output. This can be useful for outputting per-chunk
|
||||
values to a per-atom "dump file"_dump.html. Or for using an atom's
|
||||
associated chunk value in an "atom-style variable"_variable.html.
|
||||
|
||||
The "compute reduce/chunk"_compute_reduce_chunk.html command reduces a
|
||||
peratom value across the atoms in each chunk to produce a value per
|
||||
chunk. When used with the "compute
|
||||
chunk/spread/atom"_compute_chunk_spread_atom.html command it can
|
||||
create peratom values that induce a new set of chunks with a second
|
||||
"compute chunk/atom"_compute_chunk_atom.html command.
|
||||
|
||||
Example calculations with chunks :h4
|
||||
|
||||
@ -164,3 +183,13 @@ compute cluster all cluster/atom 1.0
|
||||
compute cc1 all chunk/atom c_cluster compress yes
|
||||
compute size all property/chunk cc1 count
|
||||
fix 1 all ave/histo 100 1 100 0 20 20 c_size mode vector ave running beyond ignore file tmp.histo :pre
|
||||
|
||||
(6) An example of using a per-chunk value to apply per-atom forces to
|
||||
compress individual polymer chains (molecules) in a mixture, is
|
||||
explained on the "compute
|
||||
chunk/spread/atom"_compute_chunk_spread_atom.html command doc page.
|
||||
|
||||
(7) An example of using one set of per-chunk values for molecule
|
||||
chunks, to create a 2nd set of micelle-scale chunks (clustered
|
||||
molecules, due to hydrophobicity), is explained on the "compute
|
||||
chunk/reduce"_compute_reduce_chunk.html command doc page.
|
||||
|
||||
@ -183,6 +183,7 @@ compute"_Commands_compute.html doc page are followed by one or more of
|
||||
"bond/local"_compute_bond_local.html - distance and energy of each bond
|
||||
"centro/atom"_compute_centro_atom.html - centro-symmetry parameter for each atom
|
||||
"chunk/atom"_compute_chunk_atom.html - assign chunk IDs to each atom
|
||||
"chunk/spread/atom"_compute_chunk_spread_atom.html - spreads chunk values to each atom in chunk
|
||||
"cluster/atom"_compute_cluster_atom.html - cluster ID for each atom
|
||||
"cna/atom"_compute_cna_atom.html - common neighbor analysis (CNA) for each atom
|
||||
"com"_compute_com.html - center-of-mass of group of atoms
|
||||
@ -225,6 +226,7 @@ compute"_Commands_compute.html doc page are followed by one or more of
|
||||
"property/chunk"_compute_property_chunk.html - extract various per-chunk attributes
|
||||
"rdf"_compute_rdf.html - radial distribution function g(r) histogram of group of atoms
|
||||
"reduce"_compute_reduce.html - combine per-atom quantities into a single global value
|
||||
"reduce/chunk"_compute_reduce_chunk.html - reduce per-atom quantities within each chunk
|
||||
"reduce/region"_compute_reduce.html - same as compute reduce, within a region
|
||||
"rigid/local"_compute_rigid_local.html - extract rigid body attributes
|
||||
"slice"_compute_slice.html - extract values from global vector or array
|
||||
|
||||
@ -14,7 +14,7 @@ compute ID group-ID chunk/atom style args keyword values ... :pre
|
||||
|
||||
ID, group-ID are documented in "compute"_compute.html command :ulb,l
|
||||
chunk/atom = style name of this compute command :l
|
||||
style = {bin/1d} or {bin/2d} or {bin/3d} or {bin/sphere} or {type} or {molecule} or {compute/fix/variable}
|
||||
style = {bin/1d} or {bin/2d} or {bin/3d} or {bin/sphere} or {type} or {molecule} or c_ID, c_ID\[I\], f_ID, f_ID\[I\], v_name
|
||||
{bin/1d} args = dim origin delta
|
||||
dim = {x} or {y} or {z}
|
||||
origin = {lower} or {center} or {upper} or coordinate value (distance units)
|
||||
@ -40,7 +40,7 @@ style = {bin/1d} or {bin/2d} or {bin/3d} or {bin/sphere} or {type} or {molecule}
|
||||
ncbin = # of concentric circle bins between rmin and rmax
|
||||
{type} args = none
|
||||
{molecule} args = none
|
||||
{compute/fix/variable} = c_ID, c_ID\[I\], f_ID, f_ID\[I\], v_name with no args
|
||||
c_ID, c_ID\[I\], f_ID, f_ID\[I\], v_name args = none
|
||||
c_ID = per-atom vector calculated by a compute with ID
|
||||
c_ID\[I\] = Ith column of per-atom array calculated by a compute with ID
|
||||
f_ID = per-atom vector calculated by a fix with ID
|
||||
@ -85,7 +85,8 @@ compute 1 all chunk/atom bin/1d z lower 0.02 units reduced
|
||||
compute 1 all chunk/atom bin/2d z lower 1.0 y 0.0 2.5
|
||||
compute 1 all chunk/atom molecule region sphere nchunk once ids once compress yes
|
||||
compute 1 all chunk/atom bin/sphere 5 5 5 2.0 5.0 5 discard yes
|
||||
compute 1 all chunk/atom bin/cylinder z lower 2 10 10 2.0 5.0 3 discard yes :pre
|
||||
compute 1 all chunk/atom bin/cylinder z lower 2 10 10 2.0 5.0 3 discard yes
|
||||
compute 1 all chunk/atom c_cluster :pre
|
||||
|
||||
[Description:]
|
||||
|
||||
@ -386,8 +387,8 @@ described below, which resets {Nchunk}. The {limit} keyword is then
|
||||
applied to the new {Nchunk} value, exactly as described in the
|
||||
preceding paragraph. Note that in this case, all atoms will end up
|
||||
with chunk IDs <= {Nc}, but their original values (e.g. molecule ID or
|
||||
compute/fix/variable value) may have been > {Nc}, because of the
|
||||
compression operation.
|
||||
compute/fix/variable) may have been > {Nc}, because of the compression
|
||||
operation.
|
||||
|
||||
If {compress yes} is set, and the {compress} keyword comes after the
|
||||
{limit} keyword, then the {limit} value of {Nc} is applied first to
|
||||
|
||||
173
doc/src/compute_chunk_spread_atom.txt
Normal file
173
doc/src/compute_chunk_spread_atom.txt
Normal file
@ -0,0 +1,173 @@
|
||||
"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
|
||||
|
||||
:link(lws,http://lammps.sandia.gov)
|
||||
:link(ld,Manual.html)
|
||||
:link(lc,Commands_all.html)
|
||||
|
||||
:line
|
||||
|
||||
compute chunk/spread/atom command :h3
|
||||
|
||||
[Syntax:]
|
||||
|
||||
compute ID group-ID chunk/spread/atom chunkID input1 input2 ... :pre
|
||||
|
||||
ID, group-ID are documented in "compute"_compute.html command :ulb,l
|
||||
chunk/spread/atom = style name of this compute command :l
|
||||
chunkID = ID of "compute chunk/atom"_compute_chunk_atom.html command :l
|
||||
one or more inputs can be listed :l
|
||||
input = c_ID, c_ID\[N\], f_ID, f_ID\[N\] :l
|
||||
c_ID = global vector calculated by a compute with ID
|
||||
c_ID\[I\] = Ith column of global array calculated by a compute with ID, I can include wildcard (see below)
|
||||
f_ID = global vector calculated by a fix with ID
|
||||
f_ID\[I\] = Ith column of global array calculated by a fix with ID, I can include wildcard (see below) :pre
|
||||
:ule
|
||||
|
||||
[Examples:]
|
||||
|
||||
compute 1 all chunk/spread/atom mychunk c_com[*] c_gyration :pre
|
||||
|
||||
[Description:]
|
||||
|
||||
Define a calculation that "spreads" one or more per-chunk values to
|
||||
each atom in the chunk. This can be useful for creating a "dump
|
||||
file"_dump.html where each atom lists info about the chunk it is in,
|
||||
e.g. for post-processing purposes. It can also be used in "atom-style
|
||||
variables"_variable.html that need info about the chunk each atom is
|
||||
in. Examples are given below.
|
||||
|
||||
In LAMMPS, chunks are collections of atoms defined by a "compute
|
||||
chunk/atom"_compute_chunk_atom.html command, which assigns each atom
|
||||
to a single chunk (or no chunk). The ID for this command is specified
|
||||
as chunkID. For example, a single chunk could be the atoms in a
|
||||
molecule or atoms in a spatial bin. See the "compute
|
||||
chunk/atom"_compute_chunk_atom.html and "Howto chunk"_Howto_chunk.html
|
||||
doc pages for details of how chunks can be defined and examples of how
|
||||
they can be used to measure properties of a system.
|
||||
|
||||
For inputs that are computes, they must be a compute that calculates
|
||||
per-chunk values. These are computes whose style names end in
|
||||
"/chunk".
|
||||
|
||||
For inputs that are fixes, they should be a a fix that calculates
|
||||
per-chunk values. For example, "fix ave/chunk"_fix_ave_chunk.html or
|
||||
"fix ave/time"_fix_ave_time.html (assuming it is time-averaging
|
||||
per-chunk data).
|
||||
|
||||
For each atom, this compute accesses its chunk ID from the specified
|
||||
{chunkID} compute, then accesses the per-chunk value in each input.
|
||||
Those values are copied to this compute to become the output for that
|
||||
atom.
|
||||
|
||||
The values generated by this compute will be 0.0 for atoms not in the
|
||||
specified compute group {group-ID}. They will also be 0.0 if the atom
|
||||
is not in a chunk, as assigned by the {chunkID} compute. They will
|
||||
also be 0.0 if the current chunk ID for the atom is out-of-bounds with
|
||||
respect to the number of chunks stored by a particular input compute
|
||||
or fix.
|
||||
|
||||
NOTE: LAMMPS does not check that a compute or fix which calculates
|
||||
per-chunk values uses the same definition of chunks as this compute.
|
||||
It's up to you to be consistent. Likewise, for a fix input, LAMMPS
|
||||
does not check that it is per-chunk data. It only checks that the fix
|
||||
produces a global vector or array.
|
||||
|
||||
:line
|
||||
|
||||
Each listed input is operated on independently.
|
||||
|
||||
If a bracketed index I is used, it can be specified using a wildcard
|
||||
asterisk with the index to effectively specify multiple values. This
|
||||
takes the form "*" or "*n" or "n*" or "m*n". If N = the number of
|
||||
columns in the array, then an asterisk with no numeric values means
|
||||
all indices from 1 to N. A leading asterisk means all indices from 1
|
||||
to n (inclusive). A trailing asterisk means all indices from n to N
|
||||
(inclusive). A middle asterisk means all indices from m to n
|
||||
(inclusive).
|
||||
|
||||
Using a wildcard is the same as if the individual columns of the array
|
||||
had been listed one by one. E.g. these 2 compute chunk/spread/atom
|
||||
commands are equivalent, since the "compute
|
||||
com/chunk"_compute_com_chunk.html command creates a per-atom array
|
||||
with 3 columns:
|
||||
|
||||
compute com all com/chunk mychunk
|
||||
compute 10 all chunk/spread/atom mychunk c_com\[*\]
|
||||
compute 10 all chunk/spread/atom mychunk c_com\[1\] c_com\[2\] c_com\[3\] :pre
|
||||
|
||||
:line
|
||||
|
||||
Here is an example of writing a dump file the with the center-of-mass
|
||||
(COM) for the chunk each atom is in:
|
||||
|
||||
compute cmol all chunk/atom molecule
|
||||
compute com all com/chunk cmol
|
||||
compute comchunk all chunk/spread/atom cmol c_com[*]
|
||||
dump 1 all custom 50 tmp.dump id mol type x y z c_comchunk[*]
|
||||
dump_modify 1 sort id :pre
|
||||
|
||||
The same per-chunk data for each atom could be used to define per-atom
|
||||
forces for the "fix addforce"_fix_addforce.html command. In this
|
||||
example the forces act to pull atoms of an extended polymer chain
|
||||
towards its COM in an attractive manner.
|
||||
|
||||
compute prop all property/atom xu yu zu
|
||||
variable k equal 0.1
|
||||
variable fx atom v_k*(c_comchunk\[1\]-c_prop\[1\])
|
||||
variable fy atom v_k*(c_comchunk\[2\]-c_prop\[2\])
|
||||
variable fz atom v_k*(c_comchunk\[3\]-c_prop\[3\])
|
||||
fix 3 all addforce v_fx v_fy v_fz :pre
|
||||
|
||||
Note that "compute property/atom"_compute_property_atom.html is used
|
||||
to generate unwrapped coordinates for use in the per-atom force
|
||||
calculation, so that the effect of periodic boundaries is accounted
|
||||
for properly.
|
||||
|
||||
Over time this applied force could shrink each polymer chain's radius
|
||||
of gyration in a polymer mixture simulation. Here is output after
|
||||
adding the above lines to the bench/in.chain script. The thermo
|
||||
output is shown for 1000 steps, where the last column is the average
|
||||
radius of gyration over all 320 chains in the 32000 atom system:
|
||||
|
||||
compute gyr all gyration/chunk cmol
|
||||
variable ave equal ave(c_gyr)
|
||||
thermo_style custom step etotal press v_ave :pre
|
||||
|
||||
0 22.394765 4.6721833 5.128278
|
||||
100 22.445002 4.8166709 5.0348372
|
||||
200 22.500128 4.8790392 4.9364875
|
||||
300 22.534686 4.9183766 4.8590693
|
||||
400 22.557196 4.9492211 4.7937849
|
||||
500 22.571017 4.9161853 4.7412008
|
||||
600 22.573944 5.0229708 4.6931243
|
||||
700 22.581804 5.0541301 4.6440647
|
||||
800 22.584683 4.9691734 4.6000016
|
||||
900 22.59128 5.0247538 4.5611513
|
||||
1000 22.586832 4.94697 4.5238362 :pre
|
||||
|
||||
:line
|
||||
|
||||
[Output info:]
|
||||
|
||||
This compute calculates a per-atom vector or array, which can be
|
||||
accessed by any command that uses per-atom values from a compute as
|
||||
input. See the "Howto output"_Howto_output.html doc page for an
|
||||
overview of LAMMPS output options.
|
||||
|
||||
The output is a per-atom vector if a single input value is specified,
|
||||
otherwise a per-atom array is output. The number of columns in the
|
||||
array is the number of inputs provided. The per-atom values for the
|
||||
vector or each column of the array will be in whatever
|
||||
"units"_units.html the corresponding input value is in.
|
||||
|
||||
The vector or array values are "intensive".
|
||||
|
||||
[Restrictions:] none
|
||||
|
||||
[Related commands:]
|
||||
|
||||
"compute chunk/atom"_compute_chunk_atom.html, "fix
|
||||
ave/chunk"_fix_ave_chunk.html, "compute
|
||||
reduce/chunk"_compute_reduce_chunk.html
|
||||
|
||||
[Default:] none
|
||||
@ -97,9 +97,9 @@ equivalent, since the "compute stress/atom"_compute_stress_atom.html
|
||||
command creates a per-atom array with 6 columns:
|
||||
|
||||
compute myPress all stress/atom NULL
|
||||
compute 2 all reduce min myPress\[*\]
|
||||
compute 2 all reduce min myPress\[1\] myPress\[2\] myPress\[3\] &
|
||||
myPress\[4\] myPress\[5\] myPress\[6\] :pre
|
||||
compute 2 all reduce min c_myPress\[*\]
|
||||
compute 2 all reduce min c_myPress\[1\] c_myPress\[2\] c_myPress\[3\] &
|
||||
c_myPress\[4\] c_myPress\[5\] c_myPress\[6\] :pre
|
||||
|
||||
:line
|
||||
|
||||
|
||||
177
doc/src/compute_reduce_chunk.txt
Normal file
177
doc/src/compute_reduce_chunk.txt
Normal file
@ -0,0 +1,177 @@
|
||||
"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c
|
||||
|
||||
:link(lws,http://lammps.sandia.gov)
|
||||
:link(ld,Manual.html)
|
||||
:link(lc,Commands_all.html)
|
||||
|
||||
:line
|
||||
|
||||
compute reduce/chunk command :h3
|
||||
|
||||
[Syntax:]
|
||||
|
||||
compute ID group-ID reduce/chunk chunkID mode input1 input2 ... :pre
|
||||
|
||||
ID, group-ID are documented in "compute"_compute.html command :ulb,l
|
||||
reduce/chunk = style name of this compute command :l
|
||||
chunkID = ID of "compute chunk/atom"_compute_chunk_atom.html command :l
|
||||
mode = {sum} or {min} or {max} :l
|
||||
one or more inputs can be listed :l
|
||||
input = c_ID, c_ID\[N\], f_ID, f_ID\[N\], v_ID :l
|
||||
c_ID = per-atom vector calculated by a compute with ID
|
||||
c_ID\[I\] = Ith column of per-atom array calculated by a compute with ID, I can include wildcard (see below)
|
||||
f_ID = per-atom vector calculated by a fix with ID
|
||||
f_ID\[I\] = Ith column of per-atom array calculated by a fix with ID, I can include wildcard (see below)
|
||||
v_name = per-atom vector calculated by an atom-style variable with name :pre
|
||||
:ule
|
||||
|
||||
[Examples:]
|
||||
|
||||
compute 1 all reduce/chunk/atom mychunk min c_cluster :pre
|
||||
|
||||
[Description:]
|
||||
|
||||
Define a calculation that reduces one or more per-atom vectors into
|
||||
per-chunk values. This can be useful for diagnostic output. Or when
|
||||
used in conjunction with the "compute
|
||||
chunk/spread/atom"_compute_chunk_spread_atom.html command it can be
|
||||
used ot create per-atom values that induce a new set of chunks with a
|
||||
second "compute chunk/atom"_compute_chunk_atom.html command. An
|
||||
example is given below.
|
||||
|
||||
In LAMMPS, chunks are collections of atoms defined by a "compute
|
||||
chunk/atom"_compute_chunk_atom.html command, which assigns each atom
|
||||
to a single chunk (or no chunk). The ID for this command is specified
|
||||
as chunkID. For example, a single chunk could be the atoms in a
|
||||
molecule or atoms in a spatial bin. See the "compute
|
||||
chunk/atom"_compute_chunk_atom.html and "Howto chunk"_Howto_chunk.html
|
||||
doc pages for details of how chunks can be defined and examples of how
|
||||
they can be used to measure properties of a system.
|
||||
|
||||
For each atom, this compute accesses its chunk ID from the specified
|
||||
{chunkID} compute. The per-atom value from an input contributes
|
||||
to a per-chunk value corresponding the the chunk ID.
|
||||
|
||||
The reduction operation is specified by the {mode} setting and is
|
||||
performed over all the per-atom values from the atoms in each chunk.
|
||||
The {sum} option adds the pre-atom values to a per-chunk total. The
|
||||
{min} or {max} options find the minimum or maximum value of the
|
||||
per-atom values for each chunk.
|
||||
|
||||
Note that only atoms in the specified group contribute to the
|
||||
reduction operation. If the {chunkID} compute returns a 0 for the
|
||||
chunk ID of an atom (i.e. the atom is not in a chunk defined by the
|
||||
"compute chunk/atom"_compute_chunk_atom.html command), that atom will
|
||||
also not contribute to the reduction operation. An input that is a
|
||||
compute or fix may define its own group which affects the quantities
|
||||
it returns. For example, a compute with return a zero value for atoms
|
||||
that are not in the group specified for that compute.
|
||||
|
||||
Each listed input is operated on independently. Each input can be the
|
||||
result of a "compute"_compute.html or "fix"_fix.html or the evaluation
|
||||
of an atom-style "variable"_variable.html.
|
||||
|
||||
Note that for values from a compute or fix, the bracketed index I can
|
||||
be specified using a wildcard asterisk with the index to effectively
|
||||
specify multiple values. This takes the form "*" or "*n" or "n*" or
|
||||
"m*n". If N = the size of the vector (for {mode} = scalar) or the
|
||||
number of columns in the array (for {mode} = vector), then an asterisk
|
||||
with no numeric values means all indices from 1 to N. A leading
|
||||
asterisk means all indices from 1 to n (inclusive). A trailing
|
||||
asterisk means all indices from n to N (inclusive). A middle asterisk
|
||||
means all indices from m to n (inclusive).
|
||||
|
||||
Using a wildcard is the same as if the individual columns of the array
|
||||
had been listed one by one. E.g. these 2 compute reduce/chunk
|
||||
commands are equivalent, since the "compute
|
||||
property/chunk"_compute_property_chunk.html command creates a per-atom
|
||||
array with 3 columns:
|
||||
|
||||
compute prop all property/atom vx vy vz
|
||||
compute 10 all reduce/chunk mychunk max c_prop\[*\]
|
||||
compute 10 all reduce/chunk mychunk max c_prop\[1\] c_prop\[2\] c_prop\[3\] :pre
|
||||
|
||||
:line
|
||||
|
||||
Here is an example of using this compute, in conjunction with the
|
||||
compute chunk/spread/atom command to identify self-assembled micelles.
|
||||
The commands below can be added to the examples/in.micelle script.
|
||||
|
||||
Imagine a collection of polymer chains or small molecules with
|
||||
hydrophobic end groups. All the hydrophobic (HP) atoms are assigned
|
||||
to a group called "phobic".
|
||||
|
||||
These commands will assign a unique cluster ID to all HP atoms within
|
||||
a specified distance of each other. A cluster will contain all HP
|
||||
atoms in a single molecule, but also the HP atoms in nearby molecules,
|
||||
e.g. molecules that have clumped to form a micelle due to the
|
||||
attraction induced by the hydrophobicity. The output of the
|
||||
chunk/reduce command will be a cluster ID per chunk (molecule).
|
||||
Molecules with the same cluster ID are in the same micelle.
|
||||
|
||||
group phobic type 4 # specific to in.micelle model
|
||||
compute cluster phobic cluster/atom 2.0
|
||||
compute cmol all chunk/atom molecule
|
||||
compute reduce phobic reduce/chunk cmol min c_cluster :pre
|
||||
|
||||
This per-chunk info could be output in at least two ways:
|
||||
|
||||
fix 10 all ave/time 1000 1 1000 c_reduce file tmp.phobic mode vector :pre
|
||||
|
||||
compute spread all chunk/spread/atom cmol c_reduce
|
||||
dump 1 all custom 1000 tmp.dump id type mol x y z c_cluster c_spread
|
||||
dump_modify 1 sort id :pre
|
||||
|
||||
In the first case, each snapshot in the tmp.phobic file will contain
|
||||
one line per molecule. Molecules with the same value are in the same
|
||||
micelle. In the second case each dump snapshot contains all atoms,
|
||||
each with a final field with the cluster ID of the micelle that the HP
|
||||
atoms of that atom's molecule belong to.
|
||||
|
||||
The result from compute chunk/spread/atom can be used to define a new
|
||||
set of chunks, where all the atoms in all the molecules in the same
|
||||
micelle are assigned to the same chunk, i.e. one chunk per micelle.
|
||||
|
||||
compute micelle all chunk/atom c_spread compress yes :pre
|
||||
|
||||
Further analysis on a per-micelle basis can now be performed using any
|
||||
of the per-chunk computes listed on the "Howto chunk"_Howto_chunk.html
|
||||
doc page. E.g. count the number of atoms in each micelle, calculate
|
||||
its center or mass, shape (moments of intertia), radius of gyration,
|
||||
etc.
|
||||
|
||||
compute prop all property/chunk micelle count
|
||||
fix 20 all ave/time 1000 1 1000 c_prop file tmp.micelle mode vector :pre
|
||||
|
||||
Each snapshot in the tmp.micelle file will have one line per micelle
|
||||
with its count of atoms, plus a first line for a chunk with all the
|
||||
solvent atoms. By the time 50000 steps have elapsed there are a
|
||||
handful of large micelles.
|
||||
|
||||
:line
|
||||
|
||||
[Output info:]
|
||||
|
||||
This compute calculates a global vector if a single input value is
|
||||
specified, otherwise a global array is output. The number of columns
|
||||
in the array is the number of inputs provided. The length of the
|
||||
vector or the number of vector elements or array rows = the number of
|
||||
chunks {Nchunk} as calculated by the specified "compute
|
||||
chunk/atom"_compute_chunk_atom.html command. The vector or array can
|
||||
be accessed by any command that uses global values from a compute as
|
||||
input. See the "Howto output"_Howto_output.html doc page for an
|
||||
overview of LAMMPS output options.
|
||||
|
||||
The per-atom values for the vector or each column of the array will be
|
||||
in whatever "units"_units.html the corresponding input value is in.
|
||||
The vector or array values are "intensive".
|
||||
|
||||
[Restrictions:] none
|
||||
|
||||
[Related commands:]
|
||||
|
||||
"compute chunk/atom"_compute_chunk_atom.html, "compute
|
||||
reduce"_compute_reduce.html, "compute
|
||||
chunk/spread/atom"_compute_chunk_spread_atom.html
|
||||
|
||||
[Default:] none
|
||||
@ -15,6 +15,7 @@ Computes :h1
|
||||
compute_bond_local
|
||||
compute_centro_atom
|
||||
compute_chunk_atom
|
||||
compute_chunk_spread_atom
|
||||
compute_cluster_atom
|
||||
compute_cna_atom
|
||||
compute_cnp_atom
|
||||
@ -72,6 +73,7 @@ Computes :h1
|
||||
compute_property_local
|
||||
compute_rdf
|
||||
compute_reduce
|
||||
compute_reduce_chunk
|
||||
compute_rigid_local
|
||||
compute_saed
|
||||
compute_slice
|
||||
|
||||
@ -406,6 +406,7 @@ compute_bond.html
|
||||
compute_bond_local.html
|
||||
compute_centro_atom.html
|
||||
compute_chunk_atom.html
|
||||
compute_chunk_spread_atom.html
|
||||
compute_cluster_atom.html
|
||||
compute_cna_atom.html
|
||||
compute_cnp_atom.html
|
||||
@ -463,6 +464,7 @@ compute_property_chunk.html
|
||||
compute_property_local.html
|
||||
compute_rdf.html
|
||||
compute_reduce.html
|
||||
compute_reduce_chunk.html
|
||||
compute_rigid_local.html
|
||||
compute_saed.html
|
||||
compute_slice.html
|
||||
|
||||
352
src/compute_chunk_spread_atom.cpp
Normal file
352
src/compute_chunk_spread_atom.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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 <cstring>
|
||||
#include <cstdlib>
|
||||
#include "compute_chunk_spread_atom.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
#include "modify.h"
|
||||
#include "fix.h"
|
||||
#include "compute.h"
|
||||
#include "compute_chunk_atom.h"
|
||||
#include "input.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
enum{COMPUTE,FIX};
|
||||
|
||||
#define INVOKED_VECTOR 2
|
||||
#define INVOKED_ARRAY 4
|
||||
#define INVOKED_PERATOM 8
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeChunkSpreadAtom::
|
||||
ComputeChunkSpreadAtom(LAMMPS *lmp, int narg, char **arg) :
|
||||
Compute(lmp, narg, arg),
|
||||
which(NULL), argindex(NULL), ids(NULL), value2index(NULL), idchunk(NULL)
|
||||
{
|
||||
if (narg < 5) error->all(FLERR,"Illegal compute chunk/spread/atom command");
|
||||
|
||||
// ID of compute chunk/atom
|
||||
|
||||
int n = strlen(arg[3]) + 1;
|
||||
idchunk = new char[n];
|
||||
strcpy(idchunk,arg[3]);
|
||||
init_chunk();
|
||||
|
||||
// expand args if any have wildcard character "*"
|
||||
|
||||
int iarg = 4;
|
||||
int expand = 0;
|
||||
char **earg;
|
||||
int nargnew = input->expand_args(narg-iarg,&arg[iarg],1,earg);
|
||||
|
||||
if (earg != &arg[iarg]) expand = 1;
|
||||
arg = earg;
|
||||
|
||||
// parse values
|
||||
|
||||
which = new int[nargnew];
|
||||
argindex = new int[nargnew];
|
||||
ids = new char*[nargnew];
|
||||
value2index = new int[nargnew];
|
||||
nvalues = 0;
|
||||
|
||||
iarg = 0;
|
||||
while (iarg < nargnew) {
|
||||
ids[nvalues] = NULL;
|
||||
|
||||
if (strncmp(arg[iarg],"c_",2) == 0 ||
|
||||
strncmp(arg[iarg],"f_",2) == 0) {
|
||||
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
|
||||
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
|
||||
|
||||
int n = strlen(arg[iarg]);
|
||||
char *suffix = new char[n];
|
||||
strcpy(suffix,&arg[iarg][2]);
|
||||
|
||||
char *ptr = strchr(suffix,'[');
|
||||
if (ptr) {
|
||||
if (suffix[strlen(suffix)-1] != ']')
|
||||
error->all(FLERR,"Illegal compute chunk/spread/atom command");
|
||||
argindex[nvalues] = atoi(ptr+1);
|
||||
*ptr = '\0';
|
||||
} else argindex[nvalues] = 0;
|
||||
|
||||
n = strlen(suffix) + 1;
|
||||
ids[nvalues] = new char[n];
|
||||
strcpy(ids[nvalues],suffix);
|
||||
nvalues++;
|
||||
delete [] suffix;
|
||||
|
||||
} else error->all(FLERR,"Illegal compute chunk/spread/atom command");
|
||||
|
||||
iarg++;
|
||||
}
|
||||
|
||||
// if wildcard expansion occurred, free earg memory from expand_args()
|
||||
|
||||
if (expand) {
|
||||
for (int i = 0; i < nargnew; i++) delete [] earg[i];
|
||||
memory->sfree(earg);
|
||||
}
|
||||
|
||||
// setup and error check
|
||||
// for compute, must calculate per-chunk values, i.e. style ends in "/chunk"
|
||||
// for fix, assume a global vector or array is per-chunk data
|
||||
|
||||
for (int i = 0; i < nvalues; i++) {
|
||||
if (which[i] == COMPUTE) {
|
||||
int icompute = modify->find_compute(ids[i]);
|
||||
if (icompute < 0)
|
||||
error->all(FLERR,"Compute ID for compute chunk/spread/atom "
|
||||
"does not exist");
|
||||
|
||||
char *ptr = strstr(modify->compute[icompute]->style,"/chunk");
|
||||
if (!ptr || (ptr != modify->compute[icompute]->style +
|
||||
strlen(modify->compute[icompute]->style) - strlen("/chunk")))
|
||||
error->all(FLERR,"Compute for compute chunk/spread/atom "
|
||||
"does not calculate per-chunk values");
|
||||
|
||||
if (argindex[i] == 0) {
|
||||
if (!modify->compute[icompute]->vector_flag)
|
||||
error->all(FLERR,"Compute chunk/spread/atom compute "
|
||||
"does not calculate global vector");
|
||||
} else {
|
||||
if (!modify->compute[icompute]->array_flag)
|
||||
error->all(FLERR,"Compute chunk/spread/atom compute "
|
||||
"does not calculate global array");
|
||||
if (argindex[i] > modify->compute[icompute]->size_array_cols)
|
||||
error->all(FLERR,"Compute chunk/spread/atom compute array "
|
||||
"is accessed out-of-range");
|
||||
}
|
||||
|
||||
} else if (which[i] == FIX) {
|
||||
int ifix = modify->find_fix(ids[i]);
|
||||
if (ifix < 0)
|
||||
error->all(FLERR,"Fix ID for compute chunk/spread/atom does not exist");
|
||||
if (argindex[i] == 0) {
|
||||
if (!modify->fix[ifix]->vector_flag)
|
||||
error->all(FLERR,"Compute chunk/spread/atom fix "
|
||||
"does not calculate global vector");
|
||||
} else {
|
||||
if (!modify->fix[ifix]->array_flag)
|
||||
error->all(FLERR,"Compute chunk/spread/atom fix "
|
||||
"does not calculate global array");
|
||||
if (argindex[i] > modify->fix[ifix]->size_array_cols)
|
||||
error->all(FLERR,"Compute chunk/spread/atom fix array "
|
||||
"is accessed out-of-range");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this compute produces a peratom vector or array
|
||||
|
||||
peratom_flag = 1;
|
||||
if (nvalues == 1) size_peratom_cols = 0;
|
||||
else size_peratom_cols = nvalues;
|
||||
|
||||
// per-atom vector or array
|
||||
|
||||
nmax = 0;
|
||||
vector_atom = NULL;
|
||||
array_atom = NULL;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeChunkSpreadAtom::~ComputeChunkSpreadAtom()
|
||||
{
|
||||
delete [] idchunk;
|
||||
|
||||
delete [] which;
|
||||
delete [] argindex;
|
||||
for (int i = 0; i < nvalues; i++) delete [] ids[i];
|
||||
delete [] ids;
|
||||
delete [] value2index;
|
||||
|
||||
memory->destroy(vector_atom);
|
||||
memory->destroy(array_atom);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeChunkSpreadAtom::init()
|
||||
{
|
||||
init_chunk();
|
||||
|
||||
// set indices of all computes,fixes,variables
|
||||
|
||||
for (int m = 0; m < nvalues; m++) {
|
||||
if (which[m] == COMPUTE) {
|
||||
int icompute = modify->find_compute(ids[m]);
|
||||
if (icompute < 0)
|
||||
error->all(FLERR,"Compute ID for compute chunk/spread/atom "
|
||||
"does not exist");
|
||||
value2index[m] = icompute;
|
||||
|
||||
} else if (which[m] == FIX) {
|
||||
int ifix = modify->find_fix(ids[m]);
|
||||
if (ifix < 0)
|
||||
error->all(FLERR,"Fix ID for compute chunk/spread/atom does not exist");
|
||||
value2index[m] = ifix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeChunkSpreadAtom::init_chunk()
|
||||
{
|
||||
int icompute = modify->find_compute(idchunk);
|
||||
if (icompute < 0)
|
||||
error->all(FLERR,"Chunk/atom compute does not exist for compute chunk/spread/atom");
|
||||
cchunk = (ComputeChunkAtom *) modify->compute[icompute];
|
||||
if (strcmp(cchunk->style,"chunk/atom") != 0)
|
||||
error->all(FLERR,"Compute chunk/spread/atom does not use chunk/atom compute");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeChunkSpreadAtom::compute_peratom()
|
||||
{
|
||||
invoked_peratom = update->ntimestep;
|
||||
|
||||
// grow local vector_atom or array_atom if necessary
|
||||
|
||||
if (atom->nmax > nmax) {
|
||||
if (nvalues == 1) {
|
||||
memory->destroy(vector_atom);
|
||||
nmax = atom->nmax;
|
||||
memory->create(vector_atom,nmax,"chunk/spread/atom:vector_atom");
|
||||
} else {
|
||||
memory->destroy(array_atom);
|
||||
nmax = atom->nmax;
|
||||
memory->create(array_atom,nmax,nvalues,"chunk/spread/atom:array_atom");
|
||||
}
|
||||
}
|
||||
|
||||
// compute chunk/atom assigns atoms to chunk IDs
|
||||
// extract ichunk index vector from compute
|
||||
// ichunk = 1 to Nchunk for included atoms, 0 for excluded atoms
|
||||
|
||||
int nchunk = cchunk->setup_chunks();
|
||||
cchunk->compute_ichunk();
|
||||
int *ichunk = cchunk->ichunk;
|
||||
|
||||
// loop over values, access compute or fix
|
||||
// loop over atoms, use chunk ID of each atom to store value from compute/fix
|
||||
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
int i,m,n,index,nstride;
|
||||
double *ptr;
|
||||
|
||||
for (m = 0; m < nvalues; m++) {
|
||||
n = value2index[m];
|
||||
|
||||
// copy compute/fix values into vector_atom or array_atom
|
||||
// nstride between values for each atom
|
||||
|
||||
if (nvalues == 1) {
|
||||
ptr = vector_atom;
|
||||
nstride = 1;
|
||||
} else {
|
||||
ptr = &array_atom[0][m];
|
||||
nstride = nvalues;
|
||||
}
|
||||
|
||||
// invoke compute if not previously invoked
|
||||
|
||||
if (which[m] == COMPUTE) {
|
||||
Compute *compute = modify->compute[n];
|
||||
|
||||
if (argindex[m] == 0) {
|
||||
if (!(compute->invoked_flag & INVOKED_VECTOR)) {
|
||||
compute->compute_vector();
|
||||
compute->invoked_flag |= INVOKED_VECTOR;
|
||||
}
|
||||
double *cvector = compute->vector;
|
||||
for (i = 0; i < nlocal; i++, ptr += nstride) {
|
||||
*ptr = 0.0;
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0 || index >= nchunk) continue;
|
||||
*ptr = cvector[index];
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!(compute->invoked_flag & INVOKED_ARRAY)) {
|
||||
compute->compute_array();
|
||||
compute->invoked_flag |= INVOKED_ARRAY;
|
||||
}
|
||||
int icol = argindex[m]-1;
|
||||
double **carray = compute->array;
|
||||
for (i = 0; i < nlocal; i++, ptr += nstride) {
|
||||
*ptr = 0.0;
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0 || index >= nchunk) continue;
|
||||
*ptr = carray[index][icol];
|
||||
}
|
||||
}
|
||||
|
||||
// access fix data, check if fix frequency is a match
|
||||
// are assuming the fix global vector/array is per-chunk data
|
||||
// check if index exceeds fix output length/rows
|
||||
|
||||
} else if (which[m] == FIX) {
|
||||
Fix *fix = modify->fix[n];
|
||||
if (update->ntimestep % fix->global_freq)
|
||||
error->all(FLERR,"Fix used in compute chunk/spread/atom not "
|
||||
"computed at compatible time");
|
||||
|
||||
if (argindex[m] == 0) {
|
||||
int nfix = fix->size_vector;
|
||||
for (i = 0; i < nlocal; i++, ptr += nstride) {
|
||||
*ptr = 0.0;
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0 || index >= nchunk || index >= nfix) continue;
|
||||
*ptr = fix->compute_vector(index);
|
||||
}
|
||||
|
||||
} else {
|
||||
int icol = argindex[m]-1;
|
||||
int nfix = fix->size_array_rows;
|
||||
for (i = 0; i < nlocal; i++, ptr += nstride) {
|
||||
*ptr = 0.0;
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0 || index >= nchunk || index >= nfix) continue;
|
||||
*ptr = fix->compute_array(index,icol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of local atom-based array
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double ComputeChunkSpreadAtom::memory_usage()
|
||||
{
|
||||
double bytes = nmax*nvalues * sizeof(double);
|
||||
return bytes;
|
||||
}
|
||||
61
src/compute_chunk_spread_atom.h
Normal file
61
src/compute_chunk_spread_atom.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef COMPUTE_CLASS
|
||||
|
||||
ComputeStyle(chunk/spread/atom,ComputeChunkSpreadAtom)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_COMPUTE_CHUNK_SPREAD_ATOM_H
|
||||
#define LMP_COMPUTE_CHUNK_SPREAD_ATOM_H
|
||||
|
||||
#include "compute.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ComputeChunkSpreadAtom : public Compute {
|
||||
public:
|
||||
ComputeChunkSpreadAtom(class LAMMPS *, int, char **);
|
||||
~ComputeChunkSpreadAtom();
|
||||
void init();
|
||||
void compute_peratom();
|
||||
double memory_usage();
|
||||
|
||||
protected:
|
||||
int mode,nvalues;
|
||||
char *idchunk;
|
||||
|
||||
int *which,*argindex,*value2index;
|
||||
char **ids;
|
||||
|
||||
int nmax;
|
||||
class ComputeChunkAtom *cchunk;
|
||||
|
||||
void init_chunk();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
*/
|
||||
@ -11,6 +11,7 @@
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#include <mpi.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include "compute_reduce.h"
|
||||
|
||||
512
src/compute_reduce_chunk.cpp
Normal file
512
src/compute_reduce_chunk.cpp
Normal file
@ -0,0 +1,512 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
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 <mpi.h>
|
||||
#include <string.h>
|
||||
#include "compute_reduce_chunk.h"
|
||||
#include "atom.h"
|
||||
#include "update.h"
|
||||
#include "modify.h"
|
||||
#include "fix.h"
|
||||
#include "compute.h"
|
||||
#include "compute_chunk_atom.h"
|
||||
#include "input.h"
|
||||
#include "variable.h"
|
||||
#include "memory.h"
|
||||
#include "error.h"
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
enum{SUM,MINN,MAXX};
|
||||
enum{COMPUTE,FIX,VARIABLE};
|
||||
|
||||
#define INVOKED_PERATOM 8
|
||||
|
||||
#define BIG 1.0e20
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeReduceChunk::ComputeReduceChunk(LAMMPS *lmp, int narg, char **arg) :
|
||||
Compute(lmp, narg, arg),
|
||||
vlocal(NULL), vglobal(NULL), alocal(NULL), aglobal(NULL), varatom(NULL),
|
||||
which(NULL), argindex(NULL), value2index(NULL), idchunk(NULL), ids(NULL)
|
||||
{
|
||||
if (narg < 6) error->all(FLERR,"Illegal compute reduce/chunk command");
|
||||
|
||||
// ID of compute chunk/atom
|
||||
|
||||
int n = strlen(arg[3]) + 1;
|
||||
idchunk = new char[n];
|
||||
strcpy(idchunk,arg[3]);
|
||||
init_chunk();
|
||||
|
||||
// mode
|
||||
|
||||
if (strcmp(arg[4],"sum") == 0) mode = SUM;
|
||||
else if (strcmp(arg[4],"min") == 0) mode = MINN;
|
||||
else if (strcmp(arg[4],"max") == 0) mode = MAXX;
|
||||
else error->all(FLERR,"Illegal compute reduce/chunk command");
|
||||
|
||||
int iarg = 5;
|
||||
|
||||
// expand args if any have wildcard character "*"
|
||||
|
||||
int expand = 0;
|
||||
char **earg;
|
||||
int nargnew = input->expand_args(narg-iarg,&arg[iarg],1,earg);
|
||||
|
||||
if (earg != &arg[iarg]) expand = 1;
|
||||
arg = earg;
|
||||
|
||||
// parse values until one isn't recognized
|
||||
|
||||
which = new int[nargnew];
|
||||
argindex = new int[nargnew];
|
||||
ids = new char*[nargnew];
|
||||
value2index = new int[nargnew];
|
||||
nvalues = 0;
|
||||
|
||||
iarg = 0;
|
||||
while (iarg < nargnew) {
|
||||
ids[nvalues] = NULL;
|
||||
|
||||
if (strncmp(arg[iarg],"c_",2) == 0 ||
|
||||
strncmp(arg[iarg],"f_",2) == 0 ||
|
||||
strncmp(arg[iarg],"v_",2) == 0) {
|
||||
if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE;
|
||||
else if (arg[iarg][0] == 'f') which[nvalues] = FIX;
|
||||
else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE;
|
||||
|
||||
int n = strlen(arg[iarg]);
|
||||
char *suffix = new char[n];
|
||||
strcpy(suffix,&arg[iarg][2]);
|
||||
|
||||
char *ptr = strchr(suffix,'[');
|
||||
if (ptr) {
|
||||
if (suffix[strlen(suffix)-1] != ']')
|
||||
error->all(FLERR,"Illegal compute reduce/chunk command");
|
||||
argindex[nvalues] = atoi(ptr+1);
|
||||
*ptr = '\0';
|
||||
} else argindex[nvalues] = 0;
|
||||
|
||||
n = strlen(suffix) + 1;
|
||||
ids[nvalues] = new char[n];
|
||||
strcpy(ids[nvalues],suffix);
|
||||
nvalues++;
|
||||
delete [] suffix;
|
||||
|
||||
} else error->all(FLERR,"Illegal compute reduce/chunk command");
|
||||
|
||||
iarg++;
|
||||
}
|
||||
|
||||
// if wildcard expansion occurred, free earg memory from expand_args()
|
||||
|
||||
if (expand) {
|
||||
for (int i = 0; i < nargnew; i++) delete [] earg[i];
|
||||
memory->sfree(earg);
|
||||
}
|
||||
|
||||
// error check
|
||||
|
||||
for (int i = 0; i < nvalues; i++) {
|
||||
if (which[i] == COMPUTE) {
|
||||
int icompute = modify->find_compute(ids[i]);
|
||||
if (icompute < 0)
|
||||
error->all(FLERR,"Compute ID for compute reduce/chunk does not exist");
|
||||
if (!modify->compute[icompute]->peratom_flag)
|
||||
error->all(FLERR,"Compute reduce/chunk compute does not "
|
||||
"calculate per-atom values");
|
||||
if (argindex[i] == 0 &&
|
||||
modify->compute[icompute]->size_peratom_cols != 0)
|
||||
error->all(FLERR,"Compute reduce/chunk compute does not "
|
||||
"calculate a per-atom vector");
|
||||
if (argindex[i] && modify->compute[icompute]->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Compute reduce/chunk compute does not "
|
||||
"calculate a per-atom array");
|
||||
if (argindex[i] &&
|
||||
argindex[i] > modify->compute[icompute]->size_peratom_cols)
|
||||
error->all(FLERR,
|
||||
"Compute reduce/chunk compute array is accessed out-of-range");
|
||||
|
||||
} else if (which[i] == FIX) {
|
||||
int ifix = modify->find_fix(ids[i]);
|
||||
if (ifix < 0)
|
||||
error->all(FLERR,"Fix ID for compute reduce/chunk does not exist");
|
||||
if (!modify->fix[ifix]->peratom_flag)
|
||||
error->all(FLERR,"Compute reduce/chunk fix does not "
|
||||
"calculate per-atom values");
|
||||
if (argindex[i] == 0 &&
|
||||
modify->fix[ifix]->size_peratom_cols != 0)
|
||||
error->all(FLERR,"Compute reduce/chunk fix does not "
|
||||
"calculate a per-atom vector");
|
||||
if (argindex[i] && modify->fix[ifix]->size_peratom_cols == 0)
|
||||
error->all(FLERR,"Compute reduce/chunk fix does not "
|
||||
"calculate a per-atom array");
|
||||
if (argindex[i] && argindex[i] > modify->fix[ifix]->size_peratom_cols)
|
||||
error->all(FLERR,"Compute reduce/chunk fix array is "
|
||||
"accessed out-of-range");
|
||||
|
||||
} else if (which[i] == VARIABLE) {
|
||||
int ivariable = input->variable->find(ids[i]);
|
||||
if (ivariable < 0)
|
||||
error->all(FLERR,"Variable name for compute reduce/chunk does not exist");
|
||||
if (input->variable->atomstyle(ivariable) == 0)
|
||||
error->all(FLERR,"Compute reduce/chunk variable is "
|
||||
"not atom-style variable");
|
||||
}
|
||||
}
|
||||
|
||||
// this compute produces either a vector or array
|
||||
|
||||
if (nvalues == 1) {
|
||||
vector_flag = 1;
|
||||
size_vector_variable = 1;
|
||||
extvector = 0;
|
||||
} else {
|
||||
array_flag = 1;
|
||||
size_array_rows_variable = 1;
|
||||
size_array_cols = nvalues;
|
||||
extarray = 0;
|
||||
}
|
||||
|
||||
// setup
|
||||
|
||||
if (mode == SUM) initvalue = 0.0;
|
||||
else if (mode == MINN) initvalue = BIG;
|
||||
else if (mode == MAXX) initvalue = -BIG;
|
||||
|
||||
maxchunk = 0;
|
||||
vlocal = vglobal = NULL;
|
||||
alocal = aglobal = NULL;
|
||||
|
||||
maxatom = 0;
|
||||
varatom = NULL;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeReduceChunk::~ComputeReduceChunk()
|
||||
{
|
||||
delete [] idchunk;
|
||||
|
||||
delete [] which;
|
||||
delete [] argindex;
|
||||
for (int m = 0; m < nvalues; m++) delete [] ids[m];
|
||||
delete [] ids;
|
||||
delete [] value2index;
|
||||
|
||||
memory->destroy(vlocal);
|
||||
memory->destroy(vglobal);
|
||||
memory->destroy(alocal);
|
||||
memory->destroy(aglobal);
|
||||
|
||||
memory->destroy(varatom);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::init()
|
||||
{
|
||||
init_chunk();
|
||||
|
||||
// set indices of all computes,fixes,variables
|
||||
|
||||
for (int m = 0; m < nvalues; m++) {
|
||||
if (which[m] == COMPUTE) {
|
||||
int icompute = modify->find_compute(ids[m]);
|
||||
if (icompute < 0)
|
||||
error->all(FLERR,"Compute ID for compute reduce/chunk does not exist");
|
||||
value2index[m] = icompute;
|
||||
|
||||
} else if (which[m] == FIX) {
|
||||
int ifix = modify->find_fix(ids[m]);
|
||||
if (ifix < 0)
|
||||
error->all(FLERR,"Fix ID for compute reduce/chunk does not exist");
|
||||
value2index[m] = ifix;
|
||||
|
||||
} else if (which[m] == VARIABLE) {
|
||||
int ivariable = input->variable->find(ids[m]);
|
||||
if (ivariable < 0)
|
||||
error->all(FLERR,"Variable name for compute reduce/chunk does not exist");
|
||||
value2index[m] = ivariable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::init_chunk()
|
||||
{
|
||||
int icompute = modify->find_compute(idchunk);
|
||||
if (icompute < 0)
|
||||
error->all(FLERR,"Chunk/atom compute does not exist for "
|
||||
"compute reduce/chunk");
|
||||
cchunk = (ComputeChunkAtom *) modify->compute[icompute];
|
||||
if (strcmp(cchunk->style,"chunk/atom") != 0)
|
||||
error->all(FLERR,"Compute reduce/chunk does not use chunk/atom compute");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::compute_vector()
|
||||
{
|
||||
invoked_vector = update->ntimestep;
|
||||
|
||||
// compute chunk/atom assigns atoms to chunk IDs
|
||||
// extract ichunk index vector from compute
|
||||
// ichunk = 1 to Nchunk for included atoms, 0 for excluded atoms
|
||||
|
||||
nchunk = cchunk->setup_chunks();
|
||||
cchunk->compute_ichunk();
|
||||
ichunk = cchunk->ichunk;
|
||||
if (!nchunk) return;
|
||||
|
||||
size_vector = nchunk;
|
||||
|
||||
if (nchunk > maxchunk) {
|
||||
memory->destroy(vlocal);
|
||||
memory->destroy(vglobal);
|
||||
maxchunk = nchunk;
|
||||
memory->create(vlocal,maxchunk,"reduce/chunk:vlocal");
|
||||
memory->create(vglobal,maxchunk,"reduce/chunk:vglobal");
|
||||
vector = vglobal;
|
||||
}
|
||||
|
||||
// perform local reduction of single peratom value
|
||||
|
||||
compute_one(0,vlocal,1);
|
||||
|
||||
// reduce the per-chunk values across all procs
|
||||
|
||||
if (mode == SUM)
|
||||
MPI_Allreduce(vlocal,vglobal,nchunk,MPI_DOUBLE,MPI_SUM,world);
|
||||
else if (mode == MINN)
|
||||
MPI_Allreduce(vlocal,vglobal,nchunk,MPI_DOUBLE,MPI_MIN,world);
|
||||
else if (mode == MAXX)
|
||||
MPI_Allreduce(vlocal,vglobal,nchunk,MPI_DOUBLE,MPI_MAX,world);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::compute_array()
|
||||
{
|
||||
invoked_array = update->ntimestep;
|
||||
|
||||
// compute chunk/atom assigns atoms to chunk IDs
|
||||
// extract ichunk index vector from compute
|
||||
// ichunk = 1 to Nchunk for included atoms, 0 for excluded atoms
|
||||
|
||||
nchunk = cchunk->setup_chunks();
|
||||
cchunk->compute_ichunk();
|
||||
ichunk = cchunk->ichunk;
|
||||
if (!nchunk) return;
|
||||
|
||||
size_array_rows = nchunk;
|
||||
|
||||
if (nchunk > maxchunk) {
|
||||
memory->destroy(alocal);
|
||||
memory->destroy(aglobal);
|
||||
maxchunk = nchunk;
|
||||
memory->create(alocal,maxchunk,nvalues,"reduce/chunk:alocal");
|
||||
memory->create(aglobal,maxchunk,nvalues,"reduce/chunk:aglobal");
|
||||
array = aglobal;
|
||||
}
|
||||
|
||||
// perform local reduction of all peratom values
|
||||
|
||||
for (int m = 0; m < nvalues; m++) compute_one(m,&alocal[0][m],nvalues);
|
||||
|
||||
// reduce the per-chunk values across all procs
|
||||
|
||||
if (mode == SUM)
|
||||
MPI_Allreduce(&alocal[0][0],&aglobal[0][0],nchunk*nvalues,
|
||||
MPI_DOUBLE,MPI_SUM,world);
|
||||
else if (mode == MINN)
|
||||
MPI_Allreduce(&alocal[0][0],&aglobal[0][0],nchunk*nvalues,
|
||||
MPI_DOUBLE,MPI_MIN,world);
|
||||
else if (mode == MAXX)
|
||||
MPI_Allreduce(&alocal[0][0],&aglobal[0][0],nchunk*nvalues,
|
||||
MPI_DOUBLE,MPI_MAX,world);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::compute_one(int m, double *vchunk, int nstride)
|
||||
{
|
||||
// initialize per-chunk values in accumulation vector
|
||||
|
||||
for (int i = 0; i < nchunk; i += nstride) vchunk[i] = initvalue;
|
||||
|
||||
// loop over my atoms
|
||||
// use peratom input and chunk ID of each atom to update vector
|
||||
|
||||
int *mask = atom->mask;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
int index;
|
||||
|
||||
if (which[m] == COMPUTE) {
|
||||
Compute *compute = modify->compute[value2index[m]];
|
||||
|
||||
if (!(compute->invoked_flag & INVOKED_PERATOM)) {
|
||||
compute->compute_peratom();
|
||||
compute->invoked_flag |= INVOKED_PERATOM;
|
||||
}
|
||||
|
||||
if (argindex[m] == 0) {
|
||||
double *vcompute = compute->vector_atom;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0) continue;
|
||||
combine(vchunk[index*nstride],vcompute[i]);
|
||||
}
|
||||
} else {
|
||||
double **acompute = compute->array_atom;
|
||||
int argindexm1 = argindex[m] - 1;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0) continue;
|
||||
combine(vchunk[index*nstride],acompute[i][argindexm1]);
|
||||
}
|
||||
}
|
||||
|
||||
// access fix fields, check if fix frequency is a match
|
||||
|
||||
} else if (which[m] == FIX) {
|
||||
Fix *fix = modify->fix[value2index[m]];
|
||||
if (update->ntimestep % fix->peratom_freq)
|
||||
error->all(FLERR,"Fix used in compute reduce/chunk not "
|
||||
"computed at compatible time");
|
||||
|
||||
if (argindex[m] == 0) {
|
||||
double *vfix = fix->vector_atom;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0) continue;
|
||||
combine(vchunk[index*nstride],vfix[i]);
|
||||
}
|
||||
} else {
|
||||
double **afix = fix->array_atom;
|
||||
int argindexm1 = argindex[m] - 1;
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0) continue;
|
||||
combine(vchunk[index*nstride],afix[i][argindexm1]);
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate atom-style variable
|
||||
|
||||
} else if (which[m] == VARIABLE) {
|
||||
if (atom->nmax > maxatom) {
|
||||
memory->destroy(varatom);
|
||||
maxatom = atom->nmax;
|
||||
memory->create(varatom,maxatom,"reduce/chunk:varatom");
|
||||
}
|
||||
|
||||
input->variable->compute_atom(value2index[m],igroup,varatom,1,0);
|
||||
for (int i = 0; i < nlocal; i++) {
|
||||
if (!(mask[i] & groupbit)) continue;
|
||||
index = ichunk[i]-1;
|
||||
if (index < 0) continue;
|
||||
combine(vchunk[index*nstride],varatom[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
combine two values according to reduction mode
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::combine(double &one, double two)
|
||||
{
|
||||
if (mode == SUM) one += two;
|
||||
else if (mode == MINN) {
|
||||
if (two < one) one = two;
|
||||
} else if (mode == MAXX) {
|
||||
if (two > one) one = two;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
lock methods: called by fix ave/time
|
||||
these methods insure vector/array size is locked for Nfreq epoch
|
||||
by passing lock info along to compute chunk/atom
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
increment lock counter
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::lock_enable()
|
||||
{
|
||||
cchunk->lockcount++;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
decrement lock counter in compute chunk/atom, if it still exists
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::lock_disable()
|
||||
{
|
||||
int icompute = modify->find_compute(idchunk);
|
||||
if (icompute >= 0) {
|
||||
cchunk = (ComputeChunkAtom *) modify->compute[icompute];
|
||||
cchunk->lockcount--;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
calculate and return # of chunks = length of vector/array
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int ComputeReduceChunk::lock_length()
|
||||
{
|
||||
nchunk = cchunk->setup_chunks();
|
||||
return nchunk;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
set the lock from startstep to stopstep
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::lock(Fix *fixptr, bigint startstep, bigint stopstep)
|
||||
{
|
||||
cchunk->lock(fixptr,startstep,stopstep);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
unset the lock
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void ComputeReduceChunk::unlock(Fix *fixptr)
|
||||
{
|
||||
cchunk->unlock(fixptr);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
memory usage of local data
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double ComputeReduceChunk::memory_usage()
|
||||
{
|
||||
double bytes = (bigint) maxatom * sizeof(double);
|
||||
if (nvalues == 1) bytes += (bigint) maxchunk * 2 * sizeof(double);
|
||||
else bytes += (bigint) maxchunk * nvalues * 2 * sizeof(double);
|
||||
return bytes;
|
||||
}
|
||||
77
src/compute_reduce_chunk.h
Normal file
77
src/compute_reduce_chunk.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* -*- c++ -*- ----------------------------------------------------------
|
||||
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
http://lammps.sandia.gov, Sandia National Laboratories
|
||||
Steve Plimpton, sjplimp@sandia.gov
|
||||
|
||||
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||
certain rights in this software. This software is distributed under
|
||||
the GNU General Public License.
|
||||
|
||||
See the README file in the top-level LAMMPS directory.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef COMPUTE_CLASS
|
||||
|
||||
ComputeStyle(reduce/chunk,ComputeReduceChunk)
|
||||
|
||||
#else
|
||||
|
||||
#ifndef LMP_COMPUTE_REDUCE_CHUNK_H
|
||||
#define LMP_COMPUTE_REDUCE_CHUNK_H
|
||||
|
||||
#include "compute.h"
|
||||
|
||||
namespace LAMMPS_NS {
|
||||
|
||||
class ComputeReduceChunk : public Compute {
|
||||
public:
|
||||
ComputeReduceChunk(class LAMMPS *, int, char **);
|
||||
~ComputeReduceChunk();
|
||||
void init();
|
||||
void compute_vector();
|
||||
void compute_array();
|
||||
|
||||
void lock_enable();
|
||||
void lock_disable();
|
||||
int lock_length();
|
||||
void lock(class Fix *, bigint, bigint);
|
||||
void unlock(class Fix *);
|
||||
|
||||
double memory_usage();
|
||||
|
||||
private:
|
||||
int mode,nvalues;
|
||||
int *which,*argindex,*value2index;
|
||||
char *idchunk;
|
||||
char **ids;
|
||||
|
||||
int nchunk;
|
||||
int maxchunk,maxatom;
|
||||
double initvalue;
|
||||
double *vlocal,*vglobal;
|
||||
double **alocal,**aglobal;
|
||||
double *varatom;
|
||||
|
||||
class ComputeChunkAtom *cchunk;
|
||||
int *ichunk;
|
||||
|
||||
void init_chunk();
|
||||
void compute_one(int, double *, int);
|
||||
void combine(double &, double);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ERROR/WARNING messages:
|
||||
|
||||
E: Illegal ... command
|
||||
|
||||
Self-explanatory. Check the input script syntax and compare to the
|
||||
documentation for the command. You can use -echo screen as a
|
||||
command-line option when running LAMMPS to see the offending line.
|
||||
|
||||
*/
|
||||
Reference in New Issue
Block a user