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