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: test.cc 257 2007-06-25 19:09:38Z HartmanBaker $
33 */
34
35 /// \file mraplot.cc
36 /// \brief Function plotting utility
37
38 #include <madness/mra/mra.h>
39 #include <unistd.h>
40 #include <cstdio>
41 #include <madness/constants.h>
42 #include <madness/misc/phandler.h>
43
44 using namespace madness;
45
46 template <typename T, std::size_t NDIM>
47 struct lbcost {
operator ()lbcost48 double operator()(const Key<NDIM>& key, const FunctionNode<T,NDIM>& node) const {
49 return 1.0;
50 }
51 };
52
53 std::string help = "\n\
54 Input is read from standard input.\n\
55 \n\
56 Keywords may appear in any order until the plot keyword is \n\
57 detected, at which point the plot is generated. Input processing \n\
58 then resumes with previous input values being remembered. \n\
59 \n\
60 Thus, multiple plots may be generated by one input file. \n\
61 If only one plot is being generated, the plot keyword may \n\
62 be omitted (plot is triggered by hitting EOF). \n\
63 \n\
64 REQUIRED KEYWORDS \n\
65 . input <string filename> // Input file name ... no default for this! \n\
66 \n\
67 OPTIONAL KEYWORDS \n\
68 . output <string filename> // Default is 'plot' \n\
69 . ndim <int ndim> // No. of dimensions ... default is 3 \n\
70 . cell <double lo> <double hi> [...] // Compute cell volume ... default is [0,1]^ndim \n\
71 . ascii // Text output for volume data [default is binary] \n\
72 . text // Text output for volume data [default is binary] \n\
73 . dx // Specifies DX format for volume data [default is dx] \n\
74 . vtk <str function_name> // Specifies VTK format for volume data [default is dx], giving the function name function_name \n\
75 . real // Sets data type to real, default is real \n\
76 . complex // Sets data type to complex, default is real \n\
77 . line // Sets plot type to line, default is volume \n\
78 . volume // Sets plot type to volume, default is volume \n\
79 . plot_cell <double lo> <double hi> [...] // Plot range in each dimension, default is compute cell \n\
80 . npt // No. of points in each dimension (default is 101) \n\
81 . formula // Also plot analytic expression \n\
82 . exit // exits the program gracefully \n\
83 . quit // exits the program gracefully \n\
84 \n\
85 EXAMPLE \n\
86 . For a real function in parallel archive 'psi_step22' it \n\
87 . makes a volume plot over the whole domain and then a line \n\
88 . plot along the z axis between [-10,10] \n\
89 . \n\
90 . cell -100 100 -100 100 -100 100 \n\
91 . input psi_step22 \n\
92 . output psi22.dx \n\
93 . plot \n\
94 . \n\
95 . vtk my_function \n\
96 . output psi22.vts \n\
97 . plot \n\
98 . \n\
99 . \n\
100 . dx \n\
101 . plot_cell 0 0 0 0 -10 10 \n\
102 . output psi22.dat \n\
103 . line \n\
104 . plot \n\
105 \n\
106 DEBUG TIPS\n\
107 !! If the parallel archive holding the function was generated \n\
108 !! with multiple writers you presently must run mraplot in parallel \n\
109 !! with at least as many MPI processes. \n\
110 \n\
111 input data-00000.00000 may produce the following error\n\
112 MadnessException : msg=BinaryFstreamInputArchive: ... function=open \n\
113 input data-00000 fixes the problem\n\
114 ";
115
116 class Plotter {
117
118 public:
119
120 World& world;
121 Tensor<double> cell; // Computational cell
122 Tensor<double> plot_cell; // Plotting volume
123 std::string data_type; // presently only double or complex
124 std::string plot_type; // line or volume
125 std::string input_filename; // filename for function on disk
126 std::string output_filename; // output file name for plot data
127 std::string output_format; // output format for volume data (presently only dx)
128 std::string formula; // analytic function to plot
129 std::string function_name; // function name for VTK output
130 std::vector<long> npt; // no. points in each dimension
131 int ndim; // no. of dimensions
132 bool binary; // output format for plot data
133 bool finished; // true if finishing
134
135 template <typename Archive>
serialize(Archive & ar)136 void serialize(Archive& ar) {
137 ar & cell & plot_cell & data_type & plot_type
138 & input_filename & output_filename & output_format & function_name
139 & npt & ndim & binary & finished;
140 }
141
Plotter(World & world)142 Plotter(World& world)
143 : world(world)
144 , cell()
145 , plot_cell()
146 , data_type("double")
147 , plot_type("volume")
148 , input_filename()
149 , output_filename("plot")
150 , output_format("dx")
151 , formula("")
152 , function_name("function")
153 , ndim(3)
154 , binary(true)
155 , finished(true)
156 {}
157
read_to_end_of_line(std::istream & input)158 std::string read_to_end_of_line(std::istream& input) {
159 std::string buf;
160 while (1) {
161 char c = input.get();
162 if (c == '\n') break;
163 buf.append(1, c);
164 }
165 return buf;
166 }
167
read_npt(std::istream & input)168 std::vector<long> read_npt(std::istream& input) {
169 std::istringstream s(read_to_end_of_line(input));
170 std::vector<long> npt;
171 int i;
172 while (s >> i) {
173 npt.push_back(i);
174 }
175 return npt;
176 }
177
178 // Read pairs of floating point values and return appropriately sized tensor
read_cell(std::istream & input)179 Tensor<double> read_cell(std::istream& input) {
180 std::istringstream s(read_to_end_of_line(input));
181 double v[65];
182 int n = 0;
183 while (s >> v[n]) {
184 ++n;
185 MADNESS_ASSERT(n < 65);
186 }
187 // There should be an even number
188 int ndim = n/2;
189 MADNESS_ASSERT(n==ndim*2 && ndim>=1);
190 Tensor<double> cell(ndim,2);
191 for (int i=0; i<ndim; ++i) {
192 cell(i,0) = v[2*i ];
193 cell(i,1) = v[2*i+1];
194 }
195 return cell;
196 }
197
read(std::istream & input)198 void read(std::istream& input) {
199 finished = true;
200 std::string token;
201 while (input >> token) {
202 finished = false;
203
204 if (token == "ndim") {
205 input >> ndim;
206 }
207 else if (token == "ascii") {
208 binary = false;
209 }
210 else if (token == "text") {
211 binary = false;
212 }
213 else if (token == "dx") {
214 output_format = "dx";
215 }
216 else if (token == "vtk") {
217 output_format = "vtk";
218
219 // get the name of the function
220 if(!(input >> function_name))
221 MADNESS_EXCEPTION("VTK format requires a function name", 0);
222 }
223 else if (token == "input") {
224 input >> input_filename;
225 }
226 else if (token == "real") {
227 data_type = "real";
228 }
229 else if (token == "complex") {
230 data_type = "complex";
231 }
232 else if (token == "line") {
233 plot_type = "line";
234 }
235 else if (token == "volume") {
236 plot_type = "volume";
237 }
238 else if (token == "cell") {
239 cell = read_cell(input);
240 }
241 else if (token == "plot_cell") {
242 plot_cell = read_cell(input);
243 }
244 else if (token == "npt") {
245 npt = read_npt(input);
246 }
247 else if (token == "plot") {
248 break;
249 }
250 else if (token == "input") {
251 input >> input_filename;
252 }
253 else if (token == "output") {
254 input >> output_filename;
255 }
256 else if (token == "formula") {
257 input >> formula;
258 }
259 else if (token == "quit" || token == "exit") {
260 finished = true;
261 break;
262 }
263 else {
264 print("unknown keyword =", token);
265 MADNESS_EXCEPTION("unknown plotter keyword", 0);
266 }
267 }
268
269 if (finished) return;
270
271 // Implement runtime defaults
272 if (cell.size() <= 0) {
273 MADNESS_ASSERT(ndim>0 && ndim<=6);
274 cell = Tensor<double>(ndim,2);
275 for (int i=0; i<ndim; ++i) cell(i,1) = 1.0;
276 }
277 if (plot_cell.size() <= 0) plot_cell = copy(cell);
278 while (int(npt.size()) < ndim) npt.push_back(101);
279
280 // Warm and fuzzy
281 std::string ff[2] = {"text","binary"};
282 print(plot_type,"plot of", data_type, "function in", ndim,"dimensions from file", input_filename, "to", ff[binary], "file", output_filename);
283 print(" compute cell");
284 print(cell);
285 print(" plot cell");
286 print(plot_cell);
287 print(" number of points");
288 print(npt);
289 print("");
290
291 // Sanity check
292 MADNESS_ASSERT(ndim>0 && ndim<=6);
293 MADNESS_ASSERT(cell.dim(0)==ndim && cell.dim(1)==2);
294 MADNESS_ASSERT(plot_cell.dim(0)==ndim && plot_cell.dim(1)==2);
295 }
296
297 template <typename T, std::size_t NDIM>
dolineplot(const Function<T,NDIM> & f)298 void dolineplot(const Function<T,NDIM>& f) {
299 Vector<double,NDIM> lo, hi;
300 for (std::size_t i=0; i<NDIM; ++i) {
301 lo[i] = plot_cell(i,0);
302 hi[i] = plot_cell(i,1);
303 }
304
305 plot_line(output_filename.c_str(), npt[0], lo, hi, f);
306 }
307
308
309 template <typename T, std::size_t NDIM>
dovolumeplot(const Function<T,NDIM> & f)310 void dovolumeplot(const Function<T,NDIM>& f) {
311 if(output_format == "dx") {
312 plotdx(f, output_filename.c_str(), plot_cell, npt, binary);
313 }
314 else if(output_format == "vtk") {
315 Vector<double, NDIM> plotlo, plothi;
316 Vector<long, NDIM> numpt;
317 for(std::size_t i = 0; i < NDIM; ++i) {
318 plotlo[i] = plot_cell(i, 0);
319 plothi[i] = plot_cell(i, 1);
320 numpt[i] = npt[i];
321 }
322
323 plotvtk_begin(world, output_filename.c_str(), plotlo, plothi,
324 numpt, binary);
325 plotvtk_data(f, function_name.c_str(), world,
326 output_filename.c_str(), plotlo, plothi, numpt, binary);
327 plotvtk_end<NDIM>(world, output_filename.c_str(), binary);
328 }
329 }
330
331
332 template <typename T, std::size_t NDIM>
dolineplot(const Function<T,NDIM> & f,const Function<T,NDIM> & g)333 void dolineplot(const Function<T,NDIM>& f, const Function<T,NDIM>& g) {
334 Vector<double,NDIM> lo, hi;
335 for (std::size_t i=0; i<NDIM; ++i) {
336 lo[i] = plot_cell(i,0);
337 hi[i] = plot_cell(i,1);
338 }
339
340 plot_line(output_filename.c_str(), npt[0], lo, hi, f, g);
341 }
342
343
344 template <typename T, std::size_t NDIM>
dovolumeplot(const Function<T,NDIM> & f,const Function<T,NDIM> & g)345 void dovolumeplot(const Function<T,NDIM>& f, const Function<T,NDIM>& g) {
346 if(output_format == "dx") {
347 MADNESS_EXCEPTION("plot type not supported with user functions!",0);
348 }
349 else if(output_format == "vtk") {
350 Vector<double, NDIM> plotlo, plothi;
351 Vector<long, NDIM> numpt;
352 for(std::size_t i = 0; i < NDIM; ++i) {
353 plotlo[i] = plot_cell(i, 0);
354 plothi[i] = plot_cell(i, 1);
355 numpt[i] = npt[i];
356 }
357
358 plotvtk_begin(world, output_filename.c_str(), plotlo, plothi,
359 numpt, binary);
360 plotvtk_data(f, function_name.c_str(), world,
361 output_filename.c_str(), plotlo, plothi, numpt, binary);
362 plotvtk_data(g, function_name.c_str(), world,
363 output_filename.c_str(), plotlo, plothi, numpt, binary);
364 plotvtk_end<NDIM>(world, output_filename.c_str(), binary);
365 }
366 }
367
368
369 template <typename T, std::size_t NDIM>
doplot1()370 void doplot1() {
371
372 // Set up environment for this dimension
373 FunctionDefaults<NDIM>::set_cell(cell);
374
375 // Load the function
376 Function<T,NDIM> f;
377 archive::ParallelInputArchive ar(world, input_filename.c_str());
378 ar & f;
379
380 // Load the user's function
381 if (formula != "") {
382 typedef FunctionFactory<T,NDIM> factoryT;
383 typedef std::shared_ptr< FunctionFunctorInterface<T, NDIM> > functorT;
384 Function<T,NDIM> pFunc = factoryT(world).functor(functorT(
385 new ParserHandler<T,NDIM>("exp(-abs(r))")));
386
387 if (plot_type == "volume") dovolumeplot<T,NDIM>(f,pFunc);
388 else if (plot_type == "line") dolineplot<T,NDIM>(f,pFunc);
389 else MADNESS_EXCEPTION("unknown plot type",0);
390 } // end if formula present
391 else {
392 if (plot_type == "volume") dovolumeplot<T,NDIM>(f);
393 else if (plot_type == "line") dolineplot<T,NDIM>(f);
394 else MADNESS_EXCEPTION("unknown plot type",0);
395 }
396 }
397
398
399 template <typename T>
doplot()400 void doplot() {
401 // Redirect to right dimension
402 if (ndim == 1) doplot1<T,1>();
403 else if (ndim == 2) doplot1<T,2>();
404 else if (ndim == 3) doplot1<T,3>();
405 #ifdef FUNCTION_INSTANTIATE_4
406 else if (ndim == 4) doplot1<T,4>();
407 #endif
408 // else if (ndim == 5) doplot1<T,5>();
409 // else if (ndim == 6) doplot1<T,6>();
410 else MADNESS_EXCEPTION("invalid ndim", ndim);
411 }
412
plot()413 void plot() {
414 // Redirect to right data type
415 if (data_type == "double") {
416 doplot<double>();
417 }
418 else if (data_type == "complex") {
419 doplot< std::complex<double> >();
420 }
421 else {
422 MADNESS_EXCEPTION("uknown data type",0);
423 }
424 }
425 };
426
main(int argc,char ** argv)427 int main(int argc, char**argv) {
428 initialize(argc, argv);
429
430 try {
431 World world(SafeMPI::COMM_WORLD);
432 bool done = false;
433 if (world.rank() == 0) {
434 for (int i=0; i<argc; ++i) {
435 if (!strcmp(argv[i],"--help")) {
436 print(help);
437 done = true;
438 }
439 }
440 }
441 world.gop.broadcast(done);
442 if (!done) {
443 startup(world,argc,argv);
444 if (world.rank() == 0) print(" ");
445
446 Plotter plotter(world);
447 while (1) {
448 if (world.rank() == 0) {
449 plotter.read(std::cin);
450 }
451 world.gop.broadcast_serializable(plotter, 0);
452 if (plotter.finished) break;
453 plotter.plot();
454 }
455 }
456
457 world.gop.fence();
458 }
459 catch (const SafeMPI::Exception& e) {
460 print(e);
461 error("caught an MPI exception");
462 }
463 catch (const madness::MadnessException& e) {
464 print(e);
465 error("caught a MADNESS exception");
466 }
467 catch (const madness::TensorException& e) {
468 print(e);
469 error("caught a Tensor exception");
470 }
471 catch (const char* s) {
472 print(s);
473 error("caught a c-string exception");
474 }
475 catch (const std::string& s) {
476 print(s);
477 error("caught a string (class) exception");
478 }
479 catch (const std::exception& e) {
480 print(e.what());
481 error("caught an STL exception");
482 }
483 catch (...) {
484 error("caught unhandled exception");
485 }
486
487 finalize();
488 return 0;
489 }
490
491