source: ThirdParty/mpqc_open/src/lib/chemistry/qc/basis/shellrot.cc

Candidate_v1.6.1
Last change on this file 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: 7.0 KB
Line 
1//
2// shellrot.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#ifdef __GNUC__
29#pragma implementation
30#endif
31
32#include <util/misc/formio.h>
33
34#include <chemistry/qc/basis/integral.h>
35#include <chemistry/qc/basis/shellrot.h>
36#include <chemistry/qc/basis/cartiter.h>
37#include <chemistry/qc/basis/transform.h>
38
39using namespace std;
40using namespace sc;
41
42void
43ShellRotation::done() {
44 if (r) {
45 for (int i=0; i < n_; i++) {
46 if (r[i]) delete[] r[i];
47 }
48 delete[] r;
49 r=0;
50 }
51 n_=0;
52}
53
54ShellRotation::ShellRotation(int n) :
55 n_(n),
56 am_(0),
57 r(0)
58{
59 if (n_) {
60 r = new double*[n_];
61 for (int i=0; i < n_; i++)
62 r[i] = new double[n_];
63 }
64}
65
66ShellRotation::ShellRotation(const ShellRotation& rot) :
67 n_(0),
68 am_(0),
69 r(0)
70{
71 *this = rot;
72}
73
74ShellRotation::ShellRotation(int a, SymmetryOperation& so,
75 const Ref<Integral>& ints,
76 int pure) :
77 n_(0),
78 am_(0),
79 r(0)
80{
81 if (a > 1 && pure)
82 init_pure(a,so,ints);
83 else
84 init(a,so,ints);
85}
86
87ShellRotation::~ShellRotation()
88{
89 done();
90}
91
92ShellRotation&
93ShellRotation::operator=(const ShellRotation& rot)
94{
95 done();
96
97 n_ = rot.n_;
98 am_ = rot.am_;
99
100 if (n_ && rot.r) {
101 r = new double*[n_];
102 for (int i=0; i < n_; i++) {
103 r[i] = new double[n_];
104 memcpy(r[i],rot.r[i],sizeof(double)*n_);
105 }
106 }
107
108 return *this;
109}
110
111// Compute the transformation matrices for general cartesian shells
112// using the P (xyz) transformation matrix. This is done as a
113// matrix outer product, keeping only the unique terms.
114// Written by clj...blame him
115void
116ShellRotation::init(int a, SymmetryOperation& so, const Ref<Integral>& ints)
117{
118 done();
119
120 am_=a;
121
122 if (a == 0) {
123 n_ = 1;
124 r = new double*[1];
125 r[0] = new double[1];
126 r[0][0] = 1.0;
127 return;
128 }
129
130 CartesianIter *ip = ints->new_cartesian_iter(am_);
131 RedundantCartesianIter *jp = ints->new_redundant_cartesian_iter(am_);
132
133 CartesianIter& I = *ip;
134 RedundantCartesianIter& J = *jp;
135 int lI[3];
136 int k, iI;
137
138 n_ = I.n();
139 r = new double*[n_];
140
141 for (I.start(); I; I.next()) {
142 r[I.bfn()] = new double[n_];
143 memset(r[I.bfn()],0,sizeof(double)*n_);
144
145 for (J.start(); J; J.next()) {
146 double tmp = 1.0;
147
148 for (k=0; k < 3; k++) {
149 lI[k] = I.l(k);
150 }
151
152 for (k=0; k < am_; k++) {
153 for (iI=0; lI[iI]==0; iI++);
154 lI[iI]--;
155 double contrib = so(J.axis(k),iI);
156 tmp *= contrib;
157 }
158
159 r[I.bfn()][J.bfn()] += tmp;
160 }
161 }
162
163 delete ip;
164 delete jp;
165}
166
167// Compute the transformation matrices for general pure am
168// by summing contributions from the cartesian components
169// using the P (xyz) transformation matrix. This is done as a
170// matrix outer product, keeping only the unique terms.
171void
172ShellRotation::init_pure(int a, SymmetryOperation&so, const Ref<Integral>& ints)
173{
174 if (a < 2) {
175 init(a,so,ints);
176 return;
177 }
178
179 done();
180
181 am_=a;
182
183 SphericalTransformIter *ip = ints->new_spherical_transform_iter(am_);
184 SphericalTransformIter *jp = ints->new_spherical_transform_iter(am_, 1);
185 RedundantCartesianSubIter *kp = ints->new_redundant_cartesian_sub_iter(am_);
186
187 SphericalTransformIter& I = *ip;
188 SphericalTransformIter& J = *jp;
189 RedundantCartesianSubIter& K = *kp;
190 int lI[3];
191 int m, iI;
192
193 n_ = I.n();
194
195 r = new double*[n_];
196 for (m=0; m<n_; m++) {
197 r[m] = new double[n_];
198 memset(r[m],0,sizeof(double)*n_);
199 }
200
201 for (I.start(); I; I.next()) {
202 for (J.start(); J; J.next()) {
203 double coef = I.coef()*J.coef();
204 double tmp = 0.0;
205 for (K.start(J.a(), J.b(), J.c()); K; K.next()) {
206 //printf("T(%d,%d) += %6.4f", I.bfn(), J.bfn(), coef);
207 double tmp2 = coef;
208 for (m=0; m < 3; m++) {
209 lI[m] = I.l(m);
210 }
211
212 for (m=0; m < am_; m++) {
213 for (iI=0; lI[iI]==0; iI++);
214 lI[iI]--;
215 //tmp2 *= so(iI,K.axis(m));
216 tmp2 *= so(K.axis(m),iI);
217 //printf(" * so(%d,%d) [=%4.2f]",
218 // iI,K.axis(m),so(iI,K.axis(m)));
219 }
220 //printf(" = %8.6f\n", tmp2);
221 tmp += tmp2;
222 }
223 r[I.bfn()][J.bfn()] += tmp;
224 }
225 }
226
227 delete ip;
228 delete jp;
229 delete kp;
230
231}
232
233// returns the result of rot*this
234ShellRotation
235ShellRotation::operate(const ShellRotation& rot) const
236{
237 if (n_ != rot.n_) {
238 ExEnv::err0() << indent
239 << "ShellRotation::operate(): dimensions don't match" << endl
240 << indent << scprintf(" %d != %d\n",rot.n_,n_);
241 abort();
242 }
243
244 ShellRotation ret(n_);
245 ret.am_ = am_;
246
247 for (int i=0; i < n_; i++) {
248 for (int j=0; j < n_; j++) {
249 double t=0;
250 for (int k=0; k < n_; k++)
251 t += rot.r[i][k] * r[k][j];
252 ret.r[i][j] = t;
253 }
254 }
255
256 return ret;
257}
258
259ShellRotation
260ShellRotation::transform(const ShellRotation& rot) const
261{
262 int i,j,k;
263
264 if (rot.n_ != n_) {
265 ExEnv::err0() << indent
266 << "ShellRotation::transform(): dimensions don't match" << endl
267 << indent << scprintf("%d != %d\n",rot.n_,n_);
268 abort();
269 }
270
271 ShellRotation ret(n_), foo(n_);
272 ret.am_ = foo.am_ = am_;
273
274 // foo = r * d
275 for (i=0; i < n_; i++) {
276 for (j=0; j < n_; j++) {
277 double t=0;
278 for (k=0; k < n_; k++)
279 t += rot.r[i][k] * r[k][j];
280 foo.r[i][j] = t;
281 }
282 }
283
284 // ret = (r*d)*r~ = foo*r~
285 for (i=0; i < n_; i++) {
286 for (j=0; j < n_; j++) {
287 double t=0;
288 for (k=0; k < n_; k++)
289 t += foo.r[i][k]*rot.r[j][k];
290 ret.r[i][j]=t;
291 }
292 }
293
294 return ret;
295}
296
297double
298ShellRotation::trace() const {
299 double t=0;
300 for (int i=0; i < n_; i++)
301 t += r[i][i];
302 return t;
303}
304
305void
306ShellRotation::print() const
307{
308 for (int i=0; i < n_; i++) {
309 ExEnv::out0() << indent << scprintf("%5d ",i+1);
310 for (int j=0; j < n_; j++) {
311 ExEnv::out0() << scprintf(" %10.7f",r[i][j]);
312 }
313 ExEnv::out0() << endl;
314 }
315}
316
317/////////////////////////////////////////////////////////////////////////////
318
319// Local Variables:
320// mode: c++
321// c-file-style: "ETS"
322// End:
Note: See TracBrowser for help on using the repository browser.