28#ifndef CABANA_SILOPARTICLEOUTPUT_HPP
29#define CABANA_SILOPARTICLEOUTPUT_HPP
31#include <Kokkos_Core.hpp>
32#include <Kokkos_Profiling_ScopedRegion.hpp>
51namespace SiloParticleOutput
62struct SiloTraits<short>
64 static int type() {
return DB_SHORT; }
70 static int type() {
return DB_INT; }
74struct SiloTraits<float>
76 static int type() {
return DB_FLOAT; }
80struct SiloTraits<double>
82 static int type() {
return DB_DOUBLE; }
89template <
class SliceType>
91 DBfile* silo_file,
const std::string& mesh_name,
const std::size_t begin,
92 const std::size_t end,
const SliceType& slice,
94 typename std::enable_if<
95 2 == SliceType::kokkos_view::traits::dimension::rank,
int*>::type = 0 )
98 Kokkos::View<
typename SliceType::value_type*,
99 typename SliceType::device_type>
100 view( Kokkos::ViewAllocateWithoutInitializing(
"scalar_field" ),
106 Kokkos::create_mirror_view_and_copy( Kokkos::HostSpace(), view );
109 DBPutPointvar1( silo_file,
slice.label().c_str(), mesh_name.c_str(),
110 host_view.data(), host_view.extent( 0 ),
111 SiloTraits<typename SliceType::value_type>::type(),
116template <
class SliceType>
118 DBfile* silo_file,
const std::string& mesh_name,
const std::size_t begin,
119 const std::size_t end,
const SliceType& slice,
120 typename std::enable_if<
121 3 == SliceType::kokkos_view::traits::dimension::rank,
int*>::type = 0 )
124 Kokkos::View<
typename SliceType::value_type**, Kokkos::LayoutLeft,
125 typename SliceType::device_type>
126 view( Kokkos::ViewAllocateWithoutInitializing(
"vector_field" ),
127 end - begin,
slice.extent( 2 ) );
132 Kokkos::create_mirror_view_and_copy( Kokkos::HostSpace(), view );
135 std::vector<typename SliceType::value_type*> ptrs( host_view.extent( 1 ) );
136 for ( std::size_t d0 = 0; d0 < host_view.extent( 1 ); ++d0 )
137 ptrs[d0] = Kokkos::subview( host_view, Kokkos::ALL(), d0 ).data();
140 DBPutPointvar( silo_file,
slice.label().c_str(), mesh_name.c_str(),
141 host_view.extent( 1 ), ptrs.data(), host_view.extent( 0 ),
142 SiloTraits<typename SliceType::value_type>::type(),
147template <
class SliceType>
149 DBfile* silo_file,
const std::string& mesh_name,
const std::size_t begin,
150 const std::size_t end,
const SliceType& slice,
151 typename std::enable_if<
152 4 == SliceType::kokkos_view::traits::dimension::rank,
int*>::type = 0 )
155 Kokkos::View<
typename SliceType::value_type***, Kokkos::LayoutLeft,
156 typename SliceType::device_type>
157 view( Kokkos::ViewAllocateWithoutInitializing(
"matrix_field" ),
158 end - begin,
slice.extent( 2 ),
slice.extent( 3 ) );
163 Kokkos::create_mirror_view_and_copy( Kokkos::HostSpace(), view );
166 std::vector<typename SliceType::value_type*> ptrs;
167 ptrs.reserve( host_view.extent( 1 ) * host_view.extent( 2 ) );
168 for (
unsigned d0 = 0; d0 < host_view.extent( 1 ); ++d0 )
169 for (
unsigned d1 = 0; d1 < host_view.extent( 2 ); ++d1 )
171 Kokkos::subview( host_view, Kokkos::ALL(), d0, d1 ).data() );
174 DBPutPointvar( silo_file,
slice.label().c_str(), mesh_name.c_str(),
175 host_view.extent( 1 ) * host_view.extent( 2 ), ptrs.data(),
176 host_view.extent( 0 ),
177 SiloTraits<typename SliceType::value_type>::type(),
182template <
class SliceType>
183void writeFields( DBfile* silo_file,
const std::string& mesh_name,
184 const SliceType& slice )
193template <
class SliceType>
195 const std::size_t begin,
const std::size_t end,
196 const SliceType&
slice )
198 Impl::writeFields( silo_file, mesh_name, begin, end,
slice );
202template <
class SliceType,
class... FieldSliceTypes>
204 const std::size_t begin,
const std::size_t end,
205 const SliceType&
slice, FieldSliceTypes&&... fields )
207 Impl::writeFields( silo_file, mesh_name, begin, end,
slice );
208 writeFields( silo_file, mesh_name, begin, end, fields... );
213inline void*
createFile(
const char* file_name,
const char* dir_name,
216 std::ignore = user_data;
218 DBCreate( file_name, DB_CLOBBER, DB_LOCAL,
nullptr, DB_PDB );
221 DBMkDir( silo_file, dir_name );
222 DBSetDir( silo_file, dir_name );
225 return (
void*)silo_file;
229inline void*
openFile(
const char* file_name,
const char* dir_name,
230 PMPIO_iomode_t io_mode,
void* user_data )
232 std::ignore = io_mode;
233 std::ignore = user_data;
234 DBfile* silo_file = DBOpen( file_name, DB_PDB, DB_APPEND );
237 DBMkDir( silo_file, dir_name );
238 DBSetDir( silo_file, dir_name );
240 return (
void*)silo_file;
246 std::ignore = user_data;
247 DBfile* silo_file = (DBfile*)file;
249 DBClose( silo_file );
257template <
class SliceType>
258void getFieldNames( std::vector<std::string>& names,
const SliceType&
slice )
260 names.push_back(
slice.label() );
264template <
class SliceType,
class... FieldSliceTypes>
265void getFieldNames( std::vector<std::string>& names,
const SliceType& slice,
266 FieldSliceTypes&&... fields )
268 getFieldNames( names, slice );
269 getFieldNames( names, fields... );
275template <
class... FieldSliceTypes>
278 std::vector<std::string> names;
279 Impl::getFieldNames( names, fields... );
285template <
class... FieldSliceTypes>
287 const int comm_size,
const std::string& prefix,
288 const std::string& mesh_name,
const int time_step_index,
289 const double time, FieldSliceTypes&&... fields )
292 DBSetDir( silo_file,
"/" );
295 std::vector<std::string> mb_names;
296 for (
int r = 0; r < comm_size; ++r )
298 int group_rank = PMPIO_GroupRank( baton, r );
299 if ( 0 == group_rank )
301 std::stringstream bname;
302 bname <<
"rank_" << r <<
"/" << mesh_name;
303 mb_names.push_back( bname.str() );
307 std::stringstream bname;
308 bname << prefix <<
"_" << time_step_index <<
"_group_" << group_rank
309 <<
".silo:/rank_" << r <<
"/" << mesh_name;
310 mb_names.push_back( bname.str() );
313 char** mesh_block_names = (
char**)malloc( comm_size *
sizeof(
char* ) );
314 for (
int r = 0; r < comm_size; ++r )
315 mesh_block_names[r] =
const_cast<char*
>( mb_names[r].c_str() );
317 std::vector<int> mesh_block_types( comm_size, DB_POINTMESH );
320 std::vector<std::string> field_names =
getFieldNames( fields... );
323 int num_field = field_names.size();
324 std::vector<std::vector<std::string>> fb_names( num_field );
325 for (
int f = 0; f < num_field; ++f )
327 for (
int r = 0; r < comm_size; ++r )
329 int group_rank = PMPIO_GroupRank( baton, r );
330 if ( 0 == group_rank )
332 std::stringstream bname;
333 bname <<
"rank_" << r <<
"/" << field_names[f];
334 fb_names[f].push_back( bname.str() );
338 std::stringstream bname;
339 bname << prefix <<
"_" << time_step_index <<
"_group_"
340 << group_rank <<
".silo:/rank_" << r <<
"/"
342 fb_names[f].push_back( bname.str() );
347 std::vector<char**> field_block_names( num_field );
348 for (
int f = 0; f < num_field; ++f )
350 field_block_names[f] = (
char**)malloc( comm_size *
sizeof(
char* ) );
351 for (
int r = 0; r < comm_size; ++r )
352 field_block_names[f][r] =
353 const_cast<char*
>( fb_names[f][r].c_str() );
356 std::vector<int> field_block_types( comm_size, DB_POINTVAR );
359 DBoptlist* options = DBMakeOptlist( 1 );
360 DBAddOption( options, DBOPT_DTIME, (
void*)&time );
361 DBAddOption( options, DBOPT_CYCLE, (
void*)&time_step_index );
364 std::stringstream mbname;
365 mbname <<
"multi_" << mesh_name;
366 DBPutMultimesh( silo_file, mbname.str().c_str(), comm_size,
367 mesh_block_names, mesh_block_types.data(), options );
370 for (
int f = 0; f < num_field; ++f )
372 std::stringstream mfname;
373 mfname <<
"multi_" << field_names[f];
374 DBPutMultivar( silo_file, mfname.str().c_str(), comm_size,
375 field_block_names[f], field_block_types.data(),
380 free( mesh_block_names );
381 for (
auto& f_name : field_block_names )
383 DBFreeOptlist( options );
399template <
class CoordSliceType,
class... FieldSliceTypes>
401 const int num_group,
const int time_step_index,
402 const double time,
const std::size_t begin,
403 const std::size_t end,
404 const CoordSliceType& coords,
405 FieldSliceTypes&&... fields )
407 Kokkos::Profiling::ScopedRegion region(
"Cabana::SiloParticleOutput" );
411 PMPIO_baton_t* baton =
416 DBSetAllowEmptyObjects( 1 );
420 MPI_Comm_rank( comm, &comm_rank );
421 int group_rank = PMPIO_GroupRank( baton, comm_rank );
422 std::stringstream file_name;
425 if ( 0 == group_rank )
426 file_name << prefix <<
"_" << time_step_index <<
".silo";
429 file_name << prefix <<
"_" << time_step_index <<
"_group_" << group_rank
433 std::stringstream dir_name;
434 dir_name <<
"rank_" << comm_rank;
437 DBfile* silo_file = (DBfile*)PMPIO_WaitForBaton(
438 baton, file_name.str().c_str(), dir_name.str().c_str() );
441 Kokkos::View<
typename CoordSliceType::value_type**, Kokkos::LayoutLeft,
442 typename CoordSliceType::device_type>
443 view( Kokkos::ViewAllocateWithoutInitializing(
"coords" ), end - begin,
444 coords.extent( 2 ) );
449 Kokkos::create_mirror_view_and_copy( Kokkos::HostSpace(), view );
452 std::string mesh_name = prefix;
453 auto host_x = Kokkos::subview( host_coords, Kokkos::ALL(), 0 );
454 auto host_y = Kokkos::subview( host_coords, Kokkos::ALL(), 1 );
455 auto host_z = Kokkos::subview( host_coords, Kokkos::ALL(), 2 );
456 typename CoordSliceType::value_type* ptrs[3] = {
461 DBPutPointmesh( silo_file, mesh_name.c_str(), host_coords.extent( 1 ), ptrs,
462 host_coords.extent( 0 ),
463 SiloTraits<typename CoordSliceType::value_type>::type(),
467 writeFields( silo_file, mesh_name, begin, end, fields... );
472 MPI_Comm_size( comm, &comm_size );
473 if ( 0 == comm_rank && comm_size > 1 )
475 time_step_index, time, fields... );
478 PMPIO_HandOffBaton( baton, silo_file );
481 PMPIO_Finish( baton );
494template <
class CoordSliceType,
class... FieldSliceTypes>
496 const int num_group,
const int time_step_index,
497 const double time,
const CoordSliceType& coords,
498 FieldSliceTypes&&... fields )
501 0, coords.size(), coords, fields... );
void writeFields(HDF5Config, hid_t, std::size_t, std::size_t, hsize_t, int, const char *, const char *)
Write particle data to HDF5 output. Empty overload if only writing coords.
Definition Cabana_HDF5ParticleOutput.hpp:498
void writeTimeStep(HDF5Config h5_config, const std::string &prefix, MPI_Comm comm, const int time_step_index, const double time, const std::size_t n_local, const CoordSliceType &coords_slice, FieldSliceTypes &&... fields)
Write particle output in HDF5 format.
Definition Cabana_HDF5ParticleOutput.hpp:540
void closeFile(void *file, void *user_data)
Close Silo output file.
Definition Cabana_SiloParticleOutput.hpp:244
void * openFile(const char *file_name, const char *dir_name, PMPIO_iomode_t io_mode, void *user_data)
Open Silo output file.
Definition Cabana_SiloParticleOutput.hpp:229
std::vector< std::string > getFieldNames(FieldSliceTypes &&... fields)
Get Silo output property field names.
Definition Cabana_SiloParticleOutput.hpp:276
void writeMultiMesh(PMPIO_baton_t *baton, DBfile *silo_file, const int comm_size, const std::string &prefix, const std::string &mesh_name, const int time_step_index, const double time, FieldSliceTypes &&... fields)
Write a Silo multimesh hierarchy.
Definition Cabana_SiloParticleOutput.hpp:286
void * createFile(const char *file_name, const char *dir_name, void *user_data)
Create Silo output file.
Definition Cabana_SiloParticleOutput.hpp:213
void writePartialRangeTimeStep(const std::string &prefix, MPI_Comm comm, const int num_group, const int time_step_index, const double time, const std::size_t begin, const std::size_t end, const CoordSliceType &coords, FieldSliceTypes &&... fields)
Write particle output in Silo format.
Definition Cabana_SiloParticleOutput.hpp:400
Slice a single particle property from an AoSoA.
Core: particle data structures and algorithms.
Definition Cabana_AoSoA.hpp:36
void copySliceToView(ExecutionSpace exec_space, ViewType &view, const SliceType &slice, const std::size_t begin, const std::size_t end, typename std::enable_if< 2==SliceType::kokkos_view::traits::dimension::rank, int * >::type=0)
Copy from slice to View. Rank-0.
Definition Cabana_Slice.hpp:870
AoSoA_t::template member_slice_type< M > slice(const AoSoA_t &aosoa, const std::string &slice_label="")
Create a slice from an AoSoA.
Definition Cabana_AoSoA.hpp:77