kim-api  2.3.1-git+v2.3.0-git-2-g378406f9.GNU.GNU.
An Application Programming Interface (API) for the Knowledgebase of Interatomic Models (KIM).
LennardJones_Ar.cpp
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 //
9 // SPDX-License-Identifier: LGPL-2.1-or-later
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public License
22 // along with this library; if not, write to the Free Software Foundation,
23 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 
26 
27 #include "KIM_LogMacros.hpp"
28 #include "KIM_ModelHeaders.hpp"
29 #include <cstddef>
30 #include <math.h>
31 
32 #define DIMENSION 3
33 
34 
35 namespace
36 {
38 {
39  public:
40  //****************************************************************************
41  LennardJones_Ar(KIM::ModelCreate * const modelCreate,
42  KIM::LengthUnit const requestedLengthUnit,
43  KIM::EnergyUnit const requestedEnergyUnit,
44  KIM::ChargeUnit const requestedChargeUnit,
45  KIM::TemperatureUnit const requestedTemperatureUnit,
46  KIM::TimeUnit const requestedTimeUnit,
47  int * const error) :
48  epsilon_(0.0104),
49  sigma_(3.4000),
50  influenceDistance_(8.1500),
51  cutoff_(influenceDistance_),
52  cutoffSq_(cutoff_ * cutoff_),
53  modelWillNotRequestNeighborsOfNoncontributingParticles_(1)
54  {
55  *error = ConvertUnits(modelCreate,
56  requestedLengthUnit,
57  requestedEnergyUnit,
58  requestedChargeUnit,
59  requestedTemperatureUnit,
60  requestedTimeUnit);
61  if (*error) return;
62 
64 
65  modelCreate->SetInfluenceDistancePointer(&influenceDistance_);
66  modelCreate->SetNeighborListPointers(
67  1, &cutoff_, &modelWillNotRequestNeighborsOfNoncontributingParticles_);
68 
69  modelCreate->SetSpeciesCode(KIM::SPECIES_NAME::Ar, 0);
70 
71  // use function pointer declarations to verify prototypes
78 
79  *error = modelCreate->SetRoutinePointer(
82  true,
83  reinterpret_cast<KIM::Function *>(CACreate))
84  || modelCreate->SetRoutinePointer(
87  true,
88  reinterpret_cast<KIM::Function *>(compute))
89  || modelCreate->SetRoutinePointer(
92  true,
93  reinterpret_cast<KIM::Function *>(CADestroy))
94  || modelCreate->SetRoutinePointer(
97  true,
98  reinterpret_cast<KIM::Function *>(destroy));
99  if (*error) return;
100 
101  // everything is good
102  *error = false;
103  return;
104  };
105 
106  //****************************************************************************
108 
109  //****************************************************************************
110  // no need to make these "extern" since KIM will only access them
111  // via function pointers. "static" is required so that there is not
112  // an implicit this pointer added to the prototype by the C++ compiler
113  static int Destroy(KIM::ModelDestroy * const modelDestroy)
114  {
115  LennardJones_Ar * model;
116  modelDestroy->GetModelBufferPointer(reinterpret_cast<void **>(&model));
117 
118  if (model != NULL)
119  {
120  // delete object itself
121  delete model;
122  }
123 
124  // everything is good
125  return false;
126  }
127 
128  //****************************************************************************
129 #undef KIM_LOGGER_OBJECT_NAME
130 #define KIM_LOGGER_OBJECT_NAME modelCompute
131  //
132  static int
133  Compute(KIM::ModelCompute const * const modelCompute,
134  KIM::ModelComputeArguments const * const modelComputeArguments)
135  {
136  int const * numberOfParticlesPointer;
137  int const * particleSpeciesCodes;
138  int const * particleContributing;
139  double const * coordinates;
140  double * partialEnergy;
141  double * partialForces;
142 
143  LennardJones_Ar * lj;
144  modelCompute->GetModelBufferPointer(reinterpret_cast<void **>(&lj));
145  double const epsilon = lj->epsilon_;
146  double const sigma = lj->sigma_;
147  double const cutoffSq = lj->cutoffSq_;
148 
149  int error = modelComputeArguments->GetArgumentPointer(
151  &numberOfParticlesPointer)
152  || modelComputeArguments->GetArgumentPointer(
154  &particleSpeciesCodes)
155  || modelComputeArguments->GetArgumentPointer(
157  &particleContributing)
158  || modelComputeArguments->GetArgumentPointer(
160  (double const **) &coordinates)
161  || modelComputeArguments->GetArgumentPointer(
163  || modelComputeArguments->GetArgumentPointer(
165  (double const **) &partialForces);
166  if (error)
167  {
168  LOG_ERROR("Unable to get argument pointers");
169  return error;
170  }
171 
172  int const numberOfParticles = *numberOfParticlesPointer;
173 
174  // initialize energy and forces
175  *partialEnergy = 0.0;
176  int const extent = numberOfParticles * DIMENSION;
177  for (int i = 0; i < extent; ++i) { partialForces[i] = 0.0; }
178 
179  int jContributing;
180  int i, j, jj, numberOfNeighbors;
181  int const * neighbors;
182  double phi;
183  double xcoord, ycoord, zcoord;
184  double xrij, yrij, zrij;
185  double rij2;
186  double r2inv, r6inv, dphiByR, dEidrByR;
187  double xdf, ydf, zdf;
188  double const fortyEight = 48.0 * epsilon * pow(sigma, 12.0);
189  double const twentyFour = 24.0 * epsilon * pow(sigma, 6.0);
190  double const four12 = 4.0 * epsilon * pow(sigma, 12.0);
191  double const four6 = 4.0 * epsilon * pow(sigma, 6.0);
192  for (i = 0; i < numberOfParticles; ++i)
193  {
194  if (particleContributing[i])
195  {
196  xcoord = coordinates[i * DIMENSION + 0];
197  ycoord = coordinates[i * DIMENSION + 1];
198  zcoord = coordinates[i * DIMENSION + 2];
199 
200  modelComputeArguments->GetNeighborList(
201  0, i, &numberOfNeighbors, &neighbors);
202 
203  for (jj = 0; jj < numberOfNeighbors; ++jj)
204  {
205  j = neighbors[jj];
206  jContributing = particleContributing[j];
207 
208  if (!(jContributing && (j < i)))
209  {
210  xrij = coordinates[j * DIMENSION + 0] - xcoord;
211  yrij = coordinates[j * DIMENSION + 1] - ycoord;
212  zrij = coordinates[j * DIMENSION + 2] - zcoord;
213 
214  rij2 = xrij * xrij + yrij * yrij + zrij * zrij;
215 
216  if (rij2 < cutoffSq)
217  {
218  r2inv = 1.0 / rij2;
219  r6inv = r2inv * r2inv * r2inv;
220  phi = 0.5 * r6inv * (four12 * r6inv - four6);
221  dphiByR = r6inv * (twentyFour - fortyEight * r6inv) * r2inv;
222 
223  *partialEnergy += phi;
224  if (jContributing)
225  {
226  *partialEnergy += phi;
227  dEidrByR = dphiByR;
228  }
229  else
230  {
231  dEidrByR = 0.5 * dphiByR;
232  }
233 
234  xdf = dEidrByR * xrij;
235  ydf = dEidrByR * yrij;
236  zdf = dEidrByR * zrij;
237  partialForces[i * DIMENSION + 0] += xdf;
238  partialForces[i * DIMENSION + 1] += ydf;
239  partialForces[i * DIMENSION + 2] += zdf;
240  partialForces[j * DIMENSION + 0] -= xdf;
241  partialForces[j * DIMENSION + 1] -= ydf;
242  partialForces[j * DIMENSION + 2] -= zdf;
243  } // if (rij2 < cutoffSq_)
244  } // if (i < j)
245  } // for jj
246  } // if (particleContributing[i])
247  } // for i
248 
249  // everything is good
250  return false;
251  };
252 
253  //****************************************************************************
255  KIM::ModelCompute const * const /* modelCompute */,
256  KIM::ModelComputeArgumentsCreate * const modelComputeArgumentsCreate)
257  {
258  // register arguments
259  int error = modelComputeArgumentsCreate->SetArgumentSupportStatus(
262  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
265 
266  // register callbacks
267  //
268  // none
269 
270  return error;
271  }
272 
273  //****************************************************************************
274  static int
275  ComputeArgumentsDestroy(KIM::ModelCompute const * const /* modelCompute */,
277  /* modelComputeArgumentsDestroy */)
278  {
279  // nothing further to do
280 
281  return false;
282  }
283 
284  private:
285  //****************************************************************************
286  // Member variables
287  double epsilon_;
288  double sigma_;
289  double influenceDistance_;
290  double cutoff_;
291  double cutoffSq_;
292  int const modelWillNotRequestNeighborsOfNoncontributingParticles_;
293 
294  //****************************************************************************
295 #undef KIM_LOGGER_OBJECT_NAME
296 #define KIM_LOGGER_OBJECT_NAME modelCreate
297  //
298  int ConvertUnits(KIM::ModelCreate * const modelCreate,
299  KIM::LengthUnit const requestedLengthUnit,
300  KIM::EnergyUnit const requestedEnergyUnit,
301  KIM::ChargeUnit const requestedChargeUnit,
302  KIM::TemperatureUnit const requestedTemperatureUnit,
303  KIM::TimeUnit const requestedTimeUnit)
304  {
305  int ier;
306 
307  // define default base units
313 
314  // changing units of cutoffs and sigmas
315  double convertLength = 1.0;
316  ier = KIM::ModelCreate::ConvertUnit(fromLength,
317  fromEnergy,
318  fromCharge,
319  fromTemperature,
320  fromTime,
321  requestedLengthUnit,
322  requestedEnergyUnit,
323  requestedChargeUnit,
324  requestedTemperatureUnit,
325  requestedTimeUnit,
326  1.0,
327  0.0,
328  0.0,
329  0.0,
330  0.0,
331  &convertLength);
332  if (ier)
333  {
334  LOG_ERROR("Unable to convert length unit");
335  return ier;
336  }
337  influenceDistance_ *= convertLength; // convert to active units
338  cutoff_ = influenceDistance_;
339  cutoffSq_ = cutoff_ * cutoff_;
340  sigma_ *= convertLength; // convert to active units
341 
342  // changing units of epsilons
343  double convertEnergy = 1.0;
344  ier = KIM::ModelCreate::ConvertUnit(fromLength,
345  fromEnergy,
346  fromCharge,
347  fromTemperature,
348  fromTime,
349  requestedLengthUnit,
350  requestedEnergyUnit,
351  requestedChargeUnit,
352  requestedTemperatureUnit,
353  requestedTimeUnit,
354  0.0,
355  1.0,
356  0.0,
357  0.0,
358  0.0,
359  &convertEnergy);
360  if (ier)
361  {
362  LOG_ERROR("Unable to convert energy unit");
363  return ier;
364  }
365  epsilon_ *= convertEnergy; // convert to active units
366 
367  // register units
368  ier = modelCreate->SetUnits(requestedLengthUnit,
369  requestedEnergyUnit,
373  if (ier)
374  {
375  LOG_ERROR("Unable to set units to requested values");
376  return ier;
377  }
378 
379  // everything is good
380  ier = false;
381  return ier;
382  }
383 };
384 
385 } // namespace
386 
387 extern "C" {
388 //******************************************************************************
389 int model_create(KIM::ModelCreate * const modelCreate,
390  KIM::LengthUnit const requestedLengthUnit,
391  KIM::EnergyUnit const requestedEnergyUnit,
392  KIM::ChargeUnit const requestedChargeUnit,
393  KIM::TemperatureUnit const requestedTemperatureUnit,
394  KIM::TimeUnit const requestedTimeUnit)
395 {
396  int error;
397 
398  LennardJones_Ar * const model = new LennardJones_Ar(modelCreate,
399  requestedLengthUnit,
400  requestedEnergyUnit,
401  requestedChargeUnit,
402  requestedTemperatureUnit,
403  requestedTimeUnit,
404  &error);
405  if (error)
406  {
407  // constructor already reported the error
408  delete model;
409  return error;
410  }
411 
412  // register pointer to LennardJones_Ar object in moedelCreate object
413  modelCreate->SetModelBufferPointer(reinterpret_cast<void *>(model));
414 
415  // everything is good
416  return false;
417 }
418 } // extern "C"
int ModelComputeArgumentsDestroyFunction(ModelCompute const *const modelCompute, ModelComputeArgumentsDestroy *const modelComputeArgumentsDestroy)
Prototype for MODEL_ROUTINE_NAME::ComputeArgumentsDestroy routine.
TemperatureUnit const unused
Indicates that a TemperatureUnit is not used.
An Extensible Enumeration for the TemperatureUnit&#39;s supported by the KIM API.
SpeciesName const Ar
The standard Argon species.
An Extensible Enumeration for the TimeUnit&#39;s supported by the KIM API.
int ModelDestroyFunction(ModelDestroy *const modelDestroy)
Prototype for MODEL_ROUTINE_NAME::Destroy routine.
int SetSpeciesCode(SpeciesName const speciesName, int const code)
Set integer code for supported SpeciesName.
int SetModelNumbering(Numbering const numbering)
Set the Model&#39;s particle Numbering.
recursive subroutine, public destroy(model_destroy_handle, ierr)
ComputeArgumentName const coordinates
The standard coordinates argument.
#define LOG_ERROR(message)
Convenience macro for ERROR Log entries with compile-time optimization.
ModelRoutineName const Destroy
The standard Destroy routine.
int SetUnits(LengthUnit const lengthUnit, EnergyUnit const energyUnit, ChargeUnit const chargeUnit, TemperatureUnit const temperatureUnit, TimeUnit const timeUnit)
Set the Model&#39;s base unit values.
ChargeUnit const unused
Indicates that a ChargeUnit is not used.
void GetModelBufferPointer(void **const ptr) const
Get the Model&#39;s buffer pointer within the Model object.
void SetInfluenceDistancePointer(double const *const influenceDistance)
Set the Model&#39;s influence distance data pointer.
int SetArgumentSupportStatus(ComputeArgumentName const computeArgumentName, SupportStatus const supportStatus)
Set the SupportStatus of a ComputeArgumentName.
int ModelComputeFunction(ModelCompute const *const modelCompute, ModelComputeArguments const *const modelComputeArgumentsCreate)
Prototype for MODEL_ROUTINE_NAME::Compute routine.
void SetModelBufferPointer(void *const ptr)
Set the Model&#39;s buffer pointer within the Model object.
SupportStatus const required
The standard required status.
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::D...
int GetArgumentPointer(ComputeArgumentName const computeArgumentName, int const **const ptr) const
Get the data pointer for a ComputeArgumentName.
int ModelComputeArgumentsCreateFunction(ModelCompute const *const modelCompute, ModelComputeArgumentsCreate *const modelComputeArgumentsCreate)
Prototype for MODEL_ROUTINE_NAME::ComputeArgumentsCreate routine.
ComputeArgumentName const particleContributing
The standard particleContributing argument.
ComputeArgumentName const partialEnergy
The standard partialEnergy argument.
Provides the interface to a KIM API Model object for use by models within their MODEL_ROUTINE_NAME::C...
ModelRoutineName const ComputeArgumentsCreate
The standard ComputeArgumentsCreate routine.
ModelRoutineName const ComputeArgumentsDestroy
The standard ComputeArgumentsDestroy routine.
Provides the interface to a KIM API ComputeArguments object for use by models within their MODEL_ROUT...
void SetNeighborListPointers(int const numberOfNeighborLists, double const *const cutoffs, int const *const modelWillNotRequestNeighborsOfNoncontributingParticles)
Set the Model&#39;s neighbor list data pointers.
#define DIMENSION
An Extensible Enumeration for the EnergyUnit&#39;s supported by the KIM API.
LanguageName const cpp
The standard cpp language.
ModelRoutineName const Compute
The standard Compute routine.
LengthUnit const A
The standard angstrom unit of length.
Provides the interface to a KIM API ComputeArguments object for use by models within their MODEL_ROUT...
ComputeArgumentName const partialForces
The standard partialForces argument.
void GetModelBufferPointer(void **const ptr) const
Get the Model&#39;s buffer pointer within the Model object.
EnergyUnit const eV
The standard electronvolt unit of energy.
ComputeArgumentName const particleSpeciesCodes
The standard particleSpeciesCodes argument.
Provides the interface to a KIM API ComputeArguments object for use by models within their MODEL_ROUT...
An Extensible Enumeration for the ChargeUnit&#39;s supported by the KIM API.
ComputeArgumentName const numberOfParticles
The standard numberOfParticles argument.
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 model_create(KIM::ModelCreate *const modelCreate, KIM::LengthUnit const requestedLengthUnit, KIM::EnergyUnit const requestedEnergyUnit, KIM::ChargeUnit const requestedChargeUnit, KIM::TemperatureUnit const requestedTemperatureUnit, KIM::TimeUnit const requestedTimeUnit)
LennardJones_Ar(KIM::ModelCreate *const modelCreate, KIM::LengthUnit const requestedLengthUnit, KIM::EnergyUnit const requestedEnergyUnit, KIM::ChargeUnit const requestedChargeUnit, KIM::TemperatureUnit const requestedTemperatureUnit, KIM::TimeUnit const requestedTimeUnit, int *const error)
Provides the interface to a KIM API Model object for use by models within their MODEL_ROUTINE_NAME::C...
static int Destroy(KIM::ModelDestroy *const modelDestroy)
Numbering const zeroBased
The standard zeroBased numbering.
TimeUnit const unused
Indicates that a TimeUnit is not used.
static int ComputeArgumentsDestroy(KIM::ModelCompute const *const, KIM::ModelComputeArgumentsDestroy *const)
int SetRoutinePointer(ModelRoutineName const modelRoutineName, LanguageName const languageName, int const required, Function *const fptr)
Set the function pointer for the ModelRoutineName of interest.
LogVerbosity const error
The standard error verbosity.
static int Compute(KIM::ModelCompute const *const modelCompute, KIM::ModelComputeArguments const *const modelComputeArguments)
static int ConvertUnit(LengthUnit const fromLengthUnit, EnergyUnit const fromEnergyUnit, ChargeUnit const fromChargeUnit, TemperatureUnit const fromTemperatureUnit, TimeUnit const fromTimeUnit, LengthUnit const toLengthUnit, EnergyUnit const toEnergyUnit, ChargeUnit const toChargeUnit, TemperatureUnit const toTemperatureUnit, TimeUnit const toTimeUnit, double const lengthExponent, double const energyExponent, double const chargeExponent, double const temperatureExponent, double const timeExponent, double *const conversionFactor)
Get the multiplicative factor to convert between a derived unit represented in two different sets of ...
static int ComputeArgumentsCreate(KIM::ModelCompute const *const, KIM::ModelComputeArgumentsCreate *const modelComputeArgumentsCreate)