source: ThirdParty/mpqc_open/src/lib/chemistry/qc/basis/transform.cc@ 860145

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 860145 was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 11.6 KB
Line 
1//
2// transform.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#if defined(__GNUC__)
29#pragma implementation
30#endif
31
32#include <stdlib.h>
33#include <string.h>
34#include <math.h>
35#include <float.h>
36
37#include <util/misc/formio.h>
38#include <math/scmat/matrix.h>
39#include <math/scmat/repl.h>
40#include <chemistry/qc/basis/transform.h>
41
42using namespace std;
43using namespace sc;
44
45#undef DEBUG
46
47////////////////////////////////////////////////////////////////////////////
48// Utility classes and routines to generate cartesian to pure transformation
49// matrices.
50
51class SafeUInt {
52 private:
53 unsigned long i_;
54 public:
55 SafeUInt(): i_(0) {}
56 SafeUInt(unsigned long i): i_(i) {}
57 void error() const {
58 ExEnv::errn() << "SafeUInt: integer size exceeded" << endl;
59 abort();
60 }
61 SafeUInt &operator ++ () { i_++; return *this; }
62 SafeUInt &operator ++ (int) { i_++; return *this; }
63 operator double() const { return i_; }
64 operator unsigned long() const { return i_; }
65 SafeUInt &operator =(const SafeUInt &i) { i_ = i.i_; return *this; }
66 int operator > (const SafeUInt& i) const { return i_>i.i_; }
67 int operator >= (const SafeUInt& i) const { return i_>=i.i_; }
68 int operator < (const SafeUInt& i) const { return i_<i.i_; }
69 int operator <= (const SafeUInt& i) const { return i_<=i.i_; }
70 int operator == (const SafeUInt& i) const { return i_==i.i_; }
71 int operator == (unsigned long i) const { return i_==i; }
72 int operator != (const SafeUInt& i) const { return i_!=i.i_; }
73 SafeUInt operator / (const SafeUInt& i) const { return SafeUInt(i_/i.i_); }
74 SafeUInt operator % (const SafeUInt& i) const { return SafeUInt(i_%i.i_); }
75 SafeUInt operator * (unsigned long i) const
76 {
77 unsigned long tmp = i_*i;
78 if (tmp/i != i_ || tmp%i != 0) {
79 error();
80 }
81 return SafeUInt(tmp);
82 }
83 SafeUInt operator * (const SafeUInt& i) const
84 {
85 return this->operator*(i.i_);
86 }
87 SafeUInt &operator = (unsigned long i) { i_ = i; return *this; }
88 SafeUInt &operator *= (unsigned long i) { *this = *this*i; return *this; }
89 SafeUInt &operator /= (unsigned long i) { i_ /= i; return *this; }
90};
91
92// there ordering here is arbitrary and doesn't have to match the
93// basis set ordering
94static inline int ncart(int l) { return (l>=0)?((((l)+2)*((l)+1))>>1):0; }
95static inline int npure(int l) { return 2*l+1; }
96static inline int icart(int a, int b, int c)
97{
98 return (((((a+b+c+1)<<1)-a)*(a+1))>>1)-b-1;
99}
100static inline int ipure(int l, int m) { return m<0?2*-m:(m==0?0:2*m-1); }
101
102static inline int local_abs(int i) { return i<0? -i:i; }
103
104SafeUInt
105binomial(int n, int c1)
106{
107 SafeUInt num = 1;
108 SafeUInt den = 1;
109 int c2 = n - c1;
110 int i;
111 for (i=c2+1; i<=n; i++) {
112 num *= i;
113 }
114 for (i=2; i<=c1; i++) {
115 den *= i;
116 }
117 return num/den;
118}
119
120SafeUInt
121fact(int n)
122{
123 SafeUInt r = 1;
124 for (int i=2; i<=n; i++) {
125 r *= i;
126 }
127 return r;
128}
129
130// compute nnum!/nden!, nden <= nnum
131SafeUInt
132factoverfact(int nnum,int nden)
133{
134 SafeUInt r = 1;
135 for (int i=nden+1; i<=nnum; i++) {
136 r *= i;
137 }
138 return r;
139}
140
141SafeUInt
142factfact(int n)
143{
144 SafeUInt result;
145 int i;
146
147 result = 1;
148 if (n&1) {
149 for (i=3; i<=n; i+=2) {
150 result *= i;
151 }
152 }
153 else {
154 for (i=2; i<=n; i+=2) {
155 result *= i;
156 }
157 }
158 return result;
159}
160
161void
162reduce(SafeUInt &num, SafeUInt &den)
163{
164 if (num > den) {
165 for (SafeUInt i=2; i<=den;) {
166 if (num%i == 0UL && den%i == 0UL) {
167 num /= i;
168 den /= i;
169 }
170 else i++;
171 }
172 }
173 else {
174 for (SafeUInt i=2; i<=num;) {
175 if (num%i == 0UL && den%i == 0UL) {
176 num /= i;
177 den /= i;
178 }
179 else i++;
180 }
181 }
182}
183
184SafeUInt
185powll(SafeUInt n, unsigned long p)
186{
187 SafeUInt result = 1;
188 for (unsigned long i=0; i<p; i++) result *= n;
189 return result;
190}
191
192////////////////////////////////////////////////////////////////////////////
193// SphericalTransform class
194
195SphericalTransform::SphericalTransform()
196{
197 n_ = 0;
198 l_ = 0;
199 subl_ = 0;
200 components_ = 0;
201}
202
203SphericalTransform::SphericalTransform(int l, int subl) : l_(l)
204{
205 n_ = 0;
206 if (subl == -1) subl_ = l;
207 else subl_ = subl;
208 components_ = 0;
209}
210
211static void
212solidharmcontrib(int sign,
213 const SafeUInt &bin,const SafeUInt &den,
214 SafeUInt norm2num,SafeUInt norm2den,
215 int r2,int x,int y,int z,
216 const RefSCMatrix &coefmat, int pureindex)
217{
218 if (r2>0) {
219 solidharmcontrib(sign,bin,den,norm2num,norm2den,r2-1,x+2,y,z,
220 coefmat,pureindex);
221 solidharmcontrib(sign,bin,den,norm2num,norm2den,r2-1,x,y+2,z,
222 coefmat,pureindex);
223 solidharmcontrib(sign,bin,den,norm2num,norm2den,r2-1,x,y,z+2,
224 coefmat,pureindex);
225 }
226 else {
227 double coef = sign*double(bin)/double(den);
228 double norm = sqrt(double(norm2num)/double(norm2den));
229 coefmat->accumulate_element(icart(x,y,z), pureindex, coef*norm);
230#ifdef DEBUG
231 ExEnv::outn().form(" add(%d,%d,%d, % 4ld.0",
232 x,y,z, sign*long(bin));
233 if (den!=1) {
234 ExEnv::outn().form("/%-4.1f",double(den));
235 }
236 else {
237 ExEnv::outn().form(" ");
238 }
239 if (norm2num != 1 || norm2den != 1) {
240 ExEnv::outn().form(" * sqrt(%ld.0/%ld.0)",
241 long(norm2num), long(norm2den));
242 }
243 ExEnv::outn().form(", i);");
244 ExEnv::outn() << endl;
245#endif
246 }
247}
248
249// l is the total angular momentum
250// m is the z component
251// r2 is the number of factors of r^2 that are included
252static void
253solidharm(unsigned int l, int m, unsigned int r2, RefSCMatrix coefmat)
254{
255 int pureindex = ipure(l,m);
256 for (unsigned int i=1; i<=r2; i++) pureindex += npure(l+2*i);
257
258 unsigned int absm = local_abs(m);
259
260 // the original norm2num and norm2den computation overflows 32bits for l=7
261 //SafeUInt norm2num = factoverfact(l+absm,l-absm);
262 //if (m != 0) norm2num *= 2;
263 //SafeUInt normden = factfact(2*absm)*binomial(l,absm);
264 //SafeUInt norm2den = normden*norm2den;
265 //reduce(norm2num,norm2den);
266
267 // this overflows 32bits for l=9
268 SafeUInt norm2num = factoverfact(l+absm,l);
269 SafeUInt norm2den = factoverfact(l,l-absm);
270 reduce(norm2num,norm2den);
271 norm2num *= fact(absm);
272 norm2den *= factfact(2*absm);
273 reduce(norm2num,norm2den);
274 norm2num *= fact(absm);
275 norm2den *= factfact(2*absm);
276 if (m != 0) norm2num *= 2;
277 reduce(norm2num,norm2den);
278
279#ifdef DEBUG
280 ExEnv::outn().form(" // l=%2d m=% 2d",l,m);
281 ExEnv::outn() << endl;
282#endif
283 for (unsigned int t=0; t <= (l - absm)/2; t++) {
284 for (unsigned int u=0; u<=t; u++) {
285 int v2m;
286 if (m >= 0) v2m = 0;
287 else v2m = 1;
288 for (unsigned int v2 = v2m; v2 <= absm; v2+=2) {
289 int x = 2*t + absm - 2*u - v2;
290 int y = 2*u + v2;
291 int z = l - x - y;
292 SafeUInt bin = binomial(l,t)
293 *binomial(l-t,absm+t)
294 *binomial(t,u)
295 *binomial(absm,v2);
296 SafeUInt den = powll(4,t);
297 int sign;
298 if ((t + (v2-v2m)/2)%2) sign = -1;
299 else sign = 1;
300 reduce(bin,den);
301 solidharmcontrib(sign,bin,den,norm2num,norm2den,
302 r2,x,y,z,coefmat,pureindex);
303 }
304 }
305 }
306#ifdef DEBUG
307 ExEnv::outn() << " i++;" << endl;
308#endif
309}
310
311static void
312solidharm(int l, const RefSCMatrix &coefmat)
313{
314 solidharm(l,0,0,coefmat);
315 for (int m=1; m<=l; m++) {
316 solidharm(l, m,0,coefmat);
317 solidharm(l,-m,0,coefmat);
318 }
319 for (int r=2; r<=l; r+=2) {
320 solidharm(l-r,0,r/2,coefmat);
321 for (int m=1; m<=l-r; m++) {
322 solidharm(l-r, m,r/2,coefmat);
323 solidharm(l-r,-m,r/2,coefmat);
324 }
325 }
326
327#ifdef DEBUG
328 ExEnv::outn() << coefmat;
329#endif
330}
331
332void
333SphericalTransform::init()
334{
335 Ref<SCMatrixKit> matrixkit = new ReplSCMatrixKit;
336 RefSCDimension cartdim(new SCDimension(ncart(l_)));
337 RefSCMatrix coefmat(cartdim,cartdim,matrixkit);
338 coefmat->assign(0.0);
339
340 solidharm(l_,coefmat);
341
342#ifdef DEBUG
343 ExEnv::outn() << scprintf("---> generating l=%d subl=%d", l_, subl_) << endl;
344#endif
345
346 int pureoffset = 0;
347 for (int i=1; i<=(l_-subl_)/2; i++) pureoffset += npure(subl_+2*i);
348
349 for (int p=0; p<npure(subl_); p++) {
350 for (int a=0; a<=l_; a++) {
351 for (int b=0; (a+b)<=l_; b++) {
352 int c = l_ - a - b;
353 int cart = icart(a,b,c);
354 double coef = coefmat->get_element(cart,p+pureoffset);
355 if (fabs(coef) > DBL_EPSILON) {
356 add(a,b,c, coef, p);
357#ifdef DEBUG
358 ExEnv::outn() << scprintf("---> add(%d,%d,%d, %12.8f, %d)",
359 a,b,c,coef,p) << endl;
360#endif
361 }
362 }
363 }
364 }
365}
366
367SphericalTransform::~SphericalTransform()
368{
369 if (components_) {
370 delete[] components_;
371 components_ = 0;
372 }
373}
374
375void
376SphericalTransform::add(int a, int b, int c, double coef, int pureindex)
377{
378 int i;
379
380 SphericalTransformComponent *ncomp = new_components();
381
382 for (i=0; i<n_; i++)
383 ncomp[i] = components_[i];
384
385 ncomp[i].init(a, b, c, coef, pureindex);
386
387 delete[] components_;
388 components_ = ncomp;
389 n_++;
390}
391
392///////////////////////////////////////////////////////////////////////////
393
394ISphericalTransform::ISphericalTransform() :
395 SphericalTransform()
396{
397}
398
399ISphericalTransform::ISphericalTransform(int l,int subl) :
400 SphericalTransform(l,subl)
401{
402}
403
404void
405ISphericalTransform::init()
406{
407 Ref<SCMatrixKit> matrixkit = new ReplSCMatrixKit;
408 RefSCDimension cartdim(new SCDimension(ncart(l_)));
409 RefSCMatrix coefmat(cartdim,cartdim,matrixkit);
410 coefmat->assign(0.0);
411
412 solidharm(l_,coefmat);
413
414 coefmat->invert_this();
415 coefmat->transpose_this();
416
417#ifdef DEBUG
418 ExEnv::outn() << scprintf("---> IST: generating l=%d subl=%d", l_, subl_) << endl;
419#endif
420
421 int pureoffset = 0;
422 for (int i=1; i<=(l_-subl_)/2; i++) pureoffset += npure(subl_+2*i);
423
424 for (int p=0; p<npure(subl_); p++) {
425 for (int a=0; a<=l_; a++) {
426 for (int b=0; (a+b)<=l_; b++) {
427 int c = l_ - a - b;
428 int cart = icart(a,b,c);
429 double coef = coefmat->get_element(cart,p+pureoffset);
430 if (fabs(coef) > DBL_EPSILON) {
431 add(a,b,c, coef, p);
432#ifdef DEBUG
433 ExEnv::outn() << scprintf("---> IST: add(%d,%d,%d, %12.8f, %d)",
434 a,b,c,coef,p) << endl;
435#endif
436 }
437 }
438 }
439 }
440}
441
442///////////////////////////////////////////////////////////////////////////
443
444SphericalTransformIter::SphericalTransformIter()
445{
446 transform_=0;
447}
448
449SphericalTransformIter::SphericalTransformIter(const SphericalTransform*t)
450{
451 transform_ = t;
452}
453
454/////////////////////////////////////////////////////////////////////////////
455
456// Local Variables:
457// mode: c++
458// c-file-style: "ETS"
459// End:
Note: See TracBrowser for help on using the repository browser.