179 lines
5.8 KiB
C++
179 lines
5.8 KiB
C++
// clang-format off
|
|
/* ----------------------------------------------------------------------
|
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
|
https://www.lammps.org/, Sandia National Laboratories
|
|
LAMMPS development team: developers@lammps.org
|
|
|
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
|
certain rights in this software. This software is distributed under
|
|
the GNU General Public License.
|
|
|
|
See the README file in the top-level LAMMPS directory.
|
|
------------------------------------------------------------------------- */
|
|
|
|
/* ----------------------------------------------------------------------
|
|
Contributing author: Aidan Thompson (SNL)
|
|
------------------------------------------------------------------------- */
|
|
|
|
#include "mliap_model_linear.h"
|
|
|
|
#include "mliap_data.h"
|
|
#include "error.h"
|
|
|
|
using namespace LAMMPS_NS;
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
MLIAPModelLinear::MLIAPModelLinear(LAMMPS* lmp, char* coefffilename) :
|
|
MLIAPModelSimple(lmp, coefffilename)
|
|
{
|
|
if (nparams > 0) ndescriptors = nparams - 1;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
get number of parameters
|
|
---------------------------------------------------------------------- */
|
|
|
|
int MLIAPModelLinear::get_nparams()
|
|
{
|
|
if (nparams == 0) {
|
|
if (ndescriptors == 0) error->all(FLERR,"ndescriptors not defined");
|
|
else nparams = ndescriptors + 1;
|
|
}
|
|
|
|
return nparams;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
Calculate model gradients w.r.t descriptors
|
|
for each atom beta_i = dE(B_i)/dB_i
|
|
---------------------------------------------------------------------- */
|
|
|
|
void MLIAPModelLinear::compute_gradients(MLIAPData* data)
|
|
{
|
|
data->energy = 0.0;
|
|
|
|
for (int ii = 0; ii < data->nlistatoms; ii++) {
|
|
const int ielem = data->ielems[ii];
|
|
|
|
double const* coeffi = coeffelem[ielem];
|
|
for (int icoeff = 0; icoeff < data->ndescriptors; icoeff++)
|
|
data->betas[ii][icoeff] = coeffi[icoeff+1];
|
|
|
|
// add in contributions to global and per-atom energy
|
|
// this is optional and has no effect on force calculation
|
|
if (data->eflag) {
|
|
// energy of atom I
|
|
double etmp = coeffi[0];
|
|
|
|
// E_i = beta.B_i
|
|
for (int icoeff = 0; icoeff < data->ndescriptors; icoeff++)
|
|
etmp += coeffi[icoeff+1]*data->descriptors[ii][icoeff];
|
|
|
|
data->energy += etmp;
|
|
data->eatoms[ii] = etmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
Calculate model double gradients w.r.t descriptors and parameters
|
|
for each atom energy gamma_lk = d2E(B)/dB_k/dsigma_l,
|
|
where sigma_l is a parameter, B_k a descriptor,
|
|
and atom subscript i is omitted
|
|
|
|
gamma is in CSR format:
|
|
nnz = number of non-zero values
|
|
gamma_row_index[inz] = l indices, 0 <= l < nparams
|
|
gamma_col_indexiinz] = k indices, 0 <= k < ndescriptors
|
|
gamma[i][inz] = non-zero values, 0 <= inz < nnz
|
|
|
|
egradient is derivative of energy w.r.t. parameters
|
|
---------------------------------------------------------------------- */
|
|
|
|
void MLIAPModelLinear::compute_gradgrads(class MLIAPData* data)
|
|
{
|
|
// zero out energy gradients
|
|
|
|
for (int l = 0; l < data->nelements*data->nparams; l++)
|
|
data->egradient[l] = 0.0;
|
|
|
|
for (int ii = 0; ii < data->nlistatoms; ii++) {
|
|
const int ielem = data->ielems[ii];
|
|
const int elemoffset = data->nparams*ielem;
|
|
|
|
int l = elemoffset+1;
|
|
for (int icoeff = 0; icoeff < data->ndescriptors; icoeff++) {
|
|
data->gamma[ii][icoeff] = 1.0;
|
|
data->gamma_row_index[ii][icoeff] = l++;
|
|
data->gamma_col_index[ii][icoeff] = icoeff;
|
|
}
|
|
|
|
// gradient of energy of atom I w.r.t. parameters
|
|
|
|
l = elemoffset;
|
|
data->egradient[l++] += 1.0;
|
|
for (int icoeff = 0; icoeff < data->ndescriptors; icoeff++)
|
|
data->egradient[l++] += data->descriptors[ii][icoeff];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
calculate gradients of forces w.r.t. parameters
|
|
egradient is derivative of energy w.r.t. parameters
|
|
---------------------------------------------------------------------- */
|
|
|
|
void MLIAPModelLinear::compute_force_gradients(class MLIAPData* data)
|
|
{
|
|
|
|
// zero out energy gradients
|
|
|
|
for (int l = 0; l < data->nelements*data->nparams; l++)
|
|
data->egradient[l] = 0.0;
|
|
|
|
int ij = 0;
|
|
for (int ii = 0; ii < data->nlistatoms; ii++) {
|
|
const int i = data->iatoms[ii];
|
|
const int ielem = data->ielems[ii];
|
|
const int elemoffset = data->nparams*ielem;
|
|
|
|
for (int jj = 0; jj < data->numneighs[ii]; jj++) {
|
|
const int j = data->jatoms[ij];
|
|
int l = elemoffset+1;
|
|
for (int icoeff = 0; icoeff < data->ndescriptors; icoeff++) {
|
|
data->gradforce[i][l] += data->graddesc[ij][icoeff][0];
|
|
data->gradforce[i][l+data->yoffset] += data->graddesc[ij][icoeff][1];
|
|
data->gradforce[i][l+data->zoffset] += data->graddesc[ij][icoeff][2];
|
|
data->gradforce[j][l] -= data->graddesc[ij][icoeff][0];
|
|
data->gradforce[j][l+data->yoffset] -= data->graddesc[ij][icoeff][1];
|
|
data->gradforce[j][l+data->zoffset] -= data->graddesc[ij][icoeff][2];
|
|
l++;
|
|
}
|
|
ij++;
|
|
}
|
|
|
|
// gradient of energy of atom I w.r.t. parameters
|
|
|
|
int l = elemoffset;
|
|
data->egradient[l++] += 1.0;
|
|
for (int icoeff = 0; icoeff < data->ndescriptors; icoeff++)
|
|
data->egradient[l++] += data->descriptors[ii][icoeff];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
count the number of non-zero entries in gamma matrix
|
|
---------------------------------------------------------------------- */
|
|
|
|
int MLIAPModelLinear::get_gamma_nnz(class MLIAPData* data)
|
|
{
|
|
int inz = data->ndescriptors;
|
|
return inz;
|
|
}
|
|
|