Line data Source code
1 : /*
2 : * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Martin Rupp
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #ifndef CONNECTIONVIEWEROUTPUT_H_
34 : #define CONNECTIONVIEWEROUTPUT_H_
35 :
36 : #include <iostream>
37 : #include <fstream>
38 : #include <vector>
39 : #include <string>
40 : #include <limits>
41 :
42 : #include "common/progress.h"
43 : #include "common/util/string_util.h"
44 :
45 : #ifdef UG_PARALLEL
46 : #include "pcl/pcl.h"
47 : #include "pcl/parallel_archive.h"
48 : #endif
49 :
50 :
51 : #define CONNECTION_VIEWER_VERSION 1
52 :
53 : namespace ug
54 : {
55 : namespace ConnectionViewer
56 : {
57 : extern bool g_parallelConnectionViewer;
58 : #ifdef UG_PARALLEL
59 : /**
60 : * extends the filename (add p000X extension in parallel) and writes a parallel pvec/pmat "header" file
61 : */
62 : std::string GetParallelName(std::string name, const pcl::ProcessCommunicator &pc, bool bWriteHeader=true);
63 :
64 : inline std::string GetParallelName(std::string name)
65 : {
66 : pcl::ProcessCommunicator pc;
67 : return GetParallelName(name, pc);
68 :
69 : }
70 : template<typename T>
71 : inline std::string GetParallelName(T &t, std::string name)
72 : {
73 : return GetParallelName(name, t.layouts()->proc_comm());
74 : }
75 : #else
76 : template<typename T>
77 : inline std::string GetParallelName(T &t, std::string name)
78 : {
79 0 : return name;
80 : }
81 : #endif
82 :
83 :
84 : bool AddMarkers(std::string filename, std::string markfilename);
85 : bool WriteMarkers(std::string markfilename, std::vector<bool> markers, float r, float g, float b, float alpha, int size);
86 :
87 : template<typename TPosition>
88 0 : bool WriteGridHeader(std::ostream &f, const TPosition &positions, size_t N, int dimension)
89 : {
90 : // assert(dimension == 2 || dimension == 3);
91 0 : f << 1 << "\n";
92 0 : f << dimension << "\n";
93 0 : f << N << "\n";
94 0 : if(dimension == 1)
95 0 : for(size_t i=0; i < N; i++)
96 0 : f << positions[i][0] << " 0.0\n";
97 0 : else if(dimension == 2)
98 0 : for(size_t i=0; i < N; i++)
99 0 : f << positions[i][0] << " " << positions[i][1] << "\n";
100 : else
101 0 : for(size_t i=0; i < N; i++)
102 0 : f << positions[i][0] << " " << positions[i][1] << " " << positions[i][2] << "\n";
103 :
104 0 : f << 1 << "\n"; // stringsInWindow
105 0 : return true;
106 : }
107 :
108 : template<typename TPosition>
109 : bool WriteGridHeader(std::ostream &f, const TPosition &positions, int dimension)
110 : {
111 : return WriteGridHeader(f, positions, positions.size(), dimension);
112 : }
113 :
114 : // WriteMatrixToConnectionViewer
115 : //--------------------------------------------------
116 : /**
117 : * \brief writes to a file in somewhat SparseMatrix-market format (for connection viewer)
118 : * \param filename Filename to write matrix to
119 : * \param A SparseMatrix A.
120 : * \param positions Positions, there has to be one position for each i in (0, ..., max(A.num_rows(), A.num_cols())).
121 : * \param dimensions Dimension of positions
122 : */
123 : template<typename Matrix_type, typename postype>
124 0 : void WriteMatrix(std::ostream &file, const Matrix_type &A, postype *positions, int dimensions)
125 : {
126 : PROFILE_FUNC_GROUP("debug");
127 : size_t rows = A.num_rows();
128 :
129 0 : WriteGridHeader(file, positions, rows, dimensions);
130 0 : PROGRESS_START(prog, rows, "WriteMatrixToConnectionViewer " << dimensions << "d, " << rows << "x" << rows);
131 :
132 : // write connections
133 0 : for(size_t i=0; i < rows; i++)
134 : {
135 : PROGRESS_UPDATE(prog, i);
136 0 : for(typename Matrix_type::const_row_iterator conn = A.begin_row(i); conn != A.end_row(i); ++conn)
137 0 : if(conn.value() != 0.0)
138 0 : file << i << " " << conn.index() << " " << conn.value() << std::endl;
139 : else
140 : file << i << " " << conn.index() << " 0" << std::endl;
141 : }
142 0 : }
143 :
144 : template<typename Matrix_type, typename postype>
145 0 : void WriteMatrix(std::string filename, const Matrix_type &A, postype *positions, int dimensions)
146 : {
147 0 : std::fstream file(filename.c_str(), std::ios::out);
148 0 : WriteMatrix(file, A, positions, dimensions);
149 0 : }
150 :
151 :
152 : template<typename Matrix_type, typename postype>
153 0 : void WriteMatrixPar(std::string name, const Matrix_type &A, const postype *positions, int dimensions)
154 : {
155 0 : if(!g_parallelConnectionViewer)
156 0 : WriteMatrix(GetParallelName(A, name), A, positions, dimensions);
157 : else
158 : {
159 : #ifndef UG_PARALLEL
160 0 : WriteMatrix(GetParallelName(A, name), A, positions, dimensions);
161 : #else
162 : const pcl::ProcessCommunicator &pc = A.layouts()->proc_comm();
163 : if(pcl::NumProcs() == 1)
164 : WriteMatrix(name, A, positions, dimensions);
165 :
166 : std::string buf; //char buf[20];
167 : int rank = pcl::ProcRank();
168 :
169 :
170 : std::string fname = FilenameWithoutExtension(name);
171 : std::string ext = GetFilenameExtension(name);
172 :
173 : pcl::ParallelArchive ar(name + ".tarmat", pc);
174 : if(rank == pc.get_proc_id(0))
175 : {
176 : // create the .pmat "header" file
177 : std::stringstream &file = ar.create_stringstream_file(fname + ".p" + ext);
178 : file << pc.size() << "\n";
179 : for(size_t i=0; i<pc.size(); i++)
180 : {
181 : // snprintf(buf, sizeof(buf), "_p%04d.%s", pc.get_proc_id(i), ext.c_str());
182 : buf = GetStringPrintf("_p%04d.%s", pc.get_proc_id(i), ext.c_str());
183 : file << fname << buf << "\n";
184 : }
185 : }
186 : // create the .mat file
187 : buf = GetStringPrintf("_p%04d.%s", rank, ext.c_str());
188 : WriteMatrix(ar.create_stringstream_file(fname + buf), A, positions, dimensions);
189 : #endif
190 : }
191 0 : }
192 :
193 :
194 : // NOTE: The commented version below contains a bug which only occurs in rare situations,
195 : // resulting in a matrix output, where one entry has connections to
196 : // many other entries. Most presumably a problem with the mappings.
197 : // Instead of fixing it, the method was instead replaced by the method below
198 : // the commented section, which simplifies the output. Since the version with
199 : // the mapping might still be of interest, it remains in a commented form.
200 : //// WriteMatrix
201 : ////--------------------------------------------------
202 : ///**
203 : // * this version can handle different from and to spaces
204 : // */
205 : //template <typename Matrix_type, typename postype>
206 : //bool WriteMatrixToConnectionViewerMapped(std::string filename,
207 : // const Matrix_type &A,
208 : // std::vector<postype> &positionsFrom, std::vector<postype> &positionsTo, size_t dimensions)
209 : //{
210 : // PROFILE_FUNC_GROUP("debug");
211 : //#ifdef UG_PARALLEL
212 : // filename = GetParallelName(A, filename);
213 : //#endif
214 : //
215 : // /*const char * p = strstr(filename, ".mat");
216 : // if(p == NULL)
217 : // {
218 : // UG_LOG("Currently only '.mat' format supported for domains.\n");
219 : // return false;
220 : // }*/
221 : //
222 : // if(positionsFrom.size() != A.num_cols())
223 : // {
224 : // UG_LOG("uFrom.size() != A.num_cols() !\n");
225 : // return false;
226 : // }
227 : // if(positionsTo.size() != A.num_rows())
228 : // {
229 : // UG_LOG("uTo.size() != A.num_rows() !\n");
230 : // return false;
231 : // }
232 : //
233 : // std::vector<postype> positions;
234 : // std::vector<size_t> mapFrom, mapTo;
235 : // mapFrom.resize(positionsFrom.size());
236 : // mapTo.resize(positionsTo.size());
237 : //
238 : // if(positionsFrom.size() > positionsTo.size())
239 : // {
240 : // positions.resize(positionsFrom.size());
241 : // for(size_t i=0; i<positionsFrom.size(); i++)
242 : // {
243 : // positions[i] = positionsFrom[i];
244 : // mapFrom[i] = i;
245 : // }
246 : //
247 : //
248 : // for(size_t i=0; i<positionsTo.size(); i++)
249 : // {
250 : // size_t j;
251 : // for(j=0; j<positionsFrom.size(); j++)
252 : // {
253 : // if(positionsTo[i] == positionsFrom[j])
254 : // break;
255 : // }
256 : // mapTo[i] = j;
257 : // if(j == positionsFrom.size())
258 : // positions.push_back(positionsTo[i]);
259 : // }
260 : // }
261 : // else
262 : // {
263 : // positions.resize(positionsTo.size());
264 : // for(size_t i=0; i<positionsTo.size(); i++)
265 : // {
266 : // positions[i] = positionsTo[i];
267 : // mapTo[i] = i;
268 : // }
269 : //
270 : // for(size_t i=0; i<positionsFrom.size(); i++)
271 : // {
272 : // size_t j;
273 : // for(j=0; j<positionsTo.size(); j++)
274 : // {
275 : // if(positionsFrom[i] == positionsTo[j])
276 : // break;
277 : // }
278 : // mapFrom[i] = j;
279 : // if(j == positionsTo.size())
280 : // positions.push_back(positionsFrom[i]);
281 : // }
282 : // }
283 : //
284 : //
285 : // std::fstream file(filename.c_str(), std::ios::out);
286 : // file << CONNECTION_VIEWER_VERSION << std::endl;
287 : // file << dimensions << std::endl;
288 : //
289 : // // write positions
290 : // file << positions.size() << std::endl;
291 : //
292 : // if(dimensions == 1)
293 : // for(size_t i=0; i < positions.size(); i++)
294 : // file << positions[i][0] << " 0.0" << std::endl;
295 : // else if(dimensions == 2)
296 : //
297 : // for(size_t i=0; i < positions.size(); i++)
298 : // file << positions[i][0] << " " << positions[i][1] << std::endl;
299 : // else
300 : // for(size_t i=0; i < positions.size(); i++)
301 : // file << positions[i][0] << " " << positions[i][1] << " " << positions[i][2] << std::endl;
302 : //
303 : // file << 1 << std::endl; // show all cons
304 : // // write connections
305 : // for(size_t i=0; i < A.num_rows(); i++)
306 : // {
307 : // for(typename Matrix_type::const_row_iterator conn = A.begin_row(i); conn != A.end_row(i); ++conn)
308 : // if(conn.value() != 0.0)
309 : // file << mapTo[i] << " " << mapFrom[conn.index()] << " " << conn.value() << std::endl;
310 : // else
311 : // file << mapTo[i] << " " << mapFrom[conn.index()] << " 0" << std::endl;
312 : // }
313 : // return true;
314 : //}
315 :
316 : // WriteMatrixToConnectionViewer
317 : //--------------------------------------------------
318 : /**
319 : * this version can handle different from and to spaces
320 : */
321 : template <typename Matrix_type, typename postype>
322 0 : bool WriteMatrix( std::string filename,
323 : const Matrix_type &A,
324 : const std::vector<postype> &positionsFrom,
325 : const std::vector<postype> &positionsTo, size_t dimensions)
326 : {
327 : PROFILE_FUNC_GROUP("debug");
328 :
329 0 : if(positionsFrom.size() != A.num_cols())
330 : {
331 : UG_LOG("uFrom.size() != A.num_cols() !\n");
332 0 : return false;
333 : }
334 0 : if(positionsTo.size() != A.num_rows())
335 : {
336 : UG_LOG("uTo.size() != A.num_rows() !\n");
337 0 : return false;
338 : }
339 :
340 : size_t fromOffset = positionsTo.size();
341 :
342 :
343 0 : std::fstream file(filename.c_str(), std::ios::out);
344 0 : file << CONNECTION_VIEWER_VERSION << std::endl;
345 : file << dimensions << std::endl;
346 :
347 : // write positions
348 0 : file << positionsFrom.size() + positionsTo.size() << std::endl;
349 :
350 0 : if(dimensions == 1){
351 0 : for(size_t i=0; i < positionsTo.size(); i++)
352 0 : file << positionsTo[i][0] << " 0.0" << std::endl;
353 0 : for(size_t i=0; i < positionsFrom.size(); i++)
354 0 : file << positionsFrom[i][0] << " 0.0" << std::endl;
355 : }
356 0 : else if(dimensions == 2){
357 0 : for(size_t i=0; i < positionsTo.size(); i++)
358 0 : file << positionsTo[i][0] << " " << positionsTo[i][1] << std::endl;
359 0 : for(size_t i=0; i < positionsFrom.size(); i++)
360 0 : file << positionsFrom[i][0] << " " << positionsFrom[i][1] << std::endl;
361 : }
362 : else{
363 0 : for(size_t i=0; i < positionsTo.size(); i++)
364 0 : file << positionsTo[i][0] << " " << positionsTo[i][1] << " " << positionsTo[i][2] << std::endl;
365 0 : for(size_t i=0; i < positionsFrom.size(); i++)
366 0 : file << positionsFrom[i][0] << " " << positionsFrom[i][1] << " " << positionsFrom[i][2] << std::endl;
367 : }
368 :
369 0 : file << 1 << std::endl; // show all cons
370 : // write connections
371 :
372 0 : PROGRESS_START(prog, A.num_rows(), "WriteMatrixToConnectionViewer " << dimensions << "d, " << A.num_rows() << "x" << A.num_rows() );
373 0 : for(size_t i=0; i < A.num_rows(); i++)
374 : {
375 : PROGRESS_UPDATE(prog, i);
376 0 : for(typename Matrix_type::const_row_iterator conn = A.begin_row(i); conn != A.end_row(i); ++conn)
377 0 : if(conn.value() != 0.0)
378 0 : file << i << " " << conn.index() + fromOffset << " " << conn.value() << std::endl;
379 : else
380 0 : file << i << " " << conn.index() + fromOffset << " 0" << std::endl;
381 : }
382 : return true;
383 0 : }
384 :
385 :
386 : template <typename Matrix_type, typename postype>
387 0 : bool WriteMatrixPar(std::string filename, const Matrix_type &A,
388 : const std::vector<postype> &positionsFrom, const std::vector<postype> &positionsTo, size_t dimensions)
389 : {
390 0 : return WriteMatrix(GetParallelName(A, filename), A, positionsFrom, positionsTo, dimensions);
391 : }
392 :
393 : // WriteVectorToConnectionViewer
394 : //--------------------------------------------------
395 : /**
396 : * \brief writes to a file in somewhat SparseMatrix-market format (for connection viewer)
397 : * \param filename Filename to write matrix to
398 : * \param b Vector
399 : * \param positions Positions, there has to be one position for each i in (0, ..., max(A.num_rows(), A.num_cols())).
400 : * \param dimensions Dimensions of Positions
401 : */
402 : template<typename Vector_type, typename postype>
403 0 : void WriteVector(std::string filename, const Vector_type &b, const postype *positions, int dimensions, const Vector_type *compareVec=NULL)
404 : {
405 : PROFILE_FUNC_GROUP("debug");
406 :
407 0 : std::fstream file(filename.c_str(), std::ios::out);
408 : size_t rows = b.size();
409 0 : WriteGridHeader(file, positions, rows, dimensions);
410 :
411 : // write connections
412 0 : if(compareVec == NULL)
413 0 : for(size_t i=0; i < rows; i++)
414 : file << i << " " << i << " "
415 : << std::setprecision(std::numeric_limits<number>::digits10 + 1)
416 0 : << b[i] << std::endl;
417 : else
418 0 : for(size_t i=0; i < rows; i++)
419 : file << i << " " << i << " "
420 : << std::setprecision(std::numeric_limits<number>::digits10 + 1)
421 0 : << b[i]-(*compareVec)[i] << std::endl;
422 0 : }
423 :
424 : template<typename Vector_type, typename postype>
425 0 : void WriteVectorPar(std::string filename, const Vector_type &b, const postype *positions, int dimensions, const Vector_type *compareVec=NULL)
426 : {
427 0 : WriteVector(GetParallelName(b, filename), b, positions, dimensions, compareVec);
428 0 : }
429 :
430 : template<typename Matrix_type, typename Vector_type, typename postype>
431 0 : void WriteVector(std::string filename, const Matrix_type &A, const Vector_type &v,
432 : postype *positions, int dimensions, const Vector_type *compareVec=NULL)
433 : {
434 : PROFILE_FUNC_GROUP("debug");
435 0 : if(dimensions != 2)
436 : {
437 0 : UG_LOG(__FILE__ << ":" << __LINE__ << " WriteVectorToConnectionViewer: only dimension=2 supported");
438 0 : return;
439 : }
440 0 : filename = GetParallelName(A, filename);
441 :
442 : size_t rows = A.num_rows();
443 0 : std::fstream file(filename.c_str(), std::ios::out);
444 0 : WriteGridHeader(file, positions, rows, dimensions);
445 :
446 0 : PROGRESS_START(prog, rows, "WriteVectorToConnectionViewer " << dimensions << "d, " << A.num_rows() << "x" << A.num_rows() );
447 : // write connections
448 0 : for(size_t i=0; i < rows; i++)
449 : {
450 : PROGRESS_UPDATE(prog, i);
451 0 : for(typename Matrix_type::const_row_iterator conn = A.begin_row(i); conn != A.end_row(i); ++conn)
452 0 : if(conn.value() != 0.0)
453 : file << i << " " << conn.index() << " "
454 : << std::setprecision(std::numeric_limits<number>::digits10 + 1)
455 0 : << conn.value() << std::endl;
456 : else
457 : file << i << " " << conn.index() << " 0" << std::endl;
458 : }
459 :
460 :
461 : std::string nameValues = filename;
462 : nameValues.resize(nameValues.find_last_of("."));
463 0 : nameValues.append(".values");
464 0 : file << "v " << nameValues << "\n";
465 :
466 0 : std::fstream fileValues(nameValues.c_str(), std::ios::out);
467 0 : if(compareVec == NULL)
468 : {
469 0 : for(size_t i=0; i < rows; i++)
470 0 : fileValues << i << " " << v[i] << "\n";
471 : }
472 : else
473 : {
474 : typename Vector_type::value_type t;
475 0 : for(size_t i=0; i < rows; i++)
476 : {
477 0 : t = v[i];
478 0 : t -= (*compareVec)[i];
479 0 : fileValues << i << " " << t << "\n";
480 : }
481 : }
482 :
483 0 : }
484 :
485 : template<typename Matrix_type, typename Vector_type, typename postype>
486 0 : void WriteVectorPar(std::string filename, const Matrix_type &A, const Vector_type &v,
487 : postype *positions, int dimensions, const Vector_type *compareVec=NULL)
488 : {
489 0 : WriteVector(GetParallelName(A, filename), A, v, positions, dimensions, compareVec);
490 0 : }
491 :
492 : #if 0
493 : template<typename Vector_type, typename postype>
494 : void WriteVectorNEW(std::string filename, const Vector_type &b, postype *positions, int dimensions)
495 : {
496 : PROFILE_FUNC_GROUP("debug");
497 : filename = GetParallelName(filename);
498 :
499 : std::fstream file(filename.c_str(), std::ios::out);
500 : file << CONNECTION_VIEWER_VERSION << std::endl;
501 : file << 3 << std::endl;
502 :
503 : double nmax=0;
504 : for(size_t i=0; i<b.size(); i++)
505 : if(nmax < BlockNorm(b[i])) nmax = BlockNorm(b[i]);
506 :
507 : nmax*=4;
508 : double scale = 1.0/nmax;
509 : size_t rows = b.size();
510 : // write positions
511 : file << rows << std::endl;
512 : if(dimensions == 1)
513 : for(size_t i=0; i < rows; i++)
514 : file << positions[i][0] << " 0.0" << std::endl;
515 : else if(dimensions == 2)
516 : for(size_t i=0; i < rows; i++)
517 : file << positions[i][0] << " " << positions[i][1] << " " << b[i] * scale << std::endl;
518 : else
519 : for(size_t i=0; i < rows; i++)
520 : file << positions[i][0] << " " << positions[i][1] << " " << positions[i][2] << std::endl;
521 :
522 : file << 1 << std::endl; // show all cons
523 : // write connections
524 : for(size_t i=0; i < rows; i++)
525 : {
526 : file << i << " " << i << " " << b[i] << std::endl;
527 : }
528 : }
529 : #endif
530 :
531 : } // namespace ConnectionViewer
532 : } // namespace ug
533 : #endif /* CONNECTIONVIEWEROUTPUT_H_ */
|