FOX/ObjCryst++  1.10.X (development)
SpaceGroup.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++ AsymmetricUnit and SpaceGroup classes
21 *
22 */
23 
24 #include <iomanip>
25 #include <cmath>
26 #include <typeinfo>
27 
28 #include "cctbx/sgtbx/space_group.h"
29 #include "cctbx/sgtbx/brick.h"
30 #include "cctbx/miller/sym_equiv.h"
31 #include "boost/rational.hpp"
32 
33 #include "ObjCryst/ObjCryst/SpaceGroup.h"
34 #include "ObjCryst/Quirks/VFNStreamFormat.h" //simple formatting of integers, REALs..
35 #include "ObjCryst/ObjCryst/GeomStructFactor.h" //Geometrical Struct Factor definitions
36 #include "ObjCryst/Quirks/VFNDebug.h"
37 
38 
39 #include <fstream>
40 
41 namespace ObjCryst
42 {
43 
44 #include "ObjCryst/Quirks/VFNDebug.h"
45 
46 // We need to force the C locale when using cctbx (when interpreting xyz strings)
47 tmp_C_Numeric_locale::tmp_C_Numeric_locale()
48 {
49  char *old;
50  old=setlocale(LC_NUMERIC,NULL);
51  mLocale=old;
52  setlocale(LC_NUMERIC,"C");
53 }
54 
55 tmp_C_Numeric_locale::~tmp_C_Numeric_locale()
56 {
57  setlocale(LC_NUMERIC,mLocale.c_str());
58 }
59 
61 //
62 // AsymmetricUnit
63 //
66 {
67  VFN_DEBUG_MESSAGE("AsymmetricUnit::AsymmetricUnit()",5)
68  mXmin=0;
69  mYmin=0;
70  mZmin=0;
71  mXmax=1;
72  mYmax=1;
73  mZmax=1;
74 }
75 
77 {
78  VFN_DEBUG_MESSAGE("AsymmetricUnit::AsymmetricUnit(SpGroup)",5)
79  this->SetSpaceGroup(spg);
80 }
81 
82 AsymmetricUnit::~AsymmetricUnit()
83 {
84  VFN_DEBUG_MESSAGE("AsymmetricUnit::~AsymmetricUnit(SpGroup)",5)
85 }
86 
88 {
89  VFN_DEBUG_MESSAGE("AsymmetricUnit::SetSpaceGroup(SpGroup)",5)
90  tmp_C_Numeric_locale tmploc;
91  # if 0
92  TAU_PROFILE("(AsymmetricUnit::SetSpaceGroup)","void (SpaceGroup)",TAU_DEFAULT);
93  mXmin=0.;
94  mYmin=0.;
95  mZmin=0.;
96  mXmax=1.;
97  mYmax=1.;
98  mZmax=1.;
99  if(1==spg.GetSpaceGroupNumber()) return;//no need to search an asymmetric unit
100  // Test points=reular grid of points inside the unit cell
101  // All points must be or have at least a symmetric in the asymmetric unit
102  const long nbPoints=13;
103  CrystMatrix_REAL testPoints(nbPoints*nbPoints*nbPoints,3);
104  {
105  long l=0;
106  for(long i=0;i<nbPoints;i++)
107  for(long j=0;j<nbPoints;j++)
108  for(long k=0;k<nbPoints;k++)
109  {
110  testPoints(l ,0)=i/(REAL)nbPoints;
111  testPoints(l ,1)=j/(REAL)nbPoints;
112  testPoints(l++,2)=k/(REAL)nbPoints;
113  }
114  }
115  testPoints += 0.01;
116 
117  CrystVector_REAL vert(8);//vertices limits
118  vert(0)=1/8.; vert(1)=1/6.; vert(2)=1/4.; vert(3)=1/3.;
119  vert(4)=1/2.; vert(5)=2/3.; vert(6)=3/4.; vert(7)=1.;
120 
121  const int NbStep=vert.numElements();
122 
123  CrystMatrix_REAL coords;
124 
125  double junk;
126 
127  REAL minVolume=1.;
128 
129  bool allPtsInAsym,tmp;
130  for(long nx=0;nx<NbStep;nx++)
131  for(long ny=0;ny<NbStep;ny++)
132  for(long nz=0;nz<NbStep;nz++)
133  {
134  if(minVolume<(vert(nx)*vert(ny)*vert(nz)-.0001)) break;
135  allPtsInAsym=true;
136  for(int i=0;i<testPoints.rows();i++)
137  {
138  coords=spg.GetAllSymmetrics(testPoints(i,0),testPoints(i,1),testPoints(i,2));
139  for(long j=0;j<coords.numElements();j++) coords(j)=modf(coords(j)+10.,&junk) ;
140  tmp=false;
141  for(long j=0;j<coords.rows();j++)
142  {//Test if at least one of the symmetrics is in the parallelepiped
143  if( (coords(j,0) < vert(nx))
144  &&(coords(j,1) < vert(ny))
145  &&(coords(j,2) < vert(nz)))
146  {
147  //cout << modf(coords(j,0)+10.,junk) << " "
148  // << modf(coords(j,1)+10.,junk) << " "
149  // << modf(coords(j,2)+10.,junk) << endl;
150  tmp=true;
151  break;
152  }
153  }
154  if(false==tmp)
155  {
156  //cout << " Rejected:"<<vert(nx)<<" "<<vert(ny)<<" "<<vert(nz)<<" "<<i<<endl;
157  //cout << coords <<endl;
158  allPtsInAsym=false;
159  break;
160  }
161  }
162  if( (true==allPtsInAsym))
163  {
164  mXmax=vert(nx);
165  mYmax=vert(ny);
166  mZmax=vert(nz);
167  VFN_DEBUG_MESSAGE("->ACCEPTED:" << mXmax <<" "<< mYmax <<" "<< mZmax <<endl,2)
168  //cout << "->ACCEPTED:" << mXmax <<" "<< mYmax <<" "<< mZmax <<endl;
169  minVolume=vert(nx)*vert(ny)*vert(nz);
170  break;//no need to grow any more along z
171  }
172  }
173  cout<<"->Finished Generating (pseudo) Asymmetric Unit, with:"<<endl
174  <<" 0 <= x <= "<< mXmax<<endl
175  <<" 0 <= y <= "<< mYmax<<endl
176  <<" 0 <= z <= "<< mZmax<<endl<<endl;
177  #else
178  const cctbx::sgtbx::brick b(spg.GetCCTbxSpg().type());
179  #ifdef __DEBUG__
180  cout<<"->>Parallelepipedic Asymmetric Unit, from cctbx::sgtbx::brick:"<<endl
181  <<b.as_string()<<endl;
182  #endif
183  mXmin=boost::rational_cast<REAL,int>(b(0,0).value());
184  mYmin=boost::rational_cast<REAL,int>(b(1,0).value());
185  mZmin=boost::rational_cast<REAL,int>(b(2,0).value());
186  mXmax=boost::rational_cast<REAL,int>(b(0,1).value());
187  mYmax=boost::rational_cast<REAL,int>(b(1,1).value());
188  mZmax=boost::rational_cast<REAL,int>(b(2,1).value());
189 
190  #endif
191 }
192 
193 bool AsymmetricUnit::IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z)const
194 {
195  return ( ( x <= mXmin) && ( x >= mXmax)
196  &&( y <= mYmin) && ( y >= mYmax)
197  &&( z <= mZmin) && ( z >= mZmax));
198 }
199 REAL AsymmetricUnit::Xmin() const {return mXmin;}
200 REAL AsymmetricUnit::Xmax() const {return mXmax;}
201 REAL AsymmetricUnit::Ymin() const {return mYmin;}
202 REAL AsymmetricUnit::Ymax() const {return mYmax;}
203 REAL AsymmetricUnit::Zmin() const {return mZmin;}
204 REAL AsymmetricUnit::Zmax() const {return mZmax;}
205 
207 //
208 // SpaceGroup
209 //
211 
212 SpaceGroup::SpaceGroup():mId("P1"),mpCCTbxSpaceGroup(0)
213 {
215 }
216 
217 SpaceGroup::SpaceGroup(const string &spgId):mId(spgId),mpCCTbxSpaceGroup(0)
218 {
219  InitSpaceGroup(spgId);
220 }
221 
223 {
224  if(mpCCTbxSpaceGroup!=0) delete mpCCTbxSpaceGroup;
225 }
226 
227 void SpaceGroup::ChangeSpaceGroup(const string &spgId)
228 {
229  VFN_DEBUG_MESSAGE("SpaceGroup::ChangeSpaceGroup():"<<spgId,5)
230  this->InitSpaceGroup(spgId);
231 }
232 
233 const string& SpaceGroup::GetName()const{return mId;}
234 
235 bool SpaceGroup::IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z) const
236 {
237  return mAsymmetricUnit.IsInAsymmetricUnit(x,y,z);
238 }
239 
240 void SpaceGroup::ChangeToAsymmetricUnit(REAL x, REAL y, REAL z) const
241 {
242  //:TODO:
243 }
244 
246 
247 
250 {
251  return mSpgNumber;
252 }
253 
255 {
256  return mHasInversionCenter;
257 }
258 
260 {
261  return mNbTrans;
262 }
263 
264 const std::vector<SpaceGroup::TRx>& SpaceGroup::GetTranslationVectors()const
265 {
266  return mvTrans;
267 }
268 
269 const std::vector<SpaceGroup::SMx>& SpaceGroup::GetSymmetryOperations()const
270 {
271  return mvSym;
272 }
273 
274 CrystMatrix_REAL SpaceGroup::GetAllSymmetrics(const REAL x, const REAL y, const REAL z,
275  const bool noCenter,const bool noTransl,
276  const bool noIdentical)const
277 {
278  //TAU_PROFILE("SpaceGroup::GetAllSymmetrics()","Matrix (x,y,z)",TAU_DEFAULT);
279  VFN_DEBUG_MESSAGE("SpaceGroup::GetAllSymmetrics()",0)
280  int nbMatrix, nbTrans,coeffInvert,i,j,k;
281  nbMatrix=this->GetCCTbxSpg().n_smx();
282  nbTrans=this->GetNbTranslationVectors();
283  if(this->IsCentrosymmetric()) coeffInvert=2 ; else coeffInvert=1;
284 
285  if(noCenter==true) coeffInvert=1; //skip center of symmetry
286  if(noTransl==true) nbTrans=1; //skip translation operations
287  CrystMatrix_REAL coords(nbMatrix*nbTrans*coeffInvert,3);
288 
289  k=0;
290  for(i=0;i<nbTrans;i++)
291  {
292  const REAL ltr_den=1/(REAL)(this->GetCCTbxSpg().ltr(i).den());
293  const REAL tx=this->GetCCTbxSpg().ltr(i)[0]*ltr_den;
294  const REAL ty=this->GetCCTbxSpg().ltr(i)[1]*ltr_den;
295  const REAL tz=this->GetCCTbxSpg().ltr(i)[2]*ltr_den;
296  //if(noTransl==false) cout << nbTrans <<endl;
297  //if(noTransl==false) cout << tx <<" "<< ty<<" "<< tz<<" "<<endl;
298  for(j=0;j<nbMatrix;j++)
299  {
300  const cctbx::sgtbx::rt_mx *pMatrix=&(this->GetCCTbxSpg().smx(j));
301  const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r());
302  const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t());
303  const REAL r_den=1/(REAL)(pMatrix->r().den());
304  const REAL t_den=1/(REAL)(pMatrix->t().den());
305  coords(k,0)= ((*pRot)[0]*x+(*pRot)[1]*y+(*pRot)[2]*z)*r_den+(*pTrans)[0]*t_den+tx;
306  coords(k,1)= ((*pRot)[3]*x+(*pRot)[4]*y+(*pRot)[5]*z)*r_den+(*pTrans)[1]*t_den+ty;
307  coords(k,2)= ((*pRot)[6]*x+(*pRot)[7]*y+(*pRot)[8]*z)*r_den+(*pTrans)[2]*t_den+tz;
308  k++;
309  }
310  }
311  if(coeffInvert==2) //inversion center not in ListSeitzMx, but to be applied
312  {
313  int shift=nbMatrix*nbTrans;
314  const REAL dx=((REAL)this->GetCCTbxSpg().inv_t()[0])/(REAL)this->GetCCTbxSpg().inv_t().den();//inversion not at the origin
315  const REAL dy=((REAL)this->GetCCTbxSpg().inv_t()[1])/(REAL)this->GetCCTbxSpg().inv_t().den();
316  const REAL dz=((REAL)this->GetCCTbxSpg().inv_t()[2])/(REAL)this->GetCCTbxSpg().inv_t().den();
317  for(i=0;i<shift;i++)
318  {
319  coords(i+shift,0)=dx-coords(i,0);
320  coords(i+shift,1)=dy-coords(i,1);
321  coords(i+shift,2)=dz-coords(i,2);
322  }
323  }
324  //for(i=0;i<nbTrans*nbMatrix*coeffInvert;i++)
325  //cout <<FormatFloat(coords(0,i))<<FormatFloat(coords(1,i))<<FormatFloat(coords(2,i))<<endl;
326  //if(noTransl==false) cout <<coords<<endl;
327 
328  if(true==noIdentical)
329  {
330  VFN_DEBUG_MESSAGE("SpaceGroup::GetAllSymmetrics():Removing identical atoms",5)
331  //Bring back all coordinates to [0;1[
332  REAL *p=coords.data();
333  double junk;
334  for(long i=0;i<coords.numElements();i++)
335  {
336  *p = modf(*p,&junk);
337  if(*p<0) *p += 1.;
338  p++;
339  }
340  CrystMatrix_REAL newCoords;
341  newCoords=coords;
342  const REAL eps=1e-5;
343  long nbKeep=0;
344  for(long i=0;i<coords.rows();i++)
345  {
346  bool keep=true;
347  for(long j=0;j<i;j++)
348  {
349  if( ( fabs(coords(i,0)-coords(j,0)) < eps )
350  &&( fabs(coords(i,1)-coords(j,1)) < eps )
351  &&( fabs(coords(i,2)-coords(j,2)) < eps )) keep=false;
352  }
353  if(true==keep)
354  {
355  newCoords(nbKeep ,0) = coords(i,0);
356  newCoords(nbKeep ,1) = coords(i,1);
357  newCoords(nbKeep++,2) = coords(i,2);
358  }
359  }
360  newCoords.resizeAndPreserve(nbKeep,3);
361  return newCoords;
362  }
363  VFN_DEBUG_MESSAGE("SpaceGroup::GetAllSymmetrics():End",0)
364  return coords;
365 }
366 void SpaceGroup::GetSymmetric(unsigned int idx, REAL &x, REAL &y, REAL &z,
367  const bool noCenter,const bool noTransl,
368  const bool derivative) const
369 {
370  int coeffInvert;
371  const int nbMatrix=this->GetCCTbxSpg().n_smx();
372  int nbTrans=this->GetNbTranslationVectors();
373  if(this->IsCentrosymmetric()) coeffInvert=2 ; else coeffInvert=1;
374 
375  if(noCenter==true) coeffInvert=1; //skip center of symmetry
376  if(noTransl==true) nbTrans=1; //skip translation operations
377 
378  unsigned int idx0=idx;
379  const unsigned int mxidx = nbTrans * nbMatrix;
380  if(idx > mxidx) idx0 = idx % mxidx;
381  const int i=idx/nbMatrix;//translation index
382  const int j=idx%nbMatrix;
383 
384  const REAL ltr_den=1/(REAL)(this->GetCCTbxSpg().ltr(i).den());
385  const REAL tx=this->GetCCTbxSpg().ltr(i)[0]*ltr_den;
386  const REAL ty=this->GetCCTbxSpg().ltr(i)[1]*ltr_den;
387  const REAL tz=this->GetCCTbxSpg().ltr(i)[2]*ltr_den;
388  const cctbx::sgtbx::rt_mx *pMatrix=&(this->GetCCTbxSpg().smx(j));
389  const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r());
390  const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t());
391  const REAL r_den=1/(REAL)(pMatrix->r().den());
392  const REAL t_den=1/(REAL)(pMatrix->t().den());
393  const REAL x1= ((*pRot)[0]*x+(*pRot)[1]*y+(*pRot)[2]*z)*r_den;
394  const REAL y1= ((*pRot)[3]*x+(*pRot)[4]*y+(*pRot)[5]*z)*r_den;
395  const REAL z1= ((*pRot)[6]*x+(*pRot)[7]*y+(*pRot)[8]*z)*r_den;
396  if(derivative==false)
397  {
398  x=x1+(*pTrans)[0]*t_den+tx;
399  y=y1+(*pTrans)[1]*t_den+ty;
400  z=z1+(*pTrans)[2]*t_den+tz;
401  }
402  else
403  {
404  x=x1;
405  y=y1;
406  z=z1;
407  }
408  if(coeffInvert==2) //inversion center not in ListSeitzMx, but to be applied
409  {
410  const REAL dx=((REAL)this->GetCCTbxSpg().inv_t()[0])/(REAL)this->GetCCTbxSpg().inv_t().den();//inversion not at the origin
411  const REAL dy=((REAL)this->GetCCTbxSpg().inv_t()[1])/(REAL)this->GetCCTbxSpg().inv_t().den();
412  const REAL dz=((REAL)this->GetCCTbxSpg().inv_t()[2])/(REAL)this->GetCCTbxSpg().inv_t().den();
413  x=dx-x;
414  y=dy-y;
415  z=dz-z;
416  }
417 }
418 
419 int SpaceGroup::GetNbSymmetrics(const bool noCenter,const bool noTransl)const
420 {
421  if(noCenter || (!mHasInversionCenter))
422  {
423  if(noTransl) return mNbSym;
424  else return mNbSym*mNbTrans;
425  }
426  else
427  {
428  if(noTransl) return 2*mNbSym;
429  else return 2*mNbSym*mNbTrans;
430  }
431  return 2*mNbSym*mNbTrans;
432 }
433 
434 void SpaceGroup::Print() const
435 {
436  cout << "SpaceGroup:" <<endl;
437  cout << " Schoenflies symbol = " << this->GetCCTbxSpg().match_tabulated_settings().schoenflies() << endl ;
438  cout << " Hermann-Maugin symbol = " << this->GetCCTbxSpg().match_tabulated_settings().hermann_mauguin() << endl ;
439  cout << " Hall symbol = " << this->GetCCTbxSpg().match_tabulated_settings().hall() << endl ;
440  cout << " SgNumber = " << this->GetCCTbxSpg().match_tabulated_settings().number() << endl ;
441  cout << " Number of Seitz Matrix = " << this->GetCCTbxSpg().n_smx() << endl ;
442  cout << " Number of Translation Vectors = " << this->GetCCTbxSpg().n_ltr() << endl ;
443  cout << " List of Seitz Matrices : " << endl ;
444  for(unsigned int i=0;i<this->GetCCTbxSpg().n_smx();i++)
445  cout << " " << this->GetCCTbxSpg().smx(i).as_xyz() <<endl;
446  if(true==mHasInversionCenter)
447  {
448  cout << " There is an inversion center at "
449  << (this->GetCCTbxSpg().inv_t()[0])/(REAL)this->GetCCTbxSpg().inv_t().den()/2. << " "
450  << (this->GetCCTbxSpg().inv_t()[1])/(REAL)this->GetCCTbxSpg().inv_t().den()/2. << " "
451  << (this->GetCCTbxSpg().inv_t()[2])/(REAL)this->GetCCTbxSpg().inv_t().den()/2. << endl;
452  }
453  if(this->GetCCTbxSpg().n_ltr()>0)
454  {
455  cout <<" List of Translation vectors :"<<endl;
456  for(unsigned int i=0;i<this->GetCCTbxSpg().n_ltr();i++)
457  cout << " "<< this->GetCCTbxSpg().ltr(i)[0]/(REAL)this->GetCCTbxSpg().ltr(i).den()<<","
458  << this->GetCCTbxSpg().ltr(i)[1]/(REAL)this->GetCCTbxSpg().ltr(i).den()<<","
459  << this->GetCCTbxSpg().ltr(i)[2]/(REAL)this->GetCCTbxSpg().ltr(i).den()<<endl;
460  }
461  cout<<"Extension (origin choice, rhomboedral/hexagonal):"<<mExtension<<endl;
462 }
465 const cctbx::sgtbx::space_group& SpaceGroup::GetCCTbxSpg()const{return *mpCCTbxSpaceGroup;}
466 
468 
469 unsigned int SpaceGroup::GetUniqueAxis()const{return mUniqueAxisId;}
470 
472 
473 CrystVector_REAL SpaceGroup::GetInversionCenter()const {
474  CrystVector_REAL center(3);
475  center(0) =((REAL)this->GetCCTbxSpg().inv_t()[0])/(REAL)this->GetCCTbxSpg().inv_t().den();//inversion not at the origin
476  center(1) =((REAL)this->GetCCTbxSpg().inv_t()[1])/(REAL)this->GetCCTbxSpg().inv_t().den();
477  center(2) =((REAL)this->GetCCTbxSpg().inv_t()[2])/(REAL)this->GetCCTbxSpg().inv_t().den();
478  return center;
479 }
480 
481 unsigned int SpaceGroup::AreReflEquiv(const REAL h1, const REAL k1, const REAL l1,
482  const REAL h2, const REAL k2, const REAL l2)const
483 {
484  const int ih1=scitbx::math::iround(h1);
485  const int ik1=scitbx::math::iround(k1);
486  const int il1=scitbx::math::iround(l1);
487  cctbx::miller::index<long> h0(scitbx::vec3<long>(ih1,ik1,il1));
488  const int ih2=scitbx::math::iround(h2);
489  const int ik2=scitbx::math::iround(k2);
490  const int il2=scitbx::math::iround(l2);
491  cctbx::miller::index<long> k0(scitbx::vec3<long>(ih2,ik2,il2));
492  cctbx::miller::sym_equiv_indices sei(this->GetCCTbxSpg(),k0);
493  int equiv=0;
494  //cout<<h0.as_string()<<" - "<<k0.as_string()<<","<<sei.f_mates(false)<<","<<sei.f_mates(true)<<endl;
495  for(size_t i_indices=0;i_indices<sei.indices().size();i_indices++)
496  {
497  const size_t sfm = sei.f_mates(false);
498  for(size_t i_mate = 0; i_mate < sfm; i_mate++)
499  {
500  cctbx::miller::index<long> k = sei(i_mate, i_indices).h();
501  //cout<<" ->("<<i_indices<<","<<i_mate<<")"<<k.as_string()<<endl;
502  if(h0==k)
503  {
504  if(i_mate==0) equiv=1;
505  else equiv=2;
506  break;
507  }
508  }
509  }
510  VFN_DEBUG_MESSAGE("SpaceGroup::AreReflEquiv("<<ih1<<","<<ik1<<","<<il1<<"),("<<ih2<<","<<ik2<<","<<il2<<"):"<<equiv,2)
511  return equiv;
512 }
513 
514 CrystMatrix_REAL SpaceGroup::GetAllEquivRefl(const REAL h0, const REAL k0, const REAL l0,
515  const bool excludeFriedelMate,
516  const bool forceFriedelLaw,
517  const REAL sf_re,const REAL sf_im) const
518 {
519  VFN_DEBUG_ENTRY("SpaceGroup::GetAllEquivRefl():",5)
520  const int ih0=scitbx::math::iround(h0);
521  const int ik0=scitbx::math::iround(k0);
522  const int il0=scitbx::math::iround(l0);
523  cctbx::miller::index<long> h(scitbx::vec3<long>(ih0,ik0,il0));
524  cctbx::miller::sym_equiv_indices sei(this->GetCCTbxSpg(),h);
525  int nbEquiv;
526  if(forceFriedelLaw) nbEquiv=sei.multiplicity(false);
527  else nbEquiv=sei.multiplicity(true);
528  if( ((this->IsCentrosymmetric())||forceFriedelLaw) && excludeFriedelMate) nbEquiv/=2;
529  CrystMatrix_REAL equivReflList(nbEquiv,5);
530  complex<double> sf0((double)(sf_re),(double)(sf_im));
531  for(int i=0;i<nbEquiv;i+=1)
532  {
533  cctbx::miller::index<long> k = sei(i).h();
534  equivReflList(i,0)=(REAL)k[0];
535  equivReflList(i,1)=(REAL)k[1];
536  equivReflList(i,2)=(REAL)k[2];
537  equivReflList(i,3)=(REAL)sei(i).complex_eq(sf0).real();
538  equivReflList(i,4)=(REAL)sei(i).complex_eq(sf0).imag();
539  }
540  VFN_DEBUG_EXIT("SpaceGroup::GetAllEquivRefl():",5)
541  return equivReflList;
542 }
543 
544 bool SpaceGroup::IsReflSystematicAbsent(const REAL h0, const REAL k0, const REAL l0)const
545 {
546  const int ih0=scitbx::math::iround(h0);
547  const int ik0=scitbx::math::iround(k0);
548  const int il0=scitbx::math::iround(l0);
549  cctbx::miller::index<long> h(scitbx::vec3<long>(ih0,ik0,il0));
550  return this->GetCCTbxSpg().is_sys_absent(h);
551 }
552 
553 bool SpaceGroup::IsReflCentric(const REAL h0, const REAL k0, const REAL l0)const
554 {
555  const int ih0=scitbx::math::iround(h0);
556  const int ik0=scitbx::math::iround(k0);
557  const int il0=scitbx::math::iround(l0);
558  cctbx::miller::index<long> h(scitbx::vec3<long>(ih0,ik0,il0));
559  return this->GetCCTbxSpg().is_centric(h);
560 }
561 
562 unsigned int SpaceGroup::GetExpectedIntensityFactor(const REAL h0,
563  const REAL k0,
564  const REAL l0)const
565 {
566  const int ih0=scitbx::math::iround(h0);
567  const int ik0=scitbx::math::iround(k0);
568  const int il0=scitbx::math::iround(l0);
569  cctbx::miller::index<long> h(scitbx::vec3<long>(ih0,ik0,il0));
570  return this->GetCCTbxSpg().epsilon(h);
571 }
572 
573 void SpaceGroup::InitSpaceGroup(const string &spgId)
574 {
575  if((mId==spgId)&&(mpCCTbxSpaceGroup!=0)) return;
576  VFN_DEBUG_ENTRY("SpaceGroup::InitSpaceGroup():"<<spgId,8)
577  #ifdef __DEBUG__
578  (*fpObjCrystInformUser)("Initializing spacegroup: "+spgId);
579  #endif
580  try
581  {
582  cctbx::sgtbx::space_group_symbols sgs=cctbx::sgtbx::space_group_symbols(spgId);
583  if(mpCCTbxSpaceGroup!=0) delete mpCCTbxSpaceGroup;
585  mpCCTbxSpaceGroup = new cctbx::sgtbx::space_group(sgs);
586  }
587  catch(exception &ex1)
588  {
589  try
590  {
591  (*fpObjCrystInformUser)("Failed lookup symbol ! try Hall symbol ?");
592  if(mpCCTbxSpaceGroup!=0) delete mpCCTbxSpaceGroup;
594  mpCCTbxSpaceGroup = new cctbx::sgtbx::space_group(spgId);
595  }
596  catch(exception &ex2)
597  {
598  (*fpObjCrystInformUser)("Could not interpret Spacegroup Symbol:"+spgId);
599  this->InitSpaceGroup(mId);
600  VFN_DEBUG_EXIT("SpaceGroup::InitSpaceGroup() could not interpret spacegroup:"<<spgId<<":"<<ex1.what()<<":"<<ex2.what(),8)
601  return;
602  }
603  }
604 
605  try
606  {
607  //Inversion center
608  if(this->GetCCTbxSpg().f_inv() == 2)
609  {
610  mHasInversionCenter=true ;
611  if( (this->GetCCTbxSpg().inv_t()[0] !=0) ||
612  (this->GetCCTbxSpg().inv_t()[1] !=0) ||
613  (this->GetCCTbxSpg().inv_t()[2] !=0) ) mIsInversionCenterAtOrigin=false;
614  else mIsInversionCenterAtOrigin=true;
615  }
616  else
617  {
618  mHasInversionCenter=false ;
620  }
621 
622  //initialize asymmetric unit
624 
625  mUniqueAxisId=0;
626  if( (this->GetCCTbxSpg().type().number() >2)
627  &&(this->GetCCTbxSpg().type().number() <16))
628  {
629  string ch=this->GetCCTbxSpg().match_tabulated_settings().hall();
630  if(ch.find("x")!=std::string::npos) {mUniqueAxisId=0;}
631  else
632  if(ch.find("y")!=std::string::npos) {mUniqueAxisId=1;}
633  else mUniqueAxisId=2;
634  }
635 
636  mNbSym =this->GetCCTbxSpg().n_smx();
637  mNbTrans =this->GetCCTbxSpg().n_ltr();
638  mSpgNumber=this->GetCCTbxSpg().type().number();
639 
640  mExtension='\0'; //this->GetCCTbxSpg().type().extension();
641  }
642  catch(exception &ex)
643  {
644  (*fpObjCrystInformUser)("Error initializing spacegroup (Incorrect Hall symbol ?):"+spgId);
645  this->InitSpaceGroup(mId);
646  VFN_DEBUG_EXIT("SpaceGroup::InitSpaceGroup() could not interpret spacegroup:"<<spgId<<":"<<ex.what(),8)
647  return;
648  }
649 
650  mExtension=this->GetCCTbxSpg().match_tabulated_settings().extension();
651 
652  // Force using the H-M symbol
653  if(mExtension=='\0') mId=this->GetCCTbxSpg().match_tabulated_settings().hermann_mauguin();
654  else mId=this->GetCCTbxSpg().match_tabulated_settings().hermann_mauguin()+":"+mExtension;
655 
656  // Store rotation matrices & translation vectors
657  mvTrans.resize(mNbTrans);
658  for(unsigned int i=0;i<mNbTrans;i++)
659  {
660  for(unsigned int j=0;j<3;j++)
661  mvTrans[i].tr[j] = this->GetCCTbxSpg().ltr(i)[j]/(REAL)(this->GetCCTbxSpg().ltr(i).den());
662  }
663  mvSym.resize(mNbSym);
664  for(unsigned int j=0;j<mNbSym;j++)
665  {
666  const cctbx::sgtbx::rt_mx *pMatrix=&(this->GetCCTbxSpg().smx(j));
667  const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r());
668  const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t());
669  const REAL r_den=1/(REAL)(pMatrix->r().den());
670  const REAL t_den=1/(REAL)(pMatrix->t().den());
671  for(unsigned int i=0;i<9;++i) mvSym[j].mx[i]=(*pRot)[i]*r_den;
672  for(unsigned int i=0;i<3;++i) mvSym[j].tr[i]=(*pTrans)[i]*t_den;
673  }
674  #ifdef __DEBUG__
675  this->Print();
676  #endif
677  mClock.Click();
678  string extension("");
679  if(mExtension=='1') extension=" (Using origin choice #1)";
680  if(mExtension=='2') extension=" (Using origin choice #2)";
681  if(mExtension=='R') extension=" (Using Rhombohedral cell)";
682  if(mExtension=='H') extension=" (Using Hexagonal cell)";
683  #ifdef __DEBUG__
684  (*fpObjCrystInformUser)("Initialized spacegroup, HM: "+spgId+extension+" , Hall:"+this->GetCCTbxSpg().type().hall_symbol());
685  #endif
686  VFN_DEBUG_EXIT("SpaceGroup::InitSpaceGroup():"<<spgId,8)
687 }
688 
689 }//namespace
std::vector< TRx > mvTrans
Store floating-point translation vectors for faster use.
Definition: SpaceGroup.h:342
This class only serves to temporarilly set the LC_NUMERIC C locale to "C", in order to use '...
Definition: General.h:189
unsigned int AreReflEquiv(const REAL h1, const REAL k1, const REAL l1, const REAL h2, const REAL k2, const REAL l2) const
Are these reflections equivalent ?
Definition: SpaceGroup.cpp:481
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
const cctbx::sgtbx::space_group & GetCCTbxSpg() const
Get the underlying cctbx Spacegroup object.
Definition: SpaceGroup.cpp:465
const RefinableObjClock & GetClockSpaceGroup() const
Get the SpaceGroup Clock (corresponding to the time of the initialization of the SpaceGroup) ...
Definition: SpaceGroup.cpp:467
char mExtension
Extension to space group symbol (1,2:origin choice ; R,H=rhomboedral/hexagonal)
Definition: SpaceGroup.h:338
std::vector< SMx > mvSym
Store floating-point matrices for faster use.
Definition: SpaceGroup.h:340
SpaceGroup()
Default Constructor (initializes in P1)
Definition: SpaceGroup.cpp:212
We need to record exactly when refinable objects have been modified for the last time (to avoid re-co...
Definition: RefinableObj.h:138
CrystVector_REAL GetInversionCenter() const
Get the inversion center.
Definition: SpaceGroup.cpp:473
unsigned long mNbTrans
Number of lattice translations, including (0,0,0).
Definition: SpaceGroup.h:334
bool mIsInversionCenterAtOrigin
Is center of symmetry at the origin ?
Definition: SpaceGroup.h:322
bool IsCentrosymmetric() const
Is the crystal centrosymmetric ?
Definition: SpaceGroup.cpp:254
void Click()
Record an event for this clock (generally, the 'time' an object has been modified, or some computation has been made)
bool HasInversionCenter() const
Is centrosymmetric ?
Definition: SpaceGroup.cpp:463
unsigned int GetUniqueAxis() const
Which is the unique axis (for monoclinic space groups )
Definition: SpaceGroup.cpp:469
const string & GetName() const
Get the name of this spacegroup (its name, as supplied initially by the calling program or user) ...
Definition: SpaceGroup.cpp:233
unsigned long mNbSym
Number of symmetry operations (excluding center, and translations).
Definition: SpaceGroup.h:332
void SetSpaceGroup(const SpaceGroup &spg)
Assign a SpaceGroup and generate the corrsponding Xmax, Ymax, ZMax.
Definition: SpaceGroup.cpp:87
void GetSymmetric(unsigned int i, REAL &x, REAL &y, REAL &z, const bool noCenter=false, const bool noTransl=false, const bool derivative=false) const
Get all equivalent positions of a (xyz) position.
Definition: SpaceGroup.cpp:366
int GetNbTranslationVectors() const
Number of translation vectors (1 for 'P' cells, 2 for 'I', 4 for 'F',etc..)
Definition: SpaceGroup.cpp:259
bool IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z) const
Test if a given scatterer at (x,y,z) is in the asymmetric unit.
Definition: SpaceGroup.cpp:235
const AsymmetricUnit & GetAsymUnit() const
Get the AsymmetricUnit for this spacegroup.
Definition: SpaceGroup.cpp:245
The crystallographic space group, and the cell choice.
Definition: SpaceGroup.h:104
unsigned long mSpgNumber
SpaceGroup Number.
Definition: SpaceGroup.h:336
unsigned int mUniqueAxisId
Unique axis number (0=a,1=b,2=c)
Definition: SpaceGroup.h:330
bool IsReflCentric(const REAL h, const REAL k, const REAL l) const
Is the reflection centric ?
Definition: SpaceGroup.cpp:553
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
const std::vector< SpaceGroup::SMx > & GetSymmetryOperations() const
Get all symmetry operations stored in vector of struct SMx.
Definition: SpaceGroup.cpp:269
cctbx::sgtbx::space_group * mpCCTbxSpaceGroup
SgOps structure for this spacegroup.
Definition: SpaceGroup.h:313
~SpaceGroup()
Destructor.
Definition: SpaceGroup.cpp:222
CrystMatrix_REAL GetAllEquivRefl(const REAL h, const REAL k, const REAL l, const bool excludeFriedelMate=false, const bool forceFriedelLaw=false, const REAL sf_re=0, const REAL sf_im=0) const
Get the list of all equivalent reflections.
Definition: SpaceGroup.cpp:514
bool IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z) const
Test if (x,y,z) is in the asymmetric unit.
Definition: SpaceGroup.cpp:193
The basic description of spacegroup asymmetric unit.
Definition: SpaceGroup.h:54
bool IsInversionCenterAtOrigin() const
Is the center of symmetry at the origin ?
Definition: SpaceGroup.cpp:464
unsigned int GetExpectedIntensityFactor(const REAL h, const REAL k, const REAL l) const
Get the "expected intensity factor" for a given reflection.
Definition: SpaceGroup.cpp:562
bool IsReflSystematicAbsent(const REAL h, const REAL k, const REAL l) const
Is the reflection systematically absent ?
Definition: SpaceGroup.cpp:544
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: Atom.cpp:47
AsymmetricUnit()
Default Constructor.
Definition: SpaceGroup.cpp:65
RefinableObjClock mClock
The Spacegroup clock.
Definition: SpaceGroup.h:328
void ChangeSpaceGroup(const string &spgId)
Change the Spacegroup.
Definition: SpaceGroup.cpp:227
bool mHasInversionCenter
Is spacegroup centrosymmetric ?
Definition: SpaceGroup.h:318
int GetSpaceGroupNumber() const
Id number of the spacegroup.
Definition: SpaceGroup.cpp:249
void Print() const
Prints a description of the spacegroup (symbol, properties).
Definition: SpaceGroup.cpp:434
void ChangeToAsymmetricUnit(REAL x, REAL y, REAL z) const
Move (x,y,z) coordinates to their equivalent in the asym unit.
Definition: SpaceGroup.cpp:240
AsymmetricUnit mAsymmetricUnit
The spacegroup asymmetric unit.
Definition: SpaceGroup.h:325
void InitSpaceGroup(const string &spgId)
Init the spaceGroup object from its name.
Definition: SpaceGroup.cpp:573
string mId
Spacegroup's name ( 'I422', 'D2^8','230') Maybe we should only store the Hermann-Mauguin symbol...
Definition: SpaceGroup.h:305
char GetExtension() const
Extension to space group symbol ('1','2':origin choice ; 'R','H'=rhomboedral/hexagonal) ...
Definition: SpaceGroup.cpp:471
const std::vector< SpaceGroup::TRx > & GetTranslationVectors() const
Return all Translation Vectors, as a 3 columns-array.
Definition: SpaceGroup.cpp:264