FOX/ObjCryst++  1.10.X (development)
ScatteringPower.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 #include <cmath>
20 #include <typeinfo>
21 #include <iomanip>
22 #include <fstream>
23 #include <cstring>
24 #include <stdio.h> //for sprintf()
25 
26 
27 #include "cctbx/eltbx/xray_scattering.h"
28 #include "cctbx/eltbx/tiny_pse.h"
29 #include "cctbx/eltbx/icsd_radii.h"
30 #include "cctbx/eltbx/covalent_radii.h"
31 #include "cctbx/eltbx/henke.h"
32 #include "cctbx/eltbx/neutron.h"
33 
34 #include "ObjCryst/ObjCryst/ScatteringPower.h"
35 #include "ObjCryst/Quirks/VFNStreamFormat.h"
36 #include "ObjCryst/Quirks/VFNDebug.h"
37 #include "ObjCryst/ObjCryst/Colours.h"
38 
39 #ifdef __WX__CRYST__
40  #include "ObjCryst/wxCryst/wxScatteringPower.h"
41 #endif
42 
43 namespace ObjCryst
44 {
45 
46 const RefParType *gpRefParTypeScattPow=0;
47 const RefParType *gpRefParTypeScattPowResonant=0;
48 const RefParType *gpRefParTypeScattPowTemperature=0;
49 const RefParType *gpRefParTypeScattPowTemperatureIso=0;
50 const RefParType *gpRefParTypeScattPowTemperatureAniso=0;
51 long NiftyStaticGlobalObjectsInitializer_ScatteringPower::mCount=0;
52 //######################################################################
53 //
54 // Bij to Betaij conversion
55 //
56 //######################################################################
57 CrystMatrix_REAL Bij2Betaij(const CrystVector_REAL &Bij, const UnitCell &cell)
58 {
59  // Willis & Pryor,p 101: (betaij) = 2*pi^2 * transpose(cell.Bmatrix) * (Bij) * cell.Bmatrix
60  // :TODO: this needs to be checked before being used
61  const REAL B11=Bij(0);
62  const REAL B22=Bij(1);
63  const REAL B33=Bij(2);
64  const REAL B12=Bij(3);
65  const REAL B13=Bij(4);
66  const REAL B23=Bij(5);
67  CrystMatrix_REAL B(3,3);
68  B(0,0)=B11;
69  B(0,1)=B12;
70  B(0,1)=B13;
71  B(1,0)=B12;
72  B(1,1)=B22;
73  B(1,1)=B23;
74  B(2,0)=B13;
75  B(2,1)=B23;
76  B(2,1)=B33;
77  CrystMatrix_REAL b(3,3);
78  b=cell.GetBMatrix().transpose().Mult(B.Mult(cell.GetBMatrix()));
79  b*=2*M_PI*M_PI;
80  return b;
81 }
82 
83 //######################################################################
84 //
85 // SCATTERING POWER
86 //
87 //######################################################################
88 ObjRegistry<ScatteringPower> gScatteringPowerRegistry("Global ScatteringPower Registry");
89 
90 ScatteringPower::ScatteringPower():mDynPopCorrIndex(0),mBiso(1.0),mIsIsotropic(true),
91 mMaximumLikelihoodNbGhost(0),mFormalCharge(0.0)
92 {
93  VFN_DEBUG_MESSAGE("ScatteringPower::ScatteringPower():"<<mName,5)
94  mBeta.resize(6);
95  mBeta = 0;
96  mB.resize(6);
97  mB = 0;
98  gScatteringPowerRegistry.Register(*this);
99  this->Init();
100  mClockMaster.AddChild(mClock);
101  mClockMaster.AddChild(mMaximumLikelihoodParClock);
102 }
103 ScatteringPower::ScatteringPower(const ScatteringPower& old):
104 mDynPopCorrIndex(old.mDynPopCorrIndex),mBiso(old.mBiso),mIsIsotropic(old.mIsIsotropic),
105 mBeta(old.mBeta),mB(old.mB),
106 mFormalCharge(old.mFormalCharge)
107 {
108  VFN_DEBUG_MESSAGE("ScatteringPower::ScatteringPower(&old):"<<mName,5)
109  gScatteringPowerRegistry.Register(*this);
110  this->Init();
111  mMaximumLikelihoodPositionError=old.mMaximumLikelihoodPositionError;
112  mMaximumLikelihoodNbGhost=old.mMaximumLikelihoodNbGhost;
113  mClockMaster.AddChild(mClock);
114  mClockMaster.AddChild(mMaximumLikelihoodParClock);
115 }
116 ScatteringPower::~ScatteringPower()
117 {
118  VFN_DEBUG_MESSAGE("ScatteringPower::~ScatteringPower():"<<mName,5)
119  gScatteringPowerRegistry.DeRegister(*this);
120 }
121 
122 const string& ScatteringPower::GetClassName()const
123 {
124  const static string className="ScatteringPower";
125  return className;
126 }
127 
128 void ScatteringPower::operator=(const ScatteringPower& rhs)
129 {
130  VFN_DEBUG_MESSAGE("ScatteringPower::operator=():"<<mName,2)
131  mDynPopCorrIndex=rhs.mDynPopCorrIndex;
132  mBiso=rhs.mBiso;
133  mIsIsotropic=rhs.mIsIsotropic;
134  mBeta=rhs.mBeta;
135  mB=rhs.mB;
136 }
137 
138 bool ScatteringPower::IsScatteringFactorAnisotropic()const{return false;}
141 
142 const string& ScatteringPower::GetSymbol() const {return this->GetName();}
143 REAL ScatteringPower::GetBiso() const {return mBiso;}
144 REAL& ScatteringPower::GetBiso() {mClock.Click();return mBiso;}
145 void ScatteringPower::SetBiso(const REAL newB) { mClock.Click();mBiso=newB;mIsIsotropic=true;}
146 REAL ScatteringPower::GetBij(const size_t &i, const size_t &j) const
147 {
148  size_t idx = 0;
149  if(i == j)
150  {
151  idx = i - 1;
152  }
153  else
154  {
155  idx = i + j;
156  }
157  return this->GetBij(idx);
158 }
159 REAL ScatteringPower::GetBij(const size_t &idx) const
160 {
161  return mB(idx);
162 }
163 void ScatteringPower::SetBij(const size_t &i, const size_t &j, const REAL newB)
164 {
165  size_t idx = 0;
166  if(i == j)
167  {
168  idx = i - 1;
169  }
170  else
171  {
172  idx = i + j;
173  }
174  this->SetBij(idx, newB);
175 }
176 void ScatteringPower::SetBij(const size_t &idx, const REAL newB)
177 {
178  mClock.Click();
179  mIsIsotropic=false;
180  mB(idx) = newB;
181 }
182 bool ScatteringPower::IsIsotropic() const {return mIsIsotropic;}
183 long ScatteringPower::GetDynPopCorrIndex() const {return mDynPopCorrIndex;}
186 
187 const string& ScatteringPower::GetColourName()const{ return mColourName;}
188 const float* ScatteringPower::GetColourRGB()const{ return mColourRGB;}
189 void ScatteringPower::SetColour(const string& colourName)
190 {
191  mColourName=colourName;
192  this->InitRGBColour();
193 }
194 void ScatteringPower::SetColour(const float r,const float g,const float b)
195 {
196  mColourRGB[0]=r;
197  mColourRGB[1]=g;
198  mColourRGB[2]=b;
199 }
201  CrystVector_uint & groupIndex,
202  unsigned int &first) const
203 {
204  // One group for all parameters
205  unsigned int index=0;
206  VFN_DEBUG_MESSAGE("ScatteringPower::GetGeneGroup()",4)
207  for(long i=0;i<obj.GetNbPar();i++)
208  for(long j=0;j<this->GetNbPar();j++)
209  if(&(obj.GetPar(i)) == &(this->GetPar(j)))
210  {
211  if(index==0) index=first++;
212  groupIndex(i)=index;
213  }
214 }
215 
217 {return mMaximumLikelihoodPositionError;}
218 
220 {return mMaximumLikelihoodParClock;}
221 
223 {
224  if(mle!=mMaximumLikelihoodPositionError)
225  {
226  mMaximumLikelihoodPositionError=mle;
227  mMaximumLikelihoodParClock.Click();
228  }
229 }
230 
232 {return mMaximumLikelihoodNbGhost;}
233 
235 {
236  if(nb!=mMaximumLikelihoodNbGhost)
237  {
238  mMaximumLikelihoodNbGhost=nb;
239  mMaximumLikelihoodParClock.Click();
240  }
241 }
242 
243 REAL ScatteringPower::GetFormalCharge()const{return mFormalCharge;}
244 void ScatteringPower::SetFormalCharge(const REAL charge)
245 {mFormalCharge=charge;}
246 
248 {
249  VFN_DEBUG_MESSAGE("ScatteringPower::Init():"<<mName,2)
250  mColourName="White";
251  mMaximumLikelihoodPositionError=0;
252  mMaximumLikelihoodNbGhost=0;
253  VFN_DEBUG_MESSAGE("ScatteringPower::Init():End",2)
254 }
256 {
257  VFN_DEBUG_MESSAGE("ScatteringPower::InitRGBColour()",2)
258  for(long i=0;;)
259  {
260  if(gPOVRayColours[i].mName==mColourName)
261  {
262  mColourRGB[0]=gPOVRayColours[i].mRGB[0];
263  mColourRGB[1]=gPOVRayColours[i].mRGB[1];
264  mColourRGB[2]=gPOVRayColours[i].mRGB[2];
265  break;
266  }
267  i++;
268  if(strncmp(gPOVRayColours[i].mName,"",3)==0)
269  {//could not find colour !
270  cout << "Could not find colour:"<<mColourName<<" for ScatteringPower "<<mName<<endl;
271  mColourRGB[0]=1;
272  mColourRGB[1]=1;
273  mColourRGB[2]=1;
274  break;
275  }
276  }
277  VFN_DEBUG_MESSAGE("->RGBColour:"<<mColourName<<mColourRGB[0]<<" "<<mColourRGB[1]<<" "<<mColourRGB[2],2)
278 }
279 
280 //######################################################################
281 //
282 // SCATTERING POWER ATOM
283 //
284 //######################################################################
286  gScatteringPowerAtomRegistry("Global ScatteringPowerAtom Registry");
287 
288 ScatteringPowerAtom::ScatteringPowerAtom():
289 ScatteringPower(),mSymbol(""),mAtomicNumber(0),mpGaussian(0)
290 {
291  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::ScatteringPowerAtom():"<<mName,5)
292  gScatteringPowerAtomRegistry.Register(*this);
293  this->InitRefParList();
294 }
295 
297  const string &symbol,
298  const REAL bIso):
299 mpGaussian(0)
300 {
301  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::ScatteringPowerAtom(n,s,B):"<<name,5)
302  gScatteringPowerAtomRegistry.Register(*this);
303  this->InitRefParList();
304  this->Init(name,symbol,bIso);
305 }
306 
307 ScatteringPowerAtom::ScatteringPowerAtom(const ScatteringPowerAtom& old):
308 mpGaussian(0)
309 {
310  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::ScatteringPowerAtom(&old):"<<old.mName,5)
311  gScatteringPowerAtomRegistry.Register(*this);
312  this->Init(old.GetName(),old.mSymbol,old.mBiso);
313  //this->InitRefParList(); //?? :TODO: Check
314 }
315 
317 {
318  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::~ScatteringPowerAtom():"<<mName,5)
319  gScatteringPowerAtomRegistry.DeRegister(*this);
320  delete mpGaussian;
321 }
322 
323 const string& ScatteringPowerAtom::GetClassName() const
324 {
325  const static string className="ScatteringPowerAtom";
326  return className;
327 }
328 
329 // Disable the base-class function.
331 {
332  // This should be never called.
333  abort();
334 }
335 
336 void ScatteringPowerAtom::Init(const string &name,const string &symbol,const REAL bIso)
337 {
338  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::Init(n,s,b)"<<mName,4)
339  this->ScatteringPower::Init();
340  this->SetName(name);
341  mSymbol=symbol;
342  mBiso=bIso;
343  mIsIsotropic=true;
344  if(mpGaussian!=0) delete mpGaussian;
345  try
346  {
347  cctbx::eltbx::xray_scattering::wk1995 wk95t(mSymbol);
348  mpGaussian=new cctbx::eltbx::xray_scattering::gaussian(wk95t.fetch());
349 
350  this->InitAtNeutronScattCoeffs();
351 
352  cctbx::eltbx::tiny_pse::table tpse(mSymbol);
353  mAtomicNumber=tpse.atomic_number();
354 
355  cctbx::eltbx::icsd_radii::table ticsd(mSymbol);
356  mRadius= ticsd.radius();
357  cctbx::eltbx::covalent_radii::table tcov(mSymbol);
358  mCovalentRadius=tcov.radius();
359  }
360  catch(exception &err)
361  {
362  cout << "WARNING: could not interpret Symbol name !"<<mSymbol<<endl
363  << " Reverting to H !"<<endl;
364  (*fpObjCrystInformUser)("Symbol not understood:"+mSymbol);
365  this->Init(name,"H",bIso);
366  }
367 
368 
369  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::Init():/Name="<<this->GetName() \
370  <<" /Symbol="<<mSymbol<<" /Atomic Number=" << mAtomicNumber,4)
371 
372  mDynPopCorrIndex=mAtomicNumber;
373 
374  //Init default atom colours for POVRay/GUI
375  cctbx::eltbx::tiny_pse::table tpse(mSymbol);
376  mColourName= tpse.symbol();
377  this->InitRGBColour();
378  switch(mAtomicNumber)
379  {// Values from OpenBabel element.txt
380  case 0: mMaxCovBonds=0;break;break;break;//Xx
381  case 1: mMaxCovBonds=1;break;break;break;//H
382  case 2: mMaxCovBonds=0;break;break;break;//He
383  case 3: mMaxCovBonds=1;break;break;break;//Li
384  case 4: mMaxCovBonds=2;break;//Be
385  case 5: mMaxCovBonds=4;break;//B
386  case 6: mMaxCovBonds=4;break;//C
387  case 7: mMaxCovBonds=4;break;//N
388  case 8: mMaxCovBonds=2;break;//O
389  case 9: mMaxCovBonds=1;break;//F
390  case 10: mMaxCovBonds=0;break;//Ne
391  case 11: mMaxCovBonds=1;break;//Na
392  case 12: mMaxCovBonds=2;break;//Mg
393  case 13: mMaxCovBonds=6;break;//Al
394  case 14: mMaxCovBonds=6;break;//Si
395  case 15: mMaxCovBonds=6;break;//P
396  case 16: mMaxCovBonds=6;break;//S
397  case 17: mMaxCovBonds=1;break;//Cl
398  case 18: mMaxCovBonds=0;break;//Ar
399  case 19: mMaxCovBonds=1;break;//K
400  case 20: mMaxCovBonds=2;break;//Ca
401  case 21: mMaxCovBonds=6;break;//Sc
402  case 22: mMaxCovBonds=6;break;//Ti
403  case 23: mMaxCovBonds=6;break;//V
404  case 24: mMaxCovBonds=6;break;//Cr
405  case 25: mMaxCovBonds=8;break;//Mn
406  case 26: mMaxCovBonds=6;break;//Fe
407  case 27: mMaxCovBonds=6;break;//Co
408  case 28: mMaxCovBonds=6;break;//Ni
409  case 29: mMaxCovBonds=6;break;//Cu
410  case 30: mMaxCovBonds=6;break;//Zn
411  case 31: mMaxCovBonds=3;break;//Ga
412  case 32: mMaxCovBonds=4;break;//Ge
413  case 33: mMaxCovBonds=3;break;//As
414  case 34: mMaxCovBonds=2;break;//Se
415  case 35: mMaxCovBonds=1;break;//Br
416  case 36: mMaxCovBonds=0;break;//Kr
417  case 37: mMaxCovBonds=1;break;//Rb
418  case 38: mMaxCovBonds=2;break;//Sr
419  case 39: mMaxCovBonds=6;break;//Y
420  case 40: mMaxCovBonds=6;break;//Zr
421  case 41: mMaxCovBonds=6;break;//Nb
422  case 42: mMaxCovBonds=6;break;//Mo
423  case 43: mMaxCovBonds=6;break;//Tc
424  case 44: mMaxCovBonds=6;break;//Ru
425  case 45: mMaxCovBonds=6;break;//Rh
426  case 46: mMaxCovBonds=6;break;//Pd
427  case 47: mMaxCovBonds=6;break;//Ag
428  case 48: mMaxCovBonds=6;break;//Cd
429  case 49: mMaxCovBonds=3;break;//In
430  case 50: mMaxCovBonds=4;break;//Sn
431  case 51: mMaxCovBonds=3;break;//Sb
432  case 52: mMaxCovBonds=2;break;//Te
433  case 53: mMaxCovBonds=1;break;//I
434  case 54: mMaxCovBonds=0;break;//Xe
435  case 55: mMaxCovBonds=1;break;//Cs
436  case 56: mMaxCovBonds=2;break;//Ba
437  case 57: mMaxCovBonds=12;break;//La
438  case 58: mMaxCovBonds=6;break;//Ce
439  case 59: mMaxCovBonds=6;break;//Pr
440  case 60: mMaxCovBonds=6;break;//Nd
441  case 61: mMaxCovBonds=6;break;//Pm
442  case 62: mMaxCovBonds=6;break;//Sm
443  case 63: mMaxCovBonds=6;break;//Eu
444  case 64: mMaxCovBonds=6;break;//Gd
445  case 65: mMaxCovBonds=6;break;//Tb
446  case 66: mMaxCovBonds=6;break;//Dy
447  case 67: mMaxCovBonds=6;break;//Ho
448  case 68: mMaxCovBonds=6;break;//Er
449  case 69: mMaxCovBonds=6;break;//Tm
450  case 70: mMaxCovBonds=6;break;//Yb
451  case 71: mMaxCovBonds=6;break;//Lu
452  case 72: mMaxCovBonds=6;break;//Hf
453  case 73: mMaxCovBonds=6;break;//Ta
454  case 74: mMaxCovBonds=6;break;//W
455  case 75: mMaxCovBonds=6;break;//Re
456  case 76: mMaxCovBonds=6;break;//Os
457  case 77: mMaxCovBonds=6;break;//Ir
458  case 78: mMaxCovBonds=6;break;//Pt
459  case 79: mMaxCovBonds=6;break;//Au
460  case 80: mMaxCovBonds=6;break;//Hg
461  case 81: mMaxCovBonds=3;break;//Tl
462  case 82: mMaxCovBonds=4;break;//Pb
463  case 83: mMaxCovBonds=3;break;//Bi
464  case 84: mMaxCovBonds=2;break;//Po
465  case 85: mMaxCovBonds=1;break;//At
466  case 86: mMaxCovBonds=0;break;//Rn
467  case 87: mMaxCovBonds=1;break;//Fr
468  case 88: mMaxCovBonds=2;break;//Ra
469  default: mMaxCovBonds=6;break;
470  }
471 
472  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::Init(n,s,b):End",3)
473 }
474 
476  const int spgSymPosIndex) const
477 {
478  VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor(&data):"<<mName,3)
479  CrystVector_REAL sf(data.GetNbRefl());
480  switch(data.GetRadiationType())
481  {
482  case(RAD_NEUTRON):
483  {
484  VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor():NEUTRON:"<<mName,3)
486  break;
487  }
488  case(RAD_XRAY):
489  {
490  VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor():XRAY:"<<mName,3)
491  if(mpGaussian!=0)
492  {
493  const long nb=data.GetSinThetaOverLambda().numElements();
494  const REAL *pstol=data.GetSinThetaOverLambda().data();
495  for(long i=0;i<nb;i++)
496  sf(i)=mpGaussian->at_stol(*pstol++);
497  }
498  else sf=1.0;//:KLUDGE: Should never happen
499  break;
500  }
501  case(RAD_ELECTRON):
502  {
503  VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor():ELECTRON:"<<mName,3)
504  if(mpGaussian!=0)
505  {
506  const REAL z=this->GetAtomicNumber();
507  const long nb=data.GetSinThetaOverLambda().numElements();
508  const REAL *pstol=data.GetSinThetaOverLambda().data();
509  for(long i=0;i<nb;i++)
510  sf(i)=(z-mpGaussian->at_stol(*pstol))/(*pstol * *pstol);
511  pstol++;
512  }
513  else sf=1.0;//:KLUDGE: Should never happen
514  break;
515  }
516  }
517  VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor(&data):End",3)
518  return sf;
519 }
520 
522 {
523  REAL sf = 0;
524  switch(type)
525  {
526  case(RAD_NEUTRON):
527  {
529  break;
530  }
531  case(RAD_XRAY):
532  {
533  if(mpGaussian!=0)
534  sf=mpGaussian->at_stol(0);
535  else sf=1.0;
536  break;
537  }
538  case(RAD_ELECTRON):
539  {
540  const REAL z=this->GetAtomicNumber();
541  sf=(z-mpGaussian->at_stol(0.0001))/(.0001 * .0001);
542  }
543  }
544  VFN_DEBUG_MESSAGE("ScatteringPower::GetScatteringFactor(&data):End",3)
545  return sf;
546 }
547 
548 static bool warnADP=true;
550  const int spgSymPosIndex) const
551 {
552  VFN_DEBUG_MESSAGE("ScatteringPower::GetTemperatureFactor(&data):"<<mName,3)
553  CrystVector_REAL sf(data.GetNbRefl());
554  if((mIsIsotropic==false) && warnADP)
555  { // Warn once
556  cout<<"========================== WARNING ========================="<<endl
557  <<" In ScatteringPowerAtom::GetTemperatureFactor():"<<endl
558  <<" Anisotropic Displacement Parameters are not currently properly handled"<<endl
559  <<" for Debye-Waller calculations (no symmetry handling for ADPs)."<<endl
560  <<" =>The Debye-Waller calculations will instead use only isotropic DPs"<<endl<<endl;
561  warnADP=false;
562  }
563 
564  if(true)//(mIsIsotropic)
565  {
566  CrystVector_REAL stolsq(data.GetNbRefl());
567  const CrystVector_REAL stol=data.GetSinThetaOverLambda();
568  stolsq=stol;
569  stolsq*=stol;
570 
571  #ifdef __VFN_VECTOR_USE_BLITZ__
572  #define SF sf
573  #define STOLSQ stolsq
574  #else
575  #define SF (*ssf)
576  #define STOLSQ (*sstolsq)
577 
578  REAL *ssf=sf.data();
579  const REAL *sstolsq=stolsq.data();
580 
581  for(long ii=0;ii<sf.numElements();ii++)
582  {
583  #endif
584 
585  SF=exp(-mBiso*STOLSQ);
586 
587  #ifdef __VFN_VECTOR_USE_BLITZ__
588 
589  #else
590  ssf++;
591  sstolsq++;
592  }
593  #endif
594 
595  #undef SF
596  #undef STOLSQ
597  }
598  else
599  {// :TODO: handle ADP - requires taking into account symmetries...
600  const REAL b11=mBeta(0);
601  const REAL b22=mBeta(1);
602  const REAL b33=mBeta(2);
603  const REAL b12=mBeta(3);
604  const REAL b13=mBeta(4);
605  const REAL b23=mBeta(5);
606  #ifdef __VFN_VECTOR_USE_BLITZ__
607  #define HH data.H()
608  #define KK data.K()
609  #define LL data.L()
610  #define SF sf
611  #else
612  #define HH (*hh)
613  #define KK (*kk)
614  #define LL (*ll)
615  #define SF (*ssf)
616 
617  const REAL *hh=(data.GetH()).data();
618  const REAL *kk=(data.GetK()).data();
619  const REAL *ll=(data.GetL()).data();
620  REAL *ssf=sf.data();
621 
622  for(long ii=0;ii<sf.numElements();ii++)
623  {
624  #endif
625 
626  SF= exp( -b11*pow(HH,2)
627  -b22*pow(KK,2)
628  -b33*pow(LL,2)
629  -2*b12*HH*KK
630  -2*b13*HH*LL
631  -2*b23*KK*LL);
632 
633  #ifdef __VFN_VECTOR_USE_BLITZ__
634 
635  #else
636  hh++;
637  kk++;
638  ll++;
639  ssf++;
640  }
641  #endif
642 
643  #undef HH
644  #undef KK
645  #undef LL
646  #undef SF
647  }
648  return sf;
649 }
650 
651 CrystMatrix_REAL ScatteringPowerAtom::
653  const int spgSymPosIndex) const
654 {
655  VFN_DEBUG_MESSAGE("ScatteringPower::GetResonantScattFactReal(&data):"<<mName,3)
656  CrystMatrix_REAL fprime(1,1);//:TODO: More than one wavelength
657  CrystMatrix_REAL fsecond(1,1);
658  switch(data.GetRadiationType())
659  {
660  case(RAD_NEUTRON):
661  {
662  fprime=0;
663  fsecond=mNeutronScattLengthImag;
664  break;
665  }
666  case(RAD_XRAY):
667  {
668  try
669  {
670  cctbx::eltbx::henke::table thenke(mSymbol);
671  cctbx::eltbx::fp_fdp f=thenke.at_angstrom(data.GetWavelength()(0));
672 
673  if(f.is_valid_fp()) fprime(0)=f.fp();
674  else fprime(0)=0;
675  if(f.is_valid_fdp()) fsecond(0)=f.fdp();
676  else fsecond(0)=0;
677  }
678  catch(cctbx::error)
679  {
680  fprime(0)=0;
681  fsecond(0)=0;
682  }
683  break;
684  }
685  case(RAD_ELECTRON):
686  {
687  fprime=0;
688  fsecond=0;
689  break;
690  }
691  }
692  return fprime;
693 }
694 
695 CrystMatrix_REAL ScatteringPowerAtom::
697  const int spgSymPosIndex) const
698 {
699  VFN_DEBUG_MESSAGE("ScatteringPower::GetResonantScattFactImag():"<<mName,3)
700  CrystMatrix_REAL fprime(1,1);//:TODO: More than one wavelength
701  CrystMatrix_REAL fsecond(1,1);
702  switch(data.GetRadiationType())
703  {
704  case(RAD_NEUTRON):
705  {
706  fprime=0;
707  fsecond=mNeutronScattLengthImag;
708  break;
709  }
710  case(RAD_XRAY):
711  {
712  try
713  {
714  cctbx::eltbx::henke::table thenke(mSymbol);
715  cctbx::eltbx::fp_fdp f=thenke.at_angstrom(data.GetWavelength()(0));
716 
717  if(f.is_valid_fp()) fprime(0)=f.fp();
718  else fprime(0)=0;
719  if(f.is_valid_fdp()) fsecond(0)=f.fdp();
720  else fsecond(0)=0;
721  }
722  catch(cctbx::error)
723  {
724  fprime(0)=0;
725  fsecond(0)=0;
726  }
727  break;
728  }
729  case(RAD_ELECTRON):
730  {
731  fprime=0;
732  fsecond=0;
733  break;
734  }
735  }
736  return fsecond;
737 }
738 
739 
740 void ScatteringPowerAtom::SetSymbol(const string& symbol)
741 {
742  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::SetSymbol():"<<mName,5)
743  this->Init(this->GetName(),symbol,this->GetBiso());
744 }
745 const string& ScatteringPowerAtom::GetSymbol() const
746 {
747  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::GetSymbol():"<<mName,5)
748  return mSymbol;
749 }
750 
752 {
753  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::GetElementName():"<<mName,2)
754  try
755  {
756  cctbx::eltbx::tiny_pse::table tpse(mSymbol);
757  return tpse.name();
758  }
759  catch(cctbx::error)
760  {
761  cout << "WARNING: could not interpret Symbol:"<<mSymbol<<endl;
762  }
763  return "Unknown";
764 }
765 
770 
771 void ScatteringPowerAtom::Print()const
772 {
773  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::Print()",1)
774  cout << "ScatteringPowerAtom ("<<this->GetName()<<","
775  << FormatString(this->GetSymbol(),4) << ") :"
776  << FormatFloat(this->GetBiso());
777  VFN_DEBUG_MESSAGE_SHORT("at "<<this,10)
778  cout << endl;
779 }
780 
781 void ScatteringPowerAtom::InitAtNeutronScattCoeffs()
782 {
783  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::InitAtNeutronScattCoeffs():"<<mName,3)
784  mClock.Click();
785  try
786  {
787  cctbx::eltbx::neutron::neutron_news_1992_table nn92t(mSymbol);
788  mNeutronScattLengthReal=nn92t.bound_coh_scatt_length_real();
789  mNeutronScattLengthImag=nn92t.bound_coh_scatt_length_imag();
790  }
791  catch(cctbx::error)
792  {
793  cout << "WARNING: could not interpret symbol for neutron coeefs:"<<mSymbol<<endl;
794  }
795 
796  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::InitAtNeutronScattCoeffs():End",3)
797 }
798 
799 void ScatteringPowerAtom::InitRefParList()
800 {
801  VFN_DEBUG_MESSAGE("ScatteringPowerAtom::InitRefParList():"<<mName,5)
802  {
803  RefinablePar tmp("Biso",&mBiso,0.1,5.,
804  gpRefParTypeScattPowTemperatureIso,REFPAR_DERIV_STEP_ABSOLUTE,
805  true,true,true,false);
806  tmp.SetDerivStep(1e-3);
807  tmp.SetGlobalOptimStep(.5);
808  tmp.AssignClock(mClock);
809  this->AddPar(tmp);
810  }
811  {
812  REAL* bdata = (REAL*) mB.data();
813 
814  RefinablePar B11("B11",&bdata[0],0.1,5.,
815  gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE,
816  true,true,false,false);
817  B11.SetDerivStep(1e-3);
818  B11.SetGlobalOptimStep(.5);
819  B11.AssignClock(mClock);
820  this->AddPar(B11);
821 
822  RefinablePar B22("B22",&bdata[1],0.1,5.,
823  gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE,
824  true,true,false,false);
825  B22.SetDerivStep(1e-3);
826  B22.SetGlobalOptimStep(.5);
827  B22.AssignClock(mClock);
828  this->AddPar(B22);
829 
830  RefinablePar B33("B33",&bdata[2],0.1,5.,
831  gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE,
832  true,true,false,false);
833  B33.SetDerivStep(1e-3);
834  B33.SetGlobalOptimStep(.5);
835  B33.AssignClock(mClock);
836  this->AddPar(B33);
837 
838  RefinablePar B12("B12",&bdata[3],-5,5.,
839  gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE,
840  true,true,false,false);
841  B12.SetDerivStep(1e-3);
842  B12.SetGlobalOptimStep(.5);
843  B12.AssignClock(mClock);
844  this->AddPar(B12);
845 
846  RefinablePar B13("B13",&bdata[4],-5,5.,
847  gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE,
848  true,true,false,false);
849  B13.SetDerivStep(1e-3);
850  B13.SetGlobalOptimStep(.5);
851  B13.AssignClock(mClock);
852  this->AddPar(B13);
853 
854  RefinablePar B23("B23",&bdata[5],-5,5.,
855  gpRefParTypeScattPowTemperatureAniso,REFPAR_DERIV_STEP_ABSOLUTE,
856  true,true,false,false);
857  B23.SetDerivStep(1e-3);
858  B23.SetGlobalOptimStep(.5);
859  B23.AssignClock(mClock);
860  this->AddPar(B23);
861  }
862  {
863  RefinablePar tmp("ML Error",&mMaximumLikelihoodPositionError,0.,1.,
864  gpRefParTypeScattPow,REFPAR_DERIV_STEP_ABSOLUTE,
865  false,true,true,false);
866  tmp.SetDerivStep(1e-4);
867  tmp.SetGlobalOptimStep(.001);
868  tmp.AssignClock(mMaximumLikelihoodParClock);
869  this->AddPar(tmp);
870  }
871  {
872  RefinablePar tmp("ML-Nb Ghost Atoms",&mMaximumLikelihoodNbGhost,0.,10.,
873  gpRefParTypeScattPow,REFPAR_DERIV_STEP_ABSOLUTE,
874  true,true,true,false);
875  tmp.SetDerivStep(1e-3);
876  tmp.SetGlobalOptimStep(.05);
877  tmp.AssignClock(mMaximumLikelihoodParClock);
878  this->AddPar(tmp);
879  }
880  {
881  RefinablePar tmp("Formal Charge",&mFormalCharge,-10.,10.,
882  gpRefParTypeScattPow,REFPAR_DERIV_STEP_ABSOLUTE,
883  true,true,true,false);
884  tmp.SetDerivStep(1e-3);
885  tmp.SetGlobalOptimStep(.05);
886  tmp.AssignClock(mClock);
887  this->AddPar(tmp);
888  }
889 }
890 #ifdef __WX__CRYST__
891 WXCrystObjBasic* ScatteringPowerAtom::WXCreate(wxWindow* parent)
892 {
893  //:TODO: Check mpWXCrystObj==0
894  mpWXCrystObj=new WXScatteringPowerAtom(parent,this);
895  return mpWXCrystObj;
896 }
897 #endif
898 
899 //######################################################################
900 //
901 // SCATTERING COMPONENT
902 //
903 //######################################################################
904 ScatteringComponent::ScatteringComponent():
905 mX(0),mY(0),mZ(0),mOccupancy(0),mpScattPow(0),mDynPopCorr(0)
906 {}
907 bool ScatteringComponent::operator==(const ScatteringComponent& rhs) const
908 {
909  return ((mX==rhs.mX) && (mY==rhs.mY) && (mZ==rhs.mZ) &&
910  (mOccupancy==rhs.mOccupancy) && (mpScattPow==rhs.mpScattPow));
911 }
912 bool ScatteringComponent::operator!=(const ScatteringComponent& rhs) const
913 {
914  return ((mX!=rhs.mX) || (mY!=rhs.mY) || (mZ!=rhs.mZ) ||
915  (mOccupancy!=rhs.mOccupancy) || (mpScattPow!=rhs.mpScattPow));
916 }
918 {
919  cout <<mX<<" "<<mY<<" "<<mZ<<" "<<mOccupancy<<" "<<mDynPopCorr<<" "<<mpScattPow;
920  if(0!=mpScattPow) cout <<" "<<mpScattPow->GetName();
921  cout<<endl;
922 }
923 
924 //######################################################################
925 //
926 // SCATTERING COMPONENT LIST
927 //
928 //######################################################################
929 
930 ScatteringComponentList::ScatteringComponentList()
931 {
932 }
933 
934 ScatteringComponentList::ScatteringComponentList(const long nbComponent)
935 {
936  mvScattComp.resize(nbComponent);
937 }
938 
939 ScatteringComponentList::ScatteringComponentList(const ScatteringComponentList &old):
940 mvScattComp(old.mvScattComp)
941 {
942 }
943 
944 ScatteringComponentList::~ScatteringComponentList()
945 {
946 }
948 {
949  mvScattComp.clear();
950 }
951 
953 {
954  VFN_DEBUG_MESSAGE("ScatteringComponentList::operator()("<<i<<")",1)
955  if(i>=this->GetNbComponent())
956  {
957  this->Print();
958  throw ObjCrystException("ScatteringComponentList::operator()(i)::i>mNbComponent!!");
959  }
960  if(i<0) throw ObjCrystException("ScatteringComponentList::operator()&(i)::i<0!!");
961  return mvScattComp[i];
962 }
963 
965 {
966  VFN_DEBUG_MESSAGE("ScatteringComponentList::operator()&("<<i<<")",1)
967  if(i>=this->GetNbComponent())
968  {
969  this->Print();
970  throw ObjCrystException("ScatteringComponentList::operator()&(i)::i>mNbComponent!!");
971  }
972  if(i<0) throw ObjCrystException("ScatteringComponentList::operator()&(i):: i<0!!");
973  return mvScattComp[i];
974 }
975 
977 
979 {
980  VFN_DEBUG_MESSAGE("ScatteringComponentList::operator=()",1)
982  VFN_DEBUG_MESSAGE("ScatteringComponentList::operator=():End",0)
983 }
985 {
986  if(rhs.GetNbComponent() != this->GetNbComponent()) return false;
987  for(long i=0;i<this->GetNbComponent();i++)
988  if( (*this)(i) != rhs(i) ) return false;
989  return true;
990 }
991 
993 {
994  for(long i=0;i<rhs.GetNbComponent();i++)
995  mvScattComp.push_back(rhs(i));
996 }
998 {
999  VFN_DEBUG_MESSAGE("ScatteringComponentList::operator+=()",1)
1000  mvScattComp.push_back(rhs);
1001 }
1002 
1004 {
1005  VFN_DEBUG_MESSAGE("ScatteringComponentList::operator++()",1)
1006  mvScattComp.resize(this->GetNbComponent()+1);
1007 }
1008 
1010 {
1011  VFN_DEBUG_MESSAGE("ScatteringComponentList::operator--()",1)
1012  if(this->GetNbComponent()>0)
1013  mvScattComp.resize(this->GetNbComponent()-1);
1014 }
1015 
1017 {
1018  VFN_DEBUG_ENTRY("ScatteringComponentList::Print()",5)
1019  cout<<"Number of Scattering components:"<<this->GetNbComponent()<<endl;
1020  for(long i=0;i<this->GetNbComponent();i++)
1021  {
1022  cout << i<<":";
1023  (*this)(i).Print();
1024  }
1025  VFN_DEBUG_EXIT("ScatteringComponentList::Print()",5)
1026 }
1027 
1028 }//namespace
string mColourName
Colour for this ScatteringPower (from POVRay)
virtual REAL GetForwardScatteringFactor(const RadiationType) const
Get the scattering factor at (0,0,0).
const CrystVector_REAL & GetH() const
Return the 1D array of H coordinates for all reflections.
virtual CrystMatrix_REAL GetResonantScattFactImag(const ScatteringData &data, const int spgSymPosIndex=0) const
Get the imaginary part of the resonant scattering factor.
virtual CrystVector_REAL GetTemperatureFactor(const ScatteringData &data, const int spgSymPosIndex=0) const
Get the temperature factor for all reflections of a given ScatteringData object.
REAL GetMaximumLikelihoodNbGhostAtom() const
Maximum Likelihood: get the number of ghost elements per asymmetric unit.
const string & GetColourName() const
Get the (POV-Ray) name associated to the color (if any)
virtual bool IsTemperatureFactorAnisotropic() const
Is the thermic factor anisotropic ?
void AddPar(const RefinablePar &newRefPar)
Add a refinable parameter.
RadiationType GetRadiationType() const
Neutron or x-ray experiment ? Wavelength ?
void SetColour(const string &colorName)
Set the colour from the associated POV-Ray name.
const CrystVector_REAL & GetSinThetaOverLambda() const
Return an array with for all reflections.
const RefinableObjClock & GetMaximumLikelihoodParClock() const
Get the clock value for the last change on the maximum likelihood parameters (positionnal error...
long GetDynPopCorrIndex() const
Get the number identifying this kind of scatterer, used to decide whether two scatterers are equivale...
REAL mNeutronScattLengthReal
Neutron Bond Coherent Scattering lengths.
A scattering position in a crystal, associated with the corresponding occupancy and a pointer to the ...
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
virtual bool IsResonantScatteringAnisotropic() const
Are the resonant scattering terms anisotropic ?
bool operator==(const ScatteringComponentList &rhs) const
Compare two lists.
REAL mCovalentRadius
Covalent Radius for this atom, in Angstroems (from cctbx)
CrystVector_REAL GetWavelength() const
wavelength of the experiment (in Angstroems)
REAL GetMaximumLikelihoodPositionError() const
Maximum Likelihood: get the estimated error (sigma) on the positions for this kind of element...
long GetNbPar() const
Total number of refinable parameter in the object.
unsigned int GetMaxCovBonds() const
Maximum number of covalent bonds (from openbabel element.txt)
RefinablePar & GetPar(const long i)
Access all parameters in the order they were inputted.
void Print() const
Print the list of Scattering components. For debugging.
const ScatteringComponent & operator()(const long i) const
Access to a component.
Class to compute structure factors for a set of reflections and a Crystal.
RefinableObjClock mClockMaster
Master clock, which is changed whenever the object has been altered.
const CrystVector_REAL & GetL() const
Return the 1D array of L coordinates for all reflections.
Generic Refinable Object.
Definition: RefinableObj.h:752
REAL mDynPopCorr
Dynamical Population Correction.
REAL GetBij(const size_t &i, const size_t &j) const
Returns the anisotropic temperature B factor for (i, j) pair.
void operator++()
Add component (the whole list should be updated after that)
string mName
Name for this RefinableObject. Should be unique, at least in the same scope.+.
long GetNbScatteringPower() const
Total number of ScatteringPower object.
virtual void SetBij(const size_t &i, const size_t &j, const REAL newB)
Sets the anisotropic temperature B factor for (i, j) pair.
const RefinableObjClock & GetLastChangeClock() const
ObjCrystClock time when the last modification was made to the object.
REAL mX
Coordinates of scattering positions i the crystal with the corresponding occupancy.
virtual void Init()
Initialization of the object, used by all constructors, and operator=.
cctbx::eltbx::xray_scattering::gaussian * mpGaussian
Pointer to cctbx's gaussian describing the thomson x-ray scattering factor.
bool IsIsotropic() const
Returns true if the scattering power is isotropic, else false.
const ScatteringPower * mpScattPow
The ScatteringPower associated with this position.
virtual const string & GetSymbol() const
Returns the symbol ('Ta', 'O2-',...) of the atom.
void operator+=(const ScatteringComponentList &rhs)
Add another list of components.
void SetSymbol(const string &symbol)
Set the symbol for this atom.
vector< ScatteringComponent > mvScattComp
The vector of components.
REAL GetRadius() const
Atomic radius for this atom or ion, in Angstroems (ICSD table from cctbx)
virtual CrystMatrix_REAL GetResonantScattFactReal(const ScatteringData &data, const int spgSymPosIndex=0) const
Get the real part of the resonant scattering factor.
virtual CrystVector_REAL GetScatteringFactor(const ScatteringData &data, const int spgSymPosIndex=0) const
Get the Scattering factor for all reflections of a given ScatteringData object.
virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint &groupIndex, unsigned int &firstGroup) const
Get the gene group assigned to each parameter.
virtual void SetBiso(const REAL newB)
Sets the isotropic temperature B factor.
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
void operator=(const ScatteringComponentList &rhs)
Assignement operator.
output a number as a formatted float:
ObjRegistry< ScatteringPowerAtom > gScatteringPowerAtomRegistry("Global ScatteringPowerAtom Registry")
Global registry for all ScatteringPowerAtom objects.
string mSymbol
Symbol of this atom.
void Print() const
Print one line oabout this component.
void Init()
Initialization of the object, used by all constructors, and operator=.
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
output a string with a fixed length (adding necessary space or removing excess characters) : ...
ObjRegistry< ScatteringPower > gScatteringPowerRegistry("Global ScatteringPower Registry")
Global registry for all ScatteringPower objects.
int GetAtomicNumber() const
Atomic number for this atom.
Exception class for ObjCryst++ library.
Definition: General.h:119
long GetNbRefl() const
Return the number of reflections in this experiment.
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: Atom.cpp:47
The Scattering Power for an Atom.
Generic class for parameters of refinable objects.
Definition: RefinableObj.h:223
void SetMaximumLikelihoodPositionError(const REAL mle)
Maximum Likelihood: set the estimated error (sigma) on the positions for this kind of element...
virtual const string & GetName() const
Name of the object.
int mAtomicNumber
atomic number (Z) for the atom
RadiationType
Type of radiation used.
Definition: General.h:94
REAL GetBiso() const
Returns the isotropic temperature B factor.
list of scattering positions in a crystal, associated with the corresponding occupancy and a pointer ...
REAL mRadius
Radius of the atom or ion, in Angstroems (ICSD table from cctbx)
const CrystVector_REAL & GetK() const
Return the 1D array of K coordinates for all reflections.
virtual const string & GetSymbol() const
Symbol for this Scattering power (the atom name for atoms)
string GetElementName() const
Returns the standard name of the element (ie "hydrogen", "tantalum",..).
Object Registry.
Definition: RefinableObj.h:643
void SetMaximumLikelihoodNbGhostAtom(const REAL nb)
Maximum Likelihood: set the number of ghost elements per asymmetric unit.
REAL GetCovalentRadius() const
Covalent Radius for this atom, in Angstroems (from cctbx)
void operator--()
Remove component (the whole list should be updated after that)
virtual void SetName(const string &name)
Name of the object.
virtual void InitRGBColour()
Get RGB Colour coordinates from Colour Name.
const float * GetColourRGB() const
Get the float[3] array of RGB components defining the colour of this scattering power.
CrystVector_REAL mBeta
Anisotropic Beta(ij)
unsigned int mMaxCovBonds
Maximum number of covalent bonds.