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"
41 #define POSSIBLY_UNUSED(expr) (void)(expr)
46 #include "ObjCryst/Quirks/VFNDebug.h"
49 tmp_C_Numeric_locale::tmp_C_Numeric_locale()
52 old=setlocale(LC_NUMERIC,NULL);
54 setlocale(LC_NUMERIC,
"C");
57 tmp_C_Numeric_locale::~tmp_C_Numeric_locale()
59 setlocale(LC_NUMERIC,mLocale.c_str());
69 VFN_DEBUG_MESSAGE(
"AsymmetricUnit::AsymmetricUnit()",5)
80 VFN_DEBUG_MESSAGE(
"AsymmetricUnit::AsymmetricUnit(SpGroup)",5)
84 AsymmetricUnit::~AsymmetricUnit()
86 VFN_DEBUG_MESSAGE(
"AsymmetricUnit::~AsymmetricUnit(SpGroup)",5)
91 VFN_DEBUG_MESSAGE(
"AsymmetricUnit::SetSpaceGroup(SpGroup)",5)
94 TAU_PROFILE(
"(AsymmetricUnit::SetSpaceGroup)",
"void (SpaceGroup)",TAU_DEFAULT);
104 const long nbPoints=13;
105 CrystMatrix_REAL testPoints(nbPoints*nbPoints*nbPoints,3);
108 for(
long i=0;i<nbPoints;i++)
109 for(
long j=0;j<nbPoints;j++)
110 for(
long k=0;k<nbPoints;k++)
112 testPoints(l ,0)=i/(REAL)nbPoints;
113 testPoints(l ,1)=j/(REAL)nbPoints;
114 testPoints(l++,2)=k/(REAL)nbPoints;
119 CrystVector_REAL vert(8);
120 vert(0)=1/8.; vert(1)=1/6.; vert(2)=1/4.; vert(3)=1/3.;
121 vert(4)=1/2.; vert(5)=2/3.; vert(6)=3/4.; vert(7)=1.;
123 const int NbStep=vert.numElements();
125 CrystMatrix_REAL coords;
131 bool allPtsInAsym,tmp;
132 for(
long nx=0;nx<NbStep;nx++)
133 for(
long ny=0;ny<NbStep;ny++)
134 for(
long nz=0;nz<NbStep;nz++)
136 if(minVolume<(vert(nx)*vert(ny)*vert(nz)-.0001))
break;
138 for(
int i=0;i<testPoints.rows();i++)
140 coords=spg.
GetAllSymmetrics(testPoints(i,0),testPoints(i,1),testPoints(i,2));
141 for(
long j=0;j<coords.numElements();j++) coords(j)=modf(coords(j)+10.,&junk) ;
143 for(
long j=0;j<coords.rows();j++)
145 if( (coords(j,0) < vert(nx))
146 &&(coords(j,1) < vert(ny))
147 &&(coords(j,2) < vert(nz)))
164 if( (
true==allPtsInAsym))
169 VFN_DEBUG_MESSAGE(
"->ACCEPTED:" << mXmax <<
" "<< mYmax <<
" "<< mZmax <<endl,2)
171 minVolume=vert(nx)*vert(ny)*vert(nz);
175 cout<<
"->Finished Generating (pseudo) Asymmetric Unit, with:"<<endl
176 <<
" 0 <= x <= "<< mXmax<<endl
177 <<
" 0 <= y <= "<< mYmax<<endl
178 <<
" 0 <= z <= "<< mZmax<<endl<<endl;
180 const cctbx::sgtbx::brick b(spg.
GetCCTbxSpg().type());
182 cout<<
"->>Parallelepipedic Asymmetric Unit, from cctbx::sgtbx::brick:"<<endl
183 <<b.as_string()<<endl;
185 mXmin=boost::rational_cast<REAL,int>(b(0,0).value());
186 mYmin=boost::rational_cast<REAL,int>(b(1,0).value());
187 mZmin=boost::rational_cast<REAL,int>(b(2,0).value());
188 mXmax=boost::rational_cast<REAL,int>(b(0,1).value());
189 mYmax=boost::rational_cast<REAL,int>(b(1,1).value());
190 mZmax=boost::rational_cast<REAL,int>(b(2,1).value());
197 return ( ( x <= mXmin) && ( x >= mXmax)
198 &&( y <= mYmin) && ( y >= mYmax)
199 &&( z <= mZmin) && ( z >= mZmax));
201 REAL AsymmetricUnit::Xmin()
const {
return mXmin;}
202 REAL AsymmetricUnit::Xmax()
const {
return mXmax;}
203 REAL AsymmetricUnit::Ymin()
const {
return mYmin;}
204 REAL AsymmetricUnit::Ymax()
const {
return mYmax;}
205 REAL AsymmetricUnit::Zmin()
const {
return mZmin;}
206 REAL AsymmetricUnit::Zmax()
const {
return mZmax;}
231 VFN_DEBUG_MESSAGE(
"SpaceGroup::ChangeSpaceGroup():"<<spgId,5)
277 const bool noCenter,
const bool noTransl,
278 const bool noIdentical)
const
281 VFN_DEBUG_MESSAGE(
"SpaceGroup::GetAllSymmetrics()",0)
282 int nbMatrix, nbTrans,coeffInvert,i,j,k;
287 if(noCenter==
true) coeffInvert=1;
288 if(noTransl==
true) nbTrans=1;
289 CrystMatrix_REAL coords(nbMatrix*nbTrans*coeffInvert,3);
292 for(i=0;i<nbTrans;i++)
294 const REAL ltr_den=1/(REAL)(this->
GetCCTbxSpg().ltr(i).den());
295 const REAL tx=this->
GetCCTbxSpg().ltr(i)[0]*ltr_den;
296 const REAL ty=this->
GetCCTbxSpg().ltr(i)[1]*ltr_den;
297 const REAL tz=this->
GetCCTbxSpg().ltr(i)[2]*ltr_den;
300 for(j=0;j<nbMatrix;j++)
302 const cctbx::sgtbx::rt_mx *pMatrix=&(this->
GetCCTbxSpg().smx(j));
303 const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r());
304 const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t());
305 const REAL r_den=1/(REAL)(pMatrix->r().den());
306 const REAL t_den=1/(REAL)(pMatrix->t().den());
307 coords(k,0)= ((*pRot)[0]*x+(*pRot)[1]*y+(*pRot)[2]*z)*r_den+(*pTrans)[0]*t_den+tx;
308 coords(k,1)= ((*pRot)[3]*x+(*pRot)[4]*y+(*pRot)[5]*z)*r_den+(*pTrans)[1]*t_den+ty;
309 coords(k,2)= ((*pRot)[6]*x+(*pRot)[7]*y+(*pRot)[8]*z)*r_den+(*pTrans)[2]*t_den+tz;
315 int shift=nbMatrix*nbTrans;
321 coords(i+shift,0)=dx-coords(i,0);
322 coords(i+shift,1)=dy-coords(i,1);
323 coords(i+shift,2)=dz-coords(i,2);
330 if(
true==noIdentical)
332 VFN_DEBUG_MESSAGE(
"SpaceGroup::GetAllSymmetrics():Removing identical atoms",5)
334 REAL *p=coords.data();
336 for(
long i=0;i<coords.numElements();i++)
342 CrystMatrix_REAL newCoords;
346 for(
long i=0;i<coords.rows();i++)
349 for(
long j=0;j<i;j++)
351 if( ( fabs(coords(i,0)-coords(j,0)) < eps )
352 &&( fabs(coords(i,1)-coords(j,1)) < eps )
353 &&( fabs(coords(i,2)-coords(j,2)) < eps )) keep=
false;
357 newCoords(nbKeep ,0) = coords(i,0);
358 newCoords(nbKeep ,1) = coords(i,1);
359 newCoords(nbKeep++,2) = coords(i,2);
362 newCoords.resizeAndPreserve(nbKeep,3);
365 VFN_DEBUG_MESSAGE(
"SpaceGroup::GetAllSymmetrics():End",0)
369 const bool noCenter,
const bool noTransl,
370 const bool derivative)
const
377 if(noCenter==
true) coeffInvert=1;
378 if(noTransl==
true) nbTrans=1;
380 const int i=idx/nbMatrix;
381 const int j=idx%nbMatrix;
383 const REAL ltr_den=1/(REAL)(this->
GetCCTbxSpg().ltr(i).den());
384 const REAL tx=this->
GetCCTbxSpg().ltr(i)[0]*ltr_den;
385 const REAL ty=this->
GetCCTbxSpg().ltr(i)[1]*ltr_den;
386 const REAL tz=this->
GetCCTbxSpg().ltr(i)[2]*ltr_den;
387 const cctbx::sgtbx::rt_mx *pMatrix=&(this->
GetCCTbxSpg().smx(j));
388 const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r());
389 const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t());
390 const REAL r_den=1/(REAL)(pMatrix->r().den());
391 const REAL t_den=1/(REAL)(pMatrix->t().den());
392 const REAL x1= ((*pRot)[0]*x+(*pRot)[1]*y+(*pRot)[2]*z)*r_den;
393 const REAL y1= ((*pRot)[3]*x+(*pRot)[4]*y+(*pRot)[5]*z)*r_den;
394 const REAL z1= ((*pRot)[6]*x+(*pRot)[7]*y+(*pRot)[8]*z)*r_den;
395 if(derivative==
false)
397 x=x1+(*pTrans)[0]*t_den+tx;
398 y=y1+(*pTrans)[1]*t_den+ty;
399 z=z1+(*pTrans)[2]*t_den+tz;
422 if(noTransl)
return mNbSym;
427 if(noTransl)
return 2*
mNbSym;
435 cout <<
"SpaceGroup:" <<endl;
436 cout <<
" Schoenflies symbol = " << this->
GetCCTbxSpg().match_tabulated_settings().schoenflies() << endl ;
437 cout <<
" Hermann-Maugin symbol = " << this->
GetCCTbxSpg().match_tabulated_settings().hermann_mauguin() << endl ;
438 cout <<
" Hall symbol = " << this->
GetCCTbxSpg().match_tabulated_settings().hall() << endl ;
439 cout <<
" SgNumber = " << this->
GetCCTbxSpg().match_tabulated_settings().number() << endl ;
440 cout <<
" Number of Seitz Matrix = " << this->
GetCCTbxSpg().n_smx() << endl ;
441 cout <<
" Number of Translation Vectors = " << this->
GetCCTbxSpg().n_ltr() << endl ;
442 cout <<
" List of Seitz Matrices : " << endl ;
443 for(
unsigned int i=0;i<this->
GetCCTbxSpg().n_smx();i++)
444 cout <<
" " << this->
GetCCTbxSpg().smx(i).as_xyz() <<endl;
447 cout <<
" There is an inversion center at "
454 cout <<
" List of Translation vectors :"<<endl;
455 for(
unsigned int i=0;i<this->
GetCCTbxSpg().n_ltr();i++)
460 cout<<
"Extension (origin choice, rhomboedral/hexagonal):"<<
mExtension<<endl;
473 CrystVector_REAL center(3);
484 const REAL h2,
const REAL k2,
const REAL l2)
const
486 const int ih1=scitbx::math::iround(h1);
487 const int ik1=scitbx::math::iround(k1);
488 const int il1=scitbx::math::iround(l1);
489 cctbx::miller::index<long> h0(scitbx::vec3<long>(ih1,ik1,il1));
490 const int ih2=scitbx::math::iround(h2);
491 const int ik2=scitbx::math::iround(k2);
492 const int il2=scitbx::math::iround(l2);
493 cctbx::miller::index<long> k0(scitbx::vec3<long>(ih2,ik2,il2));
494 cctbx::miller::sym_equiv_indices sei(this->
GetCCTbxSpg(),k0);
497 for(
size_t i_indices=0;i_indices<sei.indices().size();i_indices++)
499 const size_t sfm = sei.f_mates(
false);
500 for(
size_t i_mate = 0; i_mate < sfm; i_mate++)
502 cctbx::miller::index<long> k = sei(i_mate, i_indices).h();
506 if(i_mate==0) equiv=1;
512 VFN_DEBUG_MESSAGE(
"SpaceGroup::AreReflEquiv("<<ih1<<
","<<ik1<<
","<<il1<<
"),("<<ih2<<
","<<ik2<<
","<<il2<<
"):"<<equiv,2)
517 const bool excludeFriedelMate,
518 const bool forceFriedelLaw,
519 const REAL sf_re,
const REAL sf_im)
const
521 VFN_DEBUG_ENTRY(
"SpaceGroup::GetAllEquivRefl():",5)
522 const int ih0=scitbx::math::iround(h0);
523 const int ik0=scitbx::math::iround(k0);
524 const int il0=scitbx::math::iround(l0);
525 cctbx::miller::index<long> h(scitbx::vec3<long>(ih0,ik0,il0));
526 cctbx::miller::sym_equiv_indices sei(this->
GetCCTbxSpg(),h);
528 if(forceFriedelLaw) nbEquiv=sei.multiplicity(
false);
529 else nbEquiv=sei.multiplicity(
true);
530 if( ((this->
IsCentrosymmetric())||forceFriedelLaw) && excludeFriedelMate) nbEquiv/=2;
531 CrystMatrix_REAL equivReflList(nbEquiv,5);
532 complex<double> sf0((
double)(sf_re),(
double)(sf_im));
533 for(
int i=0;i<nbEquiv;i+=1)
535 cctbx::miller::index<long> k = sei(i).h();
536 equivReflList(i,0)=(REAL)k[0];
537 equivReflList(i,1)=(REAL)k[1];
538 equivReflList(i,2)=(REAL)k[2];
539 equivReflList(i,3)=(REAL)sei(i).complex_eq(sf0).real();
540 equivReflList(i,4)=(REAL)sei(i).complex_eq(sf0).imag();
542 VFN_DEBUG_EXIT(
"SpaceGroup::GetAllEquivRefl():",5)
543 return equivReflList;
548 const int ih0=scitbx::math::iround(h0);
549 const int ik0=scitbx::math::iround(k0);
550 const int il0=scitbx::math::iround(l0);
551 cctbx::miller::index<long> h(scitbx::vec3<long>(ih0,ik0,il0));
557 const int ih0=scitbx::math::iround(h0);
558 const int ik0=scitbx::math::iround(k0);
559 const int il0=scitbx::math::iround(l0);
560 cctbx::miller::index<long> h(scitbx::vec3<long>(ih0,ik0,il0));
568 const int ih0=scitbx::math::iround(h0);
569 const int ik0=scitbx::math::iround(k0);
570 const int il0=scitbx::math::iround(l0);
571 cctbx::miller::index<long> h(scitbx::vec3<long>(ih0,ik0,il0));
578 VFN_DEBUG_ENTRY(
"SpaceGroup::InitSpaceGroup():"<<spgId,8)
580 (*fpObjCrystInformUser)(
"Initializing spacegroup: "+spgId);
585 cctbx::sgtbx::space_group_symbols sgs=cctbx::sgtbx::space_group_symbols(spgId);
586 cctbx::sgtbx::space_group *nsg =
new cctbx::sgtbx::space_group(sgs);
595 (*fpObjCrystInformUser)(
"Lookup of '" + spgId +
"' symbol failed, trying as Hall symbol.");
597 cctbx::sgtbx::space_group *nsg =
new cctbx::sgtbx::space_group(spgId);
604 (*fpObjCrystInformUser)(
"Could not interpret Spacegroup Symbol:"+spgId);
605 string emsg =
"Space group symbol '" + spgId +
"' not recognized";
606 throw invalid_argument(emsg);
634 string ch=this->
GetCCTbxSpg().match_tabulated_settings().hall();
649 (*fpObjCrystInformUser)(
"Error initializing spacegroup (Incorrect Hall symbol ?):"+spgId);
652 (*fpObjCrystInformUser)(
"Reverting to spacegroup symbol:"+
mId);
655 VFN_DEBUG_EXIT(
"SpaceGroup::InitSpaceGroup() could not interpret spacegroup:"<<spgId<<
":"<<ex.what(),8)
656 string emsg =
"Space group symbol '" + spgId +
"' not recognized";
657 throw invalid_argument(emsg);
668 for(
unsigned int i=0;i<
mNbTrans;i++)
670 for(
unsigned int j=0;j<3;j++)
674 for(
unsigned int j=0;j<
mNbSym;j++)
676 const cctbx::sgtbx::rt_mx *pMatrix=&(this->
GetCCTbxSpg().smx(j));
677 const cctbx::sgtbx::rot_mx *pRot=&(pMatrix->r());
678 const cctbx::sgtbx::tr_vec *pTrans=&(pMatrix->t());
679 const REAL r_den=1/(REAL)(pMatrix->r().den());
680 const REAL t_den=1/(REAL)(pMatrix->t().den());
681 for(
unsigned int i=0;i<9;++i)
mvSym[j].mx[i]=(*pRot)[i]*r_den;
682 for(
unsigned int i=0;i<3;++i)
mvSym[j].tr[i]=(*pTrans)[i]*t_den;
688 string extension(
"");
689 if(
mExtension==
'1') extension=
" (Using origin choice #1)";
690 if(
mExtension==
'2') extension=
" (Using origin choice #2)";
691 if(
mExtension==
'R') extension=
" (Using Rhombohedral cell)";
692 if(
mExtension==
'H') extension=
" (Using Hexagonal cell)";
694 (*fpObjCrystInformUser)(
"Initialized spacegroup, HM: "+spgId+extension+
" , Hall:"+this->
GetCCTbxSpg().type().hall_symbol());
696 VFN_DEBUG_EXIT(
"SpaceGroup::InitSpaceGroup():"<<spgId,8)
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
This class only serves to temporarilly set the LC_NUMERIC C locale to "C", in order to use '.
The basic description of spacegroup asymmetric unit.
void SetSpaceGroup(const SpaceGroup &spg)
Assign a SpaceGroup and generate the corrsponding Xmax, Ymax, ZMax.
AsymmetricUnit()
Default Constructor.
bool IsInAsymmetricUnit(const REAL x, const REAL y, const REAL z) const
Test if (x,y,z) is in the asymmetric unit.
The crystallographic space group, and the cell choice.
void ChangeToAsymmetricUnit(REAL x, REAL y, REAL z) const
Move (x,y,z) coordinates to their equivalent in the asym unit.
char GetExtension() const
Extension to space group symbol ('1','2':origin choice ; 'R','H'=rhomboedral/hexagonal)
bool mHasInversionCenter
Is spacegroup centrosymmetric ?
bool IsReflCentric(const REAL h, const REAL k, const REAL l) const
Is the reflection centric ?
unsigned long mSpgNumber
SpaceGroup Number.
std::vector< SMx > mvSym
Store floating-point matrices for faster use.
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...
void Print() const
Prints a description of the spacegroup (symbol, properties).
const string & GetName() const
Get the name of this spacegroup (its name, as supplied initially by the calling program or user)
void InitSpaceGroup(const string &spgId)
Init the spaceGroup object from its name.
bool IsInversionCenterAtOrigin() const
Is the center of symmetry at the origin ?
string mId
Spacegroup's name ( 'I422', 'D2^8','230') Maybe we should only store the Hermann-Mauguin symbol,...
SpaceGroup()
Default Constructor (initializes in P1)
unsigned int GetUniqueAxis() const
Which is the unique axis (for monoclinic space groups )
unsigned int GetExpectedIntensityFactor(const REAL h, const REAL k, const REAL l) const
Get the "expected intensity factor" for a given reflection.
unsigned long mNbTrans
Number of lattice translations, including (0,0,0).
bool mIsInversionCenterAtOrigin
Is center of symmetry at the origin ?
bool IsReflSystematicAbsent(const REAL h, const REAL k, const REAL l) const
Is the reflection systematically absent ?
cctbx::sgtbx::space_group * mpCCTbxSpaceGroup
SgOps structure for this spacegroup.
int GetSpaceGroupNumber() const
Id number of the spacegroup.
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 ?
CrystVector_REAL GetInversionCenter() const
Get the inversion center.
int GetNbTranslationVectors() const
Number of translation vectors (1 for 'P' cells, 2 for 'I', 4 for 'F',etc..)
bool IsCentrosymmetric() const
Is the crystal centrosymmetric ?
bool HasInversionCenter() const
Is centrosymmetric ?
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.
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.
std::vector< TRx > mvTrans
Store floating-point translation vectors for faster use.
const RefinableObjClock & GetClockSpaceGroup() const
Get the SpaceGroup Clock (corresponding to the time of the initialization of the SpaceGroup)
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.
RefinableObjClock mClock
The Spacegroup clock.
unsigned int mUniqueAxisId
Unique axis number (0=a,1=b,2=c)
const AsymmetricUnit & GetAsymUnit() const
Get the AsymmetricUnit for this spacegroup.
const std::vector< SpaceGroup::SMx > & GetSymmetryOperations() const
Get all symmetry operations stored in vector of struct SMx.
unsigned long mNbSym
Number of symmetry operations (excluding center, and translations).
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.
const std::vector< SpaceGroup::TRx > & GetTranslationVectors() const
Return all Translation Vectors, as a 3 columns-array.
void ChangeSpaceGroup(const string &spgId)
Change the Spacegroup.
const cctbx::sgtbx::space_group & GetCCTbxSpg() const
Get the underlying cctbx Spacegroup object.
AsymmetricUnit mAsymmetricUnit
The spacegroup asymmetric unit.
char mExtension
Extension to space group symbol (1,2:origin choice ; R,H=rhomboedral/hexagonal)
We need to record exactly when refinable objects have been modified for the last time (to avoid re-co...
void Click()
Record an event for this clock (generally, the 'time' an object has been modified,...