kim-api  2.2.1+v2.2.1.GNU.GNU.
An Application Programming Interface (API) for the Knowledgebase of Interatomic Models (KIM).
LennardJones612Implementation.cpp
Go to the documentation of this file.
1 // CDDL HEADER START
2 //
3 // The contents of this file are subject to the terms of the Common Development
4 // and Distribution License Version 1.0 (the "License").
5 //
6 // You can obtain a copy of the license at
7 // http://www.opensource.org/licenses/CDDL-1.0. See the License for the
8 // specific language governing permissions and limitations under the License.
9 //
10 // When distributing Covered Code, include this CDDL HEADER in each file and
11 // include the License file in a prominent location with the name LICENSE.CDDL.
12 // If applicable, add the following below this CDDL HEADER, with the fields
13 // enclosed by brackets "[]" replaced with your own identifying information:
14 //
15 // Portions Copyright (c) [yyyy] [name of copyright owner]. All rights reserved.
16 //
17 // CDDL HEADER END
18 //
19 
20 //
21 // Copyright (c) 2013--2015, Regents of the University of Minnesota.
22 // All rights reserved.
23 //
24 // Contributors:
25 // Ryan S. Elliott
26 // Stephen M. Whalen
27 // Andrew Akerson
28 //
29 
30 
31 #include <cmath>
32 #include <cstring>
33 #include <iostream> // IWYU pragma: keep // BUG WORK-AROUND
34 #include <map>
35 #include <sstream>
36 #include <string>
37 
39 #include "LennardJones612.hpp"
41 
42 #define MAXLINE 1024
43 #define IGNORE_RESULT(fn) \
44  if (fn) {}
45 
46 
47 //==============================================================================
48 //
49 // Implementation of LennardJones612Implementation public member functions
50 //
51 //==============================================================================
52 
53 //******************************************************************************
54 #undef KIM_LOGGER_OBJECT_NAME
55 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
56 //
58  KIM::ModelDriverCreate * const modelDriverCreate,
59  KIM::LengthUnit const requestedLengthUnit,
60  KIM::EnergyUnit const requestedEnergyUnit,
61  KIM::ChargeUnit const requestedChargeUnit,
62  KIM::TemperatureUnit const requestedTemperatureUnit,
63  KIM::TimeUnit const requestedTimeUnit,
64  int * const ier) :
65  numberModelSpecies_(0),
66  numberUniqueSpeciesPairs_(0),
67  shift_(0),
68  cutoffs_(NULL),
69  epsilons_(NULL),
70  sigmas_(NULL),
71  influenceDistance_(0.0),
72  cutoffsSq2D_(NULL),
73  modelWillNotRequestNeighborsOfNoncontributingParticles_(1),
74  fourEpsilonSigma6_2D_(NULL),
75  fourEpsilonSigma12_2D_(NULL),
76  twentyFourEpsilonSigma6_2D_(NULL),
77  fortyEightEpsilonSigma12_2D_(NULL),
78  oneSixtyEightEpsilonSigma6_2D_(NULL),
79  sixTwentyFourEpsilonSigma12_2D_(NULL),
80  shifts2D_(NULL),
81  cachedNumberOfParticles_(0)
82 {
83  FILE * parameterFilePointers[MAX_PARAMETER_FILES];
84  int numberParameterFiles;
85  modelDriverCreate->GetNumberOfParameterFiles(&numberParameterFiles);
86  *ier = OpenParameterFiles(
87  modelDriverCreate, numberParameterFiles, parameterFilePointers);
88  if (*ier) return;
89 
90  *ier = ProcessParameterFiles(
91  modelDriverCreate, numberParameterFiles, parameterFilePointers);
92  CloseParameterFiles(numberParameterFiles, parameterFilePointers);
93  if (*ier) return;
94 
95  *ier = ConvertUnits(modelDriverCreate,
96  requestedLengthUnit,
97  requestedEnergyUnit,
98  requestedChargeUnit,
99  requestedTemperatureUnit,
100  requestedTimeUnit);
101  if (*ier) return;
102 
103  *ier = SetRefreshMutableValues(modelDriverCreate);
104  if (*ier) return;
105 
106  *ier = RegisterKIMModelSettings(modelDriverCreate);
107  if (*ier) return;
108 
109  *ier = RegisterKIMParameters(modelDriverCreate);
110  if (*ier) return;
111 
112  *ier = RegisterKIMFunctions(modelDriverCreate);
113  if (*ier) return;
114 
115  // everything is good
116  *ier = false;
117  return;
118 }
119 
120 //******************************************************************************
122 { // note: it is ok to delete a null pointer and we have ensured that
123  // everything is initialized to null
124 
125  delete[] cutoffs_;
126  Deallocate2DArray(cutoffsSq2D_);
127  delete[] epsilons_;
128  delete[] sigmas_;
129  Deallocate2DArray(fourEpsilonSigma6_2D_);
130  Deallocate2DArray(fourEpsilonSigma12_2D_);
131  Deallocate2DArray(twentyFourEpsilonSigma6_2D_);
132  Deallocate2DArray(fortyEightEpsilonSigma12_2D_);
133  Deallocate2DArray(oneSixtyEightEpsilonSigma6_2D_);
134  Deallocate2DArray(sixTwentyFourEpsilonSigma12_2D_);
135  Deallocate2DArray(shifts2D_);
136 }
137 
138 //******************************************************************************
139 #undef KIM_LOGGER_OBJECT_NAME
140 #define KIM_LOGGER_OBJECT_NAME modelRefresh
141 //
143  KIM::ModelRefresh * const modelRefresh)
144 {
145  int ier;
146 
147  ier = SetRefreshMutableValues(modelRefresh);
148  if (ier) return ier;
149 
150  // nothing else to do for this case
151 
152  // everything is good
153  ier = false;
154  return ier;
155 }
156 
157 //******************************************************************************
159  KIM::ModelCompute const * const modelCompute,
160  KIM::ModelComputeArguments const * const modelComputeArguments)
161 {
162  int ier;
163 
164  // KIM API Model Input compute flags
165  bool isComputeProcess_dEdr = false;
166  bool isComputeProcess_d2Edr2 = false;
167  //
168  // KIM API Model Output compute flags
169  bool isComputeEnergy = false;
170  bool isComputeForces = false;
171  bool isComputeParticleEnergy = false;
172  bool isComputeVirial = false;
173  bool isComputeParticleVirial = false;
174  //
175  // KIM API Model Input
176  int const * particleSpeciesCodes = NULL;
177  int const * particleContributing = NULL;
178  VectorOfSizeDIM const * coordinates = NULL;
179  //
180  // KIM API Model Output
181  double * energy = NULL;
182  double * particleEnergy = NULL;
183  VectorOfSizeDIM * forces = NULL;
184  VectorOfSizeSix * virial = NULL;
185  VectorOfSizeSix * particleVirial = NULL;
186  ier = SetComputeMutableValues(modelComputeArguments,
187  isComputeProcess_dEdr,
188  isComputeProcess_d2Edr2,
189  isComputeEnergy,
190  isComputeForces,
191  isComputeParticleEnergy,
192  isComputeVirial,
193  isComputeParticleVirial,
194  particleSpeciesCodes,
195  particleContributing,
196  coordinates,
197  energy,
198  particleEnergy,
199  forces,
200  virial,
201  particleVirial);
202  if (ier) return ier;
203 
204  // Skip this check for efficiency
205  //
206  // ier = CheckParticleSpecies(modelComputeArguments, particleSpeciesCodes);
207  // if (ier) return ier;
208 
209  bool const isShift = (1 == shift_);
210 
212  return ier;
213 }
214 
215 //******************************************************************************
217  KIM::ModelComputeArgumentsCreate * const modelComputeArgumentsCreate) const
218 {
219  int ier;
220 
221  ier = RegisterKIMComputeArgumentsSettings(modelComputeArgumentsCreate);
222  if (ier) return ier;
223 
224  // nothing else to do for this case
225 
226  // everything is good
227  ier = false;
228  return ier;
229 }
230 
231 //******************************************************************************
234  /* modelComputeArgumentsDestroy */) const
235 {
236  int ier;
237 
238  // nothing else to do for this case
239 
240  // everything is good
241  ier = false;
242  return ier;
243 }
244 
245 //==============================================================================
246 //
247 // Implementation of LennardJones612Implementation private member functions
248 //
249 //==============================================================================
250 
251 //******************************************************************************
252 void LennardJones612Implementation::AllocatePrivateParameterMemory()
253 {
254  // nothing to do for this case
255 }
256 
257 //******************************************************************************
258 void LennardJones612Implementation::AllocateParameterMemory()
259 { // allocate memory for data
260  cutoffs_ = new double[numberUniqueSpeciesPairs_];
262  cutoffsSq2D_, numberModelSpecies_, numberModelSpecies_);
263 
264  epsilons_ = new double[numberUniqueSpeciesPairs_];
265  sigmas_ = new double[numberUniqueSpeciesPairs_];
267  fourEpsilonSigma6_2D_, numberModelSpecies_, numberModelSpecies_);
269  fourEpsilonSigma12_2D_, numberModelSpecies_, numberModelSpecies_);
271  twentyFourEpsilonSigma6_2D_, numberModelSpecies_, numberModelSpecies_);
273  fortyEightEpsilonSigma12_2D_, numberModelSpecies_, numberModelSpecies_);
275  oneSixtyEightEpsilonSigma6_2D_, numberModelSpecies_, numberModelSpecies_);
276  AllocateAndInitialize2DArray(sixTwentyFourEpsilonSigma12_2D_,
277  numberModelSpecies_,
278  numberModelSpecies_);
279 
281  shifts2D_, numberModelSpecies_, numberModelSpecies_);
282 }
283 
284 //******************************************************************************
285 #undef KIM_LOGGER_OBJECT_NAME
286 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
287 //
288 int LennardJones612Implementation::OpenParameterFiles(
289  KIM::ModelDriverCreate * const modelDriverCreate,
290  int const numberParameterFiles,
291  FILE * parameterFilePointers[MAX_PARAMETER_FILES])
292 {
293  int ier;
294 
295  if (numberParameterFiles > MAX_PARAMETER_FILES)
296  {
297  ier = true;
298  LOG_ERROR("LennardJones612 given too many parameter files");
299  return ier;
300  }
301 
302  std::string const * paramFileDirName;
303  modelDriverCreate->GetParameterFileDirectoryName(&paramFileDirName);
304  for (int i = 0; i < numberParameterFiles; ++i)
305  {
306  std::string const * paramFileName;
307  ier = modelDriverCreate->GetParameterFileBasename(i, &paramFileName);
308  if (ier)
309  {
310  LOG_ERROR("Unable to get parameter file name");
311  return ier;
312  }
313  std::string filename = *paramFileDirName + "/" + *paramFileName;
314  parameterFilePointers[i] = fopen(filename.c_str(), "r");
315  if (parameterFilePointers[i] == 0)
316  {
317  char message[MAXLINE];
318  sprintf(message,
319  "LennardJones612 parameter file number %d cannot be opened",
320  i);
321  ier = true;
322  LOG_ERROR(message);
323  for (int j = i - 1; j >= 0; --j) { fclose(parameterFilePointers[j]); }
324  return ier;
325  }
326  }
327 
328  // everything is good
329  ier = false;
330  return ier;
331 }
332 
333 //******************************************************************************
334 #undef KIM_LOGGER_OBJECT_NAME
335 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
336 //
337 int LennardJones612Implementation::ProcessParameterFiles(
338  KIM::ModelDriverCreate * const modelDriverCreate,
339  int const /* numberParameterFiles */,
340  FILE * const parameterFilePointers[MAX_PARAMETER_FILES])
341 {
342  int N, ier;
343  int endOfFileFlag = 0;
344  char spec1[MAXLINE], spec2[MAXLINE], nextLine[MAXLINE];
345  char * nextLinePtr;
346  int iIndex, jIndex, indx, iiIndex, jjIndex;
347  double nextCutoff, nextEpsilon, nextSigma;
348 
349  nextLinePtr = nextLine;
350 
351  getNextDataLine(
352  parameterFilePointers[0], nextLinePtr, MAXLINE, &endOfFileFlag);
353  ier = sscanf(nextLine, "%d %d", &N, &shift_);
354  if (ier != 2)
355  {
356  sprintf(nextLine, "unable to read first line of the parameter file");
357  ier = true;
358  LOG_ERROR(nextLine);
359  fclose(parameterFilePointers[0]);
360  return ier;
361  }
362  numberModelSpecies_ = N;
363  numberUniqueSpeciesPairs_
364  = ((numberModelSpecies_ + 1) * numberModelSpecies_) / 2;
365  AllocateParameterMemory();
366 
367  // set all values in the arrays to -1 for mixing later
368  for (int i = 0; i < ((N + 1) * N / 2); i++)
369  {
370  cutoffs_[i] = -1;
371  epsilons_[i] = -1;
372  sigmas_[i] = -1;
373  }
374 
375 
376  // keep track of known species
377  std::map<KIM::SpeciesName const, int, KIM::SPECIES_NAME::Comparator>
378  modelSpeciesMap;
379  std::vector<KIM::SpeciesName> speciesNameVector;
380  int index = 0;
381 
382  // Read and process data lines
383  getNextDataLine(
384  parameterFilePointers[0], nextLinePtr, MAXLINE, &endOfFileFlag);
385  while (endOfFileFlag == 0)
386  {
387  ier = sscanf(nextLine,
388  "%s %s %lg %lg %lg",
389  spec1,
390  spec2,
391  &nextCutoff,
392  &nextEpsilon,
393  &nextSigma);
394  if (ier != 5)
395  {
396  sprintf(nextLine, "error reading lines of the parameter file");
397  LOG_ERROR(nextLine);
398  return true;
399  }
400 
401  // convert species strings to proper type instances
402  KIM::SpeciesName const specName1(spec1);
403  KIM::SpeciesName const specName2(spec2);
404 
405  // check for new species
406  std::map<KIM::SpeciesName const, int, KIM::SPECIES_NAME::Comparator>::
407  const_iterator iIter
408  = modelSpeciesMap.find(specName1);
409  if (iIter == modelSpeciesMap.end())
410  {
411  modelSpeciesMap[specName1] = index;
412  modelSpeciesCodeList_.push_back(index);
413  speciesNameVector.push_back(specName1);
414 
415  ier = modelDriverCreate->SetSpeciesCode(specName1, index);
416  if (ier) return ier;
417  iIndex = index;
418  index++;
419  }
420  else
421  {
422  iIndex = modelSpeciesMap[specName1];
423  }
424  std::map<KIM::SpeciesName const, int, KIM::SPECIES_NAME::Comparator>::
425  const_iterator jIter
426  = modelSpeciesMap.find(specName2);
427  if (jIter == modelSpeciesMap.end())
428  {
429  modelSpeciesMap[specName2] = index;
430  modelSpeciesCodeList_.push_back(index);
431  speciesNameVector.push_back(specName2);
432 
433  ier = modelDriverCreate->SetSpeciesCode(specName2, index);
434  if (ier) return ier;
435  jIndex = index;
436  index++;
437  }
438  else
439  {
440  jIndex = modelSpeciesMap[specName2];
441  }
442 
443  if (iIndex >= jIndex)
444  {
445  indx = jIndex * N + iIndex - (jIndex * jIndex + jIndex) / 2;
446  }
447  else
448  {
449  indx = iIndex * N + jIndex - (iIndex * iIndex + iIndex) / 2;
450  }
451  cutoffs_[indx] = nextCutoff;
452  epsilons_[indx] = nextEpsilon;
453  sigmas_[indx] = nextSigma;
454 
455  getNextDataLine(
456  parameterFilePointers[0], nextLinePtr, MAXLINE, &endOfFileFlag);
457  }
458 
459  // check that we got all like - like pairs
460  std::stringstream ss;
461  ss << "There are not values for like-like pairs of:";
462  for (int i = 0; i < N; i++)
463  {
464  if (cutoffs_[(i * N + i - (i * i + i) / 2)] == -1)
465  {
466  ss << " ";
467  ss << (speciesNameVector[i].ToString()).c_str();
468  ier = -1;
469  }
470  }
471  if (ier == -1)
472  {
473  LOG_ERROR(ss);
474  return true;
475  }
476 
477  // Perform Mixing if nessisary
478  for (int jIndex = 0; jIndex < N; jIndex++)
479  {
480  jjIndex = (jIndex * N + jIndex - (jIndex * jIndex + jIndex) / 2);
481  for (int iIndex = (jIndex + 1); iIndex < N; iIndex++)
482  {
483  indx = jIndex * N + iIndex - (jIndex * jIndex + jIndex) / 2;
484  if (cutoffs_[indx] == -1)
485  {
486  iiIndex = (iIndex * N + iIndex - (iIndex * iIndex + iIndex) / 2);
487  epsilons_[indx] = sqrt(epsilons_[iiIndex] * epsilons_[jjIndex]);
488  sigmas_[indx] = (sigmas_[iiIndex] + sigmas_[jjIndex]) / 2.0;
489  cutoffs_[indx] = (cutoffs_[iiIndex] + cutoffs_[jjIndex]) / 2.0;
490  }
491  }
492  }
493 
494  // everything is good
495  ier = false;
496  return ier;
497 }
498 
499 //******************************************************************************
500 void LennardJones612Implementation::getNextDataLine(FILE * const filePtr,
501  char * nextLinePtr,
502  int const maxSize,
503  int * endOfFileFlag)
504 {
505  do {
506  if (fgets(nextLinePtr, maxSize, filePtr) == NULL)
507  {
508  *endOfFileFlag = 1;
509  break;
510  }
511  while ((nextLinePtr[0] == ' ' || nextLinePtr[0] == '\t')
512  || (nextLinePtr[0] == '\n' || nextLinePtr[0] == '\r'))
513  {
514  nextLinePtr = (nextLinePtr + 1);
515  }
516  } while ((strncmp("#", nextLinePtr, 1) == 0) || (strlen(nextLinePtr) == 0));
517 }
518 
519 //******************************************************************************
520 void LennardJones612Implementation::CloseParameterFiles(
521  int const numberParameterFiles,
522  FILE * const parameterFilePointers[MAX_PARAMETER_FILES])
523 {
524  for (int i = 0; i < numberParameterFiles; ++i)
525  fclose(parameterFilePointers[i]);
526 }
527 
528 //******************************************************************************
529 #undef KIM_LOGGER_OBJECT_NAME
530 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
531 //
532 int LennardJones612Implementation::ConvertUnits(
533  KIM::ModelDriverCreate * const modelDriverCreate,
534  KIM::LengthUnit const requestedLengthUnit,
535  KIM::EnergyUnit const requestedEnergyUnit,
536  KIM::ChargeUnit const requestedChargeUnit,
537  KIM::TemperatureUnit const requestedTemperatureUnit,
538  KIM::TimeUnit const requestedTimeUnit)
539 {
540  int ier;
541 
542  // define default base units
548 
549  // changing units of cutoffs and sigmas
550  double convertLength = 1.0;
551  ier = KIM::ModelDriverCreate::ConvertUnit(fromLength,
552  fromEnergy,
553  fromCharge,
554  fromTemperature,
555  fromTime,
556  requestedLengthUnit,
557  requestedEnergyUnit,
558  requestedChargeUnit,
559  requestedTemperatureUnit,
560  requestedTimeUnit,
561  1.0,
562  0.0,
563  0.0,
564  0.0,
565  0.0,
566  &convertLength);
567  if (ier)
568  {
569  LOG_ERROR("Unable to convert length unit");
570  return ier;
571  }
572  if (convertLength != ONE)
573  {
574  for (int i = 0; i < numberUniqueSpeciesPairs_; ++i)
575  {
576  cutoffs_[i] *= convertLength; // convert to active units
577  sigmas_[i] *= convertLength; // convert to active units
578  }
579  }
580  // changing units of epsilons
581  double convertEnergy = 1.0;
582  ier = KIM::ModelDriverCreate::ConvertUnit(fromLength,
583  fromEnergy,
584  fromCharge,
585  fromTemperature,
586  fromTime,
587  requestedLengthUnit,
588  requestedEnergyUnit,
589  requestedChargeUnit,
590  requestedTemperatureUnit,
591  requestedTimeUnit,
592  0.0,
593  1.0,
594  0.0,
595  0.0,
596  0.0,
597  &convertEnergy);
598  if (ier)
599  {
600  LOG_ERROR("Unable to convert energy unit");
601  return ier;
602  }
603  if (convertEnergy != ONE)
604  {
605  for (int i = 0; i < numberUniqueSpeciesPairs_; ++i)
606  {
607  epsilons_[i] *= convertEnergy; // convert to active units
608  }
609  }
610 
611  // register units
612  ier = modelDriverCreate->SetUnits(requestedLengthUnit,
613  requestedEnergyUnit,
617  if (ier)
618  {
619  LOG_ERROR("Unable to set units to requested values");
620  return ier;
621  }
622 
623  // everything is good
624  ier = false;
625  return ier;
626 }
627 
628 //******************************************************************************
629 int LennardJones612Implementation::RegisterKIMModelSettings(
630  KIM::ModelDriverCreate * const modelDriverCreate) const
631 {
632  // register numbering
633  int error = modelDriverCreate->SetModelNumbering(KIM::NUMBERING::zeroBased);
634 
635  return error;
636 }
637 
638 //******************************************************************************
639 #undef KIM_LOGGER_OBJECT_NAME
640 #define KIM_LOGGER_OBJECT_NAME modelComputeArgumentsCreate
641 //
642 int LennardJones612Implementation::RegisterKIMComputeArgumentsSettings(
643  KIM::ModelComputeArgumentsCreate * const modelComputeArgumentsCreate) const
644 {
645  // register arguments
646  LOG_INFORMATION("Register argument supportStatus");
647  int error = modelComputeArgumentsCreate->SetArgumentSupportStatus(
650  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
653  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
656  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
659  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
662 
663 
664  // register callbacks
665  LOG_INFORMATION("Register callback supportStatus");
666  error = error
667  || modelComputeArgumentsCreate->SetCallbackSupportStatus(
670  || modelComputeArgumentsCreate->SetCallbackSupportStatus(
673 
674  return error;
675 }
676 
677 //******************************************************************************
678 // helper macro
679 #define SNUM(x) \
680  static_cast<std::ostringstream const &>(std::ostringstream() \
681  << std::dec << x) \
682  .str()
683 //******************************************************************************
684 #undef KIM_LOGGER_OBJECT_NAME
685 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
686 //
687 int LennardJones612Implementation::RegisterKIMParameters(
688  KIM::ModelDriverCreate * const modelDriverCreate)
689 {
690  int ier = false;
691 
692  // publish parameters (order is important)
693  ier = modelDriverCreate->SetParameterPointer(
694  1,
695  &shift_,
696  "shift",
697  "If (shift == 1), all LJ potentials are shifted to zero energy "
698  "at their respective cutoff distance. Otherwise, no shifting is "
699  "performed.");
700  if (ier)
701  {
702  LOG_ERROR("set_parameter shift");
703  return ier;
704  }
705 
706  ier = modelDriverCreate->SetParameterPointer(
707  numberUniqueSpeciesPairs_,
708  cutoffs_,
709  "cutoffs",
710  "Lower-triangular matrix (of size N=" + SNUM(numberModelSpecies_)
711  + ") "
712  "in row-major storage. Ordering is according to SpeciesCode "
713  "values. "
714  "For example, to find the parameter related to SpeciesCode 'i' and "
715  "SpeciesCode 'j' (i >= j), use (zero-based) "
716  "index = (j*N + i - (j*j + j)/2).");
717  if (ier)
718  {
719  LOG_ERROR("set_parameter cutoffs");
720  return ier;
721  }
722  ier = modelDriverCreate->SetParameterPointer(
723  numberUniqueSpeciesPairs_,
724  epsilons_,
725  "epsilons",
726  "Lower-triangular matrix (of size N=" + SNUM(numberModelSpecies_)
727  + ") "
728  "in row-major storage. Ordering is according to SpeciesCode "
729  "values. "
730  "For example, to find the parameter related to SpeciesCode 'i' and "
731  "SpeciesCode 'j' (i >= j), use (zero-based) "
732  "index = (j*N + i - (j*j + j)/2).");
733  if (ier)
734  {
735  LOG_ERROR("set_parameter epsilons");
736  return ier;
737  }
738  ier = modelDriverCreate->SetParameterPointer(
739  numberUniqueSpeciesPairs_,
740  sigmas_,
741  "sigmas",
742  "Lower-triangular matrix (of size N=" + SNUM(numberModelSpecies_)
743  + ") "
744  "in row-major storage. Ordering is according to SpeciesCode "
745  "values. "
746  "For example, to find the parameter related to SpeciesCode 'i' and "
747  "SpeciesCode 'j' (i >= j), use (zero-based) "
748  "index = (j*N + i - (j*j + j)/2).");
749  if (ier)
750  {
751  LOG_ERROR("set_parameter sigmas");
752  return ier;
753  }
754 
755  // everything is good
756  ier = false;
757  return ier;
758 }
759 
760 //******************************************************************************
761 int LennardJones612Implementation::RegisterKIMFunctions(
762  KIM::ModelDriverCreate * const modelDriverCreate) const
763 {
764  int error;
765 
766  // Use function pointer definitions to verify correct prototypes
774 
775  // register the destroy() and reinit() functions
776  error = modelDriverCreate->SetRoutinePointer(
779  true,
780  reinterpret_cast<KIM::Function *>(destroy))
781  || modelDriverCreate->SetRoutinePointer(
784  true,
785  reinterpret_cast<KIM::Function *>(refresh))
786  || modelDriverCreate->SetRoutinePointer(
789  true,
790  reinterpret_cast<KIM::Function *>(compute))
791  || modelDriverCreate->SetRoutinePointer(
794  true,
795  reinterpret_cast<KIM::Function *>(CACreate))
796  || modelDriverCreate->SetRoutinePointer(
799  true,
800  reinterpret_cast<KIM::Function *>(CADestroy));
801  return error;
802 }
803 
804 //******************************************************************************
805 template<class ModelObj>
806 int LennardJones612Implementation::SetRefreshMutableValues(
807  ModelObj * const modelObj)
808 { // use (possibly) new values of parameters to compute other quantities
809  // NOTE: This function is templated because it's called with both a
810  // modelDriverCreate object during initialization and with a
811  // modelRefresh object when the Model's parameters have been altered
812  int ier;
813 
814  // update cutoffsSq, epsilons, and sigmas
815  for (int i = 0; i < numberModelSpecies_; ++i)
816  {
817  for (int j = 0; j <= i; ++j)
818  {
819  int const index = j * numberModelSpecies_ + i - (j * j + j) / 2;
820  cutoffsSq2D_[i][j] = cutoffsSq2D_[j][i]
821  = (cutoffs_[index] * cutoffs_[index]);
822  fourEpsilonSigma6_2D_[i][j] = fourEpsilonSigma6_2D_[j][i]
823  = 4.0 * epsilons_[index] * pow(sigmas_[index], 6.0);
824  fourEpsilonSigma12_2D_[i][j] = fourEpsilonSigma12_2D_[j][i]
825  = 4.0 * epsilons_[index] * pow(sigmas_[index], 12.0);
826  twentyFourEpsilonSigma6_2D_[i][j] = twentyFourEpsilonSigma6_2D_[j][i]
827  = 6.0 * fourEpsilonSigma6_2D_[i][j];
828  fortyEightEpsilonSigma12_2D_[i][j] = fortyEightEpsilonSigma12_2D_[j][i]
829  = 12.0 * fourEpsilonSigma12_2D_[i][j];
830  oneSixtyEightEpsilonSigma6_2D_[i][j]
831  = oneSixtyEightEpsilonSigma6_2D_[j][i]
832  = 7.0 * twentyFourEpsilonSigma6_2D_[i][j];
833  sixTwentyFourEpsilonSigma12_2D_[i][j]
834  = sixTwentyFourEpsilonSigma12_2D_[j][i]
835  = 13.0 * fortyEightEpsilonSigma12_2D_[i][j];
836  }
837  }
838 
839  // update cutoff value in KIM API object
840  influenceDistance_ = 0.0;
841 
842  for (int i = 0; i < numberModelSpecies_; i++)
843  {
844  int indexI = modelSpeciesCodeList_[i];
845 
846  for (int j = 0; j < numberModelSpecies_; j++)
847  {
848  int indexJ = modelSpeciesCodeList_[j];
849 
850  if (influenceDistance_ < cutoffsSq2D_[indexI][indexJ])
851  {
852  influenceDistance_ = cutoffsSq2D_[indexI][indexJ];
853  }
854  }
855  }
856 
857  influenceDistance_ = sqrt(influenceDistance_);
858  modelObj->SetInfluenceDistancePointer(&influenceDistance_);
859  modelObj->SetNeighborListPointers(
860  1,
861  &influenceDistance_,
862  &modelWillNotRequestNeighborsOfNoncontributingParticles_);
863 
864  // update shifts
865  // compute and set shifts2D_ check if minus sign
866  double const * const * const constFourEpsSig6_2D = fourEpsilonSigma6_2D_;
867  double const * const * const constFourEpsSig12_2D = fourEpsilonSigma12_2D_;
868  if (1 == shift_)
869  {
870  double phi;
871  for (int iSpecies = 0; iSpecies < numberModelSpecies_; iSpecies++)
872  {
873  for (int jSpecies = 0; jSpecies <= iSpecies; jSpecies++)
874  {
875  int const index = jSpecies * numberModelSpecies_ + iSpecies
876  - (jSpecies * jSpecies + jSpecies) / 2;
877  double const rij2 = cutoffs_[index] * cutoffs_[index];
878  double const r2iv = 1.0 / rij2;
879  double const r6iv = r2iv * r2iv * r2iv;
881  shifts2D_[iSpecies][jSpecies] = shifts2D_[jSpecies][iSpecies] = phi;
882  }
883  }
884  }
885 
886  // everything is good
887  ier = false;
888  return ier;
889 }
890 
891 //******************************************************************************
892 #undef KIM_LOGGER_OBJECT_NAME
893 #define KIM_LOGGER_OBJECT_NAME modelComputeArguments
894 //
895 int LennardJones612Implementation::SetComputeMutableValues(
896  KIM::ModelComputeArguments const * const modelComputeArguments,
897  bool & isComputeProcess_dEdr,
898  bool & isComputeProcess_d2Edr2,
899  bool & isComputeEnergy,
900  bool & isComputeForces,
901  bool & isComputeParticleEnergy,
902  bool & isComputeVirial,
903  bool & isComputeParticleVirial,
904  int const *& particleSpeciesCodes,
905  int const *& particleContributing,
906  VectorOfSizeDIM const *& coordinates,
907  double *& energy,
908  double *& particleEnergy,
909  VectorOfSizeDIM *& forces,
910  VectorOfSizeSix *& virial,
911  VectorOfSizeSix *& particleVirial)
912 {
913  int ier = true;
914 
915  // get compute flags
916  int compProcess_dEdr;
917  int compProcess_d2Edr2;
918 
919  modelComputeArguments->IsCallbackPresent(
921  modelComputeArguments->IsCallbackPresent(
922  KIM::COMPUTE_CALLBACK_NAME::ProcessD2EDr2Term, &compProcess_d2Edr2);
923 
924  isComputeProcess_dEdr = compProcess_dEdr;
925  isComputeProcess_d2Edr2 = compProcess_d2Edr2;
926 
927  int const * numberOfParticles;
928  ier = modelComputeArguments->GetArgumentPointer(
930  || modelComputeArguments->GetArgumentPointer(
933  || modelComputeArguments->GetArgumentPointer(
936  || modelComputeArguments->GetArgumentPointer(
938  (double const **) &coordinates)
939  || modelComputeArguments->GetArgumentPointer(
941  || modelComputeArguments->GetArgumentPointer(
943  || modelComputeArguments->GetArgumentPointer(
945  (double const **) &forces)
946  || modelComputeArguments->GetArgumentPointer(
948  (double const **) &virial)
949  || modelComputeArguments->GetArgumentPointer(
951  (double const **) &particleVirial);
952  if (ier)
953  {
954  LOG_ERROR("GetArgumentPointer");
955  return ier;
956  }
957 
958  isComputeEnergy = (energy != NULL);
959  isComputeParticleEnergy = (particleEnergy != NULL);
960  isComputeForces = (forces != NULL);
961  isComputeVirial = (virial != NULL);
962  isComputeParticleVirial = (particleVirial != NULL);
963 
964  // update values
965  cachedNumberOfParticles_ = *numberOfParticles;
966 
967  // everything is good
968  ier = false;
969  return ier;
970 }
971 
972 //******************************************************************************
973 #undef KIM_LOGGER_OBJECT_NAME
974 #define KIM_LOGGER_OBJECT_NAME modelCompute
975 int LennardJones612Implementation::CheckParticleSpeciesCodes(
976  KIM::ModelCompute const * const modelCompute,
977  int const * const particleSpeciesCodes) const
978 {
979  int ier;
980  for (int i = 0; i < cachedNumberOfParticles_; ++i)
981  {
982  if ((particleSpeciesCodes[i] < 0)
983  || (particleSpeciesCodes[i] >= numberModelSpecies_))
984  {
985  ier = true;
986  LOG_ERROR("unsupported particle species codes detected");
987  return ier;
988  }
989  }
990 
991  // everything is good
992  ier = false;
993  return ier;
994 }
995 
996 //******************************************************************************
997 int LennardJones612Implementation::GetComputeIndex(
998  const bool & isComputeProcess_dEdr,
999  const bool & isComputeProcess_d2Edr2,
1000  const bool & isComputeEnergy,
1001  const bool & isComputeForces,
1002  const bool & isComputeParticleEnergy,
1003  const bool & isComputeVirial,
1004  const bool & isComputeParticleVirial,
1005  const bool & isShift) const
1006 {
1007  // const int processdE = 2;
1008  const int processd2E = 2;
1009  const int energy = 2;
1010  const int force = 2;
1011  const int particleEnergy = 2;
1012  const int virial = 2;
1013  const int particleVirial = 2;
1014  const int shift = 2;
1015 
1016 
1017  int index = 0;
1018 
1019  // processdE
1020  index += (int(isComputeProcess_dEdr)) * processd2E * energy * force
1021  * particleEnergy * virial * particleVirial * shift;
1022 
1023  // processd2E
1024  index += (int(isComputeProcess_d2Edr2)) * energy * force * particleEnergy
1025  * virial * particleVirial * shift;
1026 
1027  // energy
1028  index += (int(isComputeEnergy)) * force * particleEnergy * virial
1029  * particleVirial * shift;
1030 
1031  // force
1032  index += (int(isComputeForces)) * particleEnergy * virial * particleVirial
1033  * shift;
1034 
1035  // particleEnergy
1036  index += (int(isComputeParticleEnergy)) * virial * particleVirial * shift;
1037 
1038  // virial
1039  index += (int(isComputeVirial)) * particleVirial * shift;
1040 
1041  // particleVirial
1042  index += (int(isComputeParticleVirial)) * shift;
1043 
1044  // shift
1045  index += (int(isShift));
1046 
1047  return index;
1048 }
1049 
1050 //******************************************************************************
1051 void LennardJones612Implementation::ProcessVirialTerm(
1052  const double & dEidr,
1053  const double & rij,
1054  const double * const r_ij,
1055  const int & /* i */,
1056  const int & /* j */,
1057  VectorOfSizeSix virial) const
1058 {
1059  double const v = dEidr / rij;
1060 
1061  virial[0] += v * r_ij[0] * r_ij[0];
1062  virial[1] += v * r_ij[1] * r_ij[1];
1063  virial[2] += v * r_ij[2] * r_ij[2];
1064  virial[3] += v * r_ij[1] * r_ij[2];
1065  virial[4] += v * r_ij[0] * r_ij[2];
1066  virial[5] += v * r_ij[0] * r_ij[1];
1067 }
1068 
1069 //******************************************************************************
1070 void LennardJones612Implementation::ProcessParticleVirialTerm(
1071  const double & dEidr,
1072  const double & rij,
1073  const double * const r_ij,
1074  const int & i,
1075  const int & j,
1076  VectorOfSizeSix * const particleVirial) const
1077 {
1078  double const v = dEidr / rij;
1079  VectorOfSizeSix vir;
1080 
1081  vir[0] = 0.5 * v * r_ij[0] * r_ij[0];
1082  vir[1] = 0.5 * v * r_ij[1] * r_ij[1];
1083  vir[2] = 0.5 * v * r_ij[2] * r_ij[2];
1084  vir[3] = 0.5 * v * r_ij[1] * r_ij[2];
1085  vir[4] = 0.5 * v * r_ij[0] * r_ij[2];
1086  vir[5] = 0.5 * v * r_ij[0] * r_ij[1];
1087 
1088  for (int k = 0; k < 6; ++k)
1089  {
1090  particleVirial[i][k] += vir[k];
1091  particleVirial[j][k] += vir[k];
1092  }
1093 }
1094 
1095 //==============================================================================
1096 //
1097 // Implementation of helper functions
1098 //
1099 //==============================================================================
1100 
1101 //******************************************************************************
1102 void AllocateAndInitialize2DArray(double **& arrayPtr,
1103  int const extentZero,
1104  int const extentOne)
1105 { // allocate memory and set pointers
1106  arrayPtr = new double *[extentZero];
1107  arrayPtr[0] = new double[extentZero * extentOne];
1108  for (int i = 1; i < extentZero; ++i)
1109  {
1110  arrayPtr[i] = arrayPtr[i - 1] + extentOne;
1111  }
1112 
1113  // initialize
1114  for (int i = 0; i < extentZero; ++i)
1115  {
1116  for (int j = 0; j < extentOne; ++j) { arrayPtr[i][j] = 0.0; }
1117  }
1118 }
1119 
1120 //******************************************************************************
1121 void Deallocate2DArray(double **& arrayPtr)
1122 { // deallocate memory
1123  if (arrayPtr != NULL) delete[] arrayPtr[0];
1124  delete[] arrayPtr;
1125 
1126  // nullify pointer
1127  arrayPtr = NULL;
1128 }
int ComputeArgumentsCreate(KIM::ModelComputeArgumentsCreate *const modelComputeArgumentsCreate) const
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.
ComputeArgumentName const partialParticleEnergy
The standard partialParticleEnergy argument.
int GetParameterFileBasename(int const index, std::string const **const parameterFileBasename) const
Get a particular parameter file basename. The file is located in the Model&#39;s parameter file directory...
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.
static int Refresh(KIM::ModelRefresh *const modelRefresh)
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.
TimeUnit const ps
The standard picosecond unit of time.
recursive subroutine, public destroy(model_destroy_handle, ierr)
#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.
ModelRoutineName const Destroy
The standard Destroy routine.
ComputeArgumentName const partialVirial
The standard partialVirial argument.
ChargeUnit const unused
Indicates that a ChargeUnit is not used.
ChargeUnit const e
The standard electron unit of charge.
recursive subroutine, public refresh(model_refresh_handle, ierr)
void GetNumberOfParameterFiles(int *const numberOfParameterFiles) const
Get the number of parameter files provided by the parameterized model.
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.
ComputeCallbackName const ProcessD2EDr2Term
The standard ProcessD2EDr2Term callback.
double VectorOfSizeDIM[DIMENSION]
An Extensible Enumeration for the LengthUnit&#39;s supported by the KIM API.
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.
int SetModelNumbering(Numbering const numbering)
Set the Model&#39;s particle Numbering.
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.
static int ComputeArgumentsCreate(KIM::ModelCompute const *const modelCompute, KIM::ModelComputeArgumentsCreate *const modelComputeArgumentsCreate)
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 Refresh
The standard Refresh routine.
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)
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...
static int Destroy(KIM::ModelDestroy *const modelDestroy)
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.
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.
ComputeArgumentName const partialParticleVirial
The standard partialParticleVirial argument.
ComputeCallbackName const ProcessDEDrTerm
The standard ProcessDEDrTerm callback.
int SetRoutinePointer(ModelRoutineName const modelRoutineName, LanguageName const languageName, int const required, Function *const fptr)
Set the function pointer for the ModelRoutineName of interest.
void GetParameterFileDirectoryName(std::string const **const directoryName) const
Get absolute path name of the temporary directory where parameter files provided by the model are wri...
int Refresh(KIM::ModelRefresh *const modelRefresh)
LengthUnit const A
The standard angstrom unit of length.
int ModelRefreshFunction(ModelRefresh *const modelRefresh)
Prototype for MODEL_ROUTINE_NAME::Refresh routine.
Provides the interface to a KIM API ComputeArguments object for use by models within their MODEL_ROUT...
ComputeArgumentName const partialForces
The standard partialForces argument.
int SetParameterPointer(int const extent, int *const ptr, std::string const &name, std::string const &description)
Set the next parameter data pointer to be provided by the model.
int ComputeArgumentsDestroy(KIM::ModelComputeArgumentsDestroy *const modelComputeArgumentsDestroy) const
EnergyUnit const eV
The standard electronvolt unit of energy.
static int ComputeArgumentsDestroy(KIM::ModelCompute const *const modelCompute, KIM::ModelComputeArgumentsDestroy *const modelComputeArgumentsDestroy)
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.
ComputeArgumentName const numberOfParticles
The standard numberOfParticles argument.
SpeciesName const N
The standard Nitrogen species.
double VectorOfSizeSix[6]
#define LOG_INFORMATION(message)
Convenience macro for INFORMATION Log entries with compile-time optimization.
void AllocateAndInitialize2DArray(double **&arrayPtr, int const extentZero, int const extentOne)
void Deallocate2DArray(double **&arrayPtr)
int Compute(KIM::ModelCompute const *const modelCompute, KIM::ModelComputeArguments const *const modelComputeArguments)
Numbering const zeroBased
The standard zeroBased numbering.
static int Compute(KIM::ModelCompute const *const modelCompute, KIM::ModelComputeArguments const *const modelComputeArguments)
int SetSpeciesCode(SpeciesName const speciesName, int const code)
Set integer code for supported SpeciesName.
TimeUnit const unused
Indicates that a TimeUnit is not used.
An Extensible Enumeration for the SpeciesName&#39;s supported by the KIM API.
int SetCallbackSupportStatus(ComputeCallbackName const computeCallbackName, SupportStatus const supportStatus)
Set the SupportStatus of a ComputeCallbackName.
LogVerbosity const error
The standard error verbosity.
int IsCallbackPresent(ComputeCallbackName const computeCallbackName, int *const present) const
Determine if the Simulator has provided a non-NULL function pointer for a ComputeCallbackName of inte...
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 ...
SupportStatus const optional
The standard optional status.
TemperatureUnit const K
The standard Kelvin unit of temperature.