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"
33 #include "ObjCryst/ObjCryst/SpaceGroup.h"
34 #include "ObjCryst/Quirks/VFNStreamFormat.h"
35 #include "ObjCryst/ObjCryst/GeomStructFactor.h"
36 #include "ObjCryst/Quirks/VFNDebug.h"
44 #include "ObjCryst/Quirks/VFNDebug.h"
47 tmp_C_Numeric_locale::tmp_C_Numeric_locale()
50 old=setlocale(LC_NUMERIC,NULL);
52 setlocale(LC_NUMERIC,
"C");
55 tmp_C_Numeric_locale::~tmp_C_Numeric_locale()
57 setlocale(LC_NUMERIC,mLocale.c_str());
67 VFN_DEBUG_MESSAGE(
"AsymmetricUnit::AsymmetricUnit()",5)
78 VFN_DEBUG_MESSAGE(
"AsymmetricUnit::AsymmetricUnit(SpGroup)",5)
82 AsymmetricUnit::~AsymmetricUnit()
84 VFN_DEBUG_MESSAGE(
"AsymmetricUnit::~AsymmetricUnit(SpGroup)",5)
89 VFN_DEBUG_MESSAGE(
"AsymmetricUnit::SetSpaceGroup(SpGroup)",5)
92 TAU_PROFILE(
"(AsymmetricUnit::SetSpaceGroup)",
"void (SpaceGroup)",TAU_DEFAULT);
102 const long nbPoints=13;
103 CrystMatrix_REAL testPoints(nbPoints*nbPoints*nbPoints,3);
106 for(
long i=0;i<nbPoints;i++)
107 for(
long j=0;j<nbPoints;j++)
108 for(
long k=0;k<nbPoints;k++)
110 testPoints(l ,0)=i/(REAL)nbPoints;
111 testPoints(l ,1)=j/(REAL)nbPoints;
112 testPoints(l++,2)=k/(REAL)nbPoints;
117 CrystVector_REAL vert(8);
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.;
121 const int NbStep=vert.numElements();
123 CrystMatrix_REAL coords;
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++)
134 if(minVolume<(vert(nx)*vert(ny)*vert(nz)-.0001))
break;
136 for(
int i=0;i<testPoints.rows();i++)
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) ;
141 for(
long j=0;j<coords.rows();j++)
143 if( (coords(j,0) < vert(nx))
144 &&(coords(j,1) < vert(ny))
145 &&(coords(j,2) < vert(nz)))
162 if( (
true==allPtsInAsym))
167 VFN_DEBUG_MESSAGE(
"->ACCEPTED:" << mXmax <<
" "<< mYmax <<
" "<< mZmax <<endl,2)
169 minVolume=vert(nx)*vert(ny)*vert(nz);
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;
178 const cctbx::sgtbx::brick b(spg.
GetCCTbxSpg().type());
180 cout<<
"->>Parallelepipedic Asymmetric Unit, from cctbx::sgtbx::brick:"<<endl
181 <<b.as_string()<<endl;
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());
195 return ( ( x <= mXmin) && ( x >= mXmax)
196 &&( y <= mYmin) && ( y >= mYmax)
197 &&( z <= mZmin) && ( z >= mZmax));
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;}
229 VFN_DEBUG_MESSAGE(
"SpaceGroup::ChangeSpaceGroup():"<<spgId,5)
275 const bool noCenter,
const bool noTransl,
276 const bool noIdentical)
const
279 VFN_DEBUG_MESSAGE(
"SpaceGroup::GetAllSymmetrics()",0)
280 int nbMatrix, nbTrans,coeffInvert,i,j,k;
285 if(noCenter==
true) coeffInvert=1;
286 if(noTransl==
true) nbTrans=1;
287 CrystMatrix_REAL coords(nbMatrix*nbTrans*coeffInvert,3);
290 for(i=0;i<nbTrans;i++)
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;
298 for(j=0;j<nbMatrix;j++)
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;
313 int shift=nbMatrix*nbTrans;
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);
328 if(
true==noIdentical)
330 VFN_DEBUG_MESSAGE(
"SpaceGroup::GetAllSymmetrics():Removing identical atoms",5)
332 REAL *p=coords.data();
334 for(
long i=0;i<coords.numElements();i++)
340 CrystMatrix_REAL newCoords;
344 for(
long i=0;i<coords.rows();i++)
347 for(
long j=0;j<i;j++)
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;
355 newCoords(nbKeep ,0) = coords(i,0);
356 newCoords(nbKeep ,1) = coords(i,1);
357 newCoords(nbKeep++,2) = coords(i,2);
360 newCoords.resizeAndPreserve(nbKeep,3);
363 VFN_DEBUG_MESSAGE(
"SpaceGroup::GetAllSymmetrics():End",0)
367 const bool noCenter,
const bool noTransl,
368 const bool derivative)
const
375 if(noCenter==
true) coeffInvert=1;
376 if(noTransl==
true) nbTrans=1;
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;
382 const int j=idx%nbMatrix;
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)
398 x=x1+(*pTrans)[0]*t_den+tx;
399 y=y1+(*pTrans)[1]*t_den+ty;
400 z=z1+(*pTrans)[2]*t_den+tz;
423 if(noTransl)
return mNbSym;
428 if(noTransl)
return 2*
mNbSym;
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;
448 cout <<
" There is an inversion center at "
455 cout <<
" List of Translation vectors :"<<endl;
456 for(
unsigned int i=0;i<this->
GetCCTbxSpg().n_ltr();i++)
461 cout<<
"Extension (origin choice, rhomboedral/hexagonal):"<<
mExtension<<endl;
474 CrystVector_REAL center(3);
482 const REAL h2,
const REAL k2,
const REAL l2)
const
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);
495 for(
size_t i_indices=0;i_indices<sei.indices().size();i_indices++)
497 const size_t sfm = sei.f_mates(
false);
498 for(
size_t i_mate = 0; i_mate < sfm; i_mate++)
500 cctbx::miller::index<long> k = sei(i_mate, i_indices).h();
504 if(i_mate==0) equiv=1;
510 VFN_DEBUG_MESSAGE(
"SpaceGroup::AreReflEquiv("<<ih1<<
","<<ik1<<
","<<il1<<
"),("<<ih2<<
","<<ik2<<
","<<il2<<
"):"<<equiv,2)
515 const bool excludeFriedelMate,
516 const bool forceFriedelLaw,
517 const REAL sf_re,
const REAL sf_im)
const
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);
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)
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();
540 VFN_DEBUG_EXIT(
"SpaceGroup::GetAllEquivRefl():",5)
541 return equivReflList;
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));
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));
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));
576 VFN_DEBUG_ENTRY(
"SpaceGroup::InitSpaceGroup():"<<spgId,8)
578 (*fpObjCrystInformUser)(
"Initializing spacegroup: "+spgId);
582 cctbx::sgtbx::space_group_symbols sgs=cctbx::sgtbx::space_group_symbols(spgId);
587 catch(exception &ex1)
591 (*fpObjCrystInformUser)(
"Failed lookup symbol ! try Hall symbol ?");
596 catch(exception &ex2)
598 (*fpObjCrystInformUser)(
"Could not interpret Spacegroup Symbol:"+spgId);
600 VFN_DEBUG_EXIT(
"SpaceGroup::InitSpaceGroup() could not interpret spacegroup:"<<spgId<<
":"<<ex1.what()<<
":"<<ex2.what(),8)
629 string ch=this->
GetCCTbxSpg().match_tabulated_settings().hall();
644 (*fpObjCrystInformUser)(
"Error initializing spacegroup (Incorrect Hall symbol ?):"+spgId);
646 VFN_DEBUG_EXIT(
"SpaceGroup::InitSpaceGroup() could not interpret spacegroup:"<<spgId<<
":"<<ex.what(),8)
658 for(
unsigned int i=0;i<
mNbTrans;i++)
660 for(
unsigned int j=0;j<3;j++)
664 for(
unsigned int j=0;j<
mNbSym;j++)
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;
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)";
684 (*fpObjCrystInformUser)(
"Initialized spacegroup, HM: "+spgId+extension+
" , Hall:"+this->
GetCCTbxSpg().type().hall_symbol());
686 VFN_DEBUG_EXIT(
"SpaceGroup::InitSpaceGroup():"<<spgId,8)
std::vector< TRx > mvTrans
Store floating-point translation vectors for faster use.
This class only serves to temporarilly set the LC_NUMERIC C locale to "C", in order to use '...
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 ?
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...
const cctbx::sgtbx::space_group & GetCCTbxSpg() const
Get the underlying cctbx Spacegroup object.
const RefinableObjClock & GetClockSpaceGroup() const
Get the SpaceGroup Clock (corresponding to the time of the initialization of the SpaceGroup) ...
char mExtension
Extension to space group symbol (1,2:origin choice ; R,H=rhomboedral/hexagonal)
std::vector< SMx > mvSym
Store floating-point matrices for faster use.
SpaceGroup()
Default Constructor (initializes in P1)
We need to record exactly when refinable objects have been modified for the last time (to avoid re-co...
CrystVector_REAL GetInversionCenter() const
Get the inversion center.
unsigned long mNbTrans
Number of lattice translations, including (0,0,0).
bool mIsInversionCenterAtOrigin
Is center of symmetry at the origin ?
bool IsCentrosymmetric() const
Is the crystal centrosymmetric ?
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 ?
unsigned int GetUniqueAxis() const
Which is the unique axis (for monoclinic space groups )
const string & GetName() const
Get the name of this spacegroup (its name, as supplied initially by the calling program or user) ...
unsigned long mNbSym
Number of symmetry operations (excluding center, and translations).
void SetSpaceGroup(const SpaceGroup &spg)
Assign a SpaceGroup and generate the corrsponding Xmax, Ymax, ZMax.
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.
int GetNbTranslationVectors() const
Number of translation vectors (1 for 'P' cells, 2 for 'I', 4 for 'F',etc..)
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.
const AsymmetricUnit & GetAsymUnit() const
Get the AsymmetricUnit for this spacegroup.
The crystallographic space group, and the cell choice.
unsigned long mSpgNumber
SpaceGroup Number.
unsigned int mUniqueAxisId
Unique axis number (0=a,1=b,2=c)
bool IsReflCentric(const REAL h, const REAL k, const REAL l) const
Is the reflection centric ?
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.
const std::vector< SpaceGroup::SMx > & GetSymmetryOperations() const
Get all symmetry operations stored in vector of struct SMx.
cctbx::sgtbx::space_group * mpCCTbxSpaceGroup
SgOps structure for this spacegroup.
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.
bool IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z) const
Test if (x,y,z) is in the asymmetric unit.
The basic description of spacegroup asymmetric unit.
bool IsInversionCenterAtOrigin() const
Is the center of symmetry at the origin ?
unsigned int GetExpectedIntensityFactor(const REAL h, const REAL k, const REAL l) const
Get the "expected intensity factor" for a given reflection.
bool IsReflSystematicAbsent(const REAL h, const REAL k, const REAL l) const
Is the reflection systematically absent ?
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
AsymmetricUnit()
Default Constructor.
RefinableObjClock mClock
The Spacegroup clock.
void ChangeSpaceGroup(const string &spgId)
Change the Spacegroup.
bool mHasInversionCenter
Is spacegroup centrosymmetric ?
int GetSpaceGroupNumber() const
Id number of the spacegroup.
void Print() const
Prints a description of the spacegroup (symbol, properties).
void ChangeToAsymmetricUnit(REAL x, REAL y, REAL z) const
Move (x,y,z) coordinates to their equivalent in the asym unit.
AsymmetricUnit mAsymmetricUnit
The spacegroup asymmetric unit.
void InitSpaceGroup(const string &spgId)
Init the spaceGroup object from its name.
string mId
Spacegroup's name ( 'I422', 'D2^8','230') Maybe we should only store the Hermann-Mauguin symbol...
char GetExtension() const
Extension to space group symbol ('1','2':origin choice ; 'R','H'=rhomboedral/hexagonal) ...
const std::vector< SpaceGroup::TRx > & GetTranslationVectors() const
Return all Translation Vectors, as a 3 columns-array.