apoCHARMM 1.0.0
High-performance molecular dynamics simulations on GPUs
 
Loading...
Searching...
No Matches
GeometricRestraintForce< AT, CT > Class Template Reference

Computes atomwise and center-of-mass harmonic geometric restraints. More...

#include <GeometricRestraintForce.h>

Public Types

enum class  Geometry : int { PLANE = 0 , CYLINDER = 1 , SPHERE = 2 }
 Selects the geometry of an atomwise or RCM restraint term. More...
 
enum class  Activation : int { SYMMETRIC = 0 , INSIDE = 1 , OUTSIDE = -1 }
 Selects the activation predicate applied to the geometry coordinate. More...
 
enum class  SelectionMode : int { ATOMWISE = 0 , RCM = 1 }
 Selects independent atom evaluations or one mass-weighted center. More...
 
enum class  PotentialType : int { HARMONIC = 0 }
 Identifies the implemented geometric-restraint potential. More...
 

Public Member Functions

 GeometricRestraintForce (void)=delete
 Prevents construction without a PSF atom-count and mass snapshot.
 
 GeometricRestraintForce (const std::shared_ptr< const CharmmPSF > &psf)
 Constructs an empty geometric restraint from a PSF snapshot.
 
 GeometricRestraintForce (const GeometricRestraintForce &other)=delete
 Prevents copying a restraint that owns CUDA resources.
 
 GeometricRestraintForce (GeometricRestraintForce &&other)=delete
 Prevents moving an object referenced by subscribed force views.
 
 ~GeometricRestraintForce (void) noexcept
 Destroys the private CUDA stream and releases owned resources.
 
GeometricRestraintForce & operator= (const GeometricRestraintForce &other)=delete
 Prevents copy assignment of CUDA resource ownership.
 
GeometricRestraintForce & operator= (GeometricRestraintForce &&other)=delete
 Prevents move assignment of a potentially subscribed restraint.
 
void addPlane (const AtomSelection &selection, const std::array< double, 3 > &origin, const std::array< double, 3 > &direction, const double forceConstant, const double offset=0.0, const Activation activation=Activation::INSIDE, const SelectionMode selectionMode=SelectionMode::ATOMWISE)
 Adds a harmonic plane term for a copied atom selection.
 
void addPlane (const AtomReference &atom, const std::array< double, 3 > &origin, const std::array< double, 3 > &direction, const double forceConstant, const double offset=0.0, const Activation activation=Activation::INSIDE, const SelectionMode selectionMode=SelectionMode::ATOMWISE)
 Adds a harmonic plane term for one force-local atom index.
 
void addCylinder (const AtomSelection &selection, const std::array< double, 3 > &origin, const std::array< double, 3 > &direction, const double forceConstant, const double offset=0.0, const Activation activation=Activation::INSIDE, const SelectionMode selectionMode=SelectionMode::ATOMWISE)
 Adds a harmonic infinite-cylinder term for a copied selection.
 
void addCylinder (const AtomReference &atom, const std::array< double, 3 > &origin, const std::array< double, 3 > &direction, const double forceConstant, const double offset=0.0, const Activation activation=Activation::INSIDE, const SelectionMode selectionMode=SelectionMode::ATOMWISE)
 Adds a harmonic infinite-cylinder term for one atom index.
 
void addSphere (const AtomSelection &selection, const std::array< double, 3 > &center, const double forceConstant, const double offset=0.0, const Activation activation=Activation::INSIDE, const SelectionMode selectionMode=SelectionMode::ATOMWISE)
 Adds a harmonic sphere term for a copied atom selection.
 
void addSphere (const AtomReference &atom, const std::array< double, 3 > &center, const double forceConstant, const double offset=0.0, const Activation activation=Activation::INSIDE, const SelectionMode selectionMode=SelectionMode::ATOMWISE)
 Adds a harmonic sphere term for one force-local atom index.
 
void setMasses (const std::vector< double > &masses)
 Replaces the owned mass vector for all current and future RCM terms.
 
int getNumAtoms (void) const noexcept
 Returns the fixed atom count established during construction.
 
std::size_t getNumTerms (void) const noexcept
 Returns the number of currently installed geometric terms.
 
const std::vector< double > & getMasses (void) const noexcept
 Returns read-only access to the owned active mass vector.
 
std::shared_ptr< cudaStream_t > getStream (void)
 Returns shared access to the private CUDA stream holder.
 
std::shared_ptr< Force< AT > > getForce (void)
 Returns shared ownership of fixed-point device gradient storage.
 
std::shared_ptr< CudaEnergyVirial > getEnergyVirial (void)
 Returns shared ownership of energy and complete virial storage.
 
void reset (void)
 Removes all geometric terms while preserving masses and output.
 
void setBoxDimensions (const std::vector< double > &boxDimensions)
 Stores orthorhombic box lengths for ForceManager compatibility.
 
void initialize (const int numAtoms, const std::vector< double > &boxDimensions)
 Validates manager dimensions and prepares current device terms.
 
void clear (void)
 Enqueues clearing of all force, energy, and virial outputs.
 
void clear (const bool calcEnergy, const bool calcVirial)
 Clears gradients and the requested energy and virial outputs.
 
void calcForce (const float4 *xyzq, const bool calcEnergy, const bool calcVirial)
 Accumulates native gradients and optional energy and full virial.
 
bool supportsPBC (const PBC pbc) const noexcept
 Reports the P1-only compatibility of geometric restraints.
 

Static Public Attributes

static constexpr bool contributesVirial = true
 Reports that this restraint contributes the external virial tensor.
 
static constexpr bool computesVirial = true
 Reports that force evaluation supplies the complete virial tensor.
 

Detailed Description

template<typename AT, typename CT>
class GeometricRestraintForce< AT, CT >

Computes atomwise and center-of-mass harmonic geometric restraints.

One object owns a flattened collection of plane, cylinder, and sphere terms. For normalized direction n, position r, reference c, and displacement u, the geometry coordinates are:

u = r - c
s = dot(n, u)
q_plane = s for SYMMETRIC
q_plane = abs(s) for INSIDE or OUTSIDE
p = u - dot(n, u) * n
q_cylinder = norm(p)
q_sphere = norm(u)

A symmetric plane has grad(q) = n. A one-sided plane has grad(q) = sign(s) * n, with +n at exactly zero. Cylinder and sphere gradients are p / q and u / q, respectively. A computed squared radial distance at or below 1e-10 angstrom squared suppresses the entire radial contribution before activation, including the exact axis or center.

For force constant K and offset D, each active evaluation uses:

Delta = q - D
U_mmfp = (K / 2) * Delta^2
gradient = K * Delta * grad(q)
physical_force = -gradient

INSIDE is active for Delta > 0; OUTSIDE is active for Delta < 0; SYMMETRIC has no one-sided gate. Equality contributes zero. Finite positive, zero, and negative force constants and offsets are accepted. To preserve the characterized arithmetic, energy is evaluated as (0.5 * K) * (Delta * Delta). A computed zero energy suppresses the gradient even when energy output is disabled.

ATOMWISE evaluates each selected atom independently. RCM evaluates once at a signed mass-weighted center and distributes its gradient:

M = sum over selected atoms i of m_i
R = (sum over selected atoms i of m_i * r_i) / M
gradient_i = (m_i / M) * gradient_R

One owned mass vector serves all RCM terms. Signed and zero individual masses are accepted; each nonempty RCM selection requires a finite, nonzero total and finite mass fractions. Atomwise terms ignore masses. Selected totals use ascending atom-index order in double precision. Construction copies the PSF atom count and masses; term addition copies selected indices. No PSF, AtomSelection, or AtomReference owner is retained. A valid empty selection adds no term. Separate terms may overlap or repeat.

Only orthorhombic PBC::P1 is supported through ForceManager. Atom positions, RCM construction, and reference displacements use raw Cartesian coordinates without unwrapping or minimum-image replacement. Stored box lengths serve the manager lifecycle and do not alter this geometry. Positions and offsets are in angstroms, masses normally in atomic mass units, and K in kilocalories per mole per angstrom squared.

Gradients are summed at each atom in term insertion order before conversion to fixed point. Energy uses the named term mmfp. The complete external tensor uses raw absolute coordinates and unconverted double gradients:

W_ab = sum over atoms i of r_i,a * gradient_i,b

Energy and tensor components are in kilocalories per mole. Tensor order is XX, XY, XZ, YX, YY, YZ, ZX, ZY, ZZ; the tensor need not be symmetric or translation invariant. This defines the external coordinate-gradient tensor, not CHARMM's internal pressure accumulator. ForceManager aggregates it once and skips reconstruction because computesVirial is true.

Terms, selections, and reduction storage grow dynamically. Additions and reset() update host state; dirty device mirrors synchronize before use. setMasses() prepares coherent replacements before committing. Subscription retains shared ownership without freezing terms or masses. These operations remain available after initialization and subscription. reset() removes terms while preserving masses, box lengths, and output; clear() clears output while preserving the configured terms and masses.

Template Parameters
ATDevice force-accumulator representation. Only long long int is supported, using apoCHARMM's fixed-point scale of 2^40.
CTFinal Cartesian-gradient conversion representation, either float or double. Geometry, energy, and RCM arithmetic use double precision; both specializations read current coordinates from float4.
Warning
The class provides no internal host-thread synchronization. Callers must serialize configuration, clearing, calculation, destruction, and all operations on a subscribing manager that access this force.
Coordinate quantization and fixed-point range limit the supported numerical domain. CT = double does not recover coordinates lost at input. Directions use a positive finite std::hypot norm; this typed envelope does not emulate CHARMM's text-parser underflow or overflow paths.
calcForce() synchronizes for numerical validation before queuing its output commit. CUDA graph capture is unsupported. Keep the CUDA context and borrowed device buffers alive until queued work completes, and release owned resources before resetting their device.
See also
AtomReference
AtomSelection
ForceManager
PBC

Member Enumeration Documentation

◆ Activation

template<typename AT , typename CT >
enum class GeometricRestraintForce::Activation : int
strong

Selects the activation predicate applied to the geometry coordinate.

A plane uses signed distance for SYMMETRIC and absolute distance for one-sided modes. Cylinder and sphere coordinates are nonnegative radii. The radial singular-suppression rule takes precedence over activation.

Enumerator
SYMMETRIC 

Applies the harmonic law on both sides of the requested offset.

INSIDE 

Activates when the geometry coordinate is greater than the offset.

OUTSIDE 

Activates when the geometry coordinate is less than the offset.

◆ Geometry

template<typename AT , typename CT >
enum class GeometricRestraintForce::Geometry : int
strong

Selects the geometry of an atomwise or RCM restraint term.

Enumerator
PLANE 

Uses a plane through the reference with the configured normal.

CYLINDER 

Uses an infinite cylinder with the configured reference and axis.

SPHERE 

Uses radial distance from the configured center.

◆ PotentialType

template<typename AT , typename CT >
enum class GeometricRestraintForce::PotentialType : int
strong

Identifies the implemented geometric-restraint potential.

Enumerator
HARMONIC 

Uses energy K * (q - offset)^2 / 2 for an active evaluation.

◆ SelectionMode

template<typename AT , typename CT >
enum class GeometricRestraintForce::SelectionMode : int
strong

Selects independent atom evaluations or one mass-weighted center.

Enumerator
ATOMWISE 

Evaluates each selected atom independently without mass weighting.

RCM 

Evaluates the signed center and distributes its gradient by mass.

Constructor & Destructor Documentation

◆ GeometricRestraintForce() [1/4]

template<typename AT , typename CT >
GeometricRestraintForce< AT, CT >::GeometricRestraintForce ( void  )
delete

Prevents construction without a PSF atom-count and mass snapshot.

See also
CharmmPSF

◆ GeometricRestraintForce() [2/4]

template<typename AT , typename CT >
GeometricRestraintForce< AT, CT >::GeometricRestraintForce ( const std::shared_ptr< const CharmmPSF > &  psf)
explicit

Constructs an empty geometric restraint from a PSF snapshot.

The positive atom count and complete mass vector are copied. The PSF and its shared owner are borrowed only for this call and are not retained. Finite positive, zero, and negative individual masses are accepted.

Construction creates a private CUDA stream, a fixed-point force array, and a CudaEnergyVirial containing the named term mmfp. Force, energy, and virial outputs are cleared and the private stream is synchronized before return. Stored box dimensions are initially zero.

Parameters
[in]psfNon-null PSF with an initialized positive atom count and exactly one finite mass, in atomic mass units, per atom. The atom count must fit the existing fixed-point force-storage representation.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::NotInitialized if the PSF atom count is negative.
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if psf is null, the atom count is zero or exceeds the force-storage representation limit, or a mass is NaN or infinite.
ApoCharmmErrorWith code ApoCharmmErrorCode::Runtime if the PSF mass-vector length differs from its atom count.
ApoCharmmErrorWith code ApoCharmmErrorCode::Cuda if allocation, transfer, stream creation, output clearing, or synchronization fails.
std::bad_allocIf host storage, shared ownership state, or an error diagnostic cannot be allocated.
std::length_errorIf requested storage or an error diagnostic exceeds an implementation-defined limit.
Postcondition
getNumAtoms() == psf->getNumAtoms() and getForce()->size() == getNumAtoms().
getNumTerms() == 0, and force, energy, and virial outputs are zero.
See also
setMasses
initialize

◆ GeometricRestraintForce() [3/4]

template<typename AT , typename CT >
GeometricRestraintForce< AT, CT >::GeometricRestraintForce ( const GeometricRestraintForce< AT, CT > &  other)
delete

Prevents copying a restraint that owns CUDA resources.

Parameters
[in]otherSource restraint. Copy construction is not provided.

◆ GeometricRestraintForce() [4/4]

template<typename AT , typename CT >
GeometricRestraintForce< AT, CT >::GeometricRestraintForce ( GeometricRestraintForce< AT, CT > &&  other)
delete

Prevents moving an object referenced by subscribed force views.

Parameters
[in]otherSource restraint. Move construction is not provided.
See also
ForceView

◆ ~GeometricRestraintForce()

template<typename AT , typename CT >
GeometricRestraintForce< AT, CT >::~GeometricRestraintForce ( void  )
noexcept

Destroys the private CUDA stream and releases owned resources.

CUDA stream destruction is attempted without propagating cleanup failure. A shared holder returned by getStream() may outlive this object, but its stored stream value is set to nullptr during destruction.

Force and energy objects returned by getForce() and getEnergyVirial() remain allocated while another shared owner exists. No restraint remains to calculate into them after destruction.

Postcondition
The private CUDA stream is no longer valid.
Warning
Do not overlap destruction with host calls or external CUDA work that accesses this restraint's storage.
See also
getStream
ForceManager::subscribe

Member Function Documentation

◆ addCylinder() [1/2]

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::addCylinder ( const AtomReference &  atom,
const std::array< double, 3 > &  origin,
const std::array< double, 3 > &  direction,
const double  forceConstant,
const double  offset = 0.0,
const Activation  activation = Activation::INSIDE,
const SelectionMode  selectionMode = SelectionMode::ATOMWISE 
)

Adds a harmonic infinite-cylinder term for one atom index.

Only the force-local index is used; the AtomReference topology is not compared or retained. Geometry, singular suppression, host copying, and deferred device updates match the selection overload. The operation is valid after initialization or subscription.

Parameters
[in]atomBorrowed reference with an index in [0, getNumAtoms()).
[in]originThree finite axis-reference coordinates in [x, y, z] order and angstrom units.
[in]directionThree finite dimensionless axis components with a positive finite Euclidean norm; the normalized direction is copied.
[in]forceConstantFinite signed harmonic coefficient in kilocalories per mole per square angstrom.
[in]offsetFinite signed CHARMM DROFF value in angstroms; default zero.
[in]activationSYMMETRIC, INSIDE, or OUTSIDE; default INSIDE.
[in]selectionModeATOMWISE or RCM; default ATOMWISE. For RCM, the selected atom must have a finite nonzero active mass.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the atom index, parameter, enum value, direction norm, membership count, or RCM mass is invalid.
std::bad_allocIf copied term, index, or diagnostic storage cannot be allocated.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Postcondition
On success, one term is appended; existing terms and outputs remain.
Validation or allocation failure leaves installed terms unchanged.
See also
AtomReference
addCylinder

◆ addCylinder() [2/2]

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::addCylinder ( const AtomSelection &  selection,
const std::array< double, 3 > &  origin,
const std::array< double, 3 > &  direction,
const double  forceConstant,
const double  offset = 0.0,
const Activation  activation = Activation::INSIDE,
const SelectionMode  selectionMode = SelectionMode::ATOMWISE 
)

Adds a harmonic infinite-cylinder term for a copied selection.

The axis passes through origin along the normalized direction. The reaction coordinate is perpendicular distance to that axis. A computed squared radial distance at or below 1e-10 square angstroms suppresses energy and gradient before activation, including on the axis. Raw Cartesian displacements are used without periodic imaging.

Indices and parameters are copied into owned host storage. No caller storage is retained and no CUDA transfer or synchronization occurs. Device mirrors are updated before use. Adding a term after initialization or subscription does not require resubscription.

Parameters
[in]selectionSelection representing exactly getNumAtoms() atoms. A valid empty selection is a no-op after parameter validation and adds neither a term nor an RCM center.
[in]originThree finite axis-reference coordinates in [x, y, z] order and angstrom units.
[in]directionThree finite dimensionless axis components with a positive finite Euclidean norm, normalized using double-precision std::hypot. Positive scaling or reversal leaves the geometry unchanged.
[in]forceConstantFinite signed harmonic coefficient in kilocalories per mole per square angstrom.
[in]offsetFinite signed CHARMM DROFF value in angstroms; default zero.
[in]activationSYMMETRIC, INSIDE, or OUTSIDE; default INSIDE.
[in]selectionModeATOMWISE or RCM; default ATOMWISE. A nonempty RCM selection requires a finite nonzero signed total and finite mass/total ratios, even when forceConstant is zero.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the selection atom count, parameter, enum value, direction norm, membership count, or RCM mass requirement is invalid.
std::bad_allocIf copied term, index, or diagnostic storage cannot be allocated.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Postcondition
On success with a nonempty selection, one term is appended; existing terms and outputs remain. Validation or allocation failure preserves terms.
See also
addPlane
addSphere
setMasses

◆ addPlane() [1/2]

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::addPlane ( const AtomReference &  atom,
const std::array< double, 3 > &  origin,
const std::array< double, 3 > &  direction,
const double  forceConstant,
const double  offset = 0.0,
const Activation  activation = Activation::INSIDE,
const SelectionMode  selectionMode = SelectionMode::ATOMWISE 
)

Adds a harmonic plane term for one force-local atom index.

The AtomReference topology is not compared or retained. Only its index is validated against this restraint. Geometry, signed-parameter acceptance, host copying, and deferred device-update behavior match the selection overload. This method may be used after initialization or subscription.

Parameters
[in]atomBorrowed reference with an index in [0, getNumAtoms()).
[in]originThree finite coordinates in [x, y, z] order and angstrom units.
[in]directionThree finite dimensionless components with a positive finite Euclidean norm; the normalized direction is copied.
[in]forceConstantFinite signed harmonic coefficient in kilocalories per mole per square angstrom.
[in]offsetFinite signed CHARMM DROFF value in angstroms; default zero.
[in]activationSYMMETRIC, INSIDE, or OUTSIDE; default INSIDE.
[in]selectionModeATOMWISE or RCM; default ATOMWISE. For RCM, the selected atom must have a finite nonzero active mass.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the atom index, parameter, enum value, direction norm, membership count, or RCM mass is invalid.
std::bad_allocIf copied term, index, or diagnostic storage cannot be allocated.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Postcondition
On success, one term is appended; existing terms and outputs remain.
Validation or allocation failure leaves installed terms unchanged.
See also
AtomReference
addPlane

◆ addPlane() [2/2]

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::addPlane ( const AtomSelection &  selection,
const std::array< double, 3 > &  origin,
const std::array< double, 3 > &  direction,
const double  forceConstant,
const double  offset = 0.0,
const Activation  activation = Activation::INSIDE,
const SelectionMode  selectionMode = SelectionMode::ATOMWISE 
)

Adds a harmonic plane term for a copied atom selection.

The plane passes through origin with a normalized direction. SYMMETRIC uses signed distance; INSIDE and OUTSIDE use absolute slab distance. Direction normalization uses double-precision std::hypot.

Selected indices and parameters are copied into owned host storage. No selection, topology, or caller storage is retained. This method does not transfer or synchronize CUDA data; device mirrors are updated before the next evaluation. Terms may be added after initialization or subscription without replacing output owners or resubscribing.

Parameters
[in]selectionSelection representing exactly getNumAtoms() atoms. A valid empty selection is an accepted no-op after parameter validation; it adds no term and does not require an RCM total-mass calculation.
[in]originThree finite coordinates in [x, y, z] order and angstrom units.
[in]directionThree finite dimensionless components with a positive finite Euclidean norm. The normalized direction is copied.
[in]forceConstantFinite harmonic coefficient in kilocalories per mole per square angstrom. Positive, zero, and negative values are accepted.
[in]offsetFinite CHARMM DROFF value in angstroms. Positive, zero, and negative values are accepted; the default is zero.
[in]activationSYMMETRIC, INSIDE, or OUTSIDE; the default is INSIDE.
[in]selectionModeATOMWISE or RCM; the default is ATOMWISE. A nonempty RCM selection requires a finite nonzero signed total mass and finite mass/total ratios, including when forceConstant is zero.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the selection atom count differs, a parameter or enum value is invalid, the direction norm is invalid, membership count would overflow, or an RCM mass requirement is violated.
std::bad_allocIf copied term, index, or diagnostic storage cannot be allocated.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Postcondition
On success with a nonempty selection, one term is appended in insertion order. Existing terms and output values are preserved.
Validation or allocation failure leaves installed terms unchanged.
See also
addCylinder
addSphere
setMasses

◆ addSphere() [1/2]

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::addSphere ( const AtomReference &  atom,
const std::array< double, 3 > &  center,
const double  forceConstant,
const double  offset = 0.0,
const Activation  activation = Activation::INSIDE,
const SelectionMode  selectionMode = SelectionMode::ATOMWISE 
)

Adds a harmonic sphere term for one force-local atom index.

Only the index is used; the AtomReference topology is not compared or retained. Geometry, singular suppression, host copying, and deferred device updates match the selection overload. The operation is valid after initialization or subscription.

Parameters
[in]atomBorrowed reference with an index in [0, getNumAtoms()).
[in]centerThree finite center coordinates in [x, y, z] order and angstrom units.
[in]forceConstantFinite signed harmonic coefficient in kilocalories per mole per square angstrom.
[in]offsetFinite signed CHARMM DROFF value in angstroms; default zero.
[in]activationSYMMETRIC, INSIDE, or OUTSIDE; default INSIDE.
[in]selectionModeATOMWISE or RCM; default ATOMWISE. For RCM, the selected atom must have a finite nonzero active mass.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the atom index, parameter, enum value, membership count, or RCM mass is invalid.
std::bad_allocIf copied term, index, or diagnostic storage cannot be allocated.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Postcondition
On success, one term is appended; existing terms and outputs remain.
Validation or allocation failure leaves installed terms unchanged.
See also
AtomReference
addSphere

◆ addSphere() [2/2]

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::addSphere ( const AtomSelection &  selection,
const std::array< double, 3 > &  center,
const double  forceConstant,
const double  offset = 0.0,
const Activation  activation = Activation::INSIDE,
const SelectionMode  selectionMode = SelectionMode::ATOMWISE 
)

Adds a harmonic sphere term for a copied atom selection.

The reaction coordinate is the raw Cartesian distance to center, with no periodic imaging. A computed squared distance at or below 1e-10 square angstroms suppresses energy and gradient before activation, including at the exact center.

Indices and parameters are copied into owned host storage. No caller storage is retained and no CUDA transfer or synchronization occurs. Device mirrors are updated before use. Adding a term after initialization or subscription does not require resubscription.

Parameters
[in]selectionSelection representing exactly getNumAtoms() atoms. A valid empty selection is a no-op after parameter validation and adds neither a term nor an RCM center.
[in]centerThree finite center coordinates in [x, y, z] order and angstrom units.
[in]forceConstantFinite signed harmonic coefficient in kilocalories per mole per square angstrom.
[in]offsetFinite signed CHARMM DROFF value in angstroms; default zero.
[in]activationSYMMETRIC, INSIDE, or OUTSIDE; default INSIDE.
[in]selectionModeATOMWISE or RCM; default ATOMWISE. A nonempty RCM selection requires a finite nonzero signed total and finite mass/total ratios, even when forceConstant is zero.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the selection atom count, parameter, enum value, membership count, or RCM mass requirement is invalid.
std::bad_allocIf copied term, index, or diagnostic storage cannot be allocated.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Postcondition
On success with a nonempty selection, one term is appended; existing terms and outputs remain. Validation or allocation failure preserves terms.
See also
addPlane
addCylinder
setMasses

◆ calcForce()

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::calcForce ( const float4 *  xyzq,
const bool  calcEnergy,
const bool  calcVirial 
)

Accumulates native gradients and optional energy and full virial.

Dirty term mirrors are rebuilt before evaluation. Term gradients are summed at each atom in insertion order, converted through CT, and added to the fixed-point output. Physical force is the negative of that stored gradient. The tensor uses raw positions and the new unconverted double gradient sum, including mass-distributed RCM gradients.

Evaluation and output-range checks are staged on the private stream. The method synchronizes that stream to validate the result, then enqueues the output commit. Energy and virial are accumulated only when their flags are true; disabled outputs retain previous values and can be stale.

Parameters
[in]xyzqBorrowed CUDA-device pointer to at least getNumAtoms() contiguous float4 records in [x, y, z, charge] order. Coordinates use angstroms; the charge component is ignored. With installed terms the pointer must be non-null and remain valid until the private stream has finished using it.
[in]calcEnergyWhether to add the evaluated energy to the device mmfp term. The energy-zero gradient gate and finite-arithmetic checks still apply when this flag is false.
[in]calcVirialWhether to add all nine external virial components in W_ab = sum_i r_i,a * g_i,b order.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if terms exist and xyzq is null.
ApoCharmmErrorWith code ApoCharmmErrorCode::Runtime if a term is unsupported, evaluated arithmetic is nonfinite, gradient conversion is outside the fixed-point range, or accumulation would overflow.
ApoCharmmErrorWith code ApoCharmmErrorCode::Cuda if allocation, transfer, a kernel launch, or synchronization fails.
std::bad_allocIf rebuilding host storage or constructing an error diagnostic cannot allocate storage.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Precondition
With installed terms, xyzq is device-accessible, correctly sized, ready for this stream to read, and not subject to concurrent writes.
Order clear() before this call when fresh output is required.
Postcondition
A numerical rejection leaves the pre-existing public outputs intact.
Successful return with terms means output commitment was enqueued; the final commit may still be executing on the private stream.
Note
With no terms, the method returns without validating xyzq, clearing outputs, or synchronizing. It adds no contribution.
Warning
CUDA failures do not provide an output rollback guarantee. Complete the private stream before consuming committed outputs on another stream.
See also
clear
getForce
getEnergyVirial

◆ clear() [1/2]

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::clear ( const bool  calcEnergy,
const bool  calcVirial 
)

Clears gradients and the requested energy and virial outputs.

ForceManager uses this overload before calculation. Clears are enqueued on the private stream without synchronizing before return. Terms, masses, and box values are preserved.

Parameters
[in]calcEnergyWhether to zero energy storage. A false value preserves the previous energy, which may be stale for new coordinates.
[in]calcVirialWhether to zero virial storage. A false value preserves the previous tensor, which may be stale for new coordinates.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::Cuda if an output clear reports an immediate CUDA failure.
Postcondition
After the private stream completes the queued clears, gradients and the requested outputs are zero; disabled outputs retain their values.
Warning
A CUDA failure can leave some clears queued and others incomplete.
See also
calcForce
reset

◆ clear() [2/2]

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::clear ( void  )

Enqueues clearing of all force, energy, and virial outputs.

This overload delegates to clear(true, true). Clears use the private stream and return without synchronizing. Terms, masses, and box values are preserved.

Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::Cuda if an output clear reports an immediate CUDA failure.
Postcondition
After the private stream completes the queued clears, all force, energy, and virial outputs are zero.
Warning
A CUDA failure can leave some clears queued and others incomplete.
See also
reset
getStream

◆ getEnergyVirial()

template<typename AT , typename CT >
std::shared_ptr< CudaEnergyVirial > GeometricRestraintForce< AT, CT >::getEnergyVirial ( void  )

Returns shared ownership of energy and complete virial storage.

The object contains the named energy term mmfp and the complete external tensor W_ab = sum_i r_i,a * g_i,b, both in kilocalories per mole. Tensor components are ordered XX, XY, XZ, YX, YY, YZ, ZX, ZY, ZZ. The manager must not add another coordinate-gradient reconstruction for this force.

Returns
A copied shared owner of the restraint's CudaEnergyVirial object. No transfer or synchronization occurs. Storage may outlive this restraint while another shared owner remains.
Warning
Copy device values to the host and synchronize before reading them. A disabled calculation flag leaves its previous output stale.
See also
calcForce
computesVirial

◆ getForce()

template<typename AT , typename CT >
std::shared_ptr< Force< AT > > GeometricRestraintForce< AT, CT >::getForce ( void  )

Returns shared ownership of fixed-point device gradient storage.

The array contains getNumAtoms() vectors in structure-of-arrays layout. Multiply raw long long int components by INV_FORCE_SCALE to recover potential gradients in kilocalories per mole per angstrom. Physical forces have the opposite sign.

Returns
A copied shared owner of the restraint's Force<AT> object. No transfer or synchronization occurs. Storage may outlive this restraint while another shared owner remains.
Warning
Order accesses after pending work on getStream() and do not resize or concurrently modify this storage while the restraint or manager is using it.
See also
calcForce
ForceManager::subscribe

◆ getMasses()

template<typename AT , typename CT >
const std::vector< double > & GeometricRestraintForce< AT, CT >::getMasses ( void  ) const
noexcept

Returns read-only access to the owned active mass vector.

Returns
Borrowed host vector containing getNumAtoms() masses in atom-index order and atomic mass units. No transfer or synchronization occurs.
Warning
The reference does not extend the restraint's lifetime. Successful setMasses() replaces element storage and invalidates borrowed element pointers and iterators.
See also
setMasses

◆ getNumAtoms()

template<typename AT , typename CT >
int GeometricRestraintForce< AT, CT >::getNumAtoms ( void  ) const
noexcept

Returns the fixed atom count established during construction.

Returns
Positive dimensionless number of atom entries in the mass and force arrays. No CUDA transfer or synchronization occurs.

◆ getNumTerms()

template<typename AT , typename CT >
std::size_t GeometricRestraintForce< AT, CT >::getNumTerms ( void  ) const
noexcept

Returns the number of currently installed geometric terms.

Returns
Dimensionless term count, including duplicates and overlapping selections. Accepted empty selections add no term. No CUDA transfer or synchronization occurs.
See also
reset

◆ getStream()

template<typename AT , typename CT >
std::shared_ptr< cudaStream_t > GeometricRestraintForce< AT, CT >::getStream ( void  )

Returns shared access to the private CUDA stream holder.

The shared pointer owns the host scalar containing the handle. This restraint remains responsible for destroying the underlying CUDA stream and sets the scalar to nullptr during destruction.

Returns
A copied shared owner of the stream holder. The underlying stream is valid only while the restraint remains alive. No synchronization occurs.
Warning
Do not replace the handle or destroy the stream through the holder.
See also
ForceManager::subscribe

◆ initialize()

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::initialize ( const int  numAtoms,
const std::vector< double > &  boxDimensions 
)

Validates manager dimensions and prepares current device terms.

This ForceManager hook checks the fixed atom count, stores the supplied box, and synchronizes term mirrors when they are dirty. Rebuilding waits for the private stream and uses synchronous host-to-device transfers. No separate initialized flag is set and output owners are not replaced.

Parameters
[in]numAtomsDimensionless manager atom count; it must equal getNumAtoms().
[in]boxDimensionsExactly three finite positive orthorhombic box lengths in [x, y, z] order and angstrom units.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the atom count differs or the box contract is violated.
ApoCharmmErrorWith code ApoCharmmErrorCode::Cuda if device allocation, transfer, or synchronization fails.
std::bad_allocIf derived host storage or an error diagnostic cannot be allocated.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Postcondition
On success, device terms match current host terms and the supplied box is stored. Terms, masses, and output values are preserved.
Warning
Preparation is not fully transactional: the box is stored before device rebuilding, and allocation or transfer failure can leave mirrors partly rebuilt. They remain dirty and must rebuild successfully before use.
See also
setBoxDimensions
calcForce

◆ operator=() [1/2]

template<typename AT , typename CT >
GeometricRestraintForce & GeometricRestraintForce< AT, CT >::operator= ( const GeometricRestraintForce< AT, CT > &  other)
delete

Prevents copy assignment of CUDA resource ownership.

Parameters
[in]otherSource restraint. Copy assignment is not provided.

◆ operator=() [2/2]

template<typename AT , typename CT >
GeometricRestraintForce & GeometricRestraintForce< AT, CT >::operator= ( GeometricRestraintForce< AT, CT > &&  other)
delete

Prevents move assignment of a potentially subscribed restraint.

Parameters
[in]otherSource restraint. Move assignment is not provided.
See also
ForceView

◆ reset()

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::reset ( void  )

Removes all geometric terms while preserving masses and output.

Host term storage is emptied and device mirrors are marked for rebuilding before use. No CUDA work or synchronization is performed. The box, active masses, stream, force storage, and energy-virial owner remain unchanged. This method is valid while subscribed and does not unsubscribe the force.

Exceptions
std::bad_allocIf the replacement empty offset vector cannot be allocated.
Postcondition
getNumTerms() == 0; subsequent evaluations add no contribution until new terms are installed.
An allocation failure leaves installed terms unchanged.
Note
Existing output is not cleared and earlier queued output work is not waited for. Use clear() when zeroed output is required.
See also
clear
setMasses

◆ setBoxDimensions()

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::setBoxDimensions ( const std::vector< double > &  boxDimensions)

Stores orthorhombic box lengths for ForceManager compatibility.

The three values are copied into host scalar state after validation. They do not wrap coordinates, unwrap RCM selections, image displacements, or rescale restraint references. No CUDA transfer or synchronization occurs.

Parameters
[in]boxDimensionsExactly three finite positive lengths in [x, y, z] order and angstrom units, borrowed for this call.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the vector length is not three or any length is non-positive, NaN, or infinite.
std::bad_allocIf an error diagnostic cannot be allocated.
std::length_errorIf an error diagnostic exceeds an implementation-defined limit.
Postcondition
On success, the stored box is replaced. Validation failure preserves the previous box and all terms and outputs.
See also
initialize
supportsPBC

◆ setMasses()

template<typename AT , typename CT >
void GeometricRestraintForce< AT, CT >::setMasses ( const std::vector< double > &  masses)

Replaces the owned mass vector for all current and future RCM terms.

The entire vector and every installed RCM selection are validated before replacement storage is allocated. Every RCM total must be finite and nonzero, and each selected mass/total ratio must be finite. Signed and zero individual masses, negative totals, and tiny nonzero totals are accepted within that envelope. Atomwise terms ignore masses.

The private stream is synchronized before replacement. Independent host and device copies of masses and derived totals are prepared with synchronous transfers before a nonthrowing commit. Caller storage is not retained. Initialization or subscription does not restrict this operation, and reset() and clear() preserve the resulting masses.

Parameters
[in]massesExactly getNumAtoms() finite values in atom-index order and atomic mass units, borrowed for the duration of the call.
Exceptions
ApoCharmmErrorWith code ApoCharmmErrorCode::InvalidArgument if the length differs, any mass is nonfinite, or an installed RCM total or mass fraction is invalid.
ApoCharmmErrorWith code ApoCharmmErrorCode::Cuda if stream synchronization, replacement allocation, transfer, or device synchronization fails.
std::bad_allocIf replacement host or diagnostic storage cannot be allocated.
std::length_errorIf storage or a diagnostic exceeds an implementation-defined limit.
Postcondition
On success, all RCM terms use the copied masses on their next evaluation; installed terms and output owners are unchanged.
Failure before commit preserves active host/device masses and totals.
Warning
Reacquire element pointers and iterators borrowed through getMasses() after successful replacement.
See also
getMasses
SelectionMode

◆ supportsPBC()

template<typename AT , typename CT >
bool GeometricRestraintForce< AT, CT >::supportsPBC ( const PBC  pbc) const
noexcept

Reports the P1-only compatibility of geometric restraints.

ForceView uses this query during manager subscription and PBC mutation. The query does not change state or perform CUDA work.

Parameters
[in]pbcPeriodic-boundary value to inspect.
Returns
true only for PBC::P1; false for PBC::UNSET, PBC::P21, and unnamed enum values. UNSET is an invalid sentinel, not an aperiodic configuration.
See also
ForceView::supportsPBC
ForceManager::setPeriodicBoundaryCondition

Member Data Documentation

◆ computesVirial

template<typename AT , typename CT >
constexpr bool GeometricRestraintForce< AT, CT >::computesVirial = true
staticconstexpr

Reports that force evaluation supplies the complete virial tensor.

ForceView uses this trait to skip manager-side force conversion and coordinate-gradient reconstruction. The tensor is aggregated once.

◆ contributesVirial

template<typename AT , typename CT >
constexpr bool GeometricRestraintForce< AT, CT >::contributesVirial = true
staticconstexpr

Reports that this restraint contributes the external virial tensor.

ForceManager requests the tensor when global virial calculation is enabled and includes the stored nine-component contribution in its aggregate.