MADNESS  version 0.9
svpe_molecule_colloid.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 
31  $Id$
32 */
33 #ifndef SVPE_MOLECULE_COLLOID_H
34 #define SVPE_MOLECULE_COLLOID_H
35 
36 #include <madness/mra/mra.h>
37 #include <madness/mra/operator.h>
38 #include <madness/mra/funcplot.h>
39 #include <madness/tensor/solvers.h>
40 #include <examples/molecularmask.h>
41 #include <examples/nonlinsol.h>
42 #include <madness/constants.h>
43 #include <vector>
44 
45 using namespace madness;
46 using namespace std;
47 
48 //set coordinates of colloid atoms
49 std::vector< madness::Vector<double,3> > colloid_coords(const double&d,const double R,const std::vector<double> cc) {
50  int nsphere = 1;
51  std::vector< madness::Vector<double,3> > c(nsphere, madness::Vector<double,3>(0.0)); //6 spheres on the colloid surface
52  /* double sqrttwo = std::sqrt(2.0);
53  double dist= (sqrttwo/2.0)*R */
54  double x = cc[0], y = cc[1], z = cc[2];
55 /* c[0][0]= x - R, c[0][1]= y - d - 2.0*R, c[0][2] = z; //A base sphere
56  c[1][0]= x , c[1][1]= y - d - R, c[1][2] = z; //B base sphere
57  c[2][0]= x + R, c[2][1]= y - d + 2.0*R, c[2][2] = z; //C base sphere
58  c[3][0]= x , c[3][1]= y - d + 3.0*R, c[3][2] = z; //D base spheres
59  c[4][0]= x , c[4][1]= y - d - 2.0*R , c[4][2] = z - R; //E bottom sphere
60  c[5][0]= x , c[5][1]= y - d - 2.0*R, c[5][2] = z + R;*/ // top sphere
61  c[0][0]= x, c[0][1]= y - R - d , c[0][2] = z;// for a single sphere
62  return c;
63 }
64 /*std::vector< madness::Vector<double,3> > colloid_coordss(const double&d,const double R,std::vector<double> cc) {
65  std::vector< madness::Vector<double,3> > c(16,madness::Vector<double,3>(0,0)); //16 spheres on the colloid surface
66  double sqrttwo = std::sqrt(2.0);
67  double dist= (R/sqrttwo);
68  double x = cc[0], y = cc[1], z = cc[2];
69  c[0][0]= x - dist, c[0][1]= y - dist, c[0][2] = z-d-R; //A
70  c[1][0]= x - dist, c[1][1]= y + dist, c[1][2] = z-d-R; //B
71  c[2][0]= x + dist, c[2][1]= y + dist, c[2][2] = z-d-R; //C
72  c[3][0]= x + dist, c[3][1]= y - dist, c[3][2] = z-d-R; //D
73  c[4][0]= x + dist, c[4][1]= y + 2.0*R - dist, c[4][2] = z-d-R; //C'
74  c[5][0]= x + dist + 2.0*R, c[5][1]= y + dist, c[5][2] = z-d-R; //C"
75  c[6][0]= x + 2.0*R + dist , c[6][1]= y + 2.0*R + dist, c[6][2] = z-d-R;//C'"
76  c[7][0]= x - dist , c[7][1]= y + 2.0*R + dist, c[7][2] = z-d-R; //B'
77  c[8][0]= x - 2.0*R - dist , c[8][1]= y + dist, c[8][2] = z-d-R; //B"
78  c[9][0]= x - 2.0*R - dist , c[9][1]= y + 2.0*R + dist, c[9][2] = z-d-R; //B"'
79  c[10][0]= x - dist , c[10][1]= y - 2.0*R - dist, c[10][2] = z-d-R; //A'
80  c[11][0]= x - 2.0*R - dist , c[11][1]= y - 2.0*R - dist, c[11][2] = z-d-R; //A"
81  c[12][0]= x - 2.0*R - dist , c[12][1]= y - dist, c[12][2] = z-d-R; //A"'
82  c[13][0]= x + 2.0*R + dist , c[13][1]= y - dist, c[13][2] = z-d-R; //D'
83  c[14][0]= x + 2.0*R + dist , c[14][1]= y - 2.0*R - dist, c[14][2] = z-d-R; //D"
84  c[15][0]= x + dist , c[15][1]= y - 2.0*R - dist, c[15][2] = z-d-R; //D'"
85  return c;
86 }*/
87 
88 //colloid radii
89 //if number of colloid spheres changes don't forget to change it here
90 std::vector<double> colloid_radii(const double& R) {
91  int nsphere = 1; //number of colloid spheres
92  std::vector<double> c(nsphere,0.0);
93  for(int i=0; i<nsphere; i++)
94  c[i] = R;
95  return c;
96 }
97 
99  World& world;
100  const double thresh;
101  const double minlen;
102  const double sigma; //< Width of surface layer
103  const double epsilon_0; //< Interior dielectric
104  const double epsilon_1; //< Exterior dielectric
105  real_convolution_3d op; //< Coulomb operator (1/r ... no 4pi)
106  //std::vector<real_convolution_3d_ptr> gop; //< Gradient of the Coulomb operator
107  vector_real_function_3d dlog; //< Log-derivative of the dielectric
108  real_function_3d rdielectric; //< Reciprocal of the dielectric
109  real_function_3d volume; //< volume function of the sphere/colloid
110  double L; //<half lenght of the simulation volume
111  // vector_real_function_3d Eind; //<surface induced electric
112  const int maxiter;
113  static const double cutrho = 1e-12; //cutoff value of the surface charge
114  //this is used to perform a pointwise multiplication
115  struct Bop {
116  void operator()(const Key<3>& key,
117  real_tensor rfunc,
118  const real_tensor& func1,
119  const real_tensor& func2) const {
120  ITERATOR(rfunc,
121  double d = func1(IND);
122  double p = func2(IND);
123  rfunc(IND) = d*p;
124  );
125  }
126  template <typename Archive>
127  void serialize(Archive& ar) {}
128  };
129  real_function_3d func_pdt(const real_function_3d& func1,real_function_3d& func2) const {
130  return binary_op(func1,func2, Bop());
131  }
132 public:
134  double sigma, double epsilon_0, double epsilon_1,
135  const vector_real& atomic_radii, const vector_coord_3d& atomic_coords,
136  const double minlen,double L, const int maxiter)
137  :world(world)
138  ,thresh(FunctionDefaults<3>::get_thresh())
139  , minlen(minlen)
140  , sigma(sigma)
141  , epsilon_0(epsilon_0)
142  , epsilon_1(epsilon_1)
143  , op(CoulombOperator(world, minlen, thresh))
144  , dlog(3)
145  ,L(L)
146  , maxiter(maxiter)
147  {
148  MADNESS_ASSERT(atomic_radii.size() == atomic_coords.size());//check on the consistency
149  // Functors for mask related quantities
150  real_functor_3d rdielectric_functor(new MolecularVolumeExponentialSwitchReciprocal(sigma,epsilon_0,epsilon_1,atomic_radii,atomic_coords));
151  real_functor_3d gradx_functor(new MolecularVolumeExponentialSwitchLogGrad(sigma, epsilon_0, epsilon_1, atomic_radii, atomic_coords,0));
152  real_functor_3d grady_functor(new MolecularVolumeExponentialSwitchLogGrad(sigma, epsilon_0, epsilon_1, atomic_radii, atomic_coords,1));
153  real_functor_3d gradz_functor(new MolecularVolumeExponentialSwitchLogGrad(sigma, epsilon_0, epsilon_1, atomic_radii, atomic_coords,2));
154  real_functor_3d volume_functor(new MolecularVolumeMask(sigma,atomic_radii, atomic_coords));
155  // Make the actual functions
156  // const double rfourpi = 1.0/(4.0*constants::pi);
157  rdielectric = real_factory_3d(world).functor(rdielectric_functor).nofence();
158  volume = real_factory_3d(world).functor(volume_functor).nofence();
159  dlog[0] = real_factory_3d(world).functor(gradx_functor).nofence().truncate_on_project();
160  dlog[1] = real_factory_3d(world).functor(grady_functor).nofence().truncate_on_project();
161  dlog[2] = real_factory_3d(world).functor(gradz_functor).truncate_on_project(); // FENCE
162  // scale(world, dlog, rfourpi);
163  rdielectric.truncate(false);
164  truncate(world, dlog);
165  }
166 
167  // Given the full Coulomb potential computes the surface charge
169  real_derivative_3d Dx = free_space_derivative<double,3>(world, 0);
170  real_derivative_3d Dy = free_space_derivative<double,3>(world, 1);
171  real_derivative_3d Dz = free_space_derivative<double,3>(world, 2);
172  //double fac = -1.0/(4.0*constants::pi);
173  real_function_3d dx = Dx(u);
174  real_function_3d dy = Dy(u);
175  real_function_3d dz = Dz(u);
176  real_function_3d sc = func_pdt(dlog[0],dx).truncate() + func_pdt(dlog[1],dy).truncate() + func_pdt(dlog[2],dz).truncate();
177  //coord_3d lo,hi;
178  //lo[1]=-L, hi[1]=L;
179  //plot_line("colloid_surf_charge.dat", 1001, lo, hi, sc);
180  return sc; //.scale(fac);
181  }
182  // Given the full Laplace potential compute the surface charge
183  real_function_3d make_Laplace_surface_charge(const real_function_3d& u,std::vector<double> E=std::vector<double>(3,0.0)) const {
184  real_derivative_3d Dx = free_space_derivative<double,3>(world, 0);
185  real_derivative_3d Dy = free_space_derivative<double,3>(world, 1);
186  real_derivative_3d Dz = free_space_derivative<double,3>(world, 2);
187  //double fac = -1.0/(4.0*constants::pi);
188  real_function_3d dx = -E[0] + Dx(u);
189  real_function_3d dy = -E[1] + Dy(u);
190  real_function_3d dz = -E[2] + Dz(u);
191  real_function_3d sc = func_pdt(dlog[0],dx).truncate() + func_pdt(dlog[1],dy).truncate() + func_pdt(dlog[2],dz).truncate();
192  return sc;
193  }
194  //computes components of the the electric field due to the surface charge
196  // throw "not correct";
197  vector_real_function_3d E(3);// = madness::vector_factory(0.0, 0.0 ,0.0);
198  real_derivative_3d Dx = free_space_derivative<double,3>(u.world(), 0);
199  real_derivative_3d Dy = free_space_derivative<double,3>(u.world(), 1);
200  real_derivative_3d Dz = free_space_derivative<double,3>(u.world(), 2);
201  double fac = -1.0/(4.0*constants::pi);
202  real_function_3d Sigmax =(Dx(u)).scale(fac), Sigmay = (Dy(u)).scale(fac),Sigmaz = (Dz(u)).scale(fac); //excess charge on colloid surface
203  coord_3d lo(0.0),hi(0.0);
204  lo[1]=-L, hi[1]=L;
205  plot_line("ab_sigma.dat", 1001, hi, lo, Sigmax, Sigmay, Sigmaz);
206  E[0] = Dx(op(Sigmax)), E[1] = Dy(op(Sigmay)), E[2] = Dz(op(Sigmaz)) ;
207  return E;
208  }
209 
212  const double fac = -1.0/(4.0*constants::pi);
213  real_function_3d charge = (rdielectric*rho).scale(-1.0);
214 
215  // Initial guess is constant dielectric
216  real_function_3d u0 = op(charge);//.truncate();
217  //real_function_3d u = uguess.is_initialized() ? uguess : u0;
218  real_function_3d u = u0; // op(rho); ?? RJH
219  double unorm = u.norm2();
220  if (world.rank()==0)
221  print("UNORM IS", unorm);
222  NonlinearSolver solver;
223  if (world.rank()==0){
224  print("\n\n");//for formating output
225  madness::print(" Computing the Perturbed Potential (due to molecule) ");
226  madness::print(" Near the Colloid Surface ");
227  madness::print(" ______________________ \n ");
228  }
229  for (int iter=0; iter<maxiter; iter++) {
230  double start = wall_time();
231  real_function_3d surface_charge = make_surface_charge(u);
232  real_function_3d r = (u - u0 - op(surface_charge).scale(fac)).truncate(.032*FunctionDefaults<3>::get_thresh());
233  double sigtot = surface_charge.trace()*fac;
234  //surface_charge.clear();
235  // u0.clear();
236  real_function_3d unew = solver.update(u,r);
237  double change = (unew-u).norm2();//volume.trace(); //times 1000 when not in solvent
238  if(world.rank()==0){
239  print("iter", iter, "change", change,
240  "soln(10.0)", u(coord_3d(10.0)),
241  "surface charge", sigtot,"used",wall_time()-start);
242 
243  }
244  // Step restriction
245  if (change > 0.3*unorm)
246  u = 0.5*unew + 0.5*u;
247  else
248  u = unew;
249  //if (change < std::max(1e-4,10.0*thresh/volume.trace())) break;
250  if (change < 10.0*thresh) break;
251  }
252  if(world.rank()==0)
253  print("\n\n");//format printing
254  real_function_3d urxn = op(make_surface_charge(u)).scale(fac);//u - op(rho);
255  coord_3d lo,hi;
256  lo[1]=-L, hi[1]=L;
257  plot_line("colloid_rxn_pot.dat", 1001, lo, hi, urxn);
258  plot_line("colloid_surfcharge.dat", 1001, lo, hi, make_surface_charge(urxn).scale(fac));
259  //real_tensor cell(3,2);
260  // cell(_,0) = -L;
261  //cell(_,1) = L;
262  // plotdx(volume, "testpot.dx", cell);
263  return urxn;
264  }
266  real_function_3d solve_Laplace(std::vector<double>E) const {
267  // Initial guess is constant dielectric
268  const double fac = -1.0/(4.0*constants::pi);
269  real_function_3d u(world);// guess pot is zero;
270  double unorm = 0.0;//u.norm2();
271  NonlinearSolver solver;
272  //print for formating
273  if (world.rank()==0){
274  print("\n\n");//for formating output
275  madness::print(" Computing the Perturbed Potential (due to external field) ");
276  madness::print(" ______________________ \n ");
277  }
278  for (int iter=0; iter<maxiter; iter++) {
279  double start = wall_time();
280  real_function_3d surface_charge = make_Laplace_surface_charge(u,E);
281  real_function_3d r = (u - op(surface_charge).scale(fac)).truncate(.032*FunctionDefaults<3>::get_thresh());
282  double sigtot = surface_charge.trace()*fac;
283  //surface_charge.clear();
284  real_function_3d unew = solver.update(u, r);
285  double change = (unew-u).norm2();//volume.trace();///(8.0*std::pow(L,3.0));
286  if (world.rank()==0){
287  print("iter", iter, "change", change,
288  "soln(10.0)", u(coord_3d(10.0)),
289  "surface charge", sigtot,"used",wall_time()-start);
290  }
291  // Step restriction
292  if (change > 0.3*unorm)
293  u = 0.5*unew + 0.5*u;
294  else
295  u = unew;
296 
297  if (change < std::min(1e-4,10.0*thresh)) break;
298  }
299  if (world.rank()==0)
300  print("\n\n");
301  coord_3d lo,hi;
302  lo[1]=-L, hi[1]= L;
303  plot_line("laplace_surfcharge.dat", 1001, lo, hi, make_Laplace_surface_charge(u,E).scale(fac));
304  plot_line("laplace_pot.dat", 1001, lo, hi, u);
305  return u;
306  }
307  //calculate the average reaction field(\int C(r)F_r(r)d \tau/\int C(r)d\tau
308  //the mask is that of the molecule because the average field is that felt by the molecule
309  double ave_rxn_field(const real_function_3d& u,const real_function_3d& mask)const {
310  real_function_3d pdtx = mask*make_electric_field(u)[0];
311  real_function_3d pdty = mask*make_electric_field(u)[1];
312  real_function_3d pdtz = mask*make_electric_field(u)[2];
313  double numx = pdtx.trace(), numy = pdty.trace(), numz = pdtz.trace();
314  double denominator = mask.trace();
315  double Favx = numx/denominator, Favy = numy/denominator,Favz = numz/denominator;
316  return std::sqrt(std::pow(Favx,2.0) + std::pow(Favy,2.0) + std::pow(Favz,2.0));
317  }
318 };
319 
320 #endif
321 
const double thresh
Definition: dielectric.cc:185
A simple Krylov-subspace nonlinear equation solver.
Definition: nonlinsol.h:91
#define ITERATOR(t, exp)
Definition: tensor_macros.h:249
real_function_3d solve(const real_function_3d &rho) const
Solve for the full Coulomb potential using the free-particle GF.
Definition: svpe_molecule_colloid.h:211
Definition: shared_ptr_bits.h:38
const double pi
Mathematical constant pi.
Definition: constants.h:44
real_function_3d solve_Laplace(std::vector< double >E) const
Solve for the full Coulomb potential using the free-particle GF.
Definition: svpe_molecule_colloid.h:266
Main include file for MADNESS and defines Function interface.
Function< T, NDIM > & truncate(double tol=0.0, bool fence=true)
Truncate the function with optional fence. Compresses with fence if not compressed.
Definition: mra.h:577
#define IND
Definition: tensor_macros.h:204
FunctionDefaults holds default paramaters as static class members.
Definition: funcdefaults.h:175
const double epsilon_1
Definition: dielectric.cc:190
Implements derivatives operators with variety of boundary conditions on simulation domain...
Definition: derivative.h:272
const double sigma
Definition: dielectric.cc:187
const double L
Definition: 3dharmonic.cc:123
void truncate(World &world, std::vector< Function< T, NDIM > > &v, double tol=0.0, bool fence=true)
Truncates a vector of functions.
Definition: vmra.h:194
Defines common mathematical and physical constants.
Convolutions in separated form (including Gaussian)
Definition: operator.h:117
std::vector< madness::Vector< double, 3 > > colloid_coords(const double &d, const double R, const std::vector< double > cc)
Definition: svpe_molecule_colloid.h:49
double ave_rxn_field(const real_function_3d &u, const real_function_3d &mask) const
Definition: svpe_molecule_colloid.h:309
Definition: mpreal.h:3066
Vector< double, 3 > coord_3d
Definition: funcplot.h:634
const double epsilon_0
Definition: dielectric.cc:189
Definition: molecularmask.h:131
std::vector< double > colloid_radii(const double &R)
Definition: svpe_molecule_colloid.h:90
Defines interfaces for optimization and non-linear equation solvers.
Computes the reciprocal of MolecularVolumeExponentialSwitch.
Definition: molecularmask.h:233
std::vector< real_function_3d > vector_real_function_3d
Definition: functypedefs.h:79
std::vector< Vector< double, 3 > > vector_coord_3d
Definition: functypedefs.h:58
Implements most functionality of separated operators.
World & world() const
Returns the world.
Definition: mra.h:622
real_function_3d make_Laplace_surface_charge(const real_function_3d &u, std::vector< double > E=std::vector< double >(3, 0.0)) const
Definition: svpe_molecule_colloid.h:183
double norm2() const
Returns the 2-norm of the function ... global sum ... works in either basis.
Definition: mra.h:650
void scale(World &world, std::vector< Function< T, NDIM > > &v, const std::vector< Q > &factors, bool fence=true)
Scales inplace a vector of functions by distinct values.
Definition: vmra.h:290
Function< double, NDIM > update(const Function< double, NDIM > &u, const Function< double, NDIM > &r, const double rcondtol=1e-8, const double cabsmax=1000.0)
Computes next trial solution vector.
Definition: nonlinsol.h:111
Example implementation of Krylov-subspace nonlinear equation solver.
T trace() const
Returns global value of int(f(x),x) ... global comm required.
Definition: mra.h:1034
const mpreal min(const mpreal &x, const mpreal &y)
Definition: mpreal.h:2675
Tensor< double > real_tensor
Definition: functypedefs.h:40
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
A parallel world with full functionality wrapping an MPI communicator.
Definition: worldfwd.h:416
enable_if_c< is_serializable< T >::value &&is_output_archive< Archive >::value >::type serialize(const Archive &ar, const T *t, unsigned int n)
Definition: archive.h:615
double norm2(World &world, const std::vector< Function< T, NDIM > > &v)
Computes the 2-norm of a vector of functions.
Definition: vmra.h:325
vector_real_function_3d make_electric_field(const real_function_3d &u) const
Definition: svpe_molecule_colloid.h:195
const int maxiter
Definition: gygi_soltion.cc:69
A multiresolution adaptive numerical function.
Definition: derivative.h:61
Definition: svpe_molecule_colloid.h:98
real_function_3d make_surface_charge(const real_function_3d &u) const
Definition: svpe_molecule_colloid.h:168
ProcessID rank() const
Returns the process rank in this world (same as MPI_Comm_rank()))
Definition: worldfwd.h:526
void plot_line(const char *filename, int npt, const Vector< double, NDIM > &lo, const Vector< double, NDIM > &hi, const Function< T, NDIM > &f)
Generates ASCII file tabulating f(r) at npoints along line r=lo,...,hi.
Definition: funcplot.h:388
std::vector< double > vector_real
Definition: functypedefs.h:53
Defines/implements plotting interface for functions.
Tensor< double > op(const Tensor< double > &x)
Definition: kain.cc:508
void print(const A &a)
Print a single item to std::cout terminating with new line.
Definition: print.h:122
FunctionFactory< double, 3 > real_factory_3d
Definition: functypedefs.h:93
Returns the requested component of the derivative of the log of MolecularVolumeExponentialSwitch.
Definition: molecularmask.h:295
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
const double c
Definition: gfit.cc:200
Function< TENSOR_RESULT_TYPE(L, R), NDIM > binary_op(const Function< L, NDIM > &left, const Function< R, NDIM > &right, const opT &op, bool fence=true)
Generate new function = op(left,right) where op acts on the function values.
Definition: mra.h:1593
double wall_time()
Returns the wall time in seconds relative to arbitrary origin.
Definition: world.cc:248
Key is the index for a node of the 2^NDIM-tree.
Definition: key.h:69
SVPEColloidSolver(World &world, double sigma, double epsilon_0, double epsilon_1, const vector_real &atomic_radii, const vector_coord_3d &atomic_coords, const double minlen, double L, const int maxiter)
Definition: svpe_molecule_colloid.h:133