#include <algorithm>
#include <memory>
#include <mutex>
+#include <string>
#include "gromacs/commandline/filenm.h"
#include "gromacs/domdec/domdec_struct.h"
#include "gromacs/utility/stringutil.h"
#include "pull_internal.h"
+#include "transformationcoordinate.h"
namespace gmx
{
* region instead of potential parallel regions within apply_forces_grp.
* But there could be overlap between pull groups and this would lead
* to data races.
+ *
+ * This may also lead to potential issues with force redistribution
+ * for transformation pull coordinates
*/
if (pcrd.params.eGeom == PullGroupGeometry::Cylinder)
}
apply_forces_grp(pullGroups[pcrd.params.group[1]], masses, f_tot, 1, f);
}
+ else if (pcrd.params.eGeom == PullGroupGeometry::Transformation)
+ {
+ return;
+ }
else
{
if (pcrd.params.eGeom == PullGroupGeometry::DirectionRelative)
case PullGroupGeometry::AngleAxis:
spatialData.value = gmx_angle_between_dvecs(spatialData.dr01, spatialData.vec);
break;
+ case PullGroupGeometry::Transformation:
+ // Note that we would only need to pass the part of coord up to coord_ind
+ spatialData.value = gmx::getTransformationPullCoordinateValue(
+ pcrd, ArrayRef<const pull_coord_work_t>(pull.coord).subArray(0, pcrd->params.coordIndex));
+ break;
default: gmx_incons("Unsupported pull type in get_pull_coord_distance");
}
}
dsvmul(lambda * rm * pgrp0->invtm, vec, dr0);
dr_tot[c] += -lambda;
break;
+ case PullGroupGeometry::Transformation:
+ GMX_RELEASE_ASSERT(false, "transformation with constraints should never occur");
+ break;
default: gmx_incons("Invalid enumeration value for eGeom");
}
}
}
+/*! \brief Applies a force of any non-transformation pull coordinate
+ *
+ * \param[in] pull The pull struct, we can't pass only the coord because of cylinder pulling
+ * \param[in] coord_index The index of the coord to apply to force for
+ * \param[in] coord_force The force working on this coord
+ * \param[in] masses Atom masses
+ * \param[in] forceWithVirial Atom force and virial object
+ */
+static void apply_default_pull_coord_force(pull_t* pull,
+ const int coord_index,
+ const double coord_force,
+ gmx::ArrayRef<const real> masses,
+ gmx::ForceWithVirial* forceWithVirial)
+{
+ pull_coord_work_t* pcrd = &pull->coord[coord_index];
+ /* Set the force */
+ pcrd->scalarForce = coord_force;
+ /* Calculate the forces on the pull groups */
+ PullCoordVectorForces pullCoordForces = calculateVectorForces(*pcrd);
+
+ /* Add the forces for this coordinate to the total virial and force */
+ if (forceWithVirial->computeVirial_ && pull->comm.isMasterRank)
+ {
+ matrix virial = { { 0 } };
+ add_virial_coord(virial, *pcrd, pullCoordForces);
+ forceWithVirial->addVirialContribution(virial);
+ }
+ apply_forces_coord(pull->coord[coord_index],
+ pull->group,
+ pullCoordForces,
+ masses,
+ as_rvec_array(forceWithVirial->force_.data()));
+}
+
/* Pull takes care of adding the forces of the external potential.
* The external potential module has to make sure that the corresponding
* potential energy is added either to the pull term or to a term
GMX_ASSERT(pcrd->bExternalPotentialProviderHasBeenRegistered,
"apply_external_pull_coord_force called for an unregistered pull coordinate");
- /* Set the force */
- pcrd->scalarForce = coord_force;
-
- /* Calculate the forces on the pull groups */
- PullCoordVectorForces pullCoordForces = calculateVectorForces(*pcrd);
-
- /* Add the forces for this coordinate to the total virial and force */
- if (forceWithVirial->computeVirial_ && pull->comm.isMasterRank)
+ if (pcrd->params.eGeom == PullGroupGeometry::Transformation)
{
- matrix virial = { { 0 } };
- add_virial_coord(virial, *pcrd, pullCoordForces);
- forceWithVirial->addVirialContribution(virial);
+ gmx::applyTransformationPullCoordForce(
+ pcrd,
+ gmx::ArrayRef<pull_coord_work_t>(pull->coord).subArray(0, pcrd->params.coordIndex),
+ coord_force);
+ }
+ else
+ {
+ apply_default_pull_coord_force(pull, coord_index, coord_force, masses, forceWithVirial);
}
-
- apply_forces_coord(
- *pcrd, pull->group, pullCoordForces, masses, as_rvec_array(forceWithVirial->force_.data()));
}
-
pull->numExternalPotentialsStillToBeAppliedThisStep--;
}
{
continue;
}
-
PullCoordVectorForces pullCoordForces = do_pull_pot_coord(
*pull, &pcrd, pbc, t, lambda, &V, computeVirial ? virial : nullptr, &dVdl);
- /* Distribute the force over the atoms in the pulled groups */
- apply_forces_coord(pcrd, pull->group, pullCoordForces, masses, f);
+ if (pcrd.params.eGeom == PullGroupGeometry::Transformation)
+ {
+ gmx::applyTransformationPullCoordForce(
+ &pcrd,
+ gmx::ArrayRef<pull_coord_work_t>(pull->coord).subArray(0, pcrd.params.coordIndex),
+ pcrd.scalarForce);
+ }
+ else
+ {
+ /* Distribute the force over the atoms in the pulled groups */
+ apply_forces_coord(pcrd, pull->group, pullCoordForces, masses, f);
+ }
}
if (MASTER(cr))
case PullGroupGeometry::Direction:
case PullGroupGeometry::DirectionPBC:
case PullGroupGeometry::Cylinder:
+ case PullGroupGeometry::Transformation:
case PullGroupGeometry::AngleAxis:
copy_rvec_to_dvec(pull_params->coord[c].vec, pcrd->spatialData.vec);
break;