-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PBC fix bundle #563
base: master
Are you sure you want to change the base?
PBC fix bundle #563
Changes from all commits
42319c1
15b87dc
70ab9df
c48e4a7
18d9ccf
7fbd9e3
f2f0b6d
b115e80
122a3b4
5d162a4
52e28cd
47d59ba
afa1122
084edc6
b4c1c54
7084146
5d487c4
bf94970
c5811cb
aba1178
602f4d3
4ae06b0
9db4790
6ecab21
24db345
992195a
0502f6e
e7c5c1f
e4ce92a
f2bae3e
5db605c
25dea91
23ec4de
4d1174b
c89faf4
52535a5
fbbceb3
ccbb1e8
488a603
4967add
18c7e19
befc1f8
9e92446
c149748
341ccfc
d0f0227
96f3563
8bd0652
2dfa2f4
3f33d06
2d8e16e
d27d486
a69e9b3
d8ae908
e1686f4
862a556
0892d88
475fad8
9e3e08e
88602d9
db30822
42999a1
0f1e502
d27b3b8
b014f88
73b121f
a1c4a35
dc791f1
fc281e8
77ecb84
12a6dd1
7caa96b
ae47693
e613c4b
963a371
07d6a3f
2236bd5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
#include <madness/tensor/solvers.h> | ||
#include<madness/chem/molecule.h> | ||
#include<madness/chem/molecularbasis.h> | ||
#include<madness/chem/potentialmanager.h> | ||
#include<madness/chem/xcfunctional.h> | ||
|
||
using namespace madness; | ||
|
@@ -178,46 +179,6 @@ class AtomicOrbitalFunctor: public FunctionFunctorInterface<double,3> { | |
std::vector<coord_3d> special_points() const {return specialpt;} | ||
}; | ||
|
||
class NuclearDensityFunctor : public FunctionFunctorInterface<double,3> { | ||
private: | ||
const Molecule& molecule; | ||
const double R; | ||
std::vector<coord_3d> specialpt; | ||
const int maxR = 1; | ||
public: | ||
NuclearDensityFunctor(const Molecule& molecule, double R) | ||
: molecule(molecule), R(R), specialpt(molecule.get_all_coords_vec()) | ||
{} | ||
|
||
double operator()(const coord_3d& x) const { | ||
double big = 2*R + 6.0*molecule.smallest_length_scale(); | ||
double sum = 0.0; | ||
for (int i=-maxR; i<=+maxR; i++) { | ||
double xx = x[0]+i*R; | ||
if (xx < big && xx > -big) { | ||
for (int j=-maxR; j<=+maxR; j++) { | ||
double yy = x[1]+j*R; | ||
if (yy < big && yy > -big) { | ||
for (int k=-maxR; k<=+maxR; k++) { | ||
double zz = x[2]+k*R; | ||
if (zz < big && zz > -big) | ||
sum += molecule.nuclear_charge_density(x[0]+i*R, x[1]+j*R, x[2]+k*R); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return sum; | ||
} | ||
|
||
std::vector<coord_3d> special_points() const {return specialpt;} | ||
|
||
Level special_level() { | ||
return 10; | ||
} | ||
|
||
}; | ||
|
||
class KPeriodicBSHOperator { | ||
private: | ||
double kx, ky, kz; | ||
|
@@ -979,7 +940,7 @@ int main(int argc, char** argv) { | |
aobasis.read_file("sto-3g"); | ||
|
||
// Nuclear potential | ||
real_function_3d vnuc = real_factory_3d(world).functor(real_functor_3d(new NuclearDensityFunctor(molecule, L))).truncate_mode(0).truncate_on_project(); | ||
real_function_3d vnuc = real_factory_3d(world).functor(real_functor_3d(new NuclearDensityFunctor(molecule))).truncate_mode(0).truncate_on_project(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is actually ρnuc... This variable should probably be renamed. If we really need the memory savings, make it a smart ptr and explicitly clear the memory once we've formed the actual vnuc. |
||
double nuclear_charge=vnuc.trace(); | ||
if (world.rank() == 0) print("total nuclear charge", nuclear_charge); | ||
vnuc = -1.0*make_coulomb_potential(world, vnuc); | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,126 @@ | ||||||
#include <madness/mra/mra.h> | ||||||
#include <madness/mra/operator.h> | ||||||
|
||||||
const double L = 10; | ||||||
|
||||||
static double gaussian_3d(const madness::coord_3d& r, const double expnt) { | ||||||
const double x=r[0], y=r[1], z=r[2]; | ||||||
const double coeff = pow(expnt/M_PI, 1.5); | ||||||
return coeff * exp(-expnt * (x*x + y*y + z*z)); | ||||||
} | ||||||
|
||||||
static double rho_electronic_3d(const madness::coord_3d& r) { return gaussian_3d(r, 1); } | ||||||
static double rho_nuclear_3d(const madness::coord_3d& r) { return -gaussian_3d(r, 10000); } | ||||||
|
||||||
static double rho_gaussian_func_3d(const madness::coord_3d& r) { | ||||||
return rho_electronic_3d(r) + rho_nuclear_3d(r); | ||||||
} | ||||||
|
||||||
// filter out leading order moments up to order k by zeroing out the corresponding coefficients in compressed representation | ||||||
template<typename T, std::size_t NDIM> | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MPQC duplicates this function... Maybe this function can be moved into the core MADNESS namespace? It's a good general-purpose function, and it'd be more maintainable if the thing we test and the thing we use were identical. |
||||||
void filter_moments_inplace(madness::Function<T,NDIM>& f, const int k, const bool fence=true) { | ||||||
|
||||||
// can only filter in compressed representation | ||||||
if (!f.is_compressed()) { | ||||||
f.compress(fence); | ||||||
} | ||||||
|
||||||
auto filter_op = [&](madness::Tensor<T> &coeff) { | ||||||
if constexpr (NDIM == 3) { | ||||||
if (k >= 0) { | ||||||
coeff(0, 0, 0) = 0.; | ||||||
} | ||||||
if (k >= 1) { | ||||||
coeff(1, 0, 0) = 0.; | ||||||
coeff(0, 1, 0) = 0.; | ||||||
coeff(0, 0, 1) = 0.; | ||||||
} | ||||||
if (k >= 2) { | ||||||
coeff(2, 0, 0) = 0.; | ||||||
coeff(0, 2, 0) = 0.; | ||||||
coeff(0, 0, 2) = 0.; | ||||||
coeff(1, 1, 0) = 0.; | ||||||
coeff(1, 0, 1) = 0.; | ||||||
coeff(0, 1, 1) = 0.; | ||||||
} | ||||||
if (k >= 3) | ||||||
abort();// TODO implement support for higher moments | ||||||
} else | ||||||
static_assert("filter_moments_inplace at the moment is implemented for NDIM=3"); | ||||||
}; | ||||||
|
||||||
// on [-L,L] normalized scaling function k is Sqrt[(2 k + 1)/(2 L)] LegendreP[k, x/L] | ||||||
// the coefficient of x^k in LegendreP[k, x] is 2^(-k) Binomial[2 k, k], hence | ||||||
// coefficient of x^k in scaling function k is Sqrt[(2 k + 1)/(2 L)] Binomial[2 k, k]/(2 L)^k | ||||||
// thus if all moments of up to k-1 vanish, k-th moment (=expectation value of x^k) of | ||||||
// scaling function k is its coefficient times Sqrt[(2 L)/ (2 k + 1)] (2 L)^k / Binomial[2 k, k] | ||||||
f.unaryop_coeff([&](const madness::Key<NDIM> &key, madness::Tensor<T> &coeff) { | ||||||
MADNESS_ASSERT(f.is_compressed()); | ||||||
// for compressed form only need 1 node, but public interface does not allow mutable access to the data | ||||||
if (key == f.get_impl()->key0()) { | ||||||
filter_op(coeff); | ||||||
} | ||||||
}, | ||||||
fence); | ||||||
} | ||||||
|
||||||
int main(int argc, char**argv) { | ||||||
using namespace madness; | ||||||
{ | ||||||
auto &world = initialize(argc, argv); | ||||||
startup(world, argc, argv, true); | ||||||
|
||||||
// Function defaults | ||||||
int k = 11; | ||||||
double thresh = 1e-9; | ||||||
double eps = 1e-9; | ||||||
FunctionDefaults<3>::set_k(k); | ||||||
FunctionDefaults<3>::set_cubic_cell(-L / 2, L / 2); | ||||||
FunctionDefaults<3>::set_thresh(thresh); | ||||||
FunctionDefaults<3>::set_refine(true); | ||||||
FunctionDefaults<3>::set_initial_level(2); | ||||||
FunctionDefaults<3>::set_truncate_mode(1); | ||||||
|
||||||
Function<double, 3> rho, rhoE, rhoN, V_periodic, V_periodicE, V_periodicN; | ||||||
|
||||||
{ | ||||||
// moments to filter out (0 = charge, 1 = dipoles, 2 = quadrupoles, >=3 not supported yet) | ||||||
constexpr int filter_level = 0; | ||||||
printf("building gaussian diff charge distribution ...\n\n"); | ||||||
std::vector<coord_3d> special_pt{coord_3d(std::array<double,3>{0.0, 0.0, 0.0})}; | ||||||
rho = FunctionFactory<double, 3>(world).special_points(special_pt).initial_level(4).f(rho_gaussian_func_3d); | ||||||
// rho[E+N] is neutral, so no need to filter out the leading moment, but does not hurt | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
filter_moments_inplace(rho, filter_level); | ||||||
rho.truncate(); | ||||||
rhoE = FunctionFactory<double, 3>(world).special_points(special_pt).initial_level(4).f(rho_electronic_3d); | ||||||
filter_moments_inplace(rhoE, filter_level); | ||||||
rhoE.truncate(); | ||||||
rhoN = FunctionFactory<double, 3>(world).special_points(special_pt).initial_level(4).f(rho_nuclear_3d); | ||||||
filter_moments_inplace(rhoN, filter_level); | ||||||
rhoN.truncate(); | ||||||
|
||||||
BoundaryConditions<3> bc_periodic(BC_PERIODIC); | ||||||
SeparatedConvolution<double, 3> pop = CoulombOperator(world, 1e-4, eps, bc_periodic.is_periodic()); | ||||||
printf("applying periodic operator ...\n\n"); | ||||||
V_periodic = apply(pop, rho); | ||||||
V_periodic.truncate(); | ||||||
V_periodicE = apply(pop, rhoE); | ||||||
V_periodicE.truncate(); | ||||||
V_periodicN = apply(pop, rhoN); | ||||||
V_periodicN.truncate(); | ||||||
|
||||||
V_periodic.reconstruct(); | ||||||
V_periodicE.reconstruct(); | ||||||
V_periodicN.reconstruct(); | ||||||
} | ||||||
|
||||||
double bstep = L / 1000.0; | ||||||
printf(" z\t\tV_(E+N)[z]\tV_E[z]\t\tV_N[z]\t\tV_E[z]+V_n[z]\trho\t\terror\n"); | ||||||
for (int i = 0; i < 1001; i++) { | ||||||
double x = -L / 2 + i * bstep; | ||||||
coord_3d p(std::array<double, 3>{0,0,x}); | ||||||
printf("%.3f\t\t%.8f\t%.8f\t%.8f\t%.8f\t%.8f\t%.8f\n", p[2], V_periodic(p), V_periodicE(p), V_periodicN(p), V_periodicE(p) + V_periodicN(p), rho(p), V_periodic(p) - V_periodicN(p) - V_periodicE(p)); | ||||||
} | ||||||
} | ||||||
madness::finalize(); | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually ρnuc... This variable should probably be renamed. If we really need the memory savings, make it a smart ptr and explicitly clear the memory once we've formed the actual vnuc.