1 /* ----------------------------------------------------------------------
2     This is the
3 
4     ██╗     ██╗ ██████╗  ██████╗  ██████╗ ██╗  ██╗████████╗███████╗
5     ██║     ██║██╔════╝ ██╔════╝ ██╔════╝ ██║  ██║╚══██╔══╝██╔════╝
6     ██║     ██║██║  ███╗██║  ███╗██║  ███╗███████║   ██║   ███████╗
7     ██║     ██║██║   ██║██║   ██║██║   ██║██╔══██║   ██║   ╚════██║
8     ███████╗██║╚██████╔╝╚██████╔╝╚██████╔╝██║  ██║   ██║   ███████║
9     ╚══════╝╚═╝ ╚═════╝  ╚═════╝  ╚═════╝ ╚═╝  ╚═╝   ╚═╝   ╚══════╝®
10 
11     DEM simulation engine, released by
12     DCS Computing Gmbh, Linz, Austria
13     http://www.dcs-computing.com, office@dcs-computing.com
14 
15     LIGGGHTS® is part of CFDEM®project:
16     http://www.liggghts.com | http://www.cfdem.com
17 
18     Core developer and main author:
19     Christoph Kloss, christoph.kloss@dcs-computing.com
20 
21     LIGGGHTS® is open-source, distributed under the terms of the GNU Public
22     License, version 2 or later. It is distributed in the hope that it will
23     be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
24     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have
25     received a copy of the GNU General Public License along with LIGGGHTS®.
26     If not, see http://www.gnu.org/licenses . See also top-level README
27     and LICENSE files.
28 
29     LIGGGHTS® and CFDEM® are registered trade marks of DCS Computing GmbH,
30     the producer of the LIGGGHTS® software and the CFDEM®coupling software
31     See http://www.cfdem.com/terms-trademark-policy for details.
32 
33 -------------------------------------------------------------------------
34     Contributing author and copyright for this file:
35     This file is from LAMMPS
36     LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
37     http://lammps.sandia.gov, Sandia National Laboratories
38     Steve Plimpton, sjplimp@sandia.gov
39 
40     Copyright (2003) Sandia Corporation.  Under the terms of Contract
41     DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
42     certain rights in this software.  This software is distributed under
43     the GNU General Public License.
44 ------------------------------------------------------------------------- */
45 
46 #include <string.h>
47 #include "compute_property_molecule.h"
48 #include "atom.h"
49 #include "update.h"
50 #include "memory.h"
51 #include "error.h"
52 
53 using namespace LAMMPS_NS;
54 
55 /* ---------------------------------------------------------------------- */
56 
ComputePropertyMolecule(LAMMPS * lmp,int & iarg,int narg,char ** arg)57 ComputePropertyMolecule::ComputePropertyMolecule(LAMMPS *lmp, int &iarg, int narg, char **arg) :
58   Compute(lmp, iarg, narg, arg)
59 {
60   if (narg < iarg+1) error->all(FLERR,"Illegal compute property/molecule command");
61 
62   if (atom->molecular == 0)
63     error->all(FLERR,"Compute property/molecule requires molecular atom style");
64 
65   nvalues = narg - iarg;
66 
67   pack_choice = new FnPtrPack[nvalues];
68 
69   int i;
70   const int arg_offset = iarg;
71   for (; iarg < narg; iarg++) {
72     i = iarg-arg_offset;
73 
74     if (strcmp(arg[iarg],"mol") == 0)
75       pack_choice[i] = &ComputePropertyMolecule::pack_mol;
76     else if (strcmp(arg[iarg],"count") == 0)
77       pack_choice[i] = &ComputePropertyMolecule::pack_count;
78     else error->all(FLERR,"Invalid keyword in compute property/molecule command");
79   }
80 
81   // setup molecule-based data
82 
83   nmolecules = molecules_in_group(idlo,idhi);
84 
85   vector = NULL;
86   array = NULL;
87 
88   if (nvalues == 1) {
89     memory->create(vector,nmolecules,"property/molecule:vector");
90     vector_flag = 1;
91     size_vector = nmolecules;
92     extvector = 0;
93   } else {
94     memory->create(array,nmolecules,nvalues,"property/molecule:array");
95     array_flag = 1;
96     size_array_rows = nmolecules;
97     size_array_cols = nvalues;
98     extarray = 0;
99   }
100 
101   // fill vector or array with molecule values
102 
103   if (nvalues == 1) {
104     buf = vector;
105     (this->*pack_choice[0])(0);
106   } else {
107     if (array) buf = &array[0][0];
108     for (int n = 0; n < nvalues; n++)
109       (this->*pack_choice[n])(n);
110   }
111 }
112 
113 /* ---------------------------------------------------------------------- */
114 
~ComputePropertyMolecule()115 ComputePropertyMolecule::~ComputePropertyMolecule()
116 {
117   delete [] pack_choice;
118   memory->destroy(vector);
119   memory->destroy(array);
120 }
121 
122 /* ---------------------------------------------------------------------- */
123 
init()124 void ComputePropertyMolecule::init()
125 {
126   int ntmp = molecules_in_group(idlo,idhi);
127   if (ntmp != nmolecules)
128     error->all(FLERR,"Molecule count changed in compute property/molecule");
129 }
130 
131 /* ---------------------------------------------------------------------- */
132 
compute_vector()133 void ComputePropertyMolecule::compute_vector()
134 {
135   invoked_vector = update->ntimestep;
136 }
137 
138 /* ---------------------------------------------------------------------- */
139 
compute_array()140 void ComputePropertyMolecule::compute_array()
141 {
142   invoked_array = update->ntimestep;
143 }
144 
145 /* ----------------------------------------------------------------------
146    memory usage of local data
147 ------------------------------------------------------------------------- */
148 
memory_usage()149 double ComputePropertyMolecule::memory_usage()
150 {
151   double bytes = nmolecules*nvalues * sizeof(double);
152   if (molmap) bytes += (idhi-idlo+1) * sizeof(int);
153   return bytes;
154 }
155 
156 /* ----------------------------------------------------------------------
157    one method for every keyword compute property/molecule can output
158    the atom property is packed into buf starting at n with stride nvalues
159    customize a new keyword by adding a method
160 ------------------------------------------------------------------------- */
161 
pack_mol(int n)162 void ComputePropertyMolecule::pack_mol(int n)
163 {
164   for (int m = idlo; m <= idhi; m++)
165     if (molmap == NULL || molmap[m-idlo] >= 0) {
166       buf[n] = m;
167       n += nvalues;
168     }
169 }
170 
171 /* ---------------------------------------------------------------------- */
172 
pack_count(int n)173 void ComputePropertyMolecule::pack_count(int n)
174 {
175   int i,m,imol;
176 
177   int *count_one = new int[nmolecules];
178   for (m = 0; m < nmolecules; m++) count_one[m] = 0;
179 
180   int *molecule = atom->molecule;
181   int *mask = atom->mask;
182   int nlocal = atom->nlocal;
183 
184   for (i = 0; i < nlocal; i++)
185     if (mask[i] & groupbit) {
186       imol = molecule[i];
187       if (molmap) imol = molmap[imol-idlo];
188       else imol--;
189       count_one[imol]++;
190     }
191 
192   int *count_all = new int[nmolecules];
193   MPI_Allreduce(count_one,count_all,nmolecules,MPI_INT,MPI_SUM,world);
194 
195   for (m = 0; m < nmolecules; m++)
196     if (molmap == NULL || molmap[m] >= 0) {
197       buf[n] = count_all[m];
198       n += nvalues;
199     }
200 
201   delete [] count_one;
202   delete [] count_all;
203 }
204