| [0b990d] | 1 | //
 | 
|---|
 | 2 | // coor.cc
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // Copyright (C) 1996 Limit Point Systems, Inc.
 | 
|---|
 | 5 | //
 | 
|---|
 | 6 | // Author: Curtis Janssen <cljanss@limitpt.com>
 | 
|---|
 | 7 | // Maintainer: LPS
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // This file is part of the SC Toolkit.
 | 
|---|
 | 10 | //
 | 
|---|
 | 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
 | 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
 | 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
 | 14 | // any later version.
 | 
|---|
 | 15 | //
 | 
|---|
 | 16 | // The SC Toolkit is distributed in the hope that it will be useful,
 | 
|---|
 | 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 19 | // GNU Library General Public License for more details.
 | 
|---|
 | 20 | //
 | 
|---|
 | 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
 | 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
 | 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
 | 24 | //
 | 
|---|
 | 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
 | 26 | //
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | #ifdef __GNUC__
 | 
|---|
 | 29 | #pragma implementation
 | 
|---|
 | 30 | #endif
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | #include <set>
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | #include <util/misc/math.h>
 | 
|---|
 | 35 | 
 | 
|---|
 | 36 | #include <util/class/scexception.h>
 | 
|---|
 | 37 | #include <util/misc/formio.h>
 | 
|---|
 | 38 | #include <util/state/stateio.h>
 | 
|---|
 | 39 | #include <math/scmat/matrix.h>
 | 
|---|
 | 40 | #include <chemistry/molecule/molecule.h>
 | 
|---|
 | 41 | #include <chemistry/molecule/coor.h>
 | 
|---|
 | 42 | #include <chemistry/molecule/simple.h>
 | 
|---|
 | 43 | #include <chemistry/molecule/localdef.h>
 | 
|---|
 | 44 | 
 | 
|---|
 | 45 | #include <util/container/bitarray.h>
 | 
|---|
 | 46 | 
 | 
|---|
 | 47 | using namespace std;
 | 
|---|
 | 48 | using namespace sc;
 | 
|---|
 | 49 | 
 | 
|---|
 | 50 | ///////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 51 | // members of IntCoor
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 | double IntCoor::bohr_conv = 0.52917706;
 | 
|---|
 | 54 | double IntCoor::radian_conv = 180.0/M_PI;
 | 
|---|
 | 55 | 
 | 
|---|
 | 56 | static ClassDesc IntCoor_cd(
 | 
|---|
 | 57 |   typeid(IntCoor),"IntCoor",1,"public SavableState",
 | 
|---|
 | 58 |   0, 0, 0);
 | 
|---|
 | 59 | 
 | 
|---|
 | 60 | IntCoor::IntCoor(const char *re):
 | 
|---|
 | 61 |   label_(0), value_(0.0)
 | 
|---|
 | 62 | {
 | 
|---|
 | 63 |   if (!re) re = "noname";
 | 
|---|
 | 64 |   label_=new char[strlen(re)+1]; strcpy(label_,re);
 | 
|---|
 | 65 | }
 | 
|---|
 | 66 | 
 | 
|---|
 | 67 | IntCoor::IntCoor(const IntCoor& c):
 | 
|---|
 | 68 |   label_(0)
 | 
|---|
 | 69 | {
 | 
|---|
 | 70 |   value_ = c.value_;
 | 
|---|
 | 71 |   if (c.label_) label_ = strcpy(new char[strlen(c.label_)+1],c.label_);
 | 
|---|
 | 72 | }
 | 
|---|
 | 73 | 
 | 
|---|
 | 74 | IntCoor::IntCoor(const Ref<KeyVal>&keyval)
 | 
|---|
 | 75 | {
 | 
|---|
 | 76 |   label_ = keyval->pcharvalue("label");
 | 
|---|
 | 77 |   value_ = keyval->doublevalue("value");
 | 
|---|
 | 78 | 
 | 
|---|
 | 79 |   if (keyval->exists("unit")) {
 | 
|---|
 | 80 |       std::string unit(keyval->stringvalue("unit"));
 | 
|---|
 | 81 |       if (unit == "bohr") {
 | 
|---|
 | 82 |         }
 | 
|---|
 | 83 |       else if (unit == "angstrom") {
 | 
|---|
 | 84 |           value_ /= bohr_conv;
 | 
|---|
 | 85 |         }
 | 
|---|
 | 86 |       else if (unit == "radian") {
 | 
|---|
 | 87 |         }
 | 
|---|
 | 88 |       else if (unit == "degree") {
 | 
|---|
 | 89 |           value_ *= M_PI/180.0;
 | 
|---|
 | 90 |         }
 | 
|---|
 | 91 |       else {
 | 
|---|
 | 92 |         throw InputError("unrecognized unit value",
 | 
|---|
 | 93 |                          __FILE__, __LINE__,
 | 
|---|
 | 94 |                          "unit", unit.c_str(),
 | 
|---|
 | 95 |                          this->class_desc());
 | 
|---|
 | 96 |         }
 | 
|---|
 | 97 |     }
 | 
|---|
 | 98 | }
 | 
|---|
 | 99 | 
 | 
|---|
 | 100 | IntCoor::IntCoor(StateIn& si):
 | 
|---|
 | 101 |   SavableState(si)
 | 
|---|
 | 102 | {
 | 
|---|
 | 103 |   si.get(value_);
 | 
|---|
 | 104 |   si.getstring(label_);
 | 
|---|
 | 105 | }
 | 
|---|
 | 106 | 
 | 
|---|
 | 107 | IntCoor::~IntCoor()
 | 
|---|
 | 108 | {
 | 
|---|
 | 109 |   if (label_) delete[] label_;
 | 
|---|
 | 110 | }
 | 
|---|
 | 111 | 
 | 
|---|
 | 112 | void
 | 
|---|
 | 113 | IntCoor::save_data_state(StateOut& so)
 | 
|---|
 | 114 | {
 | 
|---|
 | 115 |   so.put(value_);
 | 
|---|
 | 116 |   so.putstring(label_);
 | 
|---|
 | 117 | }
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 | const char*
 | 
|---|
 | 120 | IntCoor::label() const
 | 
|---|
 | 121 | {
 | 
|---|
 | 122 |   return label_;
 | 
|---|
 | 123 | }
 | 
|---|
 | 124 | 
 | 
|---|
 | 125 | double
 | 
|---|
 | 126 | IntCoor::value() const
 | 
|---|
 | 127 | {
 | 
|---|
 | 128 |   return value_;
 | 
|---|
 | 129 | }
 | 
|---|
 | 130 | 
 | 
|---|
 | 131 | void
 | 
|---|
 | 132 | IntCoor::set_value(double v)
 | 
|---|
 | 133 | {
 | 
|---|
 | 134 |   value_ = v;
 | 
|---|
 | 135 | }
 | 
|---|
 | 136 | 
 | 
|---|
 | 137 | void
 | 
|---|
 | 138 | IntCoor::print(ostream &o) const
 | 
|---|
 | 139 | {
 | 
|---|
 | 140 |   print_details(0,o);
 | 
|---|
 | 141 | }
 | 
|---|
 | 142 | 
 | 
|---|
 | 143 | void
 | 
|---|
 | 144 | IntCoor::print_details(const Ref<Molecule> &mol, ostream& os) const
 | 
|---|
 | 145 | {
 | 
|---|
 | 146 |   os.setf(ios::fixed,ios::floatfield);
 | 
|---|
 | 147 |   os.precision(10);
 | 
|---|
 | 148 |   os.setf(ios::left,ios::adjustfield);
 | 
|---|
 | 149 |   os.width(10);
 | 
|---|
 | 150 | 
 | 
|---|
 | 151 |   os << indent
 | 
|---|
 | 152 |      << scprintf("%-5s \"%10s\" %15.10f\n",ctype(),label(),preferred_value());
 | 
|---|
 | 153 | }
 | 
|---|
 | 154 | 
 | 
|---|
 | 155 | double
 | 
|---|
 | 156 | IntCoor::preferred_value() const
 | 
|---|
 | 157 | {
 | 
|---|
 | 158 |   return value_;
 | 
|---|
 | 159 | }
 | 
|---|
 | 160 | 
 | 
|---|
 | 161 | ///////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 162 | // members of SetIntCoor
 | 
|---|
 | 163 | 
 | 
|---|
 | 164 | static ClassDesc SetIntCoor_cd(
 | 
|---|
 | 165 |   typeid(SetIntCoor),"SetIntCoor",1,"public SavableState",
 | 
|---|
 | 166 |   create<SetIntCoor>, create<SetIntCoor>, create<SetIntCoor>);
 | 
|---|
 | 167 | 
 | 
|---|
 | 168 | SetIntCoor::SetIntCoor()
 | 
|---|
 | 169 | {
 | 
|---|
 | 170 | }
 | 
|---|
 | 171 | 
 | 
|---|
 | 172 | SetIntCoor::SetIntCoor(const Ref<KeyVal>& keyval)
 | 
|---|
 | 173 | {
 | 
|---|
 | 174 |   int n = keyval->count();
 | 
|---|
 | 175 | 
 | 
|---|
 | 176 |   Ref<IntCoorGen> gen; gen << keyval->describedclassvalue("generator");
 | 
|---|
 | 177 | 
 | 
|---|
 | 178 |   if (gen.null() && !n) {
 | 
|---|
 | 179 |       throw InputError("not a vector and no generator given",
 | 
|---|
 | 180 |                        __FILE__, __LINE__,
 | 
|---|
 | 181 |                        0, 0,
 | 
|---|
 | 182 |                        class_desc());
 | 
|---|
 | 183 |     }
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 |   if (gen.nonnull()) {
 | 
|---|
 | 186 |       // Make sure that gen doesn't delete me before my reference
 | 
|---|
 | 187 |       // count gets incremented.
 | 
|---|
 | 188 |       this->reference();
 | 
|---|
 | 189 |       gen->generate(this);
 | 
|---|
 | 190 |       // Now it is safe to decrement my reference count back down to zero.
 | 
|---|
 | 191 |       this->dereference();
 | 
|---|
 | 192 |     }
 | 
|---|
 | 193 | 
 | 
|---|
 | 194 |   for (int i=0; i<n; i++) {
 | 
|---|
 | 195 |       Ref<IntCoor> coori; coori << keyval->describedclassvalue(i);
 | 
|---|
 | 196 |       coor_.push_back(coori);
 | 
|---|
 | 197 |     }
 | 
|---|
 | 198 | }
 | 
|---|
 | 199 | 
 | 
|---|
 | 200 | SetIntCoor::SetIntCoor(StateIn& s):
 | 
|---|
 | 201 |   SavableState(s)
 | 
|---|
 | 202 | {
 | 
|---|
 | 203 |   int n;
 | 
|---|
 | 204 |   s.get(n);
 | 
|---|
 | 205 | 
 | 
|---|
 | 206 |   Ref<IntCoor> tmp;
 | 
|---|
 | 207 |   for (int i=0; i<n; i++) {
 | 
|---|
 | 208 |       tmp << SavableState::restore_state(s);
 | 
|---|
 | 209 |       coor_.push_back(tmp);
 | 
|---|
 | 210 |     }
 | 
|---|
 | 211 | }
 | 
|---|
 | 212 | 
 | 
|---|
 | 213 | SetIntCoor::~SetIntCoor()
 | 
|---|
 | 214 | {
 | 
|---|
 | 215 | }
 | 
|---|
 | 216 | 
 | 
|---|
 | 217 | void
 | 
|---|
 | 218 | SetIntCoor::save_data_state(StateOut& s)
 | 
|---|
 | 219 | {
 | 
|---|
 | 220 |   int n = coor_.size();
 | 
|---|
 | 221 |   s.put(n);
 | 
|---|
 | 222 | 
 | 
|---|
 | 223 |   for (int i=0; i<n; i++) {
 | 
|---|
 | 224 |       SavableState::save_state(coor_[i].pointer(),s);
 | 
|---|
 | 225 |     }
 | 
|---|
 | 226 | }
 | 
|---|
 | 227 | 
 | 
|---|
 | 228 | void
 | 
|---|
 | 229 | SetIntCoor::add(const Ref<IntCoor>& coor)
 | 
|---|
 | 230 | {
 | 
|---|
 | 231 |   coor_.push_back(coor);
 | 
|---|
 | 232 | }
 | 
|---|
 | 233 | 
 | 
|---|
 | 234 | void
 | 
|---|
 | 235 | SetIntCoor::add(const Ref<SetIntCoor>& coor)
 | 
|---|
 | 236 | {
 | 
|---|
 | 237 |   for (int i=0; i<coor->n(); i++) {
 | 
|---|
 | 238 |       coor_.push_back(coor->coor(i));
 | 
|---|
 | 239 |     }
 | 
|---|
 | 240 | }
 | 
|---|
 | 241 | 
 | 
|---|
 | 242 | void
 | 
|---|
 | 243 | SetIntCoor::pop()
 | 
|---|
 | 244 | {
 | 
|---|
 | 245 |   coor_.pop_back();
 | 
|---|
 | 246 | }
 | 
|---|
 | 247 | 
 | 
|---|
 | 248 | int
 | 
|---|
 | 249 | SetIntCoor::n() const
 | 
|---|
 | 250 | {
 | 
|---|
 | 251 |   return coor_.size();
 | 
|---|
 | 252 | }
 | 
|---|
 | 253 | 
 | 
|---|
 | 254 | Ref<IntCoor>
 | 
|---|
 | 255 | SetIntCoor::coor(int i) const
 | 
|---|
 | 256 | {
 | 
|---|
 | 257 |   return coor_[i];
 | 
|---|
 | 258 | }
 | 
|---|
 | 259 | 
 | 
|---|
 | 260 | // compute the bmatrix by finite displacements
 | 
|---|
 | 261 | void
 | 
|---|
 | 262 | SetIntCoor::fd_bmat(const Ref<Molecule>& mol,RefSCMatrix& fd_bmatrix)
 | 
|---|
 | 263 | {
 | 
|---|
 | 264 |   Ref<SCMatrixKit> kit = fd_bmatrix.kit();
 | 
|---|
 | 265 | 
 | 
|---|
 | 266 |   fd_bmatrix.assign(0.0);
 | 
|---|
 | 267 |   
 | 
|---|
 | 268 |   int i;
 | 
|---|
 | 269 |   Molecule& m = * mol.pointer();
 | 
|---|
 | 270 | 
 | 
|---|
 | 271 |   const double cart_disp = 0.01;
 | 
|---|
 | 272 | 
 | 
|---|
 | 273 |   RefSCDimension dn3(fd_bmatrix.coldim());
 | 
|---|
 | 274 |   RefSCDimension dnc(fd_bmatrix.rowdim());
 | 
|---|
 | 275 |   int n3 = dn3.n();
 | 
|---|
 | 276 |   int nc = dnc.n();
 | 
|---|
 | 277 |   RefSCVector internal(dnc,kit);
 | 
|---|
 | 278 |   RefSCVector internal_p(dnc,kit);
 | 
|---|
 | 279 |   RefSCVector internal_m(dnc,kit);
 | 
|---|
 | 280 | 
 | 
|---|
 | 281 |   // the internal coordinates
 | 
|---|
 | 282 |   update_values(mol);
 | 
|---|
 | 283 |   for (i=0; i<nc; i++) {
 | 
|---|
 | 284 |       internal(i) = coor_[i]->value();
 | 
|---|
 | 285 |     }
 | 
|---|
 | 286 | 
 | 
|---|
 | 287 |   // the finite displacement bmat
 | 
|---|
 | 288 |   for (i=0; i<n3; i++) {
 | 
|---|
 | 289 |       // the plus displacement
 | 
|---|
 | 290 |       m.r(i/3,i%3) += cart_disp;
 | 
|---|
 | 291 |       update_values(mol);
 | 
|---|
 | 292 |       int j;
 | 
|---|
 | 293 |       for (j=0; j<nc; j++) {
 | 
|---|
 | 294 |           internal_p(j) = coor_[j]->value();
 | 
|---|
 | 295 |         }
 | 
|---|
 | 296 |       // the minus displacement
 | 
|---|
 | 297 |       m.r(i/3,i%3) -= 2.0*cart_disp;
 | 
|---|
 | 298 |       update_values(mol);
 | 
|---|
 | 299 |       for (j=0; j<nc; j++) {
 | 
|---|
 | 300 |           internal_m(j) = coor_[j]->value();
 | 
|---|
 | 301 |         }
 | 
|---|
 | 302 |       // reset the cartesian coordinate to its original value
 | 
|---|
 | 303 |       m.r(i/3,i%3) += cart_disp;
 | 
|---|
 | 304 | 
 | 
|---|
 | 305 |       // construct the entries in the finite displacement bmat
 | 
|---|
 | 306 |       for (j=0; j<nc; j++) {
 | 
|---|
 | 307 |           fd_bmatrix(j,i) = (internal_p(j)-internal_m(j))/(2.0*cart_disp);
 | 
|---|
 | 308 |         }
 | 
|---|
 | 309 |     }
 | 
|---|
 | 310 | }
 | 
|---|
 | 311 | 
 | 
|---|
 | 312 | void
 | 
|---|
 | 313 | SetIntCoor::bmat(const Ref<Molecule>& mol, RefSCMatrix& bmat)
 | 
|---|
 | 314 | {
 | 
|---|
 | 315 |   bmat.assign(0.0);
 | 
|---|
 | 316 | 
 | 
|---|
 | 317 |   int i, ncoor = n();
 | 
|---|
 | 318 | 
 | 
|---|
 | 319 |   RefSCVector bmatrow(bmat.coldim(),bmat.kit());
 | 
|---|
 | 320 |   // send the rows of the b matrix to each of the coordinates
 | 
|---|
 | 321 |   for (i=0; i<ncoor; i++) {
 | 
|---|
 | 322 |       bmatrow.assign(0.0);
 | 
|---|
 | 323 |       coor_[i]->bmat(mol,bmatrow);
 | 
|---|
 | 324 |       bmat.assign_row(bmatrow,i);
 | 
|---|
 | 325 |     }
 | 
|---|
 | 326 | }
 | 
|---|
 | 327 | 
 | 
|---|
 | 328 | void
 | 
|---|
 | 329 | SetIntCoor::guess_hessian(Ref<Molecule>& mol,RefSymmSCMatrix& hessian)
 | 
|---|
 | 330 | {
 | 
|---|
 | 331 |   int ncoor = hessian.n();
 | 
|---|
 | 332 | 
 | 
|---|
 | 333 |   hessian.assign(0.0);
 | 
|---|
 | 334 |   for (int i=0; i<ncoor; i++) {
 | 
|---|
 | 335 |       hessian(i,i) = coor_[i]->force_constant(mol);
 | 
|---|
 | 336 |     }
 | 
|---|
 | 337 | }
 | 
|---|
 | 338 | 
 | 
|---|
 | 339 | void
 | 
|---|
 | 340 | SetIntCoor::print_details(const Ref<Molecule> &mol, ostream& os) const
 | 
|---|
 | 341 | {
 | 
|---|
 | 342 |   int i;
 | 
|---|
 | 343 | 
 | 
|---|
 | 344 |   for(i=0; i<coor_.size(); i++) {
 | 
|---|
 | 345 |       coor_[i]->print_details(mol,os);
 | 
|---|
 | 346 |     }
 | 
|---|
 | 347 | }
 | 
|---|
 | 348 | 
 | 
|---|
 | 349 | void
 | 
|---|
 | 350 | SetIntCoor::update_values(const Ref<Molecule>&mol)
 | 
|---|
 | 351 | {
 | 
|---|
 | 352 |   for (int i=0; i<coor_.size(); i++) {
 | 
|---|
 | 353 |       coor_[i]->update_value(mol);
 | 
|---|
 | 354 |     }
 | 
|---|
 | 355 | }
 | 
|---|
 | 356 | 
 | 
|---|
 | 357 | void
 | 
|---|
 | 358 | SetIntCoor::values_to_vector(const RefSCVector&v)
 | 
|---|
 | 359 | {
 | 
|---|
 | 360 |   for (int i=0; i<coor_.size(); i++) {
 | 
|---|
 | 361 |       v(i) = coor_[i]->value();
 | 
|---|
 | 362 |     }
 | 
|---|
 | 363 | }  
 | 
|---|
 | 364 | 
 | 
|---|
 | 365 | void
 | 
|---|
 | 366 | SetIntCoor::clear()
 | 
|---|
 | 367 | {
 | 
|---|
 | 368 |   coor_.clear();
 | 
|---|
 | 369 | }
 | 
|---|
 | 370 | 
 | 
|---|
 | 371 | ///////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 372 | // members of SumIntCoor
 | 
|---|
 | 373 | 
 | 
|---|
 | 374 | static ClassDesc SumIntCoor_cd(
 | 
|---|
 | 375 |   typeid(SumIntCoor),"SumIntCoor",1,"public IntCoor",
 | 
|---|
 | 376 |   0, create<SumIntCoor>, create<SumIntCoor>);
 | 
|---|
 | 377 | 
 | 
|---|
 | 378 | SumIntCoor::SumIntCoor(const char* label):
 | 
|---|
 | 379 |   IntCoor(label)
 | 
|---|
 | 380 | {
 | 
|---|
 | 381 | }
 | 
|---|
 | 382 | 
 | 
|---|
 | 383 | SumIntCoor::SumIntCoor(const Ref<KeyVal>&keyval):
 | 
|---|
 | 384 |   IntCoor(keyval)
 | 
|---|
 | 385 | {
 | 
|---|
 | 386 |   static const char* coor = "coor";
 | 
|---|
 | 387 |   static const char* coef = "coef";
 | 
|---|
 | 388 |   int n = keyval->count(coor);
 | 
|---|
 | 389 |   int ncoef = keyval->count(coef);
 | 
|---|
 | 390 |   if (n != ncoef) {
 | 
|---|
 | 391 |     throw InputError("coor and coef do not have the same dimension",
 | 
|---|
 | 392 |                      __FILE__, __LINE__, 0, 0, class_desc());
 | 
|---|
 | 393 |     }
 | 
|---|
 | 394 |   if (!n) {
 | 
|---|
 | 395 |     throw InputError("coor and coef are zero length",
 | 
|---|
 | 396 |                      __FILE__, __LINE__, 0, 0, class_desc());
 | 
|---|
 | 397 |     }
 | 
|---|
 | 398 | 
 | 
|---|
 | 399 |   for (int i=0; i<n; i++) {
 | 
|---|
 | 400 |       double coe = keyval->doublevalue(coef,i);
 | 
|---|
 | 401 |       Ref<IntCoor> coo; coo << keyval->describedclassvalue(coor,i);
 | 
|---|
 | 402 |       add(coo,coe);
 | 
|---|
 | 403 |     }
 | 
|---|
 | 404 | }
 | 
|---|
 | 405 | 
 | 
|---|
 | 406 | SumIntCoor::SumIntCoor(StateIn&s):
 | 
|---|
 | 407 |   IntCoor(s)
 | 
|---|
 | 408 | {
 | 
|---|
 | 409 |   int n;
 | 
|---|
 | 410 |   s.get(n);
 | 
|---|
 | 411 | 
 | 
|---|
 | 412 |   coef_.resize(n);
 | 
|---|
 | 413 |   coor_.resize(n);
 | 
|---|
 | 414 |   for (int i=0; i<n; i++) {
 | 
|---|
 | 415 |       s.get(coef_[i]);
 | 
|---|
 | 416 |       coor_[i] << SavableState::restore_state(s);
 | 
|---|
 | 417 |     }
 | 
|---|
 | 418 | }
 | 
|---|
 | 419 | 
 | 
|---|
 | 420 | SumIntCoor::~SumIntCoor()
 | 
|---|
 | 421 | {
 | 
|---|
 | 422 | }
 | 
|---|
 | 423 | 
 | 
|---|
 | 424 | void
 | 
|---|
 | 425 | SumIntCoor::save_data_state(StateOut&s)
 | 
|---|
 | 426 | {
 | 
|---|
 | 427 |   int n = coef_.size();
 | 
|---|
 | 428 |   IntCoor::save_data_state(s);
 | 
|---|
 | 429 |   s.put(int(coef_.size()));
 | 
|---|
 | 430 | 
 | 
|---|
 | 431 |   for (int i=0; i<n; i++) {
 | 
|---|
 | 432 |       s.put(coef_[i]);
 | 
|---|
 | 433 |       SavableState::save_state(coor_[i].pointer(),s);
 | 
|---|
 | 434 |     }
 | 
|---|
 | 435 | }
 | 
|---|
 | 436 | 
 | 
|---|
 | 437 | int
 | 
|---|
 | 438 | SumIntCoor::n()
 | 
|---|
 | 439 | {
 | 
|---|
 | 440 |   return coef_.size();
 | 
|---|
 | 441 | }
 | 
|---|
 | 442 | 
 | 
|---|
 | 443 | void
 | 
|---|
 | 444 | SumIntCoor::add(Ref<IntCoor>&coor,double coef)
 | 
|---|
 | 445 | {
 | 
|---|
 | 446 |   // if a sum is added to a sum, unfold the nested sum
 | 
|---|
 | 447 |   SumIntCoor* scoor = dynamic_cast<SumIntCoor*>(coor.pointer());
 | 
|---|
 | 448 |   if (scoor) {
 | 
|---|
 | 449 |       int l = scoor->coor_.size();
 | 
|---|
 | 450 |       for (int i=0; i<l; i++) {
 | 
|---|
 | 451 |           add(scoor->coor_[i],coef * scoor->coef_[i]);
 | 
|---|
 | 452 |         }
 | 
|---|
 | 453 |     }
 | 
|---|
 | 454 |   else {
 | 
|---|
 | 455 |       int l = coef_.size();
 | 
|---|
 | 456 |       for (int i=0; i<l; i++) {
 | 
|---|
 | 457 |           if (coor_[i]->equivalent(coor)) {
 | 
|---|
 | 458 |               coef_[i] += coef;
 | 
|---|
 | 459 |               return;
 | 
|---|
 | 460 |             }
 | 
|---|
 | 461 |         }
 | 
|---|
 | 462 |       coef_.resize(l+1);
 | 
|---|
 | 463 |       coor_.resize(l+1);
 | 
|---|
 | 464 |       coef_[l] = coef;
 | 
|---|
 | 465 |       coor_[l] = coor;
 | 
|---|
 | 466 |     }
 | 
|---|
 | 467 | }
 | 
|---|
 | 468 | 
 | 
|---|
 | 469 | int
 | 
|---|
 | 470 | SumIntCoor::equivalent(Ref<IntCoor>&c)
 | 
|---|
 | 471 | {
 | 
|---|
 | 472 |   return 0;
 | 
|---|
 | 473 | }
 | 
|---|
 | 474 | 
 | 
|---|
 | 475 | // this normalizes and makes the biggest coordinate positive
 | 
|---|
 | 476 | void
 | 
|---|
 | 477 | SumIntCoor::normalize()
 | 
|---|
 | 478 | {
 | 
|---|
 | 479 |   int i;
 | 
|---|
 | 480 |   int n = coef_.size();
 | 
|---|
 | 481 |   double norm = 0.0;
 | 
|---|
 | 482 | 
 | 
|---|
 | 483 |   double biggest = 0.0;
 | 
|---|
 | 484 |   for (i=0; i<n; i++) {
 | 
|---|
 | 485 |       norm += coef_[i] * coef_[i];
 | 
|---|
 | 486 |       if (fabs(biggest) < fabs(coef_[i])) biggest = coef_[i];
 | 
|---|
 | 487 |     }
 | 
|---|
 | 488 |   norm = (biggest < 0.0? -1.0:1.0)/sqrt(norm);
 | 
|---|
 | 489 | 
 | 
|---|
 | 490 |   for (i=0; i<n; i++) {
 | 
|---|
 | 491 |       coef_[i] = coef_[i]*norm;
 | 
|---|
 | 492 |     }
 | 
|---|
 | 493 | }
 | 
|---|
 | 494 | 
 | 
|---|
 | 495 | double
 | 
|---|
 | 496 | SumIntCoor::preferred_value() const
 | 
|---|
 | 497 | {
 | 
|---|
 | 498 |   return value_;
 | 
|---|
 | 499 | }
 | 
|---|
 | 500 | 
 | 
|---|
 | 501 | const char*
 | 
|---|
 | 502 | SumIntCoor::ctype() const
 | 
|---|
 | 503 | {
 | 
|---|
 | 504 |   return "SUM";
 | 
|---|
 | 505 | }
 | 
|---|
 | 506 | 
 | 
|---|
 | 507 | void
 | 
|---|
 | 508 | SumIntCoor::print_details(const Ref<Molecule> &mol, ostream& os) const
 | 
|---|
 | 509 | {
 | 
|---|
 | 510 |   int initial_indent = SCFormIO::getindent(os);
 | 
|---|
 | 511 |   int i;
 | 
|---|
 | 512 | 
 | 
|---|
 | 513 |   os << indent
 | 
|---|
 | 514 |      << scprintf("%-5s %10s %14.10f\n",ctype(),
 | 
|---|
 | 515 |                  (label()?label():""), preferred_value());
 | 
|---|
 | 516 | 
 | 
|---|
 | 517 |   for(i=0; i<coor_.size(); i++) {
 | 
|---|
 | 518 |       os << incindent
 | 
|---|
 | 519 |          << indent << scprintf("%14.10f ",coef_[i]);
 | 
|---|
 | 520 | 
 | 
|---|
 | 521 |       SCFormIO::setindent(os, SCFormIO::getindent(os) + 15);
 | 
|---|
 | 522 |       os << skipnextindent;
 | 
|---|
 | 523 |       coor_[i]->print_details(mol,os);
 | 
|---|
 | 524 |       SCFormIO::setindent(os, initial_indent);
 | 
|---|
 | 525 |     }
 | 
|---|
 | 526 | }
 | 
|---|
 | 527 | 
 | 
|---|
 | 528 | // the SumIntCoor should be normalized before this is called.
 | 
|---|
 | 529 | double
 | 
|---|
 | 530 | SumIntCoor::force_constant(Ref<Molecule>&molecule)
 | 
|---|
 | 531 | {
 | 
|---|
 | 532 |   double fc = 0.0;
 | 
|---|
 | 533 |   
 | 
|---|
 | 534 |   for (int i=0; i<n(); i++) {
 | 
|---|
 | 535 |       fc += coef_[i] * coef_[i] * coor_[i]->force_constant(molecule);
 | 
|---|
 | 536 |     }
 | 
|---|
 | 537 | 
 | 
|---|
 | 538 |   return fc;
 | 
|---|
 | 539 | }
 | 
|---|
 | 540 | 
 | 
|---|
 | 541 | void
 | 
|---|
 | 542 | SumIntCoor::update_value(const Ref<Molecule>&molecule)
 | 
|---|
 | 543 | {
 | 
|---|
 | 544 |   int i, l = n();
 | 
|---|
 | 545 | 
 | 
|---|
 | 546 |   value_ = 0.0;
 | 
|---|
 | 547 |   for (i=0; i<l; i++) {
 | 
|---|
 | 548 |       coor_[i]->update_value(molecule);
 | 
|---|
 | 549 | #if OLD_BMAT
 | 
|---|
 | 550 |       if (dynamic_cast<StreSimpleCo*>(coor_[i]))
 | 
|---|
 | 551 |         value_ += coef_[i] * dynamic_cast<StreSimpleCo*>(coor_[i])->angstrom();
 | 
|---|
 | 552 |       else
 | 
|---|
 | 553 | #endif        
 | 
|---|
 | 554 |       value_ += coef_[i] * coor_[i]->value();
 | 
|---|
 | 555 |     }
 | 
|---|
 | 556 | }
 | 
|---|
 | 557 | 
 | 
|---|
 | 558 | void
 | 
|---|
 | 559 | SumIntCoor::bmat(const Ref<Molecule>&molecule,RefSCVector&bmat,double coef)
 | 
|---|
 | 560 | {
 | 
|---|
 | 561 |   int i, l = n();
 | 
|---|
 | 562 |   
 | 
|---|
 | 563 |   for (i=0; i<l; i++) {
 | 
|---|
 | 564 |       coor_[i]->bmat(molecule,bmat,coef*coef_[i]);
 | 
|---|
 | 565 |     }
 | 
|---|
 | 566 | }
 | 
|---|
 | 567 | 
 | 
|---|
 | 568 | ///////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 569 | // members of MolecularCoor
 | 
|---|
 | 570 | 
 | 
|---|
 | 571 | static ClassDesc MolecularCoor_cd(
 | 
|---|
 | 572 |   typeid(MolecularCoor),"MolecularCoor",1,"public SavableState",
 | 
|---|
 | 573 |   0, 0, 0);
 | 
|---|
 | 574 | 
 | 
|---|
 | 575 | MolecularCoor::MolecularCoor(Ref<Molecule>&mol):
 | 
|---|
 | 576 |   molecule_(mol)
 | 
|---|
 | 577 | {
 | 
|---|
 | 578 |   debug_ = 0;
 | 
|---|
 | 579 |   matrixkit_ = SCMatrixKit::default_matrixkit();
 | 
|---|
 | 580 |   dnatom3_ = new SCDimension(3*molecule_->natom());
 | 
|---|
 | 581 | }
 | 
|---|
 | 582 | 
 | 
|---|
 | 583 | MolecularCoor::MolecularCoor(const Ref<KeyVal>&keyval)
 | 
|---|
 | 584 | {
 | 
|---|
 | 585 |   molecule_ << keyval->describedclassvalue("molecule");
 | 
|---|
 | 586 | 
 | 
|---|
 | 587 |   if (molecule_.null()) {
 | 
|---|
 | 588 |       throw InputError("missing input", __FILE__, __LINE__,
 | 
|---|
 | 589 |                        "molecule", 0, class_desc());
 | 
|---|
 | 590 |     }
 | 
|---|
 | 591 | 
 | 
|---|
 | 592 |   debug_ = keyval->intvalue("debug");
 | 
|---|
 | 593 | 
 | 
|---|
 | 594 |   matrixkit_ << keyval->describedclassvalue("matrixkit");
 | 
|---|
 | 595 |   dnatom3_ << keyval->describedclassvalue("natom3");
 | 
|---|
 | 596 | 
 | 
|---|
 | 597 |   if (matrixkit_.null()) matrixkit_ = SCMatrixKit::default_matrixkit();
 | 
|---|
 | 598 | 
 | 
|---|
 | 599 |   if (dnatom3_.null()) dnatom3_ = new SCDimension(3*molecule_->natom());
 | 
|---|
 | 600 |   else if (dnatom3_->n() != 3 * molecule_->natom()) {
 | 
|---|
 | 601 |     throw InputError("natom3 given but not consistent with molecule",
 | 
|---|
 | 602 |                      __FILE__, __LINE__, "natom3", 0, class_desc());
 | 
|---|
 | 603 |     }
 | 
|---|
 | 604 | }
 | 
|---|
 | 605 | 
 | 
|---|
 | 606 | MolecularCoor::MolecularCoor(StateIn&s):
 | 
|---|
 | 607 |   SavableState(s)
 | 
|---|
 | 608 | {
 | 
|---|
 | 609 |   debug_ = 0;
 | 
|---|
 | 610 |   matrixkit_ = SCMatrixKit::default_matrixkit();
 | 
|---|
 | 611 |   molecule_ << SavableState::restore_state(s);
 | 
|---|
 | 612 |   dnatom3_ << SavableState::restore_state(s);
 | 
|---|
 | 613 | }
 | 
|---|
 | 614 | 
 | 
|---|
 | 615 | MolecularCoor::~MolecularCoor()
 | 
|---|
 | 616 | {
 | 
|---|
 | 617 | }
 | 
|---|
 | 618 | 
 | 
|---|
 | 619 | void
 | 
|---|
 | 620 | MolecularCoor::save_data_state(StateOut&s)
 | 
|---|
 | 621 | {
 | 
|---|
 | 622 |   SavableState::save_state(molecule_.pointer(),s);
 | 
|---|
 | 623 |   SavableState::save_state(dnatom3_.pointer(),s);
 | 
|---|
 | 624 | }
 | 
|---|
 | 625 | 
 | 
|---|
 | 626 | int
 | 
|---|
 | 627 | MolecularCoor::nconstrained()
 | 
|---|
 | 628 | {
 | 
|---|
 | 629 |   return 0;
 | 
|---|
 | 630 | }
 | 
|---|
 | 631 | 
 | 
|---|
 | 632 | // The default action is to never change the coordinates.
 | 
|---|
 | 633 | Ref<NonlinearTransform>
 | 
|---|
 | 634 | MolecularCoor::change_coordinates()
 | 
|---|
 | 635 | {
 | 
|---|
 | 636 |   return 0;
 | 
|---|
 | 637 | }
 | 
|---|
 | 638 | 
 | 
|---|
 | 639 | int
 | 
|---|
 | 640 | MolecularCoor::to_cartesian(const RefSCVector&internal)
 | 
|---|
 | 641 | {
 | 
|---|
 | 642 |   return to_cartesian(molecule_, internal);
 | 
|---|
 | 643 | }
 | 
|---|
 | 644 | 
 | 
|---|
 | 645 | ///////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 646 | // members of IntCoorGen
 | 
|---|
 | 647 | 
 | 
|---|
 | 648 | static ClassDesc IntCoorGen_cd(
 | 
|---|
 | 649 |   typeid(IntCoorGen),"IntCoorGen",2,"public SavableState",
 | 
|---|
 | 650 |   0, create<IntCoorGen>, create<IntCoorGen>);
 | 
|---|
 | 651 | 
 | 
|---|
 | 652 | IntCoorGen::IntCoorGen(const Ref<Molecule>& mol,
 | 
|---|
 | 653 |                        int nextra_bonds, int *extra_bonds)
 | 
|---|
 | 654 | {
 | 
|---|
 | 655 |   init_constants();
 | 
|---|
 | 656 | 
 | 
|---|
 | 657 |   molecule_ = mol;
 | 
|---|
 | 658 |   nextra_bonds_ = nextra_bonds;
 | 
|---|
 | 659 |   extra_bonds_ = extra_bonds;
 | 
|---|
 | 660 | }
 | 
|---|
 | 661 | 
 | 
|---|
 | 662 | IntCoorGen::IntCoorGen(const Ref<KeyVal>& keyval)
 | 
|---|
 | 663 | {
 | 
|---|
 | 664 |   init_constants();
 | 
|---|
 | 665 | 
 | 
|---|
 | 666 |   molecule_ << keyval->describedclassvalue("molecule");
 | 
|---|
 | 667 | 
 | 
|---|
 | 668 |   radius_scale_factor_
 | 
|---|
 | 669 |     = keyval->doublevalue("radius_scale_factor",
 | 
|---|
 | 670 |                           KeyValValuedouble(radius_scale_factor_));
 | 
|---|
 | 671 | 
 | 
|---|
 | 672 |   // degrees
 | 
|---|
 | 673 |   linear_bend_thres_
 | 
|---|
 | 674 |     = keyval->doublevalue("linear_bend_threshold",
 | 
|---|
 | 675 |                           KeyValValuedouble(linear_bend_thres_));
 | 
|---|
 | 676 | 
 | 
|---|
 | 677 |   // entered in degrees; stored as cos(theta)
 | 
|---|
 | 678 |   linear_tors_thres_
 | 
|---|
 | 679 |     = keyval->doublevalue("linear_tors_threshold",
 | 
|---|
 | 680 |                           KeyValValuedouble(linear_tors_thres_));
 | 
|---|
 | 681 | 
 | 
|---|
 | 682 |   linear_bends_
 | 
|---|
 | 683 |     = keyval->booleanvalue("linear_bend",
 | 
|---|
 | 684 |                            KeyValValueboolean(linear_bends_));
 | 
|---|
 | 685 | 
 | 
|---|
 | 686 |   linear_lbends_
 | 
|---|
 | 687 |     = keyval->booleanvalue("linear_lbend",
 | 
|---|
 | 688 |                            KeyValValueboolean(linear_lbends_));
 | 
|---|
 | 689 | 
 | 
|---|
 | 690 |   linear_tors_
 | 
|---|
 | 691 |     = keyval->booleanvalue("linear_tors",
 | 
|---|
 | 692 |                            KeyValValueboolean(linear_tors_));
 | 
|---|
 | 693 | 
 | 
|---|
 | 694 |   linear_stors_
 | 
|---|
 | 695 |     = keyval->booleanvalue("linear_stors",
 | 
|---|
 | 696 |                            KeyValValueboolean(linear_stors_));
 | 
|---|
 | 697 | 
 | 
|---|
 | 698 |   // the extra_bonds list is given as a vector of atom numbers
 | 
|---|
 | 699 |   // (atom numbering starts at 1)
 | 
|---|
 | 700 |   nextra_bonds_ = keyval->count("extra_bonds");
 | 
|---|
 | 701 |   nextra_bonds_ /= 2;
 | 
|---|
 | 702 |   if (nextra_bonds_) {
 | 
|---|
 | 703 |       extra_bonds_ = new int[nextra_bonds_*2];
 | 
|---|
 | 704 |       for (int i=0; i<nextra_bonds_*2; i++) {
 | 
|---|
 | 705 |           extra_bonds_[i] = keyval->intvalue("extra_bonds",i);
 | 
|---|
 | 706 |           if (keyval->error() != KeyVal::OK) {
 | 
|---|
 | 707 |             throw InputError("missing an expected integer value",
 | 
|---|
 | 708 |                              __FILE__, __LINE__, "extra_bonds", 0,
 | 
|---|
 | 709 |                              class_desc());
 | 
|---|
 | 710 |             }
 | 
|---|
 | 711 |         }
 | 
|---|
 | 712 |     }
 | 
|---|
 | 713 |   else {
 | 
|---|
 | 714 |       extra_bonds_ = 0;
 | 
|---|
 | 715 |     }
 | 
|---|
 | 716 | }
 | 
|---|
 | 717 | 
 | 
|---|
 | 718 | IntCoorGen::IntCoorGen(StateIn& s):
 | 
|---|
 | 719 |   SavableState(s)
 | 
|---|
 | 720 | {
 | 
|---|
 | 721 |   molecule_ << SavableState::restore_state(s);
 | 
|---|
 | 722 |   s.get(linear_bends_);
 | 
|---|
 | 723 |   if (s.version(::class_desc<IntCoorGen>()) >= 2) {
 | 
|---|
 | 724 |       s.get(linear_lbends_);
 | 
|---|
 | 725 |     }
 | 
|---|
 | 726 |   s.get(linear_tors_);
 | 
|---|
 | 727 |   s.get(linear_stors_);
 | 
|---|
 | 728 |   s.get(linear_bend_thres_);
 | 
|---|
 | 729 |   s.get(linear_tors_thres_);
 | 
|---|
 | 730 |   s.get(nextra_bonds_);
 | 
|---|
 | 731 |   s.get(extra_bonds_);
 | 
|---|
 | 732 |   s.get(radius_scale_factor_);
 | 
|---|
 | 733 | }
 | 
|---|
 | 734 | 
 | 
|---|
 | 735 | void
 | 
|---|
 | 736 | IntCoorGen::init_constants()
 | 
|---|
 | 737 | {
 | 
|---|
 | 738 |   nextra_bonds_ = 0;
 | 
|---|
 | 739 |   extra_bonds_ = 0;
 | 
|---|
 | 740 |   radius_scale_factor_ = 1.1;
 | 
|---|
 | 741 |   linear_bend_thres_ = 1.0;
 | 
|---|
 | 742 |   linear_tors_thres_ = 1.0;
 | 
|---|
 | 743 |   linear_bends_ = 0;
 | 
|---|
 | 744 |   linear_lbends_ = 1;
 | 
|---|
 | 745 |   linear_tors_ = 0;
 | 
|---|
 | 746 |   linear_stors_ = 1;
 | 
|---|
 | 747 | }
 | 
|---|
 | 748 | 
 | 
|---|
 | 749 | IntCoorGen::~IntCoorGen()
 | 
|---|
 | 750 | {
 | 
|---|
 | 751 |   if (extra_bonds_) delete[] extra_bonds_;
 | 
|---|
 | 752 | }
 | 
|---|
 | 753 | 
 | 
|---|
 | 754 | void
 | 
|---|
 | 755 | IntCoorGen::save_data_state(StateOut& s)
 | 
|---|
 | 756 | {
 | 
|---|
 | 757 |   SavableState::save_state(molecule_.pointer(),s);
 | 
|---|
 | 758 |   s.put(linear_bends_);
 | 
|---|
 | 759 |   s.put(linear_lbends_);
 | 
|---|
 | 760 |   s.put(linear_tors_);
 | 
|---|
 | 761 |   s.put(linear_stors_);
 | 
|---|
 | 762 |   s.put(linear_bend_thres_);
 | 
|---|
 | 763 |   s.put(linear_tors_thres_);
 | 
|---|
 | 764 |   s.put(nextra_bonds_);
 | 
|---|
 | 765 |   s.put(extra_bonds_,2*nextra_bonds_);
 | 
|---|
 | 766 |   s.put(radius_scale_factor_);
 | 
|---|
 | 767 | }
 | 
|---|
 | 768 | 
 | 
|---|
 | 769 | void
 | 
|---|
 | 770 | IntCoorGen::print(ostream& out) const
 | 
|---|
 | 771 | {
 | 
|---|
 | 772 |   out << indent << "IntCoorGen:" << endl << incindent
 | 
|---|
 | 773 |       << indent << "linear_bends = " << linear_bends_ << endl
 | 
|---|
 | 774 |       << indent << "linear_lbends = " << linear_lbends_ << endl
 | 
|---|
 | 775 |       << indent << "linear_tors = " << linear_tors_ << endl
 | 
|---|
 | 776 |       << indent << "linear_stors = " << linear_stors_ << endl
 | 
|---|
 | 777 |       << indent << scprintf("linear_bend_threshold = %f\n",linear_bend_thres_)
 | 
|---|
 | 778 |       << indent << scprintf("linear_tors_threshold = %f\n",linear_tors_thres_)
 | 
|---|
 | 779 |       << indent << scprintf("radius_scale_factor = %f\n",radius_scale_factor_)
 | 
|---|
 | 780 |       << indent << "nextra_bonds = " << nextra_bonds_ << endl
 | 
|---|
 | 781 |       << decindent;
 | 
|---|
 | 782 | }
 | 
|---|
 | 783 | 
 | 
|---|
 | 784 | static void
 | 
|---|
 | 785 | find_bonds(Molecule &m, BitArrayLTri &bonds,
 | 
|---|
 | 786 |            double radius_scale_factor_)
 | 
|---|
 | 787 | {
 | 
|---|
 | 788 |   int i, j;
 | 
|---|
 | 789 |   for(i=0; i < m.natom(); i++) {
 | 
|---|
 | 790 |     double at_rad_i = m.atominfo()->atomic_radius(m.Z(i));
 | 
|---|
 | 791 |     SCVector3 ri(m.r(i));
 | 
|---|
 | 792 | 
 | 
|---|
 | 793 |     for(j=0; j < i; j++) {
 | 
|---|
 | 794 |       double at_rad_j = m.atominfo()->atomic_radius(m.Z(j));
 | 
|---|
 | 795 |       SCVector3 rj(m.r(j));
 | 
|---|
 | 796 | 
 | 
|---|
 | 797 |       if (ri.dist(rj)
 | 
|---|
 | 798 |           < radius_scale_factor_*(at_rad_i+at_rad_j))
 | 
|---|
 | 799 |         bonds.set(i,j);
 | 
|---|
 | 800 |       }
 | 
|---|
 | 801 |     }
 | 
|---|
 | 802 | 
 | 
|---|
 | 803 |   // check for groups of atoms bound to nothing
 | 
|---|
 | 804 |   std::set<int> boundatoms;
 | 
|---|
 | 805 |   std::set<int> newatoms, nextnewatoms;
 | 
|---|
 | 806 |   // start out with atom 0
 | 
|---|
 | 807 |   newatoms.insert(0);
 | 
|---|
 | 808 |   std::set<int>::iterator iatom;
 | 
|---|
 | 809 |   int warning_printed = 0;
 | 
|---|
 | 810 |   while (newatoms.size() > 0) {
 | 
|---|
 | 811 |     while (newatoms.size() > 0) {
 | 
|---|
 | 812 |       // newatoms gets merged into boundatoms
 | 
|---|
 | 813 |       for (iatom=newatoms.begin(); iatom!=newatoms.end(); iatom++) {
 | 
|---|
 | 814 |         boundatoms.insert(*iatom);
 | 
|---|
 | 815 |         }
 | 
|---|
 | 816 |       // set nextnewatoms to atoms bound to boundatoms that are not already
 | 
|---|
 | 817 |       // in boundatoms
 | 
|---|
 | 818 |       nextnewatoms.clear();
 | 
|---|
 | 819 |       for (iatom=newatoms.begin(); iatom!=newatoms.end(); iatom++) {
 | 
|---|
 | 820 |         int atom = *iatom;
 | 
|---|
 | 821 |         for (i=0; i<m.natom(); i++) {
 | 
|---|
 | 822 |           if (bonds(i,atom) && boundatoms.find(i) == boundatoms.end()) {
 | 
|---|
 | 823 |             nextnewatoms.insert(i);
 | 
|---|
 | 824 |             }
 | 
|---|
 | 825 |           }
 | 
|---|
 | 826 |         }
 | 
|---|
 | 827 |       // set newatoms to nextnewatoms to start off the next iteration
 | 
|---|
 | 828 |       newatoms.clear();
 | 
|---|
 | 829 |       for (iatom=nextnewatoms.begin(); iatom!=nextnewatoms.end(); iatom++) {
 | 
|---|
 | 830 |         newatoms.insert(*iatom);
 | 
|---|
 | 831 |         }
 | 
|---|
 | 832 |       }
 | 
|---|
 | 833 | 
 | 
|---|
 | 834 |     if (boundatoms.size() != m.natom()) {
 | 
|---|
 | 835 |       if (!warning_printed) {
 | 
|---|
 | 836 |         warning_printed = 1;
 | 
|---|
 | 837 |         ExEnv::out0()
 | 
|---|
 | 838 |              << indent << "WARNING: two unbound groups of atoms" << endl
 | 
|---|
 | 839 |              << indent << "         consider using extra_bonds input" << endl
 | 
|---|
 | 840 |              << endl;
 | 
|---|
 | 841 |         }
 | 
|---|
 | 842 |       // find an unbound group
 | 
|---|
 | 843 |       double nearest_dist;
 | 
|---|
 | 844 |       int nearest_bound = -1, nearest_unbound = -1;
 | 
|---|
 | 845 |       for(i=0; i < m.natom(); i++) {
 | 
|---|
 | 846 |         if (boundatoms.find(i) == boundatoms.end()) {
 | 
|---|
 | 847 |           SCVector3 ri(m.r(i));
 | 
|---|
 | 848 |           for (iatom=boundatoms.begin(); iatom!=boundatoms.end(); iatom++) {
 | 
|---|
 | 849 |             SCVector3 rj(m.r(*iatom));
 | 
|---|
 | 850 |             double d = ri.dist(rj);
 | 
|---|
 | 851 |             if (nearest_unbound == -1 || d < nearest_dist) {
 | 
|---|
 | 852 |               nearest_dist = d;
 | 
|---|
 | 853 |               nearest_bound = *iatom;
 | 
|---|
 | 854 |               nearest_unbound = i;
 | 
|---|
 | 855 |               }
 | 
|---|
 | 856 |             }
 | 
|---|
 | 857 |           }
 | 
|---|
 | 858 |         }
 | 
|---|
 | 859 |       if (nearest_bound == -1) {
 | 
|---|
 | 860 |         throw ProgrammingError("impossible error generating coordinates",
 | 
|---|
 | 861 |                                __FILE__, __LINE__);
 | 
|---|
 | 862 |         }
 | 
|---|
 | 863 |       // add all bound atoms within a certain distance of nearest_unbound
 | 
|---|
 | 864 |       // --- should really do this for all atoms that nearest_unbound
 | 
|---|
 | 865 |       // --- is already bound to, too
 | 
|---|
 | 866 |       SCVector3 rnearest_unbound(m.r(nearest_unbound));
 | 
|---|
 | 867 |       for (iatom=boundatoms.begin(); iatom!=boundatoms.end(); iatom++) {
 | 
|---|
 | 868 |         SCVector3 r(m.r(*iatom));
 | 
|---|
 | 869 |         if (*iatom == nearest_bound
 | 
|---|
 | 870 |             || rnearest_unbound.dist(r) < 1.1 * nearest_dist) {
 | 
|---|
 | 871 |           ExEnv::out0() << indent
 | 
|---|
 | 872 |                << "         adding bond between "
 | 
|---|
 | 873 |                << *iatom+1 << " and " << nearest_unbound+1 << endl;
 | 
|---|
 | 874 |           bonds.set(*iatom,nearest_unbound);
 | 
|---|
 | 875 |           }
 | 
|---|
 | 876 |         }
 | 
|---|
 | 877 |       newatoms.insert(nearest_unbound);
 | 
|---|
 | 878 |       }
 | 
|---|
 | 879 |     }
 | 
|---|
 | 880 | }
 | 
|---|
 | 881 | 
 | 
|---|
 | 882 | void
 | 
|---|
 | 883 | IntCoorGen::generate(const Ref<SetIntCoor>& sic)
 | 
|---|
 | 884 | {
 | 
|---|
 | 885 |   int i;
 | 
|---|
 | 886 |   Molecule& m = *molecule_.pointer();
 | 
|---|
 | 887 | 
 | 
|---|
 | 888 |   // let's go through the geometry and find all the close contacts
 | 
|---|
 | 889 |   // bonds is a lower triangle matrix of 1's and 0's indicating whether
 | 
|---|
 | 890 |   // there is a bond between atoms i and j
 | 
|---|
 | 891 | 
 | 
|---|
 | 892 |   BitArrayLTri bonds(m.natom(),m.natom());
 | 
|---|
 | 893 | 
 | 
|---|
 | 894 |   for (i=0; i<nextra_bonds_; i++) {
 | 
|---|
 | 895 |     bonds.set(extra_bonds_[i*2]-1,extra_bonds_[i*2+1]-1);
 | 
|---|
 | 896 |   }
 | 
|---|
 | 897 | 
 | 
|---|
 | 898 |   find_bonds(m, bonds, radius_scale_factor_);
 | 
|---|
 | 899 |       
 | 
|---|
 | 900 |   // compute the simple internal coordinates by type
 | 
|---|
 | 901 |   add_bonds(sic,bonds,m);
 | 
|---|
 | 902 |   add_bends(sic,bonds,m);
 | 
|---|
 | 903 |   add_tors(sic,bonds,m);
 | 
|---|
 | 904 |   add_out(sic,bonds,m);
 | 
|---|
 | 905 | 
 | 
|---|
 | 906 |   ExEnv::out0() << endl << indent
 | 
|---|
 | 907 |        << "IntCoorGen: generated " << sic->n() << " coordinates." << endl;
 | 
|---|
 | 908 | }
 | 
|---|
 | 909 | 
 | 
|---|
 | 910 | ///////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 911 | // auxillary functions of IntCoorGen
 | 
|---|
 | 912 | 
 | 
|---|
 | 913 | /*
 | 
|---|
 | 914 |  * the following are translations of functions written by Gregory Humphreys
 | 
|---|
 | 915 |  * at the NIH
 | 
|---|
 | 916 |  */
 | 
|---|
 | 917 | 
 | 
|---|
 | 918 | /*
 | 
|---|
 | 919 |  * for each bonded pair, add an entry to the simple coord list
 | 
|---|
 | 920 |  */
 | 
|---|
 | 921 | 
 | 
|---|
 | 922 | void
 | 
|---|
 | 923 | IntCoorGen::add_bonds(const Ref<SetIntCoor>& list, BitArrayLTri& bonds, Molecule& m)
 | 
|---|
 | 924 | {
 | 
|---|
 | 925 |   int i,j,ij;
 | 
|---|
 | 926 |   int labelc=0;
 | 
|---|
 | 927 |   char label[80];
 | 
|---|
 | 928 | 
 | 
|---|
 | 929 |   for(i=ij=0; i < m.natom(); i++) {
 | 
|---|
 | 930 |     for(j=0; j <= i; j++,ij++) {
 | 
|---|
 | 931 |       if(bonds[ij]) {
 | 
|---|
 | 932 |         labelc++;
 | 
|---|
 | 933 |         sprintf(label,"s%d",labelc);
 | 
|---|
 | 934 |         list->add(new Stre(label,j+1,i+1));
 | 
|---|
 | 935 |         }
 | 
|---|
 | 936 |       }
 | 
|---|
 | 937 |     }
 | 
|---|
 | 938 |   }
 | 
|---|
 | 939 | 
 | 
|---|
 | 940 | /*
 | 
|---|
 | 941 |  * return 1 if all three atoms are nearly on the same line.
 | 
|---|
 | 942 |  */
 | 
|---|
 | 943 | 
 | 
|---|
 | 944 | // returns fabs(cos(theta_ijk))
 | 
|---|
 | 945 | double
 | 
|---|
 | 946 | IntCoorGen::cos_ijk(Molecule& m, int i, int j, int k)
 | 
|---|
 | 947 | {
 | 
|---|
 | 948 |   SCVector3 a, b, c;
 | 
|---|
 | 949 |   int xyz;
 | 
|---|
 | 950 |   for (xyz=0; xyz<3; xyz++) {
 | 
|---|
 | 951 |       a[xyz] = m.r(i,xyz);
 | 
|---|
 | 952 |       b[xyz] = m.r(j,xyz);
 | 
|---|
 | 953 |       c[xyz] = m.r(k,xyz);
 | 
|---|
 | 954 |     }
 | 
|---|
 | 955 |   SCVector3 ab = a - b;
 | 
|---|
 | 956 |   SCVector3 cb = c - b;
 | 
|---|
 | 957 |   return fabs(ab.dot(cb)/(ab.norm()*cb.norm()));
 | 
|---|
 | 958 | }
 | 
|---|
 | 959 | 
 | 
|---|
 | 960 | void
 | 
|---|
 | 961 | IntCoorGen::add_bends(const Ref<SetIntCoor>& list, BitArrayLTri& bonds, Molecule& m)
 | 
|---|
 | 962 | {
 | 
|---|
 | 963 |   int i,j,k;
 | 
|---|
 | 964 |   int labelc=0;
 | 
|---|
 | 965 |   char label[80];
 | 
|---|
 | 966 | 
 | 
|---|
 | 967 |   int n = m.natom();
 | 
|---|
 | 968 | 
 | 
|---|
 | 969 |   double thres = cos(linear_bend_thres_*M_PI/180.0);
 | 
|---|
 | 970 | 
 | 
|---|
 | 971 |   for(i=0; i < n; i++) {
 | 
|---|
 | 972 |     SCVector3 ri(m.r(i));
 | 
|---|
 | 973 |     for(j=0; j < n; j++) {
 | 
|---|
 | 974 |       if(bonds(i,j)) {
 | 
|---|
 | 975 |         SCVector3 rj(m.r(j));
 | 
|---|
 | 976 |         for(k=0; k < i; k++) {
 | 
|---|
 | 977 |           if(bonds(j,k)) {
 | 
|---|
 | 978 |             SCVector3 rk(m.r(k));
 | 
|---|
 | 979 |             int is_linear = (cos_ijk(m,i,j,k) >= thres);
 | 
|---|
 | 980 |             if (linear_bends_ || !is_linear) {
 | 
|---|
 | 981 |               labelc++;
 | 
|---|
 | 982 |               sprintf(label,"b%d",labelc);
 | 
|---|
 | 983 |               list->add(new Bend(label,k+1,j+1,i+1));
 | 
|---|
 | 984 |               }
 | 
|---|
 | 985 |             if (linear_lbends_ && is_linear) {
 | 
|---|
 | 986 |               // find a unit vector roughly perp to the bonds
 | 
|---|
 | 987 |               SCVector3 u;
 | 
|---|
 | 988 |               // first try to find another atom, that'll help keep one of
 | 
|---|
 | 989 |               // the coordinates totally symmetric in some cases
 | 
|---|
 | 990 |               int most_perp_atom = -1;
 | 
|---|
 | 991 |               double cos_most_perp = thres;
 | 
|---|
 | 992 |               for (int l=0; l < n; l++) {
 | 
|---|
 | 993 |                 if (l == i || l == j || l == k) continue;
 | 
|---|
 | 994 |                 double tmp = cos_ijk(m,i,j,l);
 | 
|---|
 | 995 |                 if (tmp < cos_most_perp) {
 | 
|---|
 | 996 |                   cos_most_perp = tmp;
 | 
|---|
 | 997 |                   most_perp_atom = l;
 | 
|---|
 | 998 |                   }
 | 
|---|
 | 999 |                 }
 | 
|---|
 | 1000 |               if (most_perp_atom != -1) {
 | 
|---|
 | 1001 |                 SCVector3 rmpa(m.r(most_perp_atom));
 | 
|---|
 | 1002 |                 u = rj-rmpa;
 | 
|---|
 | 1003 |                 u.normalize();
 | 
|---|
 | 1004 |                 }
 | 
|---|
 | 1005 |               else {
 | 
|---|
 | 1006 |                 SCVector3 b1, b2;
 | 
|---|
 | 1007 |                 b1 = ri-rj;
 | 
|---|
 | 1008 |                 b2 = rk-rj;
 | 
|---|
 | 1009 |                 u = b1.perp_unit(b2);
 | 
|---|
 | 1010 |                 }
 | 
|---|
 | 1011 |               labelc++;
 | 
|---|
 | 1012 |               sprintf(label,"b%d",labelc);
 | 
|---|
 | 1013 |               list->add(new LinIP(label,k+1,j+1,i+1,u));
 | 
|---|
 | 1014 |               labelc++;
 | 
|---|
 | 1015 |               sprintf(label,"b%d",labelc);
 | 
|---|
 | 1016 |               list->add(new LinOP(label,k+1,j+1,i+1,u));
 | 
|---|
 | 1017 |               }
 | 
|---|
 | 1018 |             }
 | 
|---|
 | 1019 |           }
 | 
|---|
 | 1020 |         }
 | 
|---|
 | 1021 |       }
 | 
|---|
 | 1022 |     }
 | 
|---|
 | 1023 |   }
 | 
|---|
 | 1024 | 
 | 
|---|
 | 1025 | /*
 | 
|---|
 | 1026 |  * for each pair of bends which share a common bond, add a torsion
 | 
|---|
 | 1027 |  */
 | 
|---|
 | 1028 | 
 | 
|---|
 | 1029 | /*
 | 
|---|
 | 1030 |  * just look at the heavy-atom skeleton. return true if i is a terminal
 | 
|---|
 | 1031 |  * atom.
 | 
|---|
 | 1032 |  */
 | 
|---|
 | 1033 | 
 | 
|---|
 | 1034 | int
 | 
|---|
 | 1035 | IntCoorGen::hterminal(Molecule& m, BitArrayLTri& bonds, int i)
 | 
|---|
 | 1036 | {
 | 
|---|
 | 1037 |   int nh=0;
 | 
|---|
 | 1038 |   for (int j=0; j < m.natom(); j++)
 | 
|---|
 | 1039 |     if (bonds(i,j) && m.Z(j) > 1) nh++;
 | 
|---|
 | 1040 |   return (nh==1);
 | 
|---|
 | 1041 | }
 | 
|---|
 | 1042 | 
 | 
|---|
 | 1043 | void
 | 
|---|
 | 1044 | IntCoorGen::add_tors(const Ref<SetIntCoor>& list, BitArrayLTri& bonds, Molecule& m)
 | 
|---|
 | 1045 | {
 | 
|---|
 | 1046 |   int i,j,k,l;
 | 
|---|
 | 1047 |   int labelc=0;
 | 
|---|
 | 1048 |   char label[80];
 | 
|---|
 | 1049 | 
 | 
|---|
 | 1050 |   int n = m.natom();
 | 
|---|
 | 1051 | 
 | 
|---|
 | 1052 |   double thres = cos(linear_tors_thres_*M_PI/180.0);
 | 
|---|
 | 1053 | 
 | 
|---|
 | 1054 |   for(j=0; j < n; j++) {
 | 
|---|
 | 1055 |     for(k=0; k < j; k++) {
 | 
|---|
 | 1056 |       if(bonds(j,k)) {
 | 
|---|
 | 1057 |         for(i=0; i < n; i++) {
 | 
|---|
 | 1058 |           if(k==i) continue;
 | 
|---|
 | 1059 | 
 | 
|---|
 | 1060 |          // no hydrogen torsions, ok?
 | 
|---|
 | 1061 |           if (m.Z(i) == 1 && !hterminal(m,bonds,j)) continue;
 | 
|---|
 | 1062 | 
 | 
|---|
 | 1063 |           if (bonds(j,i)) {
 | 
|---|
 | 1064 |             int is_linear = 0;
 | 
|---|
 | 1065 |             if (cos_ijk(m,i,j,k)>=thres) is_linear = 1;
 | 
|---|
 | 1066 | 
 | 
|---|
 | 1067 |             for (l=0; l < n; l++) {
 | 
|---|
 | 1068 |               if (l==j || l==i) continue;
 | 
|---|
 | 1069 | 
 | 
|---|
 | 1070 |              // no hydrogen torsions, ok?
 | 
|---|
 | 1071 |               if (m.Z(l) == 1 && !hterminal(m,bonds,k))
 | 
|---|
 | 1072 |                 continue;
 | 
|---|
 | 1073 | 
 | 
|---|
 | 1074 |               if (bonds(k,l)) {
 | 
|---|
 | 1075 |                 if(cos_ijk(m,j,k,l)>=thres) is_linear = 1;
 | 
|---|
 | 1076 | 
 | 
|---|
 | 1077 |                 if (is_linear && linear_stors_) {
 | 
|---|
 | 1078 |                     labelc++;
 | 
|---|
 | 1079 |                     sprintf(label,"st%d",labelc);
 | 
|---|
 | 1080 |                     list->add(new ScaledTors(label,l+1,k+1,j+1,i+1));
 | 
|---|
 | 1081 |                   }
 | 
|---|
 | 1082 |                 if (!is_linear || linear_tors_) {
 | 
|---|
 | 1083 |                     labelc++;
 | 
|---|
 | 1084 |                     sprintf(label,"t%d",labelc);
 | 
|---|
 | 1085 |                     list->add(new Tors(label,l+1,k+1,j+1,i+1));
 | 
|---|
 | 1086 |                   }
 | 
|---|
 | 1087 |                 }
 | 
|---|
 | 1088 |               }
 | 
|---|
 | 1089 |             }
 | 
|---|
 | 1090 |           }
 | 
|---|
 | 1091 |         }
 | 
|---|
 | 1092 |       }
 | 
|---|
 | 1093 |     }
 | 
|---|
 | 1094 |   }
 | 
|---|
 | 1095 | 
 | 
|---|
 | 1096 | void
 | 
|---|
 | 1097 | IntCoorGen::add_out(const Ref<SetIntCoor>& list, BitArrayLTri& bonds, Molecule& m)
 | 
|---|
 | 1098 | {
 | 
|---|
 | 1099 |   int i,j,k,l;
 | 
|---|
 | 1100 |   int labelc=0;
 | 
|---|
 | 1101 |   char label[80];
 | 
|---|
 | 1102 | 
 | 
|---|
 | 1103 |   int n = m.natom();
 | 
|---|
 | 1104 | 
 | 
|---|
 | 1105 |  // first find all tri-coordinate atoms
 | 
|---|
 | 1106 |   for(i=0; i < n; i++) {
 | 
|---|
 | 1107 |     if(bonds.degree(i)!=3) continue;
 | 
|---|
 | 1108 | 
 | 
|---|
 | 1109 |    // then look for terminal atoms connected to i
 | 
|---|
 | 1110 |     for(j=0; j < n; j++) {
 | 
|---|
 | 1111 |       if(bonds(i,j) && bonds.degree(j)==1) {
 | 
|---|
 | 1112 | 
 | 
|---|
 | 1113 |         for(k=0; k < n; k++) {
 | 
|---|
 | 1114 |           if(k!=j && bonds(i,k)) {
 | 
|---|
 | 1115 |             for(l=0; l < k; l++) {
 | 
|---|
 | 1116 |               if(l!=j && bonds(i,l)) {
 | 
|---|
 | 1117 |                 labelc++;
 | 
|---|
 | 1118 |                 sprintf(label,"o%d",labelc);
 | 
|---|
 | 1119 |                 list->add(new Out(label,j+1,i+1,l+1,k+1));
 | 
|---|
 | 1120 |                 }
 | 
|---|
 | 1121 |               }
 | 
|---|
 | 1122 |             }
 | 
|---|
 | 1123 |           }
 | 
|---|
 | 1124 |         }
 | 
|---|
 | 1125 |       }
 | 
|---|
 | 1126 |     }
 | 
|---|
 | 1127 |   }
 | 
|---|
 | 1128 | 
 | 
|---|
 | 1129 | int
 | 
|---|
 | 1130 | IntCoorGen::nearest_contact(int i, Molecule& m)
 | 
|---|
 | 1131 | {
 | 
|---|
 | 1132 |   double d=-1.0;
 | 
|---|
 | 1133 |   int n=0;
 | 
|---|
 | 1134 | 
 | 
|---|
 | 1135 |   SCVector3 ri(m.r(i));
 | 
|---|
 | 1136 |   
 | 
|---|
 | 1137 |   for (int j=0; j < m.natom(); j++) {
 | 
|---|
 | 1138 |     SCVector3 rj(m.r(j));
 | 
|---|
 | 1139 |     double td = ri.dist(rj);
 | 
|---|
 | 1140 |     if (j==i)
 | 
|---|
 | 1141 |       continue;
 | 
|---|
 | 1142 |     else if (d < 0 || td < d) {
 | 
|---|
 | 1143 |       d = td;
 | 
|---|
 | 1144 |       n = j;
 | 
|---|
 | 1145 |     }
 | 
|---|
 | 1146 |   }
 | 
|---|
 | 1147 |   
 | 
|---|
 | 1148 |   return n;
 | 
|---|
 | 1149 | }
 | 
|---|
 | 1150 | 
 | 
|---|
 | 1151 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 1152 | 
 | 
|---|
 | 1153 | // Local Variables:
 | 
|---|
 | 1154 | // mode: c++
 | 
|---|
 | 1155 | // c-file-style: "CLJ-CONDENSED"
 | 
|---|
 | 1156 | // End:
 | 
|---|