KIM API V2
ex_test_Ar_fcc_cluster.c
Go to the documentation of this file.
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--2018, Regents of the University of Minnesota.
24  * All rights reserved.
25  *
26  * Contributors:
27  * Ryan S. Elliott
28  * Stephen M. Whalen
29  *
30  */
31 
32 /* */
33 /* Release: This file is part of the kim-api-v2.0.0-alpha.0 package. */
34 /* */
35 
36 
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <math.h>
40 #include "KIM_LanguageName.h"
41 #include "KIM_SpeciesName.h"
42 #include "KIM_Numbering.h"
43 #include "KIM_Model.h"
44 #include "KIM_SupportStatus.h"
45 #include "KIM_ArgumentName.h"
46 #include "KIM_CallbackName.h"
47 #include "KIM_UnitSystem.h"
48 
49 #define TRUE 1
50 #define FALSE 0
51 
52 #define NAMESTRLEN 128
53 
54 #define FCCSPACING 5.260
55 #define DIM 3
56 #define NCELLSPERSIDE 2
57 #define NCLUSTERPARTS (4*(NCELLSPERSIDE*NCELLSPERSIDE*NCELLSPERSIDE) + \
58  6*(NCELLSPERSIDE*NCELLSPERSIDE) \
59  + 3*(NCELLSPERSIDE) + 1)
60 
61 
62 #define MY_ERROR(message) \
63  { \
64  printf("* Error : \"%s\" %d:%s\n", message, \
65  __LINE__, __FILE__); \
66  exit(1); \
67  }
68 
69 #define MY_WARNING(message) \
70  { \
71  printf("* Error : \"%s\" %d:%s\n", message, \
72  __LINE__, __FILE__); \
73  }
74 
75 
76 /* Define neighborlist structure */
77 typedef struct
78 {
80  int iteratorId;
81  int* NNeighbors;
82  int* neighborList;
83 } NeighList;
84 
85 /* Define prototypes */
86 void fcc_cluster_neighborlist(int allOrOne, int numberOfParticles,
87  double* coords, double cutoff, NeighList* nl);
88 
90  void const * const dataObject,
91  int const neighborListIndex,
92  int const particleNumber, int * const numberOfNeighbors,
93  int const ** const neighborsOfParticle);
94 
95 void create_FCC_cluster(double FCCspacing, int nCellsPerSide, double *coords);
96 
97 
98 /* Main program */
99 int main()
100 {
101  /* Local variable declarations */
102  double const MinSpacing = 0.8*FCCSPACING;
103  double const MaxSpacing = 1.2*FCCSPACING;
104  double const SpacingIncr = 0.025*FCCSPACING;
105  double CurrentSpacing;
106  double cutpad = 0.75; /* Angstroms */
107  int i;
108  int error;
109 
110 
111  /* KIM variable declarations */
112  KIM_Model * model;
113  /* model inputs */
114  int numberOfParticles_cluster = NCLUSTERPARTS;
115  int speciesIsSupported;
116  int particleSpecies_cluster_model[NCLUSTERPARTS];
117  int particleContributing_cluster_model[NCLUSTERPARTS];
118  int particleContributing_one_atom_model[NCLUSTERPARTS];
119  double coords_cluster[NCLUSTERPARTS][DIM];
120  NeighList nl_cluster_model;
121  /* model outputs */
122  int number_of_cutoffs_cluster_model;
123  double influence_distance_cluster_model;
124  double const * cutoff_cluster_model;
125  double energy_cluster_model = 0.0;
126  double energy_one_atom_model = 0.0;
127  double energy = 0.0;
128 
129  char modelname[NAMESTRLEN];
130  int requestedUnitsAccepted;
131  int modelArCode;
132  int numberOfAPI_Arguments;
133  KIM_ArgumentName argumentName;
134  KIM_SupportStatus supportStatus;
135  int numberOfAPI_Callbacks;
136  KIM_CallbackName callbackName;
137 
138 
139 
140  /* Get KIM Model names */
141  printf("Please enter valid KIM Model name: \n");
142  error = scanf("%s", modelname);
143  if (1 != error)
144  {
145  MY_ERROR("Unable to read model name");
146  }
147 
148  /* initialize the model */
155  modelname,
156  &requestedUnitsAccepted,
157  &model);
158  if (error) MY_ERROR("KIM_create_model_interface()");
159 
160  /* Check for compatibility with the model */
161  if (!requestedUnitsAccepted) MY_ERROR("Must adapt to model units");
162 
163  /* check species */
165  model, KIM_SPECIES_NAME_Ar, &speciesIsSupported, &modelArCode);
166  if ((error) || (!speciesIsSupported))
167  {
168  MY_ERROR("Species Ar not supported");
169  }
170 
171  /* check arguments */
172  KIM_ARGUMENT_NAME_GetNumberOfArguments(&numberOfAPI_Arguments);
173  for (i=0; i<numberOfAPI_Arguments; ++i)
174  {
175  error = KIM_ARGUMENT_NAME_GetArgumentName(i, &argumentName);
176  if (error) MY_ERROR("can't get argument name");
177  error = KIM_Model_GetArgumentSupportStatus(model, argumentName,
178  &supportStatus);
179  if (error) MY_ERROR("can't get argument supportStatus");
180 
181  /* can only handle energy as a required arg */
183  {
184  if (KIM_ArgumentNameNotEqual(argumentName,
186  {
187  MY_ERROR("unsupported required argument");
188  }
189  }
190 
191  /* must have energy */
193  {
194  if (! ((KIM_SupportStatusEqual(supportStatus,
196  ||
197  (KIM_SupportStatusEqual(supportStatus,
199  {
200  MY_ERROR("energy not available");
201  }
202  }
203  }
204 
205  /* check call backs */
206  KIM_CALLBACK_NAME_GetNumberOfCallbacks(&numberOfAPI_Callbacks);
207  for (i=0; i<numberOfAPI_Callbacks; ++i)
208  {
209  error = KIM_CALLBACK_NAME_GetCallbackName(i, &callbackName);
210  if (error) MY_ERROR("can't get call back name");
211  error = KIM_Model_GetCallbackSupportStatus(model, callbackName,
212  &supportStatus);
213  if (error) MY_ERROR("can't get call back supportStatus");
214 
215  /* cannot handle any "required" call backs */
217  {
218  MY_ERROR("unsupported required call back");
219  }
220  }
221 
222  /* We're compatible with the model. Let's do it. */
223 
224  error =
227  &numberOfParticles_cluster)
228  ||
230  model,
232  particleSpecies_cluster_model)
233  ||
235  (double*) &coords_cluster)
236  ||
238  &energy);
239  if (error) MY_ERROR("KIM_setm_data");
243  (func *) &get_cluster_neigh,
244  &nl_cluster_model);
245 
246  KIM_Model_GetInfluenceDistance(model, &influence_distance_cluster_model);
248  &number_of_cutoffs_cluster_model,
249  &cutoff_cluster_model);
250  if (number_of_cutoffs_cluster_model != 1) MY_ERROR("too many cutoffs");
251 
252  /* setup particleSpecies */
254  model,
256  &speciesIsSupported,
257  &(particleSpecies_cluster_model[0]));
258  if (error) MY_ERROR("KIM_get_species_code");
259  for (i = 1; i < NCLUSTERPARTS; ++i)
260  particleSpecies_cluster_model[i] = particleSpecies_cluster_model[0];
261 
262  /* setup particleContributing */
263  for (i = 0; i < NCLUSTERPARTS; ++i)
264  {
265  particleContributing_cluster_model[i] = 1; /* all particles contribute */
266  particleContributing_one_atom_model[i] = 0; /* none (but 30 contribute */
267  }
268  particleContributing_one_atom_model[30] = 1;
269 
270  /* setup neighbor lists */
271  /* allocate memory for list */
272  nl_cluster_model.numberOfParticles = NCLUSTERPARTS;
273  nl_cluster_model.NNeighbors = (int*) malloc(NCLUSTERPARTS*sizeof(int));
274  if (NULL==nl_cluster_model.NNeighbors) MY_ERROR("malloc unsuccessful");
275 
276  nl_cluster_model.neighborList = (int*) malloc(NCLUSTERPARTS*NCLUSTERPARTS*sizeof(int));
277  if (NULL==nl_cluster_model.neighborList) MY_ERROR("malloc unsuccessful");
278 
279  /* ready to compute */
280  printf("--------------------------------------------------------------------------------\n");
281  printf("This is Test : ex_test_Ar_fcc_cluster\n");
282  printf("MODEL is : %s\n", modelname);
283 
284  printf("There are %i particles.\n", NCLUSTERPARTS);
285  printf("%20s, %20s, %20s\n", "Cluster Energy", "One Atom Energy", "Current Spacing");
286  for (CurrentSpacing = MinSpacing; CurrentSpacing < MaxSpacing; CurrentSpacing += SpacingIncr)
287  {
288  /* update coordinates for cluster */
289  create_FCC_cluster(CurrentSpacing, NCELLSPERSIDE, &(coords_cluster[0][0]));
290  /* compute neighbor lists */
291  fcc_cluster_neighborlist(-1, NCLUSTERPARTS, &(coords_cluster[0][0]),
292  (*cutoff_cluster_model + cutpad), &nl_cluster_model);
293 
294  /* call compute functions */
295  error = KIM_Model_SetArgumentPointerInteger(model, KIM_ARGUMENT_NAME_particleContributing, particleContributing_cluster_model);
296  error = error || KIM_Model_Compute(model);
297  if (error) MY_ERROR("KIM_model_compute");
298  energy_cluster_model = energy;
299 
300  error = KIM_Model_SetArgumentPointerInteger(model, KIM_ARGUMENT_NAME_particleContributing, particleContributing_one_atom_model);
301  error = error || KIM_Model_Compute(model);
302  if (error) MY_ERROR("KIM_model_compute");
303  energy_one_atom_model = energy;
304 
305  /* print the results */
306  printf("%20.10e, %20.10e, %20.10e\n",
307  energy_cluster_model,
308  energy_one_atom_model,
309  CurrentSpacing);
310  }
311 
312 
313  /* free memory of neighbor lists */
314  free(nl_cluster_model.NNeighbors);
315  free(nl_cluster_model.neighborList);
316 
317  /* free pkim objects */
318  KIM_Model_Destroy(&model);
319 
320  /* everything is great */
321  return 0;
322 }
323 
324 void create_FCC_cluster(double FCCspacing, int nCellsPerSide, double *coords)
325 {
326  /* local variables */
327  double FCCshifts[4][DIM];
328  double latVec[DIM];
329  int a;
330  int i;
331  int j;
332  int k;
333  int m;
334  int n;
335 
336  /* create a cubic FCC cluster of parts */
337  FCCshifts[0][0] = 0.0; FCCshifts[0][1] = 0.0; FCCshifts[0][2] = 0.0;
338  FCCshifts[1][0] = 0.5*FCCspacing; FCCshifts[1][1] = 0.5*FCCspacing; FCCshifts[1][2] = 0.0;
339  FCCshifts[2][0] = 0.5*FCCspacing; FCCshifts[2][1] = 0.0; FCCshifts[2][2] = 0.5*FCCspacing;
340  FCCshifts[3][0] = 0.0; FCCshifts[3][1] = 0.5*FCCspacing; FCCshifts[3][2] = 0.5*FCCspacing;
341 
342  a = 0;
343  for (i = 0; i < nCellsPerSide; ++i)
344  {
345  latVec[0] = ((double) i)*FCCspacing;
346  for (j = 0; j < nCellsPerSide; ++j)
347  {
348  latVec[1] = ((double) j)*FCCspacing;
349  for (k = 0; k < nCellsPerSide; ++k)
350  {
351  latVec[2] = ((double) k)*FCCspacing;
352  for (m = 0; m < 4; ++m)
353  {
354  for (n = 0; n < DIM; ++n)
355  {
356  coords[a*DIM + n] = latVec[n] + FCCshifts[m][n];
357  }
358  a++;
359  }
360  }
361  /* add in the remaining three faces */
362  /* pos-x face */
363  latVec[0] = NCELLSPERSIDE*FCCspacing;
364  latVec[1] = ((double) i)*FCCspacing;
365  latVec[2] = ((double) j)*FCCspacing;
366  for (n = 0; n < DIM; ++n)
367  {
368  coords[a*DIM + n] = latVec[n];
369  }
370  a++;
371  for (n = 0; n < DIM; ++n)
372  {
373  coords[a*DIM + n] = latVec[n] + FCCshifts[3][n];
374  }
375  a++;
376  /* pos-y face */
377  latVec[0] = ((double) i)*FCCspacing;
378  latVec[1] = NCELLSPERSIDE*FCCspacing;
379  latVec[2] = ((double) j)*FCCspacing;
380  for (n = 0; n < DIM; ++n)
381  {
382  coords[a*DIM + n] = latVec[n];
383  }
384  a++;
385  for (n = 0; n < DIM; ++n)
386  {
387  coords[a*DIM + n] = latVec[n] + FCCshifts[2][n];
388  }
389  a++;
390  /* pos-z face */
391  latVec[0] = ((double) i)*FCCspacing;
392  latVec[1] = ((double) j)*FCCspacing;
393  latVec[2] = NCELLSPERSIDE*FCCspacing;
394  for (n = 0; n < DIM; ++n)
395  {
396  coords[a*DIM + n] = latVec[n];
397  }
398  a++;
399  for (n = 0; n < DIM; ++n)
400  {
401  coords[a*DIM + n] = latVec[n] + FCCshifts[1][n];
402  }
403  a++;
404  }
405  /* add in the remaining three edges */
406  latVec[0] = ((double) i)*FCCspacing;
407  latVec[1] = NCELLSPERSIDE*FCCspacing;
408  latVec[2] = NCELLSPERSIDE*FCCspacing;
409  for (n = 0; n < DIM; ++n)
410  {
411  coords[a*DIM + n] = latVec[n];
412  }
413  a++;
414  latVec[0] = NCELLSPERSIDE*FCCspacing;
415  latVec[1] = ((double) i)*FCCspacing;
416  latVec[2] = NCELLSPERSIDE*FCCspacing;
417  for (n = 0; n < DIM; ++n)
418  {
419  coords[a*DIM + n] = latVec[n];
420  }
421  a++;
422  latVec[0] = NCELLSPERSIDE*FCCspacing;
423  latVec[1] = NCELLSPERSIDE*FCCspacing;
424  latVec[2] = ((double) i)*FCCspacing;
425  for (n = 0; n < DIM; ++n)
426  {
427  coords[a*DIM + n] = latVec[n];
428  }
429  a++;
430  }
431  /* add in the remaining corner */
432  for (n = 0; n < DIM; ++n)
433  {
434  coords[a*DIM + n] = NCELLSPERSIDE*FCCspacing;
435  }
436  a++;
437 
438  return;
439 }
440 
441 
442 void fcc_cluster_neighborlist(int allOrOne, int numberOfParticles, double* coords,
443  double cutoff, NeighList* nl)
444 {
445  /* local variables */
446  int i;
447  int j;
448  int k;
449  int a;
450 
451  double dx[DIM];
452  double r2;
453  double cutoff2;
454 
455  cutoff2 = cutoff*cutoff;
456  for (i = 0; i < numberOfParticles; ++i)
457  {
458  a = 0;
459  if ((allOrOne == i) || (allOrOne < 0))
460  {
461  for (j = 0; j < numberOfParticles; ++j)
462  {
463  r2 = 0.0;
464  for (k = 0; k < DIM; ++k)
465  {
466  dx[k] = coords[j*DIM + k] - coords[i*DIM + k];
467  r2 += dx[k]*dx[k];
468  }
469 
470  if ((r2 < cutoff2) && (i != j))
471  {
472  /* part j is a neighbor of part i */
473  (*nl).neighborList[i*NCLUSTERPARTS + a] = j;
474  a++;
475  }
476  }
477  }
478  /* part i has `a' neighbors */
479  (*nl).NNeighbors[i] = a;
480  }
481 
482  return;
483 }
484 
485 int get_cluster_neigh(void const * const dataObject,
486  int const neighborListIndex,
487  int const particleNumber, int * const numberOfNeighbors,
488  int const ** const neighborsOfParticle)
489 {
490  /* local variables */
491  int error = TRUE;
492  NeighList* nl = (NeighList*) dataObject;
493  int numberOfParticles = nl->numberOfParticles;
494 
495  if (neighborListIndex != 0) return error;
496 
497  /* initialize numNeigh */
498  *numberOfNeighbors = 0;
499 
500  if ((particleNumber >= numberOfParticles) || (particleNumber < 0)) /* invalid id */
501  {
502  MY_WARNING("Invalid part ID in get_cluster_neigh");
503  return TRUE;
504  }
505 
506  /* set the returned number of neighbors for the returned part */
507  *numberOfNeighbors = (*nl).NNeighbors[particleNumber];
508 
509  /* set the location for the returned neighbor list */
510  *neighborsOfParticle = &((*nl).neighborList[(particleNumber)*numberOfParticles]);
511 
512  return FALSE;
513 }
void KIM_Model_GetInfluenceDistance(KIM_Model const *const model, double *const influenceDistance)
int KIM_ArgumentNameNotEqual(KIM_ArgumentName const left, KIM_ArgumentName const right)
KIM_SupportStatus const KIM_SUPPORT_STATUS_optional
int KIM_Model_SetArgumentPointerDouble(KIM_Model *const model, KIM_ArgumentName const argumentName, double const *const ptr)
int KIM_Model_GetArgumentSupportStatus(KIM_Model const *const model, KIM_ArgumentName const argumentName, KIM_SupportStatus *const supportStatus)
KIM_ArgumentName const KIM_ARGUMENT_NAME_particleContributing
KIM_ArgumentName const KIM_ARGUMENT_NAME_numberOfParticles
int KIM_Model_SetCallbackPointer(KIM_Model *const model, KIM_CallbackName const callbackName, KIM_LanguageName const languageName, func *const fptr, void const *const dataObject)
int main()
void KIM_Model_GetNeighborListCutoffsPointer(KIM_Model const *const model, int *const numberOfCutoffs, double const **const cutoffs)
void KIM_Model_Destroy(KIM_Model **const model)
KIM_ChargeUnit const KIM_CHARGE_UNIT_e
void create_FCC_cluster(double FCCspacing, int nCellsPerSide, double *coords)
KIM_LanguageName const KIM_LANGUAGE_NAME_c
ArgumentName const numberOfParticles
int KIM_CALLBACK_NAME_GetCallbackName(int const index, KIM_CallbackName *const callbackName)
void fcc_cluster_neighborlist(int allOrOne, int numberOfParticles, double *coords, double cutoff, NeighList *nl)
void KIM_ARGUMENT_NAME_GetNumberOfArguments(int *const numberOfArguments)
#define NAMESTRLEN
int KIM_Model_GetSpeciesSupportAndCode(KIM_Model const *const model, KIM_SpeciesName const speciesName, int *const speciesIsSupported, int *const code)
#define FALSE
KIM_SpeciesName const KIM_SPECIES_NAME_Ar
int KIM_ARGUMENT_NAME_GetArgumentName(int const index, KIM_ArgumentName *const argumentName)
#define TRUE
KIM_CallbackName const KIM_CALLBACK_NAME_GetNeighborList
#define MY_WARNING(message)
void KIM_CALLBACK_NAME_GetNumberOfCallbacks(int *const numberOfCallbacks)
#define FCCSPACING
void() func()
Definition: KIM_func.h:39
#define NCLUSTERPARTS
LengthUnit const m
int KIM_Model_Create(KIM_Numbering const numbering, KIM_LengthUnit const requestedLengthUnit, KIM_EnergyUnit const requestedEnergyUnit, KIM_ChargeUnit const requestedChargeUnit, KIM_TemperatureUnit const requestedTemperatureUnit, KIM_TimeUnit const requestedTimeUnit, char const *const modelName, int *const requestedUnitsAccepted, KIM_Model **const model)
KIM_TimeUnit const KIM_TIME_UNIT_ps
int KIM_ArgumentNameEqual(KIM_ArgumentName const left, KIM_ArgumentName const right)
#define DIM
int KIM_Model_Compute(KIM_Model const *const model)
int get_cluster_neigh(void const *const dataObject, int const neighborListIndex, int const particleNumber, int *const numberOfNeighbors, int const **const neighborsOfParticle)
KIM_EnergyUnit const KIM_ENERGY_UNIT_eV
KIM_ArgumentName const KIM_ARGUMENT_NAME_coordinates
KIM_ArgumentName const KIM_ARGUMENT_NAME_particleSpeciesCodes
#define MY_ERROR(message)
int KIM_SupportStatusEqual(KIM_SupportStatus const left, KIM_SupportStatus const right)
#define NCELLSPERSIDE
KIM_SupportStatus const KIM_SUPPORT_STATUS_required
struct KIM_Model KIM_Model
Definition: KIM_Model.h:114
int KIM_Model_SetArgumentPointerInteger(KIM_Model *const model, KIM_ArgumentName const argumentName, int const *const ptr)
KIM_LengthUnit const KIM_LENGTH_UNIT_A
KIM_ArgumentName const KIM_ARGUMENT_NAME_partialEnergy
LogVerbosity const error
KIM_TemperatureUnit const KIM_TEMPERATURE_UNIT_K
int KIM_Model_GetCallbackSupportStatus(KIM_Model const *const model, KIM_CallbackName const callbackName, KIM_SupportStatus *const supportStatus)
KIM_Numbering const KIM_NUMBERING_zeroBased