if (rsq > 0)
{
+ /* Note that unlike in the nbnxn kernels, we do not need
+ * to clamp the value of rsq before taking the invsqrt
+ * to avoid NaN in the LJ calculation, since here we do
+ * not calculate LJ interactions when C6 and C12 are zero.
+ */
+
rinv = gmx::invsqrt(rsq);
r = rsq*rinv;
}
#define NBNXN_CPU_CLUSTER_I_SIZE_2LOG 2
-/* To avoid NaN when excluded atoms are at zero distance, we add a small
- * number to r^2. NBNXN_AVOID_SING_R2_INC^-3 should fit in real.
- */
-#if !GMX_DOUBLE
-#define NBNXN_AVOID_SING_R2_INC 1.0e-12f
+// Lower limit for square interaction distances in nonbonded kernels.
+// For smaller values we will overflow when calculating r^-1 or r^-12, but
+// to keep it simple we always apply the limit from the tougher r^-12 condition.
+#if GMX_DOUBLE
+// Some double precision SIMD architectures use single precision in the first
+// step, so although the double precision criterion would allow smaller rsq,
+// we need to stay in single precision with some margin for the N-R iterations.
+#define NBNXN_MIN_RSQ 1.0e-36
#else
-/* The double prec. x86 SIMD kernels use a single prec. invsqrt, so > 1e-38 */
-#define NBNXN_AVOID_SING_R2_INC 1.0e-36
+// The worst intermediate value we might evaluate is r^-12, which
+// means we should ensure r^2 stays above pow(GMX_FLOAT_MAX,-1.0/6.0)*1.01 (some margin)
+#define NBNXN_MIN_RSQ 3.82e-07f // r > 6.2e-4
#endif
#endif /* LJ_COMB_GEOM */
#endif /* LJ_COMB */
- /* avoid NaN for excluded pairs at r=0 */
- r2 += (1.0f - int_bit) * NBNXN_AVOID_SING_R2_INC;
+ // Ensure distance do not become so small that r^-12 overflows
+ r2 = max(r2, NBNXN_MIN_RSQ);
inv_r = rsqrt(r2);
inv_r2 = inv_r * inv_r;
#endif /* LJ_COMB_GEOM */
#endif /* LJ_COMB */
- /* avoid NaN for excluded pairs at r=0 */
- r2 += (1.0f - int_bit) * NBNXN_AVOID_SING_R2_INC;
+ // Ensure distance do not become so small that r^-12 overflows
+ r2 = max(r2, NBNXN_MIN_RSQ);
inv_r = rsqrt(r2);
inv_r2 = inv_r * inv_r;
#include <cmath>
+#include <algorithm>
+
#include "gromacs/math/functions.h"
#include "gromacs/math/utilities.h"
#include "gromacs/math/vec.h"
npair++;
}
- /* avoid NaN for excluded pairs at r=0 */
- rsq += (1.0 - int_bit)*NBNXN_AVOID_SING_R2_INC;
+ // Ensure distance do not become so small that r^-12 overflows
+ rsq = std::max(rsq, NBNXN_MIN_RSQ);
rinv = gmx::invsqrt(rsq);
rinvsq = rinv*rinv;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
#include <cmath>
+#include <algorithm>
+
#include "gromacs/math/functions.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/force.h"
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
skipmask = (rsq >= rcut2) ? 0 : skipmask;
/* 9 flops for r^2 + cut-off check */
-#ifdef CHECK_EXCLS
- /* Excluded atoms are allowed to be on top of each other.
- * To avoid overflow of rinv, rinvsq and rinvsix
- * we add a small number to rsq for excluded pairs only.
- */
- rsq += (1 - interact)*NBNXN_AVOID_SING_R2_INC;
-#endif
+ // Ensure the distances do not fall below the limit where r^-12 overflows.
+ // This should never happen for normal interactions.
+ rsq = std::max(rsq, NBNXN_MIN_RSQ);
#ifdef COUNT_PAIRS
npair++;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
}
#endif
-#ifdef CHECK_EXCLS
- /* For excluded pairs add a small number to avoid r^-6 = NaN */
- rsq_S0 = rsq_S0 + selectByNotMask(avoid_sing_S, interact_S0);
- rsq_S2 = rsq_S2 + selectByNotMask(avoid_sing_S, interact_S2);
-#endif
+ // Ensure the distances do not fall below the limit where r^-12 overflows.
+ // This should never happen for normal interactions.
+ rsq_S0 = max(rsq_S0, minRsq_S);
+ rsq_S2 = max(rsq_S2, minRsq_S);
/* Calculate 1/r */
rinv_S0 = invsqrt(rsq_S0);
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
#endif
#endif /* LJ_COMB_LB */
- SimdReal avoid_sing_S;
+ SimdReal minRsq_S;
SimdReal rc2_S;
#ifdef VDW_CUTOFF_CHECK
SimdReal rcvdw2_S;
rcvdw2_S = SimdReal(ic->rvdw*ic->rvdw);
#endif
- avoid_sing_S = SimdReal(NBNXN_AVOID_SING_R2_INC);
+ minRsq_S = SimdReal(NBNXN_MIN_RSQ);
q = nbat->q;
facel = ic->epsfac;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
}
#endif
-#ifdef CHECK_EXCLS
- /* For excluded pairs add a small number to avoid r^-6 = NaN */
- rsq_S0 = rsq_S0 + selectByNotMask(avoid_sing_S, interact_S0);
- rsq_S1 = rsq_S1 + selectByNotMask(avoid_sing_S, interact_S1);
- rsq_S2 = rsq_S2 + selectByNotMask(avoid_sing_S, interact_S2);
- rsq_S3 = rsq_S3 + selectByNotMask(avoid_sing_S, interact_S3);
-#endif
+ // Ensure the distances do not fall below the limit where r^-12 overflows.
+ // This should never happen for normal interactions.
+ rsq_S0 = max(rsq_S0, minRsq_S);
+ rsq_S1 = max(rsq_S1, minRsq_S);
+ rsq_S2 = max(rsq_S2, minRsq_S);
+ rsq_S3 = max(rsq_S3, minRsq_S);
/* Calculate 1/r */
#if !GMX_DOUBLE
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015,2016, 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.
#endif
#endif /* LJ_COMB_LB */
- SimdReal avoid_sing_S;
+ SimdReal minRsq_S;
SimdReal rc2_S;
#ifdef VDW_CUTOFF_CHECK
SimdReal rcvdw2_S;
rcvdw2_S = SimdReal(ic->rvdw*ic->rvdw);
#endif
- avoid_sing_S = SimdReal(NBNXN_AVOID_SING_R2_INC);
+ minRsq_S = SimdReal(NBNXN_MIN_RSQ);
q = nbat->q;
facel = ic->epsfac;
* in the JIT compilation that happens at runtime.
*/
extraDefines += gmx::formatString(
- " -DCENTRAL=%d -DNBNXN_GPU_NCLUSTER_PER_SUPERCLUSTER=%d -DNBNXN_GPU_CLUSTER_SIZE=%d -DNBNXN_GPU_JGROUP_SIZE=%d -DNBNXN_AVOID_SING_R2_INC=%s %s",
+ " -DCENTRAL=%d -DNBNXN_GPU_NCLUSTER_PER_SUPERCLUSTER=%d -DNBNXN_GPU_CLUSTER_SIZE=%d -DNBNXN_GPU_JGROUP_SIZE=%d -DNBNXN_MIN_RSQ=%s %s",
CENTRAL, /* Defined in ishift.h */
c_nbnxnGpuNumClusterPerSupercluster, /* Defined in nbnxn_pairlist.h */
c_nbnxnGpuClusterSize, /* Defined in nbnxn_pairlist.h */
c_nbnxnGpuJgroupSize, /* Defined in nbnxn_pairlist.h */
- STRINGIFY_MACRO(NBNXN_AVOID_SING_R2_INC) /* Defined in nbnxn_consts.h */
- /* NBNXN_AVOID_SING_R2_INC passed as string to avoid
+ STRINGIFY_MACRO(NBNXN_MIN_RSQ) /* Defined in nbnxn_consts.h */
+ /* NBNXN_MIN_RSQ passed as string to avoid
floating point representation problems with sprintf */
, (nb->bPrefetchLjParam) ? "-DIATYPE_SHMEM" : ""
);
#endif /* LJ_COMB_GEOM */
#endif /* LJ_COMB */
- /* avoid NaN for excluded pairs at r=0 */
- r2 += (1.0f - int_bit) * NBNXN_AVOID_SING_R2_INC;
+ // Ensure distance do not become so small that r^-12 overflows
+ r2 = max(r2,NBNXN_MIN_RSQ);
inv_r = rsqrt(r2);
inv_r2 = inv_r * inv_r;
#endif /* LJ_COMB_GEOM */
#endif /* LJ_COMB */
- /* avoid NaN for excluded pairs at r=0 */
- r2 += (1.0f - int_bit) * NBNXN_AVOID_SING_R2_INC;
+ // Ensure distance do not become so small that r^-12 overflows
+ r2 = max(r2,NBNXN_MIN_RSQ);
inv_r = rsqrt(r2);
inv_r2 = inv_r * inv_r;
#endif /* LJ_COMB_GEOM */
#endif /* LJ_COMB */
- /* avoid NaN for excluded pairs at r=0 */
- r2 += (1.0f - int_bit) * NBNXN_AVOID_SING_R2_INC;
+ // Ensure distance do not become so small that r^-12 overflows
+ r2 = max(r2,NBNXN_MIN_RSQ);
inv_r = rsqrt(r2);
inv_r2 = inv_r * inv_r;