Vlasiator ebf0dd394 on dev (v5.4.0 + 1054 commits)
Loading...
Searching...
No Matches
compression.cpp
Go to the documentation of this file.
1/*
2 * This file is part of Vlasiator.
3 * Copyright 2010-2024 Finnish Meteorological Institute
4 *
5 * For details of usage, see the COPYING file and read the "Rules of the Road"
6 * at http://www.physics.helsinki.fi/vlasiator/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#include "compression.h"
24#include "compression_tools.h"
25#ifdef ASTERIX_ZFP
26#include "zfp/array1.hpp"
27#include <zfp.h>
28#endif
29#include <atomic>
30#include <concepts>
31#include <cstdint>
32#include <fstream>
33#include <iostream>
34#include <limits>
35#include <map>
36#include <ranges>
37#include <stdexcept>
38#include <type_traits>
39#include <unordered_map>
40#include <vector>
41#include <omp.h>
42
43extern Logger logFile;
44#define ASTERIX_USE_GPU
45#define MEMPOOL_BYTES 60ul*1024ul*1024ul*1024ul
46using namespace ASTERIX;
47using namespace spatial_cell;
48
49#ifdef ASTERIX_MLP
50#ifdef __cplusplus
51extern "C" {
52#endif
53size_t compress_phasespace6D_f64(GENERIC_TS_POOL::MemPool* p, std::size_t fin,std::size_t fout, double* coords_ptr, double* f_ptr,
54 std::size_t size, std::size_t max_epochs, std::size_t fourier_order,
55 size_t* hidden_layers_ptr, size_t n_hidden_layers, double sparsity, double tol,
56 double* weights_ptr, std::size_t weight_size, bool use_input_weights,
57 uint32_t downsampling_factor, double& error, uint32_t& epochs, int& status, int rankID);
58
59size_t compress_phasespace6D_f32(GENERIC_TS_POOL::MemPool* p, std::size_t fin,std::size_t fout, float* coords_ptr, float* f_ptr,
60 std::size_t size, std::size_t max_epochs, std::size_t fourier_order,
61 size_t* hidden_layers_ptr, size_t n_hidden_layers, float sparsity, float tol,
62 float* weights_ptr, std::size_t weight_size, bool use_input_weights,
63 uint32_t downsampling_factor, float& error, uint32_t& epochs, int& status, int rankID);
64
65
66#ifdef __cplusplus
67}
68#endif
69auto compress_vdfs_fourier_mlp(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
70 size_t number_of_spatial_cells, bool update_weights, std::vector<std::vector<char>>&bytes ,uint32_t downsampling_factor)
71 -> float;
72
73auto compress_vdfs_fourier_mlp_clustered(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
74 size_t number_of_spatial_cells, bool update_weights, std::vector<std::vector<char>>&bytes,
75 uint32_t downsampling_factor) -> float;
76#endif //ASTERIX_MLP
77
78#ifdef ASTERIX_ZFP
79
80
81auto compress_vdfs_zfp(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid, const std::vector<CellID>& local_cells)
82 -> float;
83
84auto compress(float* array, size_t arraySize, size_t& compressedSize, float tol) -> std::vector<char>;
85
86auto compress(double* array, size_t arraySize, size_t& compressedSize, double tol) -> std::vector<char>;
87
88auto decompressArrayDouble(char* compressedData, size_t compressedSize, size_t arraySize, double tol)
89 -> std::vector<double>;
90
91auto decompressArrayFloat(char* compressedData, size_t compressedSize, size_t arraySize, float tol)
92 -> std::vector<float>;
93
94#endif //ASTERIX_ZFP
95
96#ifdef ASTERIX_OCTREE
97auto compress_vdfs_octree(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid, const std::vector<CellID>& local_cells)
98 -> float;
99#endif
100
101// Main driver, look at header file for documentation
102void ASTERIX::compress_vdfs(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid, const std::vector<CellID>& cells,
103 P::ASTERIX_COMPRESSION_METHODS method, bool update_weights,
104 std::vector<std::vector<char>>& bytes, uint32_t downsampling_factor /*=1*/) {
105
106 if (downsampling_factor < 1) {
107 throw std::runtime_error("Requested downsampling factor in VDF compression makes no sense!");
108 }
109 float local_compression_ratio = 0.0;
110 switch (method) {
111#ifdef ASTERIX_MLP
113 local_compression_ratio =
114 compress_vdfs_fourier_mlp(mpiGrid, cells.size(), update_weights, bytes,downsampling_factor);
115 break;
117 local_compression_ratio =
118 compress_vdfs_fourier_mlp_clustered(mpiGrid, cells.size(), update_weights, bytes, downsampling_factor);
119 break;
120#endif
121#ifdef ASTERIX_ZFP
123 local_compression_ratio = compress_vdfs_zfp(mpiGrid, cells);
124 break;
125#endif
126#ifdef ASTERIX_OCTREE
128 local_compression_ratio = compress_vdfs_octree(mpiGrid, cells);
129 break;
130#endif
132 break;
133 default:
134 throw std::runtime_error("This is bad!. Improper Asterix method detected!");
135 break;
136 };
137
138 // Reduce global compression ratio
139 int myRank;
140 int mpiProcs;
141 float global_compression_ratio = 0.0;
142 MPI_Comm_size(MPI_COMM_WORLD, &mpiProcs);
143 MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
144 MPI_Barrier(MPI_COMM_WORLD);
145 MPI_Reduce(&local_compression_ratio, &global_compression_ratio, 1, MPI_FLOAT, MPI_SUM, MASTER_RANK, MPI_COMM_WORLD);
146 MPI_Barrier(MPI_COMM_WORLD);
147
148 if (myRank == MASTER_RANK) {
149 logFile << "(VDF COMPRESSION INFO): Compression Ratio = "
150 << global_compression_ratio / static_cast<float>(mpiProcs) << std::endl;
151 }
152}
153
154std::vector<std::pair<std::size_t, std::size_t>> partition(std::size_t array_size, std::size_t chunk_size,
155 std::size_t max_chunks) {
156 std::vector<std::pair<std::size_t, std::size_t>> result;
157 if (array_size == 0 || chunk_size <= 0 || max_chunks <= 0) {
158 throw std::runtime_error("ERROR: catastrophic failure in VDF partitioning.");
159 }
160 std::size_t optimal_chunks = std::max(1.0,std::ceil(array_size / chunk_size));
161 std::size_t numChunks = std::min(optimal_chunks, max_chunks);
162 std::size_t baseSize = array_size / numChunks;
163 std::size_t largerChunks = array_size % numChunks;
164 std::size_t start = 0;
165 for (std::size_t i = 0; i < numChunks; ++i) {
166 std::size_t chunkSize = baseSize + (i < largerChunks ? (1) : (0));
167 result.push_back({start, start + chunkSize});
168 start += chunkSize;
169 }
170 return result;
171}
172
173std::vector<CellID> sort_cells_based_on_maxwellianity(const std::vector<CellID>& local_cells, uint popID,
174 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid) {
175 std::vector<std::pair<CellID, Real>> sorted_vdf;
176 sorted_vdf.reserve(local_cells.size());
177 for (const auto& cid : local_cells) {
178 sorted_vdf.emplace_back(cid, get_Non_MaxWellianity(mpiGrid[cid], popID));
179 }
180 std::ranges::sort(sorted_vdf, {}, &std::pair<CellID, Real>::second);
181 std::vector<CellID> sorted_cells;
182 sorted_cells.reserve(sorted_vdf.size());
183 for (const auto& [cid, _] : sorted_vdf) {
184 sorted_cells.push_back(cid);
185 }
186 return sorted_cells;
187}
188
189#ifdef ASTERIX_MLP
190float compress_vdfs_fourier_mlp(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
191 size_t number_of_spatial_cells, bool update_weights,
192 std::vector<std::vector<char>>& bytes, uint32_t downsampling_factor) {
193
194 //Grab the rank TODO: remove this later
195 GENERIC_TS_POOL::MemPool p{};
196 int myRank;
197 MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
198
199 if (getObjectWrapper().particleSpecies.size() > 1) {
200 throw std::runtime_error("Multi-Pop not implemented yet!");
201 }
202 std::atomic<float> local_compression_achieved = 0.0;
203 std::size_t total_samples = 0;
204 for (uint popID = 0; popID < getObjectWrapper().particleSpecies.size(); ++popID) {
205
206 Real sparse = getObjectWrapper().particleSpecies[popID].sparseMinValue;
207 const std::vector<CellID>& _local_cells = getLocalCells();
208 std::vector<CellID> local_cells;
209 for (auto& c : _local_cells) {
210 if (mpiGrid[c]->sysBoundaryFlag == sysboundarytype::DO_NOT_COMPUTE) {
211 continue;
212 }
213 auto blockContainer = mpiGrid[c]->get_velocity_blocks(popID);
214 const size_t total_blocks = blockContainer->size();
215 if (total_blocks==0){
216 continue;
217 }
218 local_cells.push_back(c);
219 }
220 // local_cells=sort_cells_based_on_maxwellianity(local_cells, popID, mpiGrid);
221 const std::size_t num_threads = omp_get_max_threads();
222 const auto partitionScheme = partition(local_cells.size(), P::max_vdfs_per_nn, num_threads);
223
224 // printf("Compression on %zu threads\n",num_threads);
225 // for (std::size_t ii=0;ii<partitionScheme.size();++ii){
226 // printf("\tChunk(%zu): [%zu,%zu) ->len=(%zu)\n",ii, partitionScheme[ii].first,partitionScheme[ii].second,partitionScheme[ii].second-partitionScheme[ii].first );
227 // }
228 const std::size_t threads_needed = partitionScheme.size();
229 total_samples += partitionScheme.size();
230 omp_set_num_threads(threads_needed);
231 std::vector<std::vector<char>> thread_bytes(threads_needed);
232#pragma omp parallel
233 {
234 std::size_t thread_id = omp_get_thread_num();
235 const std::pair<std::size_t, std::size_t> index_range = partitionScheme.at(thread_id);
236 const std::size_t count = index_range.second - index_range.first;
237 printf("Count = %zu \n",count);
238 const auto start = local_cells.data() + index_range.first;
239 const std::span<const CellID> span(start, count);
240 PhaseSpaceUnion<Realf> b(span, popID, mpiGrid, true);
241 b.normalize();
242
243 // (2) Do the compression for this VDF
244 Realf error = std::numeric_limits<double>::max();
245 uint32_t epochs=0;
246 int status = 0;
247 // Allocate spaced for weights
248 auto network_size = calculate_total_size_bytes<Realf>(P::mlp_arch, P::mlp_fourier_order, b._cids.size());
249 b._network_weights = (Realf*)malloc(network_size);
250 b._n_weights = network_size / sizeof(Realf);
251
252#ifndef DPF
253 std::size_t nn_mem_footprint_bytes = compress_phasespace6D_f32(
254 &p, 3, span.size(), &b._vcoords[0][0], b._vspace.data(), b._vcoords.size(), P::mlp_max_epochs,
256 b._network_weights, network_size, false, downsampling_factor, error, epochs ,status,myRank);
257
258#else
259 std::size_t nn_mem_footprint_bytes = compress_phasespace6D_f64(
260 &p, 3, span.size(), &b._vcoords[0][0], b._vspace.data(), b._vcoords.size(), P::mlp_max_epochs,
262 b._network_weights, network_size, false, downsampling_factor, error, epochs, status, myRank);
263#endif
264 for (const auto sc:span){
265 mpiGrid[sc]->get_population(popID).mlp_error=static_cast<float>(error);
266 mpiGrid[sc]->get_population(popID).mlp_epochs = epochs;
267 }
268 assert(network_size == nn_mem_footprint_bytes && "Mismatch betweeen estimated and actual network size!!!");
269 thread_bytes.at(thread_id) = std::vector<char>(b.total_serialized_size_bytes());
270 b.serialize_into(reinterpret_cast<unsigned char*>(thread_bytes.at(thread_id).data()));
271
272 free(b._network_weights);
273 local_compression_achieved +=
274 static_cast<float>(b._effective_vdf_size) / static_cast<float>(nn_mem_footprint_bytes);
275 }
276 bytes = thread_bytes;
277 }
278 return local_compression_achieved / static_cast<float>(total_samples);
279}
280
281std::vector<std::vector<std::pair<CellID, Real>>>
282clusterVDFs(const std::vector<CellID>& local_cells, const dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
283 uint popID, bool single_cluster = false) {
284 std::vector<Real> non_maxwellianity(local_cells.size(), 0.0);
285 std::transform(local_cells.begin(), local_cells.end(), non_maxwellianity.begin(),
286 [&](const auto& cid) { return get_Non_MaxWellianity(mpiGrid[cid], popID); });
287 std::vector<std::pair<CellID, Real>> sorted_vdf(local_cells.size());
288 for (std::size_t i = 0; i < local_cells.size(); ++i) {
289 sorted_vdf[i] = {local_cells[i], non_maxwellianity[i]};
290 }
291 std::sort(sorted_vdf.begin(), sorted_vdf.end(), [](const auto& a, const auto& b) { return a.second < b.second; });
292 if (single_cluster) {
293 return {sorted_vdf};
294 }
295 std::vector<std::vector<std::pair<CellID, Real>>> clusters;
296 std::vector<std::pair<CellID, Real>> current_cluster;
297
298 for (const auto& pair : sorted_vdf) {
299 if (current_cluster.empty()) {
300 current_cluster.push_back(pair);
301 continue;
302 }
303 const Real last_value = current_cluster.back().second;
304 const Real margin = Real(0.2) * std::max(last_value, pair.second);
305 if (std::fabs(last_value - pair.second) <= margin) {
306 current_cluster.push_back(pair);
307 } else {
308 clusters.push_back(std::move(current_cluster));
309 current_cluster.clear();
310 current_cluster.push_back(pair);
311 }
312 }
313 if (!current_cluster.empty()) {
314 clusters.push_back(std::move(current_cluster));
315 }
316 return clusters;
317}
318
319float compress_vdfs_fourier_mlp_clustered(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
320 size_t number_of_spatial_cells, bool update_weights, std::vector<std::vector<char>>&bytes,
321 uint32_t downsampling_factor) {
322
323 //Memory allocation
324 //TODO remove later
325 int myRank;
326 MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
327 GENERIC_TS_POOL::MemPool p{};
328 if (getObjectWrapper().particleSpecies.size() > 1) {
329 throw std::runtime_error("Multi-Pop not implemented yet!");
330 }
331 float local_compression_achieved = 0.0;
332 std::size_t total_samples = 0;
333 const std::size_t max_span_size = P::max_vdfs_per_nn;
334 for (uint popID = 0; popID < getObjectWrapper().particleSpecies.size(); ++popID) {
335 Real sparse = getObjectWrapper().particleSpecies[popID].sparseMinValue;
336 const std::vector<CellID>& _local_cells = getLocalCells();
337 std::vector<CellID> local_cells;
338 for (auto& c : _local_cells) {
339 if (mpiGrid[c]->sysBoundaryFlag == sysboundarytype::DO_NOT_COMPUTE) {
340 continue;
341 }
342 local_cells.push_back(c);
343 }
344 const auto clusters = clusterVDFs(local_cells, mpiGrid, popID, true);
345 // printf("Local cells for this training pass = %zu\n",local_cells.size());
346 // std::cout << "Generated " << clusters.size() << " clusters" << std::endl;
347
348 bytes.resize(clusters.size());
349#pragma omp parallel for reduction(+ : local_compression_achieved)
350 for (std::size_t i =0 ;i< clusters.size();++i) {
351 auto& cluster = clusters.at(i);
352#pragma omp atomic
353 total_samples++;
354
355 std::vector<CellID> cids(cluster.size());
356 std::transform(cluster.begin(), cluster.end(), cids.begin(), [](const auto& pair) { return pair.first; });
357
358 // Extract this span of VDFs as a union
359 const std::span<const CellID> span(cids.data(), cids.size());
360 PhaseSpaceUnion<Realf>b(span, popID, mpiGrid, true);
361 b.normalize();
362
363 // (2) Do the compression for this VDF
364 Realf error = std::numeric_limits<double>::max();
365 uint32_t epochs=0;
366 int status = 0;
367 // Allocate spaced for weights
368 auto network_size =
370 b._network_weights = (Realf*)malloc(network_size);
371 b._n_weights = network_size / sizeof(Realf);
372
373 #ifndef DPF
374 std::size_t nn_mem_footprint_bytes = compress_phasespace6D_f32(
375 &p, 3, span.size(), &b._vcoords[0][0], b._vspace.data(), b._vcoords.size(), P::mlp_max_epochs,
377 b._network_weights, network_size, false, downsampling_factor, error, epochs, status,myRank);
378
379 #else
380 std::size_t nn_mem_footprint_bytes = compress_phasespace6D_f64(
381 &p, 3, span.size(), &b._vcoords[0][0], b._vspace.data(), b._vcoords.size(), P::mlp_max_epochs,
383 b._network_weights, network_size, false, downsampling_factor, error, epochs, status,myRank);
384 #endif
385 for (const auto sc:span){
386 mpiGrid[sc]->get_population(popID).mlp_error=static_cast<float>(error);
387 mpiGrid[sc]->get_population(popID).mlp_epochs = epochs;
388 }
389 assert(network_size == nn_mem_footprint_bytes && "Mismatch betweeen estimated and actual network size!!!");
390
391 bytes.at(i).resize(b.total_serialized_size_bytes());
392 b.serialize_into(reinterpret_cast<unsigned char*>(bytes.at(i).data()));
393 free(b._network_weights);
394 local_compression_achieved += static_cast<float>(b._effective_vdf_size) / static_cast<float>(nn_mem_footprint_bytes);
395 }
396 } // loop over all populations
397 return local_compression_achieved / static_cast<float>(total_samples);
398}
399#endif //ASTERIX_MLP
400
401#ifdef ASTERIX_ZFP
402// Compresses and reconstucts VDFs using ZFP
403float compress_vdfs_zfp(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid, const std::vector<CellID>& local_cells) {
404 float local_compression_achieved = 0.0;
405 std::size_t total_samples = 0;
406 for (uint popID = 0; popID < getObjectWrapper().particleSpecies.size(); ++popID) {
407 Real sparse = getObjectWrapper().particleSpecies[popID].sparseMinValue;
408 // Vlasiator boilerplate
409#pragma omp parallel for reduction(+ : local_compression_achieved)
410 for (auto& cid : local_cells) { // loop over spatial cells
411 SpatialCell* sc = mpiGrid[cid];
412 assert(sc && "Invalid Pointer to Spatial Cell !");
414 continue;
415 }
416 auto blockContainer = sc->get_velocity_blocks(popID);
417 const size_t total_blocks = blockContainer->size();
418 if (total_blocks==0){
420 continue;
421 }
422
423#pragma omp atomic
424 total_samples++;
425 // (1) Extract and Collect the VDF of this cell
427 // (2) Do the compression for this VDF
428 // Create spave for the reconstructed VDF
429 size_t ss{0};
431 compress(vdf.vdf_vals.data(), vdf.vdf_vals.size(), ss, sparse);
432 float ratio = static_cast<float>(vdf.vdf_vals.size() * sizeof(Realf)) / static_cast<float>(ss);
433 local_compression_achieved += ratio;
434 } // loop over all spatial cells
435 } // loop over all populations
436 return local_compression_achieved / static_cast<float>(total_samples);
437}
438
439#endif //ASTERIX_ZFP
440
441#ifdef ASTERIX_OCTREE
442// Compresses and reconstucts VDFs using ZFP
443float compress_vdfs_octree(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
444 const std::vector<CellID>& local_cells) {
445 int total_bytes = 0;
446 int global_total_bytes = 0;
447 float local_compression_achieved = 0.0;
448 std::size_t total_samples = 0;
449 for (uint popID = 0; popID < getObjectWrapper().particleSpecies.size(); ++popID) {
450 // Vlasiator boilerplate
451#pragma omp parallel for reduction(+ : total_bytes, local_compression_achieved)
452 for (auto& cid : local_cells) { // loop over spatial cells
453 SpatialCell* sc = mpiGrid[cid];
455 continue;
456 }
457 auto blockContainer = sc->get_velocity_blocks(popID);
458 const size_t total_blocks = blockContainer->size();
459 if (total_blocks==0){
461 continue;
462 }
463 // (1) Extract and Collect the VDF of this cell
465
466#pragma omp atomic
467 total_samples++;
468 // (2) Do the compression for this VDF
469 uint8_t* bytes = nullptr;
470 std::size_t n_bytes;
471 constexpr std::size_t maxiter = 50000;
472 constexpr std::size_t skip_levels = 4;
473 int status = compress_with_toctree_method(vdf.vdf_vals.data(), vdf.shape[0], vdf.shape[1], vdf.shape[2],
474 P::octree_tolerance, &bytes, &n_bytes, maxiter,skip_levels);
475
476 switch(status) {
477 case TOCTREE_COMPRESS_STAT_SUCCESS:
478 break;
479 case TOCTREE_COMPRESS_STAT_FAIL_TOL:
480 logFile << "(VDF COMPRESSION INFO): T-Octree failed to reach tolerance " <<
481 P::octree_tolerance << " in " << maxiter << " iterations (cid " << cid <<")\n";
482 break;
483 default:
484 throw std::runtime_error("(VDF COMPRESSION ERROR): T-Octree failed.");
485 break;
486 }
487
488 //Copy compressed state to SC
489 sc->get_population(popID).compressed_state_buffer.resize(n_bytes+sizeof(std::size_t) +vdf.blocks_to_ignore.size()*sizeof(vmesh::GlobalID)+3*sizeof(std::size_t)+6*sizeof(Real),0);
490
491 std::size_t ignored_blocks=vdf.blocks_to_ignore.size();
492 std::size_t write_index=0;
493 std::memcpy(sc->get_population(popID).compressed_state_buffer.data()+write_index,&ignored_blocks,sizeof(std::size_t));
494 write_index+=sizeof(std::size_t);
495 std::memcpy(sc->get_population(popID).compressed_state_buffer.data()+write_index,vdf.blocks_to_ignore.data(),ignored_blocks*sizeof(vmesh::GlobalID));
496 write_index+=ignored_blocks*sizeof(vmesh::GlobalID);
497 std::memcpy(sc->get_population(popID).compressed_state_buffer.data()+write_index,&vdf.shape[0],3*sizeof(std::size_t));
498 write_index+=3*sizeof(std::size_t);
499 std::memcpy(&sc->get_population(popID).compressed_state_buffer[write_index],&vdf.v_limits,6*sizeof(Real));
500 write_index+=6*sizeof(Real);
501 std::memcpy(&sc->get_population(popID).compressed_state_buffer[write_index],bytes,n_bytes);
502
503 if (bytes != NULL) {
504 free(bytes);
505 }
506 total_bytes += n_bytes;
507 local_compression_achieved += vdf.sparse_vdf_bytes / static_cast<float>(n_bytes);
508
509 } // loop over all spatial cells
510 } // loop over all populations
511 return local_compression_achieved / static_cast<float>(total_samples);
512}
513#endif //ASTERIX_OCTREE
514
515#ifdef ASTERIX_ZFP
516std::vector<char> compress(float* array, size_t arraySize, size_t& compressedSize, float tol) {
517 // Allocate memory for compressed data
518 zfp_stream* zfp = zfp_stream_open(NULL);
519 zfp_field* field = zfp_field_1d(array, zfp_type_float, arraySize);
520 size_t maxSize = zfp_stream_maximum_size(zfp, field);
521 std::vector<char> compressedData(maxSize);
522
523 // Initialize ZFP compression
524 zfp_stream_set_accuracy(zfp, tol);
525 bitstream* stream = stream_open(compressedData.data(), compressedSize);
526 zfp_stream_set_bit_stream(zfp, stream);
527 zfp_stream_rewind(zfp);
528
529 // Compress the array
530 compressedSize = zfp_compress(zfp, field);
531 compressedData.erase(compressedData.begin() + compressedSize, compressedData.end());
532 zfp_field_free(field);
533 zfp_stream_close(zfp);
534 stream_close(stream);
535 return compressedData;
536}
537
538// Function to decompress a compressed array of floats using ZFP
539std::vector<float> ASTERIX::decompressArrayFloat(char* compressedData, size_t compressedSize, size_t arraySize,
540 float tol) {
541 // Allocate memory for decompresseFloatd data
542 std::vector<float> decompressedArray(arraySize);
543
544 // Initialize ZFP decompression
545 zfp_stream* zfp = zfp_stream_open(NULL);
546 zfp_stream_set_accuracy(zfp, tol);
547 bitstream* stream_decompress = stream_open(compressedData, compressedSize);
548 zfp_stream_set_bit_stream(zfp, stream_decompress);
549 zfp_stream_rewind(zfp);
550
551 // Decompress the array
552 zfp_field* field_decompress = zfp_field_1d(decompressedArray.data(), zfp_type_float, decompressedArray.size());
553 size_t retval = zfp_decompress(zfp, field_decompress);
554 (void)retval;
555 zfp_field_free(field_decompress);
556 zfp_stream_close(zfp);
557 stream_close(stream_decompress);
558
559 return decompressedArray;
560}
561
562// Function to compress a 1D array of doubles using ZFP
563std::vector<char> compress(double* array, size_t arraySize, size_t& compressedSize, double tol) {
564 zfp_stream* zfp = zfp_stream_open(NULL);
565 zfp_field* field = zfp_field_1d(array, zfp_type_double, arraySize);
566 size_t maxSize = zfp_stream_maximum_size(zfp, field);
567 std::vector<char> compressedData(maxSize);
568
569 zfp_stream_set_accuracy(zfp, tol);
570 bitstream* stream = stream_open(compressedData.data(), compressedSize);
571 zfp_stream_set_bit_stream(zfp, stream);
572 zfp_stream_rewind(zfp);
573
574 compressedSize = zfp_compress(zfp, field);
575 compressedData.erase(compressedData.begin() + compressedSize, compressedData.end());
576 zfp_field_free(field);
577 zfp_stream_close(zfp);
578 stream_close(stream);
579 return compressedData;
580}
581
582// Function to decompress a compressed array of doubles using ZFP
583std::vector<double> ASTERIX::decompressArrayDouble(char* compressedData, size_t compressedSize, size_t arraySize,double tol) {
584 // Allocate memory for decompressed data
585 std::vector<double> decompressedArray(arraySize);
586
587 zfp_stream* zfp = zfp_stream_open(NULL);
588 zfp_stream_set_accuracy(zfp, tol);
589 bitstream* stream_decompress = stream_open(compressedData, compressedSize);
590 zfp_stream_set_bit_stream(zfp, stream_decompress);
591 zfp_stream_rewind(zfp);
592
593 zfp_field* field_decompress = zfp_field_1d(decompressedArray.data(), zfp_type_double, decompressedArray.size());
594 size_t retval = zfp_decompress(zfp, field_decompress);
595 (void)retval;
596 zfp_field_free(field_decompress);
597 zfp_stream_close(zfp);
598 stream_close(stream_decompress);
599 return decompressedArray;
600}
601#endif //ASTERIX_ZFP
602
for i
Definition Dispersion.m:24
Constants c
Definition Dispersion.m:45
vmesh::VelocityBlockContainer * get_velocity_blocks(const size_t &popID)
Population & get_population(const uint popID)
ARCH_HOSTDEV vmesh::LocalID size() const
const std::vector< CellID > & getLocalCells()
Definition main.cpp:39
#define MASTER_RANK
Definition common.h:67
std::vector< CellID > sort_cells_based_on_maxwellianity(const std::vector< CellID > &local_cells, uint popID, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
std::vector< std::pair< std::size_t, std::size_t > > partition(std::size_t array_size, std::size_t chunk_size, std::size_t max_chunks)
float Real
Definition definitions.h:41
float Realf
Definition definitions.h:33
int myRank
Definition gpu_base.cpp:48
Logger logFile
Definition main.cpp:25
ObjectWrapper & getObjectWrapper()
Definition main.cpp:33
auto extract_pop_vdf_from_spatial_cell(spatial_cell::SpatialCell *sc, uint popID) -> UnorderedVDF
auto calculate_total_size_bytes(const std::vector< std::size_t > &architecture, std::size_t fourier_order, std::size_t output_dim) -> std::size_t
std::vector< double > decompressArrayDouble(char *compressedData, size_t compressedSize, size_t arraySize, double tol)
std::vector< float > decompressArrayFloat(char *compressedData, size_t compressedSize, size_t arraySize, float tol)
auto extract_pop_vdf_from_spatial_cell_ordered_min_bbox_zoomed(spatial_cell::SpatialCell *sc, uint popID, int zoom) -> OrderedVDF
void compress_vdfs(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::vector< CellID > &local_cells, P::ASTERIX_COMPRESSION_METHODS method, bool update_weights, std::vector< std::vector< char > > &mpl_bytes, uint32_t downsampling_factor=1)
Real get_Non_MaxWellianity(const spatial_cell::SpatialCell *cell, uint popID)
uint32_t GlobalID
Definition definitions.h:59
std::vector< species::Species > particleSpecies
ASTERIX_COMPRESSION_METHODS
Definition parameters.h:249
static std::size_t max_vdfs_per_nn
Definition parameters.h:262
static Real mlp_tollerance
Definition parameters.h:261
static std::vector< std::size_t > mlp_arch
Definition parameters.h:257
static std::size_t mlp_max_epochs
Definition parameters.h:259
static Real octree_tolerance
Definition parameters.h:263
static std::size_t mlp_fourier_order
Definition parameters.h:258
std::vector< char > compressed_state_buffer