pele
Python energy landscape explorer
|
00001 #ifndef _PELE_HS_WCA_H 00002 #define _PELE_HS_WCA_H 00003 00004 #include <algorithm> 00005 #include <memory> 00006 00007 #include "atomlist_potential.h" 00008 #include "cell_list_potential.h" 00009 #include "distance.h" 00010 #include "frozen_atoms.h" 00011 #include "meta_pow.h" 00012 #include "simple_pairwise_ilist.h" 00013 #include "simple_pairwise_potential.h" 00014 00015 namespace pele { 00016 00038 struct sf_HS_WCA_interaction { 00039 const double m_eps; 00040 const double m_alpha; 00041 const Array<double> m_radii; 00042 const double m_delta; 00043 const double m_prfac; 00044 sf_HS_WCA_interaction(const double eps, const double alpha, const Array<double> radii, const double delta=1e-10) 00045 : m_eps(eps), 00046 m_alpha(alpha), 00047 m_radii(radii.copy()), 00048 m_delta(delta), 00049 m_prfac(std::pow((2 * m_alpha + m_alpha * m_alpha), 3) / std::sqrt(2)) 00050 {} 00051 double energy(const double r2, const size_t atomi, const size_t atomj) const 00052 { 00053 const double r_H = m_radii[atomi] + m_radii[atomj]; 00054 const double r_S = (1 + m_alpha) * r_H; 00055 const double r_S2 = pos_int_pow<2>(r_S); 00056 if (r2 > r_S2) { 00057 // Energy: separation larger than soft shell. 00058 return 0; 00059 } 00060 // r2 <= r_S2: we have to compute the remaining quantities. 00061 const double r_X = r_H + m_delta; 00062 const double r_X2 = pos_int_pow<2>(r_X); 00063 const double r_H2 = pos_int_pow<2>(r_H); 00064 if (r2 > r_X2) { 00065 // Energy: separation in fHS-WCA regime. 00066 const double dr = r2 - r_H2; 00067 const double ir2 = 1.0 / (dr * dr); 00068 const double ir6 = ir2 * ir2 * ir2; 00069 const double ir12 = ir6 * ir6; 00070 const double C3 = m_prfac * r_H2 * r_H2 * r_H2; 00071 const double C6 = C3 * C3; 00072 const double C12 = C6 * C6; 00073 return std::max<double>(0, 4. * m_eps * (-C6 * ir6 + C12 * ir12) + m_eps); 00074 } 00075 // r2 <= r_X2 00076 // Energy: separation in linear regime. 00077 const double dr = r_X2 - r_H2; 00078 const double ir2 = 1.0 / (dr * dr); 00079 const double ir6 = ir2 * ir2 * ir2; 00080 const double ir12 = ir6 * ir6; 00081 const double C3 = m_prfac * r_H2 * r_H2 * r_H2; 00082 const double C6 = C3 * C3; 00083 const double C12 = C6 * C6; 00084 const double EX = std::max<double>(0, 4. * m_eps * (-C6 * ir6 + C12 * ir12) + m_eps); 00085 const double GX = (m_eps * (- 48. * C6 * ir6 + 96. * C12 * ir12) / dr) * (-r_X); 00086 return EX + GX * (std::sqrt(r2) - r_X); 00087 } 00088 double energy_gradient(const double r2, double *const gij, const size_t atomi, const size_t atomj) const 00089 { 00090 const double r_H = m_radii[atomi] + m_radii[atomj]; 00091 const double r_S = (1 + m_alpha) * r_H; 00092 const double r_S2 = pos_int_pow<2>(r_S); 00093 if (r2 > r_S2) { 00094 // Energy, gradient: separation larger than soft shell. 00095 *gij = 0; 00096 return 0; 00097 } 00098 // r2 <= r_S2: we have to compute the remaining quantities. 00099 const double r_X = r_H + m_delta; 00100 const double r_X2 = pos_int_pow<2>(r_X); 00101 const double r_H2 = pos_int_pow<2>(r_H); 00102 if (r2 > r_X2) { 00103 // Energy, gradient: separation in fHS-WCA regime. 00104 const double dr = r2 - r_H2; 00105 const double ir2 = 1.0 / (dr * dr); 00106 const double ir6 = ir2 * ir2 * ir2; 00107 const double ir12 = ir6 * ir6; 00108 const double C3 = m_prfac * r_H2 * r_H2 * r_H2; 00109 const double C6 = C3 * C3; 00110 const double C12 = C6 * C6; 00111 *gij = m_eps * (- 48. * C6 * ir6 + 96. * C12 * ir12) / dr; 00112 return std::max<double>(0, 4. * m_eps * (-C6 * ir6 + C12 * ir12) + m_eps); 00113 } 00114 // r2 <= r_X2 00115 // Energy, gradient: separation in linear regime. 00116 const double dr = r_X2 - r_H2; 00117 const double ir2 = 1.0 / (dr * dr); 00118 const double ir6 = ir2 * ir2 * ir2; 00119 const double ir12 = ir6 * ir6; 00120 const double C3 = m_prfac * r_H2 * r_H2 * r_H2; 00121 const double C6 = C3 * C3; 00122 const double C12 = C6 * C6; 00123 const double EX = std::max<double>(0, 4. * m_eps * (-C6 * ir6 + C12 * ir12) + m_eps); 00124 const double GX = (m_eps * (- 48. * C6 * ir6 + 96. * C12 * ir12) / dr) * (-r_X); 00125 *gij = GX / (-r_X); 00126 return EX + GX * (std::sqrt(r2) - r_X); 00127 } 00128 double energy_gradient_hessian(const double r2, double *const gij, double *const hij, const size_t atomi, const size_t atomj) const 00129 { 00130 const double r_H = m_radii[atomi] + m_radii[atomj]; 00131 const double r_S = (1 + m_alpha) * r_H; 00132 const double r_S2 = pos_int_pow<2>(r_S); 00133 if (r2 > r_S2) { 00134 // Energy, gradient, hessian: separation larger than soft shell. 00135 *gij = 0; 00136 *hij = 0; 00137 return 0; 00138 } 00139 // r2 <= r_S2: we have to compute the remaining quantities. 00140 const double r_X = r_H + m_delta; 00141 const double r_X2 = pos_int_pow<2>(r_X); 00142 const double r_H2 = pos_int_pow<2>(r_H); 00143 if (r2 > r_X2) { 00144 // Energy, gradient, hessian: separation in fHS-WCA regime. 00145 const double dr = r2 - r_H2; 00146 const double ir2 = 1.0 / (dr * dr); 00147 const double ir6 = ir2 * ir2 * ir2; 00148 const double ir12 = ir6 * ir6; 00149 const double C3 = m_prfac * r_H2 * r_H2 * r_H2; 00150 const double C6 = C3 * C3; 00151 const double C12 = C6 * C6; 00152 *gij = m_eps * (- 48. * C6 * ir6 + 96. * C12 * ir12) / dr; 00153 *hij = -*gij + m_eps * ( -672. * C6 * ir6 + 2496. * C12 * ir12) * r2 * ir2; 00154 return std::max<double>(0, 4. * m_eps * (-C6 * ir6 + C12 * ir12) + m_eps); 00155 } 00156 // r2 <= r_X2 00157 // Energy, gradient, hessian: separation in linear regime. 00158 const double dr = r_X2 - r_H2; 00159 const double ir2 = 1.0 / (dr * dr); 00160 const double ir6 = ir2 * ir2 * ir2; 00161 const double ir12 = ir6 * ir6; 00162 const double C3 = m_prfac * r_H2 * r_H2 * r_H2; 00163 const double C6 = C3 * C3; 00164 const double C12 = C6 * C6; 00165 const double EX = std::max<double>(0, 4. * m_eps * (-C6 * ir6 + C12 * ir12) + m_eps); 00166 const double GX = (m_eps * (- 48. * C6 * ir6 + 96. * C12 * ir12) / dr) * (-r_X); 00167 *gij = GX / (-r_X); 00168 *hij = 0; 00169 return EX + GX * (std::sqrt(r2) - r_X); 00170 } 00174 void evaluate_pair_potential(const double rmin, const double rmax, const size_t nr_points, const size_t atomi, const size_t atomj, std::vector<double>& x, std::vector<double>& y) const 00175 { 00176 x = std::vector<double>(nr_points, 0); 00177 y = std::vector<double>(nr_points, 0); 00178 const double rdelta = (rmax - rmin) / (nr_points - 1); 00179 for (size_t i = 0; i < nr_points; ++i) { 00180 x.at(i) = rmin + i * rdelta; 00181 y.at(i) = energy(x.at(i) * x.at(i), atomi, atomj); 00182 } 00183 } 00184 }; 00185 00191 struct HS_WCA_interaction { 00192 const double _eps; 00193 const double _sca; 00194 const double _infty; 00195 const double _prfac; 00196 const Array<double> _radii; 00197 00198 HS_WCA_interaction(const double eps, const double sca, const Array<double> radii) 00199 : _eps(eps), 00200 _sca(sca), 00201 _infty(std::pow(10.0, 50)), 00202 _prfac(std::pow((2 * _sca + _sca * _sca), 3) / std::sqrt(2)), 00203 _radii(radii.copy()) 00204 {} 00205 00206 /* calculate energy from distance squared, r0 is the hard core distance, r is the distance between the centres */ 00207 double inline energy(const double r2, const size_t atomi, const size_t atomj) const 00208 { 00209 const double r0 = _radii[atomi] + _radii[atomj]; //sum of the hard core radii 00210 const double r02 = r0 * r0; 00211 if (r2 <= r02) { 00212 return _infty; 00213 } 00214 const double coff = r0 * (1.0 + _sca); //distance at which the soft cores are at contact 00215 if (r2 > coff * coff) { 00216 return 0; 00217 } 00218 const double dr = r2 - r02; // note that dr is the difference of the squares 00219 const double ir2 = 1.0 / (dr * dr); 00220 const double ir6 = ir2 * ir2 * ir2; 00221 const double ir12 = ir6 * ir6; 00222 const double C3 = _prfac * r02 * r02 * r02; 00223 const double C6 = C3 * C3; 00224 const double C12 = C6 * C6; 00225 return compute_energy(C6, C12, ir6, ir12); 00226 } 00227 00228 /* calculate energy and gradient from distance squared, gradient is in g/|rij|, r0 is the hard core distance, r is the distance between the centres */ 00229 double inline energy_gradient(const double r2, double *const gij, const size_t atomi, const size_t atomj) const 00230 { 00231 const double r0 = _radii[atomi] + _radii[atomj]; //sum of the hard core radii 00232 const double r02 = r0 * r0; 00233 if (r2 <= r02) { 00234 *gij = _infty; 00235 return _infty; 00236 } 00237 const double coff = r0 * (1.0 + _sca); //distance at which the soft cores are at contact 00238 if (r2 > coff * coff) { 00239 *gij = 0.; 00240 return 0.; 00241 } 00242 const double dr = r2 - r02; // note that dr is the difference of the squares 00243 const double ir2 = 1.0 / (dr * dr); 00244 const double ir6 = ir2 * ir2 * ir2; 00245 const double ir12 = ir6 * ir6; 00246 const double C3 = _prfac * r02 * r02 * r02; 00247 const double C6 = C3 * C3; 00248 const double C12 = C6 * C6; 00249 *gij = _eps * (- 48. * C6 * ir6 + 96. * C12 * ir12) / dr; //this is -g/r, 1/dr because powers must be 7 and 13 00250 return compute_energy(C6, C12, ir6, ir12); 00251 } 00252 00253 double inline energy_gradient_hessian(const double r2, double *const gij, double *const hij, const size_t atomi, const size_t atomj) const 00254 { 00255 const double r0 = _radii[atomi] + _radii[atomj]; //sum of the hard core radii 00256 const double r02 = r0 * r0; 00257 if (r2 <= r02) { 00258 *gij = _infty; 00259 *hij = _infty; 00260 return _infty; 00261 } 00262 const double coff = r0 * (1.0 + _sca); //distance at which the soft cores are at contact 00263 if (r2 > coff * coff) { 00264 *gij = 0.; 00265 *hij = 0.; 00266 return 0.; 00267 } 00268 const double dr = r2 - r02; // note that dr is the difference of the squares 00269 const double ir2 = 1.0 / (dr * dr); 00270 const double ir6 = ir2 * ir2 * ir2; 00271 const double ir12 = ir6 * ir6; 00272 const double C3 = _prfac * r02 * r02 * r02; 00273 const double C6 = C3 * C3; 00274 const double C12 = C6 * C6; 00275 *gij = _eps * (- 48. * C6 * ir6 + 96. * C12 * ir12) / dr; //this is -g/r, 1/dr because powers must be 7 and 13 00276 *hij = -*gij + _eps * ( -672. * C6 * ir6 + 2496. * C12 * ir12) * r2 * ir2; 00277 return compute_energy(C6, C12, ir6, ir12); 00278 } 00279 00286 double compute_energy(const double C6, const double C12, const double ir6, const double ir12) const 00287 { 00288 return std::min<double>(_infty, std::max<double>(0, 4. * _eps * (-C6 * ir6 + C12 * ir12) + _eps)); 00289 } 00290 00294 void evaluate_pair_potential(const double rmin, const double rmax, const size_t nr_points, const size_t atomi, const size_t atomj, std::vector<double>& x, std::vector<double>& y) const 00295 { 00296 x = std::vector<double>(nr_points, 0); 00297 y = std::vector<double>(nr_points, 0); 00298 const double rdelta = (rmax - rmin) / (nr_points - 1); 00299 for (size_t i = 0; i < nr_points; ++i) { 00300 x.at(i) = rmin + i * rdelta; 00301 y.at(i) = energy(x.at(i) * x.at(i), atomi, atomj); 00302 } 00303 } 00304 }; 00305 00306 // 00307 // combine the components (interaction, looping method, distance function) into 00308 // defined classes 00309 // 00310 00314 template<size_t ndim> 00315 class HS_WCA : public SimplePairwisePotential< sf_HS_WCA_interaction, cartesian_distance<ndim> > { 00316 public: 00317 HS_WCA(double eps, double sca, Array<double> radii) 00318 : SimplePairwisePotential< sf_HS_WCA_interaction, cartesian_distance<ndim> >( 00319 std::make_shared<sf_HS_WCA_interaction>(eps, sca, radii), 00320 std::make_shared<cartesian_distance<ndim> >() 00321 ) 00322 { 00323 static_assert(ndim > 0, "illegal box dimension"); 00324 if (eps < 0) { 00325 throw std::runtime_error("HS_WCA: illegal input: eps"); 00326 } 00327 if (sca < 0) { 00328 throw std::runtime_error("HS_WCA: illegal input: sca"); 00329 } 00330 if (radii.size() == 0) { 00331 throw std::runtime_error("HS_WCA: illegal input: radii"); 00332 } 00333 } 00334 }; 00335 00339 template<size_t ndim> 00340 class HS_WCAPeriodic : public SimplePairwisePotential< sf_HS_WCA_interaction, periodic_distance<ndim> > { 00341 public: 00342 HS_WCAPeriodic(double eps, double sca, Array<double> radii, Array<double> const boxvec) 00343 : SimplePairwisePotential< sf_HS_WCA_interaction, periodic_distance<ndim> > ( 00344 std::make_shared<sf_HS_WCA_interaction>(eps, sca, radii), 00345 std::make_shared<periodic_distance<ndim> >(boxvec) 00346 ) 00347 { 00348 static_assert(ndim > 0, "illegal box dimension"); 00349 if (eps < 0) { 00350 throw std::runtime_error("HS_WCA: illegal input: eps"); 00351 } 00352 if (sca < 0) { 00353 throw std::runtime_error("HS_WCA: illegal input: sca"); 00354 } 00355 if (radii.size() == 0) { 00356 throw std::runtime_error("HS_WCA: illegal input: radii"); 00357 } 00358 if (boxvec.size() != ndim) { 00359 throw std::runtime_error("HS_WCA: illegal input: boxvec"); 00360 } 00361 } 00362 }; 00363 00364 template<size_t ndim> 00365 class HS_WCACellLists : public CellListPotential< sf_HS_WCA_interaction, cartesian_distance<ndim> > { 00366 public: 00367 HS_WCACellLists(double eps, double sca, Array<double> radii, Array<double> const boxvec, 00368 const double rcut, const double ncellx_scale = 1.0) 00369 : CellListPotential< sf_HS_WCA_interaction, cartesian_distance<ndim> >( 00370 std::make_shared<sf_HS_WCA_interaction>(eps, sca, radii), 00371 std::make_shared<cartesian_distance<ndim> >(), 00372 boxvec, rcut, ncellx_scale) 00373 { 00374 static_assert(ndim > 0, "illegal box dimension"); 00375 if (eps < 0) { 00376 throw std::runtime_error("HS_WCA: illegal input: eps"); 00377 } 00378 if (sca < 0) { 00379 throw std::runtime_error("HS_WCA: illegal input: sca"); 00380 } 00381 if (radii.size() == 0) { 00382 throw std::runtime_error("HS_WCA: illegal input: radii"); 00383 } 00384 if (boxvec.size() != ndim) { 00385 throw std::runtime_error("HS_WCA: illegal input: boxvec"); 00386 } 00387 if (rcut < 2 * (1 + sca) * *std::max_element(radii.data(), radii.data() + radii.size())) { 00388 throw std::runtime_error("HS_WCA: illegal input: rcut"); 00389 } 00390 } 00391 size_t get_nr_unique_pairs() const { return CellListPotential< sf_HS_WCA_interaction, cartesian_distance<ndim> >::m_celliter->get_nr_unique_pairs(); } 00392 }; 00393 00394 template<size_t ndim> 00395 class HS_WCAPeriodicCellLists : public CellListPotential< sf_HS_WCA_interaction, periodic_distance<ndim> > { 00396 public: 00397 HS_WCAPeriodicCellLists(double eps, double sca, Array<double> radii, Array<double> const boxvec, 00398 const double rcut, const double ncellx_scale = 1.0) 00399 : CellListPotential< sf_HS_WCA_interaction, periodic_distance<ndim> >( 00400 std::make_shared<sf_HS_WCA_interaction>(eps, sca, radii), 00401 std::make_shared<periodic_distance<ndim> >(boxvec), 00402 boxvec, rcut, ncellx_scale) 00403 { 00404 static_assert(ndim > 0, "illegal box dimension"); 00405 if (eps < 0) { 00406 throw std::runtime_error("HS_WCA: illegal input: eps"); 00407 } 00408 if (sca < 0) { 00409 throw std::runtime_error("HS_WCA: illegal input: sca"); 00410 } 00411 if (radii.size() == 0) { 00412 throw std::runtime_error("HS_WCA: illegal input: radii"); 00413 } 00414 if (boxvec.size() != ndim) { 00415 throw std::runtime_error("HS_WCA: illegal input: boxvec"); 00416 } 00417 if (rcut < 2 * (1 + sca) * *std::max_element(radii.data(), radii.data() + radii.size())) { 00418 throw std::runtime_error("HS_WCA: illegal input: rcut"); 00419 } 00420 } 00421 size_t get_nr_unique_pairs() const { return CellListPotential< sf_HS_WCA_interaction, periodic_distance<ndim> >::m_celliter->get_nr_unique_pairs(); } 00422 }; 00423 00427 template<size_t ndim> 00428 class HS_WCAFrozen : public FrozenPotentialWrapper<HS_WCA<ndim> > { 00429 public: 00430 HS_WCAFrozen(double eps, double sca, Array<double> radii, Array<double>& reference_coords, Array<size_t>& frozen_dof) 00431 : FrozenPotentialWrapper< HS_WCA<ndim> > ( std::make_shared<HS_WCA<ndim> >(eps, sca, 00432 radii), reference_coords.copy(), frozen_dof.copy()) 00433 { 00434 static_assert(ndim > 0, "illegal box dimension"); 00435 if (eps < 0) { 00436 throw std::runtime_error("HS_WCA: illegal input: eps"); 00437 } 00438 if (sca < 0) { 00439 throw std::runtime_error("HS_WCA: illegal input: sca"); 00440 } 00441 if (radii.size() == 0) { 00442 throw std::runtime_error("HS_WCA: illegal input: radii"); 00443 } 00444 if (reference_coords.size() != ndim * radii.size()) { 00445 throw std::runtime_error("HS_WCA: illegal input: coords vs. radii"); 00446 } 00447 } 00448 }; 00449 00453 template<size_t ndim> 00454 class HS_WCAPeriodicFrozen : public FrozenPotentialWrapper<HS_WCAPeriodic<ndim> > { 00455 public: 00456 HS_WCAPeriodicFrozen(double eps, double sca, Array<double> radii, 00457 Array<double> const boxvec, Array<double>& reference_coords, 00458 Array<size_t>& frozen_dof) 00459 : FrozenPotentialWrapper< HS_WCAPeriodic<ndim> > ( 00460 std::make_shared<HS_WCAPeriodic<ndim> >(eps, sca, radii, boxvec), 00461 reference_coords.copy(), frozen_dof.copy()) 00462 { 00463 static_assert(ndim > 0, "illegal box dimension"); 00464 if (eps < 0) { 00465 throw std::runtime_error("HS_WCA: illegal input: eps"); 00466 } 00467 if (sca < 0) { 00468 throw std::runtime_error("HS_WCA: illegal input: sca"); 00469 } 00470 if (radii.size() == 0) { 00471 throw std::runtime_error("HS_WCA: illegal input: radii"); 00472 } 00473 if (boxvec.size() != ndim) { 00474 throw std::runtime_error("HS_WCA: illegal input: boxvec"); 00475 } 00476 if (reference_coords.size() != ndim * radii.size()) { 00477 throw std::runtime_error("HS_WCA: illegal input: coords vs. radii"); 00478 } 00479 } 00480 }; 00481 00482 template<size_t ndim> 00483 class HS_WCACellListsFrozen : public FrozenPotentialWrapper<HS_WCACellLists<ndim> > { 00484 public: 00485 HS_WCACellListsFrozen(double eps, double sca, Array<double> radii, 00486 Array<double> const boxvec, Array<double>& reference_coords, 00487 Array<size_t>& frozen_dof, const double rcut, const double ncellx_scale = 1.0) 00488 : FrozenPotentialWrapper< HS_WCACellLists<ndim> > ( 00489 std::make_shared<HS_WCACellLists<ndim> >(eps, sca, radii, boxvec, rcut, ncellx_scale), 00490 reference_coords.copy(), frozen_dof.copy()) 00491 { 00492 static_assert(ndim > 0, "illegal box dimension"); 00493 if (eps < 0) { 00494 throw std::runtime_error("HS_WCA: illegal input: eps"); 00495 } 00496 if (sca < 0) { 00497 throw std::runtime_error("HS_WCA: illegal input: sca"); 00498 } 00499 if (radii.size() == 0) { 00500 throw std::runtime_error("HS_WCA: illegal input: radii"); 00501 } 00502 if (boxvec.size() != ndim) { 00503 throw std::runtime_error("HS_WCA: illegal input: boxvec"); 00504 } 00505 if (reference_coords.size() != ndim * radii.size()) { 00506 throw std::runtime_error("HS_WCA: illegal input: coords vs. radii"); 00507 } 00508 if (rcut < 2 * (1 + sca) * *std::max_element(radii.data(), radii.data() + radii.size())) { 00509 throw std::runtime_error("HS_WCA: illegal input: rcut"); 00510 } 00511 } 00512 }; 00513 00514 template<size_t ndim> 00515 class HS_WCAPeriodicCellListsFrozen : public FrozenPotentialWrapper<HS_WCAPeriodicCellLists<ndim> > { 00516 public: 00517 HS_WCAPeriodicCellListsFrozen(double eps, double sca, Array<double> radii, 00518 Array<double> const boxvec, Array<double>& reference_coords, 00519 Array<size_t>& frozen_dof, const double rcut, const double ncellx_scale = 1.0) 00520 : FrozenPotentialWrapper< HS_WCAPeriodicCellLists<ndim> > ( 00521 std::make_shared<HS_WCAPeriodicCellLists<ndim> >(eps, sca, radii, boxvec, rcut, ncellx_scale), 00522 reference_coords.copy(), frozen_dof.copy()) 00523 { 00524 static_assert(ndim > 0, "illegal box dimension"); 00525 if (eps < 0) { 00526 throw std::runtime_error("HS_WCA: illegal input: eps"); 00527 } 00528 if (sca < 0) { 00529 throw std::runtime_error("HS_WCA: illegal input: sca"); 00530 } 00531 if (radii.size() == 0) { 00532 throw std::runtime_error("HS_WCA: illegal input: radii"); 00533 } 00534 if (boxvec.size() != ndim) { 00535 throw std::runtime_error("HS_WCA: illegal input: boxvec"); 00536 } 00537 if (reference_coords.size() != ndim * radii.size()) { 00538 throw std::runtime_error("HS_WCA: illegal input: coords vs. radii"); 00539 } 00540 if (rcut < 2 * (1 + sca) * *std::max_element(radii.data(), radii.data() + radii.size())) { 00541 throw std::runtime_error("HS_WCA: illegal input: rcut"); 00542 } 00543 } 00544 }; 00545 00549 class HS_WCANeighborList : public SimplePairwiseNeighborList< sf_HS_WCA_interaction > { 00550 public: 00551 HS_WCANeighborList(Array<size_t> & ilist, double eps, double sca, Array<double> radii) 00552 : SimplePairwiseNeighborList< sf_HS_WCA_interaction > ( 00553 std::make_shared<sf_HS_WCA_interaction>(eps, sca, radii), ilist) 00554 { 00555 if (eps < 0) { 00556 throw std::runtime_error("HS_WCA: illegal input: eps"); 00557 } 00558 if (sca < 0) { 00559 throw std::runtime_error("HS_WCA: illegal input: sca"); 00560 } 00561 if (radii.size() == 0) { 00562 throw std::runtime_error("HS_WCA: illegal input: radii"); 00563 } 00564 } 00565 }; 00566 00567 } //namespace pele 00568 #endif //#ifndef _PELE_HS_WCA_H