kim-api  2.0.2+v2.0.2.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 <cstdlib>
33 #include <cstring>
34 #include <fstream>
35 #include <iostream>
36 #include <map>
37 #include <sstream>
38 
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 //******************************************************************************
233  KIM::ModelComputeArgumentsDestroy * const modelComputeArgumentsDestroy)
234  const
235 {
236  int ier;
237 
238  (void) modelComputeArgumentsDestroy; // avoid unused parameter warning
239 
240  // nothing else to do for this case
241 
242  // everything is good
243  ier = false;
244  return ier;
245 }
246 
247 //==============================================================================
248 //
249 // Implementation of LennardJones612Implementation private member functions
250 //
251 //==============================================================================
252 
253 //******************************************************************************
254 void LennardJones612Implementation::AllocatePrivateParameterMemory()
255 {
256  // nothing to do for this case
257 }
258 
259 //******************************************************************************
260 void LennardJones612Implementation::AllocateParameterMemory()
261 { // allocate memory for data
262  cutoffs_ = new double[numberUniqueSpeciesPairs_];
264  cutoffsSq2D_, numberModelSpecies_, numberModelSpecies_);
265 
266  epsilons_ = new double[numberUniqueSpeciesPairs_];
267  sigmas_ = new double[numberUniqueSpeciesPairs_];
269  fourEpsilonSigma6_2D_, numberModelSpecies_, numberModelSpecies_);
271  fourEpsilonSigma12_2D_, numberModelSpecies_, numberModelSpecies_);
273  twentyFourEpsilonSigma6_2D_, numberModelSpecies_, numberModelSpecies_);
275  fortyEightEpsilonSigma12_2D_, numberModelSpecies_, numberModelSpecies_);
277  oneSixtyEightEpsilonSigma6_2D_, numberModelSpecies_, numberModelSpecies_);
278  AllocateAndInitialize2DArray(sixTwentyFourEpsilonSigma12_2D_,
279  numberModelSpecies_,
280  numberModelSpecies_);
281 
283  shifts2D_, numberModelSpecies_, numberModelSpecies_);
284 }
285 
286 //******************************************************************************
287 #undef KIM_LOGGER_OBJECT_NAME
288 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
289 //
290 int LennardJones612Implementation::OpenParameterFiles(
291  KIM::ModelDriverCreate * const modelDriverCreate,
292  int const numberParameterFiles,
293  FILE * parameterFilePointers[MAX_PARAMETER_FILES])
294 {
295  int ier;
296 
297  if (numberParameterFiles > MAX_PARAMETER_FILES)
298  {
299  ier = true;
300  LOG_ERROR("LennardJones612 given too many parameter files");
301  return ier;
302  }
303 
304  for (int i = 0; i < numberParameterFiles; ++i)
305  {
306  std::string const * paramFileName;
307  ier = modelDriverCreate->GetParameterFileName(i, &paramFileName);
308  if (ier)
309  {
310  LOG_ERROR("Unable to get parameter file name");
311  return ier;
312  }
313  parameterFilePointers[i] = fopen(paramFileName->c_str(), "r");
314  if (parameterFilePointers[i] == 0)
315  {
316  char message[MAXLINE];
317  sprintf(message,
318  "LennardJones612 parameter file number %d cannot be opened",
319  i);
320  ier = true;
321  LOG_ERROR(message);
322  for (int j = i - 1; j >= 0; --j) { fclose(parameterFilePointers[j]); }
323  return ier;
324  }
325  }
326 
327  // everything is good
328  ier = false;
329  return ier;
330 }
331 
332 //******************************************************************************
333 #undef KIM_LOGGER_OBJECT_NAME
334 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
335 //
336 int LennardJones612Implementation::ProcessParameterFiles(
337  KIM::ModelDriverCreate * const modelDriverCreate,
338  int const numberParameterFiles,
339  FILE * const parameterFilePointers[MAX_PARAMETER_FILES])
340 {
341  int N, ier;
342  int endOfFileFlag = 0;
343  char spec1[MAXLINE], spec2[MAXLINE], nextLine[MAXLINE];
344  char * nextLinePtr;
345  int iIndex, jIndex, indx, iiIndex, jjIndex;
346  double nextCutoff, nextEpsilon, nextSigma;
347 
348  (void) numberParameterFiles; // avoid unused parameter warning
349 
350  nextLinePtr = nextLine;
351 
352  getNextDataLine(
353  parameterFilePointers[0], nextLinePtr, MAXLINE, &endOfFileFlag);
354  ier = sscanf(nextLine, "%d %d", &N, &shift_);
355  if (ier != 2)
356  {
357  sprintf(nextLine, "unable to read first line of the parameter file");
358  ier = true;
359  LOG_ERROR(nextLine);
360  fclose(parameterFilePointers[0]);
361  return ier;
362  }
363  numberModelSpecies_ = N;
364  numberUniqueSpeciesPairs_
365  = ((numberModelSpecies_ + 1) * numberModelSpecies_) / 2;
366  AllocateParameterMemory();
367 
368  // set all values in the arrays to -1 for mixing later
369  for (int i = 0; i < ((N + 1) * N / 2); i++)
370  {
371  cutoffs_[i] = -1;
372  epsilons_[i] = -1;
373  sigmas_[i] = -1;
374  }
375 
376 
377  // keep track of known species
378  std::map<KIM::SpeciesName const, int, KIM::SPECIES_NAME::Comparator>
379  modelSpeciesMap;
380  std::vector<KIM::SpeciesName> speciesNameVector;
381  int index = 0;
382 
383  // Read and process data lines
384  getNextDataLine(
385  parameterFilePointers[0], nextLinePtr, MAXLINE, &endOfFileFlag);
386  while (endOfFileFlag == 0)
387  {
388  ier = sscanf(nextLine,
389  "%s %s %lg %lg %lg",
390  spec1,
391  spec2,
392  &nextCutoff,
393  &nextEpsilon,
394  &nextSigma);
395  if (ier != 5)
396  {
397  sprintf(nextLine, "error reading lines of the parameter file");
398  LOG_ERROR(nextLine);
399  return true;
400  }
401 
402  // convert species strings to proper type instances
403  KIM::SpeciesName const specName1(spec1);
404  KIM::SpeciesName const specName2(spec2);
405 
406  // check for new species
407  std::map<KIM::SpeciesName const, int, KIM::SPECIES_NAME::Comparator>::
408  const_iterator iIter
409  = modelSpeciesMap.find(specName1);
410  if (iIter == modelSpeciesMap.end())
411  {
412  modelSpeciesMap[specName1] = index;
413  modelSpeciesCodeList_.push_back(index);
414  speciesNameVector.push_back(specName1);
415 
416  ier = modelDriverCreate->SetSpeciesCode(specName1, index);
417  if (ier) return ier;
418  iIndex = index;
419  index++;
420  }
421  else
422  {
423  iIndex = modelSpeciesMap[specName1];
424  }
425  std::map<KIM::SpeciesName const, int, KIM::SPECIES_NAME::Comparator>::
426  const_iterator jIter
427  = modelSpeciesMap.find(specName2);
428  if (jIter == modelSpeciesMap.end())
429  {
430  modelSpeciesMap[specName2] = index;
431  modelSpeciesCodeList_.push_back(index);
432  speciesNameVector.push_back(specName2);
433 
434  ier = modelDriverCreate->SetSpeciesCode(specName2, index);
435  if (ier) return ier;
436  jIndex = index;
437  index++;
438  }
439  else
440  {
441  jIndex = modelSpeciesMap[specName2];
442  }
443 
444  if (iIndex >= jIndex)
445  { indx = jIndex * N + iIndex - (jIndex * jIndex + jIndex) / 2; }
446  else
447  {
448  indx = iIndex * N + jIndex - (iIndex * iIndex + iIndex) / 2;
449  }
450  cutoffs_[indx] = nextCutoff;
451  epsilons_[indx] = nextEpsilon;
452  sigmas_[indx] = nextSigma;
453 
454  getNextDataLine(
455  parameterFilePointers[0], nextLinePtr, MAXLINE, &endOfFileFlag);
456  }
457 
458  // check that we got all like - like pairs
459  std::stringstream ss;
460  ss << "There are not values for like-like pairs of:";
461  for (int i = 0; i < N; i++)
462  {
463  if (cutoffs_[(i * N + i - (i * i + i) / 2)] == -1)
464  {
465  ss << " ";
466  ss << (speciesNameVector[i].ToString()).c_str();
467  ier = -1;
468  }
469  }
470  if (ier == -1)
471  {
472  LOG_ERROR(ss);
473  return true;
474  }
475 
476  // Perform Mixing if nessisary
477  for (int jIndex = 0; jIndex < N; jIndex++)
478  {
479  jjIndex = (jIndex * N + jIndex - (jIndex * jIndex + jIndex) / 2);
480  for (int iIndex = (jIndex + 1); iIndex < N; iIndex++)
481  {
482  indx = jIndex * N + iIndex - (jIndex * jIndex + jIndex) / 2;
483  if (cutoffs_[indx] == -1)
484  {
485  iiIndex = (iIndex * N + iIndex - (iIndex * iIndex + iIndex) / 2);
486  epsilons_[indx] = sqrt(epsilons_[iiIndex] * epsilons_[jjIndex]);
487  sigmas_[indx] = (sigmas_[iiIndex] + sigmas_[jjIndex]) / 2.0;
488  cutoffs_[indx] = (cutoffs_[iiIndex] + cutoffs_[jjIndex]) / 2.0;
489  }
490  }
491  }
492 
493  // everything is good
494  ier = false;
495  return ier;
496 }
497 
498 //******************************************************************************
499 void LennardJones612Implementation::getNextDataLine(FILE * const filePtr,
500  char * nextLinePtr,
501  int const maxSize,
502  int * endOfFileFlag)
503 {
504  do
505  {
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  { nextLinePtr = (nextLinePtr + 1); }
514  } while ((strncmp("#", nextLinePtr, 1) == 0) || (strlen(nextLinePtr) == 0));
515 }
516 
517 //******************************************************************************
518 void LennardJones612Implementation::CloseParameterFiles(
519  int const numberParameterFiles,
520  FILE * const parameterFilePointers[MAX_PARAMETER_FILES])
521 {
522  for (int i = 0; i < numberParameterFiles; ++i)
523  fclose(parameterFilePointers[i]);
524 }
525 
526 //******************************************************************************
527 #undef KIM_LOGGER_OBJECT_NAME
528 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
529 //
530 int LennardJones612Implementation::ConvertUnits(
531  KIM::ModelDriverCreate * const modelDriverCreate,
532  KIM::LengthUnit const requestedLengthUnit,
533  KIM::EnergyUnit const requestedEnergyUnit,
534  KIM::ChargeUnit const requestedChargeUnit,
535  KIM::TemperatureUnit const requestedTemperatureUnit,
536  KIM::TimeUnit const requestedTimeUnit)
537 {
538  int ier;
539 
540  // define default base units
546 
547  // changing units of cutoffs and sigmas
548  double convertLength = 1.0;
549  ier = KIM::ModelDriverCreate::ConvertUnit(fromLength,
550  fromEnergy,
551  fromCharge,
552  fromTemperature,
553  fromTime,
554  requestedLengthUnit,
555  requestedEnergyUnit,
556  requestedChargeUnit,
557  requestedTemperatureUnit,
558  requestedTimeUnit,
559  1.0,
560  0.0,
561  0.0,
562  0.0,
563  0.0,
564  &convertLength);
565  if (ier)
566  {
567  LOG_ERROR("Unable to convert length unit");
568  return ier;
569  }
570  if (convertLength != ONE)
571  {
572  for (int i = 0; i < numberUniqueSpeciesPairs_; ++i)
573  {
574  cutoffs_[i] *= convertLength; // convert to active units
575  sigmas_[i] *= convertLength; // convert to active units
576  }
577  }
578  // changing units of epsilons
579  double convertEnergy = 1.0;
580  ier = KIM::ModelDriverCreate::ConvertUnit(fromLength,
581  fromEnergy,
582  fromCharge,
583  fromTemperature,
584  fromTime,
585  requestedLengthUnit,
586  requestedEnergyUnit,
587  requestedChargeUnit,
588  requestedTemperatureUnit,
589  requestedTimeUnit,
590  0.0,
591  1.0,
592  0.0,
593  0.0,
594  0.0,
595  &convertEnergy);
596  if (ier)
597  {
598  LOG_ERROR("Unable to convert energy unit");
599  return ier;
600  }
601  if (convertEnergy != ONE)
602  {
603  for (int i = 0; i < numberUniqueSpeciesPairs_; ++i)
604  {
605  epsilons_[i] *= convertEnergy; // convert to active units
606  }
607  }
608 
609  // register units
610  ier = modelDriverCreate->SetUnits(requestedLengthUnit,
611  requestedEnergyUnit,
615  if (ier)
616  {
617  LOG_ERROR("Unable to set units to requested values");
618  return ier;
619  }
620 
621  // everything is good
622  ier = false;
623  return ier;
624 }
625 
626 //******************************************************************************
627 int LennardJones612Implementation::RegisterKIMModelSettings(
628  KIM::ModelDriverCreate * const modelDriverCreate) const
629 {
630  // register numbering
631  int error = modelDriverCreate->SetModelNumbering(KIM::NUMBERING::zeroBased);
632 
633  return error;
634 }
635 
636 //******************************************************************************
637 #undef KIM_LOGGER_OBJECT_NAME
638 #define KIM_LOGGER_OBJECT_NAME modelComputeArgumentsCreate
639 //
640 int LennardJones612Implementation::RegisterKIMComputeArgumentsSettings(
641  KIM::ModelComputeArgumentsCreate * const modelComputeArgumentsCreate) const
642 {
643  // register arguments
644  LOG_INFORMATION("Register argument supportStatus");
645  int error = modelComputeArgumentsCreate->SetArgumentSupportStatus(
648  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
651  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
654  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
657  || modelComputeArgumentsCreate->SetArgumentSupportStatus(
660 
661 
662  // register callbacks
663  LOG_INFORMATION("Register callback supportStatus");
664  error = error
665  || modelComputeArgumentsCreate->SetCallbackSupportStatus(
668  || modelComputeArgumentsCreate->SetCallbackSupportStatus(
671 
672  return error;
673 }
674 
675 //******************************************************************************
676 // helper macro
677 #define SNUM(x) \
678  static_cast<std::ostringstream &>(std::ostringstream() << std::dec << x).str()
679 //******************************************************************************
680 #undef KIM_LOGGER_OBJECT_NAME
681 #define KIM_LOGGER_OBJECT_NAME modelDriverCreate
682 //
683 int LennardJones612Implementation::RegisterKIMParameters(
684  KIM::ModelDriverCreate * const modelDriverCreate)
685 {
686  int ier = false;
687 
688  // publish parameters (order is important)
689  ier = modelDriverCreate->SetParameterPointer(
690  1,
691  &shift_,
692  "shift",
693  "If (shift == 1), all LJ potentials are shifted to zero energy "
694  "at their respective cutoff distance. Otherwise, no shifting is "
695  "performed.");
696  if (ier)
697  {
698  LOG_ERROR("set_parameter shift");
699  return ier;
700  }
701 
702  ier = modelDriverCreate->SetParameterPointer(
703  numberUniqueSpeciesPairs_,
704  cutoffs_,
705  "cutoffs",
706  "Lower-triangular matrix (of size N=" + SNUM(numberModelSpecies_)
707  + ") "
708  "in row-major storage. Ordering is according to SpeciesCode "
709  "values. "
710  "For example, to find the parameter related to SpeciesCode 'i' and "
711  "SpeciesCode 'j' (i >= j), use (zero-based) "
712  "index = (j*N + i - (j*j + j)/2).");
713  if (ier)
714  {
715  LOG_ERROR("set_parameter cutoffs");
716  return ier;
717  }
718  ier = modelDriverCreate->SetParameterPointer(
719  numberUniqueSpeciesPairs_,
720  epsilons_,
721  "epsilons",
722  "Lower-triangular matrix (of size N=" + SNUM(numberModelSpecies_)
723  + ") "
724  "in row-major storage. Ordering is according to SpeciesCode "
725  "values. "
726  "For example, to find the parameter related to SpeciesCode 'i' and "
727  "SpeciesCode 'j' (i >= j), use (zero-based) "
728  "index = (j*N + i - (j*j + j)/2).");
729  if (ier)
730  {
731  LOG_ERROR("set_parameter epsilons");
732  return ier;
733  }
734  ier = modelDriverCreate->SetParameterPointer(
735  numberUniqueSpeciesPairs_,
736  sigmas_,
737  "sigmas",
738  "Lower-triangular matrix (of size N=" + SNUM(numberModelSpecies_)
739  + ") "
740  "in row-major storage. Ordering is according to SpeciesCode "
741  "values. "
742  "For example, to find the parameter related to SpeciesCode 'i' and "
743  "SpeciesCode 'j' (i >= j), use (zero-based) "
744  "index = (j*N + i - (j*j + j)/2).");
745  if (ier)
746  {
747  LOG_ERROR("set_parameter sigmas");
748  return ier;
749  }
750 
751  // everything is good
752  ier = false;
753  return ier;
754 }
755 
756 //******************************************************************************
757 int LennardJones612Implementation::RegisterKIMFunctions(
758  KIM::ModelDriverCreate * const modelDriverCreate) const
759 {
760  int error;
761 
762  // Use function pointer definitions to verify correct prototypes
770 
771  // register the destroy() and reinit() functions
772  error = modelDriverCreate->SetRoutinePointer(
775  true,
776  reinterpret_cast<KIM::Function *>(destroy))
777  || modelDriverCreate->SetRoutinePointer(
780  true,
781  reinterpret_cast<KIM::Function *>(refresh))
782  || modelDriverCreate->SetRoutinePointer(
785  true,
786  reinterpret_cast<KIM::Function *>(compute))
787  || modelDriverCreate->SetRoutinePointer(
790  true,
791  reinterpret_cast<KIM::Function *>(CACreate))
792  || modelDriverCreate->SetRoutinePointer(
795  true,
796  reinterpret_cast<KIM::Function *>(CADestroy));
797  return error;
798 }
799 
800 //******************************************************************************
801 template<class ModelObj>
802 int LennardJones612Implementation::SetRefreshMutableValues(
803  ModelObj * const modelObj)
804 { // use (possibly) new values of parameters to compute other quantities
805  // NOTE: This function is templated because it's called with both a
806  // modelDriverCreate object during initialization and with a
807  // modelRefresh object when the Model's parameters have been altered
808  int ier;
809 
810  // update cutoffsSq, epsilons, and sigmas
811  for (int i = 0; i < numberModelSpecies_; ++i)
812  {
813  for (int j = 0; j <= i; ++j)
814  {
815  int const index = j * numberModelSpecies_ + i - (j * j + j) / 2;
816  cutoffsSq2D_[i][j] = cutoffsSq2D_[j][i]
817  = (cutoffs_[index] * cutoffs_[index]);
818  fourEpsilonSigma6_2D_[i][j] = fourEpsilonSigma6_2D_[j][i]
819  = 4.0 * epsilons_[index] * pow(sigmas_[index], 6.0);
820  fourEpsilonSigma12_2D_[i][j] = fourEpsilonSigma12_2D_[j][i]
821  = 4.0 * epsilons_[index] * pow(sigmas_[index], 12.0);
822  twentyFourEpsilonSigma6_2D_[i][j] = twentyFourEpsilonSigma6_2D_[j][i]
823  = 6.0 * fourEpsilonSigma6_2D_[i][j];
824  fortyEightEpsilonSigma12_2D_[i][j] = fortyEightEpsilonSigma12_2D_[j][i]
825  = 12.0 * fourEpsilonSigma12_2D_[i][j];
826  oneSixtyEightEpsilonSigma6_2D_[i][j]
827  = oneSixtyEightEpsilonSigma6_2D_[j][i]
828  = 7.0 * twentyFourEpsilonSigma6_2D_[i][j];
829  sixTwentyFourEpsilonSigma12_2D_[i][j]
830  = sixTwentyFourEpsilonSigma12_2D_[j][i]
831  = 13.0 * fortyEightEpsilonSigma12_2D_[i][j];
832  }
833  }
834 
835  // update cutoff value in KIM API object
836  influenceDistance_ = 0.0;
837 
838  for (int i = 0; i < numberModelSpecies_; i++)
839  {
840  int indexI = modelSpeciesCodeList_[i];
841 
842  for (int j = 0; j < numberModelSpecies_; j++)
843  {
844  int indexJ = modelSpeciesCodeList_[j];
845 
846  if (influenceDistance_ < cutoffsSq2D_[indexI][indexJ])
847  { influenceDistance_ = cutoffsSq2D_[indexI][indexJ]; }
848  }
849  }
850 
851  influenceDistance_ = sqrt(influenceDistance_);
852  modelObj->SetInfluenceDistancePointer(&influenceDistance_);
853  modelObj->SetNeighborListPointers(
854  1,
855  &influenceDistance_,
856  &modelWillNotRequestNeighborsOfNoncontributingParticles_);
857 
858  // update shifts
859  // compute and set shifts2D_ check if minus sign
860  double const * const * const constFourEpsSig6_2D = fourEpsilonSigma6_2D_;
861  double const * const * const constFourEpsSig12_2D = fourEpsilonSigma12_2D_;
862  if (1 == shift_)
863  {
864  double phi;
865  for (int iSpecies = 0; iSpecies < numberModelSpecies_; iSpecies++)
866  {
867  for (int jSpecies = 0; jSpecies <= iSpecies; jSpecies++)
868  {
869  int const index = jSpecies * numberModelSpecies_ + iSpecies
870  - (jSpecies * jSpecies + jSpecies) / 2;
871  double const rij2 = cutoffs_[index] * cutoffs_[index];
872  double const r2iv = 1.0 / rij2;
873  double const r6iv = r2iv * r2iv * r2iv;
875  shifts2D_[iSpecies][jSpecies] = shifts2D_[jSpecies][iSpecies] = phi;
876  }
877  }
878  }
879 
880  // everything is good
881  ier = false;
882  return ier;
883 }
884 
885 //******************************************************************************
886 #undef KIM_LOGGER_OBJECT_NAME
887 #define KIM_LOGGER_OBJECT_NAME modelComputeArguments
888 //
889 int LennardJones612Implementation::SetComputeMutableValues(
890  KIM::ModelComputeArguments const * const modelComputeArguments,
891  bool & isComputeProcess_dEdr,
892  bool & isComputeProcess_d2Edr2,
893  bool & isComputeEnergy,
894  bool & isComputeForces,
895  bool & isComputeParticleEnergy,
896  bool & isComputeVirial,
897  bool & isComputeParticleVirial,
898  int const *& particleSpeciesCodes,
899  int const *& particleContributing,
900  VectorOfSizeDIM const *& coordinates,
901  double *& energy,
902  double *& particleEnergy,
903  VectorOfSizeDIM *& forces,
904  VectorOfSizeSix *& virial,
905  VectorOfSizeSix *& particleVirial)
906 {
907  int ier = true;
908 
909  // get compute flags
910  int compProcess_dEdr;
911  int compProcess_d2Edr2;
912 
913  modelComputeArguments->IsCallbackPresent(
915  modelComputeArguments->IsCallbackPresent(
916  KIM::COMPUTE_CALLBACK_NAME::ProcessD2EDr2Term, &compProcess_d2Edr2);
917 
918  isComputeProcess_dEdr = compProcess_dEdr;
919  isComputeProcess_d2Edr2 = compProcess_d2Edr2;
920 
921  int const * numberOfParticles;
922  ier = modelComputeArguments->GetArgumentPointer(
924  || modelComputeArguments->GetArgumentPointer(
927  || modelComputeArguments->GetArgumentPointer(
930  || modelComputeArguments->GetArgumentPointer(
932  (double const **) &coordinates)
933  || modelComputeArguments->GetArgumentPointer(
935  || modelComputeArguments->GetArgumentPointer(
937  || modelComputeArguments->GetArgumentPointer(
939  (double const **) &forces)
940  || modelComputeArguments->GetArgumentPointer(
942  (double const **) &virial)
943  || modelComputeArguments->GetArgumentPointer(
945  (double const **) &particleVirial);
946  if (ier)
947  {
948  LOG_ERROR("GetArgumentPointer");
949  return ier;
950  }
951 
952  isComputeEnergy = (energy != NULL);
953  isComputeParticleEnergy = (particleEnergy != NULL);
954  isComputeForces = (forces != NULL);
955  isComputeVirial = (virial != NULL);
956  isComputeParticleVirial = (particleVirial != NULL);
957 
958  // update values
959  cachedNumberOfParticles_ = *numberOfParticles;
960 
961  // everything is good
962  ier = false;
963  return ier;
964 }
965 
966 //******************************************************************************
967 #undef KIM_LOGGER_OBJECT_NAME
968 #define KIM_LOGGER_OBJECT_NAME modelCompute
969 int LennardJones612Implementation::CheckParticleSpeciesCodes(
970  KIM::ModelCompute const * const modelCompute,
971  int const * const particleSpeciesCodes) const
972 {
973  int ier;
974  for (int i = 0; i < cachedNumberOfParticles_; ++i)
975  {
976  if ((particleSpeciesCodes[i] < 0)
977  || (particleSpeciesCodes[i] >= numberModelSpecies_))
978  {
979  ier = true;
980  LOG_ERROR("unsupported particle species codes detected");
981  return ier;
982  }
983  }
984 
985  // everything is good
986  ier = false;
987  return ier;
988 }
989 
990 //******************************************************************************
991 int LennardJones612Implementation::GetComputeIndex(
992  const bool & isComputeProcess_dEdr,
993  const bool & isComputeProcess_d2Edr2,
994  const bool & isComputeEnergy,
995  const bool & isComputeForces,
996  const bool & isComputeParticleEnergy,
997  const bool & isComputeVirial,
998  const bool & isComputeParticleVirial,
999  const bool & isShift) const
1000 {
1001  // const int processdE = 2;
1002  const int processd2E = 2;
1003  const int energy = 2;
1004  const int force = 2;
1005  const int particleEnergy = 2;
1006  const int virial = 2;
1007  const int particleVirial = 2;
1008  const int shift = 2;
1009 
1010 
1011  int index = 0;
1012 
1013  // processdE
1014  index += (int(isComputeProcess_dEdr)) * processd2E * energy * force
1015  * particleEnergy * virial * particleVirial * shift;
1016 
1017  // processd2E
1018  index += (int(isComputeProcess_d2Edr2)) * energy * force * particleEnergy
1019  * virial * particleVirial * shift;
1020 
1021  // energy
1022  index += (int(isComputeEnergy)) * force * particleEnergy * virial
1023  * particleVirial * shift;
1024 
1025  // force
1026  index += (int(isComputeForces)) * particleEnergy * virial * particleVirial
1027  * shift;
1028 
1029  // particleEnergy
1030  index += (int(isComputeParticleEnergy)) * virial * particleVirial * shift;
1031 
1032  // virial
1033  index += (int(isComputeVirial)) * particleVirial * shift;
1034 
1035  // particleVirial
1036  index += (int(isComputeParticleVirial)) * shift;
1037 
1038  // shift
1039  index += (int(isShift));
1040 
1041  return index;
1042 }
1043 
1044 //******************************************************************************
1045 void LennardJones612Implementation::ProcessVirialTerm(
1046  const double & dEidr,
1047  const double & rij,
1048  const double * const r_ij,
1049  const int & i,
1050  const int & j,
1051  VectorOfSizeSix virial) const
1052 {
1053  (void) i; // avoid unused parameter warning
1054  (void) j;
1055 
1056  double const v = dEidr / rij;
1057 
1058  virial[0] += v * r_ij[0] * r_ij[0];
1059  virial[1] += v * r_ij[1] * r_ij[1];
1060  virial[2] += v * r_ij[2] * r_ij[2];
1061  virial[3] += v * r_ij[1] * r_ij[2];
1062  virial[4] += v * r_ij[0] * r_ij[2];
1063  virial[5] += v * r_ij[0] * r_ij[1];
1064 }
1065 
1066 //******************************************************************************
1067 void LennardJones612Implementation::ProcessParticleVirialTerm(
1068  const double & dEidr,
1069  const double & rij,
1070  const double * const r_ij,
1071  const int & i,
1072  const int & j,
1073  VectorOfSizeSix * const particleVirial) const
1074 {
1075  double const v = dEidr / rij;
1076  VectorOfSizeSix vir;
1077 
1078  vir[0] = 0.5 * v * r_ij[0] * r_ij[0];
1079  vir[1] = 0.5 * v * r_ij[1] * r_ij[1];
1080  vir[2] = 0.5 * v * r_ij[2] * r_ij[2];
1081  vir[3] = 0.5 * v * r_ij[1] * r_ij[2];
1082  vir[4] = 0.5 * v * r_ij[0] * r_ij[2];
1083  vir[5] = 0.5 * v * r_ij[0] * r_ij[1];
1084 
1085  for (int k = 0; k < 6; ++k)
1086  {
1087  particleVirial[i][k] += vir[k];
1088  particleVirial[j][k] += vir[k];
1089  }
1090 }
1091 
1092 //==============================================================================
1093 //
1094 // Implementation of helper functions
1095 //
1096 //==============================================================================
1097 
1098 //******************************************************************************
1099 void AllocateAndInitialize2DArray(double **& arrayPtr,
1100  int const extentZero,
1101  int const extentOne)
1102 { // allocate memory and set pointers
1103  arrayPtr = new double *[extentZero];
1104  arrayPtr[0] = new double[extentZero * extentOne];
1105  for (int i = 1; i < extentZero; ++i)
1106  { arrayPtr[i] = arrayPtr[i - 1] + extentOne; }
1107 
1108  // initialize
1109  for (int i = 0; i < extentZero; ++i)
1110  {
1111  for (int j = 0; j < extentOne; ++j) { arrayPtr[i][j] = 0.0; }
1112  }
1113 }
1114 
1115 //******************************************************************************
1116 void Deallocate2DArray(double **& arrayPtr)
1117 { // deallocate memory
1118  if (arrayPtr != NULL) delete[] arrayPtr[0];
1119  delete[] arrayPtr;
1120 
1121  // nullify pointer
1122  arrayPtr = NULL;
1123 }
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.
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.
int GetParameterFileName(int const index, std::string const **const parameterFileName) const
Get a particular parameter file name.
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.
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.