kim-api  2.2.1+v2.2.1.GNU.GNU.
An Application Programming Interface (API) for the Knowledgebase of Interatomic Models (KIM).
LennardJones612Implementation.hpp
Go to the documentation of this file.
1 //
2 // CDDL HEADER START
3 //
4 // The contents of this file are subject to the terms of the Common Development
5 // and Distribution License Version 1.0 (the "License").
6 //
7 // You can obtain a copy of the license at
8 // http://www.opensource.org/licenses/CDDL-1.0. See the License for the
9 // specific language governing permissions and limitations under the License.
10 //
11 // When distributing Covered Code, include this CDDL HEADER in each file and
12 // include the License file in a prominent location with the name LICENSE.CDDL.
13 // If applicable, add the following below this CDDL HEADER, with the fields
14 // enclosed by brackets "[]" replaced with your own identifying information:
15 //
16 // Portions Copyright (c) [yyyy] [name of copyright owner]. All rights reserved.
17 //
18 // CDDL HEADER END
19 //
20 
21 //
22 // Copyright (c) 2015, Regents of the University of Minnesota.
23 // All rights reserved.
24 //
25 // Contributors:
26 // Ryan S. Elliott
27 // Andrew Akerson
28 //
29 
30 
31 #ifndef LENNARD_JONES_612_IMPLEMENTATION_HPP_
32 #define LENNARD_JONES_612_IMPLEMENTATION_HPP_
33 
34 #include "KIM_LogMacros.hpp"
36 #include <cmath>
37 #include <cstdio>
38 #include <vector>
39 
40 #define DIMENSION 3
41 #define ONE 1.0
42 #define HALF 0.5
43 
44 #define MAX_PARAMETER_FILES 1
45 
46 #define PARAM_SHIFT_INDEX 0
47 #define PARAM_CUTOFFS_INDEX 1
48 #define PARAM_EPSILONS_INDEX 2
49 #define PARAM_SIGMAS_INDEX 3
50 
51 
52 //==============================================================================
53 //
54 // Type definitions, enumerations, and helper function prototypes
55 //
56 //==============================================================================
57 
58 // type declaration for get neighbor functions
59 typedef int(GetNeighborFunction)(void const * const,
60  int const,
61  int * const,
62  int const ** const);
63 // type declaration for vector of constant dimension
64 typedef double VectorOfSizeDIM[DIMENSION];
65 typedef double VectorOfSizeSix[6];
66 
67 // helper routine declarations
68 void AllocateAndInitialize2DArray(double **& arrayPtr,
69  int const extentZero,
70  int const extentOne);
71 void Deallocate2DArray(double **& arrayPtr);
72 
73 //==============================================================================
74 //
75 // Declaration of LennardJones612Implementation class
76 //
77 //==============================================================================
78 
79 //******************************************************************************
81 {
82  public:
84  KIM::ModelDriverCreate * const modelDriverCreate,
85  KIM::LengthUnit const requestedLengthUnit,
86  KIM::EnergyUnit const requestedEnergyUnit,
87  KIM::ChargeUnit const requestedChargeUnit,
88  KIM::TemperatureUnit const requestedTemperatureUnit,
89  KIM::TimeUnit const requestedTimeUnit,
90  int * const ier);
91  ~LennardJones612Implementation(); // no explicit Destroy() needed here
92 
93  int Refresh(KIM::ModelRefresh * const modelRefresh);
94  int Compute(KIM::ModelCompute const * const modelCompute,
95  KIM::ModelComputeArguments const * const modelComputeArguments);
97  modelComputeArgumentsCreate) const;
99  modelComputeArgumentsDestroy) const;
100 
101 
102  private:
103  // Constant values that never change
104  // Set in constructor (via SetConstantValues)
105  //
106  //
107  // LennardJones612Implementation: constants
108  int numberModelSpecies_;
109  std::vector<int> modelSpeciesCodeList_;
110  int numberUniqueSpeciesPairs_;
111 
112 
113  // Constant values that are read from the input files and never change
114  // Set in constructor (via functions listed below)
115  //
116  //
117  // Private Model Parameters
118  // Memory allocated in AllocatePrivateParameterMemory() (from constructor)
119  // Memory deallocated in destructor
120  // Data set in ReadParameterFile routines
121  // none
122  //
123  // KIM API: Model Parameters whose (pointer) values never change
124  // Memory allocated in AllocateParameterMemory() (from constructor)
125  // Memory deallocated in destructor
126  // Data set in ReadParameterFile routines OR by KIM Simulator
127  int shift_;
128  double * cutoffs_;
129  double * epsilons_;
130  double * sigmas_;
131 
132  // Mutable values that only change when Refresh() executes
133  // Set in Refresh (via SetRefreshMutableValues)
134  //
135  //
136  // KIM API: Model Parameters (can be changed directly by KIM Simulator)
137  // none
138  //
139  // LennardJones612Implementation: values (changed only by Refresh())
140  double influenceDistance_;
141  double ** cutoffsSq2D_;
142  int modelWillNotRequestNeighborsOfNoncontributingParticles_;
143  double ** fourEpsilonSigma6_2D_;
144  double ** fourEpsilonSigma12_2D_;
145  double ** twentyFourEpsilonSigma6_2D_;
146  double ** fortyEightEpsilonSigma12_2D_;
147  double ** oneSixtyEightEpsilonSigma6_2D_;
148  double ** sixTwentyFourEpsilonSigma12_2D_;
149  double ** shifts2D_;
150 
151 
152  // Mutable values that can change with each call to Refresh() and Compute()
153  // Memory may be reallocated on each call
154  //
155  //
156  // LennardJones612Implementation: values that change
157  int cachedNumberOfParticles_;
158 
159 
160  // Helper methods
161  //
162  //
163  // Related to constructor
164  void AllocatePrivateParameterMemory();
165  void AllocateParameterMemory();
166  static int
167  OpenParameterFiles(KIM::ModelDriverCreate * const modelDriverCreate,
168  int const numberParameterFiles,
169  FILE * parameterFilePointers[MAX_PARAMETER_FILES]);
170  int ProcessParameterFiles(
171  KIM::ModelDriverCreate * const modelDriverCreate,
172  int const numberParameterFiles,
173  FILE * const parameterFilePointers[MAX_PARAMETER_FILES]);
174  void getNextDataLine(FILE * const filePtr,
175  char * const nextLine,
176  int const maxSize,
177  int * endOfFileFlag);
178  static void
179  CloseParameterFiles(int const numberParameterFiles,
180  FILE * const parameterFilePointers[MAX_PARAMETER_FILES]);
181  int ConvertUnits(KIM::ModelDriverCreate * const modelDriverCreate,
182  KIM::LengthUnit const requestedLengthUnit,
183  KIM::EnergyUnit const requestedEnergyUnit,
184  KIM::ChargeUnit const requestedChargeUnit,
185  KIM::TemperatureUnit const requestedTemperatureUnit,
186  KIM::TimeUnit const requestedTimeUnit);
187  int RegisterKIMModelSettings(
188  KIM::ModelDriverCreate * const modelDriverCreate) const;
189  int RegisterKIMComputeArgumentsSettings(
190  KIM::ModelComputeArgumentsCreate * const modelComputeArgumentsCreate)
191  const;
192  int RegisterKIMParameters(KIM::ModelDriverCreate * const modelDriverCreate);
193  int RegisterKIMFunctions(
194  KIM::ModelDriverCreate * const modelDriverCreate) const;
195  //
196  // Related to Refresh()
197  template<class ModelObj>
198  int SetRefreshMutableValues(ModelObj * const modelObj);
199 
200  //
201  // Related to Compute()
202  int SetComputeMutableValues(
203  KIM::ModelComputeArguments const * const modelComputeArguments,
204  bool & isComputeProcess_dEdr,
205  bool & isComputeProcess_d2Edr2,
206  bool & isComputeEnergy,
207  bool & isComputeForces,
208  bool & isComputeParticleEnergy,
209  bool & isComputeVirial,
210  bool & isComputeParticleVirial,
211  int const *& particleSpeciesCodes,
212  int const *& particleContributing,
213  VectorOfSizeDIM const *& coordinates,
214  double *& energy,
215  double *& particleEnergy,
216  VectorOfSizeDIM *& forces,
217  VectorOfSizeSix *& virial,
218  VectorOfSizeSix *& particleViral);
219  int CheckParticleSpeciesCodes(KIM::ModelCompute const * const modelCompute,
220  int const * const particleSpeciesCodes) const;
221  int GetComputeIndex(const bool & isComputeProcess_dEdr,
222  const bool & isComputeProcess_d2Edr2,
223  const bool & isComputeEnergy,
224  const bool & isComputeForces,
225  const bool & isComputeParticleEnergy,
226  const bool & isComputeVirial,
227  const bool & isComputeParticleVirial,
228  const bool & isShift) const;
229  void ProcessVirialTerm(const double & dEidr,
230  const double & rij,
231  const double * const r_ij,
232  const int & i,
233  const int & j,
234  VectorOfSizeSix virial) const;
235  void ProcessParticleVirialTerm(const double & dEidr,
236  const double & rij,
237  const double * const r_ij,
238  const int & i,
239  const int & j,
240  VectorOfSizeSix * const particleVirial) const;
241 
242  // compute functions
243  template<bool isComputeProcess_dEdr,
244  bool isComputeProcess_d2Edr2,
245  bool isComputeEnergy,
246  bool isComputeForces,
247  bool isComputeParticleEnergy,
248  bool isComputeVirial,
249  bool isComputeParticleVirial,
250  bool isShift>
251  int Compute(KIM::ModelCompute const * const modelCompute,
252  KIM::ModelComputeArguments const * const modelComputeArguments,
253  const int * const particleSpeciesCodes,
254  const int * const particleContributing,
255  const VectorOfSizeDIM * const coordinates,
256  double * const energy,
257  VectorOfSizeDIM * const forces,
258  double * const particleEnergy,
259  VectorOfSizeSix virial,
260  VectorOfSizeSix * const particleVirial) const;
261 };
262 
263 //==============================================================================
264 //
265 // Definition of LennardJones612Implementation::Compute functions
266 //
267 // NOTE: Here we rely on the compiler optimizations to prune dead code
268 // after the template expansions. This provides high efficiency
269 // and easy maintenance.
270 //
271 //==============================================================================
272 
273 //******************************************************************************
274 // MACRO to compute Lennard-Jones phi
275 // (used for efficiency)
276 //
277 // exshift - expression to be added to the end of the phi value
278 #define LENNARD_JONES_PHI(exshift) \
279  phi = r6iv \
280  * (constFourEpsSig12_2D[iSpecies][jSpecies] * r6iv \
281  - constFourEpsSig6_2D[iSpecies][jSpecies]) exshift;
282 
283 //******************************************************************************
284 #undef KIM_LOGGER_OBJECT_NAME
285 #define KIM_LOGGER_OBJECT_NAME modelCompute
286 //
287 template<bool isComputeProcess_dEdr,
288  bool isComputeProcess_d2Edr2,
289  bool isComputeEnergy,
290  bool isComputeForces,
291  bool isComputeParticleEnergy,
292  bool isComputeVirial,
293  bool isComputeParticleVirial,
294  bool isShift>
296  KIM::ModelCompute const * const modelCompute,
297  KIM::ModelComputeArguments const * const modelComputeArguments,
298  const int * const particleSpeciesCodes,
299  const int * const particleContributing,
300  const VectorOfSizeDIM * const coordinates,
301  double * const energy,
302  VectorOfSizeDIM * const forces,
303  double * const particleEnergy,
304  VectorOfSizeSix virial,
305  VectorOfSizeSix * const particleVirial) const
306 {
307  int ier = false;
308 
309  if ((isComputeEnergy == false) && (isComputeParticleEnergy == false)
310  && (isComputeForces == false) && (isComputeProcess_dEdr == false)
311  && (isComputeProcess_d2Edr2 == false) && (isComputeVirial == false)
312  && (isComputeParticleVirial == false))
313  return ier;
314 
315  // initialize energy and forces
316  if (isComputeEnergy == true) { *energy = 0.0; }
317  if (isComputeVirial == true)
318  {
319  for (int i = 0; i < 6; ++i) virial[i] = 0.0;
320  }
321  if (isComputeParticleEnergy == true)
322  {
323  int const cachedNumParticles = cachedNumberOfParticles_;
324  for (int i = 0; i < cachedNumParticles; ++i) { particleEnergy[i] = 0.0; }
325  }
326  if (isComputeForces == true)
327  {
328  int const cachedNumParticles = cachedNumberOfParticles_;
329  for (int i = 0; i < cachedNumParticles; ++i)
330  {
331  for (int j = 0; j < DIMENSION; ++j) forces[i][j] = 0.0;
332  }
333  }
334  if (isComputeParticleVirial == true)
335  {
336  int const cachedNumParticles = cachedNumberOfParticles_;
337  for (int i = 0; i < cachedNumParticles; ++i)
338  {
339  for (int j = 0; j < 6; ++j) particleVirial[i][j] = 0.0;
340  }
341  }
342 
343  // calculate contribution from pair function
344  //
345  // Setup loop over contributing particles
346  int ii = 0;
347  int numnei = 0;
348  int const * n1atom = NULL;
349  double const * const * const constCutoffsSq2D = cutoffsSq2D_;
350  double const * const * const constFourEpsSig6_2D = fourEpsilonSigma6_2D_;
351  double const * const * const constFourEpsSig12_2D = fourEpsilonSigma12_2D_;
352  double const * const * const constTwentyFourEpsSig6_2D
353  = twentyFourEpsilonSigma6_2D_;
354  double const * const * const constFortyEightEpsSig12_2D
355  = fortyEightEpsilonSigma12_2D_;
356  double const * const * const constOneSixtyEightEpsSig6_2D
357  = oneSixtyEightEpsilonSigma6_2D_;
358  double const * const * const constSixTwentyFourEpsSig12_2D
359  = sixTwentyFourEpsilonSigma12_2D_;
360  double const * const * const constShifts2D = shifts2D_;
361  for (ii = 0; ii < cachedNumberOfParticles_; ++ii)
362  {
363  if (particleContributing[ii])
364  {
365  modelComputeArguments->GetNeighborList(0, ii, &numnei, &n1atom);
366  int const numNei = numnei;
367  int const * const n1Atom = n1atom;
368  int const i = ii;
369  int const iSpecies = particleSpeciesCodes[i];
370 
371  // Setup loop over neighbors of current particle
372  for (int jj = 0; jj < numNei; ++jj)
373  {
374  int const j = n1Atom[jj];
375  int const jContrib = particleContributing[j];
376 
377  if (!(jContrib && (j < i))) // effective half-list
378  {
379  int const jSpecies = particleSpeciesCodes[j];
380  double * r_ij;
381  double r_ijValue[DIMENSION];
382  // Compute r_ij
383  r_ij = r_ijValue;
384  for (int k = 0; k < DIMENSION; ++k)
385  r_ij[k] = coordinates[j][k] - coordinates[i][k];
386  double const * const r_ij_const = const_cast<double *>(r_ij);
387 
388  // compute distance squared
389  double const rij2 = r_ij_const[0] * r_ij_const[0]
390  + r_ij_const[1] * r_ij_const[1]
391  + r_ij_const[2] * r_ij_const[2];
392 
393  if (rij2 <= constCutoffsSq2D[iSpecies][jSpecies])
394  { // compute contribution to energy, force, etc.
395  double phi = 0.0;
396  double dphiByR = 0.0;
397  double d2phi = 0.0;
398  double dEidrByR = 0.0;
399  double d2Eidr2 = 0.0;
400  double const r2iv = 1.0 / rij2;
401  double const r6iv = r2iv * r2iv * r2iv;
402  // Compute pair potential and its derivatives
403  if (isComputeProcess_d2Edr2 == true)
404  { // Compute d2phi
405  d2phi
406  = r6iv
407  * (constSixTwentyFourEpsSig12_2D[iSpecies][jSpecies] * r6iv
408  - constOneSixtyEightEpsSig6_2D[iSpecies][jSpecies])
409  * r2iv;
410  if (jContrib == 1) { d2Eidr2 = d2phi; }
411  else
412  {
413  d2Eidr2 = 0.5 * d2phi;
414  }
415  }
416 
417  if ((isComputeProcess_dEdr == true) || (isComputeForces == true)
418  || (isComputeVirial == true)
419  || (isComputeParticleVirial == true))
420  { // Compute dphi
421  dphiByR
422  = r6iv
423  * (constTwentyFourEpsSig6_2D[iSpecies][jSpecies]
424  - constFortyEightEpsSig12_2D[iSpecies][jSpecies] * r6iv)
425  * r2iv;
426  if (jContrib == 1) { dEidrByR = dphiByR; }
427  else
428  {
429  dEidrByR = 0.5 * dphiByR;
430  }
431  }
432 
433  if ((isComputeEnergy == true) || (isComputeParticleEnergy == true))
434  { // Compute phi
435  if (isShift == true)
436  {
437  LENNARD_JONES_PHI(-constShifts2D[iSpecies][jSpecies]);
438  }
439  else
440  {
442  }
443  }
444 
445  // Contribution to energy
446  if (isComputeEnergy == true)
447  {
448  if (jContrib == 1) { *energy += phi; }
449  else
450  {
451  *energy += 0.5 * phi;
452  }
453  }
454 
455  // Contribution to particleEnergy
456  if (isComputeParticleEnergy == true)
457  {
458  double const halfPhi = 0.5 * phi;
459  particleEnergy[i] += halfPhi;
460  if (jContrib == 1) { particleEnergy[j] += halfPhi; }
461  }
462 
463  // Contribution to forces
464  if (isComputeForces == true)
465  {
466  for (int k = 0; k < DIMENSION; ++k)
467  {
468  double const contrib = dEidrByR * r_ij_const[k];
469  forces[i][k] += contrib;
470  forces[j][k] -= contrib;
471  }
472  }
473 
474  // Call process_dEdr
475  if ((isComputeProcess_dEdr == true) || (isComputeVirial == true)
476  || (isComputeParticleVirial == true))
477  {
478  double const rij = sqrt(rij2);
479  double const dEidr = dEidrByR * rij;
480 
481  if (isComputeProcess_dEdr == true)
482  {
483  ier = modelComputeArguments->ProcessDEDrTerm(
484  dEidr, rij, r_ij_const, i, j);
485  if (ier)
486  {
487  LOG_ERROR("process_dEdr");
488  return ier;
489  }
490  }
491 
492  if (isComputeVirial == true)
493  {
494  ProcessVirialTerm(dEidr, rij, r_ij_const, i, j, virial);
495  }
496 
497  if (isComputeParticleVirial == true)
498  {
499  ProcessParticleVirialTerm(
500  dEidr, rij, r_ij_const, i, j, particleVirial);
501  }
502  }
503 
504  // Call process_d2Edr2
505  if (isComputeProcess_d2Edr2 == true)
506  {
507  double const rij = sqrt(rij2);
508  double const R_pairs[2] = {rij, rij};
509  double const * const pRs = &R_pairs[0];
510  double const Rij_pairs[6] = {r_ij_const[0],
511  r_ij_const[1],
512  r_ij_const[2],
513  r_ij_const[0],
514  r_ij_const[1],
515  r_ij_const[2]};
516  double const * const pRijConsts = &Rij_pairs[0];
517  int const i_pairs[2] = {i, i};
518  int const j_pairs[2] = {j, j};
519  int const * const pis = &i_pairs[0];
520  int const * const pjs = &j_pairs[0];
521 
522  ier = modelComputeArguments->ProcessD2EDr2Term(
523  d2Eidr2, pRs, pRijConsts, pis, pjs);
524  if (ier)
525  {
526  LOG_ERROR("process_d2Edr2");
527  return ier;
528  }
529  }
530  } // if particleContributing
531  } // if i < j or j non contributing
532  } // if particles i and j interact
533  } // end of first neighbor loop
534  } // end of loop over contributing particles
535 
536  // everything is good
537  ier = false;
538  return ier;
539 }
540 
541 #endif // LENNARD_JONES_612_IMPLEMENTATION_HPP_
int ComputeArgumentsCreate(KIM::ModelComputeArgumentsCreate *const modelComputeArgumentsCreate) const
Provides the interface to a KIM API Model object for use by models within their MODEL_ROUTINE_NAME::R...
An Extensible Enumeration for the TemperatureUnit&#39;s supported by the KIM API.
An Extensible Enumeration for the TimeUnit&#39;s supported by the KIM API.
#define MAX_PARAMETER_FILES
ComputeArgumentName const coordinates
The standard coordinates argument.
#define LOG_ERROR(message)
Convenience macro for ERROR Log entries with compile-time optimization.
int() GetNeighborFunction(void const *const, int const, int *const, int const **const)
int ProcessDEDrTerm(double const de, double const r, double const *const dx, int const i, int const j) const
Call the Simulator&#39;s COMPUTE_CALLBACK_NAME::ProcessDEDrTerm routine.
int ProcessD2EDr2Term(double const de, double const *const r, double const *const dx, int const *const i, int const *const j) const
Call the Simulator&#39;s COMPUTE_CALLBACK_NAME::ProcessD2EDr2Term routine.
double VectorOfSizeDIM[DIMENSION]
void AllocateAndInitialize2DArray(double **&arrayPtr, int const extentZero, int const extentOne)
An Extensible Enumeration for the LengthUnit&#39;s supported by the KIM API.
Provides the interface to a KIM API Model object for use by models within their MODEL_ROUTINE_NAME::C...
ComputeArgumentName const particleContributing
The standard particleContributing argument.
Provides the interface to a KIM API Model object for use by models within their MODEL_ROUTINE_NAME::C...
LennardJones612Implementation(KIM::ModelDriverCreate *const modelDriverCreate, KIM::LengthUnit const requestedLengthUnit, KIM::EnergyUnit const requestedEnergyUnit, KIM::ChargeUnit const requestedChargeUnit, KIM::TemperatureUnit const requestedTemperatureUnit, KIM::TimeUnit const requestedTimeUnit, int *const ier)
void Deallocate2DArray(double **&arrayPtr)
Provides the interface to a KIM API ComputeArguments object for use by models within their MODEL_ROUT...
An Extensible Enumeration for the EnergyUnit&#39;s supported by the KIM API.
int Refresh(KIM::ModelRefresh *const modelRefresh)
Provides the interface to a KIM API ComputeArguments object for use by models within their MODEL_ROUT...
int ComputeArgumentsDestroy(KIM::ModelComputeArgumentsDestroy *const modelComputeArgumentsDestroy) const
ComputeArgumentName const particleSpeciesCodes
The standard particleSpeciesCodes argument.
Provides the interface to a KIM API ComputeArguments object for use by models within their MODEL_ROUT...
#define LENNARD_JONES_PHI(exshift)
An Extensible Enumeration for the ChargeUnit&#39;s supported by the KIM API.
int GetNeighborList(int const neighborListIndex, int const particleNumber, int *const numberOfNeighbors, int const **const neighborsOfParticle) const
Get the neighbor list for a particle of interest corresponding to a particular neighbor list cutoff d...
double VectorOfSizeSix[6]
int Compute(KIM::ModelCompute const *const modelCompute, KIM::ModelComputeArguments const *const modelComputeArguments)