FOX/ObjCryst++  1.10.X (development)
Molecule.cpp
1 /* ObjCryst++ Object-Oriented Crystallographic Library
2  (c) 2000-2009 Vincent Favre-Nicolin vincefn@users.sourceforge.net
3  2000-2001 University of Geneva (Switzerland)
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 /* Molecule.cpp
19 * Source file for the Molecule scatterer
20 *
21 */
22 #include <sstream>
23 #include <fstream>
24 #include <iterator>
25 #include <algorithm>
26 #include <iomanip>
27 
28 #include "ObjCryst/Quirks/VFNStreamFormat.h"
29 #include "ObjCryst/ObjCryst/Molecule.h"
30 #include "ObjCryst/RefinableObj/GlobalOptimObj.h"
31 
32 #ifdef OBJCRYST_GL
33  #ifdef __DARWIN__
34  #include <OpenGL/glu.h>
35  #else
36  #include <GL/glu.h>
37  #endif
38 #endif
39 
40 #ifdef __WX__CRYST__
41  #include "ObjCryst/wxCryst/wxMolecule.h"
42 #endif
43 
44 //#include <xmmintrin.h>
45 
46 // Try new approach for rigid bodies ?
47 #define RIGID_BODY_STRICT_EXPERIMENTAL
48 
49 // Tighter restraints x**2+x**4+x**6 instead of just X**2
50 #undef RESTRAINT_X2_X4_X6
51 
52 using namespace std;
53 
54 
55 namespace ObjCryst
56 {
57 XYZ::XYZ(REAL x0,REAL y0,REAL z0):x(x0),y(y0),z(z0){};
58 
59 REAL GetBondLength(const MolAtom&at1,const MolAtom&at2)
60 {
61  //TAU_PROFILE("GetBondLength()","REAL (...)",TAU_DEFAULT);
62 
63  /*
64  __m128 m128=_mm_set_ps(0.0f,
65  at1.GetZ()-at2.GetZ(),
66  at1.GetY()-at2.GetY(),
67  at1.GetX()-at2.GetX());
68 
69  __m128 a = _mm_mul_ps(m128,m128);
70 
71  // horizontal add
72  __m128 b = _mm_add_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(0,0,0,0)),
73  _mm_add_ss(_mm_shuffle_ps(a, a, _MM_SHUFFLE(1,1,1,1)),
74  _mm_shuffle_ps(a, a, _MM_SHUFFLE(2,2,2,2))));
75  union m128_float
76  {
77  __m128 m128;
78  struct
79  {
80  float x, y, z, pad;
81  };
82  };
83  union m128_float l;
84  l.m128 = _mm_sqrt_ss(b);
85 
86  return l.x;
87  */
88  return sqrt( (at1.GetX()-at2.GetX())
89  *(at1.GetX()-at2.GetX())
90  +(at1.GetY()-at2.GetY())
91  *(at1.GetY()-at2.GetY())
92  +(at1.GetZ()-at2.GetZ())
93  *(at1.GetZ()-at2.GetZ()) );
94 }
95 REAL GetBondAngle(const MolAtom &at1,const MolAtom &at2,const MolAtom &at3)
96 {
97  //TAU_PROFILE("GetBondAngle()","REAL (...)",TAU_DEFAULT);
98  const REAL x21=at1.GetX()-at2.GetX();
99  const REAL y21=at1.GetY()-at2.GetY();
100  const REAL z21=at1.GetZ()-at2.GetZ();
101  const REAL x23=at3.GetX()-at2.GetX();
102  const REAL y23=at3.GetY()-at2.GetY();
103  const REAL z23=at3.GetZ()-at2.GetZ();
104  const REAL norm21_norm23= sqrt( (x21*x21+y21*y21+z21*z21)
105  *(x23*x23+y23*y23+z23*z23)+1e-6);
106  const REAL angle=(x21*x23+y21*y23+z21*z23)/norm21_norm23;
107  if(angle>=1) return 0;
108  if(angle<=-1) return M_PI;
109  return acos(angle);
110 }
111 REAL GetDihedralAngle(const MolAtom &at1,const MolAtom &at2,const MolAtom &at3,const MolAtom &at4)
112 {
113  //TAU_PROFILE("GetDihedralAngle()","REAL (...)",TAU_DEFAULT);
114  const REAL x21=at1.GetX()-at2.GetX();
115  const REAL y21=at1.GetY()-at2.GetY();
116  const REAL z21=at1.GetZ()-at2.GetZ();
117 
118  const REAL x34=at4.GetX()-at3.GetX();
119  const REAL y34=at4.GetY()-at3.GetY();
120  const REAL z34=at4.GetZ()-at3.GetZ();
121 
122  const REAL x23=at3.GetX()-at2.GetX();
123  const REAL y23=at3.GetY()-at2.GetY();
124  const REAL z23=at3.GetZ()-at2.GetZ();
125 
126  // v21 x v23
127  const REAL x123= y21*z23-z21*y23;
128  const REAL y123= z21*x23-x21*z23;
129  const REAL z123= x21*y23-y21*x23;
130 
131  // v32 x v34 (= -v23 x v34)
132  const REAL x234= -(y23*z34-z23*y34);
133  const REAL y234= -(z23*x34-x23*z34);
134  const REAL z234= -(x23*y34-y23*x34);
135 
136  const REAL norm123_norm234= sqrt( (x123*x123+y123*y123+z123*z123)
137  *(x234*x234+y234*y234+z234*z234)+1e-6);
138 
139  REAL angle=(x123*x234+y123*y234+z123*z234)/norm123_norm234;
140  if(angle>= 1) angle=0;
141  else
142  {
143  if(angle<=-1) angle=M_PI;
144  else angle=acos(angle);
145  }
146  if((x21*x234 + y21*y234 + z21*z234)<0) return -angle;
147  return angle;
148 }
149 
150 
152  const map<MolAtom*,set<MolAtom*> > &connect,
153  set<MolAtom*> &atomlist,const MolAtom* finalAtom)
154 {
155  const pair<set<MolAtom*>::iterator,bool> status=atomlist.insert(atom);
156  if(false==status.second) return;
157  if(finalAtom==atom) return;
158  map<MolAtom*,set<MolAtom*> >::const_iterator c=connect.find(atom);
159  set<MolAtom*>::const_iterator pos;
160  for(pos=c->second.begin();pos!=c->second.end();++pos)
161  {
162  ExpandAtomGroupRecursive(*pos,connect,atomlist,finalAtom);
163  }
164 }
165 
167  const map<MolAtom*,set<MolAtom*> > &connect,
168  map<MolAtom*,unsigned long> &atomlist,const unsigned long maxdepth,unsigned long depth)
169 {
170  if(atomlist.count(atom)>0)
171  if(atomlist[atom]<=depth) return;
172  atomlist[atom]=depth;
173  if(depth==maxdepth) return;//maxdepth reached
174  map<MolAtom*,set<MolAtom*> >::const_iterator c=connect.find(atom);
175  set<MolAtom*>::const_iterator pos;
176  for(pos=c->second.begin();pos!=c->second.end();++pos)
177  {
178  ExpandAtomGroupRecursive(*pos,connect,atomlist,maxdepth,depth+1);
179  }
180 }
181 
182 //######################################################################
183 //
184 // MolAtom
185 //
186 //######################################################################
187 
188 MolAtom::MolAtom(const REAL x, const REAL y, const REAL z,
189  const ScatteringPower *pPow, const string &name, Molecule &parent):
190 mName(name),mX(x),mY(y),mZ(z),mOccupancy(1.),mpScattPow(pPow),mpMol(&parent),mIsInRing(false)
191 #ifdef __WX__CRYST__
192 ,mpWXCrystObj(0)
193 #endif
194 {
195  VFN_DEBUG_MESSAGE("MolAtom::MolAtom()",4)
196 }
197 
199 {
200 #ifdef __WX__CRYST__
201 this->WXDelete();
202 #endif
203 }
204 
205 void MolAtom::SetName(const string &name)
206 {
207  mName=name;
208  // Set parameter's name in the parent molecule
209  // The atom should already be part of a Molecule, but just in case be careful
210  if((mName!="") && (mpMol!=0))
211  {
212  try
213  {
214  mpMol->GetPar(&mX).SetName(mpMol->GetName()+"_"+mName+"_x");
215  mpMol->GetPar(&mY).SetName(mpMol->GetName()+"_"+mName+"_y");
216  mpMol->GetPar(&mZ).SetName(mpMol->GetName()+"_"+mName+"_z");
217  }
218  catch(const ObjCrystException &except)
219  {
220  cerr<<"MolAtom::SetName(): Atom parameters not yet declared in a Molecule ?"<<endl;
221  }
222  }
223 }
224 
225 const string& MolAtom::GetName()const{return mName;}
226  string& MolAtom::GetName() {return mName;}
227 
228 const Molecule& MolAtom::GetMolecule()const{return *mpMol;}
229  Molecule& MolAtom::GetMolecule() {return *mpMol;}
230 
231 const REAL& MolAtom::X()const{return mX;}
232 const REAL& MolAtom::Y()const{return mY;}
233 const REAL& MolAtom::Z()const{return mZ;}
234 
235 REAL& MolAtom::X(){return mX;}
236 REAL& MolAtom::Y(){return mY;}
237 REAL& MolAtom::Z(){return mZ;}
238 
239 REAL MolAtom::GetX()const{return mX;}
240 REAL MolAtom::GetY()const{return mY;}
241 REAL MolAtom::GetZ()const{return mZ;}
242 REAL MolAtom::GetOccupancy()const{return mOccupancy;}
243 
244 void MolAtom::SetX(const REAL a)const{ mX=a;mpMol->GetAtomPositionClock().Click();}
245 void MolAtom::SetY(const REAL a)const{ mY=a;mpMol->GetAtomPositionClock().Click();}
246 void MolAtom::SetZ(const REAL a)const{ mZ=a;mpMol->GetAtomPositionClock().Click();}
247 void MolAtom::SetOccupancy(const REAL a){ mOccupancy=a;}
248 
249 bool MolAtom::IsDummy()const{return mpScattPow==0;}
250 const ScatteringPower& MolAtom::GetScatteringPower()const{return *mpScattPow;}
251 void MolAtom::SetScatteringPower(const ScatteringPower& pow){mpScattPow=&pow;}
252 
253 void MolAtom::XMLOutput(ostream &os,int indent)const
254 {
255  VFN_DEBUG_ENTRY("MolAtom::XMLOutput()",4)
256  for(int i=0;i<indent;i++) os << " " ;
257  XMLCrystTag tag("Atom",false,true);
258  tag.AddAttribute("Name",this->GetName());
259  if(!this->IsDummy())tag.AddAttribute("ScattPow",this->GetScatteringPower().GetName());
260  {
261  stringstream ss;
262  ss.precision(os.precision());
263  ss <<mX;
264  tag.AddAttribute("x",ss.str());
265  }
266  {
267  stringstream ss;
268  ss.precision(os.precision());
269  ss <<mY;
270  tag.AddAttribute("y",ss.str());
271  }
272  {
273  stringstream ss;
274  ss.precision(os.precision());
275  ss <<mZ;
276  tag.AddAttribute("z",ss.str());
277  }
278  {
279  stringstream ss;
280  ss.precision(os.precision());
281  ss <<mOccupancy;
282  tag.AddAttribute("Occup",ss.str());
283  }
284  os <<tag<<endl;
285  VFN_DEBUG_EXIT("MolAtom::XMLOutput()",4)
286 }
287 
288 void MolAtom::XMLInput(istream &is,const XMLCrystTag &tag)
289 {
290  VFN_DEBUG_ENTRY("MolAtom::XMLInput()",7)
291  string name;
292  for(unsigned int i=0;i<tag.GetNbAttribute();i++)
293  {
294  if("Name"==tag.GetAttributeName(i))
295  {
296  name=tag.GetAttributeValue(i);
297  }
298  if("ScattPow"==tag.GetAttributeName(i))
299  {
300  mpScattPow=&(mpMol->GetCrystal().GetScatteringPower(tag.GetAttributeValue(i)));
301  }
302  if("x"==tag.GetAttributeName(i))
303  {
304  stringstream ss(tag.GetAttributeValue(i));
305  ss >>mX;
306  }
307  if("y"==tag.GetAttributeName(i))
308  {
309  stringstream ss(tag.GetAttributeValue(i));
310  ss >>mY;
311  }
312  if("z"==tag.GetAttributeName(i))
313  {
314  stringstream ss(tag.GetAttributeValue(i));
315  ss >>mZ;
316  }
317  if("Occup"==tag.GetAttributeName(i))
318  {
319  stringstream ss(tag.GetAttributeValue(i));
320  ss >>mOccupancy;
321  }
322  }
323  this->SetName(name);
324  VFN_DEBUG_EXIT("MolAtom::XMLInput()",7)
325 }
326 
327 void MolAtom::SetIsInRing(const bool r)const{mIsInRing=r;}
328 bool MolAtom::IsInRing()const{return mIsInRing;}
329 
330 #ifdef __WX__CRYST__
331 WXCrystObjBasic* MolAtom::WXCreate(wxWindow* parent)
332 {
333  VFN_DEBUG_ENTRY("MolAtom::WXCreate()",5)
334  mpWXCrystObj=new WXMolAtom(parent,this);
335  VFN_DEBUG_EXIT("MolAtom::WXCreate()",5)
336  return mpWXCrystObj;
337 }
338 WXCrystObjBasic* MolAtom::WXGet(){return mpWXCrystObj;}
339 void MolAtom::WXDelete(){if(0!=mpWXCrystObj) delete mpWXCrystObj;mpWXCrystObj=0;}
340 void MolAtom::WXNotifyDelete(){mpWXCrystObj=0;}
341 #endif
342 //######################################################################
343 //
344 // MolBond
345 //
346 //######################################################################
348  const REAL length0, const REAL sigma, const REAL delta,
349  Molecule &parent,const REAL bondOrder):
350 mAtomPair(make_pair(&atom1,&atom2)),
351 mLength0(length0),mDelta(delta),mSigma(sigma),
352 mBondOrder(bondOrder),mIsFreeTorsion(false),mpMol(&parent)
353 #ifdef __WX__CRYST__
354 ,mpWXCrystObj(0)
355 #endif
356 {}
357 
359 {
360 #ifdef __WX__CRYST__
361 this->WXDelete();
362 #endif
363 }
364 
365 const Molecule& MolBond::GetMolecule()const{return *mpMol;}
366  Molecule& MolBond::GetMolecule() {return *mpMol;}
367 
368 string MolBond::GetName()const
369 {return this->GetAtom1().GetName()+"-"+this->GetAtom2().GetName();}
370 
371 void MolBond::XMLOutput(ostream &os,int indent)const
372 {
373  VFN_DEBUG_ENTRY("MolBond::XMLOutput()",4)
374  for(int i=0;i<indent;i++) os << " " ;
375  XMLCrystTag tag("Bond",false,true);
376  tag.AddAttribute("Atom1",mAtomPair.first->GetName());
377  tag.AddAttribute("Atom2",mAtomPair.second->GetName());
378  {
379  stringstream ss;
380  ss.precision(os.precision());
381  ss <<mLength0;
382  tag.AddAttribute("Length",ss.str());
383  }
384  {
385  stringstream ss;
386  ss.precision(os.precision());
387  ss <<mDelta;
388  tag.AddAttribute("Delta",ss.str());
389  }
390  {
391  stringstream ss;
392  ss.precision(os.precision());
393  ss <<mSigma;
394  tag.AddAttribute("Sigma",ss.str());
395  }
396  {
397  stringstream ss;
398  ss.precision(os.precision());
399  ss <<mBondOrder;
400  tag.AddAttribute("BondOrder",ss.str());
401  }
402  {
403  stringstream ss;
404  ss.precision(os.precision());
405  ss <<mIsFreeTorsion;
406  tag.AddAttribute("FreeTorsion",ss.str());
407  }
408  os <<tag<<endl;
409  VFN_DEBUG_EXIT("MolBond::XMLOutput()",4)
410 }
411 
412 void MolBond::XMLInput(istream &is,const XMLCrystTag &tag)
413 {
414  VFN_DEBUG_ENTRY("MolBond::XMLInput():",7)
415  for(unsigned int i=0;i<tag.GetNbAttribute();i++)
416  {
417  if("Atom1"==tag.GetAttributeName(i))
418  {
419  mAtomPair.first=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
420  }
421  if("Atom2"==tag.GetAttributeName(i))
422  {
423  mAtomPair.second=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
424  }
425  if("Length"==tag.GetAttributeName(i))
426  {
427  stringstream ss(tag.GetAttributeValue(i));
428  ss >>mLength0;
429  }
430  if("Delta"==tag.GetAttributeName(i))
431  {
432  stringstream ss(tag.GetAttributeValue(i));
433  ss >>mDelta;
434  }
435  if("Sigma"==tag.GetAttributeName(i))
436  {
437  stringstream ss(tag.GetAttributeValue(i));
438  ss >>mSigma;
439  }
440  if("BondOrder"==tag.GetAttributeName(i))
441  {
442  stringstream ss(tag.GetAttributeValue(i));
443  ss >>mBondOrder;
444  }
445  if("FreeTorsion"==tag.GetAttributeName(i))
446  {
447  stringstream ss(tag.GetAttributeValue(i));
448  ss >>mIsFreeTorsion;
449  }
450  }
451  VFN_DEBUG_EXIT("MolBond::XMLInput():",7)
452 }
453 
454 REAL MolBond::GetLogLikelihood()const{return this->GetLogLikelihood(false,true);}
455 
456 REAL MolBond::GetLogLikelihood(const bool calcDeriv, const bool recalc)const
457 {
458  if(!recalc) return mLLK;
459  VFN_DEBUG_ENTRY("MolBond::GetLogLikelihood():",2)
460  //TAU_PROFILE("MolBond::GetLogLikelihood()","REAL (bool,bool)",TAU_DEFAULT);
461  //const REAL length=this->GetLength();
462  const REAL x=this->GetAtom2().GetX()-this->GetAtom1().GetX();
463  const REAL y=this->GetAtom2().GetY()-this->GetAtom1().GetY();
464  const REAL z=this->GetAtom2().GetZ()-this->GetAtom1().GetZ();
465  const REAL length=sqrt(abs(x*x+y*y+z*z));
466 
467  if(calcDeriv)
468  {
469  const REAL tmp2=1/(length+1e-10);
470  mDerivAtom1.x=-x*tmp2;
471  mDerivAtom1.y=-y*tmp2;
472  mDerivAtom1.z=-z*tmp2;
473 
474  mDerivAtom2.x=-mDerivAtom1.x;
475  mDerivAtom2.y=-mDerivAtom1.y;
476  mDerivAtom2.z=-mDerivAtom1.z;
477  }
478 
479  if(mSigma<1e-6)
480  {
481  if(calcDeriv) mDerivLLKCoeff=0;
482  mLLK=0;
483  return 0;
484  }
485  mLLK=length-(mLength0+mDelta);
486  if(mLLK>0)
487  {
488  mLLK /= mSigma;
489  if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma;
490  #ifdef RESTRAINT_X2_X4_X6
491  const float mLLK2=mLLK*mLLK;
492  //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma;
493  //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2);
494  if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma;
495  mLLK=mLLK2*(1+mLLK2);
496  #else
497  if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma;
498  mLLK *= mLLK;
499  #endif
500  VFN_DEBUG_EXIT("MolBond::GetLogLikelihood():",2)
501  return mLLK;
502  }
503  mLLK=length-(mLength0-mDelta);
504  if(mLLK<0)
505  {
506  mLLK /= mSigma;
507  #ifdef RESTRAINT_X2_X4_X6
508  const float mLLK2=mLLK*mLLK;
509  //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma;
510  //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2);
511  if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma;
512  mLLK=mLLK2*(1+mLLK2);
513  #else
514  if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma;
515  mLLK *= mLLK;
516  #endif
517  VFN_DEBUG_EXIT("MolBond::GetLogLikelihood():",2)
518  return mLLK;
519  }
520  if(calcDeriv) mDerivLLKCoeff=0;
521  mLLK=0;
522  VFN_DEBUG_EXIT("MolBond::GetLogLikelihood():",2)
523  return mLLK;
524 }
525 
526 REAL MolBond::GetDeriv(const map<const MolAtom*,XYZ> &m, const bool llk)const
527 {
528  //TAU_PROFILE("MolBond::GetDeriv()","REAL (mak,bool)",TAU_DEFAULT);
529  REAL d=0;
530  map<const MolAtom*,XYZ>::const_iterator pos;
531  pos=m.find(mAtomPair.first);
532  if(pos!=m.end())
533  d+= pos->second.x*mDerivAtom1.x
534  +pos->second.y*mDerivAtom1.y
535  +pos->second.z*mDerivAtom1.z;
536  pos=m.find(mAtomPair.second);
537  if(pos!=m.end())
538  d+= pos->second.x*mDerivAtom2.x
539  +pos->second.y*mDerivAtom2.y
540  +pos->second.z*mDerivAtom2.z;
541  if(llk) return mDerivLLKCoeff*d;
542  return d;
543 }
544 
545 void MolBond::CalcGradient(std::map<MolAtom*,XYZ> &m)const
546 {
547  this->GetLogLikelihood(true,true);
548  map<MolAtom*,XYZ>::iterator pos;
549  pos=m.find(mAtomPair.first);
550  if(pos!=m.end())
551  {
552  pos->second.x+=mDerivLLKCoeff*mDerivAtom1.x;
553  pos->second.y+=mDerivLLKCoeff*mDerivAtom1.y;
554  pos->second.z+=mDerivLLKCoeff*mDerivAtom1.z;
555  }
556  pos=m.find(mAtomPair.second);
557  if(pos!=m.end())
558  {
559  pos->second.x+=mDerivLLKCoeff*mDerivAtom2.x;
560  pos->second.y+=mDerivLLKCoeff*mDerivAtom2.y;
561  pos->second.z+=mDerivLLKCoeff*mDerivAtom2.z;
562  }
563  #if 0
564  // Display gradient - for tests
565  cout<<this->GetName()<<" :LLK"<<endl;
566  for(map<MolAtom*,XYZ>::const_iterator pos=m.begin();pos!=m.end();++pos)
567  {
568  char buf[100];
569  sprintf(buf,"%10s Grad LLK= (%8.3f %8.3f %8.3f)",
570  pos->first->GetName().c_str(),pos->second.x,pos->second.y,pos->second.z);
571  cout<<buf<<endl;
572  }
573  #endif
574 }
575 
576 const MolAtom& MolBond::GetAtom1()const{return *(mAtomPair.first);}
577 const MolAtom& MolBond::GetAtom2()const{return *(mAtomPair.second);}
578 MolAtom& MolBond::GetAtom1(){return *(mAtomPair.first);}
579 MolAtom& MolBond::GetAtom2(){return *(mAtomPair.second);}
580 void MolBond::SetAtom1(MolAtom &at){mAtomPair.first =&at;}
581 void MolBond::SetAtom2(MolAtom &at){mAtomPair.second=&at;}
582 REAL MolBond::GetLength()const
583 {
584  return GetBondLength(GetAtom1(),this->GetAtom2());
585 }
586 
587 REAL MolBond::GetLength0()const{return mLength0;}
588 REAL MolBond::GetLengthDelta()const{return mDelta;}
589 REAL MolBond::GetLengthSigma()const{return mSigma;}
590 REAL MolBond::GetBondOrder()const{return mBondOrder;}
591 
592 REAL& MolBond::Length0(){return mLength0;}
593 REAL& MolBond::LengthDelta(){return mDelta;}
594 REAL& MolBond::LengthSigma(){return mSigma;}
595 REAL& MolBond::BondOrder(){return mBondOrder;}
596 
597 void MolBond::SetLength0(const REAL a){mLength0=a;}
598 void MolBond::SetLengthDelta(const REAL a){mDelta=a;}
599 void MolBond::SetLengthSigma(const REAL a){mSigma=a;}
600 void MolBond::SetBondOrder(const REAL a){mBondOrder=a;}
601 
602 bool MolBond::IsFreeTorsion()const{return mIsFreeTorsion;}
603 void MolBond::SetFreeTorsion(const bool isFreeTorsion)
604 {
605  if(mIsFreeTorsion==isFreeTorsion) return;
606  mIsFreeTorsion=isFreeTorsion;
608 }
609 #ifdef __WX__CRYST__
610 WXCrystObjBasic* MolBond::WXCreate(wxWindow* parent)
611 {
612  VFN_DEBUG_ENTRY("MolBond::WXCreate()",5)
613  mpWXCrystObj=new WXMolBond(parent,this);
614  VFN_DEBUG_EXIT("MolBond::WXCreate()",5)
615  return mpWXCrystObj;
616 }
617 WXCrystObjBasic* MolBond::WXGet(){return mpWXCrystObj;}
618 void MolBond::WXDelete(){if(0!=mpWXCrystObj) delete mpWXCrystObj;mpWXCrystObj=0;}
619 void MolBond::WXNotifyDelete(){mpWXCrystObj=0;}
620 #endif
621 //######################################################################
622 //
623 // MolBondAngle
624 //
625 //######################################################################
627  const REAL angle, const REAL sigma, const REAL delta,
628  Molecule &parent):
629 mAngle0(angle),mDelta(delta),mSigma(sigma),mpMol(&parent)
630 #ifdef __WX__CRYST__
631 ,mpWXCrystObj(0)
632 #endif
633 {
634  mvpAtom.push_back(&atom1);
635  mvpAtom.push_back(&atom2);
636  mvpAtom.push_back(&atom3);
637 }
638 
640 {
641 #ifdef __WX__CRYST__
642 this->WXDelete();
643 #endif
644 }
645 
646 const Molecule& MolBondAngle::GetMolecule()const{return *mpMol;}
647  Molecule& MolBondAngle::GetMolecule() {return *mpMol;}
648 
649 string MolBondAngle::GetName()const
650 {
651  return this->GetAtom1().GetName()+"-"
652  +this->GetAtom2().GetName()+"-"
653  +this->GetAtom3().GetName();
654 }
655 
656 void MolBondAngle::XMLOutput(ostream &os,int indent)const
657 {
658  VFN_DEBUG_ENTRY("MolBondAngle::XMLOutput()",4)
659  for(int i=0;i<indent;i++) os << " " ;
660  XMLCrystTag tag("BondAngle",false,true);
661  tag.AddAttribute("Atom1",this->GetAtom1().GetName());
662  tag.AddAttribute("Atom2",this->GetAtom2().GetName());
663  tag.AddAttribute("Atom3",this->GetAtom3().GetName());
664  {
665  stringstream ss;
666  ss.precision(os.precision());
667  ss <<mAngle0*RAD2DEG;
668  tag.AddAttribute("Angle",ss.str());
669  }
670  {
671  stringstream ss;
672  ss.precision(os.precision());
673  ss <<mDelta*RAD2DEG;
674  tag.AddAttribute("Delta",ss.str());
675  }
676  {
677  stringstream ss;
678  ss.precision(os.precision());
679  ss <<mSigma*RAD2DEG;
680  tag.AddAttribute("Sigma",ss.str());
681  }
682  os <<tag<<endl;
683  VFN_DEBUG_EXIT("MolBondAngle::XMLOutput()",4)
684 }
685 
686 void MolBondAngle::XMLInput(istream &is,const XMLCrystTag &tag)
687 {
688  VFN_DEBUG_ENTRY("MolBondAngle::XMLInput():",4)
689  mvpAtom.resize(3);
690  for(unsigned int i=0;i<tag.GetNbAttribute();i++)
691  {
692  if("Atom1"==tag.GetAttributeName(i))
693  {
694  mvpAtom[0]=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
695  }
696  if("Atom2"==tag.GetAttributeName(i))
697  {
698  mvpAtom[1]=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
699  }
700  if("Atom3"==tag.GetAttributeName(i))
701  {
702  mvpAtom[2]=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
703  }
704  if("Angle"==tag.GetAttributeName(i))
705  {
706  stringstream ss(tag.GetAttributeValue(i));
707  ss >>mAngle0;
708  mAngle0*=DEG2RAD;
709  }
710  if("Delta"==tag.GetAttributeName(i))
711  {
712  stringstream ss(tag.GetAttributeValue(i));
713  ss >>mDelta;
714  mDelta*=DEG2RAD;
715  }
716  if("Sigma"==tag.GetAttributeName(i))
717  {
718  stringstream ss(tag.GetAttributeValue(i));
719  ss >>mSigma;
720  mSigma*=DEG2RAD;
721  }
722  }
723  VFN_DEBUG_EXIT("MolBondAngle::XMLInput():",4)
724 }
725 REAL& MolBondAngle::Angle0()
726 {
727  return mAngle0;
728 }
729 REAL& MolBondAngle::AngleDelta(){return mDelta;}
730 REAL& MolBondAngle::AngleSigma(){return mSigma;}
731 
732 REAL MolBondAngle::GetAngle0()const{return mAngle0;}
733 REAL MolBondAngle::GetAngleDelta()const{return mDelta;}
734 REAL MolBondAngle::GetAngleSigma()const{return mSigma;}
735 
736 void MolBondAngle::SetAngle0(const REAL angle){mAngle0=angle;}
737 void MolBondAngle::SetAngleDelta(const REAL delta){mDelta=delta;}
738 void MolBondAngle::SetAngleSigma(const REAL sigma){mSigma=sigma;}
739 
740 REAL MolBondAngle::GetAngle()const
741 {
742  return GetBondAngle(this->GetAtom1(),this->GetAtom2(),this->GetAtom3());
743 }
744 
745 REAL MolBondAngle::GetLogLikelihood()const{return this->GetLogLikelihood(false,true);}
746 
747 REAL MolBondAngle::GetLogLikelihood(const bool calcDeriv, const bool recalc)const
748 {
749  if(!recalc) return mLLK;
750  VFN_DEBUG_ENTRY("MolBondAngle::GetLogLikelihood():",2)
751  //TAU_PROFILE("MolBondAngle::GetLogLikelihood()","REAL (bool,bool)",TAU_DEFAULT);
752  //const REAL angle=this->GetAngle();
753  const REAL x21=this->GetAtom1().GetX()-this->GetAtom2().GetX();
754  const REAL y21=this->GetAtom1().GetY()-this->GetAtom2().GetY();
755  const REAL z21=this->GetAtom1().GetZ()-this->GetAtom2().GetZ();
756  const REAL x23=this->GetAtom3().GetX()-this->GetAtom2().GetX();
757  const REAL y23=this->GetAtom3().GetY()-this->GetAtom2().GetY();
758  const REAL z23=this->GetAtom3().GetZ()-this->GetAtom2().GetZ();
759 
760  const REAL n1=sqrt(abs(x21*x21+y21*y21+z21*z21));
761  const REAL n3=sqrt(abs(x23*x23+y23*y23+z23*z23));
762  const REAL p=x21*x23+y21*y23+z21*z23;
763 
764  const REAL a0=p/(n1*n3+1e-10);
765  REAL angle;
766  if(a0>=1) angle=0;
767  else
768  {
769  if(a0<=-1) angle=M_PI;
770  else angle=acos(a0);
771  }
772 
773  if(calcDeriv)
774  {
775  const REAL s=1/(sqrt(1-a0*a0+1e-6));
776  const REAL s0=-s/(n1*n3+1e-10);
777  const REAL s1= s*p/(n3*n1*n1*n1+1e-10);
778  const REAL s3= s*p/(n1*n3*n3*n3+1e-10);
779  mDerivAtom1.x=s0*x23+s1*x21;
780  mDerivAtom1.y=s0*y23+s1*y21;
781  mDerivAtom1.z=s0*z23+s1*z21;
782 
783  mDerivAtom3.x=s0*x21+s3*x23;
784  mDerivAtom3.y=s0*y21+s3*y23;
785  mDerivAtom3.z=s0*z21+s3*z23;
786 
787  mDerivAtom2.x=-(mDerivAtom1.x+mDerivAtom3.x);
788  mDerivAtom2.y=-(mDerivAtom1.y+mDerivAtom3.y);
789  mDerivAtom2.z=-(mDerivAtom1.z+mDerivAtom3.z);
790  }
791 
792  if(mSigma<1e-6)
793  {
794  if(calcDeriv) mDerivLLKCoeff=0;
795  mLLK=0;
796  return 0;
797  }
798 
799  mLLK=angle-(mAngle0+mDelta);
800  if(mLLK>0)
801  {
802  mLLK/=mSigma;
803  #ifdef RESTRAINT_X2_X4_X6
804  const float mLLK2=mLLK*mLLK;
805  //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma;
806  //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2);
807  if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma;
808  mLLK=mLLK2*(1+mLLK2);
809  #else
810  if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma;
811  mLLK *= mLLK;
812  #endif
813  VFN_DEBUG_EXIT("MolBondAngle::GetLogLikelihood():",2)
814  return mLLK;
815  }
816  mLLK=angle-(mAngle0-mDelta);
817  if(mLLK<0)
818  {
819  mLLK/=mSigma;
820  #ifdef RESTRAINT_X2_X4_X6
821  const float mLLK2=mLLK*mLLK;
822  //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma;
823  //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2);
824  if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma;
825  mLLK=mLLK2*(1+mLLK2);
826  #else
827  if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma;
828  mLLK *= mLLK;
829  #endif
830  VFN_DEBUG_EXIT("MolBondAngle::GetLogLikelihood():",2)
831  return mLLK;
832  }
833  VFN_DEBUG_EXIT("MolBondAngle::GetLogLikelihood():",2)
834  if(calcDeriv) mDerivLLKCoeff=0;
835  mLLK=0;
836  return mLLK;
837 }
838 
839 REAL MolBondAngle::GetDeriv(const std::map<const MolAtom*,XYZ> &m,const bool llk)const
840 {
841  //TAU_PROFILE("MolBondAngle::GetDeriv()","REAL (mak,bool)",TAU_DEFAULT);
842  REAL d=0;
843  map<const MolAtom*,XYZ>::const_iterator pos;
844  pos=m.find(mvpAtom[0]);
845  if(pos!=m.end())
846  d+= pos->second.x*mDerivAtom1.x
847  +pos->second.y*mDerivAtom1.y
848  +pos->second.z*mDerivAtom1.z;
849  pos=m.find(mvpAtom[1]);
850  if(pos!=m.end())
851  d+= pos->second.x*mDerivAtom2.x
852  +pos->second.y*mDerivAtom2.y
853  +pos->second.z*mDerivAtom2.z;
854  pos=m.find(mvpAtom[2]);
855  if(pos!=m.end())
856  d+= pos->second.x*mDerivAtom3.x
857  +pos->second.y*mDerivAtom3.y
858  +pos->second.z*mDerivAtom3.z;
859  if(llk) return mDerivLLKCoeff*d;
860  return d;
861 }
862 
863 void MolBondAngle::CalcGradient(std::map<MolAtom*,XYZ> &m)const
864 {
865  this->GetLogLikelihood(true,true);
866  map<MolAtom*,XYZ>::iterator pos;
867  pos=m.find(mvpAtom[0]);
868  if(pos!=m.end())
869  {
870  pos->second.x+=mDerivLLKCoeff*mDerivAtom1.x;
871  pos->second.y+=mDerivLLKCoeff*mDerivAtom1.y;
872  pos->second.z+=mDerivLLKCoeff*mDerivAtom1.z;
873  }
874  pos=m.find(mvpAtom[1]);
875  if(pos!=m.end())
876  {
877  pos->second.x+=mDerivLLKCoeff*mDerivAtom2.x;
878  pos->second.y+=mDerivLLKCoeff*mDerivAtom2.y;
879  pos->second.z+=mDerivLLKCoeff*mDerivAtom2.z;
880  }
881  pos=m.find(mvpAtom[2]);
882  if(pos!=m.end())
883  {
884  pos->second.x+=mDerivLLKCoeff*mDerivAtom3.x;
885  pos->second.y+=mDerivLLKCoeff*mDerivAtom3.y;
886  pos->second.z+=mDerivLLKCoeff*mDerivAtom3.z;
887  }
888  #if 0
889  // Display gradient - for tests
890  cout<<this->GetName()<<" :LLK"<<endl;
891  for(map<MolAtom*,XYZ>::const_iterator pos=m.begin();pos!=m.end();++pos)
892  {
893  char buf[100];
894  sprintf(buf,"%10s Grad LLK= (%8.3f %8.3f %8.3f)",
895  pos->first->GetName().c_str(),pos->second.x,pos->second.y,pos->second.z);
896  cout<<buf<<endl;
897  }
898  #endif
899 }
900 
901 const MolAtom& MolBondAngle::GetAtom1()const{return *(mvpAtom[0]);}
902 const MolAtom& MolBondAngle::GetAtom2()const{return *(mvpAtom[1]);}
903 const MolAtom& MolBondAngle::GetAtom3()const{return *(mvpAtom[2]);}
904 MolAtom& MolBondAngle::GetAtom1(){return *(mvpAtom[0]);}
905 MolAtom& MolBondAngle::GetAtom2(){return *(mvpAtom[1]);}
906 MolAtom& MolBondAngle::GetAtom3(){return *(mvpAtom[2]);}
907 void MolBondAngle::SetAtom1(MolAtom& at){mvpAtom[0]=&at;}
908 void MolBondAngle::SetAtom2(MolAtom& at){mvpAtom[1]=&at;}
909 void MolBondAngle::SetAtom3(MolAtom& at){mvpAtom[2]=&at;}
910 //MolAtom& MolBondAngle::GetAtom1(){return *(mvpAtom[0]);}
911 //MolAtom& MolBondAngle::GetAtom2(){return *(mvpAtom[1]);}
912 //MolAtom& MolBondAngle::GetAtom3(){return *(mvpAtom[2]);}
913 #ifdef __WX__CRYST__
914 WXCrystObjBasic* MolBondAngle::WXCreate(wxWindow* parent)
915 {
916  VFN_DEBUG_ENTRY("MolBondAngle::WXCreate()",5)
917  mpWXCrystObj=new WXMolBondAngle(parent,this);
918  VFN_DEBUG_EXIT("MolBondAngle::WXCreate()",5)
919  return mpWXCrystObj;
920 }
921 WXCrystObjBasic* MolBondAngle::WXGet(){return mpWXCrystObj;}
922 void MolBondAngle::WXDelete(){if(0!=mpWXCrystObj) delete mpWXCrystObj;mpWXCrystObj=0;}
923 void MolBondAngle::WXNotifyDelete(){mpWXCrystObj=0;}
924 #endif
925 //######################################################################
926 //
927 // MolDihedralAngle
928 //
929 //######################################################################
931  MolAtom &atom3, MolAtom &atom4,
932  const REAL angle, const REAL sigma, const REAL delta,
933  Molecule &parent):
934 mAngle0(angle),mDelta(delta),mSigma(sigma),mpMol(&parent)
935 #ifdef __WX__CRYST__
936 ,mpWXCrystObj(0)
937 #endif
938 {
939  VFN_DEBUG_ENTRY("MolDihedralAngle::MolDihedralAngle()",5)
940  mvpAtom.push_back(&atom1);
941  mvpAtom.push_back(&atom2);
942  mvpAtom.push_back(&atom3);
943  mvpAtom.push_back(&atom4);
944  // We want the angle in [-pi;pi]
945  mAngle0=fmod((REAL)mAngle0,(REAL)(2*M_PI));
946  if(mAngle0<(-M_PI)) mAngle0+=2*M_PI;
947  if(mAngle0>M_PI) mAngle0-=2*M_PI;
948  VFN_DEBUG_EXIT("MolDihedralAngle::MolDihedralAngle()",5)
949 }
950 
952 {
953 #ifdef __WX__CRYST__
954 this->WXDelete();
955 #endif
956 }
957 
958 const Molecule& MolDihedralAngle::GetMolecule()const{return *mpMol;}
959  Molecule& MolDihedralAngle::GetMolecule() {return *mpMol;}
960 
961 string MolDihedralAngle::GetName()const
962 {
963  return this->GetAtom1().GetName()+"-"
964  +this->GetAtom2().GetName()+"-"
965  +this->GetAtom3().GetName()+"-"
966  +this->GetAtom4().GetName();
967 }
968 
969 void MolDihedralAngle::XMLOutput(ostream &os,int indent)const
970 {
971  VFN_DEBUG_ENTRY("MolDihedralAngle::XMLOutput()",4)
972  for(int i=0;i<indent;i++) os << " " ;
973  XMLCrystTag tag("DihedralAngle",false,true);
974  tag.AddAttribute("Atom1",this->GetAtom1().GetName());
975  tag.AddAttribute("Atom2",this->GetAtom2().GetName());
976  tag.AddAttribute("Atom3",this->GetAtom3().GetName());
977  tag.AddAttribute("Atom4",this->GetAtom4().GetName());
978  {
979  stringstream ss;
980  ss.precision(os.precision());
981  ss <<mAngle0*RAD2DEG;
982  tag.AddAttribute("Angle",ss.str());
983  }
984  {
985  stringstream ss;
986  ss.precision(os.precision());
987  ss <<mDelta*RAD2DEG;
988  tag.AddAttribute("Delta",ss.str());
989  }
990  {
991  stringstream ss;
992  ss.precision(os.precision());
993  ss <<mSigma*RAD2DEG;
994  tag.AddAttribute("Sigma",ss.str());
995  }
996  os <<tag<<endl;
997  VFN_DEBUG_EXIT("MolDihedralAngle::XMLOutput()",4)
998 }
999 
1000 void MolDihedralAngle::XMLInput(istream &is,const XMLCrystTag &tag)
1001 {
1002  VFN_DEBUG_ENTRY("MolDihedralAngle::XMLInput():",5)
1003  mvpAtom.resize(4);
1004  for(unsigned int i=0;i<tag.GetNbAttribute();i++)
1005  {
1006  if("Atom1"==tag.GetAttributeName(i))
1007  {
1008  mvpAtom[0]=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
1009  }
1010  if("Atom2"==tag.GetAttributeName(i))
1011  {
1012  mvpAtom[1]=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
1013  }
1014  if("Atom3"==tag.GetAttributeName(i))
1015  {
1016  mvpAtom[2]=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
1017  }
1018  if("Atom4"==tag.GetAttributeName(i))
1019  {
1020  mvpAtom[3]=&(mpMol->GetAtom(tag.GetAttributeValue(i)));
1021  }
1022  if("Angle"==tag.GetAttributeName(i))
1023  {
1024  stringstream ss(tag.GetAttributeValue(i));
1025  ss >>mAngle0;
1026  mAngle0*=DEG2RAD;
1027  }
1028  if("Delta"==tag.GetAttributeName(i))
1029  {
1030  stringstream ss(tag.GetAttributeValue(i));
1031  ss >>mDelta;
1032  mDelta*=DEG2RAD;
1033  }
1034  if("Sigma"==tag.GetAttributeName(i))
1035  {
1036  stringstream ss(tag.GetAttributeValue(i));
1037  ss >>mSigma;
1038  mSigma*=DEG2RAD;
1039  }
1040  }
1041  VFN_DEBUG_EXIT("MolDihedralAngle::XMLInput():",5)
1042 }
1043 
1044 REAL MolDihedralAngle::GetAngle()const
1045 {
1046  //Get the angle [2pi] closest to the restraint
1047  const REAL angle=GetDihedralAngle(this->GetAtom1(),this->GetAtom2(),this->GetAtom3(),this->GetAtom4());
1048  if((angle-mAngle0)>M_PI) return angle-2*M_PI;
1049  else if((angle-mAngle0)<(-M_PI)) return angle+2*M_PI;
1050 
1051  return angle;
1052 }
1053 
1054 REAL& MolDihedralAngle::Angle0(){return mAngle0;}
1055 REAL& MolDihedralAngle::AngleDelta(){return mDelta;}
1056 REAL& MolDihedralAngle::AngleSigma(){return mSigma;}
1057 
1058 REAL MolDihedralAngle::GetAngle0()const{return mAngle0;}
1059 REAL MolDihedralAngle::GetAngleDelta()const{return mDelta;}
1060 REAL MolDihedralAngle::GetAngleSigma()const{return mSigma;}
1061 
1062 void MolDihedralAngle::SetAngle0(const REAL angle){mAngle0=angle;}
1063 void MolDihedralAngle::SetAngleDelta(const REAL delta){mDelta=delta;}
1064 void MolDihedralAngle::SetAngleSigma(const REAL sigma){mSigma=sigma;}
1065 
1066 REAL MolDihedralAngle::GetLogLikelihood()const{return this->GetLogLikelihood(false,true);}
1067 
1068 REAL MolDihedralAngle::GetLogLikelihood(const bool calcDeriv, const bool recalc)const
1069 {
1070  if(!recalc) return mLLK;
1071  VFN_DEBUG_ENTRY("MolDihedralAngle::GetLogLikelihood():",2)
1072  //TAU_PROFILE("MolDihedralAngle::GetLogLikelihood()","REAL (bool,bool)",TAU_DEFAULT);
1073  const REAL x21=this->GetAtom1().GetX()-this->GetAtom2().GetX();
1074  const REAL y21=this->GetAtom1().GetY()-this->GetAtom2().GetY();
1075  const REAL z21=this->GetAtom1().GetZ()-this->GetAtom2().GetZ();
1076 
1077  const REAL x34=this->GetAtom4().GetX()-this->GetAtom3().GetX();
1078  const REAL y34=this->GetAtom4().GetY()-this->GetAtom3().GetY();
1079  const REAL z34=this->GetAtom4().GetZ()-this->GetAtom3().GetZ();
1080 
1081  const REAL x23=this->GetAtom3().GetX()-this->GetAtom2().GetX();
1082  const REAL y23=this->GetAtom3().GetY()-this->GetAtom2().GetY();
1083  const REAL z23=this->GetAtom3().GetZ()-this->GetAtom2().GetZ();
1084 
1085  // v21 x v23
1086  const REAL x123= y21*z23-z21*y23;
1087  const REAL y123= z21*x23-x21*z23;
1088  const REAL z123= x21*y23-y21*x23;
1089 
1090  // v32 x v34 (= -v23 x v34)
1091  const REAL x234= -(y23*z34-z23*y34);
1092  const REAL y234= -(z23*x34-x23*z34);
1093  const REAL z234= -(x23*y34-y23*x34);
1094 
1095  const REAL n123= sqrt(x123*x123+y123*y123+z123*z123+1e-7);
1096  const REAL n234= sqrt(x234*x234+y234*y234+z234*z234+1e-6);
1097 
1098  const REAL p=x123*x234+y123*y234+z123*z234;
1099  const REAL a0=p/(n123*n234+1e-10);
1100  REAL angle;
1101  if(a0>= 1) angle=0;
1102  else
1103  {
1104  if(a0<=-1) angle=M_PI;
1105  else angle=acos(a0);
1106  }
1107  REAL sgn=1.0;
1108  if((x21*x34 + y21*y34 + z21*z34)<0) {angle=-angle;sgn=-1;}
1109 
1110 
1111  if(calcDeriv)
1112  {
1113  const REAL s=sgn/(sqrt(1-a0*a0+1e-6));
1114  const REAL s0=-s/(n123*n234+1e-10);
1115  const REAL s1= s*p/(n234*n123*n123*n123+1e-10);
1116  const REAL s3= s*p/(n123*n234*n234*n234+1e-10);
1117  mDerivAtom1.x=s0*(-z23*y234+y23*z234)+s1*(-z23*y123+y23*z123);
1118  mDerivAtom1.y=s0*(-x23*z234+z23*x234)+s1*(-x23*z123+z23*x123);
1119  mDerivAtom1.z=s0*(-y23*x234+x23*y234)+s1*(-y23*x123+x23*y123);
1120 
1121  mDerivAtom4.x=s0*(-z23*y123+y23*z123)+s3*(-z23*y234+y23*z234);
1122  mDerivAtom4.y=s0*(-x23*z123+z23*x123)+s3*(-x23*z234+z23*x234);
1123  mDerivAtom4.z=s0*(-y23*x123+x23*y123)+s3*(-y23*x234+x23*y234);
1124 
1125  mDerivAtom2.x=s0*((z23-z21)*y234-y123*z34+(y21-y23)*z234+z123*y34)+s1*(y123*(z23-z21)+z123*(y21-y23))+s3*(-y234*z34+z234*y34);
1126  mDerivAtom2.y=s0*((x23-x21)*z234-z123*x34+(z21-z23)*x234+x123*z34)+s1*(z123*(x23-x21)+x123*(z21-z23))+s3*(-z234*x34+x234*z34);
1127  mDerivAtom2.z=s0*((y23-y21)*x234-x123*y34+(x21-x23)*y234+y123*x34)+s1*(x123*(y23-y21)+y123*(x21-x23))+s3*(-x234*y34+y234*x34);
1128 
1129  mDerivAtom3.x=-(mDerivAtom1.x+mDerivAtom2.x+mDerivAtom4.x);
1130  mDerivAtom3.y=-(mDerivAtom1.y+mDerivAtom2.y+mDerivAtom4.y);
1131  mDerivAtom3.z=-(mDerivAtom1.z+mDerivAtom2.z+mDerivAtom4.z);
1132  }
1133 
1134  if(mSigma<1e-6)
1135  {
1136  if(calcDeriv) mDerivLLKCoeff=0;
1137  mLLK=0;
1138  return mLLK;
1139  }
1140  mLLK=angle-(mAngle0+mDelta);
1141  if(mLLK<(-M_PI)) mLLK += 2*M_PI;
1142  if(mLLK> M_PI ) mLLK -= 2*M_PI;
1143  if(mLLK>0)
1144  {
1145  mLLK/=mSigma;
1146  #ifdef RESTRAINT_X2_X4_X6
1147  const float mLLK2=mLLK*mLLK;
1148  //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma;
1149  //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2);
1150  if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma;
1151  mLLK=mLLK2*(1+mLLK2);
1152  #else
1153  if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma;
1154  mLLK *= mLLK;
1155  #endif
1156  VFN_DEBUG_EXIT("MolDihedralAngle::GetLogLikelihood():",2)
1157  return mLLK;
1158  }
1159  mLLK=angle-(mAngle0-mDelta);
1160  if(mLLK<(-M_PI)) mLLK += 2*M_PI;
1161  if(mLLK> M_PI ) mLLK -= 2*M_PI;
1162  if(mLLK<0)
1163  {
1164  mLLK/=mSigma;
1165  #ifdef RESTRAINT_X2_X4_X6
1166  const float mLLK2=mLLK*mLLK;
1167  //if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2+6*mLLK2*mLLK2)/mSigma;
1168  //mLLK=mLLK2*(1+mLLK2+mLLK2*mLLK2);
1169  if(calcDeriv) mDerivLLKCoeff=(2*mLLK+4*mLLK2)/mSigma;
1170  mLLK=mLLK2*(1+mLLK2);
1171  #else
1172  if(calcDeriv) mDerivLLKCoeff=2*mLLK/mSigma;
1173  mLLK *= mLLK;
1174  #endif
1175  VFN_DEBUG_EXIT("MolDihedralAngle::GetLogLikelihood():",2)
1176  return mLLK;
1177  }
1178  VFN_DEBUG_EXIT("MolDihedralAngle::GetLogLikelihood():",2)
1179  if(calcDeriv) mDerivLLKCoeff=0;
1180  mLLK=0;
1181  return 0;
1182 }
1183 
1184 REAL MolDihedralAngle::GetDeriv(const std::map<const MolAtom*,XYZ> &m,const bool llk)const
1185 {
1186  //TAU_PROFILE("MolDihedralAngle::GetDeriv()","REAL (mak,bool)",TAU_DEFAULT);
1187  REAL d=0;
1188  map<const MolAtom*,XYZ>::const_iterator pos;
1189  pos=m.find(mvpAtom[0]);
1190  if(pos!=m.end())
1191  d+= pos->second.x*mDerivAtom1.x
1192  +pos->second.y*mDerivAtom1.y
1193  +pos->second.z*mDerivAtom1.z;
1194  pos=m.find(mvpAtom[1]);
1195  if(pos!=m.end())
1196  d+= pos->second.x*mDerivAtom2.x
1197  +pos->second.y*mDerivAtom2.y
1198  +pos->second.z*mDerivAtom2.z;
1199  pos=m.find(mvpAtom[2]);
1200  if(pos!=m.end())
1201  d+= pos->second.x*mDerivAtom3.x
1202  +pos->second.y*mDerivAtom3.y
1203  +pos->second.z*mDerivAtom3.z;
1204  pos=m.find(mvpAtom[3]);
1205  if(pos!=m.end())
1206  d+= pos->second.x*mDerivAtom4.x
1207  +pos->second.y*mDerivAtom4.y
1208  +pos->second.z*mDerivAtom4.z;
1209  if(llk) return mDerivLLKCoeff*d;
1210  return d;
1211 }
1212 
1213 void MolDihedralAngle::CalcGradient(std::map<MolAtom*,XYZ> &m)const
1214 {
1215  this->GetLogLikelihood(true,true);
1216  map<MolAtom*,XYZ>::iterator pos;
1217  pos=m.find(mvpAtom[0]);
1218  if(pos!=m.end())
1219  {
1220  pos->second.x+=mDerivLLKCoeff*mDerivAtom1.x;
1221  pos->second.y+=mDerivLLKCoeff*mDerivAtom1.y;
1222  pos->second.z+=mDerivLLKCoeff*mDerivAtom1.z;
1223  }
1224  pos=m.find(mvpAtom[1]);
1225  if(pos!=m.end())
1226  {
1227  pos->second.x+=mDerivLLKCoeff*mDerivAtom2.x;
1228  pos->second.y+=mDerivLLKCoeff*mDerivAtom2.y;
1229  pos->second.z+=mDerivLLKCoeff*mDerivAtom2.z;
1230  }
1231  pos=m.find(mvpAtom[2]);
1232  if(pos!=m.end())
1233  {
1234  pos->second.x+=mDerivLLKCoeff*mDerivAtom3.x;
1235  pos->second.y+=mDerivLLKCoeff*mDerivAtom3.y;
1236  pos->second.z+=mDerivLLKCoeff*mDerivAtom3.z;
1237  }
1238  pos=m.find(mvpAtom[3]);
1239  if(pos!=m.end())
1240  {
1241  pos->second.x+=mDerivLLKCoeff*mDerivAtom4.x;
1242  pos->second.y+=mDerivLLKCoeff*mDerivAtom4.y;
1243  pos->second.z+=mDerivLLKCoeff*mDerivAtom4.z;
1244  }
1245  #if 0
1246  // Display gradient - for tests
1247  cout<<this->GetName()<<" :LLK"<<endl;
1248  for(map<MolAtom*,XYZ>::const_iterator pos=m.begin();pos!=m.end();++pos)
1249  {
1250  char buf[100];
1251  sprintf(buf,"%10s Grad LLK= (%8.3f %8.3f %8.3f)",
1252  pos->first->GetName().c_str(),pos->second.x,pos->second.y,pos->second.z);
1253  cout<<buf<<endl;
1254  }
1255  #endif
1256 }
1257 
1258 const MolAtom& MolDihedralAngle::GetAtom1()const{return *(mvpAtom[0]);}
1259 const MolAtom& MolDihedralAngle::GetAtom2()const{return *(mvpAtom[1]);}
1260 const MolAtom& MolDihedralAngle::GetAtom3()const{return *(mvpAtom[2]);}
1261 const MolAtom& MolDihedralAngle::GetAtom4()const{return *(mvpAtom[3]);}
1262 void MolDihedralAngle::SetAtom1(MolAtom& at){mvpAtom[0]=&at;}
1263 void MolDihedralAngle::SetAtom2(MolAtom& at){mvpAtom[1]=&at;}
1264 void MolDihedralAngle::SetAtom3(MolAtom& at){mvpAtom[2]=&at;}
1265 void MolDihedralAngle::SetAtom4(MolAtom& at){mvpAtom[3]=&at;}
1266 MolAtom& MolDihedralAngle::GetAtom1(){return *(mvpAtom[0]);}
1267 MolAtom& MolDihedralAngle::GetAtom2(){return *(mvpAtom[1]);}
1268 MolAtom& MolDihedralAngle::GetAtom3(){return *(mvpAtom[2]);}
1269 MolAtom& MolDihedralAngle::GetAtom4(){return *(mvpAtom[3]);}
1270 #ifdef __WX__CRYST__
1271 WXCrystObjBasic* MolDihedralAngle::WXCreate(wxWindow* parent)
1272 {
1273  VFN_DEBUG_ENTRY("MolDihedralAngle::WXCreate()",5)
1274  mpWXCrystObj=new WXMolDihedralAngle(parent,this);
1275  VFN_DEBUG_EXIT("MolDihedralAngle::WXCreate()",5)
1276  return mpWXCrystObj;
1277 }
1278 WXCrystObjBasic* MolDihedralAngle::WXGet(){return mpWXCrystObj;}
1279 void MolDihedralAngle::WXDelete(){if(0!=mpWXCrystObj) delete mpWXCrystObj;mpWXCrystObj=0;}
1280 void MolDihedralAngle::WXNotifyDelete(){mpWXCrystObj=0;}
1281 #endif
1282 //######################################################################
1283 //
1284 // RigidGroup
1285 //
1286 //######################################################################
1287 string RigidGroup::GetName()const
1288 {
1289  set<MolAtom *>::const_iterator at=this->begin();
1290  string name=(*at++)->GetName();
1291  for(;at!=this->end();++at) name+=", "+(*at)->GetName();
1292  return name;
1293 }
1294 //######################################################################
1295 //
1296 // MolRing
1297 //
1298 //######################################################################
1299 MolRing::MolRing()
1300 {}
1301 
1302 const std::list<MolAtom*>& MolRing::GetAtomList()const
1303 {return mvpAtom;}
1304 
1305 std::list<MolAtom*>& MolRing::GetAtomList()
1306 {return mvpAtom;}
1307 //######################################################################
1308 //
1309 // Quaternion
1310 //
1311 //######################################################################
1313 mQ0(1),mQ1(0),mQ2(0),mQ3(0),mIsUniQuaternion(true)
1314 {
1315  VFN_DEBUG_MESSAGE("Quaternion::Quaternion()",5)
1316 }
1317 
1319  const REAL q1,
1320  const REAL q2,
1321  const REAL q3,
1322  bool unit):
1323 mQ0(q0),mQ1(q1),mQ2(q2),mQ3(q3),mIsUniQuaternion(unit)
1324 {
1325  VFN_DEBUG_MESSAGE("Quaternion::Quaternion()",5)
1326  if(unit) this->Normalize();
1327 }
1328 
1329 Quaternion::~Quaternion()
1330 {
1331  VFN_DEBUG_MESSAGE("Quaternion::~Quaternion()",5)
1332 }
1333 
1335  const REAL v1,
1336  const REAL v2,
1337  const REAL v3)
1338 {
1339  VFN_DEBUG_MESSAGE("Quaternion::RotationQuaternion()",4)
1340  const REAL s=sin(ang/2.)/sqrt(v1*v1+v2*v2+v3*v3+1e-7);
1341  return Quaternion(cos(ang/2.),s*v1,s*v2,s*v3,
1342  true);
1343 }
1344 
1346 {
1347  return Quaternion(mQ0,-mQ1,-mQ2,-mQ3);
1348 }
1350 {
1351  // http://www.cs.berkeley.edu/~laura/cs184/quat/quaternion.html
1352  return Quaternion
1353  (this->Q0()*q.Q0()-this->Q1()*q.Q1()-this->Q2()*q.Q2()-this->Q3()*q.Q3(),
1354  this->Q0()*q.Q1()+this->Q1()*q.Q0()+this->Q2()*q.Q3()-this->Q3()*q.Q2(),
1355  this->Q0()*q.Q2()-this->Q1()*q.Q3()+this->Q2()*q.Q0()+this->Q3()*q.Q1(),
1356  this->Q0()*q.Q3()+this->Q1()*q.Q2()-this->Q2()*q.Q1()+this->Q3()*q.Q0(),false);
1357 }
1358 
1359 void Quaternion::operator*=(const Quaternion &q)
1360 {
1361  //cout<<"Quaternion::operator*= before:";this->XMLOutput(cout);
1362  //cout<<"Quaternion::operator*= by :";q.XMLOutput(cout);
1363  const REAL q1=this->Q0()*q.Q1()+this->Q1()*q.Q0()+this->Q2()*q.Q3()-this->Q3()*q.Q2();
1364  const REAL q2=this->Q0()*q.Q2()+this->Q2()*q.Q0()-this->Q1()*q.Q3()+this->Q3()*q.Q1();
1365  const REAL q3=this->Q0()*q.Q3()+this->Q3()*q.Q0()+this->Q1()*q.Q2()-this->Q2()*q.Q1();
1366  this->Q0()= this->Q0()*q.Q0()-this->Q1()*q.Q1()-this->Q2()*q.Q2()-this->Q3()*q.Q3();
1367  this->Q1()=q1;
1368  this->Q2()=q2;
1369  this->Q3()=q3;
1370  this->Normalize();
1371  //cout<<"Quaternion::operator*= after :";this->XMLOutput(cout);
1372 }
1373 
1374 void Quaternion::XMLOutput(ostream &os,int indent)const
1375 {
1376  VFN_DEBUG_ENTRY("Quaternion::XMLOutput()",4)
1377  for(int i=0;i<indent;i++) os << " " ;
1378  XMLCrystTag tag("Quaternion",false,true);
1379  //#error "which atoms for this bond ?"
1380  {
1381  stringstream ss;
1382  ss.precision(os.precision());
1383  ss <<mQ0;
1384  tag.AddAttribute("Q0",ss.str());
1385  }
1386  {
1387  stringstream ss;
1388  ss.precision(os.precision());
1389  ss <<mQ1;
1390  tag.AddAttribute("Q1",ss.str());
1391  }
1392  {
1393  stringstream ss;
1394  ss.precision(os.precision());
1395  ss <<mQ2;
1396  tag.AddAttribute("Q2",ss.str());
1397  }
1398  {
1399  stringstream ss;
1400  ss.precision(os.precision());
1401  ss <<mQ3;
1402  tag.AddAttribute("Q3",ss.str());
1403  }
1404  {
1405  stringstream ss;
1406  ss.precision(os.precision());
1407  ss <<mIsUniQuaternion;
1408  tag.AddAttribute("IsUnitQuaternion",ss.str());
1409  }
1410  os <<tag<<endl;
1411  VFN_DEBUG_EXIT("Quaternion::XMLOutput()",4)
1412 }
1413 
1414 void Quaternion::XMLInput(istream &is,const XMLCrystTag &tag)
1415 {
1416  VFN_DEBUG_ENTRY("Quaternion::XMLInput()",5)
1417  for(unsigned int i=0;i<tag.GetNbAttribute();i++)
1418  {
1419  if("Q0"==tag.GetAttributeName(i))
1420  {
1421  stringstream ss(tag.GetAttributeValue(i));
1422  ss >>mQ0;
1423  }
1424  if("Q1"==tag.GetAttributeName(i))
1425  {
1426  stringstream ss(tag.GetAttributeValue(i));
1427  ss >>mQ1;
1428  }
1429  if("Q2"==tag.GetAttributeName(i))
1430  {
1431  stringstream ss(tag.GetAttributeValue(i));
1432  ss >>mQ2;
1433  }
1434  if("Q3"==tag.GetAttributeName(i))
1435  {
1436  stringstream ss(tag.GetAttributeValue(i));
1437  ss >>mQ3;
1438  }
1439  if("IsUnitQuaternion"==tag.GetAttributeName(i))
1440  {
1441  stringstream ss(tag.GetAttributeValue(i));
1442  ss >>mIsUniQuaternion;
1443  }
1444  }
1445  if(mIsUniQuaternion) this->Normalize();
1446  VFN_DEBUG_EXIT("Quaternion::XMLInput()",5)
1447 }
1448 
1449 void Quaternion::RotateVector(REAL &v1,REAL &v2, REAL &v3)const
1450 {
1451  #if 0
1452  //#error P should not be a _UNIT_ quaternion...
1453  Quaternion P(0,v1,v2,v3,false);
1454  //cout<<"RotQuat:(n="<<this->GetNorm()<<")";this->XMLOutput(cout);
1455  //cout<<"before :(n="<<P.GetNorm()<<")";P.XMLOutput(cout);
1456  P= (*this)* P * this->GetConjugate();
1457  //cout<<"rotated:(n="<<P.GetNorm()<<")";P.XMLOutput(cout);
1458  v1=P.Q1();
1459  v2=P.Q2();
1460  v3=P.Q3();
1461  #endif
1462  const REAL p0=-mQ1*v1 - mQ2*v2 - mQ3*v3;
1463  const REAL p1= mQ0*v1 + mQ2*v3 - mQ3*v2;
1464  const REAL p2= mQ0*v2 - mQ1*v3 + mQ3*v1;
1465  const REAL p3= mQ0*v3 + mQ1*v2 - mQ2*v1;
1466 
1467  v1 =-p0*mQ1 + p1*mQ0 - p2*mQ3 + p3*mQ2;
1468  v2 =-p0*mQ2 + p2*mQ0 + p1*mQ3 - p3*mQ1;
1469  v3 =-p0*mQ3 + p3*mQ0 - p1*mQ2 + p2*mQ1;
1470 }
1471 
1473 {
1474  const REAL norm=sqrt( this->Q0()*this->Q0()
1475  +this->Q1()*this->Q1()
1476  +this->Q2()*this->Q2()
1477  +this->Q3()*this->Q3());
1478  mQ0 /= norm;
1479  mQ1 /= norm;
1480  mQ2 /= norm;
1481  mQ3 /= norm;
1482 }
1483 REAL Quaternion::GetNorm()const
1484 {return sqrt( this->Q0()*this->Q0()
1485  +this->Q1()*this->Q1()
1486  +this->Q2()*this->Q2()
1487  +this->Q3()*this->Q3());}
1488 
1489 const REAL& Quaternion::Q0()const{return mQ0;}
1490 const REAL& Quaternion::Q1()const{return mQ1;}
1491 const REAL& Quaternion::Q2()const{return mQ2;}
1492 const REAL& Quaternion::Q3()const{return mQ3;}
1493 REAL& Quaternion::Q0(){return mQ0;}
1494 REAL& Quaternion::Q1(){return mQ1;}
1495 REAL& Quaternion::Q2(){return mQ2;}
1496 REAL& Quaternion::Q3(){return mQ3;}
1497 //######################################################################
1498 //
1499 // Molecule Stretch Modes
1500 //
1501 //######################################################################
1502 StretchMode::~StretchMode(){}
1503 
1505  const MolBond *pBond):
1506 mpAtom0(&at0),mpAtom1(&at1),mpBond(pBond)
1507 {
1508  mBaseAmplitude=0.1;
1509  mpMol = &(at1.GetMolecule());
1510 }
1511 
1512 StretchModeBondLength::~StretchModeBondLength(){}
1513 
1514 void StretchModeBondLength::CalcDeriv(const bool derivllk)const
1515 {
1516  //TAU_PROFILE("StretchModeBondLength::CalcDeriv()","void ()",TAU_DEFAULT);
1517  // Derivative of the atom positions
1518  //mDerivXYZ.clear();
1519  REAL dx=mpAtom1->GetX()-mpAtom0->GetX();
1520  REAL dy=mpAtom1->GetY()-mpAtom0->GetY();
1521  REAL dz=mpAtom1->GetZ()-mpAtom0->GetZ();
1522  const REAL n=sqrt(dx*dx+dy*dy+dz*dz+1e-7);
1523  if(n<1e-6) return;//:KLUDGE: ?
1524  dx/=n;
1525  dy/=n;
1526  dz/=n;
1527  for(set<MolAtom *>::const_iterator pos=mvTranslatedAtomList.begin();
1528  pos!=mvTranslatedAtomList.end();++pos)
1529  {
1530  XYZ *const p=&(mDerivXYZ[*pos]);
1531  p->x=dx;
1532  p->y=dy;
1533  p->z=dz;
1534  }
1535  // Derivative of the LLK
1536  if(derivllk)
1537  {
1538  mLLKDeriv=0;
1539  for(map<const MolBond*,REAL>::const_iterator pos=this->mvpBrokenBond.begin();
1540  pos!=this->mvpBrokenBond.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1541  for(map<const MolBondAngle*,REAL>::const_iterator pos=this->mvpBrokenBondAngle.begin();
1542  pos!=this->mvpBrokenBondAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1543  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=this->mvpBrokenDihedralAngle.begin();
1544  pos!=this->mvpBrokenDihedralAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1545  }
1546 }
1547 
1548 void StretchModeBondLength::Print(ostream &os,bool full)const
1549 {
1550  cout<<mpAtom0->GetName()<<"-"<<mpAtom1->GetName();
1551  if(full)
1552  {
1553  cout<<", Translated Atoms:";
1554  for(set<MolAtom*>::const_iterator atom=mvTranslatedAtomList.begin();
1555  atom!=mvTranslatedAtomList.end();++atom)
1556  {
1557  cout<<(*atom)->GetName()<<",";
1558  }
1559  }
1560 }
1561 
1562 void StretchModeBondLength::Stretch(const REAL amplitude,
1563  const bool keepCenter)
1564 {
1565  REAL dx=mpAtom1->GetX()-mpAtom0->GetX();
1566  REAL dy=mpAtom1->GetY()-mpAtom0->GetY();
1567  REAL dz=mpAtom1->GetZ()-mpAtom0->GetZ();
1568  const REAL l=sqrt(dx*dx+dy*dy+dz*dz+1e-7);
1569  if(l<1e-6) return;// :KLUDGE:
1570  const REAL change=amplitude/l;
1571  dx*=change;
1572  dy*=change;
1573  dz*=change;
1574  mpMol->TranslateAtomGroup(mvTranslatedAtomList,dx,dy,dz,keepCenter);
1575 }
1576 
1577 void StretchModeBondLength::RandomStretch(const REAL amplitude,
1578  const bool keepCenter)
1579 {
1580  mpMol->BondLengthRandomChange(*this,amplitude,keepCenter);
1581 }
1582 
1584  const MolBondAngle *pBondAngle):
1585 mpAtom0(&at0),mpAtom1(&at1),mpAtom2(&at2),mpBondAngle(pBondAngle)
1586 {
1587  mBaseAmplitude=M_PI*0.02;
1588  mpMol = &(at1.GetMolecule());
1589 }
1590 
1591 StretchModeBondAngle::~StretchModeBondAngle(){}
1592 
1593 void StretchModeBondAngle::CalcDeriv(const bool derivllk)const
1594 {
1595  //TAU_PROFILE("StretchModeBondAngle::CalcDeriv()","void ()",TAU_DEFAULT);
1596  // Derivative of the atomic positions
1597  const REAL x1=mpAtom1->GetX(),
1598  y1=mpAtom1->GetY(),
1599  z1=mpAtom1->GetZ();
1600 
1601  const REAL dx10=mpAtom0->GetX()-x1,
1602  dy10=mpAtom0->GetY()-y1,
1603  dz10=mpAtom0->GetZ()-z1,
1604  dx12=mpAtom2->GetX()-x1,
1605  dy12=mpAtom2->GetY()-y1,
1606  dz12=mpAtom2->GetZ()-z1;
1607 
1608  REAL vx=dy10*dz12-dz10*dy12,
1609  vy=dz10*dx12-dx10*dz12,
1610  vz=dx10*dy12-dy10*dx12;
1611  //const REAL n=sqrt((dx10*dx10+dy10*dy10+dz10*dz10)*(dx12*dx12+dy12*dy12+dz12*dz12))+1e-10;
1612  const REAL n=sqrt(vx*vx+vy*vy+vz*vz+1e-10);
1613  vx/=n;
1614  vy/=n;
1615  vz/=n;
1616 
1617  if(n<1e-6)
1618  {
1619  mDerivXYZ.clear();
1620  return;//:KLUDGE: ?
1621  }
1622 
1623  for(set<MolAtom *>::const_iterator pos=mvRotatedAtomList.begin();
1624  pos!=mvRotatedAtomList.end();++pos)
1625  {
1626  XYZ *const p=&(mDerivXYZ[*pos]);
1627  const REAL x=(*pos)->GetX()-x1,
1628  y=(*pos)->GetY()-y1,
1629  z=(*pos)->GetZ()-z1;
1630  p->x=z*vy-y*vz;
1631  p->y=x*vz-z*vx;
1632  p->z=y*vx-x*vy;
1633  }
1634  // Derivative of the LLK
1635  if(derivllk)
1636  {
1637  mLLKDeriv=0;
1638  for(map<const MolBond*,REAL>::const_iterator pos=this->mvpBrokenBond.begin();
1639  pos!=this->mvpBrokenBond.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1640  for(map<const MolBondAngle*,REAL>::const_iterator pos=this->mvpBrokenBondAngle.begin();
1641  pos!=this->mvpBrokenBondAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1642  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=this->mvpBrokenDihedralAngle.begin();
1643  pos!=this->mvpBrokenDihedralAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1644  }
1645 }
1646 
1647 void StretchModeBondAngle::Print(ostream &os,bool full)const
1648 {
1649  cout<<mpAtom0->GetName()<<"-"<<mpAtom1->GetName()<<"-"<<mpAtom2->GetName();
1650  if(full)
1651  {
1652  cout<<", Rotated Atoms:";
1653  for(set<MolAtom*>::const_iterator atom=mvRotatedAtomList.begin();
1654  atom!=mvRotatedAtomList.end();++atom)
1655  {
1656  cout<<(*atom)->GetName()<<",";
1657  }
1658  }
1659 }
1660 
1661 void StretchModeBondAngle::Stretch(const REAL amplitude,
1662  const bool keepCenter)
1663 {
1664  REAL dx10=mpAtom0->GetX()-mpAtom1->GetX();
1665  REAL dy10=mpAtom0->GetY()-mpAtom1->GetY();
1666  REAL dz10=mpAtom0->GetZ()-mpAtom1->GetZ();
1667  REAL dx12=mpAtom2->GetX()-mpAtom1->GetX();
1668  REAL dy12=mpAtom2->GetY()-mpAtom1->GetY();
1669  REAL dz12=mpAtom2->GetZ()-mpAtom1->GetZ();
1670 
1671  const REAL vx=dy10*dz12-dz10*dy12;
1672  const REAL vy=dz10*dx12-dx10*dz12;
1673  const REAL vz=dx10*dy12-dy10*dx12;
1674  mpMol->RotateAtomGroup(*mpAtom1,vx,vy,vz,mvRotatedAtomList,amplitude,keepCenter);
1675 }
1676 
1677 void StretchModeBondAngle::RandomStretch(const REAL amplitude,
1678  const bool keepCenter)
1679 {
1680  mpMol->BondAngleRandomChange(*this,amplitude,keepCenter);
1681 }
1682 
1684  const MolDihedralAngle *pAngle):
1685 mpAtom1(&at1),mpAtom2(&at2),mpDihedralAngle(pAngle)
1686 {
1687  mBaseAmplitude=M_PI*0.02;
1688  mpMol = &(at1.GetMolecule());
1689 }
1690 
1691 StretchModeTorsion::~StretchModeTorsion(){}
1692 
1693 void StretchModeTorsion::CalcDeriv(const bool derivllk)const
1694 {
1695  //TAU_PROFILE("StretchModeTorsion::CalcDeriv()","void ()",TAU_DEFAULT);
1696  // Derivative of the LLK
1697  //mDerivXYZ.clear();
1698  const REAL x1=mpAtom1->GetX(),
1699  y1=mpAtom1->GetY(),
1700  z1=mpAtom1->GetZ();
1701 
1702  REAL vx=mpAtom2->GetX()-x1,
1703  vy=mpAtom2->GetY()-y1,
1704  vz=mpAtom2->GetZ()-z1;
1705 
1706  const REAL n=sqrt(vx*vx+vy*vy+vz*vz+1e-10);
1707  vx/=n;
1708  vy/=n;
1709  vz/=n;
1710 
1711  for(set<MolAtom *>::const_iterator pos=mvRotatedAtomList.begin();
1712  pos!=mvRotatedAtomList.end();++pos)
1713  {
1714  XYZ *const p=&(mDerivXYZ[*pos]);
1715  const REAL x=(*pos)->GetX()-x1,
1716  y=(*pos)->GetY()-y1,
1717  z=(*pos)->GetZ()-z1;
1718  p->x=z*vy-y*vz;
1719  p->y=x*vz-z*vx;
1720  p->z=y*vx-x*vy;
1721  }
1722  // Derivative of the LLK
1723  if(derivllk)
1724  {
1725  mLLKDeriv=0;
1726  for(map<const MolBond*,REAL>::const_iterator pos=this->mvpBrokenBond.begin();
1727  pos!=this->mvpBrokenBond.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1728  for(map<const MolBondAngle*,REAL>::const_iterator pos=this->mvpBrokenBondAngle.begin();
1729  pos!=this->mvpBrokenBondAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1730  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=this->mvpBrokenDihedralAngle.begin();
1731  pos!=this->mvpBrokenDihedralAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1732  }
1733 }
1734 
1735 void StretchModeTorsion::Print(ostream &os,bool full)const
1736 {
1737  cout<<mpAtom1->GetName()<<"-"<<mpAtom2->GetName();
1738  if(full)
1739  {
1740  cout<<", Rotated Atoms:";
1741  for(set<MolAtom*>::const_iterator atom=mvRotatedAtomList.begin();
1742  atom!=mvRotatedAtomList.end();++atom)
1743  {
1744  cout<<(*atom)->GetName()<<",";
1745  }
1746  }
1747 }
1748 
1749 void StretchModeTorsion::Stretch(const REAL amplitude, const bool keepCenter)
1750 {
1751  mpMol->RotateAtomGroup(*mpAtom1,*mpAtom2,mvRotatedAtomList,amplitude,keepCenter);
1752 }
1753 
1754 void StretchModeTorsion::RandomStretch(const REAL amplitude,
1755  const bool keepCenter)
1756 {
1757  mpMol->DihedralAngleRandomChange(*this,amplitude,keepCenter);
1758 }
1759 
1760 
1761 //######################################################################
1762 //
1763 // StretchModeTwist
1764 //
1765 //######################################################################
1767 mpAtom1(&at1),mpAtom2(&at2)
1768 {
1769  mBaseAmplitude=M_PI*0.02;
1770  mpMol = &(at1.GetMolecule());
1771 }
1772 
1773 StretchModeTwist::~StretchModeTwist(){}
1774 
1775 void StretchModeTwist::CalcDeriv(const bool derivllk)const
1776 {// Identical to StretchModeTorsion::CalcDeriv()
1777  // Derivative of the LLK
1778  //mDerivXYZ.clear();
1779  const REAL x1=mpAtom1->GetX(),
1780  y1=mpAtom1->GetY(),
1781  z1=mpAtom1->GetZ();
1782 
1783  REAL vx=mpAtom2->GetX()-x1,
1784  vy=mpAtom2->GetY()-y1,
1785  vz=mpAtom2->GetZ()-z1;
1786 
1787  const REAL n=sqrt(vx*vx+vy*vy+vz*vz+1e-10);
1788  vx/=n;
1789  vy/=n;
1790  vz/=n;
1791 
1792  for(set<MolAtom *>::const_iterator pos=mvRotatedAtomList.begin();
1793  pos!=mvRotatedAtomList.end();++pos)
1794  {
1795  XYZ *const p=&(mDerivXYZ[*pos]);
1796  const REAL x=(*pos)->GetX()-x1,
1797  y=(*pos)->GetY()-y1,
1798  z=(*pos)->GetZ()-z1;
1799  p->x=z*vy-y*vz;
1800  p->y=x*vz-z*vx;
1801  p->z=y*vx-x*vy;
1802  }
1803  // Derivative of the LLK
1804  if(derivllk)
1805  {
1806  mLLKDeriv=0;
1807  for(map<const MolBond*,REAL>::const_iterator pos=this->mvpBrokenBond.begin();
1808  pos!=this->mvpBrokenBond.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1809  for(map<const MolBondAngle*,REAL>::const_iterator pos=this->mvpBrokenBondAngle.begin();
1810  pos!=this->mvpBrokenBondAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1811  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=this->mvpBrokenDihedralAngle.begin();
1812  pos!=this->mvpBrokenDihedralAngle.end();++pos) mLLKDeriv += pos->first->GetDeriv(mDerivXYZ,true);
1813  }
1814 }
1815 
1816 void StretchModeTwist::Print(ostream &os,bool full)const
1817 {
1818  os<<mpAtom1->GetName()<<"/"<<mpAtom2->GetName()<<"-"<<mpAtom2->GetName();
1819  if(full)
1820  {
1821  os<<", Rotated Atoms:";
1822  for(set<MolAtom*>::const_iterator atom=mvRotatedAtomList.begin();
1823  atom!=mvRotatedAtomList.end();++atom)
1824  {
1825  os<<(*atom)->GetName()<<",";
1826  }
1827  }
1828 }
1829 
1830 void StretchModeTwist::Stretch(const REAL amplitude, const bool keepCenter)
1831 {
1832  mpMol->RotateAtomGroup(*mpAtom1,*mpAtom2,mvRotatedAtomList,amplitude,keepCenter);
1833 }
1834 
1835 void StretchModeTwist::RandomStretch(const REAL amplitude,
1836  const bool keepCenter)
1837 {
1838  const REAL dx=mpAtom2->GetX()-mpAtom1->GetX();
1839  const REAL dy=mpAtom2->GetY()-mpAtom1->GetY();
1840  const REAL dz=mpAtom2->GetZ()-mpAtom1->GetZ();
1841  if((abs(dx)+abs(dy)+abs(dz))<1e-6) return;// :KLUDGE:
1842  const REAL change=(REAL)(2.*rand()-RAND_MAX)/(REAL)RAND_MAX*mBaseAmplitude*amplitude;
1843  mpMol->RotateAtomGroup(*mpAtom1,*mpAtom2,mvRotatedAtomList,change,keepCenter);
1844 }
1845 
1846 //######################################################################
1847 //
1848 // MDAtomGroup
1849 //
1850 //######################################################################
1852 
1853 MDAtomGroup::MDAtomGroup(set<MolAtom*> &vat,
1854  set<MolBond*> &vb,
1855  set<MolBondAngle*> &va,
1856  set<MolDihedralAngle*> &vd):
1857 mvpAtom(vat)
1858 {
1859  // Use vector instead of sets for MolecularDynamicsEvolve & general
1860  // storage in molecule compatibility
1861  for(set<MolBond*>::iterator pos=vb.begin();pos!=vb.end();++pos)
1862  mvpBond.push_back(*pos);
1863  for(set<MolBondAngle*>::iterator pos=va.begin();pos!=va.end();++pos)
1864  mvpBondAngle.push_back(*pos);
1865  for(set<MolDihedralAngle*>::iterator pos=vd.begin();pos!=vd.end();++pos)
1866  mvpDihedralAngle.push_back(*pos);
1867 }
1868 
1869 void MDAtomGroup::Print(ostream &os,bool full)const
1870 {
1871  if(full) os<<"MDAtomGroup: ";
1872  for(set<MolAtom*>::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
1873  os<<(*pos)->GetName()<<" ";
1874  if(full)
1875  {
1876  os<<endl<<" Involving bond restraints:";
1877  for(vector<MolBond*>::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
1878  os<<(*pos)->GetName()<<" ";
1879  os<<endl<<" Involving bond angle restraints:";
1880  for(vector<MolBondAngle*>::const_iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
1881  os<<(*pos)->GetName()<<" ";
1882  os<<endl<<" Involving dihedral angle restraints:";
1883  for(vector<MolDihedralAngle*>::const_iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
1884  os<<(*pos)->GetName()<<" ";
1885  os<<endl;
1886  }
1887 }
1888 
1889 //######################################################################
1890 //
1891 // Molecule
1892 //
1893 //######################################################################
1894 Molecule::Molecule(Crystal &cryst, const string &name):
1895 mDeleteSubObjInDestructor(1), mBaseRotationAmplitude(M_PI*0.02), mIsSelfOptimizing(false),
1896 mpCenterAtom(0), mMDMoveFreq(0.0), mMDMoveEnergy(40.), mLogLikelihoodScale(1.0)
1897 {
1898  VFN_DEBUG_MESSAGE("Molecule::Molecule()",5)
1899  mpCryst=&cryst;
1900  {
1901  RefinablePar tmp(name+"_x",&mXYZ(0),0.,1.,
1902  gpRefParTypeScattTranslX,
1903  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.);
1905  tmp.SetDerivStep(1e-5);
1906  this->AddPar(tmp);
1907  }
1908  {
1909  RefinablePar tmp(name+"_y",&mXYZ(1),0,1,
1910  gpRefParTypeScattTranslY,
1911  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.);
1913  tmp.SetDerivStep(1e-5);
1914  this->AddPar(tmp);
1915  }
1916  {
1917  RefinablePar tmp(name+"_z",&mXYZ(2),0,1,
1918  gpRefParTypeScattTranslZ,
1919  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.);
1921  tmp.SetDerivStep(1e-5);
1922  this->AddPar(tmp);
1923  }
1924  {
1925  RefinablePar tmp(name+"_Occ",&mOccupancy,0,1,
1926  gpRefParTypeScattOccup,
1927  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.,1.);
1929  tmp.SetDerivStep(1e-5);
1930  this->AddPar(tmp);
1931  }
1932  {
1933  RefinablePar tmp(name+"_Q0",&(mQuat.Q0()),0,1,
1934  gpRefParTypeScattOrient,
1935  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
1937  tmp.SetGlobalOptimStep(0.04);
1938  tmp.SetDerivStep(1e-4);
1939  this->AddPar(tmp);
1940  }
1941  {
1942  RefinablePar tmp(name+"_Q1",&(mQuat.Q1()),0,1,
1943  gpRefParTypeScattOrient,
1944  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
1946  tmp.SetGlobalOptimStep(0.04);
1947  tmp.SetDerivStep(1e-4);
1948  this->AddPar(tmp);
1949  }
1950  {
1951  RefinablePar tmp(name+"_Q2",&(mQuat.Q2()),0,1,
1952  gpRefParTypeScattOrient,
1953  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
1955  tmp.SetGlobalOptimStep(0.04);
1956  tmp.SetDerivStep(1e-4);
1957  this->AddPar(tmp);
1958  }
1959  {
1960  RefinablePar tmp(name+"_Q3",&(mQuat.Q3()),0,1,
1961  gpRefParTypeScattOrient,
1962  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
1964  tmp.SetGlobalOptimStep(0.04);
1965  tmp.SetDerivStep(1e-4);
1966  this->AddPar(tmp);
1967  }
1968  this->SetName(name);
1969  mLocalParamSet=this->CreateParamSet("saved parameters for local minimization");
1970  this->InitOptions();
1971  mClockScatterer.AddChild(mClockAtomList);
1972  mClockScatterer.AddChild(mClockBondList);
1973  mClockScatterer.AddChild(mClockBondAngleList);
1974  mClockScatterer.AddChild(mClockDihedralAngleList);
1975  mClockScatterer.AddChild(mClockRingList);
1976  mClockScatterer.AddChild(mClockRigidGroup);
1977  mClockScatterer.AddChild(mClockAtomPosition);
1978  mClockScatterer.AddChild(mClockAtomScattPow);
1979  mClockScatterer.AddChild(mClockOrientation);
1980 }
1981 
1983 mDeleteSubObjInDestructor(old.mDeleteSubObjInDestructor), mIsSelfOptimizing(false), mpCenterAtom(0)
1984 {
1985  VFN_DEBUG_ENTRY("Molecule::Molecule(old&)",5)
1986  // a hack, but const-correct
1987  mpCryst=&(gCrystalRegistry.GetObj(gCrystalRegistry.Find(old.GetCrystal())));
1988  {
1989  RefinablePar tmp(this->GetName()+"_x",&mXYZ(0),0.,1.,
1990  gpRefParTypeScattTranslX,
1991  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.);
1993  tmp.SetDerivStep(1e-5);
1994  this->AddPar(tmp);
1995  }
1996  {
1997  RefinablePar tmp(this->GetName()+"_y",&mXYZ(1),0,1,
1998  gpRefParTypeScattTranslY,
1999  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.);
2001  tmp.SetDerivStep(1e-5);
2002  this->AddPar(tmp);
2003  }
2004  {
2005  RefinablePar tmp(this->GetName()+"_z",&mXYZ(2),0,1,
2006  gpRefParTypeScattTranslZ,
2007  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,true,1.,1.);
2009  tmp.SetDerivStep(1e-5);
2010  this->AddPar(tmp);
2011  }
2012  {
2013  RefinablePar tmp(this->GetName()+"_Occ",&mOccupancy,0,1,
2014  gpRefParTypeScattOccup,
2015  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.,1.);
2017  tmp.SetDerivStep(1e-5);
2018  this->AddPar(tmp);
2019  }
2020  {
2021  RefinablePar tmp(this->GetName()+"Q0",&(mQuat.Q0()),0,1,
2022  gpRefParTypeScattOrient,
2023  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
2025  tmp.SetGlobalOptimStep(0.04);
2026  tmp.SetDerivStep(1e-4);
2027  this->AddPar(tmp);
2028  }
2029  {
2030  RefinablePar tmp(this->GetName()+"Q1",&(mQuat.Q1()),0,1,
2031  gpRefParTypeScattOrient,
2032  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
2034  tmp.SetGlobalOptimStep(0.04);
2035  tmp.SetDerivStep(1e-4);
2036  this->AddPar(tmp);
2037  }
2038  {
2039  RefinablePar tmp(this->GetName()+"Q2",&(mQuat.Q2()),0,1,
2040  gpRefParTypeScattOrient,
2041  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
2043  tmp.SetGlobalOptimStep(0.04);
2044  tmp.SetDerivStep(1e-4);
2045  this->AddPar(tmp);
2046  }
2047  {
2048  RefinablePar tmp(this->GetName()+"Q3",&(mQuat.Q3()),0,1,
2049  gpRefParTypeScattOrient,
2050  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
2052  tmp.SetGlobalOptimStep(0.04);
2053  tmp.SetDerivStep(1e-4);
2054  this->AddPar(tmp);
2055  }
2056  mLocalParamSet=this->CreateParamSet("saved parameters for local minimization");
2057  this->InitOptions();
2058  mClockScatterer.AddChild(mClockAtomList);
2059  mClockScatterer.AddChild(mClockBondList);
2060  mClockScatterer.AddChild(mClockBondAngleList);
2061  mClockScatterer.AddChild(mClockDihedralAngleList);
2062  mClockScatterer.AddChild(mClockRingList);
2063  mClockScatterer.AddChild(mClockRigidGroup);
2064  mClockScatterer.AddChild(mClockAtomPosition);
2065  mClockScatterer.AddChild(mClockAtomScattPow);
2066  mClockScatterer.AddChild(mClockOrientation);
2067 
2068  stringstream str;
2069  old.XMLOutput(str);
2070  XMLCrystTag tag(str);
2071  this->XMLInput(str,tag);
2072  VFN_DEBUG_EXIT("Molecule::Molecule(old&)",5)
2073 }
2074 
2076 {
2077  VFN_DEBUG_ENTRY("Molecule::~Molecule()",5)
2079  {
2080  {
2081  vector<MolAtom*>::iterator pos;
2082  for(pos=mvpAtom.begin();pos!=mvpAtom.end();pos++) delete *pos;
2083  }
2084  {
2085  vector<MolBond*>::iterator pos;
2086  for(pos=mvpBond.begin();pos!=mvpBond.end();pos++) delete *pos;
2087  }
2088  {
2089  vector<MolBondAngle*>::iterator pos;
2090  for(pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();pos++) delete *pos;
2091  }
2092  {
2093  vector<MolDihedralAngle*>::iterator pos;
2094  for(pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();pos++) delete *pos;
2095  }
2096  }
2097  VFN_DEBUG_EXIT("Molecule::~Molecule()",5)
2098 }
2099 
2101 {
2102  VFN_DEBUG_MESSAGE("Molecule::CreateCopy()",5)
2103  return new Molecule(*this);
2104 }
2105 
2106 const string& Molecule::GetClassName() const
2107 {
2108  static const string className="Molecule";
2109  return className;
2110 }
2111 
2112 void Molecule::SetName(const string &name)
2113 {
2114  if(mName==name) return;
2115  this->RefinableObj::SetName(name);
2116  // Set parameter's name including the Molecule's name
2117  try
2118  {
2119  this->GetPar(&mXYZ(0)).SetName(mName+"_x");
2120  this->GetPar(&mXYZ(1)).SetName(mName+"_y");
2121  this->GetPar(&mXYZ(2)).SetName(mName+"_z");
2122  this->GetPar(&mOccupancy).SetName(mName+"_Occ");
2123  this->GetPar(&(mQuat.Q0())).SetName(mName+"_Q0");
2124  this->GetPar(&(mQuat.Q1())).SetName(mName+"_Q1");
2125  this->GetPar(&(mQuat.Q2())).SetName(mName+"_Q2");
2126  this->GetPar(&(mQuat.Q3())).SetName(mName+"_Q3");
2127  }
2128  catch(const ObjCrystException &except)
2129  {
2130  cerr<<"Molecule::SetName(): parameters not yet declared in a Molecule ?"<<endl;
2131  }
2132 }
2133 
2134 std::string Molecule::GetFormula() const
2135 {
2136  if(this->GetNbComponent()==0) return "";
2137  std::map<std::string,float> velts;
2138  for(std::vector<MolAtom*>::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
2139  {
2140  if((*pos)->IsDummy()) continue;
2141  string p;
2142  if((*pos)->GetScatteringPower().GetClassName()=="ScatteringPowerAtom")
2143  p=dynamic_cast<const ScatteringPowerAtom*>(&((*pos)->GetScatteringPower()))->GetSymbol();
2144  else p=(*pos)->GetScatteringPower().GetName();
2145  if(velts.count(p)==0)
2146  velts[(*pos)->GetScatteringPower().GetName()]=(*pos)->GetOccupancy();
2147  else velts[(*pos)->GetScatteringPower().GetName()]+=(*pos)->GetOccupancy();
2148  }
2149  stringstream s;
2150  s<<std::setprecision(2);
2151  for(std::map<std::string,float>::const_iterator pos=velts.begin();pos!=velts.end();++pos)
2152  {
2153  if(pos!=velts.begin()) s<<" ";
2154  float nb=pos->second;
2155  if((abs(nb)-nb)<0.01) s<<pos->first<<int(round(nb));
2156  else s<<pos->first<<nb;
2157  }
2158  return s.str();
2159 }
2160 
2161 void Molecule::Print()const
2162 {
2163  VFN_DEBUG_MESSAGE("Molecule::Print()",5)
2164  this->XMLOutput(cout);
2165 }
2166 
2167 void Molecule::XMLOutput(ostream &os,int indent)const
2168 {
2169  VFN_DEBUG_ENTRY("Molecule::XMLOutput()",4)
2170 
2171  // :KLUDGE: this may be dangerous if the molecule is beaing refined !
2172  this->ResetRigidGroupsPar();
2173 
2174  for(int i=0;i<indent;i++) os << " " ;
2175  XMLCrystTag tag("Molecule");
2176  tag.AddAttribute("Name",mName);
2177  stringstream sst;
2178  sst<<mMDMoveFreq;
2179  tag.AddAttribute("MDMoveFreq",sst.str());
2180  sst.str("");
2181  sst<<mMDMoveEnergy;
2182  tag.AddAttribute("MDMoveEnergy",sst.str());
2183  sst.str("");
2184  sst<<mLogLikelihoodScale;
2185  tag.AddAttribute("LogLikelihoodScale",sst.str());
2186  os <<tag<<endl;
2187  indent++;
2188 
2189  mQuat.Normalize();
2190  mQuat.XMLOutput(os,indent);
2191 
2192  this->GetPar(mXYZ.data()+0).XMLOutput(os,"x",indent);
2193  os <<endl;
2194 
2195  this->GetPar(mXYZ.data()+1).XMLOutput(os,"y",indent);
2196  os <<endl;
2197 
2198  this->GetPar(mXYZ.data()+2).XMLOutput(os,"z",indent);
2199  os <<endl;
2200 
2201  this->GetPar(&mOccupancy).XMLOutput(os,"Occup",indent);
2202  os <<endl<<endl;
2203 
2204  for(unsigned int i=0;i<this->GetNbOption();i++)
2205  {
2206  this->GetOption(i).XMLOutput(os,indent);
2207  os <<endl;
2208  }
2209  os <<endl;
2210 
2211  {
2212  vector<MolAtom*>::const_iterator pos;
2213  for(pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
2214  (*pos)->XMLOutput(os,indent);
2215  }
2216  {
2217  vector<MolBond*>::const_iterator pos;
2218  for(pos=mvpBond.begin();pos!=mvpBond.end();++pos)
2219  (*pos)->XMLOutput(os,indent);
2220  }
2221  {
2222  vector<MolBondAngle*>::const_iterator pos;
2223  for(pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
2224  (*pos)->XMLOutput(os,indent);
2225  }
2226  {
2227  vector<MolDihedralAngle*>::const_iterator pos;
2228  for(pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
2229  (*pos)->XMLOutput(os,indent);
2230  }
2231  {
2232  vector<RigidGroup*>::const_iterator pos;
2233  for(pos=mvRigidGroup.begin();pos!=mvRigidGroup.end();++pos)
2234  {
2235  XMLCrystTag tagg("RigidGroup",false,true);
2236  for(set<MolAtom *>::const_iterator at=(*pos)->begin();at!=(*pos)->end();++at)
2237  tagg.AddAttribute("Atom",(*at)->GetName());
2238  /*
2239  tagg.AddAttribute("Q0",(*pos)->mQuat.Q0());
2240  tagg.AddAttribute("Q1",(*pos)->mQuat.Q1());
2241  tagg.AddAttribute("Q2",(*pos)->mQuat.Q2());
2242  tagg.AddAttribute("Q3",(*pos)->mQuat.Q3());
2243  tagg.AddAttribute("dX",(*pos)->mX);
2244  tagg.AddAttribute("dY",(*pos)->mY);
2245  tagg.AddAttribute("dZ",(*pos)->mZ);
2246  */
2247  for(int i=0;i<indent;i++) os << " " ;
2248  os <<tagg<<endl;
2249  }
2250  }
2251  if(this->GetCenterAtom()!=0)
2252  {
2253 
2254  XMLCrystTag tagg("CenterAtom",false,true);
2255  tagg.AddAttribute("Name",this->GetCenterAtom()->GetName());
2256  for(int i=0;i<indent;i++) os << " " ;
2257  os <<tagg<<endl;
2258  }
2259 
2260  indent--;
2261  tag.SetIsEndTag(true);
2262  for(int i=0;i<indent;i++) os << " " ;
2263  os <<tag<<endl;
2264  VFN_DEBUG_EXIT("Molecule::XMLOutput()",4)
2265 }
2266 
2267 void Molecule::XMLInput(istream &is,const XMLCrystTag &tag)
2268 {
2269  VFN_DEBUG_ENTRY("Molecule::XMLInput()",5)
2270  for(unsigned int i=0;i<tag.GetNbAttribute();i++)
2271  {
2272  if("Name"==tag.GetAttributeName(i))
2273  {
2274  mName=tag.GetAttributeValue(i);
2275  }
2276  if("MDMoveFreq"==tag.GetAttributeName(i))
2277  {
2278  mMDMoveFreq=string2floatC(tag.GetAttributeValue(i));
2279  }
2280  if("MDMoveEnergy"==tag.GetAttributeName(i))
2281  {
2282  mMDMoveEnergy=string2floatC(tag.GetAttributeValue(i));
2283  }
2284  if("LogLikelihoodScale"==tag.GetAttributeName(i))
2285  {
2286  mLogLikelihoodScale=string2floatC(tag.GetAttributeValue(i));
2287  }
2288  }
2289  while(true)
2290  {
2291  XMLCrystTag tagg(is);
2292  if(("Molecule"==tagg.GetName())&&tagg.IsEndTag())
2293  {
2294  //this->XMLOutput(cout);
2295  this->UpdateDisplay();
2296  VFN_DEBUG_EXIT("Molecule::XMLInput():"<<this->GetName(),5)
2297  return;
2298  }
2299  if("Quaternion"==tagg.GetName())
2300  {
2301  mQuat.XMLInput(is,tagg);
2302  }
2303  if("Atom"==tagg.GetName())
2304  {
2305  this->AddAtom(0.,0.,0.,(ScatteringPower *)0,"",false);
2306  mvpAtom.back()->XMLInput(is,tagg);
2307  }
2308  if("Bond"==tagg.GetName())
2309  {
2310  this->AddBond(this->GetAtom(0),this->GetAtom(1),1.5,.01,.05,1.,false);
2311  mvpBond.back()->XMLInput(is,tagg);
2312  }
2313  if("BondAngle"==tagg.GetName())
2314  {
2315  this->AddBondAngle(this->GetAtom(0),this->GetAtom(1),this->GetAtom(2),1.5,.01,.05,false);
2316  mvpBondAngle.back()->XMLInput(is,tagg);
2317  }
2318  if("DihedralAngle"==tagg.GetName())
2319  {
2320  this->AddDihedralAngle(this->GetAtom(0),this->GetAtom(1),
2321  this->GetAtom(2),this->GetAtom(3),1.5,.01,.05,false);
2322  mvpDihedralAngle.back()->XMLInput(is,tagg);
2323  }
2324  if("RigidGroup"==tagg.GetName())
2325  {
2326  RigidGroup s;
2327  for(unsigned int i=0;i<tagg.GetNbAttribute();i++)
2328  if("Atom"==tagg.GetAttributeName(i))
2329  s.insert(&(this->GetAtom(tagg.GetAttributeValue(i))));
2330  this->AddRigidGroup(s);
2331  }
2332  if("CenterAtom"==tagg.GetName())
2333  {
2334  RigidGroup s;
2335  for(unsigned int i=0;i<tagg.GetNbAttribute();i++)
2336  if("Name"==tagg.GetAttributeName(i))
2337  this->SetCenterAtom(this->GetAtom(tagg.GetAttributeValue(i)));
2338  }
2339  if("Option"==tagg.GetName())
2340  {
2341  for(unsigned int i=0;i<tagg.GetNbAttribute();i++)
2342  if("Name"==tagg.GetAttributeName(i))
2343  mOptionRegistry.GetObj(tagg.GetAttributeValue(i)).XMLInput(is,tagg);
2344  continue;
2345  }
2346  if("Par"==tagg.GetName())
2347  {
2348  for(unsigned int i=0;i<tagg.GetNbAttribute();i++)
2349  {
2350  if("Name"==tagg.GetAttributeName(i))
2351  {
2352  if("x"==tagg.GetAttributeValue(i))
2353  {
2354  this->GetPar(mXYZ.data()+0).XMLInput(is,tagg);
2355  break;
2356  }
2357  if("y"==tagg.GetAttributeValue(i))
2358  {
2359  this->GetPar(mXYZ.data()+1).XMLInput(is,tagg);
2360  break;
2361  }
2362  if("z"==tagg.GetAttributeValue(i))
2363  {
2364  this->GetPar(mXYZ.data()+2).XMLInput(is,tagg);
2365  break;
2366  }
2367  if("Occup"==tagg.GetAttributeValue(i))
2368  {
2369  this->GetPar(&mOccupancy).XMLInput(is,tagg);
2370  break;
2371  }
2372  }
2373  }
2374  }
2375  }
2376  VFN_DEBUG_EXIT("Molecule::XMLInput()",5)
2377 }
2378 
2380 {
2381  this->ResetRigidGroupsPar();
2383 }
2384 
2385 void Molecule::BeginOptimization(const bool allowApproximations,const bool enableRestraints)
2386 {
2387  if(this->IsBeingRefined())
2388  {
2389  // RefinableObj::BeginOptimization() will increase the optimization depth
2390  this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
2391  return;
2392  }
2393  TAU_PROFILE("Molecule::BeginOptimization()","void (bool,bool)",TAU_DEFAULT);
2394  #if 1 // Is doing this automatically too dangerous ?
2395  if( (!mIsSelfOptimizing)
2396  &&(mAutoOptimizeConformation.GetChoice()==0))
2397  {
2398  if(this->GetLogLikelihood()>(mvpRestraint.size()*500))
2399  {
2400  (*fpObjCrystInformUser)("Optimizing initial conformation of Molecule:"+this->GetName());
2401  this->OptimizeConformation(100000,(REAL)(mvpRestraint.size()));
2402  (*fpObjCrystInformUser)("");
2403  }
2404  mAutoOptimizeConformation.SetChoice(1);
2405  }
2406  #endif
2407 
2408  RefinableObjClock clockConf, clockMode;
2409  clockConf=mClockAtomList;
2410  if(clockConf<mClockBondList) clockConf=mClockBondList;
2411  if(clockConf<mClockBondAngleList) clockConf=mClockBondAngleList;
2412  if(clockConf<mClockDihedralAngleList) clockConf=mClockDihedralAngleList;
2413  if(clockConf<mClockRigidGroup) clockConf=mClockRigidGroup;
2414  if(clockConf<mClockAtomScattPow) clockConf=mClockAtomScattPow;
2415 
2416  clockMode=mClockConnectivityTable;
2417  if(clockMode<mClockRingList) clockMode=mClockRingList;
2418  if(clockMode<mClockRotorGroup) clockMode=mClockRotorGroup;
2419  if(clockMode<mClockFlipGroup) clockMode=mClockFlipGroup;
2420  if(clockMode<mClockStretchModeBondLength) clockMode=mClockStretchModeBondLength;
2421  if(clockMode<mClockStretchModeBondAngle) clockMode=mClockStretchModeBondAngle;
2422  if(clockMode<mClockStretchModeTorsion) clockMode=mClockStretchModeTorsion;
2423  if(clockMode<mClockStretchModeTwist) clockMode=mClockStretchModeTwist;
2424  if(clockMode<mClockMDAtomGroup) clockMode=mClockMDAtomGroup;
2425 
2426 
2427  if( (!mIsSelfOptimizing) && (clockMode<clockConf))
2428  {
2429  #if 0
2430  this->BuildRotorGroup();
2431  #endif
2432  if(mFlexModel.GetChoice()!=1)
2433  {
2434  this->BuildFlipGroup();
2435  this->BuildRingList();
2437  this->BuildStretchModeBondAngle();
2438  this->BuildStretchModeTorsion();
2439  //this->BuildStretchModeTwist();
2441  this->BuildStretchModeGroups();
2442  this->BuildMDAtomGroups();
2443  }
2444  }
2445  if(mOptimizeOrientation.GetChoice()==1)
2446  {
2447  this->GetPar(&(mQuat.Q0())).SetIsFixed(true);
2448  this->GetPar(&(mQuat.Q1())).SetIsFixed(true);
2449  this->GetPar(&(mQuat.Q2())).SetIsFixed(true);
2450  this->GetPar(&(mQuat.Q3())).SetIsFixed(true);
2451  }
2452  else
2453  {
2454  this->GetPar(&(mQuat.Q0())).SetIsFixed(false);
2455  this->GetPar(&(mQuat.Q1())).SetIsFixed(false);
2456  this->GetPar(&(mQuat.Q2())).SetIsFixed(false);
2457  this->GetPar(&(mQuat.Q3())).SetIsFixed(false);
2458  }
2459  if(1==mFlexModel.GetChoice())
2460  {// Molecule is a rigid body - fix all individual atomic parameters
2461  for(vector<MolAtom*>::iterator at=this->GetAtomList().begin();at!=this->GetAtomList().end();++at)
2462  {
2463  this->GetPar(&((*at)->X())).SetIsFixed(true);
2464  this->GetPar(&((*at)->Y())).SetIsFixed(true);
2465  this->GetPar(&((*at)->Z())).SetIsFixed(true);
2466  }
2467  }
2468  else
2469  {// Molecule is flexible - rigid groups are handled below
2470  for(vector<MolAtom*>::iterator at=this->GetAtomList().begin();at!=this->GetAtomList().end();++at)
2471  {
2472  this->GetPar(&((*at)->X())).SetIsFixed(false);
2473  this->GetPar(&((*at)->Y())).SetIsFixed(false);
2474  this->GetPar(&((*at)->Z())).SetIsFixed(false);
2475  }
2476  }
2477  #ifdef RIGID_BODY_STRICT_EXPERIMENTAL
2478  // Block individual refinable parameters from atoms in rigid groups
2479  // And create the index of the atoms
2480  for(vector<RigidGroup *>::iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos)
2481  {
2482  // Init the translation & rotation parameters (ignored outside an optimization)
2483  (*pos)->mX=0;
2484  (*pos)->mY=0;
2485  (*pos)->mZ=0;
2486  (*pos)->mQuat.Q0()=1;
2487  (*pos)->mQuat.Q1()=0;
2488  (*pos)->mQuat.Q2()=0;
2489  (*pos)->mQuat.Q3()=0;
2490  (*pos)->mvIdx.clear();
2491  for(set<MolAtom *>::iterator at=(*pos)->begin();at!=(*pos)->end();++at)
2492  {
2493  this->GetPar(&((*at)->X())).SetIsFixed(true);
2494  this->GetPar(&((*at)->Y())).SetIsFixed(true);
2495  this->GetPar(&((*at)->Z())).SetIsFixed(true);
2496  for(int i = 0; i < this->GetNbComponent(); ++i)
2497  if(&(this->GetAtom(i))==*at)
2498  {
2499  (*pos)->mvIdx.insert(i);
2500  break;
2501  }
2502  }
2503  }
2504  #endif
2505 
2506  this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
2507  mRandomConformChangeNbTest=0;
2508  mRandomConformChangeNbAccept=0;
2509  mRandomConformChangeTemp=1.;//(REAL)this->GetNbComponent();
2510 }
2511 
2513 {
2514  /*
2515  if(mOptimizationDepth>1)
2516  {
2517  this->RefinableObj::EndOptimization();
2518  return;
2519  }
2520  */
2521  #ifdef RIGID_BODY_STRICT_EXPERIMENTAL
2522  // Un-block individual refinable parameters from atoms in rigid groups
2523  for(vector<RigidGroup *>::iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos)
2524  {
2525  for(set<MolAtom *>::iterator at=(*pos)->begin();at!=(*pos)->end();++at)
2526  {
2527  this->GetPar(&((*at)->X())).SetIsFixed(false);
2528  this->GetPar(&((*at)->Y())).SetIsFixed(false);
2529  this->GetPar(&((*at)->Z())).SetIsFixed(false);
2530  }
2531  }
2532  // Apply the translations & rotations of the rigid group parameters, and
2533  // use this as the newly stored atomic coordinates.
2534  this->ResetRigidGroupsPar();
2535  #endif
2537 }
2538 
2540 {
2541  TAU_PROFILE("Molecule::RandomizeConfiguration()","void ()",TAU_DEFAULT);
2542  VFN_DEBUG_ENTRY("Molecule::RandomizeConfiguration()",4)
2543 
2544  if( (!mIsSelfOptimizing)
2545  &&(this->GetLogLikelihood()>(mvpRestraint.size()*500))
2546  &&(mAutoOptimizeConformation.GetChoice()==0))
2547  {// This is only done once, for a newly-created molecule with atoms not conforming to restraints
2548  (*fpObjCrystInformUser)("Optimizing initial conformation of Molecule:"+this->GetName());
2549  this->OptimizeConformation(100000,(REAL)(mvpRestraint.size()));
2550  (*fpObjCrystInformUser)("");
2551  }
2552 
2553  if( (!(this->IsBeingRefined()))
2554  && (mvStretchModeTorsion.size()==0)
2555  &&(mvStretchModeBondAngle.size()==0)
2556  &&(mvStretchModeBondLength.size()==0)
2557  &&(mvStretchModeTwist.size()==0)
2558  &&(mvMDAtomGroup.size()==0))
2559  {
2560  //This will build stretch modes & MD groups
2561  if(mFlexModel.GetChoice()!=1)
2562  {
2563  this->BuildStretchModeTorsion();
2565  //this->BuildStretchModeGroups();
2566  this->BuildMDAtomGroups();
2567  }
2568  }
2569 
2570  #if 0
2571  this->BuildRotorGroup();
2572  if((mFlexModel.GetChoice()==0)||(mFlexModel.GetChoice()==2))
2573  for(list<RotorGroup>::const_iterator pos=mvRotorGroupTorsion.begin();
2574  pos!=mvRotorGroupTorsion.end();++pos)
2575  {
2576  const REAL angle=(REAL)rand()*2.*M_PI/(REAL)RAND_MAX;
2577  this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),
2578  pos->mvRotatedAtomList,angle);
2579  }
2580  if(mFlexModel.GetChoice()==0)
2581  for(list<RotorGroup>::const_iterator pos=mvRotorGroupTorsionSingleChain.begin();
2582  pos!=mvRotorGroupTorsionSingleChain.end();++pos)
2583  {
2584  const REAL angle=(REAL)rand()*2.*M_PI/(REAL)RAND_MAX;
2585  this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),
2586  pos->mvRotatedAtomList,angle);
2587  }
2588  if(mFlexModel.GetChoice()==0)
2589  for(list<RotorGroup>::const_iterator pos=mvRotorGroupInternal.begin();
2590  pos!=mvRotorGroupInternal.end();++pos)
2591  {
2592  const REAL angle=(REAL)rand()*2.*M_PI/(REAL)RAND_MAX;
2593  this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),
2594  pos->mvRotatedAtomList,angle);
2595  }
2596  #else
2597  for(list<StretchModeTorsion>::const_iterator
2598  pos=mvStretchModeTorsion.begin();
2599  pos!=mvStretchModeTorsion.end();++pos)
2600  {
2601  const REAL amp=2*M_PI*rand()/(REAL)RAND_MAX;
2602  this->DihedralAngleRandomChange(*pos,amp,true);
2603  }
2604  // Molecular dynamics moves
2605  if((mvMDAtomGroup.size()>0)&&(mMDMoveFreq>0)&&(mMDMoveEnergy>0))
2606  {
2607  // Random initial speed for all atoms
2608  map<MolAtom*,XYZ> v0;
2609  for(vector<MolAtom*>::iterator at=this->GetAtomList().begin();at!=this->GetAtomList().end();++at)
2610  v0[*at]=XYZ(rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5);
2611 
2612  const REAL nrj0=mMDMoveEnergy*( this->GetBondList().size()
2613  +this->GetBondAngleList().size()
2614  +this->GetDihedralAngleList().size());
2615  map<RigidGroup*,std::pair<XYZ,XYZ> > vr;
2616  this->MolecularDynamicsEvolve(v0, 5000,0.004,
2617  this->GetBondList(),
2618  this->GetBondAngleList(),
2619  this->GetDihedralAngleList(),
2620  vr,nrj0);
2621  }
2622 
2623  #endif
2624  // this will only change limited parameters i.e. translation
2626  #ifdef RIGID_BODY_STRICT_EXPERIMENTAL
2627  // Init rigid groups translation & rotation parameters to zero
2628  for(vector<RigidGroup *>::iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos)
2629  {
2630  // Init the translation & rotation parameters (ignored outside an optimization
2631  (*pos)->mX=0;
2632  (*pos)->mY=0;
2633  (*pos)->mZ=0;
2634  (*pos)->mQuat.Q0()=1;
2635  (*pos)->mQuat.Q1()=0;
2636  (*pos)->mQuat.Q2()=0;
2637  (*pos)->mQuat.Q3()=0;
2638  }
2639  #endif
2640  if(mOptimizeOrientation.GetChoice()==0)
2641  {//Rotate around an arbitrary vector
2642  const REAL amp=M_PI/RAND_MAX;
2644  ((2.*(REAL)rand()-(REAL)RAND_MAX)*amp,
2645  (REAL)rand(),(REAL)rand(),(REAL)rand());
2646  mQuat.Normalize();
2647  mClockOrientation.Click();
2648  }
2649  VFN_DEBUG_EXIT("Molecule::RandomizeConfiguration()",4)
2650 }
2651 
2652 void Molecule::GlobalOptRandomMove(const REAL mutationAmplitude,
2653  const RefParType *type)
2654 {
2655  if(mRandomMoveIsDone) return;
2656  if(mIsSelfOptimizing)
2657  {
2658  this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,type);
2659  mQuat.Normalize();
2660  VFN_DEBUG_EXIT("Molecule::GlobalOptRandomMove()",4)
2661  return;
2662  }
2663  TAU_PROFILE("Molecule::GlobalOptRandomMove()","void (REAL,RefParType*)",TAU_DEFAULT);
2664  TAU_PROFILE_TIMER(timer1,"Molecule::GlobalOptRandomMove 1","", TAU_FIELD);
2665  TAU_PROFILE_TIMER(timer2,"Molecule::GlobalOptRandomMove 2","", TAU_FIELD);
2666  TAU_PROFILE_TIMER(timer3,"Molecule::GlobalOptRandomMove 3","", TAU_FIELD);
2667  TAU_PROFILE_TIMER(timer4,"Molecule::GlobalOptRandomMove 4","", TAU_FIELD);
2668  TAU_PROFILE_TIMER(timer5,"Molecule::GlobalOptRandomMove 5","", TAU_FIELD);
2669  VFN_DEBUG_ENTRY("Molecule::GlobalOptRandomMove()",4)
2671 
2672 
2673  #if 1
2674  // From time to time, just do one flip
2675  if( (mFlexModel.GetChoice()!=1)
2676  &&(mFlipModel.GetChoice()==0)
2677  &&(gpRefParTypeScattConform->IsDescendantFromOrSameAs(type))
2678  &&(mvFlipGroup.size()>0)
2679  &&(((rand()%100)==0)))
2680  {
2681 
2682  this->SaveParamSet(mLocalParamSet);
2683  const REAL llk0=this->GetLogLikelihood()/mLogLikelihoodScale;
2684  const unsigned long i=rand() % mvFlipGroup.size();
2685  list<FlipGroup>::iterator pos=mvFlipGroup.begin();
2686  for(unsigned long j=0;j<i;++j)++pos;
2687  this->FlipAtomGroup(*pos,true);
2688  #if 0
2689  static unsigned long ctflip1=0,ctflip2=0;
2690  if(pos->mvRotatedChainList.begin()->first==pos->mpAtom0)
2691  {
2692  cout <<"TRYING: Flip group from atom "
2693  <<pos->mpAtom0->GetName()<<",exchanging bonds with "
2694  <<pos->mpAtom1->GetName()<<" and "
2695  <<pos->mpAtom2->GetName()<<", resulting in a 180deg rotation of atoms : ";
2696  for(set<MolAtom*>::iterator pos1=pos->mvRotatedChainList.begin()->second.begin();
2697  pos1!=pos->mvRotatedChainList.begin()->second.end();++pos1)
2698  cout<<(*pos1)->GetName()<<" ";
2699  }
2700  else
2701  {
2702  cout <<"TRYING: Flip group with respect to: "
2703  <<pos->mpAtom1->GetName()<<"-"
2704  <<pos->mpAtom0->GetName()<<"-"
2705  <<pos->mpAtom2->GetName()<<" : ";
2706  for(list<pair<const MolAtom *,set<MolAtom*> > >::const_iterator
2707  chain=pos->mvRotatedChainList.begin();
2708  chain!=pos->mvRotatedChainList.end();++chain)
2709  {
2710  cout<<" -"<<chain->first->GetName()<<":";
2711  for(set<MolAtom*>::const_iterator pos1=chain->second.begin();
2712  pos1!=chain->second.end();++pos1)
2713  cout<<(*pos1)->GetName()<<" ";
2714  }
2715  }
2716  ctflip1++;
2717  if((this->GetLogLikelihood()/mLogLikelihoodScale-llk0)>.3*llk0)
2718  {
2719  cout<<" FLIP REJECTED ("<<int(float(ctflip2)/ctflip1*100)<<"% accepted): llk="<<llk0<<" -> "<<this->GetLogLikelihood()/mLogLikelihoodScale<<endl;
2720  this->RestoreParamSet(mLocalParamSet);
2721  }
2722  else
2723  {
2724  ctflip2++;
2725  cout<<" FLIP ACCEPTED ("<<float(ctflip2)/ctflip1*100<<"% accepted)"<<endl;
2726  }
2727  #else
2728  if((this->GetLogLikelihood()/mLogLikelihoodScale-llk0)>.3*llk0)
2729  this->RestoreParamSet(mLocalParamSet);
2730  #endif
2731  }
2732  else
2733  #endif
2734  {
2735  TAU_PROFILE_START(timer1);
2736  if(mOptimizeOrientation.GetChoice()==0)
2737  {//Rotate around an arbitrary vector
2738  static const REAL amp=mBaseRotationAmplitude/(REAL)RAND_MAX;
2739  REAL mult=1.0;
2740  if((1==mFlexModel.GetChoice())||(mvRotorGroupTorsion.size()<2)) mult=2.0;
2742  ((2.*(REAL)rand()-(REAL)RAND_MAX)*amp*mutationAmplitude*mult,
2743  (REAL)rand(),(REAL)rand(),(REAL)rand());
2744  mQuat.Normalize();
2745  mClockOrientation.Click();
2746  }
2747  // Occupancy
2748  if(gpRefParTypeScattOccup->IsDescendantFromOrSameAs(type))
2749  this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,gpRefParTypeScattOccup);
2750  mRandomMoveIsDone=false;
2751  //translation
2752  if(gpRefParTypeScattTransl->IsDescendantFromOrSameAs(type))
2753  this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,gpRefParTypeScattTransl);
2754  mRandomMoveIsDone=false;
2755  TAU_PROFILE_STOP(timer1);
2756  if(gpRefParTypeScattConform->IsDescendantFromOrSameAs(type))
2757  {
2758  if(mFlexModel.GetChoice()!=1)
2759  {
2760  #if 1 // Move as many atoms as possible
2761  if((mvMDFullAtomGroup.size()>3)&&(rand()<(RAND_MAX*mMDMoveFreq)))
2762  {
2763  #if 0
2764  // Use one center for the position of an impulsion, applied to all atoms with an exponential decrease
2765  // Determine extent of atom group
2766  REAL xmin=(*mvMDFullAtomGroup.begin())->GetX();
2767  REAL xmax=(*mvMDFullAtomGroup.begin())->GetX();
2768  REAL ymin=(*mvMDFullAtomGroup.begin())->GetY();
2769  REAL ymax=(*mvMDFullAtomGroup.begin())->GetY();
2770  REAL zmin=(*mvMDFullAtomGroup.begin())->GetZ();
2771  REAL zmax=(*mvMDFullAtomGroup.begin())->GetZ();
2772  for(set<MolAtom*>::iterator at=mvMDFullAtomGroup.begin();at!=mvMDFullAtomGroup.end();++at)
2773  {
2774  if((*at)->GetX()<xmin) xmin=(*at)->GetX();
2775  if((*at)->GetX()>xmax) xmax=(*at)->GetX();
2776  if((*at)->GetY()<ymin) ymin=(*at)->GetY();
2777  if((*at)->GetY()>ymax) ymax=(*at)->GetY();
2778  if((*at)->GetZ()<zmin) zmin=(*at)->GetZ();
2779  if((*at)->GetZ()>zmax) zmax=(*at)->GetZ();
2780  }
2781  // Apply a gaussian impulsion to part of the atom group (FWHM=1/3 of group size)
2782  REAL dx=(xmax-xmin)/5.,dy=(ymax-ymin)/5.,dz=(zmax-zmin)/5.;
2783  if(dx<2) dx=2;
2784  if(dy<2) dy=2;
2785  if(dz<2) dz=2;
2786  const REAL xc=xmin+rand()/(REAL)RAND_MAX*(xmax-xmin);
2787  const REAL yc=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin);
2788  const REAL zc=zmin+rand()/(REAL)RAND_MAX*(zmax-zmin);
2789  map<MolAtom*,XYZ> v0;
2790  const REAL ax=-4.*log(2.)/(dx*dx);
2791  const REAL ay=-4.*log(2.)/(dy*dy);
2792  const REAL az=-4.*log(2.)/(dz*dz);
2793  for(set<MolAtom*>::iterator at=mvMDFullAtomGroup.begin();at!=mvMDFullAtomGroup.end();++at)
2794  v0[*at]=XYZ(exp(ax*((*at)->GetX()-xc)*((*at)->GetX()-xc)),
2795  exp(ay*((*at)->GetY()-yc)*((*at)->GetY()-yc)),
2796  exp(az*((*at)->GetZ()-zc)*((*at)->GetZ()-zc)));
2797  #else
2798  // Use one atom for the center of the impulsion, 'push' atoms depending on distance & connectivity table
2799  map<MolAtom*,XYZ> v0;
2800  for(set<MolAtom*>::iterator at=this->mvMDFullAtomGroup.begin();at!=this->mvMDFullAtomGroup.end();++at)
2801  v0[*at]=XYZ(0,0,0);
2802  std::map<MolAtom*,unsigned long> pushedAtoms;
2803  unsigned long idx=rand()%v0.size();
2804  set<MolAtom*>::iterator at0=this->mvMDFullAtomGroup.begin();
2805  for(unsigned int i=0;i<idx;i++) at0++;
2806  const REAL xc=(*at0)->GetX();
2807  const REAL yc=(*at0)->GetY();
2808  const REAL zc=(*at0)->GetZ();
2809  const map<MolAtom *,set<MolAtom *> > *pConnect=&(this-> GetConnectivityTable());
2810  ExpandAtomGroupRecursive(*at0,*pConnect,pushedAtoms,3);
2811  REAL ux,uy,uz,n=0;
2812  while(n<1)
2813  {
2814  ux=REAL(rand()-RAND_MAX/2);
2815  uy=REAL(rand()-RAND_MAX/2);
2816  uz=REAL(rand()-RAND_MAX/2);
2817  n=sqrt(ux*ux+uy*uy+uz*uz);
2818  }
2819  ux=ux/n;uy=uy/n;uz=uz/n;
2820  const REAL a=-4.*log(2.)/(2*2);//FWHM=2 Angstroems
2821  if(rand()%2==0)
2822  for(map<MolAtom*,unsigned long>::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at)
2823  v0[at->first]=XYZ(ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)),
2824  uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)),
2825  uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc)));
2826  else
2827  for(map<MolAtom*, unsigned long>::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at)
2828  v0[at->first]=XYZ((at->first->GetX()-xc)*ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)),
2829  (at->first->GetY()-yc)*uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)),
2830  (at->first->GetZ()-zc)*uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc)));
2831 
2832 
2833  #endif
2834  const REAL nrj0=mMDMoveEnergy*( this->GetBondList().size()
2835  +this->GetBondAngleList().size()
2836  +this->GetDihedralAngleList().size());
2837  map<RigidGroup*,std::pair<XYZ,XYZ> > vr;
2838  this->MolecularDynamicsEvolve(v0, int(100*sqrt(mutationAmplitude)),0.004,
2839  this->GetBondList(),
2840  this->GetBondAngleList(),
2841  this->GetDihedralAngleList(),
2842  vr,nrj0);
2843  }
2844  #else // Move atoms belonging to a MD group
2845  if((mvMDAtomGroup.size()>0)&&(rand()<(RAND_MAX*mMDMoveFreq)))
2846  {
2847  const unsigned int n=rand()%mvMDAtomGroup.size();
2848  list<MDAtomGroup>::iterator pos=mvMDAtomGroup.begin();
2849  for(unsigned int i=0;i<n;++i)++pos;
2850  map<MolAtom*,XYZ> v0;
2851  for(set<MolAtom*>::iterator at=pos->mvpAtom.begin();at!=pos->mvpAtom.end();++at)
2852  v0[*at]=XYZ(rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5);
2853 
2854  const REAL nrj0=mMDMoveEnergy*( pos->mvpBond.size()
2855  +pos->mvpBondAngle.size()
2856  +pos->mvpDihedralAngle.size());
2857  map<RigidGroup*,std::pair<XYZ,XYZ> > vr;
2858  float nrjMult=1.0+mutationAmplitude*0.2;
2859  if((rand()%20)==0) nrjMult=4.0;
2860  this->MolecularDynamicsEvolve(v0, int(100*sqrt(mutationAmplitude)),0.004,
2861  pos->mvpBond,
2862  pos->mvpBondAngle,
2863  pos->mvpDihedralAngle,
2864  vr,nrj0*nrjMult);
2865  }
2866  #endif
2867  else
2868  {
2869  #if 0 // For tests
2870  mLogLikelihood=0;
2871  for(vector<MolBond*>::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
2872  mLogLikelihood+=(*pos)->GetLogLikelihood(true,true);
2873  for(vector<MolBondAngle*>::const_iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
2874  mLogLikelihood+=(*pos)->GetLogLikelihood(true,true);
2875  for(vector<MolDihedralAngle*>::const_iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
2876  mLogLikelihood+=(*pos)->GetLogLikelihood(true,true);
2877  for(list<StretchMode*>::const_iterator mode=mvpStretchModeNotFree.begin();
2878  mode!=mvpStretchModeNotFree.end();++mode)
2879  {
2880  //if((rand()%3)==0)
2881  {
2882  // 2) Get the derivative of the overall LLK for this mode
2883  (*mode)->CalcDeriv();
2884  REAL llk=0;
2885  for(map<const MolBond*,REAL>::const_iterator pos=(*mode)->mvpBrokenBond.begin();
2886  pos!=(*mode)->mvpBrokenBond.end();++pos) llk+=pos->first->GetLogLikelihood(false,false);
2887  for(map<const MolBondAngle*,REAL>::const_iterator pos=(*mode)->mvpBrokenBondAngle.begin();
2888  pos!=(*mode)->mvpBrokenBondAngle.end();++pos) llk+=pos->first->GetLogLikelihood(false,false);
2889  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=(*mode)->mvpBrokenDihedralAngle.begin();
2890  pos!=(*mode)->mvpBrokenDihedralAngle.end();++pos) llk+=pos->first->GetLogLikelihood(false,false);
2891  // 3) Calculate MD move. base step =0.1 A (accelerated moves may go faster)
2892  REAL change=(2.*(REAL)rand()-(REAL)RAND_MAX)/(REAL)RAND_MAX;
2893  // if llk>100, change has to be in the opposite direction
2894  // For a single restraint, sqrt(llk)=dx/sigma, so do not go above 10*sigma
2895  if((*mode)->mLLKDeriv>0)
2896  {
2897  change -= 0.3*sqrt(llk);
2898  if(change<-1) change=-1;
2899  }
2900  else
2901  {
2902  change += 0.3*sqrt(llk);
2903  if(change>1) change=1;
2904  }
2905  (*mode)->Print(cout);
2906  change *= mutationAmplitude * (*mode)->mBaseAmplitude;
2907  cout <<" Change="<<change<<" (dLLK= "<<(*mode)->mLLKDeriv<<"), llk= "<<llk<<" ?->"<<llk+(*mode)->mLLKDeriv*change<<endl;
2908  //change *= mutationAmplitude * (*mode)->mBaseAmplitude;
2909  (*mode)->Stretch(change);
2910  llk=0;
2911  //(*mode)->RandomStretch(change * mutationAmplitude * (*mode)->mBaseAmplitude);
2912  for(map<const MolBond*,REAL>::const_iterator pos=(*mode)->mvpBrokenBond.begin();
2913  pos!=(*mode)->mvpBrokenBond.end();++pos)
2914  {
2915  cout<<" "<<pos->first->GetName()<<", llk= "<<pos->first->GetLogLikelihood(false,false)
2916  <<" ?->"<<pos->first->GetLogLikelihood(false,false)+pos->first->GetDeriv((*mode)->mDerivXYZ,true)*change
2917  <<"? (deriv="<<pos->first->GetDeriv((*mode)->mDerivXYZ)<<", "<<pos->first->GetDeriv((*mode)->mDerivXYZ,true);
2918  cout<<") ->" <<pos->first->GetLogLikelihood()<<endl;
2919  llk+=pos->first->GetLogLikelihood(false,false);
2920  }
2921  for(map<const MolBondAngle*,REAL>::const_iterator pos=(*mode)->mvpBrokenBondAngle.begin();
2922  pos!=(*mode)->mvpBrokenBondAngle.end();++pos)
2923  {
2924  cout<<" "<<pos->first->GetName()<<", llk= "<<pos->first->GetLogLikelihood(false,false)
2925  <<" ?->"<<pos->first->GetLogLikelihood(false,false)+pos->first->GetDeriv((*mode)->mDerivXYZ,true)*change
2926  <<"? (deriv="<<pos->first->GetDeriv((*mode)->mDerivXYZ)<<", "<<pos->first->GetDeriv((*mode)->mDerivXYZ,true);
2927  cout<<") ->" <<pos->first->GetLogLikelihood()<<endl;
2928  llk+=pos->first->GetLogLikelihood(false,false);
2929  }
2930  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=(*mode)->mvpBrokenDihedralAngle.begin();
2931  pos!=(*mode)->mvpBrokenDihedralAngle.end();++pos)
2932  {
2933  cout<<" "<<pos->first->GetName()<<", llk= "<<pos->first->GetLogLikelihood(false,false)
2934  <<" ?->"<<pos->first->GetLogLikelihood(false,false)+pos->first->GetDeriv((*mode)->mDerivXYZ,true)*change
2935  <<"? (deriv="<<pos->first->GetDeriv((*mode)->mDerivXYZ)<<", "<<pos->first->GetDeriv((*mode)->mDerivXYZ,true);
2936  cout<<") ->" <<pos->first->GetLogLikelihood()<<endl;
2937  llk+=pos->first->GetLogLikelihood(false,false);
2938  }
2939  cout <<" -> "<<llk<<endl;
2940  }
2941  }
2942  #else
2943  // First move free Stretch modes
2944  TAU_PROFILE_START(timer2);
2945  for(list<StretchMode*>::iterator mode=mvpStretchModeFree.begin();
2946  mode!=mvpStretchModeFree.end();++mode)
2947  {
2948  if((rand()%2)==0) (*mode)->RandomStretch(mutationAmplitude);
2949  }
2950  TAU_PROFILE_STOP(timer2);
2951  if((rand()%3)==0)
2952  {
2953  // Now do an hybrid move for other modes, with a smaller amplitude (<=0.5)
2954  // 1) Calc LLK and derivatives for restraints
2955  mLogLikelihood=0;
2956  TAU_PROFILE_START(timer3);
2957  for(vector<MolBond*>::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
2958  mLogLikelihood+=(*pos)->GetLogLikelihood(true,true);
2959  for(vector<MolBondAngle*>::const_iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
2960  mLogLikelihood+=(*pos)->GetLogLikelihood(true,true);
2961  for(vector<MolDihedralAngle*>::const_iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
2962  mLogLikelihood+=(*pos)->GetLogLikelihood(true,true);
2963  TAU_PROFILE_STOP(timer3);
2964 
2965  TAU_PROFILE_START(timer4);
2966  for(list<StretchMode*>::const_iterator mode=mvpStretchModeNotFree.begin();
2967  mode!=mvpStretchModeNotFree.end();++mode)
2968  {
2969  // 2) Choose Stretch modes
2970  if((rand()%3)==0)
2971  {
2972  // 2) Get the derivative of the overall LLK for this mode
2973  (*mode)->CalcDeriv();
2974  REAL llk=0;
2975  for(map<const MolBond*,REAL>::const_iterator pos=(*mode)->mvpBrokenBond.begin();
2976  pos!=(*mode)->mvpBrokenBond.end();++pos) llk+=pos->first->GetLogLikelihood(false,false);
2977  for(map<const MolBondAngle*,REAL>::const_iterator pos=(*mode)->mvpBrokenBondAngle.begin();
2978  pos!=(*mode)->mvpBrokenBondAngle.end();++pos) llk+=pos->first->GetLogLikelihood(false,false);
2979  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=(*mode)->mvpBrokenDihedralAngle.begin();
2980  pos!=(*mode)->mvpBrokenDihedralAngle.end();++pos) llk+=pos->first->GetLogLikelihood(false,false);
2981  REAL change=(2.*(REAL)rand()-(REAL)RAND_MAX)/(REAL)RAND_MAX;
2982  // if llk>100, change has to be in the direction minimising the llk
2983  if((*mode)->mLLKDeriv>0)
2984  {
2985  change -= 0.01*llk;
2986  if(change<-1) change=-1;
2987  }
2988  else
2989  {
2990  change += 0.01*llk;
2991  if(change>1) change=1;
2992  }
2993  if(mutationAmplitude<0.5) change *= mutationAmplitude * (*mode)->mBaseAmplitude;
2994  else change *= 0.5 * (*mode)->mBaseAmplitude;
2995  (*mode)->Stretch(change);
2996  }
2997  }
2998  // Here we do not take mLogLikelihoodScale into account
2999  // :TODO: take into account cases where the lllk cannot go down to 0 because of
3000  // combined restraints.
3001  if( ((rand()%100)==0) && (mLogLikelihood>(mvpRestraint.size()*10)))
3003  TAU_PROFILE_STOP(timer4);
3004  }
3005 
3006  // Perform MD moves if there are MDAtomGroups
3007  #if 0
3008  for(list<MDAtomGroup>::iterator pos=mvMDAtomGroup.begin();pos!=mvMDAtomGroup.end();++pos)
3009  {
3010  if((rand()%100)==0)
3011  {
3012  map<MolAtom*,XYZ> v0;
3013  for(set<MolAtom*>::iterator at=pos->mvpAtom.begin();at!=pos->mvpAtom.end();++at)
3014  v0[*at]=XYZ(rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5,rand()/(REAL)RAND_MAX+0.5);
3015 
3016  const REAL nrj0=20*(pos->mvpBond.size()+pos->mvpBondAngle.size()+pos->mvpDihedralAngle.size());
3017  map<RigidGroup*,std::pair<XYZ,XYZ> > vr;
3018  this->MolecularDynamicsEvolve(v0, int(100*sqrt(mutationAmplitude)),0.002,
3019  (const vector<MolBond*>) (pos->mvpBond),
3020  (const vector<MolBondAngle*>) (pos->mvpBondAngle),
3021  (const vector<MolDihedralAngle*>) (pos->mvpDihedralAngle),
3022  vr,nrj0);
3023  }
3024  }
3025  #endif
3026  }
3027  // Do a steepest descent from time to time
3028  if((rand()%100)==0) this->OptimizeConformationSteepestDescent(0.02,1);
3029 
3030  mClockLogLikelihood.Click();
3031  #endif
3032  }
3033  }
3034  }
3035  if((rand()%100)==0)
3036  {// From time to time, bring back average position to 0
3037  REAL x0=0,y0=0,z0=0;
3038  for(vector<MolAtom*>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
3039  {
3040  x0 += (*pos)->X();
3041  y0 += (*pos)->Y();
3042  z0 += (*pos)->Z();
3043  }
3044  x0 /= mvpAtom.size();
3045  y0 /= mvpAtom.size();
3046  z0 /= mvpAtom.size();
3047  for(vector<MolAtom*>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
3048  {
3049  (*pos)->X() -= x0;
3050  (*pos)->Y() -= y0;
3051  (*pos)->Z() -= z0;
3052  }
3053  }
3054  mRandomMoveIsDone=true;
3055  VFN_DEBUG_EXIT("Molecule::GlobalOptRandomMove()",4)
3056 }
3057 
3059 {
3060  if( (mClockLogLikelihood>mClockAtomList)
3061  &&(mClockLogLikelihood>mClockBondList)
3062  &&(mClockLogLikelihood>mClockBondAngleList)
3063  &&(mClockLogLikelihood>mClockDihedralAngleList)
3064  &&(mClockLogLikelihood>mClockAtomPosition)
3065  &&(mClockLogLikelihood>mClockScatterer)) return mLogLikelihood*mLogLikelihoodScale;
3066  TAU_PROFILE("Molecule::GetLogLikelihood()","REAL ()",TAU_DEFAULT);
3068  mClockLogLikelihood.Click();
3070 }
3071 
3072 unsigned int Molecule::GetNbLSQFunction()const
3073 {
3074  return 1;
3075 }
3076 
3077 const CrystVector_REAL& Molecule::GetLSQCalc(const unsigned int) const
3078 {
3079  mLSQCalc.resize(mvpRestraint.size());
3080  REAL *p=mLSQCalc.data();
3081  for(vector<MolBond*>::const_iterator pos=this->GetBondList().begin();pos!=this->GetBondList().end();++pos)
3082  *p++=(*pos)->GetLength();
3083  for(vector<MolBondAngle*>::const_iterator pos=this->GetBondAngleList().begin();pos!=this->GetBondAngleList().end();++pos)
3084  *p++=(*pos)->GetAngle();
3085  for(vector<MolDihedralAngle*>::const_iterator pos=this->GetDihedralAngleList().begin();pos!=this->GetDihedralAngleList().end();++pos)
3086  *p++=(*pos)->GetAngle();
3087  return mLSQCalc;
3088 }
3089 
3090 const CrystVector_REAL& Molecule::GetLSQObs(const unsigned int) const
3091 {
3092  mLSQObs.resize(mvpRestraint.size());
3093  REAL *p=mLSQObs.data();
3094  for(vector<MolBond*>::const_iterator pos=this->GetBondList().begin();pos!=this->GetBondList().end();++pos)
3095  *p++=(*pos)->GetLength0();
3096  for(vector<MolBondAngle*>::const_iterator pos=this->GetBondAngleList().begin();pos!=this->GetBondAngleList().end();++pos)
3097  *p++=(*pos)->GetAngle0();
3098  for(vector<MolDihedralAngle*>::const_iterator pos=this->GetDihedralAngleList().begin();pos!=this->GetDihedralAngleList().end();++pos)
3099  *p++=(*pos)->GetAngle0();
3100  return mLSQObs;
3101 }
3102 
3103 const CrystVector_REAL& Molecule::GetLSQWeight(const unsigned int) const
3104 {
3105  //:TODO: USe a clock to avoid re-computation
3106  mLSQWeight.resize(mvpRestraint.size());
3107  REAL *p=mLSQWeight.data();
3108  for(vector<MolBond*>::const_iterator pos=this->GetBondList().begin();pos!=this->GetBondList().end();++pos)
3109  *p++=1/((*pos)->GetLengthSigma()* (*pos)->GetLengthSigma()+1e-6);
3110  for(vector<MolBondAngle*>::const_iterator pos=this->GetBondAngleList().begin();pos!=this->GetBondAngleList().end();++pos)
3111  *p++=1/((*pos)->GetAngleSigma()* (*pos)->GetAngleSigma()+1e-6);
3112  for(vector<MolDihedralAngle*>::const_iterator pos=this->GetDihedralAngleList().begin();pos!=this->GetDihedralAngleList().end();++pos)
3113  *p++=1/((*pos)->GetAngleSigma()* (*pos)->GetAngleSigma()+1e-6);
3115  return mLSQWeight;
3116 }
3117 
3118 const CrystVector_REAL& Molecule::GetLSQDeriv(const unsigned int n, RefinablePar&par)
3119 {
3120  //:TODO: return analytical derivatives
3121  return RefinableObj::GetLSQDeriv(n,par);
3122 }
3123 
3125 {
3126  this->ResetRigidGroupsPar();
3127  #if 0
3128  cout<<"Molecule::TagNewBestConfig()"<<endl;
3129  {
3130  vector<MolBond*>::const_iterator pos;
3131  for(pos=mvpBond.begin();pos!=mvpBond.end();++pos)
3132  {
3133  cout<<"BondLength="<<(*pos)->GetLength();
3134  (*pos)->XMLOutput(cout);
3135  }
3136  }
3137  {
3138  vector<MolBondAngle*>::const_iterator pos;
3139  for(pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
3140  {
3141  cout<<"BondAngle="<<(*pos)->GetAngle();
3142  (*pos)->XMLOutput(cout);
3143  }
3144  }
3145  {
3146  vector<MolDihedralAngle*>::const_iterator pos;
3147  for(pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
3148  {
3149  cout<<"DihedralAngle="<<(*pos)->GetAngle();
3150  (*pos)->XMLOutput(cout);
3151  }
3152  }
3153 
3154  for(list<MDAtomGroup>::iterator pos=mvMDAtomGroup.begin();pos!=mvMDAtomGroup.end();++pos)
3155  {
3156  char buf[100];
3157  for(set<MolAtom*>::iterator at1=pos->mvpAtom.begin();at1!=pos->mvpAtom.end();++at1)
3158  {
3159  sprintf(buf,"%5s : ",(*at1)->GetName().c_str());
3160  cout<<buf;
3161  for(set<MolAtom*>::iterator at2=at1;at2!=pos->mvpAtom.end();++at2)
3162  {
3163  if(at1==at2) continue;
3164  sprintf(buf,"%5s(%6.3f),",(*at2)->GetName().c_str(),GetBondLength(**at1,**at2));
3165  cout<<buf;
3166  }
3167  cout<<endl;
3168  }
3169  }
3170  #endif
3171 }
3172 
3173 int Molecule::GetNbComponent() const { return mvpAtom.size();}
3174 
3176 {
3177  VFN_DEBUG_ENTRY("Molecule::GetScatteringComponentList()",3)
3178  this->UpdateScattCompList();
3179  VFN_DEBUG_EXIT("Molecule::GetScatteringComponentList()",3)
3180  return mScattCompList;
3181 }
3182 
3183 string Molecule::GetComponentName(const int i) const
3184 {
3185  //if(mvpAtom[i]->IsDummy()) return "Dummy";
3186  return mvpAtom[i]->GetName();
3187 }
3188 
3189 ostream& Molecule::POVRayDescription(ostream &os,const CrystalPOVRayOptions &options)const
3190 {
3191  VFN_DEBUG_ENTRY("Molecule::POVRayDescription()",3)
3192  const REAL xMin=options.mXmin; const REAL xMax=options.mXmax;
3193  const REAL yMin=options.mYmin; const REAL yMax=options.mYmax;
3194  const REAL zMin=options.mZmin; const REAL zMax=options.mZmax;
3195  if(mvpAtom.size()==0)
3196  {
3197  VFN_DEBUG_EXIT("Molecule::POVRayDescription():No atom to display !",4)
3198  return os;
3199  }
3200  this->UpdateScattCompList();
3201 
3202  const REAL aa=this->GetCrystal().GetLatticePar(0);
3203  const REAL bb=this->GetCrystal().GetLatticePar(1);
3204  const REAL cc=this->GetCrystal().GetLatticePar(2);
3205 
3206  os << "// Description of Molecule :" << this->GetName() <<endl;
3207  vector<CrystMatrix_REAL> vXYZCoords;
3208  {
3210  REAL x0,y0,z0;
3211  for(long i=0;i<mScattCompList.GetNbComponent();++i)
3212  {
3213  x0=mScattCompList(i).mX;
3214  y0=mScattCompList(i).mY;
3215  z0=mScattCompList(i).mZ;
3216  vXYZCoords.push_back(this->GetCrystal().GetSpaceGroup().
3217  GetAllSymmetrics(x0,y0,z0,false,false,false));
3218  }
3219  }
3220  CrystMatrix_int translate(27,3);
3221  translate= -1,-1,-1,
3222  -1,-1, 0,
3223  -1,-1, 1,
3224  -1, 0,-1,
3225  -1, 0, 0,
3226  -1, 0, 1,
3227  -1, 1,-1,
3228  -1, 1, 0,
3229  -1, 1, 1,
3230  0,-1,-1,
3231  0,-1, 0,
3232  0,-1, 1,
3233  0, 0,-1,
3234  0, 0, 0,
3235  0, 0, 1,
3236  0, 1,-1,
3237  0, 1, 0,
3238  0, 1, 1,
3239  1,-1,-1,
3240  1,-1, 0,
3241  1,-1, 1,
3242  1, 0,-1,
3243  1, 0, 0,
3244  1, 0, 1,
3245  1, 1,-1,
3246  1, 1, 0,
3247  1, 1, 1;
3248  REAL dx,dy,dz;
3249  CrystVector_REAL x(mvpAtom.size()),y(mvpAtom.size()),z(mvpAtom.size());
3250  CrystVector_REAL xSave,ySave,zSave;
3251  const int nbSymmetrics=vXYZCoords[0].rows();
3252  unsigned int ct=0;
3253  for(int i=0;i<nbSymmetrics;i++)
3254  {
3255  VFN_DEBUG_ENTRY("Molecule::POVRayDescription():Symmetric#"<<i,3)
3256  for(unsigned int j=0;j<mvpAtom.size();j++)
3257  {
3258  x(j)=vXYZCoords[j](i,0);
3259  y(j)=vXYZCoords[j](i,1);
3260  z(j)=vXYZCoords[j](i,2);
3261  }
3262  //Bring back central atom in unit cell; move peripheral atoms with the same amount
3263  dx=x(0);
3264  dy=y(0);
3265  dz=z(0);
3266  x(0) = fmod((float) x(0),(float)1); if(x(0)<0) x(0)+=1.;
3267  y(0) = fmod((float) y(0),(float)1); if(y(0)<0) y(0)+=1.;
3268  z(0) = fmod((float) z(0),(float)1); if(z(0)<0) z(0)+=1.;
3269  dx = x(0)-dx;
3270  dy = y(0)-dy;
3271  dz = z(0)-dz;
3272  for(unsigned int j=1;j<mvpAtom.size();j++)
3273  {
3274  x(j) += dx;
3275  y(j) += dy;
3276  z(j) += dz;
3277  }
3278  //Generate also translated atoms near the unit cell
3279  xSave=x;
3280  ySave=y;
3281  zSave=z;
3282  for(int j=0;j<translate.rows();j++)
3283  {
3284  x += translate(j,0);
3285  y += translate(j,1);
3286  z += translate(j,2);
3287  CrystVector<bool> isinside(x.numElements());
3288  CrystVector<REAL> borderdist(x.numElements());//distance to display limit
3289  CrystVector<REAL> x0,y0,z0;
3290  x0=x;y0=y;z0=z;
3291  if( ((x.min()<xMax) && (x.max()>xMin))
3292  &&((y.min()<yMax) && (y.max()>yMin))
3293  &&((z.min()<zMax) && (z.max()>zMin)))
3294  {
3295  os<<" //Symetric#"<<++ct<<endl;
3296  for(unsigned int k=0;k<mvpAtom.size();k++)
3297  {
3298  isinside(k)=((x(k)>=xMin) && (x(k)<=xMax)) && ((y(k)>=yMin) && (y(k)<=yMax)) && ((z(k)>=zMin) && (z(k)<=zMax));
3299  if(isinside(k)) borderdist(k)=0;
3300  else
3301  {
3302  borderdist(k)=0;
3303  if(xMin>x(k)) borderdist(k)+=(xMin-x(k))*aa*(xMin-x(k))*aa;
3304  if(yMin>y(k)) borderdist(k)+=(yMin-y(k))*bb*(yMin-y(k))*bb;
3305  if(zMin>z(k)) borderdist(k)+=(zMin-z(k))*cc*(zMin-z(k))*cc;
3306  if(xMax<x(k)) borderdist(k)+=(xMax-x(k))*aa*(xMax-x(k))*aa;
3307  if(yMax<y(k)) borderdist(k)+=(yMax-y(k))*bb*(yMax-y(k))*bb;
3308  if(zMax<z(k)) borderdist(k)+=(zMax-z(k))*cc*(zMax-z(k))*cc;
3309  borderdist(k)=sqrt(borderdist(k));
3310  }
3311  REAL fout=1.0;
3312  if(isinside(k)==false) fout=exp(-borderdist(k))*this->GetCrystal().GetDynPopCorr(this,k);
3313 
3314  this->GetCrystal().FractionalToOrthonormalCoords(x(k),y(k),z(k));
3315  if((mvpAtom[k]->IsDummy()) || (fout<0.001)) continue;
3316  if(options.mShowHydrogens==false && (mvpAtom[k]->GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)) continue;
3317  // const float r=mvpAtom[k]->GetScatteringPower().GetColourRGB()[0];
3318  // const float g=mvpAtom[k]->GetScatteringPower().GetColourRGB()[1];
3319  // const float b=mvpAtom[k]->GetScatteringPower().GetColourRGB()[2];
3320  const float f=mvpAtom[k]->GetOccupancy()*this->GetOccupancy();
3321  if(options.mShowLabel)
3322  {
3323  /*
3324  const float colour0[] = {0.0f, 0.0f, 0.0f, 0.0f};
3325  GLfloat colourChar [] = {1.0, 1.0, 1.0, 1.0};
3326  if((r>0.8)&&(g>0.8)&&(b>0.8))
3327  {
3328  colourChar[0] = 0.5;
3329  colourChar[1] = 0.5;
3330  colourChar[2] = 0.5;
3331  }
3332  glMaterialfv(GL_FRONT, GL_AMBIENT, colour0);
3333  glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0);
3334  glMaterialfv(GL_FRONT, GL_SPECULAR, colour0);
3335  glMaterialfv(GL_FRONT, GL_EMISSION, colourChar);
3336  glMaterialfv(GL_FRONT, GL_SHININESS,colour0);
3337  glRasterPos3f(x(k), y(k), z(k));
3338  crystGLPrint(mvpAtom[k]->GetName());
3339  */
3340  }
3341  os << " ObjCrystAtom("
3342  <<x(k)<<","
3343  <<y(k)<<","
3344  <<z(k)<<","
3345  <<mvpAtom[k]->GetScatteringPower().GetRadius()/3.0<<","
3346  <<"colour_"+mvpAtom[k]->GetScatteringPower().GetName()<<","
3347  <<f<<","<<fout
3348  <<")"<<endl;
3349  }
3350  for(unsigned int k=0;k<mvpBond.size();k++)
3351  {
3352  if( (mvpBond[k]->GetAtom1().IsDummy())
3353  ||(mvpBond[k]->GetAtom2().IsDummy()) ) continue;
3354  if(options.mShowHydrogens==false && ( (mvpBond[k]->GetAtom1().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)
3355  ||(mvpBond[k]->GetAtom2().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5))) continue;
3356  unsigned long n1,n2;
3357  //:KLUDGE: Get the atoms
3358  for(n1=0;n1<mvpAtom.size();n1++)
3359  if(mvpAtom[n1]==&(mvpBond[k]->GetAtom1())) break;
3360  for(n2=0;n2<mvpAtom.size();n2++)
3361  if(mvpAtom[n2]==&(mvpBond[k]->GetAtom2())) break;
3362  REAL fout=1.0;
3363  if((isinside(n1)==false) || (isinside(n2)==false))
3364  fout=exp(-(borderdist(n1)+borderdist(n2))/2)*(this->GetCrystal().GetDynPopCorr(this,n1)+this->GetCrystal().GetDynPopCorr(this,n2))/2;
3365  if(fout<0.001) continue;
3366  REAL x1=x(n1),y1=y(n1),z1=z(n1),
3367  x2=x(n2),y2=y(n2),z2=z(n2);
3368  REAL dx=x2-x1,dy=y2-y1,dz=z2-z1;
3369  const REAL r=sqrt(abs(dx*dx+dy*dy+dz*dz))+1e-6;
3370  const REAL r1=mvpAtom[n1]->GetScatteringPower().GetRadius()/3.0;
3371  const REAL r2=mvpAtom[n2]->GetScatteringPower().GetRadius()/3.0;
3372  x1+=dx/r*r1*sqrt(abs(1-0.1/r1));
3373  y1+=dy/r*r1*sqrt(abs(1-0.1/r1));
3374  z1+=dz/r*r1*sqrt(abs(1-0.1/r1));
3375  x2-=dx/r*r2*sqrt(abs(1-0.1/r2));
3376  y2-=dy/r*r2*sqrt(abs(1-0.1/r2));
3377  z2-=dz/r*r2*sqrt(abs(1-0.1/r2));
3378  const REAL f=this->GetOccupancy()*(mvpAtom[n1]->GetOccupancy()+mvpAtom[n2]->GetOccupancy())/2.0;
3379  os << " ObjCrystBond("
3380  <<x1<<","<<y1<<","<<z1<< ","
3381  <<x2<<","<<y2<<","<<z2<< ","
3382  << "0.1,";
3383  if(mvpBond[k]->IsFreeTorsion()) os<<"colour_freebond,";
3384  else os<<"colour_nonfreebond,";
3385  os<<f<<","<<fout<<")"<<endl;
3386  }
3387  }//if in limits
3388  x=xSave;
3389  y=ySave;
3390  z=zSave;
3391  }//for translation
3392  VFN_DEBUG_EXIT("Molecule::POVRayDescription():Symmetric#"<<i,3)
3393  }//for symmetrics
3394  VFN_DEBUG_EXIT("Molecule::POVRayDescription()",3)
3395  return os;
3396 }
3397 
3398 void Molecule::GLInitDisplayList(const bool onlyIndependentAtoms,
3399  const REAL xMin,const REAL xMax,
3400  const REAL yMin,const REAL yMax,
3401  const REAL zMin,const REAL zMax,
3402  const bool displayEnantiomer,
3403  const bool displayNames,
3404  const bool hideHydrogens)const
3405 {
3406  #ifdef OBJCRYST_GL
3407  VFN_DEBUG_ENTRY("Molecule::GLInitDisplayList()",3)
3408  if(mvpAtom.size()==0)
3409  {
3410  VFN_DEBUG_EXIT("Molecule::GLInitDisplayList():No atom to display !",4)
3411  return;
3412  }
3413  bool large=false;
3414  if(mvpAtom.size()>200) large=true;
3415  REAL en=1;
3416  if(displayEnantiomer==true) en=-1;
3417  this->UpdateScattCompList();
3418  //this->BuildRingList();
3419  //this->BuildStretchModeBondLength();
3420  //this->BuildStretchModeBondAngle();
3421  //this->BuildStretchModeTorsion();
3422 
3423  const REAL aa=this->GetCrystal().GetLatticePar(0);
3424  const REAL bb=this->GetCrystal().GetLatticePar(1);
3425  const REAL cc=this->GetCrystal().GetLatticePar(2);
3426 
3427  const GLfloat colour0[] = {0.0f, 0.0f, 0.0f, 0.0f};
3428  glMaterialfv(GL_FRONT, GL_SPECULAR, colour0);
3429  glMaterialfv(GL_FRONT, GL_EMISSION, colour0);
3430  glMaterialfv(GL_FRONT, GL_SHININESS, colour0);
3431  glPolygonMode(GL_FRONT, GL_FILL);
3432 
3433  GLUquadricObj* pQuadric = gluNewQuadric();
3434 
3435  if(true==onlyIndependentAtoms)//
3436  {
3437  REAL xc=mXYZ(0),yc=mXYZ(1),zc=mXYZ(2);
3438  this->GetCrystal().FractionalToOrthonormalCoords(xc,yc,zc);
3439  vector<MolAtom*>::const_iterator pos;
3440  for(pos=mvpAtom.begin();pos!=mvpAtom.end();pos++)
3441  {
3442 
3443  if((*pos)->IsDummy())continue;
3444  if(hideHydrogens && ((*pos)->GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)) continue;
3445  const float r=(*pos)->GetScatteringPower().GetColourRGB()[0];
3446  const float g=(*pos)->GetScatteringPower().GetColourRGB()[1];
3447  const float b=(*pos)->GetScatteringPower().GetColourRGB()[2];
3448  const float f=(*pos)->GetOccupancy()*this->GetOccupancy();
3449  glPushMatrix();
3450  if(displayNames)
3451  {
3452  GLfloat colourChar [] = {1.0, 1.0, 1.0, 1.0};
3453  GLfloat colourCharRing [] = {1.0, 1.0, 0.8, 1.0};
3454  if((r>0.8)&&(g>0.8)&&(b>0.8))
3455  {
3456  colourChar[0] = 0.5;
3457  colourChar[1] = 0.5;
3458  colourChar[2] = 0.5;
3459  }
3460  if((*pos)->IsInRing())
3461  glMaterialfv(GL_FRONT, GL_EMISSION, colourCharRing);
3462  else
3463  glMaterialfv(GL_FRONT, GL_EMISSION, colourChar);
3464  glMaterialfv(GL_FRONT, GL_SHININESS, colour0);
3465  glTranslatef((*pos)->X()*en+xc, (*pos)->Y()+yc, (*pos)->Z()+zc);
3466  crystGLPrint((*pos)->GetName());
3467  }
3468  else
3469  {
3470  const GLfloat colourAtom [] = {r, g, b, f};
3471  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, colourAtom);
3472  glTranslatef((*pos)->X()*en+xc, (*pos)->Y()+yc, (*pos)->Z()+zc);
3473  gluSphere(pQuadric,(*pos)->GetScatteringPower().GetRadius()/3.,20,20);
3474  }
3475  glPopMatrix();
3476  }
3477  }//Only independent atoms ?
3478  else
3479  {
3480  VFN_DEBUG_ENTRY("Molecule::GLInitDisplayList():Show all symmetrics",3)
3481  // Reverse index of atoms
3482  map<const MolAtom*,unsigned long> rix;
3483  {
3484  long i=0;
3485  for(vector<MolAtom*>::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
3486  rix[*pos]=i++;
3487  }
3488  vector<CrystMatrix_REAL> vXYZCoords;
3489  {
3491  REAL x0,y0,z0;
3492  for(long i=0;i<mScattCompList.GetNbComponent();++i)
3493  {
3494  x0=mScattCompList(i).mX;
3495  y0=mScattCompList(i).mY;
3496  z0=mScattCompList(i).mZ;
3497  vXYZCoords.push_back(this->GetCrystal().GetSpaceGroup().
3498  GetAllSymmetrics(x0,y0,z0,false,false,false));
3499  }
3500  }
3501  CrystMatrix_int translate(27,3);
3502  translate= -1,-1,-1,
3503  -1,-1, 0,
3504  -1,-1, 1,
3505  -1, 0,-1,
3506  -1, 0, 0,
3507  -1, 0, 1,
3508  -1, 1,-1,
3509  -1, 1, 0,
3510  -1, 1, 1,
3511  0,-1,-1,
3512  0,-1, 0,
3513  0,-1, 1,
3514  0, 0,-1,
3515  0, 0, 0,
3516  0, 0, 1,
3517  0, 1,-1,
3518  0, 1, 0,
3519  0, 1, 1,
3520  1,-1,-1,
3521  1,-1, 0,
3522  1,-1, 1,
3523  1, 0,-1,
3524  1, 0, 0,
3525  1, 0, 1,
3526  1, 1,-1,
3527  1, 1, 0,
3528  1, 1, 1;
3529  REAL dx,dy,dz;
3530  CrystVector_REAL x(mvpAtom.size()),y(mvpAtom.size()),z(mvpAtom.size());
3531  CrystVector_REAL xSave,ySave,zSave;
3532  const int nbSymmetrics=vXYZCoords[0].rows();
3533  for(int i=0;i<nbSymmetrics;i++)
3534  {
3535  VFN_DEBUG_ENTRY("Molecule::GLInitDisplayList():Symmetric#"<<i,3)
3536  for(unsigned int j=0;j<mvpAtom.size();j++)
3537  {
3538  x(j)=vXYZCoords[j](i,0);
3539  y(j)=vXYZCoords[j](i,1);
3540  z(j)=vXYZCoords[j](i,2);
3541  }
3542  //Bring back central atom in unit cell; move peripheral atoms with the same amount
3543  dx=x(0);
3544  dy=y(0);
3545  dz=z(0);
3546  x(0) = fmod((float) x(0),(float)1); if(x(0)<0) x(0)+=1.;
3547  y(0) = fmod((float) y(0),(float)1); if(y(0)<0) y(0)+=1.;
3548  z(0) = fmod((float) z(0),(float)1); if(z(0)<0) z(0)+=1.;
3549  dx = x(0)-dx;
3550  dy = y(0)-dy;
3551  dz = z(0)-dz;
3552  for(unsigned int j=1;j<mvpAtom.size();j++)
3553  {
3554  x(j) += dx;
3555  y(j) += dy;
3556  z(j) += dz;
3557  }
3558  //Generate also translated atoms near the unit cell
3559  xSave=x;
3560  ySave=y;// Keep untranslated, fractionnal values
3561  zSave=z;
3562  for(int j=0;j<translate.rows();j++)
3563  {
3564  x += translate(j,0);
3565  y += translate(j,1);
3566  z += translate(j,2);
3567  CrystVector<bool> isinside(x.numElements());
3568  CrystVector<REAL> borderdist(x.numElements());//distance to display limit
3569  if( ((x.min()<xMax) && (x.max()>xMin))
3570  &&((y.min()<yMax) && (y.max()>yMin))
3571  &&((z.min()<zMax) && (z.max()>zMin)))
3572  {
3573  for(unsigned int k=0;k<mvpAtom.size();k++)
3574  {
3575  isinside(k)=((x(k)>=xMin) && (x(k)<=xMax)) && ((y(k)>=yMin) && (y(k)<=yMax)) && ((z(k)>=zMin) && (z(k)<=zMax));
3576  if(isinside(k)) borderdist(k)=0;
3577  else
3578  {
3579  borderdist(k)=0;
3580  if(xMin>x(k)) borderdist(k)+=(xMin-x(k))*aa*(xMin-x(k))*aa;
3581  if(yMin>y(k)) borderdist(k)+=(yMin-y(k))*bb*(yMin-y(k))*bb;
3582  if(zMin>z(k)) borderdist(k)+=(zMin-z(k))*cc*(zMin-z(k))*cc;
3583  if(xMax<x(k)) borderdist(k)+=(xMax-x(k))*aa*(xMax-x(k))*aa;
3584  if(yMax<y(k)) borderdist(k)+=(yMax-y(k))*bb*(yMax-y(k))*bb;
3585  if(zMax<z(k)) borderdist(k)+=(zMax-z(k))*cc*(zMax-z(k))*cc;
3586  borderdist(k)=sqrt(borderdist(k));
3587  }
3588  REAL fout=1.0;
3589  if(isinside(k)==false) fout=exp(-borderdist(k))*this->GetCrystal().GetDynPopCorr(this,k);
3590  #ifdef __DEBUG__
3591  char ch[100];
3592  sprintf(ch,"%d %d %d %s %5.2f %5.2f %5.2f d=%5.2f fout=%5.3f",i,j,k,mvpAtom[k]->GetName().c_str(),x(k),y(k),z(k),borderdist(k),fout);
3593  VFN_DEBUG_MESSAGE(ch,4)
3594  #endif
3595  this->GetCrystal().FractionalToOrthonormalCoords(x(k),y(k),z(k));
3596  if(mvpAtom[k]->IsDummy()) continue;
3597  if(hideHydrogens && (mvpAtom[k]->GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)) continue;
3598  if(fout<0.01) continue;
3599  glPushMatrix();
3600  const float r=mvpAtom[k]->GetScatteringPower().GetColourRGB()[0];
3601  const float g=mvpAtom[k]->GetScatteringPower().GetColourRGB()[1];
3602  const float b=mvpAtom[k]->GetScatteringPower().GetColourRGB()[2];
3603  const float f=mvpAtom[k]->GetOccupancy()*this->GetOccupancy();
3604  if(displayNames)
3605  {
3606  if(fout>0.99)
3607  {
3608  GLfloat colourChar [] = {1.0, 1.0, 1.0, f*fout};
3609  GLfloat colourCharRing [] = {1.0, 1.0, 0.8, f*fout};
3610  if((r>0.8)&&(g>0.8)&&(b>0.8))
3611  {
3612  colourChar[0] = 0.5;
3613  colourChar[1] = 0.5;
3614  colourChar[2] = 0.5;
3615  }
3616  if(mvpAtom[k]->IsInRing())
3617  glMaterialfv(GL_FRONT, GL_EMISSION, colourCharRing);
3618  else
3619  glMaterialfv(GL_FRONT, GL_EMISSION, colourChar);
3620  glRasterPos3f(x(k)*en, y(k), z(k));
3621  crystGLPrint(mvpAtom[k]->GetName());
3622  }
3623  }
3624  else
3625  {
3626  if(!large)
3627  {
3628  const GLfloat colourAtom [] = {r*fout, g*fout, b*fout, f*fout};
3629  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,colourAtom);
3630  glTranslatef(x(k)*en, y(k), z(k));
3631  gluSphere(pQuadric,
3632  mvpAtom[k]->GetScatteringPower().GetRadius()/3.,20,20);
3633  }
3634  else
3635  {
3636  const GLfloat colourAtom [] = {r*fout, g*fout, b*fout, f*fout};
3637  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE,colourAtom);
3638  glTranslatef(x(k)*en, y(k), z(k));
3639  gluSphere(pQuadric,.15,10,10);
3640  }
3641  }
3642  glPopMatrix();
3643  }
3644  if(displayNames==false)
3645  {
3646  if(large)
3647  {
3648  for(unsigned int k=0;k<mvpBond.size();k++)
3649  {
3650  if( (mvpBond[k]->GetAtom1().IsDummy())
3651  ||(mvpBond[k]->GetAtom2().IsDummy()) ) continue;
3652  if(hideHydrogens && ( (mvpBond[k]->GetAtom1().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)
3653  ||(mvpBond[k]->GetAtom2().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5))) continue;
3654  const unsigned long n1=rix[&(mvpBond[k]->GetAtom1())],
3655  n2=rix[&(mvpBond[k]->GetAtom2())];
3656  REAL fout=1.0;
3657  if((isinside(n1)==false) || (isinside(n2)==false))
3658  fout=exp(-(borderdist(n1)+borderdist(n2))/2)*(this->GetCrystal().GetDynPopCorr(this,n1)+this->GetCrystal().GetDynPopCorr(this,n2))/2;
3659  if(fout<0.01) continue;
3660 
3661  const float r1=mvpBond[k]->GetAtom1().GetScatteringPower().GetColourRGB()[0];
3662  const float g1=mvpBond[k]->GetAtom1().GetScatteringPower().GetColourRGB()[1];
3663  const float b1=mvpBond[k]->GetAtom1().GetScatteringPower().GetColourRGB()[2];
3664  const float f1=mvpBond[k]->GetAtom1().GetOccupancy()*this->GetOccupancy();
3665  const float r2=mvpBond[k]->GetAtom2().GetScatteringPower().GetColourRGB()[0];
3666  const float g2=mvpBond[k]->GetAtom2().GetScatteringPower().GetColourRGB()[1];
3667  const float b2=mvpBond[k]->GetAtom2().GetScatteringPower().GetColourRGB()[2];
3668  const float f2=mvpBond[k]->GetAtom2().GetOccupancy()*this->GetOccupancy();
3669  const GLfloat colourAtom1 [] = {r1, g1, b1, f1*fout};
3670  const GLfloat colourAtom2 [] = {r2, g2, b2, f2*fout};
3671  #if 0
3672  glPushMatrix();
3673  glBegin(GL_LINE_STRIP);
3674  glMaterialfv(GL_FRONT, GL_SPECULAR, colourAtom1);
3675  glMaterialfv(GL_FRONT, GL_EMISSION, colourAtom1);
3676  glMaterialfv(GL_FRONT, GL_SHININESS, colourAtom1);
3677  glVertex3f(x(n1)*en,y(n1),z(n1));
3678  glVertex3f((x(n1)+x(n2))/2*en,(y(n1)+y(n2))/2,(z(n1)+z(n2))/2);
3679  glMaterialfv(GL_FRONT, GL_SPECULAR, colourAtom2);
3680  glMaterialfv(GL_FRONT, GL_EMISSION, colourAtom2);
3681  glMaterialfv(GL_FRONT, GL_SHININESS, colourAtom2);
3682  glVertex3f(x(n2)*en,y(n2),z(n2));
3683  glEnd();
3684  glPopMatrix();
3685  #else
3686  const REAL height= sqrt(abs( (x(n2)-x(n1))*(x(n2)-x(n1))
3687  +(y(n2)-y(n1))*(y(n2)-y(n1))
3688  +(z(n2)-z(n1))*(z(n2)-z(n1))));
3689  glPushMatrix();
3690  glTranslatef(x(n1)*en, y(n1), z(n1));
3691  GLUquadricObj *quadobj = gluNewQuadric();
3692  glRotatef(180,(x(n2)-x(n1))*en,y(n2)-y(n1),z(n2)-z(n1)+height);// ?!?!?!
3693 
3694  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colourAtom1);
3695  gluCylinder(quadobj,.1,.1,height/2,10,1 );
3696  gluDeleteQuadric(quadobj);
3697 
3698  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colourAtom2);
3699  GLUquadricObj *quadobj2 = gluNewQuadric();
3700  glTranslatef(0, 0, height/2);
3701  gluCylinder(quadobj2,.1,.1,height/2,10,1 );
3702  gluDeleteQuadric(quadobj2);
3703  glPopMatrix();
3704  #endif
3705  }
3706  }
3707  else
3708  {
3709  for(unsigned int k=0;k<mvpBond.size();k++)
3710  {
3711  if( (mvpBond[k]->GetAtom1().IsDummy())
3712  ||(mvpBond[k]->GetAtom2().IsDummy()) ) continue;
3713  if(hideHydrogens && ( (mvpBond[k]->GetAtom1().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5)
3714  ||(mvpBond[k]->GetAtom2().GetScatteringPower().GetForwardScatteringFactor(RAD_XRAY)<1.5))) continue;
3715  const unsigned long n1=rix[&(mvpBond[k]->GetAtom1())],
3716  n2=rix[&(mvpBond[k]->GetAtom2())];
3717  REAL fout=1.0;
3718  if((isinside(n1)==false) || (isinside(n2)==false)) fout=exp(-(borderdist(n1)+borderdist(n2))/2);
3719  if(fout<0.01) continue;
3720  // Is the bond in a rigid group ?
3721  bool isRigidGroup=false;
3722  for(vector<RigidGroup *>::const_iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos)
3723  {
3724  if( ((*pos)->find(&(mvpBond[k]->GetAtom1()))!=(*pos)->end())
3725  &&((*pos)->find(&(mvpBond[k]->GetAtom2()))!=(*pos)->end()) )
3726  {
3727  isRigidGroup=true;
3728  break;
3729  }
3730  }
3731  const float f=(mvpBond[k]->GetAtom1().GetOccupancy()+mvpBond[k]->GetAtom2().GetOccupancy())/2*this->GetOccupancy();
3732  const GLfloat colour_bondnonfree[]= { 0.2*fout, .2*fout, .2*fout, f*fout };
3733  const GLfloat colour_bondrigid[]= { 0.5*fout, .3*fout, .3*fout, f*fout };
3734  const GLfloat colour_bondfree[]= { 0.8*fout, .8*fout, .8*fout, f*fout };
3735  if(isRigidGroup)
3736  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colour_bondrigid);
3737  else
3738  {
3739  if(mvpBond[k]->IsFreeTorsion())
3740  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colour_bondfree);
3741  else
3742  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,colour_bondnonfree);
3743  }
3744  // Actually make the bond start/end at the surface of the spheres (matters when transparent)
3745  REAL x1=x(n1),y1=y(n1),z1=z(n1),
3746  x2=x(n2),y2=y(n2),z2=z(n2);
3747  REAL dx=x2-x1,dy=y2-y1,dz=z2-z1;
3748  const REAL r=sqrt(abs(dx*dx+dy*dy+dz*dz))+1e-6;
3749  const REAL r1=mvpAtom[n1]->GetScatteringPower().GetRadius()/3.0;
3750  const REAL r2=mvpAtom[n2]->GetScatteringPower().GetRadius()/3.0;
3751  x1+=dx/r*r1*sqrt(abs(1-0.1/r1));
3752  y1+=dy/r*r1*sqrt(abs(1-0.1/r1));
3753  z1+=dz/r*r1*sqrt(abs(1-0.1/r1));
3754  x2-=dx/r*r2*sqrt(abs(1-0.1/r2));
3755  y2-=dy/r*r2*sqrt(abs(1-0.1/r2));
3756  z2-=dz/r*r2*sqrt(abs(1-0.1/r2));
3757 
3758  glPushMatrix();
3759  glTranslatef(x1*en, y1, z1);
3760  GLUquadricObj *quadobj = gluNewQuadric();
3761  //glColor4f(1.0f,1.0f,1.0f,1.0);
3762  const REAL height= sqrt(abs( (x2-x1)*(x2-x1)
3763  +(y2-y1)*(y2-y1)
3764  +(z2-z1)*(z2-z1)));
3765  glRotatef(180,(x2-x1)*en,y2-y1,z2-z1+height);// ?!?!?!
3766  gluCylinder(quadobj,.1,.1,height,10,1 );
3767  gluDeleteQuadric(quadobj);
3768  glPopMatrix();
3769  }
3770  }
3771  }
3772  }//if in limits
3773  x=xSave;
3774  y=ySave;
3775  z=zSave;
3776  }//for translation
3777  VFN_DEBUG_EXIT("Molecule::GLInitDisplayList():Symmetric#"<<i,3)
3778  }//for symmetrics
3779  VFN_DEBUG_EXIT("Molecule::GLInitDisplayList():Show all symmetrics",3)
3780  }//else
3781  gluDeleteQuadric(pQuadric);
3782  VFN_DEBUG_EXIT("Molecule::GLInitDisplayList()",3)
3783  #endif //GLCryst
3784 }
3785 
3786 void Molecule::AddAtom(const REAL x, const REAL y, const REAL z,
3787  const ScatteringPower *pPow, const string &name,
3788  const bool updateDisplay)
3789 {
3790  VFN_DEBUG_ENTRY("Molecule::AddAtom():"<<name,5)
3791  const bool molnameasformula= this->GetName()==this->GetFormula();
3792 
3793  string thename=name;
3794  if(thename==string(""))
3795  {// This should not be needed, the atom will reset the parameters name when its name is set
3796  char buf[100];
3797  if(pPow!=0) sprintf(buf,"%s_%s_%lu",this->GetName().c_str(),pPow->GetName().c_str(),mvpAtom.size()+1);
3798  else sprintf(buf,"%s_X_%lu",this->GetName().c_str(),mvpAtom.size()+1);
3799  thename=buf;
3800  }
3801  mvpAtom.push_back(new MolAtom(x,y,z,pPow,thename,*this));
3802  mClockAtomPosition.Click();
3803  mClockAtomScattPow.Click();
3804  ++mScattCompList;
3805  {
3806  RefinablePar tmp(thename+"_x",&(mvpAtom.back()->X()),0.,1.,
3807  gpRefParTypeScattConformX,
3808  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
3809  tmp.AssignClock(mClockAtomPosition);
3810  tmp.SetGlobalOptimStep(0.05);
3811  tmp.SetDerivStep(1e-4);
3812  this->AddPar(tmp);
3813  }
3814  {
3815  RefinablePar tmp(thename+"_y",&(mvpAtom.back()->Y()),0.,1.,
3816  gpRefParTypeScattConformY,
3817  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
3818  tmp.AssignClock(mClockAtomPosition);
3819  tmp.SetGlobalOptimStep(0.05);
3820  tmp.SetDerivStep(1e-4);
3821  this->AddPar(tmp);
3822  }
3823  {
3824  RefinablePar tmp(thename+"_z",&(mvpAtom.back()->Z()),0.,1.,
3825  gpRefParTypeScattConformZ,
3826  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
3827  tmp.AssignClock(mClockAtomPosition);
3828  tmp.SetGlobalOptimStep(0.05);
3829  tmp.SetDerivStep(1e-4);
3830  this->AddPar(tmp);
3831  }
3832 
3834 
3835  if(molnameasformula || (this->GetName().size()==0))
3836  this->SetName(this->GetFormula());
3837 
3838  if(updateDisplay) this->UpdateDisplay();
3839  VFN_DEBUG_EXIT("Molecule::AddAtom()",5)
3840 }
3841 
3842 vector<MolAtom*>::iterator Molecule::RemoveAtom(MolAtom &atom, const bool del)
3843 {
3844  VFN_DEBUG_ENTRY("Molecule::RemoveAtom():"<<atom.GetName(),6)
3845  vector<MolAtom*>::iterator pos=find(mvpAtom.begin(),mvpAtom.end(),&atom);
3846  if(pos==mvpAtom.end())
3847  {
3848  throw ObjCrystException("Molecule::RemoveAtom():"+atom.GetName()
3849  +" is not in this Molecule:"+this->GetName());
3850  }
3851  const bool molnameasformula= this->GetName()==this->GetFormula();
3852  // Delete parameters
3853  this->RemovePar(&(this->GetPar(&(atom.X()))));
3854  this->RemovePar(&(this->GetPar(&(atom.Y()))));
3855  this->RemovePar(&(this->GetPar(&(atom.Z()))));
3856  // Delete relevant bonds, bond angles, dihedral angles...
3857  for(vector<MolBond*>::iterator posb=mvpBond.begin();posb!=mvpBond.end();)
3858  {
3859  if( (&atom==&((*posb)->GetAtom1())) || (&atom==&((*posb)->GetAtom2())) )
3860  {
3861  posb=this->RemoveBond(**posb, del);
3862  }
3863  else ++posb;
3864  }
3865  for(vector<MolBondAngle*>::iterator posb=mvpBondAngle.begin();posb!=mvpBondAngle.end();)
3866  {
3867  if( (&atom==&((*posb)->GetAtom1())) || (&atom==&((*posb)->GetAtom2()))
3868  ||(&atom==&((*posb)->GetAtom3())))
3869  {
3870  posb=this->RemoveBondAngle(**posb, del);
3871  }
3872  else ++posb;
3873  }
3874  for(vector<MolDihedralAngle*>::iterator posb=mvpDihedralAngle.begin();
3875  posb!=mvpDihedralAngle.end();)
3876  {
3877  if( (&atom==&((*posb)->GetAtom1())) || (&atom==&((*posb)->GetAtom2()))
3878  ||(&atom==&((*posb)->GetAtom3())) || (&atom==&((*posb)->GetAtom4())))
3879  posb=this->RemoveDihedralAngle(**posb, del);
3880  else ++posb;
3881  }
3882  mClockAtomList.Click();
3884 
3885  if(mpCenterAtom==*pos) mpCenterAtom=0;
3886  if(del) delete *pos;
3887  pos=mvpAtom.erase(pos);
3888  --mScattCompList;
3889 
3890  if(molnameasformula || (this->GetName().size()==0))
3891  this->SetName(this->GetFormula());
3892 
3893  this->UpdateDisplay();
3894  VFN_DEBUG_EXIT("Molecule::RemoveAtom()",6)
3895  return pos;
3896 }
3897 
3898 void Molecule::AddNonFlipAtom(MolAtom &atom)
3899 {
3900  VFN_DEBUG_ENTRY("Molecule::AddNonFlipAtom()",5)
3901  mvNonFlipAtom.push_back(&atom);
3902  //mvNonFlipAtom.push_back(new MolAtom(atom.x,y,z,pPow,thename,*this));
3903 
3904  mClockFlipGroup.Reset();
3905  this->UpdateDisplay();
3906  VFN_DEBUG_EXIT("Molecule::AddNonFlipAtom()",5)
3907 }
3908 void Molecule::removeNonFlipAtom(MolAtom &atom)
3909 {
3910  for(vector<MolAtom*>::iterator pos=mvNonFlipAtom.begin();pos!=mvNonFlipAtom.end();) {
3911  if(atom.GetName().compare((*pos)->GetName())==0) {
3912  pos = mvNonFlipAtom.erase(pos);
3913  break;
3914  } else {
3915  pos++;
3916  }
3917  }
3918 }
3919 vector<MolAtom*> Molecule::getNonFlipAtomList()
3920 {
3921  return mvNonFlipAtom;
3922 }
3923 void Molecule::AddBond(MolAtom &atom1, MolAtom &atom2,
3924  const REAL length, const REAL sigma, const REAL delta,
3925  const REAL bondOrder,
3926  const bool updateDisplay)
3927 {
3928  VFN_DEBUG_ENTRY("Molecule::AddBond()",5)
3929  mvpBond.push_back(new MolBond(atom1,atom2,length,sigma,delta,*this,bondOrder));
3930  this->AddRestraint(mvpBond.back());
3931  mClockBondList.Click();
3932  if(updateDisplay) this->UpdateDisplay();
3933  VFN_DEBUG_EXIT("Molecule::AddBond()",5)
3934 }
3935 
3936 vector<MolBond*>::iterator Molecule::RemoveBond(const MolBond &bond, const bool del)
3937 {
3938  VFN_DEBUG_ENTRY("Molecule::RemoveBond():"<<bond.GetName(),6)
3939  vector<MolBond*>::iterator pos=find(mvpBond.begin(),mvpBond.end(),&bond);
3940  if(pos==mvpBond.end())
3941  {
3942  throw ObjCrystException("Molecule::RemoveBond():"+bond.GetAtom1().GetName()
3943  +"-"+bond.GetAtom2().GetName()
3944  +" is not in this Molecule:"+this->GetName());
3945  }
3946  this->RemoveRestraint(*pos);
3947  mClockBondList.Click();
3948  if(del) delete *pos;
3949  pos= mvpBond.erase(pos);
3950  this->UpdateDisplay();
3951  VFN_DEBUG_EXIT("Molecule::RemoveBond():",6)
3952  return pos;
3953 }
3954 
3955 vector<MolBond*>::const_iterator Molecule::FindBond(const MolAtom &at1,const MolAtom &at2)const
3956 {
3957  for(vector<MolBond*>::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
3958  {
3959  if( ((&((*pos)->GetAtom1())==&at1)&&(&((*pos)->GetAtom2())==&at2))
3960  ||((&((*pos)->GetAtom1())==&at2)&&(&((*pos)->GetAtom2())==&at1)))
3961  return pos;
3962  }
3963  return mvpBond.end();
3964 }
3965 vector<MolBond*>::iterator Molecule::FindBond(const MolAtom &at1,const MolAtom &at2)
3966 {
3967  for(vector<MolBond*>::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
3968  {
3969  if( ((&((*pos)->GetAtom1())==&at1)&&(&((*pos)->GetAtom2())==&at2))
3970  ||((&((*pos)->GetAtom1())==&at2)&&(&((*pos)->GetAtom2())==&at1)))
3971  return pos;
3972  }
3973  return mvpBond.end();
3974 }
3975 
3976 void Molecule::AddBondAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3,
3977  const REAL angle, const REAL sigma, const REAL delta,
3978  const bool updateDisplay)
3979 {
3980  VFN_DEBUG_ENTRY("Molecule::AddBondAngle()",5)
3981  mvpBondAngle.push_back(new MolBondAngle(atom1,atom2,atom3,angle,sigma,delta,*this));
3982  this->AddRestraint(mvpBondAngle.back());
3983  mClockBondAngleList.Click();
3984  if(updateDisplay) this->UpdateDisplay();
3985  VFN_DEBUG_EXIT("Molecule::AddBondAngle()",5)
3986 }
3987 
3988 vector<MolBondAngle*>::iterator Molecule::RemoveBondAngle(const MolBondAngle &angle, const bool del)
3989 {
3990  VFN_DEBUG_ENTRY("Molecule::RemoveBondAngle():"<<angle.GetName(),6)
3991  vector<MolBondAngle*>::iterator pos=find(mvpBondAngle.begin(),mvpBondAngle.end(),&angle);
3992  if(pos==mvpBondAngle.end())
3993  {
3994  throw ObjCrystException("Molecule::RemoveBondAngle():"+angle.GetAtom1().GetName()
3995  +"-"+angle.GetAtom2().GetName()+"-"+angle.GetAtom3().GetName()
3996  +" is not in this Molecule:"+this->GetName());
3997  }
3998  this->RemoveRestraint(*pos);
3999  mClockBondAngleList.Click();
4000  if(del) delete *pos;
4001  pos=mvpBondAngle.erase(pos);
4002  this->UpdateDisplay();
4003  VFN_DEBUG_EXIT("Molecule::RemoveBondAngle():",6)
4004  return pos;
4005 }
4006 
4007 vector<MolBondAngle*>::const_iterator Molecule::FindBondAngle(const MolAtom &at1,
4008  const MolAtom &at2,
4009  const MolAtom &at3)const
4010 {
4011  for(vector<MolBondAngle*>::const_iterator pos=mvpBondAngle.begin();
4012  pos!=mvpBondAngle.end();++pos)
4013  {
4014  if( (&((*pos)->GetAtom2())==&at2)
4015  &&( ((&((*pos)->GetAtom1())==&at1)&&(&((*pos)->GetAtom3())==&at3))
4016  ||((&((*pos)->GetAtom1())==&at3)&&(&((*pos)->GetAtom3())==&at1))))
4017  return pos;
4018  }
4019  return mvpBondAngle.end();
4020 }
4021 
4023  MolAtom &atom3, MolAtom &atom4,
4024  const REAL angle, const REAL sigma, const REAL delta,
4025  const bool updateDisplay)
4026 {
4027  VFN_DEBUG_ENTRY("Molecule::AddDihedralAngle()",5)
4028  mvpDihedralAngle.push_back(new MolDihedralAngle(atom1,atom2,atom3,atom4,
4029  angle,sigma,delta,*this));
4030  this->AddRestraint(mvpDihedralAngle.back());
4031  mClockDihedralAngleList.Click();
4032  if(updateDisplay) this->UpdateDisplay();
4033  VFN_DEBUG_EXIT("Molecule::AddDihedralAngle()",5)
4034 }
4035 
4036 vector<MolDihedralAngle*>::iterator Molecule::RemoveDihedralAngle(const MolDihedralAngle &angle, const bool del)
4037 {
4038  VFN_DEBUG_ENTRY("Molecule::RemoveDihedralAngle():"<<angle.GetName(),6)
4039  vector<MolDihedralAngle*>::iterator pos=find(mvpDihedralAngle.begin(),
4040  mvpDihedralAngle.end(),&angle);
4041  if(pos==mvpDihedralAngle.end())
4042  {
4043  throw ObjCrystException("Molecule::RemoveDihedralAngle():"+angle.GetAtom1().GetName()
4044  +"-"+angle.GetAtom2().GetName()+"-"+angle.GetAtom3().GetName()
4045  +"-"+angle.GetAtom4().GetName()
4046  +" is not in this Molecule:"+this->GetName());
4047  }
4048  this->RemoveRestraint(*pos);
4049  mClockDihedralAngleList.Click();
4050  if(del) delete *pos;
4051  pos=mvpDihedralAngle.erase(pos);
4052  this->UpdateDisplay();
4053  VFN_DEBUG_ENTRY("Molecule::RemoveDihedralAngle():",6)
4054  return pos;
4055 }
4056 vector<MolDihedralAngle*>::const_iterator Molecule::FindDihedralAngle(const MolAtom &at1,
4057  const MolAtom &at2,
4058  const MolAtom &at3,
4059  const MolAtom &at4)const
4060 {
4061  for(vector<MolDihedralAngle*>::const_iterator pos=mvpDihedralAngle.begin();
4062  pos!=mvpDihedralAngle.end();++pos)
4063  {
4064  if( ( ((&((*pos)->GetAtom1())==&at1)&&(&((*pos)->GetAtom2())==&at2))
4065  &&((&((*pos)->GetAtom3())==&at3)&&(&((*pos)->GetAtom4())==&at4)))
4066  ||( ((&((*pos)->GetAtom4())==&at1)&&(&((*pos)->GetAtom3())==&at2))
4067  &&((&((*pos)->GetAtom2())==&at3)&&(&((*pos)->GetAtom1())==&at4))))
4068  return pos;
4069  }
4070  return mvpDihedralAngle.end();
4071 }
4072 
4074  const bool updateDisplay)
4075 {
4076  mvRigidGroup.push_back(new RigidGroup(group));
4077  #ifdef RIGID_BODY_STRICT_EXPERIMENTAL
4078  char buf[50];
4079  const unsigned int i=mvRigidGroup.size();
4080  RigidGroup* p=this->GetRigidGroupList().back();
4081  p->mX=0;
4082  p->mY=0;
4083  p->mZ=0;
4084  p->mQuat.Q0()=1;
4085  p->mQuat.Q1()=0;
4086  p->mQuat.Q2()=0;
4087  p->mQuat.Q3()=0;
4088  {
4089  sprintf(buf,"RigidGroup%d_x",i);
4090  RefinablePar tmp(buf,&(p->mX),0.,1.,
4091  gpRefParTypeScattConformX,
4092  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
4093  tmp.AssignClock(mClockAtomPosition);
4094  tmp.SetGlobalOptimStep(0.05);
4095  tmp.SetDerivStep(1e-4);
4096  this->AddPar(tmp);
4097  }
4098  {
4099  sprintf(buf,"RigidGroup%d_y",i);
4100  RefinablePar tmp(buf,&(p->mY),0.,1.,
4101  gpRefParTypeScattConformY,
4102  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
4103  tmp.AssignClock(mClockAtomPosition);
4104  tmp.SetGlobalOptimStep(0.05);
4105  tmp.SetDerivStep(1e-4);
4106  this->AddPar(tmp);
4107  }
4108  {
4109  sprintf(buf,"RigidGroup%d_z",i);
4110  RefinablePar tmp(buf,&(p->mZ),0.,1.,
4111  gpRefParTypeScattConformZ,
4112  REFPAR_DERIV_STEP_ABSOLUTE,false,false,true,false,1.,1.);
4113  tmp.AssignClock(mClockAtomPosition);
4114  tmp.SetGlobalOptimStep(0.05);
4115  tmp.SetDerivStep(1e-4);
4116  this->AddPar(tmp);
4117  }
4118  {
4119  sprintf(buf,"RigidGroup%d_Q1",i);
4120  RefinablePar tmp(buf,&(p->mQuat.Q1()),-1,1.,
4121  gpRefParTypeScattConform,
4122  REFPAR_DERIV_STEP_ABSOLUTE,true,false,true,false,1.,1.);
4123  tmp.AssignClock(mClockAtomPosition);
4124  tmp.SetGlobalOptimStep(0.01);
4125  tmp.SetDerivStep(1e-4);
4126  this->AddPar(tmp);
4127  }
4128  {
4129  sprintf(buf,"RigidGroup%d_Q2",i);
4130  RefinablePar tmp(buf,&(p->mQuat.Q2()),-1,1.,
4131  gpRefParTypeScattConform,
4132  REFPAR_DERIV_STEP_ABSOLUTE,true,false,true,false,1.,1.);
4133  tmp.AssignClock(mClockAtomPosition);
4134  tmp.SetGlobalOptimStep(0.01);
4135  tmp.SetDerivStep(1e-4);
4136  this->AddPar(tmp);
4137  }
4138  {
4139  sprintf(buf,"RigidGroup%d_Q3",i);
4140  RefinablePar tmp(buf,&(p->mQuat.Q3()),-1,1.,
4141  gpRefParTypeScattConform,
4142  REFPAR_DERIV_STEP_ABSOLUTE,true,false,true,false,1.,1.);
4143  tmp.AssignClock(mClockAtomPosition);
4144  tmp.SetGlobalOptimStep(0.01);
4145  tmp.SetDerivStep(1e-4);
4146  this->AddPar(tmp);
4147  }
4148  #endif
4149  mClockRigidGroup.Click();
4150  if(updateDisplay) this->UpdateDisplay();
4151 }
4152 
4153 vector<RigidGroup*>::iterator Molecule::RemoveRigidGroup(const RigidGroup &g,const bool updateDisplay, const bool del)
4154 {
4155  vector<RigidGroup*>::iterator pos=find(mvRigidGroup.begin(),mvRigidGroup.end(),&g);
4156  if(pos==mvRigidGroup.end()) return pos;
4157  #ifdef RIGID_BODY_STRICT_EXPERIMENTAL
4158  // Remove the refinable parameters (even if del==False - used for python delayed deletion)
4159  // NOTE - this should only be done outside an optimization, since rigid group translationnal
4160  // and rotationnal parameters are resetted at the end of the optimization, and the atomic
4161  // parameters are directly the correct ones (thus deletion of the rigid group does not change
4162  // the final coordinates).
4163  this->RemovePar(&(this->GetPar(&((*pos)->mX))));
4164  this->RemovePar(&(this->GetPar(&((*pos)->mY))));
4165  this->RemovePar(&(this->GetPar(&((*pos)->mZ))));
4166  this->RemovePar(&(this->GetPar(&((*pos)->mQuat.Q1()))));
4167  this->RemovePar(&(this->GetPar(&((*pos)->mQuat.Q2()))));
4168  this->RemovePar(&(this->GetPar(&((*pos)->mQuat.Q3()))));
4169  #endif
4170  if(del) delete *pos;
4171  pos=mvRigidGroup.erase(pos);
4172  if(updateDisplay) this->UpdateDisplay();
4173  return pos;
4174 }
4175 
4176 MolAtom &Molecule::GetAtom(unsigned int i){return *mvpAtom[i];}
4177 
4178 const MolAtom &Molecule::GetAtom(unsigned int i)const{return *mvpAtom[i];}
4179 
4180 MolAtom &Molecule::GetAtom(const string &name){return **(this->FindAtom(name));}
4181 
4182 const MolAtom &Molecule::GetAtom(const string &name)const{return **(this->FindAtom(name));}
4183 
4184 void Molecule::OptimizeConformation(const long nbTrial,const REAL stopCost)
4185 {
4186  VFN_DEBUG_ENTRY("Molecule::OptimizeConformation()",5)
4187  MonteCarloObj globalOptObj(true);
4188  globalOptObj.AddRefinableObj(*this);
4189  globalOptObj.SetAlgorithmParallTempering(ANNEALING_EXPONENTIAL,10000.,1.,
4190  ANNEALING_EXPONENTIAL,10,.1);
4191 
4192  long nb=nbTrial;
4193  mIsSelfOptimizing=true;
4194  globalOptObj.Optimize(nb,false,stopCost);
4195  mIsSelfOptimizing=false;
4196  // Must rebuild Flip & Rotor group, in case they were tested with an absurd conformation
4197  mClockFlipGroup.Reset();
4198  mClockRotorGroup.Reset();
4199  VFN_DEBUG_EXIT("Molecule::OptimizeConformation()",5)
4200 }
4201 
4202 void Molecule::OptimizeConformationSteepestDescent(const REAL maxStep,const unsigned nbStep)
4203 {
4204  //cout<<"LLK="<<this->GetLogLikelihood()<<endl;
4205  for(unsigned i = 0; i < nbStep; ++i)
4206  {
4207  // Calc full gradient
4208  //Calculate & display gradient
4209  map<MolAtom*,XYZ> grad;
4210  for(vector<MolAtom*>::iterator pos=this->GetAtomList().begin();
4211  pos!=this->GetAtomList().end();++pos) grad[*pos]=XYZ(0,0,0);
4212 
4213  // :TODO: remove atoms that are in rigid groups ?
4214  for(vector<MolBond*>::iterator pos=this->GetBondList().begin();
4215  pos!=this->GetBondList().end();++pos) (*pos)->CalcGradient(grad);
4216 
4217  for(vector<MolBondAngle*>::iterator pos=this->GetBondAngleList().begin();
4218  pos!=this->GetBondAngleList().end();++pos) (*pos)->CalcGradient(grad);
4219 
4220  for(vector<MolDihedralAngle*>::iterator pos=this->GetDihedralAngleList().begin();
4221  pos!=this->GetDihedralAngleList().end();++pos) (*pos)->CalcGradient(grad);
4222 
4223  #if 0
4224  // Display gradient - for tests
4225  for(map<MolAtom*,XYZ>::const_iterator pos=grad.begin();pos!=grad.end();++pos)
4226  {
4227  char buf[100];
4228  sprintf(buf,"%10s Grad LLK= (%8.3f %8.3f %8.3f)",
4229  pos->first->GetName().c_str(),pos->second.x,pos->second.y,pos->second.z);
4230  cout<<buf<<endl;
4231  }
4232  #endif
4233  // Find maximum absolute value of gradient
4234  REAL f=0;
4235  for(map<MolAtom*,XYZ>::const_iterator pos=grad.begin();pos!=grad.end();++pos)
4236  {
4237  if(abs(pos->second.x)>f) f=abs(pos->second.x);
4238  if(abs(pos->second.y)>f) f=abs(pos->second.y);
4239  if(abs(pos->second.z)>f) f=abs(pos->second.z);
4240  }
4241  if(f>1e-6) f=maxStep/f;
4242  else break;//nothing to optimize ?
4243  // Average derivatives inside rigid groups
4244  //:TODO: still allow rotations of rigid groups ?
4245  //:TODO: Handle case when one atom belongs to several rigid groups...
4246  for(vector<RigidGroup *>::const_iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos)
4247  {
4248  if((*pos)->size()==0) continue; // Just in case...
4249  REAL dx=0,dy=0,dz=0;
4250  for(set<MolAtom *>::const_iterator at=(*pos)->begin();at!=(*pos)->end();++at)
4251  {
4252  dx+=(*at)->GetX();
4253  dy+=(*at)->GetY();
4254  dz+=(*at)->GetZ();
4255  }
4256  dx/=(*pos)->size();
4257  dy/=(*pos)->size();
4258  dz/=(*pos)->size();
4259  for(set<MolAtom *>::const_iterator at=(*pos)->begin();at!=(*pos)->end();++at)
4260  {
4261  grad[*at].x=dx;
4262  grad[*at].y=dy;
4263  grad[*at].z=dz;
4264  }
4265  }
4266  // Move according to max step to minimize LLK
4267  for(map<MolAtom*,XYZ>::const_iterator pos=grad.begin();pos!=grad.end();++pos)
4268  {
4269  pos->first->SetX(pos->first->GetX()-pos->second.x*f);
4270  pos->first->SetY(pos->first->GetY()-pos->second.y*f);
4271  pos->first->SetZ(pos->first->GetZ()-pos->second.z*f);
4272  }
4273  //this->RestraintStatus(cout);
4274  //cout<<"LLK="<<this->GetLogLikelihood()<<endl;
4275  }
4276 }
4277 
4278 void Molecule::MolecularDynamicsEvolve(map<MolAtom*,XYZ> &v0,const unsigned nbStep,const REAL dt,
4279  const vector<MolBond*> &vb,const vector<MolBondAngle*> &va,
4280  const vector<MolDihedralAngle*> &vd,
4281  map<RigidGroup*,std::pair<XYZ,XYZ> > &vr, REAL nrj0)
4282 {
4283  const vector<MolBond*> *pvb=&vb;
4284  const vector<MolBondAngle*> *pva=&va;
4285  const vector<MolDihedralAngle*> *pvd=&vd;
4286  map<RigidGroup*,std::pair<XYZ,XYZ> > *pvr=&vr;
4287  if((pvb->size()==0)&&(pva->size()==0)&&(pvd->size()==0))
4288  {
4289  pvb=&(this->GetBondList());
4290  pva=&(this->GetBondAngleList());
4291  pvd=&(this->GetDihedralAngleList());
4292  for(vector<RigidGroup *>::iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos)
4293  (*pvr)[*pos]=make_pair(XYZ(0,0,0),XYZ(0,0,0));
4294  }
4295  const REAL m=500;// mass
4296  const REAL im=1./m;
4297 
4298  // Try to keep total energy constant
4299  REAL e_v,e_k,v_r=1.0;
4300  for(unsigned i = 0; i < nbStep; ++i)
4301  {
4302  // Calc full gradient
4303  map<MolAtom*,XYZ> grad;
4304  for(map<MolAtom*,XYZ>::iterator pos=v0.begin();pos!=v0.end();++pos) grad[pos->first]=XYZ(0,0,0);
4305 
4306  // :TODO: handle rigid groups ?
4307  e_v=0;
4308  for(vector<MolBond*>::const_iterator pos=pvb->begin();pos!=pvb->end();++pos)
4309  {
4310  (*pos)->CalcGradient(grad);
4311  e_v+=(*pos)->GetLogLikelihood(false,false);
4312  }
4313 
4314  for(vector<MolBondAngle*>::const_iterator pos=pva->begin();pos!=pva->end();++pos)
4315  {
4316  (*pos)->CalcGradient(grad);
4317  e_v+=(*pos)->GetLogLikelihood(false,false);
4318  }
4319 
4320  for(vector<MolDihedralAngle*>::const_iterator pos=pvd->begin();pos!=pvd->end();++pos)
4321  {
4322  (*pos)->CalcGradient(grad);
4323  e_v+=(*pos)->GetLogLikelihood(false,false);
4324  }
4325 
4326  //kinetic energy
4327  e_k=0;
4328  for(map<MolAtom*,XYZ>::const_iterator pos=v0.begin();pos!=v0.end();++pos)
4329  e_k += 0.5*m*(pos->second.x*pos->second.x + pos->second.y*pos->second.y + pos->second.z*pos->second.z);
4330 
4331  if(nrj0==0) nrj0=e_k+e_v;
4332  else
4333  {
4334  // Apply a coefficient to the speed to keep the overall energy constant
4335  const REAL de=e_k+e_v-nrj0;
4336  if(de<e_k) v_r=sqrt((e_k-de)/e_k);
4337  else v_r=0.0;
4338  }
4339 
4340  #if 0
4341  char buf[100];
4342  sprintf(buf,"(i) LLK + Ek = %10.3f + %10.3f =%10.3f (nrj0=%10.3f)",e_v,e_k,e_v+e_k,nrj0);
4343  cout<<buf<<endl;
4344 
4345  // Display gradient & speed - for tests
4346  for(map<MolAtom*,XYZ>::iterator pos=v0.begin();pos!=v0.end();++pos)
4347  {
4348  sprintf(buf,"%10s xyz= (%8.3f %8.3f %8.3f) v= (%8.3f %8.3f %8.3f) m*a= (%8.3f %8.3f %8.3f)",
4349  pos->first->GetName().c_str(),
4350  pos->first->GetX(),pos->first->GetY(),pos->first->GetZ(),
4351  v0[*pos].x ,v0[*pos].y ,v0[*pos].z,
4352  -grad[*pos].x*im,-grad[*pos].y*im,-grad[*pos].z*im);
4353  //cout<<buf<<endl;
4354  }
4355  //cout<<endl<<endl;
4356  #endif
4357  // Move according to max step to minimize LLK
4358  for(map<MolAtom*,XYZ>::const_iterator pos=v0.begin();pos!=v0.end();++pos)
4359  {
4360  const XYZ *pa=&(grad[pos->first]);
4361  pos->first->SetX(pos->first->GetX()+pos->second.x*dt*v_r-0.5*im*dt*dt*pa->x);
4362  pos->first->SetY(pos->first->GetY()+pos->second.y*dt*v_r-0.5*im*dt*dt*pa->y);
4363  pos->first->SetZ(pos->first->GetZ()+pos->second.z*dt*v_r-0.5*im*dt*dt*pa->z);
4364  }
4365  // Compute new speed
4366  for(map<MolAtom*,XYZ>::iterator pos=v0.begin();pos!=v0.end();++pos)
4367  {
4368  const XYZ *pa=&(grad[pos->first]);
4369  pos->second.x = v_r*pos->second.x - pa->x*dt*im;
4370  pos->second.y = v_r*pos->second.y - pa->y*dt*im;
4371  pos->second.z = v_r*pos->second.z - pa->z*dt*im;
4372  }
4373  }
4374 }
4375 
4376 const vector<MolAtom*>& Molecule::GetAtomList()const{return mvpAtom;}
4377 const vector<MolBond*>& Molecule::GetBondList()const{return mvpBond;}
4378 const vector<MolBondAngle*>& Molecule::GetBondAngleList()const{return mvpBondAngle;}
4379 const vector<MolDihedralAngle*>& Molecule::GetDihedralAngleList()const{return mvpDihedralAngle;}
4380 
4381 vector<MolAtom*>& Molecule::GetAtomList(){return mvpAtom;}
4382 vector<MolBond*>& Molecule::GetBondList(){return mvpBond;}
4383 vector<MolBondAngle*>& Molecule::GetBondAngleList(){return mvpBondAngle;}
4384 vector<MolDihedralAngle*>& Molecule::GetDihedralAngleList(){return mvpDihedralAngle;}
4385 
4386 list<StretchModeBondLength>& Molecule::GetStretchModeBondLengthList(){return mvStretchModeBondLength;}
4387 list<StretchModeBondAngle>& Molecule::GetStretchModeBondAngleList(){return mvStretchModeBondAngle;}
4388 list<StretchModeTorsion>& Molecule::GetStretchModeTorsionList(){return mvStretchModeTorsion;}
4389 
4390 const list<StretchModeBondLength>& Molecule::GetStretchModeBondLengthList()const{return mvStretchModeBondLength;}
4391 const list<StretchModeBondAngle>& Molecule::GetStretchModeBondAngleList()const{return mvStretchModeBondAngle;}
4392 const list<StretchModeTorsion>& Molecule::GetStretchModeTorsionList()const{return mvStretchModeTorsion;}
4393 
4394 const std::vector<RigidGroup*>& Molecule::GetRigidGroupList()const{return mvRigidGroup;}
4395 std::vector<RigidGroup*>& Molecule::GetRigidGroupList() {return mvRigidGroup;}
4396 
4397 void Molecule::RotateAtomGroup(const MolAtom &at1,const MolAtom &at2,
4398  const set<MolAtom *> &atoms, const REAL angle,
4399  const bool keepCenter)
4400 {
4401  const REAL vx=at2.X()-at1.X();
4402  const REAL vy=at2.Y()-at1.Y();
4403  const REAL vz=at2.Z()-at1.Z();
4404  this->RotateAtomGroup(at1,vx,vy,vz,atoms,angle,keepCenter);
4405 }
4406 void Molecule::RotateAtomGroup(const MolAtom &at,const REAL vx,const REAL vy,const REAL vz,
4407  const set<MolAtom *> &atoms, const REAL angle,
4408  const bool keepCenter)
4409 {
4410  TAU_PROFILE("Molecule::RotateAtomGroup(MolAtom&,vx,vy,vz,...)","void (...)",TAU_DEFAULT);
4411  if(atoms.size()==0) return;
4412  const REAL x0=at.X();
4413  const REAL y0=at.Y();
4414  const REAL z0=at.Z();
4415  // :KLUDGE: ? Refuse to do anything if vector is not well defined
4416  if((fabs(vx)+fabs(vy)+fabs(vz))<1e-6) return;
4417  REAL dx=0.,dy=0.,dz=0.;
4418  bool keepc=keepCenter;
4419  if(keepc)
4420  if( (this->GetPar(mXYZ.data() ).IsFixed())
4421  ||(this->GetPar(mXYZ.data()+1).IsFixed())
4422  ||(this->GetPar(mXYZ.data()+2).IsFixed())) keepc=false;
4423  #if 0
4424  const REAL ca=cos(angle),sa=sin(angle);
4425  const REAL ca1=1-ca;
4426  const REAL vnorm=1/sqrt(vx*vx+vy*vy+vz*vz);
4427  const REAL ux=vx*vnorm,uy=vy*vnorm,uz=vz*vnorm;
4428  const REAL m00=ca+ux*ux*ca1;// See http://en.wikipedia.org/wiki/Rotation_matrix
4429  const REAL m01=ux*uy*ca1-uz*sa;
4430  const REAL m02=ux*uz*ca1+uy*sa;
4431  const REAL m10=uy*ux*ca1+uz*sa; // :TODO: Check formulas !
4432  const REAL m11=ca+uy*uy*ca1;
4433  const REAL m12=uy*uz*ca1-ux*sa;
4434  const REAL m20=uz*ux*ca1-uy*sa;
4435  const REAL m21=uz*uy*ca1+ux*sa;
4436  const REAL m22=ca+uz*uz*ca1;
4437  for(set<MolAtom *>::const_iterator pos=atoms.begin();pos!=atoms.end();++pos)
4438  {
4439  if(keepc)
4440  {
4441  dx -= (*pos)->X();
4442  dy -= (*pos)->Y();
4443  dz -= (*pos)->Z();
4444  }
4445  const REAL x=(*pos)->X() - x0;
4446  const REAL y=(*pos)->Y() - y0;
4447  const REAL z=(*pos)->Z() - z0;
4448 
4449  (*pos)->X() = m00*x+m01*y+m02*z+x0;
4450  (*pos)->Y() = m10*x+m11*y+m12*z+y0;
4451  (*pos)->Z() = m20*x+m21*y+m22*z+z0;
4452  if(keepc)
4453  {
4454  dx += (*pos)->X();
4455  dy += (*pos)->Y();
4456  dz += (*pos)->Z();
4457  }
4458  }
4459  #else
4460  const Quaternion quat=Quaternion::RotationQuaternion(angle,vx,vy,vz);
4461  for(set<MolAtom *>::const_iterator pos=atoms.begin();pos!=atoms.end();++pos)
4462  {
4463  if(keepc)
4464  {
4465  dx -= (*pos)->X();
4466  dy -= (*pos)->Y();
4467  dz -= (*pos)->Z();
4468  }
4469  (*pos)->X() -= x0;
4470  (*pos)->Y() -= y0;
4471  (*pos)->Z() -= z0;
4472  quat.RotateVector((*pos)->X(),(*pos)->Y(),(*pos)->Z());
4473  (*pos)->X() += x0;
4474  (*pos)->Y() += y0;
4475  (*pos)->Z() += z0;
4476  if(keepc)
4477  {
4478  dx += (*pos)->X();
4479  dy += (*pos)->Y();
4480  dz += (*pos)->Z();
4481  }
4482  }
4483  #endif
4484  // (dx,dy,dz) = vector of the translation of the center of the molecule due to the rotation
4485  if(keepc)
4486  {
4487  dx /= (REAL)(this->GetNbComponent());
4488  dy /= (REAL)(this->GetNbComponent());
4489  dz /= (REAL)(this->GetNbComponent());
4490  mQuat.RotateVector(dx,dy,dz);
4491  this->GetCrystal().OrthonormalToFractionalCoords(dx,dy,dz);
4492  mXYZ(0) += dx;
4493  mXYZ(1) += dy;
4494  mXYZ(2) += dz;
4495  }
4496  mClockAtomPosition.Click();
4498 }
4499 void Molecule::TranslateAtomGroup(const set<MolAtom *> &atoms,
4500  const REAL dx,const REAL dy,const REAL dz,
4501  const bool keepCenter)
4502 {
4503  for(set<MolAtom *>::const_iterator pos=atoms.begin();pos!=atoms.end();++pos)
4504  {
4505  (*pos)->X() += dx;
4506  (*pos)->Y() += dy;
4507  (*pos)->Z() += dz;
4508  }
4509  bool keepc=keepCenter;
4510  if(keepc)
4511  if( (this->GetPar(mXYZ.data() ).IsFixed())
4512  ||(this->GetPar(mXYZ.data()+1).IsFixed())
4513  ||(this->GetPar(mXYZ.data()+2).IsFixed())) keepc=false;
4514  if(keepc)
4515  {
4516  const REAL r= (REAL)(atoms.size())/(REAL)(this->GetNbComponent());
4517  REAL dxc=dx*r,dyc=dy*r,dzc=dz*r;
4518  this->GetCrystal().OrthonormalToFractionalCoords(dxc,dyc,dzc);
4519  mXYZ(0) += dxc;
4520  mXYZ(1) += dyc;
4521  mXYZ(2) += dzc;
4522  }
4523  mClockAtomPosition.Click();
4525 }
4526 void Molecule::RestraintExport(ostream &os)const
4527 {
4528  VFN_DEBUG_ENTRY("Molecule::RestraintExport()",5)
4529  os<<"BondName, IdealLength, Length, log(likelihood)"<<endl;
4530  for(vector<MolBond*>::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
4531  os <<(*pos)->GetName()
4532  <<", "<<(*pos)->GetLength0()
4533  <<", "<<(*pos)->GetLength()
4534  <<", "<<(*pos)->GetLogLikelihood()<<endl;
4535  os<<"BondAngle, IdealAngle, Angle, log(likelihood)"<<endl;
4536  for(vector<MolBondAngle*>::const_iterator pos=mvpBondAngle.begin();
4537  pos!=mvpBondAngle.end();++pos)
4538  os <<(*pos)->GetName()
4539  <<", "<<(*pos)->Angle0()*180/M_PI
4540  <<", "<<(*pos)->GetAngle()*180/M_PI
4541  <<", "<<(*pos)->GetLogLikelihood()<<endl;
4542  os<<"DihedralAngle, IdealAngle, Angle, log(likelihood)"<<endl;
4543  for(vector<MolDihedralAngle*>::const_iterator pos=mvpDihedralAngle.begin();
4544  pos!=mvpDihedralAngle.end();++pos)
4545  os <<(*pos)->GetName()
4546  <<", "<<(*pos)->Angle0()*180/M_PI
4547  <<", "<<(*pos)->GetAngle()*180/M_PI
4548  <<", "<<(*pos)->GetLogLikelihood()<<endl;
4549  VFN_DEBUG_EXIT("Molecule::RestraintExport()",5)
4550 }
4551 void Molecule::RestraintStatus(ostream &os)const
4552 {
4553  VFN_DEBUG_ENTRY("Molecule::RestraintStatus()",5)
4554  for(vector<MolBond*>::const_iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
4555  cout <<"Bond "<<(*pos)->GetName()
4556  <<", IdealLength="<<(*pos)->GetLength0()
4557  <<", Length="<<(*pos)->GetLength()
4558  <<", log(likelihood)="<<(*pos)->GetLogLikelihood()<<endl;
4559  for(vector<MolBondAngle*>::const_iterator pos=mvpBondAngle.begin();
4560  pos!=mvpBondAngle.end();++pos)
4561  cout <<"Bond Angle "<<(*pos)->GetName()
4562  <<", IdealAngle="<<(*pos)->Angle0()*180/M_PI
4563  <<", Angle="<<(*pos)->GetAngle()*180/M_PI
4564  <<", log(likelihood)="<<(*pos)->GetLogLikelihood()<<endl;
4565  for(vector<MolDihedralAngle*>::const_iterator pos=mvpDihedralAngle.begin();
4566  pos!=mvpDihedralAngle.end();++pos)
4567  cout <<"Dihedral Angle "<<(*pos)->GetName()
4568  <<", IdealAngle="<<(*pos)->Angle0()*180/M_PI
4569  <<", Angle="<<(*pos)->GetAngle()*180/M_PI
4570  <<", log(likelihood)="<<(*pos)->GetLogLikelihood()<<endl;
4571  VFN_DEBUG_EXIT("Molecule::RestraintStatus()",5)
4572 }
4573 
4574 const map<MolAtom *,set<MolAtom *> > &Molecule::GetConnectivityTable()
4575 {
4576  this->BuildConnectivityTable();
4577  return mConnectivityTable;
4578 }
4579 
4581 const RefinableObjClock& Molecule::GetBondListClock()const{return mClockBondList;}
4582 
4584 const RefinableObjClock& Molecule::GetAtomPositionClock()const{return mClockAtomPosition;}
4585 
4587 const RefinableObjClock& Molecule::GetRigidGroupClock()const{return mClockRigidGroup;}
4588 
4590 {
4591  this->BuildConnectivityTable();
4592  for(vector<MolBond*>::iterator bond=mvpBond.begin();bond!=mvpBond.end();++bond)
4593  {
4594  MolAtom* at2=&((*bond)->GetAtom1());
4595  MolAtom* at3=&((*bond)->GetAtom2());
4596  for(set<MolAtom *>::const_iterator c2=mConnectivityTable[at2].begin();
4597  c2!=mConnectivityTable[at2].end();++c2)
4598  {
4599  //MolAtom* at1=mvpAtom[*c2];
4600  if(*c2==at3) continue;
4601  if(GetBondAngle(**c2,*at2,*at3)<(10 *DEG2RAD)) continue;
4602  if(GetBondAngle(**c2,*at2,*at3)>(180*DEG2RAD)) continue;
4603  for(set<MolAtom*>::const_iterator c3=mConnectivityTable[at3].begin();
4604  c3!=mConnectivityTable[at3].end();++c3)
4605  {
4606  //MolAtom* at4=mvpAtom[*c3];
4607  if((*c3==at2)||(*c3==*c2)) continue;
4608  if(GetBondAngle(*at2,*at3,**c3)<(10 *DEG2RAD)) continue;
4609  if(GetBondAngle(*at2,*at3,**c3)>(180*DEG2RAD)) continue;
4610  if(this->FindDihedralAngle(**c2,*at2,*at3,**c3)==mvpDihedralAngle.end())
4611  {
4612  const REAL dihed=GetDihedralAngle(**c2,*at2,*at3,**c3);
4613  this->AddDihedralAngle(**c2,*at2,*at3,**c3,dihed,.01,.05,false);
4614  }
4615  }
4616  }
4617  }
4618  this->UpdateDisplay();
4619 }
4620 #if 0
4621 
4624 static const REAL svGaussianIntX[51]
4625  ={0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2,
4626  1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3,
4627  2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3. , 3.1, 3.2, 3.3, 3.4,
4628  3.5, 3.6, 3.7, 3.8, 3.9, 4. , 4.1, 4.2, 4.3, 4.4, 4.5,
4629  4.6, 4.7, 4.8, 4.9, 5. };
4633 static const REAL svGaussianIntY[51]
4634  ={0.00000000e+00, 1.00285768e-01, 2.02498389e-01, 3.08782899e-01,
4635  4.21537858e-01, 5.43577677e-01, 6.78339751e-01, 8.30161516e-01,
4636  1.00466359e+00, 1.20929269e+00, 1.45410564e+00, 1.75292008e+00,
4637  2.12502806e+00, 2.59778353e+00, 3.21056320e+00, 4.02091257e+00,
4638  5.11421527e+00, 6.61911896e+00, 8.73249677e+00, 1.17604260e+01,
4639  1.61864569e+01, 2.27870547e+01, 3.28297946e+01, 4.84189023e+01,
4640  7.31071567e+01, 1.12996748e+02, 1.78751757e+02, 2.89337246e+02,
4641  4.79080996e+02, 8.11232960e+02, 1.40443983e+03, 2.48531490e+03,
4642  4.49461494e+03, 8.30539633e+03, 1.56790580e+04, 3.02354014e+04,
4643  5.95525189e+04, 1.19793234e+05, 2.46080284e+05, 5.16182008e+05,
4644  1.10556243e+06, 2.41765307e+06, 5.39775929e+06, 1.23033271e+07,
4645  2.86288375e+07, 6.80050408e+07, 1.64899866e+08, 4.08157783e+08,
4646  1.03122228e+09, 2.65938808e+09, 7.00012860e+09};
4650 static const CubicSpline sInvGaussianInt(svGaussianIntY,svGaussianIntX,51);
4651 
4652 REAL FlatGaussianProba(const REAL x, const REAL sigma, const REAL delta)
4653 {
4654  if(abs(x)<delta) return 1.0;
4655  const REAL z=(abs(x)-delta)/sigma;
4656  return exp(-z*z);
4657 }
4658 
4659 REAL FlatGaussianIntegral(const REAL x1,const REAL x2, const REAL sigma, const REAL delta)
4660 {
4661  static const REAL SPI2=0.88622692545275794;//sqrt(pi)/2
4662  if((x1<=-delta)&&(x2<=-delta)) return SPI2*sigma*(erf((x2+delta)/sigma)-erf((x1+delta)/sigma));
4663  if((x1<=-delta)&&(x2<= delta)) return (x2+delta)-SPI2*sigma*erf((x1+delta)/sigma);
4664  if(x1<=-delta) return 2*delta+SPI2*sigma*(erf((x2-delta)/sigma)-erf((x1+delta)/sigma));
4665  if((x1<= delta)&&(x2<= delta)) return x2-x1;
4666  if(x1<= delta) return SPI2*sigma*erf((x2-delta)/sigma)+(delta-x1);
4667  return SPI2*sigma*(erf((x2-delta)/sigma)-erf((x1-delta)/sigma));
4668 }
4669 #endif
4670 REAL FlatLorentzianProba(const REAL x, const REAL sigma, const REAL delta)
4671 {
4672  if(abs(x)<delta) return 1.0;
4673  const REAL z=(abs(x)-delta)/sigma;
4674  return 1/(1+z*z);
4675 }
4676 
4677 REAL FlatLorentzianIntegral(const REAL x1,const REAL x2, const REAL sigma, const REAL delta)
4678 {
4679  if((x1<=-delta)&&(x2<=-delta)) return atan((x2+delta)/sigma)-atan((x1+delta)/sigma);
4680  if((x1<=-delta)&&(x2<= delta)) return (x2+delta)-atan((x1+delta)/sigma);
4681  if(x1<=-delta) return 2*delta+atan((x2-delta)/sigma)-atan((x1+delta)/sigma);
4682  if((x1<= delta)&&(x2<= delta)) return x2-x1;
4683  if(x1<= delta) return atan((x2-delta)/sigma)+(delta-x1);
4684  return atan((x2-delta)/sigma)-atan((x1-delta)/sigma);
4685 }
4686 
4687 ofstream f;
4688 
4695 REAL LorentzianBiasedRandomMove(const REAL x0,const REAL sigma,const REAL delta,const REAL amplitude)
4696 {
4697  //static const REAL SPI2=0.88622692545275794;//sqrt(pi)/2
4698  REAL r=(REAL)rand()/(REAL)RAND_MAX;
4699  if(sigma<1e-6)
4700  {
4701  REAL x=x0+amplitude*(2*r-1.0);
4702  if(x> delta)x= delta;
4703  if(x<-delta)x=-delta;
4704  return x;
4705  }
4706  // Compute xmin and xmax around x0 so that:
4707  // (x0-xmin)/(xmax-x0)=Integral[xmin->x0](P(x)dx)/Integral[x0->xmax](P(x)dx)
4708  REAL xmin;
4709  REAL xmax;
4710  #if 1
4711  {
4712  REAL Pmax,Pmin;
4713  xmin=x0-amplitude;
4714  xmax=x0+amplitude;
4715  Pmin=FlatLorentzianProba((x0+xmin)/2,sigma,delta);
4716  Pmax=FlatLorentzianProba((x0+xmax)/2,sigma,delta);
4717  //Pmin=FlatLorentzianIntegral(xmin,x0,sigma,delta);
4718  //Pmax=FlatLorentzianIntegral(x0,xmax,sigma,delta);
4719  if(Pmin>Pmax)
4720  {
4721  for(int i=0;i<5;i++)
4722  {
4723  const REAL r=Pmax/Pmin;
4724  xmax=x0+r*amplitude;
4725  Pmax=FlatLorentzianProba((x0+xmax)/2,sigma,delta);
4726  //Pmax=FlatLorentzianIntegral(x0,xmax,sigma,delta);
4727  }
4728  }
4729  else
4730  {
4731  for(int i=0;i<5;i++)
4732  {
4733  const REAL r=Pmin/Pmax;
4734  xmin=x0-r*amplitude;
4735  Pmin=FlatLorentzianProba((x0+xmin)/2,sigma,delta);
4736  //Pmin=FlatLorentzianIntegral(xmin,x0,sigma,delta);
4737  }
4738  }
4739  }
4740  #else
4741  if(abs(x0)<=delta)
4742  {
4743  xmin=x0-amplitude;
4744  xmax=x0+amplitude;
4745  }
4746  else
4747  {
4748  REAL d=(abs(x0)-delta)/sigma;
4749  d=2*d*exp(-d*d);
4750  d=(1-amplitude*d/2)/(1+amplitude*d/2);//d<1
4751  if(x0>0)
4752  {
4753  xmin=x0-amplitude*2/(1+d);
4754  xmax=x0+amplitude*2*d/(1+d);
4755  }
4756  else
4757  {
4758  xmax=x0+amplitude*2/(1+d);
4759  xmin=x0-amplitude*2*d/(1+d);
4760  }
4761  }
4762  #endif
4763  //xmin=x0-amplitude;
4764  //xmax=x0+amplitude;
4765  //Now get the biased move...
4766  if(xmax<=-delta)
4767  {
4768  REAL ymin=(abs(xmin)-delta)/sigma;
4769  ymin=atan(ymin);
4770  REAL ymax=(abs(xmax)-delta)/sigma;
4771  ymax=atan(ymax);
4772  const REAL y=ymin+(ymax-ymin)*r;
4773  return -tan(y)*sigma-delta;
4774  }
4775  if(xmin<=-delta)
4776  {
4777  if(xmax<=delta)
4778  {
4779  //probability of being in [xmin;-delta] rather than [-delta;xmax]
4780  REAL p0=atan((abs(xmin)-delta)/sigma)*sigma;
4781  REAL p1=xmax+delta;
4782  const REAL n=p0+p1;
4783  if(r<p0/n)
4784  {
4785  REAL ymin=(abs(xmin)-delta)/sigma;
4786  ymin=atan(ymin);
4787  const REAL y=ymin*(REAL)rand()/(REAL)RAND_MAX;
4788  return -delta-tan(y)*sigma;
4789  }
4790  else
4791  {
4792  return -delta+(REAL)rand()/(REAL)RAND_MAX*(xmax+delta);
4793  }
4794  }
4795  else //xmax>delta && xmin <= -delta
4796  {
4797  REAL p0=atan((abs(xmin)-delta)/sigma)*sigma;//probability of being in [xmin;-delta]
4798  REAL p1=2*delta;//probability of being in [-delta;delta]
4799  REAL p2=atan((xmax-delta)/sigma)*sigma;//probability of being in [delta;xmax]
4800  const REAL n=p0+p1+p2;
4801  if(r<(p0/n))
4802  {
4803  REAL ymin=(abs(xmin)-delta)/sigma;
4804  ymin=atan(ymin);//exp(ymin*ymin);
4805  const REAL y=ymin*(REAL)rand()/(REAL)RAND_MAX;
4806  const REAL x=-delta-tan(y)*sigma;
4807  return x;
4808  }
4809  if(r<(p0+p1)/n)
4810  {
4811  const REAL x=-delta+(REAL)rand()/(REAL)RAND_MAX*2*delta;
4812  return x;
4813  }
4814 
4815  REAL ymax=(xmax-delta)/sigma;
4816  ymax=atan(ymax);
4817  const REAL y=ymax*(REAL)rand()/(REAL)RAND_MAX;
4818  const REAL x=delta+tan(y)*sigma;
4819  return x;
4820  }
4821  }
4822  if(xmin<delta)
4823  {
4824  if(xmax<delta)
4825  {
4826  return xmin+r*(xmax-xmin);
4827  }
4828 
4829  const REAL p0=delta-xmin;//relative probability of being in [xmin;delta]
4830  const REAL p1=atan((xmax-delta)/sigma)*sigma;// proba in[delta;xmax]
4831  if(r<(p0/(p0+p1)))
4832  {
4833  return xmin+(REAL)rand()/(REAL)RAND_MAX*(delta-xmin);
4834  }
4835 
4836  REAL ymax=(xmax-delta)/sigma;
4837  ymax=atan(ymax);
4838  const REAL y=ymax*(REAL)rand()/(REAL)RAND_MAX;
4839  return delta+tan(y)*sigma;
4840  }
4841  //xmin>delta
4842  REAL ymin=(xmin-delta)/sigma;
4843  ymin=atan(ymin);
4844  REAL ymax=(xmax-delta)/sigma;
4845  ymax=atan(ymax);
4846  const REAL y=ymin+(ymax-ymin)*r;
4847  return tan(y)*sigma+delta;
4848 }
4849 
4850 void TestLorentzianBiasedRandomMove()
4851 {
4852  srand(time(NULL));
4853  REAL x=0,sigma=0.1,delta=0.5,amplitude=0.05;
4854  f.open("test.dat");
4855  for(long i=0;i<400000;i++)
4856  {
4857  f<<x<<endl;
4858  x=LorentzianBiasedRandomMove(x,sigma,delta,amplitude);
4859  }
4860  f.close();
4861  exit(0);
4862  //#Histogram in Python
4863  //from scipy import *
4864  //
4865  //def histogram(y,n=100):
4866  // ymin=min(y)
4867  // ymax=max(y)
4868  // step=(ymax-ymin)/n
4869  // hx=arange(ymin,ymax+step,step)
4870  // hy=arange(ymin,ymax+step,step)
4871  // for i in xrange(n-1):
4872  // hy[i]=sum((y>hx[i])*(y<(hx[i]+step)))
4873  // return hx,hy
4874  //
4875  //
4876  //f=open("test.dat",'r')
4877  //ll=f.readlines()
4878  //f.close()
4879  //y=zeros(len(ll),Float)
4880  //for i in xrange(len(ll)):
4881  // y[i]=float(ll[i])
4882  //
4883  //hx,hy=histogram(y)
4884  //gplt.plot(hx,hy)
4885 }
4886 
4887 REAL Molecule::BondLengthRandomChange(const StretchModeBondLength& mode, const REAL amplitude,
4888  const bool respectRestraint)
4889 {
4890  REAL dx=mode.mpAtom1->GetX()-mode.mpAtom0->GetX();
4891  REAL dy=mode.mpAtom1->GetY()-mode.mpAtom0->GetY();
4892  REAL dz=mode.mpAtom1->GetZ()-mode.mpAtom0->GetZ();
4893  const REAL l=sqrt(dx*dx+dy*dy+dz*dz+1e-7);
4894  REAL change=0.0;
4895  if(l<1e-6) return change;// :KLUDGE:
4896  if(respectRestraint && mode.mpBond!=0)
4897  {
4898  const REAL d0=l-mode.mpBond->GetLength0();
4899  const REAL sigma=mode.mpBond->GetLengthSigma();
4900  const REAL delta=mode.mpBond->GetLengthDelta();
4901  const REAL max=delta+sigma*5.0;
4902  if(sigma<1e-6)
4903  {
4904  REAL d1=d0+(REAL)(2*rand()-RAND_MAX)/(REAL)RAND_MAX*amplitude*0.1;
4905  if(d1> delta)d1= delta;
4906  if(d1<-delta)d1=-delta;
4907  change=d1-d0;
4908  }
4909  else change=LorentzianBiasedRandomMove(d0,sigma,delta,amplitude*0.1)-d0;
4910  if((d0+change)>max) change=max-d0;
4911  else if((d0+change)<(-max)) change=-max-d0;
4912  #if 0
4913  if(rand()%10000==0)
4914  {
4915  cout<<"BOND LENGTH change("<<change<<"):"
4916  <<mode.mpAtom0->GetName()<<"-"
4917  <<mode.mpAtom1->GetName()
4918  <<"(Restraint="<<l-d0<<"s"<<sigma<<"d"<<delta<<"):"
4919  <<l<<"->"<<l+change<<endl;
4920  }
4921  #endif
4922  }
4923  else change=(2.*(REAL)rand()-(REAL)RAND_MAX)/(REAL)RAND_MAX*amplitude*0.1;
4924  dx*=change/l;
4925  dy*=change/l;
4926  dz*=change/l;
4927  this->TranslateAtomGroup(mode.mvTranslatedAtomList,dx,dy,dz,true);
4928  return change;
4929 }
4930 
4931 REAL Molecule::BondAngleRandomChange(const StretchModeBondAngle& mode, const REAL amplitude,
4932  const bool respectRestraint)
4933 {
4934  REAL dx10=mode.mpAtom0->GetX()-mode.mpAtom1->GetX();
4935  REAL dy10=mode.mpAtom0->GetY()-mode.mpAtom1->GetY();
4936  REAL dz10=mode.mpAtom0->GetZ()-mode.mpAtom1->GetZ();
4937  REAL dx12=mode.mpAtom2->GetX()-mode.mpAtom1->GetX();
4938  REAL dy12=mode.mpAtom2->GetY()-mode.mpAtom1->GetY();
4939  REAL dz12=mode.mpAtom2->GetZ()-mode.mpAtom1->GetZ();
4940 
4941  const REAL vx=dy10*dz12-dz10*dy12;
4942  const REAL vy=dz10*dx12-dx10*dz12;
4943  const REAL vz=dx10*dy12-dy10*dx12;
4944 
4945  REAL change=0.0;
4946  if((abs(vx)+abs(vy)+abs(vz))<1e-6) return change;// :KLUDGE:
4947  REAL angle0;
4948  if(respectRestraint && mode.mpBondAngle!=0)
4949  {
4950  const REAL norm= sqrt( (dx10*dx10+dy10*dy10+dz10*dz10)*(dx12*dx12+dy12*dy12+dz12*dz12)+1e-6);
4951  angle0=(dx10*dx12+dy10*dy12+dz10*dz12)/norm;
4952  if(angle0>=1) angle0=0;
4953  else
4954  {
4955  if(angle0<=-1) angle0=M_PI;
4956  else angle0= acos(angle0);
4957  }
4958 
4959  const REAL a0=angle0-mode.mpBondAngle->GetAngle0();
4960  const REAL sigma=mode.mpBondAngle->GetAngleSigma();
4961  const REAL delta=mode.mpBondAngle->GetAngleDelta();
4962  if(sigma<1e-6)
4963  {
4964  REAL a1=a0+(REAL)(2*rand()-RAND_MAX)/(REAL)RAND_MAX*amplitude*mode.mBaseAmplitude;
4965  if(a1> delta)a1= delta;
4966  if(a1<-delta)a1=-delta;
4967  change=a1-a0;
4968  }
4969  else change=LorentzianBiasedRandomMove(a0,sigma,delta,amplitude*mode.mBaseAmplitude)-a0;
4970  if((a0+change)>(delta+sigma*5.0)) change= delta+sigma*5.0-a0;
4971  else if((a0+change)<(-delta-sigma*5.0)) change=-delta-sigma*5.0-a0;
4972  #if 0
4973  if(rand()%1==0)
4974  {
4975  cout<<"ANGLE change("<<change*RAD2DEG<<"):"
4976  <<mode.mpAtom0->GetName()<<"-"
4977  <<mode.mpAtom1->GetName()<<"-"
4978  <<mode.mpAtom2->GetName()
4979  <<"(Restraint="<<(angle0-a0)*RAD2DEG<<"s"<<sigma*RAD2DEG<<"d"<<delta*RAD2DEG<<"):"
4980  <<angle0*RAD2DEG<<"->"<<(angle0+change)*RAD2DEG<<endl;
4981  }
4982  #endif
4983  }
4984  else change=(2.*(REAL)rand()-(REAL)RAND_MAX)/(REAL)RAND_MAX*mode.mBaseAmplitude*amplitude;
4985  this->RotateAtomGroup(*(mode.mpAtom1),vx,vy,vz,mode.mvRotatedAtomList,change,true);
4986  return change;
4987 }
4988 REAL Molecule::DihedralAngleRandomChange(const StretchModeTorsion& mode, const REAL amplitude,
4989  const bool respectRestraint)
4990 {
4991  const REAL dx=mode.mpAtom2->GetX()-mode.mpAtom1->GetX();
4992  const REAL dy=mode.mpAtom2->GetY()-mode.mpAtom1->GetY();
4993  const REAL dz=mode.mpAtom2->GetZ()-mode.mpAtom1->GetZ();
4994  REAL change=0.0;
4995  if((abs(dx)+abs(dy)+abs(dz))<1e-6) return change;// :KLUDGE:
4996  if(respectRestraint && mode.mpDihedralAngle!=0)
4997  {
4998  const REAL angle0=mode.mpDihedralAngle->GetAngle();
4999  const REAL a0=angle0-mode.mpDihedralAngle->GetAngle0();
5000  const REAL sigma=mode.mpDihedralAngle->GetAngleSigma();
5001  const REAL delta=mode.mpDihedralAngle->GetAngleDelta();
5002  if(sigma<1e-6)
5003  {
5004  REAL a1=a0+(REAL)(2*rand()-RAND_MAX)/(REAL)RAND_MAX*amplitude*mode.mBaseAmplitude;
5005  if(a1> delta)a1= delta;
5006  if(a1<-delta)a1=-delta;
5007  change=a1-a0;
5008  }
5009  else change=LorentzianBiasedRandomMove(a0,sigma,delta,amplitude*mode.mBaseAmplitude)-a0;
5010  if((a0+change)>(delta+sigma*5.0)) change= delta+sigma*5.0-a0;
5011  else if((a0+change)<(-delta-sigma*5.0)) change=-delta-sigma*5.0-a0;
5012  #if 0
5013  if(rand()%1==0)
5014  {
5015  cout<<"TORSION change ("
5016  <<mode.mpAtom1->GetName()<<"-"<<mode.mpAtom2->GetName()<<"):"<<endl
5017  <<" initial angle="<<angle0*RAD2DEG
5018  <<" (Restraint("<<mode.mpDihedralAngle->GetName()<<")="
5019  <<(angle0-a0)*RAD2DEG<<"s"<<sigma*RAD2DEG<<"d"<<delta*RAD2DEG<<"):"
5020  <<endl<<" New angle:"<<(angle0+change)*RAD2DEG<<", change="<<change*RAD2DEG<<endl;
5021  }
5022  #endif
5023  }
5024  else change=(REAL)(2.*rand()-RAND_MAX)/(REAL)RAND_MAX*mode.mBaseAmplitude*amplitude;
5025  this->RotateAtomGroup(*(mode.mpAtom1),*(mode.mpAtom2),mode.mvRotatedAtomList,change,true);
5026  return change;
5027 }
5028 
5030 {
5031  return mpCenterAtom;
5032 }
5033 
5035 {
5036  mpCenterAtom=&at;
5037  mClockAtomPosition.Click();
5038  this->UpdateDisplay();
5039 }
5040 
5041 void BuildZMatrixRecursive(long &z,const long curr,
5042  const vector<MolAtom*> &vpAtom,
5043  const map<MolAtom *, set<MolAtom *> > &connT,
5044  vector<MolZAtom> &zmatrix,
5045  const map<const MolAtom*,long> &vIndex,
5046  vector<long> &vZIndex,
5047  vector<long> &vrZIndex)
5048 {
5049  zmatrix[z].mpPow=&(vpAtom[curr]->GetScatteringPower());
5050  vZIndex[curr]=z;
5051  vrZIndex[z]=curr;
5052  // Get the list of connected atoms and sort them
5053  map<MolAtom *, set<MolAtom *> >::const_iterator pConn=connT.find(vpAtom[curr]);
5054  const long nc=pConn->second.size();
5055  vector<long> conn(nc);
5056  vector<long> zconn(nc);
5057  vector<long>::iterator pos=conn.begin();
5058  vector<long>::iterator zpos=zconn.begin();
5059  for(set<MolAtom *>::const_iterator pos1=pConn->second.begin();pos1!=pConn->second.end();++pos1)
5060  {
5061  *pos = vIndex.find(*pos1)->second;
5062  *zpos = vZIndex[*pos];
5063  cout<<(*pos1)->GetName()<<"("<<*pos<<","<<*zpos<<")"<<endl;
5064  zpos++;pos++;
5065  }
5066  sort(conn.begin(),conn.end());
5067  sort(zconn.begin(),zconn.end());
5068  if(z>0)
5069  {
5070  // Use the most recent atom in the z-matrix
5071  const long b=zconn[nc-1];
5072  zmatrix[z].mBondAtom=b;
5073  zmatrix[z].mBondLength=GetBondLength(*vpAtom[vrZIndex[b]],*vpAtom[curr]);
5074  if(z>1)
5075  {
5076  const long a=zmatrix[b].mBondAtom;
5077  zmatrix[z].mBondAngleAtom=a;
5078  zmatrix[z].mBondAngle=GetBondAngle(*vpAtom[vrZIndex[a]],*vpAtom[vrZIndex[b]],*vpAtom[curr]);
5079  if(z>2)
5080  {
5081  const long d=zmatrix[b].mBondAngleAtom;
5082  zmatrix[z].mDihedralAtom=d;
5083  zmatrix[z].mDihedralAngle=fmod(GetDihedralAngle(*vpAtom[vrZIndex[d]],*vpAtom[vrZIndex[a]],
5084  *vpAtom[vrZIndex[b]],*vpAtom[curr])+2*M_PI,
5085  2*M_PI);
5086  }
5087  else
5088  {
5089  zmatrix[z].mDihedralAtom=0;
5090  zmatrix[z].mDihedralAngle=0;
5091  }
5092  }
5093  else
5094  {
5095  zmatrix[z].mBondAngleAtom=0;
5096  zmatrix[z].mBondAngle=0;
5097  }
5098  }
5099  else
5100  {
5101  zmatrix[z].mBondAtom=0;
5102  zmatrix[z].mBondLength=0;
5103  }
5104  z++;
5105  // Continue filling up the zmatrix, beginning from thz first atoms not already in the zmatrix
5106  for(pos=conn.begin();pos!=conn.end();++pos)
5107  {
5108  if(*pos!=-1)
5109  {
5110  if(vZIndex[*pos]==-1)
5111  BuildZMatrixRecursive(z,*pos,vpAtom,connT,zmatrix,vIndex,vZIndex,vrZIndex);
5112  }
5113  }
5114 }
5115 
5116 const vector<MolZAtom>& Molecule::AsZMatrix(const bool keeporder)const
5117 {
5118  this->BuildConnectivityTable();
5119  const long n=mvpAtom.size();
5120  // index of the atoms in the list
5121  map<const MolAtom*,long> vIndex;
5122  {
5123  long i=0;
5124  for(vector<MolAtom*>::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
5125  vIndex[*pos]=i++;
5126  }
5127  mAsZMatrix.resize(n);
5128  if(keeporder)
5129  {
5130  for(long i=0;i<n;++i)
5131  {
5132  mAsZMatrix[i].mpPow=&(mvpAtom[i]->GetScatteringPower());
5133  if(i>0)
5134  {
5135  const set<MolAtom *> *pConn=&(mConnectivityTable.find(mvpAtom[i])->second);
5136  // Find a connected atom already in the mAsZMatrix, prefereably the most recent
5137  long b=-1;
5138  for(set<MolAtom *>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
5139  if((vIndex[*pos]<i)&&(vIndex[*pos]>b)) b=vIndex[*pos];
5140  // Did not find a connected atom already in the z-matrix ? Take the last one
5141  if(b==-1) b=i-1;
5142  mAsZMatrix[i].mBondAtom=b;
5143  mAsZMatrix[i].mBondLength=GetBondLength(*mvpAtom[b],*mvpAtom[i]);
5144  if(i>1)
5145  {
5146  const long a= (b==0)?1 : mAsZMatrix[b].mBondAtom;
5147  mAsZMatrix[i].mBondAngleAtom=a;
5148  mAsZMatrix[i].mBondAngle=GetBondAngle(*mvpAtom[a],*mvpAtom[b],*mvpAtom[i]);
5149  if(i>2)
5150  {
5151  long d= mAsZMatrix[a].mBondAtom;
5152  if(d==b)
5153  {// Dihedral atom is already bond atom, find another connected to angle atom
5154  d=-1;
5155  const set<MolAtom *> *pConn=&(mConnectivityTable.find(mvpAtom[a])->second);
5156  // Find a connected atom already in the mAsZMatrix, prefereably the most recent
5157  for(set<MolAtom *>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
5158  if((vIndex[*pos]<i) && (vIndex[*pos]!=b) && (vIndex[*pos]>d)) d=vIndex[*pos];
5159  }
5160  if(d==-1)
5161  {// Can't find an angle connected to angle atom, so find another with bond atom
5162  const set<MolAtom *> *pConn=&(mConnectivityTable.find(mvpAtom[b])->second);
5163  // Find a connected atom already in the mAsZMatrix, prefereably the most recent
5164  for(set<MolAtom *>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
5165  if((vIndex[*pos]<i) && (vIndex[*pos]!=a) && (vIndex[*pos]>d)) d=vIndex[*pos];
5166  }
5167  if(d==-1)
5168  {// Maybe another connected to this atom ??
5169  const set<MolAtom *> *pConn=&(mConnectivityTable.find(mvpAtom[i])->second);
5170  // Find a connected atom already in the mAsZMatrix, prefereably the most recent
5171  for(set<MolAtom *>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
5172  if( (vIndex[*pos]<i) && (vIndex[*pos]!=a)
5173  &&(vIndex[*pos]!=b) && (vIndex[*pos]>d)) d=vIndex[*pos];
5174  }
5175  if(d==-1)
5176  {// OK, pick *any* (can this happen ? Really ?)
5177  for(long j=0;j<i;++j)
5178  if((j!=a) &&(j!=b) && (j>d)) d=j;
5179  }
5180  mAsZMatrix[i].mDihedralAtom=d;
5181  mAsZMatrix[i].mDihedralAngle=fmod(GetDihedralAngle(*mvpAtom[d],
5182  *mvpAtom[a],
5183  *mvpAtom[b],
5184  *mvpAtom[i])+2*M_PI,
5185  2*M_PI);
5186  }
5187  }
5188  }
5189  }
5190  }
5191  else
5192  {
5193  // vZIndex[i] tells where mvpAtom[i] is in the z-matrix
5194  vector<long> vZIndex(n);
5195  // vrZIndex[i] tells where which index in vpAtom is ZAtom #i
5196  vector<long> vrZIndex(n);
5197  for(long i=0;i<n;++i)
5198  {
5199  vZIndex [i]=-1;
5200  vrZIndex[i]=-1;
5201  }
5202  long z=0;
5203  BuildZMatrixRecursive(z,0,mvpAtom,mConnectivityTable,mAsZMatrix,vIndex,vZIndex,vrZIndex);
5204  }
5205  return mAsZMatrix;
5206 }
5207 
5209 {
5210 }
5211 
5221 void BuildRingRecursive(MolAtom * currentAtom,
5222  MolAtom * previousAtom,
5223  const map<MolAtom *, set<MolAtom *> > &connect,
5224  list<MolAtom *> &atomlist,
5225  map<set<MolAtom *>,list<MolAtom *> > &ringlist)
5226 {
5227  list<MolAtom *>::const_iterator f=find(atomlist.begin(),atomlist.end(),currentAtom);
5228  if(f!=atomlist.end())
5229  {// This atom was already in the list ! We have found a ring !
5230  #ifdef __DEBUG__
5231  cout<<currentAtom->GetName()<<" was already in the list : ring found !"<<endl;
5232  for(list<MolAtom *>::const_iterator atom=atomlist.begin();atom!=atomlist.end();++atom)
5233  cout<<(*atom)->GetName()<<" ";
5234  cout<<endl;
5235  #endif
5236  set<MolAtom *> ring1;
5237  list<MolAtom *> ring2;
5238  for(list<MolAtom *>::const_iterator pos=f;pos!=atomlist.end();++pos)
5239  {
5240  ring1.insert(*pos);
5241  ring2.push_back(*pos);
5242  }
5243  ringlist.insert(make_pair(ring1,ring2));
5244  }
5245  else
5246  {
5247  atomlist.push_back(currentAtom);
5248  map<MolAtom *,set<MolAtom *> >::const_iterator c=connect.find(currentAtom);
5249  set<MolAtom *>::const_iterator pos;
5250  for(pos=c->second.begin();pos!=c->second.end();++pos)
5251  {
5252  if(*pos==previousAtom) continue;
5253  BuildRingRecursive(*pos,currentAtom,connect,atomlist,ringlist);
5254  }
5255  atomlist.pop_back(); //??
5256  }
5257 }
5258 
5260 {
5261  this->BuildConnectivityTable();
5262  if(mClockRingList>mClockConnectivityTable) return;
5263  VFN_DEBUG_ENTRY("Molecule::BuildRingList()",7)
5264  for(vector<MolAtom*>::const_iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
5265  (*pos)->SetIsInRing(false);
5266  list<MolAtom *> atomlist;
5267  // Use a map with a set for key to eliminate duplicate rings
5268  map<set<MolAtom *>,list<MolAtom *> > ringlist;
5269  for(unsigned long i=0;i<mvpAtom.size();i++)
5270  {
5271  atomlist.clear();
5272  BuildRingRecursive(mvpAtom[i],mvpAtom[i],mConnectivityTable,atomlist,ringlist);
5273  }
5274  for(map<set<MolAtom *>,list<MolAtom *> >::const_iterator pos0=ringlist.begin();pos0!=ringlist.end();pos0++)
5275  {
5276  mvRing.resize(mvRing.size()+1);
5277  std::list<MolAtom*> *pList=&(mvRing.back().GetAtomList());
5278  #if 1//def __DEBUG__
5279  cout<<"Found ring:";
5280  #endif
5281  for(list<MolAtom *>::const_iterator atom=pos0->second.begin();atom!=pos0->second.end();++atom)
5282  {
5283  pList->push_back(*atom);
5284  (*atom)->SetIsInRing(true);
5285  #if 1//def __DEBUG__
5286  cout<<(*atom)->GetName()<<" ";
5287  #endif
5288  }
5289  #if 1//def __DEBUG__
5290  cout<<endl;
5291  #endif
5292  }
5293 
5294  cout<<"Rings found :"<<ringlist.size()<<", "<<mvRing.size()<<" unique."<<endl;
5295  mClockRingList.Click();
5296  VFN_DEBUG_EXIT("Molecule::BuildRingList()",7)
5297 }
5298 
5300 {
5301  if( (mClockConnectivityTable>mClockBondList)
5302  &&(mClockConnectivityTable>mClockAtomList)) return;
5303  VFN_DEBUG_ENTRY("Molecule::BuildConnectivityTable()",5)
5304  TAU_PROFILE("Molecule::BuildConnectivityTable()","void ()",TAU_DEFAULT);
5305  mConnectivityTable.clear();
5306  for(unsigned long i=0;i<mvpBond.size();++i)
5307  {
5308  mConnectivityTable[&(mvpBond[i]->GetAtom1())].insert(&(mvpBond[i]->GetAtom2()));
5309  mConnectivityTable[&(mvpBond[i]->GetAtom2())].insert(&(mvpBond[i]->GetAtom1()));
5310  }
5311 
5312  #ifdef __DEBUG__
5313  {
5314  map<MolAtom *,set<MolAtom *> >::const_iterator pos;
5315  for(pos=mConnectivityTable.begin();pos!=mConnectivityTable.end();++pos)
5316  {
5317  cout<<"Atom "<<pos->first->GetName()<<" is connected to atoms: ";
5318  set<MolAtom *>::const_iterator pos1;
5319  for(pos1=pos->second.begin();pos1!=pos->second.end();++pos1)
5320  {
5321  cout<<(*pos1)->GetName()<<" ";
5322  }
5323  cout<<endl;
5324  if(pos->second.size()>24)
5325  throw ObjCrystException("Molecule: one atom ("+pos->first->GetName()+") has more than 24 bonds !");
5326  }
5327  }
5328  #endif
5329  mClockConnectivityTable.Click();
5330  VFN_DEBUG_EXIT("Molecule::BuildConnectivityTable()",5)
5331 }
5332 
5334 mpAtom1(&at1),mpAtom2(&at2),mBaseRotationAmplitude(M_PI*0.04)
5335 {}
5336 
5338 {
5339  if( (mClockRotorGroup>mClockBondList)
5340  &&(mClockRotorGroup>mClockAtomList)
5341  &&(mClockRotorGroup>mClockBondAngleList)
5342  &&(mClockRotorGroup>mClockDihedralAngleList)) return;
5343  VFN_DEBUG_ENTRY("Molecule::BuildRotorGroup()",5)
5344  TAU_PROFILE("Molecule::BuildRotorGroup()","void ()",TAU_DEFAULT);
5345  this->BuildConnectivityTable();
5346  mvRotorGroupTorsion.clear();
5348  mvRotorGroupInternal.clear();
5349 
5350  // Build Rotation groups around bonds
5351  for(unsigned long i=0;i<mvpBond.size();++i)
5352  {
5353  if((mFlexModel.GetChoice()!=0)&&(false==mvpBond[i]->IsFreeTorsion())) continue;
5354  MolAtom *const atom1=&(mvpBond[i]->GetAtom1()),
5355  *const atom2=&(mvpBond[i]->GetAtom2());
5356  for(unsigned int j=1;j<=2;++j)
5357  {
5358  const set<MolAtom*> *pConn;
5359  if(j==1) pConn=&(mConnectivityTable[atom1]);
5360  else pConn=&(mConnectivityTable[atom2]);
5361 
5362  mvRotorGroupTorsion.push_back(RotorGroup(mvpBond[i]->GetAtom1(),
5363  mvpBond[i]->GetAtom2()));
5364  mvRotorGroupTorsion.back().mvRotatedAtomList.insert(atom1);
5365  mvRotorGroupTorsion.back().mvRotatedAtomList.insert(atom2);
5366 
5367  for(set<MolAtom*>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
5368  {
5369  if((j==1)&&(*pos==atom2)) continue;
5370  if((j==2)&&(*pos==atom1)) continue;
5372  mvRotorGroupTorsion.back().mvRotatedAtomList);
5373  if(pConn->size()>2)
5374  {
5375  mvRotorGroupTorsionSingleChain.push_back(RotorGroup(mvpBond[i]->GetAtom1(),
5376  mvpBond[i]->GetAtom2()));
5377  mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.insert(atom1);
5378  mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.insert(atom2);
5380  mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList);
5381  mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.erase(atom1);
5382  mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.erase(atom2);
5383 
5384  if( (mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2))
5385  ||(mvRotorGroupTorsionSingleChain.back().mvRotatedAtomList.size()==0))
5386  mvRotorGroupTorsionSingleChain.pop_back();
5387  }
5388  }
5389  mvRotorGroupTorsion.back().mvRotatedAtomList.erase(atom1);
5390  mvRotorGroupTorsion.back().mvRotatedAtomList.erase(atom2);
5391  if( (mvRotorGroupTorsion.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2))
5392  ||(mvRotorGroupTorsion.back().mvRotatedAtomList.size()==0))
5393  mvRotorGroupTorsion.pop_back();
5394  }
5395  }
5396  #if 1
5397  // Build 'internal' rotation groups between random atoms
5398  //:TODO: This should be tried for *random* configuration of free torsion angles...
5399  if(mFlexModel.GetChoice()==0)
5400  {
5401  for(vector<MolAtom*>::const_iterator atom1=this->GetAtomList().begin();
5402  atom1!=this->GetAtomList().end();++atom1)
5403  {
5404  const set<MolAtom*> *pConn=&(mConnectivityTable[*atom1]);
5405  vector<MolAtom*>::const_iterator atom2=atom1;
5406  atom2++;
5407  for(;atom2!=this->GetAtomList().end();++atom2)
5408  {
5409  for(set<MolAtom*>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
5410  {
5411  if(*pos==*atom2) continue;
5412  mvRotorGroupInternal.push_back(RotorGroup(**atom1,**atom2));
5413  mvRotorGroupInternal.back().mvRotatedAtomList.insert(*atom1);
5415  mvRotorGroupInternal.back().mvRotatedAtomList,
5416  *atom2);
5417  //Check if this chains leads to atom2
5418  set<MolAtom*>::const_iterator check
5419  =find(mvRotorGroupInternal.back().mvRotatedAtomList.begin(),
5420  mvRotorGroupInternal.back().mvRotatedAtomList.end(),*atom2);
5421  if( (check==mvRotorGroupInternal.back().mvRotatedAtomList.end())
5422  ||(mvRotorGroupInternal.back().mvRotatedAtomList.size()<3)
5423  ||(mvRotorGroupInternal.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2)))
5424  {
5425  mvRotorGroupInternal.pop_back();
5426  }
5427  else
5428  {
5429  mvRotorGroupInternal.back().mvRotatedAtomList.erase(*atom1);
5430  mvRotorGroupInternal.back().mvRotatedAtomList.erase(*atom2);
5431  }
5432  }
5433  }
5434  }
5435  }
5436  #endif
5437 
5438  // Remove identical groups
5439  for(unsigned int i=1;i<=3;++i)
5440  {
5441  list<RotorGroup> *pRotorGroup1;
5442  switch(i)
5443  {
5444  case 1: pRotorGroup1=&mvRotorGroupTorsion;break;
5445  case 2: pRotorGroup1=&mvRotorGroupTorsionSingleChain;break;
5446  case 3: pRotorGroup1=&mvRotorGroupInternal;break;
5447  }
5448  for(list<RotorGroup>::iterator pos1=pRotorGroup1->begin();
5449  pos1!=pRotorGroup1->end();++pos1)
5450  {
5451  for(unsigned int j=i;j<=3;++j)
5452  {
5453  list<RotorGroup> *pRotorGroup2;
5454  switch(j)
5455  {
5456  case 1: pRotorGroup2=&mvRotorGroupTorsion;break;
5457  case 2: pRotorGroup2=&mvRotorGroupTorsionSingleChain;break;
5458  case 3: pRotorGroup2=&mvRotorGroupInternal;break;
5459  }
5460  for(list<RotorGroup>::iterator pos2=pRotorGroup2->begin();
5461  pos2!=pRotorGroup2->end();)
5462  {
5463  if(pos2==pos1) {++pos2;continue;}
5464  if(( ((pos1->mpAtom1 == pos2->mpAtom1) && (pos1->mpAtom2 == pos2->mpAtom2))
5465  ||((pos1->mpAtom2 == pos2->mpAtom1) && (pos1->mpAtom1 == pos2->mpAtom2)))
5466  &&pos1->mvRotatedAtomList.size() == pos2->mvRotatedAtomList.size())
5467  {
5468  bool ident=true;
5469  for(set<MolAtom*>::const_iterator pos=pos1->mvRotatedAtomList.begin();
5470  pos!=pos1->mvRotatedAtomList.end();++pos)
5471  {
5472  set<MolAtom*>::const_iterator tmp=pos2->mvRotatedAtomList.find(*pos);
5473  if(tmp == pos2->mvRotatedAtomList.end())
5474  {
5475  ident=false;
5476  break;
5477  }
5478  }
5479  if(ident)
5480  {
5481  #if 0
5482  cout<<"Identical groups:"<<endl;
5483  cout<<" G1:"
5484  <<pos1->mpAtom1->GetName()<<"-"
5485  <<pos1->mpAtom2->GetName()<<" : ";
5486  for(set<MolAtom*>::iterator pos=pos1->mvRotatedAtomList.begin();
5487  pos!=pos1->mvRotatedAtomList.end();++pos)
5488  cout<<(*pos)->GetName()<<" ";
5489  cout<<endl;
5490  cout<<" G2:"
5491  <<pos2->mpAtom1->GetName()<<"-"
5492  <<pos2->mpAtom2->GetName()<<" : ";
5493  for(set<MolAtom*>::iterator pos=pos2->mvRotatedAtomList.begin();
5494  pos!=pos2->mvRotatedAtomList.end();++pos)
5495  cout<<(*pos)->GetName()<<" ";
5496  cout<<endl;
5497  #endif
5498  pos2=pRotorGroup2->erase(pos2);
5499  }
5500  else ++pos2;
5501  }
5502  else ++pos2;
5503  }
5504  }
5505  }
5506  }
5507  // Remove all rotations which break restraints and therefore are not "free torsion"
5508  this->SaveParamSet(mLocalParamSet);
5509  const REAL llk0=this->GetLogLikelihood();
5510  for(unsigned int i=1;i<=3;++i)
5511  {
5512  list<RotorGroup> *pRotorGroup1;
5513  switch(i)
5514  {
5515  case 1: pRotorGroup1=&mvRotorGroupTorsion;break;
5516  case 2: pRotorGroup1=&mvRotorGroupTorsionSingleChain;break;
5517  case 3: pRotorGroup1=&mvRotorGroupInternal;break;
5518  }
5519  for(list<RotorGroup>::iterator pos=pRotorGroup1->begin();
5520  pos!=pRotorGroup1->end();)
5521  {
5522  REAL llk=0;
5523  for(unsigned int j=0;j<36;++j)
5524  {
5525  const REAL angle=(REAL)j*M_PI/36.;
5526  this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),
5527  pos->mvRotatedAtomList,angle);
5528  // use fabs in case we are not starting from the minimum of a restraint..
5529  llk += fabs(this->GetLogLikelihood() - llk0);
5530  this->RestoreParamSet(mLocalParamSet);
5531  }
5532  #ifdef __DEBUG__
5533  switch(i)
5534  {
5535  case 1: cout<<"Rotation Group around bond :";break;
5536  case 2: cout<<"Rotation Group (single chain) around bond :";break;
5537  case 3: cout<<"Rotation Group (internal) between :";break;
5538  }
5539  cout <<pos->mpAtom1->GetName()<<"-"
5540  <<pos->mpAtom2->GetName()<<" : ";
5541  for(set<MolAtom *>::iterator pos1=pos->mvRotatedAtomList.begin();
5542  pos1!=pos->mvRotatedAtomList.end();++pos1)
5543  cout<<(*pos1)->GetName()<<" ";
5544  cout<<" <d(LLK)>="<< llk/36.;
5545  #endif
5546  if((llk/50.)>100.)
5547  {
5548  pos = pRotorGroup1->erase(pos);
5549  //cout <<" -> NOT a free torsion"<<endl;
5550  }
5551  else ++pos;
5552  //else
5553  // cout <<" -> free torsion"<<endl;
5554  }
5555  }
5556  //cout<<endl;
5557 
5558  // Label free torsions
5559  for(vector<MolBond*>::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
5560  (*pos)->SetFreeTorsion(false);
5561  for(list<RotorGroup>::iterator pos=mvRotorGroupTorsion.begin();
5562  pos!=mvRotorGroupTorsion.end();++pos)
5563  {
5564  vector<MolBond*>::iterator bd=this->FindBond((*pos->mpAtom1),(*pos->mpAtom2));
5565  if(bd!=mvpBond.end()) (*bd)->SetFreeTorsion(true);
5566  }
5567 
5568  mClockRotorGroup.Click();
5569  VFN_DEBUG_EXIT("Molecule::BuildRotorGroup()",5)
5570 }
5571 
5573 {
5574  #if 0
5575  if( (mClockStretchModeBondLength>mClockBondList)
5576  &&(mClockStretchModeBondLength>mClockAtomList)
5577  &&(mClockStretchModeBondLength>mClockBondAngleList)
5578  &&(mClockStretchModeBondLength>mClockDihedralAngleList)) return;
5579  #endif
5580  VFN_DEBUG_ENTRY("Molecule::BuildStretchModeBondLength()",7)
5581  this->BuildConnectivityTable();
5582  TAU_PROFILE("Molecule::BuildStretchModeBondLength()","void ()",TAU_DEFAULT);
5583  TAU_PROFILE_TIMER(timer1,"Molecule::BuildStretchModeBondLength 1","", TAU_FIELD);
5584  TAU_PROFILE_TIMER(timer2,"Molecule::BuildStretchModeBondLength 2","", TAU_FIELD);
5585  TAU_PROFILE_TIMER(timer3,"Molecule::BuildStretchModeBondLength 3","", TAU_FIELD);
5586  TAU_PROFILE_TIMER(timer4,"Molecule::BuildStretchModeBondLength 4","", TAU_FIELD);
5587  TAU_PROFILE_TIMER(timer5,"Molecule::BuildStretchModeBondLength 5","", TAU_FIELD);
5588  mvStretchModeBondLength.clear();
5589  // Build list of atoms moved when stretching a bond length. Only keep the group
5590  // of atoms on the smaller side.
5591  TAU_PROFILE_START(timer1);
5592  for(unsigned long i=0;i<mvpBond.size();++i)
5593  {
5594  //if((mFlexModel.GetChoice()!=0)&&(false==mvpBond[i]->IsFreeTorsion())) continue;
5595  MolAtom* const atom1=&(mvpBond[i]->GetAtom1());
5596  MolAtom* const atom2=&(mvpBond[i]->GetAtom2());
5597  for(unsigned int j=1;j<=2;++j)
5598  {
5599  const set<MolAtom*> *pConn;
5600  if(j==1) pConn=&(mConnectivityTable[atom1]);
5601  else pConn=&(mConnectivityTable[atom2]);
5602 
5603  if(j==1)
5604  mvStretchModeBondLength.push_back(StretchModeBondLength(mvpBond[i]->GetAtom2(),
5605  mvpBond[i]->GetAtom1(),
5606  mvpBond[i]));
5607  else
5608  mvStretchModeBondLength.push_back(StretchModeBondLength(mvpBond[i]->GetAtom1(),
5609  mvpBond[i]->GetAtom2(),
5610  mvpBond[i]));
5611  if(j==1) mvStretchModeBondLength.back().mvTranslatedAtomList.insert(atom1);
5612  if(j==2) mvStretchModeBondLength.back().mvTranslatedAtomList.insert(atom2);
5613 
5614  for(set<MolAtom*>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
5615  {
5616  if((j==1)&&(*pos==atom2)) continue;
5617  if((j==2)&&(*pos==atom1)) continue;
5619  mvStretchModeBondLength.back().mvTranslatedAtomList);
5620  }
5621  const unsigned long ct1=mvStretchModeBondLength.back().mvTranslatedAtomList.count(atom1),
5622  ct2=mvStretchModeBondLength.back().mvTranslatedAtomList.count(atom2);
5623  if( ((j==1)&&(ct2>0)) || ((j==2)&&(ct1>0)) )
5624  {
5625  // We have found a ring. No use looking at the other side.
5626  // :TODO: handle this properly..
5627  mvStretchModeBondLength.pop_back();
5628  break;
5629  }
5630  if( (mvStretchModeBondLength.back().mvTranslatedAtomList.size()>((mvpAtom.size()+1)/2))
5631  ||(mvStretchModeBondLength.back().mvTranslatedAtomList.size()==0))
5632  {
5633  #ifdef __DEBUG__
5634  cout<<"Rejecting StretchModeBondLength ";mvStretchModeBondLength.back().Print(cout);cout<<endl;
5635  #endif
5636  mvStretchModeBondLength.pop_back();
5637  }
5638  else if(mvStretchModeBondLength.back().mvTranslatedAtomList.size()==((mvpAtom.size()+1)/2))
5639  break;//we translate exactly half of the atoms, so skip the other half
5640  }
5641  }
5642  TAU_PROFILE_STOP(timer1);
5643 
5644  // find rigid groups broken by each mode
5645  for(list<StretchModeBondLength>::iterator pos=mvStretchModeBondLength.begin();
5646  pos!=mvStretchModeBondLength.end();)
5647  {
5648  TAU_PROFILE_START(timer5);
5649  bool keep=true;
5650  for(vector<RigidGroup*>::const_iterator group=mvRigidGroup.begin();
5651  group!=mvRigidGroup.end();++group)
5652  {
5653  unsigned long ct=0;
5654  for(set<MolAtom *>::const_iterator at=(*group)->begin();at!=(*group)->end();++at)
5655  ct += pos->mvTranslatedAtomList.count(*at);
5656  if((ct>0)&&(ct!=(*group)->size()))
5657  {
5658  keep=false;
5659  #ifdef __DEBUG__
5660  cout<<" Breaks Rigid Group:";
5661  for(set<MolAtom *>::const_iterator at=(*group)->begin();at!=(*group)->end();++at)
5662  cout<<(*at)->GetName()<<" ";
5663  cout<<endl;
5664  #endif
5665  break;
5666  }
5667  }
5668  if(keep) ++pos;
5669  else pos=mvStretchModeBondLength.erase(pos);
5670  TAU_PROFILE_STOP(timer5);
5671  }
5672  // Generate 5 completely random atomic positions
5673  this->SaveParamSet(mLocalParamSet);
5674  unsigned long paramSetRandom[5];
5675  for(unsigned long i=0;i<5;++i)
5676  {
5677  for(vector<MolAtom*>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
5678  {
5679  (*pos)->SetX(100.*rand()/(REAL) RAND_MAX);
5680  (*pos)->SetY(100.*rand()/(REAL) RAND_MAX);
5681  (*pos)->SetZ(100.*rand()/(REAL) RAND_MAX);
5682  }
5683  paramSetRandom[i]=this->CreateParamSet();
5684  }
5685  // find bond lengths broken by each mode
5686  for(list<StretchModeBondLength>::iterator pos=mvStretchModeBondLength.begin();
5687  pos!=mvStretchModeBondLength.end();)
5688  {
5689  TAU_PROFILE_START(timer2);
5690  bool keep=true;
5691  pos->mvpBrokenBond.clear();
5692  for(vector<MolBond*>::const_iterator r=mvpBond.begin();r!=mvpBond.end();++r)
5693  {
5694  unsigned int ct=0;
5695  for(set<MolAtom *>::const_iterator at=pos->mvTranslatedAtomList.begin();
5696  at!=pos->mvTranslatedAtomList.end();++at)
5697  {
5698  if(*at==&((*r)->GetAtom1())) ct++;
5699  if(*at==&((*r)->GetAtom2())) ct++;
5700  }
5701  // If we moved either both or non of the bond atom, the bond length is unchanged.
5702  if((ct!=0)&&(ct !=2)) pos->mvpBrokenBond.insert(make_pair(*r,0));
5703  }
5704  if(mFlexModel.GetChoice()==2)
5705  {
5706  int nb=pos->mvpBrokenBond.size();
5707  if(pos->mpBond!=0) nb -= 1;
5708  if(nb>0) keep=false;
5709  }
5710  if(keep) ++pos;
5711  else pos=mvStretchModeBondLength.erase(pos);
5712  TAU_PROFILE_STOP(timer2);
5713  }
5714  // find bond angles broken by each mode
5715  for(list<StretchModeBondLength>::iterator pos=mvStretchModeBondLength.begin();
5716  pos!=mvStretchModeBondLength.end();)
5717  {
5718  TAU_PROFILE_START(timer3);
5719  bool keep=true;
5720  pos->mvpBrokenBondAngle.clear();
5721  for(vector<MolBondAngle*>::const_iterator r=mvpBondAngle.begin();r!=mvpBondAngle.end();++r)
5722  {
5723  unsigned int ct=0;
5724  for(set<MolAtom *>::const_iterator at=pos->mvTranslatedAtomList.begin();
5725  at!=pos->mvTranslatedAtomList.end();++at)
5726  {
5727  if(*at==&((*r)->GetAtom1())) ct++;
5728  if(*at==&((*r)->GetAtom2())) ct++;
5729  if(*at==&((*r)->GetAtom3())) ct++;
5730  }
5731  bool broken=true;
5732  if((ct==0)||(ct==3)) broken=false;
5733  if(broken)
5734  {// Make sure with derivatives
5735  REAL d=0;
5736  for(unsigned long i=0;i<5;++i)
5737  {
5738  this->RestoreParamSet(paramSetRandom[i]);
5739  pos->CalcDeriv(false);
5740  (*r)->GetLogLikelihood(true,true);
5741  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
5742  if(d>0.01) break;
5743  }
5744  if(abs(d)<=0.01) broken=false;
5745  }
5746  if(broken) pos->mvpBrokenBondAngle.insert(make_pair(*r,0));
5747  }
5748  if(mFlexModel.GetChoice()==2)
5749  {
5750  if(pos->mvpBrokenBondAngle.size()>0) keep=false;
5751  }
5752  if(keep) ++pos;
5753  else pos=mvStretchModeBondLength.erase(pos);
5754  TAU_PROFILE_STOP(timer3);
5755  }
5756  // find dihedral angles broken by each mode
5757  for(list<StretchModeBondLength>::iterator pos=mvStretchModeBondLength.begin();
5758  pos!=mvStretchModeBondLength.end();)
5759  {
5760  TAU_PROFILE_START(timer4);
5761  bool keep=true;
5762  pos->mvpBrokenDihedralAngle.clear();
5763  for(vector<MolDihedralAngle*>::const_iterator r=mvpDihedralAngle.begin();r!=mvpDihedralAngle.end();++r)
5764  {
5765  unsigned int ct=0;
5766  for(set<MolAtom *>::const_iterator at=pos->mvTranslatedAtomList.begin();
5767  at!=pos->mvTranslatedAtomList.end();++at)
5768  {
5769  if(*at==&((*r)->GetAtom1())) ct++;
5770  if(*at==&((*r)->GetAtom2())) ct++;
5771  if(*at==&((*r)->GetAtom3())) ct++;
5772  if(*at==&((*r)->GetAtom4())) ct++;
5773  }
5774  bool broken=true;
5775  if((ct==0)||(ct==4)) broken=false;
5776  if(broken)
5777  {// Make sure with derivatives
5778  REAL d=0;
5779  for(unsigned long i=0;i<5;++i)
5780  {
5781  this->RestoreParamSet(paramSetRandom[i]);
5782  pos->CalcDeriv(false);
5783  (*r)->GetLogLikelihood(true,true);
5784  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
5785  if(d>0.01) break;
5786  }
5787  if(abs(d)<=0.01) broken=false;
5788  }
5789  if(broken) pos->mvpBrokenDihedralAngle.insert(make_pair(*r,0));
5790  }
5791  if(mFlexModel.GetChoice()==2)
5792  {
5793  if(pos->mvpBrokenDihedralAngle.size()>0) keep=false;
5794  }
5795  if(keep) ++pos;
5796  else pos=mvStretchModeBondLength.erase(pos);
5797  TAU_PROFILE_STOP(timer4);
5798  }
5799  this->RestoreParamSet(mLocalParamSet);
5800  for(unsigned long i=0;i<5;++i) this->ClearParamSet(paramSetRandom[i]);
5801  #if 1//def __DEBUG__
5802  cout<<"List of Bond Length stretch modes"<<endl;
5803  for(list<StretchModeBondLength>::const_iterator pos=mvStretchModeBondLength.begin();
5804  pos!=mvStretchModeBondLength.end();++pos)
5805  {
5806  cout<<" Bond:"<<pos->mpAtom0->GetName()<<"-"<<pos->mpAtom1->GetName()<<", Translated Atoms: ";
5807  for(set<MolAtom*>::const_iterator atom=pos->mvTranslatedAtomList.begin();
5808  atom!=pos->mvTranslatedAtomList.end();++atom)
5809  {
5810  cout<<(*atom)->GetName()<<",";
5811  }
5812  if(pos->mpBond!=0) cout<< " ; restrained to length="<<pos->mpBond->GetLength0()
5813  <<", sigma="<<pos->mpBond->GetLengthSigma()
5814  <<", delta="<<pos->mpBond->GetLengthDelta();
5815  if(pos->mvpBrokenBond.size()>0)
5816  {
5817  cout<<endl<<" Broken bonds:";
5818  for(map<const MolBond*,REAL>::const_iterator bond=pos->mvpBrokenBond.begin();
5819  bond!=pos->mvpBrokenBond.end();++bond)
5820  cout<<bond->first->GetName()<<", ";
5821  }
5822  if(pos->mvpBrokenBondAngle.size()>0)
5823  {
5824  cout<<endl<<" Broken bond angles:";
5825  for(map<const MolBondAngle*,REAL>::const_iterator angle=pos->mvpBrokenBondAngle.begin();
5826  angle!=pos->mvpBrokenBondAngle.end();++angle)
5827  cout<<angle->first->GetName()<<", ";
5828  }
5829  if(pos->mvpBrokenDihedralAngle.size()>0)
5830  {
5831  cout<<endl<<" Broken dihedral angles:";
5832  for(map<const MolDihedralAngle*,REAL>::const_iterator
5833  angle=pos->mvpBrokenDihedralAngle.begin();
5834  angle!=pos->mvpBrokenDihedralAngle.end();++angle)
5835  cout<<angle->first->GetName()<<", ";
5836  }
5837  cout<<endl;
5838  }
5839  #endif
5840  mClockStretchModeBondLength.Click();
5841  VFN_DEBUG_EXIT("Molecule::BuildStretchModeBondLength()",7)
5842 }
5843 
5845 {
5846  #if 0
5847  if( (mClockStretchModeBondAngle>mClockBondList)
5848  &&(mClockStretchModeBondAngle>mClockAtomList)
5849  &&(mClockStretchModeBondAngle>mClockBondAngleList)
5850  &&(mClockStretchModeBondAngle>mClockDihedralAngleList)) return;
5851  #endif
5852  VFN_DEBUG_ENTRY("Molecule::BuildStretchModeBondAngle()",10)
5853  this->BuildConnectivityTable();
5854  TAU_PROFILE("Molecule::BuildStretchModeBondAngle()","void ()",TAU_DEFAULT);
5855  TAU_PROFILE_TIMER(timer1,"Molecule::BuildStretchModeBondAngle 1","", TAU_FIELD);
5856  TAU_PROFILE_TIMER(timer2,"Molecule::BuildStretchModeBondAngle 2","", TAU_FIELD);
5857  TAU_PROFILE_TIMER(timer3,"Molecule::BuildStretchModeBondAngle 3","", TAU_FIELD);
5858  TAU_PROFILE_TIMER(timer4,"Molecule::BuildStretchModeBondAngle 4","", TAU_FIELD);
5859  TAU_PROFILE_TIMER(timer5,"Molecule::BuildStretchModeBondAngle 5","", TAU_FIELD);
5860  mvStretchModeBondAngle.clear();
5861  // Build list of atoms moved when stretching a bond angle. Only keep the group
5862  // of atoms on the smaller side.
5863  TAU_PROFILE_START(timer1);
5864  for(unsigned long i=0;i<mvpAtom.size();++i)
5865  {
5866  //if((mFlexModel.GetChoice()!=0)&&(false==mvpBond[i]->IsFreeTorsion())) continue;
5867  set<MolAtom*> *pConn0=&(mConnectivityTable[mvpAtom[i]]);
5868  if(pConn0->size()<2) continue;
5869  for(set<MolAtom*>::const_iterator pos1=pConn0->begin();pos1!=pConn0->end();++pos1)
5870  {
5871  set<MolAtom*>::const_iterator pos2=pos1;
5872  pos2++;
5873  for(;pos2!=pConn0->end();++pos2)
5874  {
5875  VFN_DEBUG_MESSAGE("Molecule::BuildStretchModeBondAngle():"<<i<<","<<*pos1<<","<<*pos2,10)
5876  //Do we have a bond angle restraint corresponding to these atoms ?
5877  MolBondAngle *pMolBondAngle=0;
5878  for(vector<MolBondAngle*>::const_iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
5879  {
5880  if(&((*pos)->GetAtom2())==mvpAtom[i])
5881  {
5882  if( ((&((*pos)->GetAtom1())==*pos1)&&(&((*pos)->GetAtom3())==*pos2))
5883  ||((&((*pos)->GetAtom1())==*pos2)&&(&((*pos)->GetAtom3())==*pos1)))
5884  {
5885  pMolBondAngle=*pos;
5886  break;
5887  }
5888  }
5889  }
5890  for(unsigned int j=1;j<=2;++j)
5891  {
5892  const set<MolAtom*> *pConn;
5893  if(j==1)
5894  {
5895  pConn=&(mConnectivityTable[*pos1]);
5897  *mvpAtom[i],
5898  **pos1,
5899  pMolBondAngle));
5900  mvStretchModeBondAngle.back().mvRotatedAtomList.insert(*pos1);
5901  }
5902  else
5903  {
5904  pConn=&(mConnectivityTable[*pos2]);
5906  *mvpAtom[i],
5907  **pos2,
5908  pMolBondAngle));
5909  mvStretchModeBondAngle.back().mvRotatedAtomList.insert(*pos2);
5910  }
5911  mvStretchModeBondAngle.back().mvRotatedAtomList.insert(mvpAtom[i]);
5912 
5913  for(set<MolAtom*>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
5914  {
5915  if(*pos==mvpAtom[i]) continue;
5917  mvStretchModeBondAngle.back().mvRotatedAtomList);
5918  }
5919  //if(j==1)mvStretchModeBondAngle.back().mvRotatedAtomList.erase(*pos2);
5920  //if(j==2)mvStretchModeBondAngle.back().mvRotatedAtomList.erase(*pos1);
5921  mvStretchModeBondAngle.back().mvRotatedAtomList.erase(mvpAtom[i]);
5922 
5923  if( (mvStretchModeBondAngle.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2))
5924  ||(mvStretchModeBondAngle.back().mvRotatedAtomList.size()==0))
5925  {
5926  #ifdef __DEBUG__
5927  cout<<"Rejecting StretchModeBondAngle ";mvStretchModeBondAngle.back().Print(cout);cout<<endl;
5928  #endif
5929  mvStretchModeBondAngle.pop_back();
5930  }
5931  else
5932  {
5933  if((j==1) &&(mvStretchModeBondAngle.back().mvRotatedAtomList.find(*pos2)
5934  !=mvStretchModeBondAngle.back().mvRotatedAtomList.end()))
5935  {
5936  #if 1//def __DEBUG__
5937  cout<<"Rejecting StretchModeBondAngle (ring) ";mvStretchModeBondAngle.back().Print(cout);cout<<endl;
5938  #endif
5939  mvStretchModeBondAngle.pop_back();
5940  }
5941  if((j==2) &&(mvStretchModeBondAngle.back().mvRotatedAtomList.find(*pos1)
5942  !=mvStretchModeBondAngle.back().mvRotatedAtomList.end()))
5943  {
5944  #if 1//def __DEBUG__
5945  cout<<"Rejecting StretchModeBondAngle (ring) ";mvStretchModeBondAngle.back().Print(cout);cout<<endl;
5946  #endif
5947  mvStretchModeBondAngle.pop_back();
5948  }
5949  }
5950 
5951  }
5952  }
5953  }
5954  }
5955  TAU_PROFILE_STOP(timer1);
5956  // find rigid groups broken by each mode
5957  for(list<StretchModeBondAngle>::iterator pos=mvStretchModeBondAngle.begin();
5958  pos!=mvStretchModeBondAngle.end();)
5959  {
5960  TAU_PROFILE_START(timer5);
5961  bool keep=true;
5962  for(vector<RigidGroup*>::const_iterator group=mvRigidGroup.begin();
5963  group!=mvRigidGroup.end();++group)
5964  {
5965  unsigned long ct=0;
5966  for(set<MolAtom *>::const_iterator at=(*group)->begin();at!=(*group)->end();++at)
5967  ct += pos->mvRotatedAtomList.count(*at);
5968  if(ct>0)
5969  {
5970  // Add the origin atom, which does not move relatively to the rotated atoms
5971  ct += (*group)->count(pos->mpAtom1);
5972  if(ct!=(*group)->size())
5973  {
5974  keep=false;
5975  #ifdef __DEBUG__
5976  pos->Print(cout);
5977  cout<<" Breaks Rigid Group:";
5978  for(set<MolAtom *>::const_iterator at=(*group)->begin();at!=(*group)->end();++at)
5979  cout<<(*at)->GetName()<<" ";
5980  cout<<endl;
5981  #endif
5982  break;
5983  }
5984  }
5985  }
5986  if(keep) ++pos;
5987  else pos=mvStretchModeBondAngle.erase(pos);
5988  TAU_PROFILE_STOP(timer5);
5989  }
5990  // Generate 5 completely random atomic positions
5991  this->SaveParamSet(mLocalParamSet);
5992  unsigned long paramSetRandom[5];
5993  for(unsigned long i=0;i<5;++i)
5994  {
5995  for(vector<MolAtom*>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
5996  {
5997  (*pos)->SetX(100.*rand()/(REAL) RAND_MAX);
5998  (*pos)->SetY(100.*rand()/(REAL) RAND_MAX);
5999  (*pos)->SetZ(100.*rand()/(REAL) RAND_MAX);
6000  }
6001  paramSetRandom[i]=this->CreateParamSet();
6002  }
6003  // find bond lengths broken by each mode
6004  for(list<StretchModeBondAngle>::iterator pos=mvStretchModeBondAngle.begin();
6005  pos!=mvStretchModeBondAngle.end();)
6006  {
6007  TAU_PROFILE_START(timer2);
6008  bool keep=true;
6009  pos->mvpBrokenBond.clear();
6010  for(vector<MolBond*>::const_iterator r=mvpBond.begin();r!=mvpBond.end();++r)
6011  {
6012  unsigned int ct=0;
6013  for(set<MolAtom *>::const_iterator at=pos->mvRotatedAtomList.begin();
6014  at!=pos->mvRotatedAtomList.end();++at)
6015  {
6016  if(*at==&((*r)->GetAtom1())) ct++;
6017  if(*at==&((*r)->GetAtom2())) ct++;
6018  }
6019  bool broken=true;
6020  // If we moved either both or non of the bond atom, the bond length is unchanged.
6021  if((ct==0)||(ct==2)) broken=false;
6022  if(broken)
6023  {// Make sure with derivatives
6024  REAL d=0;
6025  for(unsigned long i=0;i<5;++i)
6026  {
6027  this->RestoreParamSet(paramSetRandom[i]);
6028  pos->CalcDeriv(false);
6029  (*r)->GetLogLikelihood(true,true);
6030  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6031  if(d>0.01) break;
6032  }
6033  if(abs(d)<=0.01) broken=false;
6034  }
6035  if(broken) pos->mvpBrokenBond.insert(make_pair(*r,0));
6036  }
6037  if(mFlexModel.GetChoice()==2)
6038  {
6039  if(pos->mvpBrokenBond.size()>0) keep=false;
6040  }
6041  if(keep) ++pos;
6042  else pos=mvStretchModeBondAngle.erase(pos);
6043  TAU_PROFILE_STOP(timer2);
6044  }
6045  // find bond angles broken by each mode
6046  for(list<StretchModeBondAngle>::iterator pos=mvStretchModeBondAngle.begin();
6047  pos!=mvStretchModeBondAngle.end();)
6048  {
6049  TAU_PROFILE_START(timer3);
6050  bool keep=true;
6051  pos->mvpBrokenBondAngle.clear();
6052  for(vector<MolBondAngle*>::const_iterator r=mvpBondAngle.begin();r!=mvpBondAngle.end();++r)
6053  {
6054  unsigned int ct=0;
6055  for(set<MolAtom *>::const_iterator at=pos->mvRotatedAtomList.begin();
6056  at!=pos->mvRotatedAtomList.end();++at)
6057  {
6058  if(*at==&((*r)->GetAtom1())) ct++;
6059  if(*at==&((*r)->GetAtom2())) ct++;
6060  if(*at==&((*r)->GetAtom3())) ct++;
6061  }
6062  bool broken=true;
6063  if(ct==0) broken=false;
6064  if(ct==3) broken=false;
6065  if(broken)
6066  {// Make sure with derivatives
6067  REAL d=0;
6068  for(unsigned long i=0;i<5;++i)
6069  {
6070  this->RestoreParamSet(paramSetRandom[i]);
6071  pos->CalcDeriv(false);
6072  (*r)->GetLogLikelihood(true,true);
6073  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6074  if(d>0.01) break;
6075  }
6076  if(abs(d)<=0.01) broken=false;
6077  }
6078  if(broken) pos->mvpBrokenBondAngle.insert(make_pair(*r,0));
6079  }
6080  if(mFlexModel.GetChoice()==2)
6081  {
6082  int nb=pos->mvpBrokenBond.size();
6083  if(pos->mpBondAngle!=0) nb -= 1;
6084  if(nb>0) keep=false;
6085  }
6086  if(keep) ++pos;
6087  else pos=mvStretchModeBondAngle.erase(pos);
6088  TAU_PROFILE_STOP(timer3);
6089  }
6090  // find dihedral angles broken by each mode
6091  for(list<StretchModeBondAngle>::iterator pos=mvStretchModeBondAngle.begin();
6092  pos!=mvStretchModeBondAngle.end();)
6093  {
6094  TAU_PROFILE_START(timer4);
6095  bool keep=true;
6096  pos->mvpBrokenDihedralAngle.clear();
6097  for(vector<MolDihedralAngle*>::const_iterator r=mvpDihedralAngle.begin();r!=mvpDihedralAngle.end();++r)
6098  {
6099  unsigned int ct=0;
6100  for(set<MolAtom *>::const_iterator at=pos->mvRotatedAtomList.begin();
6101  at!=pos->mvRotatedAtomList.end();++at)
6102  {
6103  if(*at==&((*r)->GetAtom1())) ct++;
6104  if(*at==&((*r)->GetAtom2())) ct++;
6105  if(*at==&((*r)->GetAtom3())) ct++;
6106  if(*at==&((*r)->GetAtom4())) ct++;
6107  }
6108  bool broken=true;
6109  if(ct==0) broken=false;
6110  if(ct==4) broken=false;
6111  if(broken)
6112  {// Make sure with derivatives
6113  REAL d=0;
6114  for(unsigned long i=0;i<5;++i)
6115  {
6116  this->RestoreParamSet(paramSetRandom[i]);
6117  pos->CalcDeriv(false);
6118  (*r)->GetLogLikelihood(true,true);
6119  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6120  if(d>0.01) break;
6121  }
6122  if(abs(d)<=0.01) broken=false;
6123  }
6124  if(broken) pos->mvpBrokenDihedralAngle.insert(make_pair(*r,0));
6125  }
6126  if(mFlexModel.GetChoice()==2)
6127  {
6128  if(pos->mvpBrokenDihedralAngle.size()>0) keep=false;
6129  }
6130  if(keep) ++pos;
6131  else pos=mvStretchModeBondAngle.erase(pos);
6132  TAU_PROFILE_STOP(timer4);
6133  }
6134  this->RestoreParamSet(mLocalParamSet);
6135  for(unsigned long i=0;i<5;++i) this->ClearParamSet(paramSetRandom[i]);
6136  #ifdef __DEBUG__
6137  cout<<"List of Bond Angle stretch modes"<<endl;
6138  for(list<StretchModeBondAngle>::const_iterator pos=mvStretchModeBondAngle.begin();
6139  pos!=mvStretchModeBondAngle.end();++pos)
6140  {
6141  cout<<" Angle:"<<pos->mpAtom0->GetName()<<"-"
6142  <<pos->mpAtom1->GetName()<<"-"
6143  <<pos->mpAtom2->GetName()<<", Rotated Atoms: ";
6144  for(set<MolAtom*>::const_iterator atom=pos->mvRotatedAtomList.begin();
6145  atom!=pos->mvRotatedAtomList.end();++atom)
6146  {
6147  cout<<(*atom)->GetName()<<",";
6148  }
6149  if(pos->mpBondAngle!=0) cout<< " ; restrained to angle="<<pos->mpBondAngle->GetAngle0()*RAD2DEG
6150  <<"�, sigma="<<pos->mpBondAngle->GetAngleSigma()*RAD2DEG
6151  <<"�, delta="<<pos->mpBondAngle->GetAngleDelta()*RAD2DEG<<"�";
6152  if(pos->mvpBrokenBond.size()>0)
6153  {
6154  cout<<endl<<" Broken bonds:";
6155  for(map<const MolBond*,REAL>::const_iterator bond=pos->mvpBrokenBond.begin();
6156  bond!=pos->mvpBrokenBond.end();++bond)
6157  cout<<bond->first->GetName()<<", ";
6158  }
6159  if(pos->mvpBrokenBondAngle.size()>0)
6160  {
6161  cout<<endl<<" Broken bond angles:";
6162  for(map<const MolBondAngle*,REAL>::const_iterator angle=pos->mvpBrokenBondAngle.begin();
6163  angle!=pos->mvpBrokenBondAngle.end();++angle)
6164  cout<<angle->first->GetName()<<", ";
6165  }
6166  if(pos->mvpBrokenDihedralAngle.size()>0)
6167  {
6168  cout<<endl<<" Broken dihedral angles:";
6169  for(map<const MolDihedralAngle*,REAL>::const_iterator
6170  angle=pos->mvpBrokenDihedralAngle.begin();
6171  angle!=pos->mvpBrokenDihedralAngle.end();++angle)
6172  cout<<angle->first->GetName()<<", ";
6173  }
6174  cout<<endl;
6175  }
6176  #endif
6177  mClockStretchModeBondAngle.Click();
6178  VFN_DEBUG_EXIT("Molecule::BuildStretchModeBondAngle()",10)
6179 }
6180 
6182 {
6183  #if 0
6184  if( (mClockStretchModeTorsion>mClockBondList)
6185  &&(mClockStretchModeTorsion>mClockAtomList)
6186  &&(mClockStretchModeTorsion>mClockBondAngleList)
6187  &&(mClockStretchModeTorsion>mClockDihedralAngleList)) return;
6188  #endif
6189  VFN_DEBUG_ENTRY("Molecule::BuildStretchModeTorsion()",7)
6190  TAU_PROFILE("Molecule::BuildStretchModeTorsion()","void ()",TAU_DEFAULT);
6191  TAU_PROFILE_TIMER(timer1,"Molecule::BuildStretchModeTorsion 1","", TAU_FIELD);
6192  TAU_PROFILE_TIMER(timer2,"Molecule::BuildStretchModeTorsion 2","", TAU_FIELD);
6193  TAU_PROFILE_TIMER(timer3,"Molecule::BuildStretchModeTorsion 3","", TAU_FIELD);
6194  TAU_PROFILE_TIMER(timer4,"Molecule::BuildStretchModeTorsion 4","", TAU_FIELD);
6195  TAU_PROFILE_TIMER(timer5,"Molecule::BuildStretchModeTorsion 5","", TAU_FIELD);
6196  this->BuildConnectivityTable();
6197  mvStretchModeTorsion.clear();
6198  // Build list of atoms moved when changing the angle. Only keep the group
6199  // of atoms on the smaller side.
6200  for(unsigned long i=0;i<mvpBond.size();++i)
6201  {
6202  //if((mFlexModel.GetChoice()!=0)&&(false==mvpBond[i]->IsFreeTorsion())) continue;
6203  MolAtom* const atom1=&(mvpBond[i]->GetAtom1());
6204  MolAtom* const atom2=&(mvpBond[i]->GetAtom2());
6205  for(unsigned int j=1;j<=2;++j)
6206  {
6207  const set<MolAtom*> *pConn;
6208  if(j==1) pConn=&(mConnectivityTable[atom1]);
6209  else pConn=&(mConnectivityTable[atom2]);
6210  mvStretchModeTorsion.push_back(StretchModeTorsion(*atom1,*atom2,0));
6211  mvStretchModeTorsion.back().mvRotatedAtomList.insert(atom1);
6212  mvStretchModeTorsion.back().mvRotatedAtomList.insert(atom2);
6213 
6214  for(set<MolAtom*>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
6215  {
6216  if((*pos==atom2)||(*pos==atom1)) continue;
6218  mvStretchModeTorsion.back().mvRotatedAtomList);
6219  }
6220  mvStretchModeTorsion.back().mvRotatedAtomList.erase(atom1);
6221  mvStretchModeTorsion.back().mvRotatedAtomList.erase(atom2);
6222 
6223  for(vector<MolDihedralAngle*>::const_iterator dih=mvpDihedralAngle.begin();dih!=mvpDihedralAngle.end();++dih)
6224  {
6225  // :TODO: There are some other weird cases to take into account,
6226  // for restraints with atoms *not* connected to another
6227  // More generally, should check the list of atoms rotated.
6228  if( ((&((*dih)->GetAtom2())==atom1) && (&((*dih)->GetAtom3())==atom2))
6229  ||((&((*dih)->GetAtom3())==atom1) && (&((*dih)->GetAtom2())==atom2)))
6230  {
6231  const unsigned long ct1=mvStretchModeTorsion.back().mvRotatedAtomList.count(&((*dih)->GetAtom1()));
6232  const unsigned long ct4=mvStretchModeTorsion.back().mvRotatedAtomList.count(&((*dih)->GetAtom4()));
6233 
6234  if((ct1+ct4)==1)// One of the atom is rotated, not the other
6235  {
6236  mvStretchModeTorsion.back().mpDihedralAngle=*dih;
6237  //:TODO: Check sense of rotation !
6238  if(ct4==1)
6239  {
6240  mvStretchModeTorsion.back().mpAtom1=&((*dih)->GetAtom2());
6241  mvStretchModeTorsion.back().mpAtom2=&((*dih)->GetAtom3());
6242  }
6243  else
6244  {
6245  mvStretchModeTorsion.back().mpAtom1=&((*dih)->GetAtom3());
6246  mvStretchModeTorsion.back().mpAtom2=&((*dih)->GetAtom2());
6247  }
6248  }
6249  }
6250  }
6251 
6252  if(mvStretchModeTorsion.size()>1)
6253  {//Duplicate ?
6254  // Does not work with a const_reverse_iterator ?
6255  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729
6256  list<StretchModeTorsion>::reverse_iterator mode=mvStretchModeTorsion.rbegin();
6257  ++mode;
6258  for(;mode!=mvStretchModeTorsion.rend();++mode)
6259  {
6260  if( ( ((mode->mpAtom1==atom1)&&(mode->mpAtom2==atom2))
6261  ||((mode->mpAtom1==atom2)&&(mode->mpAtom2==atom1)))
6262  &&(mode->mvRotatedAtomList==mvStretchModeTorsion.back().mvRotatedAtomList))
6263  {
6264  #ifdef __DEBUG__
6265  cout<<"Duplicate StretchModeTorsion ";mvStretchModeTorsion.back().Print(cout);cout<<endl;
6266  #endif
6267  mvStretchModeTorsion.pop_back();
6268  }
6269  }
6270  }
6271  if( (mvStretchModeTorsion.back().mvRotatedAtomList.size()>((mvpAtom.size()+1)/2))
6272  ||(mvStretchModeTorsion.back().mvRotatedAtomList.size()==0))
6273  {
6274  #ifdef __DEBUG__
6275  cout<<"Rejecting StretchModeTorsion ";mvStretchModeTorsion.back().Print(cout);cout<<endl;
6276  #endif
6277  mvStretchModeTorsion.pop_back();
6278  }
6279  else if(mvStretchModeTorsion.back().mvRotatedAtomList.size()==((mvpAtom.size()+1)/2))
6280  break;//we translate exactly half of the atoms, so skip the other half
6281  }
6282  }
6283  for(unsigned long i=0;i<mvpBond.size();++i)
6284  {//Single chains
6285  //if((mFlexModel.GetChoice()!=0)&&(false==mvpBond[i]->IsFreeTorsion())) continue;
6286  MolAtom* const atom1=&(mvpBond[i]->GetAtom1());
6287  MolAtom* const atom2=&(mvpBond[i]->GetAtom2());
6288  for(unsigned int j=1;j<=2;++j)
6289  {
6290  const set<MolAtom*> *pConn;
6291  if(j==1) pConn=&(mConnectivityTable[atom1]);
6292  else pConn=&(mConnectivityTable[atom2]);
6293 
6294  for(set<MolAtom*>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
6295  {
6296  if((*pos==atom2)||(*pos==atom1)) continue;
6297  mvStretchModeTorsion.push_back(StretchModeTorsion(*atom1,*atom2,0));
6298  mvStretchModeTorsion.back().mvRotatedAtomList.insert(atom1);
6299  mvStretchModeTorsion.back().mvRotatedAtomList.insert(atom2);
6301  mvStretchModeTorsion.back().mvRotatedAtomList);
6302  mvStretchModeTorsion.back().mvRotatedAtomList.erase(atom1);
6303  mvStretchModeTorsion.back().mvRotatedAtomList.erase(atom2);
6304 
6305  for(vector<MolDihedralAngle*>::const_iterator dih=mvpDihedralAngle.begin();dih!=mvpDihedralAngle.end();++dih)
6306  {
6307  // :TODO: There are some other weird cases to take into account,
6308  // for restraints with atoms *not* connected to another
6309  // More generally, should check the list of atoms rotated.
6310  if( ((&((*dih)->GetAtom2())==atom1) && (&((*dih)->GetAtom3())==atom2))
6311  ||((&((*dih)->GetAtom3())==atom1) && (&((*dih)->GetAtom2())==atom2)))
6312  {
6313  const unsigned long ct1=mvStretchModeTorsion.back().mvRotatedAtomList.count(&((*dih)->GetAtom1()));
6314  const unsigned long ct4=mvStretchModeTorsion.back().mvRotatedAtomList.count(&((*dih)->GetAtom4()));
6315 
6316  if((ct1+ct4)==1)// One of the atom is rotated, not the other
6317  {
6318  mvStretchModeTorsion.back().mpDihedralAngle=*dih;
6319  //:TODO: Check sense of rotation !
6320  if(ct4==1)
6321  {
6322  mvStretchModeTorsion.back().mpAtom1=&((*dih)->GetAtom2());
6323  mvStretchModeTorsion.back().mpAtom2=&((*dih)->GetAtom3());
6324  }
6325  else
6326  {
6327  mvStretchModeTorsion.back().mpAtom1=&((*dih)->GetAtom3());
6328  mvStretchModeTorsion.back().mpAtom2=&((*dih)->GetAtom2());
6329  }
6330  }
6331  }
6332  }
6333 
6334  if(mvStretchModeTorsion.size()>1)
6335  {//Duplicate ?
6336  // Does not work with a const_reverse_iterator ?
6337  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729
6338  list<StretchModeTorsion>::reverse_iterator mode=mvStretchModeTorsion.rbegin();
6339  ++mode;
6340  for(;mode!=mvStretchModeTorsion.rend();++mode)
6341  {
6342  if( ( ((mode->mpAtom1==atom1)&&(mode->mpAtom2==atom2))
6343  ||((mode->mpAtom1==atom2)&&(mode->mpAtom2==atom1)))
6344  &&(mode->mvRotatedAtomList==mvStretchModeTorsion.back().mvRotatedAtomList))
6345  {
6346  #ifdef __DEBUG__
6347  cout<<"Duplicate StretchModeTorsion ";mvStretchModeTorsion.back().Print(cout);cout<<endl;
6348  #endif
6349  mvStretchModeTorsion.pop_back();
6350  break;
6351  }
6352  }
6353  }
6354  if( (mvStretchModeTorsion.back().mvRotatedAtomList.size()>((mvpAtom.size()+1)/2))
6355  ||(mvStretchModeTorsion.back().mvRotatedAtomList.size()==0))
6356  {
6357  #ifdef __DEBUG__
6358  cout<<"Rejecting StretchModeTorsion ";mvStretchModeTorsion.back().Print(cout);cout<<endl;
6359  #endif
6360  mvStretchModeTorsion.pop_back();
6361  }
6362  else if(mvStretchModeTorsion.back().mvRotatedAtomList.size()==((mvpAtom.size()+1)/2))
6363  break;//we translate exactly half of the atoms, so skip the other half
6364  }
6365  }
6366  }
6367  // find rigid groups broken by each mode
6368  for(list<StretchModeTorsion>::iterator pos=mvStretchModeTorsion.begin();
6369  pos!=mvStretchModeTorsion.end();)
6370  {
6371  TAU_PROFILE_START(timer5);
6372  bool keep=true;
6373  for(vector<RigidGroup*>::const_iterator group=mvRigidGroup.begin();
6374  group!=mvRigidGroup.end();++group)
6375  {
6376  unsigned long ct=0;
6377  for(set<MolAtom *>::const_iterator at=(*group)->begin();at!=(*group)->end();++at)
6378  ct += pos->mvRotatedAtomList.count(*at);
6379  if(ct>0)
6380  {
6381  // Add the axis atoms, which do not move relatively to the rotated atoms
6382  ct += (*group)->count(pos->mpAtom1);
6383  ct += (*group)->count(pos->mpAtom2);
6384  if(ct!=(*group)->size())
6385  {
6386  keep=false;
6387  #ifdef __DEBUG__
6388  pos->Print(cout);
6389  cout<<" Breaks Rigid Group:";
6390  for(set<MolAtom *>::const_iterator at=(*group)->begin();at!=(*group)->end();++at)
6391  cout<<(*at)->GetName()<<" ";
6392  cout<<endl;
6393  #endif
6394  break;
6395  }
6396  }
6397  }
6398  if(keep) ++pos;
6399  else pos=mvStretchModeTorsion.erase(pos);
6400  TAU_PROFILE_STOP(timer5);
6401  }
6402  // Generate 5 completely random atomic positions
6403  this->SaveParamSet(mLocalParamSet);
6404  unsigned long paramSetRandom[5];
6405  for(unsigned long i=0;i<5;++i)
6406  {
6407  for(vector<MolAtom*>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
6408  {
6409  (*pos)->SetX(100.*rand()/(REAL) RAND_MAX);
6410  (*pos)->SetY(100.*rand()/(REAL) RAND_MAX);
6411  (*pos)->SetZ(100.*rand()/(REAL) RAND_MAX);
6412  }
6413  paramSetRandom[i]=this->CreateParamSet();
6414  }
6415  // find bond lengths broken by each mode
6416  for(list<StretchModeTorsion>::iterator pos=mvStretchModeTorsion.begin();
6417  pos!=mvStretchModeTorsion.end();)
6418  {
6419  TAU_PROFILE_START(timer2);
6420  bool keep=true;
6421  pos->mvpBrokenBond.clear();
6422  for(vector<MolBond*>::const_iterator r=mvpBond.begin();r!=mvpBond.end();++r)
6423  {
6424  unsigned int ct=0;
6425  for(set<MolAtom *>::const_iterator at=pos->mvRotatedAtomList.begin();
6426  at!=pos->mvRotatedAtomList.end();++at)
6427  {
6428  if(*at==&((*r)->GetAtom1())) ct++;
6429  if(*at==&((*r)->GetAtom2())) ct++;
6430  }
6431  bool broken=true;
6432  // If we moved either both or non of the bond atom, the bond length is unchanged.
6433  if((ct==0)||(ct==2)) broken=false;
6434  if(broken)
6435  {// Make sure with derivatives
6436  REAL d=0;
6437  for(unsigned long i=0;i<5;++i)
6438  {
6439  this->RestoreParamSet(paramSetRandom[i]);
6440  pos->CalcDeriv(false);
6441  (*r)->GetLogLikelihood(true,true);
6442  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6443  if(d>0.01) break;
6444  }
6445  if(abs(d)<=0.01) broken=false;
6446  }
6447  if(broken) pos->mvpBrokenBond.insert(make_pair(*r,0));
6448  }
6449  if(mFlexModel.GetChoice()==2)
6450  {
6451  if(pos->mvpBrokenBond.size()>0) keep=false;
6452  }
6453  if(keep) ++pos;
6454  else pos=mvStretchModeTorsion.erase(pos);
6455  TAU_PROFILE_STOP(timer2);
6456  }
6457  // find bond angles broken by each mode
6458  for(list<StretchModeTorsion>::iterator pos=mvStretchModeTorsion.begin();
6459  pos!=mvStretchModeTorsion.end();)
6460  {
6461  TAU_PROFILE_START(timer3);
6462  bool keep=true;
6463  pos->mvpBrokenBondAngle.clear();
6464  for(vector<MolBondAngle*>::const_iterator r=mvpBondAngle.begin();r!=mvpBondAngle.end();++r)
6465  {
6466  unsigned int ct=0;
6467  for(set<MolAtom *>::const_iterator at=pos->mvRotatedAtomList.begin();
6468  at!=pos->mvRotatedAtomList.end();++at)
6469  {
6470  if(*at==&((*r)->GetAtom1())) ct++;
6471  if(*at==&((*r)->GetAtom2())) ct++;
6472  if(*at==&((*r)->GetAtom3())) ct++;
6473  }
6474  bool broken=true;
6475  if((ct==0)||(ct==3)) broken=false;
6476  if(broken)
6477  {// Make sure with derivatives
6478  REAL d=0;
6479  for(unsigned long i=0;i<5;++i)
6480  {
6481  this->RestoreParamSet(paramSetRandom[i]);
6482  pos->CalcDeriv(false);
6483  (*r)->GetLogLikelihood(true,true);
6484  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6485  if(d>0.01) break;
6486  }
6487  if(abs(d)<=0.01) broken=false;
6488  }
6489  if(broken) pos->mvpBrokenBondAngle.insert(make_pair(*r,0));
6490  }
6491  if(mFlexModel.GetChoice()==2)
6492  {
6493  if(pos->mvpBrokenBond.size()>0) keep=false;
6494  }
6495  if(keep) ++pos;
6496  else pos=mvStretchModeTorsion.erase(pos);
6497  TAU_PROFILE_STOP(timer3);
6498  }
6499  // find dihedral angles broken by each mode
6500  for(list<StretchModeTorsion>::iterator pos=mvStretchModeTorsion.begin();
6501  pos!=mvStretchModeTorsion.end();)
6502  {
6503  TAU_PROFILE_START(timer4);
6504  bool keep=true;
6505  pos->mvpBrokenDihedralAngle.clear();
6506  for(vector<MolDihedralAngle*>::const_iterator r=mvpDihedralAngle.begin();r!=mvpDihedralAngle.end();++r)
6507  {
6508  unsigned int ct=0;
6509  for(set<MolAtom *>::const_iterator at=pos->mvRotatedAtomList.begin();
6510  at!=pos->mvRotatedAtomList.end();++at)
6511  {
6512  if(*at==&((*r)->GetAtom1())) ct++;
6513  if(*at==&((*r)->GetAtom2())) ct++;
6514  if(*at==&((*r)->GetAtom3())) ct++;
6515  if(*at==&((*r)->GetAtom4())) ct++;
6516  }
6517  bool broken=true;
6518  if((ct==0)||(ct==4)) broken=false;
6519  if(broken)
6520  {// Make sure with derivatives
6521  REAL d=0;
6522  for(unsigned long i=0;i<5;++i)
6523  {
6524  this->RestoreParamSet(paramSetRandom[i]);
6525  pos->CalcDeriv(false);
6526  (*r)->GetLogLikelihood(true,true);
6527  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6528  if(d>0.01) break;
6529  }
6530  if(abs(d)<=0.01) broken=false;
6531  }
6532  if(broken) pos->mvpBrokenDihedralAngle.insert(make_pair(*r,0));
6533  }
6534  if(mFlexModel.GetChoice()==2)
6535  {
6536  int nb=pos->mvpBrokenDihedralAngle.size();
6537  if(pos->mpDihedralAngle!=0) nb -= 1;
6538  if(nb>0) keep=false;
6539  }
6540  if(keep) ++pos;
6541  else pos=mvStretchModeTorsion.erase(pos);
6542  TAU_PROFILE_STOP(timer4);
6543  }
6544 
6545  for(unsigned long i=0;i<5;++i) this->ClearParamSet(paramSetRandom[i]);
6546  this->RestoreParamSet(mLocalParamSet);
6547 
6548  #ifdef __DEBUG__
6549  cout<<"List of Dihedral Angle stretch modes("<<mvStretchModeTorsion.size()<<")"<<endl;
6550  for(list<StretchModeTorsion>::const_iterator pos=mvStretchModeTorsion.begin();
6551  pos!=mvStretchModeTorsion.end();++pos)
6552  {
6553  cout<<" Dihedral Angle:"
6554  <<pos->mpAtom1->GetName()<<"-"
6555  <<pos->mpAtom2->GetName()<<", Rotated Atoms: ";
6556  for(set<MolAtom*>::const_iterator atom=pos->mvRotatedAtomList.begin();
6557  atom!=pos->mvRotatedAtomList.end();++atom)
6558  {
6559  cout<<(*atom)->GetName()<<",";
6560  }
6561  if(pos->mpDihedralAngle!=0)
6562  cout<<endl<< " ->restrained by dihedral angle "<<pos->mpDihedralAngle->GetName()
6563  <<"to :"<<pos->mpDihedralAngle->GetAngle0()*RAD2DEG
6564  <<"�, sigma="<<pos->mpDihedralAngle->GetAngleSigma()*RAD2DEG
6565  <<"�, delta="<<pos->mpDihedralAngle->GetAngleDelta()*RAD2DEG<<"�";
6566  if(pos->mvpBrokenBond.size()>0)
6567  {
6568  cout<<endl<<" Broken bonds:";
6569  for(map<const MolBond*,REAL>::const_iterator bond=pos->mvpBrokenBond.begin();
6570  bond!=pos->mvpBrokenBond.end();++bond)
6571  cout<<bond->first->GetName()<<", ";
6572  }
6573  if(pos->mvpBrokenBondAngle.size()>0)
6574  {
6575  cout<<endl<<" Broken bond angles:";
6576  for(map<const MolBondAngle*,REAL>::const_iterator angle=pos->mvpBrokenBondAngle.begin();
6577  angle!=pos->mvpBrokenBondAngle.end();++angle)
6578  cout<<angle->first->GetName()<<", ";
6579  }
6580  if(pos->mvpBrokenDihedralAngle.size()>0)
6581  {
6582  cout<<endl<<" Broken dihedral angles:";
6583  for(map<const MolDihedralAngle*,REAL>::const_iterator
6584  angle=pos->mvpBrokenDihedralAngle.begin();
6585  angle!=pos->mvpBrokenDihedralAngle.end();++angle)
6586  cout<<angle->first->GetName()<<", ";
6587  }
6588  cout<<endl;
6589  }
6590  #endif
6591  mClockStretchModeTorsion.Click();
6592  VFN_DEBUG_EXIT("Molecule::BuildStretchModeTorsion()",7)
6593 }
6594 
6596 {
6597  #if 0
6598  if( (mClockStretchModeTwist>mClockBondList)
6599  &&(mClockStretchModeTwist>mClockAtomList)
6600  &&(mClockStretchModeTwist>mClockBondAngleList)
6601  &&(mClockStretchModeTwist>mClockDihedralAngleList)) return;
6602  #endif
6603  VFN_DEBUG_ENTRY("Molecule::BuildStretchModeTwist()",7)
6604  this->BuildConnectivityTable();
6605  mvStretchModeTwist.clear();
6606 
6607  // For each pair of atoms, build an internal chain to twist.
6608  for(vector<MolAtom*>::const_iterator atom1=this->GetAtomList().begin();
6609  atom1!=this->GetAtomList().end();++atom1)
6610  {
6611  const set<MolAtom*> *pConn=&(mConnectivityTable[*atom1]);
6612  vector<MolAtom*>::const_iterator atom2=atom1;
6613  atom2++;
6614  for(;atom2!=this->GetAtomList().end();++atom2)
6615  {
6616  for(set<MolAtom*>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
6617  {// Start from one atom connected to atom1
6618  if(*pos==*atom2) continue;
6619  mvStretchModeTwist.push_back(StretchModeTwist(**atom1,**atom2));
6620  mvStretchModeTwist.back().mvRotatedAtomList.insert(*atom1);
6622  mvStretchModeTwist.back().mvRotatedAtomList,
6623  *atom2);
6624  //Check if this chains actually leads to atom2
6625  set<MolAtom*>::const_iterator check
6626  =find(mvStretchModeTwist.back().mvRotatedAtomList.begin(),
6627  mvStretchModeTwist.back().mvRotatedAtomList.end(),*atom2);
6628  bool keep =true;
6629  if( (check==mvStretchModeTwist.back().mvRotatedAtomList.end())
6630  ||(mvStretchModeTwist.back().mvRotatedAtomList.size()<3)
6631  ||(mvStretchModeTwist.back().mvRotatedAtomList.size()>=((mvpAtom.size()+1)/2)))
6632  {
6633  keep=false;
6634  }
6635  if(keep)
6636  {
6637  mvStretchModeTwist.back().mvRotatedAtomList.erase(*atom1);
6638  mvStretchModeTwist.back().mvRotatedAtomList.erase(*atom2);
6639  if( (mvStretchModeTwist.back().mvRotatedAtomList.size()>=(mvpAtom.size()/2))
6640  ||(mvStretchModeTwist.back().mvRotatedAtomList.size()==0))
6641  {
6642  #ifdef __DEBUG__
6643  cout<<"Rejecting StretchModeTwist ";mvStretchModeTwist.back().Print(cout);cout<<endl;
6644  #endif
6645  keep=false;
6646  }
6647  }
6648  if(keep)
6649  {
6650  if(mvStretchModeTwist.size()>1)
6651  {//Duplicate ?
6652  // Does not work with a const_reverse_iterator ?
6653  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729
6654  list<StretchModeTwist>::reverse_iterator mode=mvStretchModeTwist.rbegin();
6655  ++mode;
6656  for(;mode!=mvStretchModeTwist.rend();++mode)
6657  {
6658  if( ( ((mode->mpAtom1==*atom1)&&(mode->mpAtom2==*atom2))
6659  ||((mode->mpAtom1==*atom2)&&(mode->mpAtom2==*atom1)))
6660  &&(mode->mvRotatedAtomList==mvStretchModeTwist.back().mvRotatedAtomList))
6661  {
6662  #ifdef __DEBUG__
6663  cout<<"Duplicate StretchModeTwist ";mvStretchModeTwist.back().Print(cout);cout<<endl;
6664  #endif
6665  keep=false;
6666  }
6667  if(!keep) break;
6668  }
6669  }
6670  }
6671  if(keep)
6672  {
6673  if(mvStretchModeTorsion.size()>0) // Torsion and twist modes can be identical for cycles.
6674  {//Duplicate ?
6675  // Does not work with a const_reverse_iterator ?
6676  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729
6677  list<StretchModeTorsion>::reverse_iterator mode;
6678  for(mode=mvStretchModeTorsion.rbegin();mode!=mvStretchModeTorsion.rend();++mode)
6679  {
6680  if( ( ((mode->mpAtom1==*atom1)&&(mode->mpAtom2==*atom2))
6681  ||((mode->mpAtom1==*atom2)&&(mode->mpAtom2==*atom1)))
6682  &&(mode->mvRotatedAtomList==mvStretchModeTwist.back().mvRotatedAtomList))
6683  {
6684  #ifdef __DEBUG__
6685  cout<<"Duplicate StretchModeTwist (with Torsion) ";mvStretchModeTwist.back().Print(cout);cout<<endl;
6686  #endif
6687  keep=false;
6688  }
6689  if(!keep) break;
6690  }
6691  }
6692  }
6693  if(!keep) mvStretchModeTwist.pop_back();
6694  }
6695  }
6696 
6697  }
6698  // Generate 5 completely random atomic positions
6699  this->SaveParamSet(mLocalParamSet);
6700  unsigned long paramSetRandom[5];
6701  for(unsigned long i=0;i<5;++i)
6702  {
6703  for(vector<MolAtom*>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
6704  {
6705  (*pos)->SetX(100.*rand()/(REAL) RAND_MAX);
6706  (*pos)->SetY(100.*rand()/(REAL) RAND_MAX);
6707  (*pos)->SetZ(100.*rand()/(REAL) RAND_MAX);
6708  }
6709  paramSetRandom[i]=this->CreateParamSet();
6710  }
6711  // find bond, bond angles and dihedral angles broken by each mode
6712  for(list<StretchModeTwist>::iterator pos=mvStretchModeTwist.begin();
6713  pos!=mvStretchModeTwist.end();)
6714  {
6715  pos->mvpBrokenBond.clear();
6716  pos->mvpBrokenBondAngle.clear();
6717  pos->mvpBrokenDihedralAngle.clear();
6718  pos->CalcDeriv();
6719  #ifdef __DEBUG__
6720  cout<<" DerivLLK for Twist mode around:"
6721  <<pos->mpAtom1->GetName()<<"-"
6722  <<pos->mpAtom2->GetName()<<": Moving atoms:";
6723  for(set<MolAtom*>::const_iterator atom=pos->mvRotatedAtomList.begin();
6724  atom!=pos->mvRotatedAtomList.end();++atom)
6725  cout<<(*atom)->GetName()<<",";
6726  cout<<endl;
6727  #endif
6728  for(vector<MolBond*>::const_iterator r=mvpBond.begin();r!=mvpBond.end();++r)
6729  {
6730  (*r)->GetLogLikelihood(true,true);
6731  REAL d=0;
6732  for(unsigned long i=0;i<5;++i)
6733  {
6734  this->RestoreParamSet(paramSetRandom[i]);
6735  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6736  }
6737  if(abs(d)>0.1)
6738  {
6739  #ifdef __DEBUG__
6740  cout<<" Bond "<<(*r)->GetName()
6741  <<": dLength/da="<<d<<endl;
6742  #endif
6743  pos->mvpBrokenBond.insert(make_pair(*r,0.0));
6744  }
6745  }
6746  for(vector<MolBondAngle*>::const_iterator r=mvpBondAngle.begin();r!=mvpBondAngle.end();++r)
6747  {
6748  (*r)->GetLogLikelihood(true,true);
6749  REAL d=0;
6750  for(unsigned long i=0;i<5;++i)
6751  {
6752  this->RestoreParamSet(paramSetRandom[i]);
6753  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6754  }
6755  if(abs(d)>0.01)
6756  {
6757  #ifdef __DEBUG__
6758  cout<<" BondAngle:"<<(*r)->GetName()<<": dAngle/da="<<d<<endl;
6759  #endif
6760  pos->mvpBrokenBondAngle.insert(make_pair(*r,0.0));
6761  }
6762  }
6763  for(vector<MolDihedralAngle*>::const_iterator r=mvpDihedralAngle.begin();
6764  r!=mvpDihedralAngle.end();++r)
6765  {
6766  //if(*r==pos->mpDihedralAngle) continue;
6767  (*r)->GetLogLikelihood(true,true);
6768  REAL d=0;
6769  for(unsigned long i=0;i<5;++i)
6770  {
6771  this->RestoreParamSet(paramSetRandom[i]);
6772  d += abs((*r)->GetDeriv(pos->mDerivXYZ));
6773  }
6774  if(abs(d)>0.01)
6775  {
6776  #ifdef __DEBUG__
6777  cout<<" DihedralAngle:"<<(*r)->GetName()<<": dAngle/da="<<d<<endl;
6778  #endif
6779  pos->mvpBrokenDihedralAngle.insert(make_pair(*r,0.0));
6780  }
6781  }
6782  //Get rid of stretch modes that break rigid groups
6783  bool keep=true;
6784  for(vector<RigidGroup*>::const_iterator group=mvRigidGroup.begin();
6785  group!=mvRigidGroup.end();++group)
6786  {
6787  unsigned long ct=0;
6788  for(set<MolAtom *>::const_iterator at=(*group)->begin();at!=(*group)->end();++at)
6789  ct += pos->mvRotatedAtomList.count(*at);
6790  if(ct>0)
6791  {
6792  // Add atom1 and atom2 to the count only if they are in the group
6793  // They do not move in absolute or relatively to the group.
6794  ct += (*group)->count(pos->mpAtom1);
6795  ct += (*group)->count(pos->mpAtom2);
6796  if(ct!=(*group)->size())
6797  {
6798  keep=false;
6799  #ifdef __DEBUG__
6800  cout<<" Breaks Rigid Group:"<<ct<<"!="<<(*group)->size()<<":";
6801  for(set<MolAtom *>::const_iterator at=(*group)->begin();at!=(*group)->end();++at)
6802  cout<<(*at)->GetName()<<" ";
6803  cout<<endl;
6804  #endif
6805  break;
6806  }
6807  }
6808  }
6809  if(mFlexModel.GetChoice()==2)
6810  {
6811  if(pos->mvpBrokenBond.size()+pos->mvpBrokenBondAngle.size()+pos->mvpBrokenDihedralAngle.size()) keep=false;
6812  }
6813  if(keep) ++pos;
6814  else pos=mvStretchModeTwist.erase(pos);
6815  }
6816  for(unsigned long i=0;i<5;++i) this->ClearParamSet(paramSetRandom[i]);
6817  this->RestoreParamSet(mLocalParamSet);
6818 
6819  #ifdef __DEBUG__
6820  cout<<"List of Twist stretch modes("<<mvStretchModeTwist.size()<<")"<<endl;
6821  for(list<StretchModeTwist>::const_iterator pos=mvStretchModeTwist.begin();
6822  pos!=mvStretchModeTwist.end();++pos)
6823  {
6824  cout<<" Twist mode:"
6825  <<pos->mpAtom1->GetName()<<"-"
6826  <<pos->mpAtom2->GetName()<<", Rotated Atoms: ";
6827  for(set<MolAtom*>::const_iterator atom=pos->mvRotatedAtomList.begin();
6828  atom!=pos->mvRotatedAtomList.end();++atom)
6829  {
6830  cout<<(*atom)->GetName()<<",";
6831  }
6832  if(pos->mvpBrokenBond.size()>0)
6833  {
6834  cout<<endl<<" Broken bonds:";
6835  for(map<const MolBond*,REAL>::const_iterator bond=pos->mvpBrokenBond.begin();
6836  bond!=pos->mvpBrokenBond.end();++bond)
6837  cout<<bond->first->GetName()<<", ";
6838  }
6839  if(pos->mvpBrokenBondAngle.size()>0)
6840  {
6841  cout<<endl<<" Broken bond angles:";
6842  for(map<const MolBondAngle*,REAL>::const_iterator angle=pos->mvpBrokenBondAngle.begin();
6843  angle!=pos->mvpBrokenBondAngle.end();++angle)
6844  cout<<angle->first->GetName()<<", ";
6845  }
6846  if(pos->mvpBrokenDihedralAngle.size()>0)
6847  {
6848  cout<<endl<<" Broken dihedral angles:";
6849  for(map<const MolDihedralAngle*,REAL>::const_iterator
6850  angle=pos->mvpBrokenDihedralAngle.begin();
6851  angle!=pos->mvpBrokenDihedralAngle.end();++angle)
6852  cout<<angle->first->GetName()<<", ";
6853  }
6854  cout<<endl;
6855  }
6856  #endif
6857  mClockStretchModeTwist.Click();
6858  VFN_DEBUG_EXIT("Molecule::BuildStretchModeTwist()",7)
6859 }
6860 
6862 {
6863  VFN_DEBUG_ENTRY("Molecule::TuneGlobalOptimRotationAmplitude()",5)
6864  unsigned long initialConfig=this->CreateParamSet("Initial Configuration");
6865  const unsigned int nbTest=100;
6866 
6867  // First we store in mBaseRotationAmplitude the cumulated atomic displacement
6868  // for nbTest rotations of 0.01 rad
6869  for(list<StretchModeBondAngle>::iterator pos=mvStretchModeBondAngle.begin();
6870  pos!=mvStretchModeBondAngle.end();++pos) pos->mBaseAmplitude=0;
6871  for(list<StretchModeTorsion>::iterator pos=mvStretchModeTorsion.begin();
6872  pos!=mvStretchModeTorsion.end();++pos) pos->mBaseAmplitude=0;
6873 
6874  REAL displacement=0;//For the global Molecule rotation
6875 
6876  for(unsigned int j=0;j<nbTest;j++)
6877  {
6878  this->RandomizeConfiguration();
6879  // Atomic positions, orthonormal coordinates
6880  vector<REAL> x0(this->GetNbComponent());
6881  vector<REAL> y0(this->GetNbComponent());
6882  vector<REAL> z0(this->GetNbComponent());
6883  // Center of molecule coords
6884  REAL xc=0.,yc=0.,zc=0.;
6885  for(long i=0;i<this->GetNbComponent();++i)
6886  {
6887  x0[i]=mvpAtom[i]->GetX(); xc += x0[i];
6888  y0[i]=mvpAtom[i]->GetY(); yc += y0[i];
6889  z0[i]=mvpAtom[i]->GetZ(); zc += z0[i];
6890  }
6891  xc /= (REAL)(this->GetNbComponent());
6892  yc /= (REAL)(this->GetNbComponent());
6893  zc /= (REAL)(this->GetNbComponent());
6894  // Record displacement amplitude for torsion angles
6895  REAL dx,dy,dz;
6896  for(list<StretchModeBondAngle>::iterator pos=mvStretchModeBondAngle.begin();
6897  pos!=mvStretchModeBondAngle.end();++pos)
6898  {
6899  const REAL dx10=pos->mpAtom0->GetX()-pos->mpAtom1->GetX();
6900  const REAL dy10=pos->mpAtom0->GetY()-pos->mpAtom1->GetY();
6901  const REAL dz10=pos->mpAtom0->GetZ()-pos->mpAtom1->GetZ();
6902  const REAL dx12=pos->mpAtom2->GetX()-pos->mpAtom1->GetX();
6903  const REAL dy12=pos->mpAtom2->GetY()-pos->mpAtom1->GetY();
6904  const REAL dz12=pos->mpAtom2->GetZ()-pos->mpAtom1->GetZ();
6905 
6906  const REAL vx=dy10*dz12-dz10*dy12;
6907  const REAL vy=dz10*dx12-dx10*dz12;
6908  const REAL vz=dx10*dy12-dy10*dx12;
6909  this->RotateAtomGroup(*(pos->mpAtom1),vx,vy,vz,pos->mvRotatedAtomList,0.01,false);
6910  for(long i=0;i<this->GetNbComponent();++i)
6911  {
6912  dx=x0[i]-mvpAtom[i]->GetX();
6913  dy=y0[i]-mvpAtom[i]->GetY();
6914  dz=z0[i]-mvpAtom[i]->GetZ();
6915  pos->mBaseAmplitude+=sqrt(abs(dx*dx+dy*dy+dz*dz));
6916  }
6917  this->RotateAtomGroup(*(pos->mpAtom1),vx,vy,vz,pos->mvRotatedAtomList,-0.01,false);
6918  }
6919  for(list<StretchModeTorsion>::iterator pos=mvStretchModeTorsion.begin();
6920  pos!=mvStretchModeTorsion.end();++pos)
6921  {
6922  this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),pos->mvRotatedAtomList,0.01,false);
6923  for(long i=0;i<this->GetNbComponent();++i)
6924  {
6925  dx=x0[i]-mvpAtom[i]->GetX();
6926  dy=y0[i]-mvpAtom[i]->GetY();
6927  dz=z0[i]-mvpAtom[i]->GetZ();
6928  pos->mBaseAmplitude+=sqrt(abs(dx*dx+dy*dy+dz*dz));
6929  }
6930  this->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),pos->mvRotatedAtomList,-0.01,false);
6931  }
6932  // Record displacement amplitude for global rotation, for 10 random rot axis
6933  for(unsigned int k=0;k<10;++k)
6934  {
6935  Quaternion quat=Quaternion::RotationQuaternion
6936  (mBaseRotationAmplitude,(REAL)rand(),(REAL)rand(),(REAL)rand());
6937  for(long i=0;i<this->GetNbComponent();++i)
6938  {
6939  REAL x=x0[i]-xc;
6940  REAL y=y0[i]-yc;
6941  REAL z=z0[i]-zc;
6942  quat.RotateVector(x,y,z);
6943  dx=(x0[i]-xc)-x;
6944  dy=(y0[i]-yc)-y;
6945  dz=(z0[i]-zc)-z;
6946  displacement+=sqrt(abs(dx*dx+dy*dy+dz*dz));
6947  }
6948  }
6949  }
6950  // Modify base rotation amplitudes, for an average 0.02 Angstroem displacement
6951  for(list<StretchModeBondAngle>::iterator pos=mvStretchModeBondAngle.begin();
6952  pos!=mvStretchModeBondAngle.end();++pos)
6953  {
6954  pos->mBaseAmplitude/=(REAL)(nbTest*this->GetNbComponent());//(REAL)(nbTest*(0.5*pos->mvRotatedAtomList.size()+0.5*this->GetNbComponent()));
6955  pos->mBaseAmplitude=0.1*0.01/pos->mBaseAmplitude;
6956  if(pos->mBaseAmplitude>.17) pos->mBaseAmplitude=.17;
6957  bool free=true;
6958  if((pos->mvpBrokenBond.size()+pos->mvpBrokenBondAngle.size()+pos->mvpBrokenDihedralAngle.size())>0)
6959  {
6960  pos->mBaseAmplitude/=10;
6961  free=false;
6962  }
6963  #if 1// def __DEBUG__
6964  cout<<"ANGLE :"
6965  <<pos->mpAtom0->GetName()<<"-"
6966  <<pos->mpAtom1->GetName()<<"-"
6967  <<pos->mpAtom2->GetName()<<":";
6968  for(set<MolAtom*>::const_iterator atom=pos->mvRotatedAtomList.begin();
6969  atom!=pos->mvRotatedAtomList.end();++atom) cout<<(*atom)->GetName()<<",";
6970  cout <<": base rotation="<<pos->mBaseAmplitude*RAD2DEG<<" free="<<free<<endl;
6971  #endif
6972  }
6973  // Modify base rotation amplitudes, for an average 0.1 Angstroem displacement
6974  for(list<StretchModeTorsion>::iterator pos=mvStretchModeTorsion.begin();
6975  pos!=mvStretchModeTorsion.end();++pos)
6976  {
6977  pos->mBaseAmplitude/=(REAL)(nbTest*this->GetNbComponent());//(REAL)(nbTest*(0.5*pos->mvRotatedAtomList.size()+0.5*this->GetNbComponent()));
6978  pos->mBaseAmplitude=0.1*0.01/pos->mBaseAmplitude;
6979  if(pos->mBaseAmplitude>.17) pos->mBaseAmplitude=.17;
6980  bool free=true;
6981  if((pos->mvpBrokenBond.size()+pos->mvpBrokenBondAngle.size()+pos->mvpBrokenDihedralAngle.size())>0)
6982  {
6983  pos->mBaseAmplitude/=10;
6984  free=false;
6985  }
6986  #if 1// def __DEBUG__
6987  cout<<"TORSION :"
6988  <<pos->mpAtom1->GetName()<<"-"
6989  <<pos->mpAtom2->GetName()<<":";
6990  for(set<MolAtom*>::const_iterator atom=pos->mvRotatedAtomList.begin();
6991  atom!=pos->mvRotatedAtomList.end();++atom) cout<<(*atom)->GetName()<<",";
6992  cout <<": base rotation="<<pos->mBaseAmplitude*RAD2DEG<<" free="<<free<<endl;
6993  #endif
6994  }
6995  // Modify base rotation amplitudes of twist modes, for an average 0.1 Angstroem displacement
6996  for(list<StretchModeTwist>::iterator pos=mvStretchModeTwist.begin();
6997  pos!=mvStretchModeTwist.end();++pos)
6998  {
6999  pos->mBaseAmplitude/=(REAL)(nbTest*this->GetNbComponent());//(REAL)(nbTest*(0.5*pos->mvRotatedAtomList.size()+0.5*this->GetNbComponent()));
7000  pos->mBaseAmplitude=0.1*0.01/pos->mBaseAmplitude;
7001  if(pos->mBaseAmplitude>.17) pos->mBaseAmplitude=.17;
7002  bool free=true;
7003  if((pos->mvpBrokenBond.size()+pos->mvpBrokenBondAngle.size()+pos->mvpBrokenDihedralAngle.size())>0)
7004  {
7005  pos->mBaseAmplitude/=10;
7006  free=false;
7007  }
7008  #if 1// def __DEBUG__
7009  cout<<"TWIST :"
7010  <<pos->mpAtom1->GetName()<<"-"
7011  <<pos->mpAtom2->GetName()<<":";
7012  for(set<MolAtom*>::const_iterator atom=pos->mvRotatedAtomList.begin();
7013  atom!=pos->mvRotatedAtomList.end();++atom) cout<<(*atom)->GetName()<<",";
7014  cout <<": base rotation="<<pos->mBaseAmplitude*RAD2DEG<<" free="<<free<<endl;
7015  #endif
7016  }
7017  // Same for global rotation
7018  displacement/=(REAL)(10*nbTest*this->GetNbComponent());
7019  //cout<<"Overall Atomic Displacement for Global Rotation:<d>="<<displacement;
7020  if(displacement>0) mBaseRotationAmplitude*=0.1/displacement;
7021  if(mBaseRotationAmplitude<(0.02*M_PI/20.))
7022  {
7023  mBaseRotationAmplitude=0.02*M_PI/20.;
7024  //cout <<"WARNING - too low Global BaseRotationAmplitude - setting to: "
7025  // << mBaseAmplitude*RAD2DEG<< " �"<<endl;
7026  }
7027  if(mBaseRotationAmplitude>(0.02*M_PI*20.))
7028  {
7029  mBaseRotationAmplitude=0.02*M_PI*20.;
7030  //cout <<"WARNING - too high Global BaseRotationAmplitude - setting to: "
7031  // << mBaseAmplitude*RAD2DEG<< " �"<<endl;
7032  }
7033  //cout <<" -> Base rotation="<<mBaseAmplitude*RAD2DEG<<"�"<<endl;
7034 
7035  // Move back atoms to initial position
7036  this->RestoreParamSet(initialConfig);
7037  VFN_DEBUG_EXIT("Molecule::TuneGlobalOptimRotationAmplitude()",5)
7038 }
7039 
7041 {
7042  this->BuildConnectivityTable();
7043  if( (mClockFlipGroup>mClockConnectivityTable)
7044  &&(mClockFlipGroup>mClockRigidGroup)) return;
7045  VFN_DEBUG_ENTRY("Molecule::BuildFlipGroup()",5)
7046  TAU_PROFILE("Molecule::BuildFlipGroup()","void ()",TAU_DEFAULT);
7047  mvFlipGroup.clear();
7048 
7049  for(vector<MolAtom*>::const_iterator atom0=this->GetAtomList().begin();
7050  atom0!=this->GetAtomList().end();++atom0)
7051  {
7052  const set<MolAtom*> *pConn=&(mConnectivityTable[*atom0]);
7053  if(pConn->size()<3) continue;
7054  // Build all chains
7055  for(set<MolAtom*>::const_iterator pos1=pConn->begin();pos1!=pConn->end();++pos1)
7056  {
7057  for(set<MolAtom*>::const_iterator pos2=pos1;pos2!=pConn->end();++pos2)
7058  {
7059  if(*pos2==*pos1) continue;
7060  if(mFlexModel.GetChoice()==0)
7061  {
7062  mvFlipGroup.push_back(FlipGroup(**atom0,**pos1,**pos2));
7063  bool foundRing=false;
7064  for(set<MolAtom*>::const_iterator pos=pConn->begin();pos!=pConn->end();++pos)
7065  {
7066  if((pos==pos1)||(pos==pos2)) continue;
7067  mvFlipGroup.back().mvRotatedChainList.push_back(
7068  make_pair(*pos,set<MolAtom*>()));
7069  mvFlipGroup.back().mvRotatedChainList.back().second.insert(*atom0);
7071  mvFlipGroup.back().mvRotatedChainList.back().second);
7072  mvFlipGroup.back().mvRotatedChainList.back().second.erase(*atom0);
7073  set<MolAtom*>::const_iterator ringdetect1,ringdetect2;
7074  ringdetect1=find(mvFlipGroup.back().mvRotatedChainList.back().second.begin(),
7075  mvFlipGroup.back().mvRotatedChainList.back().second.end(),
7076  *pos1);
7077  ringdetect2=find(mvFlipGroup.back().mvRotatedChainList.back().second.begin(),
7078  mvFlipGroup.back().mvRotatedChainList.back().second.end(),
7079  *pos2);
7080  if( (ringdetect1!=mvFlipGroup.back().mvRotatedChainList.back().second.end())
7081  ||(ringdetect2!=mvFlipGroup.back().mvRotatedChainList.back().second.end()))
7082  foundRing=true;
7083  }
7084  unsigned long flipSize=0;
7085  for(list<pair<const MolAtom *,set<MolAtom*> > >::const_iterator
7086  chain=mvFlipGroup.back().mvRotatedChainList.begin();
7087  chain!=mvFlipGroup.back().mvRotatedChainList.end();++chain)
7088  flipSize+=chain->second.size();
7089 
7090  if(((flipSize*2)>mvpAtom.size())||foundRing) mvFlipGroup.pop_back();
7091  }
7092  // Add the entry which will exchange atom1 and atom2 (this entry can be a ring)
7093  mvFlipGroup.push_back(FlipGroup(**atom0,**pos1,**pos2));
7094  mvFlipGroup.back().mvRotatedChainList.push_back(
7095  make_pair(*atom0,set<MolAtom*>()));
7096  mvFlipGroup.back().mvRotatedChainList.back().second.insert(*atom0);
7098  mvFlipGroup.back().mvRotatedChainList.back().second);
7100  mvFlipGroup.back().mvRotatedChainList.back().second);
7101  mvFlipGroup.back().mvRotatedChainList.back().second.erase(*atom0);
7102  if((mvFlipGroup.back().mvRotatedChainList.back().second.size()*2)>mvpAtom.size())
7103  mvFlipGroup.pop_back();
7104  }
7105  }
7106  }
7107  // Exclude flip groups that include only a part of any rigid group
7108  for(list<FlipGroup>::iterator pos=mvFlipGroup.begin(); pos!=mvFlipGroup.end();)
7109  {
7110  // This should not be necessary ? Why keep one list for each chain, and not one big ?
7111  set<MolAtom*> fullset;
7112  for(list<pair<const MolAtom *,set<MolAtom *> > >::iterator chain=pos->mvRotatedChainList.begin();
7113  chain!=pos->mvRotatedChainList.end();++chain)
7114  for(set<MolAtom *>::const_iterator at=chain->second.begin();at!=chain->second.end();++at)
7115  fullset.insert(*at);
7116 
7117  bool keep=true;
7118  for(vector<RigidGroup*>::const_iterator group=mvRigidGroup.begin(); group!=mvRigidGroup.end();++group)
7119  {
7120  unsigned long ct=0;
7121  for(set<MolAtom *>::const_iterator at=fullset.begin();at!=fullset.end();++at)
7122  ct+=(*group)->count(*at);
7123 
7124  if((ct>0)&&(ct<(*group)->size())) {keep=false; break;}
7125  }
7126 
7127  if(!keep)
7128  {
7129  cout <<"EXCLUDING flip group (breaking a rigid group): "
7130  <<pos->mpAtom0->GetName()<<",exchanging bonds with "
7131  <<pos->mpAtom1->GetName()<<" and "
7132  <<pos->mpAtom2->GetName()<<", resulting in a 180deg rotation of atoms : ";
7133  for(set<MolAtom*>::iterator pos1=pos->mvRotatedChainList.begin()->second.begin();
7134  pos1!=pos->mvRotatedChainList.begin()->second.end();++pos1)
7135  cout<<(*pos1)->GetName()<<" ";
7136 
7137  pos=mvFlipGroup.erase(pos);
7138  }
7139  else pos++;
7140  }
7141  //Exclude flip groups where the central atom is in the non-flip atom list
7142  for(list<FlipGroup>::iterator pos=mvFlipGroup.begin(); pos!=mvFlipGroup.end();)
7143  {
7144  bool erase = false;
7145  for(size_t i = 0; i < mvNonFlipAtom.size(); i++) {
7146  if(pos->mpAtom0->GetName().compare(mvNonFlipAtom[i]->GetName())==0) {
7147  erase = true;
7148  break;
7149  }
7150  }
7151  if(erase) {
7152  cout <<"EXCLUDING flip group (central atom is in the non-flip list)"<<endl;
7153  pos=mvFlipGroup.erase(pos);
7154  } else {
7155  pos++;
7156  }
7157  }
7158  // List them
7159  this->SaveParamSet(mLocalParamSet);
7160  #if 1//def __DEBUG__
7161  // const REAL llk0=this->GetLogLikelihood();
7162  for(list<FlipGroup>::iterator pos=mvFlipGroup.begin();
7163  pos!=mvFlipGroup.end();++pos)
7164  {
7165  if(pos->mvRotatedChainList.begin()->first==pos->mpAtom0)
7166  {
7167  cout <<"Flip group from atom "
7168  <<pos->mpAtom0->GetName()<<",exchanging bonds with "
7169  <<pos->mpAtom1->GetName()<<" and "
7170  <<pos->mpAtom2->GetName()<<", resulting in a 180� rotation of atoms : ";
7171  for(set<MolAtom*>::iterator pos1=pos->mvRotatedChainList.begin()->second.begin();
7172  pos1!=pos->mvRotatedChainList.begin()->second.end();++pos1)
7173  cout<<(*pos1)->GetName()<<" ";
7174  }
7175  else
7176  {
7177  cout <<"Flip group with respect to: "
7178  <<pos->mpAtom1->GetName()<<"-"
7179  <<pos->mpAtom0->GetName()<<"-"
7180  <<pos->mpAtom2->GetName()<<" : ";
7181  for(list<pair<const MolAtom *,set<MolAtom*> > >::const_iterator
7182  chain=pos->mvRotatedChainList.begin();
7183  chain!=pos->mvRotatedChainList.end();++chain)
7184  {
7185  cout<<" -"<<chain->first->GetName()<<":";
7186  for(set<MolAtom*>::const_iterator pos1=chain->second.begin();
7187  pos1!=chain->second.end();++pos1)
7188  cout<<(*pos1)->GetName()<<" ";
7189  }
7190  }
7191  #if 0
7192  // test if they do not break something (dihedral angle restraint) ?
7193  // We seldom try flippping, so don't test - test is done during optimization
7194  this->FlipAtomGroup(*pos);
7195  const REAL dllk=this->GetLogLikelihood()-llk0;
7196  if(dllk>1000.)
7197  {
7198  pos = mvFlipGroup.erase(pos);
7199  --pos;
7200  cout <<" -> NOT a free flip, d(llk)="<<dllk;
7201  this->RestraintStatus(cout);
7202  }
7203  else cout <<" -> free flip, d(llk)="<<dllk;
7204  this->RestoreParamSet(mLocalParamSet);
7205  #endif
7206  cout<<endl;
7207  }
7208  #endif
7209  mClockFlipGroup.Click();
7210  VFN_DEBUG_EXIT("Molecule::BuildFlipGroup()",5)
7211 }
7212 
7214 {
7215  // Assume Stretch modes have already been built
7216  map<const MolBond*, set<const StretchMode*> > vpBond;
7217  for(list<StretchModeBondLength>::const_iterator mode=mvStretchModeBondLength.begin();
7218  mode!=mvStretchModeBondLength.end();++mode)
7219  {
7220  if(mode->mpBond!=0) vpBond[mode->mpBond].insert(&(*mode));
7221  for(map<const MolBond*,REAL>::const_iterator pos=mode->mvpBrokenBond.begin();
7222  pos!=mode->mvpBrokenBond.end();++pos)
7223  vpBond[pos->first].insert(&(*mode));
7224  }
7225  for(list<StretchModeBondAngle>::const_iterator mode=mvStretchModeBondAngle.begin();
7226  mode!=mvStretchModeBondAngle.end();++mode)
7227  for(map<const MolBond*,REAL>::const_iterator pos=mode->mvpBrokenBond.begin();
7228  pos!=mode->mvpBrokenBond.end();++pos)
7229  vpBond[pos->first].insert(&(*mode));
7230 
7231  for(list<StretchModeTorsion>::const_iterator mode=mvStretchModeTorsion.begin();
7232  mode!=mvStretchModeTorsion.end();++mode)
7233  for(map<const MolBond*,REAL>::const_iterator pos=mode->mvpBrokenBond.begin();
7234  pos!=mode->mvpBrokenBond.end();++pos)
7235  vpBond[pos->first].insert(&(*mode));
7236  for(list<StretchModeTwist>::const_iterator mode=mvStretchModeTwist.begin();
7237  mode!=mvStretchModeTwist.end();++mode)
7238  for(map<const MolBond*,REAL>::const_iterator pos=mode->mvpBrokenBond.begin();
7239  pos!=mode->mvpBrokenBond.end();++pos)
7240  vpBond[pos->first].insert(&(*mode));
7241 
7242 
7243 
7244  map<const MolBondAngle*, set<const StretchMode*> > vpAngle;
7245  for(list<StretchModeBondLength>::const_iterator mode=mvStretchModeBondLength.begin();
7246  mode!=mvStretchModeBondLength.end();++mode)
7247  for(map<const MolBondAngle*,REAL>::const_iterator pos=mode->mvpBrokenBondAngle.begin();
7248  pos!=mode->mvpBrokenBondAngle.end();++pos)
7249  vpAngle[pos->first].insert(&(*mode));
7250 
7251  for(list<StretchModeBondAngle>::const_iterator mode=mvStretchModeBondAngle.begin();
7252  mode!=mvStretchModeBondAngle.end();++mode)
7253  {
7254  if(mode->mpBondAngle!=0) vpAngle[mode->mpBondAngle].insert(&(*mode));
7255  for(map<const MolBondAngle*,REAL>::const_iterator pos=mode->mvpBrokenBondAngle.begin();
7256  pos!=mode->mvpBrokenBondAngle.end();++pos)
7257  vpAngle[pos->first].insert(&(*mode));
7258  }
7259  for(list<StretchModeTorsion>::const_iterator mode=mvStretchModeTorsion.begin();
7260  mode!=mvStretchModeTorsion.end();++mode)
7261  for(map<const MolBondAngle*,REAL>::const_iterator pos=mode->mvpBrokenBondAngle.begin();
7262  pos!=mode->mvpBrokenBondAngle.end();++pos)
7263  vpAngle[pos->first].insert(&(*mode));
7264  for(list<StretchModeTwist>::const_iterator mode=mvStretchModeTwist.begin();
7265  mode!=mvStretchModeTwist.end();++mode)
7266  for(map<const MolBondAngle*,REAL>::const_iterator pos=mode->mvpBrokenBondAngle.begin();
7267  pos!=mode->mvpBrokenBondAngle.end();++pos)
7268  vpAngle[pos->first].insert(&(*mode));
7269 
7270 
7271 
7272  map<const MolDihedralAngle*,set<const StretchMode*> > vpDihed;
7273  for(list<StretchModeBondLength>::const_iterator mode=mvStretchModeBondLength.begin();
7274  mode!=mvStretchModeBondLength.end();++mode)
7275  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=mode->mvpBrokenDihedralAngle.begin();
7276  pos!=mode->mvpBrokenDihedralAngle.end();++pos)
7277  vpDihed[pos->first].insert(&(*mode));
7278 
7279  for(list<StretchModeBondAngle>::const_iterator mode=mvStretchModeBondAngle.begin();
7280  mode!=mvStretchModeBondAngle.end();++mode)
7281  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=mode->mvpBrokenDihedralAngle.begin();
7282  pos!=mode->mvpBrokenDihedralAngle.end();++pos)
7283  vpDihed[pos->first].insert(&(*mode));
7284 
7285  for(list<StretchModeTorsion>::const_iterator mode=mvStretchModeTorsion.begin();
7286  mode!=mvStretchModeTorsion.end();++mode)
7287  {
7288  if(mode->mpDihedralAngle!=0) vpDihed[mode->mpDihedralAngle].insert(&(*mode));
7289  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=mode->mvpBrokenDihedralAngle.begin();
7290  pos!=mode->mvpBrokenDihedralAngle.end();++pos)
7291  vpDihed[pos->first].insert(&(*mode));
7292  }
7293  for(list<StretchModeTwist>::const_iterator mode=mvStretchModeTwist.begin();
7294  mode!=mvStretchModeTwist.end();++mode)
7295  for(map<const MolDihedralAngle*,REAL>::const_iterator pos=mode->mvpBrokenDihedralAngle.begin();
7296  pos!=mode->mvpBrokenDihedralAngle.end();++pos)
7297  vpDihed[pos->first].insert(&(*mode));
7298  #if 0
7299  for(map<const MolBond*,set<const StretchMode*> >::const_iterator pos=vpBond.begin();pos!=vpBond.end();++pos)
7300  {
7301  cout<<"Bond "<<pos->first->GetName()<<" is modified by the stretch modes:"<<endl;
7302  for(set<const StretchMode*>::const_iterator mode=pos->second.begin();mode!=pos->second.end();++mode)
7303  {
7304  cout<<" ";
7305  (*mode)->Print(cout);
7306  cout<<endl;
7307  }
7308  }
7309  for(map<const MolBondAngle*,set<const StretchMode*> >::const_iterator pos=vpAngle.begin();pos!=vpAngle.end();++pos)
7310  {
7311  cout<<"Bond Angle "<<pos->first->GetName()<<" is modified by the stretch modes:"<<endl;
7312  for(set<const StretchMode*>::const_iterator mode=pos->second.begin();mode!=pos->second.end();++mode)
7313  {
7314  cout<<" ";
7315  (*mode)->Print(cout);
7316  cout<<endl;
7317  }
7318  }
7319  for(map<const MolDihedralAngle*,set<const StretchMode*> >::const_iterator pos=vpDihed.begin();pos!=vpDihed.end();++pos)
7320  {
7321  cout<<"Dihedral Angle "<<pos->first->GetName()<<" is modified by the stretch modes:"<<endl;
7322  for(set<const StretchMode*>::const_iterator mode=pos->second.begin();mode!=pos->second.end();++mode)
7323  {
7324  cout<<" ";
7325  (*mode)->Print(cout);
7326  cout<<endl;
7327  }
7328  }
7329  #endif
7330  mvpStretchModeFree.clear();
7331  mvpStretchModeNotFree.clear();
7332 
7333  for(list<StretchModeBondLength>::iterator mode=mvStretchModeBondLength.begin();
7334  mode!=mvStretchModeBondLength.end();++mode)
7335  {
7336  int nb=mode->mvpBrokenDihedralAngle.size()+mode->mvpBrokenBondAngle.size()+mode->mvpBrokenBond.size();
7337  if(mode->mpBond!=0) nb -= 1;
7338  if(nb==0) mvpStretchModeFree.push_back(&(*mode));
7339  else mvpStretchModeNotFree.push_back(&(*mode));
7340  }
7341 
7342  for(list<StretchModeBondAngle>::iterator mode=mvStretchModeBondAngle.begin();
7343  mode!=mvStretchModeBondAngle.end();++mode)
7344  {
7345  int nb=mode->mvpBrokenDihedralAngle.size()+mode->mvpBrokenBondAngle.size()+mode->mvpBrokenBond.size();
7346  if(mode->mpBondAngle!=0) nb -= 1;
7347  if(nb==0) mvpStretchModeFree.push_back(&(*mode));
7348  else mvpStretchModeNotFree.push_back(&(*mode));
7349  }
7350 
7351  for(list<StretchModeTorsion>::iterator mode=mvStretchModeTorsion.begin();
7352  mode!=mvStretchModeTorsion.end();++mode)
7353  {
7354  int nb=mode->mvpBrokenDihedralAngle.size()+mode->mvpBrokenBondAngle.size()+mode->mvpBrokenBond.size();
7355  if(mode->mpDihedralAngle!=0) nb -= 1;
7356  if(nb==0) mvpStretchModeFree.push_back(&(*mode));
7357  else mvpStretchModeNotFree.push_back(&(*mode));
7358  }
7359  #if 1
7360  for(list<StretchModeTwist>::iterator mode=mvStretchModeTwist.begin();
7361  mode!=mvStretchModeTwist.end();++mode)
7362  if(mode->mvpBrokenDihedralAngle.size()+mode->mvpBrokenBondAngle.size()+mode->mvpBrokenBond.size()==0)
7363  mvpStretchModeFree.push_back(&(*mode));
7364  else mvpStretchModeNotFree.push_back(&(*mode));
7365  #endif
7366 }
7367 
7369 {
7370  // For each atom, list all atoms that are never moved relatively to it.
7371  // (not moved == distance cannot change)
7372  map<MolAtom*,set<MolAtom*> > vBoundAtoms;
7373  set<MolAtom*> set0;
7374  for(vector<MolAtom*>::iterator pos=this->GetAtomList().begin();pos!=this->GetAtomList().end();++pos)
7375  set0.insert(*pos);
7376 
7377  for(vector<MolAtom*>::iterator pat1=this->GetAtomList().begin();pat1!=this->GetAtomList().end();++pat1)
7378  {
7379  vBoundAtoms[*pat1]=set0;
7380  for(vector<MolAtom*>::iterator pat2=this->GetAtomList().begin();pat2!=this->GetAtomList().end();++pat2)
7381  {
7382  bool cont=false;
7383 
7384  for(list<StretchModeBondLength>::iterator pstretch=this->GetStretchModeBondLengthList().begin();
7385  pstretch!=this->GetStretchModeBondLengthList().end();++pstretch)
7386  {
7387  set<MolAtom *>::iterator pos1=pstretch->mvTranslatedAtomList.find(*pat1),
7388  pos2=pstretch->mvTranslatedAtomList.find(*pat2);
7389  if( ((pos1==pstretch->mvTranslatedAtomList.end())&&(pos2!=pstretch->mvTranslatedAtomList.end()))
7390  ||((pos1!=pstretch->mvTranslatedAtomList.end())&&(pos2==pstretch->mvTranslatedAtomList.end())))
7391  {
7392  vBoundAtoms[*pat1].erase(*pat2);
7393  //cout<<(*pat1)->GetName()<<" moves (b) relatively to "<<(*pat2)->GetName()<<" /";
7394  //pstretch->Print(cout);cout<<endl;
7395  cont=true;
7396  break;
7397  }
7398  }
7399  if(cont) continue;
7400 
7401  for(list<StretchModeBondAngle>::iterator pstretch=this->GetStretchModeBondAngleList().begin();
7402  pstretch!=this->GetStretchModeBondAngleList().end();++pstretch)
7403  {
7404  //pstretch->mpAtom1 does not move relatively to any atom
7405  if((*pat1==pstretch->mpAtom1)||(*pat2==pstretch->mpAtom1)) continue;
7406 
7407  set<MolAtom *>::iterator pos1=pstretch->mvRotatedAtomList.find(*pat1),
7408  pos2=pstretch->mvRotatedAtomList.find(*pat2);
7409  //:TODO: Take into account the special case of the atoms defining the bond angle
7410  if( ((pos1==pstretch->mvRotatedAtomList.end())&&(pos2!=pstretch->mvRotatedAtomList.end()))
7411  ||((pos1!=pstretch->mvRotatedAtomList.end())&&(pos2==pstretch->mvRotatedAtomList.end())))
7412  {
7413  vBoundAtoms[*pat1].erase(*pat2);
7414  //cout<<(*pat1)->GetName()<<" moves (a) relatively to "<<(*pat2)->GetName()<<" /";
7415  //pstretch->Print(cout);cout<<endl;
7416  cont=true;
7417  break;
7418  }
7419  }
7420  if(cont) continue;
7421 
7422  for(list<StretchModeTorsion>::iterator pstretch=this->GetStretchModeTorsionList().begin();
7423  pstretch!=this->GetStretchModeTorsionList().end();++pstretch)
7424  {
7425  set<MolAtom *>::iterator pos1=pstretch->mvRotatedAtomList.find(*pat1),
7426  pos2=pstretch->mvRotatedAtomList.find(*pat2);
7427 
7428  if( (pos1!=pstretch->mvRotatedAtomList.end())&&(pos2==pstretch->mvRotatedAtomList.end())
7429  &&(*pat2!=pstretch->mpAtom1) &&(*pat2!=pstretch->mpAtom2) )
7430  {
7431  vBoundAtoms[*pat1].erase(*pat2);
7432  //cout<<(*pat1)->GetName()<<" moves (d1) relatively to "<<(*pat2)->GetName()<<" /";
7433  //pstretch->Print(cout);cout<<endl;
7434  break;
7435  }
7436  if( (pos1==pstretch->mvRotatedAtomList.end())&&(pos2!=pstretch->mvRotatedAtomList.end())
7437  &&(*pat1!=pstretch->mpAtom1) && (*pat1!=pstretch->mpAtom2) )
7438  {
7439  vBoundAtoms[*pat1].erase(*pat2);
7440  //cout<<(*pat1)->GetName()<<" moves (d2) relatively to "<<(*pat2)->GetName()<<" /";
7441  //pstretch->Print(cout);cout<<endl;
7442  break;
7443  }
7444  }
7445  }
7446  }
7447 
7448  // List remaining group of atoms, take care of rigid groups
7449  set<set<MolAtom*> > vBoundGroups;
7450  for(map<MolAtom*,set<MolAtom*> >::iterator pos=vBoundAtoms.begin();pos!=vBoundAtoms.end();++pos)
7451  {
7452  #if 0
7453  cout<<"Non-flexible group from "<<pos->first->GetName()<<": ";
7454  for(set<MolAtom*>::const_iterator atom=pos->second.begin();atom!=pos->second.end();++atom)
7455  cout<<(*atom)->GetName()<<",";
7456  cout<<endl;
7457  #endif
7458  // Remove atoms belonging to a rigid group
7459  for(vector<RigidGroup *>::iterator pr=this->GetRigidGroupList().begin();pr!=this->GetRigidGroupList().end();++pr)
7460  for(set<MolAtom *>::iterator at=(*pr)->begin();at!=(*pr)->end();++at)
7461  pos->second.erase(*at);
7462  if(pos->second.size()>1) vBoundGroups.insert(pos->second);
7463  }
7464  #if 0
7465  for(set<set<MolAtom*> >::iterator pos=vBoundGroups.begin();pos!=vBoundGroups.end();++pos)
7466  {
7467  cout<<"Non-flexible group:";
7468  for(set<MolAtom*>::const_iterator atom=pos->begin();atom!=pos->end();++atom)
7469  cout<<(*atom)->GetName()<<",";
7470  cout<<endl;
7471  }
7472  #endif
7473  // Create relevant MDAtomGroup, listing associated restraints
7474  mvMDAtomGroup.clear();
7475  for(set<set<MolAtom*> >::iterator pos=vBoundGroups.begin();pos!=vBoundGroups.end();++pos)
7476  {
7477  set<MolBond*> vb;
7478  for(vector<MolBond*>::iterator pr=this->GetBondList().begin();pr!=this->GetBondList().end();++pr)
7479  if( (pos->find(&(*pr)->GetAtom1())!=pos->end())
7480  ||(pos->find(&(*pr)->GetAtom2())!=pos->end())) vb.insert(*pr);
7481 
7482  set<MolBondAngle*> va;
7483  for(vector<MolBondAngle*>::iterator pr=this->GetBondAngleList().begin();pr!=this->GetBondAngleList().end();++pr)
7484  if( (pos->find(&(*pr)->GetAtom1())!=pos->end())
7485  ||(pos->find(&(*pr)->GetAtom2())!=pos->end())
7486  ||(pos->find(&(*pr)->GetAtom3())!=pos->end())) va.insert(*pr);
7487 
7488  set<MolDihedralAngle*> vd;
7489  for(vector<MolDihedralAngle*>::iterator pr=this->GetDihedralAngleList().begin();pr!=this->GetDihedralAngleList().end();++pr)
7490  if( (pos->find(&(*pr)->GetAtom1())!=pos->end())
7491  ||(pos->find(&(*pr)->GetAtom2())!=pos->end())
7492  ||(pos->find(&(*pr)->GetAtom3())!=pos->end())
7493  ||(pos->find(&(*pr)->GetAtom4())!=pos->end())) vd.insert(*pr);
7494 
7495  set<MolAtom*> tmp= *pos;// Cannot pass *pos directly ? gcc bug evaluating const-ness?
7496  mvMDAtomGroup.push_back(MDAtomGroup(tmp,vb,va,vd));
7497  mvMDAtomGroup.back().Print(cout);
7498  }
7499 
7500  // Create mvMDFullAtomGroup
7501  mvMDFullAtomGroup.clear();
7502  #if 1
7503  // All atoms except those in rigid groups
7504  for(vector<MolAtom*>::iterator at=this->GetAtomList().begin();at!=this->GetAtomList().end();++at)
7505  mvMDFullAtomGroup.insert(*at);
7506  for(vector<RigidGroup *>::iterator pr=this->GetRigidGroupList().begin();pr!=this->GetRigidGroupList().end();++pr)
7507  for(set<MolAtom *>::iterator at=(*pr)->begin();at!=(*pr)->end();++at)
7508  mvMDFullAtomGroup.erase(*at);
7509  cout<<"Full MD atom group:"<<endl<<" ";
7510  for(set<MolAtom*>::const_iterator pos=mvMDFullAtomGroup.begin();pos!=mvMDFullAtomGroup.end();++pos)
7511  cout<<(*pos)->GetName()<<" ";
7512  cout<<endl;
7513  #else
7514  // All atoms listed in at leat one mvMDAtomGroup
7515  mvMDFullAtomGroup.clear();
7516  for(list<MDAtomGroup>::const_iterator pos= mvMDAtomGroup.begin();pos!= mvMDAtomGroup.end();++pos)
7517  for(set<MolAtom*>::const_iterator at=pos->mvpAtom.begin();at!=pos->mvpAtom.end();++at)
7518  mvMDFullAtomGroup.insert(*at);
7519  cout<<"Full MD atom group:"<<endl<<" ";
7520  for(set<MolAtom*>::const_iterator pos=mvMDFullAtomGroup.begin();pos!=mvMDFullAtomGroup.end();++pos)
7521  cout<<(*pos)->GetName()<<" ";
7522  cout<<endl;
7523  #endif
7524  mClockMDAtomGroup.Click();
7525 }
7526 
7528 {
7529  if( (mClockAtomPosition<mClockScattCompList)
7530  &&(mClockOrientation <mClockScattCompList)
7531  &&(mClockAtomScattPow<mClockScattCompList)
7533  &&(this->GetCrystal().GetClockLatticePar()<mClockScattCompList))return;
7534  VFN_DEBUG_ENTRY("Molecule::UpdateScattCompList()",5)
7535  TAU_PROFILE("Molecule::UpdateScattCompList()","void ()",TAU_DEFAULT);
7536  const long nb=this->GetNbComponent();
7537  // Get internal coords
7538  for(long i=0;i<nb;++i)
7539  {
7540  if(mvpAtom[i]->IsDummy()) mScattCompList(i).mpScattPow=0;
7541  else mScattCompList(i).mpScattPow=&(mvpAtom[i]->GetScatteringPower());
7542  mScattCompList(i).mX=mvpAtom[i]->GetX();
7543  mScattCompList(i).mY=mvpAtom[i]->GetY();
7544  mScattCompList(i).mZ=mvpAtom[i]->GetZ();
7545  mScattCompList(i).mOccupancy=mvpAtom[i]->GetOccupancy()*mOccupancy;
7546  }
7547 
7548  #ifdef RIGID_BODY_STRICT_EXPERIMENTAL
7549  // During an optimization, apply the translations & rotations of the rigid group parameters
7550  if(true)//this->IsBeingRefined())
7551  {
7552  for(vector<RigidGroup *>::const_iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos)
7553  {
7554  (*pos)->mQuat.Normalize();
7555  // Center of the atom group
7556  REAL x0=0,y0=0,z0=0;
7557  for(set<unsigned int>::iterator at=(*pos)->mvIdx.begin();at!=(*pos)->mvIdx.end();++at)
7558  {
7559  x0+=mvpAtom[*at]->GetX();
7560  y0+=mvpAtom[*at]->GetY();
7561  z0+=mvpAtom[*at]->GetZ();
7562  }
7563  x0/=(*pos)->size();
7564  y0/=(*pos)->size();
7565  z0/=(*pos)->size();
7566 
7567  // Apply rotation & translation to all atoms
7568  for(set<unsigned int>::iterator at=(*pos)->mvIdx.begin();at!=(*pos)->mvIdx.end();++at)
7569  {
7570  REAL x=mvpAtom[*at]->GetX()-x0, y=mvpAtom[*at]->GetY()-y0, z=mvpAtom[*at]->GetZ()-z0;
7571  (*pos)->mQuat.RotateVector(x,y,z);
7572  mScattCompList(*at).mX=x+x0+(*pos)->mX;
7573  mScattCompList(*at).mY=y+y0+(*pos)->mY;
7574  mScattCompList(*at).mZ=z+z0+(*pos)->mZ;
7575  }
7576  }
7577  }
7578  #endif
7579  // translate center to (0,0,0)
7580  REAL x0=0,y0=0,z0=0;
7581  if((mMoleculeCenter.GetChoice()==0) || (mpCenterAtom==0))
7582  {
7583  for(long i=0;i<nb;++i)
7584  {
7585  x0 += mScattCompList(i).mX;
7586  y0 += mScattCompList(i).mY;
7587  z0 += mScattCompList(i).mZ;
7588  }
7589  x0 /= nb;
7590  y0 /= nb;
7591  z0 /= nb;
7592  }
7593  else
7594  {
7595  x0=mpCenterAtom->GetX();
7596  y0=mpCenterAtom->GetY();
7597  z0=mpCenterAtom->GetZ();
7598  }
7599  for(long i=0;i<nb;++i)
7600  {
7601  mScattCompList(i).mX -= x0;
7602  mScattCompList(i).mY -= y0;
7603  mScattCompList(i).mZ -= z0;
7604  }
7605  //VFN_DEBUG_MESSAGE("Molecule::UpdateScattCompList()",10)
7606  // rotate
7607  mQuat.Normalize();
7608  for(long i=0;i<nb;++i)
7609  {
7610  //#error the vector must not be normalized !
7612  }
7613  // Convert to fractionnal coordinates
7614  for(long i=0;i<nb;++i)
7615  {
7617  mScattCompList(i).mY,
7618  mScattCompList(i).mZ);
7619  }
7620  // translate center to position in unit cell
7621  for(long i=0;i<nb;++i)
7622  {
7623  mScattCompList(i).mX += mXYZ(0);
7624  mScattCompList(i).mY += mXYZ(1);
7625  mScattCompList(i).mZ += mXYZ(2);
7626  }
7628  VFN_DEBUG_EXIT("Molecule::UpdateScattCompList()",5)
7629 }
7630 vector<MolAtom*>::reverse_iterator Molecule::FindAtom(const string &name)
7631 {
7632  VFN_DEBUG_ENTRY("Molecule::FindAtom():"<<name,4)
7633  vector<MolAtom*>::reverse_iterator rpos;
7634  for(rpos=mvpAtom.rbegin();rpos!=mvpAtom.rend();++rpos)
7635  if(name==(*rpos)->GetName())
7636  {
7637  VFN_DEBUG_EXIT("Molecule::FindAtom():"<<name<<"...NOT FOUND !",4)
7638  return rpos;
7639  }
7640  VFN_DEBUG_EXIT("Molecule::FindAtom():"<<name<<"...NOT FOUND !",4)
7641  return rpos;
7642 }
7643 vector<MolAtom*>::const_reverse_iterator Molecule::FindAtom(const string &name)const
7644 {
7645  vector<MolAtom*>::const_reverse_iterator rpos;
7646  rpos=mvpAtom.rbegin();
7647  for(rpos=mvpAtom.rbegin();rpos!=mvpAtom.rend();++rpos)
7648  if(name==(*rpos)->GetName()) return rpos;
7649  return rpos;
7650 }
7652 {
7653  VFN_DEBUG_ENTRY("Molecule::InitOptions",7)
7654  static string Flexname;
7655  static string Flexchoices[3];
7656 
7657  static string FlipName;
7658  static string FlipChoice[2];
7659 
7660  static string autoOptimizeConformationName;
7661  static string autoOptimizeConformationChoices[2];
7662 
7663  static string optimizeOrientationName;
7664  static string optimizeOrientationChoices[2];
7665 
7666  static string moleculeCenterName;
7667  static string moleculeCenterChoices[2];
7668 
7669  static bool needInitNames=true;
7670  if(true==needInitNames)
7671  {
7672  Flexname="Flexibility Model";
7673  Flexchoices[0]="Automatic from Restraints, relaxed - RECOMMENDED";
7674  Flexchoices[1]="Rigid Body";
7675  Flexchoices[2]="Automatic from Restraints, strict";
7676  //Flexchoices[3]="Molecular Dynamics";
7677 
7678  FlipName="Enable Flipping";
7679  FlipChoice[0]="Yes";
7680  FlipChoice[1]="No";
7681 
7682  autoOptimizeConformationName="Auto Optimize Starting Conformation";
7683  autoOptimizeConformationChoices[0]="Yes";
7684  autoOptimizeConformationChoices[1]="No";
7685 
7686  optimizeOrientationName="Optimize Orientation";
7687  optimizeOrientationChoices[0]="Yes";
7688  optimizeOrientationChoices[1]="No";
7689 
7690  moleculeCenterName="Rotation Center";
7691  moleculeCenterChoices[0]="Geometrical center (recommended)";
7692  moleculeCenterChoices[1]="User-chosen Atom";
7693 
7694  needInitNames=false;
7695  }
7696  mFlexModel.Init(3,&Flexname,Flexchoices);
7697  mFlexModel.SetChoice(0);
7698  this->AddOption(&mFlexModel);
7699 
7700  mFlipModel.Init(2, &FlipName, FlipChoice);
7701  mFlipModel.SetChoice(0);
7702  this->AddOption(&mFlipModel);
7703 
7704  mAutoOptimizeConformation.Init(2,&autoOptimizeConformationName,
7705  autoOptimizeConformationChoices);
7707 
7708  mOptimizeOrientation.Init(2,&optimizeOrientationName,optimizeOrientationChoices);
7710 
7711  mMoleculeCenter.Init(2,&moleculeCenterName,moleculeCenterChoices);
7712  this->AddOption(&mMoleculeCenter);
7713 
7714  VFN_DEBUG_EXIT("Molecule::InitOptions",7)
7715 }
7716 
7717 Molecule::FlipGroup::FlipGroup(const MolAtom &at0,const MolAtom &at1,const MolAtom &at2):
7718 mpAtom0(&at0),mpAtom1(&at1),mpAtom2(&at2),mNbTest(0),mNbAccept(0)
7719 {
7720 }
7721 
7722 void Molecule::FlipAtomGroup(const FlipGroup& group, const bool keepCenter)
7723 {
7724  TAU_PROFILE("Molecule::FlipAtomGroup(FlipGroup&)","void (...)",TAU_DEFAULT);
7725  if(group.mpAtom0==group.mvRotatedChainList.back().first)
7726  {// We are doing a 180� rotation exchanging two bonds
7727  const REAL vx=group.mpAtom0->X()-(group.mpAtom1->X()+group.mpAtom2->X())/2.;
7728  const REAL vy=group.mpAtom0->Y()-(group.mpAtom1->Y()+group.mpAtom2->Y())/2.;
7729  const REAL vz=group.mpAtom0->Z()-(group.mpAtom1->Z()+group.mpAtom2->Z())/2.;
7730  this->RotateAtomGroup(*(group.mpAtom0),vx,vy,vz,
7731  group.mvRotatedChainList.back().second,M_PI,keepCenter);
7732  }
7733  else
7734  {// we are flipping bonds with respect to a plane defined by other bonds
7735  REAL v01x=group.mpAtom1->X()-group.mpAtom0->X();
7736  REAL v01y=group.mpAtom1->Y()-group.mpAtom0->Y();
7737  REAL v01z=group.mpAtom1->Z()-group.mpAtom0->Z();
7738  const REAL norm01=sqrt(v01x*v01x+v01y*v01y+v01z*v01z+1e-7);
7739  v01x /= norm01;v01y /= norm01;v01z /= norm01;
7740 
7741  REAL v02x=group.mpAtom2->X()-group.mpAtom0->X();
7742  REAL v02y=group.mpAtom2->Y()-group.mpAtom0->Y();
7743  REAL v02z=group.mpAtom2->Z()-group.mpAtom0->Z();
7744  const REAL norm02=sqrt(v02x*v02x+v02y*v02y+v02z*v02z+1e-7);
7745  v02x /= norm02;v02y /= norm02;v02z /= norm02;
7746 
7747  REAL v12x=group.mpAtom2->X()-group.mpAtom1->X();
7748  REAL v12y=group.mpAtom2->Y()-group.mpAtom1->Y();
7749  REAL v12z=group.mpAtom2->Z()-group.mpAtom1->Z();
7750  const REAL norm12=sqrt(v12x*v12x+v12y*v12y+v12z*v12z+1e-7);
7751  v12x /= norm12;v12y /= norm12;v12z /= norm12;
7752 
7753  REAL v0mx=group.mpAtom0->X()-(group.mpAtom1->X()+group.mpAtom2->X())/2.;
7754  REAL v0my=group.mpAtom0->Y()-(group.mpAtom1->Y()+group.mpAtom2->Y())/2.;
7755  REAL v0mz=group.mpAtom0->Z()-(group.mpAtom1->Z()+group.mpAtom2->Z())/2.;
7756  const REAL norm0m=sqrt(v0mx*v0mx+v0my*v0my+v0mz*v0mz+1e-7);
7757  v0mx /= norm0m;v0my /= norm0m;v0mz /= norm0m;
7758 
7759  if(fabs(v01x*v02x+v01y*v02y+v01z*v02z)
7760  >0.05*sqrt(abs( (v01x*v01x+v01y*v01y+v01z*v01z)
7761  *(v02x*v02x+v02y*v02y+v02z*v02z))))
7762  {
7763  REAL v012x=v01y*v02z-v01z*v02y;
7764  REAL v012y=v01z*v02x-v01x*v02z;
7765  REAL v012z=v01x*v02y-v01y*v02x;
7766  const REAL norm012=sqrt(v012x*v012x+v012y*v012y+v012z*v012z+1e-7);
7767  v012x /= norm012;v012y /= norm012;v012z /= norm012;
7768 
7769 
7770  for(list<pair<const MolAtom *,set<MolAtom*> > >::const_iterator
7771  chain=group.mvRotatedChainList.begin();
7772  chain!=group.mvRotatedChainList.end();++chain)
7773  {
7774  REAL v03x=chain->first->X()-group.mpAtom0->X();
7775  REAL v03y=chain->first->Y()-group.mpAtom0->Y();
7776  REAL v03z=chain->first->Z()-group.mpAtom0->Z();
7777  const REAL norm03=sqrt( v03x*v03x + v03y*v03y + v03z*v03z +1e-7);
7778  v03x /= norm03;v03y /= norm03;v03z /= norm03;
7779 
7780  const REAL a1=v012x*v03x+v012y*v03y+v012z*v03z;
7781  const REAL a2= v0mx*v03x+ v0my*v03y+ v0mz*v03z;
7782  const REAL a3= v12x*v03x+ v12y*v03y+ v12z*v03z;
7783  REAL angle = -a1/sqrt(1-a3*a3+1e-7);
7784  if(angle>=1.)
7785  angle = M_PI/2.;
7786  else
7787  {
7788  if(angle<=-1.)
7789  {
7790  angle = -M_PI/2.;
7791  }
7792  else angle = asin(angle);
7793  }
7794  if(a2<0) angle=M_PI-angle;
7795  this->RotateAtomGroup(*(group.mpAtom0),v12x,v12y,v12z,
7796  chain->second,2*angle,keepCenter);
7797  }
7798  }
7799  }
7800 }
7801 
7804 }
7805 
7807 {
7808  #ifdef RIGID_BODY_STRICT_EXPERIMENTAL
7809  // Apply the translations & rotations of all rigid group parameters, and
7810  // use this as the newly stored atomic coordinates.
7811  for(vector<RigidGroup *>::const_iterator pos=this->GetRigidGroupList().begin();pos!=this->GetRigidGroupList().end();++pos)
7812  {
7813  (*pos)->mQuat.Normalize();
7814  // Center of atom group
7815  REAL x0=0,y0=0,z0=0;
7816  for(set<MolAtom *>::iterator at=(*pos)->begin();at!=(*pos)->end();++at)
7817  {
7818  x0+=(*at)->GetX();
7819  y0+=(*at)->GetY();
7820  z0+=(*at)->GetZ();
7821  }
7822  x0/=(*pos)->size();
7823  y0/=(*pos)->size();
7824  z0/=(*pos)->size();
7825 
7826  // Apply rotation & translation to all atoms
7827  for(set<MolAtom *>::iterator at=(*pos)->begin();at!=(*pos)->end();++at)
7828  {
7829  REAL x=(*at)->GetX()-x0, y=(*at)->GetY()-y0, z=(*at)->GetZ()-z0;
7830  (*pos)->mQuat.RotateVector(x,y,z);
7831  (*at)->SetX(x+x0+(*pos)->mX);
7832  (*at)->SetY(y+y0+(*pos)->mY);
7833  (*at)->SetZ(z+z0+(*pos)->mZ);
7834  }
7835 
7836  // Reset the translation & rotation parameters, only useful during an optimization
7837  (*pos)->mX=0;
7838  (*pos)->mY=0;
7839  (*pos)->mZ=0;
7840  (*pos)->mQuat.Q0()=1;
7841  (*pos)->mQuat.Q1()=0;
7842  (*pos)->mQuat.Q2()=0;
7843  (*pos)->mQuat.Q3()=0;
7844  }
7845  #endif
7846 }
7847 
7848 #ifdef __WX__CRYST__
7849 WXCrystObjBasic* Molecule::WXCreate(wxWindow* parent)
7850 {
7851  VFN_DEBUG_ENTRY("Molecule::WXCreate()",5)
7852  mpWXCrystObj=new WXMolecule(parent,this);
7853  VFN_DEBUG_EXIT("Molecule::WXCreate()",5)
7854  return mpWXCrystObj;
7855 }
7856 #endif
7857 
7858 }//namespace
MolAtom(const REAL x, const REAL y, const REAL z, const ScatteringPower *pPow, const string &name, Molecule &parent)
Constructor for a MolAtom.
Definition: Molecule.cpp:188
CrystVector_REAL GetLatticePar() const
Lattice parameters (a,b,c,alpha,beta,gamma) as a 6-element vector in Angstroems and radians...
Definition: UnitCell.cpp:92
RotorGroup(const MolAtom &at1, const MolAtom &at2)
Constructor, with the two atoms around which the rotation shall be made.
Definition: Molecule.cpp:5333
void SetDerivStep(const REAL)
Fixed step to use to compute numerical derivative.
list< MDAtomGroup > mvMDAtomGroup
Groups of atoms that should be moved according to molecular dynamics principles.
Definition: Molecule.h:1344
REAL mOccupancy
Occupancy.
Definition: Molecule.h:125
void RestraintExport(ostream &os) const
Print the restraints (bond length, angles...) as whole labels and number in column text format which ...
Definition: Molecule.cpp:4526
map< MolAtom *, set< MolAtom * > > mConnectivityTable
Connectivity table: for each atom, keep the list of atoms bonded to it.
Definition: Molecule.h:1230
MolAtom * mpAtom1
The second atom (first atom moved)
Definition: Molecule.h:584
StretchModeTwist(MolAtom &at1, MolAtom &at2)
Constructor If pDihedralAngle!=0, the dihedral angle length restraint is respected.
Definition: Molecule.cpp:1766
XYZ mDerivAtom1
Partial derivatives of the angle with respect to the coordinates of the atoms.
Definition: Molecule.h:325
void AddPar(const RefinablePar &newRefPar)
Add a refinable parameter.
vector< MolDihedralAngle * >::iterator RemoveDihedralAngle(const MolDihedralAngle &, const bool del=true)
Remove a dihedral angle.
Definition: Molecule.cpp:4036
virtual void UpdateDisplay() const
If there is an interface, this should be automatically be called each time there is a 'new...
vector< MolBond * > mvpBond
The list of bonds.
Definition: Molecule.h:1133
REAL mXmin
Display limits in reduced coordinates.
Definition: General.h:178
bool mShowLabel
Show labels ?
Definition: General.h:180
void BuildRotorGroup()
Build the groups of atoms that will be rotated during global optimization.
Definition: Molecule.cpp:5337
REAL mLLK
Stored log(likelihood)
Definition: Molecule.h:320
REAL mX
The translation of all the atoms as a group The values will be resetted whenever entering or leaving ...
Definition: Molecule.h:511
Bond angle restraint between 3 atoms.
Definition: Molecule.h:256
void TuneGlobalOptimRotationAmplitude()
Tune the rotation amplitude for free torsions and for the overall Molecule Rotation.
Definition: Molecule.cpp:6861
virtual void Print(ostream &os, bool full=true) const
Print one-line list of atoms moved.
Definition: Molecule.cpp:1735
vector< MolDihedralAngle * >::const_iterator FindDihedralAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3, const MolAtom &at4) const
Searches whether a dihedral between four atoms already exists, searching for either (at1...
Definition: Molecule.cpp:4056
Molecule * mpMol
Parent Molecule.
Definition: Molecule.h:314
virtual void Stretch(const REAL change, const bool keepCenter=true)
Move the atoms according to this mode.
Definition: Molecule.cpp:1562
virtual void Optimize(long &nbSteps, const bool silent=false, const REAL finalcost=0, const REAL maxTime=-1)
Launch optimization (a single run) for N steps.
virtual REAL GetLogLikelihood() const
Get -ln(likelihood) for this restraint.
Definition: Molecule.cpp:1066
float string2floatC(const string &s)
Function to convert a substring to a floating point value, imposing a C locale (using '...
Definition: ObjCryst/IO.cpp:59
bool mIsInRing
Is the atom in a ring ?
Definition: Molecule.h:131
Atoms moved when changing a bond angle.
Definition: Molecule.h:595
REAL GetBondLength(const MolAtom &at1, const MolAtom &at2)
Get The Bond Length between two atoms.
Definition: Molecule.cpp:59
MolBondAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, const REAL angle, const REAL sigma, const REAL delta, Molecule &parent)
Constructor.
Definition: Molecule.cpp:626
void OrthonormalToFractionalCoords(REAL &x, REAL &y, REAL &z) const
Get fractional cartesian coordinates for a set of (x,y,z) orthonormal coordinates.
Definition: UnitCell.cpp:271
virtual void CalcDeriv(const bool derivllk=true) const
Calculate the derivative of the Molecule's Log(likelihood) and atomic positions versus a change of th...
Definition: Molecule.cpp:1693
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
Definition: Molecule.cpp:2106
set< MolAtom * > mvRotatedAtomList
The set of atoms that are to be rotated around the direction going through at1 and perpendicular to t...
Definition: Molecule.h:620
long GetNbComponent() const
Number of components.
We need to record exactly when refinable objects have been modified for the last time (to avoid re-co...
Definition: RefinableObj.h:138
std::map< const MolAtom *, XYZ > mDerivXYZ
Derivative of the atomic positions versus a change of the bond length.
Definition: Molecule.h:550
virtual ~MolAtom()
Destructor.
Definition: Molecule.cpp:198
bool IsBeingRefined() const
Is the object being refined ? (Can be refined by one algorithm at a time only.)
void BuildFlipGroup()
Build the groups of atoms that can be flipped.
Definition: Molecule.cpp:7040
virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst)
Make a random move of the current configuration.
void FractionalToOrthonormalCoords(REAL &x, REAL &y, REAL &z) const
Get orthonormal cartesian coordinates for a set of (x,y,z) fractional coordinates.
Definition: UnitCell.cpp:261
string GetName() const
Name of the bond, e.g. "C3-O4".
Definition: Molecule.cpp:368
CrystVector_REAL mXYZ
coordinates of the scatterer (or of its center..)
Definition: Scatterer.h:273
vector< MolBond * >::const_iterator FindBond(const MolAtom &, const MolAtom &) const
Searches whether a bond between two atoms already exists.
Definition: Molecule.cpp:3955
CrystVector_REAL mLSQObs
Current LSQ Calc - one value for each restraint (bond distance, angle or dihedral angle ideal values)...
Definition: Molecule.h:1370
void AddRefinableObj(RefinableObj &)
Add a refined object. All sub-objects are also added.
MolAtom * mpAtom2
The third atom.
Definition: Molecule.h:615
std::vector< RigidGroup * >::iterator RemoveRigidGroup(const RigidGroup &group, const bool updateDisplay=true, const bool del=true)
Remove a rigid group of atoms.
Definition: Molecule.cpp:4153
REAL mLLK
Stored log(likelihood)
Definition: Molecule.h:408
virtual void Stretch(const REAL change, const bool keepCenter=true)
Move the atoms according to this mode.
Definition: Molecule.cpp:1830
void BuildStretchModeTorsion()
Build the groups of atoms moved when changing a dihedral angle, while respecting the Molecule restrai...
Definition: Molecule.cpp:6181
REAL mDerivLLKCoeff
The factor used to change the derivative of the length/angle, to the derivative of the log(likelihood...
Definition: Molecule.h:239
virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false)
This should be called by any optimization class at the begining of an optimization.
void SaveParamSet(const unsigned long id) const
Save the current set of refined values over a previously-created set of saved values.
const MolAtom * mpCenterAtom
Atom chosen as center of rotation, if mRotationCenter is set to use an atom rather than the geometric...
Definition: Molecule.h:1226
StretchModeBondLength(MolAtom &at0, MolAtom &at1, const MolBond *pBond)
Constructor If pBond!=0, the bond length restraint is respected.
Definition: Molecule.cpp:1504
list< StretchModeBondLength > mvStretchModeBondLength
List of StretchModeBondLength.
Definition: Molecule.h:1320
virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type)
Make a random move of the current configuration.
Definition: Molecule.cpp:2652
vector< MolAtom * > mvpAtom
The vector of the 3 atoms involved in the bond angle.
Definition: Molecule.h:311
Molecule * mpMol
The Molecule corresponding to this stretch mode.
Definition: Molecule.h:552
virtual void TagNewBestConfig() const
During a global optimization, tells the object that the current config is the latest "best" config...
Definition: Molecule.cpp:3124
MolAtom * mpAtom1
The first atom.
Definition: Molecule.h:673
const MolAtom * mpAtom1
The first atom defining the rotation axis.
Definition: Molecule.h:1295
virtual void Print(ostream &os, bool full=true) const
Print one-line list of atoms moved.
Definition: Molecule.cpp:1647
void AddBondAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, const REAL angle, const REAL sigma, const REAL delta, const bool updateDisplay=true)
Add a bond angle restraint.
Definition: Molecule.cpp:3976
virtual REAL GetLogLikelihood() const
Get -ln(likelihood) for this restraint.
Definition: Molecule.cpp:454
void Click()
Record an event for this clock (generally, the 'time' an object has been modified, or some computation has been made)
FlipGroup(const MolAtom &at0, const MolAtom &at1, const MolAtom &at2)
Constructor, with the central atom.
Definition: Molecule.cpp:7717
vector< Restraint * >::iterator RemoveRestraint(Restraint *pRestraint)
Remove a restraint from the list of known restraints.
void AddChild(const RefinableObjClock &)
Add a 'child' clock.
bool mDeleteSubObjInDestructor
Base Rotation amplitude (in radians) for the Molecule, so that the average atomic displacement is equ...
Definition: Molecule.h:1169
virtual const CrystVector_REAL & GetLSQDeriv(const unsigned int n, RefinablePar &par)
Get the first derivative values for the LSQ function, for a given parameter.
Definition: Molecule.cpp:3118
Quaternion mQuat
The unit quaternion defining the orientation - this is used during optimizations to rotate all atoms ...
Definition: Molecule.h:508
void ResetRigidGroupsPar() const
Set the orientation & translation parameters of all rigid groups to 0, after correcting the atomic po...
Definition: Molecule.cpp:7806
virtual const CrystVector_REAL & GetLSQObs(const unsigned int) const
Get the observed values for the LSQ function.
Definition: Molecule.cpp:3090
REAL DihedralAngleRandomChange(const StretchModeTorsion &mode, const REAL amplitude, const bool respectRestraint=true)
Change a dihedral angle, while respecting the Restraint (if any).
Definition: Molecule.cpp:4988
vector< MolAtom * > mvpAtom
The list of atoms.
Definition: Molecule.h:1129
void XMLInput(istream &is, const XMLCrystTag &tag)
XMLInput From stream.
std::vector< RigidGroup * > mvRigidGroup
Rigid groups of atoms.
Definition: Molecule.h:1151
RefinablePar & GetPar(const long i)
Access all parameters in the order they were inputted.
StretchModeBondAngle(MolAtom &at0, MolAtom &at1, MolAtom &at2, const MolBondAngle *pBondAngle)
Constructor If pBondAngle!=0, the bond angle length restraint is respected.
Definition: Molecule.cpp:1583
A quaternion class, used to represent the orientation of the molecule.
Definition: Molecule.h:448
const MolAtom * mpAtom0
The atom which is an asymmetric center.
Definition: Molecule.h:1293
Bond between two atoms, also a restraint on the associated bond length.
Definition: Molecule.h:152
REAL mLLK
Stored log(likelihood)
Definition: Molecule.h:230
virtual ostream & POVRayDescription(ostream &os, const CrystalPOVRayOptions &options) const
Definition: Molecule.cpp:3189
ScatteringComponentList mScattCompList
The list of scattering components.
Definition: Molecule.h:1123
MDAtomGroup()
Default constructor.
Definition: Molecule.cpp:1851
void Print(ostream &os, bool full=true) const
Print one-line list of atoms moved.
Definition: Molecule.cpp:1869
std::list< StretchMode * > mvpStretchModeNotFree
Groups of StretchMode breaking restraints (beyond the one they are associated to) ...
Definition: Molecule.h:1331
wxCryst class for Molecule objects
Definition: wxMolecule.h:127
virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false)
This should be called by any optimization class at the begining of an optimization.
Definition: Molecule.cpp:2385
void RotateAtomGroup(const MolAtom &at1, const MolAtom &at2, const set< MolAtom * > &atoms, const REAL angle, const bool keepCenter=true)
Rotate a group of atoms around an axis defined by two atoms.
Definition: Molecule.cpp:4397
MolDihedralAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, MolAtom &atom4, const REAL angle, const REAL sigma, const REAL delta, Molecule &parent)
Constructor.
Definition: Molecule.cpp:930
list< MolRing > mvRing
The list of rings.
Definition: Molecule.h:1156
Structure holding 3 coordinates, or deriviatives with respect to each of these coordinates.
Definition: Molecule.h:43
XYZ mDerivAtom1
Derivatives of the bond length with respect to the coordinates of the atoms.
Definition: Molecule.h:235
Atoms moved when rotated around a bond at0-at1-at2-at3.
Definition: Molecule.h:626
MolAtom * mpAtom2
The second atom.
Definition: Molecule.h:644
list< StretchModeTwist > mvStretchModeTwist
List of StretchModeTwist.
Definition: Molecule.h:1326
void AddDihedralAngle(MolAtom &atom1, MolAtom &atom2, MolAtom &atom3, MolAtom &atom4, const REAL angle, const REAL sigma, const REAL delta, const bool updateDisplay=true)
Add a dihedral angle restraint.
Definition: Molecule.cpp:4022
Rigid groups of atoms inside a molecule.
Definition: Molecule.h:500
virtual int GetNbComponent() const
Number of components in the scatterer (eg number of point scatterers)
Definition: Molecule.cpp:3173
RefinableObjClock & GetBondListClock()
get the clock associated to the list of bonds
Definition: Molecule.cpp:4580
void AddAtom(const REAL x, const REAL y, const REAL z, const ScatteringPower *pPow, const string &name, const bool updateDisplay=true)
Add an atom.
Definition: Molecule.cpp:3786
unsigned int GetNbOption() const
Number of Options for this object.
RefObjOpt & GetOption(const unsigned int i)
Access to the options.
std::vector< MolZAtom > mAsZMatrix
The Molecule, as a lightweight ZMatrix, for export purposes.
Definition: Molecule.h:1356
void CalcGradient(std::map< MolAtom *, XYZ > &m) const
Calc log(likelihood) gradient - versus all atomic coordinates.
Definition: Molecule.cpp:1213
list< StretchModeTorsion > mvStretchModeTorsion
List of StretchModeBondLength.
Definition: Molecule.h:1324
REAL mQ0
The components of the quaternion z=(q0,v) with v=(q1,q2,q3)
Definition: Molecule.h:486
list< RotorGroup > mvRotorGroupTorsion
List of RotorGroups corresponding to free torsion bonds.
Definition: Molecule.h:1261
CrystVector_REAL mLSQCalc
Current LSQ Calc - one value for each restraint (bond distance, angle or dihedral angle) ...
Definition: Molecule.h:1368
MolBond(MolAtom &atom1, MolAtom &atom2, const REAL length, const REAL sigma, const REAL delta, Molecule &parent, const REAL bondOrder=1.)
Constructor.
Definition: Molecule.cpp:347
~Molecule()
Destructor.
Definition: Molecule.cpp:2075
void BuildStretchModeTwist()
Build the groups of atoms used to twist internally the Molecule, e.g.
Definition: Molecule.cpp:6595
virtual void Print(ostream &os, bool full=true) const
Print one-line list of atoms moved.
Definition: Molecule.cpp:1548
void MolecularDynamicsEvolve(std::map< MolAtom *, XYZ > &v0, const unsigned nbStep, const REAL dt, const std::vector< MolBond * > &vb, const std::vector< MolBondAngle * > &va, const std::vector< MolDihedralAngle * > &vd, std::map< RigidGroup *, std::pair< XYZ, XYZ > > &vr, REAL nrj0=0)
Change the conformation of the molecule using molecular dynamics principles.
Definition: Molecule.cpp:4278
REAL GetZ() const
Z coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:105
std::map< const MolDihedralAngle *, REAL > mvpBrokenDihedralAngle
List of dihedral angle restraints modified by this mode The key is the restraint, the value is the de...
Definition: Molecule.h:546
void BuildStretchModeBondAngle()
Build the groups of atoms moved when changing a bond angle, while respecting the Molecule restraints...
Definition: Molecule.cpp:5844
void BuildRingRecursive(MolAtom *currentAtom, MolAtom *previousAtom, const map< MolAtom *, set< MolAtom * > > &connect, list< MolAtom * > &atomlist, map< set< MolAtom * >, list< MolAtom * > > &ringlist)
Find rings, starting from a one atom, and given a connectivity table.
Definition: Molecule.cpp:5221
ObjRegistry< Crystal > gCrystalRegistry("List of all Crystals")
Global registry for all Crystal objects.
Definition: Crystal.h:525
REAL GetOccupancy() const
Get the occupancy of the scatterer (0.
Definition: Scatterer.cpp:106
const MolAtom * GetCenterAtom() const
Get the atom defining the origin of the Molecule Equal to 0 if no atom as been set.
Definition: Molecule.cpp:5029
Abstract base class for all objects in wxCryst.
Definition: wxCryst.h:127
virtual const CrystVector_REAL & GetLSQWeight(const unsigned int) const
Get the weight values for the LSQ function.
Definition: Molecule.cpp:3103
Base object for Monte-Carlo Global Optimization methods.
Quaternion operator*(const Quaternion &q) const
Quaternion multiplication.
Definition: Molecule.cpp:1349
const ScatteringPower * mpScattPow
ScatteringPower.
Definition: Molecule.h:127
virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true)
Move the atoms according to this mode, randomly.
Definition: Molecule.cpp:1835
string mName
Name for this RefinableObject. Should be unique, at least in the same scope.+.
void BuildStretchModeGroups()
Separate StretchMode that break more than their assigned restraint from others.
Definition: Molecule.cpp:7213
const std::vector< MolZAtom > & AsZMatrix(const bool keeporder) const
Molecule as Z-matrix.
Definition: Molecule.cpp:5116
virtual void GLInitDisplayList(const bool onlyIndependentAtoms=false, const REAL xMin=-.1, const REAL xMax=1.1, const REAL yMin=-.1, const REAL yMax=1.1, const REAL zMin=-.1, const REAL zMax=1.1, const bool displayEnantiomer=false, const bool displayNames=false, const bool hideHydrogens=false) const
Definition: Molecule.cpp:3398
virtual const CrystVector_REAL & GetLSQDeriv(const unsigned int, RefinablePar &)
Get the first derivative values for the LSQ function, for a given parameter.
void BuildMDAtomGroups()
Find groups of atoms that cannot be moved relatively to each other using the free or non-free stretch...
Definition: Molecule.cpp:7368
virtual Molecule * CreateCopy() const
Definition: Molecule.cpp:2100
static Quaternion RotationQuaternion(const REAL ang, const REAL v1, const REAL v2, const REAL v3)
Create a rotation quaternion around a given vector for a given angle.
Definition: Molecule.cpp:1334
Quaternion GetConjugate() const
Get the conjugate of this quaternion (== the inverse if unit quaternion)
Definition: Molecule.cpp:1345
void SetIsInRing(const bool r) const
Flag this atom as being in a ring (or not).
Definition: Molecule.cpp:327
virtual REAL GetLogLikelihood() const
Get -ln(likelihood) for this restraint.
Definition: Molecule.cpp:745
virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true)
Move the atoms according to this mode, randomly.
Definition: Molecule.cpp:1677
virtual ~MolBondAngle()
Destructor.
Definition: Molecule.cpp:639
REAL mX
Cartesian oordinates in the Molecule reference frame.
Definition: Molecule.h:123
REAL mDerivLLKCoeff
The factor used to change the derivative of the length/angle, to the derivative of the log(likelihood...
Definition: Molecule.h:417
REAL mLogLikelihood
The current log(likelihood)
Definition: Molecule.h:1359
REAL GetBondAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3)
Get The Bond Angle of 3 atoms.
Definition: Molecule.cpp:95
virtual void Stretch(const REAL change, const bool keepCenter=true)
Move the atoms according to this mode.
Definition: Molecule.cpp:1749
Defines a group of atoms which can be rotated around an axis defined by two other atoms...
Definition: Molecule.h:1234
Molecule : class for complex scatterer descriptions using cartesian coordinates with bond length/angl...
Definition: Molecule.h:731
vector< MolAtom * >::reverse_iterator FindAtom(const string &name)
Search a MolAtom from its name.
Definition: Molecule.cpp:7630
Class to store POV-Ray output options.
Definition: General.h:175
Molecule(Crystal &cryst, const string &name="")
Constructor.
Definition: Molecule.cpp:1894
Molecule * mpMol
Parent Molecule.
Definition: Molecule.h:129
const MolDihedralAngle * mpDihedralAngle
The (optional) bond angle restraint which this stretch mode should respect.
Definition: Molecule.h:647
void BuildStretchModeBondLength()
Build the groups of atoms moved when stretching a bond length, while respecting the Molecule restrain...
Definition: Molecule.cpp:5572
void RestoreParamSet(const unsigned long id)
Restore a saved set of values.
vector< MolBondAngle * >::iterator RemoveBondAngle(const MolBondAngle &, const bool del=true)
Remove a BondAngle.
Definition: Molecule.cpp:3988
set< MolAtom * > mvTranslatedAtomList
The set of atoms that are to be translated, including at1.
Definition: Molecule.h:588
void FlipAtomGroup(const FlipGroup &, const bool keepCenter=true)
Flip a group of atom. See Molecule::FlipGroup.
Definition: Molecule.cpp:7722
void SetAlgorithmParallTempering(const AnnealingSchedule scheduleTemp, const REAL tMax, const REAL tMin, const AnnealingSchedule scheduleMutation=ANNEALING_CONSTANT, const REAL mutMax=16., const REAL mutMin=.125)
Set the refinement method to Parallel Tempering.
RefinableObjClock mClockScattCompList
Definition: Scatterer.h:287
void AssignClock(RefinableObjClock &clock)
bool mShowHydrogens
Show hydrogens ?
Definition: General.h:182
vector< Restraint * > mvpRestraint
Vector of pointers to the restraints for this object.
virtual string GetComponentName(const int i) const
Name for the i-th component of this scatterer.
Definition: Molecule.cpp:3183
void XMLOutput(ostream &os, int indent=0) const
XMLOutput to stream in well-formed XML.
REAL GetX() const
X coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:103
Vector library (Blitz++ mimic) for ObjCryst++.
Definition: CrystVector.h:122
void UpdateScattCompList() const
Update the Molecule::mScattCompList from the cartesian coordinates of all atoms, and the orientation ...
Definition: Molecule.cpp:7527
virtual void XMLInput(istream &is, const XMLCrystTag &tag)
Input From stream.
Definition: Molecule.cpp:2267
virtual unsigned int GetNbLSQFunction() const
Number of LSQ functions.
Definition: Molecule.cpp:3072
REAL mDerivLLKCoeff
The factor used to change the derivative of the length/angle, to the derivative of the log(likelihood...
Definition: Molecule.h:329
Molecule * mpMol
Parent Molecule.
Definition: Molecule.h:406
MolAtom * mpAtom2
The second atom.
Definition: Molecule.h:675
void Normalize() const
Re-normalize the quaternion to unity.
Definition: Molecule.cpp:1472
REAL mOccupancy
Occupancy : 0 <= occ <= 1 For a multi-atom scatterer (polyhedron,..), this is the overall occupancy o...
Definition: Scatterer.h:279
XYZ mDerivAtom1
Partial derivatives of the angle with respect to the coordinates of the atoms.
Definition: Molecule.h:413
REAL LorentzianBiasedRandomMove(const REAL x0, const REAL sigma, const REAL delta, const REAL amplitude)
Random move respecting a gaussian probability distribution with a flat top.
Definition: Molecule.cpp:4695
void CalcGradient(std::map< MolAtom *, XYZ > &m) const
Calc log(likelihood) gradient - versus all atomic coordinates.
Definition: Molecule.cpp:545
REAL GetDynPopCorr(const Scatterer *pscatt, unsigned int component) const
Access the Dynamical Occupancy Correction for a given component (atom) in a given Scatterer...
Definition: Crystal.cpp:773
void RotateVector(REAL &v1, REAL &v2, REAL &v3) const
Rotate vector v=(v1,v2,v3). The rotated components are directly written.
Definition: Molecule.cpp:1449
virtual void RandomizeConfiguration()
Randomize Configuration (before a global optimization).
MolAtom : atom inside a Molecule.
Definition: Molecule.h:58
void SetCenterAtom(const MolAtom &at)
Get the atom defining the origin of the Molecule Equal to 0 if no atom as been set.
Definition: Molecule.cpp:5034
REAL mLLKDeriv
Derivative of the Molecule's Log(likelihood) versus a change of the bond length.
Definition: Molecule.h:548
REAL GetDihedralAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3, const MolAtom &at4)
Get The dihedral angle defined by 4 atoms.
Definition: Molecule.cpp:111
REAL GetDeriv(const std::map< const MolAtom *, XYZ > &m, const bool llk=false) const
Get the derivative of the bond length, given the derivatives of the atom positions This requires that...
Definition: Molecule.cpp:526
REAL mBaseAmplitude
The recommended change amplitude, for a base global optimization displacement, to obtain an average 0...
Definition: Molecule.h:560
const map< MolAtom *, set< MolAtom * > > & GetConnectivityTable()
Get the connectivity table.
Definition: Molecule.cpp:4574
RefObjOpt mFlexModel
OPtion for the different types of flexibility possible for this molecule: rigid body, free atoms + restraints, torsion angles...
Definition: Molecule.h:1201
void InitOptions()
Build options for this object.
Definition: Molecule.cpp:7651
vector< MolAtom * >::iterator RemoveAtom(MolAtom &, const bool del=true)
Remove an atom.
Definition: Molecule.cpp:3842
virtual ~MolDihedralAngle()
Destructor.
Definition: Molecule.cpp:951
REAL mLogLikelihoodScale
Scale (multiplier) for the log(likelihood)
Definition: Molecule.h:1366
virtual void InitRefParList()
Definition: Molecule.cpp:5208
Quaternion mQuat
The unit quaternion defining the orientation.
Definition: Molecule.h:1160
void AddRigidGroup(const RigidGroup &, const bool updateDisplay=true)
Add a rigid group of atoms.
Definition: Molecule.cpp:4073
MolAtom * mpAtom0
The first atom.
Definition: Molecule.h:611
const MolBond * mpBond
The (optional) bond length which this stretch mode should respect.
Definition: Molecule.h:586
virtual void XMLOutput(ostream &os, int indent=0) const
Output to stream in well-formed XML.
Definition: Molecule.cpp:2167
REAL GetDeriv(const std::map< const MolAtom *, XYZ > &m, const bool llk=false) const
Get the derivative of the angle, given the derivatives of the atom positions This requires that GetLo...
Definition: Molecule.cpp:839
RefinableObjClock & GetRigidGroupClock()
Get the clock associated to the list of rigid groups (clicked also whenever a rigid group is modified...
Definition: Molecule.cpp:4586
list< RotorGroup > mvRotorGroupInternal
List of RotorGroups for internal rotations.
Definition: Molecule.h:1276
const MolBondAngle * mpBondAngle
The (optional) bond angle restraint which this stretch mode should respect.
Definition: Molecule.h:617
Molecule * mpMol
Parent Molecule.
Definition: Molecule.h:228
string mName
Name for this atom.
Definition: Molecule.h:114
void SetDeleteSubObjInDestructor(const bool b)
Set whether to delete the MolAtoms, MolBonds, MolBondAngles and MolDihedralAngles in the destructor...
Definition: Molecule.cpp:7802
void CalcGradient(std::map< MolAtom *, XYZ > &m) const
Calc log(likelihood) gradient - versus all atomic coordinates.
Definition: Molecule.cpp:863
std::map< const MolBond *, REAL > mvpBrokenBond
List of bond restraints affected by this mode The key is the restraint, the value is the derivative o...
Definition: Molecule.h:540
list< RotorGroup > mvRotorGroupTorsionSingleChain
List of RotorGroups corresponding to free torsion bonds, but with only one chain of atoms listed...
Definition: Molecule.h:1270
Dihedral angle restraint between 4 atoms.
Definition: Molecule.h:346
void ClearParamSet(const unsigned long id) const
Erase the param set with the given id, releasing memory.
virtual void RandomizeConfiguration()
Randomize Configuration (before a global optimization).
Definition: Molecule.cpp:2539
vector< MolBondAngle * > mvpBondAngle
The list of bond angles.
Definition: Molecule.h:1137
virtual void SetName(const string &name)
Name of the object.
Definition: Molecule.cpp:2112
std::list< StretchMode * > mvpStretchModeFree
Groups of StretchMode not breaking any restraint (unless the one they are associated to) ...
Definition: Molecule.h:1329
list< FlipGroup > mvFlipGroup
The list of FlipGroups.
Definition: Molecule.h:1316
virtual void CalcDeriv(const bool derivllk=true) const
Calculate the derivative of the Molecule's Log(likelihood) and atomic positions versus a change of th...
Definition: Molecule.cpp:1775
const Crystal & GetCrystal() const
In which crystal is this Scatterer included ?
Definition: Scatterer.cpp:137
virtual REAL GetLogLikelihood() const
Get -log(likelihood) of the current configuration for the object.
Definition: Molecule.cpp:3058
bool IsDescendantFromOrSameAs(const RefParType *type) const
Returns true if the parameter is a descendant of 'type'.
void Reset()
Reset a Clock to 0, to force an update.
virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true)
Move the atoms according to this mode, randomly.
Definition: Molecule.cpp:1754
Exception class for ObjCryst++ library.
Definition: General.h:119
vector< MolBondAngle * >::const_iterator FindBondAngle(const MolAtom &at1, const MolAtom &at0, const MolAtom &at2) const
Searches whether a bond between three atoms already exists, searching for either (at1,at2,at3) and (at3,at2,at1), as these are equivalent.
Definition: Molecule.cpp:4007
virtual void EndOptimization()
This should be called by any optimization class at the end of an optimization.
virtual const CrystVector_REAL & GetLSQCalc(const unsigned int) const
Get the current calculated value for the LSQ function.
Definition: Molecule.cpp:3077
Cubic spline interpolation.
Definition: CrystVector.h:564
RefObjOpt mAutoOptimizeConformation
Option to automatically optimize the starting conformation, if the total restraint cost is too high...
Definition: Molecule.h:1211
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: Atom.cpp:47
REAL mMDMoveFreq
Frequency of using molecular dynamics move during GlobalOptRandomMove()
Definition: Molecule.h:1350
virtual void EndOptimization()
This should be called by any optimization class at the end of an optimization.
Definition: Molecule.cpp:2512
StretchModeTorsion(MolAtom &at1, MolAtom &at2, const MolDihedralAngle *pDihedralAngle)
Constructor If pDihedralAngle!=0, the dihedral angle length restraint is respected.
Definition: Molecule.cpp:1683
std::map< const MolBondAngle *, REAL > mvpBrokenBondAngle
List of bond angle restraints modified by this mode The key is the restraint, the value is the deriva...
Definition: Molecule.h:543
void BuildConnectivityTable() const
Build the Connectivity table.
Definition: Molecule.cpp:5299
std::string GetFormula() const
Formula with atoms in alphabetic order.
Definition: Molecule.cpp:2134
virtual REAL GetLogLikelihood() const
Get -log(likelihood) of the current configuration for the object.
Generic class for parameters of refinable objects.
Definition: RefinableObj.h:223
virtual const ScatteringComponentList & GetScatteringComponentList() const
Get the list of all scattering components for this scatterer.
Definition: Molecule.cpp:3175
REAL BondLengthRandomChange(const StretchModeBondLength &mode, const REAL amplitude, const bool respectRestraint=true)
Stretch a bond, while respecting the Restraint (if any).
Definition: Molecule.cpp:4887
virtual const string & GetName() const
Name of the object.
virtual void Stretch(const REAL change, const bool keepCenter=true)
Move the atoms according to this mode.
Definition: Molecule.cpp:1661
const std::vector< RigidGroup * > & GetRigidGroupList() const
List of rigid group of atoms.
Definition: Molecule.cpp:4394
virtual void RandomStretch(const REAL amplitude, const bool keepCenter=true)
Move the atoms according to this mode, randomly.
Definition: Molecule.cpp:1577
set< MolAtom * > mvRotatedAtomList
The set of atoms that are to be rotated around at1-at2.
Definition: Molecule.h:649
void ExpandAtomGroupRecursive(MolAtom *atom, const map< MolAtom *, set< MolAtom * > > &connect, set< MolAtom * > &atomlist, const MolAtom *finalAtom)
Build recursively a list of atoms, starting from a one atom, and given a connectivity table...
Definition: Molecule.cpp:151
void BuildRingList()
Build the list of rings in the molecule.
Definition: Molecule.cpp:5259
virtual void Print(ostream &os, bool full=true) const
Print one-line list of atoms moved.
Definition: Molecule.cpp:1816
void RestraintStatus(ostream &os) const
Print the status of all restraints (bond length, angles...)
Definition: Molecule.cpp:4551
set< MolAtom * > mvRotatedAtomList
The set of atoms that are to be rotated around at1-at2.
Definition: Molecule.h:677
void AddRestraint(Restraint *pNewRestraint)
Add a new restraint.
virtual ~MolBond()
Destructor.
Definition: Molecule.cpp:358
MolAtom * mpAtom1
The second atom.
Definition: Molecule.h:613
void SetX(const REAL) const
Set the X,Y,Z coordinate - this is const because sometimes their coordinate must be changed even thou...
Definition: Molecule.cpp:244
virtual void UpdateDisplay() const
If there is an interface, this should be automatically be called each time there is a 'new...
Definition: Molecule.cpp:2379
RefinableObjClock & GetAtomPositionClock()
Get the clock associated to the atomic positions.
Definition: Molecule.cpp:4583
Groups of atoms that can be moved using molecular dynamics principles, taking a list of restraints as...
Definition: Molecule.h:685
RefObjOpt mMoleculeCenter
Option to choose the center of rotation of the Molecule for the global orientation either as the geom...
Definition: Molecule.h:1221
Crystal class: Unit cell, spacegroup, scatterers.
Definition: Crystal.h:97
vector< MolBond * >::iterator RemoveBond(const MolBond &, const bool del=true)
Remove a bond.
Definition: Molecule.cpp:3936
vector< RefinablePar * >::iterator RemovePar(RefinablePar *refPar)
Remove a refinable parameter.
vector< MolDihedralAngle * > mvpDihedralAngle
The list of dihedral angles.
Definition: Molecule.h:1141
const MolAtom * mpAtom2
The second atom defining the rotation axis.
Definition: Molecule.h:1297
REAL GetY() const
Y coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:104
virtual void CalcDeriv(const bool derivllk=true) const
Calculate the derivative of the Molecule's Log(likelihood) and atomic positions versus a change of th...
Definition: Molecule.cpp:1593
class to input or output a well-formatted xml beginning or ending tag.
ObjRegistry< RefObjOpt > mOptionRegistry
List of options for this object.
Group of atoms for random moves changing a bond length.
Definition: Molecule.h:567
CrystVector_REAL mLSQWeight
Current LSQ Calc - one value for each restraint(bond distance, angle or dihedral angle sigmas) ...
Definition: Molecule.h:1372
MolAtom * mpAtom1
The first atom.
Definition: Molecule.h:642
RefinableObjClock mClockScatterer
Last time anything (number of atoms, positions, scattering power) was changed.
Definition: Scatterer.h:285
list< pair< const MolAtom *, set< MolAtom * > > > mvRotatedChainList
The set of atoms that are to be rotated during the flip.
Definition: Molecule.h:1304
ScatteringPower & GetScatteringPower(const string &name)
Find a ScatteringPower from its name. Names must be unique in a given Crystal.
Definition: Crystal.cpp:270
class of refinable parameter types.
Definition: RefinableObj.h:78
list of scattering positions in a crystal, associated with the corresponding occupancy and a pointer ...
REAL GetDeriv(const std::map< const MolAtom *, XYZ > &m, const bool llk=false) const
Get the derivative of the Angle, given the derivatives of the atom positions This requires that GetLo...
Definition: Molecule.cpp:1184
virtual void Print() const
Print some info about the scatterer (ideally this should be one line...).
Definition: Molecule.cpp:2161
unsigned long CreateParamSet(const string name="") const
Save the current set of refined values in a new set.
REAL mMDMoveEnergy
Relative energy of molecule during molecular dynamics move Default: 40, 10 (slow conformation change)...
Definition: Molecule.h:1353
void SetName(const string &)
Set the name of the parameter. It should be unique in the RefinableObj.
virtual void CalcDeriv(const bool derivllk=true) const
Calculate the derivative of the Molecule's Log(likelihood) and atomic positions versus a change of th...
Definition: Molecule.cpp:1514
Crystal * mpCryst
The crystal in which the Scatterer is This is needed so that we can know which scattering powers are ...
Definition: Scatterer.h:294
MolAtom * mpAtom0
The first atom (fixed).
Definition: Molecule.h:582
std::set< MolAtom * > mvMDFullAtomGroup
Full list of atoms that can be moved using molecular dynamics This excludes any atom part of a rigid ...
Definition: Molecule.h:1347
void RigidifyWithDihedralAngles()
Add dihedral angles so as to rigidify the Molecule.
Definition: Molecule.cpp:4589
Quaternion()
Default constructor, yields q=(1,0,0,0)
Definition: Molecule.cpp:1312
REAL BondAngleRandomChange(const StretchModeBondAngle &mode, const REAL amplitude, const bool respectRestraint=true)
change a bond angle, while respecting the Restraint (if any).
Definition: Molecule.cpp:4931
void AddOption(RefObjOpt *opt)
void SetGlobalOptimStep(const REAL)
Maximum step to use during Global Optimization algorithms.
list< StretchModeBondAngle > mvStretchModeBondAngle
List of StretchModeBondLength.
Definition: Molecule.h:1322
void TranslateAtomGroup(const set< MolAtom * > &atoms, const REAL dx, const REAL dy, const REAL dz, const bool keepCenter=true)
Translate a group of atoms in a given direction.
Definition: Molecule.cpp:4499
virtual void SetName(const string &name)
Name of the object.
void AddBond(MolAtom &atom1, MolAtom &atom2, const REAL length, const REAL sigma, const REAL delta, const REAL bondOrder=1., const bool updateDisplay=true)
Add a bond.
Definition: Molecule.cpp:3923
bool IsDummy() const
Returns true if this is a dummy atom, i.e.
Definition: Molecule.cpp:249
Atoms moved between two other atoms, using a "twist" of their positions - only small twists of their ...
Definition: Molecule.h:658
When 3(A1..1n) or more atoms are connected to a same atom A, it defines a 'flip' group, where it is possible to rotate bonds to their symmetric with respect to one plane defined by atoms Ai-A-Aj.
Definition: Molecule.h:1287
void XMLOutput(ostream &os, const string &name, int indent=0) const
XMLOutput to stream in well-formed XML.
RefObjOpt mOptimizeOrientation
Option to optimize the Molecule's orientation.
Definition: Molecule.h:1216
vector< MolAtom * > mvpAtom
The vector of the 4 atoms involved in the bond angle.
Definition: Molecule.h:403
void OptimizeConformationSteepestDescent(const REAL maxStep=0.1, const unsigned nbStep=1)
Optimize the conformation from internal restraints (bond lengths, angles and dihedral angles)...
Definition: Molecule.cpp:4202
void OptimizeConformation(const long nbTrial=10000, const REAL stopCost=0.)
Minimize configuration from internal restraints (bond lengths, angles and dihedral angles)...
Definition: Molecule.cpp:4184
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal...