source: ThirdParty/mpqc_open/src/lib/chemistry/qc/wfn/density.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: 22.4 KB
Line 
1//
2// density.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 <stdexcept>
33
34#include <util/misc/formio.h>
35#include <util/render/polygons.h>
36#include <math/scmat/local.h>
37#include <math/scmat/vector3.h>
38#include <chemistry/molecule/molecule.h>
39#include <chemistry/qc/wfn/density.h>
40
41using namespace std;
42using namespace sc;
43
44/////////////////////////////////////////////////////////////////////////////
45// ElectronDensity
46
47static ClassDesc ElectronDensity_cd(
48 typeid(ElectronDensity),"ElectronDensity",1,"public Volume",
49 0, create<ElectronDensity>, 0);
50
51ElectronDensity::ElectronDensity(const Ref<KeyVal> &keyval):
52 Volume(keyval)
53{
54 wfn_ << keyval->describedclassvalue("wfn");
55}
56
57ElectronDensity::ElectronDensity(const Ref<Wavefunction>& wfn):
58 Volume(),
59 wfn_(wfn)
60{
61}
62
63ElectronDensity::~ElectronDensity()
64{
65}
66
67void
68ElectronDensity::compute()
69{
70 SCVector3 r;
71 get_x(r);
72 // do_gradient will automatically cause the value to be computed
73 if (gradient_needed()) {
74 double v[3];
75 set_value(wfn_->density_gradient(r,v));
76 set_actual_value_accuracy(desired_value_accuracy());
77 SCVector3 d(v);
78 set_gradient(d);
79 set_actual_gradient_accuracy(desired_gradient_accuracy());
80 }
81 else if (value_needed()) {
82 set_value(wfn_->density(r));
83 set_actual_value_accuracy(desired_value_accuracy());
84 }
85 if (hessian_needed()) {
86 ExEnv::err0() << indent
87 << "ElectronDensity::compute(): hessian isn't yet implemented\n";
88 abort();
89 }
90}
91
92// make a wild guess about the bounding box
93void
94ElectronDensity::boundingbox(double valuemin,
95 double valuemax,
96 SCVector3& p1, SCVector3& p2)
97{
98 Molecule& mol = *wfn_->molecule();
99
100 if (mol.natom() == 0) {
101 for (int i=0; i<3; i++) p1[i] = p2[i] = 0.0;
102 }
103
104 int i;
105 for (i=0; i<3; i++) p1[i] = p2[i] = mol.r(0,i);
106 for (i=1; i<mol.natom(); i++) {
107 for (int j=0; j<3; j++) {
108 if (mol.r(i,j) < p1[j]) p1[j] = mol.r(i,j);
109 if (mol.r(i,j) > p2[j]) p2[j] = mol.r(i,j);
110 }
111 }
112 for (i=0; i<3; i++) {
113 p1[i] = p1[i] - 3.0;
114 p2[i] = p2[i] + 3.0;
115 }
116}
117
118/////////////////////////////////////////////////////////////////////////////
119// BatchElectronDensity
120
121static ClassDesc BatchElectronDensity_cd(
122 typeid(BatchElectronDensity),"BatchElectronDensity",1,"public Volume",
123 0, create<BatchElectronDensity>, 0);
124
125BatchElectronDensity::BatchElectronDensity(const Ref<Wavefunction> &wfn,
126 double accuracy):
127 Volume()
128{
129 wfn_ = wfn;
130 accuracy_ = accuracy;
131 zero_pointers();
132 using_shared_data_ = false;
133 linear_scaling_ = true;
134 use_dmat_bound_ = true;
135 need_basis_gradient_ = false;
136 need_basis_hessian_ = false;
137}
138
139BatchElectronDensity::BatchElectronDensity(const Ref<KeyVal> &keyval):
140 Volume(keyval)
141{
142 wfn_ << keyval->describedclassvalue("wfn");
143 accuracy_ = keyval->doublevalue("accuracy");
144 zero_pointers();
145 using_shared_data_ = false;
146 linear_scaling_ = true;
147 use_dmat_bound_ = true;
148 need_basis_gradient_ = false;
149 need_basis_hessian_ = false;
150}
151
152BatchElectronDensity::BatchElectronDensity(const Ref<BatchElectronDensity>&d,
153 bool reference_parent_data):
154 Volume()
155{
156 wfn_ = d->wfn_;
157 zero_pointers();
158 using_shared_data_ = reference_parent_data;
159 accuracy_ = d->accuracy_;
160 need_basis_gradient_ = d->need_basis_gradient_;
161 need_basis_hessian_ = d->need_basis_hessian_;
162 if (using_shared_data_) {
163 if (d->alpha_dmat_ == 0) {
164 throw std::runtime_error("BatchElectronDensity: attempted to use shared data, but parent data not initialized");
165 }
166
167 spin_polarized_ = d->spin_polarized_;
168 nshell_ = d->nshell_;
169 nbasis_ = d->nbasis_;
170 basis_ = d->basis_;
171 extent_ = d->extent_;
172 alpha_dmat_ = d->alpha_dmat_;
173 beta_dmat_ = d->beta_dmat_;
174 dmat_bound_ = d->dmat_bound_;
175 linear_scaling_ = d->linear_scaling_;
176 use_dmat_bound_ = d->use_dmat_bound_;
177
178 init_scratch_data();
179 }
180}
181
182BatchElectronDensity::~BatchElectronDensity()
183{
184 clear();
185}
186
187void
188BatchElectronDensity::zero_pointers()
189{
190 valdat_ = 0;
191 extent_ = 0;
192
193 alpha_dmat_ = 0;
194 beta_dmat_ = 0;
195 dmat_bound_ = 0;
196 contrib_ = 0;
197 contrib_bf_ = 0;
198 bs_values_ = 0;
199 bsg_values_ = 0;
200 bsh_values_ = 0;
201}
202
203void
204BatchElectronDensity::clear()
205{
206 if (!using_shared_data_) {
207 delete extent_;
208 delete[] alpha_dmat_;
209 delete[] beta_dmat_;
210 delete[] dmat_bound_;
211 }
212
213 delete[] contrib_;
214 delete[] contrib_bf_;
215 delete[] bs_values_;
216 delete[] bsg_values_;
217 delete[] bsh_values_;
218 delete valdat_;
219
220 zero_pointers();
221}
222
223void
224BatchElectronDensity::init(bool initialize_density_matrices)
225{
226 if (using_shared_data_)
227 throw std::runtime_error("BatchElectronDensity::init: should not be called if using_shared_data");
228
229 clear();
230 init_common_data(initialize_density_matrices);
231 init_scratch_data();
232}
233
234void
235BatchElectronDensity::init_common_data(bool initialize_density_matrices)
236{
237 spin_polarized_ = wfn_->spin_polarized();
238 nshell_ = wfn_->basis()->nshell();
239 nbasis_ = wfn_->basis()->nbasis();
240 basis_ = wfn_->basis();
241
242 if (linear_scaling_) {
243 extent_ = new ShellExtent;
244 extent_->init(wfn_->basis());
245 }
246
247 alpha_dmat_ = new double[(nbasis_*(nbasis_+1))/2];
248
249 beta_dmat_ = 0;
250 if (spin_polarized_) {
251 beta_dmat_ = new double[(nbasis_*(nbasis_+1))/2];
252 }
253
254 dmat_bound_ = new double[(nshell_*(nshell_+1))/2];
255
256 if (initialize_density_matrices) {
257 RefSymmSCMatrix beta_ao_density;
258 if (spin_polarized_) beta_ao_density = wfn_->beta_ao_density();
259 set_densities(wfn_->alpha_ao_density(), beta_ao_density);
260 }
261}
262
263void
264BatchElectronDensity::set_densities(const RefSymmSCMatrix &aden,
265 const RefSymmSCMatrix &bden)
266{
267 RefSymmSCMatrix ad = aden;
268 RefSymmSCMatrix bd = bden;
269 if (ad.null()) ad = wfn_->alpha_ao_density();
270 if (bd.null()) bd = wfn_->beta_ao_density();
271
272 ad->convert(alpha_dmat_);
273 if (spin_polarized_) bd->convert(beta_dmat_);
274
275 int ij = 0;
276 for (int i=0; i<nshell_; i++) {
277 int ni = wfn_->basis()->shell(i).nfunction();
278 for (int j=0; j<=i; j++,ij++) {
279 int nj = wfn_->basis()->shell(j).nfunction();
280 double bound = 0.0;
281 int ibf = wfn_->basis()->shell_to_function(i);
282 for (int k=0; k<ni; k++,ibf++) {
283 int lmax = nj-1;
284 if (i==j) lmax = k;
285 int jbf = wfn_->basis()->shell_to_function(j);
286 int ijbf = (ibf*(ibf+1))/2 + jbf;
287 for (int l=0; l<=lmax; l++,ijbf++) {
288 double a = fabs(alpha_dmat_[ijbf]);
289 if (a > bound) bound = a;
290 if (beta_dmat_) {
291 double b = fabs(beta_dmat_[ijbf]);
292 if (b > bound) bound = b;
293 }
294 }
295 }
296 dmat_bound_[ij] = bound;
297 }
298 }
299}
300
301void
302BatchElectronDensity::init_scratch_data()
303{
304 contrib_ = new int[nshell_];
305 contrib_bf_ = new int[nbasis_];
306 bs_values_ = new double[nbasis_];
307 bsg_values_ = new double[3*nbasis_];
308 bsh_values_ = new double[6*nbasis_];
309 valdat_ = new GaussianBasisSet::ValueData(basis_, wfn_->integral());
310}
311
312void
313BatchElectronDensity::compute_basis_values(const SCVector3&r)
314{
315 // only consider those shells for which phi_i * (Max_j D_ij phi_j) > tol
316 if (linear_scaling_ && use_dmat_bound_ && extent_ != 0) {
317 const std::vector<ExtentData> &cs = extent_->contributing_shells(r[0],r[1],r[2]);
318 ncontrib_ = 0;
319 for (int i=0; i<cs.size(); i++) {
320 int ish = cs[i].shell;
321 int contrib = 0;
322 for (int j=0; j<cs.size(); j++) {
323 int jsh = cs[j].shell;
324 int ijsh = (ish>jsh)?((ish*(ish+1))/2+jsh):((jsh*(jsh+1))/2+ish);
325// std::cout << "cs[i].bound = " << cs[i].bound << std::endl;
326// std::cout << "cs[j].bound = " << cs[j].bound << std::endl;
327// std::cout << "dmat_bound_[ijsh] = " << dmat_bound_[ijsh] << std::endl;
328// std::cout << "accuracy_ = " << accuracy_ << std::endl;
329 if (cs[i].bound*cs[j].bound*dmat_bound_[ijsh] > 0.00001*accuracy_) {
330 contrib = 1;
331 break;
332 }
333 }
334 if (contrib) {
335 contrib_[ncontrib_++] = ish;
336 }
337 }
338 }
339 else if (linear_scaling_ && extent_ != 0) {
340 const std::vector<ExtentData> &cs = extent_->contributing_shells(r[0],r[1],r[2]);
341 ncontrib_ = cs.size();
342 for (int i=0; i<ncontrib_; i++) {
343 contrib_[i] = cs[i].shell;
344 }
345 }
346 else {
347 ncontrib_ = nshell_;
348 for (int i=0; i<nshell_; i++) contrib_[i] = i;
349 }
350
351 ncontrib_bf_ = 0;
352 for (int i=0; i<ncontrib_; i++) {
353 int nbf = basis_->shell(contrib_[i]).nfunction();
354 int bf = basis_->shell_to_function(contrib_[i]);
355 for (int j=0; j<nbf; j++, bf++) {
356 contrib_bf_[ncontrib_bf_++] = bf;
357 }
358 }
359
360 // compute the basis set values
361 double *bsv = bs_values_;
362 double *bsg = ((need_basis_gradient_||need_gradient_)?bsg_values_:0);
363 double *bsh = ((need_basis_hessian_||need_hessian_)?bsh_values_:0);
364 for (int i=0; i<ncontrib_; i++) {
365 basis_->hessian_shell_values(r,contrib_[i],valdat_,bsh,bsg,bsv);
366 int shsize = basis_->shell(contrib_[i]).nfunction();
367
368 if (bsh) bsh += 6 * shsize;
369 if (bsg) bsg += 3 * shsize;
370 if (bsv) bsv += shsize;
371 }
372}
373
374void
375BatchElectronDensity::compute_spin_density(const double *dmat,
376 double *rho,
377 double *grad,
378 double *hess)
379{
380 int i, j;
381
382 double tmp = 0.0;
383 double densij;
384 double bvi, bvix, bviy, bviz;
385 double bvixx, bviyx, bviyy, bvizx, bvizy, bvizz;
386
387 if (need_gradient_) for (i=0; i<3; i++) grad[i] = 0.0;
388 if (need_hessian_) for (i=0; i<6; i++) hess[i] = 0.0;
389
390 if (need_gradient_ || need_hessian_) {
391 for (i=0; i < ncontrib_bf_; i++) {
392 int it = contrib_bf_[i];
393 bvi = bs_values_[i];
394 if (need_gradient_) {
395 bvix = bsg_values_[i*3+X];
396 bviy = bsg_values_[i*3+Y];
397 bviz = bsg_values_[i*3+Z];
398 }
399 if (need_hessian_) {
400 bvixx = bsh_values_[i*6+XX];
401 bviyx = bsh_values_[i*6+YX];
402 bviyy = bsh_values_[i*6+YY];
403 bvizx = bsh_values_[i*6+ZX];
404 bvizy = bsh_values_[i*6+ZY];
405 bvizz = bsh_values_[i*6+ZZ];
406 }
407 int j3 = 0, j6 = 0;
408 int itoff = (it*(it+1))>>1;
409 int itjt;
410 double t = 0.0;
411 for (j=0; j < i; j++) {
412 int jt = contrib_bf_[j];
413 itjt = itoff+jt;
414
415 densij = dmat[itjt];
416 double bvj = bs_values_[j];
417
418 t += densij*bvi*bvj;
419
420 double bvjx, bvjy, bvjz;
421 if (need_gradient_) {
422 bvjx = bsg_values_[j3+X];
423 bvjy = bsg_values_[j3+Y];
424 bvjz = bsg_values_[j3+Z];
425 grad[X] += densij*(bvi*bvjx + bvj*bvix);
426 grad[Y] += densij*(bvi*bvjy + bvj*bviy);
427 grad[Z] += densij*(bvi*bvjz + bvj*bviz);
428 j3 += 3;
429 }
430
431 if (need_hessian_) {
432 double bvjxx = bsh_values_[j6+XX];
433 double bvjyx = bsh_values_[j6+YX];
434 double bvjyy = bsh_values_[j6+YY];
435 double bvjzx = bsh_values_[j6+ZX];
436 double bvjzy = bsh_values_[j6+ZY];
437 double bvjzz = bsh_values_[j6+ZZ];
438
439 hess[XX] += densij*(bvi*bvjxx+bvix*bvjx+bvjx*bvix+bvixx*bvj);
440 hess[YX] += densij*(bvi*bvjyx+bviy*bvjx+bvjy*bvix+bviyx*bvj);
441 hess[YY] += densij*(bvi*bvjyy+bviy*bvjy+bvjy*bviy+bviyy*bvj);
442 hess[ZX] += densij*(bvi*bvjzx+bviz*bvjx+bvjz*bvix+bvizx*bvj);
443 hess[ZY] += densij*(bvi*bvjzy+bviz*bvjy+bvjz*bviy+bvizy*bvj);
444 hess[ZZ] += densij*(bvi*bvjzz+bviz*bvjz+bvjz*bviz+bvizz*bvj);
445
446 j6 += 6;
447 }
448 }
449 densij = dmat[itoff+it]*bvi;
450 tmp += t + 0.5*densij*bvi;
451 if (need_gradient_) {
452 grad[X] += densij*bvix;
453 grad[Y] += densij*bviy;
454 grad[Z] += densij*bviz;
455 }
456 if (need_hessian_) {
457 hess[XX] += densij*bvixx;
458 hess[YX] += densij*bviyx;
459 hess[YY] += densij*bviyy;
460 hess[ZX] += densij*bvizx;
461 hess[ZY] += densij*bvizy;
462 hess[ZZ] += densij*bvizz;
463 }
464 }
465 }
466 else {
467 for (i=0; i < ncontrib_bf_; i++) {
468 int it = contrib_bf_[i];
469 bvi = bs_values_[i];
470 int itoff = (it*(it+1))>>1;
471 int itjt;
472 double t = 0.0;
473 for (j=0; j < i; j++) {
474 int jt = contrib_bf_[j];
475 itjt = itoff+jt;
476
477 densij = dmat[itjt];
478 double bvj = bs_values_[j];
479
480 t += densij*bvi*bvj;
481 }
482 densij = dmat[itoff+it]*bvi;
483 tmp += t + 0.5*densij*bvi;
484 }
485 }
486 if (rho!=0) *rho = tmp;
487
488}
489
490void
491BatchElectronDensity::compute_density(const SCVector3 &r,
492 double *adens,
493 double *agrad,
494 double *ahess,
495 double *bdens,
496 double *bgrad,
497 double *bhess)
498{
499 if (alpha_dmat_ == 0) init();
500
501 need_gradient_ = (agrad!=0) || (bgrad!=0);
502 need_hessian_ = (ahess!=0) || (bhess!=0);
503
504 compute_basis_values(r);
505
506 compute_spin_density(alpha_dmat_,
507 adens,
508 agrad,
509 ahess);
510
511 bool mismatch = (adens==0 && bdens!=0)
512 ||(agrad==0 && bgrad!=0)
513 ||(ahess==0 && bhess!=0);
514
515 if (spin_polarized_ || mismatch) {
516 compute_spin_density(beta_dmat_,
517 bdens,
518 bgrad,
519 bhess);
520 }
521 else {
522 if (bdens!=0) *bdens = *adens;
523 if (bgrad!=0)
524 for (int i=0;i<3;i++) bgrad[i] = agrad[i];
525 if (bhess!=0)
526 for (int i=0;i<6;i++) bhess[i] = ahess[i];
527 }
528
529 if (adens!=0) *adens *= 2.0;
530 if (agrad!=0)
531 for (int i=0;i<3;i++) agrad[i] *= 2.0;
532 if (ahess!=0)
533 for (int i=0;i<6;i++) ahess[i] *= 2.0;
534 if (bdens!=0) *bdens *= 2.0;
535 if (bgrad!=0)
536 for (int i=0;i<3;i++) bgrad[i] *= 2.0;
537 if (bhess!=0)
538 for (int i=0;i<6;i++) bhess[i] *= 2.0;
539
540// if (agrad) {
541// cout << scprintf("compute_density: agrad = %12.8f %12.8f %12.8f",
542// agrad[0], agrad[1], agrad[2])
543// << endl;
544// }
545
546// cout << "compute_density: exiting"
547// << std::endl;
548
549}
550
551void
552BatchElectronDensity::compute()
553{
554 SCVector3 r;
555 get_x(r);
556
557 double val;
558 double grad[3];
559 double hess[6];
560 double aval;
561 double agrad[3];
562 double ahess[6];
563 double bval;
564 double bgrad[3];
565 double bhess[6];
566 compute_density(r,
567 &aval,
568 (gradient_needed()?agrad:0),
569 (hessian_needed()?ahess:0),
570 &bval,
571 (gradient_needed()?bgrad:0),
572 (hessian_needed()?bhess:0));
573 val = aval + bval;
574 for (int i=0; i<3; i++) grad[i] = agrad[i] + bgrad[i];
575 for (int i=0; i<6; i++) hess[i] = ahess[i] + bhess[i];
576
577 if (value_needed()) {
578 set_value(val);
579 set_actual_value_accuracy(desired_value_accuracy());
580 }
581 if (gradient_needed()) {
582 set_value(val);
583 set_actual_value_accuracy(desired_value_accuracy());
584 SCVector3 d(grad);
585 set_gradient(d);
586 set_actual_gradient_accuracy(desired_gradient_accuracy());
587 }
588 if (hessian_needed()) {
589 ExEnv::err0() << indent
590 << "BatchElectronDensity::compute(): hessian isn't yet implemented\n";
591 abort();
592 }
593}
594
595void
596BatchElectronDensity::boundingbox(double valuemin,
597 double valuemax,
598 SCVector3& p1, SCVector3& p2)
599{
600#if 0
601 // this is a very conservative bounding box
602 // also, this code is not correct since extent is not
603 // necessarily initialized
604 if (alpha_dmat_ == 0) init();
605 for (int i=0; i<3; i++) p1[i] = extent_->lower(i);
606 for (int i=0; i<3; i++) p2[i] = extent_->upper(i);
607#else
608 Molecule& mol = *wfn_->molecule();
609
610 if (mol.natom() == 0) {
611 for (int i=0; i<3; i++) p1[i] = p2[i] = 0.0;
612 }
613
614 int i;
615 for (i=0; i<3; i++) p1[i] = p2[i] = mol.r(0,i);
616 for (i=1; i<mol.natom(); i++) {
617 for (int j=0; j<3; j++) {
618 if (mol.r(i,j) < p1[j]) p1[j] = mol.r(i,j);
619 if (mol.r(i,j) > p2[j]) p2[j] = mol.r(i,j);
620 }
621 }
622 for (i=0; i<3; i++) {
623 p1[i] = p1[i] - 3.0;
624 p2[i] = p2[i] + 3.0;
625 }
626#endif
627}
628
629/////////////////////////////////////////////////////////////////////////////
630// DensityColorizer
631
632static ClassDesc DensityColorizer_cd(
633 typeid(DensityColorizer),"DensityColorizer",1,"public MoleculeColorizer",
634 0, create<DensityColorizer>, 0);
635
636DensityColorizer::DensityColorizer(const Ref<KeyVal>&keyval):
637 MoleculeColorizer(keyval)
638{
639 wfn_ << keyval->describedclassvalue("wfn");
640 reference_ = keyval->doublevalue("reference");
641 if (keyval->error() == KeyVal::OK) have_reference_ = 1;
642 else have_reference_ = 0;
643 scale_ = keyval->doublevalue("scale");
644 if (keyval->error() == KeyVal::OK) have_scale_ = 1;
645 else have_scale_ = 0;
646}
647
648DensityColorizer::~DensityColorizer()
649{
650}
651
652void
653DensityColorizer::colorize(const Ref<RenderedPolygons> &poly)
654{
655 const double base = 0.3;
656 int i;
657 int nvertex = poly->nvertex();
658
659 if (nvertex) {
660 double *data = new double[nvertex];
661
662 for (i=0; i<nvertex; i++) {
663 SCVector3 v(poly->vertex(i));
664 data[i] = wfn_->density(v);
665 }
666
667 double min = data[0], max = data[0];
668 for (i=1; i<nvertex; i++) {
669 if (min > data[i]) min = data[i];
670 if (max < data[i]) max = data[i];
671 }
672
673 double center, scale;
674
675 if (have_reference_) center = reference_;
676 else center = (max+min)/2.0;
677
678 double maxdiff = fabs(max - center);
679 double mindiff = fabs(min - center);
680
681 if (have_scale_) {
682 scale = scale_;
683 }
684 else {
685 if (maxdiff>mindiff && maxdiff>1.0e-6) scale = (1.0-base)/maxdiff;
686 else if (mindiff>1.0e-6) scale = (1.0-base)/mindiff;
687 else scale = (1.0-base);
688 }
689
690 ExEnv::out0() << indent << "DensityColorizer:"
691 << scprintf(" reference=%6.5f", center)
692 << scprintf(" scale=%8.4f",scale)
693 << scprintf(" (%6.5f<=rho<=%6.5f)", max, min)
694 << endl;
695 for (i=0; i<nvertex; i++) {
696 data[i] = (data[i]-center)*scale;
697 }
698
699 for (i=0; i<nvertex; i++) {
700 Color c;
701 if (data[i] < 0.0) c.set_rgb(-data[i]+base,0.3,0.3);
702 else c.set_rgb(0.3,0.3,data[i]+base);
703 poly->set_vertex_color(i,c);
704 }
705
706 delete[] data;
707 }
708}
709
710/////////////////////////////////////////////////////////////////////////////
711// GradDensityColorizer
712
713static ClassDesc GradDensityColorizer_cd(
714 typeid(GradDensityColorizer),"GradDensityColorizer",1,"public MoleculeColorizer",
715 0, create<GradDensityColorizer>, 0);
716
717GradDensityColorizer::GradDensityColorizer(const Ref<KeyVal>&keyval):
718 MoleculeColorizer(keyval)
719{
720 wfn_ << keyval->describedclassvalue("wfn");
721 reference_ = keyval->doublevalue("reference");
722 if (keyval->error() == KeyVal::OK) have_reference_ = 1;
723 else have_reference_ = 0;
724 scale_ = keyval->doublevalue("scale");
725 if (keyval->error() == KeyVal::OK) have_scale_ = 1;
726 else have_scale_ = 0;
727}
728
729GradDensityColorizer::~GradDensityColorizer()
730{
731}
732
733void
734GradDensityColorizer::colorize(const Ref<RenderedPolygons> &poly)
735{
736 const double base = 0.3;
737 int i;
738 int nvertex = poly->nvertex();
739
740 Ref<BatchElectronDensity> den = new BatchElectronDensity(wfn_);
741
742 if (nvertex) {
743 double *data = new double[nvertex];
744
745 for (i=0; i<nvertex; i++) {
746 SCVector3 v(poly->vertex(i));
747 SCVector3 g;
748 den->set_x(v);
749 den->get_gradient(g);
750 data[i] = g.norm();
751 }
752
753 double min = data[0], max = data[0];
754 for (i=1; i<nvertex; i++) {
755 if (min > data[i]) min = data[i];
756 if (max < data[i]) max = data[i];
757 }
758
759 double center, scale;
760
761 if (have_reference_) center = reference_;
762 else center = (max+min)/2.0;
763
764 double maxdiff = fabs(max - center);
765 double mindiff = fabs(min - center);
766
767 if (have_scale_) {
768 scale = scale_;
769 }
770 else {
771 if (maxdiff>mindiff && maxdiff>1.0e-6) scale = (1.0-base)/maxdiff;
772 else if (mindiff>1.0e-6) scale = (1.0-base)/mindiff;
773 else scale = (1.0-base);
774 }
775
776 ExEnv::out0() << indent << "GradDensityColorizer:"
777 << scprintf(" reference=%6.5f", center)
778 << scprintf(" scale=%6.2f",scale)
779 << scprintf(" (%6.5f<=rho<=%6.5f)", max, min)
780 << endl;
781 for (i=0; i<nvertex; i++) {
782 data[i] = (data[i]-center)*scale;
783 }
784
785 for (i=0; i<nvertex; i++) {
786 Color c;
787 if (data[i] > 0.0) c.set_rgb(data[i]+base,0.3,0.3);
788 else c.set_rgb(0.3,0.3,-data[i]+base);
789 poly->set_vertex_color(i,c);
790 }
791
792 delete[] data;
793 }
794}
795
796/////////////////////////////////////////////////////////////////////////////
797
798// Local Variables:
799// mode: c++
800// c-file-style: "CLJ"
801// End:
Note: See TracBrowser for help on using the repository browser.