#include "gromacs/gmxlib/network.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/math/gmxcomplex.h"
+#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/units.h"
#include "gromacs/math/vec.h"
#include "gromacs/math/vectypes.h"
atc->f = f;
}
- m_inv_ur0(box, pme->recipbox);
+ gmx::invertBoxMatrix(box, pme->recipbox);
bFirst = TRUE;
/* For simplicity, we construct the splines for all particles if
#include "gromacs/gmxana/gmx_ana.h"
#include "gromacs/gmxana/gstat.h"
#include "gromacs/math/functions.h"
+#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
#include "gromacs/topology/index.h"
fprintf(stderr, "\rProcessing frame %d", f);
}
/* Scale all the configuration to the average box */
- m_inv_ur0(sbox[f], corr);
+ gmx::invertBoxMatrix(sbox[f], corr);
mmul_ur0(avbox, corr, corr);
for (i = 0; i < isize; i++)
{
#include "gromacs/gmxpreprocess/vsite_parm.h"
#include "gromacs/imd/imd.h"
#include "gromacs/math/functions.h"
+#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/units.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/calc_verletbuf.h"
clear_rvec(invbox[j]);
invbox[j][j] = 1;
}
- m_inv_ur0(invbox, invbox);
+ gmx::invertBoxMatrix(invbox, invbox);
}
/* Copy the reference coordinates to mtop */
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
+/*! \internal \file
+ * \brief
+ * Routines to invert 3x3 matrices
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_math
+ */
#include "gmxpre.h"
+#include "invertmatrix.h"
+
#include <cmath>
-#include "gromacs/math/vec.h"
#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/gmxassert.h"
-void m_inv_ur0(const matrix src, matrix dest)
+namespace gmx
+{
+
+void invertBoxMatrix(const matrix src, matrix dest)
{
double tmp = src[XX][XX]*src[YY][YY]*src[ZZ][ZZ];
if (std::fabs(tmp) <= 100*GMX_REAL_MIN)
dest[YY][ZZ] = 0.0;
}
-void m_inv(const matrix src, matrix dest)
+void invertMatrix(const matrix src, matrix dest)
{
const real smallreal = (real)1.0e-24;
const real largereal = (real)1.0e24;
{
gmx_fatal(FARGS, "Can not invert matrix, determinant = %e", determinant);
}
+ GMX_ASSERT(dest != src, "Cannot do in-place inversion of matrix");
dest[XX][XX] = c*(src[YY][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[YY][ZZ]);
dest[XX][YY] = -c*(src[XX][YY]*src[ZZ][ZZ]-src[ZZ][YY]*src[XX][ZZ]);
dest[ZZ][YY] = -c*(src[XX][XX]*src[ZZ][YY]-src[ZZ][XX]*src[XX][YY]);
dest[ZZ][ZZ] = c*(src[XX][XX]*src[YY][YY]-src[YY][XX]*src[XX][YY]);
}
+
+} // namespace
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2015, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \libinternal \file
+ * \brief
+ * Declares routines to invert 3x3 matrices
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_math
+ * \inlibraryapi
+ */
+#ifndef GMX_MATH_INVERTMATRIX_H
+#define GMX_MATH_INVERTMATRIX_H
+
+#include "gromacs/math/vec.h"
+#include "gromacs/utility/basedefinitions.h"
+
+namespace gmx
+{
+
+/*! \brief Invert a simulation-box matrix in \c src, return in \c dest
+ *
+ * This routine assumes that src is a simulation-box matrix, i.e. has
+ * zeroes in the upper-right triangle. A fatal error occurs if the
+ * product of the leading diagonal is too small. The inversion can be
+ * done "in place", i.e \c src and \c dest can be the same matrix.
+ */
+void invertBoxMatrix(const matrix src, matrix dest);
+
+/*! \brief Invert a general 3x3 matrix in \c src, return in \c dest
+ *
+ * A fatal error occurs if the determinant is too small. \c src and
+ * \c dest cannot be the same matrix.
+ */
+void invertMatrix(const matrix src, matrix dest);
+
+} // namespace gmx
+
+#endif
gmx_add_unit_test(MathUnitTests math-test
functions.cpp
+ invertmatrix.cpp
vectypes.cpp
)
--- /dev/null
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2015, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Tests matrix inversion routines
+ *
+ * \todo Test error conditions when they throw exceptions
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_math
+ */
+#include "gmxpre.h"
+
+#include "gromacs/math/invertmatrix.h"
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/math/vec.h"
+
+#include "testutils/testasserts.h"
+
+namespace
+{
+
+using gmx::invertMatrix;
+using gmx::invertBoxMatrix;
+using gmx::test::defaultRealTolerance;
+
+TEST(InvertMatrixTest, IdentityIsImpotent)
+{
+ matrix in = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+ matrix out;
+
+ invertMatrix(in, out);
+
+ EXPECT_REAL_EQ_TOL(out[XX][XX], in[XX][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[XX][YY], in[XX][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[XX][ZZ], in[XX][ZZ], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[YY][XX], in[YY][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[YY][YY], in[YY][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[YY][ZZ], in[YY][ZZ], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[ZZ][XX], in[ZZ][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[ZZ][YY], in[ZZ][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[ZZ][ZZ], in[ZZ][ZZ], defaultRealTolerance());
+}
+
+TEST(InvertMatrixTest, ComputesInverse)
+{
+ matrix in = {{1, 2, 3}, {-1, 2.5, 1}, {10, -2, 1.2}};
+ matrix out;
+ matrix expected = {{-0.12019230769230768,
+ 0.20192307692307693,
+ 0.13221153846153844},
+ {-0.26923076923076916,
+ 0.69230769230769229,
+ 0.096153846153846145},
+ {0.55288461538461531,
+ -0.52884615384615374,
+ -0.10817307692307691}};
+
+ invertMatrix(in, out);
+
+ EXPECT_REAL_EQ_TOL(out[XX][XX], expected[XX][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[XX][YY], expected[XX][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[XX][ZZ], expected[XX][ZZ], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[YY][XX], expected[YY][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[YY][YY], expected[YY][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[YY][ZZ], expected[YY][ZZ], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[ZZ][XX], expected[ZZ][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[ZZ][YY], expected[ZZ][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(out[ZZ][ZZ], expected[ZZ][ZZ], defaultRealTolerance());
+}
+
+TEST(InvertBoxMatrixTest, IdentityIsImpotent)
+{
+ matrix in = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
+
+ invertBoxMatrix(in, in);
+
+ EXPECT_REAL_EQ_TOL(in[XX][XX], in[XX][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(in[XX][YY], in[XX][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(in[XX][ZZ], in[XX][ZZ], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(in[YY][XX], in[YY][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(in[YY][YY], in[YY][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(in[YY][ZZ], in[YY][ZZ], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(in[ZZ][XX], in[ZZ][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(in[ZZ][YY], in[ZZ][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(in[ZZ][ZZ], in[ZZ][ZZ], defaultRealTolerance());
+}
+
+TEST(InvertBoxMatrixTest, ComputesInverseInPlace)
+{
+ matrix in = {{1, 0, 0}, {-1, 2.5, 0}, {10, -2, 1.2}};
+ matrix expected = {{1, 0, 0},
+ {0.4, 0.4, 0},
+ {-23.0/3.0, 2.0/3.0, 5.0/6.0}};
+
+ invertBoxMatrix(in, in);
+
+ EXPECT_REAL_EQ_TOL(expected[XX][XX], in[XX][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(expected[XX][YY], in[XX][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(expected[XX][ZZ], in[XX][ZZ], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(expected[YY][XX], in[YY][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(expected[YY][YY], in[YY][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(expected[YY][ZZ], in[YY][ZZ], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(expected[ZZ][XX], in[ZZ][XX], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(expected[ZZ][YY], in[ZZ][YY], defaultRealTolerance());
+ EXPECT_REAL_EQ_TOL(expected[ZZ][ZZ], in[ZZ][ZZ], defaultRealTolerance());
+}
+
+} // namespace
void m_add(matrix a,matrix b,matrix dest) dest = a + b
void m_sub(matrix a,matrix b,matrix dest) dest = a - b
void msmul(matrix m1,real r1,matrix dest) dest = r1 * m1
- void m_inv_ur0(matrix src,matrix dest) dest = src^-1
- void m_inv(matrix src,matrix dest) ! dest = src^-1
void mvmul(matrix a,rvec src,rvec dest) ! dest = a . src
void mvmul_ur0(matrix a,rvec src,rvec dest) dest = a . src
void tmvmul_ur0(matrix a,rvec src,rvec dest) dest = a* . src
dest[ZZ][ZZ] = r1*m1[ZZ][ZZ];
}
-/* Routines defined in invertmatrix.cpp */
-void m_inv_ur0(const matrix src, matrix dest);
-void m_inv(const matrix src, matrix dest);
-
static inline void mvmul(const matrix a, const rvec src, rvec dest)
{
dest[XX] = a[XX][XX]*src[XX]+a[XX][YY]*src[YY]+a[XX][ZZ]*src[ZZ];
#include "gromacs/domdec/domdec_struct.h"
#include "gromacs/gmxlib/nrnb.h"
#include "gromacs/math/functions.h"
+#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/units.h"
#include "gromacs/math/vec.h"
#include "gromacs/math/vecdump.h"
real maxl;
- m_inv_ur0(box, invbox);
+ gmx::invertBoxMatrix(box, invbox);
if (!bFirstStep)
{
#include <stdio.h>
#include "gromacs/math/functions.h"
+#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/constr.h"
#include "gromacs/pbcutil/ishift.h"
p->imH = invmH;
/* We normalize the inverse masses with imO for the matrix inversion.
* so we can keep using masses of almost zero for frozen particles,
- * without running out of the float range in m_inv.
+ * without running out of the float range in invertMatrix.
*/
imOn = 1;
imHn = p->imH/p->imO;
mat[2][0] = mat[0][2];
mat[2][1] = mat[1][2];
- m_inv(mat, p->invmat);
+ gmx::invertMatrix(mat, p->invmat);
msmul(p->invmat, 1/p->imO, p->invmat);
#include "gromacs/listed-forces/disre.h"
#include "gromacs/listed-forces/orires.h"
#include "gromacs/math/functions.h"
+#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/units.h"
#include "gromacs/math/vec.h"
#include "gromacs/math/vecdump.h"
}
}
}
- m_inv_ur0(box, invbox);
+ gmx::invertBoxMatrix(box, invbox);
copy_mat(bnew, box);
mmul_ur0(box, invbox, mu);
#include "gromacs/gmxlib/network.h"
#include "gromacs/math/functions.h"
+#include "gromacs/math/invertmatrix.h"
#include "gromacs/math/vec.h"
#include "gromacs/math/vecdump.h"
#include "gromacs/mdtypes/md_enums.h"
tmp[m][n] *= fac;
}
}
- m_inv(tmp, B);
+ gmx::invertMatrix(tmp, B);
for (m = 0; (m < DIM); m++)
{
for (n = 0; (n < DIM); n++)