double get_time_step(const ::npctransport_proto::Assignment& config, double max_trans_relative_to_radius) { double time_step_factor= config.time_step_factor().value(); double max_d_factor=1; double min_radius=std::numeric_limits<double>::max(); double max_k=0; UPDATE_MAX(k, config.interaction_k); UPDATE_MAX(k, config.backbone_k); // TODO: is this valid for harmonic k? UPDATE_MAX(k, config.nonspecific_k); UPDATE_MAX(k, config.excluded_volume_k); double max_k_factor=1; for ( int i=0; i< config.fgs_size(); ++i) { UPDATE_MAX(d_factor, config.fgs(i).d_factor); UPDATE_MIN(radius, config.fgs(i).radius); UPDATE_MAX(k_factor, config.fgs(i).interaction_k_factor); } for ( int i=0; i< config.floaters_size(); ++i) { UPDATE_MAX(d_factor, config.floaters(i).d_factor); UPDATE_MIN(radius, config.floaters(i).radius); UPDATE_MAX(k_factor, config.floaters(i).interaction_k_factor); } for ( int i=0; i< config.interactions_size(); ++i) { if (config.interactions(i).has_interaction_k()) { UPDATE_MAX(k_factor, config.interactions(i).interaction_k); } } return get_time_step(max_d_factor, max_k*max_k_factor, min_radius, max_trans_relative_to_radius, time_step_factor); }
double get_close_pairs_range(const ::npctransport_proto::Assignment& config) { double max_range= config.interaction_range().value(); UPDATE_MAX(range, config.nonspecific_range); double max_range_factor= 1; for ( int i=0; i< config.fgs_size(); ++i) { UPDATE_MAX(range_factor, config.fgs(i).interaction_range_factor); } for ( int i=0; i< config.floaters_size(); ++i) { UPDATE_MAX(range_factor, config.floaters(i).interaction_range_factor); } for ( int i=0; i< config.interactions_size(); ++i) { if (config.interactions(i).has_interaction_range()) { UPDATE_MAX(range, config.interactions(i).interaction_range); } } return get_close_pairs_range(max_range, max_range_factor); }
double get_time_step(const ::npctransport_proto::Assignment& a, double max_trans_relative_to_radius) { // NOTE: this is not a tight bound - a tight bound would involve // computing time step for each interactions (factored by relevant // constants and accounting for particle radii and interaction range // / k). So this is a conservative time step choice in that respect. double time_step_factor = a.time_step_factor().value(); double max_d_factor = 1.0; double min_radius = std::numeric_limits<double>::max(); // in A double min_range = std::numeric_limits<double>::max(); // in A double max_k = 0.0; // in kcal/mol/A UPDATE_MAX(k, a.backbone_k); // TODO: is this valid for harmonic k? if(a.nonspecific_range().value()>0.0 && a.nonspecific_k().value()>0.0) { UPDATE_MAX(k, a.nonspecific_k); UPDATE_MIN(range, a.nonspecific_range); } UPDATE_MAX(k, a.excluded_volume_k); for (int i = 0; i < a.fgs_size(); ++i) { UPDATE_MAX(d_factor, a.fgs(i).d_factor); UPDATE_MIN(radius, a.fgs(i).radius); } for (int i = 0; i < a.floaters_size(); ++i) { UPDATE_MAX(d_factor, a.floaters(i).d_factor); UPDATE_MIN(radius, a.floaters(i).radius); } double base_k = a.interaction_k().value(); double base_range = a.interaction_range().value(); // go over all interaction and compute their maximal k (in kcal/mol/A) // and minimum range (in A) for (int i = 0; i < a.interactions_size(); ++i) { double k=base_k; double range=base_range; if (a.interactions(i).has_interaction_k()) { k=a.interactions(i).interaction_k().value(); } if (a.interactions(i).has_interaction_range()) { range=a.interactions(i).interaction_range().value(); } // factor k and range + retrieve particles radii std::string type0=a.interactions(i).type0(); std::string type1=a.interactions(i).type1(); double R0(-1.0); double R1(-1.0); bool is_found0= false; bool is_found1= false; for(int ii=0; ii<a.floaters_size(); ii++){ if(a.floaters(ii).type()==type0){ if(a.floaters(ii).interactions().value()==0){ range=0.0; // skip continue; } k*=a.floaters(ii).interaction_k_factor().value(); range*=a.floaters(ii).interaction_range_factor().value(); R0=a.floaters(ii).radius().value(); is_found0= true; } if(a.floaters(ii).type()==type1){ if(a.floaters(ii).interactions().value()==0){ range=0.0; // skip continue; } k*=a.floaters(ii).interaction_k_factor().value(); range*=a.floaters(ii).interaction_range_factor().value(); R1=a.floaters(ii).radius().value(); is_found1= true; } } for(int ii=0; ii<a.fgs_size(); ii++){ if(is_fg_type_match(type0, a.fgs(ii))){ if(a.fgs(ii).interactions().value()==0){ range=0.0; // skip continue; } k*=a.fgs(ii).interaction_k_factor().value(); range*=a.fgs(ii).interaction_range_factor().value(); R0=a.fgs(ii).radius().value(); is_found0= true; } if(is_fg_type_match(type1, a.fgs(ii))){ if(a.fgs(ii).interactions().value()==0){ range=0.0; // skip continue; } k*=a.fgs(ii).interaction_k_factor().value(); range*=a.fgs(ii).interaction_range_factor().value(); R1=a.fgs(ii).radius().value(); is_found1= true; } } if(!is_found0 || !is_found1){ IMP_LOG(TERSE, "get_time_step() - ignoring interaction " << type0 << "-" << type1 << " since no particles of one these types are defined" << std::endl); continue; } // compute skewed range if needed bool is_orientational=false; if(a.interactions(i).has_range_sigma0_deg() && a.interactions(i).has_range_sigma1_deg()) { if(a.interactions(i).range_sigma0_deg().value()!=0.0 && a.interactions(i).range_sigma1_deg().value()!=0.0) { is_orientational=true; } } if(is_orientational && range > 0.0 && is_found0 && is_found1){ IMP_USAGE_CHECK(R0>0.0 && R1>0.0, "R0 or R1 could not be found for type " << type0 << " or type " << type1 << std::endl); k*=0.5*range; // the maximal force for this interction const double pi = 3.1415926535897; double range_sigma0_rad=a.interactions(i).range_sigma0_deg().value()*pi/180.0; double range_sigma1_rad=a.interactions(i).range_sigma1_deg().value()*pi/180.0; double chord0=2*R0*std::sin(range_sigma0_rad/2.0); double chord1=2*R1*std::sin(range_sigma1_rad/2.0); double min_chord=std::min(chord0,chord1); range=std::min(range, min_chord); } // if is_orientation if(range>0.0 && k>0.0) { max_k=std::max(max_k, k); min_range=std::min(min_range, range); } } // for interactions(i) IMP_LOG(VERBOSE, "get_time_step(): " << " max_d_factor " << max_d_factor << " max-k " << max_k << " min-range " << min_range << " max-trans-relative-to-R " << max_trans_relative_to_radius << " time-step-factor " << time_step_factor << std::endl); double dT_fs= get_time_step(max_d_factor, max_k, min_radius, min_range, max_trans_relative_to_radius, time_step_factor); IMP_LOG(VERBOSE, "dT = " << dT_fs << " [fs]" << std::endl); return dT_fs; }