KIM API V2
|
Previous Section: Summary of Differences Between kim-api-v1 and kim-api-v2.
Version 2 of the KIM API constitutes a major rewrite with a simplified interface, best practice design, and new capabilities. For more details, see the Features of the KIM API package page.
Version 2 is NOT backward compatible and therefore requires significant modifications to existing code (Model Drivers, Models, Test Drivers, and Tests) to work. The purpose of this document is to provide step-by-step instructions on how to transition content from version 1 to 2.
A complete translation table of v1 and v2 identifier names is available on the Summary of Differences Between kim-api-v1 and kim-api-v2 page.
This page includes instructions for Porting Models and Model Drivers and for Porting Simulators.
Model drivers and stand-alone models compatible with version 1 of the KIM API will need to be modified to conform to version 2. A step-by-step process for doing so is described below. (In what follows the generic term "model" will be used to refer to both Model Drivers and Models. The only difference between the two cases is that Model Drivers have these two additional functions: KIM::ModelDriverCreate::GetNumberOfParameterFiles() and KIM::ModelDriverCreate::GetParameterFileName().)
Setup your machine to perform the conversion. We suggest that you create a local installation of kim-api-v1 and kim-api-v2 in your home directory so that you can work with everything simultaneously.
Now, "activate" (update the PATH
variable and set up tab-completion) both versions of the KIM API within your bash shell
Now, you can use the kim-api-v#-build-config
and kim-api-v#-collections-management
utilities as you perform your work.
When you are done working on this activity, you can deactivate the KIM API with
Or, simply exit the shell.
Next, copy the example codes associated with these instructions
The porting-content-from-v1-to-v2-examples codes include two models (one in C and one in Fortran) and three simulators (one each in C, C++, and Fortran). Links to these codes are provided for each step in the instructiuons below (where changes occur). These can be compared to see a specific example of the code changes described below.
To start, the kim-api-v1 compatible versions of the models can be installed
It will be useful to know the output of these models generated by the example simulator. This can be generated as follows:
You can see the corresponding example codes by following these links: Step0~Fortan~Model, Step0~C~Model, Step0~C~Simulator.
Working with v1 of the model, strip out all supported neighbor list and boundary conditions (NBCs) except for NEIGH_PURE_F
, which is the only one supported by v2. If the model does not support this NBC, add it.
Next, strip out all supported neighbor list methods except for Neigh_LocaAccess
. If the model does not support this method, add it.
In the Makefile, append "_step1" to the model name. This will allow you to install the updated model alongside the original version and check that they give the same output.
When ready, install the new model. For the example codes, do
If you make further changes to the code, you can reinstall (remove and install) the model with commands such as
(The above commands will fail if the model was not previously successfully installed. Alternatively, you can use the commands
These commands will work even if the model is not currently installed.)
You can see the installed models using the kim-api-v1-collections-managment
utility:
Execute the model using the example test ex_test_Ar_fcc_cluster
to generate output that can be compared with the original model. For example:
You can see the corresponding example codes by following these links: Step1~Fortran~Model, Step1~C~Model.
Become familiar with v2 by reading the documentation, and reviewing the example Model Drivers and/or Models. (The examples are under "Files" in the documentation. The ex_model_Ar_P_MLJ_F03.F03 and ex_model_Ar_P_Morse_07C.c examples are the same codes found in the Guide for porting content from KIM API v1 to v2 examples used in these instructions.)
As you review the material, if you have any questions, post them to the OpenKIM Google Group forum by emailing openk or by visiting the im@g oogle grou ps.co mgroup. This will help others with similar questions. Continue using the forum for support in the next steps.
You are now ready to make the modifications to the code needed for it to be compatible with v2.
Start with the ModelDriverCreate
or ModelCreate
routine. Since KIM descriptor files no longer exist in v2, the information encoded in these files must be incorporated into this routine (and the ModelComputeArgumentsCreate
routine described in the next step) to make it available to the API.
Update the Makefile to use new pre/post-amble and to provide kim-api-v2 variables. For Paramaterized Models, remove the SPECIES_###_NAME
variables and convert PARAM_FILE_###_NAME
variables to PARAM_FILE_
#
(numbering should start from 1 and be in sequence without any gaps). Also, update the model name to end in "_step3" so that it can be installed alongside the previous versions._NAME
Update source files to use new v2 header file (module) as opposed to old v1 versions.
Comment out the v1 versions of the model's compute
, reinit
, and destroy
functions.
Update the v1 model_init routine to a v2 ModelDriverCreate
of ModelCreate
routine:
Change the prototype to match the v2 requirements (see examples).
Translate the model's v1 KIM descriptor file into appropriate code within the new routine:
First, a list of things in the descriptor file that will be simply discarded:
KIM_API_Version
value Neigh_LocaAccess
NEIGH_PURE_F
Set the base units to be used by the model. If the v1 model has flexible-units, simply make a call to KIM::ModelCreate::SetUnits() and pass in the "requested" unit values (Although, be careful to convert any "unused" values to appropriate unit values as necessary). Update the model's parameters to the requested units with call(s) to KIM::ModelCreate::ConvertUnit(). If the v1 model has fixed-units, simply make a call to KIM::ModelCreate::SetUnits() with the desired values. Make sure to specify the new "unused" value where appropriate.
Register the model's supported species and their codes with call(s) to KIM::ModelCreate::SetSpeciesCode(). (By default no species are supported.)
Set the model's numbering with a call to KIM::ModelCreate::SetModelNumbering().
Register the model's ComputeArgumentsCreate function pointer with a call to KIM::ModelCreate::SetComputeArgumentsCreatePointer(). (Use 2
for now (for Fortran, use c_funloc(kim_model_compute_string)
) as a placeholder. We'll implement this function and update this call in a later step.)
Register the model's ComputeArgumentsDestroy function pointer with a call to KIM::ModelCreate::SetComputeArgumentsDestroyPointer(). (Use 2
for now (for Fortran, use c_funloc(kim_model_compute_string)
) as a placeholder. We'll implement this function and update this call in a later step.)
Register the model's Compute function pointer with a call to KIM::ModelCreate::SetComputePointer(). (Use 2
for now (for Fortran, use c_funloc(kim_model_compute_string)
) as a placeholder. We'll implement this function and update this call in a later step.)
Register the model's Destroy function pointer with a call to KIM::ModelCreate::SetDestroyPointer(). (Use 2
for now (for Fortran, use c_funloc(kim_model_compute_string)
) as a placeholder. We'll implement this function and update this call in a later step.)
Register the model's Refresh function pointer with a call to KIM::ModelCreate::SetRefreshPointer(). (Use 2
for now (for Fortran, use c_funloc(kim_model_compute_string)
) as a placeholder. We'll implement this function and update this call in a later step.)
The last set of items in the v1 KIM descriptor file is the model's parameters. These will be registered with call(s) to KIM::ModelCreate::SetParameterPointer(). However, before doing this, you will need to setup and register the model's buffer memory space (See below items).
Update/Create the model buffer structure that will contain the model's influence distance value, the model's neighbor list cutoff value(s), and the model's parameters (if any). In the ModelCreate
routine, allocate memory for this structure and register the buffer with a call to KIM::ModelCreate::SetModelBufferPointer(). Next, set the values to be stored in the buffer (remember to perform unit conversion, if necessary, using call(s) to KIM::ModelCreate::ConvertUnit()).
Register the model's influence distance pointer with a call to KIM::ModelCreate::SetInfluenceDistancePointer().
Register the model's neighbor list cutoffs and hints pointers with a call to KIM::ModelCreate::SetNeighborListPointers().
Register the parameters with call(s) to KIM::ModelCreate::SetParameterPointer(), if necessary.
Make sure to update all error codes from the v1 codes to the v2 codes. v2 has just two error codes error = 1
(true, an error has occurred) and error = 0
(false, no error has occurred).
At the end of the ModelCreate
routine, just before a successful return, print out the content of the model object to verify the settings. See the examples provided below for the necessary code.
Build the model and use a simulator to execute it. You will receive a segmentation fault due to the missing compute routine (etc.), but you should also see a print out of all the data registered by the ModelCreate
routine. Make updates to the code until this data is all correct.
Note that the v2
collections management utility is now used. If build errors are reported for the model being updated, correct the reported compiler errors and try again. To test the model, a v2 version of the simulator is needed:
Now the new ModelCreate
routine can be tested to verify it is performing correctly. For example, the ex_model_Ar_P_Morse_07C_step3
produces
You can see the corresponding example codes by following these links: Step3~Fortran~Model, Step3~C~Model. Compare these with the versions from Step 1 to see the changes associated with this step.
Next you will implement the ModelComputeArgumentsCreate
and ModelComputeArgumentsDestroy
routines. The create routine registers the model's supported compute arguments and compute callbacks. The destroy routine allows the model to clean up the memory (if any) it stored at the compute-arguments object's model buffer pointer.
Modify the Makefile to update the model name to end in "_step4".
Create the ModelComputeArgumentsCreate
routine to conform to the v2 specifications.
Register the model's compute argument support status with call(s) to KIM::ModelComputeArgumentsCreate::SetArgumentSupportStatus(). (By default all arguments are either requiredByAPI
or notSupported
as defined on the Implementation page.)
Register the model's compute callback support status with call(s) to KIM::ModelComputeArgumentsCreate::SetCallbackSupportStatus(). (By default all callbacks are either requriedByAPI
or notSupported
as defined on the Implementation page.)
At the end of the ModelComputeArgumentsCreate
routine, just before a successful return, print out the content of the compute arguments object to verify the settings. See the examples provided below for the necessary code.
Create the ModelComputeArgumentsDestroy
routine to conform to the v1 specifications. In many cases this routine will be empty. See the examples provided below for the necessary code.
Finally, go back to the ModelCreate
routine:
Update the call to KIM::ModelCreate::SetComputeArgumentsCreatePointer() to reference the new ModelComputeArgumentsCreate
routine.
Update the call to KIM::ModelCreate::SetComputeArgumentsDestroyPointer() to reference the new ModelComputeArgumentsDestroy
routine.
Build the model and use a simulator to execute it. You will receive a segmentation fault due to the missing compute routine (etc.), but you should also see a print out of all the data registered by the ModelComputeArgumentsCreate
routine. Make updates to the code until this data is all correct.
Now the new ModelComputeArgumentsCreate
routine can be tested to verify it is performing correctly. For example, the ex_model_Ar_P_Morse_07C_step4
produces
You can see the corresponding example codes by following these links: Step4~Fortran~Model, Step4~C~Model. Compare these with the versions from Step 3 to see the changes associated with this step.
Modify/create the ModelRefresh
and ModelDestroy
routines to conform to v2.
The ModelRefresh
routine is used to allow the model to refresh the values of private data in its model buffer based on changes to the published parameter values in the model buffer which have been changed by the simulator. Additionally, at the end of the ModelRefresh
routine, the model must re-register pointers to its influence distance, neighbor list cutoffs and hints data (since, generally, these values will change due to the changes made to the published parameters by the simulator).
Create the ModelRefresh
routine (or convert the v1 reinit function)
Get the model buffer pointer with a call to KIM::ModelRefresh::GetModelBufferPointer().
Update any private data and, if necessary, the influence distance and cutoffs.
Register the influence distance with a call to KIM::ModelRefresh::SetInfluenceDistancePointer().
Register the cutoffs and hints pointers with a call to KIM::ModelRefresh::SetNeighborListPointers().
The ModelDestroy
routine is used to clean up the model buffer memory when the model is being destroyed.
Create the ModelDestroy
routine (or convert the v1 destroy function)
Get the model buffer pointer with a call to KIM::ModelDestroy::GetModelBufferPointer().
Deallocate memory associated with the buffer.
Go back to the ModelCreate
routine:
Update the call to KIM::ModelCreate::SetRefreshPointer() to reference the new ModelRefresh
routine.
Update the call to KIM::ModelCreate::SetDestroyPointer() to reference the new ModelDestroy
routine.
Finally, remove the code that prints the model object and the code that prints the compute arguments object.
Build the model to ensure no compiler errors are generated. It is probably not worth executing a simulator with this version as it will simply give a segmentation fault due to the ModelCompute
routine still being missing.
You can see the corresponding example codes by following these links: Step5~Fortran~Model, Step5~C~Model. Compare these with the versions from Step 4 to see the changes associated with this step.
Modify the Makefile to have the final v2 model name. (This may be the same as the v1 model name since the v1 model cannot be used with kim-api-v2.)
Update the ModelCompute
routine to get everything working.
Update the ModelCompute
routine prototype (for Fortran, this also includes changing from a FUNCTION to a SUBROUTINE).
For Fortran codes, remove type(c_ptr)
variables, they will not be needed in the v2 version of the compute routine. This also means that the C_F_POINTER
intrinsic function should not be needed.
Make changes to the code to use one of the LOG_*
macros or the KIM::ModelCompute::LogEntry() routine as opposed to the v1 KIM_API_report_error()
routine.
Make changes to the code that determines what computations have been requested and unpacking the arguments. In v1 this is associated with calls to KIM_API_get(m)_compute()
, and KIM_API_get(m)_data()
. In v2, these should be replaced with calls to KIM::ModelComputeArguments::IsCallbackPresent(), and KIM::ModelComputeArguments::GetArgumentPointer() (in C there are KIM_ModelComputeArguments_GetArgumentPointerInteger() and KIM_ModelComputeArguments_GetArgumentPointerDouble(); C++ and Fortran use function overloading and have only KIM::ModelComputeArguments::GetArgumentPointer()). The KIM::COMPUTE_CALLBACK_NAME::GetNeighborList() callback is requiredByAPI
so it will always be present, and it is not necessary to check explicitly with a call to KIM::ModelComputeArguments::IsCallbackPresent(). In v2, an argument is present if its pointer value is not NULL
(zero). Thus, once the pointer values have been unpacked with a call to KIM::ModelComputeArguments::GetArgumentPointer() a comparison of the pointer to NULL
(for Fortran, use the intrinsic function ASSOCIATED
) will determine if the argument is present or not.
Make changes to the code so that it gets the neighbor list cutoff, not from the cutoff argument as in v1, but from the value(s) stored in the model buffer. This will require a call to the KIM::ModelCompute::GetModelBufferPointer() routine.
Make changes to the code to use the particleContributing
argument values to identify contributing or non-contributing particles, as opposed to the approach in v1 where the number of neighbors for a particle is used.
Make changes to the code to use the v2 KIM::ModelComputeArguments::GetNeighborList() routine as opposed to the v1 KIM_API_get_neigh
routine.
Make changes to the code to use the v2 KIM::ModelComputeArguments::ProcessDEDrTerm() and KIM::ModelComputeArguments::ProcessD2EDr2Term() routines as opposed to the v1 KIM_API_process_dEdr()
and KIM_API_process_d2Edr2()
routines, if necessary.
Make sure to update all error codes from the v1 codes to the v2 codes. v2 has just two error codes error = 1
(true, an error has occurred) and error = 0
(false, no error has occurred).
Finally, go back to the ModelCreate
routine:
Update the call to KIM::ModelCreate::SetComputePointer() to reference the new ModelCompute
routine.
Build and install the final updated model.
If build errors are reported for the model being updated, correct the reported compiler errors and try again.
You can see the corresponding example codes by following these links: Step6~Fortran~Model, Step6~C~Model. Compare these with the versions from Step 5 to see the changes associated with this step.
Now the new model can be used with the v2 simulator and the output compared with the original output from Step 1.
See Porting Models: Step 0, above.
You can see the corresponding example codes by following these links: Step0~C~Simulator, Step0~C++~Simulator, and Step0~Fortran~Simulator.
Working with v1 of the simulator, strip out all supported neighbor list and boundary conditions (NBCs) except for NEIGH_PURE_F
, which is the only one supported by v2. If the simulator does not support this NBC, add it.
Next, strip out all supported neighbor list methods except for Neigh_LocaAccess
. If the simulator does not support this method, add it.
When ready, build the simulator and test it with the v1 models you installed in Porting Models: Step 0.
You can see the corresponding example codes by following these links: Step1~C~Simulator, Step1~C++~Simulator, and Step1~Fortran~Simulator. Compare these with the versions from Step 0 to see the changes associated with this step.
See Step 2 for Models, above.
You are now ready to make the modifications to the code needed to make it compatible with v2.
Update the Makefile to use new preamble build-config variables.
Update the source files to use new v2 header file (module) as opposed to old v1 version.
Change any error messages using the KIM_API_report_error, as v2 does not provide a similar capability. If desired, v2 does provide access to its logging facility (see the KIM::Log documentation) which places messages in the kim.log
file.
Change the simulator's neighbor list data structure to include any needed values (such as the number of cutoffs, cutoff values, and number of particles), as the KIM Model object is not available within the GetNeighborList
function in v2. Also, v2 now requires that the GetNeighborList
callback routine verifies that the neighbor list cutoff values used to generate the neighbor lists are compatible with the model's cutoffs. Next, change the prototype of the simulator's GetNeighborList
routine to match the v2 specification. Update the GetNeighborList
function to conform to the v2 specification.
If appropriate, change the simulator's ProcessDEDrTerm
and ProcessD2EDr2Term
callbacks in a manner similar to the changes needed for the previous item.
You can see the corresponding example codes online by following these links: Step3~C~Simulator, Step3~C++~Simulator, and Step3~Fortran~Simulator. Compare these with the versions from Step 1 to see the changes associated with this step.
Translate the simulator's v1 KIM descriptor file into appropriate code within the new Simulator's main routine:
First, a list of things in the descriptor file that will be simply discarded:
KIM_API_Version
value Neigh_LocaAccess
NEIGH_PURE_F
Provide the simulator's numbering and requested base units as part of the call to KIM::Model::Create(). Be sure to use "unused" values as appropriate. After the KIM::Model::Create() routine returns, check to see if the units request was accepted. If not, adjust the simulator's behavior appropriately, or exit with an error message.
Check to see that the model supports the simulator's required species with call(s) to KIM::Model::GetSpeciesSupportAndCode().
Use the model object to create an associated compute-arguments object that will be used to communicate data between the simulator and model. Use a call to KIM::Model::ComputeArgumentsCreate().
Check (with call(s) to KIM::COMPUTE_ARGUMENT_NAME::GetNumberOfComputeArgumentNames(), KIM::COMPUTE_ARGUMENT_NAME::GetComputeArgumentName(), and KIM::ComputeArguments::GetArgumentSupportStatus()) to see that the model supports the arguments (with the appropriate SupportStatus: required
or optional
) that the simulator will use. Also, check to see that the model does not have any other required
arguments not supported by the simulator.
Check (with call(s) to KIM::COMPUTE_CALLBACK_NAME::GetNumberOfComputeCallbackNames(), KIM::COMPUTE_CALLBACK_NAME::GetComputeCallbackName(), and KIM::ComputeArguments::GetCallbackSupportStatus()) to see that the model supports the callbacks (with the appropriate SupportStatus: required
or optional
) that the simulator will use. Also, check to see that the model does not have any other required
callbacks not supported by the simulator.
If the v1 simulator used the KIM_API_file_init()
routine, remove the descriptor.kim file. If it used the KIM_API_string_init()
routine, remove the associated string and/or routine.
You can see the corresponding example codes by following these links: Step4~C~Simulator, Step4~C++~Simulator, and Step4~Fortran~Simulator. Compare these with the versions from Step 3 to see the changes associated with this step.
Remove the v1 numberOfSpecies
argument, which is not needed in v2.
Register the simulator's arguments memory pointers with call(s) to KIM::ComputeArguments::SetArgumentPointer() (in C there are KIM_ComputeArguments_SetArgumentPointerInteger() and KIM_ComputeArguments_SetArgumentPointerDouble(); C++ and Fortran use function overloading and have only KIM::ComputeArguments::SetArgumentPointer()).
Register the simulator's callback memory pointers and data object pointers with call(s) to KIM::ComputeArguments::SetCallbackPointer().
Update the simulator code to work with the v2 model's influence distance and multiple cutoffs features.
Update the simulator code to populate the particleSpeciesCode
array.
Add code to the simulator to populate the particleContributing
array.
Update call(s) to KIM::Model::Compute().
Add call(s) to KIM::Model::ComputeArgumentsDestroy() to clean up and release memory associated with the compute-arguments object(s).
Update call(s) to KIM::Model::Destroy(). Note, the single v2 call to KIM::Model::Destroy() covers the two v1 calls to KIM_API_model_destroy()
and KIM_API_free()
.
When ready, build the simulator and test it with the v2 models installed as part of Step 6 for porting models.
(If you have not already copied the example simulator as part of Porting Models: Step 3, do the following)
Now, execute your simulator
You can also try the C++ and Fortran examples.
You can see the corresponding example codes by following these links: Step5~C~Simulator, Step5~C++~Simulator, and Step5~Fortran~Simulator. Compare these with the versions from Step 4 to see the changes associated with this step.
Next Seciton: Browse files.