/*                                                                            */
/* 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--2019, 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-2.0.2 package.                   */
/*                                                                            */

/**
\page implementation Implementation

Previous Section: \ref theory.

In code, a model (or model driver) consists of up to eight routines which
perform specific tasks:

-# The <em>ModelCreate</em> (or \em ModelDriverCreate ) routine (required),
   which performs initialization tasks for the model object.

-# The <em>ModelComputeArgumentsCreate</em> routine (required), which performs
   initialization tasks for a compute-arguments object.

-# The \em ModelCompute routine (required), which uses the configuration
   information stored in a compute-arguments object to perform the
   model's core computational tasks.

-# The <em>ModelExtension</em> routine (optional), which provides a mechanism
   for creating and using non-standard extensions to the %KIM API.

-# The <em>ModelRefresh</em> routine (required if parameter pointers are set,
   otherwise should not be provided), which performs updates after a simulator
   makes changes to the model's parameters (if this is supported).

-# The <em>ModelWriteParameterizedModel</em> (optional) routine, which can be
   used to write the parameter files and CMake file necessary to create a new
   parameterized model from the current set of in-memory parameters.

-# The \em ModelComputeArgumentsDestroy routine (required), which performs
   finalization tasks for a compute-arguments object.

-# The <em>ModelDestroy</em> routine (required), which performs finalization
   tasks for the model object.

These are summarized in the following table.

| Model Routine                                    | Required / Optional |
| ------------------------------------------------ | ------------------- |
| KIM::MODEL_ROUTINE_NAME::Create                  | required            |
| KIM::MODEL_ROUTINE_NAME::ComputeArgumentsCreate  | required            |
| KIM::MODEL_ROUTINE_NAME::Compute                 | required            |
| KIM::MODEL_ROUTINE_NAME::Extension               | optional            |
| KIM::MODEL_ROUTINE_NAME::Refresh                 | required if one or more parameter pointers set, otherwise should not be provided |
| KIM::MODEL_ROUTINE_NAME::WriteParameterizedModel | optional            |
| KIM::MODEL_ROUTINE_NAME::ComputeArgumentsDestroy | required            |
| KIM::MODEL_ROUTINE_NAME::Destroy                 | required            |

The above table indicates which routines must be provided by a model.  For
optional routines, each model must indicate that the routine is required or
optional for use by the simulator, as described below.

The interaction between the simulator and a model involves the following
steps:

- A simulator creates a <em>model object</em>, by calling KIM::Model::Create,
  that will be used to exchange pointers to data and functions related to the
  model between the simulator and model.  Creating this object includes the
  specification of how the simulator will number particles (zero-based or
  one-based), determination of the physical base units that the model will use,
  and execution of the model's <em>ModelCreate</em> routine.

  When calling KIM::Model::Create to create a <em>model object</em>, the
  simulator provides a set of "requested" base units that it would prefer to
  use.  <em>The %KIM API gives the model final authority to decide on the base
  units it will use.</em> Best practice for models is to respect the request of
  the simulator and to use the requested base units by converting its
  parameters appropriately.  The \c requestedUnitsAccepted output argument of
  the KIM::Model::Create routine is a convenience that allows the simulator a
  short-cut to determine if its request for base units was accepted.  (The
  alternative is for the simulator to call to KIM::Model::GetUnits and compare
  the results to the requested units.)

  If a base unit is not relevant to the simulator (e.g., a unit of time is not
  necessary for static equilibrium computations), then the simulator should
  specify that the corresponding requested base unit(s) is/are "unused".
  Similarly, if a base unit is irrelevant to the model (e.g., many models only
  require units of length and energy; Thus, units of charge, temperature, and
  time are irrelevant), then the model should specify that the corresponding
  base unit(s) is/are "unused" (regardless of the simulator's requested values)
  when calling KIM::ModelCreate::SetUnits within its <em>ModelCreate</em>
  routine.  Additionally, the model should select its preferred (non-"unused")
  base unit value when the simulator provides a request of "unused" for a
  relevant base unit.

- Once a model object is obtained, the simulator should use
  KIM::Model::IsRoutinePresent to determine which routines the model has
  provided and if they are required or optional.  From this information the
  simulator should determine if it can proceed to work with the model, or if
  the model requires the use of routines that are not supported by the
  simulator it should exit.

- Next, the simulator creates a <em>compute-arguments object</em>, by calling
  KIM::Model::ComputeArgumentsCreate, that will be used to exchange pointers to
  data and functions related to the atomic configuration and values being
  computed for it.  Creating this object includes execution of the model's
  <em>ModelComputeArgumentsCreate</em> routine.

- Then, to perform a computation, the simulator provides a compute-arguments
  object to the KIM::Model::Compute routine (which, in part, executes the
  model's <em>ModelCompute</em> function).

  - There are input compute-arguments that include the various components that
    make up a configuration (number of particles, particle position vectors,
    etc.).

  - 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.

- When a simulator is finished working with a model, it needs to clean up by
  calling KIM::Model::ComputeArgumentsDestroy (which, in part, executes the
  model's <em>ModelComputeArgumentsDestroy</em> routine) to delete each of the
  compute-arguments objects that were created, and finally calling
  KIM::Model::Destroy (which, in part, executes the model's
  <em>ModelDestroy</em> routine) to delete the model object.

The %KIM API provides a list of all compute-arguments and compute-callbacks
defined as part of the official API.  Each argument and callback has a "Support
Status" that can be one of four values: <em>requiredByAPI</em>,
<em>notSupported</em>, <em>required</em>, or <em>optional</em>.  A model
specifies a support status value, as part of its
<em>ModelComputeArgumentsCreate</em> 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.

Below, lists of each input compute-argument, output compute-argument, and
compute-callback are provided.  To be explicit, 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                     |                                                                    | <b>requiredByAPI</b>                     |
| particleSpeciesCodes  | N/A    | integer   | numberOfParticles     | \f$sc^{(0)}, sc^{(1)}, \dots\f$                                    | <b>requiredByAPI</b>                     |
| particleContributing  | N/A    | integer   | numberOfParticles     | \f$c^{(0)}, c^{(1)}, \dots\f$                                      | <b>requiredByAPI</b>                     |
| coordinates           | length | double    | numberOfParticles * 3 | \f$r^{(0)}_1, r^{(0)}_2, r^{(0)}_3, r^{(1)}_1, r^{(1)}_2, \dots\f$ | <b>requiredByAPI</b>                     |

- 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.

- 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, <b>notSupported</b>  |
| \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, <b>notSupported</b>     |
| \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, <b>notSupported</b>     |
| \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}}_{31}, V^{\mathcal{C}}_{12}\f$ | required, optional, <b>notSupported</b>     |
| \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, <b>notSupported</b>     |

- 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       | <b>requiredByAPI</b>                     |
| ProcessDEDrTerm       | required, optional, <b>notSupported</b>  |
| ProcessD2EDr2Term     | required, optional, <b>notSupported</b>  |

- 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 (not including itself).  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 <em>severely</em> impacted.  This is especially true for
  models that request multiple neighbor lists with a wide range of cutoff
  distances.

  <b>Neighbor List Hint \anchor neighbor_list_hint :</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 <em>neighbor list hint</em>
  provided by the model a simulator may provide the model with a modified
  neighbor list that is more efficient.  If the model sets its
  "modelWillNotRequestNeighborsOfNoncontributingParticles" value to 1 (true),
  it is guaranteeing that it will not request the neighbors of non-contributing
  particles.  In this case, the simulator does not need to generate a neighbor
  list for such particles.  The model has no way of knowing if the simulator is
  taking advantage of its hint, so it must work correctly for all types of
  neighbor lists consistent with its provided hint.

- 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} \sum_{j \in \mathcal{N}^{(i)}_{r_{\text{infl}}}} \;\;
  \sum_{k \not= j; \; k \in \bar{\mathcal{N}}^{(i)}_{r_{\text{infl}}}}
  \left(\frac{1}{2 r^{(j,k)}} \frac{\partial \tilde{E}_i}{\partial r^{(j,k)}}
  \right) \mathbf{r}^{(j,k)} \otimes \mathbf{r}^{(j,k)}.
  \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 em
LocalWords:  ModelComputeArgumentsCreate ModelComputeArgumentsDestroy ge cdot
LocalWords:  Modelcompureargumentsdestroy ModelExtension CMake
LocalWords:  modelWillNotRequestNeighborsOfNoncontributingParticles
LocalWords:  ModelWriteParameterizedModel requestedUnitsAccepted
