| 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 | 
 | 
|---|
| 41 | using namespace std;
 | 
|---|
| 42 | using namespace sc;
 | 
|---|
| 43 | 
 | 
|---|
| 44 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 45 | // ElectronDensity
 | 
|---|
| 46 | 
 | 
|---|
| 47 | static ClassDesc ElectronDensity_cd(
 | 
|---|
| 48 |   typeid(ElectronDensity),"ElectronDensity",1,"public Volume",
 | 
|---|
| 49 |   0, create<ElectronDensity>, 0);
 | 
|---|
| 50 | 
 | 
|---|
| 51 | ElectronDensity::ElectronDensity(const Ref<KeyVal> &keyval):
 | 
|---|
| 52 |   Volume(keyval)
 | 
|---|
| 53 | {
 | 
|---|
| 54 |   wfn_ << keyval->describedclassvalue("wfn");
 | 
|---|
| 55 | }
 | 
|---|
| 56 | 
 | 
|---|
| 57 | ElectronDensity::ElectronDensity(const Ref<Wavefunction>& wfn):
 | 
|---|
| 58 |   Volume(),
 | 
|---|
| 59 |   wfn_(wfn)
 | 
|---|
| 60 | {
 | 
|---|
| 61 | }
 | 
|---|
| 62 | 
 | 
|---|
| 63 | ElectronDensity::~ElectronDensity()
 | 
|---|
| 64 | {
 | 
|---|
| 65 | }
 | 
|---|
| 66 | 
 | 
|---|
| 67 | void
 | 
|---|
| 68 | ElectronDensity::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
 | 
|---|
| 93 | void
 | 
|---|
| 94 | ElectronDensity::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 | 
 | 
|---|
| 121 | static ClassDesc BatchElectronDensity_cd(
 | 
|---|
| 122 |   typeid(BatchElectronDensity),"BatchElectronDensity",1,"public Volume",
 | 
|---|
| 123 |   0, create<BatchElectronDensity>, 0);
 | 
|---|
| 124 | 
 | 
|---|
| 125 | BatchElectronDensity::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 | 
 | 
|---|
| 139 | BatchElectronDensity::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 | 
 | 
|---|
| 152 | BatchElectronDensity::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 | 
 | 
|---|
| 182 | BatchElectronDensity::~BatchElectronDensity()
 | 
|---|
| 183 | {
 | 
|---|
| 184 |   clear();
 | 
|---|
| 185 | }
 | 
|---|
| 186 | 
 | 
|---|
| 187 | void
 | 
|---|
| 188 | BatchElectronDensity::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 | 
 | 
|---|
| 203 | void
 | 
|---|
| 204 | BatchElectronDensity::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 | 
 | 
|---|
| 223 | void
 | 
|---|
| 224 | BatchElectronDensity::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 | 
 | 
|---|
| 234 | void
 | 
|---|
| 235 | BatchElectronDensity::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 | 
 | 
|---|
| 263 | void
 | 
|---|
| 264 | BatchElectronDensity::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 | 
 | 
|---|
| 301 | void
 | 
|---|
| 302 | BatchElectronDensity::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 | 
 | 
|---|
| 312 | void
 | 
|---|
| 313 | BatchElectronDensity::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 | 
 | 
|---|
| 374 | void
 | 
|---|
| 375 | BatchElectronDensity::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 | 
 | 
|---|
| 490 | void
 | 
|---|
| 491 | BatchElectronDensity::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 | 
 | 
|---|
| 551 | void
 | 
|---|
| 552 | BatchElectronDensity::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 | 
 | 
|---|
| 595 | void
 | 
|---|
| 596 | BatchElectronDensity::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 | 
 | 
|---|
| 632 | static ClassDesc DensityColorizer_cd(
 | 
|---|
| 633 |   typeid(DensityColorizer),"DensityColorizer",1,"public MoleculeColorizer",
 | 
|---|
| 634 |   0, create<DensityColorizer>, 0);
 | 
|---|
| 635 | 
 | 
|---|
| 636 | DensityColorizer::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 | 
 | 
|---|
| 648 | DensityColorizer::~DensityColorizer()
 | 
|---|
| 649 | {
 | 
|---|
| 650 | }
 | 
|---|
| 651 | 
 | 
|---|
| 652 | void
 | 
|---|
| 653 | DensityColorizer::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 | 
 | 
|---|
| 713 | static ClassDesc GradDensityColorizer_cd(
 | 
|---|
| 714 |   typeid(GradDensityColorizer),"GradDensityColorizer",1,"public MoleculeColorizer",
 | 
|---|
| 715 |   0, create<GradDensityColorizer>, 0);
 | 
|---|
| 716 | 
 | 
|---|
| 717 | GradDensityColorizer::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 | 
 | 
|---|
| 729 | GradDensityColorizer::~GradDensityColorizer()
 | 
|---|
| 730 | {
 | 
|---|
| 731 | }
 | 
|---|
| 732 | 
 | 
|---|
| 733 | void
 | 
|---|
| 734 | GradDensityColorizer::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:
 | 
|---|