MADNESS  version 0.9
density.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: test_problems.h 1856 2010-04-06 14:03:52Z mgr522 $
32 */
33 
39 #ifndef MADNESS_INTERIOR_BC_DENSITY_H__INCLUDED
40 #define MADNESS_INTERIOR_BC_DENSITY_H__INCLUDED
41 
42 //#define WORLD_INSTANTIATE_STATIC_TEMPLATES
43 #include <madness/mra/mra.h>
44 #include <madness/mra/lbdeux.h>
46 #include <string>
47 
48 using namespace madness;
49 
52 
53 // load balancing structure lifted from dataloadbal.cc
54 template <int NDIM>
56  double leaf_value;
57  double parent_value;
58  DirichletLBCost(double leaf_value = 1.0, double parent_value = 1.0)
59  : leaf_value(leaf_value), parent_value(parent_value) {}
60 
61  double operator() (const Key<NDIM> &key,
62  const FunctionNode<double, NDIM> &node) const {
63 
64  if(key.level() <= 1) {
65  return 100.0*(leaf_value+parent_value);
66  }
67  else if(node.is_leaf()) {
68  return leaf_value;
69  }
70  else {
71  return parent_value;
72  }
73  }
74 };
75 
77 class TipMolecule : public FunctionFunctorInterface<double, 3> {
78  private:
79  TipMolecule() : dmi(1.0), denscoeffs(Tensor<double>()),
80  basis(std::vector<BasisFunc>(0)) {}
81 
82  protected:
85  double penalty_prefact, eps;
86  int dda_init_level, pdens_init_level, edens_init_level;
87  const Tensor<double> &denscoeffs;
88  const std::vector<BasisFunc> &basis;
89  std::vector<Vector<double, 3> > atom_centers;
90  double phi, d;
91  double proton_stdev, proton_inverse;
92 
93  public:
101 
103  TipMolecule(double eps, double penalty,
104  const Tensor<double> &denscoeffs, const std::vector<Atom*> &atoms,
105  const std::vector<BasisFunc> &basis, double phi, double d)
106  : dmi(eps), tip(NULL), solid(NULL), penalty_prefact(penalty),
107  eps(eps), denscoeffs(denscoeffs), basis(basis),
108  atom_centers(0), phi(0.5*phi), d(d), proton_stdev(0.0003/0.052918),
109  fop(DIRICHLET_RHS) {
110 
111  // note on phi: distribute the potential difference across the
112  // two surfaces (only half on each)
113 
114  // calculate some nice initial projection level
115  // should be no lower than 6, but may need to be higher for small
116  // length scales
117 
118  // epsilon from the diffuse domain approximation
119  dda_init_level = ceil(log(5669.15 / eps) / log(2.0) - 4);
120  if(dda_init_level < 6)
121  dda_init_level = 6;
122 
123  // smallest length scale from the electron density
124  edens_init_level = ceil(log(5669.15 / sqrt(0.5 / 18.731137))
125  / log(2.0) - 4);
126  if(edens_init_level < 6)
127  edens_init_level = 6;
128 
129  // smallest length scale from the total density
130  pdens_init_level = ceil(log(5669.15 / proton_stdev)
131  / log(2.0) - 1);
132  if(pdens_init_level < 6)
133  pdens_init_level = 6;
134 
135  // make the list of special points for the atoms
136  for(std::vector<Atom*>::const_iterator iter = atoms.begin();
137  iter != atoms.end(); ++iter) {
138 
139  atom_centers.push_back((*iter)->getCenter());
140  }
141 
142  // make the sdfs
143  coord_3d normal, point;
144 
145  // solid surface is the xy-plane
146  normal[0] = normal[1] = 0.0;
147  normal[2] = -1.0;
148  point[0] = point[1] = point[2] = 0.0;
149  solid = new SDFPlane(normal, point);
150 
151  // tip apex is at (0, 0, d)
152  point[2] = d;
153  normal[2] = 1.0;
154  tip = new SDFParaboloid(25.0 / 0.052918, point, normal);
155 
156  proton_inverse = 0.5 / (proton_stdev * proton_stdev);
157  }
158 
159  virtual ~TipMolecule() {
160  if(solid != NULL)
161  delete solid;
162  if(tip != NULL)
163  delete tip;
164  }
165 
167  double operator() (const Vector<double, 3> &x) const {
168  switch(fop) {
169  case DIRICHLET_RHS:
170  return dmi.mask(solid->sdf(x)) * dmi.mask(-tip->sdf(x))
171  * Inhomogeneity(x) - DirichletCond(x) *
172  (dmi.surface(solid->sdf(x)) + dmi.surface(-tip->sdf(x))) *
173  penalty_prefact;
174  break;
175  case SURFACE:
176  return (dmi.surface(solid->sdf(x)) + dmi.surface(-tip->sdf(x)))
177  * penalty_prefact;
178  break;
179  case DOMAIN_MASK:
180  return dmi.mask(solid->sdf(x)) * dmi.mask(-tip->sdf(x));
181  break;
182  case DENSITY:
183  // remember that Inhomogeneity returns -4Pi n(x)...
184  return Inhomogeneity(x) * (-0.25) / constants::pi;
185  break;
186  case ELECTRON_DENSITY:
187  return ElectronDensity(x);
188  break;
189  default:
190  error("shouldn't be here...");
191  return 0.0;
192  break;
193  }
194  }
195 
196  virtual double DirichletCond(const Vector<double, 3> &x) const {
197  if(x[2] > 0.5*d)
198  return phi;
199  else
200  return -phi;
201  }
202 
206  virtual double Inhomogeneity(const Vector<double, 3> &x) const {
207  // all density is close to the (0,0,5ang) for this problem
208  double dens;
209  double r2;
210  double norm = sqrt(proton_inverse / constants::pi);
211  norm *= norm*norm;
212 
213  // proton density -----------------
214  // go through the atoms
215  dens = 0.0;
216  for(std::vector<Vector<double, 3> >::const_iterator iter =
217  atom_centers.begin();
218  iter != atom_centers.end();
219  ++iter) {
220 
221  r2 = (x[0] - (*iter)[0])*(x[0] - (*iter)[0])
222  + (x[1] - (*iter)[1])*(x[1] - (*iter)[1])
223  + (x[2] - (*iter)[2])*(x[2] - (*iter)[2]);
224 
225  r2 *= proton_inverse;
226  if(r2 < 30.0)
227  dens += exp(-r2) * norm;
228  }
229 
230  // add in the electron density
231  dens += ElectronDensity(x);
232 
233  // The inhomogeneity of the PDE is -4Pi n(x); dens is presently
234  // n(x)
235  return -4.0*constants::pi*dens;
236  }
237 
238  virtual double ElectronDensity(const Vector<double, 3> &x) const {
239  // all density is close to the (0,0,5ang) for this problem
240  if(x[0]*x[0] + x[1]*x[1] +
241  (x[2]-5.0/0.052918)*(x[2]-5.0/0.052918) > 100.0)
242  return 0.0;
243 
244  double ret = 0.0;
245  double perstate;
246 
247  // go through the states
248  long nstate = denscoeffs.dim(0);
249  long nbasis = denscoeffs.dim(1);
250  for(long state = 0; state < nstate; ++state) {
251  perstate = 0.0;
252 
253  // go through the coefficients
254  for(long func = 0; func < nbasis; ++func) {
255  perstate += denscoeffs(state, func) *
256  basis[func]->operator()(x);
257  }
258 
259  ret += perstate * perstate;
260  }
261 
262  if(ret < 1.0e-8)
263  return 0.0;
264 
265  // n(x) = -2.0*ret is the density (2 for spin degeneracy and a
266  // negative sign for charge)
267  return -2.0*ret;
268  }
269 
270  std::vector<Vector<double, 3> > special_points() const {
271  if(fop == DOMAIN_MASK || fop == SURFACE) {
272  return std::vector<Vector<double, 3> >();
273  }
274  else
275  return atom_centers;
276  }
277 
279  if(fop == DOMAIN_MASK || fop == SURFACE) {
280  return dda_init_level;
281  }
282  else if(fop == DENSITY) {
283  return pdens_init_level;
284  }
285  else if(fop == ELECTRON_DENSITY) {
286  return edens_init_level;
287  }
288  else {
289  if(pdens_init_level > dda_init_level)
290  return pdens_init_level;
291  else
292  return dda_init_level;
293  }
294  }
295 };
296 
298 template<int NDIM>
299 class DirichletCondIntOp : public Operator<Function<double, NDIM> > {
300  protected:
305 
312  void action(const Function<double, NDIM> &invec,
313  Function<double, NDIM> &outvec) const {
314 
315  outvec = invec + G(b*invec);
316  outvec.scale(-1.0);
317  outvec.truncate();
318  }
319 
320  public:
322  const Function<double, NDIM> &bin)
323  : G(gin), b(bin) {}
324 };
325 
326 #endif // MADNESS_INTERIOR_BC_DENSITY_H__INCLUDED
bool is_leaf() const
Returns true if this does not have children.
Definition: funcimpl.h:202
Use a Gaussian for the surface function and the corresponding erf for the domain mask.
Definition: sdf_domainmask.h:374
void error(const char *msg)
Definition: world.cc:128
double mask(double d) const
Value of characteristic function at normal distance d from the surface.
Definition: sdf_domainmask.h:395
const mpreal exp(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2234
A paraboloid (3 dimensions)
Definition: sdf_shape_3D.h:219
const double pi
Mathematical constant pi.
Definition: constants.h:44
T norm(Vector< T, N > v)
Compute norm of a Vector.
Definition: array.h:447
Setup the tip-molecule problem.
Definition: density.h:77
std::complex< double > func(int n, int t1, int t2, int t3, double xx, double yy, double zz)
Definition: wannier.cc:98
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
std::vector< Vector< double, 3 > > special_points() const
Override this to return list of special points to be refined more deeply.
Definition: density.h:270
const mpreal log(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2213
Definition: density.h:55
int pdens_init_level
Definition: density.h:86
std::vector< Vector< double, 3 > > atom_centers
Definition: density.h:89
double proton_stdev
Definition: density.h:91
Definition: density.h:50
Level special_level()
Override this change level refinement for special points (default is 6)
Definition: density.h:278
DirichletCondIntOp(const SeparatedConvolution< double, NDIM > &gin, const Function< double, NDIM > &bin)
Definition: density.h:321
virtual double sdf(const Vector< double, NDIM > &x) const =0
Returns the signed distance from the surface,.
iterator begin()
Definition: array.h:189
Definition: density.h:50
double parent_value
Definition: density.h:57
Function< T, NDIM > & scale(const Q q, bool fence=true)
Inplace, scale the function by a constant. No communication except for optional fence.
Definition: mra.h:896
Definition: density.h:51
double penalty_prefact
Definition: density.h:85
const mpreal ceil(const mpreal &v)
Definition: mpreal.h:2596
Definition: density.h:50
TipMolecule(double eps, double penalty, const Tensor< double > &denscoeffs, const std::vector< Atom * > &atoms, const std::vector< BasisFunc > &basis, double phi, double d)
Sets up the data for the problem-inspecific parts.
Definition: density.h:103
virtual double DirichletCond(const Vector< double, 3 > &x) const
Definition: density.h:196
const std::vector< BasisFunc > & basis
Definition: density.h:88
void action(const Function< double, NDIM > &invec, Function< double, NDIM > &outvec) const
Applies the operator to invec.
Definition: density.h:312
double surface(double d) const
Value of surface function at distance d normal to surface.
Definition: sdf_domainmask.h:426
pcomplex_operatorT G
Definition: tdse1d.cc:168
The operator needed for solving for with GMRES.
Definition: density.h:299
double phi
Definition: density.h:90
Level level() const
Definition: key.h:220
const SeparatedConvolution< double, NDIM > & G
The Green's function.
Definition: density.h:302
FunctorOutput
Definition: density.h:50
Definition: density.h:50
const Function< double, NDIM > & b
The surface function (normalized)
Definition: density.h:304
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
int Level
Definition: key.h:58
double leaf_value
Definition: density.h:56
FunctionNode holds the coefficients, etc., at each node of the 2^NDIM-tree.
Definition: derivative.h:58
Implements the SignedDFInterface for common 3-D geometric objects.This file provides signed distance ...
Abstract base class interface required for functors used as input to Functions.
Definition: function_interface.h:58
DirichletLBCost(double leaf_value=1.0, double parent_value=1.0)
Definition: density.h:58
A plane surface (3 dimensions)
Definition: sdf_shape_3D.h:67
Implements (2nd generation) static load/data balancing for functions.
SignedDFInterface< 3 > * tip
Definition: density.h:84
FunctorOutput fop
Definition: density.h:100
const Tensor< double > & denscoeffs
Definition: density.h:87
virtual double Inhomogeneity(const Vector< double, 3 > &x) const
The PDE's inhomogeneity.
Definition: density.h:206
GaussianDomainMask dmi
Definition: density.h:83
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
A generic operator: takes in one T and produces another T.
Definition: gmres.h:62
virtual double ElectronDensity(const Vector< double, 3 > &x) const
Definition: density.h:238
Key is the index for a node of the 2^NDIM-tree.
Definition: key.h:69
virtual ~TipMolecule()
Definition: density.h:159