Difference for src/colvardeps.C from version 1.6 to 1.7

version 1.6version 1.7
Line 10
Line 10
  
 #include "colvardeps.h" #include "colvardeps.h"
  
  colvardeps::colvardeps()
    : time_step_factor (1) {}
  
 colvardeps::~colvardeps() { colvardeps::~colvardeps() {
   size_t i;   size_t i;
  
    // Protest if we are deleting an object while a parent object may still depend on it
    // Another possible strategy is to have the child unlist itself from the parent's children
    if (parents.size()) {
      cvm::log("Warning: destroying \"" + description + "\" before its parents objects:");
      for (i=0; i<parents.size(); i++) {
        cvm::log(parents[i]->description);
      }
    }
  
       // Do not delete features if it's static       // Do not delete features if it's static
 //     for (i=0; i<features.size(); i++) { //     for (i=0; i<features.size(); i++) {
 //       if (features[i] != NULL) delete features[i]; //       if (features[i] != NULL) delete features[i];
 //     } //     }
  
   remove_all_children();   remove_all_children();
  }
  
   // Protest if we are deleting an object while a parent object may still depend on it 
   // Another possible strategy is to have the child unlist itself from the parent's children void colvardeps::free_children_deps() {
   if (parents.size()) {   // Dereference children requirements of all enabled features
     cvm::log("Warning: destroying " + description + " before its parents objects:");   // Useful when object is destroyed or set inactive
     for (i=0; i<parents.size(); i++) {   // CAUTION: when setting the parent object inactive, disable "active" first
       cvm::log(parents[i]->description);   // then call this, to avoid double-dereferencing the deps of "active"
  
    // Cannot be in the base class destructor because it needs the derived class features()
    size_t i,j,fid;
  
    if (cvm::debug()) cvm::log("DEPS: freeing children deps for " + description);
  
    for (fid = 0; fid < feature_states.size(); fid++) {
      if (is_enabled(fid)) {
        for (i=0; i<features()[fid]->requires_children.size(); i++) {
          int g = features()[fid]->requires_children[i];
          for (j=0; j<children.size(); j++) {
            cvm::increase_depth();
            if (cvm::debug()) cvm::log("DEPS: dereferencing children's "
              + children[j]->features()[g]->description);
            children[j]->decr_ref_count(g);
            cvm::decrease_depth();
          }
        }
      }
    }
  }
  
  
  // re-enable children features (and increase ref count accordingly)
  // So free_children_deps() can be called whenever an object becomes inactive
  void colvardeps::restore_children_deps() {
    size_t i,j,fid;
    for (fid = 0; fid < feature_states.size(); fid++) {
      if (is_enabled(fid)) {
        for (i=0; i<features()[fid]->requires_children.size(); i++) {
          int g = features()[fid]->requires_children[i];
          for (j=0; j<children.size(); j++) {
            cvm::increase_depth();
            if (cvm::debug()) cvm::log("DEPS: re-enabling children's "
              + children[j]->features()[g]->description);
            children[j]->enable(g, false, false);
            cvm::decrease_depth();
          }
        }
     }     }
   }   }
 } }
Line 37
Line 89
  
  
 void colvardeps::set_enabled(int feature_id, bool truefalse) { void colvardeps::set_enabled(int feature_id, bool truefalse) {
 //   if (!is_static(feature_id)) { 
 //     cvm::error("Cannot set feature " + features()[feature_id]->description + " statically in " + description + ".\n"); 
 //     return; 
 //   } 
   if (truefalse) {   if (truefalse) {
     // Resolve dependencies too 
     enable(feature_id);     enable(feature_id);
   } else {   } else {
     feature_states[feature_id].enabled = false;     disable(feature_id);
   }   }
 } }
  
Line 56
Line 103
                                     colvarparse::Parse_Mode const parse_mode)                                     colvarparse::Parse_Mode const parse_mode)
 { {
   if (!is_user(feature_id)) {   if (!is_user(feature_id)) {
     cvm::error("Cannot set feature " + features()[feature_id]->description + " from user input in " + description + ".\n");     cvm::error("Cannot set feature \"" + features()[feature_id]->description + "\" from user input in \"" + description + "\".\n");
     return false;     return false;
   }   }
   bool value;   bool value;
Line 83
Line 130
  
   if (cvm::debug()) {   if (cvm::debug()) {
     cvm::log("DEPS: " + description +     cvm::log("DEPS: " + description +
       (dry_run ? " testing " : " requiring ") +       (dry_run ? " testing " : " enabling ") +
       "\"" + f->description +"\"");       "\"" + f->description +"\"");
   }   }
  
   if (fs->enabled) {   if (fs->enabled) {
     // Do not try to solve deps if already enabled     if (!(dry_run || toplevel)) {
        // This is a dependency
        // Prevent disabling this feature as long
        // as requirement is enabled
        fs->ref_count++;
        if (cvm::debug())
          cvm::log("DEPS: bumping ref_count to " + cvm::to_str(fs->ref_count));
      }
      // Do not try to further resolve deps
     return COLVARS_OK;     return COLVARS_OK;
   }   }
  
    std::string feature_type_descr = is_static(feature_id) ? "Static" :
      (is_dynamic(feature_id) ? "Dynamic" : "User-controlled");
  
   if (!fs->available) {   if (!fs->available) {
     if (!dry_run) {     if (!dry_run) {
       if (toplevel) {       if (toplevel) {
         cvm::error("Error: Feature unavailable: \"" + f->description + "\" in " + description + ".");         cvm::error("Error: " + feature_type_descr + " feature unavailable: \""
            + f->description + "\" in " + description + ".");
       } else {       } else {
         cvm::log("Feature unavailable: \"" + f->description + "\" in " + description);         cvm::log(feature_type_descr + " feature unavailable: \""
            + f->description + "\" in " + description + ".");
       }       }
     }     }
     return COLVARS_ERROR;     return COLVARS_ERROR;
Line 105
Line 165
  
   if (!toplevel && !is_dynamic(feature_id)) {   if (!toplevel && !is_dynamic(feature_id)) {
     if (!dry_run) {     if (!dry_run) {
       cvm::log("Non-dynamic feature : \"" + f->description       cvm::log(feature_type_descr + " feature \"" + f->description
         + "\" in " + description + " may not be enabled as a dependency.\n");         + "\" may not be enabled as a dependency in " + description + ".\n");
     }     }
     return COLVARS_ERROR;     return COLVARS_ERROR;
   }   }
  
   // 1) enforce exclusions   // 1) enforce exclusions
    // reminder: exclusions must be mutual for this to work
   for (i=0; i<f->requires_exclude.size(); i++) {   for (i=0; i<f->requires_exclude.size(); i++) {
     feature *g = features()[f->requires_exclude[i]];     feature *g = features()[f->requires_exclude[i]];
     if (cvm::debug())     if (cvm::debug())
       cvm::log(f->description + " requires exclude " + g->description);       cvm::log(f->description + " requires exclude " + g->description);
     if (is_enabled(f->requires_exclude[i])) {     if (is_enabled(f->requires_exclude[i])) {
       if (!dry_run) {       if (!dry_run) {
         cvm::log("Features \"" + f->description + "\" is incompatible with \""         cvm::log("Feature \"" + f->description + "\" is incompatible with \""
         + g->description + "\" in " + description);         + g->description + "\" in " + description + ".");
         if (toplevel) {         if (toplevel) {
           cvm::error("Error: Failed dependency in " + description + ".");           cvm::error("Error: Failed dependency in " + description + ".");
         }         }
Line 156
Line 217
       res = enable(g, true, false);  // see if available       res = enable(g, true, false);  // see if available
       if (res == COLVARS_OK) {       if (res == COLVARS_OK) {
         ok = true;         ok = true;
         if (!dry_run) enable(g, false, false); // Require again, for real         if (!dry_run) {
            enable(g, false, false); // Require again, for real
            fs->alternate_refs.push_back(g); // We remember we enabled this
            // so we can free it if this feature gets disabled
          }
         break;         break;
       }       }
     }     }
Line 182
Line 247
   }   }
  
   // 4) solve deps in children   // 4) solve deps in children
    // if the object is inactive, we solve but do not enable: will be enabled
    // when the object becomes active
   for (i=0; i<f->requires_children.size(); i++) {   for (i=0; i<f->requires_children.size(); i++) {
     int g = f->requires_children[i];     int g = f->requires_children[i];
     for (j=0; j<children.size(); j++) {     for (j=0; j<children.size(); j++) {
       cvm::increase_depth();       cvm::increase_depth();
       res = children[j]->enable(g, dry_run, false);       res = children[j]->enable(g, dry_run || !is_enabled(), false);
       cvm::decrease_depth();       cvm::decrease_depth();
       if (res != COLVARS_OK) {       if (res != COLVARS_OK) {
         if (!dry_run) {         if (!dry_run) {
Line 198
Line 265
         return res;         return res;
       }       }
     }     }
     // If we've just touched the features of child objects, refresh them   }
     if (!dry_run && f->requires_children.size() != 0) { 
    // Actually enable feature only once everything checks out
    if (!dry_run) {
      fs->enabled = true;
      // This should be the only reference
      if (!toplevel) fs->ref_count = 1;
      if (feature_id == 0) {
        // Waking up this object, enable all deps in children
        restore_children_deps();
      }
      do_feature_side_effects(feature_id);
      if (cvm::debug())
        cvm::log("DEPS: feature \"" + f->description + "\" in "
          + description + " enabled, ref_count = 1.");
    }
    return COLVARS_OK;
  }
  
  
  int colvardeps::disable(int feature_id) {
    size_t i, j;
    feature *f = features()[feature_id];
    feature_state *fs = &feature_states[feature_id];
  
    if (cvm::debug()) cvm::log("DEPS: disabling feature \""
        + f->description + "\" in " + description);
  
    if (fs->enabled == false) {
      return COLVARS_OK;
    }
  
    if (fs->ref_count > 1) {
      cvm::error("Error: cannot disable feature \"" + f->description
       + "\" in " + description + " because of " + cvm::to_str(fs->ref_count-1)
       + " remaining references.\n" );
      return COLVARS_ERROR;
    }
  
    // internal deps (self)
    for (i=0; i<f->requires_self.size(); i++) {
      if (cvm::debug()) cvm::log("DEPS: dereferencing self "
        + features()[f->requires_self[i]]->description);
      decr_ref_count(f->requires_self[i]);
    }
  
    // alternates
    for (i=0; i<fs->alternate_refs.size(); i++) {
      if (cvm::debug()) cvm::log("DEPS: dereferencing alt "
        + features()[fs->alternate_refs[i]]->description);
      decr_ref_count(fs->alternate_refs[i]);
    }
    // Forget these, now that they are dereferenced
    fs->alternate_refs.clear();
  
    // deps in children
    // except if the object is inactive, then children dependencies
    // have already been dereferenced by this function
    // (or never referenced if feature was enabled while the object
    // was inactive)
    if (is_enabled()) {
      for (i=0; i<f->requires_children.size(); i++) {
        int g = f->requires_children[i];
       for (j=0; j<children.size(); j++) {       for (j=0; j<children.size(); j++) {
         children[j]->refresh_deps();         cvm::increase_depth();
          if (cvm::debug()) cvm::log("DEPS: dereferencing children's "
            + children[j]->features()[g]->description);
          children[j]->decr_ref_count(g);
          cvm::decrease_depth();
       }       }
     }     }
   }   }
  
   // Actually enable feature only once everything checks out   fs->enabled = false;
   if (!dry_run) fs->enabled = true;   fs->ref_count = 0;
    if (feature_id == 0) {
      // Putting this object to sleep
      free_children_deps();
    }
   return COLVARS_OK;   return COLVARS_OK;
 } }
  
  int colvardeps::decr_ref_count(int feature_id) {
    int &rc = feature_states[feature_id].ref_count;
    feature *f = features()[feature_id];
  
    if (cvm::debug())
        cvm::log("DEPS: decreasing reference count of \"" + f->description
       + "\" in " + description + ".\n");
  
    if (rc <= 0) {
      cvm::error("Error: cannot decrease reference count of feature \"" + f->description +  "\" in " + description + ", which is " + cvm::to_str(rc) + ".\n");
      return COLVARS_ERROR;
    }
  
    rc--;
    if (rc == 0 && f->is_dynamic()) {
      // we can auto-disable this feature
      if (cvm::debug())
        cvm::log("DEPS will now auto-disable dynamic feature \"" + f->description
       + "\" in " + description + ".\n");
      disable(feature_id);
    }
    return COLVARS_OK;
  }
  
 //     disable() { 
 // 
 //       // we need refs to parents to walk up the deps tree! 
 //       // or refresh 
 //     } 
 void colvardeps::init_feature(int feature_id, const char *description, feature_type type) { void colvardeps::init_feature(int feature_id, const char *description, feature_type type) {
   features()[feature_id]->description = description;   features()[feature_id]->description = description;
   features()[feature_id]->type = type;   features()[feature_id]->type = type;
Line 246
Line 400
     init_feature(f_cvb_active, "active", f_type_dynamic);     init_feature(f_cvb_active, "active", f_type_dynamic);
     f_req_children(f_cvb_active, f_cv_active);     f_req_children(f_cvb_active, f_cv_active);
  
      init_feature(f_cvb_awake, "awake", f_type_static);
      f_req_self(f_cvb_awake, f_cvb_active);
  
     init_feature(f_cvb_apply_force, "apply force", f_type_user);     init_feature(f_cvb_apply_force, "apply force", f_type_user);
     f_req_children(f_cvb_apply_force, f_cv_gradient);     f_req_children(f_cvb_apply_force, f_cv_gradient);
  
Line 282
Line 439
     // Colvars must be either a linear combination, or scalar (and polynomial) or scripted     // Colvars must be either a linear combination, or scalar (and polynomial) or scripted
     f_req_alt3(f_cv_active, f_cv_scalar, f_cv_linear, f_cv_scripted);     f_req_alt3(f_cv_active, f_cv_scalar, f_cv_linear, f_cv_scripted);
  
      init_feature(f_cv_awake, "awake", f_type_static);
      f_req_self(f_cv_awake, f_cv_active);
  
     init_feature(f_cv_gradient, "gradient", f_type_dynamic);     init_feature(f_cv_gradient, "gradient", f_type_dynamic);
     f_req_children(f_cv_gradient, f_cvc_gradient);     f_req_children(f_cv_gradient, f_cvc_gradient);
  
     init_feature(f_cv_collect_gradient, "collect gradient", f_type_dynamic);     init_feature(f_cv_collect_gradient, "collect gradient", f_type_dynamic);
     f_req_self(f_cv_collect_gradient, f_cv_gradient);     f_req_self(f_cv_collect_gradient, f_cv_gradient);
     f_req_self(f_cv_collect_gradient, f_cv_scalar);     f_req_self(f_cv_collect_gradient, f_cv_scalar);
      // The following exlusion could be lifted by implementing the feature
      f_req_exclude(f_cv_collect_gradient, f_cv_scripted);
  
     init_feature(f_cv_fdiff_velocity, "fdiff_velocity", f_type_dynamic);     init_feature(f_cv_fdiff_velocity, "fdiff_velocity", f_type_dynamic);
  
Line 359
Line 521
     init_feature(f_cv_scalar, "scalar", f_type_static);     init_feature(f_cv_scalar, "scalar", f_type_static);
     init_feature(f_cv_linear, "linear", f_type_static);     init_feature(f_cv_linear, "linear", f_type_static);
     init_feature(f_cv_homogeneous, "homogeneous", f_type_static);     init_feature(f_cv_homogeneous, "homogeneous", f_type_static);
  
      // because total forces are obtained from the previous time step,
      // we cannot (currently) have colvar values and total forces for the same timestep
      init_feature(f_cv_multiple_ts, "multiple timestep colvar");
      f_req_exclude(f_cv_multiple_ts, f_cv_total_force_calc);
   }   }
  
   // Initialize feature_states for each instance   // Initialize feature_states for each instance
Line 467
Line 634
     init_feature(f_ag_center, "translational fit", f_type_static);     init_feature(f_ag_center, "translational fit", f_type_static);
     init_feature(f_ag_rotate, "rotational fit", f_type_static);     init_feature(f_ag_rotate, "rotational fit", f_type_static);
     init_feature(f_ag_fitting_group, "reference positions group", f_type_static);     init_feature(f_ag_fitting_group, "reference positions group", f_type_static);
     init_feature(f_ag_fit_gradient_group, "fit gradient for main group", f_type_static);     init_feature(f_ag_fit_gradients, "fit gradients", f_type_user);
     init_feature(f_ag_fit_gradient_ref, "fit gradient for reference group", f_type_static); 
     init_feature(f_ag_atom_forces, "atomic forces", f_type_dynamic);     init_feature(f_ag_atom_forces, "atomic forces", f_type_dynamic);
  
     // parallel calculation implies that we have at least a scalable center of mass,     // parallel calculation implies that we have at least a scalable center of mass,
Line 496
Line 662
   feature_states[f_ag_scalable_com].available = false;   feature_states[f_ag_scalable_com].available = false;
   // TODO make f_ag_scalable depend on f_ag_scalable_com (or something else)   // TODO make f_ag_scalable depend on f_ag_scalable_com (or something else)
   feature_states[f_ag_scalable].available = true;   feature_states[f_ag_scalable].available = true;
    feature_states[f_ag_fit_gradients].available = true;
 } }
  
  
 void colvardeps::print_state() { void colvardeps::print_state() {
   size_t i;   size_t i;
   cvm::log("Enabled features of " + description);   cvm::log("Enabled features of \"" + description + "\" (with reference count)");
   for (i = 0; i < feature_states.size(); i++) {   for (i = 0; i < feature_states.size(); i++) {
     if (feature_states[i].enabled)     if (is_enabled(i))
       cvm::log("- " + features()[i]->description);       cvm::log("- " + features()[i]->description + " ("
          + cvm::to_str(feature_states[i].ref_count) + ")");
   }   }
   for (i=0; i<children.size(); i++) {   for (i=0; i<children.size(); i++) {
     cvm::log("* child " + cvm::to_str(i+1));     cvm::log("* child " + cvm::to_str(i+1));


Legend:
Removed in v.1.6 
changed lines
 Added in v.1.7



Made by using version 1.53 of cvs2html