Files
rdkit/Code/ForceField/ForceField.cpp
Ric 2bd6481280 Fix some build warnings (#6618)
* fixes a copy constructor issue:

In copy constructor ‘boost::shared_ptr<T>::shared_ptr(const boost::shared_ptr<T>&) [with T = RDKit::ROMol]’,
    inlined from ‘PyObject* RDKit::RunReactant(ChemicalReaction*, T, unsigned int) [with T = boost::python::api::object]’ at /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp:129:14:
/usr/include/boost/smart_ptr/shared_ptr.hpp:416:66: warning: ‘*(const boost::shared_ptr<RDKit::ROMol>*)((char*)&<unnamed> + offsetof(boost::python::extract<boost::shared_ptr<RDKit::ROMol> >,boost::python::extract<boost::shared_ptr<RDKit::ROMol> >::<unnamed>.boost::python::converter::extract_rvalue<boost::shared_ptr<RDKit::ROMol> >::m_data.boost::python::converter::rvalue_from_python_data<boost::shared_ptr<RDKit::ROMol> >::<unnamed>.boost::python::converter::rvalue_from_python_storage<boost::shared_ptr<RDKit::ROMol> >::storage)).boost::shared_ptr<RDKit::ROMol>::px’ may be used uninitialized [-Wmaybe-uninitialized]
  416 |     shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
      |                                                                ~~^~
/tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp: In function ‘PyObject* RDKit::RunReactant(ChemicalReaction*, T, unsigned int) [with T = boost::python::api::object]’:
/tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp:129:30: note: ‘<anonymous>’ declared here
  129 |   ROMOL_SPTR react = python::extract<ROMOL_SPTR>(reactant);
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/smart_ptr/shared_ptr.hpp:17:
In copy constructor ‘boost::detail::shared_count::shared_count(const boost::detail::shared_count&)’,
    inlined from ‘boost::shared_ptr<T>::shared_ptr(const boost::shared_ptr<T>&) [with T = RDKit::ROMol]’ at /usr/include/boost/smart_ptr/shared_ptr.hpp:416:72,
    inlined from ‘PyObject* RDKit::RunReactant(ChemicalReaction*, T, unsigned int) [with T = boost::python::api::object]’ at /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp:129:14:
/usr/include/boost/smart_ptr/detail/shared_count.hpp:438:67: warning: ‘((const boost::detail::shared_count*)((char*)&<unnamed> + offsetof(boost::python::extract<boost::shared_ptr<RDKit::ROMol> >,boost::python::extract<boost::shared_ptr<RDKit::ROMol> >::<unnamed>.boost::python::converter::extract_rvalue<boost::shared_ptr<RDKit::ROMol> >::m_data.boost::python::converter::rvalue_from_python_data<boost::shared_ptr<RDKit::ROMol> >::<unnamed>.boost::python::converter::rvalue_from_python_storage<boost::shared_ptr<RDKit::ROMol> >::storage)))[1].boost::detail::shared_count::pi_’ may be used uninitialized [-Wmaybe-uninitialized]
  438 |     shared_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
      |                                                                 ~~^~~
/tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp: In function ‘PyObject* RDKit::RunReactant(ChemicalReaction*, T, unsigned int) [with T = boost::python::api::object]’:
/tmp/rdkit_builder/rdkit/Code/GraphMol/ChemReactions/Wrap/rdChemReactions.cpp:129:30: note: ‘<anonymous>’ declared here
  129 |   ROMOL_SPTR react = python::extract<ROMOL_SPTR>(reactant);
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* Fixes a (weird) allocation warning in GCC 12

In file included from /usr/include/c++/12/bits/alloc_traits.h:33,
                 from /usr/include/c++/12/ext/alloc_traits.h:34,
                 from /usr/include/c++/12/bits/basic_string.h:39,
                 from /usr/include/c++/12/string:53,
                 from /usr/include/c++/12/bits/locale_classes.h:40,
                 from /usr/include/c++/12/bits/ios_base.h:41,
                 from /usr/include/c++/12/streambuf:41,
                 from /usr/include/c++/12/bits/streambuf_iterator.h:35,
                 from /usr/include/c++/12/iterator:66,
                 from /usr/include/boost/iterator/iterator_traits.hpp:10,
                 from /usr/include/boost/range/iterator_range_core.hpp:26,
                 from /usr/include/boost/range/iterator_range.hpp:13,
                 from /usr/include/boost/iostreams/traits.hpp:38,
                 from /usr/include/boost/iostreams/detail/call_traits.hpp:15,
                 from /usr/include/boost/iostreams/detail/adapter/device_adapter.hpp:22,
                 from /usr/include/boost/iostreams/tee.hpp:18,
                 from /tmp/rdkit_builder/rdkit/Code/RDGeneral/RDLog.h:17,
                 from /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemTransforms/testChemTransforms.cpp:11:
In function ‘void std::_Construct(_Tp*, _Args&& ...) [with _Tp = pair<int, int>; _Args = {const pair<int, int>&}]’,
    inlined from ‘_ForwardIterator std::__do_uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const pair<int, int>*; _ForwardIterator = pair<int, int>*]’ at /usr/include/c++/12/bits/stl_uninitialized.h:120:21,
    inlined from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::pair<int, int>*; _ForwardIterator = std::pair<int, int>*; bool _TrivialValueTypes = false]’ at /usr/include/c++/12/bits/stl_uninitialized.h:137:32,
    inlined from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const pair<int, int>*; _ForwardIterator = pair<int, int>*]’ at /usr/include/c++/12/bits/stl_uninitialized.h:185:15,
    inlined from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, allocator<_Tp>&) [with _InputIterator = const pair<int, int>*; _ForwardIterator = pair<int, int>*; _Tp = pair<int, int>]’ at /usr/include/c++/12/bits/stl_uninitialized.h:372:37,
    inlined from ‘void std::vector<_Tp, _Alloc>::_M_range_insert(iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::pair<int, int>*; _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/vector.tcc:808:38,
    inlined from ‘std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(const_iterator, std::initializer_list<_Tp>) [with _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/stl_vector.h:1409:17,
    inlined from ‘void testReplaceCoreMatchVectMultipleMappingToCore()’ at /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemTransforms/testChemTransforms.cpp:974:17:
/usr/include/c++/12/bits/stl_construct.h:119:7: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’ writing 56 bytes into a region of size 48 overflows the destination [-Wstringop-overflow=]
  119 |       ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
      |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/x86_64-linux-gnu/c++/12/bits/c++allocator.h:33,
                 from /usr/include/c++/12/bits/allocator.h:46,
                 from /usr/include/c++/12/string:41:
In member function ‘_Tp* std::__new_allocator<_Tp>::allocate(size_type, const void*) [with _Tp = std::pair<int, int>]’,
    inlined from ‘static _Tp* std::allocator_traits<std::allocator<_CharT> >::allocate(allocator_type&, size_type) [with _Tp = std::pair<int, int>]’ at /usr/include/c++/12/bits/alloc_traits.h:464:28,
    inlined from ‘std::_Vector_base<_Tp, _Alloc>::pointer std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/stl_vector.h:378:33,
    inlined from ‘void std::vector<_Tp, _Alloc>::_M_range_insert(iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::pair<int, int>*; _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/vector.tcc:799:40,
    inlined from ‘std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(const_iterator, std::initializer_list<_Tp>) [with _Tp = std::pair<int, int>; _Alloc = std::allocator<std::pair<int, int> >]’ at /usr/include/c++/12/bits/stl_vector.h:1409:17,
    inlined from ‘void testReplaceCoreMatchVectMultipleMappingToCore()’ at /tmp/rdkit_builder/rdkit/Code/GraphMol/ChemTransforms/testChemTransforms.cpp:974:17:
/usr/include/c++/12/bits/new_allocator.h:137:55: note: at offset [8, 56] into destination object of size 56 allocated by ‘operator new’
  137 |         return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));
      |                                                       ^

* finalForce maybe uninitialized in inlined copy constructor

* failure is being used uninitialized

* MaeWriter::write overrides a method of the base class without being marked 'override'

This one is annoying because it happens in an exported header, so it propagates
to any code using the header!

* otq is never used

* fix implicitly declared assignment operator warning

* variables in catch statements that are never used

* fix type (sign) mismatch warning

* drop duplicate export macro
2023-08-11 06:04:55 +02:00

428 lines
12 KiB
C++

// $Id$
//
// Copyright (C) 2004-2006 Rational Discovery LLC
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
// The contents are covered by the terms of the BSD license
// which is included in the file license.txt, found at the root
// of the RDKit source tree.
//
#include "ForceField.h"
#include "Contrib.h"
#include <RDGeneral/Invariant.h>
#include <Numerics/Optimizer/BFGSOpt.h>
namespace RDKit {
namespace ForceFieldsHelper {
void normalizeAngleDeg(double &angleDeg) {
angleDeg = fmod(angleDeg, 360.0);
if (angleDeg < -180.0) {
angleDeg += 360.0;
} else if (angleDeg > 180.0) {
angleDeg -= 360.0;
}
}
void computeDihedral(const RDGeom::PointPtrVect &pos, unsigned int idx1,
unsigned int idx2, unsigned int idx3, unsigned int idx4,
double *dihedral, double *cosPhi, RDGeom::Point3D r[4],
RDGeom::Point3D t[2], double d[2]) {
computeDihedral(static_cast<RDGeom::Point3D *>(pos[idx1]),
static_cast<RDGeom::Point3D *>(pos[idx2]),
static_cast<RDGeom::Point3D *>(pos[idx3]),
static_cast<RDGeom::Point3D *>(pos[idx4]), dihedral, cosPhi,
r, t, d);
}
void computeDihedral(const double *pos, unsigned int idx1, unsigned int idx2,
unsigned int idx3, unsigned int idx4, double *dihedral,
double *cosPhi, RDGeom::Point3D r[4], RDGeom::Point3D t[2],
double d[2]) {
RDGeom::Point3D p1(pos[3 * idx1], pos[3 * idx1 + 1], pos[3 * idx1 + 2]);
RDGeom::Point3D p2(pos[3 * idx2], pos[3 * idx2 + 1], pos[3 * idx2 + 2]);
RDGeom::Point3D p3(pos[3 * idx3], pos[3 * idx3 + 1], pos[3 * idx3 + 2]);
RDGeom::Point3D p4(pos[3 * idx4], pos[3 * idx4 + 1], pos[3 * idx4 + 2]);
computeDihedral(&p1, &p2, &p3, &p4, dihedral, cosPhi, r, t, d);
}
void computeDihedral(const RDGeom::Point3D *p1, const RDGeom::Point3D *p2,
const RDGeom::Point3D *p3, const RDGeom::Point3D *p4,
double *dihedral, double *cosPhi, RDGeom::Point3D r[4],
RDGeom::Point3D t[2], double d[2]) {
PRECONDITION(p1, "p1 must not be null");
PRECONDITION(p2, "p2 must not be null");
PRECONDITION(p3, "p3 must not be null");
PRECONDITION(p4, "p4 must not be null");
RDGeom::Point3D rLocal[4];
RDGeom::Point3D tLocal[2];
double dLocal[2];
if (!r) {
r = rLocal;
}
if (!t) {
t = tLocal;
}
if (!d) {
d = dLocal;
}
r[0] = *p1 - *p2;
r[1] = *p3 - *p2;
r[2] = -r[1];
r[3] = *p4 - *p3;
t[0] = r[0].crossProduct(r[1]);
d[0] = (std::max)(t[0].length(), 1.0e-5);
t[0] /= d[0];
t[1] = r[2].crossProduct(r[3]);
d[1] = (std::max)(t[1].length(), 1.0e-5);
t[1] /= d[1];
double cosPhiLocal;
if (!cosPhi) {
cosPhi = &cosPhiLocal;
}
*cosPhi = (std::max)(-1.0, (std::min)(t[0].dotProduct(t[1]), 1.0));
// we want a signed dihedral, that's why we use atan2 instead of acos
if (dihedral) {
RDGeom::Point3D m = t[0].crossProduct(r[1]);
double mLength = (std::max)(m.length(), 1.0e-5);
*dihedral = -atan2(m.dotProduct(t[1]) / mLength, *cosPhi);
}
}
} // namespace ForceFieldsHelper
} // namespace RDKit
namespace ForceFieldsHelper {
class calcEnergy {
public:
calcEnergy(ForceFields::ForceField *ffHolder) : mp_ffHolder(ffHolder){};
double operator()(double *pos) const { return mp_ffHolder->calcEnergy(pos); }
private:
ForceFields::ForceField *mp_ffHolder;
};
class calcGradient {
public:
calcGradient(ForceFields::ForceField *ffHolder) : mp_ffHolder(ffHolder){};
double operator()(double *pos, double *grad) const {
double res = 1.0;
// the contribs to the gradient function use +=, so we need
// to zero the grad out before moving on:
for (unsigned int i = 0;
i < mp_ffHolder->numPoints() * mp_ffHolder->dimension(); i++) {
grad[i] = 0.0;
}
mp_ffHolder->calcGrad(pos, grad);
#if 1
// FIX: this hack reduces the gradients so that the
// minimizer is more efficient.
double maxGrad = -1e8;
double gradScale = 0.1;
for (unsigned int i = 0;
i < mp_ffHolder->numPoints() * mp_ffHolder->dimension(); i++) {
grad[i] *= gradScale;
if (grad[i] > maxGrad) {
maxGrad = grad[i];
}
}
// this is a continuation of the same hack to avoid
// some potential numeric instabilities:
if (maxGrad > 10.0) {
while (maxGrad * gradScale > 10.0) {
gradScale *= .5;
}
for (unsigned int i = 0;
i < mp_ffHolder->numPoints() * mp_ffHolder->dimension(); i++) {
grad[i] *= gradScale;
}
}
res = gradScale;
#endif
return res;
}
private:
ForceFields::ForceField *mp_ffHolder;
};
} // namespace ForceFieldsHelper
namespace ForceFields {
ForceField::~ForceField() {
d_numPoints = 0;
d_positions.clear();
d_contribs.clear();
delete[] dp_distMat;
dp_distMat = nullptr;
}
ForceField::ForceField(const ForceField &other)
: d_dimension(other.d_dimension),
df_init(false),
d_numPoints(other.d_numPoints),
dp_distMat(nullptr) {
d_contribs.clear();
for (const auto &contrib : other.d_contribs) {
ForceFieldContrib *ncontrib = contrib->copy();
ncontrib->dp_forceField = this;
d_contribs.push_back(ContribPtr(ncontrib));
}
};
double ForceField::distance(unsigned int i, unsigned int j, double *pos) {
PRECONDITION(df_init, "not initialized");
URANGE_CHECK(i, d_numPoints);
URANGE_CHECK(j, d_numPoints);
if (j < i) {
int tmp = j;
j = i;
i = tmp;
}
unsigned int idx = i + j * (j + 1) / 2;
CHECK_INVARIANT(idx < d_matSize, "Bad index");
double &res = dp_distMat[idx];
if (res < 0.0) {
// we need to calculate this distance:
if (!pos) {
res = 0.0;
for (unsigned int idx = 0; idx < d_dimension; ++idx) {
double tmp =
(*(this->positions()[i]))[idx] - (*(this->positions()[j]))[idx];
res += tmp * tmp;
}
} else {
res = 0.0;
#if 0
for (unsigned int idx = 0; idx < d_dimension; idx++) {
double tmp = pos[d_dimension * i + idx] - pos[d_dimension * j + idx];
res += tmp * tmp;
}
#else
double *pi = &(pos[d_dimension * i]), *pj = &(pos[d_dimension * j]);
for (unsigned int idx = 0; idx < d_dimension; ++idx, ++pi, ++pj) {
double tmp = *pi - *pj;
res += tmp * tmp;
}
#endif
}
res = sqrt(res);
}
return res;
}
double ForceField::distance(unsigned int i, unsigned int j, double *pos) const {
PRECONDITION(df_init, "not initialized");
URANGE_CHECK(i, d_numPoints);
URANGE_CHECK(j, d_numPoints);
if (j < i) {
int tmp = j;
j = i;
i = tmp;
}
double res;
if (!pos) {
res = 0.0;
for (unsigned int idx = 0; idx < d_dimension; ++idx) {
double tmp =
(*(this->positions()[i]))[idx] - (*(this->positions()[j]))[idx];
res += tmp * tmp;
}
} else {
res = 0.0;
#if 0
for (unsigned int idx = 0; idx < d_dimension; idx++) {
double tmp = pos[d_dimension * i + idx] - pos[d_dimension * j + idx];
res += tmp * tmp;
}
#else
double *pi = &(pos[d_dimension * i]), *pj = &(pos[d_dimension * j]);
for (unsigned int idx = 0; idx < d_dimension; ++idx, ++pi, ++pj) {
double tmp = *pi - *pj;
res += tmp * tmp;
}
#endif
}
res = sqrt(res);
return res;
}
void ForceField::initialize() {
// clean up if we have used this already:
df_init = false;
delete[] dp_distMat;
dp_distMat = nullptr;
d_numPoints = d_positions.size();
d_matSize = d_numPoints * (d_numPoints + 1) / 2;
dp_distMat = new double[d_matSize];
this->initDistanceMatrix();
df_init = true;
}
int ForceField::minimize(unsigned int maxIts, double forceTol,
double energyTol) {
return minimize(0, nullptr, maxIts, forceTol, energyTol);
}
int ForceField::minimize(unsigned int snapshotFreq,
RDKit::SnapshotVect *snapshotVect, unsigned int maxIts,
double forceTol, double energyTol) {
PRECONDITION(df_init, "not initialized");
PRECONDITION(static_cast<unsigned int>(d_numPoints) == d_positions.size(),
"size mismatch");
if (d_contribs.empty()) {
return 0;
}
unsigned int numIters = 0;
unsigned int dim = this->d_numPoints * d_dimension;
double finalForce = 0.0;
auto *points = new double[dim];
this->scatter(points);
ForceFieldsHelper::calcEnergy eCalc(this);
ForceFieldsHelper::calcGradient gCalc(this);
int res =
BFGSOpt::minimize(dim, points, forceTol, numIters, finalForce, eCalc,
gCalc, snapshotFreq, snapshotVect, energyTol, maxIts);
this->gather(points);
delete[] points;
return res;
}
double ForceField::calcEnergy(std::vector<double> *contribs) const {
PRECONDITION(df_init, "not initialized");
double res = 0.0;
if (d_contribs.empty()) {
return res;
}
if (contribs) {
contribs->clear();
contribs->reserve(d_contribs.size());
}
unsigned int N = d_positions.size();
auto *pos = new double[d_dimension * N];
this->scatter(pos);
// now loop over the contribs
for (const auto &d_contrib : d_contribs) {
double e = d_contrib->getEnergy(pos);
res += e;
if (contribs) {
contribs->push_back(e);
}
}
delete[] pos;
return res;
}
double ForceField::calcEnergy(double *pos) {
PRECONDITION(df_init, "not initialized");
PRECONDITION(pos, "bad position vector");
double res = 0.0;
this->initDistanceMatrix();
if (d_contribs.empty()) {
return res;
}
// now loop over the contribs
for (ContribPtrVect::const_iterator contrib = d_contribs.begin();
contrib != d_contribs.end(); contrib++) {
double E = (*contrib)->getEnergy(pos);
res += E;
}
return res;
}
void ForceField::calcGrad(double *grad) const {
PRECONDITION(df_init, "not initialized");
PRECONDITION(grad, "bad gradient vector");
if (d_contribs.empty()) {
return;
}
unsigned int N = d_positions.size();
auto *pos = new double[d_dimension * N];
this->scatter(pos);
for (const auto &d_contrib : d_contribs) {
d_contrib->getGrad(pos, grad);
}
// zero out gradient values for any fixed points:
for (int d_fixedPoint : d_fixedPoints) {
CHECK_INVARIANT(static_cast<unsigned int>(d_fixedPoint) < d_numPoints,
"bad fixed point index");
unsigned int idx = d_dimension * d_fixedPoint;
for (unsigned int di = 0; di < this->dimension(); ++di) {
grad[idx + di] = 0.0;
}
}
delete[] pos;
}
void ForceField::calcGrad(double *pos, double *grad) {
PRECONDITION(df_init, "not initialized");
PRECONDITION(pos, "bad position vector");
PRECONDITION(grad, "bad gradient vector");
if (d_contribs.empty()) {
return;
}
for (ContribPtrVect::const_iterator contrib = d_contribs.begin();
contrib != d_contribs.end(); contrib++) {
(*contrib)->getGrad(pos, grad);
}
for (INT_VECT::const_iterator it = d_fixedPoints.begin();
it != d_fixedPoints.end(); it++) {
CHECK_INVARIANT(static_cast<unsigned int>(*it) < d_numPoints,
"bad fixed point index");
unsigned int idx = d_dimension * (*it);
for (unsigned int di = 0; di < this->dimension(); ++di) {
grad[idx + di] = 0.0;
}
}
}
void ForceField::scatter(double *pos) const {
PRECONDITION(df_init, "not initialized");
PRECONDITION(pos, "bad position vector");
unsigned int tab = 0;
for (auto d_position : d_positions) {
for (unsigned int di = 0; di < this->dimension(); ++di) {
pos[tab + di] = (*d_position)[di]; //->x;
}
tab += this->dimension();
}
POSTCONDITION(tab == this->dimension() * d_positions.size(), "bad index");
}
void ForceField::gather(double *pos) {
PRECONDITION(df_init, "not initialized");
PRECONDITION(pos, "bad position vector");
unsigned int tab = 0;
for (auto &d_position : d_positions) {
for (unsigned int di = 0; di < this->dimension(); ++di) {
(*d_position)[di] = pos[tab + di];
}
tab += this->dimension();
}
}
void ForceField::initDistanceMatrix() {
PRECONDITION(d_numPoints, "no points");
PRECONDITION(dp_distMat, "no distance matrix");
PRECONDITION(static_cast<unsigned int>(d_numPoints * (d_numPoints + 1) / 2) <=
d_matSize,
"matrix size mismatch");
for (unsigned int i = 0; i < d_numPoints * (d_numPoints + 1) / 2; i++) {
dp_distMat[i] = -1.0;
}
}
} // namespace ForceFields