KASKADE 7 development version
Loading...
Searching...
No Matches
bddcTransferAudit.hh
Go to the documentation of this file.
1
2/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3/* */
4/* This file is part of the library KASKADE 7 */
5/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
6/* */
7/* Copyright (C) 2026 Zuse Institute Berlin */
8/* */
9/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
10/* see $KASKADE/academic.txt */
11/* */
12/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14// Read-only, first-packet transfer audit. Disabled unless explicitly requested.
15#ifndef KASKADE_BDDC_TRANSFER_AUDIT_HH
16#define KASKADE_BDDC_TRANSFER_AUDIT_HH
17#include <algorithm>
18#include <cstdlib>
19#include <filesystem>
20#include <fstream>
21#include <iomanip>
22#include <limits>
23#include <mutex>
24#include <set>
25#include <stdexcept>
26#include <string>
27#include <type_traits>
28#include <vector>
29
31{
32 inline std::string const& directory()
33 {
34 static std::string const path = [] {
35 auto p = std::getenv("KASKADE_TRANSFER_AUDIT_DIR");
36 return std::string(p ? p : "");
37 }();
38 return path;
39 }
40 inline bool enabled() { return !directory().empty(); }
41 inline std::mutex outputMutex;
42 inline std::set<std::string> written;
43
44 // Capture the first observation of each stage on each directed interface.
45 // MPI owners write distinct subdomain names. No reductions, feedback changes,
46 // codebook changes or transfer-counter updates are performed by this observer.
47 template<class T>
48 void vector(char const* phase, char const* direction, int id, int peer,
49 char const* stage, std::vector<T> const& data)
50 {
51 if (!enabled()) return;
52 std::string key = std::string(phase)+"_"+direction+"_"+std::to_string(id)+"_"+
53 std::to_string(peer)+"_"+stage;
54 std::lock_guard<std::mutex> lock(outputMutex);
55 if (written.count(key)) return;
56 std::filesystem::create_directories(directory());
57 std::ofstream out(std::filesystem::path(directory())/(key+".txt"));
58 if (!out) throw std::runtime_error("Cannot open transfer audit: "+key);
59 out << data.size() << '\n' << std::setprecision(std::numeric_limits<double>::max_digits10);
60 for (auto const& value : data)
61 {
62 if constexpr (std::is_integral_v<T>) out << +value << '\n';
63 else out << value << '\n';
64 }
65 out.close();
66 if (!out) throw std::runtime_error("Cannot finish transfer audit: "+key);
67 written.insert(key);
68 }
69
70 // Interface-relative indices describe the exact predictor used in lifting.
71 // Comparing these plans does not depend on subdomain-local DOF numbering.
72 template<class Scalar>
73 void plan(char const* phase, char const* direction, int id, int peer,
74 std::vector<int> const& coarse, std::vector<int> const& fine,
75 std::vector<std::vector<int>> const& neighbors,
76 std::vector<std::vector<Scalar>> const& weights)
77 {
78 if (!enabled()) return;
79 std::vector<std::size_t> offsets{0};
80 std::vector<int> flatNeighbors;
81 std::vector<Scalar> flatWeights;
82 for (std::size_t k=0; k<neighbors.size(); ++k)
83 {
84 flatNeighbors.insert(flatNeighbors.end(),neighbors[k].begin(),neighbors[k].end());
85 flatWeights.insert(flatWeights.end(),weights[k].begin(),weights[k].end());
86 offsets.push_back(flatNeighbors.size());
87 }
88 vector(phase,direction,id,peer,"coarse",coarse);
89 vector(phase,direction,id,peer,"fine",fine);
90 vector(phase,direction,id,peer,"offsets",offsets);
91 vector(phase,direction,id,peer,"neighbors",flatNeighbors);
92 vector(phase,direction,id,peer,"weights",flatWeights);
93 }
94
95 template<class Packet>
96 void wire(char const* phase, char const* direction, int id, int peer,
97 Packet const& packet)
98 {
99 if (!enabled()) return;
100 std::vector<unsigned char> bytes(packet.size()*sizeof(typename Packet::value_type));
101 if (!bytes.empty())
102 {
103 auto p = reinterpret_cast<unsigned char const*>(packet.data());
104 std::copy(p,p+bytes.size(),bytes.begin());
105 }
106 vector(phase,direction,id,peer,"wire",bytes);
107 }
108}
109#endif
void wire(char const *phase, char const *direction, int id, int peer, Packet const &packet)
std::set< std::string > written
void plan(char const *phase, char const *direction, int id, int peer, std::vector< int > const &coarse, std::vector< int > const &fine, std::vector< std::vector< int > > const &neighbors, std::vector< std::vector< Scalar > > const &weights)
std::string const & directory()
void vector(char const *phase, char const *direction, int id, int peer, char const *stage, std::vector< T > const &data)