Line data Source code
1 : /*
2 : * Copyright (c) 2017: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
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 __H__UG_mg_stats_impl
34 : #define __H__UG_mg_stats_impl
35 :
36 : #include "common/util/stringify.h"
37 : #include "lib_disc/function_spaces/grid_function_util.h"
38 :
39 : namespace ug{
40 :
41 : template <typename TDomain, typename TAlgebra>
42 0 : MGStats<TDomain, TAlgebra>::
43 : MGStats() :
44 0 : m_statsRow(-1),
45 0 : m_lastLvlWritten(-1),
46 0 : m_maxLvl(0),
47 0 : m_filenamePrefix("mgstats"),
48 0 : m_exitOnError(false),
49 0 : m_writeErrVecs(false),
50 0 : m_writeErrDiffs(false)
51 : {
52 0 : for(int i = 0; i < NUM_STAGES; ++i)
53 0 : m_stageIsActive[i] = true;
54 0 : m_stageIsActive[INVALID] = false;
55 0 : }
56 :
57 : template <typename TDomain, typename TAlgebra>
58 0 : void MGStats<TDomain, TAlgebra>::
59 : set_exit_on_error(bool exitOnError)
60 : {
61 0 : m_exitOnError = exitOnError;
62 0 : }
63 :
64 :
65 : template <typename TDomain, typename TAlgebra>
66 0 : void MGStats<TDomain, TAlgebra>::
67 : set_write_err_vecs(bool writeErrVecs)
68 : {
69 0 : m_writeErrVecs = writeErrVecs;
70 0 : }
71 :
72 : template <typename TDomain, typename TAlgebra>
73 0 : void MGStats<TDomain, TAlgebra>::
74 : set_write_err_diffs(bool writeErrDiffs)
75 : {
76 0 : m_writeErrDiffs = writeErrDiffs;
77 0 : }
78 :
79 : template <typename TDomain, typename TAlgebra>
80 0 : void MGStats<TDomain, TAlgebra>::
81 : set_filename_prefix(const char* filename)
82 : {
83 0 : m_filenamePrefix = filename;
84 0 : }
85 :
86 : template <typename TDomain, typename TAlgebra>
87 0 : void MGStats<TDomain, TAlgebra>::
88 : set_active_stages(const std::vector<int>& activeStages)
89 : {
90 0 : for(int i = 0; i < NUM_STAGES; ++i)
91 0 : m_stageIsActive[i] = false;
92 :
93 0 : for(size_t i = 0; i < activeStages.size(); ++i){
94 0 : if(activeStages[i] >= 0 && (int)activeStages[i] < NUM_STAGES)
95 0 : m_stageIsActive[activeStages[i]] = true;
96 : }
97 :
98 0 : m_stageIsActive[INVALID] = false;
99 0 : }
100 :
101 : template <typename TDomain, typename TAlgebra>
102 0 : void MGStats<TDomain, TAlgebra>::
103 : save_stats_to_file()
104 : {
105 0 : std::string filename = mkstr(m_filenamePrefix << ".log");
106 0 : save_stats_to_file(filename.c_str());
107 0 : }
108 :
109 : template <typename TDomain, typename TAlgebra>
110 0 : void MGStats<TDomain, TAlgebra>::
111 : save_stats_to_file(const char* filename)
112 : {
113 : #ifdef UG_PARALLEL
114 : if(pcl::ProcRank() == 0){
115 : #endif
116 :
117 0 : std::ofstream out(filename);
118 0 : UG_COND_THROW(!out, "MGStats: Couldn't open '" << filename << "' for writing.");
119 0 : out << m_stats << std::endl;
120 0 : out.close();
121 :
122 : #ifdef UG_PARALLEL
123 : }
124 : #endif
125 0 : }
126 :
127 : template <typename TDomain, typename TAlgebra>
128 0 : void MGStats<TDomain, TAlgebra>::
129 : print()
130 : {
131 0 : UG_LOG(m_stats << std::endl);
132 0 : }
133 :
134 : template <typename TDomain, typename TAlgebra>
135 0 : void MGStats<TDomain, TAlgebra>::
136 : clear()
137 : {
138 0 : m_stats.clear();
139 0 : }
140 :
141 :
142 : template <typename TDomain, typename TAlgebra>
143 0 : void MGStats<TDomain, TAlgebra>::
144 : set_defect(grid_func_t& gf, int lvl, Stage stage)
145 : {
146 0 : if(lvl < 0)
147 0 : return;
148 :
149 0 : if(!m_stageIsActive[stage])
150 : return;
151 :
152 : level_required(lvl);
153 0 : FuncEntry& fe = m_funcs[lvl];
154 :
155 0 : if(stage == INVALID){
156 0 : fe.stage = INVALID;
157 0 : return;
158 : }
159 :
160 0 : if(fe.func.invalid() || fe.func->num_indices() != gf.num_indices()){
161 0 : fe.func = gf.clone_without_values();
162 0 : fe.tmpFunc = gf.clone_without_values();
163 0 : fe.stage = INVALID;
164 0 : fe.norm = 0;
165 : }
166 :
167 : // this is just an assumption that a new cycle started
168 0 : if(stage <= fe.stage && lvl >= m_lastLvlWritten){
169 0 : ++m_statsRow;
170 0 : m_lastLvlWritten = -1;
171 0 : write_header(lvl);
172 : // write a line to cout so that the output and the stats can be connected
173 0 : UG_LOG(" >>> mg-stats row: " << m_statsRow << std::endl);
174 : }
175 :
176 0 : ++m_statsRow;
177 :
178 : const int r = m_statsRow;
179 :
180 0 : m_lastLvlWritten = lvl;
181 :
182 : // write the current row index
183 0 : m_stats(r, 0) = mkstr(r);
184 0 : m_stats(r, 1) = stage_norm_name(stage);
185 :
186 :
187 : // compute statistics
188 : // copy gf to fe.tmpFunc to avoid any side effects on the multigrid iteration
189 : fe.tmpFunc->assign(gf);
190 : grid_func_t& newFunc = *fe.tmpFunc;
191 0 : const number norm = newFunc.norm();
192 0 : m_stats(r, 2 + m_maxLvl - lvl) = mkstr(norm);
193 :
194 0 : if((fe.stage < stage) && (norm > fe.norm)){
195 : // during the last operation the defect grew.
196 : // output the old and new grid functions and their difference
197 : std::string filename;
198 :
199 0 : if(m_writeErrVecs){
200 0 : filename = mkstr(m_filenamePrefix << "-row-" << r << "-lvl-"
201 : << lvl << "--" << fe.stage << "-"
202 : << stage_name(fe.stage) << ".vec");
203 :
204 : SaveVectorForConnectionViewer((*fe.func), filename.c_str());
205 :
206 :
207 0 : filename = mkstr(m_filenamePrefix << "-row-" << r << "-lvl-"
208 : << lvl << "--" << stage << "-"
209 : << stage_name(stage) << ".vec");
210 :
211 : SaveVectorForConnectionViewer(gf, filename.c_str());
212 : }
213 :
214 0 : if(m_writeErrDiffs){
215 0 : filename = mkstr(m_filenamePrefix << "-row-" << r << "-lvl-"
216 : << lvl << "-diff--" << stage << "-"
217 : << stage_name(fe.stage) << "-"
218 : << stage_name(stage) << ".vec");
219 : SaveVectorDiffForConnectionViewer(gf, *fe.func, filename.c_str());
220 : }
221 :
222 : std::string errMsg =
223 0 : mkstr("MGStats: Defect deteriorated on level " << lvl
224 : << " between stages '" << stage_name(fe.stage) << "' and '"
225 : << stage_name(stage) << "'. (MGStats row: " << r << ")");
226 :
227 0 : if(m_exitOnError){
228 0 : save_stats_to_file();
229 0 : print();
230 0 : UG_THROW(errMsg);
231 : }
232 : else{
233 : UG_LOG(errMsg << std::endl);
234 : }
235 : }
236 :
237 : // swap grid function of fe
238 : sp_grid_func_t sptmp = fe.func;
239 0 : fe.func = fe.tmpFunc;
240 0 : fe.tmpFunc = sptmp;
241 0 : fe.norm = norm;
242 0 : fe.stage = stage;
243 : }
244 :
245 :
246 : template <typename TDomain, typename TAlgebra>
247 : void MGStats<TDomain, TAlgebra>::
248 : level_required(int lvl)
249 : {
250 0 : if((int)m_funcs.size() <= lvl)
251 0 : m_funcs.resize(lvl + 1);
252 : }
253 :
254 :
255 : template <typename TDomain, typename TAlgebra>
256 0 : void MGStats<TDomain, TAlgebra>::
257 : write_header(int maxLvl)
258 : {
259 0 : m_maxLvl = maxLvl;
260 0 : m_stats(m_statsRow, 0) = "row";
261 0 : m_stats(m_statsRow, 1) = "stage";
262 0 : for(int i = 0; i < maxLvl; ++i){
263 0 : m_stats(m_statsRow, i+2) = mkstr("lvl " << maxLvl - i);
264 : }
265 0 : }
266 :
267 :
268 : }// end of namespace
269 :
270 : #endif //__H__UG_mg_stats_impl
|