+#include "gromacs/utility/exceptions.h"
+
+gmx_ekindata_t::gmx_ekindata_t(int numTempCoupleGroups, real cos_accel, int numThreads) :
+ ngtc(numTempCoupleGroups),
+ nthreads_(numThreads)
+{
+ tcstat.resize(ngtc);
+ /* Set Berendsen tcoupl lambda's to 1,
+ * so runs without Berendsen coupling are not affected.
+ */
+ for (int i = 0; i < ngtc; i++)
+ {
+ tcstat[i].lambda = 1.0;
+ tcstat[i].vscale_nhc = 1.0;
+ tcstat[i].ekinscaleh_nhc = 1.0;
+ tcstat[i].ekinscalef_nhc = 1.0;
+ }
+
+ snew(ekin_work_alloc, nthreads_);
+ snew(ekin_work, nthreads_);
+ snew(dekindl_work, nthreads_);
+
+#pragma omp parallel for num_threads(nthreads_) schedule(static)
+ for (int thread = 0; thread < nthreads_; thread++)
+ {
+ try
+ {
+ constexpr int EKIN_WORK_BUFFER_SIZE = 2;
+ /* Allocate 2 extra elements on both sides, so in single
+ * precision we have
+ * EKIN_WORK_BUFFER_SIZE*DIM*DIM*sizeof(real) = 72/144 bytes
+ * buffer on both sides to avoid cache pollution.
+ */
+ snew(ekin_work_alloc[thread], ngtc + 2 * EKIN_WORK_BUFFER_SIZE);
+ ekin_work[thread] = ekin_work_alloc[thread] + EKIN_WORK_BUFFER_SIZE;
+ /* Nasty hack so we can have the per-thread accumulation
+ * variable for dekindl in the same thread-local cache lines
+ * as the per-thread accumulation tensors for ekin[fh],
+ * because they are accumulated in the same loop. */
+ dekindl_work[thread] = &(ekin_work[thread][ngtc][0][0]);
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
+ }
+
+ cosacc.cos_accel = cos_accel;
+}
+