1 /*
2 *
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the Common Development
6 * and Distribution License Version 1.0 (the "License").
7 *
8 * You can obtain a copy of the license at
9 * http://www.opensource.org/licenses/CDDL-1.0.  See the License for the
10 * specific language governing permissions and limitations under the License.
11 *
12 * When distributing Covered Code, include this CDDL HEADER in each file and
13 * include the License file in a prominent location with the name LICENSE.CDDL.
14 * If applicable, add the following below this CDDL HEADER, with the fields
15 * enclosed by brackets "[]" replaced with your own identifying information:
16 *
17 * Portions Copyright (c) [yyyy] [name of copyright owner]. All rights reserved.
18 *
19 * CDDL HEADER END
20 *
21 
22 *
23 * Copyright (c) 2013, Regents of the University of Minnesota.
24 * All rights reserved.
25 *
26 * Contributors:
27 *    Ryan S. Elliott
28 *    Ellad B. Tadmor
29 *    Stephen M. Whalen
30 *
31 */
32 
33 /*******************************************************************************
34  *
35  *  EAM_NN_Johnson_1988_Cu
36  *
37  *  Johnson pair functional model for Cu
38  *
39  *  Reference: R. A. Johnson, "Analytic nearest-neighbor model for fcc metals",
40  *             Phys. Rev. B, 55(8):4941-4946, 1988.
41  *
42  *  Language: C
43  *
44  *******************************************************************************/
45 
46 
47 #include "KIM_ModelHeaders.h"
48 #include <math.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 
53 #include "KIM_LogMacros.h"
54 
55 #define TRUE 1
56 #define FALSE 0
57 
58 /******************************************************************************
59  * Below are the definitions and values of all Model parameters
60  *******************************************************************************/
61 #define DIM 3 /* dimensionality of space */
62 #define SPECCODE 1 /* internal species code */
63 #define MODEL_CUTOFF 3.5 /* cutoff radius in angstroms */
64 #define MODEL_CUTSQ (MODEL_CUTOFF * MODEL_CUTOFF)
65 #define JEAM_R0 2.556 /* A */
66 #define JEAM_PHI0 0.59 /* eV */
67 #define JEAM_GAM 8.00
68 #define JEAM_G0 0.30 /* eV */
69 #define JEAM_BET 5.85
70 #define JEAM_EC 3.54 /* eV/atom */
71 #define JEAM_ALF 5.09
72 #define JEAM_RHO0 3.60 /* eV (=12*JEAM_G0) */
73 
74 /* Model buffer definition */
75 struct buffer
76 {
77   int modelWillNotRequestNeighborsOfNoncontributingParticles;
78 
79   double influenceDistance;
80   double cutoff;
81 };
82 typedef struct buffer buffer;
83 
84 /* Define prototype for Model create */
85 int model_create(KIM_ModelCreate * const modelCreate,
86                  KIM_LengthUnit const requestedLengthUnit,
87                  KIM_EnergyUnit const requestedEnergyUnit,
88                  KIM_ChargeUnit const requestedChargeUnit,
89                  KIM_TemperatureUnit const requestedTemperatureUnit,
90                  KIM_TimeUnit const requestedTimeUnit);
91 
92 /* Define prototypes for model reinit, compute, and destroy */
93 /* defined as static to avoid namespace clashes with other Models */
94 /**/
95 static int
96 compute(KIM_ModelCompute const * const modelCompute,
97         KIM_ModelComputeArguments const * const modelComputeArguments);
98 static int compute_arguments_create(
99     KIM_ModelCompute const * const modelCompute,
100     KIM_ModelComputeArgumentsCreate * const modelComputeArgumentsCreate);
101 static int compute_arguments_destroy(
102     KIM_ModelCompute const * const modelCompute,
103     KIM_ModelComputeArgumentsDestroy * const modelComputeArgumentsDestroy);
104 
105 static int model_destroy(KIM_ModelDestroy * const modelDestroy);
106 /**/
107 static void calc_phi(double r, double * phi);
108 static void calc_phi_dphi(double r, double * phi, double * dphi);
109 static void calc_g(double r, double * g);
110 static void calc_dg(double r, double * dg);
111 static void calc_U(double rho, double * U);
112 static void calc_U_dU(double rho, double * U, double * dU);
113 
114 /* Calculate pair potential phi(r) */
calc_phi(double r,double * phi)115 static void calc_phi(double r, double * phi)
116 {
117   /* local variables */
118   double rnorm;
119 
120   if (r > MODEL_CUTOFF)
121   {
122     /* Argument exceeds cutoff radius */
123     *phi = 0.0;
124   }
125   else
126   {
127     rnorm = r / JEAM_R0;
128     *phi = JEAM_PHI0 * exp(-JEAM_GAM * (rnorm - 1.0));
129   }
130 
131   return;
132 }
133 
134 /* Calculate pair potential phi(r) and its derivative dphi(r) */
calc_phi_dphi(double r,double * phi,double * dphi)135 static void calc_phi_dphi(double r, double * phi, double * dphi)
136 {
137   /* local variables */
138   double rnorm;
139 
140   if (r > MODEL_CUTOFF)
141   {
142     /* Argument exceeds cutoff radius */
143     *phi = 0.0;
144     *dphi = 0.0;
145   }
146   else
147   {
148     rnorm = r / JEAM_R0;
149     *phi = JEAM_PHI0 * exp(-JEAM_GAM * (rnorm - 1.0));
150     *dphi = -(JEAM_GAM / JEAM_R0) * (*phi);
151   }
152 
153   return;
154 }
155 
156 /* Calculate electron density g(r) */
calc_g(double r,double * g)157 static void calc_g(double r, double * g)
158 {
159   /* local variables */
160   double rnorm;
161 
162   if (r > MODEL_CUTOFF)
163   {
164     /* Argument exceeds cutoff radius */
165     *g = 0.0;
166   }
167   else
168   {
169     rnorm = r / JEAM_R0;
170     *g = JEAM_G0 * exp(-JEAM_BET * (rnorm - 1.0));
171   }
172 
173   return;
174 }
175 
176 /* Calculate electron density derivative dg(r) */
calc_dg(double r,double * dg)177 static void calc_dg(double r, double * dg)
178 {
179   /* local variables */
180   double rnorm;
181   double g;
182 
183   if (r > MODEL_CUTOFF)
184   {
185     /* Argument exceeds cutoff radius */
186     *dg = 0.0;
187   }
188   else
189   {
190     rnorm = r / JEAM_R0;
191     g = JEAM_G0 * exp(-JEAM_BET * (rnorm - 1.0));
192     *dg = -(JEAM_BET / JEAM_R0) * g;
193   }
194 
195   return;
196 }
197 
198 /* Calculate embedding function U(rho) */
calc_U(double rho,double * U)199 static void calc_U(double rho, double * U)
200 {
201   /* local variables */
202   double rhonorm;
203   double rhonorm_gob;
204   double rhonorm_aob;
205   double logrhonorm;
206   double aob;
207   double gob;
208 
209   if (rho == 0.0)
210   {
211     *U = 0.0;
212 
213     return;
214   }
215 
216   aob = JEAM_ALF / JEAM_BET;
217   gob = JEAM_GAM / JEAM_BET;
218   rhonorm = rho / JEAM_RHO0;
219   rhonorm_aob = pow(rhonorm, aob);
220   rhonorm_gob = pow(rhonorm, gob);
221   logrhonorm = log(rhonorm);
222 
223   *U = -JEAM_EC * (1.0 - aob * logrhonorm) * rhonorm_aob
224        - 6.0 * JEAM_PHI0 * rhonorm_gob;
225 
226   return;
227 }
228 
229 /* Calculate embedding function U(rho) and first derivative dU(rho) */
calc_U_dU(double rho,double * U,double * dU)230 static void calc_U_dU(double rho, double * U, double * dU)
231 {
232   /* local variables */
233   double rhonorm;
234   double rhonorm_gob;
235   double rhonorm_aob;
236   double logrhonorm;
237   double aob;
238   double gob;
239 
240   if (rho == 0.0)
241   {
242     *U = 0.0;
243     *dU = 0.0;
244 
245     return;
246   }
247 
248   aob = JEAM_ALF / JEAM_BET;
249   gob = JEAM_GAM / JEAM_BET;
250   rhonorm = rho / JEAM_RHO0;
251   rhonorm_aob = pow(rhonorm, aob);
252   rhonorm_gob = pow(rhonorm, gob);
253   logrhonorm = log(rhonorm);
254 
255   *U = -JEAM_EC * (1.0 - aob * logrhonorm) * rhonorm_aob
256        - 6.0 * JEAM_PHI0 * rhonorm_gob;
257   *dU = (JEAM_EC * aob * aob * logrhonorm * rhonorm_aob
258          - 6.0 * JEAM_PHI0 * gob * rhonorm_gob)
259         / rho;
260 
261   return;
262 }
263 
264 /* compute function */
265 #undef KIM_LOGGER_FUNCTION_NAME
266 #define KIM_LOGGER_FUNCTION_NAME KIM_ModelCompute_LogEntry
267 #undef KIM_LOGGER_OBJECT_NAME
268 #define KIM_LOGGER_OBJECT_NAME modelCompute
269 static int
compute(KIM_ModelCompute const * const modelCompute,KIM_ModelComputeArguments const * const modelComputeArguments)270 compute(KIM_ModelCompute const * const modelCompute,
271         KIM_ModelComputeArguments const * const modelComputeArguments)
272 {
273   double r;
274   double Rij[DIM];
275   double Rsqij;
276   double phi;
277   double dphi;
278   double g;
279   double dg;
280   double dU;
281   double dphieff = 0.0;
282   double dphii;
283   double dUi;
284   double Ei;
285   double dphij;
286   double dUj;
287   double Ej;
288   int ier;
289   int i;
290   int j;
291   int jj;
292   int k;
293   int comp_force;
294   int comp_particleEnergy;
295   int comp_virial;
296   int comp_energy;
297   double * rho;
298   double U;
299   double * derU = 0;
300 
301   int const * neighListOfCurrentPart;
302   int numOfPartNeigh;
303   int * nParts;
304   double * energy;
305   double * coords;
306   double * force;
307   double * particleEnergy;
308 
309   int * particleContributing;
310   int * particleSpeciesCodes;
311   double * virial;
312 
313   LOG_INFORMATION("Getting data pointers");
314   ier = KIM_ModelComputeArguments_GetArgumentPointerInteger(
315             modelComputeArguments,
316             KIM_COMPUTE_ARGUMENT_NAME_numberOfParticles,
317             &nParts)
318         || KIM_ModelComputeArguments_GetArgumentPointerInteger(
319                modelComputeArguments,
320                KIM_COMPUTE_ARGUMENT_NAME_particleSpeciesCodes,
321                &particleSpeciesCodes)
322         || KIM_ModelComputeArguments_GetArgumentPointerInteger(
323                modelComputeArguments,
324                KIM_COMPUTE_ARGUMENT_NAME_particleContributing,
325                &particleContributing)
326         || KIM_ModelComputeArguments_GetArgumentPointerDouble(
327                modelComputeArguments,
328                KIM_COMPUTE_ARGUMENT_NAME_coordinates,
329                &coords)
330         || KIM_ModelComputeArguments_GetArgumentPointerDouble(
331                modelComputeArguments,
332                KIM_COMPUTE_ARGUMENT_NAME_partialEnergy,
333                &energy)
334         || KIM_ModelComputeArguments_GetArgumentPointerDouble(
335                modelComputeArguments,
336                KIM_COMPUTE_ARGUMENT_NAME_partialForces,
337                &force)
338         || KIM_ModelComputeArguments_GetArgumentPointerDouble(
339                modelComputeArguments,
340                KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy,
341                &particleEnergy)
342         || KIM_ModelComputeArguments_GetArgumentPointerDouble(
343                modelComputeArguments,
344                KIM_COMPUTE_ARGUMENT_NAME_partialVirial,
345                &virial);
346 
347   if (ier)
348   {
349     LOG_ERROR("get data pointers failed");
350     return ier;
351   }
352 
353   comp_energy = (energy != 0);
354   comp_force = (force != 0);
355   comp_particleEnergy = (particleEnergy != 0);
356   comp_virial = (virial != 0);
357 
358   /* Check to be sure that the species are correct */
359   /**/
360   ier = TRUE; /* assume an error */
361   for (i = 0; i < *nParts; ++i)
362   {
363     if (SPECCODE != particleSpeciesCodes[i])
364     {
365       LOG_ERROR("Unexpected species code detected");
366       return ier;
367     }
368   }
369   ier = FALSE; /* everything is ok */
370 
371   /* initialize potential energies, forces, and virial term */
372   /* Note: that the variable `particleEnergy' does not need to be initialized
373    * because it's initial value is set during the embedding energy calculation.
374    */
375   if (comp_energy) { *energy = 0.0; }
376 
377   if (comp_force)
378   {
379     for (i = 0; i < *nParts; ++i)
380     {
381       for (k = 0; k < DIM; ++k) { force[i * DIM + k] = 0.0; }
382     }
383   }
384 
385   if (comp_virial)
386   {
387     for (i = 0; i < 6; ++i) { virial[i] = 0.0; }
388   }
389 
390   /* pair functional electron density */
391   rho = (double *) malloc((*nParts) * sizeof(double));
392   for (i = 0; i < *nParts; ++i) { rho[i] = 0.0; }
393 
394   /* EAM embedded energy deriv */
395   if ((comp_force) || (comp_virial))
396   { derU = (double *) malloc((*nParts) * sizeof(double)); }
397 
398   /* loop over particles in the neighbor list a first time,
399    * to compute electron density (=coordination)
400    */
401   LOG_INFORMATION("Starting first compute loop for elctron density");
402   for (i = 0; i < *nParts; ++i)
403   {
404     if (particleContributing[i])
405     {
406       ier = KIM_ModelComputeArguments_GetNeighborList(modelComputeArguments,
407                                                       0,
408                                                       i,
409                                                       &numOfPartNeigh,
410                                                       &neighListOfCurrentPart);
411       if (ier)
412       {
413         /* some sort of problem, exit */
414         LOG_ERROR("GetNeighborList failed");
415         ier = TRUE;
416         return ier;
417       }
418 
419       /* loop over the neighbors of particle i */
420       for (jj = 0; jj < numOfPartNeigh; ++jj)
421       {
422         j = neighListOfCurrentPart[jj]; /* get neighbor ID */
423 
424         if (!(particleContributing[j] && j < i)) /* short-circuit half-list */
425         {
426           /* compute relative position vector and squared distance */
427           Rsqij = 0.0;
428           for (k = 0; k < DIM; ++k)
429           {
430             Rij[k] = coords[j * DIM + k] - coords[i * DIM + k];
431 
432             /* compute squared distance */
433             Rsqij += Rij[k] * Rij[k];
434           }
435 
436           /* compute contribution to electron density */
437           if (Rsqij < MODEL_CUTSQ) /* particles are interacting ? */
438           {
439             r = sqrt(Rsqij); /* compute distance */
440             calc_g(r, &g); /* compute electron density */
441             rho[i] += g; /* accumulate electron density */
442 
443             if (particleContributing[j]) { rho[j] += g; }
444           }
445         }
446       } /* loop on jj */
447     } /* if contributing */
448   } /* loop on i */
449 
450   /* Now that we know the electron densities, calculate embedding part
451    * of energy U and its derivative U' (derU)
452    */
453   LOG_INFORMATION("Starting second compute loop for embedding part of energy");
454   for (i = 0; i < *nParts; ++i)
455   {
456     if (particleContributing[i])
457     {
458       if (comp_force || comp_virial)
459       {
460         calc_U_dU(
461             rho[i], &U, &dU); /* compute embedding energy and its derivative */
462         derU[i] = dU; /* store dU for later use */
463       }
464       else
465       {
466         calc_U(rho[i], &U); /* compute just embedding energy */
467       }
468 
469       /* accumulate the embedding energy contribution */
470       /* Assuming U)rho=0) = 0.0 */
471       if (comp_particleEnergy) { particleEnergy[i] += U; }
472       else if (comp_energy)
473       {
474         *energy += U;
475       }
476     }
477   }
478 
479   /* Loop over particles in the neighbor list a second time to compute
480    * the forces and complete energy calculation
481    */
482 
483   LOG_INFORMATION("Starting thrid compute loop for forces and energy");
484   for (i = 0; i < *nParts; ++i)
485   {
486     if (particleContributing[i])
487     {
488       ier = KIM_ModelComputeArguments_GetNeighborList(modelComputeArguments,
489                                                       0,
490                                                       i,
491                                                       &numOfPartNeigh,
492                                                       &neighListOfCurrentPart);
493       if (ier)
494       {
495         /* some sort of problem, exit */
496         LOG_ERROR("GetNeighborList failed");
497         ier = TRUE;
498         return ier;
499       }
500       /* loop over the neighbors of atom i */
501       for (jj = 0; jj < numOfPartNeigh; ++jj)
502       {
503         j = neighListOfCurrentPart[jj]; /* get neighbor ID */
504 
505         if (!(particleContributing[j] && j < i)) /* short-circuit half-list */
506         {
507           /* compute relative position vector and squared distance */
508           Rsqij = 0.0;
509           for (k = 0; k < DIM; ++k)
510           {
511             Rij[k] = coords[j * DIM + k] - coords[i * DIM + k];
512 
513             /* compute squared distance */
514             Rsqij += Rij[k] * Rij[k];
515           }
516 
517           /* compute energy and force */
518           if (Rsqij < MODEL_CUTSQ) /* particles are interacting ? */
519           {
520             r = sqrt(Rsqij);
521             if (comp_force || comp_virial)
522             {
523               /* compute pair potential and its derivative */
524               calc_phi_dphi(r, &phi, &dphi);
525 
526               /* copmute elect dens first deriv */
527               calc_dg(r, &dg);
528 
529               /* compute dEidr */
530 
531               /* HALF mode -- double contribution */
532               if (particleContributing[j])
533               {
534                 dphii = 0.5 * dphi;
535                 dphij = 0.5 * dphi;
536                 dUi = derU[i] * dg;
537                 dUj = derU[j] * dg;
538               }
539               else
540               {
541                 dphii = 0.5 * dphi;
542                 dphij = 0.0;
543                 dUi = derU[i] * dg;
544                 dUj = 0.0;
545               }
546 
547               dphieff = dphii + dphij + dUi + dUj;
548             }
549             else
550             {
551               /* compute just pair potential */
552               calc_phi(r, &phi);
553             }
554 
555 
556             /* HALF mode */
557             Ei = 0.5 * phi;
558             if (particleContributing[j])
559               Ej = 0.5 * phi;
560             else
561               Ej = 0.0;
562 
563             /* contribution to energy */
564             if (comp_particleEnergy)
565             {
566               particleEnergy[i] += Ei; /* accumulate energy Ei */
567               particleEnergy[j] += Ej; /* accumulate energy Ej */
568             }
569             if (comp_energy)
570             {
571               *energy += Ei; /* accumulate energy */
572               *energy += Ej; /* accumulate energy */
573             }
574 
575             /* contribution to virial tensor */
576             if (comp_virial)
577             {
578               /* virial(i,j) = r(i)*r(j)*(dV/dr)/r */
579               virial[0] += Rij[0] * Rij[0] * dphieff / r;
580               virial[1] += Rij[1] * Rij[1] * dphieff / r;
581               virial[2] += Rij[2] * Rij[2] * dphieff / r;
582               virial[3] += Rij[1] * Rij[2] * dphieff / r;
583               virial[4] += Rij[0] * Rij[2] * dphieff / r;
584               virial[5] += Rij[0] * Rij[1] * dphieff / r;
585             }
586 
587             /* contribution to forces */
588             if (comp_force)
589             { /* Ei contribution */
590               for (k = 0; k < DIM; ++k)
591               {
592                 force[i * DIM + k]
593                     += dphieff * Rij[k] / r; /* accumulate force on atom i */
594                 force[j * DIM + k]
595                     -= dphieff * Rij[k] / r; /* accumulate force on atom j */
596               }
597             }
598           }
599         }
600       } /* loop on jj */
601     } /* if contributing */
602   } /* loop on i */
603   LOG_INFORMATION("Finished compute loop");
604 
605   /* Free temporary storage */
606   free(rho);
607   if (comp_force || comp_virial) { free(derU); }
608 
609   /* everything is great */
610   ier = FALSE;
611 
612   return ier;
613 }
614 
615 
616 /* Create function */
617 /* Define prototype for Model create */
618 #undef KIM_LOGGER_FUNCTION_NAME
619 #define KIM_LOGGER_FUNCTION_NAME KIM_ModelCreate_LogEntry
620 #undef KIM_LOGGER_OBJECT_NAME
621 #define KIM_LOGGER_OBJECT_NAME modelCreate
model_create(KIM_ModelCreate * const modelCreate,KIM_LengthUnit const requestedLengthUnit,KIM_EnergyUnit const requestedEnergyUnit,KIM_ChargeUnit const requestedChargeUnit,KIM_TemperatureUnit const requestedTemperatureUnit,KIM_TimeUnit const requestedTimeUnit)622 int model_create(KIM_ModelCreate * const modelCreate,
623                  KIM_LengthUnit const requestedLengthUnit,
624                  KIM_EnergyUnit const requestedEnergyUnit,
625                  KIM_ChargeUnit const requestedChargeUnit,
626                  KIM_TemperatureUnit const requestedTemperatureUnit,
627                  KIM_TimeUnit const requestedTimeUnit)
628 {
629   buffer * bufferPointer;
630   int error;
631 
632   /* set units */
633   LOG_INFORMATION("Set model units");
634   error = KIM_ModelCreate_SetUnits(modelCreate, /* ignoring requested units */
635                                    KIM_LENGTH_UNIT_A,
636                                    KIM_ENERGY_UNIT_eV,
637                                    KIM_CHARGE_UNIT_unused,
638                                    KIM_TEMPERATURE_UNIT_unused,
639                                    KIM_TIME_UNIT_unused);
640 
641   /* register species */
642   LOG_INFORMATION("Setting species code");
643   error = error
644           || KIM_ModelCreate_SetSpeciesCode(
645                  modelCreate, KIM_SPECIES_NAME_Cu, SPECCODE);
646 
647   /* register numbering */
648   LOG_INFORMATION("Setting model numbering");
649   error = error
650           || KIM_ModelCreate_SetModelNumbering(modelCreate,
651                                                KIM_NUMBERING_zeroBased);
652 
653   /* register function pointers */
654   LOG_INFORMATION("Register model function pointers");
655   error = error
656           || KIM_ModelCreate_SetRoutinePointer(modelCreate,
657                                                KIM_MODEL_ROUTINE_NAME_Compute,
658                                                KIM_LANGUAGE_NAME_c,
659                                                TRUE,
660                                                (KIM_Function *) &compute);
661   error = error
662           || KIM_ModelCreate_SetRoutinePointer(
663                  modelCreate,
664                  KIM_MODEL_ROUTINE_NAME_ComputeArgumentsCreate,
665                  KIM_LANGUAGE_NAME_c,
666                  TRUE,
667                  (KIM_Function *) &compute_arguments_create);
668   error = error
669           || KIM_ModelCreate_SetRoutinePointer(
670                  modelCreate,
671                  KIM_MODEL_ROUTINE_NAME_ComputeArgumentsDestroy,
672                  KIM_LANGUAGE_NAME_c,
673                  TRUE,
674                  (KIM_Function *) &compute_arguments_destroy);
675   error = error
676           || KIM_ModelCreate_SetRoutinePointer(modelCreate,
677                                                KIM_MODEL_ROUTINE_NAME_Destroy,
678                                                KIM_LANGUAGE_NAME_c,
679                                                TRUE,
680                                                (KIM_Function *) &model_destroy);
681 
682   /* allocate buffer */
683   bufferPointer = (buffer *) malloc(sizeof(buffer));
684 
685   /* store model buffer in KIM object */
686   LOG_INFORMATION("Set influence distance and cutoffs");
687   KIM_ModelCreate_SetModelBufferPointer(modelCreate, bufferPointer);
688 
689   /* set buffer values */
690   bufferPointer->influenceDistance = MODEL_CUTOFF;
691   bufferPointer->cutoff = MODEL_CUTOFF;
692   bufferPointer->modelWillNotRequestNeighborsOfNoncontributingParticles = 1;
693 
694   /* register influence distance */
695   KIM_ModelCreate_SetInfluenceDistancePointer(
696       modelCreate, &(bufferPointer->influenceDistance));
697 
698   /* register cutoff */
699   KIM_ModelCreate_SetNeighborListPointers(
700       modelCreate,
701       1,
702       &(bufferPointer->cutoff),
703       (const int *) &(
704           bufferPointer
705               ->modelWillNotRequestNeighborsOfNoncontributingParticles));
706 
707   if (error)
708   {
709     free(bufferPointer);
710     LOG_ERROR("Unable to successfully initialize model");
711     return TRUE;
712   }
713   else
714   {
715     return FALSE;
716   }
717 }
718 
719 /* Initialization function */
720 #undef KIM_LOGGER_FUNCTION_NAME
721 #define KIM_LOGGER_FUNCTION_NAME KIM_ModelDestroy_LogEntry
722 #undef KIM_LOGGER_OBJECT_NAME
723 #define KIM_LOGGER_OBJECT_NAME modelDestroy
model_destroy(KIM_ModelDestroy * const modelDestroy)724 int model_destroy(KIM_ModelDestroy * const modelDestroy)
725 {
726   buffer * bufferPointer;
727 
728   LOG_INFORMATION("Getting buffer");
729   KIM_ModelDestroy_GetModelBufferPointer(modelDestroy,
730                                          (void **) &bufferPointer);
731   LOG_INFORMATION("Freeing model memory");
732   free(bufferPointer);
733 
734   return FALSE;
735 }
736 
737 /* compute arguments create routine */
738 #undef KIM_LOGGER_FUNCTION_NAME
739 #define KIM_LOGGER_FUNCTION_NAME KIM_ModelComputeArgumentsCreate_LogEntry
740 #undef KIM_LOGGER_OBJECT_NAME
741 #define KIM_LOGGER_OBJECT_NAME modelComputeArgumentsCreate
compute_arguments_create(KIM_ModelCompute const * const modelCompute,KIM_ModelComputeArgumentsCreate * const modelComputeArgumentsCreate)742 static int compute_arguments_create(
743     KIM_ModelCompute const * const modelCompute,
744     KIM_ModelComputeArgumentsCreate * const modelComputeArgumentsCreate)
745 {
746   int error;
747 
748   (void) modelCompute; /* Avoid unused argument warning */
749 
750   /* register arguments */
751   LOG_INFORMATION("Register argument supportStatus");
752   error = KIM_ModelComputeArgumentsCreate_SetArgumentSupportStatus(
753       modelComputeArgumentsCreate,
754       KIM_COMPUTE_ARGUMENT_NAME_partialEnergy,
755       KIM_SUPPORT_STATUS_optional);
756 
757   error = error
758           || KIM_ModelComputeArgumentsCreate_SetArgumentSupportStatus(
759                  modelComputeArgumentsCreate,
760                  KIM_COMPUTE_ARGUMENT_NAME_partialForces,
761                  KIM_SUPPORT_STATUS_optional);
762 
763   error = error
764           || KIM_ModelComputeArgumentsCreate_SetArgumentSupportStatus(
765                  modelComputeArgumentsCreate,
766                  KIM_COMPUTE_ARGUMENT_NAME_partialParticleEnergy,
767                  KIM_SUPPORT_STATUS_optional);
768 
769   error = error
770           || KIM_ModelComputeArgumentsCreate_SetArgumentSupportStatus(
771                  modelComputeArgumentsCreate,
772                  KIM_COMPUTE_ARGUMENT_NAME_partialVirial,
773                  KIM_SUPPORT_STATUS_optional);
774 
775   /* register call backs */
776   LOG_INFORMATION("Register call back supportStatus");
777 
778   if (error)
779   {
780     LOG_ERROR("Unable to successfully initialize compute arguments");
781     return TRUE;
782   }
783   else
784   {
785     return FALSE;
786   }
787 }
788 
789 /* compute arguments destroy routine */
compute_arguments_destroy(KIM_ModelCompute const * const modelCompute,KIM_ModelComputeArgumentsDestroy * const modelComputeArgumentsDestroy)790 static int compute_arguments_destroy(
791     KIM_ModelCompute const * const modelCompute,
792     KIM_ModelComputeArgumentsDestroy * const modelComputeArgumentsDestroy)
793 {
794   (void) modelCompute; /* avoid unused parameter warning */
795   (void) modelComputeArgumentsDestroy; /* avoid unused parameter warning */
796 
797   /* Nothing further to do */
798 
799   return FALSE;
800 }
801