#
# 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) 2012, Regents of the University of Minnesota.  All rights reserved.
#
# Contributors:
#    Valeriu Smirichinski
#    Ryan S. Elliott
#    Ellad B. Tadmor
#

################################################################################
#
# Release: This file is part of the openkim-api-v1.1.0 package.
#
################################################################################


Description of the KIM Service routines:

This file provides a basic description of the KIM API functions.  For each
function the main description is for the C interface.  At the end of the
description the corresponding Fortran interface is provided.  The C++ interface
is always the same as the C interface, but is called as a member-function of
the KIM_API_model object whose name does not include the `KIM_API_' part of the
C interface function name.  (For example, to call KIM_API_model_compute() in
C++, you would use the code `mdl->model_compute()'.)

In the following description several constants are used:

STATUS codes: The openkim-api uses a set of defined status code keys to return
         information to the user.  These symbolic code keys are defined in the
         KIM_API_status.h file which can be #include'd by any source file.  The
         codes associated with these keys (defined in KIM_API_status.h) are
         subject to change and should not be used directly.  By convention, any
         status code, `kimerror', returned by an openkim-api service routine
         that is less than KIM_STATUS_OK (i.e., "kimerror < KIM_STATUS_OK")
         indicates an error has occurred.

C style: KIM_DIR, KIM_DIR_MODELS, KIM_DIR_TESTS

         These string constants are defined in KIM_API.h and give the
         locations of KIM directories.


Fortran style: integer, parameter :: kim_intptr = 4 (or 8)

         This parameter is defined in the Fortran 90 module `kim_api'
         in the file KIM_API_F.F90 and gives the length of an integer variable
         that can be used to store CRAY pointers. Depending on the system, its
         value is 4 (on 32 bit machines) or 8 (on 64 bit machines).


==============================  GLOBAL METHODS  ==============================

int KIM_API_init(void *kimmdl, char *testname, char *modelname);

    This routine creates the KIM API object that can store every pointer to the
    data described in the KIM descriptor file for the model.  It also checks if
    arguments described in descriptor files (Tests and Models) are compatible
    with KIM standard naming convention (stored in the file `standard.kim') and
    if Models are compatible with Tests.  It will return KIM_STATUS_OK upon
    successful completion or KIM_STATUS_FAIL otherwise.  Also if it is
    unsuccessful, kimmdl will have NULL value.

Arguments:

      void *kimmdl
              reference pointer to KIM_API_model object (in C++ style, the
              definition will be (KIM_API_model **)).

      char *testname
              null terminated character string that defines Test name. The
              routine prepends the string constant KIM_DIR_TESTS to obtain the
              file location of the Test descriptor (.kim) file.

      char *modelname
              null terminated character string that defines the Model name.
              The routine uses this name to find the character string in memory
              that contains the Model's descriptor (.kim) file.  At compile
              time the descriptor file is stored in the Model's binary library
              file.  Thus, it is necessary to perform a `make' of the
              openkim-api package after editing a Model's .kim file.

Corresponding Fortran style interface:

      integer function kim_api_init_f(kimmdl, testname, modelname)
                      character (len=*) :: testname, modelname
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_init_f
      end function kim_api_init_f

******************************************************************************

int KIM_API_string_init(void *kimmdl, char *testdescriptor, char *modelname);

    This routine performs the same function as the KIM_API_init() routine.
    However, in this case the argument `testname' is a (long) null (or eof)
    terminated string with the complete content of the Test's KIM descriptor
    file.

Arguments:

      void *kimmdl
              reference pointer to KIM_API_model object (in C++ style the
              definition will be (KIM_API_model **)).

      char *testdescriptor
              null ( char(0) ) or eof terminated character string with the
              complete content of the Test's KIM descriptor file.

      char *modelname
              null terminated character string that defines the Model name.
              The routine uses this name to find the character string in memory
              that contains the Model's descriptor (.kim) file.  At compile
              time the descriptor file is stored in the Model's binary library
              file.  Thus, it is necessary to perform a `make' of the
              openkim-api package after editing a Model's .kim file.

Corresponding Fortran style interface:

      integer function kim_api_string_init_f(kimmdl, testdescriptor, modelname)
                      character (len=*) :: testdescriptor, modelname
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_string_init_f
      end function kim_api_string_init_f

******************************************************************************

int KIM_API_model_info(void *kimmdl, char *modelname);

    This routine creates a KIM API object that represents the capabilities of a
    Model.  Standard service routines (described below) can be used to probe
    this object in order to determine (most) of the items listed in the Model's
    KIM descriptor file. For example, A Test could determine what atom/particle
    types are supported by a Model and adjust it's calculations appropriately.
    Return value: KIM_STATUS_OK if successful and KIM_STATUS_FAIL if
    unsuccessful.

Arguments:

      void *kimmdl
              reference pointer to KIM_API_model object (in C++ style, the
              definition will be (KIM_API_model **)).

      char *modelname
              null terminated character string that defines the Model name.
              The routine uses this name to find the character string in memory
              that contains the Model's descriptor (.kim) file.  At compile
              time the descriptor file is stored in the Model's binary library
              file.  Thus, it is necessary to perform a `make' of the
              openkim-api package after editing a Model's .kim file.

Corresponding Fortran style interface:

      integer function kim_api_model_info_f(kimmdl, modelname)
                      character (len=*) :: modelname
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kim_api_model_info_f
      end function kim_api_model_info_f

******************************************************************************

void KIM_API_allocate(void *kimmdl, int nParticles, int nParticleTypes, int *kimerror);

    This routine allocates memory for each data argument stored in the
    initialized KIM API object kimmdl.  It will return with an error code if an
    error occurs during allocation.  KIM_API_allocate should not be used in
    conjunction with KIM_API_set_data for array data (this would create a
    memory leak).

    NOTE: Prior to calling this routine a valid KIM API object must be obtained
          by calling KIM_API_init().  However, calling this routine multiple
          times with the same KIM API object will cause a memory leak.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int nParticles
              total number of particles.

      int nParticleTypes
              number of particles types.

      int *kimerror
              error code: KIM_STATUS_OK    -- successful completion,
                          KIM_STATUS_FAIL  -- unsuccessful

Corresponding Fortran style interface:

      subroutine kim_api_allocate_f(kimmdl, npartilces, nparticletypes, kimerror)
                      integer(kind=kim_intptr) :: kimmdl, nparticles
                      integer  :: nparticletypes, kimerror
      end subroutine kim_api_allocate_f

******************************************************************************

void KIM_API_free(void *kimmdl, int *kimerror);

    This routine deallocates all memory allocated by KIM_API_allocate and also
    destroys the KIM API object.

    NOTE: Prior to calling this routine, the Test is responsible for calling
          the KIM_API_model_destroy() function and deallocating any memory
          associated with arguments in the KIM API object as appropriate.

Arguments:

      void *kimmdl
              reference pointer to KIM_API_model object (in C++ style, the
              definition will be (KIM_API_model **)).

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      subroutine kim_api_free_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kimerror
      end subroutine kim_api_free_f

******************************************************************************

void KIM_API_print(void *kimmdl, int *kimerror);

    This routine prints to standard output, the KIM API object: structure, data
    and flags.  This is normally used for debugging purposes.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      subroutine kim_api_print_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kimerror
      end subroutine kim_api_print_f

******************************************************************************

int KIM_API_model_compute(void *kimmdl);

    This routine executes the `compute' method of the Model by using the
    address of the compute routine stored in KIM API object.  Return value:
    KIM_STATUS_OK on success or KIM_STATUS_FAIL on failure.

    NOTES:

    (1) Prior to calling this routine the KIM API object pointed to by `kimmdl'
        must contain the necessary information that the Model requires to run.
        In addition, KIM_API_model_init() must have successfully executed for
        this KIM API object.

    (2) It is important to stress that a Model must not make assumptions about
        the state of the KIM API object in its model_compute() function.  For
        example, the value of `numberOfParticles' could change every time that
        model_compute() is called.  This would also imply that the `coordinates'
        array pointer, and other similar pointers, would change too.  Thus, the
        Model must be careful to accurately determine the validity of any data
        has previously stored in its Model Buffer.  (See details and cautionary
        notes about this in the documentation for KIM_API_set/get_model_buffer
        and also in the standard.kim file.)

    (3) The Model must define a model_compute function (the name of this
           function is not important) with prototype:
           extern "C" { int model_compute(void *kimmdl); } // in C++
           int model_compute(void *kimmdl);                /* in C */
           integer function model_compute(pkim)
              integer(kind=kim_intptr), intent(in) :: pkim
                                                     ! in Fortran
        A pointer to the Model's model_compute function must be registered in
        the KIM_API object using one of the "set data" api service routines.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *))

Corresponding Fortran style interface:

      integer function kim_api_model_compute_f(kimmdl)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kim_api_model_compute_f
      end function kim_api_model_compute_f

******************************************************************************

int KIM_API_model_destroy(void *kimmdl);

    This routine executes the `destroy' method of the model by using the
    address of the destroy routine stored in KIM API object.  This routine
    performs any necessary clean-up tasks.  In particular, it must deallocate
    the memory for all Model parameters stored in the KIM API object.  Return
    value is KIM_STATUS_OK on success and KIM_STATUS_FAIL on failure.

    NOTES:

    (1) Prior to calling this routine KIM_API_model_init() must have been
        called for this KIM API object.

    (2) The Model may define a model_destroy function (the name of this
           function is not important) with prototype:
           extern "C" { int model_destroy(void *kimmdl); } // in C++
           int model_destroy(void *kimmdl);                /* in C */
           integer function model_destroy(pkim)
              integer(kind=kim_intptr), intent(in) :: pkim
                                                     ! in Fortran
        If a model defines a model_destroy functions, a pointer to this
        function must be registered in the KIM_API object using one of the "set
        data" api service routines.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *))

Corresponding Fortran style interface:

      integer function kim_api_model_destroy_f(kimmdl)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kim_api_model_destroy_f
      end function kim_api_model_destroy_f

******************************************************************************

int KIM_API_get_model_index_shift(void *kimmdl);

    This routine returns an integer that indicates the offset in indices
    between Tests and Models for array access. The return value can be only
    -1,0 or +1.
    If the Test has ZeroBasedList and the Model has OneBasedList  the return value is +1
    If the Test has OneBasedList  and the Model has OneBasedList  the return value is  0
    If the Test has ZeroBasedList and the Model has ZeroBasedList the return value is  0
    If the Test has OneBasedList  and the Model has ZeroBasedList the return value is -1

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

Corresponding Fortran style interface:

      integer function kim_api_get_model_index_shift_f(kimmdl)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kim_api_get_model_index_shift_f
      end function kim_api_get_model_index_shift_f

******************************************************************************

void KIM_API_set_model_buffer(void *kimmdl, void *ob, int *kimerror);

    This routine allows the Model to store a pointer to a buffer of memory.
    The Model can use this buffer as persistent memory between calls to its
    various functions.

    NOTE: This feature must be used with caution.  There is no mechanism to
          notify the Model when changes are made to the data (controlled by the
          Test) in the KIM API object (such as the number of particles, or the
          memory location of the `forces' argument).  In particular, the
          pointer values returned by KIM_API_get_data() are, generally, NOT
          safe to store in the Model Buffer.  An example of a safe quantity to
          store in the Model Buffer is the index for an argument returned by
          the KIM_API_get_index() function.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      void *ob
              pointer to Model Buffer

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      subroutine kim_api_set_model_buffer_f(kimmdl, ob, kimerror)
                      integer(kind=kim_intptr) :: kimmdl, ob
                      integer :: kimerror
      end subroutine kim_api_set_model_buffer_f

******************************************************************************

void KIM_API_set_test_buffer(void *kimmdl, void *ob, int *kimerror);

    This routine allows the Test to store a pointer to a buffer of memory.  The
    Test can use this buffer as persistent memory associated with the KIM API
    object.

    NOTE: This feature must be used with caution.  There is no mechanism to
          notify the Test when changes are made to the data (controlled by the
          Model) in the KIM API object (such as the pointer to the Model's
          `compute' function, the pointers to its Parameters or their values).
          In particular, the pointer values returned by KIM_API_get_data() are,
          generally, NOT safe to store in the Test Buffer.  An example of a
          safe quantity to store in the Test Buffer is the index for an
          argument returned by the KIM_API_get_index() function.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      void *ob
              pointer to Test Buffer

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      subroutine kim_api_set_test_buffer_f(kimmdl,ob,kimerror)
                      integer(kind=kim_intptr) :: kimmdl, ob
                      integer :: kimerror
      end subroutine kim_api_set_test_buffer_f

******************************************************************************

void *KIM_API_get_model_buffer(void *kimmdl, int *kimerror);

    This routine gets (returns) the pointer to the Model buffer.  See the
    description of KIM_API_get_model_buffer() above.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      function kim_api_get_model_buffer_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_model_buffer_f
                      integer :: kimerror
      end function kim_api_get_model_buffer_f

******************************************************************************

void *KIM_API_get_test_buffer(void *kimmdl, int *kimerror);

    This routine gets (returns) the pointer to the Test buffer.  See the
    description of KIM_API_get_test_buffer() above.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      function kim_api_get_test_buffer_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_test_buffer_f
                      integer :: kimerror
      end function kim_api_get_test_buffer_f

******************************************************************************

int KIM_API_is_half_neighbors(void *kimmdl, int *kimerror);

    This routine returns 1 if KIM_API Model object setting is for half
    neighbors or 0 if it is for full neighbors.  The type of neighbor list
    being used (if any) is determined by the "active" NBC method (See
    KIM_API_get_NBC_method() below).  This is a convenience routine which makes
    it easy to quickly determine the type of neighbor list in use.  This routine
    returns 1 for the CLUSTER NBC method even though neighbor lists are not
    used as part of the CLUSTER NBC method.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      integer function kim_api_is_half_neighbors_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kim_api_is_half_neighbors_f
                      integer :: kimerror
      end function kim_api_is_half_neighbors_f


================== ELEMENT ACCESS METHODS ROUTINES BY NAME ====================

int KIM_API_set_data(void *kimmdl, char *nm, intptr_t size, void *dt);

    This routine searches for the string `nm' in the KIM API object `kimmdl'. If
    found, it stores in the KIM API object the value of `dt' which points to the
    location in memory where the data associated with `nm' is to be stored.  Upon
    successful completion this routine returns KIM_STATUS_OK.  If `nm' is not in
    the KIM API object this routine returns KIM_STATUS_ARG_UNKNOWN.  If an
    existing pointer in the KIM API object is overwritten by this operation, a
    memory leak may result. (This could indicate that storage for the same data
    has been allocated more than once.)  Thus, care must be taken if this
    routine is used in conjunction with KIM_API_allocate for array data.

    NOTE: Prior to calling this routine a valid KIM API object must be obtained
          by calling KIM_API_init().

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *))

      char *nm
              null terminated string is the name of the argument field exactly
              as it appears in the .kim descriptor file

      intptr_t size
              size of the data in terms of underlying elements

      void *dt
              pointer to the data

Corresponding Fortran style interface:

      integer function kim_api_set_data_f(kimmdl, nm, size, dt)
                      ! dt is address (cray pointer to actual data)
                      integer(kind=kim_intptr) :: kimmdl, size, dt
                      character (len=*) :: nm
                      integer :: kim_api_set_data_f
      end function kim_api_set_data_f

******************************************************************************

void *KIM_API_get_data(void *kimmdl, char *nm, int *kimerror);

    This routine returns a pointer from the KIM API object that points to
    memory where data associated with the string `nm' is stored.  It returns NULL
    if the string nm is not found in the KIM API object.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *))

      char *nm
              null terminated string is the name of the argument field exactly
              as it appears in the .kim descriptor file

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:
      integer(kind=kim_intptr) function kim_api_get_data_f(kimmdl, nm, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_data_f
                      character (len=*) :: nm
                      integer :: kimerror
      end function kim_api_get_data_f

******************************************************************************

intptr_t KIM_API_get_size(void *kimmdl, char *nm, int *kimerror);

     The functionality of this routine is the same as KIM_API_get_data, except
     it returns the size of the data in terms of underlying elements. (For
     example, if the data is an array of shape [numberOfParticles,3],
     KIM_API_get_size() will return numberOfParticles*3.)  If no data with name
     `nm' is in the KIM API object, a negative value will be returned.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *))

      char *nm
              null terminated string is the name of the argument field exactly
              as it appears in the .kim descriptor file

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      integer(kind=kim_intptr) function kim_api_get_size_f(kimmdl, nm, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_size_f
                      character (len=*) :: nm
                      integer :: kimerror
      end function kim_api_get_size_f

******************************************************************************

intptr_t KIM_API_get_shape(void *kimmdl, char *nm, int *shape, int *kimerror);

    This routine returns the rank of `nm' and provides its shape in the argument
    `shape'.  If the name of the argument is not in the KIM API object, a
    negative value will be returned.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *))

      char *nm
              null terminated string is the name of the argument field exactly
              as it appears in the .kim descriptor file

      int *shape
              An array of integers for the shape of the array data. The routine
              will set values in this array for each dimension of the data
              object (the number of these is equal to the rank value returned
              by this function).  Shape gives the extent of each index for the
              array data. Shape[0] is the slowest changing index.  Shape has to
              be allocated and should have sufficient memory to hold a value
              for each dimension.

      int *kimerror
                error code: KIM_STATUS_OK   -- successful completion,
                            KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      integer(kind=kim_intptr) function kim_api_get_shape_f(kimmdl, nm, shape, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_shape_f
                      character (len=*) :: nm
                      integer :: kimerror
                      integer, pointer :: shape(:)
      end function kim_api_get_shape_f

******************************************************************************

void KIM_API_set_shape(void *kimmdl, char *nm, int *shape, int rank, int *kimerror);

    This routine sets the `shape' of `nm' and checks if the `rank' provided is
    the same as that already stored in the KIM API object.  This will overwrite
    all of the shape data stored in the KIM API object for this argument.  This
    routine should not be used in conjunction with arguments for which
    KIM_API_allocate() has previously allocated memory.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *))

      char *nm
              null terminated string is the name of the argument field exactly
              as it appears in the .kim descriptor file

      int *shape
              An array of integers for the shape of the array data.  The
              routine will use the values in this array for each dimension of
              the data object (the number of these must be equal to the rank
              value passed to the function).  Shape gives the range of each
              index for the array data.  Shape[0] is the slowest changing
              index.

      int rank
              Rank of the array and size of shape

      int *kimerror
              error code: KIM_STATUS_OK                -- successful completion,
                          KIM_STATUS_ARG_UNKNOWN       -- name nm is not in KIM
                          KIM_STATUS_ARG_INVALID_RANK  -- rank provided, does
                                                          not match KIM API
                                                          argument rank
                          KIM_STATUS_ARG_INVALID_SHAPE -- negative index in
                                                          shape

Corresponding Fortran style interface:

      subroutine kim_api_set_shape_f(kimmdl, nm, shape, rank, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      character (len=*) :: nm
                      integer :: rank, kimerror, shape(rank)
      subroutine kim_api_set_shape_f

******************************************************************************

void KIM_API_set_compute(void *kimmdl, char *nm, int flag, int *kimerror);

    This routine sets the status of the `compute' flag.  If the argument can be
    optionally computed, a Model can check if a Test wants the argument to be
    computed.

    NOTES:

    (1) The Test is responsible for ensuring that memory has been allocated for
        the argument being requested.

    (2) All arguments that appear in the descriptor (.kim) files of both the
        Test and Model are initially set to `compute'.  Therefore, this routine
        would normally only be called if a change to this default behavior is
        desired.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      char *nm
              null terminated string is the name of the argument field, exactly
              as it appears in the .kim descriptor file.

      int flag
              KIM_COMPUTE_FALSE or KIM_COMPUTE_TRUE to turn off compute or turn
              on compute, respectively.

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      subroutine kim_api_set_compute_f(kimmdl, nm, flag, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      character (len=*) :: nm
                      integer :: flag,kimerror
      end subroutine kim_api_set_compute_f

******************************************************************************

int KIM_API_get_compute(void *kimmdl, char *nm, int *kimerror);

    This routine checks the status of the `compute' flag.  If the argument can
    be optionally computed, a Model can check if a Test wants the argument to
    be computed.  Returned value: KIM_COMPUTE_FALSE means do not compute,
    KIM_COMPUTE_TRUE means compute.  KIM_STATUS_ARG_UNKNOWN is returned on
    error.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      char *nm
              null terminated string is the name of the argument field, exactly
              as it appears in the .kim descriptor file.

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      integer function kim_api_get_compute_f(kimmdl, nm, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      character (len=*) :: nm
                      integer :: kimerror
                      integer :: kim_api_get_compute_f
      end function kim_api_get_compute_f

******************************************************************************

int KIM_API_get_index(void *kimmdl, char*nm, int *kimerror);

    This routine returns the index of an argument field in the KIM API object.
    This index serves as an integer offset that allows for efficient access to
    the KIM API object.  (This eliminates the overhead in the element access
    routines associated with using the string `nm' to search for the argument.)
    This index is guaranteed to remain valid for the lifetime of the KIM API
    object.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      char *nm
              null terminated string is the name of the argument field exactly
              as it appears in the .kim descriptor file.

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      integer function kim_api_get_index_f(kimmdl, nm, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      character (len=*) :: nm
                      integer :: kimerror
                      integer :: kim_api_get_index_f
      end function kim_api_get_index_f

******************************************************************************

int KIM_API_model_init(void *kimmdl);

    This routine will initialize the Model associated with the KIM API object
    by calling the init routine supplied by the Model.  It uses the Model's
    name (which is stored in KIM API object by the KIM_API_init routine).  The
    return value will be KIM_STATUS_OK in case of success and KIM_STATUS_FAIL
    otherwise.

    NOTES:

    (1) In order to call KIM_API_model_init() it is necessary to have a valid
        KIM API object pointed to by `kimmdl' (see KIM_API_init() above).  The
        mandatory argument `cutoff' must be registered in this KIM API object
        and it must have memory allocated to it (via either the
        KIM_API_allocate() or KIM_API_set_data() routines).

    (2) The Model's init routine must store its cutoff value in the KIM API
        object and register pointers to its `compute' function (and its
        `reinit' and `destroy' functions, if supported).  If the Model supports
        `flexible' units, it must query the KIM API object (via the
        KIM_API_get_unit_*() functions) and adjust its parameters
        appropriately.  It may also publish its parameters as either fixed or
        free (see the standard.kim file) and perform any other necessary
        initialization steps.  It is important to stress that a Model may not
        store data in static memory since it may be called with different KIM
        API objects.  Any information that should persist between calls must be
        stored in the KIM API object.  Fixed parameters may be used for this
        purpose or the Model Buffer (See details and cautionary notes about
        this in the documentation for KIM_API_set/get_model_buffer and also in
        the standard.kim file.)

    (3) The Model must define a model_init function (the name of this function
        must be the lower-case version of the Model's name with _init appended
        to the end [and with an underscore appended to the end for C and C++];
        here we use the example Model name "ex_Model_1") with prototype:
           extern "C" { int ex_model_1_init_(void *kimmdl); } // in C++
           int ex_model_1_init_(void *kimmdl);                /* in C */
           integer function ex_Model_1_init(pkim)
              integer(kind=kim_intptr), intent(in) :: pkim
                                                              ! in Fortran

    (4) ***Model Drivers*** The KIM_API, as described in this document, has no
        knowledge of the Model Driver concept.  The openkim-api Makefile system
        does all the magic to completely hide the distinction between a
        "standard Model" and a "driver based Model".  In practice, there is
        only one interface difference between a Model and a Model Driver.  This
        is the model_init function.  The model_init function for a Model Driver
        must accept additional arguments in order for it to have access to the
        parameter files needed to implement a particular "driver based Model."
        The model_init function for a Model Driver (the name of this function
        must be the lower-case version of the Model Driver's name with _init
        appended to the end [and with an underscore appended to the end for C
        and C++]; here we use the example Model Driver name "ex_Driver_5") with
        prototype:
           extern "C" { int ex_driver_5_init_(void *kimmdl, char *paramfile_names,
                                              int *nmstrlen, int *numparamfiles);}
                                                                     // in C++
           int ex_driver_5_init_(void *kimmdl, char *paramfile_names,
                                 int *nmstrlen, int *numparamfiles); /* in C */
           integer function ex_Driver_5_init(pkim, byte_paramfile_names, &
                                             nmstrlen, numparamfiles)
              integer(kind=kim_intptr), intent(in) :: pkim
              integer,                  intent(in) :: nmstrlen
              integer,                  intent(in) :: numparamfiles
              byte,                     intent(in) :: byte_paramfile_names(nmstrlen*numparamfiles)
                                                                     ! in Fortran
        The argument `paramfile_names' is a pointer to a 2D character array (in
        C, char paramfile_names[numparamfiles][nmstrlen]).  `nmparamfiles' and
        `nmstrlen' make up the extent of the paramfile_name array.  The i-th
        row of this array will contain a string with the absolute path to the
        Model's i-th parameter file, which the Model Driver should read from.

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

Corresponding Fortran style interface:

      integer function kim_api_model_init_f(kimmdl)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kim_api_model_init_f
      end function kim_api_model_init_f

******************************************************************************

int KIM_API_model_reinit(void *kimmdl);

    This routine will reinitialize the Model associated with the KIM API object
    by calling the reinit routine supplied by the Model.  The return value will
    be KIM_STATUS_OK in case of success and KIM_STATUS_FAIL otherwise.

    NOTES:

    (1) In order to call KIM_API_model_reinit() it is necessary to have a valid
        KIM API object pointed to by `kimmdl' (see KIM_API_init()).
        Additionally, KIM_API_model_init() must have been previously executed
        for this KIM API object.

    (2) This routine must be called if the Test has changed one or more of the
        Model's free parameters (see standard.kim for more discussion about
        Model Parameters).

    (3) The Model may define a model_reinit function (the name of this
           function is not important) with prototype:
           extern "C" { int model_reinit(void *kimmdl); } // in C++
           int model_reinit(void *kimmdl);                /* in C */
           integer function model_reinit(pkim)
              integer(kind=kim_intptr), intent(in) :: pkim
                                                          ! in Fortran
        If a model defines a model_reinit functions, a pointer to this function
        must be registered in the KIM_API object using one of the "set data"
        api service routines.

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

Corresponding Fortran style interface:

      integer function kim_api_model_reinit_f(kimmdl)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kim_api_model_reinit_f
      end function kim_api_model_reinit_f

******************************************************************************

char *KIM_API_get_model_partcl_typs(void *kimmdl, int *nPTypes, int *kimerror);

    This routine returns a sorted list of the Model's supported particle
    types. This routine returns a pointer to an array of fixed size text
    strings.  (The text strings are of size KIM_KEY_STRING_LENGTH, which is a
    constant defined by the KIM API.)  The memory pointed to by this pointer is
    allocated by the routine, but should be released by the user to avoid a
    memory leak.  Each string is an atom/particle symbol.  In the case where no
    particle types are specified by the Model or Test, the routine returns
    NULL.

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *nPTypes
              total number of particle types. In case of error will be
              negative.

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      function kim_api_get_model_partcl_typs_f(kimmdl, nptypes, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_model_partcl_typs
                      integer :: nptypes, kimerror
      end function kim_api_get_model_partcl_typs_f

******************************************************************************

char *KIM_API_get_test_partcl_typs(void *kimmdl, int *nPTypes, int *kimerror);

    This routine returns a sorted list of the Test's supported particle
    types. This routine returns a pointer to an array of fixed size text
    strings.  (The text strings are of size KIM_KEY_STRING_LENGTH, which is a
    constant defined by the KIM API.)  The memory pointed to by this pointer is
    allocated by the routine, but should be released by the user to avoid a
    memory leak.  Each string is an atom/particle symbol.  In the case where no
    particle types are specified by the Model or Test, the routine returns
    NULL.

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *nPTypes
              total number of particle types. In case of error will be
              negative.

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      function kim_api_get_test_partcl_typs_f(kimmdl, nptypes, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_test_partcl_typs
                      integer :: nptypes, kimerror
      end function kim_api_get_test_partcl_typs_f

******************************************************************************

char *KIM_API_get_params(void *kimmdl, int *nVpar, int *kimerror);

    This routine returns a pointer to an array of fixed size text strings, each
    string is the name of a Model parameter argument.  (The text strings are of
    size KIM_KEY_STRING_LENGTH, which is a constant defined by the KIM API.)
    The memory pointed to by this pointer is allocated by the routine, but
    should be released by the user to avoid a memory leak.  A Model parameter
    argument is one whose name starts with `PARAM_FREE_' or `PARAM_FIXED_'.
    Each parameter argument described in the Model's .kim file will have a
    place in the KIM API object, but it will not be checked against the
    standard.kim file.  (See the standard.kim file for more information on
    Model parameters.)

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *nVpar
              total number of parameters.

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      function kim_api_get_params_f(kimmdl, nvpar, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_params_f
                      integer :: nvpar, kimerror
      end function kim_api_get_params_f

******************************************************************************

char *KIM_API_get_free_params(void *kimmdl, int *nVpar, int *kimerror);

    This routine returns a pointer to an array of fixed size text strings, each
    string is the name of one of the Model's FREE parameter arguments.  (The
    text strings are of size KIM_KEY_STRING_LENGTH, which is a constant defined
    by the KIM API.)  The memory pointed to by this pointer is allocated by the
    routine, but should be released by the user to avoid a memory leak.  A
    Model FREE parameter argument is one whose name starts with `PARAM_FREE_'.
    Each FREE parameter argument described in the Model's .kim file will have a
    place in the KIM API object, but it will not be checked against the
    standard.kim file.  (See the standard.kim file for more information on
    Model FREE parameters.)

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *nVpar
              total number of parameters.

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      function kim_api_get_free_params_f(kimmdl, nvpar, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_free_params_f
                      integer :: nvpar, kimerror
      end function kim_api_get_free_params_f

******************************************************************************

char *KIM_API_get_fixed_params(void *kimmdl, int *nVpar, int *kimerror);

    This routine returns a pointer to an array of fixed size text strings, each
    string is the name of one of the Model's FIXED parameter arguments.  (The
    text strings are of size KIM_KEY_STRING_LENGTH, which is a constant defined
    by the KIM API.)  The memory pointed to by this pointer is allocated by the
    routine, but should be released by the user to avoid a memory leak.  A
    Model FIXED parameter argument is one whose name starts with
    `PARAM_FIXED_'.  Each FIXED parameter argument described in the Model's
    .kim file will have a place in the KIM API object, but it will not be
    checked against the standard.kim file.  (See the standard.kim file for more
    information on Model FIXED parameters.)

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *nVpar
              total number of parameters.

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      function kim_api_get_fixed_params_f(kimmdl, nvpar, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_fixed_params_f
                      integer :: nvpar, kimerror
      end function kim_api_get_fixed_params_f

******************************************************************************

char *KIM_API_get_NBC_method(void *kimmdl, int *kimerror);

    This routine returns a pointer to a fixed size text string (of size
    KIM_KEY_STRING_LENGTH, which is a constant defined by the KIM API).  The
    memory pointed to by this pointer is allocated by the routine, but should
    be released by the user to avoid a memory leak.  The string is the NBC
    (Neighbor list and Boundary Conditions) method in use by the KIM_API object
    `kimmdl'.  (See the standard.kim file for more information on NBC methods.)

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      function kim_api_get_nbc_method_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_nbc_method_f
                      integer :: kimerror
      end function kim_api_get_nbc_method_f

******************************************************************************

int KIM_API_get_partcl_type_code(void *kimmdl, char* particle, int *kimerror);

    This routine returns the particle type ID for a given particle symbol, as
    defined by the Model associated with the KIM API object.  The routine
    returns KIM_STATUS_PARTICLE_TYPES_UNDEFINED if no atom/particle types have
    been provided in the .kim files.  (See the standard.kim file for more
    information on atom/particle types.)  The routine returns
    KIM_STATUS_PARTICLE_INVALID_TYPE if the supplied symbol, particle, is not
    among the KIM supported particle symbols.  (See standard.kim for the list
    of supported atom/particle types.)

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      char *particle
              atom/particle symbol

      int *kimerror
              error code: KIM_STATUS_OK                       -- successful completion
                          KIM_STATUS_FAIL                     -- unsuccessful
                          KIM_STATUS_PARTICLE_INVALID_TYPE    -- symbol is not among the
                                                                 KIM supported atom symbols
                          KIM_STATUS_PARTICLE_TYPES_UNDEFINED -- no atom/particle types have
                                                                 been specified by the
                                                                 Test or Model.

Corresponding Fortran style interface:

      integer function kim_api_get_partcl_type_code_f(kimmdl, nm, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      character (len=*) :: nm
                      integer :: kimerror
                      integer :: kim_api_get_partcl_type_code_f
      end function kim_api_get_partcl_type_code_f

******************************************************************************

void KIM_API_set_partcl_type_code(void *kimmdl, char* particle, int code, int *kimerror);

    This routine sets the particle type ID for a given particle symbol.  Only
    those particle types which the Model listed with code `-1' in its
    descriptor file may be changed.  The routine returns
    KIM_STATUS_PARTICLE_TYPES_UNDEFINED if no atom/particle types have been
    provided in the .kim files.  (See the standard.kim file for more
    information on atom/particle types.)  The routine returns
    KIM_STATUS_PARTICLE_INVALID_TYPE if the supplied symbol, particle, is not
    among the KIM supported particle symbols.  (See standard.kim for the list
    of supported atom/particle types.)

Arguments:
      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      char *particle
              atom/particle symbol

      int code
              integer value used by the Model to represent the specified particle type

      int *kimerror
              error code: KIM_STATUS_OK                       -- successful completion
                          KIM_STATUS_FAIL                     -- unsuccessful
                          KIM_STATUS_PARTICLE_INVALID_TYPE    -- symbol is not among the
                                                                 KIM supported atom symbols
                          KIM_STATUS_PARTICLE_TYPES_UNDEFINED -- no atom/particle types have
                                                                 been specified by the
                                                                 Test or Model.

Corresponding Fortran style interface:

      subroutine kim_api_set_partcl_type_code_f(kimmdl, nm, code, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      character (len=*) :: nm
                      integer :: code
                      integer :: kimerror
      end subroutine kim_api_set_partcl_type_code_f

******************************************************************************

char *KIM_API_get_model_kim_str(char *modelname, int *kimerror);

    This routines returns a pointer to a NULL terminated string containing the
    complete KIM descriptor file for the Model modelname.  The memory pointed
    to by this pointer is allocated by the routine, but should be released by
    the user to avoid a memory leak.  If any errors occur they are fatal and
    the routine prints a message to kim.log and exits.

Arguments:

      char *modelname
              model name in KIM

      int *kimerror
              error code: KIM_STATUS_OK  -- successful completion

Corresponding Fortran style interface:

      function kim_api_get_model_kim_str_f(modelname, kimerror)
                      integer(kind=kim_intptr):: modelname
                      integer(kind=kim_intptr):: kim_api_get_model_kim_str_f
                      integer :: kimerror
      end function kim_api_get_model_kim_str_f

******************************************************************************

int KIM_API_get_neigh_mode(void *kimmdl, int *kimerror);

    This routine returns a code for the neighbor list mode that should be used
    by the Model and Test.  The codes and their corresponding meanings are:
         1  -- for Iterator mode
         2  -- for Locator mode
         3  -- for Both (Model needs iterator and locator mode)

    The routine returns a negative value if it encounters an error.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style the definition
              will be (KIM_API_model *)).

      int *kimerror
              error code: KIM_STATUS_OK   -- successful completion,
                          KIM_STATUS_FAIL -- unsuccessful

Corresponding Fortran style interface:

      integer function kim_api_get_neigh_mode_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kimerror
                      integer :: kim_api_get_neigh_mode_f
      end function kim_api_get_neigh_mode_f

******************************************************************************

int KIM_API_get_neigh(void *kimmdl, int mode, int request, int *particle,
                      int *numnei, int **nei1particle, double **rij);

    This routine provides standardized access to the neighbor list supplied by
    the Test.  The Test must have previously registered, in the KIM API object,
    a pointer to its neighbor list access routine with the same interface as
    above (except that `mode' and `request' must be of type `int *'). That is,
       extern "C" { int get_neigh(void *kimmdl, int *mode, int* request,
                                  int *particle, int *numnei, int **nei1particle,
                                  double **rij); }                   // in C++
       int get_neigh(void *kimmdl, int *mode, int* request, int *particle,
                     int *numnei, int **nei1particle, double **rij); /* in C */
       integer function get_neigh(pkim, mode, request, atom, numnei,
                                  pnei1atom, pRij)
          integer(kind=kim_intptr), intent(in)  :: pkim
          integer,                  intent(in)  :: mode
          integer,                  intent(in)  :: request
          integer,                  intent(out) :: atom
          integer,                  intent(out) :: numnei
          integer(kind=kim_intptr), intent(out) :: pnei1atom
          integer(kind=kim_intptr), intent(out) :: pRij              ! in Fortran

    Two modes are supported: `Iterator' and `Locator'.  In Iterator mode, the
    Iterator should, first, be reset.  Then, a call to this function will
    return the neighbor list for the "next" particle (the order in which
    particles are returned is immaterial in Iterator mode, and therefore
    undefined).  This process repeats until the neighbor list of every particle
    has been returned and the iterator is incremented past the end of the list.
    In Locator mode, the user explicitly requests the particle for which a
    neighbor list is desired.  This mode must be used when the order in which
    particle neighbor lists are processed is important.

    NOTE: The list of neighbors returned for a given particle should not
          include the particle itself unless it is an image particle with a
          non-zero rij vector entry. (See explanation of rij vectors below.)

    The return value depends on the results of execution:
      KIM_STATUS_NEIGH_ITER_INIT_OK             -- iterator has been
                                                   successfully initialized
      KIM_STATUS_OK                             -- successful operation
      KIM_STATUS_NEIGH_ITER_PAST_END            -- iterator has been
                                                   incremented past end of list
      KIM_STATUS_NEIGH_INVALID_REQUEST          -- invalid particle ID requested
                                                   (request out of range)
      KIM_STATUS_NEIGH_INVALID_MODE             -- invalid mode value
      KIM_STATUS_API_OBJECT_INVALID             -- invalid KIM API object
      KIM_STATUS_NEIGH_TOO_MANY_NEIGHBORS       -- Number of neighbors of a
                                                   particle too big to allocate
                                                   memory for index conversion
      KIM_STATUS_NEIGH_FULL_METHOD_NOT_PROVIDED -- get_neigh method in
                                                   KIM API object is not
                                                   set (NULL value)
Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int mode
              Operate in iterator or locator mode
              mode = 0 : iterator mode
              mode = 1 : locator mode

      int request
              Requested operation
              If mode = 0
                  request = 0 : reset iterator (and return without neighbors)
                  request = 1 : increment iterator
              If mode = 1
                  request = # : number of particle whose neighbor list is
                                requested.  This id should be 0-based if the
                                Model includes ZeroBasedLists in its KIM
                                descriptor file and 1-based if OneBasedLists is
                                included.  (The KIM API will automatically do
                                any necessary conversions.)

      int *particle
              The number of the particle whose neighbor list is returned.  This
              id value will be 0-based if the Model includes ZeroBasedLists in
              its KIM descriptor file and 1-based if OneBasedLists is included.
              (The KIM API will automatically do any necessary conversions.)

      int *numnei
              number of neighbors returned

      int **nei1particle
               pointer argument which will point to the list of neighbors on
               exit.  The neighbor ID values stored in this list will be
               0-based if the Model includes ZeroBasedLists in its KIM
               descriptor file and 1-based if OneBasedLists is included.  (The
               KIM API will automatically do any necessary conversions.)

      double **rij
              pointer argument which will point to the list of relative
              position vectors of the neighbors of a `particle', i.e. if the
              particle index is `i' and its neighbors are indexed by `j', then
              r_ij = x_j - x_i (including boundary conditions if applied). This
              data is only available for NBC method NEIGH_RVEC_F. The returned
              value is NULL for all other NBC methods. (See standard.kim for
              more information on NBC methods.)

Corresponding Fortran style interface:

      integer function kim_api_get_neigh_f(kimmdl, mode, request, particle, &
                                           numnei, pnei1particle, prij)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kim_api_get_neigh_f
                      integer :: mode, request, particle, numnei
                      ! array from which neighbors are accessed
                      integer :: nei1particle(1)
                      ! actual cray pointer associated with nei1particle
                      pointer(pnei1particle, nei1particle)
                      real*8 :: rij(3,1)
                      pointer(prij, rij)
      end function kim_api_get_neigh_f

******************************************************************************

int KIM_API_process_dEdr(void **km, double *dEdr, double *r, double **dx, &
                          int *i, int *j);

    This routine can be called by a Model to provide the Test with a
    contribution, dEdr, to the first derivative of the Model's energy with
    respect to the (scalar) distance r_ij between particle `i' and particle
    `j'.  The Test can use this information to compute, via the chain-rule,
    many properties.  Examples include forces, the virial, and other
    thermodynamic tensions.  The KIM API performs automatic index conversion
    (based on ZeroBasedList and OneBasedList flag settings) before calling the
    Test's supplied process_dEdr function.  If the Test provides a process_dEdr
    function, it must register, in the KIM API object, a pointer to this
    function.  The function must conform to the following interface:
       extern "C" { int process_dEdr(void *kimmdl, double *dEdr, double *r,
                                     double **dx, int *i, int *j); } // in C++
       int process_dEdr(void *kimmdl, double *dEdr, double *r,
                        double **dx, int *i, int *j);                /* in C */
       integer function process_dEdr(pkim, dEdr, r, pdx, i, j)
          integer(kind=kim_intptr), intent(in) :: pkim
          real*8,                   intent(in) :: dEdr
          real*8,                   intent(in) :: r
          integer(kind=kim_intptr), intent(in) :: pdx
          integer,                  intent(in) :: i
          integer,                  intent(in) :: j                  ! in Fortran

    If the Test does not provide its own process_dEdr routine, then the KIM API
    standard process_dEdr routine is used.  If the standard process_dEdr
    routine is used, the KIM API ensures that any appropriate memory
    initializations are performed.  This routine currently supports the
    computation of `virial' and `particleVirial'.  Return value: KIM_STATUS_OK
    if successful and KIM_STATUS_FAIL if unsuccessful.

Arguments:

      void **km
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model **)).

      double *dEdr
              pointer to the contribution to the first derivative of the energy
              with respect to the pair-distance r_ij (dE/dr_ij).

      double *r
              pointer to r_ij -- the distance between particles i and j

      double **dx
              pointer to the relative position vector of particle j
              relative to particle i (i.e., r_ij = x_j - x_i).

      int *i
              pointer to particle index i

      int *j
              pointer to particle index j

Corresponding Fortran style interface:

      subroutine kim_api_process_dedr_f(kimmdl, de, r, dx, i, j, kimerror)
                      integer(kind=kim_intptr) :: kimmdl, dx
                      real*8 :: de, r
                      integer ::i, j, kimerror
      end subroutine kim_api_process_dedr_f

******************************************************************************

int KIM_API_process_d2Edr2(void **km, double *d2Edr2, double **r, &
                            double **dx, int **i, int **j);

    This routine can be called by a Model to provide the Test with a
    contribution, d2Edr2, to the second derivative of the Model's energy with
    respect to the (scalar) distances r_i[0]j[0] and r_i[1]j[1] between
    particle i[0] and j[0] and between particles i[1] and j[1], respectively.
    The Test can use this information (often in conjunction with information
    from process_dEdr) to compute, via the chain-rule, many properties.  An
    example is the hessian.  The KIM API performs automatic index conversion
    (based on ZeroBasedList and OneBasedList flag settings) before calling the
    Test's supplied process_d2Edr2 function.  If the Test provides a process_d2Edr2
    function, it must register, in the KIM API object, a pointer to this
    function.  The function must conform to the following interface:
       extern "C" { int process_d2Edr2(void *kimmdl, double *d2Edr2, double **r,
                                       double **dx, int **i, int **j); } // in C++
       int process_d2Edr2(void *kimmdl, double *d2Edr2, double **r,
                          double **dx, int **i, int **j);                /* in C */
       integer function process_d2Edr2(pkim, d2Edr2, pr, pdx, pi, pj)
          integer(kind=kim_intptr), intent(in) :: pkim
          real*8,                   intent(in) :: d2Edr2
          integer(kind=kim_intptr), intent(in) :: pr
          integer(kind=kim_intptr), intent(in) :: pdx
          integer(kind=kim_intptr), intent(in) :: pi
          integer(kind=kim_intptr), intent(in) :: pj                     ! in Fortran

    If the Test does not provide its own process_d2Edr2 routine, then the KIM
    API standard process_d2Edr2 routine is used.  If the standard process_dEdr
    routine is used, the KIM API ensures that any appropriate memory
    initializations are performed.  This routine and currently supports the
    computation of `hessian' (process_dEdr is also required in order to
    correctly compute the hessian).  Return value: KIM_STATUS_OK if successful
    and KIM_STATUS_FAIL if unsuccessful.

Arguments:

      void **km
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model **)).

      double *d2Edr2
              pointer to contribution to the second derivative of energy with
              respect to the pair-distances r_i[0]j[0] and r_i[1]j[1]
              (d^2E/dr_kl dr_mn).

      double **r
              pointer to array of two doubles -- the distances r[0] and r[1]
              between particles i[0] and j[0] and i[1] and j[1], respectively.

      double **dx
              pointer to the relative position vectors {dx[0], dx[1], dx[2]}
              and {dx[3], dx[4], dx[5]} of particle j[0] relative to i[0] and
              j[1] relative to i[1], respectively.

      int **i
              pointer to particle indices i[0] and i[1]

      int **j
              pointer to particle indices j[0] and j[1]

Corresponding Fortran style interface:

      subroutine kim_api_process_d2edr2_f(kimmdl, d2edr2, r, dx, i, j, kimerror)
                      integer(kind=kim_intptr) :: kimmdl, dx
                      real*8 :: d2edr2, r
                      integer :: i, j, kimerror
      end subroutine kim_api_process_d2edr2_f

******************************************************************************

char *KIM_API_get_status_msg(int status_code);

    This routine returns a null terminated character string that describes the
    `status_code'.  `status_code' should contain a `kimerror' code returned by
    a KIM service routine.

Arguments:
      int status_code
              kimerror code for which a description is desired.

Corresponding Fortran style interface:

     function kim_api_get_status_msg_f(status_code)
                      integer :: status_code
                      integer(kind=kim_intptr) :: kim_api_get_status_msg_f
     end function kim_api_get_status_msg_f

******************************************************************************

int KIM_API_report_error(int line, char *file, char *usermsg, int status_code);

    This routine prints the standard KIM error message associated with
    `status_code' as well as the user supplied message `usermsg'.  It returns
    KIM_STATUS_FAIL if status_code is less than KIM_STATUS_OK. Otherwise it
    returns KIM_STATUS_OK.

Arguments:

      int line
              line in the file where the call is made (the preprocessor value
              of __LINE__ may be used here)

      char * file
              name of the file from which the call is made (the preprocessor
              value of __FILE__ may be used here)

      char * usermsg
              user defined error message

      int status_code
              kimerror status code returned by a KIM service routine.

Corresponding Fortran style interface:

     integer function kim_api_report_error_f(line, fl, usermsg, status_code)
                      integer :: status_code, line
                      integer :: kim_api_report_error_f
                      character(len=*) :: fl, usermsg
     end function kim_api_report_error_f

******************************************************************************

double KIM_API_get_scale_conversion(char *u_from, char *u_to, int *kimerror);

    This routine returns the scale conversion factor between one unit and
    another.  For example, KIM_API_get_scale_conversion("cm","m", &kimerror)
    will return the value 0.01.  Both `u_from' and `u_to' must be from the same
    supported base unit (length, energy, charge, temperature, or time).  See
    standard.kim for valid values within each base unit.  The function returns
    a negative value if an error occurs.

Arguments:

      char *u_from
              conversion from unit string

      char *u_to
              conversion to unit string

      int *kimerror
              error status -- a standard KIM_STATUS value

Corresponding Fortran style interface:

      real*8 function kim_api_get_scale_conversion_f(from, to, kimerror)
                      integer :: kimerror
                      character(len=*) :: from, to
                      real*8 kim_api_get_scale_conversion_f
      end function kim_api_get_scale_conversion_f

******************************************************************************

int KIM_API_get_unit_handling(void *kimmdl, int *kimerror);

    Returns 1 if Unit_Handling is `flexible', 0 otherwise.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              KIM_STATUS_OK is always returned

Corresponding Fortran style interface:

      integer function kim_api_get_unit_handling_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer :: kimerror
                      integer :: kim_api_get_unit_handling_f
      end function kim_api_get_unit_handling_f

******************************************************************************

char *KIM_API_get_unit_length(void *kimmdl, int *kimerror);

    Returns the current setting of the KIM_API_model object for the base unit
    of length.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              KIM_STATUS_OK is always returned

Corresponding Fortran style interface:

      function kim_api_get_unit_length_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_unit_length_f
                      integer :: kimerror
      end function kim_api_get_unit_length_f

******************************************************************************

char *KIM_API_get_unit_energy(void *kimmdl, int *kimerror);

    Returns the current setting of the KIM_API_model object for the base unit
    of energy.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              KIM_STATUS_OK is always returned

Corresponding Fortran style interface:

      function kim_api_get_unit_energy_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_unit_energy_f
                      integer :: kimerror
      end function kim_api_get_unit_energy_f

******************************************************************************

char *KIM_API_get_unit_charge(void *kimmdl, int *kimerror);

    Returns the current setting of the KIM_API_model object for the base unit
    of charge.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              KIM_STATUS_OK is always returned

Corresponding Fortran style interface:

      function kim_api_get_unit_charge_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_unit_charge_f
                      integer :: kimerror
      end function kim_api_get_unit_charge_f

******************************************************************************

char *KIM_API_get_unit_temperature(void *kimmdl, int *kimerror);

    Returns the current setting of the KIM_API_model object for the base unit
    of temperature.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              KIM_STATUS_OK is always returned

Corresponding Fortran style interface:

      function kim_api_get_unit_temperature_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_unit_temperature_f
                      integer :: kimerror
      end function kim_api_get_unit_temperature_f

******************************************************************************

char *KIM_API_get_unit_time(void *kimmdl, int *kimerror);

    Returns the current setting of the KIM_API_model object for the base unit
    of time.

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      int *kimerror
              KIM_STATUS_OK is always returned

Corresponding Fortran style interface:

      function kim_api_get_unit_time_f(kimmdl, kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      integer(kind=kim_intptr) :: kim_api_get_unit_time_f
                      integer :: kimerror
      end function kim_api_get_unit_time_f

******************************************************************************

double KIM_API_convert_to_act_unit(void *kimmdl, char *length, char *energy,
                                   char *charge, char *temperature, char *time,
                                   double length_exponent,
                                   double energy_exponent,
                                   double charge_exponent,
                                   double temperature_exponent,
                                   double time_exponent,
                                   int *kimerror);

    This function returns scale conversion factor for a derived unit from the
    supplied base units to the "active" set of base units associated with the
    KIM API object kimmdl.  The derived unit is defined by the supplied
    exponents for each of the base units.  If the supplied base units are not
    among the standard supported base units (see standard.kim), an appropriate
    KIM status code is returned.  For example, consider the conversion of the
    quantity `10 N/s' to the equivalent active unit.  C code for this would be:

      double forcePerTime = 10.0; /* N/s */
      forcePerTime *= KIM_API_convert_to_act_unit(kimmdl,
                                                   "m",  "J", "C", "K",  "s",
                                                  -1.0,  1.0, 0.0, 0.0, -1.0,
                                                  kimerror);

Arguments:

      void *kimmdl
              pointer to KIM_API_model object (in C++ style, the definition
              will be (KIM_API_model *)).

      char *length
              base unit of length string

      char *energy
              base unit of energy string

      char *charge
              base unit of charge string

      char *temperature
              base unit of temperature string

      char *time
              base unit of time string

      double length_exponent
              exponent for length contribution to derived unit

      double energy_exponent
              exponent for energy contribution to derived unit

      double charge_exponent
              exponent for charge contribution to derived unit

      double temperature_exponent
              exponent for temperature contribution to derived unit

      double time_exponent
              exponent for time contribution to derived unit

      int *kimerror
              KIM_STATUS_OK (if successful completion)

Corresponding Fortran style interface:

      real*8 function kim_api_convert_to_act_unit_f(kimmdl, length, energy, &
                                                    charge, temperature,    &
                                                    time,                   &
                                                    length_exponent,        &
                                                    energy_exponent,        &
                                                    charge_exponent,        &
                                                    temperature_exponent,   &
                                                    time_exponent,          &
                                                    kimerror)
                      integer(kind=kim_intptr) :: kimmdl
                      character(len=*) :: length, energy, charge
                      character(len=*) :: temperature, time
                      real*8 :: length_exponent, energy_exponent
                      real*8 :: charge_exponent, temperature_exponent
                      real*8 :: time_exponent
                      real*8 :: kim_api_convert_to_act_unit_f
                      integer :: kimerror
      end function kim_api_convert_to_act_unit_f

******************************************************************************



==================ELEMENT ACCESS METHODS ROUTINES BY INDEX====================

The "by index" routines have the same functionality as "by name" and the same
arguments except "char *nm" is replaced by "int I".  The index of each argument
in the KIM API object is obtained by the KIM_API_get_index() routine described
above.

The prototypes of the supported "by index" routines are:

int KIM_API_set_data_by_index(void *kimmdl, int I, intptr_t size, void *dt);

void *KIM_API_get_data_by_index(void *kimmdl, int I, int *kimerror);

intptr_t KIM_API_get_size_by_index(void *kimmdl, int I, int *kimerror);

intptr_t KIM_API_get_shape_by_index(void *kimmdl, int I, int *shape, int *kimerror);

void KIM_API_set_compute_by_index(void *kimmdl, int I, int flag, int *kimerror);

int KIM_API_get_compute_by_index(void *kimmdl, int I, int *kimerror);



******************************************************************************

                          MULTIPLE ACCESS ROUTINES

******************************************************************************

In order to simplify access to KIM API object, MULTIPLE ACCESS ROUTINES are
included among the KIM service methods.  There are 9 of these routines:

c-style:
     1) KIM_API_getm_compute
     2) KIM_API_setm_compute
     3) KIM_API_getm_compute_by_index
     4) KIM_API_setm_compute_by_index
     5) KIM_API_getm_data
     6) KIM_API_setm_data
     7) KIM_API_getm_data_by_index
     8) KIM_API_setm_data_by_index
     9) KIM_API_getm_index

     Each of these routines provides access to multiple KIM API object
     arguments in one function call.  These routines have a uniform
     interface:

     void KIM_API_*m_*(void *kimmdl, int *kimerror, int numargs, ...);

     A code line that calls these routine will look like:

     KIM_API_*m_*(kimmdl, &kimerror, numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

     numargs -- must be the number of all arguments that follows it.

     There can be up to 15 VARIABLE_GROUPs in one call.  Each
     VARIABLE_GROUP has either 3 or 4 function arguments.  Therefore
     numargs must be divisible by either 3 or 4 (depending on which
     MULTIPLE ACCESS function is being called).  VARIABLE_GROUPS have
     different types of function arguments depending on the context.  The
     last variable in the group is always an integer flag (gkey) which can
     be 1 or 0.  If gkey = 1 the routine will perform the requested
     operation for the associated VARIABLE_GROUP, if gkey=0 the
     VARIABLE_GROUP will be skipped.

     The VARIABLE_GROUP definitions are:

     1.   void KIM_API_getm_compute(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

          Here VARIABLE_GROUP has 3 variables: char *name, int *compute, int gkey

     2.   void KIM_API_setm_compute(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

          Here VARIABLE_GROUP has 3 variables: char *name, int compute, int gkey

     3.   void KIM_API_getm_compute_by_index(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

          Here VARIABLE_GROUP has 3 variables: int index, int *compute, int gkey

     4.   void KIM_API_setm_compute_by_index(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

          Here VARIABLE_GROUP has 3 variables: int index, int compute, int gkey

     5.   void KIM_API_getm_data(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

          Here VARIABLE_GROUP has 3 variables: char *name, void **data, int gkey

     6.   void KIM_API_setm_data(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

          Here VARIABLE_GROUP has 4 variables: char *name, intptr_t size, void *data, int gkey

     7.   void KIM_API_getm_data_by_index(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

          Here VARIABLE_GROUP has 3 variables: int index, void **data, int gkey

     8.   void KIM_API_setm_data_by_index(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...]);

          Here VARIABLE_GROUP has 4 variables: int index, intptr_t size, void *data, int gkey

     9.   void KIM_API_getm_index(void *kimmdl, int *kimerror, int numargs, VARIABLE_GROUP1, [VARIABLE_GROUP2, ...] );

          Here VARIABLE_GROUP has 3 variables: char *name, int *index, int gkey

    `kimerror' in these routines will be KIM_STATUS_OK if the routine is successful,
    otherwise KIM_STATUS_FAIL (or other error codes < KIM_STATUS_OK).

f90-style:
    1) kim_api_getm_compute_f
    2) kim_api_setm_compute_f
    3) kim_api_getm_compute_by_index_f
    4) kim_api_setm_compute_by_index_f
    5) kim_api_getm_data_f
    6) kim_api_setm_data_f
    7) kim_api_getm_data_by_index_f
    8) kim_api_setm_data_by_index_f
    9) kim_api_getm_index_f

    The interface here is exactly as it is for the c-style, except that the
    `numargs' argument is not required.

    As an example, in C, suppose a Model wants to determine if the Test has
    requested that the `energy', `virial', and/or the `hessian' should be
    computed.  Then, for each requested argument the Model needs to get a
    memory pointer to know where to store the results of the computations.  The
    corresponding code looks like:

      int     comp_energy,  comp_virial,  comp_hessian;
      double *energy_data, *virial_data, *hessian_data;
      KIM_API_getm_compute(kimmdl, &kimerror, 3*3,
                           "energy",  &comp_energy,  1,
                           "virial",  &comp_virial,  1,
                           "hessian", &comp_hessian, 1);
      KIM_API_getm_data(kimmdl, &kimerror, 3*3,
                        "energy",   &energy_data,  (comp_energy  == 1),
                        "virial",   &virial_data,  (comp_virial  == 1),
                        "hessian",  &hessian_data, (comp_hessian == 1));

      If the Test has not requested computation of the `virial', for example,
      then the `comp_virial' variable will be set to zero by the call to
      KIM_API_getm_compute().  Then, in the KIM_API_getm_data() call the
      logical statement (comp_virial == 1) will evaluate to false (0) and the
      value of the `virial_data' will not be retrieved.

******************************************************************************



========================Fortran AUXILIARY ROUTINES============================

Several auxiliary routines are provided which are not directly connected with
the KIM API.  These routines simplify handling and transforming data, for
example, from cray pointers to Fortran 90 array pointers.

The following subroutine converts a C-type array to a Fortran 90 type array
(pointer).  For example the C-type array can be a pointee of a cray pointer.
Using this routine, one can cast a cray pointer to a Fortran 90 array pointer.

       subroutine KIM_to_F90_real_array_2d(cTypeArray, ArrayWithDescriptor, n, m)
                        implicit none
                        integer :: n, m
                        real*8, target  :: cTypeArray(n,m)
                        real*8, pointer :: ArrayWithDescriptor(:,:)
       end subroutine KIM_to_F90_real_array_2d

Arguments:

      real*8 cTypeArray
              This argument corresponds to a C-type pointer to a block of
              memory

      real*8 ArrayWithDescriptor
              This argument corresponds to a native F90 array which includes a
              pointer to the block of memory, but also some additional memory
              (created, managed, and used only by the compiler) to keep track
              of the array's shape and extents.

An example of the use of these routines is:

   integer kimerror, DIM
   integer numberOfParticles; pointer(pnumberOfParticles, numberOfParticles)
   real*8  coordum(DIM,1);    pointer(pcoor,coordum)
   real*8, pointer :: coor(:,:)

   DIM = 3
   kim_api_getm_data_f(kimmdl, kimerror,                           &
                       "numberOfParticles", pnumberOfParticles, 1, &
                       "coordinates",       pcoor,              1)

   call KIM_to_F90_real_array_2d(coordum, coor, DIM, numberOfParticles)


The following routines exist for casting cray pointers to different shapes
and types of Fortran 90 style arrays:

KIM_to_F90_int_array_1d(ctypeArray, ArrayWithDescriptor, n)
KIM_to_F90_int_array_2d(ctypeArray, ArrayWithDescriptor, n, m)
KIM_to_F90_int_array_3d(ctypeArray, ArrayWithDescriptor, n, m, p)

KIM_to_F90_real_array_1d(ctypeArray, ArrayWithDescriptor, n)
KIM_to_F90_real_array_2d(ctypeArray, ArrayWithDescriptor, n, m)
KIM_to_F90_real_array_3d(ctypeArray, ArrayWithDescriptor, n, m, p)


*** END of KIM_API_Description.txt file ***
