deal.II version 9.8.0
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
utilities.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2005 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#include <deal.II/base/config.h>
14
16#include <deal.II/base/mpi.h>
17#include <deal.II/base/point.h>
21
22#define BOOST_BIND_GLOBAL_PLACEHOLDERS
23#include <boost/archive/iterators/base64_from_binary.hpp>
24#include <boost/archive/iterators/binary_from_base64.hpp>
25#include <boost/archive/iterators/transform_width.hpp>
26#include <boost/iostreams/copy.hpp>
27#include <boost/lexical_cast.hpp>
28#include <boost/random.hpp>
29
30#include <algorithm>
31#undef BOOST_BIND_GLOBAL_PLACEHOLDERS
32
33#ifdef DEAL_II_WITH_ZLIB
34# include <boost/iostreams/filter/gzip.hpp>
35#endif
36
37#include <algorithm>
38#include <bitset>
39#include <cctype>
40#include <cmath>
41#include <cstddef>
42#include <cstdio>
43#include <ctime>
44#include <fstream>
45#include <iomanip>
46#include <iostream>
47#include <limits>
48#include <sstream>
49#include <string>
50
51#if defined(DEAL_II_HAVE_UNISTD_H) && defined(DEAL_II_HAVE_GETHOSTNAME)
52# include <unistd.h>
53#endif
54
55#ifndef DEAL_II_MSVC
56// On Unix-type systems, we use posix_memalign:
57# include <cstdlib>
58#endif
59
60// It's necessary to include winsock2.h before thread_local_storage.h,
61// because Intel implementation of TBB includes winsock.h,
62// and we'll get a conflict between winsock.h and winsock2.h otherwise.
63#ifdef DEAL_II_MSVC
64# include <winsock2.h>
65#endif
66
67
68
70
71
72namespace Utilities
73{
75 unsigned int,
76 unsigned int,
77 << "When trying to convert " << arg1 << " to a string with "
78 << arg2 << " digits");
79 DeclException1(ExcInvalidNumber, unsigned int, << "Invalid number " << arg1);
81 std::string,
82 << "Can't convert the string " << arg1
83 << " to the desired type");
84
85
86 std::string
91
92
93 namespace
94 {
95 template <int dim,
96 typename Number,
97 int effective_dim,
98 typename LongDouble,
99 typename Integer>
100 std::vector<std::array<std::uint64_t, effective_dim>>
101 inverse_Hilbert_space_filling_curve_effective(
102 const std::vector<Point<dim, Number>> &points,
103 const Point<dim, Number> &bl,
104 const std::array<LongDouble, dim> &extents,
105 const std::bitset<dim> &valid_extents,
106 const int min_bits,
107 const Integer max_int)
108 {
109 std::vector<std::array<Integer, effective_dim>> int_points(points.size());
110
111 for (unsigned int i = 0; i < points.size(); ++i)
112 {
113 // convert into integers:
114 unsigned int eff_d = 0;
115 for (unsigned int d = 0; d < dim; ++d)
116 if (valid_extents[d])
117 {
118 Assert(extents[d] > 0, ExcInternalError());
119 const LongDouble v = (static_cast<LongDouble>(points[i][d]) -
120 static_cast<LongDouble>(bl[d])) /
121 extents[d];
122 Assert(v >= 0. && v <= 1., ExcInternalError());
123 AssertIndexRange(eff_d, effective_dim);
124 int_points[i][eff_d] =
125 static_cast<Integer>(v * static_cast<LongDouble>(max_int));
126 ++eff_d;
127 }
128 }
129
130 // note that we call this with "min_bits"
132 min_bits);
133 }
134 } // namespace
135
136 template <int dim, typename Number>
137 std::vector<std::array<std::uint64_t, dim>>
139 const std::vector<Point<dim, Number>> &points,
140 const int bits_per_dim)
141 {
142 using Integer = std::uint64_t;
143 // take floating point number hopefully with mantissa >= 64bit
144 using LongDouble = long double;
145
146 // return if there is nothing to do
147 if (points.empty())
148 return std::vector<std::array<std::uint64_t, dim>>();
149
150 // get bounding box:
151 Point<dim, Number> bl = points[0], tr = points[0];
152 for (const auto &p : points)
153 for (unsigned int d = 0; d < dim; ++d)
154 {
155 const double cid = p[d];
156 bl[d] = std::min(cid, bl[d]);
157 tr[d] = std::max(cid, tr[d]);
158 }
159
160 std::array<LongDouble, dim> extents;
161 std::bitset<dim> valid_extents;
162 for (unsigned int i = 0; i < dim; ++i)
163 {
164 extents[i] =
165 static_cast<LongDouble>(tr[i]) - static_cast<LongDouble>(bl[i]);
166 valid_extents[i] = (extents[i] > 0.);
167 }
168
169 // make sure our conversion from fractional coordinates to
170 // Integers work as expected, namely our cast (LongDouble)max_int
171 const int min_bits = std::min({bits_per_dim,
172 std::numeric_limits<Integer>::digits,
173 std::numeric_limits<LongDouble>::digits});
174
175 // based on that get the maximum integer:
176 const Integer max_int = (min_bits == std::numeric_limits<Integer>::digits ?
177 std::numeric_limits<Integer>::max() :
178 (Integer(1) << min_bits) - 1);
179
180 const unsigned int effective_dim = valid_extents.count();
181 if (effective_dim == dim)
182 {
183 return inverse_Hilbert_space_filling_curve_effective<dim,
184 Number,
185 dim,
186 LongDouble,
187 Integer>(
188 points, bl, extents, valid_extents, min_bits, max_int);
189 }
190
191 // various degenerate cases
192 std::array<std::uint64_t, dim> zero_ind;
193 for (unsigned int d = 0; d < dim; ++d)
194 zero_ind[d] = 0;
195
196 std::vector<std::array<std::uint64_t, dim>> ind(points.size(), zero_ind);
197 // manually check effective_dim == 1 and effective_dim == 2
198 if (dim == 3 && effective_dim == 2)
199 {
200 const auto ind2 =
201 inverse_Hilbert_space_filling_curve_effective<dim,
202 Number,
203 2,
204 LongDouble,
205 Integer>(
206 points, bl, extents, valid_extents, min_bits, max_int);
207
208 for (unsigned int i = 0; i < ind.size(); ++i)
209 for (unsigned int d = 0; d < 2; ++d)
210 ind[i][d + 1] = ind2[i][d];
211
212 return ind;
213 }
214 else if (effective_dim == 1)
215 {
216 const auto ind1 =
217 inverse_Hilbert_space_filling_curve_effective<dim,
218 Number,
219 1,
220 LongDouble,
221 Integer>(
222 points, bl, extents, valid_extents, min_bits, max_int);
223
224 for (unsigned int i = 0; i < ind.size(); ++i)
225 ind[i][dim - 1] = ind1[i][0];
226
227 return ind;
228 }
229
230 // we should get here only if effective_dim == 0
231 Assert(effective_dim == 0, ExcInternalError());
232
233 // if the bounding box is degenerate in all dimensions,
234 // can't do much but exit gracefully by setting index according
235 // to the index of each point so that there is no re-ordering
236 for (unsigned int i = 0; i < points.size(); ++i)
237 ind[i][dim - 1] = i;
238
239 return ind;
240 }
241
242
243
244 template <int dim>
245 std::vector<std::array<std::uint64_t, dim>>
247 const std::vector<std::array<std::uint64_t, dim>> &points,
248 const int bits_per_dim)
249 {
250 using Integer = std::uint64_t;
251
252 std::vector<std::array<Integer, dim>> int_points(points);
253
254 std::vector<std::array<Integer, dim>> res(int_points.size());
255
256 // follow
257 // J. Skilling, Programming the Hilbert curve, AIP Conf. Proc. 707, 381
258 // (2004); http://dx.doi.org/10.1063/1.1751381 also see
259 // https://stackoverflow.com/questions/499166/mapping-n-dimensional-value-to-a-point-on-hilbert-curve
260 // https://gitlab.com/octopus-code/octopus/blob/develop/src/grid/hilbert.c
261 // https://github.com/trilinos/Trilinos/blob/master/packages/zoltan/src/hsfc/hsfc_hilbert.c
262 // (Zoltan_HSFC_InvHilbertXd)
263 // https://github.com/aditi137/Hilbert/blob/master/Hilbert/hilbert.cpp
264
265 // now we can map to 1d coordinate stored in Transpose format
266 // adopt AxestoTranspose function from the paper, that
267 // transforms in-place between geometrical axes and Hilbert transpose.
268 // Example: b=5 bits for each of n=3 coordinates.
269 // 15-bit Hilbert integer = A B C D E F G H I J K L M N O is
270 // stored as its Transpose
271 // X[0] = A D G J M X[2]|
272 // X[1] = B E H K N <-------> | /X[1]
273 // X[2] = C F I L O axes |/
274 // high low 0------ X[0]
275
276 // Depth of the Hilbert curve
277 Assert(bits_per_dim <= std::numeric_limits<Integer>::digits,
278 ExcMessage("This integer type can not hold " +
279 std::to_string(bits_per_dim) + " bits."));
280
281 const Integer M = Integer(1) << (bits_per_dim - 1); // largest bit
282
283 for (unsigned int index = 0; index < int_points.size(); ++index)
284 {
285 auto &X = int_points[index];
286 auto &L = res[index];
287
288 // Inverse undo
289 for (Integer q = M; q > 1; q >>= 1)
290 {
291 const Integer p = q - 1;
292 for (unsigned int i = 0; i < dim; ++i)
293 {
294 // invert
295 if (X[i] & q)
296 {
297 X[0] ^= p;
298 }
299 // exchange
300 else
301 {
302 const Integer t = (X[0] ^ X[i]) & p;
303 X[0] ^= t;
304 X[i] ^= t;
305 }
306 }
307 }
308
309 // Gray encode (inverse of decode)
310 for (unsigned int i = 1; i < dim; ++i)
311 X[i] ^= X[i - 1];
312
313 Integer t = 0;
314 for (Integer q = M; q > 1; q >>= 1)
315 if (X[dim - 1] & q)
316 t ^= q - 1;
317 for (unsigned int i = 0; i < dim; ++i)
318 X[i] ^= t;
319
320 // now we need to go from index stored in transpose format to
321 // consecutive format, which is better suited for comparators.
322 // we could interleave into some big unsigned int...
323 // https://www.forceflow.be/2013/10/07/morton-encodingdecoding-through-bit-interleaving-implementations/
324 // https://stackoverflow.com/questions/4431522/given-2-16-bit-ints-can-i-interleave-those-bits-to-form-a-single-32-bit-int
325 // ...but we would loose spatial resolution!
326
327 // interleave using brute force, follow TransposetoLine from
328 // https://github.com/aditi137/Hilbert/blob/master/Hilbert/hilbert.cpp
329 {
330 Integer p = M;
331 unsigned int j = 0;
332 for (unsigned int i = 0; i < dim; ++i)
333 {
334 L[i] = 0;
335 // go through bits using a mask q
336 for (Integer q = M; q > 0; q >>= 1)
337 {
338 if (X[j] & p)
339 L[i] |= q;
340 if (++j == dim)
341 {
342 j = 0;
343 p >>= 1;
344 }
345 }
346 }
347 }
348
349 } // end of the loop over points
350
351 return res;
352 }
353
354
355
356 template <int dim>
357 std::uint64_t
358 pack_integers(const std::array<std::uint64_t, dim> &index,
359 const int bits_per_dim)
360 {
361 using Integer = std::uint64_t;
362
363 AssertIndexRange(bits_per_dim * dim, 65);
364 Assert(bits_per_dim > 0, ExcMessage("bits_per_dim should be positive"));
365
366 const Integer mask = (Integer(1) << bits_per_dim) - 1;
367
368 Integer res = 0;
369 for (unsigned int i = 0; i < dim; ++i)
370 {
371 // take bits_per_dim from each integer and shift them
372 const Integer v = (mask & index[dim - 1 - i]) << (bits_per_dim * i);
373 res |= v;
374 }
375 return res;
376 }
377
378
379
380 std::string
381 compress(const std::string &input)
382 {
383#ifdef DEAL_II_WITH_ZLIB
384 namespace bio = boost::iostreams;
385
386 std::stringstream compressed;
387 std::stringstream origin(input);
388
389 bio::filtering_streambuf<bio::input> out;
390 out.push(bio::gzip_compressor());
391 out.push(origin);
392 bio::copy(out, compressed);
393
394 return compressed.str();
395#else
396 return input;
397#endif
398 }
399
400
401
402 std::string
403 decompress(const std::string &compressed_input)
404 {
405#ifdef DEAL_II_WITH_ZLIB
406 namespace bio = boost::iostreams;
407
408 std::stringstream compressed(compressed_input);
409 std::stringstream decompressed;
410
411 bio::filtering_streambuf<bio::input> out;
412 out.push(bio::gzip_decompressor());
413 out.push(compressed);
414 bio::copy(out, decompressed);
415
416 return decompressed.str();
417#else
418 return compressed_input;
419#endif
420 }
421
422
423
424 std::string
425 encode_base64(const std::vector<unsigned char> &binary_input)
426 {
427 using It = boost::archive::iterators::base64_from_binary<
428 boost::archive::iterators::
429 transform_width<std::vector<unsigned char>::const_iterator, 6, 8>>;
430 auto base64 = std::string(It(binary_input.begin()), It(binary_input.end()));
431 // Add padding.
432 return base64.append((3 - binary_input.size() % 3) % 3, '=');
433 }
434
435
436
437 std::vector<unsigned char>
438 decode_base64(const std::string &base64_input)
439 {
440 using It = boost::archive::iterators::transform_width<
441 boost::archive::iterators::binary_from_base64<
442 std::string::const_iterator>,
443 8,
444 6>;
445 auto binary = std::vector<unsigned char>(It(base64_input.begin()),
446 It(base64_input.end()));
447 // Remove padding.
448 auto length = base64_input.size();
449 if (binary.size() > 2 && base64_input[length - 1] == '=' &&
450 base64_input[length - 2] == '=')
451 {
452 binary.erase(binary.end() - 2, binary.end());
453 }
454 else if (binary.size() > 1 && base64_input[length - 1] == '=')
455 {
456 binary.erase(binary.end() - 1, binary.end());
457 }
458 return binary;
459 }
460
461
462
463 std::string
464 int_to_string(const unsigned int value, const unsigned int digits)
465 {
466 return to_string(value, digits);
467 }
468
469
470
471 template <typename number>
472 std::string
473 to_string(const number value, const unsigned int digits)
474 {
475 // For integer data types, use the standard std::to_string()
476 // function. On the other hand, that function is defined in terms
477 // of std::sprintf, which does not use the usual std::iostream
478 // interface and tries to render floating point numbers in awkward
479 // ways (see
480 // https://en.cppreference.com/w/cpp/string/basic_string/to_string). So
481 // resort to boost::lexical_cast for all other types (in
482 // particular for floating point types.
483 std::string lc_string =
484 (std::is_integral_v<number> ? std::to_string(value) :
485 boost::lexical_cast<std::string>(value));
486
487 if ((digits != numbers::invalid_unsigned_int) &&
488 (lc_string.size() < digits))
489 {
490 // We have to add the padding zeroes in front of the number
491 const unsigned int padding_position = (lc_string[0] == '-') ? 1 : 0;
492
493 const std::string padding(digits - lc_string.size(), '0');
494 lc_string.insert(padding_position, padding);
495 }
496
497 return lc_string;
498 }
499
500
501
502 std::string
503 replace_in_string(const std::string &input,
504 const std::string &from,
505 const std::string &to)
506 {
507 if (from.empty())
508 return input;
509
510 std::string out = input;
511 std::string::size_type pos = out.find(from);
512
513 while (pos != std::string::npos)
514 {
515 out.replace(pos, from.size(), to);
516 pos = out.find(from, pos + to.size());
517 }
518 return out;
519 }
520
521 std::string
522 trim(const std::string &input)
523 {
524 std::string::size_type left = 0;
525 std::string::size_type right = input.size() > 0 ? input.size() - 1 : 0;
526
527 for (; left < input.size(); ++left)
528 {
529 if (std::isspace(input[left]) == 0)
530 {
531 break;
532 }
533 }
534
535 for (; right >= left; --right)
536 {
537 if (std::isspace(input[right]) == 0)
538 {
539 break;
540 }
541 }
542
543 return std::string(input, left, right - left + 1);
544 }
545
546
547
548 std::string
549 dim_string(const int dim, const int spacedim)
550 {
551 if (dim == spacedim)
552 return int_to_string(dim);
553 else
554 return int_to_string(dim) + "," + int_to_string(spacedim);
555 }
556
557
558 unsigned int
559 needed_digits(const unsigned int max_number)
560 {
561 if (max_number > 0)
562 return static_cast<int>(
563 std::ceil(std::log10(std::fabs(max_number + 0.1))));
564
565 return 1;
566 }
567
568
569
570 template <typename Number>
571 Number
572 truncate_to_n_digits(const Number number, const unsigned int n_digits)
573 {
574 AssertThrow(n_digits >= 1, ExcMessage("invalid parameter."));
575
576 if (!(std::fabs(number) > std::numeric_limits<Number>::min()))
577 return number;
578
579 const int order =
580 static_cast<int>(std::floor(std::log10(std::fabs(number))));
581
582 const int shift = -order + static_cast<int>(n_digits) - 1;
583
584 Assert(shift <= static_cast<int>(std::floor(
585 std::log10(std::numeric_limits<Number>::max()))),
587 "Overflow. Use a smaller value for n_digits and/or make sure "
588 "that the absolute value of 'number' does not become too small."));
589
590 const Number factor = std::pow(10.0, static_cast<Number>(shift));
591
592 const Number number_cutoff = std::trunc(number * factor) / factor;
593
594 return number_cutoff;
595 }
596
597
598 int
599 string_to_int(const std::string &s_)
600 {
601 // trim whitespace on either side of the text if necessary
602 std::string s = s_;
603 while ((s.size() > 0) && (s[0] == ' '))
604 s.erase(s.begin());
605 while ((s.size() > 0) && (s.back() == ' '))
606 s.erase(s.end() - 1);
607
608 // Now convert and see whether we succeed:
609 std::size_t pos;
610 int i = std::numeric_limits<int>::max();
611 try
612 {
613 i = std::stoi(s, &pos);
614
615 // If we got here, std::stod() has succeeded (rather than throwing an
616 // exception) but it is entirely possible that it only succeeded
617 // in reading a number from the first part of the string. In that
618 // case, it will have set 'pos' to a number of characters
619 // processed that is less than the length of the string. If that is
620 // the case, throw an (arbitrary) exception that gets us into the
621 // 'catch' clause below so that we can issue a proper exception:
622 if (pos < s.size())
623 throw 1;
624 }
625 catch (...)
626 {
627 AssertThrow(false,
628 ExcMessage("Can't convert <" + s + "> to a double."));
629 }
630
631 return i;
632 }
633
634
635
636 std::vector<int>
637 string_to_int(const std::vector<std::string> &s)
638 {
639 std::vector<int> tmp(s.size());
640 for (unsigned int i = 0; i < s.size(); ++i)
641 tmp[i] = string_to_int(s[i]);
642 return tmp;
643 }
644
645
646
647 double
648 string_to_double(const std::string &s_)
649 {
650 // trim whitespace on either side of the text if necessary
651 std::string s = s_;
652 while ((s.size() > 0) && (s[0] == ' '))
653 s.erase(s.begin());
654 while ((s.size() > 0) && (s.back() == ' '))
655 s.erase(s.end() - 1);
656
657 // Now convert and see whether we succeed:
658 std::size_t pos;
660 try
661 {
662 d = std::stod(s, &pos);
663
664 // If we got here, std::stod() has succeeded (rather than throwing an
665 // exception) but it is entirely possible that it only succeeded
666 // in reading a number from the first part of the string. In that
667 // case, it will have set 'pos' to a number of characters
668 // processed that is less than the length of the string. If that is
669 // the case, throw an (arbitrary) exception that gets us into the
670 // 'catch' clause below so that we can issue a proper exception:
671 if (pos < s.size())
672 throw 1;
673 }
674 catch (...)
675 {
676 AssertThrow(false,
677 ExcMessage("Can't convert <" + s + "> to a double."));
678 }
679
680 return d;
681 }
682
683
684
685 std::vector<double>
686 string_to_double(const std::vector<std::string> &s)
687 {
688 std::vector<double> tmp(s.size());
689 for (unsigned int i = 0; i < s.size(); ++i)
690 tmp[i] = string_to_double(s[i]);
691 return tmp;
692 }
693
694
695
696 std::vector<std::string>
697 split_string_list(const std::string &s, const std::string &delimiter)
698 {
699 // keep the currently remaining part of the input string in 'tmp' and
700 // keep chopping elements of the list off the front
701 std::string tmp = s;
702
703 // as discussed in the documentation, eat whitespace from the end
704 // of the string
705 while (tmp.size() != 0 && tmp.back() == ' ')
706 tmp.erase(tmp.size() - 1, 1);
707
708 // split the input list until it is empty. since in every iteration
709 // 'tmp' is what's left of the string after the next delimiter,
710 // and since we've stripped trailing space already, 'tmp' will
711 // be empty at one point if 's' ended in a delimiter, even if
712 // there was space after the last delimiter. this matches what's
713 // discussed in the documentation
714 std::vector<std::string> split_list;
715 while (tmp.size() != 0)
716 {
717 std::string name;
718 name = tmp;
719
720 if (name.find(delimiter) != std::string::npos)
721 {
722 name.erase(name.find(delimiter), std::string::npos);
723 tmp.erase(0, tmp.find(delimiter) + delimiter.size());
724 }
725 else
726 tmp = "";
727
728 // strip spaces from this element's front and end
729 while ((name.size() != 0) && (name[0] == ' '))
730 name.erase(0, 1);
731 while (name.size() != 0 && name.back() == ' ')
732 name.erase(name.size() - 1, 1);
733
734 split_list.push_back(name);
735 }
736
737 return split_list;
738 }
739
740
741 std::vector<std::string>
742 split_string_list(const std::string &s, const char delimiter)
743 {
744 std::string d = ",";
745 d[0] = delimiter;
746 return split_string_list(s, d);
747 }
748
749
750 std::vector<std::string>
751 break_text_into_lines(const std::string &original_text,
752 const unsigned int width,
753 const char delimiter)
754 {
755 std::string text = original_text;
756 std::vector<std::string> lines;
757
758 // remove trailing spaces
759 while ((text.size() != 0) && (text.back() == delimiter))
760 text.erase(text.size() - 1, 1);
761
762 // then split the text into lines
763 while (text.size() != 0)
764 {
765 // in each iteration, first remove
766 // leading spaces
767 while ((text.size() != 0) && (text[0] == delimiter))
768 text.erase(0, 1);
769
770 std::size_t pos_newline = text.find_first_of('\n', 0);
771 if (pos_newline != std::string::npos && pos_newline <= width)
772 {
773 std::string line(text, 0, pos_newline);
774 while ((line.size() != 0) && (line.back() == delimiter))
775 line.erase(line.size() - 1, 1);
776 lines.push_back(line);
777 text.erase(0, pos_newline + 1);
778 continue;
779 }
780
781 // if we can fit everything into one
782 // line, then do so. otherwise, we have
783 // to keep breaking
784 if (text.size() < width)
785 {
786 // remove trailing spaces
787 while ((text.size() != 0) && (text.back() == delimiter))
788 text.erase(text.size() - 1, 1);
789 lines.push_back(text);
790 text = "";
791 }
792 else
793 {
794 // starting at position width, find the
795 // location of the previous space, so
796 // that we can break around there
797 int location = std::min<int>(width, text.size() - 1);
798 for (; location > 0; --location)
799 if (text[location] == delimiter)
800 break;
801
802 // if there are no spaces, then try if
803 // there are spaces coming up
804 if (location == 0)
805 for (location = std::min<int>(width, text.size() - 1);
806 location < static_cast<int>(text.size());
807 ++location)
808 if (text[location] == delimiter)
809 break;
810
811 // now take the text up to the found
812 // location and put it into a single
813 // line, and remove it from 'text'
814 std::string line(text, 0, location);
815 while ((line.size() != 0) && (line.back() == delimiter))
816 line.erase(line.size() - 1, 1);
817 lines.push_back(line);
818 text.erase(0, location);
819 }
820 }
821
822 return lines;
823 }
824
825
826
827 bool
828 match_at_string_start(const std::string &name, const std::string &pattern)
829 {
830 if (pattern.size() > name.size())
831 return false;
832
833 for (unsigned int i = 0; i < pattern.size(); ++i)
834 if (pattern[i] != name[i])
835 return false;
836
837 return true;
838 }
839
840
841
842 std::pair<int, unsigned int>
843 get_integer_at_position(const std::string &name, const unsigned int position)
844 {
845 Assert(position < name.size(), ExcInternalError());
846
847 const std::string test_string(name.begin() + position, name.end());
848
849 std::istringstream str(test_string);
850
851 int i;
852 if (str >> i)
853 {
854 // compute the number of
855 // digits of i. assuming it
856 // is less than 8 is likely
857 // ok
858 if (i < 10)
859 return std::make_pair(i, 1U);
860 else if (i < 100)
861 return std::make_pair(i, 2U);
862 else if (i < 1000)
863 return std::make_pair(i, 3U);
864 else if (i < 10000)
865 return std::make_pair(i, 4U);
866 else if (i < 100000)
867 return std::make_pair(i, 5U);
868 else if (i < 1000000)
869 return std::make_pair(i, 6U);
870 else if (i < 10000000)
871 return std::make_pair(i, 7U);
872 else
873 {
875 return std::make_pair(-1, numbers::invalid_unsigned_int);
876 }
877 }
878 else
879 return std::make_pair(-1, numbers::invalid_unsigned_int);
880 }
881
882
883
884 double
885 generate_normal_random_number(const double a, const double sigma)
886 {
887 // if no noise: return now
888 if (sigma == 0)
889 return a;
890
891 // we would want to use rand(), but that function is not reentrant
892 // in a thread context. one could use rand_r, but this does not
893 // produce reproducible results between threads either (though at
894 // least it is reentrant). these two approaches being
895 // non-workable, use a thread-local random number generator here.
896 // we could use std::mt19937 but doing so results in compiler-dependent
897 // output.
898 static Threads::ThreadLocalStorage<boost::mt19937> random_number_generator;
899 return boost::normal_distribution<>(a,
900 sigma)(random_number_generator.get());
901 }
902
903
904
905 namespace System
906 {
907#ifdef __linux__
908
909 double
911 {
912 std::ifstream cpuinfo;
913 cpuinfo.open("/proc/loadavg");
914
915 AssertThrow(cpuinfo.fail() == false, ExcIO());
916
917 double load;
918 cpuinfo >> load;
919
920 return load;
921 }
922
923#else
924
925 double
927 {
928 return 0.;
929 }
930
931#endif
932
933 std::string
935 {
937 {
938 case 0:
939 return "disabled";
940 case 128:
941#ifdef __ALTIVEC__
942 return "AltiVec";
943#else
944 return "SSE2";
945#endif
946 case 256:
947 return "AVX";
948 case 512:
949 return "AVX512";
950 default:
951 AssertThrow(false,
953 "Invalid DEAL_II_VECTORIZATION_WIDTH_IN_BITS."));
954 return "ERROR";
955 }
956 }
957
958
959 void
961 {
962 stats.VmPeak = stats.VmSize = stats.VmHWM = stats.VmRSS = 0;
963
964 // parsing /proc/self/stat would be a
965 // lot easier, but it does not contain
966 // VmHWM, so we use /status instead.
967#ifdef __linux__
968 std::ifstream file("/proc/self/status");
969 std::string line;
970 std::string name;
971 while (!file.eof())
972 {
973 file >> name;
974 if (name == "VmPeak:")
975 file >> stats.VmPeak;
976 else if (name == "VmSize:")
977 file >> stats.VmSize;
978 else if (name == "VmHWM:")
979 file >> stats.VmHWM;
980 else if (name == "VmRSS:")
981 {
982 file >> stats.VmRSS;
983 break; // this is always the last entry
984 }
985
986 getline(file, line);
987 }
988#endif
989 }
990
991
992
993 std::string
995 {
996#if defined(DEAL_II_HAVE_UNISTD_H) && defined(DEAL_II_HAVE_GETHOSTNAME)
997 const unsigned int N = 1024;
998 char hostname[N];
999 gethostname(&(hostname[0]), N - 1);
1000#else
1001 std::string hostname("unknown");
1002#endif
1003 return hostname;
1004 }
1005
1006
1007
1008 std::string
1010 {
1011 std::time_t time1 = std::time(nullptr);
1012 const std::tm *time = std::localtime(&time1);
1013
1014 std::ostringstream o;
1015 o << time->tm_hour << ":" << (time->tm_min < 10 ? "0" : "")
1016 << time->tm_min << ":" << (time->tm_sec < 10 ? "0" : "")
1017 << time->tm_sec;
1018
1019 return o.str();
1020 }
1021
1022
1023
1024 std::string
1026 {
1027 std::time_t time1 = std::time(nullptr);
1028 const std::tm *time = std::localtime(&time1);
1029
1030 std::ostringstream o;
1031 o << time->tm_year + 1900 << "/" << time->tm_mon + 1 << "/"
1032 << time->tm_mday;
1033
1034 return o.str();
1035 }
1036
1037
1038
1039 void
1040 posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
1041 {
1042 // Strictly speaking, one can call both posix_memalign() and malloc()
1043 // with size==0. This is documented as returning a pointer that can
1044 // be given to free(), but for which using it is otherwise undefined.
1045 // That just seems like a bad idea -- let's just return a nullptr to
1046 // *ensure* that it can not be used. free() is documented as accepting
1047 // a nullptr, in which it simply does nothing.
1048 if (size > 0)
1049 {
1050#ifndef DEAL_II_MSVC
1051 const int ierr = ::posix_memalign(memptr, alignment, size);
1052
1053 AssertThrow(ierr == 0, ExcOutOfMemory(size));
1054 AssertThrow(*memptr != nullptr, ExcOutOfMemory(size));
1055#else
1056 // Windows does not appear to have posix_memalign. just use the
1057 // regular malloc in that case
1058 *memptr = std::malloc(size);
1059 (void)alignment;
1060 AssertThrow(*memptr != nullptr, ExcOutOfMemory(size));
1061#endif
1062 }
1063 else
1064 *memptr = nullptr;
1065 }
1066
1067
1068
1069 bool
1074 } // namespace System
1075
1076#ifndef DOXYGEN
1077 template std::string
1078 to_string<int>(int, unsigned int);
1079 template std::string
1080 to_string<long int>(long int, unsigned int);
1081 template std::string
1082 to_string<long long int>(long long int, unsigned int);
1083 template std::string
1084 to_string<unsigned int>(unsigned int, unsigned int);
1085 template std::string
1086 to_string<unsigned long int>(unsigned long int, unsigned int);
1087 template std::string
1088 to_string<unsigned long long int>(unsigned long long int, unsigned int);
1089 template std::string
1090 to_string<float>(float, unsigned int);
1091 template std::string
1092 to_string<double>(double, unsigned int);
1093 template std::string
1094 to_string<long double>(long double, unsigned int);
1095
1096 template double
1097 truncate_to_n_digits(const double, const unsigned int);
1098 template float
1099 truncate_to_n_digits(const float, const unsigned int);
1100
1101 template std::vector<std::array<std::uint64_t, 1>>
1103 const std::vector<Point<1, double>> &,
1104 const int);
1105 template std::vector<std::array<std::uint64_t, 1>>
1107 const std::vector<std::array<std::uint64_t, 1>> &,
1108 const int);
1109 template std::vector<std::array<std::uint64_t, 2>>
1111 const std::vector<Point<2, double>> &,
1112 const int);
1113 template std::vector<std::array<std::uint64_t, 2>>
1115 const std::vector<std::array<std::uint64_t, 2>> &,
1116 const int);
1117 template std::vector<std::array<std::uint64_t, 3>>
1119 const std::vector<Point<3, double>> &,
1120 const int);
1121 template std::vector<std::array<std::uint64_t, 3>>
1123 const std::vector<std::array<std::uint64_t, 3>> &,
1124 const int);
1125
1126 template std::uint64_t
1127 pack_integers<1>(const std::array<std::uint64_t, 1> &, const int);
1128 template std::uint64_t
1129 pack_integers<2>(const std::array<std::uint64_t, 2> &, const int);
1130 template std::uint64_t
1131 pack_integers<3>(const std::array<std::uint64_t, 3> &, const int);
1132
1133#endif
1134
1135} // namespace Utilities
1136
Definition point.h:111
A class that provides a separate storage location on each thread that accesses the object.
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_PACKAGE_VERSION
Definition config.h:27
#define DEAL_II_VECTORIZATION_WIDTH_IN_BITS
Definition config.h:198
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_PACKAGE_NAME
Definition config.h:25
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcInvalidNumber2StringConversersion(unsigned int arg1, unsigned int arg2)
static ::ExceptionBase & ExcOutOfMemory(std::size_t arg1)
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcInvalidNumber(unsigned int arg1)
#define Assert(cond, exc)
#define DeclException2(Exception2, type1, type2, outsequence)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcCantConvertString(std::string arg1)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
const bool IsBlockVector< VectorType >::value
bool job_supports_mpi()
Definition mpi.cc:680
void get_memory_stats(MemoryStats &stats)
Definition utilities.cc:960
std::string get_hostname()
Definition utilities.cc:994
std::string get_time()
void posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
double get_cpu_load()
Definition utilities.cc:926
std::string get_current_vectorization_level()
Definition utilities.cc:934
std::string get_date()
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition utilities.cc:697
Number truncate_to_n_digits(const Number number, const unsigned int n_digits)
Definition utilities.cc:572
std::string dim_string(const int dim, const int spacedim)
Definition utilities.cc:549
std::uint64_t pack_integers(const std::array< std::uint64_t, dim > &index, const int bits_per_dim)
Definition utilities.cc:358
std::pair< int, unsigned int > get_integer_at_position(const std::string &name, const unsigned int position)
Definition utilities.cc:843
std::string encode_base64(const std::vector< unsigned char > &binary_input)
Definition utilities.cc:425
std::string replace_in_string(const std::string &input, const std::string &from, const std::string &to)
Definition utilities.cc:503
std::vector< unsigned char > decode_base64(const std::string &base64_input)
Definition utilities.cc:438
std::vector< std::string > break_text_into_lines(const std::string &original_text, const unsigned int width, const char delimiter=' ')
Definition utilities.cc:751
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:473
std::vector< std::array< std::uint64_t, dim > > inverse_Hilbert_space_filling_curve(const std::vector< Point< dim, Number > > &points, const int bits_per_dim=64)
Definition utilities.cc:138
std::string compress(const std::string &input)
Definition utilities.cc:381
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition utilities.cc:464
bool match_at_string_start(const std::string &name, const std::string &pattern)
Definition utilities.cc:828
std::string decompress(const std::string &compressed_input)
Definition utilities.cc:403
unsigned int needed_digits(const unsigned int max_number)
Definition utilities.cc:559
double string_to_double(const std::string &s)
Definition utilities.cc:648
std::string dealii_version_string()
Definition utilities.cc:87
std::string trim(const std::string &input)
Definition utilities.cc:522
double generate_normal_random_number(const double a, const double sigma)
Definition utilities.cc:885
int string_to_int(const std::string &s)
Definition utilities.cc:599
constexpr unsigned int invalid_unsigned_int
Definition types.h:236
T signaling_nan()
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)