TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Debog_Pb.tpp
1/****************************************************************************
2* Copyright (c) 2025, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#ifndef Debog_Pb_TPP_included
17#define Debog_Pb_TPP_included
18
19// In gdb: set the message number in parentheses in this variable with "set msg_debog_breakpoint=x" and a breakpoint in the debog_breakpoint() method
20static int msg_debog_breakpoint = 0;
21inline void debog_breakpoint() { }
22inline void debog_break_test(int msg) { if (msg == msg_debog_breakpoint) debog_breakpoint(); }
23
24template<typename _TYPE_>
25void Debog_Pb::verifier_gen(const char *const msg, const TRUSTVect<_TYPE_>& arr, TRUSTVect<_TYPE_> *arr_ref)
26{
27 if (!arr.get_md_vector().non_nul())
28 {
29 Cerr << "WARNING in Debog::verifier_gen: array has no parallel metadata. Not checked\n (message: " << msg << ")" << finl;
31 log_file_ << "WARNING in Debog::verifier_gen: array has no parallel metadata. Not checked\n (message: " << msg << ")" << finl;
32
33 detailed_log_file_ << "WARNING in Debog::verifier_gen: array has no parallel metadata. Not checked\n (message: " << msg << ")" << finl;
34 return;
35 }
36
37 if (test_ignore_msg(msg)) return; // Ignore this test
38
39 goto_msg(msg);
40 const TRUSTTab<_TYPE_>* scalT = dynamic_cast<const TRUSTTab<_TYPE_>*>(&arr);
41 if (scalT)
42 {
43 // read tab header
44 ArrOfInt dims;
45 debog_data_file_ >> dims;
46 }
47
48 TRUSTVect<_TYPE_> reference;
49 debog_data_file_ >> reference;
50
51 const int n = reference.size_array();
52 const trustIdType nb_items_seq = arr.get_md_vector()->nb_items_seq_tot();
53 const int ls = arr.line_size();
54
55 if (n != nb_items_seq * ls)
56 {
57 Cerr << "Error in Debog_Pb::verifier_gen : wrong sequential size " << n << " (expected " << nb_items_seq * ls << ")" << finl;
59 }
60 verifier_partie(reference, arr, arr_ref);
61}
62
63template <typename _TYPE_>
65{
66 const MD_Vector_base& md = arr.get_md_vector().valeur();
67 if (sub_type(MD_Vector_std, md) || sub_type(MD_Vector_seq, md))
68 {
69 verifier_partie_std(reference, arr, arr_ref);
70 }
71 else if (sub_type(MD_Vector_composite, md))
72 {
73 // This way, each processor writes each part sequentially : part1proc1, part1proc2, ... part2proc1, part2proc2, etc...
75 TRUSTTab<_TYPE_> ref_part;
76 const int n = parts.size();
77 int index = 0;
78 for (int i = 0; i < n; i++)
79 {
80 // Build the reference sub-part:
81 // (the reference array contains all sequential values, sub-part by sub-part; the size of a sub-part equals the total number
82 // of sequential items multiplied by the linesize of that sub-part). Note: not all sub-parts necessarily have the same linesize
83 const TRUSTTab<_TYPE_>& part = parts[i];
84 const trustIdType s0 = part.get_md_vector()->nb_items_seq_tot();
85 if (s0 > std::numeric_limits<int>::max())
86 Process::exit("Debog_Pb::verifier_partie() - case is too big to be checked with Debog_Pb!!");
87 const int sequential_size = static_cast<int>(s0);
88 const int line_size = part.line_size();
89 // ref_array() requires a non-const array, but we will use it as const only...
90 TRUSTArray<_TYPE_>& cast_array = ref_cast_non_const(TRUSTArray<_TYPE_>, reference);
91 ref_part.ref_array(cast_array, index, sequential_size * line_size);
92 // Recursive call for the sub-part:
93 verifier_partie(ref_part, part, arr_ref);
94 index += sequential_size * line_size;
95 }
96 }
97}
98
99template <typename _TYPE_>
100void Debog_Pb::verifier_partie_std(const TRUSTVect<_TYPE_>& reference, const TRUSTVect<_TYPE_>& array, TRUSTVect<_TYPE_> *arr_reference)
101{
102 TRUSTVect<_TYPE_> arr(array);
103 // Sanity check if HostDevice (e.g.: the array was modified on the host via pointers but the flag was not updated!)
104 if (array.get_data_location()==DataLocation::HostDevice)
105 {
106 // Force copy to host:
107 arr.set_data_location(DataLocation::Device);
108 copyFromDevice(arr);
109 assert(arr.get_data_location()==DataLocation::HostDevice);
110 // Comparison with array:
111 int size = arr.size_array();
112 for (int i = 0; i < size; i++)
113 if (arr.addr()[i] != array.addr()[i])
114 {
115 Cerr << "An array has a wrong status of HostDevice!" << finl;
117 }
118 }
119 else
120 copyFromDevice(arr); // Copy to host if Device
121
122 static constexpr bool IS_DOUBLE = std::is_same<_TYPE_,double>::value;
123 Nom identificateur;
124 // Search for the descriptor of array arr among the known descriptors
125 const IntVect& renum = find_renum_vector(arr.get_md_vector(), identificateur);
126
127 _TYPE_ adim = 0;
128 if (IS_DOUBLE)
129 {
130 // Compute a reference value for non-dimensionalization:
131 // The reference array is sequential: all processors have the same
132 const _TYPE_ adim1 = local_max_abs_vect(reference);
133 // The arr array is parallel. We compute the reference using only
134 // the real part (the virtual part may not be up to date)
135 const _TYPE_ adim2 = mp_max_abs_vect(arr, VECT_REAL_ITEMS);
136 adim = std::max(adim1, adim2);
137
138 if (seuil_absolu_ <= 0.)
139 {
140 Cerr << "Error in Debog.cpp verifier_partie_std: seuil_absolu <= 0" << finl;
142 }
143 if (adim < seuil_absolu_)
144 {
145 // All values are below the absolute threshold => ok
147 {
148 log_file_ << " OK : All values below seuil_absolu_ (" << seuil_absolu_ << ") id=" << identificateur << finl;
149 detailed_log_file_ << " OK : All values below seuil_absolu_ (" << seuil_absolu_ << ") id=" << identificateur << finl;
150 }
151 return;
152 }
153 }
154
155 const int ls = arr.line_size();
156 int i = 0;
157 _TYPE_ max_err_items_reels = 0, max_err_items_virt = 0;
158
159 int outbounds = 0;
160 // real items, then virtual items
161 for (int step = 0; step < 2; step++)
162 {
163 int n;
164 const char * message;
165 if (step == 0)
166 {
167 n = renum.size();
168 message = "on real item:";
169 }
170 else
171 {
172 n = renum.size_totale();
173 message = "on virtual item:";
174 }
175 _TYPE_ max_err = 0;
176 const _TYPE_ *arr_ptr = arr.addr();
177
178 for (; i < n; i++)
179 {
180 if (renum[i]>=0)
181 {
182 const int i1 = i * ls; // index in "arr"
183 const int i2 = renum[i] * ls; // index in "reference"
184 for (int j = 0; j < ls; j++)
185 {
186 const _TYPE_ x = arr_ptr[i1 + j]; // do not use operator[] to avoid crashing on DMAXFLOAT
187 const _TYPE_ y = reference[i2 + j];
188 // Comparison of x and y
189 if (IS_DOUBLE)
190 {
191 const _TYPE_ delta = (_TYPE_)std::fabs(x - y) / adim;
192 max_err = std::max(max_err, delta);
193 // for real items, indicate if out of bounds:
194 if (step == 0 && !(x >= -DMAXFLOAT && x <= DMAXFLOAT))
195 outbounds = 1;
196 if (delta > seuil_relatif_)
197 {
198 detailed_log_file_ << " DIFF " << message << " reference[" << i2 + j << "]=" << y << " \tcurrent[" << i1 + j
199 << "]=" << x << " \trelative error=" << delta << finl;
200 }
201 }
202 else // int
203 {
204 // For integers, values must match exactly !
205 if (x != y)
206 {
207 detailed_log_file_ << " DIFF " << message << " reference[" << i2 + j << "]=" << y << " \tcurrent[" << i1 + j
208 << "]=" << x << finl;
209 max_err = 1;
210 }
211 }
212 }
213 }
214 }
215
216 max_err = Process::mp_max(max_err);
217
218 if (step == 0)
219 max_err_items_reels = max_err;
220 else
221 max_err_items_virt = max_err;
222 }
223
224 const char * resu = 0;
225 int call_error_function = 0;
226 _TYPE_ seuil = IS_DOUBLE ? seuil_relatif_ : 0;
227
228 if (max_err_items_reels <= seuil)
229 {
230 if (max_err_items_virt <= seuil)
231 resu = "OK ";
232 else
233 resu = "OK REAL ONLY ";
234 }
235 else
236 {
237 call_error_function = 1;
238 if (!outbounds)
239 resu = "ERROR ";
240 else
241 resu = "ERROR(DMAXFLT)";
242 }
244 {
245 if (IS_DOUBLE)
246 log_file_ << " " << resu << " : Max relative error " << max_err_items_reels << " (max ref value=" << adim << ") id=" << identificateur << finl;
247 else
248 log_file_ << " " << resu << " : integer field " << identificateur << finl;
249 }
250
251 if (IS_DOUBLE)
252 detailed_log_file_ << " " << resu << " : Max relative error " << max_err_items_reels << " (max ref value=" << adim << ") id=" << identificateur << finl;
253 else
254 detailed_log_file_ << " " << resu << " : integer field " << identificateur << finl;
255
256 if (call_error_function)
258 if (arr_reference)
259 {
260 TRUSTVect<_TYPE_>& arr_ref = *arr_reference;
261
262 if (arr_ref.line_size() != ls || !(arr_ref.get_md_vector() == arr.get_md_vector()))
263 {
264 Cerr << "Error in Debog_Pb::verifier_partie_std: the array provided to store the reference value\n"
265 << " does not have the same size/descriptor as the source array" << finl;
267 }
269 log_file_ << " Return reference value (including virtual items)" << finl;
270 const int n = renum.size_totale();
271 _TYPE_ *arr_ptr = arr_ref.addr();
272 for (int ibis = 0; ibis < n; ibis++)
273 {
274 if (renum[ibis]>=0)
275 {
276 const int i1 = ibis * ls; // index in "arr"
277 const int i2 = renum[ibis] * ls; // index in "reference"
278 for (int j = 0; j < ls; j++)
279 {
280 const _TYPE_ y = reference[i2 + j];
281 arr_ptr[i1 + j] = y; // do not use operator[] to avoid crashing on DMAXFLOAT
282 }
283 }
284 }
285 }
286}
287
288template <typename _TYPE_>
289void Debog_Pb::ecrire_gen(const char* const msg, const TRUSTVect<_TYPE_>& arr, int num_deb)
290{
291 if (!arr.get_md_vector().non_nul())
292 {
293 Cerr << "WARNING in Debog::ecrire: array has no parallel metadata" << finl;
294 Cerr << " (message: " << msg << ")" << finl;
295 return;
296 }
298 const MD_Vector_base& md = arr.get_md_vector().valeur();
299 const int ls = arr.line_size();
301 {
302 os << "msg : " << debog_msg_count_ << " : " << msg << " FinMsg " << finl;
303 Cerr << "DEBOG: writing array, message " << debog_msg_count_ << " : " << msg << finl;
304 if (num_deb >= 0)
305 os << num_deb << finl;
306 // Dump array header:
307
308 const TRUSTTab<_TYPE_>* tabb = dynamic_cast<const TRUSTTab<_TYPE_>*>(&arr);
309 if (tabb)
310 {
311 // Header for TRUSTTab<_TYPE_>:
312 const TRUSTTab<_TYPE_>& tab = *tabb;
313 const int n = tab.nb_dim();
314 os << n << finl;
315 // total number of lines:
316 os << md.nb_items_seq_tot();
317 // other dimensions:
318 for (int i = 1; i < n; i++)
319 os << tspace << tab.dimension(i);
320 os << finl;
321 }
322 // Header of ArrayOfDouble:
323 os << md.nb_items_seq_tot() * ls << finl;
324 }
325
326 ecrire_partie(arr);
327}
328
329template<typename _TYPE_>
331{
332 const MD_Vector_base& md = arr.get_md_vector().valeur();
333 if (sub_type(MD_Vector_std, md) || sub_type(MD_Vector_seq, md))
334 {
335 const int ls = arr.line_size();
336 write_debog_data_file_.put(arr.addr(), arr.size_array(), ls);
337 }
338 else if (sub_type(MD_Vector_composite, md))
339 {
340 // This way, each processor writes each part sequentially : part1proc1, part1proc2, ... part2proc1, part2proc2, etc...
342 const int n = parts.size();
343 for (int i = 0; i < n; i++)
344 {
345 const TRUSTTab<_TYPE_>& t = parts[i];
346 ecrire_partie(t);
347 }
348 }
349}
350
351template<typename _TYPE_>
352void Debog_Pb::verifier(const char *const msg, const TRUSTVect<_TYPE_>& arr, TRUSTVect<_TYPE_> *arr_ref)
353{
354 if (nom_pb_ != nom_pb_actuel_)
355 return;
356
357 if (test_ignore_msg(msg))
358 {
359 // Ignorer ce test
360 return;
361 }
362 debog_break_test(debog_msg_count_);
363 if(mode_db_ == 0)
364 {
365 ecrire_gen(msg, arr);
366 }
367 else
368 {
369 verifier_gen(msg, arr, arr_ref);
370 }
372}
373
374template<typename _TYPE_> std::enable_if_t< (std::is_convertible<_TYPE_, double>::value) || (std::is_convertible<_TYPE_, int>::value),void >
375Debog_Pb::verifier(const char *const msg, _TYPE_ x, _TYPE_ *ref_value)
376{
377 static constexpr bool IS_DOUBLE = std::is_same<_TYPE_,double>::value;
378
379 if (nom_pb_ != nom_pb_actuel_) return;
380
381 if (test_ignore_msg(msg)) return; // Ignore this test
382
383 debog_break_test (debog_msg_count_);
384 if (mode_db_ == 0)
385 {
386 // write
388 Cerr << "DEBOG: writing scalar, message " << debog_msg_count_ << " : " << msg << finl;
389 os << "msg : " << debog_msg_count_ << " : " << msg << " FinMsg " << finl;
390 os << x << finl;
391 }
392 else
393 {
394 // read and compare
395 goto_msg(msg);
396 _TYPE_ y, err;
397 debog_data_file_ >> y;
398
399 if (IS_DOUBLE)
400 {
401 const _TYPE_ adim = (_TYPE_)std::max(std::fabs(x), std::fabs(y)); // explicit (double) for old compilo which do not handle const expr properly
402 const _TYPE_ delta = (_TYPE_)std::fabs(x - y);
403 err = 0;
404 if (delta >= seuil_absolu_ && delta / adim >= seuil_relatif_)
405 {
406 err = (_TYPE_)delta;
407 detailed_log_file_ << " DIFF (double) reference=" << y << " \tcurrent=" << x << " \trelative error=" << delta / adim << " \t(max ref value=" << adim << ")" << finl;
408 }
409 }
410 else // int
411 {
412 err = ((x - y) != 0);
413 if (err) detailed_log_file_ << " DIFF (int) reference=" << y << " \tcurrent=" << x << finl;
414 }
415
416 //err = static_cast<int>(mp_sum(err)); // always within 'int' range
417 err = Process::mp_max(err);
419 {
420 const char *ok = (err > 0.) ? " ERROR " : " OK ";
421 if (IS_DOUBLE)
422 {
423 log_file_ << ok << " : comparing double: reference=" << y << " absolute error=" << err << finl;
424 if (err > 0.) error_function();
425 }
426 else // int
427 {
428 log_file_ << ok << " : comparing int: reference=" << y << finl;
429 if (err) error_function();
430 }
431 }
432 if (ref_value)
433 {
435 log_file_ << " Request reference value" << finl;
436 *ref_value = y;
437 }
438 }
440}
441
442#endif /* Debog_Pb_TPP_included */
This class allows to access the individual sub-parts of 'const DoubleTab' objects that have a MD_Vect...
void ecrire_gen(const char *const msg, const TRUSTVect< _TYPE_ > &arr, int num_deb=-1)
Definition Debog_Pb.tpp:289
void ecrire_partie(const TRUSTVect< _TYPE_ > &arr)
Definition Debog_Pb.tpp:330
double seuil_relatif_
Definition Debog_Pb.h:91
SFichier write_debog_data_file_
Definition Debog_Pb.h:111
Nom nom_pb_actuel_
Definition Debog_Pb.h:119
const IntVect & find_renum_vector(const MD_Vector &, Nom &id) const
Definition Debog_Pb.cpp:365
int mode_db_
Definition Debog_Pb.h:96
void goto_msg(const char *const msg)
Definition Debog_Pb.cpp:128
EFichier debog_data_file_
Definition Debog_Pb.h:113
Nom nom_pb_
Definition Debog_Pb.h:85
EcrFicCollecte detailed_log_file_
Definition Debog_Pb.h:117
void error_function()
Method called as soon as an error is found in real space.
Definition Debog_Pb.cpp:59
std::enable_if_t<(std::is_convertible< _TYPE_, double >::value)||(std::is_convertible< _TYPE_, int >::value), void > verifier(const char *const msg, _TYPE_, _TYPE_ *refvalue=0)
Definition Debog_Pb.tpp:375
double seuil_absolu_
Definition Debog_Pb.h:90
SFichier log_file_
Definition Debog_Pb.h:115
int debog_msg_count_
Definition Debog_Pb.h:84
void verifier_partie(const TRUSTVect< _TYPE_ > &reference, const TRUSTVect< _TYPE_ > &arr, TRUSTVect< _TYPE_ > *arr_ref=0)
Definition Debog_Pb.tpp:64
void verifier_gen(const char *const msg, const TRUSTVect< _TYPE_ > &arr, TRUSTVect< _TYPE_ > *arr_ref=0)
Definition Debog_Pb.tpp:25
int test_ignore_msg(const char *const msg)
Definition Debog_Pb.cpp:123
void verifier_partie_std(const TRUSTVect< _TYPE_ > &reference, const TRUSTVect< _TYPE_ > &arr, TRUSTVect< _TYPE_ > *arr_ref=0)
Definition Debog_Pb.tpp:100
Base class for distributed vectors parallel descriptors.
virtual trustIdType nb_items_seq_tot() const
Metadata for a distributed composite vector.
Dummy parallel descriptor used for sequential computations.
This is the simplest descriptor, used for arrays of values at vertices, elements, faces,...
int non_nul() const
Definition MD_Vector.h:56
const MD_Vector_base & valeur() const
Definition MD_Vector.h:77
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
friend class Sortie
Definition Objet_U.h:70
static double mp_max(double)
Definition Process.cpp:379
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
Represents a an array of int/int64/double/... values.
Definition TRUSTArray.h:81
_SIZE_ size_array() const
DataLocation get_data_location()
Definition TRUSTArray.h:245
_TYPE_ * addr()
void set_data_location(DataLocation flag)
Definition TRUSTArray.h:247
N-dimensional array for N <= 4.
Definition TRUSTTab.h:31
void ref_array(TRUSTArray< _TYPE_, _SIZE_ > &, _SIZE_ start=0, _SIZE_ sz=-1) override
Definition TRUSTTab.tpp:332
int nb_dim() const
Definition TRUSTTab.h:199
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
int line_size() const
Definition TRUSTVect.tpp:67
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123