[0b990d] | 1 | //
|
---|
| 2 | // cscphf.cc
|
---|
| 3 | //
|
---|
| 4 | // Copyright (C) 1996 Limit Point Systems, Inc.
|
---|
| 5 | //
|
---|
| 6 | // Author: Ida Nielsen <ida@kemi.aau.dk>
|
---|
| 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 | #include <math.h>
|
---|
| 29 | #include <stdlib.h>
|
---|
| 30 | #include <iostream>
|
---|
| 31 |
|
---|
| 32 | #include <util/misc/formio.h>
|
---|
| 33 | #include <util/keyval/keyval.h>
|
---|
| 34 | #include <math/scmat/matrix.h>
|
---|
| 35 | #include <chemistry/molecule/molecule.h>
|
---|
| 36 | #include <chemistry/qc/basis/basis.h>
|
---|
| 37 | #include <chemistry/qc/mbpt/mbpt.h>
|
---|
| 38 |
|
---|
| 39 | using namespace std;
|
---|
| 40 | using namespace sc;
|
---|
| 41 |
|
---|
| 42 | static void
|
---|
| 43 | compute_alpha(int dim, double **AP, double **alpha,
|
---|
| 44 | double **P, double *eigval, int nocc, int nvir);
|
---|
| 45 |
|
---|
| 46 | //////////////////////////////////////////////////////////////////////////
|
---|
| 47 | // Do a direct CPHF calculation in the AO basis; equations are formulated
|
---|
| 48 | // in terms of the occ-vir block P2aj of the second order correction (P2) to
|
---|
| 49 | // the MP2 density matrix (cf. Frisch et al., CPL 166, p. 275 (1990)).
|
---|
| 50 | //
|
---|
| 51 | // CPHF equations:
|
---|
| 52 | // (I-A)P2aj - B = 0 (B(a,j) = L(a,j)/(eigval[a]-eigval[j]))
|
---|
| 53 | // A is a matrix (dimension dimP*dimP),
|
---|
| 54 | // P2aj and B are vectors (dimension dimP)
|
---|
| 55 | // (P2aj is kept as a RefSCMatrix);
|
---|
| 56 | // Only closed-shell cases handled; no orbitals can be frozen
|
---|
| 57 | // On exit, P2aj has been computed.
|
---|
| 58 |
|
---|
| 59 | void
|
---|
| 60 | MBPT2::cs_cphf(double **scf_vector,
|
---|
| 61 | double *Laj, double *eigval, RefSCMatrix& P2aj)
|
---|
| 62 | {
|
---|
| 63 | double epsilon = cphf_epsilon_; //convergence criterion for P2aj
|
---|
| 64 |
|
---|
| 65 | int i, j, k, l, a;
|
---|
| 66 | int niter;
|
---|
| 67 | int dimP = nocc*nvir;
|
---|
| 68 |
|
---|
| 69 | Ref<SCMatrixKit> kit = basis()->matrixkit();
|
---|
| 70 |
|
---|
| 71 | RefSCDimension nbasis_dim = ao_dimension()->blocks()->subdim(0);
|
---|
| 72 | RefSCDimension nvir_dim(new SCDimension(nvir,1));
|
---|
| 73 | nvir_dim->blocks()->set_subdim(0, new SCDimension(nvir));
|
---|
| 74 | RefSCDimension nocc_dim(new SCDimension(nocc,1));
|
---|
| 75 | nocc_dim->blocks()->set_subdim(0, new SCDimension(nocc));
|
---|
| 76 |
|
---|
| 77 | RefSCMatrix Cv(nbasis_dim,nvir_dim,kit);
|
---|
| 78 | RefSCMatrix Co(nbasis_dim,nocc_dim,kit);
|
---|
| 79 | RefSCMatrix D_matrix(nbasis_dim,nbasis_dim,kit);
|
---|
| 80 | RefSCMatrix AP_matrix(nvir_dim,nocc_dim,kit); // holds A*P[i-1]
|
---|
| 81 | RefSCMatrix P_matrix(nvir_dim, nocc_dim, kit);
|
---|
| 82 | RefSymmSCMatrix G(nbasis_dim,kit);
|
---|
| 83 |
|
---|
| 84 |
|
---|
| 85 | double *projctn = new double[dimP];
|
---|
| 86 | double *P_sum_new = new double[dimP];
|
---|
| 87 | double *P_sum_old = new double[dimP];
|
---|
| 88 | double **AP_matrix_tot; // row is A*P[k]
|
---|
| 89 | double **P_tmp, **alpha_tmp, **AP_matrix_tmp;
|
---|
| 90 | double **P;
|
---|
| 91 | double *D;
|
---|
| 92 | double **alpha;
|
---|
| 93 | double *ptr1, *ptr2;
|
---|
| 94 | double *laj_ptr;
|
---|
| 95 | double dot_prod;
|
---|
| 96 | double coef;
|
---|
| 97 | double tmp_val1, tmp_val2;
|
---|
| 98 | double maxabs;
|
---|
| 99 |
|
---|
| 100 | // Debug print
|
---|
| 101 | if (debug_)
|
---|
| 102 | ExEnv::out0() << indent << "Entered cphf" << endl;
|
---|
| 103 | // End of debug print
|
---|
| 104 |
|
---|
| 105 | ////////////////////////////////////////////////////////////
|
---|
| 106 | // Allocate and initialize various variables
|
---|
| 107 | ////////////////////////////////////////////////////////////
|
---|
| 108 |
|
---|
| 109 | AP_matrix_tot = new double*[1];
|
---|
| 110 | AP_matrix_tot[0] = new double[dimP];
|
---|
| 111 |
|
---|
| 112 | alpha = new double*[1];
|
---|
| 113 | alpha[0] = new double[1];
|
---|
| 114 |
|
---|
| 115 | P = new double*[1];
|
---|
| 116 | P[0] = new double[dimP];
|
---|
| 117 |
|
---|
| 118 | D = new double[nbasis*nbasis];
|
---|
| 119 |
|
---|
| 120 | // NB: Elements in Laj are ordered as (j*nvir + a)
|
---|
| 121 | // since this ordering has been used with benefit in
|
---|
| 122 | // MP2 gradient program
|
---|
| 123 | ptr1 = P[0];
|
---|
| 124 | ptr2 = P_sum_old;
|
---|
| 125 | for (a=0; a<nvir; a++) {
|
---|
| 126 | laj_ptr = &Laj[a];
|
---|
| 127 | for (j=0; j<nocc; j++) {
|
---|
| 128 | *ptr1++ = *laj_ptr/(eigval[a+nocc]-eigval[j]);
|
---|
| 129 | *ptr2++ = 0.0;
|
---|
| 130 | laj_ptr += nvir;
|
---|
| 131 | }
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | for (i=0; i<nbasis; i++) {
|
---|
| 135 | for (j=0; j<noso; j++) {
|
---|
| 136 | if (j<nocc) Co(i,j) = scf_vector[i][j];
|
---|
| 137 | else Cv(i,j-nocc) = scf_vector[i][j];
|
---|
| 138 | }
|
---|
| 139 | }
|
---|
| 140 |
|
---|
| 141 | /////////////////////////////////////////////////////////////////
|
---|
| 142 | // Solve the CPHF equations (iteratively, with DIIS like method)
|
---|
| 143 | /////////////////////////////////////////////////////////////////
|
---|
| 144 |
|
---|
| 145 | i = 0;
|
---|
| 146 | niter = 0;
|
---|
| 147 |
|
---|
| 148 | const int maxiter = 30;
|
---|
| 149 | const int warniter = 1;
|
---|
| 150 | while (niter < maxiter) { // Allow max maxiter iterations
|
---|
| 151 |
|
---|
| 152 | niter++;
|
---|
| 153 | i++;
|
---|
| 154 | if (debug_)
|
---|
| 155 | ExEnv::out0() << indent << scprintf("niter: %i\n", niter);
|
---|
| 156 |
|
---|
| 157 | // First expand AP_matrix_tot, alpha and P with an extra row
|
---|
| 158 |
|
---|
| 159 | AP_matrix_tmp = new double *[i+1];
|
---|
| 160 | if (!AP_matrix_tmp) {
|
---|
| 161 | ExEnv::errn() << "Could not allocate AP_matrix_tmp" << endl;
|
---|
| 162 | abort();
|
---|
| 163 | }
|
---|
| 164 |
|
---|
| 165 | alpha_tmp = new double *[i+1];
|
---|
| 166 |
|
---|
| 167 | if (!alpha_tmp) {
|
---|
| 168 | ExEnv::errn() << "Could not allocate alpha_tmp" << endl;
|
---|
| 169 | abort();
|
---|
| 170 | }
|
---|
| 171 |
|
---|
| 172 | P_tmp = new double *[i+1];
|
---|
| 173 |
|
---|
| 174 | if (!P_tmp) {
|
---|
| 175 | ExEnv::errn() << "Could not allocate P_tmp" << endl;
|
---|
| 176 | abort();
|
---|
| 177 | }
|
---|
| 178 |
|
---|
| 179 | for (j=0; j<i; j++) {
|
---|
| 180 | AP_matrix_tmp[j] = AP_matrix_tot[j];
|
---|
| 181 | alpha_tmp[j] = alpha[j];
|
---|
| 182 | P_tmp[j] = P[j];
|
---|
| 183 | }
|
---|
| 184 |
|
---|
| 185 | AP_matrix_tmp[i] = new double[dimP];
|
---|
| 186 | if (!AP_matrix_tmp[i]) {
|
---|
| 187 | ExEnv::errn() << scprintf("Could not allocate AP_matrix_tmp[i], i = %i",i) << endl;
|
---|
| 188 | abort();
|
---|
| 189 | }
|
---|
| 190 | delete[] AP_matrix_tot;
|
---|
| 191 | AP_matrix_tot = AP_matrix_tmp;
|
---|
| 192 |
|
---|
| 193 | alpha_tmp[i] = new double[1];
|
---|
| 194 | if (!alpha_tmp[i]) {
|
---|
| 195 | ExEnv::errn() << scprintf("Could not allocate alpha_tmp[i], i = %i",i) << endl;
|
---|
| 196 | abort();
|
---|
| 197 | }
|
---|
| 198 | delete[] alpha;
|
---|
| 199 | alpha = alpha_tmp;
|
---|
| 200 |
|
---|
| 201 | P_tmp[i] = new double[dimP];
|
---|
| 202 | if (!P_tmp[i]) {
|
---|
| 203 | ExEnv::errn() << scprintf("Could not allocate P_tmp[i], i = %i",i) << endl;
|
---|
| 204 | abort();
|
---|
| 205 | }
|
---|
| 206 | delete[] P;
|
---|
| 207 | P = P_tmp;
|
---|
| 208 |
|
---|
| 209 | // Initialize P[i]
|
---|
| 210 | for (j=0; j<dimP; j++) P[i][j] = 0.0;
|
---|
| 211 |
|
---|
| 212 | // Compute A*P[i-1] (called AP_matrix) which is required to get P[i]
|
---|
| 213 | // A*P[i-1] is treated as a matrix to facilitate its computation
|
---|
| 214 | // A*P[i-1] is put into row i-1 of AP_matrix_tot
|
---|
| 215 |
|
---|
| 216 | ptr1 = P[i-1];
|
---|
| 217 | for (j=0; j<nvir; j++) {
|
---|
| 218 | for (k=0; k<nocc; k++) {
|
---|
| 219 | P_matrix->set_element(j,k,*ptr1++); // Convert P[i-1] to RefSCMatrix
|
---|
| 220 | }
|
---|
| 221 | }
|
---|
| 222 | D_matrix = Cv*P_matrix*Co.t();
|
---|
| 223 | #if 0
|
---|
| 224 | D_matrix = D_matrix + D_matrix.t();
|
---|
| 225 | D_matrix->convert(D); // Convert D_matrix to double* D
|
---|
| 226 | make_cs_gmat(G, D);
|
---|
| 227 | #else
|
---|
| 228 | RefSymmSCMatrix sD(D_matrix.rowdim(), kit);
|
---|
| 229 | sD.assign(0.0);
|
---|
| 230 | sD.accumulate_symmetric_sum(D_matrix);
|
---|
| 231 | make_cs_gmat_new(G, sD);
|
---|
| 232 | #endif
|
---|
| 233 | AP_matrix = 2*Cv.t()*G*Co;
|
---|
| 234 |
|
---|
| 235 | ptr1 = AP_matrix_tot[i-1];
|
---|
| 236 | for (j=0; j<nvir; j++) {
|
---|
| 237 | for (k=0; k<nocc; k++) {
|
---|
| 238 | tmp_val1 = AP_matrix->get_element(j,k)/(eigval[k]-eigval[j+nocc]);
|
---|
| 239 | AP_matrix->set_element(j,k,tmp_val1);
|
---|
| 240 | *ptr1++ = tmp_val1;
|
---|
| 241 | }
|
---|
| 242 | }
|
---|
| 243 | // End of AP_matrix computation
|
---|
| 244 |
|
---|
| 245 | // Compute coefficients alpha[0],...,alpha[i-1]
|
---|
| 246 | compute_alpha(i, AP_matrix_tot, alpha, P, eigval, nocc, nvir);
|
---|
| 247 |
|
---|
| 248 | // Compute the vector P_sum_new = alpha[0]P[0]+...+alpha[i-1]P[i-1]
|
---|
| 249 | ptr1 = P_sum_new;
|
---|
| 250 | for (j=0; j<dimP; j++) *ptr1++ = 0.0;
|
---|
| 251 | for (j=0; j<i; j++) {
|
---|
| 252 | tmp_val1 = alpha[j][0];
|
---|
| 253 | ptr1 = P_sum_new;
|
---|
| 254 | ptr2 = P[j];
|
---|
| 255 | for (k=0; k<dimP; k++) {
|
---|
| 256 | *ptr1++ += tmp_val1 * *ptr2++;
|
---|
| 257 | }
|
---|
| 258 | }
|
---|
| 259 |
|
---|
| 260 |
|
---|
| 261 | /////////////////////////////////////////////////////////////
|
---|
| 262 | // Test for convergence
|
---|
| 263 | // (based on RMS(P2aj_new - P2aj_old)
|
---|
| 264 | // and max abs. val. of element)
|
---|
| 265 | /////////////////////////////////////////////////////////////
|
---|
| 266 | ptr1 = P_sum_new;
|
---|
| 267 | ptr2 = P_sum_old;
|
---|
| 268 | tmp_val1 = 0.0;
|
---|
| 269 | maxabs = 0.0;
|
---|
| 270 | for (j=0; j<dimP; j++) {
|
---|
| 271 | tmp_val2 = *ptr1++ - *ptr2++;
|
---|
| 272 | tmp_val1 += tmp_val2*tmp_val2;
|
---|
| 273 | if (fabs(tmp_val2) > maxabs) maxabs = fabs(tmp_val2);
|
---|
| 274 | }
|
---|
| 275 | if (debug_) {
|
---|
| 276 | ExEnv::out0() << indent << scprintf("RMS(P2aj_new-P2aj_old) = %12.10lf",
|
---|
| 277 | sqrt((tmp_val1)/dimP))
|
---|
| 278 | << endl;
|
---|
| 279 | ExEnv::out0() << indent
|
---|
| 280 | << scprintf("max. abs. element of (P2aj_new-P2aj_old) = %12.10lf",
|
---|
| 281 | maxabs)
|
---|
| 282 | << endl;
|
---|
| 283 | }
|
---|
| 284 | if (sqrt(tmp_val1)/dimP < epsilon && maxabs < epsilon) break; // Converged
|
---|
| 285 |
|
---|
| 286 | // Put P_sum_new into P_sum old
|
---|
| 287 | ptr1 = P_sum_new;
|
---|
| 288 | ptr2 = P_sum_old;
|
---|
| 289 | for (j=0; j<dimP; j++) {
|
---|
| 290 | *ptr2++ = *ptr1++;
|
---|
| 291 | }
|
---|
| 292 |
|
---|
| 293 | // Compute projection of A*P[i-1] on P[0],...,P[i-1]
|
---|
| 294 |
|
---|
| 295 | ptr1 = projctn;
|
---|
| 296 | for (j=0; j<dimP; j++) *ptr1++ = 0.0;
|
---|
| 297 | for (j=0; j<i; j++) {
|
---|
| 298 | dot_prod = 0.0;
|
---|
| 299 | ptr1 = P[j];
|
---|
| 300 | for (k=0; k<dimP; k++) {
|
---|
| 301 | tmp_val1 = *ptr1++;
|
---|
| 302 | dot_prod += tmp_val1*tmp_val1; // Compute dot product <P[j]|P[j]>
|
---|
| 303 | }
|
---|
| 304 | ptr1 = P[j];
|
---|
| 305 | coef = 0.0;
|
---|
| 306 | for (k=0; k<nvir; k++) {
|
---|
| 307 | for (l=0; l<nocc; l++) {
|
---|
| 308 | coef += *ptr1++ * AP_matrix->get_element(k,l);
|
---|
| 309 | }
|
---|
| 310 | }
|
---|
| 311 | coef /= dot_prod;
|
---|
| 312 | ptr1 = P[j];
|
---|
| 313 | ptr2 = projctn;
|
---|
| 314 | for (k=0; k<dimP; k++) {
|
---|
| 315 | *ptr2++ += coef * *ptr1++;
|
---|
| 316 | }
|
---|
| 317 | }
|
---|
| 318 |
|
---|
| 319 | // Compute P[i] as A*P[i-1] - projctn
|
---|
| 320 |
|
---|
| 321 | ptr1 = P[i];
|
---|
| 322 | ptr2 = projctn;
|
---|
| 323 | for (j=0; j<nvir; j++) {
|
---|
| 324 | for (k=0; k<nocc; k++) {
|
---|
| 325 | *ptr1++ = AP_matrix->get_element(j,k) - *ptr2++;
|
---|
| 326 | }
|
---|
| 327 | }
|
---|
| 328 |
|
---|
| 329 | /////////////////////////////////////////////
|
---|
| 330 | // Test for convergence (based on norm(P[i])
|
---|
| 331 | /////////////////////////////////////////////
|
---|
| 332 | tmp_val1 = 0.0;
|
---|
| 333 | for (l=0; l<dimP; l++) {
|
---|
| 334 | tmp_val1 += P[niter][l]*P[niter][l];
|
---|
| 335 | }
|
---|
| 336 | tmp_val1 = sqrt(tmp_val1/dimP);
|
---|
| 337 | if (debug_)
|
---|
| 338 | ExEnv::out0() << indent
|
---|
| 339 | << scprintf("norm(P[niter]) = %12.10lf", tmp_val1) << endl;
|
---|
| 340 | if (tmp_val1 < epsilon) { // Converged (if norm of new vector is zero)
|
---|
| 341 | ExEnv::out0() << indent
|
---|
| 342 | << scprintf("CPHF: iter = %2d rms(P) = %12.10f eps = %12.10f",
|
---|
| 343 | niter, tmp_val1, epsilon)
|
---|
| 344 | << endl << endl;
|
---|
| 345 | break;
|
---|
| 346 | }
|
---|
| 347 |
|
---|
| 348 | if (niter >= warniter) {
|
---|
| 349 | ExEnv::out0() << indent
|
---|
| 350 | << scprintf("CPHF: iter = %2d rms(P) = %12.10f eps = %12.10f",
|
---|
| 351 | niter, tmp_val1, epsilon)
|
---|
| 352 | << endl;
|
---|
| 353 | }
|
---|
| 354 |
|
---|
| 355 | }
|
---|
| 356 |
|
---|
| 357 | ///////////////////////////////////////////////////////////////
|
---|
| 358 | // If CPHF equations did not converge, exit with error message
|
---|
| 359 | ///////////////////////////////////////////////////////////////
|
---|
| 360 | if (niter == maxiter) {
|
---|
| 361 | ExEnv::out0() << indent
|
---|
| 362 | << "CPHF equations did not converge in " << maxiter << " iterations"
|
---|
| 363 | << endl;
|
---|
| 364 | abort();
|
---|
| 365 | }
|
---|
| 366 |
|
---|
| 367 | /////////////////////////////////////////////////////
|
---|
| 368 | // The converged vector is in P_sum_new;
|
---|
| 369 | // Put elements into P2aj
|
---|
| 370 | // NB: Elements in P2aj are ordered as (a*nocc + j);
|
---|
| 371 | /////////////////////////////////////////////////////
|
---|
| 372 | ptr1 = P_sum_new;
|
---|
| 373 | for (i=0; i<nvir; i++) {
|
---|
| 374 | for (j=0; j<nocc; j++) {
|
---|
| 375 | P2aj->set_element(i,j,*ptr1++);
|
---|
| 376 | }
|
---|
| 377 | }
|
---|
| 378 |
|
---|
| 379 | // Debug print
|
---|
| 380 | if (debug_)
|
---|
| 381 | ExEnv::out0() << indent << "Exiting cphf" << endl;
|
---|
| 382 | // End of debug print
|
---|
| 383 |
|
---|
| 384 | // Deallocate various arrays
|
---|
| 385 | delete[] D;
|
---|
| 386 |
|
---|
| 387 | for (i=0; i<niter+1; i++) {
|
---|
| 388 | delete[] AP_matrix_tot[i];
|
---|
| 389 | delete[] alpha[i];
|
---|
| 390 | delete[] P[i];
|
---|
| 391 | }
|
---|
| 392 | delete[] AP_matrix_tot;
|
---|
| 393 | delete[] alpha;
|
---|
| 394 | delete[] P;
|
---|
| 395 | delete[] projctn;
|
---|
| 396 | delete[] P_sum_new;
|
---|
| 397 | delete[] P_sum_old;
|
---|
| 398 | }
|
---|
| 399 |
|
---|
| 400 |
|
---|
| 401 | static void
|
---|
| 402 | compute_alpha(int dim, double **AP, double **alpha,
|
---|
| 403 | double **P, double *eigval, int nocc, int nvir)
|
---|
| 404 | {
|
---|
| 405 | //////////////////////////////////////////////////////
|
---|
| 406 | // Solve the linear system of equations C*X = B
|
---|
| 407 | // where C is RefSCMatrix and X and B are RefSCVector
|
---|
| 408 | // Put result (X) into array alpha
|
---|
| 409 | //////////////////////////////////////////////////////
|
---|
| 410 | int i, j, k;
|
---|
| 411 | int vect_dim = nocc*nvir;
|
---|
| 412 |
|
---|
| 413 | double tmp1, tmp2;
|
---|
| 414 | double *ptr1, *ptr2;
|
---|
| 415 | double *norm = new double[dim]; // contains norms of vectors P[i], i=0,dim
|
---|
| 416 |
|
---|
| 417 | Ref<SCMatrixKit> kit = SCMatrixKit::default_matrixkit();
|
---|
| 418 | RefSCDimension C_dim(new SCDimension(dim));
|
---|
| 419 |
|
---|
| 420 | RefSCMatrix C(C_dim,C_dim,kit);
|
---|
| 421 | RefSCVector B(C_dim,kit);
|
---|
| 422 | RefSCVector X(C_dim,kit);
|
---|
| 423 |
|
---|
| 424 | // Compute norms of vectors P[i] and put into norm
|
---|
| 425 | for (i=0; i<dim; i++) norm[i] = 0.0;
|
---|
| 426 | ptr1 = norm;
|
---|
| 427 | for (i=0; i<dim; i++) {
|
---|
| 428 | ptr2 = P[i];
|
---|
| 429 | for (j=0; j<vect_dim; j++) {
|
---|
| 430 | *ptr1 += *ptr2 * *ptr2;
|
---|
| 431 | ptr2++;
|
---|
| 432 | }
|
---|
| 433 | ptr1++;
|
---|
| 434 | }
|
---|
| 435 | for (i=0; i<dim; i++) norm[i] = sqrt(norm[i]);
|
---|
| 436 |
|
---|
| 437 | // Construct matrix C
|
---|
| 438 | for (i=0; i<dim; i++) {
|
---|
| 439 | for (j=0; j<dim; j++) {
|
---|
| 440 | tmp1 = 0.0;
|
---|
| 441 | ptr1 = P[i];
|
---|
| 442 | ptr2 = AP[j];
|
---|
| 443 | for (k=0; k<vect_dim; k++) {
|
---|
| 444 | tmp1 -= *ptr1++ * *ptr2++;
|
---|
| 445 | }
|
---|
| 446 | if (i == j) {
|
---|
| 447 | ptr1 = P[i];
|
---|
| 448 | for (k=0; k<vect_dim; k++) {
|
---|
| 449 | tmp2 = *ptr1++;
|
---|
| 450 | tmp1 += tmp2*tmp2;
|
---|
| 451 | }
|
---|
| 452 | }
|
---|
| 453 | C->set_element(i,j,tmp1/(norm[i]*norm[j]));
|
---|
| 454 | }
|
---|
| 455 | }
|
---|
| 456 |
|
---|
| 457 | // Construct vector B
|
---|
| 458 | B->set_element(0,norm[0]);
|
---|
| 459 | for (i=1; i<dim; i++) B->set_element(i,0.0);
|
---|
| 460 |
|
---|
| 461 | // Compute X = inv(C)*B
|
---|
| 462 | X = C.i()*B;
|
---|
| 463 |
|
---|
| 464 | // Put elements of X into alpha
|
---|
| 465 | for (i=0; i<dim; i++) {
|
---|
| 466 | alpha[i][0] = X->get_element(i)/norm[i];
|
---|
| 467 | }
|
---|
| 468 |
|
---|
| 469 | delete[] norm;
|
---|
| 470 | }
|
---|
| 471 |
|
---|
| 472 | ////////////////////////////////////////////////////////////////////////////
|
---|
| 473 |
|
---|
| 474 | // Local Variables:
|
---|
| 475 | // mode: c++
|
---|
| 476 | // c-file-style: "CLJ-CONDENSED"
|
---|
| 477 | // End:
|
---|