deal.II version GIT relicensing-6809-ge913b9bb34 2026-09-25 17:20:01+00:00
\(\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"
131 return inverse_Hilbert_space_filling_curve<effective_dim>(int_points,
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 lc_string.insert(padding_position, digits - lc_string.size(), '0');
493 }
494
495 return lc_string;
496 }
497
498
499
500 std::string
501 replace_in_string(const std::string &input,
502 const std::string &from,
503 const std::string &to)
504 {
505 if (from.empty())
506 return input;
507
508 std::string out = input;
509 std::string::size_type pos = out.find(from);
510
511 while (pos != std::string::npos)
512 {
513 out.replace(pos, from.size(), to);
514 pos = out.find(from, pos + to.size());
515 }
516 return out;
517 }
518
519 std::string
520 trim(const std::string &input)
521 {
522 std::string::size_type left = 0;
523 std::string::size_type right = input.size() > 0 ? input.size() - 1 : 0;
524
525 for (; left < input.size(); ++left)
526 {
527 if (std::isspace(input[left]) == 0)
528 {
529 break;
530 }
531 }
532
533 for (; right >= left; --right)
534 {
535 if (std::isspace(input[right]) == 0)
536 {
537 break;
538 }
539 }
540
541 return std::string(input, left, right - left + 1);
542 }
543
544
545
546 std::string
547 dim_string(const int dim, const int spacedim)
548 {
549 if (dim == spacedim)
550 return int_to_string(dim);
551 else
552 return int_to_string(dim) + "," + int_to_string(spacedim);
553 }
554
555
556 unsigned int
557 needed_digits(const unsigned int max_number)
558 {
559 if (max_number > 0)
560 return static_cast<int>(
561 std::ceil(std::log10(std::fabs(max_number + 0.1))));
562
563 return 1;
564 }
565
566
567
568 template <typename Number>
569 Number
570 truncate_to_n_digits(const Number number, const unsigned int n_digits)
571 {
572 AssertThrow(n_digits >= 1, ExcMessage("invalid parameter."));
573
574 if (!(std::fabs(number) > std::numeric_limits<Number>::min()))
575 return number;
576
577 const int order =
578 static_cast<int>(std::floor(std::log10(std::fabs(number))));
579
580 const int shift = -order + static_cast<int>(n_digits) - 1;
581
582 Assert(shift <= static_cast<int>(std::floor(
583 std::log10(std::numeric_limits<Number>::max()))),
585 "Overflow. Use a smaller value for n_digits and/or make sure "
586 "that the absolute value of 'number' does not become too small."));
587
588 const Number factor = std::pow(10.0, static_cast<Number>(shift));
589
590 const Number number_cutoff = std::trunc(number * factor) / factor;
591
592 return number_cutoff;
593 }
594
595
596 int
597 string_to_int(const std::string &s_)
598 {
599 // trim whitespace on either side of the text if necessary
600 std::string s = s_;
601 while ((s.size() > 0) && (s[0] == ' '))
602 s.erase(s.begin());
603 while ((s.size() > 0) && (s.back() == ' '))
604 s.erase(s.end() - 1);
605
606 // Now convert and see whether we succeed:
607 std::size_t pos;
608 int i = std::numeric_limits<int>::max();
609 try
610 {
611 i = std::stoi(s, &pos);
612
613 // If we got here, std::stod() has succeeded (rather than throwing an
614 // exception) but it is entirely possible that it only succeeded
615 // in reading a number from the first part of the string. In that
616 // case, it will have set 'pos' to a number of characters
617 // processed that is less than the length of the string. If that is
618 // the case, throw an (arbitrary) exception that gets us into the
619 // 'catch' clause below so that we can issue a proper exception:
620 if (pos < s.size())
621 throw 1;
622 }
623 catch (...)
624 {
625 AssertThrow(false,
626 ExcMessage("Can't convert <" + s + "> to a double."));
627 }
628
629 return i;
630 }
631
632
633
634 std::vector<int>
635 string_to_int(const std::vector<std::string> &s)
636 {
637 std::vector<int> tmp(s.size());
638 for (unsigned int i = 0; i < s.size(); ++i)
639 tmp[i] = string_to_int(s[i]);
640 return tmp;
641 }
642
643
644
645 double
646 string_to_double(const std::string &s_)
647 {
648 // trim whitespace on either side of the text if necessary
649 std::string s = s_;
650 while ((s.size() > 0) && (s[0] == ' '))
651 s.erase(s.begin());
652 while ((s.size() > 0) && (s.back() == ' '))
653 s.erase(s.end() - 1);
654
655 // Now convert and see whether we succeed:
656 std::size_t pos;
657 double d = numbers::signaling_nan<double>();
658 try
659 {
660 d = std::stod(s, &pos);
661
662 // If we got here, std::stod() has succeeded (rather than throwing an
663 // exception) but it is entirely possible that it only succeeded
664 // in reading a number from the first part of the string. In that
665 // case, it will have set 'pos' to a number of characters
666 // processed that is less than the length of the string. If that is
667 // the case, throw an (arbitrary) exception that gets us into the
668 // 'catch' clause below so that we can issue a proper exception:
669 if (pos < s.size())
670 throw 1;
671 }
672 catch (...)
673 {
674 AssertThrow(false,
675 ExcMessage("Can't convert <" + s + "> to a double."));
676 }
677
678 return d;
679 }
680
681
682
683 std::vector<double>
684 string_to_double(const std::vector<std::string> &s)
685 {
686 std::vector<double> tmp(s.size());
687 for (unsigned int i = 0; i < s.size(); ++i)
688 tmp[i] = string_to_double(s[i]);
689 return tmp;
690 }
691
692
693
694 std::vector<std::string>
695 split_string_list(const std::string &s, const std::string &delimiter)
696 {
697 // keep the currently remaining part of the input string in 'tmp' and
698 // keep chopping elements of the list off the front
699 std::string tmp = s;
700
701 // as discussed in the documentation, eat whitespace from the end
702 // of the string
703 while (tmp.size() != 0 && tmp.back() == ' ')
704 tmp.erase(tmp.size() - 1, 1);
705
706 // split the input list until it is empty. since in every iteration
707 // 'tmp' is what's left of the string after the next delimiter,
708 // and since we've stripped trailing space already, 'tmp' will
709 // be empty at one point if 's' ended in a delimiter, even if
710 // there was space after the last delimiter. this matches what's
711 // discussed in the documentation
712 std::vector<std::string> split_list;
713 while (tmp.size() != 0)
714 {
715 std::string name;
716 name = tmp;
717
718 if (name.find(delimiter) != std::string::npos)
719 {
720 name.erase(name.find(delimiter), std::string::npos);
721 tmp.erase(0, tmp.find(delimiter) + delimiter.size());
722 }
723 else
724 tmp = "";
725
726 // strip spaces from this element's front and end
727 while ((name.size() != 0) && (name[0] == ' '))
728 name.erase(0, 1);
729 while (name.size() != 0 && name.back() == ' ')
730 name.erase(name.size() - 1, 1);
731
732 split_list.push_back(name);
733 }
734
735 return split_list;
736 }
737
738
739 std::vector<std::string>
740 split_string_list(const std::string &s, const char delimiter)
741 {
742 std::string d = ",";
743 d[0] = delimiter;
744 return split_string_list(s, d);
745 }
746
747
748 std::vector<std::string>
749 break_text_into_lines(const std::string &original_text,
750 const unsigned int width,
751 const char delimiter)
752 {
753 std::vector<std::string> lines;
754
755 // First split at each '\n', then wrap every resulting piece to width.
756 std::size_t start = 0;
757 while (true)
758 {
759 const std::size_t pos = original_text.find('\n', start);
760 std::string text = original_text.substr(
761 start, (pos == std::string::npos ? std::string::npos : pos - start));
762
763 // Remove leading/trailing delimiters on this piece.
764 while ((text.size() != 0) && (text.front() == delimiter))
765 text.erase(0, 1);
766 while ((text.size() != 0) && (text.back() == delimiter))
767 text.pop_back();
768
769 if (text.empty())
770 {
771 // Keep blank lines from consecutive newlines, but not a trailing
772 // empty segment from a final '\n' (or a fully empty input).
773 if (pos != std::string::npos)
774 lines.emplace_back();
775 }
776 else
777 {
778 while (text.size() > width)
779 {
780 // Prefer the last delimiter that still yields a line of length
781 // at most width. If there is none, take up to the next
782 // delimiter (a single word longer than width).
783 std::size_t location = text.rfind(delimiter, width);
784 if (location == 0 || location == std::string::npos)
785 {
786 location = text.find(delimiter, width);
787 if (location == std::string::npos)
788 break;
789 }
790
791 std::string line = text.substr(0, location);
792 while ((line.size() != 0) && (line.back() == delimiter))
793 line.pop_back();
794 lines.push_back(line);
795
796 text.erase(0, location);
797 while ((text.size() != 0) && (text.front() == delimiter))
798 text.erase(0, 1);
799 }
800
801 if (text.size() != 0)
802 lines.push_back(text);
803 }
804
805 if (pos == std::string::npos)
806 break;
807 start = pos + 1;
808 }
809
810 return lines;
811 }
812
813
814
815 bool
816 match_at_string_start(const std::string &name, const std::string &pattern)
817 {
818 if (pattern.size() > name.size())
819 return false;
820
821 for (unsigned int i = 0; i < pattern.size(); ++i)
822 if (pattern[i] != name[i])
823 return false;
824
825 return true;
826 }
827
828
829
830 std::pair<int, unsigned int>
831 get_integer_at_position(const std::string &name, const unsigned int position)
832 {
833 Assert(position < name.size(), ExcInternalError());
834
835 const std::string test_string(name.begin() + position, name.end());
836
837 std::istringstream str(test_string);
838
839 int i;
840 if (str >> i)
841 {
842 // compute the number of
843 // digits of i. assuming it
844 // is less than 8 is likely
845 // ok
846 if (i < 10)
847 return std::make_pair(i, 1U);
848 else if (i < 100)
849 return std::make_pair(i, 2U);
850 else if (i < 1000)
851 return std::make_pair(i, 3U);
852 else if (i < 10000)
853 return std::make_pair(i, 4U);
854 else if (i < 100000)
855 return std::make_pair(i, 5U);
856 else if (i < 1000000)
857 return std::make_pair(i, 6U);
858 else if (i < 10000000)
859 return std::make_pair(i, 7U);
860 else
861 {
863 return std::make_pair(-1, numbers::invalid_unsigned_int);
864 }
865 }
866 else
867 return std::make_pair(-1, numbers::invalid_unsigned_int);
868 }
869
870
871
872 double
873 generate_normal_random_number(const double a, const double sigma)
874 {
875 // if no noise: return now
876 if (sigma == 0)
877 return a;
878
879 // we would want to use rand(), but that function is not reentrant
880 // in a thread context. one could use rand_r, but this does not
881 // produce reproducible results between threads either (though at
882 // least it is reentrant). these two approaches being
883 // non-workable, use a thread-local random number generator here.
884 // we could use std::mt19937 but doing so results in compiler-dependent
885 // output.
886 static Threads::ThreadLocalStorage<boost::mt19937> random_number_generator;
887 return boost::normal_distribution<>(a,
888 sigma)(random_number_generator.get());
889 }
890
891
892
893 namespace System
894 {
895#ifdef __linux__
896
897 double
899 {
900 std::ifstream cpuinfo;
901 cpuinfo.open("/proc/loadavg");
902
903 AssertThrow(cpuinfo.fail() == false, ExcIO());
904
905 double load;
906 cpuinfo >> load;
907
908 return load;
909 }
910
911#else
912
913 double
915 {
916 return 0.;
917 }
918
919#endif
920
921 std::string
923 {
925 {
926 case 0:
927 return "disabled";
928 case 128:
929#ifdef __ALTIVEC__
930 return "AltiVec";
931#else
932 return "SSE2";
933#endif
934 case 256:
935 return "AVX";
936 case 512:
937 return "AVX512";
938 default:
939 AssertThrow(false,
941 "Invalid DEAL_II_VECTORIZATION_WIDTH_IN_BITS."));
942 return "ERROR";
943 }
944 }
945
946
947 void
949 {
950 stats.VmPeak = stats.VmSize = stats.VmHWM = stats.VmRSS = 0;
951
952 // parsing /proc/self/stat would be a
953 // lot easier, but it does not contain
954 // VmHWM, so we use /status instead.
955#ifdef __linux__
956 std::ifstream file("/proc/self/status");
957 std::string line;
958 std::string name;
959 while (!file.eof())
960 {
961 file >> name;
962 if (name == "VmPeak:")
963 file >> stats.VmPeak;
964 else if (name == "VmSize:")
965 file >> stats.VmSize;
966 else if (name == "VmHWM:")
967 file >> stats.VmHWM;
968 else if (name == "VmRSS:")
969 {
970 file >> stats.VmRSS;
971 break; // this is always the last entry
972 }
973
974 getline(file, line);
975 }
976#endif
977 }
978
979
980
981 std::string
983 {
984#if defined(DEAL_II_HAVE_UNISTD_H) && defined(DEAL_II_HAVE_GETHOSTNAME)
985 const unsigned int N = 1024;
986 char hostname[N];
987 gethostname(&(hostname[0]), N - 1);
988#else
989 std::string hostname("unknown");
990#endif
991 return hostname;
992 }
993
994
995
996 std::string
998 {
999 std::time_t time1 = std::time(nullptr);
1000 const std::tm *time = std::localtime(&time1);
1001
1002 std::ostringstream o;
1003 o << time->tm_hour << ":" << (time->tm_min < 10 ? "0" : "")
1004 << time->tm_min << ":" << (time->tm_sec < 10 ? "0" : "")
1005 << time->tm_sec;
1006
1007 return o.str();
1008 }
1009
1010
1011
1012 std::string
1014 {
1015 std::time_t time1 = std::time(nullptr);
1016 const std::tm *time = std::localtime(&time1);
1017
1018 std::ostringstream o;
1019 o << time->tm_year + 1900 << "/" << time->tm_mon + 1 << "/"
1020 << time->tm_mday;
1021
1022 return o.str();
1023 }
1024
1025
1026
1027 void
1028 posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
1029 {
1030 // Strictly speaking, one can call both posix_memalign() and malloc()
1031 // with size==0. This is documented as returning a pointer that can
1032 // be given to free(), but for which using it is otherwise undefined.
1033 // That just seems like a bad idea -- let's just return a nullptr to
1034 // *ensure* that it can not be used. free() is documented as accepting
1035 // a nullptr, in which it simply does nothing.
1036 if (size > 0)
1037 {
1038#ifndef DEAL_II_MSVC
1039 const int ierr = ::posix_memalign(memptr, alignment, size);
1040
1041 AssertThrow(ierr == 0, ExcOutOfMemory(size));
1042 AssertThrow(*memptr != nullptr, ExcOutOfMemory(size));
1043#else
1044 // Windows does not appear to have posix_memalign. just use the
1045 // regular malloc in that case
1046 *memptr = std::malloc(size);
1047 (void)alignment;
1048 AssertThrow(*memptr != nullptr, ExcOutOfMemory(size));
1049#endif
1050 }
1051 else
1052 *memptr = nullptr;
1053 }
1054
1055
1056
1057 bool
1062 } // namespace System
1063
1064#ifndef DOXYGEN
1065 template std::string
1066 to_string<int>(int, unsigned int);
1067 template std::string
1068 to_string<long int>(long int, unsigned int);
1069 template std::string
1070 to_string<long long int>(long long int, unsigned int);
1071 template std::string
1072 to_string<unsigned int>(unsigned int, unsigned int);
1073 template std::string
1074 to_string<unsigned long int>(unsigned long int, unsigned int);
1075 template std::string
1076 to_string<unsigned long long int>(unsigned long long int, unsigned int);
1077 template std::string
1078 to_string<float>(float, unsigned int);
1079 template std::string
1080 to_string<double>(double, unsigned int);
1081 template std::string
1082 to_string<long double>(long double, unsigned int);
1083
1084 template double
1085 truncate_to_n_digits(const double, const unsigned int);
1086 template float
1087 truncate_to_n_digits(const float, const unsigned int);
1088
1089 template std::vector<std::array<std::uint64_t, 1>>
1090 inverse_Hilbert_space_filling_curve<1, double>(
1091 const std::vector<Point<1, double>> &,
1092 const int);
1093 template std::vector<std::array<std::uint64_t, 1>>
1094 inverse_Hilbert_space_filling_curve<1>(
1095 const std::vector<std::array<std::uint64_t, 1>> &,
1096 const int);
1097 template std::vector<std::array<std::uint64_t, 2>>
1098 inverse_Hilbert_space_filling_curve<2, double>(
1099 const std::vector<Point<2, double>> &,
1100 const int);
1101 template std::vector<std::array<std::uint64_t, 2>>
1102 inverse_Hilbert_space_filling_curve<2>(
1103 const std::vector<std::array<std::uint64_t, 2>> &,
1104 const int);
1105 template std::vector<std::array<std::uint64_t, 3>>
1106 inverse_Hilbert_space_filling_curve<3, double>(
1107 const std::vector<Point<3, double>> &,
1108 const int);
1109 template std::vector<std::array<std::uint64_t, 3>>
1110 inverse_Hilbert_space_filling_curve<3>(
1111 const std::vector<std::array<std::uint64_t, 3>> &,
1112 const int);
1113
1114 template std::uint64_t
1115 pack_integers<1>(const std::array<std::uint64_t, 1> &, const int);
1116 template std::uint64_t
1117 pack_integers<2>(const std::array<std::uint64_t, 2> &, const int);
1118 template std::uint64_t
1119 pack_integers<3>(const std::array<std::uint64_t, 3> &, const int);
1120
1121#endif
1122
1123} // namespace Utilities
1124
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:199
#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)
std::size_t size
Definition mpi.cc:733
bool job_supports_mpi()
Definition mpi.cc:680
void get_memory_stats(MemoryStats &stats)
Definition utilities.cc:948
std::string get_hostname()
Definition utilities.cc:982
std::string get_time()
Definition utilities.cc:997
void posix_memalign(void **memptr, std::size_t alignment, std::size_t size)
double get_cpu_load()
Definition utilities.cc:914
std::string get_current_vectorization_level()
Definition utilities.cc:922
std::string get_date()
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition utilities.cc:695
Number truncate_to_n_digits(const Number number, const unsigned int n_digits)
Definition utilities.cc:570
std::string dim_string(const int dim, const int spacedim)
Definition utilities.cc:547
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:831
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:501
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:749
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:816
std::string decompress(const std::string &compressed_input)
Definition utilities.cc:403
unsigned int needed_digits(const unsigned int max_number)
Definition utilities.cc:557
double string_to_double(const std::string &s)
Definition utilities.cc:646
std::string dealii_version_string()
Definition utilities.cc:87
std::string trim(const std::string &input)
Definition utilities.cc:520
double generate_normal_random_number(const double a, const double sigma)
Definition utilities.cc:873
int string_to_int(const std::string &s)
Definition utilities.cc:597
constexpr unsigned int invalid_unsigned_int
Definition types.h:228
::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)