00001
00002
00003
00004
00005
00006
00007 #ifndef IMPMISC_WORM_LIKE_CHAIN_H
00008 #define IMPMISC_WORM_LIKE_CHAIN_H
00009
00010 #include "misc_config.h"
00011 #include <IMP/UnaryFunction.h>
00012 #include <IMP/internal/constants.h>
00013 #include <IMP/internal/units.h>
00014
00015 IMPMISC_BEGIN_NAMESPACE
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 class WormLikeChain : public UnaryFunction
00027 {
00028 public:
00029
00030
00031
00032
00033 WormLikeChain(Float l_max, Float lp) : lmax_(l_max), lp_(lp) {
00034 IMP_USAGE_CHECK(l_max > lp, "The persistence length should be less "
00035 << "than the total length for this model");
00036 }
00037
00038 IMP_UNARY_FUNCTION(WormLikeChain);
00039
00040 private:
00041 unit::Piconewton cderiv(unit::Angstrom l) const {
00042 unit::Piconewton pn= IMP::internal::KB*IMP::internal::DEFAULT_TEMPERATURE
00043 /lp_*(.25/ square(1.0-(l/lmax_))
00044 -.25+(l/lmax_));
00045 return pn;
00046 }
00047
00048 unit::Picojoule eval(unit::Angstrom m) const {
00049 unit::Picojoule J
00050 = IMP::internal::KB *
00051 IMP::internal::DEFAULT_TEMPERATURE/lp_*(.25*square(lmax_)
00052 /(lmax_-m)
00053 -m*.25
00054 +.5*square(m)
00055 /lmax_);
00056 return J;
00057 }
00058
00059 unit::Angstrom cutoff() const {
00060 return .99*lmax_;
00061 }
00062
00063 unit::Angstrom lmax_, lp_;
00064 };
00065
00066 #ifndef IMP_DOXYGEN
00067 inline double WormLikeChain::evaluate(double v) const {
00068 return evaluate_with_derivative(v).first;
00069 }
00070
00071 inline DerivativePair WormLikeChain::evaluate_with_derivative(double v) const {
00072 static const unit::Picojoule zero=eval(unit::Angstrom(0));
00073 unit::Angstrom l(v);
00074 if (l < unit::Angstrom(0)) l=unit::Angstrom(0);
00075 unit::Picojoule ret;
00076
00077 unit::Piconewton doubled;
00078 if (l < cutoff()) {
00079 ret= (eval(l) - zero);
00080 doubled= cderiv(l);
00081 } else {
00082 unit::Picojoule springterm=(l-cutoff())*cderiv(cutoff());
00083 ret= (eval(cutoff())+ springterm -zero);
00084 doubled= cderiv(cutoff());
00085 IMP_LOG(VERBOSE, "Overstretched " << cderiv(cutoff()) << " " << doubled
00086 << " " << l << " " << lmax_ << " " << cutoff()
00087 << std::endl);
00088 }
00089 unit::YoctoKilocalorie zc= convert_J_to_Cal(ret);
00090 double value=(zc*unit::ATOMS_PER_MOL).get_value();
00091
00092
00093 unit::YoctoKilocaloriePerAngstrom du= unit::convert_J_to_Cal(doubled);
00094
00095 double deriv = (du*unit::ATOMS_PER_MOL).get_value();
00096
00097 return std::make_pair(value, deriv);
00098 }
00099
00100 inline void WormLikeChain::do_show(std::ostream &out) const {
00101 out << "params " << lmax_ << " " << lp_ << std::endl;
00102 }
00103 #endif
00104
00105 IMPMISC_END_NAMESPACE
00106
00107 #endif