diff --git a/doc/src/Commands_compute.txt b/doc/src/Commands_compute.txt index 028e274c9be4a80555dfcab5a417d738b763bfda..6185634187fb0e5089bf9759b221aae5ee53a53a 100644 --- a/doc/src/Commands_compute.txt +++ b/doc/src/Commands_compute.txt @@ -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, diff --git a/doc/src/Howto_chunk.txt b/doc/src/Howto_chunk.txt index 8e52acf4b8693569bac54304bb5f2c0ffd56d0fb..611b71dac7d4546ad85241ac3d0b1786a05aff2b 100644 --- a/doc/src/Howto_chunk.txt +++ b/doc/src/Howto_chunk.txt @@ -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. diff --git a/doc/src/compute.txt b/doc/src/compute.txt index 8facb4de63ebfb527e11108ba02e381db6a1425f..72ea1c193004b132a32af49797e12a58478bdaad 100644 --- a/doc/src/compute.txt +++ b/doc/src/compute.txt @@ -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 diff --git a/doc/src/compute_chunk_atom.txt b/doc/src/compute_chunk_atom.txt index e76b51e6ec9df377f4e1354f0090c588f6dd4b53..c29a5600a982659325cd6af6948eb8ed16de22d9 100644 --- a/doc/src/compute_chunk_atom.txt +++ b/doc/src/compute_chunk_atom.txt @@ -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 diff --git a/doc/src/compute_chunk_spread_atom.txt b/doc/src/compute_chunk_spread_atom.txt new file mode 100644 index 0000000000000000000000000000000000000000..59662035e531479a36ac73e116abc31a6e9924ff --- /dev/null +++ b/doc/src/compute_chunk_spread_atom.txt @@ -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 diff --git a/doc/src/compute_reduce.txt b/doc/src/compute_reduce.txt index ef3c7c6489e03ef3c1056edefd8d4dc419766cdf..0bd2accf3c08ba9d7f50cb008c8b8151fe8b4012 100644 --- a/doc/src/compute_reduce.txt +++ b/doc/src/compute_reduce.txt @@ -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 diff --git a/doc/src/compute_reduce_chunk.txt b/doc/src/compute_reduce_chunk.txt new file mode 100644 index 0000000000000000000000000000000000000000..3628c0f1ad7a0a0e1add2773d24ecf97d86b89ee --- /dev/null +++ b/doc/src/compute_reduce_chunk.txt @@ -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 diff --git a/doc/src/computes.txt b/doc/src/computes.txt index 46dd30f7570f7a87d9874367f67f1d4af85a2fca..6528f78e40e38424828bc0349ec5689c8987d593 100644 --- a/doc/src/computes.txt +++ b/doc/src/computes.txt @@ -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 diff --git a/doc/src/lammps.book b/doc/src/lammps.book index c296ff4039e0827464ba616081d6bb9630943056..c7f0b2fddd60ae395e084a1f5b2a735c2227fdff 100644 --- a/doc/src/lammps.book +++ b/doc/src/lammps.book @@ -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 diff --git a/src/compute_chunk_spread_atom.cpp b/src/compute_chunk_spread_atom.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93a4d30a2e313c305f1abc7875280e2ddaa7745e --- /dev/null +++ b/src/compute_chunk_spread_atom.cpp @@ -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; +} diff --git a/src/compute_chunk_spread_atom.h b/src/compute_chunk_spread_atom.h new file mode 100644 index 0000000000000000000000000000000000000000..9a4df080ca2d4de652f357f0a84c46f15fb260a7 --- /dev/null +++ b/src/compute_chunk_spread_atom.h @@ -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. + +*/ diff --git a/src/compute_reduce.cpp b/src/compute_reduce.cpp index 7c61d666b2d9db9c9625b69bb08dfdafff49fa29..e3c3c5b70a9c3adbad74163e5b0ac9149c24c813 100644 --- a/src/compute_reduce.cpp +++ b/src/compute_reduce.cpp @@ -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" diff --git a/src/compute_reduce_chunk.cpp b/src/compute_reduce_chunk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40e9dad8dd4f9a7fcb2177551b2489066f06bc61 --- /dev/null +++ b/src/compute_reduce_chunk.cpp @@ -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; +} diff --git a/src/compute_reduce_chunk.h b/src/compute_reduce_chunk.h new file mode 100644 index 0000000000000000000000000000000000000000..ac556907b7352cbcf7fb47d44e13a537286bdbae --- /dev/null +++ b/src/compute_reduce_chunk.h @@ -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. + +*/