// -*- C++ -*-
//
// asap_emt_driver.cpp: OpenKIM Model Driver interface for EMT.
//
// Copyright (C) 2012-2013 Jakob Schiotz and the Department of Physics,
// Technical University of Denmark. Email: schiotz@fysik.dtu.dk
//
// This file is part of Asap version 3.
// Asap is released under the GNU Lesser Public License (LGPL) version 3.
// However, the parts of Asap distributed within the OpenKIM project
// (including this file) are also released under the Common Development
// and Distribution License (CDDL) version 1.0.
//
// This program is free software: you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// version 3 as published by the Free Software Foundation. Permission
// to use other versions of the GNU Lesser General Public License may
// granted by Jakob Schiotz or the head of department of the
// Department of Physics, Technical University of Denmark, as
// described in section 14 of the GNU General Public License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// and the GNU Lesser Public License along with this program. If not,
// see .
#include "KIM_API_C.h"
#include "KIM_API_status.h"
#include "asap_kim_api.h"
#include "asap_emt_driver.h"
#include "KimParameterProvider.h"
#include
static int asap_emt_driver_initmodel(AsapKimPotential *model);
KimEMT::KimEMT(AsapKimPotential *owner, EMTParameterProvider *provider) : EMT(NULL)
{
this->owner = owner;
nblist = NULL;
nblist_obj = NULL;
provider_obj = NULL; // Bypass EMT's Python-based memory management.
this->provider = provider;
}
KimEMT::~KimEMT()
{
assert(provider_obj == NULL);
delete provider;
}
void KimEMT::CreateNeighborList()
{
PyAsap_NeighborLocatorObject *nbl = owner->CreateNeighborList(atoms, rNbCut, driftfactor);
nblist = nbl->cobj;
nblist_obj = (PyObject *) nbl;
nblist->UpdateNeighborList();
}
/* Destruction function */
static int asap_emt_destroy(void *km)
{
intptr_t* pkim = *((intptr_t**) km);
int ier;
AsapKimPotential *model = (AsapKimPotential *) KIM_API_get_model_buffer(pkim, &ier);
if (KIM_STATUS_OK > ier)
{
KIM_API_report_error(__LINE__, __FILE__, "KIM_API_get_model_buffer", ier);
return ier;
}
delete model;
// Remove the model pointer from the model buffer (if left, the API will
// release it with free instead of delete).
KIM_API_set_model_buffer(pkim, NULL, &ier);
if (KIM_STATUS_OK > ier)
{
KIM_API_report_error(__LINE__, __FILE__, "KIM_API_set_model_buffer", ier);
return ier;
}
return KIM_STATUS_OK;
}
/* Reinit function */
static int asap_emt_reinit(void *km)
{
intptr_t* pkim = *((intptr_t**) km);
int ier;
// Remove the old model
AsapKimPotential *model = (AsapKimPotential *) KIM_API_get_model_buffer(pkim, &ier);
if (KIM_STATUS_OK > ier)
{
KIM_API_report_error(__LINE__, __FILE__, "KIM_API_get_model_buffer", ier);
return ier;
}
// Add the new model
AsapKimPotential *newmodel = new AsapKimPotential(pkim, model->paramfile_names, model->nmstrlen,
model->numparamfiles, true);
delete model;
return asap_emt_driver_initmodel(newmodel);
}
/* Initialization function */
extern "C" int model_driver_init(void *km, char* paramfile_names, int* nmstrlen, int* numparamfiles)
{
intptr_t* pkim = *((intptr_t**) km);
int ier;
if(*numparamfiles !=1)
{
ier = KIM_STATUS_FAIL;
KIM_API_report_error(__LINE__, __FILE__, "Wrong number of parameter files", ier);
return ier;
}
/* store pointer to compute function in KIM object */
ier = KIM_API_set_method(pkim, "compute", 1, (func_ptr) &AsapKimPotential::compute_static);
if (KIM_STATUS_OK > ier)
{
KIM_API_report_error(__LINE__, __FILE__, "KIM_API_set_method", ier);
return ier;
}
/* store pointer to destroy function in KIM object */
ier = KIM_API_set_method(pkim, "destroy", 1, (func_ptr) &asap_emt_destroy);
if (KIM_STATUS_OK > ier)
{
KIM_API_report_error(__LINE__, __FILE__, "KIM_API_set_method", ier);
return ier;
}
/* store pointer to reinit function in KIM object */
ier = KIM_API_set_method(pkim, "reinit", 1, (func_ptr) &asap_emt_reinit);
if (KIM_STATUS_OK > ier)
{
KIM_API_report_error(__LINE__, __FILE__, "KIM_API_set_method", ier);
return ier;
}
// Create the model
AsapKimPotential *model = new AsapKimPotential(pkim, paramfile_names,
*nmstrlen, *numparamfiles, true);
return asap_emt_driver_initmodel(model);
}
static int asap_emt_driver_initmodel(AsapKimPotential *model)
{
intptr_t *pkim = model->pkim;
const char *paramfile_names = model->paramfile_names;
double *model_cutoff;
int ier;
KimParameterProvider *provider = NULL;
try
{
provider = new KimParameterProvider(paramfile_names, pkim);
}
catch (AsapError &e)
{
std::cerr << e.GetMessage() << std::endl;
return KIM_STATUS_FAIL;
}
model->potential = new KimEMT(model, provider);
// Store the model in the model buffer
KIM_API_set_model_buffer(pkim, (void*) model, &ier);
if (KIM_STATUS_OK > ier)
{
KIM_API_report_error(__LINE__, __FILE__, "KIM_API_set_model_buffer", ier);
return ier;
}
/* store maximal model cutoff in KIM object */
model_cutoff = (double*) KIM_API_get_data(pkim, "cutoff", &ier);
if (KIM_STATUS_OK > ier){
KIM_API_report_error(__LINE__, __FILE__, "KIM_API_get_data", ier);
return ier;
}
provider->CalcGammaEtc();
*model_cutoff = provider->GetCutoffDistance();
//std::cerr << "Setting cutoff to " << *model_cutoff << std::endl;
return KIM_STATUS_OK;
}