forked from lijiext/lammps
715 lines
22 KiB
C++
715 lines
22 KiB
C++
// -*- c++ -*-
|
|
|
|
// This file is part of the Collective Variables module (Colvars).
|
|
// The original version of Colvars and its updates are located at:
|
|
// https://github.com/colvars/colvars
|
|
// Please update all Colvars source files before making any changes.
|
|
// If you wish to distribute your changes, please submit them to the
|
|
// Colvars repository at GitHub.
|
|
|
|
#ifndef COLVARVALUE_H
|
|
#define COLVARVALUE_H
|
|
|
|
#include "colvarmodule.h"
|
|
#include "colvartypes.h"
|
|
|
|
|
|
/// \brief Value of a collective variable: this is a metatype which
|
|
/// can be set at runtime. By default it is set to be a scalar
|
|
/// number, and can be treated as such in all operations (this is
|
|
/// done by most \link cvc \endlink implementations).
|
|
///
|
|
/// \link colvarvalue \endlink allows \link colvar \endlink to be
|
|
/// treat different data types. By default, a \link colvarvalue
|
|
/// \endlink variable is a scalar number. To use it as
|
|
/// another type, declare and initialize it as
|
|
/// \code colvarvalue x(colvarvalue::type_xxx)\endcode, use \link x.type
|
|
/// (colvarvalue::type_xxx) \endlink at a later stage, or if unset,
|
|
/// assign the type with \code x = y; \endcode, provided y is correctly set.
|
|
///
|
|
/// All operators (either unary or binary) on a \link
|
|
/// colvarvalue \endlink object performs one or more checks on the
|
|
/// \link Type \endlink, except when reading from a stream, when there is no way to
|
|
/// detect the \link Type \endlink. To use \code is >> x; \endcode x \b MUST
|
|
/// already have a type correcly set up for properly parsing the
|
|
/// stream. No problem of course with the output streams: \code os << x; \endcode
|
|
///
|
|
/// \em Note \em on \em performance: to avoid type checks in a long array of \link
|
|
/// colvarvalue \endlink objects, use one of the existing "_opt" functions or implement a new one
|
|
|
|
|
|
class colvarvalue {
|
|
|
|
public:
|
|
|
|
/// \brief Possible types of value
|
|
///
|
|
/// These three cover most possibilities of data type one can
|
|
/// devise. If you need to implement a new colvar with a very
|
|
/// complex data type, it's better to put an allocatable class here
|
|
enum Type {
|
|
/// Undefined type
|
|
type_notset,
|
|
/// Scalar number, implemented as \link colvarmodule::real \endlink (default)
|
|
type_scalar,
|
|
/// 3-dimensional vector, implemented as \link colvarmodule::rvector \endlink
|
|
type_3vector,
|
|
/// 3-dimensional unit vector, implemented as \link colvarmodule::rvector \endlink
|
|
type_unit3vector,
|
|
/// 3-dimensional vector that is a derivative of a unitvector
|
|
type_unit3vectorderiv,
|
|
/// 4-dimensional unit vector representing a rotation, implemented as \link colvarmodule::quaternion \endlink
|
|
type_quaternion,
|
|
/// 4-dimensional vector that is a derivative of a quaternion
|
|
type_quaternionderiv,
|
|
/// vector (arbitrary dimension)
|
|
type_vector,
|
|
/// Needed to iterate through enum
|
|
type_all
|
|
};
|
|
|
|
/// Current type of this colvarvalue object
|
|
Type value_type;
|
|
|
|
/// \brief Real data member
|
|
cvm::real real_value;
|
|
|
|
/// \brief 3-dimensional vector data member
|
|
cvm::rvector rvector_value;
|
|
|
|
/// \brief Quaternion data member
|
|
cvm::quaternion quaternion_value;
|
|
|
|
/// \brief Generic vector data member
|
|
cvm::vector1d<cvm::real> vector1d_value;
|
|
|
|
/// \brief If \link vector1d_value \endlink is a concatenation of colvarvalues,
|
|
/// keep track of the individual types
|
|
std::vector<Type> elem_types;
|
|
|
|
/// \brief If \link vector1d_value \endlink is a concatenation of colvarvalues,
|
|
/// these mark the initial components of each colvarvalue
|
|
std::vector<int> elem_indices;
|
|
|
|
/// \brief If \link vector1d_value \endlink is a concatenation of colvarvalues,
|
|
/// these mark how many components for each colvarvalue
|
|
std::vector<int> elem_sizes;
|
|
|
|
/// \brief Whether or not the type check is enforced
|
|
static inline bool type_checking()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/// Runtime description of value types
|
|
static std::string const type_desc(Type t);
|
|
|
|
/// User keywords for specifying value types in the configuration
|
|
static std::string const type_keyword(Type t);
|
|
|
|
/// Number of degrees of freedom for each supported type
|
|
static size_t num_df(Type t);
|
|
|
|
/// Number of dimensions for each supported type (used to allocate vector1d_value)
|
|
static size_t num_dimensions(Type t);
|
|
|
|
/// Number of dimensions of this variable
|
|
size_t size() const;
|
|
|
|
/// \brief Default constructor: this class defaults to a scalar
|
|
/// number and always behaves like it unless you change its type
|
|
inline colvarvalue()
|
|
: value_type(type_scalar), real_value(0.0)
|
|
{}
|
|
|
|
/// Constructor from a type specification
|
|
inline colvarvalue(Type const &vti)
|
|
: value_type(vti)
|
|
{
|
|
reset();
|
|
}
|
|
|
|
/// Copy constructor from real base type
|
|
inline colvarvalue(cvm::real const &x)
|
|
: value_type(type_scalar), real_value(x)
|
|
{}
|
|
|
|
/// \brief Copy constructor from rvector base type (Note: this sets
|
|
/// by default a type \link type_3vector \endlink , if you want a
|
|
/// \link type_unit3vector \endlink you must set it explicitly)
|
|
inline colvarvalue(cvm::rvector const &v, Type vti = type_3vector)
|
|
: value_type(vti), rvector_value(v)
|
|
{}
|
|
|
|
/// \brief Copy constructor from quaternion base type
|
|
inline colvarvalue(cvm::quaternion const &q, Type vti = type_quaternion)
|
|
: value_type(vti), quaternion_value(q)
|
|
{}
|
|
|
|
/// Copy constructor from vector1d base type
|
|
colvarvalue(cvm::vector1d<cvm::real> const &v, Type vti = type_vector);
|
|
|
|
/// Copy constructor from another \link colvarvalue \endlink
|
|
colvarvalue(colvarvalue const &x);
|
|
|
|
|
|
/// Set to the null value for the data type currently defined
|
|
void reset();
|
|
|
|
/// \brief If the variable has constraints (e.g. unitvector or
|
|
/// quaternion), transform it to satisfy them; this function needs
|
|
/// to be called only when the \link colvarvalue \endlink
|
|
/// is calculated outside of \link cvc \endlink objects
|
|
void apply_constraints();
|
|
|
|
/// Get the current type
|
|
inline Type type() const
|
|
{
|
|
return value_type;
|
|
}
|
|
|
|
/// Set the type explicitly
|
|
void type(Type const &vti);
|
|
|
|
/// Set the type after another \link colvarvalue \endlink
|
|
void type(colvarvalue const &x);
|
|
|
|
/// Make the type a derivative of the original type
|
|
/// (so that its constraints do not apply)
|
|
void is_derivative();
|
|
|
|
/// Square norm of this colvarvalue
|
|
cvm::real norm2() const;
|
|
|
|
/// Norm of this colvarvalue
|
|
inline cvm::real norm() const
|
|
{
|
|
return std::sqrt(this->norm2());
|
|
}
|
|
|
|
/// Square distance between this \link colvarvalue \endlink and another
|
|
cvm::real dist2(colvarvalue const &x2) const;
|
|
|
|
/// Derivative with respect to this \link colvarvalue \endlink of the square distance
|
|
colvarvalue dist2_grad(colvarvalue const &x2) const;
|
|
|
|
/// Return the midpoint between x1 and x2, optionally weighted by lambda
|
|
/// (which must be between 0.0 and 1.0)
|
|
static colvarvalue const interpolate(colvarvalue const &x1,
|
|
colvarvalue const &x2,
|
|
cvm::real const lambda = 0.5);
|
|
|
|
/// Assignment operator (type of x is checked)
|
|
colvarvalue & operator = (colvarvalue const &x);
|
|
|
|
void operator += (colvarvalue const &x);
|
|
void operator -= (colvarvalue const &x);
|
|
void operator *= (cvm::real const &a);
|
|
void operator /= (cvm::real const &a);
|
|
|
|
// Binary operators (return values)
|
|
friend colvarvalue operator + (colvarvalue const &x1, colvarvalue const &x2);
|
|
friend colvarvalue operator - (colvarvalue const &x1, colvarvalue const &x2);
|
|
friend colvarvalue operator * (colvarvalue const &x, cvm::real const &a);
|
|
friend colvarvalue operator * (cvm::real const &a, colvarvalue const &x);
|
|
friend colvarvalue operator / (colvarvalue const &x, cvm::real const &a);
|
|
|
|
/// Inner product
|
|
friend cvm::real operator * (colvarvalue const &x1, colvarvalue const &x2);
|
|
|
|
// Cast to scalar
|
|
inline operator cvm::real() const
|
|
{
|
|
if (value_type != type_scalar) {
|
|
cvm::error("Error: trying to use a variable of type \""+
|
|
type_desc(value_type)+"\" as one of type \""+
|
|
type_desc(type_scalar)+"\".\n");
|
|
}
|
|
return real_value;
|
|
}
|
|
|
|
// Cast to 3-vector
|
|
inline operator cvm::rvector() const
|
|
{
|
|
if ((value_type != type_3vector) &&
|
|
(value_type != type_unit3vector) &&
|
|
(value_type != type_unit3vectorderiv)) {
|
|
cvm::error("Error: trying to use a variable of type \""+
|
|
type_desc(value_type)+"\" as one of type \""+
|
|
type_desc(type_3vector)+"\".\n");
|
|
}
|
|
return rvector_value;
|
|
}
|
|
|
|
// Cast to quaternion
|
|
inline operator cvm::quaternion() const
|
|
{
|
|
if ((value_type != type_quaternion) &&
|
|
(value_type != type_quaternionderiv)) {
|
|
cvm::error("Error: trying to use a variable of type \""+
|
|
type_desc(value_type)+"\" as one of type \""+
|
|
type_desc(type_quaternion)+"\".\n");
|
|
}
|
|
return quaternion_value;
|
|
}
|
|
|
|
// Create a n-dimensional vector from one of the basic types, or return the existing vector
|
|
cvm::vector1d<cvm::real> const as_vector() const;
|
|
|
|
|
|
/// Whether this variable is a real number
|
|
inline bool is_scalar() const
|
|
{
|
|
return (value_type == type_scalar);
|
|
}
|
|
|
|
|
|
/// Add an element to the vector (requires that type_vector is already set).
|
|
/// This is only needed to use this object as a vector of "complex" colvar values.
|
|
/// To use it instead as a plain n-dimensional vector, access vector1d_value directly.
|
|
void add_elem(colvarvalue const &x);
|
|
|
|
/// Get a single colvarvalue out of elements of the vector
|
|
colvarvalue const get_elem(int const i_begin, int const i_end, Type const vt) const;
|
|
|
|
/// Set elements of the vector from a single colvarvalue
|
|
void set_elem(int const i_begin, int const i_end, colvarvalue const &x);
|
|
|
|
/// Make each element a random number in N(0,1)
|
|
void set_random();
|
|
|
|
/// Get a single colvarvalue out of elements of the vector
|
|
colvarvalue const get_elem(int const icv) const;
|
|
|
|
/// Set elements of the vector from a single colvarvalue
|
|
void set_elem(int const icv, colvarvalue const &x);
|
|
|
|
/// Get a scalar number out of an element of the vector
|
|
cvm::real operator [] (int const i) const;
|
|
|
|
/// Use an element of the vector as a scalar number
|
|
cvm::real & operator [] (int const i);
|
|
|
|
/// Ensure that the two types are the same within a binary operator
|
|
static int check_types(colvarvalue const &x1, colvarvalue const &x2);
|
|
|
|
/// Ensure that the two types are the same within an assignment, or that the left side is type_notset
|
|
static int check_types_assign(Type const &vt1, Type const &vt2);
|
|
|
|
/// Undefined operation
|
|
void undef_op() const;
|
|
|
|
|
|
/// \brief Formatted output operator
|
|
friend std::ostream & operator << (std::ostream &os, colvarvalue const &q);
|
|
|
|
/// \brief Formatted input operator
|
|
friend std::istream & operator >> (std::istream &is, colvarvalue &q);
|
|
|
|
/// Give the number of characters required to output this
|
|
/// colvarvalue, given the current type assigned and the number of
|
|
/// characters for a real number
|
|
size_t output_width(size_t const &real_width) const;
|
|
|
|
/// Formats value as a script-friendly string (space separated list)
|
|
std::string to_simple_string() const;
|
|
|
|
/// Parses value from a script-friendly string (space separated list)
|
|
int from_simple_string(std::string const &s);
|
|
|
|
|
|
// optimized routines for operations on arrays of colvar values;
|
|
// xv and result are assumed to have the same number of elements
|
|
|
|
/// \brief Optimized routine for the inner product of one collective
|
|
/// variable with an array
|
|
static void inner_opt(colvarvalue const &x,
|
|
std::vector<colvarvalue>::iterator &xv,
|
|
std::vector<colvarvalue>::iterator const &xv_end,
|
|
std::vector<cvm::real>::iterator &result);
|
|
|
|
/// \brief Optimized routine for the inner product of one collective
|
|
/// variable with an array
|
|
static void inner_opt(colvarvalue const &x,
|
|
std::list<colvarvalue>::iterator &xv,
|
|
std::list<colvarvalue>::iterator const &xv_end,
|
|
std::vector<cvm::real>::iterator &result);
|
|
|
|
/// \brief Optimized routine for the second order Legendre
|
|
/// polynomial, (3cos^2(w)-1)/2, of one collective variable with an
|
|
/// array
|
|
static void p2leg_opt(colvarvalue const &x,
|
|
std::vector<colvarvalue>::iterator &xv,
|
|
std::vector<colvarvalue>::iterator const &xv_end,
|
|
std::vector<cvm::real>::iterator &result);
|
|
|
|
/// \brief Optimized routine for the second order Legendre
|
|
/// polynomial of one collective variable with an array
|
|
static void p2leg_opt(colvarvalue const &x,
|
|
std::list<colvarvalue>::iterator &xv,
|
|
std::list<colvarvalue>::iterator const &xv_end,
|
|
std::vector<cvm::real>::iterator &result);
|
|
|
|
};
|
|
|
|
|
|
inline size_t colvarvalue::size() const
|
|
{
|
|
switch (value_type) {
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
return 0; break;
|
|
case colvarvalue::type_scalar:
|
|
return 1; break;
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
return 3; break;
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
return 4; break;
|
|
case colvarvalue::type_vector:
|
|
return vector1d_value.size(); break;
|
|
}
|
|
}
|
|
|
|
|
|
inline cvm::real colvarvalue::operator [] (int const i) const
|
|
{
|
|
switch (value_type) {
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
cvm::error("Error: trying to access a colvar value "
|
|
"that is not initialized.\n", BUG_ERROR);
|
|
return 0.0; break;
|
|
case colvarvalue::type_scalar:
|
|
return real_value; break;
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
return rvector_value[i]; break;
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
return quaternion_value[i]; break;
|
|
case colvarvalue::type_vector:
|
|
return vector1d_value[i]; break;
|
|
}
|
|
}
|
|
|
|
|
|
inline cvm::real & colvarvalue::operator [] (int const i)
|
|
{
|
|
switch (value_type) {
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
cvm::error("Error: trying to access a colvar value "
|
|
"that is not initialized.\n", BUG_ERROR);
|
|
return real_value; break;
|
|
case colvarvalue::type_scalar:
|
|
return real_value; break;
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
return rvector_value[i]; break;
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
return quaternion_value[i]; break;
|
|
case colvarvalue::type_vector:
|
|
return vector1d_value[i]; break;
|
|
}
|
|
}
|
|
|
|
|
|
inline int colvarvalue::check_types(colvarvalue const &x1,
|
|
colvarvalue const &x2)
|
|
{
|
|
if (!colvarvalue::type_checking()) {
|
|
return COLVARS_OK;
|
|
}
|
|
|
|
if (x1.type() != x2.type()) {
|
|
if (((x1.type() == type_unit3vector) &&
|
|
(x2.type() == type_unit3vectorderiv)) ||
|
|
((x2.type() == type_unit3vector) &&
|
|
(x1.type() == type_unit3vectorderiv)) ||
|
|
((x1.type() == type_quaternion) &&
|
|
(x2.type() == type_quaternionderiv)) ||
|
|
((x2.type() == type_quaternion) &&
|
|
(x1.type() == type_quaternionderiv))) {
|
|
return COLVARS_OK;
|
|
} else {
|
|
cvm::error("Trying to perform an operation between two colvar "
|
|
"values with different types, \""+
|
|
colvarvalue::type_desc(x1.type())+
|
|
"\" and \""+
|
|
colvarvalue::type_desc(x2.type())+
|
|
"\".\n");
|
|
return COLVARS_ERROR;
|
|
}
|
|
}
|
|
|
|
if (x1.type() == type_vector) {
|
|
if (x1.vector1d_value.size() != x2.vector1d_value.size()) {
|
|
cvm::error("Trying to perform an operation between two vector colvar "
|
|
"values with different sizes, "+
|
|
cvm::to_str(x1.vector1d_value.size())+
|
|
" and "+
|
|
cvm::to_str(x2.vector1d_value.size())+
|
|
".\n");
|
|
return COLVARS_ERROR;
|
|
}
|
|
}
|
|
return COLVARS_OK;
|
|
}
|
|
|
|
|
|
inline int colvarvalue::check_types_assign(colvarvalue::Type const &vt1,
|
|
colvarvalue::Type const &vt2)
|
|
{
|
|
if (!colvarvalue::type_checking()) {
|
|
return COLVARS_OK;
|
|
}
|
|
|
|
if (vt1 != type_notset) {
|
|
if (((vt1 == type_unit3vector) &&
|
|
(vt2 == type_unit3vectorderiv)) ||
|
|
((vt2 == type_unit3vector) &&
|
|
(vt1 == type_unit3vectorderiv)) ||
|
|
((vt1 == type_quaternion) &&
|
|
(vt2 == type_quaternionderiv)) ||
|
|
((vt2 == type_quaternion) &&
|
|
(vt1 == type_quaternionderiv))) {
|
|
return COLVARS_OK;
|
|
} else {
|
|
if (vt1 != vt2) {
|
|
cvm::error("Trying to assign a colvar value with type \""+
|
|
type_desc(vt2)+"\" to one with type \""+
|
|
type_desc(vt1)+"\".\n");
|
|
return COLVARS_ERROR;
|
|
}
|
|
}
|
|
}
|
|
return COLVARS_OK;
|
|
}
|
|
|
|
|
|
inline colvarvalue & colvarvalue::operator = (colvarvalue const &x)
|
|
{
|
|
check_types_assign(this->type(), x.type());
|
|
value_type = x.type();
|
|
|
|
switch (this->type()) {
|
|
case colvarvalue::type_scalar:
|
|
this->real_value = x.real_value;
|
|
break;
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
this->rvector_value = x.rvector_value;
|
|
break;
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
this->quaternion_value = x.quaternion_value;
|
|
break;
|
|
case colvarvalue::type_vector:
|
|
vector1d_value = x.vector1d_value;
|
|
elem_types = x.elem_types;
|
|
elem_indices = x.elem_indices;
|
|
elem_sizes = x.elem_sizes;
|
|
break;
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
undef_op();
|
|
break;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
inline void colvarvalue::operator += (colvarvalue const &x)
|
|
{
|
|
colvarvalue::check_types(*this, x);
|
|
|
|
switch (this->type()) {
|
|
case colvarvalue::type_scalar:
|
|
this->real_value += x.real_value;
|
|
break;
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
this->rvector_value += x.rvector_value;
|
|
break;
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
this->quaternion_value += x.quaternion_value;
|
|
break;
|
|
case colvarvalue::type_vector:
|
|
this->vector1d_value += x.vector1d_value;
|
|
break;
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
undef_op();
|
|
}
|
|
}
|
|
|
|
|
|
inline void colvarvalue::operator -= (colvarvalue const &x)
|
|
{
|
|
colvarvalue::check_types(*this, x);
|
|
|
|
switch (value_type) {
|
|
case colvarvalue::type_scalar:
|
|
real_value -= x.real_value;
|
|
break;
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
rvector_value -= x.rvector_value;
|
|
break;
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
quaternion_value -= x.quaternion_value;
|
|
break;
|
|
case colvarvalue::type_vector:
|
|
this->vector1d_value -= x.vector1d_value;
|
|
break;
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
undef_op();
|
|
}
|
|
}
|
|
|
|
|
|
inline void colvarvalue::operator *= (cvm::real const &a)
|
|
{
|
|
switch (value_type) {
|
|
case colvarvalue::type_scalar:
|
|
real_value *= a;
|
|
break;
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
rvector_value *= a;
|
|
break;
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
quaternion_value *= a;
|
|
break;
|
|
case colvarvalue::type_vector:
|
|
this->vector1d_value *= a;
|
|
break;
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
undef_op();
|
|
}
|
|
}
|
|
|
|
|
|
inline void colvarvalue::operator /= (cvm::real const &a)
|
|
{
|
|
switch (value_type) {
|
|
case colvarvalue::type_scalar:
|
|
real_value /= a; break;
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
rvector_value /= a; break;
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
quaternion_value /= a; break;
|
|
case colvarvalue::type_vector:
|
|
this->vector1d_value /= a;
|
|
break;
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
undef_op();
|
|
}
|
|
}
|
|
|
|
|
|
inline cvm::vector1d<cvm::real> const colvarvalue::as_vector() const
|
|
{
|
|
switch (value_type) {
|
|
case colvarvalue::type_scalar:
|
|
{
|
|
cvm::vector1d<cvm::real> v(1);
|
|
v[0] = real_value;
|
|
return v;
|
|
}
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
return rvector_value.as_vector();
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
return quaternion_value.as_vector();
|
|
case colvarvalue::type_vector:
|
|
return vector1d_value;
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
return cvm::vector1d<cvm::real>(0);
|
|
}
|
|
}
|
|
|
|
|
|
inline cvm::real colvarvalue::norm2() const
|
|
{
|
|
switch (value_type) {
|
|
case colvarvalue::type_scalar:
|
|
return (this->real_value)*(this->real_value);
|
|
case colvarvalue::type_3vector:
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
return (this->rvector_value).norm2();
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
return (this->quaternion_value).norm2();
|
|
case colvarvalue::type_vector:
|
|
if (elem_types.size() > 0) {
|
|
// if we have information about non-scalar types, use it
|
|
cvm::real result = 0.0;
|
|
size_t i;
|
|
for (i = 0; i < elem_types.size(); i++) {
|
|
result += (this->get_elem(i)).norm2();
|
|
}
|
|
return result;
|
|
} else {
|
|
return vector1d_value.norm2();
|
|
}
|
|
break;
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
|
|
inline cvm::real colvarvalue::dist2(colvarvalue const &x2) const
|
|
{
|
|
colvarvalue::check_types(*this, x2);
|
|
|
|
switch (this->type()) {
|
|
case colvarvalue::type_scalar:
|
|
return (this->real_value - x2.real_value)*(this->real_value - x2.real_value);
|
|
case colvarvalue::type_3vector:
|
|
return (this->rvector_value - x2.rvector_value).norm2();
|
|
case colvarvalue::type_unit3vector:
|
|
case colvarvalue::type_unit3vectorderiv:
|
|
// angle between (*this) and x2 is the distance
|
|
return std::acos(this->rvector_value * x2.rvector_value) * std::acos(this->rvector_value * x2.rvector_value);
|
|
case colvarvalue::type_quaternion:
|
|
case colvarvalue::type_quaternionderiv:
|
|
// angle between (*this) and x2 is the distance, the quaternion
|
|
// object has it implemented internally
|
|
return this->quaternion_value.dist2(x2.quaternion_value);
|
|
case colvarvalue::type_vector:
|
|
return (this->vector1d_value - x2.vector1d_value).norm2();
|
|
case colvarvalue::type_notset:
|
|
default:
|
|
this->undef_op();
|
|
return 0.0;
|
|
};
|
|
}
|
|
|
|
|
|
#endif
|