kim-api  2.2.1+v2.2.1.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 // 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) 2018--2020, Regents of the University of Minnesota.
23 // All rights reserved.
24 //
25 // Contributors:
26 // Ryan S. Elliott
27 //
28 
29 
30 #include "KIM_LogMacros.hpp"
31 #include "KIM_ModelHeaders.hpp"
32 #include <cstddef>
33 #include <math.h>
34 
35 #define DIMENSION 3
36 
37 
38 namespace
39 {
41 {
42  public:
43  //****************************************************************************
44  LennardJones_Ar(KIM::ModelCreate * const modelCreate,
45  KIM::LengthUnit const requestedLengthUnit,
46  KIM::EnergyUnit const requestedEnergyUnit,
47  KIM::ChargeUnit const requestedChargeUnit,
48  KIM::TemperatureUnit const requestedTemperatureUnit,
49  KIM::TimeUnit const requestedTimeUnit,
50  int * const error) :
51  epsilon_(0.0104),
52  sigma_(3.4000),
53  influenceDistance_(8.1500),
54  cutoff_(influenceDistance_),
55  cutoffSq_(cutoff_ * cutoff_),
56  modelWillNotRequestNeighborsOfNoncontributingParticles_(1)
57  {
58  *error = ConvertUnits(modelCreate,
59  requestedLengthUnit,
60  requestedEnergyUnit,
61  requestedChargeUnit,
62  requestedTemperatureUnit,
63  requestedTimeUnit);
64  if (*error) return;
65 
67 
68  modelCreate->SetInfluenceDistancePointer(&influenceDistance_);
69  modelCreate->SetNeighborListPointers(
70  1, &cutoff_, &modelWillNotRequestNeighborsOfNoncontributingParticles_);
71 
72  modelCreate->SetSpeciesCode(KIM::SPECIES_NAME::Ar, 0);
73 
74  // use function pointer declarations to verify prototypes
81 
82  *error = modelCreate->SetRoutinePointer(
85  true,
86  reinterpret_cast<KIM::Function *>(CACreate))
87  || modelCreate->SetRoutinePointer(
90  true,
91  reinterpret_cast<KIM::Function *>(compute))
92  || modelCreate->SetRoutinePointer(
95  true,
96  reinterpret_cast<KIM::Function *>(CADestroy))
97  || modelCreate->SetRoutinePointer(
100  true,
101  reinterpret_cast<KIM::Function *>(destroy));
102  if (*error) return;
103 
104  // everything is good
105  *error = false;
106  return;
107  };
108 
109  //****************************************************************************
111 
112  //****************************************************************************
113  // no need to make these "extern" since KIM will only access them
114  // via function pointers. "static" is required so that there is not
115  // an implicit this pointer added to the prototype by the C++ compiler
116  static int Destroy(KIM::ModelDestroy * const modelDestroy)
117  {
118  LennardJones_Ar * model;
119  modelDestroy->GetModelBufferPointer(reinterpret_cast<void **>(&model));
120 
121  if (model != NULL)
122  {
123  // delete object itself
124  delete model;
125  }
126 
127  // everything is good
128  return false;
129  }
130 
131  //****************************************************************************
132 #undef KIM_LOGGER_OBJECT_NAME
133 #define KIM_LOGGER_OBJECT_NAME modelCompute
134  //
135  static int
136  Compute(KIM::ModelCompute const * const modelCompute,
137  KIM::ModelComputeArguments const * const modelComputeArguments)
138  {
139  int const * numberOfParticlesPointer;
140  int const * particleSpeciesCodes;
141  int const * particleContributing;
142  double const * coordinates;
143  double * partialEnergy;
144  double * partialForces;
145 
146  LennardJones_Ar * lj;
147  modelCompute->GetModelBufferPointer(reinterpret_cast<void **>(&lj));
148  double const epsilon = lj->epsilon_;
149  double const sigma = lj->sigma_;
150  double const cutoffSq = lj->cutoffSq_;
151 
152  int error = modelComputeArguments->GetArgumentPointer(
154  &numberOfParticlesPointer)
155  || modelComputeArguments->GetArgumentPointer(
157  &particleSpeciesCodes)
158  || modelComputeArguments->GetArgumentPointer(
160  &particleContributing)
161  || modelComputeArguments->GetArgumentPointer(
163  (double const **) &coordinates)
164  || modelComputeArguments->GetArgumentPointer(
166  || modelComputeArguments->GetArgumentPointer(
168  (double const **) &partialForces);
169  if (error)
170  {
171  LOG_ERROR("Unable to get argument pointers");
172  return error;
173  }
174 
175  int const numberOfParticles = *numberOfParticlesPointer;
176 
177  // initialize energy and forces
178  *partialEnergy = 0.0;
179  int const extent = numberOfParticles * DIMENSION;
180  for (int i = 0; i < extent; ++i) { partialForces[i] = 0.0; }
181 
182  int jContributing;
183  int i, j, jj, numberOfNeighbors;
184  int const * neighbors;
185  double phi;
186  double xcoord, ycoord, zcoord;
187  double xrij, yrij, zrij;
188  double rij2;
189  double r2inv, r6inv, dphiByR, dEidrByR;
190  double xdf, ydf, zdf;
191  double const fortyEight = 48.0 * epsilon * pow(sigma, 12.0);
192  double const twentyFour = 24.0 * epsilon * pow(sigma, 6.0);
193  double const four12 = 4.0 * epsilon * pow(sigma, 12.0);
194  double const four6 = 4.0 * epsilon * pow(sigma, 6.0);
195  for (i = 0; i < numberOfParticles; ++i)
196  {
197  if (particleContributing[i])
198  {
199  xcoord = coordinates[i * DIMENSION + 0];
200  ycoord = coordinates[i * DIMENSION + 1];
201  zcoord = coordinates[i * DIMENSION + 2];
202 
203  modelComputeArguments->GetNeighborList(
204  0, i, &numberOfNeighbors, &neighbors);
205 
206  for (jj = 0; jj < numberOfNeighbors; ++jj)
207  {
208  j = neighbors[jj];
209  jContributing = particleContributing[j];
210 
211  if (!(jContributing && (j < i)))
212  {
213  xrij = coordinates[j * DIMENSION + 0] - xcoord;
214  yrij = coordinates[j * DIMENSION + 1] - ycoord;
215  zrij = coordinates[j * DIMENSION + 2] - zcoord;
216 
217  rij2 = xrij * xrij + yrij * yrij + zrij * zrij;
218 
219  if (rij2 < cutoffSq)
220  {
221  r2inv = 1.0 / rij2;
222  r6inv = r2inv * r2inv * r2inv;
223  phi = 0.5 * r6inv * (four12 * r6inv - four6);
224  dphiByR = r6inv * (twentyFour - fortyEight * r6inv) * r2inv;
225 
226  *partialEnergy += phi;
227  if (jContributing)
228  {
229  *partialEnergy += phi;
230  dEidrByR = dphiByR;
231  }
232  else
233  {
234  dEidrByR = 0.5 * dphiByR;
235  }
236 
237  xdf = dEidrByR * xrij;
238  ydf = dEidrByR * yrij;
239  zdf = dEidrByR * zrij;
240  partialForces[i * DIMENSION + 0] += xdf;
241  partialForces[i * DIMENSION + 1] += ydf;
242  partialForces[i * DIMENSION + 2] += zdf;
243  partialForces[j * DIMENSION + 0] -= xdf;
244  partialForces[j * DIMENSION + 1] -= ydf;
245  partialForces[j * DIMENSION + 2] -= zdf;
246  } // if (rij2 < cutoffSq_)
247  } // if (i < j)
248  } // for jj
249  } // if (particleContributing[i])
250  } // for i
251 
252  // everything is good
253  return false;
254  };
255 
256  //****************************************************************************
258  KIM::ModelCompute const * const /* modelCompute */,
259  KIM::ModelComputeArgumentsCreate * const modelComputeArgumentsCreate)
260  {
261  // register arguments
262  int error = modelComputeArgumentsCreate->SetArgumentSupportStatus(
265  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
268 
269  // register callbacks
270  //
271  // none
272 
273  return error;
274  }
275 
276  //****************************************************************************
277  static int
278  ComputeArgumentsDestroy(KIM::ModelCompute const * const /* modelCompute */,
280  /* modelComputeArgumentsDestroy */)
281  {
282  // nothing further to do
283 
284  return false;
285  }
286 
287  private:
288  //****************************************************************************
289  // Member variables
290  double epsilon_;
291  double sigma_;
292  double influenceDistance_;
293  double cutoff_;
294  double cutoffSq_;
295  int const modelWillNotRequestNeighborsOfNoncontributingParticles_;
296 
297  //****************************************************************************
298 #undef KIM_LOGGER_OBJECT_NAME
299 #define KIM_LOGGER_OBJECT_NAME modelCreate
300  //
301  int ConvertUnits(KIM::ModelCreate * const modelCreate,
302  KIM::LengthUnit const requestedLengthUnit,
303  KIM::EnergyUnit const requestedEnergyUnit,
304  KIM::ChargeUnit const requestedChargeUnit,
305  KIM::TemperatureUnit const requestedTemperatureUnit,
306  KIM::TimeUnit const requestedTimeUnit)
307  {
308  int ier;
309 
310  // define default base units
316 
317  // changing units of cutoffs and sigmas
318  double convertLength = 1.0;
319  ier = KIM::ModelCreate::ConvertUnit(fromLength,
320  fromEnergy,
321  fromCharge,
322  fromTemperature,
323  fromTime,
324  requestedLengthUnit,
325  requestedEnergyUnit,
326  requestedChargeUnit,
327  requestedTemperatureUnit,
328  requestedTimeUnit,
329  1.0,
330  0.0,
331  0.0,
332  0.0,
333  0.0,
334  &convertLength);
335  if (ier)
336  {
337  LOG_ERROR("Unable to convert length unit");
338  return ier;
339  }
340  influenceDistance_ *= convertLength; // convert to active units
341  cutoff_ = influenceDistance_;
342  cutoffSq_ = cutoff_ * cutoff_;
343  sigma_ *= convertLength; // convert to active units
344 
345  // changing units of epsilons
346  double convertEnergy = 1.0;
347  ier = KIM::ModelCreate::ConvertUnit(fromLength,
348  fromEnergy,
349  fromCharge,
350  fromTemperature,
351  fromTime,
352  requestedLengthUnit,
353  requestedEnergyUnit,
354  requestedChargeUnit,
355  requestedTemperatureUnit,
356  requestedTimeUnit,
357  0.0,
358  1.0,
359  0.0,
360  0.0,
361  0.0,
362  &convertEnergy);
363  if (ier)
364  {
365  LOG_ERROR("Unable to convert energy unit");
366  return ier;
367  }
368  epsilon_ *= convertEnergy; // convert to active units
369 
370  // register units
371  ier = modelCreate->SetUnits(requestedLengthUnit,
372  requestedEnergyUnit,
376  if (ier)
377  {
378  LOG_ERROR("Unable to set units to requested values");
379  return ier;
380  }
381 
382  // everything is good
383  ier = false;
384  return ier;
385  }
386 };
387 
388 } // namespace
389 
390 extern "C" {
391 //******************************************************************************
392 int model_create(KIM::ModelCreate * const modelCreate,
393  KIM::LengthUnit const requestedLengthUnit,
394  KIM::EnergyUnit const requestedEnergyUnit,
395  KIM::ChargeUnit const requestedChargeUnit,
396  KIM::TemperatureUnit const requestedTemperatureUnit,
397  KIM::TimeUnit const requestedTimeUnit)
398 {
399  int error;
400 
401  LennardJones_Ar * const model = new LennardJones_Ar(modelCreate,
402  requestedLengthUnit,
403  requestedEnergyUnit,
404  requestedChargeUnit,
405  requestedTemperatureUnit,
406  requestedTimeUnit,
407  &error);
408  if (error)
409  {
410  // constructor already reported the error
411  delete model;
412  return error;
413  }
414 
415  // register pointer to LennardJones_Ar object in moedelCreate object
416  modelCreate->SetModelBufferPointer(reinterpret_cast<void *>(model));
417 
418  // everything is good
419  return false;
420 }
421 } // 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)