git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@10118 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp 2013-06-27 22:48:27 +00:00
parent 38112d0063
commit 4da20dce99
30 changed files with 883 additions and 571 deletions

View File

@ -1,4 +1,4 @@
# library build makefile for colvars module
# library build -*- makefile -*- for colvars module
# which file will be copied to Makefile.lammps
@ -25,11 +25,13 @@ EXE = #colvars_standalone
# ------ MAKE PROCEDURE ------
default: $(LIB) $(EXE)
default: $(LIB) $(EXE) Makefile.lammps
Makefile.lammps:
@cp $(EXTRAMAKE) Makefile.lammps
$(LIB): $(OBJ)
$(ARCHIVE) $(ARFLAGS) $(LIB) $(OBJ)
@cp $(EXTRAMAKE) Makefile.lammps
colvars_standalone: colvars_main.o colvarproxy_standalone.o $(LIB)
$(CXX) -o $@ $(CXXFLAGS) $^

View File

@ -1,4 +1,4 @@
# library build makefile for colvars module
# library build -*- makefile -*- for colvars module
# which file will be copied to Makefile.lammps
@ -6,12 +6,12 @@ EXTRAMAKE = Makefile.lammps.empty
# ------ SETTINGS ------
CXX = i686-pc-mingw32-g++
CXX = i686-w64-mingw32-g++
CXXFLAGS = -O2 -march=i686 -mtune=generic -mfpmath=387 -mpc64 \
-fno-rtti -fno-exceptions -finline-functions \
-ffast-math -funroll-loops -fstrict-aliasing \
-Wall -W -Wno-uninitialized
ARCHIVE = i686-pc-mingw32-ar
ARCHIVE = i686-w64-mingw32-ar
ARCHFLAG = -rscv
SHELL = /bin/sh
@ -22,19 +22,26 @@ SRC = colvaratoms.cpp colvarbias_abf.cpp colvarbias.cpp colvarbias_meta.cpp \
colvarcomp_distances.cpp colvarcomp_protein.cpp colvarcomp_rotations.cpp \
colvargrid.cpp colvarmodule.cpp colvarparse.cpp colvarvalue.cpp
LIB = libcolvars.a
OBJ = $(SRC:.cpp=.o)
DIR = Obj_mingw32/
LIB = $(DIR)libcolvars.a
OBJ = $(SRC:%.cpp=$(DIR)%.o)
EXE = #colvars_standalone
# ------ MAKE PROCEDURE ------
default: $(LIB) $(EXE)
default: $(DIR) $(LIB) $(EXE) Makefile.lammps
$(LIB): $(OBJ)
$(DIR):
mkdir $(DIR)
Makefile.lammps:
@cp $(EXTRAMAKE) Makefile.lammps
$(LIB): $(DIR) $(OBJ)
$(ARCHIVE) $(ARFLAGS) $(LIB) $(OBJ)
@cp $(EXTRAMAKE) Makefile.lammps
colvars_standalone: colvars_main.o colvarproxy_standalone.o $(LIB)
$(DIR)colvars_standalone: colvars_main.o colvarproxy_standalone.o $(LIB)
$(CXX) -o $@ $(CXXFLAGS) $^
# ------ MAKE FLAGS ------
@ -46,58 +53,59 @@ colvars_standalone: colvars_main.o colvarproxy_standalone.o $(LIB)
# ------ COMPILE RULES ------
.cpp.o:
$(CXX) $(CXXFLAGS) -c $<
$(DIR)%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
# ------ DEPENDENCIES ------
#
colvars_main.o: colvars_main.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvars_main.o: colvars_main.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarproxy_standalone.h colvaratoms.h colvarparse.h colvarvalue.h
colvarproxy_standalone.o: colvarproxy_standalone.cpp colvarmodule.h \
$(DIR)colvarproxy_standalone.o: colvarproxy_standalone.cpp colvarmodule.h \
colvartypes.h colvarproxy.h colvaratoms.h colvarparse.h colvarvalue.h \
colvarproxy_standalone.h
colvaratoms.o: colvaratoms.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvaratoms.o: colvaratoms.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarparse.h colvarvalue.h colvaratoms.h
colvarbias_abf.o: colvarbias_abf.cpp colvarmodule.h colvartypes.h \
$(DIR)colvarbias_abf.o: colvarbias_abf.cpp colvarmodule.h colvartypes.h \
colvarproxy.h colvar.h colvarvalue.h colvarparse.h colvarbias_abf.h \
colvarbias.h colvargrid.h
colvarbias.o: colvarbias.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvarbias.o: colvarbias.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarvalue.h colvarbias.h colvar.h colvarparse.h
colvarbias_meta.o: colvarbias_meta.cpp colvar.h colvarmodule.h \
$(DIR)colvarbias_meta.o: colvarbias_meta.cpp colvar.h colvarmodule.h \
colvartypes.h colvarproxy.h colvarvalue.h colvarparse.h \
colvarbias_meta.h colvarbias.h colvargrid.h
colvar.o: colvar.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvar.o: colvar.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarvalue.h colvarparse.h colvar.h colvarcomp.h colvaratoms.h
colvarcomp_angles.o: colvarcomp_angles.cpp colvarmodule.h colvartypes.h \
$(DIR)colvarcomp_angles.o: colvarcomp_angles.cpp colvarmodule.h colvartypes.h \
colvarproxy.h colvar.h colvarvalue.h colvarparse.h colvarcomp.h \
colvaratoms.h
colvarcomp.o: colvarcomp.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvarcomp.o: colvarcomp.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarvalue.h colvar.h colvarparse.h colvarcomp.h colvaratoms.h
colvarcomp_coordnums.o: colvarcomp_coordnums.cpp colvarmodule.h \
$(DIR)colvarcomp_coordnums.o: colvarcomp_coordnums.cpp colvarmodule.h \
colvartypes.h colvarproxy.h colvarparse.h colvarvalue.h colvaratoms.h \
colvar.h colvarcomp.h
colvarcomp_distances.o: colvarcomp_distances.cpp colvarmodule.h \
$(DIR)colvarcomp_distances.o: colvarcomp_distances.cpp colvarmodule.h \
colvartypes.h colvarproxy.h colvarvalue.h colvarparse.h colvar.h \
colvarcomp.h colvaratoms.h
colvarcomp_protein.o: colvarcomp_protein.cpp colvarmodule.h colvartypes.h \
$(DIR)colvarcomp_protein.o: colvarcomp_protein.cpp colvarmodule.h colvartypes.h \
colvarproxy.h colvarvalue.h colvarparse.h colvar.h colvarcomp.h \
colvaratoms.h
colvarcomp_rotations.o: colvarcomp_rotations.cpp colvarmodule.h \
$(DIR)colvarcomp_rotations.o: colvarcomp_rotations.cpp colvarmodule.h \
colvartypes.h colvarproxy.h colvarvalue.h colvarparse.h colvar.h \
colvarcomp.h colvaratoms.h
colvargrid.o: colvargrid.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvargrid.o: colvargrid.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarvalue.h colvarparse.h colvar.h colvarcomp.h colvaratoms.h \
colvargrid.h
colvarmodule.o: colvarmodule.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvarmodule.o: colvarmodule.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarparse.h colvarvalue.h colvar.h colvarbias.h colvarbias_meta.h \
colvargrid.h colvarbias_abf.h
colvarparse.o: colvarparse.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvarparse.o: colvarparse.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarvalue.h colvarparse.h
colvarvalue.o: colvarvalue.cpp colvarmodule.h colvartypes.h colvarproxy.h \
$(DIR)colvarvalue.o: colvarvalue.cpp colvarmodule.h colvartypes.h colvarproxy.h \
colvarvalue.h
# ------ CLEAN ------
clean:
-rm *.o *~ $(LIB)
-rm $(DIR)*.o *~ $(LIB)
-rmdir $(DIR)

View File

@ -4,9 +4,24 @@ that allows enhanced sampling in molecular dynamics simulations.
The module is written to maximize performance, portability,
flexibility of usage for the user, and extensibility for the developer.
The following publication describes the principles of
The development of the colvars library is now hosted on github at:
http://colvars.github.io/
You can use this site to get access to the latest development sources
and the up-to-date documentation.
Copy of the specific documentation is also in
doc/PDF/colvars-refman-lammps.pdf
Please report bugs and request new features at:
https://github.com/colvars/colvars/issues
The following publications describe the principles of
the implementation of this library:
Using collective variables to drive molecular dynamics simulations,
Giacomo Fiorin , Michael L. Klein & Jérôme Hénin (2013):
Molecular Physics DOI:10.1080/00268976.2013.813594
Exploring Multidimensional Free Energy Landscapes Using
Time-Dependent Biases on Collective Variables,
J. Hénin, G. Fiorin, C. Chipot, and M. L. Klein,

View File

@ -167,6 +167,9 @@ colvar::colvar (std::string const &conf)
// check the available features of each cvc
for (size_t i = 0; i < cvcs.size(); i++) {
if ((cvcs[i])->b_debug_gradients)
enable (task_gradients);
if ((cvcs[i])->sup_np != 1) {
if (cvm::debug() && b_linear)
cvm::log ("Warning: You are using a non-linear polynomial "
@ -664,6 +667,18 @@ void colvar::disable (colvar::task const &t)
}
void colvar::setup() {
// loop over all components to reset masses of all groups
for (size_t i = 0; i < cvcs.size(); i++) {
for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
cvm::atom_group &atoms = *(cvcs[i]->atom_groups[ig]);
atoms.read_positions();
atoms.reset_mass(name,i,ig);
}
}
}
colvar::~colvar()
{
for (size_t i = 0; i < cvcs.size(); i++) {
@ -682,6 +697,8 @@ void colvar::calc()
cvm::log ("Calculating colvar \""+this->name+"\".\n");
// prepare atom groups for calculation
if (cvm::debug())
cvm::log ("Collecting data from atom groups.\n");
for (size_t i = 0; i < cvcs.size(); i++) {
for (size_t ig = 0; ig < cvcs[i]->atom_groups.size(); ig++) {
cvm::atom_group &atoms = *(cvcs[i]->atom_groups[ig]);
@ -710,6 +727,8 @@ void colvar::calc()
// calculate the value of the colvar
if (cvm::debug())
cvm::log ("Calculating colvar components.\n");
x.reset();
if (x.type() == colvarvalue::type_scalar) {
// polynomial combination allowed

View File

@ -288,6 +288,9 @@ public:
/// Disable the specified task
void disable (colvar::task const &t);
/// Get ready for a run and possibly re-initialize internal data
void setup();
/// Destructor
~colvar();

View File

@ -71,6 +71,18 @@ void cvm::atom_group::add_atom (cvm::atom const &a)
}
void cvm::atom_group::reset_mass(std::string &name, int i, int j)
{
total_mass = 0.0;
for (cvm::atom_iter ai = this->begin();
ai != this->end(); ai++) {
total_mass += ai->mass;
}
cvm::log ("Re-initialized atom group "+name+":"+cvm::to_str (i)+"/"+
cvm::to_str (j)+". "+ cvm::to_str (this->size())+
" atoms: total mass = "+cvm::to_str (this->total_mass)+".\n");
}
void cvm::atom_group::parse (std::string const &conf,
char const *key)
{
@ -129,6 +141,25 @@ void cvm::atom_group::parse (std::string const &conf,
atom_indexes.clear();
}
std::string index_group_name;
if (get_keyval (group_conf, "indexGroup", index_group_name)) {
// use an index group from the index file read globally
std::list<std::string>::iterator names_i = cvm::index_group_names.begin();
std::list<std::vector<int> >::iterator index_groups_i = cvm::index_groups.begin();
for ( ; names_i != cvm::index_group_names.end() ; names_i++, index_groups_i++) {
if (*names_i == index_group_name)
break;
}
if (names_i == cvm::index_group_names.end()) {
cvm::fatal_error ("Error: could not find index group "+
index_group_name+" among those provided by the index file.\n");
}
this->reserve (index_groups_i->size());
for (size_t i = 0; i < index_groups_i->size(); i++) {
this->push_back (cvm::atom ((*index_groups_i)[i]));
}
}
}
{

View File

@ -23,7 +23,7 @@ protected:
/// \brief Index in the list of atoms involved by the colvars (\b
/// NOT in the global topology!)
size_t index;
int index;
public:
@ -57,8 +57,8 @@ public:
/// implementation
cvm::rvector grad;
/// \brief Default constructor, setting id to a non-valid value
inline atom() {}
/// \brief Default constructor, setting id and index to invalid numbers
atom() : id (-1), index (-1) { reset_data(); }
/// \brief Initialize an atom for collective variable calculation
/// and get its internal identifier \param atom_number Atom index in
@ -121,7 +121,7 @@ class colvarmodule::atom_group
public colvarparse
{
public:
// Note: all members here are kept public, to make possible to any
// Note: all members here are kept public, to allow any
// object accessing and manipulating them
@ -202,6 +202,11 @@ public:
/// \brief Add an atom to this group
void add_atom (cvm::atom const &a);
/// \brief Re-initialize the total mass of a group.
/// This is needed in case the hosting MD code has an option to
/// change atom masses after their initialization.
void reset_mass (std::string &name, int i, int j);
/// \brief Default constructor
atom_group();

View File

@ -41,10 +41,11 @@ colvarbias::colvarbias (std::string const &conf, char const *key)
add_colvar (colvars_str[i]);
}
}
if (!colvars.size()) {
cvm::fatal_error ("Error: no collective variables specified.\n");
}
get_keyval (conf, "outputEnergy", b_output_energy, false);
}
@ -82,6 +83,40 @@ void colvarbias::communicate_forces()
}
void colvarbias::change_configuration(std::string const &conf)
{
cvm::fatal_error ("Error: change_configuration() not implemented.\n");
}
cvm::real colvarbias::energy_difference(std::string const &conf)
{
cvm::fatal_error ("Error: energy_difference() not implemented.\n");
return 0.;
}
std::ostream & colvarbias::write_traj_label (std::ostream &os)
{
os << " ";
if (b_output_energy)
os << " E_"
<< cvm::wrap_string (this->name, cvm::en_width-2);
return os;
}
std::ostream & colvarbias::write_traj (std::ostream &os)
{
os << " ";
if (b_output_energy)
os << " "
<< bias_energy;
return os;
}
colvarbias_harmonic::colvarbias_harmonic (std::string const &conf,
char const *key)
@ -171,21 +206,18 @@ colvarbias_harmonic::colvarbias_harmonic (std::string const &conf,
}
}
get_keyval (conf, "outputCenters", b_output_centers, false);
get_keyval (conf, "outputAccumulatedWork", b_output_acc_work, false);
acc_work = 0.0;
if (cvm::debug())
cvm::log ("Done initializing a new harmonic restraint bias.\n");
}
void colvarbias::change_configuration(std::string const &conf)
colvarbias_harmonic::~colvarbias_harmonic ()
{
cvm::fatal_error ("Error: change_configuration() not implemented.\n");
}
cvm::real colvarbias::energy_difference(std::string const &conf)
{
cvm::fatal_error ("Error: energy_difference() not implemented.\n");
return 0.;
if (cvm::n_harm_biases > 0)
cvm::n_harm_biases -= 1;
}
@ -379,6 +411,15 @@ cvm::real colvarbias_harmonic::update()
colvar_centers[i]))+"\n");
}
if (b_output_acc_work) {
if ((cvm::step_relative() > 0) || (cvm::step_absolute() == 0)) {
for (size_t i = 0; i < colvars.size(); i++) {
// project forces on the calculated increments at this step
acc_work += colvar_forces[i] * centers_incr[i];
}
}
}
if (cvm::debug())
cvm::log ("Current forces for the harmonic bias \""+
this->name+"\": "+cvm::to_str (colvar_forces)+".\n");
@ -442,6 +483,11 @@ std::istream & colvarbias_harmonic::read_restart (std::istream &is)
cvm::fatal_error ("Error: current stage is missing from the restart.\n");
}
if (b_output_acc_work) {
if (!get_keyval (conf, "accumulatedWork", acc_work))
cvm::fatal_error ("Error: accumulatedWork is missing from the restart.\n");
}
is >> brace;
if (brace != "}") {
cvm::fatal_error ("Error: corrupt restart information for harmonic bias \""+
@ -484,9 +530,61 @@ std::ostream & colvarbias_harmonic::write_restart (std::ostream &os)
<< stage << "\n";
}
if (b_output_acc_work) {
os << " accumulatedWork " << acc_work << "\n";
}
os << " }\n"
<< "}\n\n";
return os;
}
std::ostream & colvarbias_harmonic::write_traj_label (std::ostream &os)
{
os << " ";
if (b_output_energy)
os << " E_"
<< cvm::wrap_string (this->name, cvm::en_width-2);
if (b_output_centers)
for (size_t i = 0; i < colvars.size(); i++) {
size_t const this_cv_width = (colvars[i]->value()).output_width (cvm::cv_width);
os << " x0_"
<< cvm::wrap_string (colvars[i]->name, this_cv_width-3);
}
if (b_output_acc_work)
os << " W_"
<< cvm::wrap_string (this->name, cvm::en_width-2);
return os;
}
std::ostream & colvarbias_harmonic::write_traj (std::ostream &os)
{
os << " ";
if (b_output_energy)
os << " "
<< std::setprecision (cvm::en_prec) << std::setw (cvm::en_width)
<< bias_energy;
if (b_output_centers)
for (size_t i = 0; i < colvars.size(); i++) {
os << " "
<< std::setprecision (cvm::cv_prec) << std::setw (cvm::cv_width)
<< colvar_centers[i];
}
if (b_output_acc_work)
os << " "
<< std::setprecision (cvm::en_prec) << std::setw (cvm::en_width)
<< acc_work;
return os;
}

View File

@ -52,6 +52,13 @@ public:
/// Write the bias configuration to a restart file
virtual std::ostream & write_restart (std::ostream &os) = 0;
/// Write a label to the trajectory file (comment line)
virtual std::ostream & write_traj_label (std::ostream &os);
/// Output quantities such as the bias energy to the trajectory file
virtual std::ostream & write_traj (std::ostream &os);
protected:
/// \brief Pointers to collective variables to which the bias is
@ -62,10 +69,12 @@ protected:
/// \brief Current forces from this bias to the colvars
std::vector<colvarvalue> colvar_forces;
/// \brief Current energy of this bias (colvar_forces should be
/// obtained by deriving this)
/// \brief Current energy of this bias (colvar_forces should be obtained by deriving this)
cvm::real bias_energy;
/// Whether to write the current bias energy from this bias to the trajectory file
bool b_output_energy;
/// \brief Whether this bias has already accumulated information
/// (when relevant)
bool has_data;
@ -94,11 +103,17 @@ public:
/// Write the bias configuration to a restart file
virtual std::ostream & write_restart (std::ostream &os);
/// Write a label to the trajectory file (comment line)
virtual std::ostream & write_traj_label (std::ostream &os);
/// Output quantities such as the bias energy to the trajectory file
virtual std::ostream & write_traj (std::ostream &os);
/// \brief Constructor
colvarbias_harmonic (std::string const &conf, char const *key);
/// Destructor
virtual inline ~colvarbias_harmonic() {}
virtual ~colvarbias_harmonic();
protected:
@ -109,27 +124,9 @@ protected:
/// \brief Restraint centers without wrapping or constraints applied
std::vector<colvarvalue> colvar_centers_raw;
/// \brief Restraint force constant
cvm::real force_k;
/// \brief Moving target?
bool b_chg_centers;
/// \brief Changing force constant?
bool b_chg_force_k;
/// \brief Restraint force constant (target value)
cvm::real target_force_k;
/// \brief Equilibration steps for restraint FE calculation through TI
cvm::real target_equil_steps;
/// \brief Restraint force constant (starting value)
cvm::real starting_force_k;
/// \brief Lambda-schedule for custom varying force constant
std::vector<cvm::real> lambda_schedule;
/// \brief New restraint centers
std::vector<colvarvalue> target_centers;
@ -137,12 +134,41 @@ protected:
/// (or stage) towards the new values (calculated from target_nsteps)
std::vector<colvarvalue> centers_incr;
/// Whether to write the current restraint centers to the trajectory file
bool b_output_centers;
/// Whether to write the current accumulated work to the trajectory file
bool b_output_acc_work;
/// \brief Accumulated work
cvm::real acc_work;
/// \brief Restraint force constant
cvm::real force_k;
/// \brief Changing force constant?
bool b_chg_force_k;
/// \brief Restraint force constant (target value)
cvm::real target_force_k;
/// \brief Restraint force constant (starting value)
cvm::real starting_force_k;
/// \brief Lambda-schedule for custom varying force constant
std::vector<cvm::real> lambda_schedule;
/// \brief Exponent for varying the force constant
cvm::real force_k_exp;
/// \brief Number of steps required to reach the target force constant
/// or restraint centers
size_t target_nsteps;
/// \brief Intermediate quantity to compute the restraint free energy
/// (in TI, would be the accumulating FE derivative)
cvm::real restraint_FE;
/// \brief Equilibration steps for restraint FE calculation through TI
cvm::real target_equil_steps;
/// \brief Number of stages over which to perform the change
/// If zero, perform a continuous change
@ -151,9 +177,9 @@ protected:
/// \brief Number of current stage of the perturbation
int stage;
/// \brief Intermediate quantity to compute the restraint free energy
/// (in TI, would be the accumulating FE derivative)
cvm::real restraint_FE;
/// \brief Number of steps required to reach the target force constant
/// or restraint centers
size_t target_nsteps;
};

View File

@ -82,6 +82,20 @@ colvarbias_abf::colvarbias_abf (std::string const &conf, char const *key)
// and make it just a warning if some parameter is set?
}
if (get_keyval (conf, "maxForce", max_force)) {
if (max_force.size() != colvars.size()) {
cvm::fatal_error ("Error: Number of parameters to maxForce does not match number of colvars.");
}
for (size_t i=0; i<colvars.size(); i++) {
if (max_force[i] < 0.0) {
cvm::fatal_error ("Error: maxForce should be non-negative.");
}
}
cap_force = true;
} else {
cap_force = false;
}
bin.assign (colvars.size(), 0);
force_bin.assign (colvars.size(), 0);
force = new cvm::real [colvars.size()];
@ -114,6 +128,9 @@ colvarbias_abf::~colvarbias_abf()
}
delete [] force;
if (cvm::n_abf_biases > 0)
cvm::n_abf_biases -= 1;
}
@ -180,15 +197,21 @@ cvm::real colvarbias_abf::update()
const cvm::real * grad = &(gradients->value (bin));
if ( fact != 0.0 ) {
if ( (colvars.size() == 1) && colvars[0]->periodic_boundaries() ) {
// Enforce a zero-mean bias on periodic, 1D coordinates
colvar_forces[0].real_value += fact * (grad[0] / cvm::real (count) - gradients->average ());
// in other words: boundary condition is that the biasing potential is periodic
colvar_forces[0].real_value = fact * (grad[0] / cvm::real (count) - gradients->average ());
} else {
for (size_t i=0; i<colvars.size(); i++) {
// subtracting the mean force (opposite of the FE gradient) means adding the gradient
colvar_forces[i].real_value += fact * grad[i] / cvm::real (count);
// without .real_value, the above would do (cheap) runtime type checking
colvar_forces[i].real_value = fact * grad[i] / cvm::real (count);
}
}
if (cap_force) {
for (size_t i=0; i<colvars.size(); i++) {
if ( colvar_forces[i].real_value * colvar_forces[i].real_value > max_force[i] * max_force[i] ) {
colvar_forces[i].real_value = (colvar_forces[i].real_value > 0 ? max_force[i] : -1.0 * max_force[i]);
}
}
}
}
@ -203,7 +226,7 @@ cvm::real colvarbias_abf::update()
// otherwise, backup and replace
write_gradients_samples (output_prefix + ".hist", (cvm::step_absolute() > 0));
}
return 0.0; // TODO compute bias energy whenever possible (i.e. 1D with updateBias off)
return 0.0;
}
@ -395,6 +418,9 @@ colvarbias_histogram::~colvarbias_histogram()
delete grid;
grid = NULL;
}
if (cvm::n_histo_biases > 0)
cvm::n_histo_biases -= 1;
}
/// Update the grid

View File

@ -46,6 +46,10 @@ private:
bool b_history_files;
size_t history_freq;
/// Cap applied biasing force?
bool cap_force;
std::vector<cvm::real> max_force;
// Internal data and methods
std::vector<int> bin, force_bin;

View File

@ -76,7 +76,8 @@ colvarbias_meta::colvarbias_meta (std::string const &conf, char const *key)
}
get_keyval (conf, "keepHills", keep_hills, false);
get_keyval (conf, "dumpFreeEnergyFile", dump_fes, true);
if (! get_keyval (conf, "writeFreeEnergyFile", dump_fes, true))
get_keyval (conf, "dumpFreeEnergyFile", dump_fes, true, colvarparse::parse_silent);
get_keyval (conf, "saveFreeEnergyFile", dump_fes_save, false);
for (size_t i = 0; i < colvars.size(); i++) {
@ -258,6 +259,9 @@ colvarbias_meta::~colvarbias_meta()
if (hills_traj_os.good())
hills_traj_os.close();
if (cvm::n_meta_biases > 0)
cvm::n_meta_biases -= 1;
}

View File

@ -1,6 +1,16 @@
#ifndef COLVARCOMP_H
#define COLVARCOMP_H
// Declaration of colvar::cvc base class and derived ones.
//
// Future cvc's could be declared on additional header files.
// After the declaration of a new derived class, its metric
// functions must be reimplemented as well.
// If the new cvc has no symmetry or periodicity,
// this can be done straightforwardly by using the macro:
// simple_scalar_dist_functions (derived_class)
#include <fstream>
#include <cmath>
@ -591,7 +601,7 @@ protected:
std::vector<cvm::atom_pos> ref_pos;
/// Geometric center of the reference coordinates
cvm::rvector ref_pos_center;
cvm::atom_pos ref_pos_center;
/// Eigenvector (of a normal or essential mode): will always have zero center
std::vector<cvm::rvector> eigenvec;
@ -1140,6 +1150,62 @@ public:
};
// metrics functions for cvc implementations
// simple definitions of the distance functions; these are useful only
// for optimization (the type check performed in the default
// colvarcomp functions is skipped)
// definitions assuming the scalar type
#define simple_scalar_dist_functions(TYPE) \
\
inline cvm::real colvar::TYPE::dist2 (colvarvalue const &x1, \
colvarvalue const &x2) const \
{ \
return (x1.real_value - x2.real_value)*(x1.real_value - x2.real_value); \
} \
\
inline colvarvalue colvar::TYPE::dist2_lgrad (colvarvalue const &x1, \
colvarvalue const &x2) const \
{ \
return 2.0 * (x1.real_value - x2.real_value); \
} \
\
inline colvarvalue colvar::TYPE::dist2_rgrad (colvarvalue const &x1, \
colvarvalue const &x2) const \
{ \
return this->dist2_lgrad (x2, x1); \
} \
\
inline cvm::real colvar::TYPE::compare (colvarvalue const &x1, \
colvarvalue const &x2) const \
{ \
return this->dist2_lgrad (x1, x2); \
} \
\
simple_scalar_dist_functions (distance)
// NOTE: distance_z has explicit functions, see below
simple_scalar_dist_functions (distance_xy)
simple_scalar_dist_functions (distance_inv)
simple_scalar_dist_functions (angle)
simple_scalar_dist_functions (coordnum)
simple_scalar_dist_functions (selfcoordnum)
simple_scalar_dist_functions (h_bond)
simple_scalar_dist_functions (gyration)
simple_scalar_dist_functions (inertia)
simple_scalar_dist_functions (inertia_z)
simple_scalar_dist_functions (rmsd)
simple_scalar_dist_functions (orientation_angle)
simple_scalar_dist_functions (tilt)
simple_scalar_dist_functions (eigenvector)
// simple_scalar_dist_functions (alpha_dihedrals)
simple_scalar_dist_functions (alpha_angles)
simple_scalar_dist_functions (dihedPC)
// metrics functions for cvc implementations with a periodicity
inline cvm::real colvar::dihedral::dist2 (colvarvalue const &x1,
@ -1232,58 +1298,6 @@ inline void colvar::spin_angle::wrap (colvarvalue &x) const
return;
}
// simple definitions of the distance functions; these are useful only
// for optimization (the type check performed in the default
// colvarcomp functions is skipped)
// definitions assuming the scalar type
#define simple_scalar_dist_functions(TYPE) \
\
inline cvm::real colvar::TYPE::dist2 (colvarvalue const &x1, \
colvarvalue const &x2) const \
{ \
return (x1.real_value - x2.real_value)*(x1.real_value - x2.real_value); \
} \
\
inline colvarvalue colvar::TYPE::dist2_lgrad (colvarvalue const &x1, \
colvarvalue const &x2) const \
{ \
return 2.0 * (x1.real_value - x2.real_value); \
} \
\
inline colvarvalue colvar::TYPE::dist2_rgrad (colvarvalue const &x1, \
colvarvalue const &x2) const \
{ \
return this->dist2_lgrad (x2, x1); \
} \
\
inline cvm::real colvar::TYPE::compare (colvarvalue const &x1, \
colvarvalue const &x2) const \
{ \
return this->dist2_lgrad (x1, x2); \
} \
\
simple_scalar_dist_functions (distance)
// NOTE: distance_z has explicit functions, see below
simple_scalar_dist_functions (distance_xy)
simple_scalar_dist_functions (distance_inv)
simple_scalar_dist_functions (angle)
simple_scalar_dist_functions (coordnum)
simple_scalar_dist_functions (selfcoordnum)
simple_scalar_dist_functions (h_bond)
simple_scalar_dist_functions (gyration)
simple_scalar_dist_functions (inertia)
simple_scalar_dist_functions (inertia_z)
simple_scalar_dist_functions (rmsd)
simple_scalar_dist_functions (orientation_angle)
simple_scalar_dist_functions (tilt)
simple_scalar_dist_functions (eigenvector)
// simple_scalar_dist_functions (alpha_dihedrals)
simple_scalar_dist_functions (alpha_angles)
simple_scalar_dist_functions (dihedPC)
// Projected distance
// Differences should always be wrapped around 0 (ignoring wrap_center)
@ -1422,9 +1436,6 @@ inline cvm::real colvar::orientation::compare (colvarvalue const &x1,
}
#endif

View File

@ -77,6 +77,9 @@ colvar::coordnum::coordnum (std::string const &conf)
x.type (colvarvalue::type_scalar);
// group1 and group2 are already initialized by distance()
if (group1.b_dummy)
cvm::fatal_error ("Error: only group2 is allowed to be a dummy atom\n");
// need to specify this explicitly because the distance() constructor
// has set it to true
@ -105,7 +108,7 @@ colvar::coordnum::coordnum (std::string const &conf)
cvm::fatal_error ("Error: odd exponents provided, can only use even ones.\n");
}
get_keyval (conf, "group2CenterOnly", b_group2_center_only, false);
get_keyval (conf, "group2CenterOnly", b_group2_center_only, group2.b_dummy);
}
@ -121,18 +124,10 @@ void colvar::coordnum::calc_value()
{
x.real_value = 0.0;
// these are necessary: for each atom, gradients are summed together
// by multiple calls to switching_function()
group1.reset_atoms_data();
group2.reset_atoms_data();
group1.read_positions();
group2.read_positions();
if (b_group2_center_only) {
// create a fake atom to hold the group2 com coordinates
cvm::atom group2_com_atom (group2[0]);
cvm::atom group2_com_atom;
group2_com_atom.pos = group2.center_of_mass();
if (b_anisotropic) {
@ -165,9 +160,10 @@ void colvar::coordnum::calc_gradients()
if (b_group2_center_only) {
// create a fake atom to hold the group2 com coordinates
cvm::atom group2_com_atom (group2[0]);
cvm::atom group2_com_atom;
group2_com_atom.pos = group2.center_of_mass();
if (b_anisotropic) {
for (cvm::atom_iter ai1 = group1.begin(); ai1 != group1.end(); ai1++)
switching_function<true> (r0_vec, en, ed, *ai1, group2_com_atom);
@ -288,14 +284,6 @@ colvar::h_bond::~h_bond()
void colvar::h_bond::calc_value()
{
// this is necessary, because switching_function() will sum the new
// gradient to the current one
acceptor.reset_data();
donor.reset_data();
acceptor.read_position();
donor.read_position();
x.real_value = colvar::coordnum::switching_function<false> (r0, en, ed, acceptor, donor);
}
@ -315,35 +303,6 @@ void colvar::h_bond::apply_force (colvarvalue const &force)
}
// Self-coordination number for a group
template<bool calculate_gradients>
cvm::real colvar::selfcoordnum::switching_function (cvm::real const &r0,
int const &en,
int const &ed,
cvm::atom &A1,
cvm::atom &A2)
{
cvm::rvector const diff = cvm::position_distance (A1.pos, A2.pos);
cvm::real const l2 = diff.norm2()/(r0*r0);
// Assume en and ed are even integers, and avoid sqrt in the following
int const en2 = en/2;
int const ed2 = ed/2;
cvm::real const xn = std::pow (l2, en2);
cvm::real const xd = std::pow (l2, ed2);
cvm::real const func = (1.0-xn)/(1.0-xd);
if (calculate_gradients) {
cvm::real const dFdl2 = (1.0/(1.0-xd))*(en2*(xn/l2) - func*ed2*(xd/l2))*(-1.0);
cvm::rvector const dl2dx = (2.0/(r0*r0))*diff;
A1.grad += (-1.0)*dFdl2*dl2dx;
A2.grad += dFdl2*dl2dx;
}
return func;
}
colvar::selfcoordnum::selfcoordnum (std::string const &conf)
@ -379,13 +338,9 @@ void colvar::selfcoordnum::calc_value()
{
x.real_value = 0.0;
// for each atom, gradients are summed by multiple calls to switching_function()
group1.reset_atoms_data();
group1.read_positions();
for (size_t i = 0; i < group1.size() - 1; i++)
for (size_t j = i + 1; j < group1.size(); j++)
x.real_value += switching_function<false> (r0, en, ed, group1[i], group1[j]);
x.real_value += colvar::coordnum::switching_function<false> (r0, en, ed, group1[i], group1[j]);
}
@ -393,7 +348,7 @@ void colvar::selfcoordnum::calc_gradients()
{
for (size_t i = 0; i < group1.size() - 1; i++)
for (size_t j = i + 1; j < group1.size(); j++)
switching_function<true> (r0, en, ed, group1[i], group1[j]);
colvar::coordnum::switching_function<true> (r0, en, ed, group1[i], group1[j]);
}
void colvar::selfcoordnum::apply_force (colvarvalue const &force)

View File

@ -522,7 +522,7 @@ colvar::gyration::gyration (std::string const &conf)
cvm::log ("WARNING: explicit fitting parameters were provided for atom group \"atoms\".");
} else {
atoms.b_center = true;
atoms.ref_pos.assign (1, cvm::rvector (0.0, 0.0, 0.0));
atoms.ref_pos.assign (1, cvm::atom_pos (0.0, 0.0, 0.0));
}
x.type (colvarvalue::type_scalar);
@ -991,7 +991,7 @@ colvar::eigenvector::eigenvector (std::string const &conf)
"and eigenvector must be defined.\n");
}
cvm::rvector eig_center (0.0, 0.0, 0.0);
cvm::atom_pos eig_center (0.0, 0.0, 0.0);
for (size_t i = 0; i < atoms.size(); i++) {
eig_center += eigenvec[i];
}

View File

@ -15,8 +15,8 @@ colvarmodule::colvarmodule (char const *config_filename,
proxy = proxy_in;
parse = new colvarparse();
} else {
cvm::fatal_error ("Error: trying to allocate twice the collective "
"variable module.\n");
cvm::fatal_error ("Error: trying to allocate the collective "
"variable module twice.\n");
}
cvm::log (cvm::line_marker);
@ -44,6 +44,11 @@ colvarmodule::colvarmodule (char const *config_filename,
config_s.close();
}
std::string index_file_name;
if (parse->get_keyval (conf, "indexFile", index_file_name)) {
read_index_file (index_file_name.c_str());
}
parse->get_keyval (conf, "analysis", b_analysis, false);
parse->get_keyval (conf, "debugGradientsStepSize", debug_gradients_step_size, 1.0e-07,
@ -84,8 +89,6 @@ colvarmodule::colvarmodule (char const *config_filename,
(output_prefix.size() ?
std::string (output_prefix+".colvars.traj") :
std::string ("colvars.traj"));
cvm::log ("The trajectory file will be \""+
cv_traj_name+"\".\n");
if (cv_traj_freq) {
// open trajectory file
@ -94,6 +97,8 @@ colvarmodule::colvarmodule (char const *config_filename,
"\".\n");
cv_traj_os.open (cv_traj_name.c_str(), std::ios::app);
} else {
cvm::log ("Writing to colvar trajectory file \""+cv_traj_name+
"\".\n");
proxy->backup_file (cv_traj_name.c_str());
cv_traj_os.open (cv_traj_name.c_str(), std::ios::out);
}
@ -478,6 +483,11 @@ void colvarmodule::calc() {
cvi++) {
(*cvi)->write_traj_label (cv_traj_os);
}
for (std::vector<colvarbias *>::iterator bi = biases.begin();
bi != biases.end();
bi++) {
(*bi)->write_traj_label (cv_traj_os);
}
cv_traj_os << "\n";
if (cvm::debug())
cv_traj_os.flush();
@ -494,6 +504,11 @@ void colvarmodule::calc() {
cvi++) {
(*cvi)->write_traj (cv_traj_os);
}
for (std::vector<colvarbias *>::iterator bi = biases.begin();
bi != biases.end();
bi++) {
(*bi)->write_traj (cv_traj_os);
}
cv_traj_os << "\n";
if (cvm::debug())
cv_traj_os.flush();
@ -542,6 +557,14 @@ void colvarmodule::analyze()
}
void colvarmodule::setup()
{
// loop over all components of all colvars to reset masses of all groups
for (std::vector<colvar *>::iterator cvi = colvars.begin();
cvi != colvars.end(); cvi++) {
(*cvi)->setup();
}
}
colvarmodule::~colvarmodule()
{
@ -721,6 +744,55 @@ void cvm::exit (std::string const &message)
}
void cvm::read_index_file (char const *filename)
{
std::ifstream is (filename);
if (!is.good())
fatal_error ("Error: in opening index file \""+
std::string (filename)+"\".\n");
// std::list<std::string>::iterator names_i = cvm::index_group_names.begin();
// std::list<std::vector<int> >::iterator lists_i = cvm::index_groups.begin();
while (is.good()) {
char open, close;
std::string group_name;
if ( (is >> open) && (open == '[') &&
(is >> group_name) &&
(is >> close) && (close == ']') ) {
cvm::index_group_names.push_back (group_name);
cvm::index_groups.push_back (std::vector<int> ());
} else {
cvm::fatal_error ("Error: in parsing index file \""+
std::string (filename)+"\".\n");
}
int atom_number = 1;
size_t pos = is.tellg();
while ( (is >> atom_number) && (atom_number > 0) ) {
(cvm::index_groups.back()).push_back (atom_number);
pos = is.tellg();
}
is.clear();
is.seekg (pos, std::ios::beg);
std::string delim;
if ( (is >> delim) && (delim == "[") ) {
// new group
is.clear();
is.seekg (pos, std::ios::beg);
} else {
break;
}
}
cvm::log ("The following index groups were read from the index file \""+
std::string (filename)+"\":\n");
std::list<std::string>::iterator names_i = cvm::index_group_names.begin();
std::list<std::vector<int> >::iterator lists_i = cvm::index_groups.begin();
for ( ; names_i != cvm::index_group_names.end() ; names_i++, lists_i++) {
cvm::log (" "+(*names_i)+" ("+cvm::to_str (lists_i->size())+" atoms).\n");
}
}
// static pointers
std::vector<colvar *> colvarmodule::colvars;
@ -741,6 +813,8 @@ size_t colvarmodule::cv_traj_freq = 0;
size_t colvarmodule::depth = 0;
bool colvarmodule::b_analysis = false;
cvm::real colvarmodule::rotation::crossing_threshold = 1.0E-04;
std::list<std::string> colvarmodule::index_group_names;
std::list<std::vector<int> > colvarmodule::index_groups;
// file name prefixes
@ -932,15 +1006,13 @@ cvm::quaternion::position_derivative_inner (cvm::rvector const &pos,
// Calculate the optimal rotation between two groups, and implement it
// as a quaternion. The method is the one documented in: Coutsias EA,
// Seok C, Dill KA. Using quaternions to calculate RMSD. J Comput
// Chem. 25(15):1849-57 (2004) DOI: 10.1002/jcc.20110 PubMed: 15376254
void colvarmodule::rotation::build_matrix (std::vector<cvm::atom_pos> const &pos1,
std::vector<cvm::atom_pos> const &pos2,
matrix2d<cvm::real, 4, 4> &S)
@ -1068,7 +1140,8 @@ void colvarmodule::rotation::calc_optimal_rotation
if (q_old.norm2() > 0.0) {
q.match (q_old);
if (q_old.inner (q) < (1.0 - crossing_threshold)) {
cvm::log ("Warning: discontinuous rotation!\n");
cvm::log ("Warning: one molecular orientation has changed by more than "+
cvm::to_str (crossing_threshold)+": discontinuous rotation ?\n");
}
}
q_old = q;

View File

@ -2,7 +2,7 @@
#define COLVARMODULE_H
#ifndef COLVARS_VERSION
#define COLVARS_VERSION "2013-04-17"
#define COLVARS_VERSION "2013-06-19"
#endif
#ifndef COLVARS_DEBUG
@ -159,6 +159,7 @@ public:
/// \param restart_name (optional) Restart file name
colvarmodule (char const *config_name,
colvarproxy *proxy_in);
/// Destructor
~colvarmodule();
@ -168,6 +169,11 @@ public:
/// Initialize collective variable biases
void init_biases (std::string const &conf);
/// Re-initialize data at the beginning of a run. For use with
/// MD codes that can change system parameters like atom masses
/// between run commands.
void setup();
/// Load new configuration for the given bias -
/// currently works for harmonic (force constant and/or centers)
void change_configuration (std::string const &bias_name, std::string const &conf);
@ -290,6 +296,16 @@ public:
atom_pos const &ref_pos);
/// \brief Names of groups from a Gromacs .ndx file to be read at startup
static std::list<std::string> index_group_names;
/// \brief Groups from a Gromacs .ndx file read at startup
static std::list<std::vector<int> > index_groups;
/// \brief Read a Gromacs .ndx file
static void read_index_file (char const *filename);
/// \brief Create atoms from a file \param filename name of the file
/// (usually a PDB) \param atoms array of the atoms to be allocated
/// \param pdb_field (optiona) if "filename" is a PDB file, use this

View File

@ -371,8 +371,8 @@ void colvarparse::check_keywords (std::string &conf, char const *key)
std::string uk;
std::istringstream line_is (line);
line_is >> uk;
if (cvm::debug())
cvm::log ("Checking the validity of \""+uk+"\" from line:\n" + line);
// if (cvm::debug())
// cvm::log ("Checking the validity of \""+uk+"\" from line:\n" + line);
uk = to_lower_cppstr (uk);
bool found_keyword = false;

View File

@ -16,6 +16,12 @@ public:
/// Pointer to the instance of colvarmodule
colvarmodule *colvars;
/// Default destructor
virtual inline ~colvarproxy() {}
// **************** SYSTEM-WIDE PHYSICAL QUANTITIES ****************
/// \brief Value of the unit for atomic coordinates with respect to
/// angstroms (used by some variables for hard-coded default values)
virtual cvm::real unit_angstrom() = 0;
@ -29,21 +35,11 @@ public:
/// \brief Time step of the simulation (fs)
virtual cvm::real dt() = 0;
/// Pass restraint energy value for current timestep to MD engine
virtual void add_energy (cvm::real energy) = 0;
/// \brief Pseudo-random number with Gaussian distribution
virtual cvm::real rand_gaussian (void) = 0;
/// Tell the proxy whether system forces are needed
virtual void request_system_force (bool yesno) = 0;
/// Print a message to the main log
virtual void log (std::string const &message) = 0;
/// Print a message to the main log and exit with error code
virtual void fatal_error (std::string const &message) = 0;
/// Print a message to the main log and exit normally
virtual void exit (std::string const &message) = 0;
// **************** SIMULATION PARAMETERS ****************
/// \brief Prefix to be used for input files (restarts, not
/// configuration)
@ -59,21 +55,28 @@ public:
/// \brief Restarts will be fritten each time this number of steps has passed
virtual size_t restart_frequency() = 0;
// **************** ACCESS ATOMIC DATA ****************
/// Pass restraint energy value for current timestep to MD engine
virtual void add_energy (cvm::real energy) = 0;
/// Tell the proxy whether system forces are needed (may not always be available)
virtual void request_system_force (bool yesno) = 0;
// **************** PERIODIC BOUNDARY CONDITIONS ****************
/// \brief Get the simple distance vector between two positions
/// (with periodic boundary conditions handled transparently)
/// \brief Get the PBC-aware distance vector between two positions
virtual cvm::rvector position_distance (cvm::atom_pos const &pos1,
cvm::atom_pos const &pos2) = 0;
/// \brief Get the square distance between two positions (with
/// periodic boundary conditions handled transparently)
///
/// Note: in the case of periodic boundary conditions, this provides
/// an analytical square distance (while taking the square of
/// position_distance() would produce leads to a cusp)
/// \brief Get the PBC-aware square distance between two positions;
/// may be implemented independently from position_distance() for optimization purposes
virtual cvm::real position_dist2 (cvm::atom_pos const &pos1,
cvm::atom_pos const &pos2) = 0;
cvm::atom_pos const &pos2);
/// \brief Get the closest periodic image to a reference position
/// \param pos The position to look for the closest periodic image
@ -89,6 +92,18 @@ public:
cvm::atom_pos const &ref_pos);
// **************** INPUT/OUTPUT ****************
/// Print a message to the main log
virtual void log (std::string const &message) = 0;
/// Print a message to the main log and exit with error code
virtual void fatal_error (std::string const &message) = 0;
/// Print a message to the main log and exit normally
virtual void exit (std::string const &message) = 0;
/// \brief Read atom identifiers from a file \param filename name of
/// the file (usually a PDB) \param atoms array to which atoms read
/// from "filename" will be appended \param pdb_field (optiona) if
@ -97,7 +112,7 @@ public:
virtual void load_atoms (char const *filename,
std::vector<cvm::atom> &atoms,
std::string const pdb_field,
double const pdb_field_value = 0.0) = 0;
double const pdb_field_value = 0.0) {}
/// \brief Load the coordinates for a group of atoms from a file
/// (usually a PDB); if "pos" is already allocated, the number of its
@ -108,14 +123,9 @@ public:
std::string const pdb_field,
double const pdb_field_value = 0.0) = 0;
/// \brief Rename the given file, under the convention provided by
/// the MD program
virtual void backup_file (char const *filename) = 0;
/// \brief Rename the given file, before overwriting it
virtual void backup_file (char const *filename) {}
/// \brief Pseudo-random number with Gaussian distribution
virtual cvm::real rand_gaussian (void) = 0;
virtual inline ~colvarproxy() {}
};
@ -128,6 +138,12 @@ inline void colvarproxy::select_closest_images (std::vector<cvm::atom_pos> &pos,
}
}
inline cvm::real colvarproxy::position_dist2 (cvm::atom_pos const &pos1,
cvm::atom_pos const &pos2)
{
return (position_distance (pos1, pos2)).norm2();
}
#endif

View File

@ -242,7 +242,7 @@ std::istream & operator >> (std::istream &is, colvarvalue &x)
}
size_t colvarvalue::output_width (size_t const &real_width)
size_t colvarvalue::output_width (size_t const &real_width) const
{
switch (this->value_type) {
case colvarvalue::type_scalar:

View File

@ -265,10 +265,10 @@ public:
/// with a different type to this object
void error_rside (Type const &vt) const;
///<EFBFBD>Give the number of characters required to output this
/// 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);
size_t output_width (size_t const &real_width) const;
// optimized routines for operations with an array; xv and inner as