Use std::vector in t_state
authorBerk Hess <hess@kth.se>
Tue, 6 Sep 2016 09:32:58 +0000 (11:32 +0200)
committerDavid van der Spoel <davidvanderspoel@gmail.com>
Thu, 29 Sep 2016 07:20:06 +0000 (09:20 +0200)
Changed x, v and cg_p pointers in t_state to PaddedRVecVector.
PaddedRVecVector is currently std::vector<RVec> and is always
sized with one element extra for 4-wide SIMD (gather) loads.
But this will be replaced by a proper class.
t_state is now freed by the default destructor with some issues:
* ekinstate_t is fully converted to std::vector in a child change
* state struct of special algorithms still need conversion

Changes to t_state propagate over large parts of the core code.
This change extracts rvec pointers at intermediate levels to
make this single change manageable.
The state in EM also needed to be updated, which led to a lot
of changes in minimize.cpp, especially to do_lbfgs() which was not
yet converted to use em_state_t.

Change-Id: Ib6ead1f13741ead8dbeeddd118ecdd4bf1cc6584

37 files changed:
src/gromacs/domdec/domdec.cpp
src/gromacs/domdec/domdec.h
src/gromacs/domdec/domdec_network.cpp
src/gromacs/domdec/domdec_network.h
src/gromacs/domdec/domdec_topology.cpp
src/gromacs/fileio/checkpoint.cpp
src/gromacs/fileio/tpxio.cpp
src/gromacs/gmxana/gmx_pme_error.cpp
src/gromacs/gmxpreprocess/grompp.cpp
src/gromacs/imd/imd.cpp
src/gromacs/mdlib/broadcaststructs.cpp
src/gromacs/mdlib/constr.cpp
src/gromacs/mdlib/coupling.cpp
src/gromacs/mdlib/force.cpp
src/gromacs/mdlib/force.h
src/gromacs/mdlib/md_support.cpp
src/gromacs/mdlib/md_support.h
src/gromacs/mdlib/mdoutf.cpp
src/gromacs/mdlib/mdoutf.h
src/gromacs/mdlib/minimize.cpp
src/gromacs/mdlib/shellfc.cpp
src/gromacs/mdlib/shellfc.h
src/gromacs/mdlib/sim_util.cpp
src/gromacs/mdlib/sim_util.h
src/gromacs/mdlib/tpi.cpp
src/gromacs/mdlib/trajectory_writing.cpp
src/gromacs/mdlib/trajectory_writing.h
src/gromacs/mdlib/update.cpp
src/gromacs/mdlib/update.h
src/gromacs/mdtypes/state.cpp
src/gromacs/mdtypes/state.h
src/gromacs/tools/convert_tpr.cpp
src/gromacs/tools/dump.cpp
src/programs/mdrun/md.cpp
src/programs/mdrun/membed.cpp
src/programs/mdrun/repl_ex.cpp
src/programs/mdrun/runner.cpp

index 88cc3593a4553b39c3c48b5e48475b75f05d7d04..a18620ccfc2805a0079b9ae3a73b058fcd6e3ec6 100644 (file)
@@ -284,13 +284,8 @@ void dd_store_state(gmx_domdec_t *dd, t_state *state)
         gmx_incons("The state does not the domain decomposition state");
     }
 
-    state->ncg_gl = dd->ncg_home;
-    if (state->ncg_gl > state->cg_gl_nalloc)
-    {
-        state->cg_gl_nalloc = over_alloc_dd(state->ncg_gl);
-        srenew(state->cg_gl, state->cg_gl_nalloc);
-    }
-    for (i = 0; i < state->ncg_gl; i++)
+    state->cg_gl.resize(dd->ncg_home);
+    for (i = 0; i < dd->ncg_home; i++)
     {
         state->cg_gl[i] = dd->index_gl[i];
     }
@@ -1067,8 +1062,8 @@ static void dd_collect_cg(gmx_domdec_t *dd,
 
         cgs_gl = &dd->comm->cgs_gl;
 
-        ncg_home = state_local->ncg_gl;
-        cg       = state_local->cg_gl;
+        ncg_home = state_local->cg_gl.size();
+        cg       = state_local->cg_gl.data();
         nat_home = 0;
         for (i = 0; i < ncg_home; i++)
         {
@@ -1132,7 +1127,7 @@ static void dd_collect_cg(gmx_domdec_t *dd,
 }
 
 static void dd_collect_vec_sendrecv(gmx_domdec_t *dd,
-                                    rvec *lv, rvec *v)
+                                    const rvec *lv, rvec *v)
 {
     gmx_domdec_master_t *ma;
     int                  n, i, c, a, nalloc = 0;
@@ -1144,8 +1139,8 @@ static void dd_collect_vec_sendrecv(gmx_domdec_t *dd,
     if (!DDMASTER(dd))
     {
 #if GMX_MPI
-        MPI_Send(lv, dd->nat_home*sizeof(rvec), MPI_BYTE, DDMASTERRANK(dd),
-                 dd->rank, dd->mpi_comm_all);
+        MPI_Send(const_cast<void *>(static_cast<const void *>(lv)), dd->nat_home*sizeof(rvec), MPI_BYTE,
+                 DDMASTERRANK(dd), dd->rank, dd->mpi_comm_all);
 #endif
     }
     else
@@ -1209,7 +1204,7 @@ static void get_commbuffer_counts(gmx_domdec_t *dd,
 }
 
 static void dd_collect_vec_gatherv(gmx_domdec_t *dd,
-                                   rvec *lv, rvec *v)
+                                   const rvec *lv, rvec *v)
 {
     gmx_domdec_master_t *ma;
     int                 *rcounts = NULL, *disps = NULL;
@@ -1246,11 +1241,15 @@ static void dd_collect_vec_gatherv(gmx_domdec_t *dd,
     }
 }
 
-void dd_collect_vec(gmx_domdec_t *dd,
-                    t_state *state_local, rvec *lv, rvec *v)
+void dd_collect_vec(gmx_domdec_t           *dd,
+                    t_state                *state_local,
+                    const PaddedRVecVector *localVector,
+                    rvec                   *v)
 {
     dd_collect_cg(dd, state_local);
 
+    const rvec *lv = as_rvec_array(localVector->data());
+
     if (dd->nnodes <= GMX_DD_NNODES_SENDRECV)
     {
         dd_collect_vec_sendrecv(dd, lv, v);
@@ -1261,6 +1260,14 @@ void dd_collect_vec(gmx_domdec_t *dd,
     }
 }
 
+void dd_collect_vec(gmx_domdec_t           *dd,
+                    t_state                *state_local,
+                    const PaddedRVecVector *localVector,
+                    PaddedRVecVector       *vector)
+{
+    dd_collect_vec(dd, state_local, localVector, as_rvec_array(vector->data()));
+}
+
 
 void dd_collect_state(gmx_domdec_t *dd,
                       t_state *state_local, t_state *state)
@@ -1309,15 +1316,15 @@ void dd_collect_state(gmx_domdec_t *dd,
             switch (est)
             {
                 case estX:
-                    dd_collect_vec(dd, state_local, state_local->x, state->x);
+                    dd_collect_vec(dd, state_local, &state_local->x, &state->x);
                     break;
                 case estV:
-                    dd_collect_vec(dd, state_local, state_local->v, state->v);
+                    dd_collect_vec(dd, state_local, &state_local->v, &state->v);
                     break;
                 case est_SDX_NOTSUPPORTED:
                     break;
                 case estCGP:
-                    dd_collect_vec(dd, state_local, state_local->cg_p, state->cg_p);
+                    dd_collect_vec(dd, state_local, &state_local->cg_p, &state->cg_p);
                     break;
                 case estDISRE_INITF:
                 case estDISRE_RM3TAV:
@@ -1331,17 +1338,15 @@ void dd_collect_state(gmx_domdec_t *dd,
     }
 }
 
-static void dd_realloc_state(t_state *state, rvec **f, int nalloc)
+static void dd_resize_state(t_state *state, PaddedRVecVector *f, int natoms)
 {
     int est;
 
     if (debug)
     {
-        fprintf(debug, "Reallocating state: currently %d, required %d, allocating %d\n", state->nalloc, nalloc, over_alloc_dd(nalloc));
+        fprintf(debug, "Resizing state: currently %d, required %d\n", state->natoms, natoms);
     }
 
-    state->nalloc = over_alloc_dd(nalloc);
-
     for (est = 0; est < estNR; est++)
     {
         if (EST_DISTR(est) && (state->flags & (1<<est)))
@@ -1352,15 +1357,15 @@ static void dd_realloc_state(t_state *state, rvec **f, int nalloc)
             switch (est)
             {
                 case estX:
-                    srenew(state->x, state->nalloc + 1);
+                    state->x.resize(natoms + 1);
                     break;
                 case estV:
-                    srenew(state->v, state->nalloc + 1);
+                    state->v.resize(natoms + 1);
                     break;
                 case est_SDX_NOTSUPPORTED:
                     break;
                 case estCGP:
-                    srenew(state->cg_p, state->nalloc + 1);
+                    state->cg_p.resize(natoms + 1);
                     break;
                 case estDISRE_INITF:
                 case estDISRE_RM3TAV:
@@ -1369,39 +1374,41 @@ static void dd_realloc_state(t_state *state, rvec **f, int nalloc)
                     /* No reallocation required */
                     break;
                 default:
-                    gmx_incons("Unknown state entry encountered in dd_realloc_state");
+                    gmx_incons("Unknown state entry encountered in dd_resize_state");
             }
         }
     }
 
     if (f != NULL)
     {
-        srenew(*f, state->nalloc);
+        (*f).resize(natoms + 1);
     }
 }
 
-static void dd_check_alloc_ncg(t_forcerec *fr, t_state *state, rvec **f,
-                               int nalloc)
+static void dd_check_alloc_ncg(t_forcerec       *fr,
+                               t_state          *state,
+                               PaddedRVecVector *f,
+                               int               numChargeGroups)
 {
-    if (nalloc > fr->cg_nalloc)
+    if (numChargeGroups > fr->cg_nalloc)
     {
         if (debug)
         {
-            fprintf(debug, "Reallocating forcerec: currently %d, required %d, allocating %d\n", fr->cg_nalloc, nalloc, over_alloc_dd(nalloc));
+            fprintf(debug, "Reallocating forcerec: currently %d, required %d, allocating %d\n", fr->cg_nalloc, numChargeGroups, over_alloc_dd(numChargeGroups));
         }
-        fr->cg_nalloc = over_alloc_dd(nalloc);
+        fr->cg_nalloc = over_alloc_dd(numChargeGroups);
         srenew(fr->cginfo, fr->cg_nalloc);
         if (fr->cutoff_scheme == ecutsGROUP)
         {
             srenew(fr->cg_cm, fr->cg_nalloc);
         }
     }
-    if (fr->cutoff_scheme == ecutsVERLET && nalloc > state->nalloc)
+    if (fr->cutoff_scheme == ecutsVERLET)
     {
         /* We don't use charge groups, we use x in state to set up
          * the atom communication.
          */
-        dd_realloc_state(state, f, nalloc);
+        dd_resize_state(state, f, numChargeGroups);
     }
 }
 
@@ -1544,7 +1551,7 @@ static void dd_distribute_dfhist(gmx_domdec_t *dd, df_history_t *dfhist)
 
 static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
                                 t_state *state, t_state *state_local,
-                                rvec **f)
+                                PaddedRVecVector *f)
 {
     int  i, j, nh;
 
@@ -1586,7 +1593,7 @@ static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
             }
         }
     }
-    dd_bcast(dd, ((efptNR)*sizeof(real)), state_local->lambda);
+    dd_bcast(dd, ((efptNR)*sizeof(real)), state_local->lambda.data());
     dd_bcast(dd, sizeof(int), &state_local->fep_state);
     dd_bcast(dd, sizeof(real), &state_local->veta);
     dd_bcast(dd, sizeof(real), &state_local->vol0);
@@ -1595,19 +1602,17 @@ static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
     dd_bcast(dd, sizeof(state_local->boxv), state_local->boxv);
     dd_bcast(dd, sizeof(state_local->svir_prev), state_local->svir_prev);
     dd_bcast(dd, sizeof(state_local->fvir_prev), state_local->fvir_prev);
-    dd_bcast(dd, ((state_local->ngtc*nh)*sizeof(double)), state_local->nosehoover_xi);
-    dd_bcast(dd, ((state_local->ngtc*nh)*sizeof(double)), state_local->nosehoover_vxi);
-    dd_bcast(dd, state_local->ngtc*sizeof(double), state_local->therm_integral);
-    dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_xi);
-    dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_vxi);
+    dd_bcast(dd, ((state_local->ngtc*nh)*sizeof(double)), state_local->nosehoover_xi.data());
+    dd_bcast(dd, ((state_local->ngtc*nh)*sizeof(double)), state_local->nosehoover_vxi.data());
+    dd_bcast(dd, state_local->ngtc*sizeof(double), state_local->therm_integral.data());
+    dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_xi.data());
+    dd_bcast(dd, ((state_local->nnhpres*nh)*sizeof(double)), state_local->nhpres_vxi.data());
 
     /* communicate df_history -- required for restarting from checkpoint */
     dd_distribute_dfhist(dd, state_local->dfhist);
 
-    if (dd->nat_home > state_local->nalloc)
-    {
-        dd_realloc_state(state_local, f, dd->nat_home);
-    }
+    dd_resize_state(state_local, f, dd->nat_home);
+
     for (i = 0; i < estNR; i++)
     {
         if (EST_DISTR(i) && (state_local->flags & (1<<i)))
@@ -1615,15 +1620,15 @@ static void dd_distribute_state(gmx_domdec_t *dd, t_block *cgs,
             switch (i)
             {
                 case estX:
-                    dd_distribute_vec(dd, cgs, state->x, state_local->x);
+                    dd_distribute_vec(dd, cgs, as_rvec_array(state->x.data()), as_rvec_array(state_local->x.data()));
                     break;
                 case estV:
-                    dd_distribute_vec(dd, cgs, state->v, state_local->v);
+                    dd_distribute_vec(dd, cgs, as_rvec_array(state->v.data()), as_rvec_array(state_local->v.data()));
                     break;
                 case est_SDX_NOTSUPPORTED:
                     break;
                 case estCGP:
-                    dd_distribute_vec(dd, cgs, state->cg_p, state_local->cg_p);
+                    dd_distribute_vec(dd, cgs, as_rvec_array(state->cg_p.data()), as_rvec_array(state_local->cg_p.data()));
                     break;
                 case estDISRE_INITF:
                 case estDISRE_RM3TAV:
@@ -2148,25 +2153,26 @@ static void set_zones_ncg_home(gmx_domdec_t *dd)
 }
 
 static void rebuild_cgindex(gmx_domdec_t *dd,
-                            const int *gcgs_index, t_state *state)
+                            const int *gcgs_index, const t_state *state)
 {
-    int nat, i, *ind, *dd_cg_gl, *cgindex, cg_gl;
+    int * gmx_restrict dd_cg_gl = dd->index_gl;
+    int * gmx_restrict cgindex  = dd->cgindex;
+    int                nat      = 0;
 
-    ind        = state->cg_gl;
-    dd_cg_gl   = dd->index_gl;
-    cgindex    = dd->cgindex;
-    nat        = 0;
+    /* Copy back the global charge group indices from state
+     * and rebuild the local charge group to atom index.
+     */
     cgindex[0] = nat;
-    for (i = 0; i < state->ncg_gl; i++)
+    for (unsigned int i = 0; i < state->cg_gl.size(); i++)
     {
         cgindex[i]  = nat;
-        cg_gl       = ind[i];
+        int cg_gl   = state->cg_gl[i];
         dd_cg_gl[i] = cg_gl;
         nat        += gcgs_index[cg_gl+1] - gcgs_index[cg_gl];
     }
-    cgindex[i] = nat;
+    cgindex[state->cg_gl.size()] = nat;
 
-    dd->ncg_home = state->ncg_gl;
+    dd->ncg_home = state->cg_gl.size();
     dd->nat_home = nat;
 
     set_zones_ncg_home(dd);
@@ -4229,7 +4235,7 @@ static void calc_cg_move(FILE *fplog, gmx_int64_t step,
                     if (pos_d >= limit1[d])
                     {
                         cg_move_error(fplog, dd, step, cg, d, 1,
-                                      cg_cm != state->x, limitd[d],
+                                      cg_cm != as_rvec_array(state->x.data()), limitd[d],
                                       cg_cm[cg], cm_new, pos_d);
                     }
                     dev[d] = 1;
@@ -4256,7 +4262,7 @@ static void calc_cg_move(FILE *fplog, gmx_int64_t step,
                     if (pos_d < limit0[d])
                     {
                         cg_move_error(fplog, dd, step, cg, d, -1,
-                                      cg_cm != state->x, limitd[d],
+                                      cg_cm != as_rvec_array(state->x.data()), limitd[d],
                                       cg_cm[cg], cm_new, pos_d);
                     }
                     dev[d] = -1;
@@ -4340,7 +4346,7 @@ static void calc_cg_move(FILE *fplog, gmx_int64_t step,
 
 static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
                                gmx_domdec_t *dd, ivec tric_dir,
-                               t_state *state, rvec **f,
+                               t_state *state, PaddedRVecVector *f,
                                t_forcerec *fr,
                                gmx_bool bCompact,
                                t_nrnb *nrnb,
@@ -4469,7 +4475,7 @@ static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
                          cgindex,
                          ( thread   *dd->ncg_home)/nthread,
                          ((thread+1)*dd->ncg_home)/nthread,
-                         fr->cutoff_scheme == ecutsGROUP ? cg_cm : state->x,
+                         fr->cutoff_scheme == ecutsGROUP ? cg_cm : as_rvec_array(state->x.data()),
                          move);
         }
         GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
@@ -4548,7 +4554,7 @@ static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
              */
             home_pos_cg =
                 compact_and_copy_vec_cg(dd->ncg_home, move, cgindex,
-                                        nvec, state->x, comm, FALSE);
+                                        nvec, as_rvec_array(state->x.data()), comm, FALSE);
             if (bCompact)
             {
                 home_pos_cg -= *ncg_moved;
@@ -4562,16 +4568,19 @@ static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
     vec         = 0;
     home_pos_at =
         compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
-                                nvec, vec++, state->x, comm, bCompact);
+                                nvec, vec++, as_rvec_array(state->x.data()),
+                                comm, bCompact);
     if (bV)
     {
         compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
-                                nvec, vec++, state->v, comm, bCompact);
+                                nvec, vec++, as_rvec_array(state->v.data()),
+                                comm, bCompact);
     }
     if (bCGP)
     {
         compact_and_copy_vec_at(dd->ncg_home, move, cgindex,
-                                nvec, vec++, state->cg_p, comm, bCompact);
+                                nvec, vec++, as_rvec_array(state->cg_p.data()),
+                                comm, bCompact);
     }
 
     if (bCompact)
@@ -4647,6 +4656,13 @@ static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
             nvr      += i;
         }
 
+        dd_check_alloc_ncg(fr, state, f, home_pos_cg + ncg_recv);
+        if (fr->cutoff_scheme == ecutsGROUP)
+        {
+            /* Here we resize to more than necessary and shrink later */
+            dd_resize_state(state, f, home_pos_at + ncg_recv*MAX_CGCGSIZE);
+        }
+
         /* Process the received charge groups */
         buf_pos = 0;
         for (cg = 0; cg < ncg_recv; cg++)
@@ -4759,7 +4775,6 @@ static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
                 dd->index_gl[home_pos_cg]  = comm->buf_int[cg*DD_CGIBS];
                 dd->cgindex[home_pos_cg+1] = dd->cgindex[home_pos_cg] + nrcg;
                 /* Copy the state from the buffer */
-                dd_check_alloc_ncg(fr, state, f, home_pos_cg+1);
                 if (fr->cutoff_scheme == ecutsGROUP)
                 {
                     cg_cm = fr->cg_cm;
@@ -4775,10 +4790,6 @@ static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
                     comm->bLocalCG[dd->index_gl[home_pos_cg]] = TRUE;
                 }
 
-                if (home_pos_at+nrcg > state->nalloc)
-                {
-                    dd_realloc_state(state, f, home_pos_at+nrcg);
-                }
                 for (i = 0; i < nrcg; i++)
                 {
                     copy_rvec(comm->vbuf.v[buf_pos++],
@@ -4847,6 +4858,12 @@ static void dd_redistribute_cg(FILE *fplog, gmx_int64_t step,
     dd->ncg_home = home_pos_cg;
     dd->nat_home = home_pos_at;
 
+    if (fr->cutoff_scheme == ecutsGROUP && !bCompact)
+    {
+        /* We overallocated before, we need to set the right size here */
+        dd_resize_state(state, f, dd->nat_home);
+    }
+
     if (debug)
     {
         fprintf(debug,
@@ -7217,7 +7234,7 @@ static gmx_bool test_dd_cutoff(t_commrec *cr,
     dd = cr->dd;
 
     set_ddbox(dd, FALSE, cr, ir, state->box,
-              TRUE, &dd->comm->cgs_gl, state->x, &ddbox);
+              TRUE, &dd->comm->cgs_gl, as_rvec_array(state->x.data()), &ddbox);
 
     LocallyLimited = 0;
 
@@ -7881,7 +7898,8 @@ get_zone_pulse_cgs(gmx_domdec_t *dd,
 
 static void setup_dd_communication(gmx_domdec_t *dd,
                                    matrix box, gmx_ddbox_t *ddbox,
-                                   t_forcerec *fr, t_state *state, rvec **f)
+                                   t_forcerec *fr,
+                                   t_state *state, PaddedRVecVector *f)
 {
     int                    dim_ind, dim, dim0, dim1, dim2, dimd, p, nat_tot;
     int                    nzone, nzone_send, zone, zonei, cg0, cg1;
@@ -7928,7 +7946,7 @@ static void setup_dd_communication(gmx_domdec_t *dd,
             cg_cm = fr->cg_cm;
             break;
         case ecutsVERLET:
-            cg_cm = state->x;
+            cg_cm = as_rvec_array(state->x.data());
             break;
         default:
             gmx_incons("unimplemented");
@@ -8266,7 +8284,7 @@ static void setup_dd_communication(gmx_domdec_t *dd,
             }
             else
             {
-                cg_cm = state->x;
+                cg_cm = as_rvec_array(state->x.data());
             }
             /* Communicate cg_cm */
             if (cd->bInPlace)
@@ -8908,15 +8926,15 @@ static void dd_sort_state(gmx_domdec_t *dd, rvec *cgcm, t_forcerec *fr, t_state
             switch (i)
             {
                 case estX:
-                    order_vec_atom(dd->ncg_home, cgindex, cgsort, state->x, vbuf);
+                    order_vec_atom(dd->ncg_home, cgindex, cgsort, as_rvec_array(state->x.data()), vbuf);
                     break;
                 case estV:
-                    order_vec_atom(dd->ncg_home, cgindex, cgsort, state->v, vbuf);
+                    order_vec_atom(dd->ncg_home, cgindex, cgsort, as_rvec_array(state->v.data()), vbuf);
                     break;
                 case est_SDX_NOTSUPPORTED:
                     break;
                 case estCGP:
-                    order_vec_atom(dd->ncg_home, cgindex, cgsort, state->cg_p, vbuf);
+                    order_vec_atom(dd->ncg_home, cgindex, cgsort, as_rvec_array(state->cg_p.data()), vbuf);
                     break;
                 case estLD_RNG:
                 case estLD_RNGI:
@@ -9090,7 +9108,7 @@ void dd_partition_system(FILE                *fplog,
                          const gmx_mtop_t    *top_global,
                          const t_inputrec    *ir,
                          t_state             *state_local,
-                         rvec               **f,
+                         PaddedRVecVector    *f,
                          t_mdatoms           *mdatoms,
                          gmx_localtop_t      *top_local,
                          t_forcerec          *fr,
@@ -9251,10 +9269,10 @@ void dd_partition_system(FILE                *fplog,
         ncgindex_set = 0;
 
         set_ddbox(dd, bMasterState, cr, ir, state_global->box,
-                  TRUE, cgs_gl, state_global->x, &ddbox);
+                  TRUE, cgs_gl, as_rvec_array(state_global->x.data()), &ddbox);
 
         get_cg_distribution(fplog, dd, cgs_gl,
-                            state_global->box, &ddbox, state_global->x);
+                            state_global->box, &ddbox, as_rvec_array(state_global->x.data()));
 
         dd_distribute_state(dd, cgs_gl,
                             state_global, state_local, f);
@@ -9267,7 +9285,7 @@ void dd_partition_system(FILE                *fplog,
         if (fr->cutoff_scheme == ecutsGROUP)
         {
             calc_cgcm(fplog, 0, dd->ncg_home,
-                      &top_local->cgs, state_local->x, fr->cg_cm);
+                      &top_local->cgs, as_rvec_array(state_local->x.data()), fr->cg_cm);
         }
 
         inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
@@ -9298,7 +9316,7 @@ void dd_partition_system(FILE                *fplog,
         {
             /* Redetermine the cg COMs */
             calc_cgcm(fplog, 0, dd->ncg_home,
-                      &top_local->cgs, state_local->x, fr->cg_cm);
+                      &top_local->cgs, as_rvec_array(state_local->x.data()), fr->cg_cm);
         }
 
         inc_nrnb(nrnb, eNR_CGCM, dd->nat_home);
@@ -9306,7 +9324,7 @@ void dd_partition_system(FILE                *fplog,
         dd_set_cginfo(dd->index_gl, 0, dd->ncg_home, fr, comm->bLocalCG);
 
         set_ddbox(dd, bMasterState, cr, ir, state_local->box,
-                  TRUE, &top_local->cgs, state_local->x, &ddbox);
+                  TRUE, &top_local->cgs, as_rvec_array(state_local->x.data()), &ddbox);
 
         bRedist = dlbIsOn(comm);
     }
@@ -9325,7 +9343,7 @@ void dd_partition_system(FILE                *fplog,
             copy_rvec(comm->box_size, ddbox.box_size);
         }
         set_ddbox(dd, bMasterState, cr, ir, state_local->box,
-                  bNStGlobalComm, &top_local->cgs, state_local->x, &ddbox);
+                  bNStGlobalComm, &top_local->cgs, as_rvec_array(state_local->x.data()), &ddbox);
 
         bBoxChanged = TRUE;
         bRedist     = TRUE;
@@ -9414,7 +9432,7 @@ void dd_partition_system(FILE                *fplog,
                                   0, dd->ncg_home,
                                   comm->zones.dens_zone0,
                                   fr->cginfo,
-                                  state_local->x,
+                                  as_rvec_array(state_local->x.data()),
                                   ncg_moved, bRedist ? comm->moved : NULL,
                                   fr->nbv->grp[eintLocal].kernel_type,
                                   fr->nbv->grp[eintLocal].nbat);
@@ -9450,6 +9468,10 @@ void dd_partition_system(FILE                *fplog,
         }
         dd_sort_state(dd, fr->cg_cm, fr, state_local,
                       bResortAll ? -1 : ncg_home_old);
+
+        /* After sorting and compacting we set the correct size */
+        dd_resize_state(state_local, f, dd->nat_home);
+
         /* Rebuild all the indices */
         ga2la_clear(dd->ga2la);
         ncgindex_set = 0;
@@ -9478,7 +9500,7 @@ void dd_partition_system(FILE                *fplog,
 
     /*
        write_dd_pdb("dd_home",step,"dump",top_global,cr,
-                 -1,state_local->x,state_local->box);
+                 -1,as_rvec_array(state_local->x.data()),state_local->box);
      */
 
     wallcycle_sub_start(wcycle, ewcsDD_MAKETOP);
@@ -9491,7 +9513,7 @@ void dd_partition_system(FILE                *fplog,
     dd_make_local_top(dd, &comm->zones, dd->npbcdim, state_local->box,
                       comm->cellsize_min, np,
                       fr,
-                      fr->cutoff_scheme == ecutsGROUP ? fr->cg_cm : state_local->x,
+                      fr->cutoff_scheme == ecutsGROUP ? fr->cg_cm : as_rvec_array(state_local->x.data()),
                       vsite, top_global, top_local);
 
     wallcycle_sub_stop(wcycle, ewcsDD_MAKETOP);
@@ -9533,10 +9555,8 @@ void dd_partition_system(FILE                *fplog,
      * or constraint communication.
      */
     state_local->natoms = comm->nat[ddnatNR-1];
-    if (state_local->natoms > state_local->nalloc)
-    {
-        dd_realloc_state(state_local, f, state_local->natoms);
-    }
+
+    dd_resize_state(state_local, f, state_local->natoms);
 
     if (fr->bF_NoVirSum)
     {
@@ -9626,15 +9646,15 @@ void dd_partition_system(FILE                *fplog,
      * the last vsite construction, we need to communicate the constructing
      * atom coordinates again (for spreading the forces this MD step).
      */
-    dd_move_x_vsites(dd, state_local->box, state_local->x);
+    dd_move_x_vsites(dd, state_local->box, as_rvec_array(state_local->x.data()));
 
     wallcycle_sub_stop(wcycle, ewcsDD_TOPOTHER);
 
     if (comm->nstDDDump > 0 && step % comm->nstDDDump == 0)
     {
-        dd_move_x(dd, state_local->box, state_local->x);
+        dd_move_x(dd, state_local->box, as_rvec_array(state_local->x.data()));
         write_dd_pdb("dd_dump", step, "dump", top_global, cr,
-                     -1, state_local->x, state_local->box);
+                     -1, as_rvec_array(state_local->x.data()), state_local->box);
     }
 
     /* Store the partitioning step */
index 5164004d68a8e9f875d59a1b8267a4beaaa00037..7934b5bdc008768e34c13fe5c867955ab46d4e09 100644 (file)
@@ -81,10 +81,6 @@ struct gmx_domdec_zones_t;
 struct t_commrec;
 struct t_inputrec;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /*! \brief Returns the global topology atom number belonging to local atom index i.
  *
  * This function is intended for writing ASCII output
@@ -211,7 +207,11 @@ void dd_setup_dlb_resource_sharing(struct t_commrec           *cr,
 
 /*! \brief Collects local rvec arrays \p lv to \p v on the master rank */
 void dd_collect_vec(struct gmx_domdec_t *dd,
-                    t_state *state_local, rvec *lv, rvec *v);
+                    t_state *state_local, const PaddedRVecVector *lv, rvec *v);
+
+/*! \brief Collects local rvec arrays \p lv to \p v on the master rank */
+void dd_collect_vec(struct gmx_domdec_t *dd,
+                    t_state *state_local, const PaddedRVecVector *lv, PaddedRVecVector *v);
 
 /*! \brief Collects the local state \p state_local to \p state on the master rank */
 void dd_collect_state(struct gmx_domdec_t *dd,
@@ -269,7 +269,7 @@ void dd_partition_system(FILE                *fplog,
                          const gmx_mtop_t    *top_global,
                          const t_inputrec    *ir,
                          t_state             *state_local,
-                         rvec               **f,
+                         PaddedRVecVector    *f,
                          t_mdatoms           *mdatoms,
                          gmx_localtop_t      *top_local,
                          t_forcerec          *fr,
@@ -402,8 +402,4 @@ void set_ddbox_cr(t_commrec *cr, const ivec *dd_nc,
                   const t_block *cgs, const rvec *x,
                   gmx_ddbox_t *ddbox);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
index 95ba742703c777753d98bf1635dbacf43110f200..452c0abaed9d24c1ade4f299736acbd6ab6d257d 100644 (file)
@@ -249,12 +249,13 @@ void dd_bcastc(gmx_domdec_t *dd, int nbytes, void *src, void *dest)
 #endif
 }
 
-void dd_scatter(gmx_domdec_t gmx_unused *dd, int gmx_unused nbytes, void gmx_unused *src, void *dest)
+void dd_scatter(gmx_domdec_t gmx_unused *dd, int gmx_unused nbytes, const void gmx_unused *src, void *dest)
 {
 #if GMX_MPI
     if (dd->nnodes > 1)
     {
-        MPI_Scatter(src, nbytes, MPI_BYTE,
+        /* Some MPI implementions don't specify const */
+        MPI_Scatter(const_cast<void *>(src), nbytes, MPI_BYTE,
                     dest, nbytes, MPI_BYTE,
                     DDMASTERRANK(dd), dd->mpi_comm_all);
     }
@@ -269,17 +270,18 @@ void dd_scatter(gmx_domdec_t gmx_unused *dd, int gmx_unused nbytes, void gmx_unu
     }
 }
 
-void dd_gather(gmx_domdec_t gmx_unused *dd, int gmx_unused nbytes, void gmx_unused *src, void gmx_unused *dest)
+void dd_gather(gmx_domdec_t gmx_unused *dd, int gmx_unused nbytes, const void gmx_unused *src, void gmx_unused *dest)
 {
 #if GMX_MPI
-    MPI_Gather(src, nbytes, MPI_BYTE,
+    /* Some MPI implementions don't specify const */
+    MPI_Gather(const_cast<void *>(src), nbytes, MPI_BYTE,
                dest, nbytes, MPI_BYTE,
                DDMASTERRANK(dd), dd->mpi_comm_all);
 #endif
 }
 
 void dd_scatterv(gmx_domdec_t gmx_unused *dd,
-                 int gmx_unused *scounts, int gmx_unused *disps, void *sbuf,
+                 int gmx_unused *scounts, int gmx_unused *disps, const void *sbuf,
                  int rcount, void *rbuf)
 {
 #if GMX_MPI
@@ -292,7 +294,8 @@ void dd_scatterv(gmx_domdec_t gmx_unused *dd,
             /* MPI does not allow NULL pointers */
             rbuf = &dum;
         }
-        MPI_Scatterv(sbuf, scounts, disps, MPI_BYTE,
+        /* Some MPI implementions don't specify const */
+        MPI_Scatterv(const_cast<void *>(sbuf), scounts, disps, MPI_BYTE,
                      rbuf, rcount, MPI_BYTE,
                      DDMASTERRANK(dd), dd->mpi_comm_all);
     }
@@ -308,7 +311,7 @@ void dd_scatterv(gmx_domdec_t gmx_unused *dd,
 }
 
 void dd_gatherv(gmx_domdec_t gmx_unused *dd,
-                int gmx_unused scount, void gmx_unused *sbuf,
+                int gmx_unused scount, const void gmx_unused *sbuf,
                 int gmx_unused *rcounts, int gmx_unused *disps, void gmx_unused *rbuf)
 {
 #if GMX_MPI
@@ -319,7 +322,8 @@ void dd_gatherv(gmx_domdec_t gmx_unused *dd,
         /* MPI does not allow NULL pointers */
         sbuf = &dum;
     }
-    MPI_Gatherv(sbuf, scount, MPI_BYTE,
+    /* Some MPI implementions don't specify const */
+    MPI_Gatherv(const_cast<void *>(sbuf), scount, MPI_BYTE,
                 rbuf, rcounts, disps, MPI_BYTE,
                 DDMASTERRANK(dd), dd->mpi_comm_all);
 #endif
index faf224c47089c50d31ec61acebbf699b7266bf32..7223336a8ec9220c4fdefe9589f1d11d2b2f561a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2008,2009,2010,2012,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2008,2009,2010,2012,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.
@@ -123,11 +123,11 @@ dd_bcastc(struct gmx_domdec_t *dd, int nbytes, void *src, void *dest);
 
 /*! \brief Scatters \p nbytes from \p src on \p DDMASTERRANK to all PP ranks, received in \p dest */
 void
-dd_scatter(struct gmx_domdec_t *dd, int nbytes, void *src, void *dest);
+dd_scatter(struct gmx_domdec_t *dd, int nbytes, const void *src, void *dest);
 
 /*! \brief Gathers \p nbytes from \p src on all PP ranks, received in \p dest on \p DDMASTERRANK */
 void
-dd_gather(struct gmx_domdec_t *dd, int nbytes, void *src, void *dest);
+dd_gather(struct gmx_domdec_t *dd, int nbytes, const void *src, void *dest);
 
 /*! \brief Scatters \p scounts bytes from \p src on \p DDMASTERRANK to all PP ranks, receiving \p rcount bytes in \p dest.
  *
@@ -135,7 +135,7 @@ dd_gather(struct gmx_domdec_t *dd, int nbytes, void *src, void *dest);
  * If rcount==0, rbuf is allowed to be NULL */
 void
 dd_scatterv(struct gmx_domdec_t *dd,
-            int *scounts, int *disps, void *sbuf,
+            int *scounts, int *disps, const void *sbuf,
             int rcount, void *rbuf);
 
 /*! \brief Gathers \p rcount bytes from \p src on all PP ranks, received in \p scounts bytes in \p dest on \p DDMASTERRANK.
@@ -145,7 +145,7 @@ dd_scatterv(struct gmx_domdec_t *dd,
  * If scount==0, sbuf is allowed to be NULL */
 void
 dd_gatherv(struct gmx_domdec_t *dd,
-           int scount, void *sbuf,
+           int scount, const void *sbuf,
            int *rcounts, int *disps, void *rbuf);
 
 #endif
index d34ec487d85b8309fc325280fc24a7656c07fe53..28666053ba6c7b70bd5f29d0656ff304bf42ae17 100644 (file)
@@ -419,7 +419,7 @@ void dd_print_missing_interactions(FILE *fplog, t_commrec *cr,
 
     print_missing_interactions_atoms(fplog, cr, top_global, &top_local->idef);
     write_dd_pdb("dd_dump_err", 0, "dump", top_global, cr,
-                 -1, state_local->x, state_local->box);
+                 -1, as_rvec_array(state_local->x.data()), state_local->box);
 
     std::string errorMessage;
 
index f5ac996264a8e970d39e55393a559f583126c6c5..5dc2eda04438050fbd3e5bea7e976c205b392067 100644 (file)
@@ -60,6 +60,7 @@
 #include "gromacs/gmxlib/network.h"
 #include "gromacs/math/vec.h"
 #include "gromacs/math/vecdump.h"
+#include "gromacs/math/vectypes.h"
 #include "gromacs/mdtypes/commrec.h"
 #include "gromacs/mdtypes/df_history.h"
 #include "gromacs/mdtypes/energyhistory.h"
@@ -468,6 +469,28 @@ static int do_cpte_reals(XDR *xd, int cptp, int ecpt, int sflags,
     return do_cpte_reals_low(xd, cptp, ecpt, sflags, n, NULL, v, list, ecprREAL);
 }
 
+/* This function stores n along with the reals for reading,
+ * but on reading it assumes that n matches the value in the checkpoint file,
+ * a fatal error is generated when this is not the case.
+ */
+static int do_cpte_reals(XDR *xd, int cptp, int ecpt, int sflags,
+                         int n, std::vector<real> *v, FILE *list)
+{
+    real *v_real;
+    if (list == NULL && (sflags & (1 << ecpt)))
+    {
+        /* Resizes on read, on write the size should already be n */
+        v->resize(n);
+        v_real = v->data();
+    }
+    else
+    {
+        v_real = NULL;
+    }
+
+    return do_cpte_reals_low(xd, cptp, ecpt, sflags, n, NULL, &v_real, list, ecprREAL);
+}
+
 /* This function does the same as do_cpte_reals,
  * except that on reading it ignores the passed value of *n
  * and stored the value read from the checkpoint file in *n.
@@ -612,6 +635,24 @@ static int do_cpte_doubles(XDR *xd, int cptp, int ecpt, int sflags,
     return 0;
 }
 
+static int do_cpte_doubles(XDR *xd, int cptp, int ecpt, int sflags,
+                           int n, std::vector<double> *v, FILE *list)
+{
+    double *v_double;
+    if (list == NULL && (sflags & (1 << ecpt)))
+    {
+        /* Resizes on read, on write the size should already be n */
+        v->resize(n);
+        v_double = v->data();
+    }
+    else
+    {
+        v_double = NULL;
+    }
+
+    return do_cpte_doubles(xd, cptp, ecpt, sflags, n, &v_double, list);
+}
+
 static int do_cpte_double(XDR *xd, int cptp, int ecpt, int sflags,
                           double *r, FILE *list)
 {
@@ -620,10 +661,25 @@ static int do_cpte_double(XDR *xd, int cptp, int ecpt, int sflags,
 
 
 static int do_cpte_rvecs(XDR *xd, int cptp, int ecpt, int sflags,
-                         int n, rvec **v, FILE *list)
+                         int n, std::vector<gmx::RVec> *v, FILE *list)
 {
+    rvec *v_rvec;
+
+    if (list == NULL && (sflags & (1 << ecpt)))
+    {
+        /* We resize the vector here to avoid pointer reallocation in
+         * do_cpte_reals_low. Note the we allocate 1 element extra for SIMD.
+         */
+        v->resize(n + 1);
+        v_rvec = as_rvec_array(v->data());
+    }
+    else
+    {
+        v_rvec = NULL;
+    }
+
     return do_cpte_reals_low(xd, cptp, ecpt, sflags,
-                             n*DIM, NULL, (real **)v, list, ecprRVEC);
+                             n*DIM, NULL, (real **)(&v_rvec), list, ecprRVEC);
 }
 
 static int do_cpte_matrix(XDR *xd, int cptp, int ecpt, int sflags,
@@ -2478,14 +2534,12 @@ void read_checkpoint_trxframe(t_fileio *fp, t_trxframe *fr)
     fr->bX         = (state.flags & (1<<estX));
     if (fr->bX)
     {
-        fr->x     = state.x;
-        state.x   = NULL;
+        fr->x   = getRvecArrayFromPaddedRVecVector(&state.x, state.natoms);
     }
     fr->bV      = (state.flags & (1<<estV));
     if (fr->bV)
     {
-        fr->v     = state.v;
-        state.v   = NULL;
+        fr->v   = getRvecArrayFromPaddedRVecVector(&state.v, state.natoms);
     }
     fr->bF      = FALSE;
     fr->bBox    = (state.flags & (1<<estBOX));
@@ -2493,7 +2547,6 @@ void read_checkpoint_trxframe(t_fileio *fp, t_trxframe *fr)
     {
         copy_mat(state.box, fr->box);
     }
-    done_state(&state);
 }
 
 void list_checkpoint(const char *fn, FILE *out)
@@ -2571,8 +2624,6 @@ void list_checkpoint(const char *fn, FILE *out)
     {
         gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
     }
-
-    done_state(&state);
 }
 
 /* This routine cannot print tons of data, since it is called before the log file is opened. */
@@ -2594,5 +2645,4 @@ read_checkpoint_simulation_part_and_filenames(t_fileio             *fp,
     {
         gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of disk space?");
     }
-    done_state(&state);
 }
index 0829751582b78ff38458ee25bd1a72c8ec4bbd70..dce979e3c4081d4b20153246637b481da79a0aad 100644 (file)
@@ -3083,29 +3083,34 @@ static void do_tpxheader(t_fileio *fio, gmx_bool bRead, t_tpxheader *tpx,
 }
 
 static int do_tpx(t_fileio *fio, gmx_bool bRead,
-                  t_inputrec *ir, t_state *state, gmx_mtop_t *mtop,
-                  gmx_bool bXVallocated)
+                  t_inputrec *ir, t_state *state, rvec *x, rvec *v,
+                  gmx_mtop_t *mtop)
 {
     t_tpxheader     tpx;
     gmx_mtop_t      dum_top;
     gmx_bool        TopOnlyOK;
-    rvec           *xptr, *vptr;
     int             ePBC;
     gmx_bool        bPeriodicMols;
 
     if (!bRead)
     {
+        GMX_RELEASE_ASSERT(x == NULL && v == NULL, "Passing separate x and v pointers to do_tpx() is not supported when writing");
+
         tpx.natoms    = state->natoms;
         tpx.ngtc      = state->ngtc;
         tpx.fep_state = state->fep_state;
         tpx.lambda    = state->lambda[efptFEP];
         tpx.bIr       = (ir       != NULL);
         tpx.bTop      = (mtop     != NULL);
-        tpx.bX        = (state->x != NULL);
-        tpx.bV        = (state->v != NULL);
+        tpx.bX        = (state->flags & (1 << estX));
+        tpx.bV        = (state->flags & (1 << estV));
         tpx.bF        = FALSE;
         tpx.bBox      = TRUE;
     }
+    else
+    {
+        GMX_RELEASE_ASSERT(!(x == NULL && v != NULL), "Passing x==NULL and v!=NULL is not supported");
+    }
 
     TopOnlyOK = (ir == NULL);
 
@@ -3116,15 +3121,9 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
     if (bRead)
     {
         state->flags  = 0;
-        if (bXVallocated)
+        if (x != NULL)
         {
-            xptr = state->x;
-            vptr = state->v;
             init_state(state, 0, tpx.ngtc, 0, 0, 0);
-            state->natoms = tpx.natoms;
-            state->nalloc = tpx.natoms;
-            state->x      = xptr;
-            state->v      = vptr;
         }
         else
         {
@@ -3132,6 +3131,12 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
         }
     }
 
+    if (x == NULL)
+    {
+        x = as_rvec_array(state->x.data());
+        v = as_rvec_array(state->v.data());
+    }
+
 #define do_test(fio, b, p) if (bRead && (p != NULL) && !b) gmx_fatal(FARGS, "No %s in %s",#p, gmx_fio_getname(fio))
 
     do_test(fio, tpx.bBox, state->box);
@@ -3181,24 +3186,24 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
             done_mtop(&dum_top, TRUE);
         }
     }
-    do_test(fio, tpx.bX, state->x);
+    do_test(fio, tpx.bX, x);
     if (tpx.bX)
     {
         if (bRead)
         {
             state->flags |= (1<<estX);
         }
-        gmx_fio_ndo_rvec(fio, state->x, state->natoms);
+        gmx_fio_ndo_rvec(fio, x, tpx.natoms);
     }
 
-    do_test(fio, tpx.bV, state->v);
+    do_test(fio, tpx.bV, v);
     if (tpx.bV)
     {
         if (bRead)
         {
             state->flags |= (1<<estV);
         }
-        gmx_fio_ndo_rvec(fio, state->v, state->natoms);
+        gmx_fio_ndo_rvec(fio, v, tpx.natoms);
     }
 
     // No need to run do_test when the last argument is NULL
@@ -3206,7 +3211,7 @@ static int do_tpx(t_fileio *fio, gmx_bool bRead,
     {
         rvec *dummyForces;
         snew(dummyForces, state->natoms);
-        gmx_fio_ndo_rvec(fio, dummyForces, state->natoms);
+        gmx_fio_ndo_rvec(fio, dummyForces, tpx.natoms);
         sfree(dummyForces);
     }
 
@@ -3323,8 +3328,8 @@ void write_tpx_state(const char *fn,
     fio = open_tpx(fn, "w");
     do_tpx(fio, FALSE,
            const_cast<t_inputrec *>(ir),
-           const_cast<t_state *>(state),
-           const_cast<gmx_mtop_t *>(mtop), FALSE);
+           const_cast<t_state *>(state), NULL, NULL,
+           const_cast<gmx_mtop_t *>(mtop));
     close_tpx(fio);
 }
 
@@ -3334,7 +3339,7 @@ void read_tpx_state(const char *fn,
     t_fileio *fio;
 
     fio = open_tpx(fn, "r");
-    do_tpx(fio, TRUE, ir, state, mtop, FALSE);
+    do_tpx(fio, TRUE, ir, state, NULL, NULL, mtop);
     close_tpx(fio);
 }
 
@@ -3343,22 +3348,17 @@ int read_tpx(const char *fn,
              rvec *x, rvec *v, gmx_mtop_t *mtop)
 {
     t_fileio *fio;
-    t_state   state;
+    t_state   state {};
     int       ePBC;
 
-    state.x = x;
-    state.v = v;
     fio     = open_tpx(fn, "r");
-    ePBC    = do_tpx(fio, TRUE, ir, &state, mtop, TRUE);
+    ePBC    = do_tpx(fio, TRUE, ir, &state, x, v, mtop);
     close_tpx(fio);
-    *natoms = state.natoms;
+    *natoms = mtop->natoms;
     if (box)
     {
         copy_mat(state.box, box);
     }
-    state.x = NULL;
-    state.v = NULL;
-    done_state(&state);
 
     return ePBC;
 }
index 1fafd298bbf769d74f2636dedf22bbe8247878c2..4025d73b7865b80fa7dceaa79b21db7782a8f96d 100644 (file)
@@ -946,7 +946,7 @@ static void estimate_PME_error(t_inputinfo *info, const t_state *state,
     }
 
     /* Prepare an x and q array with only the charged atoms */
-    ncharges = prepare_x_q(&q, &x, mtop, state->x, cr);
+    ncharges = prepare_x_q(&q, &x, mtop, as_rvec_array(state->x.data()), cr);
     if (MASTER(cr))
     {
         calc_q2all(mtop, &(info->q2all), &(info->q2allnr));
index 6a3dcbbee4a0916e87d95cf4b9cc883a9086bbf1..ca768804ea8738da69b7b4074fe985482cb3932c 100644 (file)
@@ -603,16 +603,38 @@ new_status(const char *topfile, const char *topppfile, const char *confin,
     }
 
     t_topology *conftop;
+    rvec       *x = NULL;
+    rvec       *v = NULL;
     snew(conftop, 1);
     init_state(state, 0, 0, 0, 0, 0);
-    read_tps_conf(confin, conftop, NULL, &state->x, &state->v, state->box, FALSE);
-    state->natoms = state->nalloc = conftop->atoms.nr;
+    read_tps_conf(confin, conftop, NULL, &x, &v, state->box, FALSE);
+    state->natoms = conftop->atoms.nr;
     if (state->natoms != sys->natoms)
     {
         gmx_fatal(FARGS, "number of coordinates in coordinate file (%s, %d)\n"
                   "             does not match topology (%s, %d)",
                   confin, state->natoms, topfile, sys->natoms);
     }
+    /* It would be nice to get rid of the copies below, but we don't know
+     * a priori if the number of atoms in confin matches what we expect.
+     */
+    state->flags |= (1 << estX);
+    state->x.resize(state->natoms);
+    for (int i = 0; i < state->natoms; i++)
+    {
+        copy_rvec(x[i], state->x[i]);
+    }
+    sfree(x);
+    if (v != NULL)
+    {
+        state->flags |= (1 << estV);
+        state->v.resize(state->natoms);
+        for (int i = 0; i < state->natoms; i++)
+        {
+            copy_rvec(v[i], state->v[i]);
+        }
+        sfree(v);
+    }
     /* This call fixes the box shape for runs with pressure scaling */
     set_box_rel(ir, state);
 
@@ -662,9 +684,10 @@ new_status(const char *topfile, const char *topppfile, const char *confin,
             opts->seed = static_cast<int>(gmx::makeRandomSeed());
             fprintf(stderr, "Setting gen_seed to %d\n", opts->seed);
         }
-        maxwell_speed(opts->tempi, opts->seed, sys, state->v);
+        state->flags |= (1 << estV);
+        maxwell_speed(opts->tempi, opts->seed, sys, as_rvec_array(state->v.data()));
 
-        stop_cm(stdout, state->natoms, mass, state->x, state->v);
+        stop_cm(stdout, state->natoms, mass, as_rvec_array(state->x.data()), as_rvec_array(state->v.data()));
         sfree(mass);
     }
 
@@ -1576,7 +1599,6 @@ int gmx_grompp(int argc, char *argv[])
     t_inputrec        *ir;
     int                nvsite, comb, mt;
     t_params          *plist;
-    t_state           *state;
     matrix             box;
     real               fudgeQQ;
     double             reppow;
@@ -1691,9 +1713,10 @@ int gmx_grompp(int argc, char *argv[])
     {
         gmx_fatal(FARGS, "%s does not exist", fn);
     }
-    snew(state, 1);
+
+    t_state state {};
     new_status(fn, opt2fn_null("-pp", NFILE, fnm), opt2fn("-c", NFILE, fnm),
-               opts, ir, bZero, bGenVel, bVerbose, state,
+               opts, ir, bZero, bGenVel, bVerbose, &state,
                atype, sys, &nmi, &mi, &intermolecular_interactions,
                plist, &comb, &reppow, &fudgeQQ,
                opts->bMorse,
@@ -1870,7 +1893,7 @@ int gmx_grompp(int argc, char *argv[])
     /* Check velocity for virtual sites and shells */
     if (bGenVel)
     {
-        check_vel(sys, state->v);
+        check_vel(sys, as_rvec_array(state.v.data()));
     }
 
     /* check for shells and inpurecs */
@@ -1920,7 +1943,7 @@ int gmx_grompp(int argc, char *argv[])
                 }
                 else
                 {
-                    buffer_temp = calc_temp(sys, ir, state->v);
+                    buffer_temp = calc_temp(sys, ir, as_rvec_array(state.v.data()));
                 }
                 if (buffer_temp > 0)
                 {
@@ -1975,13 +1998,13 @@ int gmx_grompp(int argc, char *argv[])
                     }
                 }
 
-                set_verlet_buffer(sys, ir, buffer_temp, state->box, wi);
+                set_verlet_buffer(sys, ir, buffer_temp, state.box, wi);
             }
         }
     }
 
     /* Init the temperature coupling state */
-    init_gtc_state(state, ir->opts.ngtc, 0, ir->opts.nhchainlength); /* need to add nnhpres here? */
+    init_gtc_state(&state, ir->opts.ngtc, 0, ir->opts.nhchainlength); /* need to add nnhpres here? */
 
     if (bVerbose)
     {
@@ -2021,24 +2044,24 @@ int gmx_grompp(int argc, char *argv[])
             fprintf(stderr, "getting data from old trajectory ...\n");
         }
         cont_status(ftp2fn(efTRN, NFILE, fnm), ftp2fn_null(efEDR, NFILE, fnm),
-                    bNeedVel, bGenVel, fr_time, ir, state, sys, oenv);
+                    bNeedVel, bGenVel, fr_time, ir, &state, sys, oenv);
     }
 
     if (ir->ePBC == epbcXY && ir->nwall != 2)
     {
-        clear_rvec(state->box[ZZ]);
+        clear_rvec(state.box[ZZ]);
     }
 
     if (ir->cutoff_scheme != ecutsVERLET && ir->rlist > 0)
     {
         set_warning_line(wi, mdparin, -1);
-        check_chargegroup_radii(sys, ir, state->x, wi);
+        check_chargegroup_radii(sys, ir, as_rvec_array(state.x.data()), wi);
     }
 
     if (EEL_FULL(ir->coulombtype) || EVDW_PME(ir->vdwtype))
     {
         /* Calculate the optimal grid dimensions */
-        copy_mat(state->box, box);
+        copy_mat(state.box, box);
         if (ir->ePBC == epbcXY && ir->nwall == 2)
         {
             svmul(ir->wall_ewald_zfac, box[ZZ], box[ZZ]);
@@ -2062,13 +2085,13 @@ int gmx_grompp(int argc, char *argv[])
        potentially conflict if not handled correctly. */
     if (ir->efep != efepNO)
     {
-        state->fep_state = ir->fepvals->init_fep_state;
+        state.fep_state = ir->fepvals->init_fep_state;
         for (i = 0; i < efptNR; i++)
         {
             /* init_lambda trumps state definitions*/
             if (ir->fepvals->init_lambda >= 0)
             {
-                state->lambda[i] = ir->fepvals->init_lambda;
+                state.lambda[i] = ir->fepvals->init_lambda;
             }
             else
             {
@@ -2078,7 +2101,7 @@ int gmx_grompp(int argc, char *argv[])
                 }
                 else
                 {
-                    state->lambda[i] = ir->fepvals->all_lambda[i][state->fep_state];
+                    state.lambda[i] = ir->fepvals->all_lambda[i][state.fep_state];
                 }
             }
         }
@@ -2088,7 +2111,7 @@ int gmx_grompp(int argc, char *argv[])
 
     if (ir->bPull)
     {
-        pull = set_pull_init(ir, sys, state->x, state->box, state->lambda[efptMASS], oenv);
+        pull = set_pull_init(ir, sys, as_rvec_array(state.x.data()), state.box, state.lambda[efptMASS], oenv);
     }
 
     /* Modules that supply external potential for pull coordinates
@@ -2103,7 +2126,7 @@ int gmx_grompp(int argc, char *argv[])
 
     if (ir->bRot)
     {
-        set_reference_positions(ir->rot, state->x, state->box,
+        set_reference_positions(ir->rot, as_rvec_array(state.x.data()), state.box,
                                 opt2fn("-ref", NFILE, fnm), opt2bSet("-ref", NFILE, fnm),
                                 wi);
     }
@@ -2112,7 +2135,7 @@ int gmx_grompp(int argc, char *argv[])
 
     if (EEL_PME(ir->coulombtype))
     {
-        float ratio = pme_load_estimate(sys, ir, state->box);
+        float ratio = pme_load_estimate(sys, ir, state.box);
         fprintf(stderr, "Estimate for the relative computational load of the PME mesh part: %.2f\n", ratio);
         /* With free energy we might need to do PME both for the A and B state
          * charges. This will double the cost, but the optimal performance will
@@ -2154,13 +2177,11 @@ int gmx_grompp(int argc, char *argv[])
     }
 
     done_warning(wi, FARGS);
-    write_tpx_state(ftp2fn(efTPR, NFILE, fnm), ir, state, sys);
+    write_tpx_state(ftp2fn(efTPR, NFILE, fnm), ir, &state, sys);
 
     /* Output IMD group, if bIMD is TRUE */
-    write_IMDgroup_to_file(ir->bIMD, ir, state, sys, NFILE, fnm);
+    write_IMDgroup_to_file(ir->bIMD, ir, &state, sys, NFILE, fnm);
 
-    done_state(state);
-    sfree(state);
     done_atomtype(atype);
     done_mtop(sys, TRUE);
     done_inputrec_strings();
index 2908c7b9f285834356d75929741e44507b1ce7aa..763b030ca6723951c398a47d7059f0b740ea4b16 100644 (file)
@@ -442,7 +442,7 @@ void write_IMDgroup_to_file(gmx_bool bIMD, t_inputrec *ir, t_state *state,
     {
         IMDatoms = gmx_mtop_global_atoms(sys);
         write_sto_conf_indexed(opt2fn("-imd", nfile, fnm), "IMDgroup", &IMDatoms,
-                               state->x, state->v, ir->ePBC, state->box, ir->imd->nat, ir->imd->ind);
+                               as_rvec_array(state->x.data()), as_rvec_array(state->v.data()), ir->ePBC, state->box, ir->imd->nat, ir->imd->ind);
     }
 }
 
index ba50858af25a4f320017e574d505c25e03b311dc..631ee3587da2a65ca8495a3a4186cb371b876bb9 100644 (file)
 #define   block_bc(cr,   d) gmx_bcast(     sizeof(d),     &(d), (cr))
 #define  nblock_bc(cr, nr, d) { gmx_bcast((nr)*sizeof((d)[0]), (d), (cr)); }
 #define    snew_bc(cr, d, nr) { if (!MASTER(cr)) {snew((d), (nr)); }}
-/* Dirty macro with bAlloc not as an argument */
-#define nblock_abc(cr, nr, d) { if (bAlloc) {snew((d), (nr)); } nblock_bc(cr, (nr), (d)); }
+
+#if !GMX_DOUBLE
+static void nblock_abc(const t_commrec *cr, int numElements, real **v)
+{
+    if (!MASTER(cr))
+    {
+        snew(*v, numElements);
+    }
+    nblock_bc(cr, numElements, *v);
+}
+#endif
+
+static void nblock_abc(const t_commrec *cr, int numElements, double **v)
+{
+    if (!MASTER(cr))
+    {
+        snew(*v, numElements);
+    }
+    nblock_bc(cr, numElements, *v);
+}
+
+static void nblock_abc(const t_commrec *cr, int numElements, std::vector<double> *v)
+{
+    if (!MASTER(cr))
+    {
+        v->resize(numElements);
+    }
+    gmx_bcast(numElements*sizeof(double), v->data(), cr);
+}
 
 static void bc_cstring(const t_commrec *cr, char **s)
 {
@@ -259,10 +286,15 @@ static void bc_groups(const t_commrec *cr, t_symtab *symtab,
     }
 }
 
+static void bcastPaddedRVecVector(const t_commrec *cr, PaddedRVecVector *v, unsigned int n)
+{
+    (*v).resize(n + 1);
+    nblock_bc(cr, n, as_rvec_array(v->data()));
+}
+
 void bcast_state(const t_commrec *cr, t_state *state)
 {
     int      i, nnht, nnhtp;
-    gmx_bool bAlloc;
 
     if (!PAR(cr) || (cr->nnodes - cr->npmenodes <= 1))
     {
@@ -276,10 +308,7 @@ void bcast_state(const t_commrec *cr, t_state *state)
     block_bc(cr, state->nnhpres);
     block_bc(cr, state->nhchainlength);
     block_bc(cr, state->flags);
-    if (state->lambda == NULL)
-    {
-        snew_bc(cr, state->lambda, efptNR)
-    }
+    state->lambda.resize(efptNR);
 
     if (cr->dd)
     {
@@ -292,21 +321,13 @@ void bcast_state(const t_commrec *cr, t_state *state)
     nnht  = (state->ngtc)*(state->nhchainlength);
     nnhtp = (state->nnhpres)*(state->nhchainlength);
 
-    /* We still need to allocate the arrays in state for non-master
-     * ranks, which is done (implicitly via bAlloc) in the dirty,
-     * dirty nblock_abc macro. */
-    bAlloc = !MASTER(cr);
-    if (bAlloc)
-    {
-        state->nalloc = state->natoms;
-    }
     for (i = 0; i < estNR; i++)
     {
         if (state->flags & (1<<i))
         {
             switch (i)
             {
-                case estLAMBDA:  nblock_bc(cr, efptNR, state->lambda); break;
+                case estLAMBDA:  nblock_bc(cr, efptNR, state->lambda.data()); break;
                 case estFEPSTATE: block_bc(cr, state->fep_state); break;
                 case estBOX:     block_bc(cr, state->box); break;
                 case estBOX_REL: block_bc(cr, state->box_rel); break;
@@ -314,25 +335,25 @@ void bcast_state(const t_commrec *cr, t_state *state)
                 case estPRES_PREV: block_bc(cr, state->pres_prev); break;
                 case estSVIR_PREV: block_bc(cr, state->svir_prev); break;
                 case estFVIR_PREV: block_bc(cr, state->fvir_prev); break;
-                case estNH_XI:   nblock_abc(cr, nnht, state->nosehoover_xi); break;
-                case estNH_VXI:  nblock_abc(cr, nnht, state->nosehoover_vxi); break;
-                case estNHPRES_XI:   nblock_abc(cr, nnhtp, state->nhpres_xi); break;
-                case estNHPRES_VXI:  nblock_abc(cr, nnhtp, state->nhpres_vxi); break;
-                case estTC_INT:  nblock_abc(cr, state->ngtc, state->therm_integral); break;
+                case estNH_XI:   nblock_abc(cr, nnht, &state->nosehoover_xi); break;
+                case estNH_VXI:  nblock_abc(cr, nnht, &state->nosehoover_vxi); break;
+                case estNHPRES_XI:   nblock_abc(cr, nnhtp, &state->nhpres_xi); break;
+                case estNHPRES_VXI:  nblock_abc(cr, nnhtp, &state->nhpres_vxi); break;
+                case estTC_INT:  nblock_abc(cr, state->ngtc, &state->therm_integral); break;
                 case estVETA:    block_bc(cr, state->veta); break;
                 case estVOL0:    block_bc(cr, state->vol0); break;
-                case estX:       nblock_abc(cr, state->natoms, state->x); break;
-                case estV:       nblock_abc(cr, state->natoms, state->v); break;
-                case estCGP:     nblock_abc(cr, state->natoms, state->cg_p); break;
+                case estX:       bcastPaddedRVecVector(cr, &state->x, state->natoms);
+                case estV:       bcastPaddedRVecVector(cr, &state->v, state->natoms);
+                case estCGP:     bcastPaddedRVecVector(cr, &state->cg_p, state->natoms);
                 case estDISRE_INITF: block_bc(cr, state->hist.disre_initf); break;
                 case estDISRE_RM3TAV:
                     block_bc(cr, state->hist.ndisrepairs);
-                    nblock_abc(cr, state->hist.ndisrepairs, state->hist.disre_rm3tav);
+                    nblock_abc(cr, state->hist.ndisrepairs, &state->hist.disre_rm3tav);
                     break;
                 case estORIRE_INITF: block_bc(cr, state->hist.orire_initf); break;
                 case estORIRE_DTAV:
                     block_bc(cr, state->hist.norire_Dtav);
-                    nblock_abc(cr, state->hist.norire_Dtav, state->hist.orire_Dtav);
+                    nblock_abc(cr, state->hist.norire_Dtav, &state->hist.orire_Dtav);
                     break;
                 default:
                     gmx_fatal(FARGS,
index c422a4bf1fd2fc9144e161ef0cf38ac2da8938c1..5ed9837feaf0adef94304e07783cec665c3f3945 100644 (file)
@@ -1302,7 +1302,7 @@ gmx_constr_t init_constraints(FILE *fplog,
     constr->ed = ed;
     if (ed != NULL || state->edsamstate != NULL)
     {
-        init_edsam(mtop, ir, cr, ed, state->x, state->box, state->edsamstate);
+        init_edsam(mtop, ir, cr, ed, as_rvec_array(state->x.data()), state->box, state->edsamstate);
     }
 
     constr->warn_mtop = mtop;
index abafb2b8b050576fceadd4c939dbdae57904b9ff..465709a1b73ad745678486518d48571eb0a967a7 100644 (file)
@@ -822,32 +822,6 @@ void nosehoover_tcoupl(t_grpopts *opts, gmx_ekindata_t *ekind, real dt,
     }
 }
 
-t_state *init_bufstate(const t_state *template_state)
-{
-    t_state *state;
-    int      nc = template_state->nhchainlength;
-    snew(state, 1);
-    snew(state->nosehoover_xi, nc*template_state->ngtc);
-    snew(state->nosehoover_vxi, nc*template_state->ngtc);
-    snew(state->therm_integral, template_state->ngtc);
-    snew(state->nhpres_xi, nc*template_state->nnhpres);
-    snew(state->nhpres_vxi, nc*template_state->nnhpres);
-
-    return state;
-}
-
-void destroy_bufstate(t_state *state)
-{
-    sfree(state->x);
-    sfree(state->v);
-    sfree(state->nosehoover_xi);
-    sfree(state->nosehoover_vxi);
-    sfree(state->therm_integral);
-    sfree(state->nhpres_xi);
-    sfree(state->nhpres_vxi);
-    sfree(state);
-}
-
 void trotter_update(t_inputrec *ir, gmx_int64_t step, gmx_ekindata_t *ekind,
                     gmx_enerdata_t *enerd, t_state *state,
                     tensor vir, t_mdatoms *md,
@@ -917,13 +891,13 @@ void trotter_update(t_inputrec *ir, gmx_int64_t step, gmx_ekindata_t *ekind,
                 break;
             case etrtBARONHC:
             case etrtBARONHC2:
-                NHC_trotter(opts, state->nnhpres, ekind, dt, state->nhpres_xi,
-                            state->nhpres_vxi, NULL, &(state->veta), MassQ, FALSE);
+                NHC_trotter(opts, state->nnhpres, ekind, dt, state->nhpres_xi.data(),
+                            state->nhpres_vxi.data(), NULL, &(state->veta), MassQ, FALSE);
                 break;
             case etrtNHC:
             case etrtNHC2:
-                NHC_trotter(opts, opts->ngtc, ekind, dt, state->nosehoover_xi,
-                            state->nosehoover_vxi, scalefac, NULL, MassQ, (ir->eI == eiVV));
+                NHC_trotter(opts, opts->ngtc, ekind, dt, state->nosehoover_xi.data(),
+                            state->nosehoover_vxi.data(), scalefac, NULL, MassQ, (ir->eI == eiVV));
                 /* need to rescale the kinetic energies and velocities here.  Could
                    scale the velocities later, but we need them scaled in order to
                    produce the correct outputs, so we'll scale them here. */
index 30c0ed7ecf18cb2e41d7034573105ebf8781802c..d2fa3edfcc87f5dcc53f0a305310de03e0cbb2c3 100644 (file)
@@ -732,7 +732,7 @@ void sum_epot(gmx_grppairener_t *grpp, real *epot)
     }
 }
 
-void sum_dhdl(gmx_enerdata_t *enerd, real *lambda, t_lambda *fepvals)
+void sum_dhdl(gmx_enerdata_t *enerd, const std::vector<real> *lambda, t_lambda *fepvals)
 {
     int    i, j, index;
     double dlam;
@@ -814,7 +814,7 @@ void sum_dhdl(gmx_enerdata_t *enerd, real *lambda, t_lambda *fepvals)
         for (j = 0; j < efptNR; j++)
         {
             /* Note that this loop is over all dhdl components, not just the separated ones */
-            dlam = (fepvals->all_lambda[j][i]-lambda[j]);
+            dlam = (fepvals->all_lambda[j][i] - (*lambda)[j]);
             enerd->enerpart_lambda[i+1] += dlam*enerd->dvdl_lin[j];
             if (debug)
             {
index 4d145f582b5988b90f0bda062d66316fed598c0f..b582dc1ea4abb0542b416b67a0e2a81918384f1a 100644 (file)
@@ -41,6 +41,7 @@
 #include "gromacs/mdlib/vsite.h"
 #include "gromacs/mdtypes/fcdata.h"
 #include "gromacs/mdtypes/forcerec.h"
+#include "gromacs/mdtypes/state.h"
 #include "gromacs/timing/wallcycle.h"
 
 struct gmx_edsam;
@@ -149,7 +150,7 @@ void reset_enerdata(gmx_enerdata_t *enerd);
 void sum_epot(gmx_grppairener_t *grpp, real *epot);
 /* Locally sum the non-bonded potential energy terms */
 
-void sum_dhdl(gmx_enerdata_t *enerd, real *lambda, t_lambda *fepvals);
+void sum_dhdl(gmx_enerdata_t *enerd, const std::vector<real> *lambda, t_lambda *fepvals);
 /* Sum the free energy contributions */
 
 /* Compute the average C6 and C12 params for LJ corrections */
@@ -161,12 +162,12 @@ void do_force(FILE *log, t_commrec *cr,
               gmx_int64_t step, struct t_nrnb *nrnb, gmx_wallcycle_t wcycle,
               gmx_localtop_t *top,
               gmx_groups_t *groups,
-              matrix box, rvec x[], history_t *hist,
-              rvec f[],
+              matrix box, PaddedRVecVector *coordinates, history_t *hist,
+              PaddedRVecVector *force,
               tensor vir_force,
               t_mdatoms *mdatoms,
               gmx_enerdata_t *enerd, t_fcdata *fcd,
-              real *lambda, struct t_graph *graph,
+              std::vector<real> *lambda, struct t_graph *graph,
               t_forcerec *fr,
               gmx_vsite_t *vsite, rvec mu_tot,
               double t, FILE *field, struct gmx_edsam *ed,
index 412aa9e7787d8c87889c2efd5b8093b607b34cb3..f4dbde6b062a9d1e943f66c8a4155a58e4897507 100644 (file)
@@ -146,72 +146,6 @@ int multisim_min(const gmx_multisim_t *ms, int nmin, int n)
     return nmin;
 }
 
-void copy_coupling_state(t_state *statea, t_state *stateb,
-                         gmx_ekindata_t *ekinda, gmx_ekindata_t *ekindb, t_grpopts* opts)
-{
-
-    /* MRS note -- might be able to get rid of some of the arguments.  Look over it when it's all debugged */
-
-    int i, j, nc;
-
-    /* Make sure we have enough space for x and v */
-    if (statea->nalloc > stateb->nalloc)
-    {
-        stateb->nalloc = statea->nalloc;
-        /* We need to allocate one element extra, since we might use
-         * (unaligned) 4-wide SIMD loads to access rvec entries.
-         */
-        srenew(stateb->x, stateb->nalloc + 1);
-        srenew(stateb->v, stateb->nalloc + 1);
-    }
-
-    stateb->natoms     = statea->natoms;
-    stateb->ngtc       = statea->ngtc;
-    stateb->nnhpres    = statea->nnhpres;
-    stateb->veta       = statea->veta;
-    if (ekinda)
-    {
-        copy_mat(ekinda->ekin, ekindb->ekin);
-        for (i = 0; i < stateb->ngtc; i++)
-        {
-            ekindb->tcstat[i].T  = ekinda->tcstat[i].T;
-            ekindb->tcstat[i].Th = ekinda->tcstat[i].Th;
-            copy_mat(ekinda->tcstat[i].ekinh, ekindb->tcstat[i].ekinh);
-            copy_mat(ekinda->tcstat[i].ekinf, ekindb->tcstat[i].ekinf);
-            ekindb->tcstat[i].ekinscalef_nhc =  ekinda->tcstat[i].ekinscalef_nhc;
-            ekindb->tcstat[i].ekinscaleh_nhc =  ekinda->tcstat[i].ekinscaleh_nhc;
-            ekindb->tcstat[i].vscale_nhc     =  ekinda->tcstat[i].vscale_nhc;
-        }
-    }
-    copy_rvecn(statea->x, stateb->x, 0, stateb->natoms);
-    copy_rvecn(statea->v, stateb->v, 0, stateb->natoms);
-    copy_mat(statea->box, stateb->box);
-    copy_mat(statea->box_rel, stateb->box_rel);
-    copy_mat(statea->boxv, stateb->boxv);
-
-    for (i = 0; i < stateb->ngtc; i++)
-    {
-        nc = i*opts->nhchainlength;
-        for (j = 0; j < opts->nhchainlength; j++)
-        {
-            stateb->nosehoover_xi[nc+j]  = statea->nosehoover_xi[nc+j];
-            stateb->nosehoover_vxi[nc+j] = statea->nosehoover_vxi[nc+j];
-        }
-    }
-    if (stateb->nhpres_xi != NULL)
-    {
-        for (i = 0; i < stateb->nnhpres; i++)
-        {
-            nc = i*opts->nhchainlength;
-            for (j = 0; j < opts->nhchainlength; j++)
-            {
-                stateb->nhpres_xi[nc+j]  = statea->nhpres_xi[nc+j];
-                stateb->nhpres_vxi[nc+j] = statea->nhpres_vxi[nc+j];
-            }
-        }
-    }
-}
-
 real compute_conserved_from_auxiliary(t_inputrec *ir, t_state *state, t_extmass *MassQ)
 {
     real quantity = 0;
@@ -225,7 +159,7 @@ real compute_conserved_from_auxiliary(t_inputrec *ir, t_state *state, t_extmass
             quantity = NPT_energy(ir, state, MassQ);
             break;
         case etcVRESCALE:
-            quantity = vrescale_energy(&(ir->opts), state->therm_integral);
+            quantity = vrescale_energy(&(ir->opts), state->therm_integral.data());
             break;
         default:
             break;
@@ -291,7 +225,7 @@ void compute_globals(FILE *fplog, gmx_global_stat *gstat, t_commrec *cr, t_input
     if (bStopCM)
     {
         calc_vcm_grp(0, mdatoms->homenr, mdatoms,
-                     state->x, state->v, vcm);
+                     as_rvec_array(state->x.data()), as_rvec_array(state->v.data()), vcm);
     }
 
     if (bTemp || bStopCM || bPres || bEner || bConstrain)
@@ -326,7 +260,7 @@ void compute_globals(FILE *fplog, gmx_global_stat *gstat, t_commrec *cr, t_input
     {
         correct_ekin(debug,
                      0, mdatoms->homenr,
-                     state->v, vcm->group_p[0],
+                     as_rvec_array(state->v.data()), vcm->group_p[0],
                      mdatoms->massT, mdatoms->tmass, ekind->ekin);
     }
 
@@ -335,7 +269,7 @@ void compute_globals(FILE *fplog, gmx_global_stat *gstat, t_commrec *cr, t_input
     {
         check_cm_grp(fplog, vcm, ir, 1);
         do_stopcm_grp(0, mdatoms->homenr, mdatoms->cVCM,
-                      state->x, state->v, vcm);
+                      as_rvec_array(state->x.data()), as_rvec_array(state->v.data()), vcm);
         inc_nrnb(nrnb, eNR_STOPCM, mdatoms->homenr);
     }
 
@@ -658,33 +592,18 @@ void set_state_entries(t_state *state, const t_inputrec *ir)
         state->flags |= (1<<estFEPSTATE);
     }
     state->flags |= (1<<estX);
-    if (state->lambda == NULL)
-    {
-        snew(state->lambda, efptNR);
-    }
-    if (state->x == NULL)
-    {
-        /* We need to allocate one element extra, since we might use
-         * (unaligned) 4-wide SIMD loads to access rvec entries.
-         */
-        snew(state->x, state->nalloc + 1);
-    }
+    state->lambda.resize(efptNR);
+    GMX_RELEASE_ASSERT(state->x.size() >= static_cast<unsigned int>(state->natoms), "We should start a run with an initialized state->x");
     if (EI_DYNAMICS(ir->eI))
     {
         state->flags |= (1<<estV);
-        if (state->v == NULL)
-        {
-            snew(state->v, state->nalloc + 1);
-        }
+        state->v.resize(state->natoms + 1);
     }
     if (ir->eI == eiCG)
     {
         state->flags |= (1<<estCGP);
-        if (state->cg_p == NULL)
-        {
-            /* cg_p is not stored in the tpx file, so we need to allocate it */
-            snew(state->cg_p, state->nalloc + 1);
-        }
+        /* cg_p is not stored in the tpx file, so we need to allocate it */
+        state->cg_p.resize(state->natoms + 1);
     }
 
     state->nnhpres = 0;
index 409faf06949d0518cb455806284aecd0692547f6..e9403783e08c911012384d9d28eb40fc9df036d5 100644 (file)
@@ -115,10 +115,6 @@ void set_current_lambdas(gmx_int64_t step, t_lambda *fepvals, gmx_bool bRerunMD,
 int multisim_min(const gmx_multisim_t *ms, int nmin, int n);
 /* Set an appropriate value for n across the whole multi-simulation */
 
-void copy_coupling_state(t_state *statea, t_state *stateb,
-                         gmx_ekindata_t *ekinda, gmx_ekindata_t *ekindb, t_grpopts* opts);
-/* Copy stuff from state A to state B */
-
 void compute_globals(FILE *fplog, gmx_global_stat *gstat, t_commrec *cr, t_inputrec *ir,
                      t_forcerec *fr, gmx_ekindata_t *ekind,
                      t_state *state, t_mdatoms *mdatoms,
index 4ef52a0d94274249c1664fc0e819643c19c30c19..369b2a4afe125d499b2e8e402aee8532073589d8 100644 (file)
@@ -265,7 +265,7 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr,
                                       gmx_mtop_t *top_global,
                                       gmx_int64_t step, double t,
                                       t_state *state_local, t_state *state_global,
-                                      rvec *f_local)
+                                      PaddedRVecVector *f_local)
 {
     rvec *f_global;
 
@@ -279,13 +279,13 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr,
         {
             if (mdof_flags & (MDOF_X | MDOF_X_COMPRESSED))
             {
-                dd_collect_vec(cr->dd, state_local, state_local->x,
-                               state_global->x);
+                dd_collect_vec(cr->dd, state_local, &state_local->x,
+                               &state_global->x);
             }
             if (mdof_flags & MDOF_V)
             {
-                dd_collect_vec(cr->dd, state_local, state_local->v,
-                               state_global->v);
+                dd_collect_vec(cr->dd, state_local, &state_local->v,
+                               &state_global->v);
             }
         }
         f_global = of->f_global;
@@ -299,7 +299,7 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr,
         /* We have the whole state locally: copy the local state pointer */
         state_global = state_local;
 
-        f_global     = f_local;
+        f_global     = as_rvec_array(f_local->data());
     }
 
     if (MASTER(cr))
@@ -319,13 +319,15 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr,
 
         if (mdof_flags & (MDOF_X | MDOF_V | MDOF_F))
         {
+            const rvec *x = (mdof_flags & MDOF_X) ? as_rvec_array(state_global->x.data()) : NULL;
+            const rvec *v = (mdof_flags & MDOF_V) ? as_rvec_array(state_global->v.data()) : NULL;
+            const rvec *f = (mdof_flags & MDOF_F) ? f_global : NULL;
+
             if (of->fp_trn)
             {
                 gmx_trr_write_frame(of->fp_trn, step, t, state_local->lambda[efptFEP],
                                     state_local->box, top_global->natoms,
-                                    (mdof_flags & MDOF_X) ? state_global->x : NULL,
-                                    (mdof_flags & MDOF_V) ? state_global->v : NULL,
-                                    (mdof_flags & MDOF_F) ? f_global : NULL);
+                                    x, v, f);
                 if (gmx_fio_flush(of->fp_trn) != 0)
                 {
                     gmx_file("Cannot write trajectory; maybe you are out of disk space?");
@@ -339,9 +341,7 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr,
                 gmx_fwrite_tng(of->tng, FALSE, step, t, state_local->lambda[efptFEP],
                                state_local->box,
                                top_global->natoms,
-                               (mdof_flags & MDOF_X) ? state_global->x : NULL,
-                               (mdof_flags & MDOF_V) ? state_global->v : NULL,
-                               (mdof_flags & MDOF_F) ? f_global : NULL);
+                               x, v, f);
             }
             /* If only a TNG file is open for compressed coordinate output (no uncompressed
                coordinate output) also write forces and velocities to it. */
@@ -350,9 +350,7 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr,
                 gmx_fwrite_tng(of->tng_low_prec, FALSE, step, t, state_local->lambda[efptFEP],
                                state_local->box,
                                top_global->natoms,
-                               (mdof_flags & MDOF_X) ? state_global->x : NULL,
-                               (mdof_flags & MDOF_V) ? state_global->v : NULL,
-                               (mdof_flags & MDOF_F) ? f_global : NULL);
+                               x, v, f);
             }
         }
         if (mdof_flags & MDOF_X_COMPRESSED)
@@ -363,7 +361,7 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr,
             {
                 /* We are writing the positions of all of the atoms to
                    the compressed output */
-                xxtc = state_global->x;
+                xxtc = as_rvec_array(state_global->x.data());
             }
             else
             {
index a0a3f6a6d32b763c3e29d215fe4622f85168b0f3..c830e1f2b9ee67c1d7d57035b26b5e355972c187 100644 (file)
@@ -100,7 +100,7 @@ void mdoutf_write_to_trajectory_files(FILE *fplog, t_commrec *cr,
                                       gmx_mtop_t *top_global,
                                       gmx_int64_t step, double t,
                                       t_state *state_local, t_state *state_global,
-                                      rvec *f_local);
+                                      PaddedRVecVector *f_local);
 
 #define MDOF_X            (1<<0)
 #define MDOF_V            (1<<1)
index 1fee19c96766343ad6dddcd63f5c7b9aa27a7156..fe629ce7f77f25586fc2667960762fd5e6d90164 100644 (file)
 //! Utility structure for manipulating states during EM
 typedef struct {
     //! Copy of the global state
-    t_state  s;
+    t_state          s;
     //! Force array
-    rvec    *f;
+    PaddedRVecVector f;
     //! Potential energy
-    real     epot;
+    real             epot;
     //! Norm of the force
-    real     fnorm;
+    real             fnorm;
     //! Maximum force
-    real     fmax;
+    real             fmax;
     //! Direction
-    int      a_fmax;
+    int              a_fmax;
 } em_state_t;
 
-//! Initiate em_state_t structure and return pointer to it
-static em_state_t *init_em_state()
-{
-    em_state_t *ems;
-
-    snew(ems, 1);
-
-    /* does this need to be here?  Should the array be declared differently (staticaly)in the state definition? */
-    snew(ems->s.lambda, efptNR);
-
-    return ems;
-}
-
 //! Print the EM starting conditions
 static void print_em_start(FILE                     *fplog,
                            t_commrec                *cr,
@@ -197,7 +184,7 @@ static void warn_step(FILE *fp, real ftol, gmx_bool bLastStep, gmx_bool bConstra
 //! Print message about convergence of the EM
 static void print_converged(FILE *fp, const char *alg, real ftol,
                             gmx_int64_t count, gmx_bool bDone, gmx_int64_t nsteps,
-                            real epot, real fmax, int nfmax, real fnorm)
+                            const em_state_t *ems, double sqrtNumAtoms)
 {
     char buf[STEPSTRSIZE];
 
@@ -219,19 +206,19 @@ static void print_converged(FILE *fp, const char *alg, real ftol,
     }
 
 #if GMX_DOUBLE
-    fprintf(fp, "Potential Energy  = %21.14e\n", epot);
-    fprintf(fp, "Maximum force     = %21.14e on atom %d\n", fmax, nfmax+1);
-    fprintf(fp, "Norm of force     = %21.14e\n", fnorm);
+    fprintf(fp, "Potential Energy  = %21.14e\n", ems->epot);
+    fprintf(fp, "Maximum force     = %21.14e on atom %d\n", ems->fmax, ems->a_fmax + 1);
+    fprintf(fp, "Norm of force     = %21.14e\n", ems->fnorm/sqrtNumAtoms);
 #else
-    fprintf(fp, "Potential Energy  = %14.7e\n", epot);
-    fprintf(fp, "Maximum force     = %14.7e on atom %d\n", fmax, nfmax+1);
-    fprintf(fp, "Norm of force     = %14.7e\n", fnorm);
+    fprintf(fp, "Potential Energy  = %14.7e\n", ems->epot);
+    fprintf(fp, "Maximum force     = %14.7e on atom %d\n", ems->fmax, ems->a_fmax + 1);
+    fprintf(fp, "Norm of force     = %14.7e\n", ems->fnorm/sqrtNumAtoms);
 #endif
 }
 
 //! Compute the norm and max of the force array in parallel
 static void get_f_norm_max(t_commrec *cr,
-                           t_grpopts *opts, t_mdatoms *mdatoms, rvec *f,
+                           t_grpopts *opts, t_mdatoms *mdatoms, const rvec *f,
                            real *fnorm, real *fmax, int *a_fmax)
 {
     double fnorm2, *sum;
@@ -328,7 +315,8 @@ static void get_state_f_norm_max(t_commrec *cr,
                                  t_grpopts *opts, t_mdatoms *mdatoms,
                                  em_state_t *ems)
 {
-    get_f_norm_max(cr, opts, mdatoms, ems->f, &ems->fnorm, &ems->fmax, &ems->a_fmax);
+    get_f_norm_max(cr, opts, mdatoms, as_rvec_array(ems->f.data()),
+                   &ems->fnorm, &ems->fmax, &ems->a_fmax);
 }
 
 //! Initialize the energy minimization
@@ -336,7 +324,6 @@ void init_em(FILE *fplog, const char *title,
              t_commrec *cr, t_inputrec *ir,
              t_state *state_global, gmx_mtop_t *top_global,
              em_state_t *ems, gmx_localtop_t **top,
-             rvec **f,
              t_nrnb *nrnb, rvec mu_tot,
              t_forcerec *fr, gmx_enerdata_t **enerd,
              t_graph **graph, t_mdatoms *mdatoms, gmx_global_stat_t *gstat,
@@ -346,7 +333,6 @@ void init_em(FILE *fplog, const char *title,
              int imdport, unsigned long gmx_unused Flags,
              gmx_wallcycle_t wcycle)
 {
-    int  i;
     real dvdl_constr;
 
     if (fplog)
@@ -357,12 +343,12 @@ void init_em(FILE *fplog, const char *title,
     state_global->ngtc = 0;
 
     /* Initialize lambda variables */
-    initialize_lambdas(fplog, ir, &(state_global->fep_state), state_global->lambda, NULL);
+    initialize_lambdas(fplog, ir, &(state_global->fep_state), &state_global->lambda, NULL);
 
     init_nrnb(nrnb);
 
     /* Interactive molecular dynamics */
-    init_IMD(ir, cr, top_global, fplog, 1, state_global->x,
+    init_IMD(ir, cr, top_global, fplog, 1, as_rvec_array(state_global->x.data()),
              nfile, fnm, NULL, imdport, Flags);
 
     if (ir->eI == eiNM)
@@ -394,8 +380,6 @@ void init_em(FILE *fplog, const char *title,
 
         dd_init_local_state(cr->dd, state_global, &ems->s);
 
-        *f = NULL;
-
         /* Distribute the charge groups over the nodes from the master node */
         dd_partition_system(fplog, ir->init_step, cr, TRUE, 1,
                             state_global, top_global, ir,
@@ -408,22 +392,13 @@ void init_em(FILE *fplog, const char *title,
     }
     else
     {
-        snew(*f, top_global->natoms);
-
         /* Just copy the state */
         ems->s = *state_global;
         /* We need to allocate one element extra, since we might use
          * (unaligned) 4-wide SIMD loads to access rvec entries.
          */
-        snew(ems->s.x, ems->s.nalloc + 1);
-        snew(ems->f, ems->s.nalloc+1);
-        snew(ems->s.v, ems->s.nalloc+1);
-        for (i = 0; i < state_global->natoms; i++)
-        {
-            copy_rvec(state_global->x[i], ems->s.x[i]);
-        }
-        copy_mat(state_global->box, ems->s.box);
-
+        ems->s.x.resize(ems->s.natoms + 1);
+        ems->f.resize(ems->s.natoms + 1);
 
         snew(*top, 1);
         mdAlgorithmsSetupAtomData(cr, ir, top_global, *top, fr,
@@ -458,7 +433,10 @@ void init_em(FILE *fplog, const char *title,
             dvdl_constr = 0;
             constrain(PAR(cr) ? NULL : fplog, TRUE, TRUE, constr, &(*top)->idef,
                       ir, cr, -1, 0, 1.0, mdatoms,
-                      ems->s.x, ems->s.x, NULL, fr->bMolPBC, ems->s.box,
+                      as_rvec_array(ems->s.x.data()),
+                      as_rvec_array(ems->s.x.data()),
+                      NULL,
+                      fr->bMolPBC, ems->s.box,
                       ems->s.lambda[efptFEP], &dvdl_constr,
                       NULL, NULL, nrnb, econqCoord);
         }
@@ -506,9 +484,9 @@ static void finish_em(t_commrec *cr, gmx_mdoutf_t outf,
 }
 
 //! Swap two different EM states during minimization
-static void swap_em_state(em_state_t *ems1, em_state_t *ems2)
+static void swap_em_state(em_state_t **ems1, em_state_t **ems2)
 {
-    em_state_t tmp;
+    em_state_t *tmp;
 
     tmp   = *ems1;
     *ems1 = *ems2;
@@ -543,7 +521,8 @@ static void write_em_traj(FILE *fplog, t_commrec *cr,
 
     mdoutf_write_to_trajectory_files(fplog, cr, outf, mdof_flags,
                                      top_global, step, (double)step,
-                                     &state->s, state_global, state->f);
+                                     &state->s, state_global,
+                                     &state->f);
 
     if (confout != NULL && MASTER(cr))
     {
@@ -551,12 +530,12 @@ static void write_em_traj(FILE *fplog, t_commrec *cr,
         {
             /* Make molecules whole only for confout writing */
             do_pbc_mtop(fplog, ir->ePBC, state_global->box, top_global,
-                        state_global->x);
+                        as_rvec_array(state_global->x.data()));
         }
 
         write_sto_conf_mtop(confout,
                             *top_global->name, top_global,
-                            state_global->x, NULL, ir->ePBC, state_global->box);
+                            as_rvec_array(state_global->x.data()), NULL, ir->ePBC, state_global->box);
     }
 }
 
@@ -565,7 +544,8 @@ static void write_em_traj(FILE *fplog, t_commrec *cr,
 // \returns true when the step succeeded, false when a constraint error occurred
 static bool do_em_step(t_commrec *cr, t_inputrec *ir, t_mdatoms *md,
                        gmx_bool bMolPBC,
-                       em_state_t *ems1, real a, rvec *f, em_state_t *ems2,
+                       em_state_t *ems1, real a, const PaddedRVecVector *force,
+                       em_state_t *ems2,
                        gmx_constr_t constr, gmx_localtop_t *top,
                        t_nrnb *nrnb, gmx_wallcycle_t wcycle,
                        gmx_int64_t count)
@@ -588,27 +568,28 @@ static bool do_em_step(t_commrec *cr, t_inputrec *ir, t_mdatoms *md,
 
     s2->flags = s1->flags;
 
-    if (s2->nalloc != s1->nalloc)
+    if (s2->natoms != s1->natoms)
     {
-        s2->nalloc = s1->nalloc;
+        s2->natoms = s1->natoms;
         /* We need to allocate one element extra, since we might use
          * (unaligned) 4-wide SIMD loads to access rvec entries.
          */
-        srenew(s2->x, s1->nalloc + 1);
-        srenew(ems2->f,  s1->nalloc);
+        s2->x.resize(s1->natoms + 1);
+        ems2->f.resize(s1->natoms + 1);
         if (s2->flags & (1<<estCGP))
         {
-            srenew(s2->cg_p,  s1->nalloc + 1);
+            s2->cg_p.resize(s1->natoms + 1);
         }
     }
+    if (DOMAINDECOMP(cr) && s2->cg_gl.size() != s1->cg_gl.size())
+    {
+        s2->cg_gl.resize(s1->cg_gl.size());
+    }
 
     s2->natoms = s1->natoms;
     copy_mat(s1->box, s2->box);
     /* Copy free energy state */
-    for (int i = 0; i < efptNR; i++)
-    {
-        s2->lambda[i] = s1->lambda[i];
-    }
+    s2->lambda = s1->lambda;
     copy_mat(s1->box, s2->box);
 
     start = 0;
@@ -618,10 +599,11 @@ static bool do_em_step(t_commrec *cr, t_inputrec *ir, t_mdatoms *md,
     nthreads = gmx_omp_nthreads_get(emntUpdate);
 #pragma omp parallel num_threads(nthreads)
     {
-        rvec *x1 = s1->x;
-        rvec *x2 = s2->x;
+        const rvec *x1 = as_rvec_array(s1->x.data());
+        rvec       *x2 = as_rvec_array(s2->x.data());
+        const rvec *f  = as_rvec_array(force->data());
 
-        int   gf = 0;
+        int         gf = 0;
 #pragma omp for schedule(static) nowait
         for (int i = start; i < end; i++)
         {
@@ -649,8 +631,8 @@ static bool do_em_step(t_commrec *cr, t_inputrec *ir, t_mdatoms *md,
         if (s2->flags & (1<<estCGP))
         {
             /* Copy the CG p vector */
-            rvec *p1 = s1->cg_p;
-            rvec *p2 = s2->cg_p;
+            const rvec *p1 = as_rvec_array(s1->cg_p.data());
+            rvec       *p2 = as_rvec_array(s2->cg_p.data());
 #pragma omp for schedule(static) nowait
             for (int i = start; i < end; i++)
             {
@@ -662,23 +644,10 @@ static bool do_em_step(t_commrec *cr, t_inputrec *ir, t_mdatoms *md,
         if (DOMAINDECOMP(cr))
         {
             s2->ddp_count = s1->ddp_count;
-            if (s2->cg_gl_nalloc < s1->cg_gl_nalloc)
-            {
-#pragma omp barrier
-                s2->cg_gl_nalloc = s1->cg_gl_nalloc;
-                try
-                {
-                    /* We need to allocate one element extra, since we might use
-                     * (unaligned) 4-wide SIMD loads to access rvec entries.
-                     */
-                    srenew(s2->cg_gl, s2->cg_gl_nalloc + 1);
-                }
-                GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
-#pragma omp barrier
-            }
-            s2->ncg_gl = s1->ncg_gl;
+
+            /* OpenMP does not supported unsigned loop variables */
 #pragma omp for schedule(static) nowait
-            for (int i = 0; i < s2->ncg_gl; i++)
+            for (int i = 0; i < static_cast<int>(s2->cg_gl.size()); i++)
             {
                 s2->cg_gl[i] = s1->cg_gl[i];
             }
@@ -693,7 +662,8 @@ static bool do_em_step(t_commrec *cr, t_inputrec *ir, t_mdatoms *md,
         validStep   =
             constrain(NULL, TRUE, TRUE, constr, &top->idef,
                       ir, cr, count, 0, 1.0, md,
-                      s1->x, s2->x, NULL, bMolPBC, s2->box,
+                      as_rvec_array(s1->x.data()), as_rvec_array(s2->x.data()),
+                      NULL, bMolPBC, s2->box,
                       s2->lambda[efptBONDED], &dvdl_constr,
                       NULL, NULL, nrnb, econqCoord);
         wallcycle_stop(wcycle, ewcCONSTR);
@@ -766,7 +736,7 @@ static void evaluate_energy(FILE *fplog, t_commrec *cr,
 
     if (vsite)
     {
-        construct_vsites(vsite, ems->s.x, 1, NULL,
+        construct_vsites(vsite, as_rvec_array(ems->s.x.data()), 1, NULL,
                          top->idef.iparams, top->idef.il,
                          fr->ePBC, fr->bMolPBC, cr, ems->s.box);
     }
@@ -785,9 +755,9 @@ static void evaluate_energy(FILE *fplog, t_commrec *cr,
      */
     do_force(fplog, cr, inputrec,
              count, nrnb, wcycle, top, &top_global->groups,
-             ems->s.box, ems->s.x, &ems->s.hist,
-             ems->f, force_vir, mdatoms, enerd, fcd,
-             ems->s.lambda, graph, fr, vsite, mu_tot, t, NULL, NULL, TRUE,
+             ems->s.box, &ems->s.x, &ems->s.hist,
+             &ems->f, force_vir, mdatoms, enerd, fcd,
+             &ems->s.lambda, graph, fr, vsite, mu_tot, t, NULL, NULL, TRUE,
              GMX_FORCE_STATECHANGED | GMX_FORCE_ALLFORCES |
              GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY |
              (bNS ? GMX_FORCE_NS : 0));
@@ -826,9 +796,11 @@ static void evaluate_energy(FILE *fplog, t_commrec *cr,
         /* Project out the constraint components of the force */
         wallcycle_start(wcycle, ewcCONSTR);
         dvdl_constr = 0;
+        rvec *f_rvec = as_rvec_array(ems->f.data());
         constrain(NULL, FALSE, FALSE, constr, &top->idef,
                   inputrec, cr, count, 0, 1.0, mdatoms,
-                  ems->s.x, ems->f, ems->f, fr->bMolPBC, ems->s.box,
+                  as_rvec_array(ems->s.x.data()), f_rvec, f_rvec,
+                  fr->bMolPBC, ems->s.box,
                   ems->s.lambda[efptBONDED], &dvdl_constr,
                   NULL, &shake_vir, nrnb, econqForceDispl);
         enerd->term[F_DVDL_CONSTR] += dvdl_constr;
@@ -844,7 +816,7 @@ static void evaluate_energy(FILE *fplog, t_commrec *cr,
     enerd->term[F_PRES] =
         calc_pres(fr->ePBC, inputrec->nwall, ems->s.box, ekin, vir, pres);
 
-    sum_dhdl(enerd, ems->s.lambda, inputrec->fepvals);
+    sum_dhdl(enerd, &ems->s.lambda, inputrec->fepvals);
 
     if (EI_ENERGY_MINIMIZATION(inputrec->eI))
     {
@@ -857,7 +829,6 @@ static double reorder_partsum(t_commrec *cr, t_grpopts *opts, t_mdatoms *mdatoms
                               gmx_mtop_t *top_global,
                               em_state_t *s_min, em_state_t *s_b)
 {
-    rvec          *fm, *fb, *fmg;
     t_block       *cgs_gl;
     int            ncg, *cg_gl, *index, c, cg, i, a0, a1, a, gf, m;
     double         partsum;
@@ -868,8 +839,8 @@ static double reorder_partsum(t_commrec *cr, t_grpopts *opts, t_mdatoms *mdatoms
         fprintf(debug, "Doing reorder_partsum\n");
     }
 
-    fm = s_min->f;
-    fb = s_b->f;
+    const rvec *fm = as_rvec_array(s_min->f.data());
+    const rvec *fb = as_rvec_array(s_b->f.data());
 
     cgs_gl = dd_charge_groups_global(cr->dd);
     index  = cgs_gl->index;
@@ -878,10 +849,11 @@ static double reorder_partsum(t_commrec *cr, t_grpopts *opts, t_mdatoms *mdatoms
      * This conflicts with the spirit of domain decomposition,
      * but to fully optimize this a much more complicated algorithm is required.
      */
+    rvec *fmg;
     snew(fmg, top_global->natoms);
 
-    ncg   = s_min->s.ncg_gl;
-    cg_gl = s_min->s.cg_gl;
+    ncg   = s_min->s.cg_gl.size();
+    cg_gl = s_min->s.cg_gl.data();
     i     = 0;
     for (c = 0; c < ncg; c++)
     {
@@ -897,8 +869,8 @@ static double reorder_partsum(t_commrec *cr, t_grpopts *opts, t_mdatoms *mdatoms
     gmx_sum(top_global->natoms*3, fmg[0], cr);
 
     /* Now we will determine the part of the sum for the cgs in state s_b */
-    ncg         = s_b->s.ncg_gl;
-    cg_gl       = s_b->s.cg_gl;
+    ncg         = s_b->s.cg_gl.size();
+    cg_gl       = s_b->s.cg_gl.data();
     partsum     = 0;
     i           = 0;
     gf          = 0;
@@ -935,9 +907,7 @@ static real pr_beta(t_commrec *cr, t_grpopts *opts, t_mdatoms *mdatoms,
                     gmx_mtop_t *top_global,
                     em_state_t *s_min, em_state_t *s_b)
 {
-    rvec  *fm, *fb;
     double sum;
-    int    gf, i, m;
 
     /* This is just the classical Polak-Ribiere calculation of beta;
      * it looks a bit complicated since we take freeze groups into account,
@@ -948,20 +918,20 @@ static real pr_beta(t_commrec *cr, t_grpopts *opts, t_mdatoms *mdatoms,
         (s_min->s.ddp_count == cr->dd->ddp_count &&
          s_b->s.ddp_count   == cr->dd->ddp_count))
     {
-        fm  = s_min->f;
-        fb  = s_b->f;
-        sum = 0;
-        gf  = 0;
+        const rvec *fm  = as_rvec_array(s_min->f.data());
+        const rvec *fb  = as_rvec_array(s_b->f.data());
+        sum             = 0;
+        int         gf  = 0;
         /* This part of code can be incorrect with DD,
          * since the atom ordering in s_b and s_min might differ.
          */
-        for (i = 0; i < mdatoms->homenr; i++)
+        for (int i = 0; i < mdatoms->homenr; i++)
         {
             if (mdatoms->cFREEZE)
             {
                 gf = mdatoms->cFREEZE[i];
             }
-            for (m = 0; m < DIM; m++)
+            for (int m = 0; m < DIM; m++)
             {
                 if (!opts->nFreeze[gf][m])
                 {
@@ -1029,15 +999,11 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
 {
     const char       *CG = "Polak-Ribiere Conjugate Gradients";
 
-    em_state_t       *s_min, *s_a, *s_b, *s_c;
     gmx_localtop_t   *top;
     gmx_enerdata_t   *enerd;
-    rvec             *f;
     gmx_global_stat_t gstat;
     t_graph          *graph;
-    rvec             *p, *sf;
-    double            gpa, gpb, gpc, tmp, minstep;
-    real              fnormn;
+    double            tmp, minstep;
     real              stepsize;
     real              a, b, c, beta = 0.0;
     real              epot_repl = 0;
@@ -1049,18 +1015,20 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
     tensor            vir, pres;
     int               number_steps, neval = 0, nstcg = inputrec->nstcgsteep;
     gmx_mdoutf_t      outf;
-    int               i, m, gf, step, nminstep;
+    int               m, step, nminstep;
 
     step = 0;
 
-    s_min = init_em_state();
-    s_a   = init_em_state();
-    s_b   = init_em_state();
-    s_c   = init_em_state();
+    /* Create 4 states on the stack and extract pointers that we will swap */
+    em_state_t  s0 {}, s1 {}, s2 {}, s3 {};
+    em_state_t *s_min = &s0;
+    em_state_t *s_a   = &s1;
+    em_state_t *s_b   = &s2;
+    em_state_t *s_c   = &s3;
 
     /* Init em and store the local state in s_min */
     init_em(fplog, CG, cr, inputrec,
-            state_global, top_global, s_min, &top, &f,
+            state_global, top_global, s_min, &top,
             nrnb, mu_tot, fr, &enerd, &graph, mdatoms, &gstat,
             vsite, constr, NULL,
             nfile, fnm, &outf, &mdebin, imdport, Flags, wcycle);
@@ -1136,11 +1104,11 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
          */
 
         /* Calculate the new direction in p, and the gradient in this direction, gpa */
-        p   = s_min->s.cg_p;
-        sf  = s_min->f;
-        gpa = 0;
-        gf  = 0;
-        for (i = 0; i < mdatoms->homenr; i++)
+        rvec       *pm  = as_rvec_array(s_min->s.cg_p.data());
+        const rvec *sfm = as_rvec_array(s_min->f.data());
+        double      gpa = 0;
+        int         gf  = 0;
+        for (int i = 0; i < mdatoms->homenr; i++)
         {
             if (mdatoms->cFREEZE)
             {
@@ -1150,13 +1118,13 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
             {
                 if (!inputrec->opts.nFreeze[gf][m])
                 {
-                    p[i][m] = sf[i][m] + beta*p[i][m];
-                    gpa    -= p[i][m]*sf[i][m];
+                    pm[i][m] = sfm[i][m] + beta*pm[i][m];
+                    gpa     -= pm[i][m]*sfm[i][m];
                     /* f is negative gradient, thus the sign */
                 }
                 else
                 {
-                    p[i][m] = 0;
+                    pm[i][m] = 0;
                 }
             }
         }
@@ -1168,7 +1136,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
         }
 
         /* Calculate the norm of the search vector */
-        get_f_norm_max(cr, &(inputrec->opts), mdatoms, p, &pnorm, NULL, NULL);
+        get_f_norm_max(cr, &(inputrec->opts), mdatoms, pm, &pnorm, NULL, NULL);
 
         /* Just in case stepsize reaches zero due to numerical precision... */
         if (stepsize <= 0)
@@ -1193,7 +1161,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
          * relative change in coordinate is smaller than precision
          */
         minstep = 0;
-        for (i = 0; i < mdatoms->homenr; i++)
+        for (int i = 0; i < mdatoms->homenr; i++)
         {
             for (m = 0; m < DIM; m++)
             {
@@ -1202,7 +1170,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                 {
                     tmp = 1.0;
                 }
-                tmp      = p[i][m]/tmp;
+                tmp      = pm[i][m]/tmp;
                 minstep += tmp*tmp;
             }
         }
@@ -1257,7 +1225,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
         }
 
         /* Take a trial step (new coords in s_c) */
-        do_em_step(cr, inputrec, mdatoms, fr->bMolPBC, s_min, c, s_min->s.cg_p, s_c,
+        do_em_step(cr, inputrec, mdatoms, fr->bMolPBC, s_min, c, &s_min->s.cg_p, s_c,
                    constr, top, nrnb, wcycle, -1);
 
         neval++;
@@ -1269,14 +1237,14 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                         mu_tot, enerd, vir, pres, -1, FALSE);
 
         /* Calc derivative along line */
-        p   = s_c->s.cg_p;
-        sf  = s_c->f;
-        gpc = 0;
-        for (i = 0; i < mdatoms->homenr; i++)
+        const rvec *pc  = as_rvec_array(s_c->s.cg_p.data());
+        const rvec *sfc = as_rvec_array(s_c->f.data());
+        double      gpc = 0;
+        for (int i = 0; i < mdatoms->homenr; i++)
         {
             for (m = 0; m < DIM; m++)
             {
-                gpc -= p[i][m]*sf[i][m]; /* f is negative gradient, thus the sign */
+                gpc -= pc[i][m]*sfc[i][m]; /* f is negative gradient, thus the sign */
             }
         }
         /* Sum the gradient along the line across CPUs */
@@ -1329,6 +1297,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
          *
          * If we already found a lower value we just skip this step and continue to the update.
          */
+        double gpb;
         if (!foundlower)
         {
             nminstep = 0;
@@ -1365,7 +1334,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                 }
 
                 /* Take a trial step to this new point - new coords in s_b */
-                do_em_step(cr, inputrec, mdatoms, fr->bMolPBC, s_min, b, s_min->s.cg_p, s_b,
+                do_em_step(cr, inputrec, mdatoms, fr->bMolPBC, s_min, b, &s_min->s.cg_p, s_b,
                            constr, top, nrnb, wcycle, -1);
 
                 neval++;
@@ -1379,14 +1348,14 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                 /* p does not change within a step, but since the domain decomposition
                  * might change, we have to use cg_p of s_b here.
                  */
-                p   = s_b->s.cg_p;
-                sf  = s_b->f;
-                gpb = 0;
-                for (i = 0; i < mdatoms->homenr; i++)
+                const rvec *pb  = as_rvec_array(s_b->s.cg_p.data());
+                const rvec *sfb = as_rvec_array(s_b->f.data());
+                gpb             = 0;
+                for (int i = 0; i < mdatoms->homenr; i++)
                 {
                     for (m = 0; m < DIM; m++)
                     {
-                        gpb -= p[i][m]*sf[i][m]; /* f is negative gradient, thus the sign */
+                        gpb -= pb[i][m]*sfb[i][m]; /* f is negative gradient, thus the sign */
                     }
                 }
                 /* Sum the gradient along the line across CPUs */
@@ -1407,14 +1376,14 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                 if (gpb > 0)
                 {
                     /* Replace c endpoint with b */
-                    swap_em_state(s_b, s_c);
+                    swap_em_state(&s_b, &s_c);
                     c   = b;
                     gpc = gpb;
                 }
                 else
                 {
                     /* Replace a endpoint with b */
-                    swap_em_state(s_b, s_a);
+                    swap_em_state(&s_b, &s_a);
                     a   = b;
                     gpa = gpb;
                 }
@@ -1458,7 +1427,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                     fprintf(debug, "CGE: C (%f) is lower than A (%f), moving C to B\n",
                             s_c->epot, s_a->epot);
                 }
-                swap_em_state(s_b, s_c);
+                swap_em_state(&s_b, &s_c);
                 gpb = gpc;
             }
             else
@@ -1468,7 +1437,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                     fprintf(debug, "CGE: A (%f) is lower than C (%f), moving A to B\n",
                             s_a->epot, s_c->epot);
                 }
-                swap_em_state(s_b, s_a);
+                swap_em_state(&s_b, &s_a);
                 gpb = gpa;
             }
 
@@ -1480,7 +1449,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                 fprintf(debug, "CGE: Found a lower energy %f, moving C to B\n",
                         s_c->epot);
             }
-            swap_em_state(s_b, s_c);
+            swap_em_state(&s_b, &s_c);
             gpb = gpc;
         }
 
@@ -1509,7 +1478,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
 
 
         /* update positions */
-        swap_em_state(s_min, s_b);
+        swap_em_state(&s_min, &s_b);
         gpa = gpb;
 
         /* Print it if necessary */
@@ -1544,7 +1513,7 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
         }
 
         /* Send energies and positions to the IMD client if bIMD is TRUE. */
-        if (do_IMD(inputrec->bIMD, step, cr, TRUE, state_global->box, state_global->x, inputrec, 0, wcycle) && MASTER(cr))
+        if (do_IMD(inputrec->bIMD, step, cr, TRUE, state_global->box, as_rvec_array(state_global->x.data()), inputrec, 0, wcycle) && MASTER(cr))
         {
             IMD_send_positions(inputrec->imd);
         }
@@ -1617,11 +1586,10 @@ double do_cg(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
     if (MASTER(cr))
     {
         double sqrtNumAtoms = sqrt(static_cast<double>(state_global->natoms));
-        fnormn = s_min->fnorm/sqrtNumAtoms;
         print_converged(stderr, CG, inputrec->em_tol, step, converged, number_steps,
-                        s_min->epot, s_min->fmax, s_min->a_fmax, fnormn);
+                        s_min, sqrtNumAtoms);
         print_converged(fplog, CG, inputrec->em_tol, step, converged, number_steps,
-                        s_min->epot, s_min->fmax, s_min->a_fmax, fnormn);
+                        s_min, sqrtNumAtoms);
 
         fprintf(fplog, "\nPerformed %d energy evaluations in total.\n", neval);
     }
@@ -1679,25 +1647,22 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     em_state_t         ems;
     gmx_localtop_t    *top;
     gmx_enerdata_t    *enerd;
-    rvec              *f;
     gmx_global_stat_t  gstat;
     t_graph           *graph;
     int                ncorr, nmaxcorr, point, cp, neval, nminstep;
     double             stepsize, step_taken, gpa, gpb, gpc, tmp, minstep;
-    real              *rho, *alpha, *ff, *xx, *p, *s, *lastx, *lastf, **dx, **dg;
-    real              *xa, *xb, *xc, *fa, *fb, *fc, *xtmp, *ftmp;
+    real              *rho, *alpha, *p, *s, **dx, **dg;
     real               a, b, c, maxdelta, delta;
-    real               diag, Epot0, Epot, EpotA, EpotB, EpotC;
+    real               diag, Epot0;
     real               dgdx, dgdg, sq, yr, beta;
     t_mdebin          *mdebin;
     gmx_bool           converged;
     rvec               mu_tot;
-    real               fnorm, fmax;
     gmx_bool           do_log, do_ene, do_x, do_f, foundlower, *frozen;
     tensor             vir, pres;
     int                start, end, number_steps;
     gmx_mdoutf_t       outf;
-    int                i, k, m, n, nfmax, gf, step;
+    int                i, k, m, n, gf, step;
     int                mdof_flags;
 
     if (PAR(cr))
@@ -1713,23 +1678,9 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     n        = 3*state_global->natoms;
     nmaxcorr = inputrec->nbfgscorr;
 
-    /* Allocate memory */
-    /* Use pointers to real so we dont have to loop over both atoms and
-     * dimensions all the time...
-     * x/f are allocated as rvec *, so make new x0/f0 pointers-to-real
-     * that point to the same memory.
-     */
-    snew(xa, n);
-    snew(xb, n);
-    snew(xc, n);
-    snew(fa, n);
-    snew(fb, n);
-    snew(fc, n);
     snew(frozen, n);
 
     snew(p, n);
-    snew(lastx, n);
-    snew(lastf, n);
     snew(rho, nmaxcorr);
     snew(alpha, nmaxcorr);
 
@@ -1750,22 +1701,25 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
 
     /* Init em */
     init_em(fplog, LBFGS, cr, inputrec,
-            state_global, top_global, &ems, &top, &f,
+            state_global, top_global, &ems, &top,
             nrnb, mu_tot, fr, &enerd, &graph, mdatoms, &gstat,
             vsite, constr, NULL,
             nfile, fnm, &outf, &mdebin, imdport, Flags, wcycle);
-    /* Do_lbfgs is not completely updated like do_steep and do_cg,
-     * so we free some memory again.
-     */
-    sfree(ems.s.x);
-    sfree(ems.f);
-
-    xx = (real *)state_global->x;
-    ff = (real *)f;
 
     start = 0;
     end   = mdatoms->homenr;
 
+    /* We need 4 working states */
+    em_state_t  s0 {}, s1 {}, s2 {}, s3 {};
+    em_state_t *sa   = &s0;
+    em_state_t *sb   = &s1;
+    em_state_t *sc   = &s2;
+    em_state_t *last = &s3;
+    /* Initialize by copying the state from ems (we could skip x and f here) */
+    *sa              = ems;
+    *sb              = ems;
+    *sc              = ems;
+
     /* Print to log file */
     print_em_start(fplog, cr, walltime_accounting, wcycle, LBFGS);
 
@@ -1798,7 +1752,7 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
 
     if (vsite)
     {
-        construct_vsites(vsite, state_global->x, 1, NULL,
+        construct_vsites(vsite, as_rvec_array(state_global->x.data()), 1, NULL,
                          top->idef.iparams, top->idef.il,
                          fr->ePBC, fr->bMolPBC, cr, state_global->box);
     }
@@ -1808,8 +1762,6 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
      * We do not unshift, so molecules are always whole
      */
     neval++;
-    ems.s.x = state_global->x;
-    ems.f   = f;
     evaluate_energy(fplog, cr,
                     top_global, &ems, top,
                     inputrec, nrnb, wcycle, gstat,
@@ -1830,13 +1782,6 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     }
     where();
 
-    /* This is the starting energy */
-    Epot = enerd->term[F_EPOT];
-
-    fnorm = ems.fnorm;
-    fmax  = ems.fmax;
-    nfmax = ems.a_fmax;
-
     /* Set the initial step.
      * since it will be multiplied by the non-normalized search direction
      * vector (force vector the first time), we scale it by the
@@ -1847,13 +1792,13 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     {
         double sqrtNumAtoms = sqrt(static_cast<double>(state_global->natoms));
         fprintf(stderr, "Using %d BFGS correction steps.\n\n", nmaxcorr);
-        fprintf(stderr, "   F-max             = %12.5e on atom %d\n", fmax, nfmax+1);
-        fprintf(stderr, "   F-Norm            = %12.5e\n", fnorm/sqrtNumAtoms);
+        fprintf(stderr, "   F-max             = %12.5e on atom %d\n", ems.fmax, ems.a_fmax + 1);
+        fprintf(stderr, "   F-Norm            = %12.5e\n", ems.fnorm/sqrtNumAtoms);
         fprintf(stderr, "\n");
         /* and copy to the log file too... */
         fprintf(fplog, "Using %d BFGS correction steps.\n\n", nmaxcorr);
-        fprintf(fplog, "   F-max             = %12.5e on atom %d\n", fmax, nfmax+1);
-        fprintf(fplog, "   F-Norm            = %12.5e\n", fnorm/sqrtNumAtoms);
+        fprintf(fplog, "   F-max             = %12.5e on atom %d\n", ems.fmax, ems.a_fmax + 1);
+        fprintf(fplog, "   F-Norm            = %12.5e\n", ems.fnorm/sqrtNumAtoms);
         fprintf(fplog, "\n");
     }
 
@@ -1861,11 +1806,12 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     point = 0;
 
     // Set initial search direction to the force (-gradient), or 0 for frozen particles.
+    real *fInit = static_cast<real *>(as_rvec_array(ems.f.data())[0]);
     for (i = 0; i < n; i++)
     {
         if (!frozen[i])
         {
-            dx[point][i] = ff[i]; /* Initial search direction */
+            dx[point][i] = fInit[i]; /* Initial search direction */
         }
         else
         {
@@ -1877,7 +1823,7 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     // (the main efficiency in the algorithm comes from changing directions), but
     // we still need an initial value, so estimate it as the inverse of the norm
     // so we take small steps where the potential fluctuates a lot.
-    stepsize  = 1.0/fnorm;
+    stepsize  = 1.0/ems.fnorm;
 
     /* Start the loop over BFGS steps.
      * Each successful step is counted, and we continue until
@@ -1912,13 +1858,16 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         }
 
         mdoutf_write_to_trajectory_files(fplog, cr, outf, mdof_flags,
-                                         top_global, step, (real)step, state_global, state_global, f);
+                                         top_global, step, (real)step, &ems.s, state_global, &ems.f);
 
         /* Do the linesearching in the direction dx[point][0..(n-1)] */
 
         /* make s a pointer to current search direction - point=0 first time we get here */
         s = dx[point];
 
+        real *xx = static_cast<real *>(as_rvec_array(ems.s.x.data())[0]);
+        real *ff = static_cast<real *>(as_rvec_array(ems.f.data())[0]);
+
         // calculate line gradient in position A
         for (gpa = 0, i = 0; i < n; i++)
         {
@@ -1947,17 +1896,12 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         }
 
         // Before taking any steps along the line, store the old position
-        for (i = 0; i < n; i++)
-        {
-            lastx[i] = xx[i];
-            lastf[i] = ff[i];
-        }
-        Epot0 = Epot;
+        *last       = ems;
+        real *lastx = static_cast<real *>(as_rvec_array(last->s.x.data())[0]);
+        real *lastf = static_cast<real *>(as_rvec_array(last->f.data())[0]);
+        Epot0       = ems.epot;
 
-        for (i = 0; i < n; i++)
-        {
-            xa[i] = xx[i];
-        }
+        *sa         = ems;
 
         /* Take a step downhill.
          * In theory, we should find the actual minimum of the function in this
@@ -1986,7 +1930,6 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
 
         // State "A" is the first position along the line.
         // reference position along line is initially zero
-        EpotA      = Epot0;
         a          = 0.0;
 
         // Check stepsize first. We do not allow displacements
@@ -2017,6 +1960,7 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         while (maxdelta > inputrec->em_stepsize);
 
         // Take a trial step and move the coordinate array xc[] to position C
+        real *xc = static_cast<real *>(as_rvec_array(sc->s.x.data())[0]);
         for (i = 0; i < n; i++)
         {
             xc[i] = lastx[i] + c*s[i];
@@ -2024,16 +1968,14 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
 
         neval++;
         // Calculate energy for the trial step in position C
-        ems.s.x = (rvec *)xc;
-        ems.f   = (rvec *)fc;
         evaluate_energy(fplog, cr,
-                        top_global, &ems, top,
+                        top_global, sc, top,
                         inputrec, nrnb, wcycle, gstat,
                         vsite, constr, fcd, graph, mdatoms, fr,
                         mu_tot, enerd, vir, pres, step, FALSE);
-        EpotC = ems.epot;
 
         // Calc line gradient in position C
+        real *fc = static_cast<real *>(as_rvec_array(sc->f.data())[0]);
         for (gpc = 0, i = 0; i < n; i++)
         {
             gpc -= s[i]*fc[i]; /* f is negative gradient, thus the sign */
@@ -2047,11 +1989,11 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         // This is the max amount of increase in energy we tolerate.
         // By allowing VERY small changes (close to numerical precision) we
         // frequently find even better (lower) final energies.
-        tmp = sqrt(GMX_REAL_EPS)*fabs(EpotA);
+        tmp = sqrt(GMX_REAL_EPS)*fabs(sa->epot);
 
         // Accept the step if the energy is lower in the new position C (compared to A),
         // or if it is not significantly higher and the line derivative is still negative.
-        if (EpotC < EpotA || (gpc < 0 && EpotC < (EpotA+tmp)))
+        if (sc->epot < sa->epot || (gpc < 0 && sc->epot < (sa->epot + tmp)))
         {
             // Great, we found a better energy. We no longer try to alter the
             // stepsize, but simply accept this new better position. The we select a new
@@ -2059,7 +2001,6 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
             // to take smaller steps along a line. Set fnorm based on the new C position,
             // which will be used to update the stepsize to 1/fnorm further down.
             foundlower = TRUE;
-            fnorm      = ems.fnorm;
         }
         else
         {
@@ -2084,7 +2025,8 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
             // I also have a safeguard for potentially really pathological functions so we never
             // take more than 20 steps before we give up.
             // If we already found a lower value we just skip this step and continue to the update.
-            nminstep = 0;
+            real fnorm = 0;
+            nminstep   = 0;
             do
             {
                 // Select a new trial point B in the interval [A,C].
@@ -2109,6 +2051,7 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
                 }
 
                 // Take a trial step to point B
+                real *xb = static_cast<real *>(as_rvec_array(sb->s.x.data())[0]);
                 for (i = 0; i < n; i++)
                 {
                     xb[i] = lastx[i] + b*s[i];
@@ -2116,17 +2059,15 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
 
                 neval++;
                 // Calculate energy for the trial step in point B
-                ems.s.x = (rvec *)xb;
-                ems.f   = (rvec *)fb;
                 evaluate_energy(fplog, cr,
-                                top_global, &ems, top,
+                                top_global, sb, top,
                                 inputrec, nrnb, wcycle, gstat,
                                 vsite, constr, fcd, graph, mdatoms, fr,
                                 mu_tot, enerd, vir, pres, step, FALSE);
-                EpotB = ems.epot;
-                fnorm = ems.fnorm;
+                fnorm = sb->fnorm;
 
                 // Calculate gradient in point B
+                real *fb = static_cast<real *>(as_rvec_array(sb->f.data())[0]);
                 for (gpb = 0, i = 0; i < n; i++)
                 {
                     gpb -= s[i]*fb[i]; /* f is negative gradient, thus the sign */
@@ -2143,30 +2084,16 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
                 if (gpb > 0)
                 {
                     /* Replace c endpoint with b */
-                    EpotC = EpotB;
-                    c     = b;
-                    gpc   = gpb;
-                    /* swap coord pointers b/c */
-                    xtmp = xb;
-                    ftmp = fb;
-                    xb   = xc;
-                    fb   = fc;
-                    xc   = xtmp;
-                    fc   = ftmp;
+                    c   = b;
+                    /* swap states b and c */
+                    swap_em_state(&sb, &sc);
                 }
                 else
                 {
                     /* Replace a endpoint with b */
-                    EpotA = EpotB;
-                    a     = b;
-                    gpa   = gpb;
-                    /* swap coord pointers a/b */
-                    xtmp = xb;
-                    ftmp = fb;
-                    xb   = xa;
-                    fb   = fa;
-                    xa   = xtmp;
-                    fa   = ftmp;
+                    a   = b;
+                    /* swap states a and b */
+                    swap_em_state(&sa, &sb);
                 }
 
                 /*
@@ -2176,9 +2103,9 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
                  */
                 nminstep++;
             }
-            while ((EpotB > EpotA || EpotB > EpotC) && (nminstep < 20));
+            while ((sb->epot > sa->epot || sb->epot > sc->epot) && (nminstep < 20));
 
-            if (fabs(EpotB-Epot0) < GMX_REAL_EPS || nminstep >= 20)
+            if (fabs(sb->epot - Epot0) < GMX_REAL_EPS || nminstep >= 20)
             {
                 /* OK. We couldn't find a significantly lower energy.
                  * If ncorr==0 this was steepest descent, and then we give up.
@@ -2207,26 +2134,16 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
 
             /* Select min energy state of A & C, put the best in xx/ff/Epot
              */
-            if (EpotC < EpotA)
+            if (sc->epot < sa->epot)
             {
-                Epot = EpotC;
                 /* Use state C */
-                for (i = 0; i < n; i++)
-                {
-                    xx[i] = xc[i];
-                    ff[i] = fc[i];
-                }
+                ems        = *sc;
                 step_taken = c;
             }
             else
             {
-                Epot = EpotA;
                 /* Use state A */
-                for (i = 0; i < n; i++)
-                {
-                    xx[i] = xa[i];
-                    ff[i] = fa[i];
-                }
+                ems        = *sa;
                 step_taken = a;
             }
 
@@ -2234,13 +2151,8 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         else
         {
             /* found lower */
-            Epot = EpotC;
             /* Use state C */
-            for (i = 0; i < n; i++)
-            {
-                xx[i] = xc[i];
-                ff[i] = fc[i];
-            }
+            ems        = *sc;
             step_taken = c;
         }
 
@@ -2350,9 +2262,6 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
             }
         }
 
-        /* Test whether the convergence criterion is met */
-        get_f_norm_max(cr, &(inputrec->opts), mdatoms, f, &fnorm, &fmax, &nfmax);
-
         /* Print it if necessary */
         if (MASTER(cr))
         {
@@ -2360,7 +2269,7 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
             {
                 double sqrtNumAtoms = sqrt(static_cast<double>(state_global->natoms));
                 fprintf(stderr, "\rStep %d, Epot=%12.6e, Fnorm=%9.3e, Fmax=%9.3e (atom %d)\n",
-                        step, Epot, fnorm/sqrtNumAtoms, fmax, nfmax+1);
+                        step, ems.epot, ems.fnorm/sqrtNumAtoms, ems.fmax, ems.a_fmax + 1);
                 fflush(stderr);
             }
             /* Store the new (lower) energies */
@@ -2379,18 +2288,18 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         }
 
         /* Send x and E to IMD client, if bIMD is TRUE. */
-        if (do_IMD(inputrec->bIMD, step, cr, TRUE, state_global->box, state_global->x, inputrec, 0, wcycle) && MASTER(cr))
+        if (do_IMD(inputrec->bIMD, step, cr, TRUE, state_global->box, as_rvec_array(state_global->x.data()), inputrec, 0, wcycle) && MASTER(cr))
         {
             IMD_send_positions(inputrec->imd);
         }
 
         // Reset stepsize in we are doing more iterations
-        stepsize = 1.0/fnorm;
+        stepsize = 1.0/ems.fnorm;
 
         /* Stop when the maximum force lies below tolerance.
          * If we have reached machine precision, converged is already set to true.
          */
-        converged = converged || (fmax < inputrec->em_tol);
+        converged = converged || (ems.fmax < inputrec->em_tol);
 
     }   /* End of the loop */
 
@@ -2402,7 +2311,7 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         step--; /* we never took that last step in this case */
 
     }
-    if (fmax > inputrec->em_tol)
+    if (ems.fmax > inputrec->em_tol)
     {
         if (MASTER(cr))
         {
@@ -2449,9 +2358,9 @@ double do_lbfgs(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     {
         double sqrtNumAtoms = sqrt(static_cast<double>(state_global->natoms));
         print_converged(stderr, LBFGS, inputrec->em_tol, step, converged,
-                        number_steps, Epot, fmax, nfmax, fnorm/sqrtNumAtoms);
+                        number_steps, &ems, sqrtNumAtoms);
         print_converged(fplog, LBFGS, inputrec->em_tol, step, converged,
-                        number_steps, Epot, fmax, nfmax, fnorm/sqrtNumAtoms);
+                        number_steps, &ems, sqrtNumAtoms);
 
         fprintf(fplog, "\nPerformed %d energy evaluations in total.\n", neval);
     }
@@ -2505,14 +2414,12 @@ double do_steep(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
                 gmx_walltime_accounting_t walltime_accounting)
 {
     const char       *SD = "Steepest Descents";
-    em_state_t       *s_min, *s_try;
     gmx_localtop_t   *top;
     gmx_enerdata_t   *enerd;
-    rvec             *f;
     gmx_global_stat_t gstat;
     t_graph          *graph;
     real              stepsize;
-    real              ustep, fnormn;
+    real              ustep;
     gmx_mdoutf_t      outf;
     t_mdebin         *mdebin;
     gmx_bool          bDone, bAbort, do_x, do_f;
@@ -2522,12 +2429,14 @@ double do_steep(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     int               count          = 0;
     int               steps_accepted = 0;
 
-    s_min = init_em_state();
-    s_try = init_em_state();
+    /* Create 2 states on the stack and extract pointers that we will swap */
+    em_state_t  s0 {}, s1 {};
+    em_state_t *s_min = &s0;
+    em_state_t *s_try = &s1;
 
     /* Init em and store the local state in s_try */
     init_em(fplog, SD, cr, inputrec,
-            state_global, top_global, s_try, &top, &f,
+            state_global, top_global, s_try, &top,
             nrnb, mu_tot, fr, &enerd, &graph, mdatoms, &gstat,
             vsite, constr, NULL,
             nfile, fnm, &outf, &mdebin, imdport, Flags, wcycle);
@@ -2573,7 +2482,7 @@ double do_steep(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         {
             validStep =
                 do_em_step(cr, inputrec, mdatoms, fr->bMolPBC,
-                           s_min, stepsize, s_min->f, s_try,
+                           s_min, stepsize, &s_min->f, s_try,
                            constr, top, nrnb, wcycle, count);
         }
 
@@ -2646,7 +2555,7 @@ double do_steep(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
             /* Copy the arrays for force, positions and energy  */
             /* The 'Min' array always holds the coords and forces of the minimal
                sampled energy  */
-            swap_em_state(s_min, s_try);
+            swap_em_state(&s_min, &s_try);
             if (count > 0)
             {
                 ustep *= 1.2;
@@ -2692,7 +2601,7 @@ double do_steep(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
         }
 
         /* Send IMD energies and positions, if bIMD is TRUE. */
-        if (do_IMD(inputrec->bIMD, count, cr, TRUE, state_global->box, state_global->x, inputrec, 0, wcycle) && MASTER(cr))
+        if (do_IMD(inputrec->bIMD, count, cr, TRUE, state_global->box, as_rvec_array(state_global->x.data()), inputrec, 0, wcycle) && MASTER(cr))
         {
             IMD_send_positions(inputrec->imd);
         }
@@ -2715,12 +2624,11 @@ double do_steep(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlo
     if (MASTER(cr))
     {
         double sqrtNumAtoms = sqrt(static_cast<double>(state_global->natoms));
-        fnormn = s_min->fnorm/sqrtNumAtoms;
 
         print_converged(stderr, SD, inputrec->em_tol, count, bDone, nsteps,
-                        s_min->epot, s_min->fmax, s_min->a_fmax, fnormn);
+                        s_min, sqrtNumAtoms);
         print_converged(fplog, SD, inputrec->em_tol, count, bDone, nsteps,
-                        s_min->epot, s_min->fmax, s_min->a_fmax, fnormn);
+                        s_min, sqrtNumAtoms);
     }
 
     finish_em(cr, outf, walltime_accounting, wcycle);
@@ -2778,7 +2686,6 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
     int                  nnodes, node;
     gmx_localtop_t      *top;
     gmx_enerdata_t      *enerd;
-    rvec                *f;
     gmx_global_stat_t    gstat;
     t_graph             *graph;
     tensor               vir, pres;
@@ -2788,7 +2695,6 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
     size_t               sz;
     gmx_sparsematrix_t * sparse_matrix           = NULL;
     real           *     full_matrix             = NULL;
-    em_state_t       *   state_work;
 
     /* added with respect to mdrun */
     int                       row, col;
@@ -2801,14 +2707,13 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
         gmx_fatal(FARGS, "Constraints present with Normal Mode Analysis, this combination is not supported");
     }
 
-    state_work = init_em_state();
-
     gmx_shellfc_t *shellfc;
 
+    em_state_t     state_work {};
+
     /* Init em and store the local state in state_minimum */
     init_em(fplog, NM, cr, inputrec,
-            state_global, top_global, state_work, &top,
-            &f,
+            state_global, top_global, &state_work, &top,
             nrnb, mu_tot, fr, &enerd, &graph, mdatoms, &gstat,
             vsite, constr, &shellfc,
             nfile, fnm, &outf, NULL, imdport, Flags, wcycle);
@@ -2887,17 +2792,17 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
     /* Make evaluate_energy do a single node force calculation */
     cr->nnodes = 1;
     evaluate_energy(fplog, cr,
-                    top_global, state_work, top,
+                    top_global, &state_work, top,
                     inputrec, nrnb, wcycle, gstat,
                     vsite, constr, fcd, graph, mdatoms, fr,
                     mu_tot, enerd, vir, pres, -1, TRUE);
     cr->nnodes = nnodes;
 
     /* if forces are not small, warn user */
-    get_state_f_norm_max(cr, &(inputrec->opts), mdatoms, state_work);
+    get_state_f_norm_max(cr, &(inputrec->opts), mdatoms, &state_work);
 
-    GMX_LOG(mdlog.warning).appendTextFormatted("Maximum force:%12.5e", state_work->fmax);
-    if (state_work->fmax > 1.0e-3)
+    GMX_LOG(mdlog.warning).appendTextFormatted("Maximum force:%12.5e", state_work.fmax);
+    if (state_work.fmax > 1.0e-3)
     {
         GMX_LOG(mdlog.warning).appendText(
                 "The force is probably not small enough to "
@@ -2927,17 +2832,17 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             int         force_flags = GMX_FORCE_STATECHANGED | GMX_FORCE_ALLFORCES;
             double      t           = 0;
 
-            x_min = state_work->s.x[atom][d];
+            x_min = state_work.s.x[atom][d];
 
             for (unsigned int dx = 0; (dx < 2); dx++)
             {
                 if (dx == 0)
                 {
-                    state_work->s.x[atom][d] = x_min - der_range;
+                    state_work.s.x[atom][d] = x_min - der_range;
                 }
                 else
                 {
-                    state_work->s.x[atom][d] = x_min + der_range;
+                    state_work.s.x[atom][d] = x_min + der_range;
                 }
 
                 /* Make evaluate_energy do a single node force calculation */
@@ -2949,7 +2854,7 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                                                inputrec, bNS, force_flags,
                                                top,
                                                constr, enerd, fcd,
-                                               &state_work->s, state_work->f, vir, mdatoms,
+                                               &state_work.s, &state_work.f, vir, mdatoms,
                                                nrnb, wcycle, graph, &top_global->groups,
                                                shellfc, fr, bBornRadii, t, mu_tot,
                                                vsite, NULL);
@@ -2959,7 +2864,7 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                 else
                 {
                     evaluate_energy(fplog, cr,
-                                    top_global, state_work, top,
+                                    top_global, &state_work, top,
                                     inputrec, nrnb, wcycle, gstat,
                                     vsite, constr, fcd, graph, mdatoms, fr,
                                     mu_tot, enerd, vir, pres, atom*2+dx, FALSE);
@@ -2971,20 +2876,20 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                 {
                     for (size_t i = 0; i < atom_index.size(); i++)
                     {
-                        copy_rvec(state_work->f[atom_index[i]], fneg[i]);
+                        copy_rvec(state_work.f[atom_index[i]], fneg[i]);
                     }
                 }
             }
 
             /* x is restored to original */
-            state_work->s.x[atom][d] = x_min;
+            state_work.s.x[atom][d] = x_min;
 
             for (size_t j = 0; j < atom_index.size(); j++)
             {
                 for (size_t k = 0; (k < DIM); k++)
                 {
                     dfdx[j][k] =
-                        -(state_work->f[atom_index[j]][k] - fneg[j][k])/(2*der_range);
+                        -(state_work.f[atom_index[j]][k] - fneg[j][k])/(2*der_range);
                 }
             }
 
index c62ae769c199ccc731b53c417044eb923535625a..7fc5ae8d521395023d622f09523c475ce50a335b 100644 (file)
@@ -83,6 +83,7 @@ typedef struct {
 } t_shell;
 
 struct gmx_shellfc_t {
+    /* Shell counts, indices, parameters and working data */
     int          nshell_gl;              /* The number of shells in the system        */
     t_shell     *shell_gl;               /* All the shells (for DD only)              */
     int         *shell_index_gl;         /* Global shell index (for DD only)          */
@@ -93,9 +94,12 @@ struct gmx_shellfc_t {
     gmx_bool     bPredict;               /* Predict shell positions                   */
     gmx_bool     bRequireInit;           /* Require initialization of shell positions */
     int          nflexcon;               /* The number of flexible constraints        */
-    rvec        *x[2];                   /* Array for iterative minimization          */
-    rvec        *f[2];                   /* Array for iterative minimization          */
-    int          x_nalloc;               /* The allocation size of x and f            */
+
+    /* Temporary arrays, should be fixed size 2 when fully converted to C++ */
+    PaddedRVecVector *x;                 /* Array for iterative minimization          */
+    PaddedRVecVector *f;                 /* Array for iterative minimization          */
+
+    /* Flexible constraint working data */
     rvec        *acc_dir;                /* Acceleration direction for flexcon        */
     rvec        *x_old;                  /* Old coordinates for flexcon               */
     int          flex_nalloc;            /* The allocation size of acc_dir and x_old  */
@@ -334,6 +338,8 @@ gmx_shellfc_t *init_shell_flexcon(FILE *fplog,
     }
 
     snew(shfc, 1);
+    shfc->x        = new PaddedRVecVector[2] {};
+    shfc->f        = new PaddedRVecVector[2] {};
     shfc->nflexcon = nflexcon;
 
     if (nshell == 0)
@@ -666,7 +672,7 @@ void make_local_shells(t_commrec *cr, t_mdatoms *md,
     shfc->shell  = shell;
 }
 
-static void do_1pos(rvec xnew, rvec xold, rvec f, real step)
+static void do_1pos(rvec xnew, const rvec xold, const rvec f, real step)
 {
     real xo, yo, zo;
     real dx, dy, dz;
@@ -684,7 +690,7 @@ static void do_1pos(rvec xnew, rvec xold, rvec f, real step)
     xnew[ZZ] = zo+dz;
 }
 
-static void do_1pos3(rvec xnew, rvec xold, rvec f, rvec step)
+static void do_1pos3(rvec xnew, const rvec xold, const rvec f, const rvec step)
 {
     real xo, yo, zo;
     real dx, dy, dz;
@@ -702,18 +708,21 @@ static void do_1pos3(rvec xnew, rvec xold, rvec f, rvec step)
     xnew[ZZ] = zo+dz;
 }
 
-static void directional_sd(rvec xold[], rvec xnew[], rvec acc_dir[],
-                           int start, int homenr, real step)
+static void directional_sd(const PaddedRVecVector *xold, PaddedRVecVector *xnew, const rvec acc_dir[],
+                           int homenr, real step)
 {
-    int  i;
+    const rvec *xo = as_rvec_array(xold->data());
+    rvec       *xn = as_rvec_array(xnew->data());
 
-    for (i = start; i < homenr; i++)
+    for (int i = 0; i < homenr; i++)
     {
-        do_1pos(xnew[i], xold[i], acc_dir[i], step);
+        do_1pos(xn[i], xo[i], acc_dir[i], step);
     }
 }
 
-static void shell_pos_sd(rvec xcur[], rvec xnew[], rvec f[],
+static void shell_pos_sd(const PaddedRVecVector * gmx_restrict xcur,
+                         PaddedRVecVector * gmx_restrict xnew,
+                         const PaddedRVecVector *f,
                          int ns, t_shell s[], int count)
 {
     const real step_scale_min       = 0.8,
@@ -747,8 +756,8 @@ static void shell_pos_sd(rvec xcur[], rvec xnew[], rvec f[],
         {
             for (d = 0; d < DIM; d++)
             {
-                dx = xcur[shell][d] - s[i].xold[d];
-                df =    f[shell][d] - s[i].fold[d];
+                dx = (*xcur)[shell][d] - s[i].xold[d];
+                df =    (*f)[shell][d] - s[i].fold[d];
                 /* -dx/df gets used to generate an interpolated value, but would
                  * cause a NaN if df were binary-equal to zero. Values close to
                  * zero won't cause problems (because of the min() and max()), so
@@ -782,18 +791,18 @@ static void shell_pos_sd(rvec xcur[], rvec xnew[], rvec f[],
 #endif
             }
         }
-        copy_rvec(xcur[shell], s[i].xold);
-        copy_rvec(f[shell],   s[i].fold);
+        copy_rvec((*xcur)[shell], s[i].xold);
+        copy_rvec((*f)[shell],   s[i].fold);
 
-        do_1pos3(xnew[shell], xcur[shell], f[shell], s[i].step);
+        do_1pos3((*xnew)[shell], (*xcur)[shell], (*f)[shell], s[i].step);
 
         if (gmx_debug_at)
         {
             fprintf(debug, "shell[%d] = %d\n", i, shell);
-            pr_rvec(debug, 0, "fshell", f[shell], DIM, TRUE);
-            pr_rvec(debug, 0, "xold", xcur[shell], DIM, TRUE);
+            pr_rvec(debug, 0, "fshell", (*f)[shell], DIM, TRUE);
+            pr_rvec(debug, 0, "xold", (*xcur)[shell], DIM, TRUE);
             pr_rvec(debug, 0, "step", s[i].step, DIM, TRUE);
-            pr_rvec(debug, 0, "xnew", xnew[shell], DIM, TRUE);
+            pr_rvec(debug, 0, "xnew", (*xnew)[shell], DIM, TRUE);
         }
     }
 #ifdef PRINT_STEP
@@ -829,19 +838,19 @@ static void print_epot(FILE *fp, gmx_int64_t mdstep, int count, real epot, real
 }
 
 
-static real rms_force(t_commrec *cr, rvec f[], int ns, t_shell s[],
+static real rms_force(t_commrec *cr, const PaddedRVecVector *force, int ns, t_shell s[],
                       int ndir, real *sf_dir, real *Epot)
 {
-    int    i, shell, ntot;
-    double buf[4];
+    double      buf[4];
+    const rvec *f = as_rvec_array(force->data());
 
     buf[0] = *sf_dir;
-    for (i = 0; i < ns; i++)
+    for (int i = 0; i < ns; i++)
     {
-        shell    = s[i].shell;
-        buf[0]  += norm2(f[shell]);
+        int shell  = s[i].shell;
+        buf[0]    += norm2(f[shell]);
     }
-    ntot = ns;
+    int ntot = ns;
 
     if (PAR(cr))
     {
@@ -858,7 +867,7 @@ static real rms_force(t_commrec *cr, rvec f[], int ns, t_shell s[],
     return (ntot ? std::sqrt(buf[0]/ntot) : 0);
 }
 
-static void check_pbc(FILE *fp, rvec x[], int shell)
+static void check_pbc(FILE *fp, PaddedRVecVector x, int shell)
 {
     int m, now;
 
@@ -867,13 +876,13 @@ static void check_pbc(FILE *fp, rvec x[], int shell)
     {
         if (fabs(x[shell][m]-x[now][m]) > 0.3)
         {
-            pr_rvecs(fp, 0, "SHELL-X", x+now, 5);
+            pr_rvecs(fp, 0, "SHELL-X", as_rvec_array(x.data())+now, 5);
             break;
         }
     }
 }
 
-static void dump_shells(FILE *fp, rvec x[], rvec f[], real ftol, int ns, t_shell s[])
+static void dump_shells(FILE *fp, PaddedRVecVector x, PaddedRVecVector f, real ftol, int ns, t_shell s[])
 {
     int  i, shell;
     real ft2, ff2;
@@ -896,11 +905,12 @@ static void dump_shells(FILE *fp, rvec x[], rvec f[], real ftol, int ns, t_shell
 static void init_adir(FILE *log, gmx_shellfc_t *shfc,
                       gmx_constr_t constr, t_idef *idef, t_inputrec *ir,
                       t_commrec *cr, int dd_ac1,
-                      gmx_int64_t step, t_mdatoms *md, int start, int end,
+                      gmx_int64_t step, t_mdatoms *md, int end,
                       rvec *x_old, rvec *x_init, rvec *x,
                       rvec *f, rvec *acc_dir,
                       gmx_bool bMolPBC, matrix box,
-                      real *lambda, real *dvdlambda, t_nrnb *nrnb)
+                      const std::vector<real> *lambda, real *dvdlambda,
+                      t_nrnb *nrnb)
 {
     rvec           *xnold, *xnew;
     double          dt, w_dt;
@@ -913,7 +923,7 @@ static void init_adir(FILE *log, gmx_shellfc_t *shfc,
     }
     else
     {
-        n = end - start;
+        n = end;
     }
     if (n > shfc->adir_nalloc)
     {
@@ -929,7 +939,7 @@ static void init_adir(FILE *log, gmx_shellfc_t *shfc,
     dt = ir->delta_t;
 
     /* Does NOT work with freeze or acceleration groups (yet) */
-    for (n = start; n < end; n++)
+    for (n = 0; n < end; n++)
     {
         w_dt = md->invmass[n]*dt;
 
@@ -937,31 +947,31 @@ static void init_adir(FILE *log, gmx_shellfc_t *shfc,
         {
             if ((ptype[n] != eptVSite) && (ptype[n] != eptShell))
             {
-                xnold[n-start][d] = x[n][d] - (x_init[n][d] - x_old[n][d]);
-                xnew[n-start][d]  = 2*x[n][d] - x_old[n][d] + f[n][d]*w_dt*dt;
+                xnold[n][d] = x[n][d] - (x_init[n][d] - x_old[n][d]);
+                xnew[n][d]  = 2*x[n][d] - x_old[n][d] + f[n][d]*w_dt*dt;
             }
             else
             {
-                xnold[n-start][d] = x[n][d];
-                xnew[n-start][d]  = x[n][d];
+                xnold[n][d] = x[n][d];
+                xnew[n][d]  = x[n][d];
             }
         }
     }
     constrain(log, FALSE, FALSE, constr, idef, ir, cr, step, 0, 1.0, md,
-              x, xnold-start, NULL, bMolPBC, box,
-              lambda[efptBONDED], &(dvdlambda[efptBONDED]),
+              x, xnold, NULL, bMolPBC, box,
+              (*lambda)[efptBONDED], &(dvdlambda[efptBONDED]),
               NULL, NULL, nrnb, econqCoord);
     constrain(log, FALSE, FALSE, constr, idef, ir, cr, step, 0, 1.0, md,
-              x, xnew-start, NULL, bMolPBC, box,
-              lambda[efptBONDED], &(dvdlambda[efptBONDED]),
+              x, xnew, NULL, bMolPBC, box,
+              (*lambda)[efptBONDED], &(dvdlambda[efptBONDED]),
               NULL, NULL, nrnb, econqCoord);
 
-    for (n = start; n < end; n++)
+    for (n = 0; n < end; n++)
     {
         for (d = 0; d < DIM; d++)
         {
-            xnew[n-start][d] =
-                -(2*x[n][d]-xnold[n-start][d]-xnew[n-start][d])/gmx::square(dt)
+            xnew[n][d] =
+                -(2*x[n][d]-xnold[n][d]-xnew[n][d])/gmx::square(dt)
                 - f[n][d]*md->invmass[n];
         }
         clear_rvec(acc_dir[n]);
@@ -969,8 +979,8 @@ static void init_adir(FILE *log, gmx_shellfc_t *shfc,
 
     /* Project the acceleration on the old bond directions */
     constrain(log, FALSE, FALSE, constr, idef, ir, cr, step, 0, 1.0, md,
-              x_old, xnew-start, acc_dir, bMolPBC, box,
-              lambda[efptBONDED], &(dvdlambda[efptBONDED]),
+              x_old, xnew, acc_dir, bMolPBC, box,
+              (*lambda)[efptBONDED], &(dvdlambda[efptBONDED]),
               NULL, NULL, nrnb, econqDeriv_FlexCon);
 }
 
@@ -980,7 +990,7 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
                          gmx_localtop_t *top,
                          gmx_constr_t constr,
                          gmx_enerdata_t *enerd, t_fcdata *fcd,
-                         t_state *state, rvec f[],
+                         t_state *state, PaddedRVecVector *f,
                          tensor force_vir,
                          t_mdatoms *md,
                          t_nrnb *nrnb, gmx_wallcycle_t wcycle,
@@ -996,14 +1006,14 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
     int        nshell;
     t_shell   *shell;
     t_idef    *idef;
-    rvec      *pos[2], *force[2], *acc_dir = NULL, *x_old = NULL;
+    rvec      *acc_dir = NULL, *x_old = NULL;
     real       Epot[2], df[2];
     real       sf_dir, invdt;
     real       ftol, dum = 0;
     char       sbuf[22];
     gmx_bool   bCont, bInit, bConverged;
     int        nat, dd_ac0, dd_ac1 = 0, i;
-    int        start = 0, homenr = md->homenr, end = start+homenr, cg0, cg1;
+    int        homenr = md->homenr, end = homenr, cg0, cg1;
     int        nflexcon, number_steps, d, Min = 0, count = 0;
 #define  Try (1-Min)             /* At start Try = 1 */
 
@@ -1031,20 +1041,19 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
         nat = state->natoms;
     }
 
-    if (nat > shfc->x_nalloc)
+    for (i = 0; (i < 2); i++)
     {
-        /* Allocate local arrays */
-        shfc->x_nalloc = over_alloc_dd(nat);
-        for (i = 0; (i < 2); i++)
-        {
-            srenew(shfc->x[i], shfc->x_nalloc);
-            srenew(shfc->f[i], shfc->x_nalloc);
-        }
+        shfc->x[i].resize(nat + 1);
+        shfc->f[i].resize(nat + 1);
     }
+
+    /* Create pointer that we can swap */
+    PaddedRVecVector *pos[2];
+    PaddedRVecVector *force[2];
     for (i = 0; (i < 2); i++)
     {
-        pos[i]   = shfc->x[i];
-        force[i] = shfc->f[i];
+        pos[i]   = &shfc->x[i];
+        force[i] = &shfc->f[i];
     }
 
     if (bDoNS && inputrec->ePBC != epbcNONE && !DOMAINDECOMP(cr))
@@ -1055,26 +1064,26 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
          */
         if (inputrec->cutoff_scheme == ecutsVERLET)
         {
-            put_atoms_in_box_omp(fr->ePBC, state->box, md->homenr, state->x);
+            put_atoms_in_box_omp(fr->ePBC, state->box, md->homenr, as_rvec_array(state->x.data()));
         }
         else
         {
             cg0 = 0;
             cg1 = top->cgs.nr;
             put_charge_groups_in_box(fplog, cg0, cg1, fr->ePBC, state->box,
-                                     &(top->cgs), state->x, fr->cg_cm);
+                                     &(top->cgs), as_rvec_array(state->x.data()), fr->cg_cm);
         }
 
         if (graph)
         {
-            mk_mshift(fplog, graph, fr->ePBC, state->box, state->x);
+            mk_mshift(fplog, graph, fr->ePBC, state->box, as_rvec_array(state->x.data()));
         }
     }
 
     /* After this all coordinate arrays will contain whole charge groups */
     if (graph)
     {
-        shift_self(graph, state->box, state->x);
+        shift_self(graph, state->box, as_rvec_array(state->x.data()));
     }
 
     if (nflexcon)
@@ -1092,7 +1101,7 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
             for (d = 0; d < DIM; d++)
             {
                 shfc->x_old[i][d] =
-                    state->x[start+i][d] - state->v[start+i][d]*inputrec->delta_t;
+                    state->x[i][d] - state->v[i][d]*inputrec->delta_t;
             }
         }
     }
@@ -1100,25 +1109,25 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
     /* Do a prediction of the shell positions */
     if (shfc->bPredict && !bCont)
     {
-        predict_shells(fplog, state->x, state->v, inputrec->delta_t, nshell, shell,
+        predict_shells(fplog, as_rvec_array(state->x.data()), as_rvec_array(state->v.data()), inputrec->delta_t, nshell, shell,
                        md->massT, NULL, bInit);
     }
 
     /* do_force expected the charge groups to be in the box */
     if (graph)
     {
-        unshift_self(graph, state->box, state->x);
+        unshift_self(graph, state->box, as_rvec_array(state->x.data()));
     }
 
     /* Calculate the forces first time around */
     if (gmx_debug_at)
     {
-        pr_rvecs(debug, 0, "x b4 do_force", state->x + start, homenr);
+        pr_rvecs(debug, 0, "x b4 do_force", as_rvec_array(state->x.data()), homenr);
     }
     do_force(fplog, cr, inputrec, mdstep, nrnb, wcycle, top, groups,
-             state->box, state->x, &state->hist,
+             state->box, &state->x, &state->hist,
              force[Min], force_vir, md, enerd, fcd,
-             state->lambda, graph,
+             &state->lambda, graph,
              fr, vsite, mu_tot, t, fp_field, NULL, bBornRadii,
              (bDoNS ? GMX_FORCE_NS : 0) | force_flags);
 
@@ -1126,20 +1135,20 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
     if (nflexcon)
     {
         init_adir(fplog, shfc,
-                  constr, idef, inputrec, cr, dd_ac1, mdstep, md, start, end,
-                  shfc->x_old-start, state->x, state->x, force[Min],
-                  shfc->acc_dir-start,
-                  fr->bMolPBC, state->box, state->lambda, &dum, nrnb);
+                  constr, idef, inputrec, cr, dd_ac1, mdstep, md, end,
+                  shfc->x_old, as_rvec_array(state->x.data()), as_rvec_array(state->x.data()), as_rvec_array(force[Min]->data()),
+                  shfc->acc_dir,
+                  fr->bMolPBC, state->box, &state->lambda, &dum, nrnb);
 
-        for (i = start; i < end; i++)
+        for (i = 0; i < end; i++)
         {
-            sf_dir += md->massT[i]*norm2(shfc->acc_dir[i-start]);
+            sf_dir += md->massT[i]*norm2(shfc->acc_dir[i]);
         }
     }
 
     Epot[Min] = enerd->term[F_EPOT];
 
-    df[Min] = rms_force(cr, shfc->f[Min], nshell, shell, nflexcon, &sf_dir, &Epot[Min]);
+    df[Min] = rms_force(cr, &shfc->f[Min], nshell, shell, nflexcon, &sf_dir, &Epot[Min]);
     df[Try] = 0;
     if (debug)
     {
@@ -1148,7 +1157,7 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
 
     if (gmx_debug_at)
     {
-        pr_rvecs(debug, 0, "force0", force[Min], md->nr);
+        pr_rvecs(debug, 0, "force0", as_rvec_array(force[Min]->data()), md->nr);
     }
 
     if (nshell+nflexcon > 0)
@@ -1157,8 +1166,8 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
          * shell positions are updated, therefore the other particles must
          * be set here.
          */
-        memcpy(pos[Min], state->x, nat*sizeof(state->x[0]));
-        memcpy(pos[Try], state->x, nat*sizeof(state->x[0]));
+        *pos[Min] = state->x;
+        *pos[Try] = state->x;
     }
 
     if (bVerbose && MASTER(cr))
@@ -1186,7 +1195,8 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
     {
         if (vsite)
         {
-            construct_vsites(vsite, pos[Min], inputrec->delta_t, state->v,
+            construct_vsites(vsite, as_rvec_array(pos[Min]->data()),
+                             inputrec->delta_t, as_rvec_array(state->v.data()),
                              idef->iparams, idef->il,
                              fr->ePBC, fr->bMolPBC, cr, state->box);
         }
@@ -1194,12 +1204,11 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
         if (nflexcon)
         {
             init_adir(fplog, shfc,
-                      constr, idef, inputrec, cr, dd_ac1, mdstep, md, start, end,
-                      x_old-start, state->x, pos[Min], force[Min], acc_dir-start,
-                      fr->bMolPBC, state->box, state->lambda, &dum, nrnb);
+                      constr, idef, inputrec, cr, dd_ac1, mdstep, md, end,
+                      x_old, as_rvec_array(state->x.data()), as_rvec_array(pos[Min]->data()), as_rvec_array(force[Min]->data()), acc_dir,
+                      fr->bMolPBC, state->box, &state->lambda, &dum, nrnb);
 
-            directional_sd(pos[Min], pos[Try], acc_dir-start, start, end,
-                           fr->fc_stepsize);
+            directional_sd(pos[Min], pos[Try], acc_dir, end, fr->fc_stepsize);
         }
 
         /* New positions, Steepest descent */
@@ -1208,38 +1217,38 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
         /* do_force expected the charge groups to be in the box */
         if (graph)
         {
-            unshift_self(graph, state->box, pos[Try]);
+            unshift_self(graph, state->box, as_rvec_array(pos[Try]->data()));
         }
 
         if (gmx_debug_at)
         {
-            pr_rvecs(debug, 0, "RELAX: pos[Min]  ", pos[Min] + start, homenr);
-            pr_rvecs(debug, 0, "RELAX: pos[Try]  ", pos[Try] + start, homenr);
+            pr_rvecs(debug, 0, "RELAX: pos[Min]  ", as_rvec_array(pos[Min]->data()), homenr);
+            pr_rvecs(debug, 0, "RELAX: pos[Try]  ", as_rvec_array(pos[Try]->data()), homenr);
         }
         /* Try the new positions */
         do_force(fplog, cr, inputrec, 1, nrnb, wcycle,
                  top, groups, state->box, pos[Try], &state->hist,
                  force[Try], force_vir,
-                 md, enerd, fcd, state->lambda, graph,
+                 md, enerd, fcd, &state->lambda, graph,
                  fr, vsite, mu_tot, t, fp_field, NULL, bBornRadii,
                  force_flags);
 
         if (gmx_debug_at)
         {
-            pr_rvecs(debug, 0, "RELAX: force[Min]", force[Min] + start, homenr);
-            pr_rvecs(debug, 0, "RELAX: force[Try]", force[Try] + start, homenr);
+            pr_rvecs(debug, 0, "RELAX: force[Min]", as_rvec_array(force[Min]->data()), homenr);
+            pr_rvecs(debug, 0, "RELAX: force[Try]", as_rvec_array(force[Try]->data()), homenr);
         }
         sf_dir = 0;
         if (nflexcon)
         {
             init_adir(fplog, shfc,
-                      constr, idef, inputrec, cr, dd_ac1, mdstep, md, start, end,
-                      x_old-start, state->x, pos[Try], force[Try], acc_dir-start,
-                      fr->bMolPBC, state->box, state->lambda, &dum, nrnb);
+                      constr, idef, inputrec, cr, dd_ac1, mdstep, md, end,
+                      x_old, as_rvec_array(state->x.data()), as_rvec_array(pos[Try]->data()), as_rvec_array(force[Try]->data()), acc_dir,
+                      fr->bMolPBC, state->box, &state->lambda, &dum, nrnb);
 
-            for (i = start; i < end; i++)
+            for (i = 0; i < end; i++)
             {
-                sf_dir += md->massT[i]*norm2(acc_dir[i-start]);
+                sf_dir += md->massT[i]*norm2(acc_dir[i]);
             }
         }
 
@@ -1256,12 +1265,12 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
         {
             if (gmx_debug_at)
             {
-                pr_rvecs(debug, 0, "F na do_force", force[Try] + start, homenr);
+                pr_rvecs(debug, 0, "F na do_force", as_rvec_array(force[Try]->data()), homenr);
             }
             if (gmx_debug_at)
             {
                 fprintf(debug, "SHELL ITER %d\n", count);
-                dump_shells(debug, pos[Try], force[Try], ftol, nshell, shell);
+                dump_shells(debug, *pos[Try], *force[Try], ftol, nshell, shell);
             }
         }
 
@@ -1282,7 +1291,7 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
             {
                 /* Correct the velocities for the flexible constraints */
                 invdt = 1/inputrec->delta_t;
-                for (i = start; i < end; i++)
+                for (i = 0; i < end; i++)
                 {
                     for (d = 0; d < DIM; d++)
                     {
@@ -1317,8 +1326,8 @@ void relax_shell_flexcon(FILE *fplog, t_commrec *cr, gmx_bool bVerbose,
     }
 
     /* Copy back the coordinates and the forces */
-    memcpy(state->x, pos[Min], nat*sizeof(state->x[0]));
-    memcpy(f, force[Min], nat*sizeof(f[0]));
+    state->x = *pos[Min];
+    *f       = *force[Min];
 }
 
 void done_shellfc(FILE *fplog, gmx_shellfc_t *shfc, gmx_int64_t numSteps)
index 11581d0f9b2ec72ccf81aef30eefd003af17390d..0fb154e2146dba7702feb3c863ced44cf342c2bc 100644 (file)
@@ -40,6 +40,7 @@
 #include <cstdio>
 
 #include "gromacs/mdlib/vsite.h"
+#include "gromacs/mdtypes/state.h"
 #include "gromacs/timing/wallcycle.h"
 
 struct gmx_constr;
@@ -71,7 +72,7 @@ void relax_shell_flexcon(FILE *log, t_commrec *cr, gmx_bool bVerbose,
                          gmx_localtop_t *top,
                          gmx_constr *constr,
                          gmx_enerdata_t *enerd, t_fcdata *fcd,
-                         t_state *state, rvec f[],
+                         t_state *state, PaddedRVecVector *f,
                          tensor force_vir,
                          t_mdatoms *md,
                          t_nrnb *nrnb, gmx_wallcycle_t wcycle,
index 7311afcaec0f8f46496c0f1e9b74bdc8c3318257..5e7a41bbda3cfca3d8941e711cc95acf0e38da01 100644 (file)
@@ -1923,12 +1923,12 @@ void do_force(FILE *fplog, t_commrec *cr,
               gmx_int64_t step, t_nrnb *nrnb, gmx_wallcycle_t wcycle,
               gmx_localtop_t *top,
               gmx_groups_t *groups,
-              matrix box, rvec x[], history_t *hist,
-              rvec f[],
+              matrix box, PaddedRVecVector *coordinates, history_t *hist,
+              PaddedRVecVector *force,
               tensor vir_force,
               t_mdatoms *mdatoms,
               gmx_enerdata_t *enerd, t_fcdata *fcd,
-              real *lambda, t_graph *graph,
+              std::vector<real> *lambda, t_graph *graph,
               t_forcerec *fr,
               gmx_vsite_t *vsite, rvec mu_tot,
               double t, FILE *field, gmx_edsam_t ed,
@@ -1941,6 +1941,12 @@ void do_force(FILE *fplog, t_commrec *cr,
         flags &= ~GMX_FORCE_NONBONDED;
     }
 
+    GMX_ASSERT(coordinates->size() >= static_cast<unsigned int>(fr->natoms_force + 1), "We might need 1 element extra for SIMD");
+    GMX_ASSERT(force->size() >= static_cast<unsigned int>(fr->natoms_force + 1), "We might need 1 element extra for SIMD");
+
+    rvec *x = as_rvec_array(coordinates->data());
+    rvec *f = as_rvec_array(force->data());
+
     switch (inputrec->cutoff_scheme)
     {
         case ecutsVERLET:
@@ -1952,7 +1958,7 @@ void do_force(FILE *fplog, t_commrec *cr,
                                 f, vir_force,
                                 mdatoms,
                                 enerd, fcd,
-                                lambda, graph,
+                                lambda->data(), graph,
                                 fr, fr->ic,
                                 vsite, mu_tot,
                                 t, field, ed,
@@ -1968,7 +1974,7 @@ void do_force(FILE *fplog, t_commrec *cr,
                                f, vir_force,
                                mdatoms,
                                enerd, fcd,
-                               lambda, graph,
+                               lambda->data(), graph,
                                fr, vsite, mu_tot,
                                t, field, ed,
                                bBornRadii,
@@ -2017,7 +2023,7 @@ void do_constrain_first(FILE *fplog, gmx_constr_t constr,
     /* constrain the current position */
     constrain(NULL, TRUE, FALSE, constr, &(top->idef),
               ir, cr, step, 0, 1.0, md,
-              state->x, state->x, NULL,
+              as_rvec_array(state->x.data()), as_rvec_array(state->x.data()), NULL,
               fr->bMolPBC, state->box,
               state->lambda[efptBONDED], &dvdl_dum,
               NULL, NULL, nrnb, econqCoord);
@@ -2027,7 +2033,7 @@ void do_constrain_first(FILE *fplog, gmx_constr_t constr,
         /* also may be useful if we need the ekin from the halfstep for velocity verlet */
         constrain(NULL, TRUE, FALSE, constr, &(top->idef),
                   ir, cr, step, 0, 1.0, md,
-                  state->x, state->v, state->v,
+                  as_rvec_array(state->x.data()), as_rvec_array(state->v.data()), as_rvec_array(state->v.data()),
                   fr->bMolPBC, state->box,
                   state->lambda[efptBONDED], &dvdl_dum,
                   NULL, NULL, nrnb, econqVeloc);
@@ -2057,10 +2063,10 @@ void do_constrain_first(FILE *fplog, gmx_constr_t constr,
         dvdl_dum = 0;
         constrain(NULL, TRUE, FALSE, constr, &(top->idef),
                   ir, cr, step, -1, 1.0, md,
-                  state->x, savex, NULL,
+                  as_rvec_array(state->x.data()), savex, NULL,
                   fr->bMolPBC, state->box,
                   state->lambda[efptBONDED], &dvdl_dum,
-                  state->v, NULL, nrnb, econqCoord);
+                  as_rvec_array(state->v.data()), NULL, nrnb, econqCoord);
 
         for (i = start; i < end; i++)
         {
@@ -2648,60 +2654,51 @@ void finish_run(FILE *fplog, const gmx::MDLogger &mdlog, t_commrec *cr,
     }
 }
 
-extern void initialize_lambdas(FILE *fplog, t_inputrec *ir, int *fep_state, real *lambda, double *lam0)
+extern void initialize_lambdas(FILE *fplog, t_inputrec *ir, int *fep_state, std::vector<real> *lambda, double *lam0)
 {
     /* this function works, but could probably use a logic rewrite to keep all the different
        types of efep straight. */
 
-    int       i;
+    if ((ir->efep == efepNO) && (ir->bSimTemp == FALSE))
+    {
+        return;
+    }
+
     t_lambda *fep = ir->fepvals;
+    *fep_state    = fep->init_fep_state; /* this might overwrite the checkpoint
+                                            if checkpoint is set -- a kludge is in for now
+                                            to prevent this.*/
 
-    if ((ir->efep == efepNO) && (ir->bSimTemp == FALSE))
+    lambda->resize(efptNR);
+
+    for (int i = 0; i < efptNR; i++)
     {
-        for (i = 0; i < efptNR; i++)
+        /* overwrite lambda state with init_lambda for now for backwards compatibility */
+        if (fep->init_lambda >= 0) /* if it's -1, it was never initializd */
         {
-            lambda[i] = 0.0;
+            (*lambda)[i] = fep->init_lambda;
             if (lam0)
             {
-                lam0[i] = 0.0;
+                lam0[i] = (*lambda)[i];
             }
         }
-        return;
-    }
-    else
-    {
-        *fep_state = fep->init_fep_state; /* this might overwrite the checkpoint
-                                             if checkpoint is set -- a kludge is in for now
-                                             to prevent this.*/
-        for (i = 0; i < efptNR; i++)
+        else
         {
-            /* overwrite lambda state with init_lambda for now for backwards compatibility */
-            if (fep->init_lambda >= 0) /* if it's -1, it was never initializd */
+            (*lambda)[i] = fep->all_lambda[i][*fep_state];
+            if (lam0)
             {
-                lambda[i] = fep->init_lambda;
-                if (lam0)
-                {
-                    lam0[i] = lambda[i];
-                }
-            }
-            else
-            {
-                lambda[i] = fep->all_lambda[i][*fep_state];
-                if (lam0)
-                {
-                    lam0[i] = lambda[i];
-                }
+                lam0[i] = (*lambda)[i];
             }
         }
-        if (ir->bSimTemp)
+    }
+    if (ir->bSimTemp)
+    {
+        /* need to rescale control temperatures to match current state */
+        for (int i = 0; i < ir->opts.ngtc; i++)
         {
-            /* need to rescale control temperatures to match current state */
-            for (i = 0; i < ir->opts.ngtc; i++)
+            if (ir->opts.ref_t[i] > 0)
             {
-                if (ir->opts.ref_t[i] > 0)
-                {
-                    ir->opts.ref_t[i] = ir->simtempvals->temperatures[*fep_state];
-                }
+                ir->opts.ref_t[i] = ir->simtempvals->temperatures[*fep_state];
             }
         }
     }
@@ -2710,9 +2707,9 @@ extern void initialize_lambdas(FILE *fplog, t_inputrec *ir, int *fep_state, real
     if (fplog != NULL)
     {
         fprintf(fplog, "Initial vector of lambda components:[ ");
-        for (i = 0; i < efptNR; i++)
+        for (int i = 0; i < efptNR; i++)
         {
-            fprintf(fplog, "%10.4f ", lambda[i]);
+            fprintf(fplog, "%10.4f ", (*lambda)[i]);
         }
         fprintf(fplog, "]\n");
     }
@@ -2723,7 +2720,7 @@ extern void initialize_lambdas(FILE *fplog, t_inputrec *ir, int *fep_state, real
 void init_md(FILE *fplog,
              t_commrec *cr, t_inputrec *ir, const gmx_output_env_t *oenv,
              double *t, double *t0,
-             real *lambda, int *fep_state, double *lam0,
+             std::vector<real> *lambda, int *fep_state, double *lam0,
              t_nrnb *nrnb, gmx_mtop_t *mtop,
              gmx_update_t **upd,
              int nfile, const t_filenm fnm[],
index dc91aaa27211e667ad4656acf9d73284084d3c74..0b969c514e1bf98a1eb75434be1af6b741899d4f 100644 (file)
@@ -135,7 +135,7 @@ void calc_dispcorr(t_inputrec *ir, t_forcerec *fr,
                    matrix box, real lambda, tensor pres, tensor virial,
                    real *prescorr, real *enercorr, real *dvdlcorr);
 
-void initialize_lambdas(FILE *fplog, t_inputrec *ir, int *fep_state, real *lambda, double *lam0);
+void initialize_lambdas(FILE *fplog, t_inputrec *ir, int *fep_state, std::vector<real> *lambda, double *lam0);
 
 void do_constrain_first(FILE *log, gmx_constr *constr,
                         t_inputrec *inputrec, t_mdatoms *md,
@@ -145,7 +145,7 @@ void do_constrain_first(FILE *log, gmx_constr *constr,
 void init_md(FILE *fplog,
              t_commrec *cr, t_inputrec *ir, const gmx_output_env_t *oenv,
              double *t, double *t0,
-             real *lambda, int *fep_state, double *lam0,
+             std::vector<real> *lambda, int *fep_state, double *lam0,
              t_nrnb *nrnb, gmx_mtop_t *mtop,
              gmx_update_t **upd,
              int nfile, const t_filenm fnm[],
index 085ce7af7fee931f4ecf21e2fb5305aa7076aac0..98c2d353d53d20564996cd825005bda430f337db 100644 (file)
@@ -165,35 +165,35 @@ double do_tpi(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
               unsigned long gmx_unused Flags,
               gmx_walltime_accounting_t walltime_accounting)
 {
-    gmx_localtop_t *top;
-    gmx_groups_t   *groups;
-    gmx_enerdata_t *enerd;
-    rvec           *f;
-    real            lambda, t, temp, beta, drmax, epot;
-    double          embU, sum_embU, *sum_UgembU, V, V_all, VembU_all;
-    t_trxstatus    *status;
-    t_trxframe      rerun_fr;
-    gmx_bool        bDispCorr, bCharge, bRFExcl, bNotLastFrame, bStateChanged, bNS;
-    tensor          force_vir, shake_vir, vir, pres;
-    int             cg_tp, a_tp0, a_tp1, ngid, gid_tp, nener, e;
-    rvec           *x_mol;
-    rvec            mu_tot, x_init, dx, x_tp;
-    int             nnodes, frame;
-    gmx_int64_t     frame_step_prev, frame_step;
-    gmx_int64_t     nsteps, stepblocksize = 0, step;
-    gmx_int64_t     seed;
-    int             i;
-    FILE           *fp_tpi = NULL;
-    char           *ptr, *dump_pdb, **leg, str[STRLEN], str2[STRLEN];
-    double          dbl, dump_ener;
-    gmx_bool        bCavity;
-    int             nat_cavity  = 0, d;
-    real           *mass_cavity = NULL, mass_tot;
-    int             nbin;
-    double          invbinw, *bin, refvolshift, logV, bUlogV;
-    real            prescorr, enercorr, dvdlcorr;
-    gmx_bool        bEnergyOutOfBounds;
-    const char     *tpid_leg[2] = {"direct", "reweighted"};
+    gmx_localtop_t  *top;
+    gmx_groups_t    *groups;
+    gmx_enerdata_t  *enerd;
+    PaddedRVecVector f {};
+    real             lambda, t, temp, beta, drmax, epot;
+    double           embU, sum_embU, *sum_UgembU, V, V_all, VembU_all;
+    t_trxstatus     *status;
+    t_trxframe       rerun_fr;
+    gmx_bool         bDispCorr, bCharge, bRFExcl, bNotLastFrame, bStateChanged, bNS;
+    tensor           force_vir, shake_vir, vir, pres;
+    int              cg_tp, a_tp0, a_tp1, ngid, gid_tp, nener, e;
+    rvec            *x_mol;
+    rvec             mu_tot, x_init, dx, x_tp;
+    int              nnodes, frame;
+    gmx_int64_t      frame_step_prev, frame_step;
+    gmx_int64_t      nsteps, stepblocksize = 0, step;
+    gmx_int64_t      seed;
+    int              i;
+    FILE            *fp_tpi = NULL;
+    char            *ptr, *dump_pdb, **leg, str[STRLEN], str2[STRLEN];
+    double           dbl, dump_ener;
+    gmx_bool         bCavity;
+    int              nat_cavity  = 0, d;
+    real            *mass_cavity = NULL, mass_tot;
+    int              nbin;
+    double           invbinw, *bin, refvolshift, logV, bUlogV;
+    real             prescorr, enercorr, dvdlcorr;
+    gmx_bool         bEnergyOutOfBounds;
+    const char      *tpid_leg[2] = {"direct", "reweighted"};
 
     /* Since there is no upper limit to the insertion energies,
      * we need to set an upper limit for the distribution output.
@@ -289,7 +289,7 @@ double do_tpi(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
 
     snew(enerd, 1);
     init_enerdata(groups->grps[egcENER].nr, inputrec->fepvals->n_lambda, enerd);
-    snew(f, top_global->natoms);
+    f.resize(top_global->natoms + 1);
 
     /* Print to log file  */
     walltime_accounting_start(walltime_accounting);
@@ -321,7 +321,7 @@ double do_tpi(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
     }
     bRFExcl = (bCharge && EEL_RF(fr->eeltype));
 
-    calc_cgcm(fplog, cg_tp, cg_tp+1, &(top->cgs), state_global->x, fr->cg_cm);
+    calc_cgcm(fplog, cg_tp, cg_tp+1, &(top->cgs), as_rvec_array(state_global->x.data()), fr->cg_cm);
     if (bCavity)
     {
         if (norm(fr->cg_cm[cg_tp]) > 0.5*inputrec->rlist && fplog)
@@ -629,7 +629,7 @@ double do_tpi(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
                     copy_rvec(x_mol[i-a_tp0], state_global->x[i]);
                 }
                 /* Rotate the molecule randomly */
-                rotate_conf(a_tp1-a_tp0, state_global->x+a_tp0, NULL,
+                rotate_conf(a_tp1-a_tp0, as_rvec_array(state_global->x.data())+a_tp0, NULL,
                             2*M_PI*dist(rng),
                             2*M_PI*dist(rng),
                             2*M_PI*dist(rng));
@@ -659,9 +659,9 @@ double do_tpi(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
             cr->nnodes = 1;
             do_force(fplog, cr, inputrec,
                      step, nrnb, wcycle, top, &top_global->groups,
-                     state_global->box, state_global->x, &state_global->hist,
-                     f, force_vir, mdatoms, enerd, fcd,
-                     state_global->lambda,
+                     state_global->box, &state_global->x, &state_global->hist,
+                     &f, force_vir, mdatoms, enerd, fcd,
+                     &state_global->lambda,
                      NULL, fr, NULL, mu_tot, t, NULL, NULL, FALSE,
                      GMX_FORCE_NONBONDED | GMX_FORCE_ENERGY |
                      (bNS ? GMX_FORCE_DYNAMICBOX | GMX_FORCE_NS : 0) |
@@ -782,7 +782,7 @@ double do_tpi(FILE *fplog, t_commrec *cr, const gmx::MDLogger gmx_unused &mdlog,
             {
                 sprintf(str, "t%g_step%d.pdb", t, (int)step);
                 sprintf(str2, "t: %f step %d ener: %f", t, (int)step, epot);
-                write_sto_conf_mtop(str, str2, top_global, state_global->x, state_global->v,
+                write_sto_conf_mtop(str, str2, top_global, as_rvec_array(state_global->x.data()), as_rvec_array(state_global->v.data()),
                                     inputrec->ePBC, state_global->box);
             }
 
index d210d731c5f4e02c7bb2bc88bc9bbb8e6b5573a1..619ea5e40013f45bbc9c6f86441dcfa6c2595f33 100644 (file)
 #include "gromacs/utility/smalloc.h"
 
 void
-do_md_trajectory_writing(FILE           *fplog,
-                         t_commrec      *cr,
-                         int             nfile,
-                         const t_filenm  fnm[],
-                         gmx_int64_t     step,
-                         gmx_int64_t     step_rel,
-                         double          t,
-                         t_inputrec     *ir,
-                         t_state        *state,
-                         t_state        *state_global,
-                         gmx_mtop_t     *top_global,
-                         t_forcerec     *fr,
-                         gmx_mdoutf_t    outf,
-                         t_mdebin       *mdebin,
-                         gmx_ekindata_t *ekind,
-                         rvec           *f,
-                         int            *nchkpt,
-                         gmx_bool        bCPT,
-                         gmx_bool        bRerunMD,
-                         gmx_bool        bLastStep,
-                         gmx_bool        bDoConfOut,
-                         gmx_bool        bSumEkinhOld
+do_md_trajectory_writing(FILE             *fplog,
+                         t_commrec        *cr,
+                         int               nfile,
+                         const t_filenm    fnm[],
+                         gmx_int64_t       step,
+                         gmx_int64_t       step_rel,
+                         double            t,
+                         t_inputrec       *ir,
+                         t_state          *state,
+                         t_state          *state_global,
+                         gmx_mtop_t       *top_global,
+                         t_forcerec       *fr,
+                         gmx_mdoutf_t      outf,
+                         t_mdebin         *mdebin,
+                         gmx_ekindata_t   *ekind,
+                         PaddedRVecVector *f,
+                         int              *nchkpt,
+                         gmx_bool          bCPT,
+                         gmx_bool          bRerunMD,
+                         gmx_bool          bLastStep,
+                         gmx_bool          bDoConfOut,
+                         gmx_bool          bSumEkinhOld
                          )
 {
     int   mdof_flags;
@@ -152,7 +152,7 @@ do_md_trajectory_writing(FILE           *fplog,
             bDoConfOut && MASTER(cr) &&
             !bRerunMD)
         {
-            if (fr->bMolPBC && state->x == state_global->x)
+            if (fr->bMolPBC && state == state_global)
             {
                 /* This (single-rank) run needs to allocate a
                    temporary array of size natoms so that any
@@ -162,13 +162,13 @@ do_md_trajectory_writing(FILE           *fplog,
                    identical, and makes .edr restarts binary
                    identical. */
                 snew(x_for_confout, state_global->natoms);
-                copy_rvecn(state_global->x, x_for_confout, 0, state_global->natoms);
+                copy_rvecn(as_rvec_array(state_global->x.data()), x_for_confout, 0, state_global->natoms);
             }
             else
             {
                 /* With DD, or no bMolPBC, it doesn't matter if
-                   we change state_global->x */
-                x_for_confout = state_global->x;
+                   we change as_rvec_array(state_global->x.data()) */
+                x_for_confout = as_rvec_array(state_global->x.data());
             }
 
             /* x and v have been collected in mdoutf_write_to_trajectory_files,
@@ -183,9 +183,9 @@ do_md_trajectory_writing(FILE           *fplog,
             }
             write_sto_conf_mtop(ftp2fn(efSTO, nfile, fnm),
                                 *top_global->name, top_global,
-                                x_for_confout, state_global->v,
+                                x_for_confout, as_rvec_array(state_global->v.data()),
                                 ir->ePBC, state->box);
-            if (fr->bMolPBC && state->x == state_global->x)
+            if (fr->bMolPBC && state == state_global)
             {
                 sfree(x_for_confout);
             }
index f9edb57e83020c896e52518f9c77a154eafa8fdb..310e7b437c0ed6f9423d98b50706f4c6b4d86d04 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 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.
@@ -72,7 +72,7 @@ do_md_trajectory_writing(FILE                     *fplog,
                          gmx_mdoutf_t              outf,
                          t_mdebin                 *mdebin,
                          struct gmx_ekindata_t    *ekind,
-                         rvec                     *f,
+                         PaddedRVecVector         *f,
                          int                      *nchkpt,
                          gmx_bool                  bCPT,
                          gmx_bool                  bRerunMD,
index cc01f266c007e30ea5691bdc99942026f6c9950c..de6e471dbe1eac4e1e3c8fff57c7dade33d9d7b1 100644 (file)
@@ -102,14 +102,13 @@ typedef struct {
 
 struct gmx_update_t
 {
-    gmx_stochd_t *sd;
+    gmx_stochd_t     *sd;
     /* xprime for constraint algorithms */
-    rvec         *xp;
-    int           xp_nalloc;
+    PaddedRVecVector  xp;
 
     /* Variables for the deform algorithm */
-    gmx_int64_t     deformref_step;
-    matrix          deformref_box;
+    gmx_int64_t       deformref_step;
+    matrix            deformref_box;
 };
 
 
@@ -122,8 +121,8 @@ static void do_update_md(int start, int nrend,
                          real invmass[],
                          unsigned short ptype[], unsigned short cFREEZE[],
                          unsigned short cACC[], unsigned short cTC[],
-                         rvec x[], rvec xprime[], rvec v[],
-                         rvec f[], matrix M,
+                         const rvec x[], rvec xprime[], rvec v[],
+                         const rvec f[], matrix M,
                          gmx_bool bNH, gmx_bool bPR)
 {
     double imass, w_dt;
@@ -261,7 +260,7 @@ static void do_update_md(int start, int nrend,
 static void do_update_vv_vel(int start, int nrend, double dt,
                              rvec accel[], ivec nFreeze[], real invmass[],
                              unsigned short ptype[], unsigned short cFREEZE[],
-                             unsigned short cACC[], rvec v[], rvec f[],
+                             unsigned short cACC[], rvec v[], const rvec f[],
                              gmx_bool bExtended, real veta, real alpha)
 {
     double w_dt;
@@ -309,7 +308,7 @@ static void do_update_vv_vel(int start, int nrend, double dt,
 static void do_update_vv_pos(int start, int nrend, double dt,
                              ivec nFreeze[],
                              unsigned short ptype[], unsigned short cFREEZE[],
-                             rvec x[], rvec xprime[], rvec v[],
+                             const rvec x[], rvec xprime[], rvec v[],
                              gmx_bool bExtended, real veta)
 {
     int    gf = 0;
@@ -357,8 +356,8 @@ static void do_update_visc(int start, int nrend,
                            double nh_vxi[],
                            real invmass[],
                            unsigned short ptype[], unsigned short cTC[],
-                           rvec x[], rvec xprime[], rvec v[],
-                           rvec f[], matrix M, matrix box, real
+                           const rvec x[], rvec xprime[], rvec v[],
+                           const rvec f[], matrix M, matrix box, real
                            cos_accel, real vcos,
                            gmx_bool bNH, gmx_bool bPR)
 {
@@ -550,9 +549,7 @@ void update_temperature_constants(gmx_update_t *upd, const t_inputrec *ir)
 
 gmx_update_t *init_update(const t_inputrec *ir)
 {
-    gmx_update_t *upd;
-
-    snew(upd, 1);
+    gmx_update_t *upd = new(gmx_update_t);
 
     if (ir->eI == eiBD || EI_SD(ir->eI) || ir->etc == etcVRESCALE || ETC_ANDERSEN(ir->etc))
     {
@@ -561,22 +558,18 @@ gmx_update_t *init_update(const t_inputrec *ir)
 
     update_temperature_constants(upd, ir);
 
-    upd->xp        = NULL;
-    upd->xp_nalloc = 0;
+    upd->xp.resize(0);
 
     return upd;
 }
 
-void update_realloc(gmx_update_t *upd, int state_nalloc)
+void update_realloc(gmx_update_t *upd, int natoms)
 {
     GMX_ASSERT(upd, "upd must be allocated before its fields can be reallocated");
-    if (state_nalloc > upd->xp_nalloc)
-    {
-        upd->xp_nalloc = state_nalloc;
-        /* We need to allocate one element extra, since we might use
-         * (unaligned) 4-wide SIMD loads to access rvec entries. */
-        srenew(upd->xp, upd->xp_nalloc + 1);
-    }
+
+    /* We need to allocate one element extra, since we might use
+     * (unaligned) 4-wide SIMD loads to access rvec entries. */
+    upd->xp.resize(natoms + 1);
 }
 
 static void do_update_sd1(gmx_stochd_t *sd,
@@ -585,7 +578,7 @@ static void do_update_sd1(gmx_stochd_t *sd,
                           real invmass[], unsigned short ptype[],
                           unsigned short cFREEZE[], unsigned short cACC[],
                           unsigned short cTC[],
-                          rvec x[], rvec xprime[], rvec v[], rvec f[],
+                          const rvec x[], rvec xprime[], rvec v[], const rvec f[],
                           gmx_bool bDoConstr,
                           gmx_bool bFirstHalfConstr,
                           gmx_int64_t step, int seed, int* gatindex)
@@ -728,8 +721,8 @@ static void do_update_bd(int start, int nrend, double dt,
                          ivec nFreeze[],
                          real invmass[], unsigned short ptype[],
                          unsigned short cFREEZE[], unsigned short cTC[],
-                         rvec x[], rvec xprime[], rvec v[],
-                         rvec f[], real friction_coefficient,
+                         const rvec x[], rvec xprime[], rvec v[],
+                         const rvec f[], real friction_coefficient,
                          real *rf, gmx_int64_t step, int seed,
                          int* gatindex)
 {
@@ -791,17 +784,23 @@ static void do_update_bd(int start, int nrend, double dt,
 }
 
 static void dump_it_all(FILE gmx_unused *fp, const char gmx_unused *title,
-                        int gmx_unused natoms, rvec gmx_unused x[], rvec gmx_unused xp[],
-                        rvec gmx_unused v[], rvec gmx_unused f[])
+                        int gmx_unused natoms,
+                        const gmx_unused PaddedRVecVector *x,
+                        const gmx_unused PaddedRVecVector *xp,
+                        const gmx_unused PaddedRVecVector *v,
+                        const gmx_unused PaddedRVecVector *f)
 {
 #ifdef DEBUG
     if (fp)
     {
         fprintf(fp, "%s\n", title);
-        pr_rvecs(fp, 0, "x", x, natoms);
-        pr_rvecs(fp, 0, "xp", xp, natoms);
-        pr_rvecs(fp, 0, "v", v, natoms);
-        pr_rvecs(fp, 0, "f", f, natoms);
+        pr_rvecs(fp, 0, "x", as_rvec_array(x->data()), natoms);
+        pr_rvecs(fp, 0, "xp", as_rvec_array(xp->data()), natoms);
+        pr_rvecs(fp, 0, "v", as_rvec_array(v->data()), natoms);
+        if (f != NULL)
+        {
+            pr_rvecs(fp, 0, "f", as_rvec_array(f->data()), natoms);
+        }
     }
 #endif
 }
@@ -1000,11 +999,11 @@ void calc_ke_part(t_state *state, t_grpopts *opts, t_mdatoms *md,
 {
     if (ekind->cosacc.cos_accel == 0)
     {
-        calc_ke_part_normal(state->v, opts, md, ekind, nrnb, bEkinAveVel);
+        calc_ke_part_normal(as_rvec_array(state->v.data()), opts, md, ekind, nrnb, bEkinAveVel);
     }
     else
     {
-        calc_ke_part_visc(state->box, state->x, state->v, opts, md, ekind, nrnb, bEkinAveVel);
+        calc_ke_part_visc(state->box, as_rvec_array(state->x.data()), as_rvec_array(state->v.data()), opts, md, ekind, nrnb, bEkinAveVel);
     }
 }
 
@@ -1014,9 +1013,9 @@ extern void init_ekinstate(ekinstate_t *ekinstate, const t_inputrec *ir)
     snew(ekinstate->ekinh, ekinstate->ekin_n);
     snew(ekinstate->ekinf, ekinstate->ekin_n);
     snew(ekinstate->ekinh_old, ekinstate->ekin_n);
-    snew(ekinstate->ekinscalef_nhc, ekinstate->ekin_n);
-    snew(ekinstate->ekinscaleh_nhc, ekinstate->ekin_n);
-    snew(ekinstate->vscale_nhc, ekinstate->ekin_n);
+    ekinstate->ekinscalef_nhc.resize(ekinstate->ekin_n);
+    ekinstate->ekinscaleh_nhc.resize(ekinstate->ekin_n);
+    ekinstate->vscale_nhc.resize(ekinstate->ekin_n);
     ekinstate->dekindl = 0;
     ekinstate->mvcos   = 0;
 }
@@ -1194,17 +1193,17 @@ void update_tcouple(gmx_int64_t       step,
                 break;
             case etcNOSEHOOVER:
                 nosehoover_tcoupl(&(inputrec->opts), ekind, dttc,
-                                  state->nosehoover_xi, state->nosehoover_vxi, MassQ);
+                                  state->nosehoover_xi.data(), state->nosehoover_vxi.data(), MassQ);
                 break;
             case etcVRESCALE:
                 vrescale_tcoupl(inputrec, step, ekind, dttc,
-                                state->therm_integral);
+                                state->therm_integral.data());
                 break;
         }
         /* rescale in place here */
         if (EI_VV(inputrec->eI))
         {
-            rescale_velocities(ekind, md, 0, md->homenr, state->v);
+            rescale_velocities(ekind, md, 0, md->homenr, as_rvec_array(state->v.data()));
         }
     }
     else
@@ -1284,7 +1283,7 @@ void update_constraints(FILE             *fplog,
                         t_state          *state,
                         gmx_bool          bMolPBC,
                         t_graph          *graph,
-                        rvec              force[],   /* forces on home particles */
+                        PaddedRVecVector *force,     /* forces on home particles */
                         t_idef           *idef,
                         tensor            vir_part,
                         t_commrec        *cr,
@@ -1344,7 +1343,7 @@ void update_constraints(FILE             *fplog,
         {
             constrain(NULL, bLog, bEner, constr, idef,
                       inputrec, cr, step, 1, 1.0, md,
-                      state->x, state->v, state->v,
+                      as_rvec_array(state->x.data()), as_rvec_array(state->v.data()), as_rvec_array(state->v.data()),
                       bMolPBC, state->box,
                       state->lambda[efptBONDED], dvdlambda,
                       NULL, bCalcVir ? &vir_con : NULL, nrnb, econqVeloc);
@@ -1353,17 +1352,17 @@ void update_constraints(FILE             *fplog,
         {
             constrain(NULL, bLog, bEner, constr, idef,
                       inputrec, cr, step, 1, 1.0, md,
-                      state->x, upd->xp, NULL,
+                      as_rvec_array(state->x.data()), as_rvec_array(upd->xp.data()), NULL,
                       bMolPBC, state->box,
                       state->lambda[efptBONDED], dvdlambda,
-                      state->v, bCalcVir ? &vir_con : NULL, nrnb, econqCoord);
+                      as_rvec_array(state->v.data()), bCalcVir ? &vir_con : NULL, nrnb, econqCoord);
         }
         wallcycle_stop(wcycle, ewcCONSTR);
 
         where();
 
         dump_it_all(fplog, "After Shake",
-                    state->natoms, state->x, upd->xp, state->v, force);
+                    state->natoms, &state->x, &upd->xp, &state->v, force);
 
         if (bCalcVir)
         {
@@ -1399,7 +1398,7 @@ void update_constraints(FILE             *fplog,
                               inputrec->opts.acc, inputrec->opts.nFreeze,
                               md->invmass, md->ptype,
                               md->cFREEZE, md->cACC, md->cTC,
-                              state->x, upd->xp, state->v, force,
+                              as_rvec_array(state->x.data()), as_rvec_array(upd->xp.data()), as_rvec_array(state->v.data()), as_rvec_array(force->data()),
                               bDoConstr, FALSE,
                               step, inputrec->ld_seed,
                               DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
@@ -1416,10 +1415,10 @@ void update_constraints(FILE             *fplog,
 
             constrain(NULL, bLog, bEner, constr, idef,
                       inputrec, cr, step, 1, 0.5, md,
-                      state->x, upd->xp, NULL,
+                      as_rvec_array(state->x.data()), as_rvec_array(upd->xp.data()), NULL,
                       bMolPBC, state->box,
                       state->lambda[efptBONDED], dvdlambda,
-                      state->v, NULL, nrnb, econqCoord);
+                      as_rvec_array(state->v.data()), NULL, nrnb, econqCoord);
 
             wallcycle_stop(wcycle, ewcCONSTR);
         }
@@ -1475,7 +1474,7 @@ void update_constraints(FILE             *fplog,
 
         if (graph && (graph->nnodes > 0))
         {
-            unshift_x(graph, state->box, state->x, upd->xp);
+            unshift_x(graph, state->box, as_rvec_array(state->x.data()), as_rvec_array(upd->xp.data()));
             if (TRICLINIC(state->box))
             {
                 inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes);
@@ -1487,6 +1486,8 @@ void update_constraints(FILE             *fplog,
         }
         else
         {
+            /* The copy is performance sensitive, so use a bare pointer */
+            rvec *xp = as_rvec_array(upd->xp.data());
 #ifndef __clang_analyzer__
             // cppcheck-suppress unreadVariable
             nth = gmx_omp_nthreads_get(emntUpdate);
@@ -1495,13 +1496,13 @@ void update_constraints(FILE             *fplog,
             for (i = start; i < nrend; i++)
             {
                 // Trivial statement, does not throw
-                copy_rvec(upd->xp[i], state->x[i]);
+                copy_rvec(xp[i], state->x[i]);
             }
         }
         wallcycle_stop(wcycle, ewcUPDATE);
 
         dump_it_all(fplog, "After unshift",
-                    state->natoms, state->x, upd->xp, state->v, force);
+                    state->natoms, &state->x, &upd->xp, &state->v, force);
     }
 /* ############# END the update of velocities and positions ######### */
 }
@@ -1511,7 +1512,6 @@ void update_box(FILE             *fplog,
                 t_inputrec       *inputrec,  /* input record and box stuff     */
                 t_mdatoms        *md,
                 t_state          *state,
-                rvec              force[],   /* forces on home particles */
                 matrix            pcoupl_mu,
                 t_nrnb           *nrnb,
                 gmx_update_t     *upd)
@@ -1540,7 +1540,7 @@ void update_box(FILE             *fplog,
             if (inputrec->nstpcouple == 1 || (step % inputrec->nstpcouple == 1))
             {
                 berendsen_pscale(inputrec, pcoupl_mu, state->box, state->box_rel,
-                                 start, homenr, state->x, md->cFREEZE, nrnb);
+                                 start, homenr, as_rvec_array(state->x.data()), md->cFREEZE, nrnb);
             }
             break;
         case (epcPARRINELLORAHMAN):
@@ -1594,11 +1594,11 @@ void update_box(FILE             *fplog,
 
     if (inputrecDeform(inputrec))
     {
-        deform(upd, start, homenr, state->x, state->box, inputrec, step);
+        deform(upd, start, homenr, as_rvec_array(state->x.data()), state->box, inputrec, step);
     }
     where();
     dump_it_all(fplog, "After update",
-                state->natoms, state->x, upd->xp, state->v, force);
+                state->natoms, &state->x, &upd->xp, &state->v, NULL);
 }
 
 void update_coords(FILE             *fplog,
@@ -1606,7 +1606,7 @@ void update_coords(FILE             *fplog,
                    t_inputrec       *inputrec,  /* input record and box stuff  */
                    t_mdatoms        *md,
                    t_state          *state,
-                   rvec             *f,    /* forces on home particles */
+                   PaddedRVecVector *f,    /* forces on home particles */
                    t_fcdata         *fcd,
                    gmx_ekindata_t   *ekind,
                    matrix            M,
@@ -1652,7 +1652,7 @@ void update_coords(FILE             *fplog,
     /* ############# START The update of velocities and positions ######### */
     where();
     dump_it_all(fplog, "Before update",
-                state->natoms, state->x, upd->xp, state->v, f);
+                state->natoms, &state->x, &upd->xp, &state->v, f);
 
     nth = gmx_omp_nthreads_get(emntUpdate);
 
@@ -1666,6 +1666,11 @@ void update_coords(FILE             *fplog,
             start_th = start + ((nrend-start)* th   )/nth;
             end_th   = start + ((nrend-start)*(th+1))/nth;
 
+            const rvec *x_rvec  = as_rvec_array(state->x.data());
+            rvec       *xp_rvec = as_rvec_array(upd->xp.data());
+            rvec       *v_rvec  = as_rvec_array(state->v.data());
+            const rvec *f_rvec  = as_rvec_array(f->data());
+
             switch (inputrec->eI)
             {
                 case (eiMD):
@@ -1673,21 +1678,21 @@ void update_coords(FILE             *fplog,
                     {
                         do_update_md(start_th, end_th,
                                      dt, inputrec->nstpcouple,
-                                     ekind->tcstat, state->nosehoover_vxi,
+                                     ekind->tcstat, state->nosehoover_vxi.data(),
                                      ekind->bNEMD, ekind->grpstat, inputrec->opts.acc,
                                      inputrec->opts.nFreeze,
                                      md->invmass, md->ptype,
                                      md->cFREEZE, md->cACC, md->cTC,
-                                     state->x, upd->xp, state->v, f, M,
+                                     x_rvec, xp_rvec, v_rvec, f_rvec, M,
                                      bNH, bPR);
                     }
                     else
                     {
                         do_update_visc(start_th, end_th,
                                        dt, inputrec->nstpcouple,
-                                       ekind->tcstat, state->nosehoover_vxi,
+                                       ekind->tcstat, state->nosehoover_vxi.data(),
                                        md->invmass, md->ptype,
-                                       md->cTC, state->x, upd->xp, state->v, f, M,
+                                       md->cTC, x_rvec, xp_rvec, v_rvec, f_rvec, M,
                                        state->box,
                                        ekind->cosacc.cos_accel,
                                        ekind->cosacc.vcos,
@@ -1701,7 +1706,7 @@ void update_coords(FILE             *fplog,
                                   inputrec->opts.acc, inputrec->opts.nFreeze,
                                   md->invmass, md->ptype,
                                   md->cFREEZE, md->cACC, md->cTC,
-                                  state->x, upd->xp, state->v, f,
+                                  x_rvec, xp_rvec, v_rvec, f_rvec,
                                   bDoConstr, TRUE,
                                   step, inputrec->ld_seed, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
                     break;
@@ -1709,7 +1714,7 @@ void update_coords(FILE             *fplog,
                     do_update_bd(start_th, end_th, dt,
                                  inputrec->opts.nFreeze, md->invmass, md->ptype,
                                  md->cFREEZE, md->cTC,
-                                 state->x, upd->xp, state->v, f,
+                                 x_rvec, xp_rvec, v_rvec, f_rvec,
                                  inputrec->bd_fric,
                                  upd->sd->bd_rf,
                                  step, inputrec->ld_seed, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
@@ -1725,14 +1730,14 @@ void update_coords(FILE             *fplog,
                                              inputrec->opts.acc, inputrec->opts.nFreeze,
                                              md->invmass, md->ptype,
                                              md->cFREEZE, md->cACC,
-                                             state->v, f,
+                                             v_rvec, f_rvec,
                                              (bNH || bPR), state->veta, alpha);
                             break;
                         case etrtPOSITION:
                             do_update_vv_pos(start_th, end_th, dt,
                                              inputrec->opts.nFreeze,
                                              md->ptype, md->cFREEZE,
-                                             state->x, upd->xp, state->v,
+                                             x_rvec, xp_rvec, v_rvec,
                                              (bNH || bPR), state->veta);
                             break;
                     }
index 7abef4add28c53695464a4da855c511daf685b26..698a48aee1ee5d61e732d53e5302262bb0c4d411 100644 (file)
@@ -38,6 +38,7 @@
 #define GMX_MDLIB_UPDATE_H
 
 #include "gromacs/math/vectypes.h"
+#include "gromacs/mdtypes/state.h"
 #include "gromacs/timing/wallcycle.h"
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/real.h"
@@ -70,7 +71,7 @@ void update_temperature_constants(gmx_update_t *upd, const t_inputrec *ir);
 
 /* Update the size of per-atom arrays (e.g. after DD re-partitioning,
    which might increase the number of home atoms). */
-void update_realloc(gmx_update_t *upd, int state_nalloc);
+void update_realloc(gmx_update_t *upd, int natoms);
 
 /* Store the box at step step
  * as a reference state for simulations with box deformation.
@@ -99,7 +100,7 @@ void update_coords(FILE              *fplog,
                    t_inputrec        *inputrec, /* input record and box stuff  */
                    t_mdatoms         *md,
                    t_state           *state,
-                   rvec              *f, /* forces on home particles */
+                   PaddedRVecVector  *f, /* forces on home particles */
                    t_fcdata          *fcd,
                    gmx_ekindata_t    *ekind,
                    matrix             M,
@@ -120,7 +121,7 @@ void update_constraints(FILE              *fplog,
                         t_state           *state,
                         gmx_bool           bMolPBC,
                         t_graph           *graph,
-                        rvec               force[], /* forces on home particles */
+                        PaddedRVecVector  *force, /* forces on home particles */
                         t_idef            *idef,
                         tensor             vir_part,
                         t_commrec         *cr,
@@ -138,7 +139,6 @@ void update_box(FILE             *fplog,
                 t_inputrec       *inputrec, /* input record and box stuff      */
                 t_mdatoms        *md,
                 t_state          *state,
-                rvec              force[], /* forces on home particles */
                 matrix            pcoupl_mu,
                 t_nrnb           *nrnb,
                 gmx_update_t     *upd);
@@ -183,10 +183,6 @@ void andersen_tcoupl(t_inputrec *ir, gmx_int64_t step,
 void nosehoover_tcoupl(t_grpopts *opts, gmx_ekindata_t *ekind, real dt,
                        double xi[], double vxi[], t_extmass *MassQ);
 
-t_state *init_bufstate(const t_state *template_state);
-
-void destroy_bufstate(t_state *state);
-
 void trotter_update(t_inputrec *ir, gmx_int64_t step, gmx_ekindata_t *ekind,
                     gmx_enerdata_t *enerd, t_state *state, tensor vir, t_mdatoms *md,
                     t_extmass *MassQ, int **trotter_seqlist, int trotter_seqno);
index 0c8b7b3ac5ed06171c05643ed848916c26b8df62..40a202f4ffc32ef9c5525875a3c391f9859c3a74 100644 (file)
@@ -50,6 +50,7 @@
 #include "gromacs/mdtypes/inputrec.h"
 #include "gromacs/mdtypes/md_enums.h"
 #include "gromacs/utility/compare.h"
+#include "gromacs/utility/gmxassert.h"
 #include "gromacs/utility/smalloc.h"
 
 /* The source code in this file should be thread-safe.
@@ -71,9 +72,9 @@ static void zero_ekinstate(ekinstate_t *eks)
     eks->ekinh          = NULL;
     eks->ekinf          = NULL;
     eks->ekinh_old      = NULL;
-    eks->ekinscalef_nhc = NULL;
-    eks->ekinscaleh_nhc = NULL;
-    eks->vscale_nhc     = NULL;
+    eks->ekinscalef_nhc.resize(0);
+    eks->ekinscaleh_nhc.resize(0);
+    eks->vscale_nhc.resize(0);
     eks->dekindl        = 0;
     eks->mvcos          = 0;
 }
@@ -98,70 +99,23 @@ static void init_swapstate(swapstate_t *swapstate)
 
 void init_gtc_state(t_state *state, int ngtc, int nnhpres, int nhchainlength)
 {
-    int i, j;
-
     state->ngtc          = ngtc;
     state->nnhpres       = nnhpres;
     state->nhchainlength = nhchainlength;
-    if (state->ngtc > 0)
-    {
-        snew(state->nosehoover_xi, state->nhchainlength*state->ngtc);
-        snew(state->nosehoover_vxi, state->nhchainlength*state->ngtc);
-        snew(state->therm_integral, state->ngtc);
-        for (i = 0; i < state->ngtc; i++)
-        {
-            for (j = 0; j < state->nhchainlength; j++)
-            {
-                state->nosehoover_xi[i*state->nhchainlength + j]   = 0.0;
-                state->nosehoover_vxi[i*state->nhchainlength + j]  = 0.0;
-            }
-        }
-        for (i = 0; i < state->ngtc; i++)
-        {
-            state->therm_integral[i]  = 0.0;
-        }
-    }
-    else
-    {
-        state->nosehoover_xi  = NULL;
-        state->nosehoover_vxi = NULL;
-        state->therm_integral = NULL;
-    }
-
-    if (state->nnhpres > 0)
-    {
-        snew(state->nhpres_xi, state->nhchainlength*nnhpres);
-        snew(state->nhpres_vxi, state->nhchainlength*nnhpres);
-        for (i = 0; i < nnhpres; i++)
-        {
-            for (j = 0; j < state->nhchainlength; j++)
-            {
-                state->nhpres_xi[i*nhchainlength + j]   = 0.0;
-                state->nhpres_vxi[i*nhchainlength + j]  = 0.0;
-            }
-        }
-    }
-    else
-    {
-        state->nhpres_xi  = NULL;
-        state->nhpres_vxi = NULL;
-    }
+    state->nosehoover_xi.resize(state->nhchainlength*state->ngtc, 0);
+    state->nosehoover_vxi.resize(state->nhchainlength*state->ngtc, 0);
+    state->therm_integral.resize(state->ngtc, 0);
+    state->nhpres_xi.resize(state->nhchainlength*nnhpres, 0);
+    state->nhpres_vxi.resize(state->nhchainlength*nnhpres, 0);
 }
 
 
 void init_state(t_state *state, int natoms, int ngtc, int nnhpres, int nhchainlength, int dfhistNumLambda)
 {
-    int i;
-
     state->natoms    = natoms;
     state->flags     = 0;
     state->fep_state = 0;
-    state->lambda    = 0;
-    snew(state->lambda, efptNR);
-    for (i = 0; i < efptNR; i++)
-    {
-        state->lambda[i] = 0;
-    }
+    state->lambda.resize(efptNR, 0);
     state->veta   = 0;
     clear_mat(state->box);
     clear_mat(state->box_rel);
@@ -170,21 +124,20 @@ void init_state(t_state *state, int natoms, int ngtc, int nnhpres, int nhchainle
     clear_mat(state->svir_prev);
     clear_mat(state->fvir_prev);
     init_gtc_state(state, ngtc, nnhpres, nhchainlength);
-    state->nalloc = state->natoms;
-    if (state->nalloc > 0)
+    if (state->natoms > 0)
     {
         /* We need to allocate one element extra, since we might use
          * (unaligned) 4-wide SIMD loads to access rvec entries.
          */
-        snew(state->x, state->nalloc + 1);
-        snew(state->v, state->nalloc + 1);
+        state->x.resize(state->natoms + 1);
+        state->v.resize(state->natoms + 1);
     }
     else
     {
-        state->x = NULL;
-        state->v = NULL;
+        state->x.resize(0);
+        state->v.resize(0);
     }
-    state->cg_p = NULL;
+    state->cg_p.resize(0);
     zero_history(&state->hist);
     zero_ekinstate(&state->ekinstate);
     snew(state->enerhist, 1);
@@ -202,26 +155,7 @@ void init_state(t_state *state, int natoms, int ngtc, int nnhpres, int nhchainle
     state->edsamstate      = NULL;
     state->ddp_count       = 0;
     state->ddp_count_cg_gl = 0;
-    state->cg_gl           = NULL;
-    state->cg_gl_nalloc    = 0;
-}
-
-void done_state(t_state *state)
-{
-    sfree(state->x);
-    sfree(state->v);
-    sfree(state->cg_p);
-    sfree(state->enerhist);
-    state->nalloc = 0;
-    sfree(state->cg_gl);
-    state->cg_gl_nalloc = 0;
-    sfree(state->lambda);
-    if (state->ngtc > 0)
-    {
-        sfree(state->nosehoover_xi);
-        sfree(state->nosehoover_vxi);
-        sfree(state->therm_integral);
-    }
+    state->cg_gl.resize(0);
 }
 
 void comp_state(const t_state *st1, const t_state *st2,
@@ -286,12 +220,30 @@ void comp_state(const t_state *st1, const t_state *st2,
         if ((st1->flags & (1<<estX)) && (st2->flags & (1<<estX)))
         {
             fprintf(stdout, "comparing x\n");
-            cmp_rvecs(stdout, "x", st1->natoms, st1->x, st2->x, bRMSD, ftol, abstol);
+            cmp_rvecs(stdout, "x", st1->natoms, as_rvec_array(st1->x.data()), as_rvec_array(st2->x.data()), bRMSD, ftol, abstol);
         }
         if ((st1->flags & (1<<estV)) && (st2->flags & (1<<estV)))
         {
             fprintf(stdout, "comparing v\n");
-            cmp_rvecs(stdout, "v", st1->natoms, st1->v, st2->v, bRMSD, ftol, abstol);
+            cmp_rvecs(stdout, "v", st1->natoms, as_rvec_array(st1->v.data()), as_rvec_array(st2->v.data()), bRMSD, ftol, abstol);
         }
     }
 }
+
+rvec *getRvecArrayFromPaddedRVecVector(const PaddedRVecVector *v,
+                                       unsigned int            n)
+{
+    GMX_ASSERT(v->size() >= n, "We can't copy more elements than the vector size");
+
+    rvec *dest;
+
+    snew(dest, n);
+
+    const rvec *vPtr = as_rvec_array(v->data());
+    for (unsigned int i = 0; i < n; i++)
+    {
+        copy_rvec(vPtr[i], dest[i]);
+    }
+
+    return dest;
+}
index 991416c747d4b27cd7ee6faa94a6bc164568d1e7..388e946b73db0bad55bdcc379712b2afd0559ae3 100644 (file)
@@ -37,6 +37,8 @@
 #ifndef GMX_MDTYPES_STATE_H
 #define GMX_MDTYPES_STATE_H
 
+#include <vector>
+
 #include "gromacs/math/vectypes.h"
 #include "gromacs/mdtypes/md_enums.h"
 #include "gromacs/utility/basedefinitions.h"
@@ -71,6 +73,9 @@ enum {
 /* The names of the state entries, defined in src/gmxlib/checkpoint.c */
 extern const char *est_names[estNR];
 
+/* This vector is not padded yet, padding will be added soon */
+typedef std::vector<gmx::RVec> PaddedRVecVector;
+
 typedef struct history_t
 {
     real  disre_initf;  /* The scaling factor for initializing the time av. */
@@ -89,17 +94,17 @@ typedef struct history_t
  */
 typedef struct ekinstate_t
 {
-    gmx_bool     bUpToDate;
-    int          ekin_n;
-    tensor      *ekinh;
-    tensor      *ekinf;
-    tensor      *ekinh_old;
-    tensor       ekin_total;
-    double      *ekinscalef_nhc;
-    double      *ekinscaleh_nhc;
-    double      *vscale_nhc;
-    real         dekindl;
-    real         mvcos;
+    gmx_bool             bUpToDate;
+    int                  ekin_n;
+    tensor              *ekinh;
+    tensor              *ekinf;
+    tensor              *ekinh_old;
+    tensor               ekin_total;
+    std::vector<double>  ekinscalef_nhc;
+    std::vector<double>  ekinscaleh_nhc;
+    std::vector<double>  vscale_nhc;
+    real                 dekindl;
+    real                 mvcos;
 } ekinstate_t;
 
 typedef struct df_history_t
@@ -199,24 +204,23 @@ typedef struct t_state
     int                     nhchainlength;   /* number of nose-hoover chains               */
     int                     flags;           /* Flags telling which entries are present      */
     int                     fep_state;       /* indicates which of the alchemical states we are in                 */
-    real                   *lambda;          /* lambda vector                               */
+    std::vector<real>       lambda;          /* lambda vector                               */
     matrix                  box;             /* box vector coordinates                         */
     matrix                  box_rel;         /* Relitaive box vectors to preserve shape        */
     matrix                  boxv;            /* box velocitites for Parrinello-Rahman pcoupl */
     matrix                  pres_prev;       /* Pressure of the previous step for pcoupl  */
     matrix                  svir_prev;       /* Shake virial for previous step for pcoupl */
     matrix                  fvir_prev;       /* Force virial of the previous step for pcoupl  */
-    double                 *nosehoover_xi;   /* for Nose-Hoover tcoupl (ngtc)       */
-    double                 *nosehoover_vxi;  /* for N-H tcoupl (ngtc)               */
-    double                 *nhpres_xi;       /* for Nose-Hoover pcoupl for barostat     */
-    double                 *nhpres_vxi;      /* for Nose-Hoover pcoupl for barostat     */
-    double                 *therm_integral;  /* for N-H/V-rescale tcoupl (ngtc)     */
+    std::vector<double>     nosehoover_xi;   /* for Nose-Hoover tcoupl (ngtc)       */
+    std::vector<double>     nosehoover_vxi;  /* for N-H tcoupl (ngtc)               */
+    std::vector<double>     nhpres_xi;       /* for Nose-Hoover pcoupl for barostat     */
+    std::vector<double>     nhpres_vxi;      /* for Nose-Hoover pcoupl for barostat     */
+    std::vector<double>     therm_integral;  /* for N-H/V-rescale tcoupl (ngtc)     */
     real                    veta;            /* trotter based isotropic P-coupling             */
     real                    vol0;            /* initial volume,required for computing NPT conserverd quantity */
-    int                     nalloc;          /* Allocation size for x and v when !=NULL*/
-    rvec                   *x;               /* the coordinates (natoms)                     */
-    rvec                   *v;               /* the velocities (natoms)                      */
-    rvec                   *cg_p;            /* p vector for conjugate gradient minimization */
+    PaddedRVecVector        x;               /* the coordinates (natoms)                     */
+    PaddedRVecVector        v;               /* the velocities (natoms)                      */
+    PaddedRVecVector        cg_p;            /* p vector for conjugate gradient minimization */
 
     history_t               hist;            /* Time history for restraints                  */
 
@@ -229,9 +233,7 @@ typedef struct t_state
 
     int                     ddp_count;       /* The DD partitioning count for this state  */
     int                     ddp_count_cg_gl; /* The DD part. count for index_gl     */
-    int                     ncg_gl;          /* The number of local charge groups            */
-    int                    *cg_gl;           /* The global cg number of the local cgs        */
-    int                     cg_gl_nalloc;    /* Allocation size of cg_gl;              */
+    std::vector<int>        cg_gl;           /* The global cg number of the local cgs        */
 } t_state;
 
 typedef struct t_extmass
@@ -257,8 +259,10 @@ void init_gtc_state(t_state *state, int ngtc, int nnhpres, int nhchainlength);
 
 void init_state(t_state *state, int natoms, int ngtc, int nnhpres, int nhchainlength, int dfhistNumLambda);
 
-void done_state(t_state *state);
-
 void comp_state(const t_state *st1, const t_state *st2, gmx_bool bRMSD, real ftol, real abstol);
 
+/*! \brief Allocate an rvec pointer and copy the contents of v to it */
+rvec *getRvecArrayFromPaddedRVecVector(const PaddedRVecVector *v,
+                                       unsigned int            n);
+
 #endif
index 6cb6d9a8511e56b630d85b73f18f39e60ab11a06..da7bff85de83ece3a2853e21a76f076b5dd5128b 100644 (file)
@@ -461,7 +461,7 @@ int gmx_convert_tpr(int argc, char *argv[])
             {
                 fprintf(stderr, "Will write subset %s of original tpx containing %d "
                         "atoms\n", grpname, gnx);
-                reduce_topology_x(gnx, index, &mtop, state.x, state.v);
+                reduce_topology_x(gnx, index, &mtop, as_rvec_array(state.x.data()), as_rvec_array(state.v.data()));
                 state.natoms = gnx;
             }
             else if (bZeroQ)
index d795af9356e541250ef5f447a421b6173590e0da..c6fd2941d82cbcf4e416b76d408370da09a5bcdc 100644 (file)
@@ -76,7 +76,7 @@ static void list_tpx(const char *fn, gmx_bool bShowNumbers, const char *mdpfn,
 {
     FILE         *gp;
     int           indent, i, j, **gcount, atot;
-    t_state       state;
+    t_state       state {};
     t_inputrec   *ir = nullptr;
     t_tpxheader   tpx;
     gmx_mtop_t    mtop;
@@ -132,11 +132,11 @@ static void list_tpx(const char *fn, gmx_bool bShowNumbers, const char *mdpfn,
             pr_rvecs(stdout, indent, "svir_prev", tpx.bBox ? state.svir_prev : NULL, DIM);
             pr_rvecs(stdout, indent, "fvir_prev", tpx.bBox ? state.fvir_prev : NULL, DIM);
             /* leave nosehoover_xi in for now to match the tpr version */
-            pr_doubles(stdout, indent, "nosehoover_xi", state.nosehoover_xi, state.ngtc);
+            pr_doubles(stdout, indent, "nosehoover_xi", state.nosehoover_xi.data(), state.ngtc);
             /*pr_doubles(stdout,indent,"nosehoover_vxi",state.nosehoover_vxi,state.ngtc);*/
             /*pr_doubles(stdout,indent,"therm_integral",state.therm_integral,state.ngtc);*/
-            pr_rvecs(stdout, indent, "x", tpx.bX ? state.x : NULL, state.natoms);
-            pr_rvecs(stdout, indent, "v", tpx.bV ? state.v : NULL, state.natoms);
+            pr_rvecs(stdout, indent, "x", tpx.bX ? as_rvec_array(state.x.data()) : NULL, state.natoms);
+            pr_rvecs(stdout, indent, "v", tpx.bV ? as_rvec_array(state.v.data()) : NULL, state.natoms);
         }
 
         groups = &mtop.groups;
@@ -169,7 +169,6 @@ static void list_tpx(const char *fn, gmx_bool bShowNumbers, const char *mdpfn,
         }
         sfree(gcount);
     }
-    done_state(&state);
 }
 
 static void list_top(const char *fn)
index 03ec3a0590401679596e35416f370cb29777b230..e8e56c831766ec47af1b1e89b3187320e673ca6f 100644 (file)
@@ -45,6 +45,7 @@
 #include <stdlib.h>
 
 #include <algorithm>
+#include <memory>
 
 #include "thread_mpi/threads.h"
 
@@ -252,9 +253,8 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
     int               nchkpt  = 1;
     gmx_localtop_t   *top;
     t_mdebin         *mdebin   = NULL;
-    t_state          *state    = NULL;
     gmx_enerdata_t   *enerd;
-    rvec             *f = NULL;
+    PaddedRVecVector  f {};
     gmx_global_stat_t gstat;
     gmx_update_t     *upd   = NULL;
     t_graph          *graph = NULL;
@@ -347,11 +347,11 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
     {
         /* Initialize ion swapping code */
         init_swapcoords(fplog, bVerbose, ir, opt2fn_master("-swap", nfile, fnm, cr),
-                        top_global, state_global->x, state_global->box, &state_global->swapstate, cr, oenv, Flags);
+                        top_global, as_rvec_array(state_global->x.data()), state_global->box, &state_global->swapstate, cr, oenv, Flags);
     }
 
     /* Initial values */
-    init_md(fplog, cr, ir, oenv, &t, &t0, state_global->lambda,
+    init_md(fplog, cr, ir, oenv, &t, &t0, &state_global->lambda,
             &(state_global->fep_state), lam0,
             nrnb, top_global, &upd,
             nfile, fnm, &outf, &mdebin,
@@ -363,13 +363,9 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
     snew(enerd, 1);
     init_enerdata(top_global->groups.grps[egcENER].nr, ir->fepvals->n_lambda,
                   enerd);
-    if (DOMAINDECOMP(cr))
+    if (!DOMAINDECOMP(cr))
     {
-        f = NULL;
-    }
-    else
-    {
-        snew(f, top_global->natoms);
+        f.resize(top_global->natoms + 1);
     }
 
     /* Kinetic energy data */
@@ -413,11 +409,15 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
         }
     }
 
+    std::unique_ptr<t_state> stateInstance;
+    t_state *                state;
+
     if (DOMAINDECOMP(cr))
     {
         top = dd_init_local_top(top_global);
 
-        snew(state, 1);
+        stateInstance = std::unique_ptr<t_state>(new t_state {});
+        state         = stateInstance.get();
         dd_init_local_state(cr->dd, state_global, state);
     }
     else
@@ -429,11 +429,11 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
         mdAlgorithmsSetupAtomData(cr, ir, top_global, top, fr,
                                   &graph, mdatoms, vsite, shellfc);
 
-        update_realloc(upd, state->nalloc);
+        update_realloc(upd, state->natoms);
     }
 
     /* Set up interactive MD (IMD) */
-    init_IMD(ir, cr, top_global, fplog, ir->nstcalcenergy, state_global->x,
+    init_IMD(ir, cr, top_global, fplog, ir->nstcalcenergy, as_rvec_array(state_global->x.data()),
              nfile, fnm, oenv, imdport, Flags);
 
     if (DOMAINDECOMP(cr))
@@ -445,7 +445,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                             vsite, constr,
                             nrnb, NULL, FALSE);
         shouldCheckNumberOfBondedInteractions = true;
-        update_realloc(upd, state->nalloc);
+        update_realloc(upd, state->natoms);
     }
 
     update_mdatoms(mdatoms, state->lambda[efptMASS]);
@@ -529,7 +529,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
         if (vsite)
         {
             /* Construct the virtual sites for the initial configuration */
-            construct_vsites(vsite, state->x, ir->delta_t, NULL,
+            construct_vsites(vsite, as_rvec_array(state->x.data()), ir->delta_t, NULL,
                              top->idef.iparams, top->idef.il,
                              fr->ePBC, fr->bMolPBC, cr, state->box);
         }
@@ -885,15 +885,15 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                     /* Following is necessary because the graph may get out of sync
                      * with the coordinates if we only have every N'th coordinate set
                      */
-                    mk_mshift(fplog, graph, fr->ePBC, state->box, state->x);
-                    shift_self(graph, state->box, state->x);
+                    mk_mshift(fplog, graph, fr->ePBC, state->box, as_rvec_array(state->x.data()));
+                    shift_self(graph, state->box, as_rvec_array(state->x.data()));
                 }
-                construct_vsites(vsite, state->x, ir->delta_t, state->v,
+                construct_vsites(vsite, as_rvec_array(state->x.data()), ir->delta_t, as_rvec_array(state->v.data()),
                                  top->idef.iparams, top->idef.il,
                                  fr->ePBC, fr->bMolPBC, cr, state->box);
                 if (graph)
                 {
-                    unshift_self(graph, state->box, state->x);
+                    unshift_self(graph, state->box, as_rvec_array(state->x.data()));
                 }
             }
         }
@@ -970,7 +970,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                                     nrnb, wcycle,
                                     do_verbose && !bPMETunePrinting);
                 shouldCheckNumberOfBondedInteractions = true;
-                update_realloc(upd, state->nalloc);
+                update_realloc(upd, state->natoms);
             }
         }
 
@@ -1064,7 +1064,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             relax_shell_flexcon(fplog, cr, bVerbose, step,
                                 ir, bNS, force_flags, top,
                                 constr, enerd, fcd,
-                                state, f, force_vir, mdatoms,
+                                state, &f, force_vir, mdatoms,
                                 nrnb, wcycle, graph, groups,
                                 shellfc, fr, bBornRadii, t, mu_tot,
                                 vsite, mdoutf_get_fp_field(outf));
@@ -1077,9 +1077,9 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
              * Check comments in sim_util.c
              */
             do_force(fplog, cr, ir, step, nrnb, wcycle, top, groups,
-                     state->box, state->x, &state->hist,
-                     f, force_vir, mdatoms, enerd, fcd,
-                     state->lambda, graph,
+                     state->box, &state->x, &state->hist,
+                     &f, force_vir, mdatoms, enerd, fcd,
+                     &state->lambda, graph,
                      fr, vsite, mu_tot, t, mdoutf_get_fp_field(outf), ed, bBornRadii,
                      (bNS ? GMX_FORCE_NS : 0) | force_flags);
         }
@@ -1099,7 +1099,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                  * so that the input is actually the initial step.
                  */
                 snew(vbuf, state->natoms);
-                copy_rvecn(state->v, vbuf, 0, state->natoms); /* should make this better for parallelizing? */
+                copy_rvecn(as_rvec_array(state->v.data()), vbuf, 0, state->natoms); /* should make this better for parallelizing? */
             }
             else
             {
@@ -1107,7 +1107,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                 trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, &MassQ, trotter_seq, ettTSEQ1);
             }
 
-            update_coords(fplog, step, ir, mdatoms, state, f, fcd,
+            update_coords(fplog, step, ir, mdatoms, state, &f, fcd,
                           ekind, M, upd, etrtVELOCITY1,
                           cr, constr);
 
@@ -1115,7 +1115,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             {
                 wallcycle_stop(wcycle, ewcUPDATE);
                 update_constraints(fplog, step, NULL, ir, mdatoms,
-                                   state, fr->bMolPBC, graph, f,
+                                   state, fr->bMolPBC, graph, &f,
                                    &top->idef, shake_vir,
                                    cr, nrnb, wcycle, upd, constr,
                                    TRUE, bCalcVir);
@@ -1125,7 +1125,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             {
                 /* Need to unshift here if a do_force has been
                    called in the previous step */
-                unshift_self(graph, state->box, state->x);
+                unshift_self(graph, state->box, as_rvec_array(state->x.data()));
             }
             /* if VV, compute the pressure and constraints */
             /* For VV2, we strictly only need this if using pressure
@@ -1206,7 +1206,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             /* if it's the initial step, we performed this first step just to get the constraint virial */
             if (ir->eI == eiVV && bInitStep)
             {
-                copy_rvecn(vbuf, state->v, 0, state->natoms);
+                copy_rvecn(vbuf, as_rvec_array(state->v.data()), 0, state->natoms);
                 sfree(vbuf);
             }
             wallcycle_stop(wcycle, ewcUPDATE);
@@ -1227,7 +1227,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             /* sum up the foreign energy and dhdl terms for vv.  currently done every step so that dhdl is correct in the .edr */
             if (ir->efep != efepNO && !bRerunMD)
             {
-                sum_dhdl(enerd, state->lambda, ir->fepvals);
+                sum_dhdl(enerd, &state->lambda, ir->fepvals);
             }
         }
 
@@ -1240,7 +1240,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                statistics, but if performing simulated tempering, we
                do update the velocities and the tau_t. */
 
-            lamnew = ExpandedEnsembleDynamics(fplog, ir, enerd, state, &MassQ, state->fep_state, state->dfhist, step, state->v, mdatoms);
+            lamnew = ExpandedEnsembleDynamics(fplog, ir, enerd, state, &MassQ, state->fep_state, state->dfhist, step, as_rvec_array(state->v.data()), mdatoms);
             /* history is maintained in state->dfhist, but state_global is what is sent to trajectory and log output */
             copy_df_history(state_global->dfhist, state->dfhist);
         }
@@ -1251,12 +1251,12 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
          */
         do_md_trajectory_writing(fplog, cr, nfile, fnm, step, step_rel, t,
                                  ir, state, state_global, top_global, fr,
-                                 outf, mdebin, ekind, f,
+                                 outf, mdebin, ekind, &f,
                                  &nchkpt,
                                  bCPT, bRerunMD, bLastStep, (Flags & MD_CONFOUT),
                                  bSumEkinhOld);
         /* Check if IMD step and do IMD communication, if bIMD is TRUE. */
-        bIMDstep = do_IMD(ir->bIMD, step, cr, bNS, state->box, state->x, ir, t, wcycle);
+        bIMDstep = do_IMD(ir->bIMD, step, cr, bNS, state->box, as_rvec_array(state->x.data()), ir, t, wcycle);
 
         /* kludge -- virial is lost with restart for MTTK NPT control. Must reload (saved earlier). */
         if (startingFromCheckpoint && bTrotter)
@@ -1348,7 +1348,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             if (constr && bIfRandomize)
             {
                 update_constraints(fplog, step, NULL, ir, mdatoms,
-                                   state, fr->bMolPBC, graph, f,
+                                   state, fr->bMolPBC, graph, &f,
                                    &top->idef, tmp_vir,
                                    cr, nrnb, wcycle, upd, constr,
                                    TRUE, bCalcVir);
@@ -1385,7 +1385,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             if (EI_VV(ir->eI))
             {
                 /* velocity half-step update */
-                update_coords(fplog, step, ir, mdatoms, state, f, fcd,
+                update_coords(fplog, step, ir, mdatoms, state, &f, fcd,
                               ekind, M, upd, etrtVELOCITY2,
                               cr, constr);
             }
@@ -1403,15 +1403,15 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                     cbuf_nalloc = state->natoms;
                     srenew(cbuf, cbuf_nalloc);
                 }
-                copy_rvecn(state->x, cbuf, 0, state->natoms);
+                copy_rvecn(as_rvec_array(state->x.data()), cbuf, 0, state->natoms);
             }
 
-            update_coords(fplog, step, ir, mdatoms, state, f, fcd,
+            update_coords(fplog, step, ir, mdatoms, state, &f, fcd,
                           ekind, M, upd, etrtPOSITION, cr, constr);
             wallcycle_stop(wcycle, ewcUPDATE);
 
             update_constraints(fplog, step, &dvdl_constr, ir, mdatoms, state,
-                               fr->bMolPBC, graph, f,
+                               fr->bMolPBC, graph, &f,
                                &top->idef, shake_vir,
                                cr, nrnb, wcycle, upd, constr,
                                FALSE, bCalcVir);
@@ -1429,19 +1429,19 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                 wallcycle_start(wcycle, ewcUPDATE);
                 trotter_update(ir, step, ekind, enerd, state, total_vir, mdatoms, &MassQ, trotter_seq, ettTSEQ4);
                 /* now we know the scaling, we can compute the positions again again */
-                copy_rvecn(cbuf, state->x, 0, state->natoms);
+                copy_rvecn(cbuf, as_rvec_array(state->x.data()), 0, state->natoms);
 
-                update_coords(fplog, step, ir, mdatoms, state, f, fcd,
+                update_coords(fplog, step, ir, mdatoms, state, &f, fcd,
                               ekind, M, upd, etrtPOSITION, cr, constr);
                 wallcycle_stop(wcycle, ewcUPDATE);
 
-                /* do we need an extra constraint here? just need to copy out of state->v to upd->xp? */
+                /* do we need an extra constraint here? just need to copy out of as_rvec_array(state->v.data()) to upd->xp? */
                 /* are the small terms in the shake_vir here due
                  * to numerical errors, or are they important
                  * physically? I'm thinking they are just errors, but not completely sure.
                  * For now, will call without actually constraining, constr=NULL*/
                 update_constraints(fplog, step, NULL, ir, mdatoms,
-                                   state, fr->bMolPBC, graph, f,
+                                   state, fr->bMolPBC, graph, &f,
                                    &top->idef, tmp_vir,
                                    cr, nrnb, wcycle, upd, NULL,
                                    FALSE, bCalcVir);
@@ -1472,7 +1472,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
         else if (graph)
         {
             /* Need to unshift here */
-            unshift_self(graph, state->box, state->x);
+            unshift_self(graph, state->box, as_rvec_array(state->x.data()));
         }
 
         if (vsite != NULL)
@@ -1480,15 +1480,15 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             wallcycle_start(wcycle, ewcVSITECONSTR);
             if (graph != NULL)
             {
-                shift_self(graph, state->box, state->x);
+                shift_self(graph, state->box, as_rvec_array(state->x.data()));
             }
-            construct_vsites(vsite, state->x, ir->delta_t, state->v,
+            construct_vsites(vsite, as_rvec_array(state->x.data()), ir->delta_t, as_rvec_array(state->v.data()),
                              top->idef.iparams, top->idef.il,
                              fr->ePBC, fr->bMolPBC, cr, state->box);
 
             if (graph != NULL)
             {
-                unshift_self(graph, state->box, state->x);
+                unshift_self(graph, state->box, as_rvec_array(state->x.data()));
             }
             wallcycle_stop(wcycle, ewcVSITECONSTR);
         }
@@ -1545,9 +1545,9 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
         {
             /* Sum up the foreign energy and dhdl terms for md and sd.
                Currently done every step so that dhdl is correct in the .edr */
-            sum_dhdl(enerd, state->lambda, ir->fepvals);
+            sum_dhdl(enerd, &state->lambda, ir->fepvals);
         }
-        update_box(fplog, step, ir, mdatoms, state, f,
+        update_box(fplog, step, ir, mdatoms, state,
                    pcoupl_mu, nrnb, upd);
 
         /* ################# END UPDATE STEP 2 ################# */
@@ -1649,7 +1649,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             do_per_step(step, ir->swap->nstswap))
         {
             bNeedRepartition = do_swapcoords(cr, step, t, ir, wcycle,
-                                             bRerunMD ? rerun_fr.x   : state->x,
+                                             bRerunMD ? rerun_fr.x   : as_rvec_array(state->x.data()),
                                              bRerunMD ? rerun_fr.box : state->box,
                                              top_global, MASTER(cr) && bVerbose, bRerunMD);
 
@@ -1676,7 +1676,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                                 vsite, constr,
                                 nrnb, wcycle, FALSE);
             shouldCheckNumberOfBondedInteractions = true;
-            update_realloc(upd, state->nalloc);
+            update_realloc(upd, state->natoms);
         }
 
         bFirstStep             = FALSE;
@@ -1701,7 +1701,7 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
 
         if ( (membed != NULL) && (!bLastStep) )
         {
-            rescale_membed(step_rel, membed, state_global->x);
+            rescale_membed(step_rel, membed, as_rvec_array(state_global->x.data()));
         }
 
         if (bRerunMD)
index f7f47d9b936e5dd3d0b30a165fd539681df71bb8..03b35b200a22f01c5bd376ac575598576552d097 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,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.
@@ -721,9 +721,8 @@ static void rm_group(gmx_groups_t *groups, gmx_mtop_t *mtop, rm_t *rm_p, t_state
     mtop->mols.index = new_mols;
     mtop->natoms    -= n;
     state->natoms   -= n;
-    state->nalloc    = state->natoms;
-    snew(x_tmp, state->nalloc);
-    snew(v_tmp, state->nalloc);
+    snew(x_tmp, state->natoms);
+    snew(v_tmp, state->natoms);
 
     for (i = 0; i < egcNR; i++)
     {
@@ -778,10 +777,16 @@ static void rm_group(gmx_groups_t *groups, gmx_mtop_t *mtop, rm_t *rm_p, t_state
             }
         }
     }
-    sfree(state->x);
-    state->x = x_tmp;
-    sfree(state->v);
-    state->v = v_tmp;
+    for (int i = 0; i < state->natoms; i++)
+    {
+        copy_rvec(x_tmp[i], state->x[i]);
+    }
+    sfree(x_tmp);
+    for (int i = 0; i < state->natoms; i++)
+    {
+        copy_rvec(v_tmp[i], state->v[i]);
+    }
+    sfree(v_tmp);
 
     for (i = 0; i < egcNR; i++)
     {
@@ -1203,9 +1208,9 @@ gmx_membed_t *init_membed(FILE *fplog, int nfile, const t_filenm fnm[], gmx_mtop
         /* Check that moleculetypes in insertion group are not part of the rest of the system */
         check_types(ins_at, rest_at, mtop);
 
-        init_mem_at(mem_p, mtop, state->x, state->box, pos_ins);
+        init_mem_at(mem_p, mtop, as_rvec_array(state->x.data()), state->box, pos_ins);
 
-        prot_area = est_prot_area(pos_ins, state->x, ins_at, mem_p);
+        prot_area = est_prot_area(pos_ins, as_rvec_array(state->x.data()), ins_at, mem_p);
         if ( (prot_area > prot_vs_box) && ( (state->box[XX][XX]*state->box[YY][YY]-state->box[XX][YY]*state->box[YY][XX]) < box_vs_prot) )
         {
             warn++;
@@ -1235,14 +1240,14 @@ gmx_membed_t *init_membed(FILE *fplog, int nfile, const t_filenm fnm[], gmx_mtop
 
         /* resize the protein by xy and by z if necessary*/
         snew(r_ins, ins_at->nr);
-        init_resize(ins_at, r_ins, pos_ins, mem_p, state->x, bALLOW_ASYMMETRY);
+        init_resize(ins_at, r_ins, pos_ins, mem_p, as_rvec_array(state->x.data()), bALLOW_ASYMMETRY);
         membed->fac[0] = membed->fac[1] = xy_fac;
         membed->fac[2] = z_fac;
 
         membed->xy_step = (xy_max-xy_fac)/(double)(it_xy);
         membed->z_step  = (z_max-z_fac)/(double)(it_z-1);
 
-        resize(r_ins, state->x, pos_ins, membed->fac);
+        resize(r_ins, as_rvec_array(state->x.data()), pos_ins, membed->fac);
 
         /* remove overlapping lipids and water from the membrane box*/
         /*mark molecules to be removed*/
@@ -1250,7 +1255,7 @@ gmx_membed_t *init_membed(FILE *fplog, int nfile, const t_filenm fnm[], gmx_mtop
         set_pbc(pbc, inputrec->ePBC, state->box);
 
         snew(rm_p, 1);
-        lip_rm = gen_rm_list(rm_p, ins_at, rest_at, pbc, mtop, state->x, mem_p, pos_ins,
+        lip_rm = gen_rm_list(rm_p, ins_at, rest_at, pbc, mtop, as_rvec_array(state->x.data()), mem_p, pos_ins,
                              probe_rad, low_up_rm, bALLOW_ASYMMETRY);
         lip_rm -= low_up_rm;
 
index e439f652714217295001b40c3adbb355367789d0..83c1e43a23c5d774b827cc6f9ec397514c9f0b8d 100644 (file)
@@ -542,13 +542,13 @@ static void exchange_state(const gmx_multisim_t *ms, int b, t_state *state)
     exchange_rvecs(ms, b, state->svir_prev, DIM);
     exchange_rvecs(ms, b, state->fvir_prev, DIM);
     exchange_rvecs(ms, b, state->pres_prev, DIM);
-    exchange_doubles(ms, b, state->nosehoover_xi, ngtc);
-    exchange_doubles(ms, b, state->nosehoover_vxi, ngtc);
-    exchange_doubles(ms, b, state->nhpres_xi, nnhpres);
-    exchange_doubles(ms, b, state->nhpres_vxi, nnhpres);
-    exchange_doubles(ms, b, state->therm_integral, state->ngtc);
-    exchange_rvecs(ms, b, state->x, state->natoms);
-    exchange_rvecs(ms, b, state->v, state->natoms);
+    exchange_doubles(ms, b, state->nosehoover_xi.data(), ngtc);
+    exchange_doubles(ms, b, state->nosehoover_vxi.data(), ngtc);
+    exchange_doubles(ms, b, state->nhpres_xi.data(), nnhpres);
+    exchange_doubles(ms, b, state->nhpres_vxi.data(), nnhpres);
+    exchange_doubles(ms, b, state->therm_integral.data(), state->ngtc);
+    exchange_rvecs(ms, b, as_rvec_array(state->x.data()), state->natoms);
+    exchange_rvecs(ms, b, as_rvec_array(state->v.data()), state->natoms);
 }
 
 static void copy_state_serial(const t_state *src, t_state *dest)
@@ -567,7 +567,7 @@ static void scale_velocities(t_state *state, real fac)
 {
     int i;
 
-    if (state->v)
+    if (as_rvec_array(state->v.data()))
     {
         for (i = 0; i < state->natoms; i++)
         {
index 8fa892bfffd3764dbc82bab1f4797711a0f4832d..59d06413dabf8f8e82b624f8f34cc201070657e7 100644 (file)
@@ -344,7 +344,6 @@ static void increase_nstlist(FILE *fp, t_commrec *cr,
     real                   rlistWithReferenceNstlist, rlist_inc, rlist_ok, rlist_max;
     real                   rlist_new, rlist_prev;
     size_t                 nstlist_ind = 0;
-    t_state                state_tmp;
     gmx_bool               bBox, bDD, bCont;
     const char            *nstl_gpu = "\nFor optimal performance with a GPU nstlist (now %d) should be larger.\nThe optimum depends on your CPU and GPU resources.\nYou might want to try several nstlist values.\n";
     const char            *nve_err  = "Can not increase nstlist because an NVE ensemble is used";
@@ -483,6 +482,7 @@ static void increase_nstlist(FILE *fp, t_commrec *cr,
             {
                 gmx_incons("Changing nstlist with domain decomposition and unbounded dimensions is not implemented yet");
             }
+            t_state state_tmp {};
             copy_mat(box, state_tmp.box);
             bDD = change_dd_cutoff(cr, &state_tmp, ir, rlist_new);
         }
@@ -706,7 +706,6 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
 {
     gmx_bool                  bForceUseGPU, bTryUseGPU, bRerunMD;
     t_inputrec               *inputrec;
-    t_state                  *state = NULL;
     matrix                    box;
     gmx_ddbox_t               ddbox = {0};
     int                       npme_major, npme_minor;
@@ -771,7 +770,9 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
         please_cite(fplog, "Berendsen95a");
     }
 
-    snew(state, 1);
+    std::unique_ptr<t_state> stateInstance = std::unique_ptr<t_state>(new t_state {});
+    t_state *                state         = stateInstance.get();
+
     if (SIMMASTER(cr))
     {
         /* Read (nearly) all data required for the simulation */
@@ -973,7 +974,7 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
     /* This needs to be called before read_checkpoint to extend the state */
     init_disres(fplog, mtop, inputrec, cr, fcd, state, repl_ex_nst > 0);
 
-    init_orires(fplog, mtop, state->x, inputrec, cr, &(fcd->orires),
+    init_orires(fplog, mtop, as_rvec_array(state->x.data()), inputrec, cr, &(fcd->orires),
                 state);
 
     if (inputrecDeform(inputrec))
@@ -1059,7 +1060,7 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
                                            dddlb_opt, dlb_scale,
                                            ddcsx, ddcsy, ddcsz,
                                            mtop, inputrec,
-                                           box, state->x,
+                                           box, as_rvec_array(state->x.data()),
                                            &ddbox, &npme_major, &npme_minor);
     }
     else
@@ -1228,7 +1229,7 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
             /* Make molecules whole at start of run */
             if (fr->ePBC != epbcNONE)
             {
-                do_pbc_first_mtop(fplog, inputrec->ePBC, box, mtop, state->x);
+                do_pbc_first_mtop(fplog, inputrec->ePBC, box, mtop, as_rvec_array(state->x.data()));
             }
             if (vsite)
             {
@@ -1236,7 +1237,7 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
                  * for the initial distribution in the domain decomposition
                  * and for the initial shell prediction.
                  */
-                construct_vsites_mtop(vsite, mtop, state->x);
+                construct_vsites_mtop(vsite, mtop, as_rvec_array(state->x.data()));
             }
         }
 
@@ -1256,7 +1257,8 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
         /* This is a PME only node */
 
         /* We don't need the state */
-        done_state(state);
+        stateInstance.reset();
+        state         = NULL;
 
         ewaldcoeff_q  = calc_ewaldcoeff_q(inputrec->rcoulomb, inputrec->ewald_rtol);
         ewaldcoeff_lj = calc_ewaldcoeff_lj(inputrec->rvdw, inputrec->ewald_rtol_lj);
@@ -1349,7 +1351,7 @@ int mdrunner(gmx_hw_opt_t *hw_opt,
         if (inputrec->bRot)
         {
             /* Initialize enforced rotation code */
-            init_rot(fplog, inputrec, nfile, fnm, cr, state->x, state->box, mtop, oenv,
+            init_rot(fplog, inputrec, nfile, fnm, cr, as_rvec_array(state->x.data()), state->box, mtop, oenv,
                      bVerbose, Flags);
         }