FOX/ObjCryst++  1.10.X (development)
Crystal.cpp
1 /* ObjCryst++ Object-Oriented Crystallographic Library
2  (c) 2000-2002 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; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 /*
20 * source file LibCryst++ Crystal class
21 *
22 */
23 
24 #include <cmath>
25 #include <set>
26 #include <vector>
27 #include <typeinfo>
28 
29 #include "cctbx/sgtbx/space_group.h"
30 
31 #include "ObjCryst/ObjCryst/Crystal.h"
32 #include "ObjCryst/ObjCryst/Molecule.h"
33 #include "ObjCryst/ObjCryst/Atom.h"
34 
35 #include "ObjCryst/Quirks/VFNStreamFormat.h" //simple formatting of integers, REALs..
36 #include "ObjCryst/Quirks/VFNDebug.h"
37 
38 #ifdef __WX__CRYST__
39  #include "ObjCryst/wxCryst/wxCrystal.h"
40 #endif
41 
42 #include <fstream>
43 #include <iomanip>
44 
45 namespace ObjCryst
46 {
47 const RefParType *gpRefParTypeCrystal=0;
48 long NiftyStaticGlobalObjectsInitializer_Crystal::mCount=0;
50 //
51 // CRYSTAL : the crystal (Unit cell, spaceGroup, scatterers)
52 //
54 ObjRegistry<Crystal> gCrystalRegistry("List of all Crystals");
55 
57 mScattererRegistry("List of Crystal Scatterers"),
58 mBumpMergeCost(0.0),mBumpMergeScale(1.0),
59 mDistTableMaxDistance(1.0),
60 mScatteringPowerRegistry("List of Crystal ScatteringPowers"),
61 mBondValenceCost(0.0),mBondValenceCostScale(1.0),mDeleteSubObjInDestructor(1)
62 {
63  VFN_DEBUG_MESSAGE("Crystal::Crystal()",10)
64  this->InitOptions();
65  this->Init(10,11,12,M_PI/2+.1,M_PI/2+.2,M_PI/2+.3,"P1","");
66  gCrystalRegistry.Register(*this);
67  gTopRefinableObjRegistry.Register(*this);
69  mClockMaster.AddChild(this->mScattererRegistry.GetRegistryClock());
70  mClockMaster.AddChild(this->mScatteringPowerRegistry.GetRegistryClock());
71 }
72 
73 Crystal::Crystal(const REAL a, const REAL b, const REAL c, const string &SpaceGroupId):
74 mScattererRegistry("List of Crystal Scatterers"),
75 mBumpMergeCost(0.0),mBumpMergeScale(1.0),
76 mDistTableMaxDistance(1.0),
77 mScatteringPowerRegistry("List of Crystal ScatteringPowers"),
78 mBondValenceCost(0.0),mBondValenceCostScale(1.0),mDeleteSubObjInDestructor(1)
79 {
80  VFN_DEBUG_MESSAGE("Crystal::Crystal(a,b,c,Sg)",10)
81  this->Init(a,b,c,M_PI/2,M_PI/2,M_PI/2,SpaceGroupId,"");
82  this->InitOptions();
83  gCrystalRegistry.Register(*this);
84  gTopRefinableObjRegistry.Register(*this);
86  mClockMaster.AddChild(this->mScattererRegistry.GetRegistryClock());
87  mClockMaster.AddChild(this->mScatteringPowerRegistry.GetRegistryClock());
88 }
89 
90 Crystal::Crystal(const REAL a, const REAL b, const REAL c, const REAL alpha,
91  const REAL beta, const REAL gamma,const string &SpaceGroupId):
92 mScattererRegistry("List of Crystal Scatterers"),
93 mBumpMergeCost(0.0),mBumpMergeScale(1.0),
94 mDistTableMaxDistance(1.0),
95 mScatteringPowerRegistry("List of Crystal ScatteringPowers"),
96 mBondValenceCost(0.0),mBondValenceCostScale(1.0),mDeleteSubObjInDestructor(1)
97 {
98  VFN_DEBUG_MESSAGE("Crystal::Crystal(a,b,c,alpha,beta,gamma,Sg)",10)
99  this->Init(a,b,c,alpha,beta,gamma,SpaceGroupId,"");
100  this->InitOptions();
101  gCrystalRegistry.Register(*this);
102  gTopRefinableObjRegistry.Register(*this);
104  mClockMaster.AddChild(this->mScattererRegistry.GetRegistryClock());
105  mClockMaster.AddChild(this->mScatteringPowerRegistry.GetRegistryClock());
106 }
107 
109 mScattererRegistry("List of Crystal Scatterers"),
110 mBumpMergeCost(0.0),mBumpMergeScale(1.0),
111 mDistTableMaxDistance(1.0),
112 mScatteringPowerRegistry("List of Crystal ScatteringPowers"),
113 mBondValenceCost(0.0),mBondValenceCostScale(1.0),mDeleteSubObjInDestructor(1)
114 {
115  VFN_DEBUG_MESSAGE("Crystal::Crystal()",10)
116  // Only create a default crystal, then copy old using XML
117  this->InitOptions();
118  this->Init(10,11,12,M_PI/2+.1,M_PI/2+.2,M_PI/2+.3,"P1","");
119  gCrystalRegistry.Register(*this);
120  gTopRefinableObjRegistry.Register(*this);
122  mClockMaster.AddChild(this->mScattererRegistry.GetRegistryClock());
123  mClockMaster.AddChild(this->mScatteringPowerRegistry.GetRegistryClock());
124 
125  stringstream sst;
126  old.XMLOutput(sst);
127  XMLCrystTag tag(sst);
128  this->XMLInput(sst,tag);
129 }
130 
132 {
133  VFN_DEBUG_ENTRY("Crystal::~Crystal()",5)
134  for(long i=0;i<mScattererRegistry.GetNb();i++)
135  {
136  VFN_DEBUG_MESSAGE("Crystal::~Crystal(&scatt):1:"<<i,5)
137  this->RemoveSubRefObj(mScattererRegistry.GetObj(i));
138  mScattererRegistry.GetObj(i).DeRegisterClient(*this);
139  }
140  if( mDeleteSubObjInDestructor )
141  {
142  mScattererRegistry.DeleteAll();
143  }
144  else
145  {
146  mScattererRegistry.DeRegisterAll();
147  }
148  for(long i=0;i<mScatteringPowerRegistry.GetNb();i++)
149  {
150  VFN_DEBUG_MESSAGE("Crystal::~Crystal(&scatt):2:"<<i,5)
151  this->RemoveSubRefObj(mScatteringPowerRegistry.GetObj(i));
152  mScatteringPowerRegistry.GetObj(i).DeRegisterClient(*this);
153  // :TODO: check if it is not used by another Crystal (forbidden!)
154  }
155  if( mDeleteSubObjInDestructor )
156  {
157  mScatteringPowerRegistry.DeleteAll();
158  }
159  else
160  {
161  mScatteringPowerRegistry.DeRegisterAll();
162  }
163  gCrystalRegistry.DeRegister(*this);
164  gTopRefinableObjRegistry.DeRegister(*this);
165  VFN_DEBUG_EXIT("Crystal::~Crystal()",5)
166 }
167 
168 const string& Crystal::GetClassName() const
169 {
170  const static string className="Crystal";
171  return className;
172 }
173 
175 {
176  VFN_DEBUG_ENTRY("Crystal::AddScatterer(&scatt)",5)
177  mScattererRegistry.Register(*scatt);
178  scatt->RegisterClient(*this);
179  this->AddSubRefObj(*scatt);
180  scatt->SetCrystal(*this);
182  VFN_DEBUG_EXIT("Crystal::AddScatterer(&scatt):Finished",5)
183 }
184 
185 void Crystal::RemoveScatterer(Scatterer *scatt, const bool del)
186 {
187  VFN_DEBUG_MESSAGE("Crystal::RemoveScatterer(&scatt)",5)
188  mScattererRegistry.DeRegister(*scatt);
189  scatt->DeRegisterClient(*this);
190  this->RemoveSubRefObj(*scatt);
191  if(del) delete scatt;
193  VFN_DEBUG_MESSAGE("Crystal::RemoveScatterer(&scatt):Finished",5)
194 }
195 
196 long Crystal::GetNbScatterer()const {return mScattererRegistry.GetNb();}
197 
198 Scatterer& Crystal::GetScatt(const string &scattName)
199 {
200  return mScattererRegistry.GetObj(scattName);
201 }
202 
203 const Scatterer& Crystal::GetScatt(const string &scattName) const
204 {
205  return mScattererRegistry.GetObj(scattName);
206 }
207 
208 Scatterer& Crystal::GetScatt(const long scattIndex)
209 {
210  return mScattererRegistry.GetObj(scattIndex);
211 }
212 
213 const Scatterer& Crystal::GetScatt(const long scattIndex) const
214 {
215  return mScattererRegistry.GetObj(scattIndex);
216 }
217 
219 
221 
223 {return mScatteringPowerRegistry;}
225 {return mScatteringPowerRegistry;}
226 
228 {
229  mScatteringPowerRegistry.Register(*scattPow);
230  scattPow->RegisterClient(*this);//:TODO: Should register as (unique) 'owner'.
231  this->AddSubRefObj(*scattPow);
232  mClockMaster.AddChild(scattPow->GetClockMaster());
235 }
236 
237 void Crystal::RemoveScatteringPower(ScatteringPower *scattPow, const bool del)
238 {
239  VFN_DEBUG_ENTRY("Crystal::RemoveScatteringPower()",2)
240  mScatteringPowerRegistry.DeRegister(*scattPow);
241  this->RemoveSubRefObj(*scattPow);
245  if(del) delete scattPow;
246 
247  for(Crystal::VBumpMergePar::iterator pos=mvBumpMergePar.begin();pos!=mvBumpMergePar.end();)
248  {
249  if((pos->first.first==scattPow)||(pos->first.second==scattPow))
250  {
251  mvBumpMergePar.erase(pos++);
253  }
254  else ++pos;// See Josuttis Std C++ Lib p.205 for safe method
255  }
256 
257  for(map<pair<const ScatteringPower*,const ScatteringPower*>, REAL>::iterator
258  pos=mvBondValenceRo.begin();pos!=mvBondValenceRo.end();)
259  {
260  if((pos->first.first==scattPow)||(pos->first.second==scattPow))
261  {
262  mvBondValenceRo.erase(pos++);
264  }
265  else ++pos;// See Josuttis Std C++ Lib p.205 for safe method
266  }
267  VFN_DEBUG_EXIT("Crystal::RemoveScatteringPower()",2)
268 }
269 
271 {
272  return mScatteringPowerRegistry.GetObj(name);
273 }
274 
275 const ScatteringPower& Crystal::GetScatteringPower(const string &name)const
276 {
277  return mScatteringPowerRegistry.GetObj(name);
278 }
279 
282 
284 {
286  bool update=false;
287  if(mClockScattCompList<this->GetClockLatticePar()) update=true;
288  if(update==false)
289  for(long i=0;i<mScattererRegistry.GetNb();i++)
290  {
291  //mClockScattCompList.Print();
292  //this->GetScatt(i).GetClockScatterer().Print();
293  if(mClockScattCompList<this->GetScatt(i).GetClockScatterer()) {update=true;break;}
294  }
295  if(true==update)
296  {
297  VFN_DEBUG_MESSAGE("Crystal::GetScatteringComponentList()",2)
298  TAU_PROFILE("Crystal::GetScatteringComponentList()","ScattCompList& ()",TAU_DEFAULT);
300  for(long i=0;i<mScattererRegistry.GetNb();i++)
301  {
302  //this->GetScatt(i).GetScatteringComponentList().Print();
304  }
305 
306  //:KLUDGE: this must be *before* calling CalcDynPopCorr() to avoid an infinite loop..
308 
309  if(1==mUseDynPopCorr.GetChoice())
310  this->CalcDynPopCorr(1.,.5); else this->ResetDynPopCorr();
311  VFN_DEBUG_MESSAGE("Crystal::GetScatteringComponentList():End",2)
312  }
313  #ifdef __DEBUG__
314  if(gVFNDebugMessageLevel<2) mScattCompList.Print();
315  #endif
316  return mScattCompList;
317 }
318 
320 {
321  return mClockScattCompList;
322 }
323 
324 void Crystal::Print(ostream &os)const
325 {
326  VFN_DEBUG_MESSAGE("Crystal::Print()",5)
327  this->UnitCell::Print(os);
328 
330  this->CalcBondValenceSum();
331 
332  os << "List of scattering components (atoms): " << mScattCompList.GetNbComponent() << endl ;
333 
334  long k=0;
335  std::map<long, REAL>::const_iterator posBV;
336  for(int i=0;i<mScattererRegistry.GetNb();i++)
337  {
338  //mpScatterrer[i]->Print();
340  for(int j=0;j<list.GetNbComponent();j++)
341  {
342  os << FormatString(this->GetScatt(i).GetComponentName(j),16) << " at : "
343  << FormatFloat(list(j).mX,7,4)
344  << FormatFloat(list(j).mY,7,4)
345  << FormatFloat(list(j).mZ,7,4)
346  << ", Occup=" << FormatFloat(list(j).mOccupancy,6,4)
347  << " * " << FormatFloat(mScattCompList(k).mDynPopCorr,6,4);
348  // Check for dummy atoms
349  if( NULL != list(j).mpScattPow )
350  {
351  os << ", ScattPow:" << FormatString(list(j).mpScattPow->GetName(),16)
352  << ", Biso=" << FormatFloat(list(j).mpScattPow->GetBiso());
353  }
354  else
355  {
356  os << ", ScattPow: dummy";
357  }
358  // Check for dummy atoms
359  if( NULL != this->mScattCompList(k).mpScattPow )
360  {
361  posBV=this->mvBondValenceCalc.find(k);
362  if(posBV!=this->mvBondValenceCalc.end())
363  os <<": Valence="<<posBV->second<<" (expected="
364  <<this->mScattCompList(k).mpScattPow->GetFormalCharge()<<")";
365  }
366  os << endl;
367  k++;
368  }
369  }
370  os <<endl
371  << "Occupancy = occ * dyn, where:"<<endl
372  << " - occ is the 'real' occupancy"<< endl
373  << " - dyn is the dynamical occupancy correction, indicating either"<< endl
374  << " an atom on a special position, or several identical atoms "<< endl
375  << " overlapping (dyn=0.5 -> atom on a symetry plane / 2fold axis.."<< endl
376  << " -> OR 2 atoms strictly overlapping)"<< endl
377  <<endl;
378  REAL nbAtoms=0;
379  const long genMult=this->GetSpaceGroup().GetNbSymmetrics();
380  for(int i=0;i<mScattCompList.GetNbComponent();i++)
381  nbAtoms += genMult * mScattCompList(i).mOccupancy * mScattCompList(i).mDynPopCorr;
382  os << " Total number of components (atoms) in one unit cell : " << nbAtoms<<endl<<endl;
383 
384  VFN_DEBUG_MESSAGE("Crystal::Print():End",5)
385 }
386 
387 CrystMatrix_REAL Crystal::GetMinDistanceTable(const REAL minDistance) const
388 {
389  VFN_DEBUG_MESSAGE("Crystal::MinDistanceTable()",5)
390  this->CalcDistTable(true);
391  const long nbComponent=mScattCompList.GetNbComponent();
392 
393  CrystMatrix_REAL minDistTable(nbComponent,nbComponent);
394  REAL dist;
395  REAL tmp;
396  REAL min=minDistance*minDistance;
397  if(minDistance<0) min = -1.;// no min distance
398  minDistTable=10000.;
399  for(int i=0;i<nbComponent;i++)
400  {
401  //VFN_DEBUG_MESSAGE("Crystal::MinDistanceTable():comp="<<i,10)
402  std::vector<Crystal::Neighbour>::const_iterator pos;
403  for(pos=mvDistTableSq[i].mvNeighbour.begin();
404  pos<mvDistTableSq[i].mvNeighbour.end();pos++)
405  {
406  tmp=pos->mDist2;
407  dist=minDistTable(i,pos->mNeighbourIndex);
408  if( (tmp<dist)
409  && ((tmp>min) || ( (mvDistTableSq[i].mIndex !=pos->mNeighbourIndex)
410  &&(mvDistTableSq[i].mUniquePosSymmetryIndex
411  !=pos->mNeighbourSymmetryIndex))))
412  minDistTable(i,pos->mNeighbourIndex)=tmp;
413  }
414  }
415  for(int i=0;i<nbComponent;i++)
416  {
417  for(int j=0;j<=i;j++)
418  {
419  if(9999.>minDistTable(i,j)) minDistTable(i,j)=sqrt(minDistTable(i,j));
420  else minDistTable(i,j)=-1;
421  minDistTable(j,i)=minDistTable(i,j);
422  }
423  }
424  VFN_DEBUG_MESSAGE("Crystal::MinDistanceTable():End",3)
425  return minDistTable;
426 }
427 
428 void Crystal::PrintMinDistanceTable(const REAL minDistance,ostream &os) const
429 {
430  VFN_DEBUG_MESSAGE("Crystal::PrintMinDistanceTable()",5)
431  CrystMatrix_REAL minDistTable;
432  minDistTable=this->GetMinDistanceTable(minDistance);
433  VFN_DEBUG_MESSAGE("Crystal::PrintMinDistanceTable():0",5)
434  os << "Table of minimal distances between all components (atoms)"<<endl;
435  os << " ";
436  for(long i=0;i<mScattererRegistry.GetNb();i++)
437  {
438  VFN_DEBUG_MESSAGE("Crystal::PrintMinDistanceTable()1:Scatt:"<<i,3)
439  for(long j=0;j<this->GetScatt(i).GetNbComponent();j++)
440  os << FormatString(this->GetScatt(i).GetComponentName(j),7);
441  }
442  os << endl;
443  long l=0;
444  const long nbComponent=mScattCompList.GetNbComponent();
445  for(long i=0;i<mScattererRegistry.GetNb();i++)
446  for(long j=0;j<this->GetScatt(i).GetNbComponent();j++)
447  {
448  VFN_DEBUG_MESSAGE("Crystal::PrintMinDistanceTable()2:Scatt,comp:"<<i<<","<<j,3)
449  os << FormatString(this->GetScatt(i).GetComponentName(j),14);
450  for(long k=0;k<nbComponent;k++)
451  {
452  if(minDistTable(l,k)>0) os << FormatFloat(minDistTable(l,k),6,3) ;
453  else os<<" >10 ";
454  }
455  os << endl;
456  l++;
457  }
458  VFN_DEBUG_MESSAGE("Crystal::PrintMinDistanceTable():End",3)
459 }
460 
461 ostream& Crystal::POVRayDescription(ostream &os,const CrystalPOVRayOptions &options)const
462 {
463  VFN_DEBUG_MESSAGE("Crystal::POVRayDescription(os,bool)",5)
464  os <<"/////////////////////// MACROS////////////////////"<<endl;
465 
466  os << "#macro ObjCrystAtom(atomx,atomy,atomz,atomr,atomc,occ,atten)"
467  << " sphere"<<endl
468  << " { <atomx,atomy,atomz>,atomr"<<endl
469  << " finish {ambient 0.5*occ*atten diffuse 0.4*occ*atten phong occ*atten specular 0.2*occ*atten "
470  << "roughness 0.02 metallic reflection 0.0}"<<endl
471  << " pigment { colour atomc transmit (1-occ*atten)}"<<endl
472  << " no_shadow"<<endl
473  << " }"<<endl
474  << "#end"<<endl<<endl;
475 
476  os << "#macro ObjCrystBond(x1,y1,z1,x2,y2,z2,bondradius,bondColour,occ,atten)"<<endl
477  << " cylinder"<<endl
478  << " { <x1,y1,z1>,"<<endl
479  << " <x2,y2,z2>,"<<endl
480  << " bondradius"<<endl
481  << " finish {ambient 0.5*occ*atten diffuse 0.4*occ*atten phong occ*atten specular 0.2*occ*atten "
482  << "roughness 0.02 metallic reflection 0.0}"<<endl
483  << " pigment { colour bondColour transmit (1-occ*atten)}"<<endl
484  << " no_shadow"<<endl
485  << " }"<<endl
486  << "#end"<<endl<<endl;
487 
488  os <<"//////////// Crystal Unit Cell /////////////////" <<endl;
489  REAL x=1,y=1,z=1;
490  this->FractionalToOrthonormalCoords(x,y,z);
491  os << " //box{ <0,0,0>, <"<< x << "," << y << "," << z << ">" <<endl;
492  os << " // pigment {colour rgbf<1,1,1,0.9>}" << endl;
493  os << " // hollow" << endl;
494  os << " //}" <<endl<<endl;
495 
496  #define UNITCELL_EDGE(X0,Y0,Z0,X1,Y1,Z1)\
497  {\
498  REAL x0=X0,y0=Y0,z0=Z0,x1=X1,y1=Y1,z1=Z1;\
499  this->FractionalToOrthonormalCoords(x0,y0,z0);\
500  this->FractionalToOrthonormalCoords(x1,y1,z1);\
501  os << " ObjCrystBond("\
502  <<x0<<","<<y0<<","<<z0<< ","\
503  <<x1<<","<<y1<<","<<z1<< ","\
504  << "0.02,rgb<1.0,1.0,1.0>,1.0,1.0)"<<endl;\
505  }
506 
507  UNITCELL_EDGE(0,0,0,1,0,0)
508  UNITCELL_EDGE(0,0,0,0,1,0)
509  UNITCELL_EDGE(0,0,0,0,0,1)
510 
511  UNITCELL_EDGE(1,1,1,0,1,1)
512  UNITCELL_EDGE(1,1,1,1,0,1)
513  UNITCELL_EDGE(1,1,1,1,1,0)
514 
515  UNITCELL_EDGE(1,0,0,1,1,0)
516  UNITCELL_EDGE(1,0,0,1,0,1)
517 
518  UNITCELL_EDGE(0,1,0,1,1,0)
519  UNITCELL_EDGE(0,1,0,0,1,1)
520 
521  UNITCELL_EDGE(0,0,1,1,0,1)
522  UNITCELL_EDGE(0,0,1,0,1,1)
523 
524  os <<endl<<"/////////////// GLOBAL DECLARATIONS FOR ATOMS & BONDS ///////"<<endl;
525  os << "// Atom colours"<<endl;
526  for(int i=0;i<mScatteringPowerRegistry.GetNb();i++)
527  {
528  const float r=mScatteringPowerRegistry.GetObj(i).GetColourRGB()[0];
529  const float g=mScatteringPowerRegistry.GetObj(i).GetColourRGB()[1];
530  const float b=mScatteringPowerRegistry.GetObj(i).GetColourRGB()[2];
531  os << " #declare colour_"<< mScatteringPowerRegistry.GetObj(i).GetName()
532  <<"= rgb <"<< r<<","<<g<<","<<b<<">;"<< endl;
533  }
534  os << "// Bond colours"<<endl
535  << " #declare colour_freebond = rgb <0.7,0.7,0.7>;"<< endl
536  << " #declare colour_nonfreebond= rgb <0.3,0.3,0.3>;"<< endl;
537 
538  os<<endl;
539  os << "/////////////// SCATTERERS ///////"<<endl;
540  for(int i=0;i<mScattererRegistry.GetNb();i++)
541  this->GetScatt(i).POVRayDescription(os,options) ;
542  return os;
543 }
544 
545 void Crystal::GLInitDisplayList(const bool onlyIndependentAtoms,
546  const REAL xMin,const REAL xMax,
547  const REAL yMin,const REAL yMax,
548  const REAL zMin,const REAL zMax,
549  const bool displayNames,
550  const bool hideHydrogens)const
551 {
552  VFN_DEBUG_ENTRY("Crystal::GLInitDisplayList()",5)
553  #ifdef OBJCRYST_GL
554  REAL en=1;// if -1, display enantiomeric structure
555  if(mDisplayEnantiomer.GetChoice()==1) en=-1;
556 
557  //Center of displayed unit
558  REAL xc=(xMin+xMax)/2.;
559  REAL yc=(yMin+yMax)/2.;
560  REAL zc=(zMin+zMax)/2.;
561  if(false==displayNames)
562  {
563  //Describe Unit Cell
564  REAL x111= 1.;
565  REAL y111= 1.;
566  REAL z111= 1.;
567  this->FractionalToOrthonormalCoords(x111,y111,z111);
568  REAL x110= 1.;
569  REAL y110= 1.;
570  REAL z110= 0.;
571  this->FractionalToOrthonormalCoords(x110,y110,z110);
572  REAL x101= 1.;
573  REAL y101= 0.;
574  REAL z101= 1.;
575  this->FractionalToOrthonormalCoords(x101,y101,z101);
576  REAL x100= 1.;
577  REAL y100= 0.;
578  REAL z100= 0.;
579  this->FractionalToOrthonormalCoords(x100,y100,z100);
580  REAL x011= 0.;
581  REAL y011= 1.;
582  REAL z011= 1.;
583  this->FractionalToOrthonormalCoords(x011,y011,z011);
584  REAL x010= 0.;
585  REAL y010= 1.;
586  REAL z010= 0.;
587  this->FractionalToOrthonormalCoords(x010,y010,z010);
588  REAL x001= 0.;
589  REAL y001= 0.;
590  REAL z001= 1.;
591  this->FractionalToOrthonormalCoords(x001,y001,z001);
592  REAL x000= 0.;
593  REAL y000= 0.;
594  REAL z000= 0.;
595  this->FractionalToOrthonormalCoords(x000,y000,z000);
596  REAL xM= 0.5;
597  REAL yM= 0.5;
598  REAL zM= 0.5;
599  this->FractionalToOrthonormalCoords(xM,yM,zM);
600  xM*=2;yM*=2;zM*=2;
601  glPushMatrix();
602  //Add Axis & axis names
603  const GLfloat colour0 [] = {0.00, 0.00, 0.00, 0.00};
604  const GLfloat colour1 [] = {0.50, 0.50, 0.50, 1.00};
605  const GLfloat colour2 [] = {1.00, 1.00, 1.00, 1.00};
606  glMaterialfv(GL_FRONT, GL_AMBIENT, colour2);
607  glMaterialfv(GL_FRONT, GL_DIFFUSE, colour0);
608  glMaterialfv(GL_FRONT, GL_SPECULAR, colour0);
609  glMaterialfv(GL_FRONT, GL_EMISSION, colour2);
610  glMaterialfv(GL_FRONT, GL_SHININESS, colour0);
611  REAL x,y,z;
612  x=1.2-xc;y=-yc;z=-zc;
613  this->FractionalToOrthonormalCoords(x,y,z);
614  glRasterPos3f(en*x,y,z);
615  crystGLPrint("a");
616 
617  x=-xc;y=1.2-yc;z=-zc;
618  this->FractionalToOrthonormalCoords(x,y,z);
619  glRasterPos3f(en*x,y,z);
620  crystGLPrint("b");
621 
622  x=-xc;y=-yc;z=1.2-zc;
623  this->FractionalToOrthonormalCoords(x,y,z);
624  glRasterPos3f(en*x,y,z);
625  crystGLPrint("c");
626  // Cell
627  glMaterialfv(GL_FRONT, GL_AMBIENT, colour1);
628  glMaterialfv(GL_FRONT, GL_DIFFUSE, colour2);
629  glMaterialfv(GL_FRONT, GL_SPECULAR, colour2);
630  glMaterialfv(GL_FRONT, GL_EMISSION, colour0);
631  glMaterialfv(GL_FRONT, GL_SHININESS, colour0);
632  this->FractionalToOrthonormalCoords(xc,yc,zc);
633  glTranslatef(-xc*en, -yc, -zc);
634  glBegin(GL_LINES);
635  //top
636  glNormal3f((x110+x010-xM)*en,y110+y010-yM,z110+z010-zM);
637  glVertex3f( x110*en, y110, z110);
638  glVertex3f( x010*en, y010, z010);
639 
640  glNormal3f((x011+x010-xM)*en,y011+y010-yM,z011+z010-zM);
641  glVertex3f( x010*en, y010, z010);
642  glVertex3f( x011*en, y011, z011);
643 
644  glNormal3f((x011+x111-xM)*en,y011+y111-yM,z011+z111-zM);
645  glVertex3f( x011*en, y011, z011);
646  glVertex3f( x111*en, y111, z111);
647 
648  glNormal3f((x110+x111-xM)*en,y110+y111-yM,z110+z111-zM);
649  glVertex3f( x111*en, y111, z111);
650  glVertex3f( x110*en, y110, z110);
651  //bottom
652  glNormal3f((x101+x001-xM)*en,y101+y001-yM,z101+z001-zM);
653  glVertex3f( x101*en, y101, z101);
654  glVertex3f( x001*en, y001, z001);
655 
656  glNormal3f((x000+x001-xM)*en,y000+y001-yM,z000+z001-zM);
657  glVertex3f( x001*en, y001, z001);
658  glVertex3f( x000*en, y000, z000);
659 
660  glNormal3f((x000+x100-xM)*en,y000+y100-yM,z000+z100-zM);
661  glVertex3f( x000*en, y000, z000);
662  glVertex3f( x100*en, y100, z100);
663 
664  glNormal3f((x101+x100-xM)*en,y101+y100-yM,z101+z100-zM);
665  glVertex3f( x100*en, y100, z100);
666  glVertex3f( x101*en, y101, z101);
667  //sides
668  glNormal3f((x101+x111-xM)*en,y101+y111-yM,z101+z111-zM);
669  glVertex3f( x101*en, y101, z101);
670  glVertex3f( x111*en, y111, z111);
671 
672  glNormal3f((x001+x011-xM)*en,y001+y011-yM,z001+z011-zM);
673  glVertex3f( x001*en, y001, z001);
674  glVertex3f( x011*en, y011, z011);
675 
676  glNormal3f((x000+x010-xM)*en,y000+y010-yM,z000+z010-zM);
677  glVertex3f( x000*en, y000, z000);
678  glVertex3f( x010*en, y010, z010);
679 
680  glNormal3f((x100+x110-xM)*en,y100+y110-yM,z100+z110-zM);
681  glVertex3f( x100*en, y100, z100);
682  glVertex3f( x110*en, y110, z110);
683  glEnd();
684  glPopMatrix();
685  }
686 
687  //Describe all Scatterers
688  VFN_DEBUG_MESSAGE("Crystal::GLView(bool):Scatterers...",5)
689  glPushMatrix();
690  if(displayNames) this->FractionalToOrthonormalCoords(xc,yc,zc);
691  glTranslatef(-xc*en, -yc, -zc);
692  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
693  {
694  bool displayEnantiomer=false;
695  if(mDisplayEnantiomer.GetChoice()==1) displayEnantiomer=true;
696  for(int i=0;i<mScattererRegistry.GetNb();i++)
697  this->GetScatt(i).GLInitDisplayList(onlyIndependentAtoms,
698  xMin,xMax,yMin,yMax,zMin,zMax,
699  displayEnantiomer,displayNames,hideHydrogens);
700  }
701  glPopMatrix();
702  #else
703  cout << "Crystal::GLView(): Compiled without OpenGL support !" <<endl;
704  #endif
705  VFN_DEBUG_EXIT("Crystal::GLInitDisplayList(bool)",5)
706 }
707 
708 void Crystal::CalcDynPopCorr(const REAL overlapDist, const REAL mergeDist) const
709 {
710  VFN_DEBUG_ENTRY("Crystal::CalcDynPopCorr(REAL)",4)
711  TAU_PROFILE("Crystal::CalcDynPopCorr()","void (REAL)",TAU_DEFAULT);
712 
713  this->CalcDistTable(true);
715 
716  const long nbComponent=mScattCompList.GetNbComponent();
717  const int nbSymmetrics=this->GetSpaceGroup().GetNbSymmetrics();
718  CrystVector_REAL neighborsDist(nbComponent*nbSymmetrics);
719  long nbNeighbors=0;
720  REAL corr;
721 
722  int atomicNumber;
723  const REAL overlapDistSq=overlapDist*overlapDist;
724  REAL dist;
725  for(long i=0;i<nbComponent;i++)
726  {
727  VFN_DEBUG_MESSAGE("Crystal::CalcDynPopCorr(): Component:"<<i,0)
728  if(0==mScattCompList(i).mpScattPow)
729  {
730  mScattCompList(i).mDynPopCorr=1.;
731  continue;
732  }
733  atomicNumber=mScattCompList(i).mpScattPow->GetDynPopCorrIndex();
734  nbNeighbors=0;
735  std::vector<Crystal::Neighbour>::const_iterator pos;
736  for(pos=mvDistTableSq[i].mvNeighbour.begin();
737  pos<mvDistTableSq[i].mvNeighbour.end();pos++)
738  {
739  VFN_DEBUG_MESSAGE("Crystal::CalcDynPopCorr(): Component:"<<i<<"Neighbour:"<<pos->mNeighbourIndex,0)
740  if(0==mScattCompList(pos->mNeighbourIndex).mpScattPow)continue;
741  if(atomicNumber==mScattCompList(pos->mNeighbourIndex).mpScattPow->GetDynPopCorrIndex())
742  {
743  if(overlapDistSq > pos->mDist2)
744  {
745  //resizing can be necessary if the unit cell is small, so that an atom two unit cells away is
746  //still considered a neighbor...
747  if(nbNeighbors==neighborsDist.numElements()) neighborsDist.resizeAndPreserve(nbNeighbors+20);
748  neighborsDist(nbNeighbors++)=sqrt(pos->mDist2);
749  }
750  }
751  }
752  corr=0.;
753  for(long j=0;j<nbNeighbors;j++)
754  {
755  dist=neighborsDist(j)-mergeDist;
756  if(dist<0.) dist=0.;
757  corr += fabs((overlapDist-dist-mergeDist)/(overlapDist-mergeDist));
758  }
759  mScattCompList(i).mDynPopCorr=1./(1+corr);
760  }
762  VFN_DEBUG_EXIT("Crystal::CalcDynPopCorr(REAL):End.",4)
763 }
764 
766 {
767  //:NOTE: This is useless !!
769  const long nbComponent=mScattCompList.GetNbComponent();
770  for(long i=0;i<nbComponent;i++) mScattCompList(i).mDynPopCorr=1.;
771 }
772 
773 REAL Crystal::GetDynPopCorr(const Scatterer* pscatt, unsigned int component)const
774 {
775  if(this->GetUseDynPopCorr()==0) return 1.0;
777  unsigned int j=0;
778  for(long i=0;i<mScattererRegistry.GetNb();i++)
779  {
780  if(pscatt==&(this->GetScatt(i)))
781  {
782  return mScattCompList(j+component).mDynPopCorr;
783  }
785  }
786  // Something is wrong if we got here !
787  throw ObjCrystException("Crystal::GetDynPopCorr(): did not find this scatterer !");
788  return 1.0;
789 }
790 
791 void Crystal::SetUseDynPopCorr(const int b)
792 {
793  VFN_DEBUG_MESSAGE("Crystal::SetUseDynPopCorr()",1)
794  mUseDynPopCorr.SetChoice(b);
796 }
797 
799 {
800  return mUseDynPopCorr.GetChoice();
801 }
802 
803 int Crystal::FindScatterer(const string &scattName)const
804 {
805  VFN_DEBUG_MESSAGE("Crystal::FindScatterer(name)",0)
806  for(int i=0;i<this->GetNbScatterer();i++)
807  {
808  if( mScattererRegistry.GetObj(i).GetName() == scattName) return i;
809  }
810  throw ObjCrystException("Crystal::FindScatterer(string)\
811  Cannot find this scatterer:"+scattName);
812 }
813 
814 Crystal::BumpMergePar::BumpMergePar():
815  mDist2(1.),mCanOverlap(false){}
816 
817 Crystal::BumpMergePar::BumpMergePar(const REAL dist, const bool canOverlap):
818  mDist2(dist*dist),mCanOverlap(canOverlap){}
819 
821 {
822  if(mvBumpMergePar.size()==0) return 0;
823  if(mBumpMergeScale<1e-5) return 0;
824  this->CalcDistTable(true);
825  VFN_DEBUG_ENTRY("Crystal::GetBumpMergeCost()",4)
828  TAU_PROFILE("Crystal::GetBumpMergeCost()","REAL (REAL)",TAU_DEFAULT);
829 
830  mBumpMergeCost=0;
831 
832  std::vector<NeighbourHood>::const_iterator pos;
833  std::vector<Crystal::Neighbour>::const_iterator neigh;
834  REAL tmp;
835  const ScatteringPower *i1,*i2;
836  VBumpMergePar::const_iterator par;
837  for(pos=mvDistTableSq.begin();pos<mvDistTableSq.end();pos++)
838  {
839  i1=mScattCompList(pos->mIndex).mpScattPow;
840  for(neigh=pos->mvNeighbour.begin();neigh<pos->mvNeighbour.end();neigh++)
841  {
842  i2=mScattCompList(neigh->mNeighbourIndex).mpScattPow;
843  if(i1<i2) par=mvBumpMergePar.find(std::make_pair(i1,i2));
844  else par=mvBumpMergePar.find(std::make_pair(i2,i1));
845  if(par==mvBumpMergePar.end()) continue;
846  if(neigh->mDist2 > par->second.mDist2) continue;
847  if(true==par->second.mCanOverlap)
848  tmp = 0.5*sin(M_PI*(1.-sqrt(neigh->mDist2/par->second.mDist2)))/0.1;
849  else
850  tmp = tan(M_PI*0.49999*(1.-sqrt(neigh->mDist2/par->second.mDist2)))/0.1;
851  mBumpMergeCost += tmp*tmp;
852  }
853  }
856  VFN_DEBUG_EXIT("Crystal::GetBumpMergeCost():"<<mBumpMergeCost,4)
858 }
859 
861  const ScatteringPower &scatt2,const REAL dist)
862 {
863  VFN_DEBUG_MESSAGE("Crystal::SetBumpMergeDistance()",5)
864  if(&scatt1 == &scatt2) this->SetBumpMergeDistance(scatt1,scatt2,dist,true) ;
865  else this->SetBumpMergeDistance(scatt1,scatt2,dist,false);
866 }
867 
869  const ScatteringPower &scatt2,const REAL dist,
870  const bool allowMerge)
871 {
872  VFN_DEBUG_MESSAGE("Crystal::SetBumpMergeDistance("<<scatt1.GetName()<<","<<scatt2.GetName()<<")="<<dist<<","<<allowMerge,3)
873  if(&scatt1 < &scatt2)
874  mvBumpMergePar[std::make_pair(&scatt1,&scatt2)]=BumpMergePar(dist,allowMerge);
875  else
876  mvBumpMergePar[std::make_pair(&scatt2,&scatt1)]=BumpMergePar(dist,allowMerge);
878 }
880  const ScatteringPower &scatt2)
881 {
882  Crystal::VBumpMergePar::iterator pos;
883  if(&scatt1 < &scatt2) pos=mvBumpMergePar.find(make_pair(&scatt1 , &scatt2));
884  else pos=mvBumpMergePar.find(make_pair(&scatt2 , &scatt1));
885  if(pos!=mvBumpMergePar.end()) mvBumpMergePar.erase(pos);
887 }
888 
889 const Crystal::VBumpMergePar& Crystal::GetBumpMergeParList()const{return mvBumpMergePar;}
890 Crystal::VBumpMergePar& Crystal::GetBumpMergeParList(){return mvBumpMergePar;}
891 
893 
894 void Crystal::GlobalOptRandomMove(const REAL mutationAmplitude,
895  const RefParType *type)
896 {
897  if(mRandomMoveIsDone) return;
898  VFN_DEBUG_ENTRY("Crystal::GlobalOptRandomMove()",2)
899  //Either a random move or a permutation of two scatterers
900  const unsigned long nb=(unsigned long)this->GetNbScatterer();
901  if( ((rand()/(REAL)RAND_MAX)<.02) && (nb>1))
902  {
903  // This is safe even if one scatterer is partially fixed,
904  // since we the SetX/SetY/SetZ actually use the MutateTo() function.
905  const unsigned long n1=rand()%nb;
906  const unsigned long n2=( (rand()%(nb-1)) +n1+1) %nb;
907  const float x1=this->GetScatt(n1).GetX();
908  const float y1=this->GetScatt(n1).GetY();
909  const float z1=this->GetScatt(n1).GetZ();
910  this->GetScatt(n1).SetX(this->GetScatt(n2).GetX());
911  this->GetScatt(n1).SetY(this->GetScatt(n2).GetY());
912  this->GetScatt(n1).SetZ(this->GetScatt(n2).GetZ());
913  this->GetScatt(n2).SetX(x1);
914  this->GetScatt(n2).SetY(y1);
915  this->GetScatt(n2).SetZ(z1);
916  }
917  else
918  {
919  this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,type);
920  }
921  mRandomMoveIsDone=true;
922  VFN_DEBUG_EXIT("Crystal::GlobalOptRandomMove()",2)
923 }
924 
926 {
927  return this->GetBumpMergeCost()+this->GetBondValenceCost();
928 }
929 
930 void Crystal::CIFOutput(ostream &os, double mindist)const
931 {
932  VFN_DEBUG_ENTRY("Crystal::OutputCIF()",5)
933 
934  //Data block name (must have no spaces)
935  string tempname = mName;
936  int where, size;
937  size = tempname.size();
938  if (size > 32)
939  {
940  tempname = tempname.substr(0,32);
941  size = tempname.size();
942  }
943  if (size == 0)
944  {
945  tempname = "3D";
946  size = 2;
947  }
948  where = tempname.find(" ",0);
949  while (where != (int)string::npos)
950  {
951  tempname.replace(where,1,"_");
952  where = tempname.find(" ",0);
953  //cout << tempname << endl;
954  }
955  os << "data_" << tempname <<endl<<endl;
956 
957  //Program
958  os <<"_computing_structure_solution 'FOX http://objcryst.sourceforge.net'"<<endl<<endl;
959 
960  //Scattering powers
961  /* This is making troubles when the cif file is imported to the JANA2006
962  os << "loop_"<<endl
963  << " _atom_type_symbol" <<endl
964  << " _atom_type_description"<<endl
965  << " _atom_type_scat_source" <<endl;
966  for(int i=0;i<this->GetScatteringPowerRegistry().GetNb();i++)
967  os << " "
968  << this->GetScatteringPowerRegistry().GetObj(i).GetName()<<" "
969  <<this->GetScatteringPowerRegistry().GetObj(i).GetSymbol()<<" "
970  <<"'International Tables for Crystallography (Vol. IV)'"
971  <<endl;
972  os <<endl;
973  */
974 
975  //Symmetry
976  os <<"_symmetry_space_group_name_H-M '"
977  << this->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin()<<":"<<this->GetSpaceGroup().GetExtension()<<"'"<<endl;
978  os <<"_symmetry_space_group_name_Hall '"
979  << this->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hall()<<"'"<<endl;
980  os <<endl;
981 
982  os << "_cell_length_a " << FormatFloat(this->GetLatticePar(0),8,5) << endl
983  << "_cell_length_b " << FormatFloat(this->GetLatticePar(1),8,5) << endl
984  << "_cell_length_c " << FormatFloat(this->GetLatticePar(2),8,5) << endl
985  << "_cell_angle_alpha " << FormatFloat(this->GetLatticePar(3)*RAD2DEG,7,3) << endl
986  << "_cell_angle_beta " << FormatFloat(this->GetLatticePar(4)*RAD2DEG,7,3) << endl
987  << "_cell_angle_gamma " << FormatFloat(this->GetLatticePar(5)*RAD2DEG,7,3) << endl
988  << "_cell_volume " << FormatFloat(this->GetVolume(),7,2);
989  os <<endl;
991 
992  /*
993  TODO:
994  loop_
995  _symmetry_equiv_pos_site_id
996  _symmetry_equiv_pos_as_xyz
997 
998  */
999 
1000  os << "loop_" << endl
1001  << " _atom_site_label" <<endl
1002  << " _atom_site_type_symbol" <<endl
1003  << " _atom_site_fract_x"<<endl
1004  << " _atom_site_fract_y" <<endl
1005  << " _atom_site_fract_z" <<endl
1006  << " _atom_site_U_iso_or_equiv" <<endl
1007  << " _atom_site_occupancy" <<endl
1008  << " _atom_site_adp_type" <<endl;
1009 
1010  const double BtoU = 1.0 / (8 * M_PI * M_PI);
1011  std::vector<const ScatteringPower*> anisovec;
1012  std::vector<std::string> namevec;
1013  CrystMatrix_REAL minDistTable;
1014  minDistTable=this->GetMinDistanceTable(-1.);
1015  unsigned long k=0;
1016  for(int i=0;i<mScattererRegistry.GetNb();i++)
1017  {
1018  //mpScatterrer[i]->Print();
1020  for(int j=0;j<list.GetNbComponent();j++)
1021  {
1022  if(0==list(j).mpScattPow) continue;
1023  bool redundant=false;
1024  for(unsigned long l=0;l<k;++l) if(abs(minDistTable(l,k))<mindist) redundant=true;//-1 means dist > 10A
1025  if(!redundant)
1026  {
1027  // We can't have spaces in atom labels
1028  string s=this->GetScatt(i).GetComponentName(j);
1029  size_t posc=s.find(' ');
1030  while(posc!=string::npos){s[posc]='~';posc=s.find(' ');}
1031 
1032  bool isiso = list(j).mpScattPow->IsIsotropic();
1033  if(!isiso)
1034  {
1035  anisovec.push_back(list(j).mpScattPow);
1036  namevec.push_back(s);
1037  }
1038 
1039  os << " "
1040  << FormatString(s,10) << " "
1041  << FormatString(list(j).mpScattPow->GetSymbol(),8) << " "
1042  << FormatFloat(list(j).mX,9,6) << " "
1043  << FormatFloat(list(j).mY,9,6) << " "
1044  << FormatFloat(list(j).mZ,9,6) << " "
1045  << FormatFloat(list(j).mpScattPow->GetBiso()*BtoU,9,6) << " "
1046  << FormatFloat(list(j).mOccupancy,6,4)
1047  << (isiso ? " Uiso" : " Uani")
1048  << endl;
1049  }
1050  k++;
1051  }
1052  }
1053 
1054 
1055  // Handle anisotropic atoms
1056  if( anisovec.size() > 0 )
1057  {
1058 
1059  os << endl
1060  << "loop_" << endl
1061  << " _atom_site_aniso_label" << endl
1062  << " _atom_site_aniso_U_11" << endl
1063  << " _atom_site_aniso_U_22" << endl
1064  << " _atom_site_aniso_U_33" << endl
1065  << " _atom_site_aniso_U_12" << endl
1066  << " _atom_site_aniso_U_13" << endl
1067  << " _atom_site_aniso_U_23" << endl;
1068 
1069 
1070  for(size_t i = 0; i < anisovec.size(); ++i)
1071  {
1072  os << " " << FormatString(namevec[i],8) << " ";
1073  for(int j=0; j<6; ++j)
1074  os << FormatFloat(anisovec[i]->GetBij(j)*BtoU,9,6) << " ";
1075  os << endl;
1076  }
1077  }
1078 
1079 
1080  bool first=true;
1081  k=0;
1082  for(int i=0;i<mScattererRegistry.GetNb();i++)
1083  {
1085  for(int j=0;j<list.GetNbComponent();j++)
1086  {
1087  if(0==list(j).mpScattPow) continue;
1088  bool redundant=false;
1089  for(unsigned long l=0;l<k;++l) if(abs(minDistTable(l,k))<mindist) redundant=true;//-1 means dist > 10A
1090  if(redundant)
1091  {
1092  if(first)
1093  {
1094  first=false;
1095  os <<endl
1096  << "# The following atoms have been excluded by Fox because they are"<<endl
1097  << "# almost fully overlapping with another atom (d<" << mindist << "A)"<< endl;
1098  }
1099  os << "# "
1100  << FormatString(list(j).mpScattPow->GetName(),8) << " "
1101  << FormatString(this->GetScatt(i).GetComponentName(j),10) << " "
1102  << FormatFloat(list(j).mX,9,6) << " "
1103  << FormatFloat(list(j).mY,9,6) << " "
1104  << FormatFloat(list(j).mZ,9,6) << " "
1105  << FormatFloat(list(j).mpScattPow->GetBiso()*BtoU,9,6) << " "
1106  << FormatFloat(list(j).mOccupancy,6,4)
1107  << " Uiso"
1108  << endl;
1109  }
1110  k++;
1111  }
1112  }
1113 
1114  os <<endl;
1115  k=0;
1116  if(1==mUseDynPopCorr.GetChoice())
1117  {
1118  os << "# Dynamical occupancy corrections found by ObjCryst++:"<<endl
1119  << "# values below 1. (100%) indicate a correction,"<<endl
1120  << "# which means either that the atom is on a special position,"<<endl
1121  << "# or that it is overlapping with another identical atom."<<endl;
1122  for(int i=0;i<mScattererRegistry.GetNb();i++)
1123  {
1124  //mpScatterrer[i]->Print();
1126  for(int j=0;j<list.GetNbComponent();j++)
1127  {
1128  os << "# "
1129  << FormatString(this->GetScatt(i).GetComponentName(j),16)
1130  << " : " << FormatFloat(mScattCompList(k).mDynPopCorr,6,4)
1131  << endl;
1132  k++;
1133  }
1134  }
1135  os << "#"<<endl;
1136  }
1137 
1138  VFN_DEBUG_EXIT("Crystal::OutputCIF()",5)
1139 }
1140 
1142  CrystVector_uint & groupIndex,
1143  unsigned int &first) const
1144 {
1145  // One group for all lattice parameters
1146  unsigned int latticeIndex=0;
1147  VFN_DEBUG_MESSAGE("Crystal::GetGeneGroup()",4)
1148  for(long i=0;i<obj.GetNbPar();i++)
1149  for(long j=0;j<this->GetNbPar();j++)
1150  if(&(obj.GetPar(i)) == &(this->GetPar(j)))
1151  {
1152  //if(this->GetPar(j).GetType()->IsDescendantFromOrSameAs(gpRefParTypeUnitCell))
1153  //{
1154  if(latticeIndex==0) latticeIndex=first++;
1155  groupIndex(i)=latticeIndex;
1156  //}
1157  //else //no parameters other than unit cell
1158  }
1159 }
1160 void Crystal::BeginOptimization(const bool allowApproximations,const bool enableRestraints)
1161 {
1162  if(this->IsBeingRefined())
1163  {
1164  // RefinableObj::BeginOptimization() will increase the optimization depth
1165  this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
1166  return;
1167  }
1168  for(int i=0;i<this->GetScattererRegistry().GetNb();i++)
1169  {
1170  this->GetScattererRegistry().GetObj(i).
1171  SetGlobalOptimStep(gpRefParTypeScattTranslX,0.1/this->GetLatticePar(0));
1172  this->GetScattererRegistry().GetObj(i).
1173  SetGlobalOptimStep(gpRefParTypeScattTranslY,0.1/this->GetLatticePar(1));
1174  this->GetScattererRegistry().GetObj(i).
1175  SetGlobalOptimStep(gpRefParTypeScattTranslZ,0.1/this->GetLatticePar(2));
1176  }
1177  this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
1178  // Calculate mDistTableMaxDistance: Default 1 Angstroem, for dynamical occupancy correction
1180  // Up to 4 Angstroem if bond-valence is used
1181  if((mvBondValenceRo.size()>0) && (mBondValenceCostScale>1e-5)) mDistTableMaxDistance=4;
1182  // Up to whatever antibump distance the user requires (hopefully not too large !)
1183  for(Crystal::VBumpMergePar::iterator pos=mvBumpMergePar.begin();pos!=mvBumpMergePar.end();++pos)
1184  if(sqrt(pos->second.mDist2)>mDistTableMaxDistance) mDistTableMaxDistance=sqrt(pos->second.mDist2);
1185  VFN_DEBUG_MESSAGE("Crystal::BeginOptimization():mDistTableMaxDistance="<<mDistTableMaxDistance,10)
1186 }
1187 
1188 void Crystal::AddBondValenceRo(const ScatteringPower &pow1,const ScatteringPower &pow2,const REAL ro)
1189 {
1190  if(&pow1 < &pow2) mvBondValenceRo[make_pair(&pow1,&pow2)]=ro;
1191  else mvBondValenceRo[make_pair(&pow2,&pow1)]=ro;
1193  this->UpdateDisplay();
1194 }
1195 
1196 void Crystal::RemoveBondValenceRo(const ScatteringPower &pow1,const ScatteringPower &pow2)
1197 {
1198  map<pair<const ScatteringPower*,const ScatteringPower*>, REAL>::iterator pos;
1199  if(&pow1 < &pow2) pos=mvBondValenceRo.find(make_pair(&pow1 , &pow2));
1200  else pos=mvBondValenceRo.find(make_pair(&pow2 , &pow1));
1201  if(pos!=mvBondValenceRo.end()) mvBondValenceRo.erase(pos);
1203 }
1204 
1206 {
1207  VFN_DEBUG_MESSAGE("Crystal::GetBondValenceCost()?",4)
1208  if(mBondValenceCostScale<1e-5) return 0.0;
1209  if(mvBondValenceRo.size()==0)
1210  {
1211  mBondValenceCost=0.0;
1213  }
1214  this->CalcBondValenceSum();
1217  VFN_DEBUG_MESSAGE("Crystal::GetBondValenceCost():"<<mvBondValenceCalc.size()<<" valences",4)
1218  TAU_PROFILE("Crystal::GetBondValenceCost()","REAL ()",TAU_DEFAULT);
1219  mBondValenceCost=0.0;
1220  std::map<long, REAL>::const_iterator pos;
1221  for(pos=mvBondValenceCalc.begin();pos!=mvBondValenceCalc.end();++pos)
1222  {
1223  const REAL a=pos->second-mScattCompList(pos->first).mpScattPow->GetFormalCharge();
1224  mBondValenceCost += a*a;
1225  VFN_DEBUG_MESSAGE("Crystal::GetBondValenceCost():"
1226  <<mScattCompList(pos->first).mpScattPow->GetName()
1227  <<"="<<pos->second,4)
1228  }
1231 }
1232 
1233 std::map<pair<const ScatteringPower*,const ScatteringPower*>, REAL>& Crystal::GetBondValenceRoList()
1234 { return mvBondValenceRo;}
1235 
1236 const std::map<pair<const ScatteringPower*,const ScatteringPower*>, REAL>& Crystal::GetBondValenceRoList()const
1237 { return mvBondValenceRo;}
1238 
1240 {
1241  if(mvBondValenceRo.size()==0) return;
1242  this->CalcDistTable(true);
1243  VFN_DEBUG_MESSAGE("Crystal::CalcBondValenceSum()?",4)
1246  VFN_DEBUG_MESSAGE("Crystal::CalcBondValenceSum()",4)
1247  TAU_PROFILE("Crystal::CalcBondValenceSum()","void ()",TAU_DEFAULT);
1248  mvBondValenceCalc.clear();
1249  for(long i=0;i<mScattCompList.GetNbComponent();i++)
1250  {
1251  const ScatteringPower *pow1=mScattCompList(i).mpScattPow;
1252  int nb=0;
1253  REAL val=0.0;
1254  std::vector<Crystal::Neighbour>::const_iterator pos;
1255  for(pos=mvDistTableSq[i].mvNeighbour.begin();
1256  pos<mvDistTableSq[i].mvNeighbour.end();pos++)
1257  {
1258  const REAL dist=sqrt(pos->mDist2);
1259  const REAL occup= mScattCompList(pos->mNeighbourIndex).mOccupancy
1260  *mScattCompList(pos->mNeighbourIndex).mDynPopCorr;
1261  const ScatteringPower *pow2=mScattCompList(pos->mNeighbourIndex).mpScattPow;
1262  map<pair<const ScatteringPower*,const ScatteringPower*>,REAL>::const_iterator pos;
1263  if(pow1<pow2) pos=mvBondValenceRo.find(make_pair(pow1,pow2));
1264  else pos=mvBondValenceRo.find(make_pair(pow2,pow1));
1265  if(pos!=mvBondValenceRo.end())
1266  {
1267  const REAL v=exp((pos->second-dist)/0.37);
1268  val += occup * v;
1269  nb++;
1270  }
1271  }
1272  if(nb!=0) mvBondValenceCalc[i]=val;
1273  }
1275 }
1276 
1277 void Crystal::Init(const REAL a, const REAL b, const REAL c, const REAL alpha,
1278  const REAL beta, const REAL gamma,const string &SpaceGroupId,
1279  const string& name)
1280 {
1281  VFN_DEBUG_MESSAGE("Crystal::Init(a,b,c,alpha,beta,gamma,Sg,name)",10)
1282  this->UnitCell::Init(a,b,c,alpha,beta,gamma,SpaceGroupId,name);
1286 
1287  VFN_DEBUG_MESSAGE("Crystal::Init(a,b,c,alpha,beta,gamma,Sg,name):End",10)
1288 }
1289 
1290 bool CompareBondDist(MolBond* b1, MolBond* b2)
1291 {
1292  return b1->GetLength()<b2->GetLength();
1293 }
1294 
1295 void Crystal::ConnectAtoms(const REAL min_relat_dist, const REAL max_relat_dist, const bool warnuser_fail)
1296 {
1297  VFN_DEBUG_ENTRY("Crystal::ConnectAtoms(...)",10)
1298  // Make sure there are only atoms
1299  for(unsigned int i=0;i<mScattererRegistry.GetNb();i++)
1300  {
1301  if(mScattererRegistry.GetObj(i).GetClassName()!="Atom")
1302  {
1303  if(warnuser_fail) (*fpObjCrystInformUser)("Crystal::ConnectAtoms(): cannot connect atoms unless there are only Atoms in a Crystal");
1304  return;
1305  }
1306  }
1307  this->CalcDistTable(true);
1309 
1310  // Create first Molecule
1311  // start from start_carbon
1312  Molecule *pmol=NULL;
1313  std::set<int> vAssignedAtoms;//atoms already assigned to a Molecule
1314  std::set<int> vTriedAtom0;//atoms already tried as starting point for a Molecule
1315  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...)",10)
1316  while(long(vAssignedAtoms.size()) != mScattererRegistry.GetNb())
1317  {
1318  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): new Molecule ?",7)
1319  // We need at least one carbon atom to start
1320  int atom0=-1;
1321  int maxAtomicNumber = 0;
1322  for(unsigned int i=0;i<mScattCompList.GetNbComponent();i++)
1323  {
1324  if((vAssignedAtoms.count(i)>0) || (vTriedAtom0.find(i)!=vTriedAtom0.end()) ) continue;
1325  if(mScattCompList(i).mpScattPow->GetClassName()=="ScatteringPowerAtom")
1326  {
1327  const ScatteringPowerAtom *p=dynamic_cast<const ScatteringPowerAtom*>(mScattCompList(i).mpScattPow);
1328  if((p->GetAtomicNumber()==6)&&(maxAtomicNumber!=6))
1329  {// Start from the first Carbon found
1330  atom0=i;
1331  maxAtomicNumber=6;
1332  }
1333  else if((p->GetAtomicNumber()>maxAtomicNumber) && (maxAtomicNumber!=6))
1334  {// Else we'll try from the heaviest atom
1335  maxAtomicNumber=p->GetAtomicNumber();
1336  atom0=i;
1337  }
1338  }
1339  else
1340  {
1341  if(warnuser_fail)
1342  (*fpObjCrystInformUser)("Crystal::ConnectAtoms(): cannot connect atoms unless there are only Atoms in a Crystal");
1343  VFN_DEBUG_EXIT("Crystal::ConnectAtoms(...):cannot connect atoms unless there are only Atoms in th structure:"<<i<<":"<<mScattCompList(i).mpScattPow->GetClassName(),10)
1344  return;
1345  }
1346  }
1347  if(atom0<0)
1348  {
1349  if((pmol==NULL) && warnuser_fail) // We did not create any Molecule :-(
1350  {
1351  (*fpObjCrystInformUser)("Crystal::ConnectAtoms(): cannot connect atoms unless there is at least one carbon atom");
1352  VFN_DEBUG_EXIT("Crystal::ConnectAtoms(...):cannot connect atoms unless there is at least one carbon atom",10)
1353  return;
1354  }
1355  break;
1356  }
1357  vTriedAtom0.insert(atom0);
1358  // Atoms in Molecule but for which neighbors have not yet been searched
1359  // first: index in the Crystal's scatt comp list, second: index in the Molecule
1360  std::map<int,int>newAtoms;
1361  // List of all atoms in the Molecule. First is the MolAtom* in the molecule, second is the index in the Crystal
1362  std::map<MolAtom*,int> molAtoms;
1363 
1364  pmol=new Molecule(*this);
1365 
1366  // Add atom0 to Molecule.
1367  newAtoms[atom0]=0;
1368  vAssignedAtoms.insert(atom0);
1369  const ScatteringPowerAtom *p0=dynamic_cast<const ScatteringPowerAtom*>(mScattCompList(atom0).mpScattPow);
1370  {
1371  REAL x=mScattCompList(atom0).mX;
1372  REAL y=mScattCompList(atom0).mY;
1373  REAL z=mScattCompList(atom0).mZ;
1374  const REAL occ=mScattCompList(atom0).mOccupancy;
1375  this->FractionalToOrthonormalCoords(x,y,z);
1376  pmol->AddAtom(x,y,z,p0,mScattererRegistry.GetObj(atom0).GetName(),false);
1377  pmol->GetAtomList().back()->SetOccupancy(occ);
1378  }
1379  molAtoms[pmol->GetAtomList().back()]=atom0;
1380  // Count atoms in the Molecule per element type
1381  vector<unsigned int> vElementCount(140);// Should be safe pending a trans-uranian breakthrough
1382  for(vector<unsigned int>::iterator pos=vElementCount.begin();pos!=vElementCount.end();++pos) *pos=0;
1383  vElementCount[p0->GetAtomicNumber()]+=1;
1384  while(newAtoms.size()>0)
1385  {
1386  atom0=newAtoms.begin()->first;
1387  p0=dynamic_cast<const ScatteringPowerAtom*>(mScattCompList(atom0).mpScattPow);
1388  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):atom0="<<atom0<<","<<newAtoms.size()<<" new atoms",7)
1389  // Add neigbours if between min and max * sum of covalent bonds
1390  for(std::vector<Crystal::Neighbour>::const_iterator pos=mvDistTableSq[atom0].mvNeighbour.begin();
1391  pos!=mvDistTableSq[atom0].mvNeighbour.end();pos++)
1392  {
1393  const ScatteringPowerAtom *p1=dynamic_cast<const ScatteringPowerAtom*>(mScattCompList(pos->mNeighbourIndex).mpScattPow);
1394  const REAL dcov= p0->GetCovalentRadius()+p1->GetCovalentRadius();
1395  if( (vAssignedAtoms.count(pos->mNeighbourIndex)!=0) || (p1->GetMaxCovBonds()==0))
1396  continue;
1397  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):atom0="<<p0->GetName()<<"-"<<p1->GetName()<<"("<<p1->GetMaxCovBonds()<<"):dcov="<<dcov<<",d="<<sqrt(pos->mDist2),7)
1398  if( ((min_relat_dist*dcov)<sqrt(pos->mDist2))
1399  &&((max_relat_dist*dcov)>sqrt(pos->mDist2)))
1400  {
1401  vAssignedAtoms.insert(pos->mNeighbourIndex);
1402  REAL x=mScattCompList(pos->mNeighbourIndex).mX;
1403  REAL y=mScattCompList(pos->mNeighbourIndex).mY;
1404  REAL z=mScattCompList(pos->mNeighbourIndex).mZ;
1405  this->FractionalToOrthonormalCoords(x,y,z);
1406  const REAL occ=mScattCompList(pos->mNeighbourIndex).mOccupancy;
1407  pmol->AddAtom(x,y,z,p1,mScattererRegistry.GetObj(pos->mNeighbourIndex).GetName(),false);
1408  pmol->GetAtomList().back()->SetOccupancy(occ);
1409  newAtoms[pos->mNeighbourIndex]=pmol->GetNbComponent()-1;
1410  molAtoms[pmol->GetAtomList().back()]=pos->mNeighbourIndex;
1411  vElementCount[p1->GetAtomicNumber()]+=1;
1412  }
1413  }
1414  newAtoms.erase(atom0);
1415  }
1416  // Check this is a valid Molecule object
1417  bool keep=false;
1418  if((vElementCount[6]>0) && (pmol->GetNbComponent()>=3)) keep=true;
1419  else
1420  {// no carbon ?
1421 
1422  std::vector<unsigned int> vnb;
1423  #ifdef __DEBUG__
1424  cout<<" Crystal::ConnectAtoms(..): Molecule ?";
1425  #endif
1426  for(unsigned int i=0;i<vElementCount.size();++i)
1427  if(vElementCount[i]!=0)
1428  {
1429  vnb.push_back(vElementCount[i]);
1430  #ifdef __DEBUG__
1431  cout<<"Z="<<i<<"("<< vElementCount[i]<<") ";
1432  #endif
1433  }
1434  #ifdef __DEBUG__
1435  cout<<endl;
1436  #endif
1437  if(vnb.size()==2)
1438  {
1439  #if 0
1440  if((vElementCount[8]==1) && (vElementCount[1]==2)) keep=true; //H2O
1441  if((vElementCount[8]==1) && (vElementCount[1]==3)) keep=true; //H3O+
1442  if((vElementCount[7]==1) && (vElementCount[1]==3)) keep=true; //NH3
1443  if((vElementCount[7]==1) && (vElementCount[1]==4)) keep=true; //NH4+
1444  if((vElementCount[7]==1) && (vElementCount[8]==2)) keep=true; //NO2
1445  if((vElementCount[7]==1) && (vElementCount[8]==3)) keep=true; //NO3-
1446  if((vElementCount[5]==1) && (vElementCount[1]==3)) keep=true; //BH3
1447  if((vElementCount[5]==1) && (vElementCount[1]==4)) keep=true; //BH4-
1448  if((vElementCount[14]==1) && (vElementCount[8]==4)) keep=true; //SiO4
1449  if((vElementCount[15]==1) && (vElementCount[8]==4)) keep=true; //PO4
1450  #else
1451  // Accept any type of small molecule/polyedra with one center atom
1452  if( ((vnb[0]==1)||(vnb[1]==1)) &&((vnb[0]+vnb[1])>2)) keep=true;
1453  #endif
1454  }
1455  }
1456  if(!keep)
1457  {
1458  delete pmol;
1459  for(std::map<MolAtom*,int>::const_iterator pos=molAtoms.begin();pos!=molAtoms.end();++pos) vAssignedAtoms.erase(pos->second);
1460  continue;// Will start from another atom to build a molecule
1461  }
1462 
1463  // Add bonds
1464  for(unsigned int i=0;i<pmol->GetAtomList().size();i++)
1465  {
1466  for(unsigned int j=i+1;j<pmol->GetAtomList().size();j++)
1467  {
1468  const REAL d=GetBondLength(pmol->GetAtom(i), pmol->GetAtom(j));
1469  const REAL dcov= dynamic_cast<const ScatteringPowerAtom*>(&(pmol->GetAtom(i).GetScatteringPower()))->GetCovalentRadius()
1470  +dynamic_cast<const ScatteringPowerAtom*>(&(pmol->GetAtom(j).GetScatteringPower()))->GetCovalentRadius();
1471  if( ((min_relat_dist*dcov)<d) && ((max_relat_dist*dcov)>d))
1472  {
1473  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):Add bond="<<pmol->GetAtom(i).GetName()<<"-"<<pmol->GetAtom(j).GetName()<<", d="<<d<<"(dcov="<<dcov<<")",6)
1474  pmol->AddBond(pmol->GetAtom(i),pmol->GetAtom(j),d,.01,.02,false);
1475  }
1476  }
1477  }
1478  // Remove longest bonds if it exceeds the expected coordination
1479  for(vector<MolAtom*>::iterator pos=pmol->GetAtomList().begin();pos!=pmol->GetAtomList().end();)
1480  {
1481  pmol->BuildConnectivityTable();
1482  map<MolAtom *,set<MolAtom *> >::const_iterator p=pmol->GetConnectivityTable().find(*pos);
1483  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):max bonds for:"<<(*pos)->GetName()<<"?",10)
1484  if(p==pmol->GetConnectivityTable().end())
1485  {// While cleaning the longest bond, this atom had all his bonds removed !
1486  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...):no bond remaining for:"<<(*pos)->GetName()<<"! Removing atom from Molecule",10)
1487  //Remove MolAtom from Molecule and keep in Crystal.
1488  vAssignedAtoms.erase(molAtoms[*pos]);
1489  molAtoms.erase(*pos);
1490  pos=pmol->RemoveAtom(**pos);
1491  continue;
1492  }
1493  const unsigned int maxbonds=dynamic_cast<const ScatteringPowerAtom*>(&(p->first->GetScatteringPower()))->GetMaxCovBonds();
1494  int extra=p->second.size()-maxbonds;
1495  if(extra>0)
1496  {
1497  // Check real number of bonds taking into account occupancy, and sort bonds by length
1498  std::vector<MolBond*> vbonds;
1499  REAL nbbond=0;
1500  for(std::set<MolAtom*>::iterator p1=p->second.begin();p1!=p->second.end();++p1)
1501  {
1502  vbonds.push_back(*(pmol->FindBond(**pos,**p1)));// We can assume that exactly one bond is found
1503  nbbond+=(*p1)->GetOccupancy();
1504  }
1505  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): too many bonds for"<<(*pos)->GetName()<<" ?(allowed="<<maxbonds<<",nb="<<p->second.size()<<",nb_occ="<<nbbond<<")", 10)
1506  if((nbbond-maxbonds)>0.2)
1507  {
1508  std::sort(vbonds.begin(), vbonds.end(),CompareBondDist);
1509  std::vector<MolBond*>::reverse_iterator p=vbonds.rbegin();
1510  for(int j=0;j<extra;j++)
1511  {
1512  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): Remove bond="<<(*p)->GetAtom1().GetName()<<"-"<<(*p)->GetAtom2().GetName()<<", d="<<(*p)->GetLength(),10)
1513  pmol->RemoveBond(**p++);
1514  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): Next bond ="<<(*p)->GetAtom1().GetName()<<"-"<<(*p)->GetAtom2().GetName()<<", d="<<(*p)->GetLength(),10)
1515  }
1516  }
1517  }
1518  ++pos;
1519  }
1520 
1521  // Add all bond angles
1522  pmol->BuildConnectivityTable();
1523  for(map<MolAtom*,set<MolAtom*> >::const_iterator pos=pmol->GetConnectivityTable().begin();
1524  pos!=pmol->GetConnectivityTable().end();++pos)
1525  {
1526  for(set<MolAtom*>::const_iterator pos1=pos->second.begin();
1527  pos1!=pos->second.end();++pos1)
1528  {
1529  for(set<MolAtom*>::const_iterator pos2=pos1;
1530  pos2!=pos->second.end();++pos2)
1531  {
1532  if(pos2==pos1) continue;
1533  if(pmol->FindBondAngle(**pos1,*(pos->first),**pos2)== pmol->GetBondAngleList().end())
1534  pmol->AddBondAngle(**pos1,*(pos->first),**pos2,
1535  GetBondAngle(**pos1,*(pos->first),**pos2),0.01,0.02,false);
1536  }
1537  }
1538  }
1539  // Correct center of Molecule
1540  REAL xc=0,yc=0,zc=0;
1541  for(std::map<MolAtom*,int>::const_iterator pos=molAtoms.begin();pos!=molAtoms.end();++pos)
1542  {
1543  REAL x=mScattCompList(pos->second).mX;
1544  REAL y=mScattCompList(pos->second).mY;
1545  REAL z=mScattCompList(pos->second).mZ;
1546  this->FractionalToOrthonormalCoords(x,y,z);
1547  xc+=x;
1548  yc+=y;
1549  zc+=z;
1550  }
1551  xc /= pmol->GetNbComponent();
1552  yc /= pmol->GetNbComponent();
1553  zc /= pmol->GetNbComponent();
1554  this->OrthonormalToFractionalCoords(xc,yc,zc);
1555  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): center?"<<pmol->GetNbComponent()<<","<<molAtoms.size()<<":"<<xc<<","<<yc<<","<<zc,10)
1556  pmol->SetX(xc);
1557  pmol->SetY(yc);
1558  pmol->SetZ(zc);
1559  this->AddScatterer(pmol);
1560  }
1561  std::set<Scatterer*> vpAtom;
1562  for(std::set<int>::const_iterator pos=vAssignedAtoms.begin();pos!=vAssignedAtoms.end();++pos)
1563  {
1564  Scatterer *s=&(this->GetScattererRegistry().GetObj(*pos));
1565  vpAtom.insert(s);
1566  }
1567  while(vpAtom.size()>0)
1568  {
1569  VFN_DEBUG_MESSAGE("Crystal::ConnectAtoms(...): remove atom:"<<(*vpAtom.begin())->GetName()<<","<<vpAtom.size()<<" remaining...",6)
1570  this->RemoveScatterer(*vpAtom.begin(),true);
1571  vpAtom.erase(vpAtom.begin());
1572  }
1573  VFN_DEBUG_EXIT("Crystal::ConnectAtoms(...)",10)
1574 }
1575 
1577 {
1578  VFN_DEBUG_ENTRY("Crystal::InitOptions",10)
1579  static string UseDynPopCorrname;
1580  static string UseDynPopCorrchoices[2];
1581 
1582  static string DisplayEnantiomername;
1583  static string DisplayEnantiomerchoices[2];
1584 
1585  static bool needInitNames=true;
1586  if(true==needInitNames)
1587  {
1588  UseDynPopCorrname="Use Dynamical Occupancy Correction";
1589  UseDynPopCorrchoices[0]="No";
1590  UseDynPopCorrchoices[1]="Yes";
1591 
1592  DisplayEnantiomername="Display Enantiomer";
1593  DisplayEnantiomerchoices[0]="No";
1594  DisplayEnantiomerchoices[1]="Yes";
1595 
1596  needInitNames=false;//Only once for the class
1597  }
1598  VFN_DEBUG_MESSAGE("Crystal::Init(a,b,c,alpha,beta,gamma,Sg,name):Init options",5)
1599  mUseDynPopCorr.Init(2,&UseDynPopCorrname,UseDynPopCorrchoices);
1600  mUseDynPopCorr.SetChoice(1);
1601  this->AddOption(&mUseDynPopCorr);
1602 
1603  mDisplayEnantiomer.Init(2,&DisplayEnantiomername,DisplayEnantiomerchoices);
1604  mDisplayEnantiomer.SetChoice(0);
1605  this->AddOption(&mDisplayEnantiomer);
1606  VFN_DEBUG_EXIT("Crystal::InitOptions",10)
1607 }
1608 
1609 Crystal::Neighbour::Neighbour(const unsigned long neighbourIndex,const int sym,
1610  const REAL dist2):
1611 mNeighbourIndex(neighbourIndex),mNeighbourSymmetryIndex(sym),mDist2(dist2)
1612 {}
1613 
1614 struct DistTableInternalPosition
1615 {
1616  DistTableInternalPosition(const long atomIndex, const int sym,
1617  const REAL x,const REAL y,const REAL z):
1618  mAtomIndex(atomIndex),mSymmetryIndex(sym),mX(x),mY(y),mZ(z)
1619  {}
1621  long mAtomIndex;
1623  int mSymmetryIndex;
1625  REAL mX,mY,mZ;
1626 };
1627 
1628 void Crystal::CalcDistTable(const bool fast) const
1629 {
1631  if(!this->IsBeingRefined())
1632  {
1635  }
1636 
1638  &&(mDistTableClock>this->GetClockMetricMatrix())) return;
1639  VFN_DEBUG_ENTRY("Crystal::CalcDistTable(fast="<<fast<<"),maxDist="<<mDistTableMaxDistance,4)
1640 
1641  const long nbComponent=mScattCompList.GetNbComponent();
1642 
1643  mvDistTableSq.resize(nbComponent);
1644  {
1645  std::vector<NeighbourHood>::iterator pos;
1646  for(pos=mvDistTableSq.begin();pos<mvDistTableSq.end();pos++)
1647  pos->mvNeighbour.clear();
1648  }
1649  VFN_DEBUG_MESSAGE("Crystal::CalcDistTable():1",3)
1650 
1651  // Get range and origin of the (pseudo) asymmetric unit
1652  const REAL asux0=this->GetSpaceGroup().GetAsymUnit().Xmin();
1653  const REAL asuy0=this->GetSpaceGroup().GetAsymUnit().Ymin();
1654  const REAL asuz0=this->GetSpaceGroup().GetAsymUnit().Zmin();
1655 
1656  const REAL asux1=this->GetSpaceGroup().GetAsymUnit().Xmax();
1657  const REAL asuy1=this->GetSpaceGroup().GetAsymUnit().Ymax();
1658  const REAL asuz1=this->GetSpaceGroup().GetAsymUnit().Zmax();
1659 
1660  const REAL halfasuxrange=(asux1-asux0)*0.5+1e-5;
1661  const REAL halfasuyrange=(asuy1-asuy0)*0.5+1e-5;
1662  const REAL halfasuzrange=(asuz1-asuz0)*0.5+1e-5;
1663 
1664  const REAL asuxc=0.5*(asux0+asux1);
1665  const REAL asuyc=0.5*(asuy0+asuy1);
1666  const REAL asuzc=0.5*(asuz0+asuz1);
1667 
1668  const REAL maxdx=halfasuxrange+mDistTableMaxDistance/GetLatticePar(0);
1669  const REAL maxdy=halfasuyrange+mDistTableMaxDistance/GetLatticePar(1);
1670  const REAL maxdz=halfasuzrange+mDistTableMaxDistance/GetLatticePar(2);
1671 
1672  // List of all positions within or near the first atom generated
1673  std::vector<DistTableInternalPosition> vPos;
1674  // index of unique atoms in vPos, which are strictly in the asymmetric unit
1675  std::vector<unsigned long> vUniqueIndex(nbComponent);
1676 
1677  const REAL asymUnitMargin2 = mDistTableMaxDistance*mDistTableMaxDistance;
1678 
1679  if(true)//(true==fast)
1680  {
1681  VFN_DEBUG_MESSAGE("Crystal::CalcDistTable(fast):2",3)
1682  TAU_PROFILE("Crystal::CalcDistTable(fast=true)","Matrix (string&)",TAU_DEFAULT);
1683  TAU_PROFILE_TIMER(timer1,"DiffractionData::CalcDistTable1","", TAU_FIELD);
1684  TAU_PROFILE_TIMER(timer2,"DiffractionData::CalcDistTable2","", TAU_FIELD);
1685 
1686  TAU_PROFILE_START(timer1);
1687 
1688  // No need to loop on a,b,c translations if mDistTableMaxDistance is small enough
1689  bool loopOnLattice=true;
1690  if( ((this->GetLatticePar(0)*.5)>mDistTableMaxDistance)
1691  &&((this->GetLatticePar(1)*.5)>mDistTableMaxDistance)
1692  &&((this->GetLatticePar(2)*.5)>mDistTableMaxDistance)) loopOnLattice=false;
1693 
1694  CrystMatrix_REAL symmetricsCoords;
1695 
1696  const int nbSymmetrics=this->GetSpaceGroup().GetNbSymmetrics(false,false);
1697 
1698  // Get the list of all atoms within or near the asymmetric unit
1699  for(long i=0;i<nbComponent;i++)
1700  {
1701  VFN_DEBUG_MESSAGE("Crystal::CalcDistTable(fast):3:component "<<i,0)
1702  // generate all symmetrics, excluding translations
1703  symmetricsCoords=this->GetSpaceGroup().GetAllSymmetrics(mScattCompList(i).mX,
1704  mScattCompList(i).mY,
1705  mScattCompList(i).mZ,
1706  false,false,false);
1707  mvDistTableSq[i].mIndex=i;//USELESS ?
1708  bool hasUnique=false;
1709  for(int j=0;j<nbSymmetrics;j++)
1710  {
1711  // take the closest position (using lattice translations) to the center of the ASU
1712  REAL x=fmod(symmetricsCoords(j,0)-asuxc,(REAL)1.0);if(x<-.5)x+=1;else if(x>.5)x-=1;
1713  REAL y=fmod(symmetricsCoords(j,1)-asuyc,(REAL)1.0);if(y<-.5)y+=1;else if(y>.5)y-=1;
1714  REAL z=fmod(symmetricsCoords(j,2)-asuzc,(REAL)1.0);if(z<-.5)z+=1;else if(z>.5)z-=1;
1715 
1716  //cout<<i<<","<<j<<":"<<FormatFloat(x,8,5)<<","<<FormatFloat(y,8,5)<<","<<FormatFloat(z,8,5)<<endl;
1717  if( (abs(x)<maxdx) && (abs(y)<maxdy) && (abs(z)<maxdz) )
1718  vPos.push_back(DistTableInternalPosition(i, j, x+asuxc, y+asuyc, z+asuzc));
1719  // Get one reference atom strictly within the pseudo-ASU
1720  if(!hasUnique)
1721  if( (abs(x)<halfasuxrange) && (abs(y)<halfasuyrange) && (abs(z)<halfasuzrange) )
1722  {
1723  hasUnique=true;
1724  vUniqueIndex[i]=vPos.size()-1;
1725  mvDistTableSq[i].mUniquePosSymmetryIndex=j;
1726  }
1727  }
1728  if(!hasUnique)
1729  {
1730  throw ObjCrystException("One atom did not have any symmetric in the ASU !");
1731  }
1732  }
1733  TAU_PROFILE_STOP(timer1);
1734  TAU_PROFILE_START(timer2);
1735  // Compute interatomic vectors & distance
1736  // between (i) unique atoms and (ii) all remaining atoms
1737 
1738  const CrystMatrix_REAL* pOrthMatrix=&(this->GetOrthMatrix());
1739 
1740  const REAL m00=(*pOrthMatrix)(0,0);
1741  const REAL m01=(*pOrthMatrix)(0,1);
1742  const REAL m02=(*pOrthMatrix)(0,2);
1743  const REAL m11=(*pOrthMatrix)(1,1);
1744  const REAL m12=(*pOrthMatrix)(1,2);
1745  const REAL m22=(*pOrthMatrix)(2,2);
1746 
1747  for(long i=0;i<nbComponent;i++)
1748  {
1749  VFN_DEBUG_MESSAGE("Crystal::CalcDistTable(fast):4:component "<<i,0)
1750  #if 0
1751  if(!this->IsBeingRefined()) cout<<endl<<"Unique pos:"<<vUniqueIndex[i]<<":"
1752  <<vPos[vUniqueIndex[i]].mAtomIndex<<":"
1753  <<mScattCompList(vPos[vUniqueIndex[i]].mAtomIndex).mpScattPow->GetName()<<":"
1754  <<vPos[vUniqueIndex[i]].mSymmetryIndex<<":"
1755  <<FormatFloat(vPos[vUniqueIndex[i]].mX,8,5)<<","
1756  <<FormatFloat(vPos[vUniqueIndex[i]].mY,8,5)<<","
1757  <<FormatFloat(vPos[vUniqueIndex[i]].mZ,8,5)<<endl;
1758  #endif
1759  std::vector<Crystal::Neighbour> * const vnb=&(mvDistTableSq[i].mvNeighbour);
1760  const REAL x0i=vPos[vUniqueIndex[i] ].mX;
1761  const REAL y0i=vPos[vUniqueIndex[i] ].mY;
1762  const REAL z0i=vPos[vUniqueIndex[i] ].mZ;
1763  for(unsigned long j=0;j<vPos.size();j++)
1764  {
1765  if((vUniqueIndex[i]==j) && (!loopOnLattice)) continue;// distance to self !
1766  // Start with the smallest absolute coordinates possible
1767  REAL x=fmod(vPos[j].mX - x0i,(REAL)1.0);if(x<-.5)x+=1;if(x>.5)x-=1;
1768  REAL y=fmod(vPos[j].mY - y0i,(REAL)1.0);if(y<-.5)y+=1;if(y>.5)y-=1;
1769  REAL z=fmod(vPos[j].mZ - z0i,(REAL)1.0);if(z<-.5)z+=1;if(z>.5)z-=1;
1770 
1771  const REAL x0=m00 * x + m01 * y + m02 * z;
1772  const REAL y0= m11 * y + m12 * z;
1773  const REAL z0= m22 * z;
1774 
1775  if(loopOnLattice)// distance to self !
1776  {//Now loop over lattice translations
1777  for(int sz=-1;sz<=1;sz+=2)// Sign of translation
1778  {
1779  for(int nz=(sz+1)/2;;++nz)
1780  {
1781  const REAL z=z0+sz*nz*m22;
1782  if(abs(z)>mDistTableMaxDistance) break;
1783  for(int sy=-1;sy<=1;sy+=2)// Sign of translation
1784  {
1785  for(int ny=(sy+1)/2;;++ny)
1786  {
1787  const REAL y=y0 + sy*ny*m11 + sz*nz*m12;
1788  if(abs(y)>mDistTableMaxDistance) break;
1789  for(int sx=-1;sx<=1;sx+=2)// Sign of translation
1790  {
1791  for(int nx=(sx+1)/2;;++nx)
1792  {
1793  if((vUniqueIndex[i]==j) && (nx==0) && (ny==0) && (nz==0)) continue;// distance to self !
1794  const REAL x=x0 + sx*nx*m00 + sy*ny*m01 + sz*nz*m02;
1795  if(abs(x)>mDistTableMaxDistance) break;
1796  const REAL d2=x*x+y*y+z*z;
1797  if(d2<=asymUnitMargin2)
1798  {
1799  Neighbour neigh(vPos[j].mAtomIndex,vPos[j].mSymmetryIndex,d2);
1800  vnb->push_back(neigh);
1801  #if 0
1802  if(!this->IsBeingRefined()) cout<<" "<<vPos[j].mAtomIndex<<":"
1803  <<mScattCompList(vPos[j].mAtomIndex).mpScattPow->GetName()<<":"
1804  <<vPos[j].mSymmetryIndex<<":"
1805  <<FormatFloat(vPos[j].mX,8,5)<<","
1806  <<FormatFloat(vPos[j].mY,8,5)<<","<<","
1807  <<FormatFloat(vPos[j].mZ,8,5)<<","<<" vector="
1808  <<FormatFloat(x,8,5)<<","
1809  <<FormatFloat(y,8,5)<<","
1810  <<FormatFloat(z,8,5)<<":"<<sqrt(d2)<<","
1811  <<"("<<sx*nx<<","<<sy*ny<<","<<sz*nz<<")"<<endl;
1812  #endif
1813  }
1814  }
1815  }
1816  }
1817  }
1818  }
1819  }
1820  }
1821  else
1822  {
1823  const REAL d2=x0*x0+y0*y0+z0*z0;
1824  if(d2<=asymUnitMargin2)
1825  {
1826  Neighbour neigh(vPos[j].mAtomIndex,vPos[j].mSymmetryIndex,d2);
1827  vnb->push_back(neigh);
1828  #if 0
1829  if(!this->IsBeingRefined()) cout<<vPos[j].mAtomIndex<<":"
1830  <<mScattCompList(vPos[j].mAtomIndex).mpScattPow->GetName()<<":"
1831  <<vPos[j].mSymmetryIndex<<":"
1832  <<vPos[j].mX<<","
1833  <<vPos[j].mY<<","
1834  <<vPos[j].mZ<<" vector="
1835  <<x0<<","<<y0<<","<<z0<<":"<<sqrt(d2)<<","<<asymUnitMargin2<<endl;
1836  #endif
1837  }
1838  }
1839 
1840  }
1841  }
1842  TAU_PROFILE_STOP(timer2);
1843  }
1845  VFN_DEBUG_EXIT("Crystal::CalcDistTable()",4)
1846 }
1847 
1849  mDeleteSubObjInDestructor=b;
1850 }
1851 
1852 #ifdef __WX__CRYST__
1853 WXCrystObjBasic* Crystal::WXCreate(wxWindow* parent)
1854 {
1855  VFN_DEBUG_ENTRY("Crystal::WXCreate(wxWindow*)",6)
1856  //:TODO: Check mpWXCrystObj==0
1857  mpWXCrystObj=new WXCrystal(parent,this);
1858  VFN_DEBUG_EXIT("Crystal::WXCreate(wxWindow*)",6)
1859  return mpWXCrystObj;
1860 }
1861 #endif
1862 
1863 }//namespace
RefinableObjClock mBondValenceCalcClock
Last time Bond Valences were calculated.
Definition: Crystal.h:502
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
const RefinableObjClock & GetMasterClockScatteringPower() const
Get the clock which reports all changes in ScatteringPowers.
Definition: Crystal.cpp:280
void RemoveBumpMergeDistance(const ScatteringPower &scatt1, const ScatteringPower &scatt2)
Remove an Anti-bumping distance between two scattering types.
Definition: Crystal.cpp:879
void RemoveScatterer(Scatterer *scatt, const bool del=true)
Remove a Scatterer. This also deletes the scatterer unless del=false.
Definition: Crystal.cpp:185
RefinableObjClock mClockScattCompList
Definition: Crystal.h:482
void CalcBondValenceSum() const
Calculate all Bond Valences.
Definition: Crystal.cpp:1239
void AddSubRefObj(RefinableObj &)
Crystal()
Default Constructor.
Definition: Crystal.cpp:56
void PrintMinDistanceTable(const REAL minDistance=0.1, ostream &os=cout) const
Print the minimum distance table between all scattering centers (atoms) in the crystal.
Definition: Crystal.cpp:428
virtual void Init(const REAL a, const REAL b, const REAL c, const REAL alpha, const REAL beta, const REAL gamma, const string &SpaceGroupId, const string &name)
Init all UnitCell parameters.
Definition: UnitCell.cpp:339
virtual void UpdateDisplay() const
If there is an interface, this should be automatically be called each time there is a 'new...
int GetNbSymmetrics(const bool noCenter=false, const bool noTransl=false) const
Return the number of equivalent positions in the spacegroup, ie the multilicity of the general positi...
Definition: SpaceGroup.cpp:419
virtual ostream & POVRayDescription(ostream &os, const CrystalPOVRayOptions &options) const =0
virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst)
Make a random move of the current configuration.
Definition: Crystal.cpp:894
const RefinableObjClock & GetClockLatticePar() const
last time the Lattice parameters were changed
Definition: UnitCell.cpp:323
~Crystal()
Crystal destructor.
Definition: Crystal.cpp:131
virtual const ScatteringComponentList & GetScatteringComponentList() const
Get the list of all scattering components.
Definition: Crystal.cpp:283
const cctbx::sgtbx::space_group & GetCCTbxSpg() const
Get the underlying cctbx Spacegroup object.
Definition: SpaceGroup.cpp:465
const RefinableObjClock & GetMaximumLikelihoodParClock() const
Get the clock value for the last change on the maximum likelihood parameters (positionnal error...
const RefinableObjClock & GetClockScatterer() const
Last time anything in the scatterer was changed (atoms, positions, scattering power) ...
Definition: Scatterer.cpp:133
REAL mBondValenceCostScale
Bond Valence cost scale factor.
Definition: Crystal.h:508
REAL GetBondLength(const MolAtom &at1, const MolAtom &at2)
Get The Bond Length between two atoms.
Definition: Molecule.cpp:59
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
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
void SetUseDynPopCorr(const int use)
Set the use of dynamical population correction (Crystal::mUseDynPopCorr).
Definition: Crystal.cpp:791
bool IsBeingRefined() const
Is the object being refined ? (Can be refined by one algorithm at a time only.)
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
RefinableObjClock mLatticeClock
Clock for lattice paramaters.
Definition: Crystal.h:470
vector< MolBond * >::const_iterator FindBond(const MolAtom &, const MolAtom &) const
Searches whether a bond between two atoms already exists.
Definition: Molecule.cpp:3955
int FindScatterer(const string &scattName) const
Find a scatterer (its index # in mpScatterrer[]) with a given name.
Definition: Crystal.cpp:803
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.
Interatomic distance for a given neighbour.
Definition: Crystal.h:433
RefinableObjClock mBondValenceCostClock
Last time the Bond Valence cost was calculated.
Definition: Crystal.h:504
ObjRegistry< ScatteringPower > mScatteringPowerRegistry
The registry of ScatteringPower for this Crystal.
Definition: Crystal.h:476
ObjRegistry< Scatterer > mScattererRegistry
The registry of scatterers for this UnitCell.
Definition: Crystal.h:418
int GetUseDynPopCorr() const
Get dynamical population correction setting.
Definition: Crystal.cpp:798
REAL GetBumpMergeCost() const
Get the Anti-bumping/pro-Merging cost function.
Definition: Crystal.cpp:820
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
void Click()
Record an event for this clock (generally, the 'time' an object has been modified, or some computation has been made)
void RemoveSubRefObj(RefinableObj &)
long GetNbPar() const
Total number of refinable parameter in the object.
virtual REAL GetLogLikelihood() const
Get -log(likelihood) of the current configuration for the object.
Definition: Crystal.cpp:925
void AddChild(const RefinableObjClock &)
Add a 'child' clock.
unsigned int GetMaxCovBonds() const
Maximum number of covalent bonds (from openbabel element.txt)
void SetBumpMergeDistance(const ScatteringPower &scatt1, const ScatteringPower &scatt2, const REAL dist=1.5)
Set the Anti-bumping distance between two scattering types.
Definition: Crystal.cpp:860
RefinableObjClock mClockDynPopCorr
Definition: Crystal.h:486
RefinablePar & GetPar(const long i)
Access all parameters in the order they were inputted.
const RefinableObjClock & GetClockScattererList() const
When was the list of scatterers last changed ?
Definition: Crystal.cpp:892
void Print() const
Print the list of Scattering components. For debugging.
Bond between two atoms, also a restraint on the associated bond length.
Definition: Molecule.h:152
RefinableObjClock mClockScattererList
Last time the list of Scatterers was changed.
Definition: Crystal.h:480
virtual int GetNbComponent() const =0
Number of components in the scatterer (eg number of point scatterers)
void CalcDynPopCorr(const REAL overlapDist=1., const REAL mergeDist=.0) const
Compute the 'Dynamical population correction for all atoms. Atoms which are considered "equivalent" (...
Definition: Crystal.cpp:708
virtual void RegisterClient(RefinableObj &) const
Register a new object using this object.
REAL mBumpMergeScale
Bump-merge scale factor.
Definition: Crystal.h:429
virtual int GetNbComponent() const
Number of components in the scatterer (eg number of point scatterers)
Definition: Molecule.cpp:3173
RefinableObjClock mMasterClockScatteringPower
master clock recording every change in Scattering Powers
Definition: Crystal.h:488
ObjRegistry< RefinableObj > gTopRefinableObjRegistry("Global Top RefinableObj registry")
This is a special registry for 'top' object for an optimization.
RefinableObjClock mClockMaster
Master clock, which is changed whenever the object has been altered.
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
Generic Refinable Object.
Definition: RefinableObj.h:752
const SpaceGroup & GetSpaceGroup() const
Access to the SpaceGroup object.
Definition: UnitCell.cpp:320
void AddScatterer(Scatterer *scatt)
Add a scatterer to the crystal.
Definition: Crystal.cpp:174
RefinableObjClock mBondValenceParClock
Last Time Bond Valence parameters were changed.
Definition: Crystal.h:500
REAL GetZ() const
Z coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:105
const RefinableObjClock & GetClockMaster() const
This clocks records any change in the object. See refinableObj::mClockMaster.
ScatteringComponentList mScattCompList
The list of all scattering components in the crystal.
Definition: Crystal.h:467
void ResetDynPopCorr() const
Reset Dynamical Population Correction factors (ie set it to 1)
Definition: Crystal.cpp:765
RefinableObjClock mBumpMergeParClock
Last Time Anti-bump parameters were changed.
Definition: Crystal.h:423
ObjRegistry< Crystal > gCrystalRegistry("List of all Crystals")
Global registry for all Crystal objects.
Definition: Crystal.h:525
Abstract base class for all objects in wxCryst.
Definition: wxCryst.h:127
const RefinableObjClock & GetClockMetricMatrix() const
last time the metric matrices were changed
Definition: UnitCell.cpp:324
void SetDeleteSubObjInDestructor(const bool b)
Set whether to delete the Scatterers and ScatteringPowers in the destructor.
Definition: Crystal.cpp:1848
string mName
Name for this RefinableObject. Should be unique, at least in the same scope.+.
REAL mBondValenceCost
Current Bond Valence cost.
Definition: Crystal.h:506
REAL GetBondValenceCost() const
Get the Bond-Valence cost function, which compares the expected valence to the one computed from Bond...
Definition: Crystal.cpp:1205
void RemoveScatteringPower(ScatteringPower *scattPow, const bool del=true)
Remove a ScatteringPower for this Crystal.
Definition: Crystal.cpp:237
const AsymmetricUnit & GetAsymUnit() const
Get the AsymmetricUnit for this spacegroup.
Definition: SpaceGroup.cpp:245
std::vector< NeighbourHood > mvDistTableSq
Interatomic distance table for all unique atoms.
Definition: Crystal.h:460
void ConnectAtoms(const REAL min_relat_dist=0.4, const REAL max_relat_dist=1.3, const bool warnuser_fail=false)
Convert as much as possible the crystal's atoms to molecule(s).
Definition: Crystal.cpp:1295
REAL GetBondAngle(const MolAtom &at1, const MolAtom &at2, const MolAtom &at3)
Get The Bond Angle of 3 atoms.
Definition: Molecule.cpp:95
Molecule : class for complex scatterer descriptions using cartesian coordinates with bond length/angl...
Definition: Molecule.h:731
Class to store POV-Ray output options.
Definition: General.h:175
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
Definition: Crystal.cpp:168
virtual void XMLInput(istream &is, const XMLCrystTag &tag)
Input From stream.
virtual void SetY(const REAL y)
Y coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:110
const RefinableObjClock & GetClockScattCompList() const
Get the list of all scattering components.
Definition: Crystal.cpp:319
REAL mBumpMergeCost
Current bump-merge cost.
Definition: Crystal.h:427
REAL GetVolume() const
Volume of Unit Cell (in Angstroems)
Definition: UnitCell.cpp:326
RefObjOpt mUseDynPopCorr
Use Dynamical population correction (ScatteringComponent::mDynPopCorr) during Structure factor calcul...
Definition: Crystal.h:473
virtual void GLInitDisplayList(const bool noSymmetrics=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 =0
wxCryst class for Crystals
Definition: wxCrystal.h:80
virtual void XMLOutput(ostream &os, int indent=0) const
Output to stream in well-formed XML.
void RemoveChild(const RefinableObjClock &)
remove a child clock. This also tells the child clock to remove the parent.
REAL GetX() const
X coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:103
ostream & POVRayDescription(ostream &os, const CrystalPOVRayOptions &options) const
XMLOutput POV-Ray Description for this Crystal.
Definition: Crystal.cpp:461
CrystMatrix_REAL GetAllSymmetrics(const REAL x, const REAL y, const REAL z, const bool noCenter=false, const bool noTransl=false, const bool noIdentical=false) const
Get all equivalent positions of a (xyz) position.
Definition: SpaceGroup.cpp:274
Scatterer & GetScatt(const string &scattName)
Provides an access to the scatterers.
Definition: Crystal.cpp:198
virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint &groupIndex, unsigned int &firstGroup) const
Get the gene group assigned to each parameter.
Definition: Crystal.cpp:1141
output a number as a formatted float:
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
MolAtom : atom inside a Molecule.
Definition: Molecule.h:58
ObjRegistry< Scatterer > & GetScattererRegistry()
Get the registry of scatterers.
Definition: Crystal.cpp:218
const map< MolAtom *, set< MolAtom * > > & GetConnectivityTable()
Get the connectivity table.
Definition: Molecule.cpp:4574
vector< MolAtom * >::iterator RemoveAtom(MolAtom &, const bool del=true)
Remove an atom.
Definition: Molecule.cpp:3842
CrystMatrix_REAL GetMinDistanceTable(const REAL minDistance=0.1) const
Minimum interatomic distance between all scattering components (atoms) in the crystal.
Definition: Crystal.cpp:387
ObjRegistry< ScatteringPower > & GetScatteringPowerRegistry()
Get the registry of ScatteringPower included in this Crystal.
Definition: Crystal.cpp:222
VBumpMergePar mvBumpMergePar
Anti-bump parameters map.
Definition: Crystal.h:421
output a string with a fixed length (adding necessary space or removing excess characters) : ...
virtual void SetX(const REAL x)
X coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:109
void CalcDistTable(const bool fast) const
Compute the distance Table (mDistTable) for all scattering components.
Definition: Crystal.cpp:1628
RefObjOpt mDisplayEnantiomer
Display the enantiomeric (mirror along x) structure in 3D? This can be helpful for non-centrosymmetri...
Definition: Crystal.h:493
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: Crystal.cpp:1160
void SetCrystal(Crystal &)
Set the crystal in which is included this Scatterer.
Definition: Scatterer.cpp:136
virtual string GetComponentName(const int i) const =0
Name for the i-th component of this scatterer.
virtual void CIFOutput(ostream &os, double mindist=0.5) const
output Crystal structure as a cif file (EXPERIMENTAL !)
Definition: Crystal.cpp:930
void Reset()
Reset a Clock to 0, to force an update.
int GetAtomicNumber() const
Atomic number for this atom.
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
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: Atom.cpp:47
The Scattering Power for an Atom.
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 displayNames=false, const bool hideHydrogens=false) const
Create an OpenGL DisplayList of the crystal.
Definition: Crystal.cpp:545
void BuildConnectivityTable() const
Build the Connectivity table.
Definition: Molecule.cpp:5299
const CrystMatrix_REAL & GetOrthMatrix() const
Get the orthogonalization matrix (UnitCell::mOrthMatrix)for the UnitCell in real space.
Definition: UnitCell.cpp:242
map< pair< const ScatteringPower *, const ScatteringPower * >, REAL > mvBondValenceRo
Map of Bond Valence "Ro" parameters for each couple of ScatteringPower.
Definition: Crystal.h:498
virtual const string & GetName() const
Name of the object.
void Init(const REAL a, const REAL b, const REAL c, const REAL alpha, const REAL beta, const REAL gamma, const string &SpaceGroupId, const string &name)
Init all Crystal parameters.
Definition: Crystal.cpp:1277
RefinableObjClock mClockNeighborTable
Definition: Crystal.h:484
virtual const ScatteringComponentList & GetScatteringComponentList() const =0
Get the list of all scattering components for this scatterer.
std::map< long, REAL > mvBondValenceCalc
List of calculated bond valences, as a map, the key being the index of the atom in Crystal::mScattCom...
Definition: Crystal.h:511
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
void SetGlobalOptimStep(const RefParType *type, const REAL step)
Change the maximum step to use during Global Optimization algorithms.
REAL GetY() const
Y coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:104
Storage for anti-bump/merge parameters.
Definition: Crystal.h:309
class to input or output a well-formatted xml beginning or ending tag.
RefinableObjClock mDistTableClock
The time when the distance table was last calculated.
Definition: Crystal.h:462
long GetNbScatterer() const
Number of scatterers in the crystal.
Definition: Crystal.cpp:196
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 ...
virtual void DeRegisterClient(RefinableObj &) const
Deregister an object (which not any more) using this object.
Generic type of scatterer: can be an atom, or a more complex assembly of atoms.
Definition: Scatterer.h:130
void AddScatteringPower(ScatteringPower *scattPow)
Add a ScatteringPower for this Crystal.
Definition: Crystal.cpp:227
char GetExtension() const
Extension to space group symbol ('1','2':origin choice ; 'R','H'=rhomboedral/hexagonal) ...
Definition: SpaceGroup.cpp:471
RefinableObjClock mBumpMergeCostClock
Last Time Anti-bump parameters were changed.
Definition: Crystal.h:425
Object Registry.
Definition: RefinableObj.h:643
void AddOption(RefObjOpt *opt)
REAL mDistTableMaxDistance
The distance up to which the distance table & neighbours needs to be calculated.
Definition: Crystal.h:464
REAL GetCovalentRadius() const
Covalent Radius for this atom, in Angstroems (from cctbx)
void InitOptions()
Init options.
Definition: Crystal.cpp:1576
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
std::map< pair< const ScatteringPower *, const ScatteringPower * >, Crystal::BumpMergePar > VBumpMergePar
Anti-bump parameters.
Definition: Crystal.h:325
virtual void SetZ(const REAL z)
Z coordinate (fractionnal) of the scatterer (for complex scatterers, this corresponds to the position...
Definition: Scatterer.cpp:111
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal...