1 //
2 // Solvmat.cpp
3 // pbsam_xcode
4 //
5 // Created by David Brookes on 6/20/16.
6 // Copyright © 2016 David Brookes. All rights reserved.
7 //
8
9 #include "Solvmat.h"
10
11
12 // computes Y = alpha*A*X + beta*Y
13 //applyMMat(IMat, &(fin), &(fout), 1.0, 0.0, p2, D, p2);
applyMMat(const double * A,const double * X,double * Y,const double alpha,const double beta,int ma,int nc,int na)14 void applyMMat(const double * A, const double * X, double * Y,
15 const double alpha, const double beta, int ma, int nc, int na)
16
17 {
18 const int M = ma;
19 const int N = nc;
20 const int K = na;
21 const int lda = M;
22 const int ldb = K;
23 const int ldc = M;
24
25 #ifdef __ACML
26 char transA = 'N';
27 char transB = 'N';
28 dgemm(transA, transB, M, N, &K, alpha, const_cast<double*>(A), lda,
29 const_cast<double*>(X), ldb, beta, Y, ldc);
30 #endif // ifACML
31
32 #ifdef __MKL
33 char transA = 'N';
34 char transB = 'N';
35 dgemm(&transA, &transB, &M, &N, &K, &alpha, const_cast<double*>(A), &lda,
36 const_cast<double*>(X), &ldb, &beta, Y, &ldc);
37 #endif // ifMKL
38
39 #if defined(__MACOS) || defined(__XCODE)
40 CBLAS_ORDER Order = CblasColMajor;
41 CBLAS_TRANSPOSE TransA = CblasNoTrans;
42 CBLAS_TRANSPOSE TransB = CblasNoTrans;
43 cblas_dgemm(Order, TransA, TransB, M, N, K, alpha, A, lda,
44 X, ldb, beta, Y, ldc);
45 #endif
46
47 return;
48 }
49
50
make_uniform_sph_grid(int m_grid,double r)51 vector<Pt> make_uniform_sph_grid(int m_grid, double r)
52 {
53 vector<Pt> grid (m_grid);
54 Pt gp;
55 grid[0].set_r(r);
56 grid[0].set_theta(0.0);
57 grid[0].set_phi(0.0);
58 double hk;
59 for (int k = 1; k < m_grid+1; k++)
60 {
61 grid[k-1].set_r(r);
62 hk = -1.0 + ((2.0 * ( (double)k-1.0)) / ( (double) m_grid-1.0));
63 grid[k-1].set_theta(acos(hk));
64
65
66 if ( k == 1 || k == m_grid) grid[k-1].set_phi(0);
67 else
68 grid[k-1].set_phi(grid[k-2].phi() +
69 (3.6/sqrt(m_grid*(1.0-(hk*hk)))));
70
71 while(grid[k-1].phi() > 2*M_PI) grid[k-1].set_phi(grid[k-1].phi()-2*M_PI);
72 while(grid[k-1].phi() <-2*M_PI) grid[k-1].set_phi(grid[k-1].phi()+2*M_PI);
73 }
74 return grid;
75 }
76
calc_n_grid_pts(int p,double r)77 int calc_n_grid_pts(int p, double r)
78 {
79 // not about how these were chosen, taken directly from old stuff
80 int npPerOsc(5), nmin(1000), nmax(72000), nFinal;
81 int npts = (int) npPerOsc * 0.5 * p;
82 if (npts < nmin) npts = nmin;
83 if (npts > nmax) npts = nmax;
84
85 int minPts = 200;
86 double cutoff(1.5), maxrad(10.0);
87 const double gradient = npts / ((maxrad-cutoff)*(maxrad-cutoff));
88 if (r < cutoff ) nFinal = minPts;
89 else
90 {
91 nFinal = int ( minPts + gradient * (r-cutoff) * (r-cutoff) );
92 if (nFinal > npts) nFinal = npts;
93 }
94 return nFinal;
95 }
96
compute_coeffs()97 void ExpansionConstants::compute_coeffs()
98 {
99 int ct = 0;
100 // constants
101 for(int l=0; l < p_; l++)
102 {
103 set_const1_l( l, (2.0*l+1.0) / (4.0*M_PI));
104 set_const2_l( l, 1.0/ (double)(2*l+1));
105 for(int m=0; m <= l; m++)
106 {
107 imatLoc_[ct] = vector<int> {l, m};
108 ct++;
109 }
110 }
111 }
112
inner_prod(MyMatrix<cmplx> & M1,MyMatrix<cmplx> & M2,int p)113 double inner_prod( MyMatrix<cmplx> & M1, MyMatrix<cmplx> & M2, int p )
114 {
115 double sum = 0;
116
117 for (int n = 0; n < p; n++)
118 for (int m = -n; m <= n; m++)
119 {
120 sum += (M1(n, m+p).real() * M2(n, m+p).real()
121 + M1(n, m+p).imag() * M2(n, m+p).imag());
122 }
123 return sum;
124 }
125
126
ExpansionConstants(int p)127 ExpansionConstants::ExpansionConstants(int p)
128 : p_(p), expansionConst1_(p), expansionConst2_(p), imatLoc_(p*p)
129 {
130 compute_coeffs();
131 }
132
133
ComplexMoleculeMatrix(int I,int ns,int p)134 ComplexMoleculeMatrix::ComplexMoleculeMatrix(int I, int ns, int p)
135 :p_(p), mat_(ns, MyMatrix<cmplx> (p, 2*p+1)), I_(I)
136 {
137 }
138
reset_mat(int k)139 void ComplexMoleculeMatrix::reset_mat(int k)
140 {
141 for (int i = 0; i < mat_[k].get_nrows(); i++)
142 {
143 for (int j = 0; j < mat_[k].get_ncols(); j++)
144 {
145 mat_[k].set_val(i, j, cmplx(0, 0));
146 }
147 }
148 }
149
NumericalMatrix(int I,int ns,int p)150 NumericalMatrix::NumericalMatrix(int I, int ns, int p)
151 :p_(p), mat_(ns), mat_cmplx_(ns, MyMatrix<cmplx> (p, 2*p+1)), I_(I)
152 {
153 }
154
reset_mat(int k)155 void NumericalMatrix::reset_mat(int k)
156 {
157 for (int i = 0; i < mat_cmplx_[k].get_nrows(); i++)
158 {
159 for (int j = 0; j < mat_cmplx_[k].get_ncols(); j++)
160 {
161 mat_cmplx_[k].set_val(i, j, cmplx(0, 0));
162 }
163 }
164
165 }
166
167
EMatrix(int I,int ns,int p)168 EMatrix::EMatrix(int I, int ns, int p)
169 :ComplexMoleculeMatrix(I, ns, p)
170 {
171 }
172
calc_vals(shared_ptr<BaseMolecule> mol,shared_ptr<SHCalc> _shcalc,double eps_in)173 void EMatrix::calc_vals(shared_ptr<BaseMolecule> mol,
174 shared_ptr<SHCalc> _shcalc,
175 double eps_in)
176 {
177 cmplx val;
178 Pt cen;
179 double r_alpha, a_k, q_alpha;
180 for (int k=0; k< mol->get_ns(); k++)
181 {
182 vector<int> allin = mol->get_ch_allin_k(k);
183 for (int alpha=0; alpha < allin.size(); alpha++)
184 {
185 cen = (mol->get_posj_realspace(allin[alpha]) - mol->get_centerk(k));
186 _shcalc->calc_sh(cen.theta(), cen.phi());
187 for (int n = 0; n < p_; n++)
188 {
189 for (int m = -n; m < n+1; m++)
190 {
191 q_alpha = mol->get_qj(allin[alpha]);
192 r_alpha = cen.r();
193 a_k = mol->get_ak(k);
194
195 val = _shcalc->get_result(n, m);
196 val *= q_alpha / eps_in;
197 val *= pow(r_alpha / a_k, n);
198 val += get_mat_knm(k, n, m);
199 set_mat_knm(k, n, m, val);
200 }
201 }
202 }
203 }
204 }
205
LEMatrix(int I,int ns,int p)206 LEMatrix::LEMatrix(int I, int ns, int p)
207 :ComplexMoleculeMatrix(I, ns, p)
208 {
209 }
210
calc_vals(shared_ptr<BaseMolecule> mol,shared_ptr<SHCalc> _shcalc,double eps_in)211 void LEMatrix::calc_vals(shared_ptr<BaseMolecule> mol,
212 shared_ptr<SHCalc> _shcalc,
213 double eps_in)
214 {
215 cmplx val;
216 Pt cen;
217
218 double r_alpha, a_k, q_alpha;
219 for (int k=0; k< mol->get_ns(); k++)
220 {
221 vector<int> allout = mol->get_ch_allout_k(k);
222 for (int alpha=0; alpha < allout.size(); alpha++)
223 {
224 cen = mol->get_posj_realspace(allout[alpha]) - mol->get_centerk(k);
225 _shcalc->calc_sh(cen.theta(), cen.phi());
226 for (int n = 0; n < p_; n++)
227 {
228 for (int m = -n; m < n+1; m++)
229 {
230 q_alpha = mol->get_qj(allout[alpha]);
231 r_alpha = cen.r();
232 a_k = mol->get_ak(k);
233
234 val = _shcalc->get_result(n, m);
235 val *= q_alpha / eps_in;
236 val *= 1 / r_alpha;
237 val *= pow(a_k / r_alpha, n);
238 val += get_mat_knm(k, n, m);
239 set_mat_knm(k, n, m, val);
240 }
241 }
242 }
243 }
244 }
245
246
IEMatrix(int I,shared_ptr<BaseMolecule> _mol,shared_ptr<SHCalc> _shcalc,int p,shared_ptr<ExpansionConstants> _expconst,bool calc_npts,int npts,bool set_mol)247 IEMatrix::IEMatrix(int I, shared_ptr<BaseMolecule> _mol,
248 shared_ptr<SHCalc> _shcalc, int p,
249 shared_ptr<ExpansionConstants> _expconst,
250 bool calc_npts, int npts, bool set_mol)
251 : p_(p), I_(I),
252 IE_orig_(_mol->get_ns(), vector<double> (p*p*p*p)),
253 _expConst_(_expconst), calc_pts_(calc_npts), set_mol_(set_mol),
254 gridPts_(npts), gridPtLocs_(_mol->get_ns()),
255 grid_exp_(_mol->get_ns()),grid_bur_(_mol->get_ns())
256 {
257 compute_grid_pts(_mol);
258 }
259
IEMatrix(shared_ptr<IEMatrix> imat_in)260 IEMatrix::IEMatrix(shared_ptr<IEMatrix> imat_in)
261 : p_(imat_in->p_), I_(imat_in->I_),
262 IE_orig_(imat_in->IE_orig_),
263 _expConst_(imat_in->_expConst_),
264 calc_pts_(imat_in->calc_pts_), set_mol_(imat_in->set_mol_),
265 gridPts_(imat_in->gridPts_), gridPtLocs_(imat_in->gridPtLocs_),
266 grid_exp_(imat_in->grid_exp_),grid_bur_(imat_in->grid_bur_)
267 { }
268
init_from_file(string imatfile,int k)269 void IEMatrix::init_from_file(string imatfile, int k )
270 {
271 IMatFile imat(imatfile, p_);
272 set_IE_k(k, imat.get_mat());
273 }
274
init_from_other(shared_ptr<IEMatrix> other)275 void IEMatrix::init_from_other(shared_ptr<IEMatrix> other)
276 {
277 for (int k=0; k < other->get_k(); k++)
278 set_IE_k(k, other->get_IE_k_org(k));
279 }
280
281
get_IE_k(int k)282 MyMatrix<double> IEMatrix::get_IE_k(int k)
283 {
284 MyMatrix<double> IMat(p_*p_, p_*p_);
285
286 int ind(0);
287 for (int l = 0; l < p_; l++) // rows in old matrix
288 for (int s = 0; s < 2*l+1; s++) //columns in old matrix
289 for (int n = 0; n < p_; n++) // rows in new matrix
290 for (int m = 0; m < 2*n+1; m++) // columns in new matrix
291 {
292 IMat(n*n+m, l*l+s) = get_IE_k_ind(k, ind);
293 ind++;
294 }
295
296 return IMat;
297 }
298
write_mat_k_reg(string imatFname,int k)299 void IEMatrix::write_mat_k_reg(string imatFname, int k)
300 {
301 ofstream fout;
302 fout.open(imatFname, ofstream::binary); //for writing
303 if (!fout)
304 {
305 cout << "file "<< imatFname << " could not be opened."<< endl;
306 exit(1);
307 }
308 fout << p_ << endl; // pole order
309 for (int i = 0; i< p_*p_*p_*p_; i++)
310 {
311 fout << IE_orig_[k][i] << " "; //mat
312 if ( (i%(p_*p_-1)) == 0 && (i > 0)) fout << endl;
313 }
314
315 fout.close();
316 }
317
write_mat_k(string imatFname,int k)318 void IEMatrix::write_mat_k(string imatFname, int k)
319 {
320 ofstream fout;
321 fout.open(imatFname, ofstream::binary); //for writing
322 if (!fout)
323 {
324 cout << "file "<< imatFname << " could not be opened."<< endl;
325 exit(1);
326 }
327 int length = p_*p_*p_*p_;
328 fout.write( reinterpret_cast<char const *> (&p_), sizeof(p_)); // pole order
329 fout.write( reinterpret_cast<char const *>(&IE_orig_[k][0]),
330 length*sizeof(double) ); //mat
331
332 fout.close();
333 }
334
compute_grid_pts(shared_ptr<BaseMolecule> _mol)335 void IEMatrix::compute_grid_pts(shared_ptr<BaseMolecule> _mol)
336 {
337 Pt real_grid;
338 vector<Pt> grid_loc;
339 for (int k = 0; k < _mol->get_ns(); k++)
340 {
341 vector<int> grid_exp, grid_bur;
342 vector<int> neighs = _mol->get_neighj(k);
343 if (calc_pts_) gridPts_ = calc_n_grid_pts(p_, _mol->get_ak(k));
344 grid_loc = make_uniform_sph_grid(gridPts_, _mol->get_ak(k));
345 if (set_mol_) _mol->set_gridj(k, grid_loc);
346 else gridPtLocs_[k] = grid_loc;
347
348 // Loop through points to find the exposed ones
349 for (int g = 0; g < gridPts_; g++)
350 {
351 bool buried = false;
352 // loop through other spheres in this BaseMolecule to find exposed gd pts:
353 for (int k2 = 0; k2 < neighs.size(); k2++)
354 {
355 real_grid = grid_loc[g] + _mol->get_centerk(k);
356 // check if sphere is overlapping another
357 if (real_grid.dist(_mol->get_centerk(neighs[k2]))
358 < _mol->get_ak(neighs[k2]))
359 {
360 grid_bur.push_back(g);
361 buried = true;
362 break;
363 }
364 }
365 if (!buried) grid_exp.push_back(g);
366 }
367
368 if (set_mol_)
369 {
370 _mol->set_gridexpj(k, grid_exp);
371 _mol->set_gridburj(k, grid_bur);
372 } else
373 {
374 grid_bur_[k] = grid_bur;
375 grid_exp_[k] = grid_exp;
376 }
377
378 grid_exp.clear(); grid_bur.clear();
379 }
380 }
381
382 vector<MatOfMats<cmplx>::type >
compute_integral(shared_ptr<BaseMolecule> _mol,shared_ptr<SHCalc> sh_calc,int k)383 IEMatrix::compute_integral(shared_ptr<BaseMolecule> _mol,
384 shared_ptr<SHCalc> sh_calc,
385 int k)
386 {
387 int min, grid_tot;
388 bool bur;
389 vector<MatOfMats<cmplx>::type > Ys(2,
390 MatOfMats<cmplx>::type(p_, p_,
391 MyMatrix<cmplx>
392 (p_, p_)));
393 if (set_mol_)
394 {
395 gridPtLocs_[k] = _mol->get_gridj(k);
396 grid_bur_[k] = _mol->get_gdpt_burj(k);
397 grid_exp_[k] = _mol->get_gdpt_expj(k);
398 }
399
400 grid_tot = (int) (grid_bur_[k].size() + grid_exp_[k].size());
401
402 if ( grid_bur_[k].size() < grid_exp_[k].size() )
403 {
404 bur = true;
405 min = (int)grid_bur_[k].size();
406 }
407 else
408 {
409 bur = false;
410 min = (int)grid_exp_[k].size();
411 }
412 for(int h=0; h<min; h++)
413 {
414 double w=0;
415 int ind = (bur) ? grid_bur_[k][h] : grid_exp_[k][h];
416 Pt gdpt = gridPtLocs_[k][ind];
417 // convert the position relative to the center to spherical coordinates.
418 sh_calc->calc_sh(gdpt.theta(), gdpt.phi());
419
420 // collect sums for (n,m) rows x (l,s) column
421 for(int l = 0; l < p_; l++)
422 for(int s = 0; s <= l; s++)
423 {
424 cmplx Yls, Ynm;
425 if(s==0) Yls = complex<double> (sh_calc->get_result(l,0));
426 else Yls = complex<double> (sh_calc->get_result(l,s));
427
428 for(int n=0; n<=l; n++)
429 for(int m=0; m<=n; m++)
430 {
431 if( n==l && m > s) break;
432 if(m==0) Ynm = complex<double> (sh_calc->get_result(n,0));
433 else Ynm = complex<double> (sh_calc->get_result(n,m));
434
435 // integrate using the appropriate integration rules
436 if(m==0 && s==0 && (n+l)%2==0) //simpson's rule
437 {
438 if(h > 0 && h < grid_tot)
439 {
440 if(h % 2 == 0 ) w = 2.0/3.0; // even
441 else w = 4.0/3.0; //odd
442 } else w = 1.0/3.0;
443 } else w = 1.0; // rectangular
444 // Yrr and Yri
445 Ys[0](l,s).set_val(n, m, Ys[0](l,s)(n,m)+ w * complex<double>
446 (Yls.real()*Ynm.real(), Yls.real()*Ynm.imag()));
447 // Yir and Yii
448 Ys[1](l,s).set_val(n, m, Ys[1](l,s)(n,m) + w * complex<double>
449 (Yls.imag()*Ynm.real(), Yls.imag()*Ynm.imag()));
450 }//nm
451 }//ls
452 if( h % 10000 == 0 ) cout <<"completed "<<h<<" points "<<endl;
453 }//h
454
455 double dA = 4*M_PI / (double)(grid_tot-1);
456 double mul = (bur) ? -1.0 : 1.0;
457 for(int l=0; l<p_; l++)
458 {
459 double delta = (bur) ? 1.0/_expConst_->get_const1_l(l) : 0.0;
460 for(int s=0; s<=l; s++)
461 for(int n=0; n<=l; n++)
462 for(int m=0; m<=n; m++)
463 {
464 if( n==l && m > s ) break;
465 if( n==l && m==s )
466 {
467 if(m==0)
468 {
469 Ys[0](l,s)(n,m).real(delta + mul*dA*Ys[0](l,s)(n,m).real());
470 Ys[1](l,s)(n,m).imag(0.0);
471 }
472 else
473 {
474 Ys[0](l,s)(n,m).real(0.5*delta + mul*dA*Ys[0](l,s)(n,m).real());
475 Ys[1](l,s)(n,m).imag(0.5*delta + mul*dA*Ys[1](l,s)(n,m).imag());
476 }
477 Ys[0](l,s)(n,m).imag(Ys[0](l,s)(n,m).imag()*mul*dA);
478 Ys[1](l,s)(n,m).real(Ys[1](l,s)(n,m).real()*mul*dA);
479 }
480 else
481 {
482 Ys[0](l,s)(n,m) *= (mul*dA);
483 Ys[1](l,s)(n,m) *= (mul*dA);
484 }
485 } // end m
486 } // end l
487
488 for(int l=0; l<p_; l++)
489 for(int s=0; s<=l; s++)
490 for(int n=0; n<=l; n++)
491 for(int m=0; m<=n; m++)
492 {
493 if( n==l && s < m)
494 {
495 vector<int> myind = _expConst_->get_imat_loc(m-s-1);
496 Ys[0](l,s).set_val(n, m, Ys[0](l,s+1)(myind[0], myind[1]));
497 Ys[1](l,s).set_val(n, m, Ys[1](l,s+1)(myind[0], myind[1]));
498 }
499 }
500
501 return Ys;
502 } // end compute_integral
503
504 // Currently using old format because I dont know whats going on!
505 // TODO: change to understandable
populate_mat(vector<MatOfMats<cmplx>::type> Ys,int k)506 void IEMatrix::populate_mat(vector<MatOfMats<cmplx>::type > Ys, int k)
507 {
508 int i = 0;
509 int sNeg = -1; int mNeg = -1;
510 for(int l=0; l<p_; l++)
511 {
512 double imat;
513 for(int n=0; n<p_; n++) // s=0
514 {
515 double scl = _expConst_->get_const1_l(n);
516 for(int m=0; m<=n; m++)
517 {
518 bool bUpper = ( n<l || (n==l && m==0) );
519 imat = scl * (bUpper? Ys[0](l,0)(n,m).real():Ys[0](n,m)(l,0).real());
520 IE_orig_[k][i] = imat;
521 i++;
522 if ( m != 0 )
523 {
524 imat = (bUpper ? Ys[0](l,0)(n,m).imag():Ys[1](n,m)(l,0).real());
525 IE_orig_[k][i] = (-1.0 * mNeg * scl * imat);
526 i++;
527 }
528 } //m
529 }//n
530
531 for(int s=1; s<=l; s++) // s>0 and // (l,s)real columns
532 {
533 for(int n=0; n<p_; n++)
534 {
535 double scl = _expConst_->get_const1_l(n);
536 for(int m=0; m<=n; m++)
537 {
538 bool bUpper = ( n<l || (n==l && m<=s) );
539 imat = 2.*scl*(bUpper? Ys[0](l,s)(n,m).real():Ys[0](n,m)(l,s).real());
540 IE_orig_[k][i] = imat;
541 i++;
542 if ( m != 0 )
543 {
544 imat = (bUpper? Ys[0](l,s)(n,m).imag():Ys[1](n,m)(l,s).real());
545 IE_orig_[k][i] = (mNeg * -2.0 * scl * imat);
546 i++;
547 }
548 } //m
549 }//n
550
551 // (l,s)imag columns
552 for(int n=0; n<p_; n++)
553 {
554 double scl = _expConst_->get_const1_l(n);
555 for(int m=0; m<=n; m++)
556 {
557 bool bUpper = ( n<l || (n==l && m<=s) );
558 imat = (bUpper? Ys[1](l,s)(n,m).real():Ys[0](n,m)(l,s).imag());
559 IE_orig_[k][i] = (sNeg * -2.0 * scl * imat);
560 i++;
561 if ( m != 0 )
562 {
563 imat = (bUpper? Ys[1](l,s)(n,m).imag():Ys[1](n,m)(l,s).imag());
564 IE_orig_[k][i] = (2.0 * scl * imat);
565 i++;
566 }
567 } //m
568 }//n
569 }//s
570 }//l
571 }
572
calc_vals(shared_ptr<BaseMolecule> _mol,shared_ptr<SHCalc> _shcalc)573 void IEMatrix::calc_vals(shared_ptr<BaseMolecule> _mol,
574 shared_ptr<SHCalc> _shcalc)
575 {
576 for (int k = 0; k < _mol->get_ns(); k++)
577 {
578 vector<MatOfMats<cmplx>::type > Ys = compute_integral(_mol, _shcalc, k);
579 populate_mat(Ys, k);
580 }
581 }
582
reset_mat()583 void IEMatrix::reset_mat()
584 {
585 for (int k = 0; k < IE_orig_.size(); k++)
586 {
587 for (int ind = 0; ind < p_*p_*p_*p_; ind++)
588 IE_orig_[k][ind] = 0.0;
589 }
590 }
591
LFMatrix(int I,int ns,int p)592 LFMatrix::LFMatrix(int I, int ns, int p)
593 :NumericalMatrix(I, ns, p)
594 {
595 }
596
init(shared_ptr<BaseMolecule> mol,shared_ptr<FMatrix> F,shared_ptr<SHCalc> shcalc,shared_ptr<BesselCalc> bcalc,shared_ptr<PreCalcSH> pre_sh,shared_ptr<ExpansionConstants> _expconst,bool no_pre_sh)597 void LFMatrix::init(shared_ptr<BaseMolecule> mol, shared_ptr<FMatrix> F,
598 shared_ptr<SHCalc> shcalc, shared_ptr<BesselCalc> bcalc,
599 shared_ptr<PreCalcSH> pre_sh,
600 shared_ptr<ExpansionConstants> _expconst,
601 bool no_pre_sh)
602 {
603 double rl, im;
604 cmplx sh;
605 for (int k=0; k< mol->get_ns(); k++)
606 {
607 vector <int> exp_pts = mol->get_gdpt_expj(k);
608 mat_[k].resize( (int) exp_pts.size() );
609 double dA = 4 * M_PI / (double) mol->get_gridj(k).size();
610
611 for (int h = 0; h < exp_pts.size(); h++)
612 {
613 double val = 0.0;
614 Pt q = mol->get_gridjh(k, exp_pts[h]);
615
616 if (no_pre_sh) pre_sh->calc_and_add(q, shcalc);
617
618 for (int n=0; n<p_; n++)
619 {
620 for (int m = -n; m <= n; m++)
621 {
622 sh = pre_sh->get_sh(q, n, m);
623 rl = sh.real()*F->get_mat_knm(k,n,m).real();
624 im = sh.imag()*F->get_mat_knm(k,n,m).imag();
625 val += dA*_expconst->get_const1_l(n) * ( rl + im );
626 }
627 }
628 set_mat_kh(k, h, val);
629 }
630 }
631 }
632
calc_vals(shared_ptr<TMatrix> T,shared_ptr<FMatrix> F,shared_ptr<SystemSAM> sys,shared_ptr<PreCalcSH> pre_sh,int k,bool no_pre_sh)633 void LFMatrix::calc_vals(shared_ptr<TMatrix> T, shared_ptr<FMatrix> F,
634 shared_ptr<SystemSAM> sys, shared_ptr<PreCalcSH> pre_sh,
635 int k, bool no_pre_sh)
636 {
637 reset_mat(k);
638 MyMatrix<cmplx> reex;
639 for (int j = 0; j < T->get_nsi(I_); j++)
640 {
641 if (j==k) continue;
642
643 if (T->is_analytic(I_, k, I_, j))
644 {
645 bool isF = true;
646 reex = T->re_expandX(F->get_mat_k(j), I_, k, I_, j, isF );
647 }
648 else
649 {
650 reex = T->re_expandX_numeric(get_mat(), I_, k, I_, j, 0.0, pre_sh,
651 no_pre_sh);
652 }
653
654 mat_cmplx_[k] += reex;
655 }
656 }
657
658
LHMatrix(int I,int ns,int p,double kappa)659 LHMatrix::LHMatrix(int I, int ns, int p, double kappa)
660 :NumericalMatrix(I, ns, p), kappa_(kappa)
661 {
662 }
663
init(shared_ptr<BaseMolecule> mol,shared_ptr<HMatrix> H,shared_ptr<SHCalc> shcalc,shared_ptr<BesselCalc> bcalc,shared_ptr<PreCalcSH> pre_sh,shared_ptr<ExpansionConstants> _expconst,bool no_pre_sh)664 void LHMatrix::init(shared_ptr<BaseMolecule> mol, shared_ptr<HMatrix> H,
665 shared_ptr<SHCalc> shcalc, shared_ptr<BesselCalc> bcalc,
666 shared_ptr<PreCalcSH> pre_sh,
667 shared_ptr<ExpansionConstants> _expconst,
668 bool no_pre_sh)
669 {
670 double rl, im;
671 cmplx sh;
672 for (int k=0; k< mol->get_ns(); k++)
673 {
674 vector <int> exp_pts = mol->get_gdpt_expj(k);
675 mat_[k].resize( (int) exp_pts.size() );
676 double dA = 4 * M_PI / (double) mol->get_gridj(k).size();
677
678 for (int h = 0; h < exp_pts.size(); h++)
679 {
680 double val = 0.0;
681 Pt q = mol->get_gridjh(k, exp_pts[h]);
682 if (no_pre_sh) pre_sh->calc_and_add(q, shcalc);
683
684 vector<double> bessI = bcalc->calc_mbfI(p_+1, kappa_*q.r());
685
686 for (int n=0; n<p_; n++)
687 {
688 for (int m = -n; m <= n; m++)
689 {
690 sh = pre_sh->get_sh(q, n, m);
691
692 rl = sh.real()*H->get_mat_knm(k,n,m).real();
693 im = sh.imag()*H->get_mat_knm(k,n,m).imag();
694 val += dA*_expconst->get_const1_l(n)*( rl + im )/bessI[n];
695 }
696 }
697 set_mat_kh(k, h, val);
698 }
699 }
700 }
701
calc_vals(shared_ptr<TMatrix> T,shared_ptr<HMatrix> H,shared_ptr<PreCalcSH> pre_sh,int k,bool no_pre_sh)702 void LHMatrix::calc_vals(shared_ptr<TMatrix> T, shared_ptr<HMatrix> H,
703 shared_ptr<PreCalcSH> pre_sh, int k, bool no_pre_sh)
704 {
705 reset_mat(k);
706 MyMatrix<cmplx> reex;
707
708 for (int j = 0; j < T->get_nsi(I_); j++)
709 {
710 if (j==k) continue;
711
712 if (T->is_analytic(I_, k, I_, j))
713 reex = T->re_expandX(H->get_mat_k(j), I_, k, I_, j );
714 else
715 reex = T->re_expandX_numeric(get_mat(), I_, k, I_, j, kappa_, pre_sh,
716 no_pre_sh);
717
718 mat_cmplx_[k] += reex;
719 }
720 }
721
722
LHNMatrix(int I,int ns,int p,shared_ptr<SystemSAM> sys)723 LHNMatrix::LHNMatrix(int I, int ns, int p, shared_ptr<SystemSAM> sys)
724 :interPol_(ns, 1), ComplexMoleculeMatrix(I, ns, p)
725 {
726 Pt Ik, Jl;
727 double aIk, aJl, interPolcut = 10.0;
728 for (int k = 0; k <sys->get_Ns_i(I); k++)
729 {
730 for (int J = 0; J < sys->get_n(); J++)
731 {
732 if (J == I_) continue;
733 Ik = sys->get_centerik(I_, k);
734 aIk = sys->get_aik(I_, k);
735 for (int l = 0 ; l < sys->get_Ns_i(J); l++)
736 {
737 Jl = sys->get_centerik(J, l);
738 aJl = sys->get_aik(J, l);
739
740 if ( sys->get_pbc_dist_vec_base(Ik, Jl).norm() < (interPolcut+aIk+aJl))
741 {
742 interPol_[k] = 0;
743 }
744 }
745 }
746 }
747 }
748
calc_vals(shared_ptr<SystemSAM> sys,shared_ptr<TMatrix> T,vector<shared_ptr<HMatrix>> H,int k)749 void LHNMatrix::calc_vals(shared_ptr<SystemSAM> sys, shared_ptr<TMatrix> T,
750 vector<shared_ptr<HMatrix> > H, int k)
751 {
752 reset_mat(k);
753 MyMatrix<cmplx> reex;
754 Pt Ik, Jl;
755 double aIk, aJl, interPolcut = 10.0;
756 for (int J = 0; J < T->get_nmol(); J++)
757 {
758 if (J == I_) continue;
759 Ik = sys->get_centerik(I_, k);
760 aIk = sys->get_aik(I_, k);
761 for (int l = 0 ; l < T->get_nsi(J); l++)
762 {
763 Jl = sys->get_centerik(J, l);
764 aJl = sys->get_aik(J, l);
765
766 if ( sys->get_pbc_dist_vec_base(Ik, Jl).norm() < (interPolcut+aIk+aJl))
767 {
768 // cout << "This is H before I " << I_ << " and k " << k
769 // << " and j " << J << " and l " << l<< endl;
770 // H[J]->print_kmat(l);
771 reex = T->re_expandX(H[J]->get_mat_k(l), I_, k, J, l);
772 mat_[k] += reex;
773
774 // cout << "This is H After " << endl;
775 // for (int n = 0; n < p_; n++)
776 // {
777 // for (int m = 0; m <= n; m++)
778 // {
779 // cout << reex(n, m+p_) << ", ";
780 // }
781 // cout << endl;
782 // }
783 }
784 }
785 }
786
787 // cout << "This is LHN I " << I_ << " and k " << k << endl;
788 // print_kmat(k);
789 }
790
XHMatrix(int I,int ns,int p,shared_ptr<BaseMolecule> mol,shared_ptr<EMatrix> E,shared_ptr<LEMatrix> LE)791 XHMatrix::XHMatrix(int I, int ns, int p,
792 shared_ptr<BaseMolecule> mol,
793 shared_ptr<EMatrix> E,
794 shared_ptr<LEMatrix> LE)
795 : ComplexMoleculeMatrix(I, ns, p), E_LE_mat_(ns, MyMatrix<cmplx> (p, 2*p+1))
796 {
797 double ak;
798
799 for (int k = 0; k < ns; k++)
800 {
801 ak = mol->get_ak(k);
802 for (int n = 0; n < p_; n++)
803 {
804 for (int m = -n; m < n+1; m++)
805 {
806 E_LE_mat_[k](n, m+p) = (E->get_mat_knm(k, n, m) +
807 ak*LE->get_mat_knm(k, n, m));
808 }
809 }
810 }
811 }
812
calc_vals(shared_ptr<BaseMolecule> mol,shared_ptr<BesselCalc> bcalc,shared_ptr<LHMatrix> LH,shared_ptr<LFMatrix> LF,shared_ptr<LHNMatrix> LHN,double kappa,int k)813 void XHMatrix::calc_vals(shared_ptr<BaseMolecule> mol, shared_ptr<BesselCalc> bcalc,
814 shared_ptr<LHMatrix> LH, shared_ptr<LFMatrix> LF,
815 shared_ptr<LHNMatrix> LHN, double kappa, int k)
816 {
817 cmplx inner;
818 double ak = mol->get_ak(k);
819 vector<double> in_k = bcalc->calc_mbfI(p_, kappa * ak);
820
821 for (int n = 0; n < p_; n++)
822 {
823 for (int m = - n; m <= n; m++)
824 {
825 inner = E_LE_mat_[k]( n, m+p_);
826 inner += ak*LF->get_mat_knm(k, n, m);
827 inner -= ak*in_k[n]*(LH->get_mat_knm(k, n, m)+LHN->get_mat_knm(k, n, m));
828 set_mat_knm(k, n, m, inner);
829 }
830 }
831 }
832
833
XFMatrix(int I,int ns,int p,double eps_in,double eps_out,shared_ptr<BaseMolecule> mol,shared_ptr<EMatrix> E,shared_ptr<LEMatrix> LE)834 XFMatrix::XFMatrix(int I, int ns, int p, double eps_in, double eps_out,
835 shared_ptr<BaseMolecule> mol, shared_ptr<EMatrix> E,
836 shared_ptr<LEMatrix> LE)
837 :ComplexMoleculeMatrix(I, ns, p), eps_(eps_in/eps_out),
838 E_LE_mat_(ns, MyMatrix<cmplx> (p, 2*p+1))
839 {
840 double ak;
841
842 for (int k = 0; k < ns; k++)
843 {
844 ak = mol->get_ak(k);
845 for (int n = 0; n < p_; n++)
846 {
847 for (int m = -n; m <= n; m++)
848 {
849 E_LE_mat_[k](n, m+p_) = eps_ * ((double)(n+1) * E->get_mat_knm(k, n, m)
850 - n * ak * LE->get_mat_knm(k, n, m));
851 }
852 }
853 }
854 }
855
calc_vals(shared_ptr<BaseMolecule> mol,shared_ptr<BesselCalc> bcalc,shared_ptr<LHMatrix> LH,shared_ptr<LFMatrix> LF,shared_ptr<LHNMatrix> LHN,double kappa,int k)856 void XFMatrix::calc_vals(shared_ptr<BaseMolecule> mol, shared_ptr<BesselCalc> bcalc,
857 shared_ptr<LHMatrix> LH, shared_ptr<LFMatrix> LF,
858 shared_ptr<LHNMatrix> LHN, double kappa, int k)
859 {
860 cmplx inner;
861 double ak = mol->get_ak(k);
862 vector<double> in_k = bcalc->calc_mbfI(p_+1, kappa * ak);
863
864 for (int n = 0; n < p_; n++)
865 {
866 for (int m = -n; m < n+1; m++)
867 {
868 inner = (pow(kappa * ak, 2.0) * in_k[n+1])/(double)(2*n+3);
869 inner += double(n * in_k[n]);
870 inner *= ( ak * (LH->get_mat_knm(k, n, m) + LHN->get_mat_knm(k, n, m)));
871 inner += E_LE_mat_[k]( n, m+p_);
872 inner -= ( n * eps_ * ak * LF->get_mat_knm(k, n, m));
873 set_mat_knm(k, n, m, inner);
874 }
875 }
876
877 }
878
HMatrix(int I,int ns,int p,double kappa)879 HMatrix::HMatrix(int I, int ns, int p, double kappa)
880 :ComplexMoleculeMatrix(I, ns, p), kappa_(kappa)
881 {
882 }
883
884
init_from_exp(string hfilename,int k)885 void HMatrix::init_from_exp(string hfilename, int k)
886 {
887 HFFile hfil( hfilename, p_);
888 set_mat_k(k, hfil.get_mat());
889 }
890
891
892 // Initialize H matrix to E with charges mapped to cg (mol.cgCharges_)
init(shared_ptr<BaseMolecule> mol,shared_ptr<SHCalc> _sh_calc,double eps_in)893 void HMatrix::init(shared_ptr<BaseMolecule> mol,
894 shared_ptr<SHCalc> _sh_calc, double eps_in)
895 {
896 cmplx val;
897 Pt cen;
898 double r_alpha, a_k, q_alpha;
899 for (int k=0; k< mol->get_ns(); k++)
900 {
901 for (int alpha=0; alpha < mol->get_nc_k(k); alpha++)
902 {
903 cen = mol->get_posj(mol->get_ch_k_alpha(k, alpha));
904 _sh_calc->calc_sh(cen.theta(), cen.phi());
905 for (int n = 0; n < p_; n++)
906 {
907 for (int m = -n; m < n+1; m++)
908 {
909 q_alpha = mol->get_qj(mol->get_ch_k_alpha(k, alpha));
910 r_alpha = cen.r();
911 a_k = mol->get_ak(k);
912
913 val = _sh_calc->get_result(n, m);
914 val *= q_alpha / eps_in;
915 val *= pow(r_alpha / a_k, n);
916 val += get_mat_knm(k, n, m);
917 set_mat_knm(k, n, m, val);
918 }
919 }
920 }
921 }
922 }
923
calc_vals(shared_ptr<BaseMolecule> mol,shared_ptr<HMatrix> prev,shared_ptr<XHMatrix> XH,shared_ptr<FMatrix> F,shared_ptr<IEMatrix> IE,shared_ptr<BesselCalc> bcalc,int k)924 void HMatrix::calc_vals(shared_ptr<BaseMolecule> mol,
925 shared_ptr<HMatrix> prev,
926 shared_ptr<XHMatrix> XH,
927 shared_ptr<FMatrix> F,
928 shared_ptr<IEMatrix> IE,
929 shared_ptr<BesselCalc> bcalc, int k)
930 {
931 int ct = 0;
932 cmplx inner;
933 double ak = mol->get_ak(k);
934 double h_in[p_*p_], h_out[p_*p_];
935 vector<double> bessel_i = bcalc->calc_mbfI(p_+1, kappa_*ak);
936 vector<double> bessel_k = bcalc->calc_mbfK(p_+1, kappa_*ak);
937
938 for (int l = 0; l < p_; l++) // rows in old matrix
939 {
940 for (int s = 0; s < l+1; s++) //columns in old matrix
941 {
942 inner = (2.0 * l + 1.0) / bessel_i[l];
943 inner -= exp(-kappa_*ak) * bessel_k[l];
944 inner *= prev->get_mat_knm(k, l, s);
945 inner += F->get_mat_knm(k, l, s);
946 inner += XH->get_mat_knm(k, l, s);
947
948 h_in[ct] = inner.real();
949 ct++;
950 if ( s > 0 )
951 {
952 h_in[ct] = inner.imag();
953 ct++;
954 }
955 }
956 }
957
958 const int p2 = p_*p_;
959 #ifdef __LAU
960 applyMMat(&IE->get_IE_k_org(k)[0], &h_in[0], &h_out[0], 1.0, 0.0, p2, 1, p2);
961 #else
962 MyMatrix<double> h_out1(p2, 1);
963 MyMatrix<double> h_in1 (p2, 1, h_in);
964 h_out1 = IE->get_IE_k(k) * h_in1; // Matrix vector multiplication
965 #endif
966
967 int ctr(0);
968 for (int n = 0; n < p_; n++) // rows in new matrix
969 {
970 double scl = bessel_i[n] / (double)(2.0*n+1.0);
971 for (int m = 0; m < n+1; m++) // columns in new matrix
972 {
973 double hRe, hIm;
974 #ifdef __LAU
975 hRe = h_out[ctr];
976 #else
977 hRe = h_out1(ctr,0);
978 #endif
979 ctr++;
980
981 if ( m > 0 )
982 {
983 #ifdef __LAU
984 hIm = h_out[ctr];
985 #else
986 hIm = h_out1(ctr,0);
987 #endif
988 ctr++;
989 } else
990 hIm = 0.0;
991
992 set_mat_knm(k, n, m, scl * complex<double> (hRe, hIm));
993 if ( m > 0 ) set_mat_knm(k, n, -m, scl * complex<double> (hRe, -hIm));
994 }
995 }
996 }
997
make_hb_Ik(int k,Pt rb,shared_ptr<SHCalc> shcalc,vector<double> besseli)998 cmplx HMatrix::make_hb_Ik(int k, Pt rb,
999 shared_ptr<SHCalc> shcalc,
1000 vector<double> besseli)
1001 {
1002 cmplx hb_inner, hbj;
1003 vector<cmplx> h;
1004
1005 shcalc->calc_sh(rb.theta(), rb.phi());
1006 hbj = 0;
1007 for (int n = 0; n < p_; n++)
1008 {
1009 for (int m = -n; m < n+1; m++)
1010 {
1011 hb_inner = ((2*n+1)/ (4*M_PI)) * get_mat_knm(k, n, m) ;
1012 hb_inner /= besseli[n];
1013 hb_inner *= shcalc->get_result(n, m);
1014 hbj += hb_inner;
1015 }
1016 }
1017 hbj /= pow(rb.r(), 2); // make h_hat into h
1018 return hbj;
1019 }
1020
1021
1022
FMatrix(int I,int ns,int p,double kappa)1023 FMatrix::FMatrix(int I, int ns, int p, double kappa)
1024 :ComplexMoleculeMatrix(I, ns, p), kappa_(kappa)
1025 {
1026 }
1027
init_from_exp(string ffilename,int k)1028 void FMatrix::init_from_exp(string ffilename, int k)
1029 {
1030 HFFile ffil( ffilename, p_);
1031 set_mat_k(k, ffil.get_mat());
1032 }
1033
1034
calc_vals(shared_ptr<BaseMolecule> mol,shared_ptr<FMatrix> prev,shared_ptr<XFMatrix> XF,shared_ptr<HMatrix> H,shared_ptr<IEMatrix> IE,shared_ptr<BesselCalc> bcalc,int k,double kappa)1035 void FMatrix::calc_vals(shared_ptr<BaseMolecule> mol,
1036 shared_ptr<FMatrix> prev,
1037 shared_ptr<XFMatrix> XF,
1038 shared_ptr<HMatrix> H,
1039 shared_ptr<IEMatrix> IE,
1040 shared_ptr<BesselCalc> bcalc, int k, double kappa)
1041 {
1042 int ct(0), p2(p_*p_);
1043 cmplx inner;
1044 double ak = mol->get_ak(k), fRe, fIm, scl;
1045 vector<double> bessel_i = bcalc->calc_mbfI(p_+1, kappa*ak);
1046 vector<double> bessel_k = bcalc->calc_mbfK(p_+1, kappa*ak);
1047 double f_in[p_*p_], f_out[p_*p_];;
1048
1049 for (int l = 0; l < p_; l++)
1050 {
1051 for (int s = 0; s < l+1; s++)
1052 {
1053 inner = double(l * bessel_k[l]) - ((2.0*l+1.0) * bessel_k[l+1]);
1054 inner *= exp(-kappa*ak) * H->get_mat_knm(k, l, s);
1055 inner += XF->get_mat_knm(k, l, s);
1056 inner += (double(2*l + 1 - l * XF->get_eps()) *
1057 prev->get_mat_knm(k, l, s));
1058 f_in[ct] = inner.real();
1059 ct++;
1060 if ( s > 0 )
1061 {
1062 f_in[ct] = inner.imag();
1063 ct++;
1064 }
1065 }
1066 }
1067
1068 #ifdef __LAU
1069 applyMMat(&IE->get_IE_k_org(k)[0], &f_in[0], &f_out[0], 1.0, 0.0, p2, 1, p2);
1070 #else
1071 MyMatrix<double> f_out1(p2, 1);
1072 MyMatrix<double> f_in1 (p2, 1, f_in);
1073 f_out1 = IE->get_IE_k(k) * f_in1; // Matrix vector multiplication
1074 #endif
1075
1076 ct = 0;
1077 for (int n = 0; n < p_; n++) // rows in new matrix
1078 {
1079 scl = 1.0 / (double)(2.0*n+1.0);
1080 for (int m = 0; m < n+1; m++) // columns in new matrix
1081 {
1082 #ifdef __LAU
1083 fRe = f_out[ct];
1084 #else
1085 fRe = f_out1(ct,0);
1086 #endif
1087 ct++;
1088
1089 if ( m > 0 )
1090 {
1091 #ifdef __LAU
1092 fIm = f_out[ct];
1093 #else
1094 fIm = f_out1(ct,0);
1095 #endif
1096 ct++;
1097 } else
1098 fIm = 0.0;
1099
1100 set_mat_knm(k, n, m, scl * complex<double> (fRe, fIm));
1101 if ( m > 0 ) set_mat_knm(k, n, -m, scl * complex<double> (fRe, -fIm));
1102 }
1103 }
1104 }
1105