00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <ctime>
00011 #include <fstream>
00012
00013 #include "colvarmodule.h"
00014 #include "colvarvalue.h"
00015 #include "colvarparse.h"
00016 #include "colvar.h"
00017 #include "colvarcomp.h"
00018 #include "colvargrid.h"
00019 #include "colvargrid_def.h"
00020
00021
00022
00023 colvar_grid_count::colvar_grid_count()
00024 : colvar_grid<size_t>()
00025 {
00026 mult = 1;
00027 }
00028
00029 colvar_grid_count::colvar_grid_count(std::vector<int> const &nx_i,
00030 size_t const &def_count)
00031 : colvar_grid<size_t>(nx_i, def_count, 1)
00032 {}
00033
00034 colvar_grid_count::colvar_grid_count(std::vector<colvar *> &colvars,
00035 size_t const &def_count,
00036 bool margin)
00037 : colvar_grid<size_t>(colvars, def_count, 1, margin)
00038 {}
00039
00040 std::istream & colvar_grid_count::read_multicol(std::istream &is, bool add)
00041 {
00042 return colvar_grid<size_t>::read_multicol(is, add);
00043 }
00044
00045 int colvar_grid_count::read_multicol(std::string const &filename,
00046 std::string description,
00047 bool add)
00048 {
00049 return colvar_grid<size_t>::read_multicol(filename, description, add);
00050 }
00051
00052 std::ostream & colvar_grid_count::write_multicol(std::ostream &os) const
00053 {
00054 return colvar_grid<size_t>::write_multicol(os);
00055 }
00056
00057 int colvar_grid_count::write_multicol(std::string const &filename,
00058 std::string description) const
00059 {
00060 return colvar_grid<size_t>::write_multicol(filename, description);
00061 }
00062
00063 std::ostream & colvar_grid_count::write_opendx(std::ostream &os) const
00064 {
00065 return colvar_grid<size_t>::write_opendx(os);
00066 }
00067
00068 int colvar_grid_count::write_opendx(std::string const &filename,
00069 std::string description) const
00070 {
00071 return colvar_grid<size_t>::write_opendx(filename, description);
00072 }
00073
00074
00075
00076 colvar_grid_scalar::colvar_grid_scalar()
00077 : colvar_grid<cvm::real>(), samples(NULL)
00078 {}
00079
00080 colvar_grid_scalar::colvar_grid_scalar(colvar_grid_scalar const &g)
00081 : colvar_grid<cvm::real>(g), samples(NULL)
00082 {
00083 }
00084
00085 colvar_grid_scalar::colvar_grid_scalar(std::vector<int> const &nx_i)
00086 : colvar_grid<cvm::real>(nx_i, 0.0, 1), samples(NULL)
00087 {
00088 }
00089
00090 colvar_grid_scalar::colvar_grid_scalar(std::vector<colvar *> &colvars, bool margin)
00091 : colvar_grid<cvm::real>(colvars, 0.0, 1, margin), samples(NULL)
00092 {
00093 }
00094
00095 colvar_grid_scalar::~colvar_grid_scalar()
00096 {
00097 }
00098
00099 std::istream & colvar_grid_scalar::read_multicol(std::istream &is, bool add)
00100 {
00101 return colvar_grid<cvm::real>::read_multicol(is, add);
00102 }
00103
00104 int colvar_grid_scalar::read_multicol(std::string const &filename,
00105 std::string description,
00106 bool add)
00107 {
00108 return colvar_grid<cvm::real>::read_multicol(filename, description, add);
00109 }
00110
00111 std::ostream & colvar_grid_scalar::write_multicol(std::ostream &os) const
00112 {
00113 return colvar_grid<cvm::real>::write_multicol(os);
00114 }
00115
00116 int colvar_grid_scalar::write_multicol(std::string const &filename,
00117 std::string description) const
00118 {
00119 return colvar_grid<cvm::real>::write_multicol(filename, description);
00120 }
00121
00122 std::ostream & colvar_grid_scalar::write_opendx(std::ostream &os) const
00123 {
00124 return colvar_grid<cvm::real>::write_opendx(os);
00125 }
00126
00127 int colvar_grid_scalar::write_opendx(std::string const &filename,
00128 std::string description) const
00129 {
00130 return colvar_grid<cvm::real>::write_opendx(filename, description);
00131 }
00132
00133
00134 cvm::real colvar_grid_scalar::maximum_value() const
00135 {
00136 cvm::real max = data[0];
00137 for (size_t i = 0; i < nt; i++) {
00138 if (data[i] > max) max = data[i];
00139 }
00140 return max;
00141 }
00142
00143
00144 cvm::real colvar_grid_scalar::minimum_value() const
00145 {
00146 cvm::real min = data[0];
00147 for (size_t i = 0; i < nt; i++) {
00148 if (data[i] < min) min = data[i];
00149 }
00150 return min;
00151 }
00152
00153 cvm::real colvar_grid_scalar::minimum_pos_value() const
00154 {
00155 cvm::real minpos = data[0];
00156 size_t i;
00157 for (i = 0; i < nt; i++) {
00158 if(data[i] > 0) {
00159 minpos = data[i];
00160 break;
00161 }
00162 }
00163 for (i = 0; i < nt; i++) {
00164 if (data[i] > 0 && data[i] < minpos) minpos = data[i];
00165 }
00166 return minpos;
00167 }
00168
00169 cvm::real colvar_grid_scalar::integral() const
00170 {
00171 cvm::real sum = 0.0;
00172 for (size_t i = 0; i < nt; i++) {
00173 sum += data[i];
00174 }
00175 cvm::real bin_volume = 1.0;
00176 for (size_t id = 0; id < widths.size(); id++) {
00177 bin_volume *= widths[id];
00178 }
00179 return bin_volume * sum;
00180 }
00181
00182
00183 cvm::real colvar_grid_scalar::entropy() const
00184 {
00185 cvm::real sum = 0.0;
00186 for (size_t i = 0; i < nt; i++) {
00187 if (data[i] >0) {
00188 sum += -1.0 * data[i] * cvm::logn(data[i]);
00189 }
00190 }
00191 cvm::real bin_volume = 1.0;
00192 for (size_t id = 0; id < widths.size(); id++) {
00193 bin_volume *= widths[id];
00194 }
00195 return bin_volume * sum;
00196 }
00197
00198
00199 colvar_grid_gradient::colvar_grid_gradient()
00200 : colvar_grid<cvm::real>(),
00201 samples(NULL),
00202 weights(NULL)
00203 {}
00204
00205 colvar_grid_gradient::colvar_grid_gradient(std::vector<int> const &nx_i)
00206 : colvar_grid<cvm::real>(nx_i, 0.0, nx_i.size()),
00207 samples(NULL),
00208 weights(NULL)
00209 {}
00210
00211 colvar_grid_gradient::colvar_grid_gradient(std::vector<colvar *> &colvars)
00212 : colvar_grid<cvm::real>(colvars, 0.0, colvars.size()),
00213 samples(NULL),
00214 weights(NULL)
00215 {}
00216
00217
00218 colvar_grid_gradient::colvar_grid_gradient(std::string &filename)
00219 : colvar_grid<cvm::real>(),
00220 samples(NULL),
00221 weights(NULL)
00222 {
00223 std::istream &is = cvm::main()->proxy->input_stream(filename,
00224 "gradient file");
00225 if (!is) {
00226 return;
00227 }
00228
00229
00230
00231
00232 std::string hash;
00233 size_t i;
00234
00235 if ( !(is >> hash) || (hash != "#") ) {
00236 cvm::error("Error reading grid at position "+
00237 cvm::to_str(static_cast<size_t>(is.tellg()))+
00238 " in stream(read \"" + hash + "\")\n");
00239 return;
00240 }
00241
00242 is >> nd;
00243
00244 if (nd > 50) {
00245 cvm::error("Error: excessive number of dimensions in file \""+
00246 filename+"\". Please ensure that the file is not corrupt.\n",
00247 COLVARS_INPUT_ERROR);
00248 return;
00249 }
00250
00251 mult = nd;
00252 std::vector<cvm::real> lower_in(nd), widths_in(nd);
00253 std::vector<int> nx_in(nd);
00254 std::vector<int> periodic_in(nd);
00255
00256 for (i = 0; i < nd; i++ ) {
00257 if ( !(is >> hash) || (hash != "#") ) {
00258 cvm::error("Error reading grid at position "+
00259 cvm::to_str(static_cast<size_t>(is.tellg()))+
00260 " in stream(read \"" + hash + "\")\n");
00261 return;
00262 }
00263
00264 is >> lower_in[i] >> widths_in[i] >> nx_in[i] >> periodic_in[i];
00265 }
00266
00267 this->setup(nx_in, 0., mult);
00268
00269 widths = widths_in;
00270
00271 for (i = 0; i < nd; i++ ) {
00272 lower_boundaries.push_back(colvarvalue(lower_in[i]));
00273 periodic.push_back(static_cast<bool>(periodic_in[i]));
00274 }
00275
00276
00277 is.clear();
00278 is.seekg(0);
00279 read_multicol(is);
00280 cvm::main()->proxy->close_input_stream(filename);
00281 }
00282
00283
00284 std::istream & colvar_grid_gradient::read_multicol(std::istream &is, bool add)
00285 {
00286 return colvar_grid<cvm::real>::read_multicol(is, add);
00287 }
00288
00289 int colvar_grid_gradient::read_multicol(std::string const &filename,
00290 std::string description,
00291 bool add)
00292 {
00293 return colvar_grid<cvm::real>::read_multicol(filename, description, add);
00294 }
00295
00296 std::ostream & colvar_grid_gradient::write_multicol(std::ostream &os) const
00297 {
00298 return colvar_grid<cvm::real>::write_multicol(os);
00299 }
00300
00301 int colvar_grid_gradient::write_multicol(std::string const &filename,
00302 std::string description) const
00303 {
00304 return colvar_grid<cvm::real>::write_multicol(filename, description);
00305 }
00306
00307 std::ostream & colvar_grid_gradient::write_opendx(std::ostream &os) const
00308 {
00309 return colvar_grid<cvm::real>::write_opendx(os);
00310 }
00311
00312 int colvar_grid_gradient::write_opendx(std::string const &filename,
00313 std::string description) const
00314 {
00315 return colvar_grid<cvm::real>::write_opendx(filename, description);
00316 }
00317
00318
00319 void colvar_grid_gradient::write_1D_integral(std::ostream &os)
00320 {
00321 cvm::real bin, min, integral;
00322 std::vector<cvm::real> int_vals;
00323
00324 os << "# xi A(xi)\n";
00325
00326 if (cv.size() != 1) {
00327 cvm::error("Cannot write integral for multi-dimensional gradient grids.");
00328 return;
00329 }
00330
00331 integral = 0.0;
00332 int_vals.push_back(0.0);
00333 min = 0.0;
00334
00335
00336 cvm::real corr;
00337 if (periodic[0]) {
00338 corr = average();
00339 } else {
00340 corr = 0.0;
00341 }
00342
00343 for (std::vector<int> ix = new_index(); index_ok(ix); incr(ix)) {
00344
00345 if (samples) {
00346 size_t const samples_here = samples->value(ix);
00347 if (samples_here)
00348 integral += (value(ix) / cvm::real(samples_here) - corr) * cv[0]->width;
00349 } else {
00350 integral += (value(ix) - corr) * cv[0]->width;
00351 }
00352
00353 if ( integral < min ) min = integral;
00354 int_vals.push_back(integral);
00355 }
00356
00357 bin = 0.0;
00358 for ( int i = 0; i < nx[0]; i++, bin += 1.0 ) {
00359 os << std::setw(10) << cv[0]->lower_boundary.real_value + cv[0]->width * bin << " "
00360 << std::setw(cvm::cv_width)
00361 << std::setprecision(cvm::cv_prec)
00362 << int_vals[i] - min << "\n";
00363 }
00364
00365 os << std::setw(10) << cv[0]->lower_boundary.real_value + cv[0]->width * bin << " "
00366 << std::setw(cvm::cv_width)
00367 << std::setprecision(cvm::cv_prec)
00368 << int_vals[nx[0]] - min << "\n";
00369
00370 return;
00371 }
00372
00373
00374
00375 integrate_potential::integrate_potential(std::vector<colvar *> &colvars, colvar_grid_gradient * gradients)
00376 : colvar_grid_scalar(colvars, true),
00377 gradients(gradients)
00378 {
00379
00380
00381
00382 if (nd > 1) {
00383 cvm::main()->cite_feature("Poisson integration of 2D/3D free energy surfaces");
00384 divergence.resize(nt);
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 }
00402 }
00403
00404
00405 integrate_potential::integrate_potential(colvar_grid_gradient * gradients)
00406 : gradients(gradients)
00407 {
00408 nd = gradients->num_variables();
00409 nx = gradients->number_of_points_vec();
00410 widths = gradients->widths;
00411 periodic = gradients->periodic;
00412
00413
00414 for (size_t i = 0; i < nd; i++ ) {
00415 if (!periodic[i]) nx[i]++;
00416
00417 lower_boundaries.push_back(gradients->lower_boundaries[i].real_value - 0.5 * widths[i]);
00418 }
00419
00420 setup(nx);
00421
00422 if (nd > 1) {
00423 divergence.resize(nt);
00424 }
00425 }
00426
00427
00428 int integrate_potential::integrate(const int itmax, const cvm::real &tol, cvm::real & err)
00429 {
00430 int iter = 0;
00431
00432 if (nd == 1) {
00433
00434 cvm::real sum = 0.0;
00435 cvm::real corr;
00436 if ( periodic[0] ) {
00437 corr = gradients->average();
00438 } else {
00439 corr = 0.0;
00440 }
00441
00442 std::vector<int> ix;
00443
00444 for (ix = new_index(); gradients->index_ok(ix); incr(ix)) {
00445 set_value(ix, sum);
00446 sum += (gradients->value_output(ix) - corr) * widths[0];
00447 }
00448 if (index_ok(ix)) {
00449
00450 set_value(ix, sum);
00451 }
00452
00453 } else if (nd <= 3) {
00454
00455 nr_linbcg_sym(divergence, data, tol, itmax, iter, err);
00456 cvm::log("Integrated in " + cvm::to_str(iter) + " steps, error: " + cvm::to_str(err) + "\n");
00457
00458 } else {
00459 cvm::error("Cannot integrate PMF in dimension > 3\n");
00460 }
00461
00462 return iter;
00463 }
00464
00465
00466 void integrate_potential::set_div()
00467 {
00468 if (nd == 1) return;
00469 for (std::vector<int> ix = new_index(); index_ok(ix); incr(ix)) {
00470 update_div_local(ix);
00471 }
00472 }
00473
00474
00475 void integrate_potential::update_div_neighbors(const std::vector<int> &ix0)
00476 {
00477 std::vector<int> ix(ix0);
00478 int i, j, k;
00479
00480
00481 if (nd == 1) {
00482 return;
00483
00484 } else if (nd == 2) {
00485
00486 update_div_local(ix);
00487 ix[0]++; wrap(ix);
00488 update_div_local(ix);
00489 ix[1]++; wrap(ix);
00490 update_div_local(ix);
00491 ix[0]--; wrap(ix);
00492 update_div_local(ix);
00493
00494 } else if (nd == 3) {
00495
00496 for (i = 0; i<2; i++) {
00497 ix[1] = ix0[1];
00498 for (j = 0; j<2; j++) {
00499 ix[2] = ix0[2];
00500 for (k = 0; k<2; k++) {
00501 wrap(ix);
00502 update_div_local(ix);
00503 ix[2]++;
00504 }
00505 ix[1]++;
00506 }
00507 ix[0]++;
00508 }
00509 }
00510 }
00511
00512 void integrate_potential::get_grad(cvm::real * g, std::vector<int> &ix)
00513 {
00514 size_t count, i;
00515 bool edge = gradients->wrap_edge(ix);
00516
00517 if (gradients->samples) {
00518 count = gradients->samples->value(ix);
00519 } else {
00520 count = 1;
00521 }
00522
00523 if (!edge && count) {
00524 cvm::real const *grad = &(gradients->value(ix));
00525 cvm::real const fact = 1.0 / count;
00526 for ( i = 0; i<nd; i++ ) {
00527 g[i] = fact * grad[i];
00528 }
00529 } else {
00530 for ( i = 0; i<nd; i++ ) {
00531 g[i] = 0.0;
00532 }
00533 }
00534 }
00535
00536 void integrate_potential::update_div_local(const std::vector<int> &ix0)
00537 {
00538 const size_t linear_index = address(ix0);
00539 int i, j, k;
00540 std::vector<int> ix = ix0;
00541
00542 if (nd == 2) {
00543
00544 cvm::real g00[2], g01[2], g10[2], g11[2];
00545
00546 get_grad(g11, ix);
00547 ix[0] = ix0[0] - 1;
00548 get_grad(g01, ix);
00549 ix[1] = ix0[1] - 1;
00550 get_grad(g00, ix);
00551 ix[0] = ix0[0];
00552 get_grad(g10, ix);
00553
00554 divergence[linear_index] = ((g10[0]-g00[0] + g11[0]-g01[0]) / widths[0]
00555 + (g01[1]-g00[1] + g11[1]-g10[1]) / widths[1]) * 0.5;
00556 } else if (nd == 3) {
00557 cvm::real gc[24];
00558 int index = 0;
00559
00560 ix[0] = ix0[0] - 1;
00561 for (i = 0; i<2; i++) {
00562 ix[1] = ix0[1] - 1;
00563 for (j = 0; j<2; j++) {
00564 ix[2] = ix0[2] - 1;
00565 for (k = 0; k<2; k++) {
00566 get_grad(gc + index, ix);
00567 index += 3;
00568 ix[2]++;
00569 }
00570 ix[1]++;
00571 }
00572 ix[0]++;
00573 }
00574
00575 divergence[linear_index] =
00576 ((gc[3*4]-gc[0] + gc[3*5]-gc[3*1] + gc[3*6]-gc[3*2] + gc[3*7]-gc[3*3])
00577 / widths[0]
00578 + (gc[3*2+1]-gc[0+1] + gc[3*3+1]-gc[3*1+1] + gc[3*6+1]-gc[3*4+1] + gc[3*7+1]-gc[3*5+1])
00579 / widths[1]
00580 + (gc[3*1+2]-gc[0+2] + gc[3*3+2]-gc[3*2+2] + gc[3*5+2]-gc[3*4+2] + gc[3*7+2]-gc[3*6+2])
00581 / widths[2]) * 0.25;
00582 }
00583 }
00584
00585
00588 void integrate_potential::atimes(const std::vector<cvm::real> &A, std::vector<cvm::real> &LA)
00589 {
00590 if (nd == 2) {
00591
00592
00593 size_t index, index2;
00594 int i, j;
00595 cvm::real fact;
00596 const cvm::real ffx = 1.0 / (widths[0] * widths[0]);
00597 const cvm::real ffy = 1.0 / (widths[1] * widths[1]);
00598 const int h = nx[1];
00599 const int w = nx[0];
00600
00601 int xm = -h;
00602 int xp = h;
00603 int ym = -1;
00604 int yp = 1;
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 index = h;
00616
00617
00618
00619 fact = periodic[1] ? 1.0 : 0.5;
00620
00621 for (i=1; i<w-1; i++) {
00622
00623 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00624 index++;
00625 for (j=1; j<h-1; j++) {
00626 LA[index] = ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00627 index++;
00628 }
00629 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00630 index++;
00631 }
00632
00633 index = 0L;
00634 index2 = h * static_cast<size_t>(w - 1);
00635 if (periodic[0]) {
00636 xm = h * (w - 1);
00637 xp = h;
00638 fact = periodic[1] ? 1.0 : 0.5;
00639 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00640 LA[index2] = fact * ffx * (A[index2 - xp] + A[index2 - xm] - 2.0 * A[index2]);
00641 index++;
00642 index2++;
00643 for (j=1; j<h-1; j++) {
00644 LA[index] = ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00645 LA[index2] = ffx * (A[index2 - xp] + A[index2 - xm] - 2.0 * A[index2]);
00646 index++;
00647 index2++;
00648 }
00649 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00650 LA[index2] = fact * ffx * (A[index2 - xp] + A[index2 - xm] - 2.0 * A[index2]);
00651 } else {
00652 xm = -h;
00653 xp = h;
00654 fact = periodic[1] ? 1.0 : 0.5;
00655
00656 LA[index] = fact * ffx * (A[index + xp] - A[index]);
00657 LA[index2] = fact * ffx * (A[index2 + xm] - A[index2]);
00658 index++;
00659 index2++;
00660 for (j=1; j<h-1; j++) {
00661
00662 LA[index] = ffx * (A[index + xp] - A[index]);
00663 LA[index2] = ffx * (A[index2 + xm] - A[index2]);
00664 index++;
00665 index2++;
00666 }
00667
00668 LA[index] = fact * ffx * (A[index + xp] - A[index]);
00669 LA[index2] = fact * ffx * (A[index2 + xm] - A[index2]);
00670 }
00671
00672
00673
00674 index = 1;
00675
00676 fact = periodic[0] ? 1.0 : 0.5;
00677 for (i=0; i<w; i++) {
00678
00679 if (i == 1) fact = 1.0;
00680 if (i == w - 1) fact = periodic[0] ? 1.0 : 0.5;
00681 for (j=1; j<h-1; j++) {
00682 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00683 index++;
00684 }
00685 index += 2;
00686 }
00687
00688 index = 0L;
00689 index2 = h - 1;
00690 if (periodic[1]) {
00691 fact = periodic[0] ? 1.0 : 0.5;
00692 ym = h - 1;
00693 yp = 1;
00694 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00695 LA[index2] += fact * ffy * (A[index2 - yp] + A[index2 - ym] - 2.0 * A[index2]);
00696 index += h;
00697 index2 += h;
00698 for (i=1; i<w-1; i++) {
00699 LA[index] += ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00700 LA[index2] += ffy * (A[index2 - yp] + A[index2 - ym] - 2.0 * A[index2]);
00701 index += h;
00702 index2 += h;
00703 }
00704 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00705 LA[index2] += fact * ffy * (A[index2 - yp] + A[index2 - ym] - 2.0 * A[index2]);
00706 } else {
00707 ym = -1;
00708 yp = 1;
00709 fact = periodic[0] ? 1.0 : 0.5;
00710
00711 LA[index] += fact * ffy * (A[index + yp] - A[index]);
00712 LA[index2] += fact * ffy * (A[index2 + ym] - A[index2]);
00713 index += h;
00714 index2 += h;
00715 for (i=1; i<w-1; i++) {
00716
00717 LA[index] += ffy * (A[index + yp] - A[index]);
00718 LA[index2] += ffy * (A[index2 + ym] - A[index2]);
00719 index += h;
00720 index2 += h;
00721 }
00722
00723 LA[index] += fact * ffy * (A[index + yp] - A[index]);
00724 LA[index2] += fact * ffy * (A[index2 + ym] - A[index2]);
00725 }
00726
00727 } else if (nd == 3) {
00728
00729
00730 int i, j, k;
00731 size_t index, index2;
00732 cvm::real fact = 1.0;
00733 const cvm::real ffx = 1.0 / (widths[0] * widths[0]);
00734 const cvm::real ffy = 1.0 / (widths[1] * widths[1]);
00735 const cvm::real ffz = 1.0 / (widths[2] * widths[2]);
00736 const int h = nx[2];
00737 const int d = nx[1];
00738 const int w = nx[0];
00739
00740 int xm = -d * h;
00741 int xp = d * h;
00742 int ym = -h;
00743 int yp = h;
00744 int zm = -1;
00745 int zp = 1;
00746
00747 cvm::real factx = periodic[0] ? 1 : 0.5;
00748 cvm::real facty = periodic[1] ? 1 : 0.5;
00749 cvm::real factz = periodic[2] ? 1 : 0.5;
00750 cvm::real ifactx = 1 / factx;
00751 cvm::real ifacty = 1 / facty;
00752 cvm::real ifactz = 1 / factz;
00753
00754
00755 index = d * static_cast<size_t>(h);
00756 fact = facty * factz;
00757 for (i=1; i<w-1; i++) {
00758 for (j=0; j<d; j++) {
00759 if (j == 1) fact *= ifacty;
00760 if (j == d-1) fact *= facty;
00761 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00762 index++;
00763 fact *= ifactz;
00764 for (k=1; k<h-1; k++) {
00765 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00766 index++;
00767 }
00768 fact *= factz;
00769 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00770 index++;
00771 }
00772 }
00773
00774 index = 0L;
00775 index2 = static_cast<size_t>(d) * h * (w - 1);
00776 if (periodic[0]) {
00777 xm = d * h * (w - 1);
00778 xp = d * h;
00779 fact = facty * factz;
00780 for (j=0; j<d; j++) {
00781 if (j == 1) fact *= ifacty;
00782 if (j == d-1) fact *= facty;
00783 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00784 LA[index2] = fact * ffx * (A[index2 - xp] + A[index2 - xm] - 2.0 * A[index2]);
00785 index++;
00786 index2++;
00787 fact *= ifactz;
00788 for (k=1; k<h-1; k++) {
00789 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00790 LA[index2] = fact * ffx * (A[index2 - xp] + A[index2 - xm] - 2.0 * A[index2]);
00791 index++;
00792 index2++;
00793 }
00794 fact *= factz;
00795 LA[index] = fact * ffx * (A[index + xm] + A[index + xp] - 2.0 * A[index]);
00796 LA[index2] = fact * ffx * (A[index2 - xp] + A[index2 - xm] - 2.0 * A[index2]);
00797 index++;
00798 index2++;
00799 }
00800 } else {
00801 xm = -d * h;
00802 xp = d * h;
00803 fact = facty * factz;
00804 for (j=0; j<d; j++) {
00805 if (j == 1) fact *= ifacty;
00806 if (j == d-1) fact *= facty;
00807 LA[index] = fact * ffx * (A[index + xp] - A[index]);
00808 LA[index2] = fact * ffx * (A[index2 + xm] - A[index2]);
00809 index++;
00810 index2++;
00811 fact *= ifactz;
00812 for (k=1; k<h-1; k++) {
00813
00814 LA[index] = fact * ffx * (A[index + xp] - A[index]);
00815 LA[index2] = fact * ffx * (A[index2 + xm] - A[index2]);
00816 index++;
00817 index2++;
00818 }
00819 fact *= factz;
00820 LA[index] = fact * ffx * (A[index + xp] - A[index]);
00821 LA[index2] = fact * ffx * (A[index2 + xm] - A[index2]);
00822 index++;
00823 index2++;
00824 }
00825 }
00826
00827
00828
00829 index = h;
00830 fact = factx * factz;
00831 for (i=0; i<w; i++) {
00832 if (i == 1) fact *= ifactx;
00833 if (i == w-1) fact *= factx;
00834 for (j=1; j<d-1; j++) {
00835 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00836 index++;
00837 fact *= ifactz;
00838 for (k=1; k<h-1; k++) {
00839 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00840 index++;
00841 }
00842 fact *= factz;
00843 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00844 index++;
00845 }
00846 index += 2 * h;
00847 }
00848
00849 index = 0L;
00850 index2 = h * static_cast<size_t>(d - 1);
00851 if (periodic[1]) {
00852 ym = h * (d - 1);
00853 yp = h;
00854 fact = factx * factz;
00855 for (i=0; i<w; i++) {
00856 if (i == 1) fact *= ifactx;
00857 if (i == w-1) fact *= factx;
00858 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00859 LA[index2] += fact * ffy * (A[index2 - yp] + A[index2 - ym] - 2.0 * A[index2]);
00860 index++;
00861 index2++;
00862 fact *= ifactz;
00863 for (k=1; k<h-1; k++) {
00864 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00865 LA[index2] += fact * ffy * (A[index2 - yp] + A[index2 - ym] - 2.0 * A[index2]);
00866 index++;
00867 index2++;
00868 }
00869 fact *= factz;
00870 LA[index] += fact * ffy * (A[index + ym] + A[index + yp] - 2.0 * A[index]);
00871 LA[index2] += fact * ffy * (A[index2 - yp] + A[index2 - ym] - 2.0 * A[index2]);
00872 index++;
00873 index2++;
00874 index += h * static_cast<size_t>(d - 1);
00875 index2 += h * static_cast<size_t>(d - 1);
00876 }
00877 } else {
00878 ym = -h;
00879 yp = h;
00880 fact = factx * factz;
00881 for (i=0; i<w; i++) {
00882 if (i == 1) fact *= ifactx;
00883 if (i == w-1) fact *= factx;
00884 LA[index] += fact * ffy * (A[index + yp] - A[index]);
00885 LA[index2] += fact * ffy * (A[index2 + ym] - A[index2]);
00886 index++;
00887 index2++;
00888 fact *= ifactz;
00889 for (k=1; k<h-1; k++) {
00890
00891 LA[index] += fact * ffy * (A[index + yp] - A[index]);
00892 LA[index2] += fact * ffy * (A[index2 + ym] - A[index2]);
00893 index++;
00894 index2++;
00895 }
00896 fact *= factz;
00897 LA[index] += fact * ffy * (A[index + yp] - A[index]);
00898 LA[index2] += fact * ffy * (A[index2 + ym] - A[index2]);
00899 index++;
00900 index2++;
00901 index += h * static_cast<size_t>(d - 1);
00902 index2 += h * static_cast<size_t>(d - 1);
00903 }
00904 }
00905
00906
00907
00908 index = 1;
00909 fact = factx * facty;
00910 for (i=0; i<w; i++) {
00911 if (i == 1) fact *= ifactx;
00912 if (i == w-1) fact *= factx;
00913 for (k=1; k<h-1; k++) {
00914 LA[index] += fact * ffz * (A[index + zm] + A[index + zp] - 2.0 * A[index]);
00915 index++;
00916 }
00917 fact *= ifacty;
00918 index += 2;
00919 for (j=1; j<d-1; j++) {
00920 for (k=1; k<h-1; k++) {
00921 LA[index] += fact * ffz * (A[index + zm] + A[index + zp] - 2.0 * A[index]);
00922 index++;
00923 }
00924 index += 2;
00925 }
00926 fact *= facty;
00927 for (k=1; k<h-1; k++) {
00928 LA[index] += fact * ffz * (A[index + zm] + A[index + zp] - 2.0 * A[index]);
00929 index++;
00930 }
00931 index += 2;
00932 }
00933
00934 index = 0;
00935 index2 = h - 1;
00936 if (periodic[2]) {
00937 zm = h - 1;
00938 zp = 1;
00939 fact = factx * facty;
00940 for (i=0; i<w; i++) {
00941 if (i == 1) fact *= ifactx;
00942 if (i == w-1) fact *= factx;
00943 LA[index] += fact * ffz * (A[index + zm] + A[index + zp] - 2.0 * A[index]);
00944 LA[index2] += fact * ffz * (A[index2 - zp] + A[index2 - zm] - 2.0 * A[index2]);
00945 index += h;
00946 index2 += h;
00947 fact *= ifacty;
00948 for (j=1; j<d-1; j++) {
00949 LA[index] += fact * ffz * (A[index + zm] + A[index + zp] - 2.0 * A[index]);
00950 LA[index2] += fact * ffz * (A[index2 - zp] + A[index2 - zm] - 2.0 * A[index2]);
00951 index += h;
00952 index2 += h;
00953 }
00954 fact *= facty;
00955 LA[index] += fact * ffz * (A[index + zm] + A[index + zp] - 2.0 * A[index]);
00956 LA[index2] += fact * ffz * (A[index2 - zp] + A[index2 - zm] - 2.0 * A[index2]);
00957 index += h;
00958 index2 += h;
00959 }
00960 } else {
00961 zm = -1;
00962 zp = 1;
00963 fact = factx * facty;
00964 for (i=0; i<w; i++) {
00965 if (i == 1) fact *= ifactx;
00966 if (i == w-1) fact *= factx;
00967 LA[index] += fact * ffz * (A[index + zp] - A[index]);
00968 LA[index2] += fact * ffz * (A[index2 + zm] - A[index2]);
00969 index += h;
00970 index2 += h;
00971 fact *= ifacty;
00972 for (j=1; j<d-1; j++) {
00973
00974 LA[index] += fact * ffz * (A[index + zp] - A[index]);
00975 LA[index2] += fact * ffz * (A[index2 + zm] - A[index2]);
00976 index += h;
00977 index2 += h;
00978 }
00979 fact *= facty;
00980 LA[index] += fact * ffz * (A[index + zp] - A[index]);
00981 LA[index2] += fact * ffz * (A[index2 + zm] - A[index2]);
00982 index += h;
00983 index2 += h;
00984 }
00985 }
00986 }
00987 }
00988
00989
00990
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 void integrate_potential::nr_linbcg_sym(const std::vector<cvm::real> &b, std::vector<cvm::real> &x, const cvm::real &tol,
01005 const int itmax, int &iter, cvm::real &err)
01006 {
01007 cvm::real ak,akden,bk,bkden,bknum,bnrm;
01008 const cvm::real EPS=1.0e-14;
01009 int j;
01010 std::vector<cvm::real> p(nt), r(nt), z(nt);
01011
01012 iter=0;
01013 atimes(x,r);
01014 for (j=0;j<int(nt);j++) {
01015 r[j]=b[j]-r[j];
01016 }
01017 bnrm=l2norm(b);
01018 if (bnrm < EPS) {
01019 return;
01020 }
01021
01022 bkden = 1.0;
01023 while (iter < itmax) {
01024 ++iter;
01025 for (bknum=0.0,j=0;j<int(nt);j++) {
01026 bknum += r[j]*r[j];
01027 }
01028 if (iter == 1) {
01029 for (j=0;j<int(nt);j++) {
01030 p[j] = r[j];
01031 }
01032 } else {
01033 bk=bknum/bkden;
01034 for (j=0;j<int(nt);j++) {
01035 p[j] = bk*p[j] + r[j];
01036 }
01037 }
01038 bkden = bknum;
01039 atimes(p,z);
01040 for (akden=0.0,j=0;j<int(nt);j++) {
01041 akden += z[j]*p[j];
01042 }
01043 ak = bknum/akden;
01044 for (j=0;j<int(nt);j++) {
01045 x[j] += ak*p[j];
01046 r[j] -= ak*z[j];
01047 }
01048
01049 err = l2norm(r)/bnrm;
01050 if (cvm::debug())
01051 std::cout << "iter=" << std::setw(4) << iter+1 << std::setw(12) << err << std::endl;
01052 if (err <= tol)
01053 break;
01054 }
01055 }
01056
01057 cvm::real integrate_potential::l2norm(const std::vector<cvm::real> &x)
01058 {
01059 size_t i;
01060 cvm::real sum = 0.0;
01061 for (i=0;i<x.size();i++)
01062 sum += x[i]*x[i];
01063 return sqrt(sum);
01064 }