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