1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 | // *****************************************************************************
/*!
\file src/Inciter/DiagReducer.cpp
\copyright 2012-2015 J. Bakosi,
2016-2018 Los Alamos National Security, LLC.,
2019-2021 Triad National Security, LLC.
All rights reserved. See the LICENSE file for details.
\brief Custom Charm++ reducer for merging std::vectors across PEs
\details Custom Charm++ reducer for merging std::vectors across PEs.
*/
// *****************************************************************************
#include <stddef.h>
#include <type_traits>
#include <memory>
#include "DiagReducer.hpp"
#include "Diagnostics.hpp"
#include "Exception.hpp"
namespace inciter {
std::pair< int, std::unique_ptr<char[]> >
serialize( std::size_t meshid, const std::vector< std::vector< tk::real > >& d )
// *****************************************************************************
// Serialize std::vectors to raw memory stream
//! \param[in] meshid Mesh ID
//! \param[in] d Diagnostics vector of vectors (of eq components)
//! \return Pair of the length and the raw stream containing the serialized
//! vectors
// *****************************************************************************
{
// Prepare for serializing diagnostics to a raw binary stream, compute size
PUP::sizer sizer;
sizer | meshid;
sizer | const_cast< std::vector< std::vector< tk::real > >& >( d );
// Create raw character stream to store the serialized vectors
std::unique_ptr<char[]> flatData = std::make_unique<char[]>( sizer.size() );
// Serialize vector, each message will contain a vector
PUP::toMem packer( flatData.get() );
packer | meshid;
packer | const_cast< std::vector< std::vector< tk::real > >& >( d );
// Return size of and raw stream
return { sizer.size(), std::move(flatData) };
}
CkReductionMsg*
mergeDiag( int nmsg, CkReductionMsg **msgs )
// *****************************************************************************
// Charm++ custom reducer for merging diagnostics during reduction across PEs
//! \param[in] nmsg Number of messages in msgs
//! \param[in] msgs Charm++ reduction message containing the serialized
//! diagnostics
//! \return Aggregated diagnostics built for further aggregation if needed
// *****************************************************************************
{
// Will store deserialized diagnostics vector of vectors
std::size_t meshid;
std::vector< std::vector< tk::real > > v;
// Create PUP deserializer based on message passed in
PUP::fromMem creator( msgs[0]->getData() );
// Deserialize vector from raw stream
creator | meshid;<--- Uninitialized variable: meshid
creator | v;
for (int m=1; m<nmsg; ++m) {
// Unpack vector
std::size_t mid;
std::vector< std::vector< tk::real > > w;
PUP::fromMem curCreator( msgs[m]->getData() );
curCreator | mid;<--- Uninitialized variable: mid
curCreator | w;
// Aggregate diagnostics vector
meshid = mid;<--- Uninitialized variable: mid<--- Variable 'meshid' is assigned a value that is never used.
Assert( v.size() == w.size(),
"Size mismatch during diagnostics aggregation" );
Assert( v.size() == inciter::NUMDIAG,
"Size mismatch during diagnostics aggregation" );
for (std::size_t i=0; i<v.size(); ++i)<--- Unsigned less than zero
Assert( v[i].size() == w[i].size(),
"Size mismatch during diagnostics aggregation" );
// Apply diagnostics aggregation policy
// Sum for L2 normal of the numerical solution for all scalar components
for (std::size_t i=0; i<v[L2SOL].size(); ++i) v[L2SOL][i] += w[L2SOL][i];
// Sum for the L2 norm of the numerical - analytical solution for all comps
for (std::size_t i=0; i<v[L2ERR].size(); ++i) v[L2ERR][i] += w[L2ERR][i];
// Sum for the L2 norm of the residual of all components
for (std::size_t i=0; i<v[L2RES].size(); ++i) v[L2RES][i] += w[L2RES][i];
// Max for the Linf norm of the numerical - analytical solution for all comp
for (std::size_t i=0; i<v[LINFERR].size(); ++i)
if (w[LINFERR][i] > v[LINFERR][i]) v[LINFERR][i] = w[LINFERR][i];
// Sum of the total energy over the entire domain
v[TOTALSOL][0] += w[TOTALSOL][0];
// Copy ITER, TIME, DT
for (std::size_t j=v.size()-3; j<v.size(); ++j)
for (std::size_t i=0; i<v[j].size(); ++i)
v[j][i] = w[j][i];
}
// Serialize concatenated diagnostics vector to raw stream
auto stream = serialize( meshid, v );
// Forward serialized diagnostics
return CkReductionMsg::buildNew( stream.first, stream.second.get() );
}
} // inciter::
|