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::memory_space>
 
  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::memory_space>
 
  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::memory_space>
 
  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::memory_space>
 
  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:504
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:546
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:877
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