/*                                                                            */
/* CDDL HEADER START                                                          */
/*                                                                            */
/* The contents of this file are subject to the terms of the Common           */
/* Development and Distribution License Version 1.0 (the "License").          */
/*                                                                            */
/* You can obtain a copy of the license at                                    */
/* http://www.opensource.org/licenses/CDDL-1.0.  See the License for the      */
/* specific language governing permissions and limitations under the License. */
/*                                                                            */
/* When distributing Covered Code, include this CDDL HEADER in each file and  */
/* include the License file in a prominent location with the name             */
/* LICENSE.CDDL.                                                              */
/* If applicable, add the following below this CDDL HEADER, with the fields   */
/* enclosed by brackets "[]" replaced with your own identifying information:  */
/*                                                                            */
/* Portions Copyright (c) [yyyy] [name of copyright owner].                   */
/* All rights reserved.                                                       */
/*                                                                            */
/* CDDL HEADER END                                                            */
/*                                                                            */

/*                                                                            */
/* Copyright (c) 2017--2018, Regents of the University of Minnesota.          */
/* All rights reserved.                                                       */
/*                                                                            */
/* Contributors:                                                              */
/*    Ryan S. Elliott                                                         */
/*    Ellad B. Tadmor                                                         */
/*    Daniel Karls                                                            */
/*                                                                            */

/*                                                                            */
/* Release: This file is part of the kim-api.git repository.                  */
/*                                                                            */

/**
\page implementation Implementation

Previous Section: \ref theory.

In code, a model (or model driver) consists of six routines which perform
specific tasks.  The first is the *ModelCreate* (or *ModelDriverCreate*)
routine, which performs initialization tasks for the model object.  The second
is the *ModelComputeArgumentsCreate* routine, which performs initialization
tasks for a compute-arguments object.  The third is the
* *ModelComputeArgumentsDestroy* routine, which performs finalization tasks for
a compute-arguments object.  The fourth is the *ModelCompute* routine, which
uses the configuration information stored in a compute-arguments object to
perform the model's core computational tasks.  The fifth is the *ModelRefresh*
routine, which performs updates after a simulator makes changes to the model's
parameters (if this is supported).  The sixth is the *ModelDestroy* routine,
which performs finalization tasks for the model object.

To interact with a model, a simulator creates a model object (which, in part,
includes execution of the model's *ModelCreate* routine).  Using this object,
the simulator creates a compute-arguments object (which, in part, includes
execution of the model's *ModelComputeArgumentsCreate* routine).  Then, the
simulator provides a compute-arguments object to the model's *ModelCompute*
function.  There are input compute-arguments that include the various
components that make up a configuration (number of particles, particle position
vectors, etc.).  And, there are output compute-arguments that include the
quantities (like partial energy and partial forces), defined in Section \ref
theory, associated with the configuration.  There are also compute-callback
functions (such as a function to get a particle's neighbor list) that the
simulator provides for use by the model.

The %KIM API provides a list of all compute-arguments and compute-callbacks
defined as part of the official API.  Each such argument and callback has a
"Support Status" which can be one of four values: *requiredByAPI*,
* *notSupported*, *required*, or *optional*.  A model specifies a support status
value, as part of its *ModelComputeArgumentsCreate* routine, for every
compute-argument and compute-callback defined by the %KIM API.  It is the
responsibility of the simulator to use the compute-arguments object interface
to determine the support status of each compute-argument and compute-callback
and to use this information to determine if the model is capable of performing
the desired computation.

Next, lists of each input compute-argument, output compute-argument, and
compute-callback are provided.  To be explicit, below zero-based particle
numbering is used where necessary.

Input compute-argument table:
Compute Argument Name | Unit   | Data Type | Extent                | Memory Layout                                                      | Valid Support Statuses (bold -- default) |
--------------------- | ------ | --------- | --------------------- | ------------------------------------------------------------------ | ---------------------------------------- |
numberOfParticles     | N/A    | integer   | 1                     |                                                                    | **requiredByAPI**                        |
particleSpeciesCodes  | N/A    | integer   | numberOfParticles     | \f$sc^{(0)}, sc^{(1)}, \dots\f$                                    | **requiredByAPI**                        |
particleContributing  | N/A    | integer   | numberOfParticles     | \f$c^{(0)}, c^{(1)}, \dots\f$                                      | **requiredByAPI**                        |
coordinates           | length | double    | numberOfParticles * 3 | \f$r^{(0)}_1, r^{(0)}_2, r^{(0)}_3, r^{(1)}_1, r^{(1)}_2, \dots\f$ | **requiredByAPI**                        |

- numberOfParticles is the number of particles (contributing and
non-contributing) in the configuration.

- particleSpeciesCodes contains integer codes (as defined by the model)
specifying the species of each particle.  For example, if the model defines the
mapping Cu \f$\leftrightarrow 1\f$, Al \f$\leftrightarrow 2\f$, and Ni
\f$\leftrightarrow 3\f$, then \f$sc^{(0)} = 3, sc^{(1)} = 1, sc^{(2)} = 2, \dots\f$
means that particle 0 is a nickel atom, particle 1 is a copper atom, particle 2
is an aluminum atom, etc.

- particleContributing contains the contributing/non-contributing status
of each particle.  Particle \f$i\f$ is contributing if \f$c^{(i)} = 1\f$ and
non-contributing if \f$c^{(i)} = 0\f$.

- coordinates contains the Cartesian components of the particles' position
  vectors, \f$\mathbf{r}^{(i)} = r^{(i)}_1 \mathbf{e}_1 + r^{(i)}_2
  \mathbf{e}_2 + r^{(i)}_3 \mathbf{e}_3\f$.

Output compute-argument table:
Compute Argument Name                                | Unit                       | Data Type | Extent                | Memory Layout                                                           | Valid Support Statuses (bold -- default) |
---------------------------------------------------- | -------------------------- | --------- | --------------------- | ----------------------------------------------------------------------- | ---------------------------------------- |
\ref partial_energy "partialEnergy"                  | energy                     | double    | 1                     |                                                                         | required, optional, **notSupported**     |
\ref partial_forces "partialForces"                  | force                      | double    | numberOfParticles * 3 | \f$f^{\mathcal{C}(0)}_1, f^{\mathcal{C}(0)}_2, f^{\mathcal{C}(0)}_3, f^{\mathcal{C}(1)}_1, f^{\mathcal{C}(1)}_2\dots\f$ | required, optional, **notSupported**     |
\ref partial_particle_energy "partialParticleEnergy" | energy                     | double    | numberOfParticles     | \f$E^{\mathcal{C}(0)}, E^{\mathcal{C}(1)}, E^{\mathcal{C}(2)}, \dots\f$ | required, optional, **notSupported**     |
\ref partial_virial "partialVirial"                  | energy                     | double    | 6                     | \f$V^{\mathcal{C}}_{11}, V^{\mathcal{C}}_{22}, V^{\mathcal{C}}_{33}, V^{\mathcal{C}}_{23}, V^{\mathcal{C}}_{32}, V^{\mathcal{C}}_{13}\f$ | required, optional, **notSupported**     |
\ref partial_particle_virial "partialParticleVirial" | energy                     | double    | numberOfParticles * 6 | \f$\mathbf{V}^{\mathcal{C}(0)}, \mathbf{V}^{\mathcal{C}(1)}, \mathbf{V}^{\mathcal{C}(2)}, \dots\f$ | required, optional, **notSupported**     |

- partialEnergy is the configuration's partial energy \f$E^{\mathcal{C}}\f$.

- partialForces contains the partial force vector for each particle,
  \f$\mathbf{f}^{\mathcal{C}(i)} = f^{\mathcal{C}(i)}_1 \mathbf{e}_1 +
  f^{\mathcal{C}(i)}_2 \mathbf{e}_2 + f^{\mathcal{C}(i)}_3 \mathbf{e}_3\f$.

- partialParticleEnergy contains the partial particle energy for each particle,
  \f$E^{\mathcal{C}(i)}\f$.

- partialVirial is the configuration's partial virial tensor,
  \f$\mathbf{V}^{\mathcal{C}}\f$.

- partialParticleVirial contains the partial particle virial tensor for each
  particle, \f$\mathbf{V}^{\mathcal{C}(i)}\f$.



Compute-callback table:
Compute Callback Name | Valid Support Statuses (bold -- default) |
--------------------- | ---------------------------------------- |
GetNeighborList       | **requiredByAPI**                        |
ProcessDEDrTerm       | required, optional, **notSupported**     |
ProcessD2EDr2Term     | required, optional, **notSupported**     |

- GetNeighborList is a callback function that allows a model to obtain the list
  of neighbors of a particle.  The model may request any number (\f$\ge1\f$) of
  neighbor lists with different (or equal) cutoff distances.  The
  GetNeighborList callback function must support the return of the appropriate
  list of neighbors.  The returned list of neighbors consists of a
  contiguous-in-memory list of integers corresponding to an unordered full list
  of a particle's neighbors.  Each such neighbor list must contain at least all
  particles within the corresponding cutoff distance of the specified particle.
  (However, the returned list may contain particles beyond the cutoff
  distance.)  Neighbor lists provided by the simulator must be consistent with
  the configuration coordinates and the model's cutoff values.  In particular,
  the model must, in principle, be able to independently construct its own
  equivalent neighbor list using just the particle coordinates.  Further, the
  GetNeighborList callback routine must check to ensure that the neighbor list
  data (provided, via the Simulator, by the compute-arguments object) is
  consistent with the model's cutoff values.

  <b>CAUTION - SIMULATOR DEVELOPERS:</b> In general, it is important that
  neighbor lists provided by a simulator are "efficient" in the sense that the
  list contains only a small number of particles that are located outside the
  cutoff distance.  If the lists are not efficient, then the model
  computational time may be *severely* impacted.  This is especially true for
  models that request multiple neighbor lists with a wide range of cutoff
  distances.

  <b>Neighbor List Hints \anchor neighbor_list_hints</b> The above describes
  the default behavior and all models must work correctly when provided with
  neighbor lists of this type.  However, based on the neighbor list hints
  provided by the model a simulator may provide the model with a modified
  neighbor list that is more efficient.  If the model sets its
  "paddingNeighborHint" to 1 (true), it is guaranteeing that it will not need
  access to the neighbors of non-contributing (padding) particles.  So, the
  simulator does not need to generate a neighbor list for such particles.  If
  the model sets its "halfListHint" to 1 (true), it is guaranteeing that it
  will only use neighbors \f$j\f$ of particle \f$i\f$ if \f$i < j\f$.  So, the
  simulator can construct a "half list" of neighbors where each pair of
  neighbors is listed only once in such a way that the list of neighbors for
  particle \f$i\f$ contains only particles \f$j\f$ numbered greater than
  \f$i\f$.  The model has no way of knowing if the simulator is taking advantage
  of its hints, so it must work correctly for all types of neighbor lists
  consistent with its provided hints.

- ProcessDEDrTerm is a callback function that allows for access to the
  derivatives of the configuration's partial energy, \f$E^{\mathcal{C}}\f$,
  with respect to all pair-distances, \f$r^{(i,j)}, i,j \in C_{p}\f$.  That is,
  it allows the model to communicate the values of \f$\frac{\partial
  E^{\mathcal{C}}}{\partial r^{(i,j)}}\f$ to the simulator.  Recall that
  \f$r^{(i,j)}\f$ and \f$r^{(j,i)}\f$ are just two different notations for the
  same quantity.  Thus, there are only \f$\frac{\text{numberOfParticles} \cdot
  (\text{numberOfParticles} + 1)}{2}\f$ quantities (as opposed to
  \f$(\text{numberOfParticles})^2\f$) referred to by the notation
  \f$\frac{\partial E^{\mathcal{C}}}{\partial r^{(i,j)}}\f$.

  These quantities can be used to compute many quantities of interest
  associated with the configuration.  For example, it is possible to
  independently compute the partial virial from this information using the
  formula

  \f[
  \mathbf{V}^{\mathcal{C}} = \sum_{i \in C_p} \mathbf{V}^{\mathcal{C}(i)}
  = \sum_{i \in C_p} \sum_{j \in \mathcal{N}^{(i)}_{r_{\text{infl}}}}
  \frac{\bar{E}_i}{\partial \mathbf{r}^{(j)}} \otimes \mathbf{r}^{(j)}
  = \sum_{i \in C_p} \sum_{j \in \mathcal{N}^{(i)}_{r_{\text{infl}}}} \;\;
  \sum_{k \not= j; \; k \in \bar{\mathcal{N}}^{(i)}_{r_{\text{infl}}}}
  \frac{\partial \tilde{E}_i}{\partial r^{(j,k)}}
  \frac{\partial r^{(j,k)}}{\partial \mathbf{r}^{(j)}}
  \otimes \mathbf{r}^{(j)}.
  \f]

- ProcessD2EDr2Term is a callback function that allows for access to the second
  derivatives of the configuration's partial energy, \f$E^{\mathcal{C}}\f$,
  with respect to all pair-distances, \f$r^{(i,j)}, i,j \in C_{p}\f$.  That is,
  it allows the model to communicate the values of \f$\frac{\partial^2
  E^{\mathcal{C}}}{\partial r^{(i,j)} \partial r^{(m,n)}}\f$ to the simulator.

Next Section: \ref version2_differences.

*/

LocalWords:  CDDL yyyy Ellad Tadmor Karls kim api ref ModelCreate ModelCompute
LocalWords:  ModelDriverCreate ModelRefresh ModelDestroy requiredByAPI sc Cu
LocalWords:  notSupported numberOfParticles particleSpeciesCodes Ni mathbf EDr
LocalWords:  particleContributing leftrightarrow partialEnergy partialForces
LocalWords:  mathcal partialParticleEnergy partialVirial partialParticleVirial
LocalWords:  virial GetNeighborList ProcessDEDrTerm ProcessD ac infl otimes
LocalWords:  ModelComputeArgumentsCreate ModelComputeArgumentsDestroy
