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
32 $Id$
33 */
34
35 /// \file test6.cc
36 /// \brief test various functionality for 6d functions
37
38 #include <madness/mra/mra.h>
39
40 using namespace madness;
41
ok(const bool b)42 std::string ok(const bool b) {if (b) return "ok "; return "fail ";};
43
check_small(const double val,const double eps,const std::string message)44 int check_small(const double val, const double eps, const std::string message) {
45 bool is_small=(fabs(val)<eps);
46 print(ok(is_small),val,message);
47 return (is_small) ? 0 : 1;
48 }
49
check(bool b,const std::string message)50 int check(bool b, const std::string message) {
51 print(ok(b),message);
52 return (b) ? 0 : 1;
53 }
54
is_small(const double & val,const double & eps)55 bool is_small(const double& val, const double& eps) {
56 return (val<eps);
57 }
58
59
is_large(const double & val,const double & eps)60 bool is_large(const double& val, const double& eps) {
61 return (val>eps);
62 }
63
64 template<size_t NDIM>
load_function(World & world,Function<double,NDIM> & pair,const std::string name)65 void load_function(World& world, Function<double,NDIM>& pair, const std::string name) {
66 if (world.rank()==0) print("loading function ", name);
67
68 archive::ParallelInputArchive ar(world, name.c_str());
69 ar & pair;
70
71 FunctionDefaults<3>::set_k(pair.k());
72 FunctionDefaults<6>::set_k(pair.k());
73
74 FunctionDefaults<3>::set_thresh(pair.thresh());
75 FunctionDefaults<6>::set_thresh(pair.thresh());
76
77 std::string line="loaded function "+name;
78 pair.print_size(line);
79
80 }
81
82 template<size_t NDIM>
save_function(World & world,Function<double,NDIM> & pair,const std::string name)83 void save_function(World& world, Function<double,NDIM>& pair, const std::string name) {
84 if (world.rank()==0) print("saving function ", name);
85
86 archive::ParallelOutputArchive ar(world, name.c_str());
87 ar & pair;
88
89 std::string line="saved function "+name;
90 pair.print_size(line);
91
92 }
93
94
one_3d(const coord_3d & r)95 static double one_3d(const coord_3d& r) {
96 return 1.0;
97 }
98
zero_3d(const coord_3d & r)99 static double zero_3d(const coord_3d& r) {
100 return 0.0;
101 }
102
one_6d(const coord_6d & r)103 static double one_6d(const coord_6d& r) {
104 return 1.0;
105 }
106
gauss_3d(const coord_3d & r)107 static double gauss_3d(const coord_3d& r) {
108 const double x=r[0], y=r[1], z=r[2];
109 const double r2= sqrt(x*x + y*y + z*z);
110 const double norm=0.712705695388313;
111 return norm*exp(-r2);
112 }
113
tightgauss_3d(const coord_3d & r)114 static double tightgauss_3d(const coord_3d& r) {
115 const double x=r[0], y=r[1], z=r[2];
116 const double r2= sqrt(x*x + y*y + z*z);
117 const double norm=0.712705695388313;
118 return norm*exp(-2.0*r2);
119 }
120
gauss_plus_one_3d(const coord_3d & r)121 static double gauss_plus_one_3d(const coord_3d& r) {
122 return gauss_3d(r)+one_3d(r);
123 }
gauss_plus_tight_3d(const coord_3d & r)124 static double gauss_plus_tight_3d(const coord_3d& r) {
125 return gauss_3d(r)+tightgauss_3d(r);
126 }
127
128
gauss_6d(const coord_6d & r)129 static double gauss_6d(const coord_6d& r) {
130 coord_3d r1, r2;
131 r1[0]=r[0], r1[1]=r[1], r1[2]=r[2];
132 r2[0]=r[3], r2[1]=r[4], r2[2]=r[5];
133 return gauss_3d(r1)*gauss_3d(r2);
134 }
135
136
r2r(const coord_6d & r)137 static double r2r(const coord_6d& r) {
138 coord_3d r1, r2;
139 r1[0]=r[0], r1[1]=r[1], r1[2]=r[2];
140 r2[0]=r[3], r2[1]=r[4], r2[2]=r[5];
141 double g1=gauss_3d(r1);
142 return g1*g1*gauss_3d(r2);
143 }
144
145 //static double add_test(const coord_6d& r) {
146 // coord_3d r1, r2;
147 // r1[0]=r[0], r1[1]=r[1], r1[2]=r[2];
148 // r2[0]=r[3], r2[1]=r[4], r2[2]=r[5];
149 // double g1=gauss_3d(r1);
150 // double g2=gauss_3d(r2);
151 //
152 // return g1*g2 + g1*g1*g2;
153 //}
154
V(const Vector<double,3> & r)155 static double V(const Vector<double,3>& r) {
156 return -1.0/sqrt(r[0]*r[0]+r[1]*r[1]+r[2]*r[2]+1e-12);
157 }
158
159 /// test f(1,2) = g(1) h(2)
test_hartree_product(World & world,const long & k,const double thresh)160 int test_hartree_product(World& world, const long& k, const double thresh) {
161
162 print("entering hartree_product");
163 int nerror=0;
164 bool good;
165
166 real_function_3d phi=real_factory_3d(world).f(gauss_3d);
167 real_function_3d phisq=phi*phi;
168
169 {
170 real_function_6d ij=hartree_product(phi,phi);
171 ij.truncate();
172
173 double norm=ij.norm2();
174 print("norm(ij)",norm);
175
176 double err=ij.err(gauss_6d);
177 good=is_small(err,thresh);
178 print(ok(good), "hartree_product(phi,phi) error:",err);
179 if (not good) nerror++;
180
181 }
182
183 {
184 real_function_6d ij=hartree_product(phisq,phi);
185 double err=ij.err(r2r);
186 good=is_small(err,thresh);
187 print(ok(good), "hartree_product(phi^2,phi) error:",err);
188 if (not good) nerror++;
189 }
190
191 print("all done\n");
192 return nerror;
193 }
194
195 /// test f(1,2)*g(1)
test_multiply(World & world,const long & k,const double thresh)196 int test_multiply(World& world, const long& k, const double thresh) {
197
198 print("entering multiply f(1,2)*g(1)");
199 int nerror=0;
200 bool good;
201
202 real_function_6d f12=TwoElectronFactory(world).f12().thresh(thresh).gamma(1.0);
203
204
205 const real_function_3d phi=real_factory_3d(world).f(gauss_3d);
206 const real_function_3d phisq=phi*phi;
207
208 real_function_6d fii=CompositeFactory<double,6,3>(world)
209 .particle1(copy(phi))
210 .particle2(copy(phi))
211 .g12(f12);
212 real_function_6d fi2i=CompositeFactory<double,6,3>(world)
213 .particle1(copy(phisq))
214 .particle2(copy(phi))
215 .g12(f12);
216
217 real_function_6d fii2=CompositeFactory<double,6,3>(world)
218 .particle1(copy(phi))
219 .particle2(copy(phisq))
220 .g12(f12);
221
222
223 if (1) {
224 fii.fill_tree();
225 save_function(world,fii,"fii");
226 fi2i.fill_tree();
227 save_function(world,fi2i,"fi2i");
228 fii2.fill_tree();
229 save_function(world,fii2,"fii2");
230
231 } else {
232 load_function(world,fii,"fii");
233 load_function(world,fi2i,"fi2i");
234 load_function(world,fii2,"fii2");
235 }
236 fii.print_size("f12 |phi phi>");
237 fi2i.print_size("f12 |phi^2 phi>");
238 fii2.print_size("f12 |phi phi^2>");
239
240
241 real_function_6d iij1=multiply(copy(fii),phi,1);
242 iij1.print_size("multiply 1");
243 iij1.truncate().reduce_rank();
244 iij1.print_size("multiply 1 truncated");
245 double err=(fi2i-iij1).norm2();
246 good=is_small(err,thresh);
247 print(ok(good), "multiply f(1,2)*g(1) error:",err);
248
249 {
250 real_function_6d iij2=multiply(copy(fii),phi,2);
251 iij2.print_size("multiply 2");
252 iij2.truncate().reduce_rank();
253 iij2.print_size("multiply 2 truncated");
254 double err=(fii2-iij2).norm2();
255 good=is_small(err,thresh);
256 print(ok(good), "multiply f(1,2)*g(2) error:",err);
257 }
258
259
260
261 real_function_6d iij3=CompositeFactory<double,6,3>(world)
262 .ket(copy(fii)).V_for_particle1(copy(phi));
263 iij3.fill_tree();
264 iij3.print_size("CompositeFactory");
265 iij3.truncate();
266 iij3.print_size("CompositeFactory truncated");
267
268 double err4=(fi2i-iij3).norm2();
269 print("error in CompositeFactory 1",err4);
270 good=is_small(err4,thresh);
271 print(ok(good), "CompositeFactory f(1,2)*g(1) error:",err4);
272
273
274 if (not good) nerror++;
275
276 print("all done\n");
277 return nerror;
278 }
279
280 /// test f(1,2) + g(1,2) for both f and g reconstructed
test_add(World & world,const long & k,const double thresh)281 int test_add(World& world, const long& k, const double thresh) {
282
283 print("entering add");
284 int nerror=0;
285
286 // simple test for 3d functions and different adding schemes
287 real_function_3d one3=real_factory_3d(world).f(one_3d);
288 real_function_3d gauss3=real_factory_3d(world).f(gauss_3d);
289 real_function_3d gauss_plus_one3=real_factory_3d(world).f(gauss_plus_one_3d);
290
291 {
292 real_function_3d r1=one3+gauss3;
293 double error1=r1.err(gauss_plus_one_3d);
294 nerror+=check_small(error1,thresh,"operator+");
295 }
296 {
297 real_function_3d r1=one3+gauss3; // this has been checked before
298 real_function_3d r2=r1-gauss_plus_one3;
299 double error2=r2.err(zero_3d);
300 nerror+=check_small(error2,thresh,"operator-");
301 }
302 {
303 one3.compress(); gauss3.compress();
304 real_function_3d r3=gaxpy_oop(1.0,one3,1.0,gauss3);
305 nerror+=check(r3.is_compressed(),"is compressed");
306 double error3=r3.err(gauss_plus_one_3d);
307 nerror+=check_small(error3,thresh,"gaxpy_oop add");
308 }
309 {
310 one3.reconstruct(); gauss3.reconstruct();
311 real_function_3d r4=gaxpy_oop_reconstructed(1.0,one3,1.0,gauss3);
312 nerror+=check(!r4.is_compressed(),"is reconstructed");
313 double error4=r4.err(gauss_plus_one_3d);
314 nerror+=check_small(error4,thresh,"gaxpy_oop_reconstructed");
315 }
316 {
317 real_function_3d r=copy(one3);
318 r.compress(); gauss3.compress();
319 r+=gauss3;
320 nerror+=check(r.is_compressed(),"is reconstructed");
321 double error1=r.err(gauss_plus_one_3d);
322 nerror+=check_small(error1,thresh,"operator+=, compressed");
323 }
324 {
325 real_function_3d r=copy(one3);
326 r.reconstruct(); gauss3.reconstruct();
327 r+=gauss3;
328 nerror+=check(r.is_compressed(),"is reconstructed");
329 double error1=r.err(gauss_plus_one_3d);
330 nerror+=check_small(error1,thresh,"operator+=, reconstructed");
331 }
332 {
333 one3.reconstruct(); gauss3.reconstruct();
334 real_function_3d r=gaxpy_oop_reconstructed(1.0,one3,-1.0,gauss3);
335 nerror+=check(!r.is_compressed(),"is reconstructed");
336 real_function_3d r2=one3-gauss3;
337 double error=(r-r2).norm2();
338 nerror+=check_small(error,thresh,"gaxpy_oop_reconstructed subtract");
339 }
340 {
341 real_function_3d r=copy(gauss3);
342 r.reconstruct(); gauss3.reconstruct();
343 r.add_scalar(1.0);
344 nerror+=check(!r.is_compressed(),"is reconstructed");
345 double error1=r.err(gauss_plus_one_3d);
346 nerror+=check_small(error1,thresh,"add_scalar");
347 }
348
349
350 // 6d tests; mainly consistency checks since err() function is very expensive in 6d
351 real_function_6d f=hartree_product(gauss3,gauss3);
352 real_function_6d one6=real_factory_6d(world).f(one_6d);
353
354 {
355 real_function_6d r=copy(f);
356 r.add_scalar(1.0);
357 real_function_6d r2=one6+f;
358 double error=(r2-r).norm2();
359 nerror+=check_small(error,thresh,"6d add_scalar/operator+/-");
360 }
361 {
362 real_function_3d tightgauss3=real_factory_3d(world).f(tightgauss_3d);
363 real_function_3d gauss_plus_tight3=real_factory_3d(world).f(gauss_plus_tight_3d);
364
365 real_function_6d r=hartree_product(gauss_plus_tight3,gauss_plus_tight3);
366 real_function_6d r1=hartree_product(gauss3,gauss3);
367 real_function_6d r2=hartree_product(gauss3,tightgauss3);
368 real_function_6d r22=hartree_product(tightgauss3,gauss3);
369 r22+=r2;
370 r22.scale(0.5);
371 real_function_6d r3=hartree_product(tightgauss3,tightgauss3);
372 real_function_6d r4=gaxpy_oop_reconstructed(1.0,r,-2.0,r22)-r1-r3;
373 double error=r4.norm2();
374 nerror+=check_small(error,1.5*thresh,"6d gaxpy_oop_reconstructed/operator+=/operator- note loosened threshold");
375 }
376
377 print("all done\n");
378 return nerror;
379 }
380
381
382 /// test f(1,2) + g(1,2) for both f and g reconstructed
test_exchange(World & world,const long & k,const double thresh)383 int test_exchange(World& world, const long& k, const double thresh) {
384
385 print("entering exchange f(1,2)*g(1)");
386 int nerror=0;
387 bool good;
388
389 double norm;
390 real_function_3d phi=real_factory_3d(world).f(gauss_3d);
391
392
393 real_convolution_3d poisson = CoulombOperator(world,0.0001,thresh);
394
395 real_function_3d rho = 2.0*phi*phi;
396 real_function_3d coulombpot=poisson(rho);
397
398
399 real_function_6d f=2.0*hartree_product(phi,phi);
400 real_function_6d f2=multiply(f,phi,1);
401 f2.print_size("f2 after apply");
402 norm=f2.norm2();
403 if (world.rank()==0) print("f2 norm",norm);
404 real_function_6d x=poisson(f2);
405
406 x.print_size("x after apply");
407 norm=x.norm2();
408 if (world.rank()==0) print("x norm",norm);
409 x=multiply(x,phi,1);
410 x.print_size("x after multiply");
411 norm=x.norm2();
412 if (world.rank()==0) print("x norm",norm);
413
414
415 real_function_6d tmp=0.5*multiply(f,coulombpot,1);
416 tmp.print_size("tmp after multiply");
417 norm=tmp.norm2();
418 if (world.rank()==0) print("tmp norm",norm);
419
420 real_function_6d diff=tmp-x;
421 diff.print_size("diff");
422 norm=diff.norm2();
423 if (world.rank()==0) print("diff norm",norm);
424 good=is_small(norm,thresh);
425 print(ok(good), "exchange error:",norm);
426 if (not good) nerror++;
427
428 // do only orbital
429 real_function_3d tmp2=phi*coulombpot;
430 tmp2.print_size("J phi after multiply");
431 norm=tmp2.norm2()*phi.norm2();
432 if (world.rank()==0) print("J phi norm",norm);
433
434
435
436 print("all done\n");
437 return nerror;
438 }
439
440 /// test inner product using redundant wave functions
test_inner(World & world,const long & k,const double thresh)441 int test_inner(World& world, const long& k, const double thresh) {
442
443 print("entering inner");
444 int nerror=0;
445 bool good;
446
447 double norm;
448 real_function_3d phi=real_factory_3d(world).f(gauss_3d);
449 real_function_3d phi2=phi*phi;
450
451 real_function_6d f1=hartree_product(phi,phi);
452 real_function_6d f2=hartree_product(phi,phi2);
453
454 double a1=inner(f1,f2);
455 double a2=inner(phi,phi) * inner(phi,phi2);
456 norm=a1-a2;
457
458 if (world.rank()==0) print("diff norm",norm);
459 good=is_small(norm,thresh);
460 print(ok(good), "inner error:",norm);
461 if (not good) nerror++;
462
463 print("all done\n");
464 return nerror;
465 }
466
467
468 /// test 6D convolution
test_convolution(World & world,const long & k,const double thresh)469 int test_convolution(World& world, const long& k, const double thresh) {
470
471 print("entering convolution");
472 int nerror=0;
473 bool good;
474
475 double eps=-0.5;
476
477 // solve the 3D H-atom
478 real_function_3d phi=real_factory_3d(world).f(gauss_3d);
479 const real_function_3d v=real_factory_3d(world).f(V);
480 real_function_3d vphi=v*phi;
481
482 v.print_size("v");
483 // real_convolution_3d poisson = CoulombOperator(world,0.0001,thresh);
484 real_convolution_3d green = BSHOperator<3>(world, sqrt(-2.0*eps), 1.e-8, 1.e-6);
485
486 for (int i=0; i<10; ++i) {
487
488 vphi=v*phi;
489 double PE=inner(vphi,phi);
490 print("<phi | V | phi>: ",PE);
491
492 real_derivative_3d Dx = free_space_derivative<double,3>(world,0);
493 Function<double,3> du = Dx(phi);
494 double KE = 3*0.5*(du.inner(du));
495 print("<phi | T | phi>: ",KE);
496 print("<phi | H | phi>: ",KE + PE);
497
498
499 phi=green(-2.0*vphi);
500 double norm=phi.norm2();
501 phi.scale(1.0/norm);
502 print("phi.norm2()",norm);
503 }
504
505 vphi=v*phi;
506 double PE=inner(vphi,phi);
507 print("<phi | V | phi>: ",PE);
508
509 // solve the H-atom in 6D
510 real_convolution_6d green6 = BSHOperator<6>(world, sqrt(-2.0*(eps+eps)), 1.e-8, 1.e-6);
511
512 real_function_6d result1=-2.0*green6(copy(vphi),copy(phi)).truncate().reduce_rank();
513 result1=result1-2.0*green6(copy(phi),copy(vphi)).truncate().reduce_rank();
514 world.gop.fence();
515
516 double a=result1.norm2();
517 if (world.rank()==0) print("<GVphi | GVphi> ",a);
518
519 real_function_6d diff=result1-hartree_product(phi,phi);
520 double norm=diff.norm2();
521
522 if (world.rank()==0) print("diff norm",norm);
523 good=is_small(norm,thresh);
524 print(ok(good), "inner error:",norm);
525 if (not good) nerror++;
526
527 print("all done\n");
528 return nerror;
529 }
530
531
532
533
test(World & world,const long & k,const double thresh)534 int test(World& world, const long& k, const double thresh) {
535
536 print("entering test");
537 int nerror=0;
538
539 typedef Key<3> keyT;
540
541 real_function_3d phi=real_factory_3d(world).f(gauss_3d);
542
543 // real_function_6d ij=hartree_product(phi,phi);
544 real_function_3d ij=phi;
545 ij.compress();
546
547 // get the root NS coeffs
548 keyT key0=ij.get_impl()->get_cdata().key0;
549 GenTensor<double> NScoeff=(ij.get_impl()->get_coeffs().find(key0)).get()->second.coeff();
550
551 {
552 // convert NS coeffs to values directly
553 GenTensor<double> val1=ij.get_impl()->NScoeffs2values(key0,NScoeff,false);
554
555 // convert NS coeffs to S coeffs, and then to values
556 Tensor<double> Scoeff=ij.get_impl()->unfilter(NScoeff).full_tensor_copy();
557 Tensor<double> val2(ij.get_impl()->get_cdata().v2k);
558
559 for (KeyChildIterator<3> kit(key0); kit; ++kit) {
560 const keyT& child = kit.key();
561 std::vector<Slice> cp = ij.get_impl()->child_patch(child);
562 Tensor<double> child_s_coeff=Scoeff(cp);
563 val2(cp)=ij.get_impl()->coeffs2values(child,child_s_coeff);
564 }
565
566 Tensor<double> diff=val2-val1.full_tensor_copy();
567 double error=diff.normf();
568 print("error in NScoeff2values",error);
569 }
570
571 {
572 // convert S coeffs to values directly
573 const std::vector<Slice>& s0=ij.get_impl()->get_cdata().s0;
574 GenTensor<double> val1=ij.get_impl()->NScoeffs2values(key0,GenTensor<double>(NScoeff(s0)),true);
575
576 // convert NS coeffs to S coeffs, and then to values
577 Tensor<double> Scoeff(ij.get_impl()->get_cdata().v2k);
578 Scoeff(s0)=(NScoeff.full_tensor_copy()(s0));
579 Scoeff=ij.get_impl()->unfilter(Scoeff);
580 Tensor<double> val2(ij.get_impl()->get_cdata().v2k);
581
582 for (KeyChildIterator<3> kit(key0); kit; ++kit) {
583 const keyT& child = kit.key();
584 std::vector<Slice> cp = ij.get_impl()->child_patch(child);
585 Tensor<double> child_s_coeff=Scoeff(cp);
586 val2(cp)=ij.get_impl()->coeffs2values(child,child_s_coeff);
587 }
588
589 Tensor<double> diff=val2-val1.full_tensor_copy();
590 double error=diff.normf();
591 print("error in Scoeff2values",error);
592 }
593
594 {
595 // convert S coeffs to values directly
596 const std::vector<Slice>& s0=ij.get_impl()->get_cdata().s0;
597 GenTensor<double> val1=ij.get_impl()->NS_fcube_for_mul(key0,key0,GenTensor<double>(NScoeff(s0)),true);
598
599 // convert NS coeffs to S coeffs, and then to values
600 Tensor<double> Scoeff(ij.get_impl()->get_cdata().v2k);
601 Scoeff(s0)=(NScoeff.full_tensor_copy()(s0));
602 Scoeff=ij.get_impl()->unfilter(Scoeff);
603 Tensor<double> val2(ij.get_impl()->get_cdata().v2k);
604
605 for (KeyChildIterator<3> kit(key0); kit; ++kit) {
606 const keyT& child = kit.key();
607 std::vector<Slice> cp = ij.get_impl()->child_patch(child);
608 Tensor<double> child_s_coeff=Scoeff(cp);
609 val2(cp)=ij.get_impl()->coeffs2values(child,child_s_coeff);
610 }
611
612 Tensor<double> diff=val2-val1.full_tensor_copy();
613 double error=diff.normf();
614 print("error in NS_fcube_for_mul",error);
615 }
616
617 {
618 // convert NS coeffs to values directly
619 GenTensor<double> val1=ij.get_impl()->NScoeffs2values(key0,NScoeff,false);
620 GenTensor<double> coeff1=ij.get_impl()->values2NScoeffs(key0,val1);
621 GenTensor<double> val2=ij.get_impl()->NScoeffs2values(key0,coeff1,false);
622
623 Tensor<double> diff=val2.full_tensor_copy()-val1.full_tensor_copy();
624 double error=diff.normf();
625 print("error in values2NScoeffs(NScoeff2values)",error);
626 }
627
628 print("all done\n");
629 return nerror;
630 }
631
632
main(int argc,char ** argv)633 int main(int argc, char**argv) {
634
635 initialize(argc,argv);
636 World world(SafeMPI::COMM_WORLD);
637 srand(time(nullptr));
638 startup(world,argc,argv);
639
640 // the parameters
641 long k=5;
642 double thresh=1.e-3;
643 double L=16;
644 TensorType tt=TT_2D;
645
646 // override the default parameters
647 for(int i = 1; i < argc; i++) {
648 const std::string arg=argv[i];
649
650 // break parameters into key and val
651 size_t pos=arg.find("=");
652 std::string key=arg.substr(0,pos);
653 std::string val=arg.substr(pos+1);
654
655 if (key=="size") L=atof(val.c_str()); // usage: size=10
656 if (key=="k") k=atoi(val.c_str()); // usage: k=5
657 if (key=="thresh") thresh=atof(val.c_str()); // usage: thresh=1.e-3
658 if (key=="TT") {
659 if (val=="TT_2D") tt=TT_2D;
660 else if (val=="TT_FULL") tt=TT_FULL;
661 else if (val=="TT_TENSORTRAIN") tt=TT_TENSORTRAIN;
662 else {
663 print("arg",arg, "key",key,"val",val);
664 MADNESS_EXCEPTION("confused tensor type",0);
665 }
666
667 }
668 }
669
670 FunctionDefaults<3>::set_thresh(thresh);
671 FunctionDefaults<3>::set_k(k);
672 FunctionDefaults<3>::set_cubic_cell(-L/2,L/2);
673 FunctionDefaults<6>::set_thresh(thresh);
674 FunctionDefaults<6>::set_k(k);
675 FunctionDefaults<6>::set_cubic_cell(-L/2,L/2);
676 FunctionDefaults<6>::set_tensor_type(tt);
677
678 print("entering testsuite for 6-dimensional functions\n");
679 print("k ",k);
680 print("thresh ",thresh);
681 print("boxsize ",L);
682 print("tensor type: ", FunctionDefaults<6>::get_tensor_type());
683 print("");
684
685
686 int error=0;
687
688 real_function_3d phi=real_factory_3d(world).f(gauss_3d);
689 double norm=phi.norm2();
690 if (world.rank()==0) printf("phi.norm2() %12.8f\n",norm);
691
692 real_function_3d phi2=2.0*phi*phi;
693 norm=phi2.norm2();
694 if (world.rank()==0) printf("phi2.norm2() %12.8f\n",norm);
695
696 test(world,k,thresh);
697 error+=test_hartree_product(world,k,thresh);
698 error+=test_convolution(world,k,thresh);
699 error+=test_multiply(world,k,thresh);
700 error+=test_add(world,k,thresh);
701 error+=test_exchange(world,k,thresh);
702 error+=test_inner(world,k,thresh);
703
704
705 print(ok(error==0),error,"finished test suite\n");
706
707 world.gop.fence();
708 finalize();
709
710 return error;
711 }
712
713
714