Commit c4af1cdb authored by sjplimp's avatar sjplimp
Browse files

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@12811 f3b2605a-c512-4ea7-a41b-209d697bcdaa
parent 9c0f8495
Loading
Loading
Loading
Loading
+479 −434
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ colvar::colvar (std::string const &conf)

  initialize_components("distance",         "distance",       distance);
  initialize_components("distance vector",  "distanceVec",    distance_vec);
  initialize_components("Cartesian coordinates", "cartesian",  cartesian);
  initialize_components("distance vector "
                         "direction",        "distanceDir",    distance_dir);
  initialize_components("distance projection "
@@ -107,6 +108,8 @@ colvar::colvar (std::string const &conf)
                         "on a plane",       "distanceXY",     distance_xy);
  initialize_components("average distance weighted by inverse power",
                         "distanceInv", distance_inv);
  initialize_components("N1xN2-long vector of pairwise distances",
                         "distancePairs", distance_pairs);

  initialize_components("coordination "
                         "number",           "coordNum",       coordnum);
@@ -159,11 +162,33 @@ colvar::colvar (std::string const &conf)
    enable(task_scripted);
    cvm::log("This colvar uses scripted function \"" + scripted_function + "\".");

    // Only accept scalar scripted colvars
    // might accept other types when the infrastructure is in place
    // for derivatives of vectors wrt vectors
    x.type(colvarvalue::type_scalar);
    std::string type_str;
    get_keyval(conf, "scriptedFunctionType", type_str, "scalar");

    x.type(colvarvalue::type_notset);
    int t;
    for (t = 0; t < colvarvalue::type_all; t++) {
      if (type_str == colvarvalue::type_keyword(colvarvalue::Type(t))) {
        x.type(colvarvalue::Type(t));
        break;
      }
    }
    if (x.type() == colvarvalue::type_notset) {
      cvm::error("Could not parse scripted colvar type.");
      return;
    }
    x_reported.type (x.type());
    cvm::log(std::string("Expecting colvar value of type ")
      + colvarvalue::type_desc(x.type()));

    if (x.type() == colvarvalue::type_vector) {
      int size;
      if (!get_keyval(conf, "scriptedFunctionVectorSize", size)) {
        cvm::error("Error: no size specified for vector scripted function.");
        return;
      }
      x.vector1d_value.resize(size);
    }

    // Sort array of cvcs based on values of componentExp
    std::vector<cvc *> temp_vec;
@@ -185,41 +210,39 @@ colvar::colvar (std::string const &conf)
    // Build ordered list of component values that will be
    // passed to the script
    for (j = 0; j < cvcs.size(); j++) {
      sorted_cvc_values.push_back(cvcs[j]->p_value());
    }
      sorted_cvc_values.push_back(&(cvcs[j]->value()));
    }

  if (!tasks[task_scripted]) {
    // this is set false if any of the components has an exponent
    // different from 1 in the polynomial
    b_linear = true;
    // these will be set to false if any of the cvcs has them false
    b_inverse_gradients = true;
    b_Jacobian_force    = true;
  }

  // Test whether this is a single-component variable
  // Decide whether the colvar is periodic
  // Used to wrap extended DOF if extendedLagrangian is on
  if (cvcs.size() == 1  && (cvcs[0])->sup_np == 1
                        && (cvcs[0])->sup_coeff == 1.0
                        && !tasks[task_scripted]) {

    b_single_cvc = true;
    b_periodic = (cvcs[0])->b_periodic;
    period = (cvcs[0])->period;
    // TODO write explicit wrap() function for colvars to allow for
    // sup_coeff different from 1
    // this->period = (cvcs[0])->period * (cvcs[0])->sup_coeff;
  } else {
    b_single_cvc = false;
    b_homogeneous = false;
    // Scripted functions are deemed non-periodic
    b_periodic = false;
    period = 0.0;
    b_inverse_gradients = false;
    b_Jacobian_force = false;
  }

  // check the available features of each cvc
  for (i = 0; i < cvcs.size(); i++) {
  if (!tasks[task_scripted]) {
    colvarvalue const &cvc_value = (cvcs[0])->value();
    if (cvm::debug())
      cvm::log ("This collective variable is a "+
                colvarvalue::type_desc(cvc_value.type())+
                ((cvc_value.size() > 1) ? " with "+
                 cvm::to_str(cvc_value.size())+" individual components.\n" :
                 ".\n"));
    x.type(cvc_value);
    x_reported.type(cvc_value);
  }

  // If using scripted biases, any colvar may receive bias forces
  // and will need its gradient
  if (cvm::scripted_forces()) {
    enable(task_gradients);
  }

  // check for linear combinations

  b_linear = !tasks[task_scripted];
  for (i = 0; i < cvcs.size(); i++) {
    if ((cvcs[i])->b_debug_gradients)
      enable(task_gradients);

@@ -237,7 +260,41 @@ colvar::colvar (std::string const &conf)
                  (cvcs[i])->function_type+"\" approaches zero.\n");
      }
    }
  }

  // Colvar is homogeneous iff:
  // - it is not scripted
  // - it is linear
  // - all cvcs have coefficient 1 or -1
  // i.e. sum or difference of cvcs

  b_homogeneous = !tasks[task_scripted] && b_linear;
  for (i = 0; i < cvcs.size(); i++) {
    if ((std::fabs(cvcs[i]->sup_coeff) - 1.0) > 1.0e-10) {
      b_homogeneous = false;
    }
  }

  // Colvar is deemed periodic iff:
  // - it is homogeneous
  // - all cvcs are periodic
  // - all cvcs have the same period

  b_periodic = cvcs[0]->b_periodic && b_homogeneous;
  period = cvcs[0]->period;
  for (i = 1; i < cvcs.size(); i++) {
    if (!cvcs[i]->b_periodic || cvcs[i]->period != period) {
      b_periodic = false;
      period = 0.0;
    }
  }

  // these will be set to false if any of the cvcs has them false
  b_inverse_gradients = !tasks[task_scripted];
  b_Jacobian_force    = !tasks[task_scripted];

  // check the available features of each cvc
  for (i = 0; i < cvcs.size(); i++) {
    if ((cvcs[i])->b_periodic && !b_periodic) {
        cvm::log("Warning: although this component is periodic, the colvar will "
                  "not be treated as periodic, either because the exponent is not "
@@ -251,34 +308,15 @@ colvar::colvar (std::string const &conf)
    if (! (cvcs[i])->b_Jacobian_derivative)
      b_Jacobian_force = false;

    if (!tasks[task_scripted]) {
      // If the combination of components is a scripted function,
      // the components may have different types
      for (size_t j = i; j < cvcs.size(); j++) {
        if ( (cvcs[i])->type() != (cvcs[j])->type() ) {
          cvm::log ("ERROR: you are definining this collective variable "
                            "by using components of different types, \""+
                            colvarvalue::type_desc[(cvcs[i])->type()]+
                            "\" and \""+
                            colvarvalue::type_desc[(cvcs[j])->type()]+
                            "\". "
    // components may have different types only for scripted functions
    if (!tasks[task_scripted] && (colvarvalue::check_types(cvcs[i]->value(),
                                                           cvcs[0]->value())) ) {
      cvm::error("ERROR: you are definining this collective variable "
                 "by using components of different types. "
                 "You must use the same type in order to "
                            " sum them together.\n");
          cvm::set_error_bits(INPUT_ERROR);
        }
      }
    }
                 " sum them together.\n", INPUT_ERROR);
      return;
    }

  if (!tasks[task_scripted]) {
    colvarvalue::Type const value_type = (cvcs[0])->type();
    if (cvm::debug())
      cvm::log ("This collective variable is a "+
                colvarvalue::type_desc[value_type]+", corresponding to "+
                cvm::to_str (colvarvalue::dof_num[value_type])+
                " internal degrees of freedom.\n");
    x.type (value_type);
    x_reported.type (value_type);
  }

  get_keyval(conf, "width", width, 1.0);
@@ -286,13 +324,13 @@ colvar::colvar (std::string const &conf)
    cvm::error("Error: \"width\" must be positive.\n", INPUT_ERROR);
  }

  lower_boundary.type (this->type());
  lower_wall.type     (this->type());
  lower_boundary.type(value());
  lower_wall.type(value());

  upper_boundary.type (this->type());
  upper_wall.type     (this->type());
  upper_boundary.type(value());
  upper_wall.type(value());

  if (this->type() == colvarvalue::type_scalar) {
  if (value().type() == colvarvalue::type_scalar) {

    if (get_keyval(conf, "lowerBoundary", lower_boundary, lower_boundary)) {
      enable(task_lower_boundary);
@@ -375,14 +413,14 @@ colvar::colvar (std::string const &conf)

      enable(task_extended_lagrangian);

      xr.type (this->type());
      vr.type (this->type());
      fr.type (this->type());
      xr.type(value());
      vr.type(value());
      fr.type(value());

      const bool found = get_keyval(conf, "extendedTemp", temp, cvm::temperature());
      if (temp <= 0.0) {
        if (found)
          cvm::log ("Error: \"extendedTemp\" must be positive.\n");
          cvm::error("Error: \"extendedTemp\" must be positive.\n", INPUT_ERROR);
        else
          cvm::error("Error: a positive temperature must be provided, either "
                     "by enabling a thermostat, or through \"extendedTemp\".\n",
@@ -621,7 +659,7 @@ int colvar::enable (colvar::task const &t)
        cvm::log("Enabling calculation of the Jacobian force "
                  "on this colvar.\n");
    }
    fj.type (this->type());
    fj.type(value());
    break;

  case task_system_force:
@@ -634,8 +672,8 @@ int colvar::enable (colvar::task const &t)
      }
      cvm::request_system_force();
    }
    ft.type (this->type());
    ft_reported.type (this->type());
    ft.type(value());
    ft_reported.type(value());
    break;

  case task_output_applied_force:
@@ -646,9 +684,9 @@ int colvar::enable (colvar::task const &t)
    break;

  case task_fdiff_velocity:
    x_old.type (this->type());
    v_fdiff.type (this->type());
    v_reported.type (this->type());
    x_old.type(value());
    v_fdiff.type(value());
    v_reported.type(value());
    break;

  case task_output_velocity:
@@ -656,7 +694,7 @@ int colvar::enable (colvar::task const &t)
    break;

  case task_grid:
    if (this->type() != colvarvalue::type_scalar) {
    if (value().type() != colvarvalue::type_scalar) {
      cvm::error("Cannot calculate a grid for collective variable, \""+
                        this->name+"\", because its value is not a scalar number.\n",
                  INPUT_ERROR);
@@ -665,12 +703,12 @@ int colvar::enable (colvar::task const &t)

  case task_extended_lagrangian:
    enable(task_gradients);
    v_reported.type (this->type());
    v_reported.type(value());
    break;

  case task_lower_boundary:
  case task_upper_boundary:
    if (this->type() != colvarvalue::type_scalar) {
    if (value().type() != colvarvalue::type_scalar) {
      cvm::error("Error: this colvar is not a scalar value "
                        "and cannot produce a grid.\n",
                INPUT_ERROR);
@@ -687,12 +725,12 @@ int colvar::enable (colvar::task const &t)
    break;

  case task_gradients:
    f.type  (this->type());
    fb.type (this->type());
    f.type(value());
    fb.type(value());
    break;

  case task_collect_gradients:
    if (this->type() != colvarvalue::type_scalar) {
    if (value().type() != colvarvalue::type_scalar) {
      cvm::error("Collecting atomic gradients for non-scalar collective variable \""+
                        this->name+"\" is not yet implemented.\n",
                  INPUT_ERROR);
@@ -1032,8 +1070,8 @@ cvm::real colvar::update()
  if (cvm::debug())
    cvm::log("Updating colvar \""+this->name+"\".\n");


  // set to zero the applied force
  f.type(value());
  f.reset();

  // add the biases' force, which at this point should already have
@@ -1044,7 +1082,11 @@ cvm::real colvar::update()
  if (tasks[task_lower_wall] || tasks[task_upper_wall]) {

    // wall force
    colvarvalue fw (this->type());
    colvarvalue fw(value());
    fw.reset();

    if (cvm::debug())
      cvm::log("Calculating wall forces for colvar \""+this->name+"\".\n");

    // if the two walls are applied concurrently, decide which is the
    // closer one (on a periodic colvar, both walls may be applicable
@@ -1148,25 +1190,28 @@ void colvar::communicate_forces()
    cvm::log("Communicating forces from colvar \""+this->name+"\".\n");

  if (tasks[task_scripted]) {
    std::vector<colvarvalue> func_grads(cvcs.size());
    std::vector<cvm::matrix2d<cvm::real> > func_grads;
    for (i = 0; i < cvcs.size(); i++) {
      func_grads.push_back(cvm::matrix2d<cvm::real> (x.size(),
                                                     cvcs[i]->value().size()));
    }
    int res = cvm::proxy->run_colvar_gradient_callback(scripted_function, sorted_cvc_values, func_grads);

    if (res != COLVARS_OK) {
      if (res == COLVARS_NOT_IMPLEMENTED) {
        cvm::error("Colvar gradient scripts are not implemented.");
      return;
    }
    if (res != COLVARS_OK) {
      } else {
        cvm::error("Error running colvar gradient script");
      }
      return;
    }

    for (i = 0; i < cvcs.size(); i++) {
      cvm::increase_depth();
      // Force is scalar times colvarvalue (scalar or vector)
      // Note: this can only handle scalar colvars (scalar values of f)
      // A non-scalar colvar would need the gradient to be expressed
      // as an order-2 tensor
      (cvcs[i])->apply_force (f.real_value * func_grads[i]);
      // cvc force is colvar force times colvar/cvc Jacobian
      // (vector-matrix product)
      (cvcs[i])->apply_force(colvarvalue(f.as_vector() * func_grads[i],
                             cvcs[i]->value().type()));
      cvm::decrease_depth();
    }
  } else if (x.type() == colvarvalue::type_scalar) {
@@ -1235,7 +1280,7 @@ bool colvar::periodic_boundaries() const
cvm::real colvar::dist2(colvarvalue const &x1,
                         colvarvalue const &x2) const
{
  if (b_single_cvc) {
  if (b_homogeneous) {
    return (cvcs[0])->dist2(x1, x2);
  } else {
    return x1.dist2(x2);
@@ -1245,7 +1290,7 @@ cvm::real colvar::dist2 (colvarvalue const &x1,
colvarvalue colvar::dist2_lgrad(colvarvalue const &x1,
                                 colvarvalue const &x2) const
{
  if (b_single_cvc) {
  if (b_homogeneous) {
    return (cvcs[0])->dist2_lgrad(x1, x2);
  } else {
    return x1.dist2_grad(x2);
@@ -1255,7 +1300,7 @@ colvarvalue colvar::dist2_lgrad (colvarvalue const &x1,
colvarvalue colvar::dist2_rgrad(colvarvalue const &x1,
                                 colvarvalue const &x2) const
{
  if (b_single_cvc) {
  if (b_homogeneous) {
    return (cvcs[0])->dist2_rgrad(x1, x2);
  } else {
    return x2.dist2_grad(x1);
@@ -1264,7 +1309,7 @@ colvarvalue colvar::dist2_rgrad (colvarvalue const &x1,

void colvar::wrap(colvarvalue &x) const
{
  if (b_single_cvc) {
  if (b_homogeneous) {
    (cvcs[0])->wrap(x);
  }
  return;
@@ -1612,7 +1657,7 @@ int colvar::calc_acf()
    colvar *cfcv = (acf_colvar_name.size() ?
                    cvm::colvar_by_name(acf_colvar_name) :
                    this);
    if (cfcv->type() != this->type()) {
    if (colvarvalue::check_types(cfcv->value(), value())) {
      cvm::error("Error: correlation function between \""+cfcv->name+
                 "\" and \""+this->name+"\" cannot be calculated, "
                 "because their value types are different.\n",
@@ -1799,7 +1844,7 @@ void colvar::calc_runave()
{
  if (x_history.empty()) {

    runave.type (x.type());
    runave.type(value().type());
    runave.reset();

    // first-step operations
+44 −43
Original line number Diff line number Diff line
@@ -31,9 +31,8 @@
///
/// Please note that most of its members are \link colvarvalue
/// \endlink objects, i.e. they can handle different data types
/// together, and must all be set to the same type of colvar::x by
/// using the colvarvalue::type() member function before using them
/// together in assignments or other operations; this is usually done
/// together, and must all be set to the same type of colvar::value()
/// before using them together in assignments or other operations; this is usually done
/// automatically in the constructor.  If you add a new member of
/// \link colvarvalue \endlink type, you should also add its
/// initialization line in the \link colvar \endlink constructor.
@@ -45,16 +44,13 @@ public:
  /// Name
  std::string name;

  /// Type of value
  colvarvalue::Type type() const;

  /// \brief Current value (previously obtained from calc() or read_traj())
  /// \brief Current value (previously set by calc() or by read_traj())
  colvarvalue const & value() const;

  /// \brief Current actual value (not extended DOF)
  colvarvalue const & actual_value() const;

  /// \brief Current velocity (previously obtained from calc() or read_traj())
  /// \brief Current velocity (previously set by calc() or by read_traj())
  colvarvalue const & velocity() const;

  /// \brief Current system force (previously obtained from calc() or
@@ -83,9 +79,9 @@ public:
  /// combination of \link cvc \endlink elements
  bool b_linear;

  /// \brief True if this \link colvar \endlink is equal to
  /// its only constituent cvc
  bool b_single_cvc;
  /// \brief True if this \link colvar \endlink is a linear
  /// combination of cvcs with coefficients 1 or -1
  bool b_homogeneous;

  /// \brief True if all \link cvc \endlink objects are capable
  /// of calculating inverse gradients
@@ -190,6 +186,13 @@ protected:
  /// Value of the colvar
  colvarvalue x;

  // TODO: implement functionality to treat these
  // /// Vector of individual values from CVCs
  // colvarvalue x_cvc;

  // /// Jacobian matrix of individual values from CVCs
  // colvarvalue dx_cvc;

  /// Cached reported value (x may be manipulated)
  colvarvalue x_reported;

@@ -479,6 +482,7 @@ public:
  class distance_z;
  class distance_xy;
  class distance_inv;
  class distance_pairs;
  class angle;
  class dihedral;
  class coordnum;
@@ -500,6 +504,7 @@ public:
  // non-scalar components
  class distance_vec;
  class distance_dir;
  class cartesian;
  class orientation;

protected:
@@ -533,11 +538,6 @@ public:
  }
};

inline colvarvalue::Type colvar::type() const
{
  return x.type();
}


inline colvarvalue const & colvar::value() const
{
@@ -570,6 +570,7 @@ inline void colvar::add_bias_force (colvarvalue const &force)


inline void colvar::reset_bias_force() {
  fb.type(value());
  fb.reset();
}

+50 −45
Original line number Diff line number Diff line
@@ -83,14 +83,16 @@ colvarbias::~colvarbias()

void colvarbias::add_colvar(std::string const &cv_name)
{
  if (colvar *cvp = cvm::colvar_by_name (cv_name)) {
    cvp->enable (colvar::task_gradients);
  if (colvar *cv = cvm::colvar_by_name(cv_name)) {
    cv->enable(colvar::task_gradients);
    if (cvm::debug())
      cvm::log("Applying this bias to collective variable \""+
                cvp->name+"\".\n");
    colvars.push_back (cvp);
    colvar_forces.push_back (colvarvalue (cvp->type()));
    cvp->biases.push_back (this); // add back-reference to this bias to colvar
                cv->name+"\".\n");
    colvars.push_back(cv);
    colvar_forces.push_back(colvarvalue());
    colvar_forces.back().type(cv->value()); // make sure each forces is initialized to zero
    colvar_forces.back().reset();
    cv->biases.push_back(this); // add back-reference to this bias to colvar
  } else {
    cvm::error("Error: cannot find a colvar named \""+
               cv_name+"\".\n");
@@ -103,8 +105,7 @@ void colvarbias::communicate_forces()
  for (size_t i = 0; i < colvars.size(); i++) {
    if (cvm::debug()) {
      cvm::log("Communicating a force to colvar \""+
                colvars[i]->name+"\", of type \""+
                colvarvalue::type_desc[colvars[i]->type()]+"\".\n");
               colvars[i]->name+"\".\n");
    }
    colvars[i]->add_bias_force(colvar_forces[i]);
  }
@@ -128,19 +129,23 @@ cvm::real colvarbias::energy_difference(std::string const &conf)
int colvarbias::bin_num()
{
  cvm::error("Error: bin_num() not implemented.\n");
  return -1;
  return COLVARS_NOT_IMPLEMENTED;
}
int colvarbias::current_bin()
{
  cvm::error("Error: current_bin() not implemented.\n");
  return -1;
  return COLVARS_NOT_IMPLEMENTED;
}
int colvarbias::bin_count(int bin_index)
{
  cvm::error("Error: bin_count() not implemented.\n");
  return -1;
  return COLVARS_NOT_IMPLEMENTED;
}
int colvarbias::replica_share()
{
  cvm::error("Error: replica_share() not implemented.\n");
  return COLVARS_NOT_IMPLEMENTED;
}


std::ostream & colvarbias::write_traj_label(std::ostream &os)
{
+9 −9
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ public:
  //// Give the count at a given bin index.
  virtual int bin_count(int bin_index);
  //// Share information between replicas, whatever it may be.
  virtual void replica_share() {};
  virtual int replica_share();

  /// Perform analysis tasks
  virtual inline void analyse() {}
+172 −165
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ colvarbias_abf::colvarbias_abf (std::string const &conf, char const *key)

  for (size_t i = 0; i < colvars.size(); i++) {

    if (colvars[i]->type() != colvarvalue::type_scalar) {
    if (colvars[i]->value().type() != colvarvalue::type_scalar) {
      cvm::error("Error: ABF bias can only use scalar-type variables.\n");
    }

@@ -282,17 +282,17 @@ cvm::real colvarbias_abf::update()
  return 0.0;
}

void colvarbias_abf::replica_share () {
int colvarbias_abf::replica_share() {
  int p;

  if ( !cvm::replica_enabled() ) {
    cvm::error("Error: shared ABF: No replicas.\n");
    return;
    return COLVARS_ERROR;
  }
  // We must have stored the last_gradients and last_samples.
  if (shared_last_step < 0 ) {
    cvm::error("Error: shared ABF: Tried to apply shared ABF before any sampling had occurred.\n");
    return;
    return COLVARS_ERROR;
  }

  // Share gradients for shared ABF.
@@ -355,6 +355,8 @@ void colvarbias_abf::replica_share () {
  last_gradients->copy_grid(*gradients);
  last_samples->copy_grid(*samples);
  shared_last_step = cvm::step_absolute();

  return COLVARS_OK;
}

void colvarbias_abf::write_gradients_samples(const std::string &prefix, bool append)
@@ -546,7 +548,7 @@ std::istream & colvarbias_abf::read_restart (std::istream& is)

colvarbias_histogram::colvarbias_histogram(std::string const &conf, char const *key)
  : colvarbias(conf, key),
    grid (NULL)
    grid(NULL), out_name("")
{
  get_keyval(conf, "outputfreq", output_freq, cvm::restart_out_freq);

@@ -557,9 +559,6 @@ colvarbias_histogram::colvarbias_histogram (std::string const &conf, char const
  grid   = new colvar_grid_count    (colvars);
  bin.assign(colvars.size(), 0);

  out_name = cvm::output_prefix + "." + this->name + ".dat";
  cvm::log ("Histogram will be written to file " + out_name);

  cvm::log("Finished histogram setup.\n");
}

@@ -582,6 +581,14 @@ cvm::real colvarbias_histogram::update()
{
  if (cvm::debug()) cvm::log("Updating Grid bias " + this->name);

  // At the first timestep, we need to assign out_name since
  // output_prefix is unset during the constructor

  if (cvm::step_relative() == 0) {
    out_name = cvm::output_prefix + "." + this->name + ".dat";
    cvm::log("Histogram " + this->name + " will be written to file \"" + out_name + "\"");
  }

  for (size_t i=0; i<colvars.size(); i++) {
    bin[i] = grid->current_bin_scalar(i);
  }
Loading