From 9ea23ea581755365cdee3a0de5a14328942aac36 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Fri, 4 Feb 2022 00:33:54 +0100 Subject: [PATCH 01/21] first commit of the masked particle load for the upcoming Virgo consortium simulations --- example.conf | 3 +- include/particle_generator.hh | 268 ++++++++++++++++++++++++++++++++-- src/ic_generator.cc | 12 +- 3 files changed, 263 insertions(+), 20 deletions(-) diff --git a/example.conf b/example.conf index 8c72613..9781316 100644 --- a/example.conf +++ b/example.conf @@ -20,7 +20,8 @@ DoFixing = no # do mode fixing à la Angulo&Pontzen (https://arxiv.o DoInversion = no # invert phases (for paired simulations) ParticleLoad = sc # particle load, can be 'sc' (1x), 'bcc' (2x) or 'fcc' (4x) - # (increases number of particles by given factor!), or 'glass' + # (increases number of particles by given factor!), + # or 'glass' or 'masked' ## if `ParticleLoad = glass' then specify here where to load the glass distribution from # GlassFileName = glass128.hdf5 diff --git a/include/particle_generator.hh b/include/particle_generator.hh index bc72ae7..3cb3cdb 100644 --- a/include/particle_generator.hh +++ b/include/particle_generator.hh @@ -29,13 +29,20 @@ namespace particle enum lattice { - lattice_glass = -1, + lattice_masked = -2, // masked lattices are SC lattices with a specifiable mask leaving out particles + lattice_glass = -1, // glass: needs a glass file lattice_sc = 0, // SC : simple cubic lattice_bcc = 1, // BCC: body-centered cubic lattice_fcc = 2, // FCC: face-centered cubic lattice_rsc = 3, // RSC: refined simple cubic }; + const std::vector> lattice_masks = + { + // mask from Richings et al. https://arxiv.org/pdf/2005.14495.pdf + {true,true,true,true,true,true,true,false}, + }; + const std::vector>> lattice_shifts = { // first shift must always be zero! (otherwise set_positions and set_velocities break) @@ -149,11 +156,40 @@ namespace particle private: particle::container particles_; + size_t global_num_particles_; + + static constexpr int masksize_ = 2; + std::array particle_type_mask_; + + inline int get_mask_value( const vec3_t& global_idx_3d ) const + { + int sig = ((global_idx_3d[0]%masksize_)*masksize_ + +global_idx_3d[1]%masksize_)*masksize_ + +global_idx_3d[2]%masksize_; + return particle_type_mask_[sig]; + } public: - lattice_generator(lattice lattice_type, const bool b64reals, const bool b64ids, const bool bwithmasses, size_t IDoffset, const field_t &field, config_file &cf) + /** + * @brief Construct a new lattice generator object + * + * @param lattice_type Type of the lattice (currently: 0=SC, 1=BCC, 2=FCC, 3=double SC, -1=glass, -2=masked SC) + * @param lattice_index Index of the 'atom type', i.e. whether CDM, baryons, ... (currently only supports 0 or 1) + * @param b64reals Boolean whether 64bit floating point shall be used to store positions/velocities/masses + * @param b64ids Boolean whether 64bit integers should be used for IDS + * @param bwithmasses Boolean whether distinct masses for each particle shall be stored + * @param IDoffset The global ID offset to be applied to this generation of particles + * @param field Reference to the field from which particles shall be generated (used only to set dimensions) + * @param cf Reference to the config_file object + */ + + lattice_generator(lattice lattice_type, int lattice_index, const bool b64reals, const bool b64ids, const bool bwithmasses, size_t IDoffset, const field_t &field, config_file &cf) + : global_num_particles_(0) { - if (lattice_type != lattice_glass) + // initialise the particle mask with zeros (only used if lattice_type==lattice_masked) + for( auto& m : particle_type_mask_) m = 0; + + if (lattice_type >= 0) // These are the Bravais lattices { music::wlog << "Glass ICs will currently be incorrect due to disabled ghost zone updates! "; @@ -163,6 +199,9 @@ namespace particle const size_t overload = 1ull << std::max(0, lattice_type); // 1 for sc, 2 for bcc, 4 for fcc, 8 for rsc // allocate memory for all local particles particles_.allocate(overload * num_p_in_load, b64reals, b64ids, bwithmasses); + // set the global number of particles for this lattice_type and lattice_index + global_num_particles_ = field.global_size() * overload; + // set particle IDs to the Lagrangian coordinate (1D encoded) with additionally the field shift encoded as well IDoffset = IDoffset * overload * field.global_size(); @@ -188,7 +227,82 @@ namespace particle } } } - else + else if( lattice_type == lattice_masked ) + { + if( field.global_size()%8 != 0 ){ + music::elog << "For masked lattice type, linear field resolution must be a multiple of two." << std::endl; + abort(); + } + + if( lattice_index > 1 || lattice_index < 0 ){ + music::elog << "For masked lattice type, lattice index must be 0 or 1." << std::endl; + abort(); + } + + // set the particle mask + if( cf.get_value_safe("setup","DoBaryons",false) ) + { + // mask everywehere 0, except the last element + for( auto& m : particle_type_mask_) m = 0; + particle_type_mask_[7] = 1; + }else{ + // mask everywehere 0 + for( auto& m : particle_type_mask_) m = 0; + } + + // count number of particles taking into account masking + size_t ipcount = 0; + for (size_t i = 0; i < field.rsize(0); ++i) + { + for (size_t j = 0; j < field.rsize(1); ++j) + { + for (size_t k = 0; k < field.rsize(2); ++k) + { + if( this->get_mask_value(field.get_cell_idx_3d(i,j,k)) != lattice_index ) continue; + ++ipcount; + } + } + } + + // set global number of particles +#if defined(USE_MPI) + MPI_Allreduce( &ipcount, &global_num_particles_, 1, MPI_UNSIGNED_LONG_LONG, MPI_SUM, MPI_COMM_WORLD ); +#else + global_num_particles_ = ipcount; +#endif + + // number of modes present in the field + const size_t num_p_in_load = ipcount; + + // allocate memory for all local particles + particles_.allocate(num_p_in_load, b64reals, b64ids, bwithmasses); + + // set particle IDs to the Lagrangian coordinate (1D encoded) with additionally the field shift encoded as well + IDoffset = IDoffset * field.global_size(); + + for (size_t i = 0, ipcount = 0; i < field.rsize(0); ++i) + { + for (size_t j = 0; j < field.rsize(1); ++j) + { + for (size_t k = 0; k < field.rsize(2); ++k) + { + if( this->get_mask_value(field.get_cell_idx_3d(i,j,k)) != lattice_index ) continue; + + if (b64ids) + { + particles_.set_id64(ipcount, IDoffset + field.get_cell_idx_1d(i, j, k)); + } + else + { + particles_.set_id32(ipcount, IDoffset + field.get_cell_idx_1d(i, j, k)); + } + ++ipcount; + } + } + } + + } + else if( lattice_type == lattice_glass ) { glass_ptr_ = std::make_unique( cf, field ); particles_.allocate(glass_ptr_->size(), b64reals, b64ids, false); @@ -206,14 +320,24 @@ namespace particle } } } + + music::ilog << "Created Particles [" << lattice_index << "] : " << global_num_particles_ << std::endl; + } // invalidates field, phase shifted to unspecified position after return - void set_masses(const lattice lattice_type, bool is_second_lattice, const real_t munit, const bool b64reals, field_t &field, config_file &cf) + void set_masses(const lattice lattice_type, int lattice_index, const real_t munit, const bool b64reals, field_t &field, config_file &cf) { - // works only for Bravais types - if (lattice_type >= 0) + // works only for Bravais types and masked type + assert( lattice_type>=0 || lattice_type==lattice_masked ); + + if (lattice_type >= 0) // Bravais lattices { + if( lattice_index > 1 || lattice_index < 0 ){ + music::elog << "For Bravais lattice type, lattice index must be 0 or 1." << std::endl; + abort(); + } + const size_t overload = 1ull << std::max(0, lattice_type); // 1 for sc, 2 for bcc, 4 for fcc, 8 for rsc const size_t num_p_in_load = field.local_size(); const real_t pmeanmass = munit / real_t(field.global_size()* overload); @@ -225,7 +349,7 @@ namespace particle for (int ishift = 0; ishift < (1 << lattice_type); ++ishift) { // if we are dealing with the secondary lattice, apply a global shift - if (ishift == 0 && is_second_lattice) + if (ishift == 0 && lattice_index > 0) { field.shift_field(second_lattice_shift[lattice_type]); } @@ -261,7 +385,49 @@ namespace particle music::ilog << "Particle Mass : mean/munit = " << mean_pm/munit << " ; fractional RMS = " << std_pm / mean_pm * 100.0 << "%" << std::endl; if(std_pm / mean_pm > 0.1 ) music::wlog << "Particle mass perturbation larger than 10%, consider decreasing \n\t the starting redshift or disabling baryon decaying modes." << std::endl; if(bmass_negative) music::elog << "Negative particle mass produced! Decrease the starting \n\t redshift or disable baryon decaying modes!" << std::endl; + } else if( lattice_type == lattice_masked ) { + if( field.global_size()%8 != 0 ){ + music::elog << "For masked lattice type, linear field resolution must be a multiple of two." << std::endl; + abort(); + } + if( lattice_index > 1 || lattice_index < 0 ){ + music::elog << "For masked lattice type, lattice index must be 0 or 1." << std::endl; + abort(); + } + + const real_t pmeanmass = munit / global_num_particles_; + + bool bmass_negative = false; + auto mean_pm = field.mean() * pmeanmass; + auto std_pm = field.std() * pmeanmass; + + // read out values from phase shifted field and set assoc. particle's value + for (size_t i = 0, ipcount = 0; i < field.size(0); ++i) + { + for (size_t j = 0; j < field.size(1); ++j) + { + for (size_t k = 0; k < field.size(2); ++k) + { + if( this->get_mask_value(field.get_cell_idx_3d(i,j,k)) != lattice_index ) continue; + + // get + const auto pmass = pmeanmass * field.relem(i, j, k); + + // check for negative mass + bmass_negative |= pmass<0.0; + + // set + if (b64reals) particles_.set_mass64(ipcount++, pmass); + else particles_.set_mass32(ipcount++, pmass); + } + } + } + + // diagnostics + music::ilog << "Particle Mass : mean/munit = " << mean_pm/munit << " ; fractional RMS = " << std_pm / mean_pm * 100.0 << "%" << std::endl; + if(std_pm / mean_pm > 0.1 ) music::wlog << "Particle mass perturbation larger than 10%, consider decreasing \n\t the starting redshift or disabling baryon decaying modes." << std::endl; + if(bmass_negative) music::elog << "Negative particle mass produced! Decrease the starting \n\t redshift or disable baryon decaying modes!" << std::endl; }else{ // should not happen music::elog << "Cannot have individual particle masses for glasses!" << std::endl; @@ -270,15 +436,21 @@ namespace particle } // invalidates field, phase shifted to unspecified position after return - void set_positions(const lattice lattice_type, bool is_second_lattice, int idim, real_t lunit, const bool b64reals, field_t &field, config_file &cf) + void set_positions(const lattice lattice_type, int lattice_index, int idim, real_t lunit, const bool b64reals, field_t &field, config_file &cf) { - if (lattice_type >= 0) + + if (lattice_type >= 0) // Bravais lattice { + if( lattice_index > 1 || lattice_index < 0 ){ + music::elog << "For Bravais lattice type, lattice index must be 0 or 1." << std::endl; + abort(); + } + const size_t num_p_in_load = field.local_size(); for (int ishift = 0; ishift < (1 << lattice_type); ++ishift) { // if we are dealing with the secondary lattice, apply a global shift - if (ishift == 0 && is_second_lattice) + if (ishift == 0 && lattice_index==1) { field.shift_field(second_lattice_shift[lattice_type]); } @@ -296,7 +468,7 @@ namespace particle { for (size_t k = 0; k < field.size(2); ++k) { - auto pos = field.template get_unit_r_shifted(i, j, k, lattice_shifts[lattice_type][ishift] + (is_second_lattice ? second_lattice_shift[lattice_type] : vec3_t{real_t(0.), real_t(0.), real_t(0.)})); + auto pos = field.template get_unit_r_shifted(i, j, k, lattice_shifts[lattice_type][ishift] + (lattice_index==1 ? second_lattice_shift[lattice_type] : vec3_t{real_t(0.), real_t(0.), real_t(0.)})); if (b64reals) { particles_.set_pos64(ipcount++, idim, pos[idim] * lunit + field.relem(i, j, k)); @@ -310,6 +482,38 @@ namespace particle } } } + else if( lattice_type == lattice_masked ) + { + if( field.global_size()%8 != 0 ){ + music::elog << "For masked lattice type, linear field resolution must be a multiple of two." << std::endl; + abort(); + } + + if( lattice_index > 1 || lattice_index < 0 ){ + music::elog << "For masked lattice type, lattice index must be 0 or 1." << std::endl; + abort(); + } + + for (size_t i = 0, ipcount = 0; i < field.size(0); ++i) + { + for (size_t j = 0; j < field.size(1); ++j) + { + for (size_t k = 0; k < field.size(2); ++k) + { + if( this->get_mask_value(field.get_cell_idx_3d(i,j,k)) != lattice_index ) continue; + + // get position (in box units) of the current cell of 3d array 'field' + auto pos = field.template get_unit_r(i, j, k); + // add the displacement to get the particle position + if (b64reals){ + particles_.set_pos64(ipcount++, idim, pos[idim] * lunit + field.relem(i, j, k)); + }else{ + particles_.set_pos32(ipcount++, idim, pos[idim] * lunit + field.relem(i, j, k)); + } + } + } + } + } else { glass_ptr_->update_ghosts( field ); @@ -330,15 +534,20 @@ namespace particle } } - void set_velocities(lattice lattice_type, bool is_second_lattice, int idim, const bool b64reals, field_t &field, config_file &cf) + void set_velocities(lattice lattice_type, int lattice_index, int idim, const bool b64reals, field_t &field, config_file &cf) { - if (lattice_type >= 0) + if (lattice_type >= 0) // Bravais lattice { + if( lattice_index > 1 || lattice_index < 0 ){ + music::elog << "For Bravais lattice type, lattice index must be 0 or 1." << std::endl; + abort(); + } + const size_t num_p_in_load = field.local_size(); for (int ishift = 0; ishift < (1 << lattice_type); ++ishift) { // if we are dealing with the secondary lattice, apply a global shift - if (ishift == 0 && is_second_lattice) + if (ishift == 0 && lattice_index==1) { field.shift_field(second_lattice_shift[lattice_type]); } @@ -368,6 +577,35 @@ namespace particle } } } + else if( lattice_type == lattice_masked ) + { + if( field.global_size()%8 != 0 ){ + music::elog << "For masked lattice type, linear field resolution must be a multiple of two." << std::endl; + abort(); + } + + if( lattice_index > 1 || lattice_index < 0 ){ + music::elog << "For masked lattice type, lattice index must be 0 or 1." << std::endl; + abort(); + } + + for (size_t i = 0, ipcount = 0; i < field.size(0); ++i) + { + for (size_t j = 0; j < field.size(1); ++j) + { + for (size_t k = 0; k < field.size(2); ++k) + { + if( this->get_mask_value(field.get_cell_idx_3d(i,j,k)) != lattice_index ) continue; + + if (b64reals){ + particles_.set_vel64(ipcount++, idim, field.relem(i, j, k)); + }else{ + particles_.set_vel32(ipcount++, idim, field.relem(i, j, k)); + } + } + } + } + } else { glass_ptr_->update_ghosts( field ); diff --git a/src/ic_generator.cc b/src/ic_generator.cc index 1561b1a..9e5e907 100644 --- a/src/ic_generator.cc +++ b/src/ic_generator.cc @@ -116,7 +116,8 @@ int run( config_file& the_config ) : ((lattice_str=="fcc")? particle::lattice_fcc : ((lattice_str=="rsc")? particle::lattice_rsc : ((lattice_str=="glass")? particle::lattice_glass - : particle::lattice_sc)))); + : ((lattice_str=="masked")? particle::lattice_masked + : particle::lattice_sc))))); //-------------------------------------------------------------------------------------------------------- //! apply fixing of the complex mode amplitude following Angulo & Pontzen (2016) [https://arxiv.org/abs/1603.05253] @@ -536,8 +537,11 @@ int run( config_file& the_config ) size_t IDoffset = (this_species == cosmo_species::baryon)? ((the_output_plugin->has_64bit_ids())? 1 : 1): 0 ; // allocate particle structure and generate particle IDs + bool secondary_lattice = (this_species == cosmo_species::baryon && + the_output_plugin->write_species_as(this_species) == output_type::particles) ? true : false; + particle_lattice_generator_ptr = - std::make_unique>>( lattice_type, the_output_plugin->has_64bit_reals(), the_output_plugin->has_64bit_ids(), + std::make_unique>>( lattice_type, secondary_lattice, the_output_plugin->has_64bit_reals(), the_output_plugin->has_64bit_ids(), bDoBaryons, IDoffset, tmp, the_config ); } @@ -545,7 +549,7 @@ int run( config_file& the_config ) if( bDoBaryons && (the_output_plugin->write_species_as( this_species ) == output_type::particles || the_output_plugin->write_species_as( this_species ) == output_type::field_lagrangian) ) { - bool shifted_lattice = (this_species == cosmo_species::baryon && + bool secondary_lattice = (this_species == cosmo_species::baryon && the_output_plugin->write_species_as(this_species) == output_type::particles) ? true : false; const real_t munit = the_output_plugin->mass_unit(); @@ -568,7 +572,7 @@ int run( config_file& the_config ) }); if( the_output_plugin->write_species_as( this_species ) == output_type::particles ){ - particle_lattice_generator_ptr->set_masses( lattice_type, shifted_lattice, 1.0, the_output_plugin->has_64bit_reals(), rho, the_config ); + particle_lattice_generator_ptr->set_masses( lattice_type, secondary_lattice, 1.0, the_output_plugin->has_64bit_reals(), rho, the_config ); }else if( the_output_plugin->write_species_as( this_species ) == output_type::field_lagrangian ){ the_output_plugin->write_grid_data( rho, this_species, fluid_component::mass ); } From 7155897fd8521b76412c065a1f8bbd54ecb8f61c Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Fri, 4 Feb 2022 02:09:47 +0100 Subject: [PATCH 02/21] added new ghost zone routines (that should be robust with MPI) --- include/grid_ghosts.hh | 209 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 include/grid_ghosts.hh diff --git a/include/grid_ghosts.hh b/include/grid_ghosts.hh new file mode 100644 index 0000000..be31ede --- /dev/null +++ b/include/grid_ghosts.hh @@ -0,0 +1,209 @@ +// This file is part of monofonIC (MUSIC2) +// A software package to generate ICs for cosmological simulations +// Copyright (C) 2022 by Oliver Hahn +// +// monofonIC is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// monofonIC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +#pragma once + +#include +#include + +#include + +#include +#include + +template +struct grid_with_ghosts +{ + using data_t = typename grid_t::data_t; + using vec3 = std::array; + + static constexpr bool is_distributed_trait = grid_t::is_distributed_trait; + static constexpr int num_ghosts = numghosts; + static constexpr bool have_left = haveleft, have_right = haveright; + + std::vector boundary_left_, boundary_right_; + std::vector local0starts_; + const grid_t &gridref; + size_t nx_, ny_, nz_, nzp_; + + + //... determine communication offsets + std::vector offsets_, sizes_; + + int get_task(ptrdiff_t index) const + { + int itask = 0; + while (itask < MPI::get_size() - 1 && offsets_[itask + 1] <= index) + ++itask; + return itask; + } + + explicit grid_with_ghosts(const grid_t &g) + : gridref(g), nx_(g.n_[0]), ny_(g.n_[1]), nz_(g.n_[2]), nzp_(g.n_[2]+2) + { + if (is_distributed_trait) + { + int ntasks(MPI::get_size()); + + offsets_.assign(ntasks+1, 0); + sizes_.assign(ntasks, 0); + + MPI_Allgather(&g.local_0_size_, 1, MPI_LONG_LONG, &sizes_[0], 1, + MPI_LONG_LONG, MPI_COMM_WORLD); + MPI_Allgather(&g.local_0_start_, 1, MPI_LONG_LONG, &offsets_[0], 1, + MPI_LONG_LONG, MPI_COMM_WORLD); + + for( int i=0; i< CONFIG::MPI_task_size; i++ ){ + if( offsets_[i+1] < offsets_[i] + sizes_[i] ) offsets_[i+1] = offsets_[i] + sizes_[i]; + } + + update_ghosts_allow_multiple( g ); + } + } + + void update_ghosts_allow_multiple( const grid_t &g ) + { + #if defined(USE_MPI) + //... exchange boundary + if( have_left ) boundary_left_.assign(num_ghosts * ny_ * nzp_, data_t{0.0}); + if( have_right ) boundary_right_.assign(num_ghosts * ny_ * nzp_, data_t{0.0}); + + size_t slicesz = ny_ * nzp_; + + MPI_Status status; + std::vector req; + MPI_Request temp_req; + + if( have_right ){ + for( int itask=0; itask= g.local_0_start_ && iglobal_request < g.local_0_start_ + g.local_0_size_ ){ + size_t ii = iglobal_request - g.local_0_start_; + MPI_Isend( &g.relem(ii*slicesz), slicesz, MPI::get_datatype(), itask, iglobal_request, MPI_COMM_WORLD, &temp_req); + req.push_back(temp_req); + } + } + } + + //--- receive data ------------------------------------------------------------ + #pragma omp parallel if(CONFIG::MPI_threads_ok) + { + MPI_Status status; + + #pragma omp for + for( size_t i=0; i(), recvfrom, (int)iglobal_request, MPI_COMM_WORLD, &status); + assert(status.MPI_ERROR == MPI_SUCCESS); + } + } + } + } + + MPI_Barrier( MPI_COMM_WORLD ); + + if( have_left ){ + for( int itask=0; itask= g.local_0_start_ && iglobal_request < g.local_0_start_ + g.local_0_size_ ){ + size_t ii = iglobal_request - g.local_0_start_; + MPI_Isend( &g.relem(ii*slicesz), slicesz, MPI::get_datatype(), itask, iglobal_request, MPI_COMM_WORLD, &temp_req); + req.push_back(temp_req); + } + } + } + + //--- receive data ------------------------------------------------------------ + #pragma omp parallel if(CONFIG::MPI_threads_ok) + { + MPI_Status status; + + #pragma omp for + for( size_t i=0; i(), recvfrom, (int)iglobal_request, MPI_COMM_WORLD, &status); + assert(status.MPI_ERROR == MPI_SUCCESS); + } + } + } + } + + MPI_Barrier( MPI_COMM_WORLD ); + + for (size_t i = 0; i < req.size(); ++i) + { + // need to set status as wait does not necessarily modify it + // c.f. http://www.open-mpi.org/community/lists/devel/2007/04/1402.php + status.MPI_ERROR = MPI_SUCCESS; + // std::cout << "task " << CONFIG::MPI_task_rank << " : checking request No" << i << std::endl; + int flag(1); + MPI_Test(&req[i], &flag, &status); + if( !flag ){ + std::cout << "task " << CONFIG::MPI_task_rank << " : request No" << i << " unsuccessful" << std::endl; + } + + MPI_Wait(&req[i], &status); + // std::cout << "---> ok!" << std::endl; + assert(status.MPI_ERROR == MPI_SUCCESS); + } + + MPI_Barrier(MPI_COMM_WORLD); + + #endif + } + + data_t relem(const ptrdiff_t& i, const ptrdiff_t& j, const ptrdiff_t&k ) const noexcept + { + return this->relem({i,j,k}); + } + + data_t relem(const std::array &pos) const noexcept + { + const ptrdiff_t ix = pos[0]; + const ptrdiff_t iy = (pos[1]+gridref.n_[1])%gridref.n_[1]; + const ptrdiff_t iz = (pos[2]+gridref.n_[2])%gridref.n_[2]; + + if( is_distributed_trait ){ + const ptrdiff_t localix = ix; + if( localix < 0 ){ + return boundary_left_[((localix+num_ghosts)*ny_+iy)*nzp_+iz]; + }else if( localix >= gridref.local_0_size_ ){ + return boundary_right_[((localix-gridref.local_0_size_)*ny_+iy)*nzp_+iz]; + }else{ + return gridref.relem(localix, iy, iz); + } + } + + return gridref.relem((ix+gridref.n_[0])%gridref.n_[0], iy, iz); + } +}; + From a1e2158f17eaba4f798ba74e16c14a79ba02f9f7 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Fri, 4 Feb 2022 02:10:10 +0100 Subject: [PATCH 03/21] subtract mean so that masked particles have correct statistics --- include/particle_generator.hh | 54 ++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/include/particle_generator.hh b/include/particle_generator.hh index 3cb3cdb..febd478 100644 --- a/include/particle_generator.hh +++ b/include/particle_generator.hh @@ -17,6 +17,7 @@ #pragma once #include +#include #include #if defined(USE_HDF5) @@ -169,6 +170,31 @@ namespace particle return particle_type_mask_[sig]; } + template< typename ggrid_t > + inline real_t get_mean_mask_value( const ggrid_t& gg_field, const vec3_t& global_idx_3d, size_t i, size_t j, size_t k, int lattice_index ) const + { + ptrdiff_t ox = (ptrdiff_t)i-(ptrdiff_t)(global_idx_3d[0]%masksize_); + ptrdiff_t oy = (ptrdiff_t)j-(ptrdiff_t)(global_idx_3d[1]%masksize_); + ptrdiff_t oz = (ptrdiff_t)k-(ptrdiff_t)(global_idx_3d[2]%masksize_); + size_t count_full{0}, count_masked{0}; + real_t mean_full{0.0}, mean_masked{0.0}; + for( size_t i=0; i gg_field(field); + const real_t pmeanmass = munit / global_num_particles_; bool bmass_negative = false; - auto mean_pm = field.mean() * pmeanmass; - auto std_pm = field.std() * pmeanmass; + real_t mean_pm = 0.0;//field.mean() * pmeanmass; + real_t std_pm = 0.0; //field.std() * pmeanmass; // read out values from phase shifted field and set assoc. particle's value for (size_t i = 0, ipcount = 0; i < field.size(0); ++i) @@ -409,10 +437,14 @@ namespace particle { for (size_t k = 0; k < field.size(2); ++k) { - if( this->get_mask_value(field.get_cell_idx_3d(i,j,k)) != lattice_index ) continue; + const auto idx3 = field.get_cell_idx_3d(i,j,k); + + if( this->get_mask_value(idx3) != lattice_index ) continue; + + const auto mean_mask = this->get_mean_mask_value( gg_field, idx3, i, j, k, lattice_index ); // get - const auto pmass = pmeanmass * field.relem(i, j, k); + const auto pmass = pmeanmass * (field.relem(i, j, k) - mean_mask); // check for negative mass bmass_negative |= pmass<0.0; @@ -420,9 +452,23 @@ namespace particle // set if (b64reals) particles_.set_mass64(ipcount++, pmass); else particles_.set_mass32(ipcount++, pmass); + + // statistics + mean_pm += pmass; + std_pm += pmass*pmass; } } } + #if defined(USE_MPI) + { + double local_mean_pm = mean_pm, local_std_pm = std_pm; + MPI_Allreduce( &local_mean_pm, &mean_pm, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD ); + MPI_Allreduce( &local_std_pm, &std_pm, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD ); + } + #endif + mean_pm /= global_num_particles_; + std_pm /= global_num_particles_; + std_pm -= mean_pm*mean_pm; // diagnostics music::ilog << "Particle Mass : mean/munit = " << mean_pm/munit << " ; fractional RMS = " << std_pm / mean_pm * 100.0 << "%" << std::endl; From a015ec0f42929cb7c91943170ec3b258b8d61cf8 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Fri, 4 Feb 2022 21:16:55 +0100 Subject: [PATCH 04/21] cleaned up some compiler warnings --- .../panphasia_ho/uniform_rand_threefry4x64.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/external/panphasia_ho/uniform_rand_threefry4x64.c b/external/panphasia_ho/uniform_rand_threefry4x64.c index 2dcf8dc..683ba85 100644 --- a/external/panphasia_ho/uniform_rand_threefry4x64.c +++ b/external/panphasia_ho/uniform_rand_threefry4x64.c @@ -100,8 +100,8 @@ void threefry4x64_test_(int verbose) if ((rand.v[0] != result.v[0]) || (rand.v[1] != result.v[1]) || (rand.v[2] != result.v[2]) || (rand.v[3] != result.v[3])) { printf("Serious error occured !!!!!!!!!! Random generator is not working correctly \n"); - printf("Random generated: %lu %lu %lu %lu\n", rand.v[0], rand.v[1], rand.v[2], rand.v[3]); - printf("Random expected: %lu %lu %lu %lu\n", result.v[0], result.v[1], result.v[2], result.v[3]); + printf("Random generated: %llu %llu %llu %llu\n", rand.v[0], rand.v[1], rand.v[2], rand.v[3]); + printf("Random expected: %llu %llu %llu %llu\n", result.v[0], result.v[1], result.v[2], result.v[3]); //abort(); } else @@ -121,8 +121,8 @@ void threefry4x64_test_(int verbose) if ((rand.v[0] != result.v[0]) || (rand.v[1] != result.v[1]) || (rand.v[2] != result.v[2]) || (rand.v[3] != result.v[3])) { printf("Serious error occured !!!!!!!!!! Random generator is not working correctly \n"); - printf("Random generated: %lu %lu %lu %lu\n", rand.v[0], rand.v[1], rand.v[2], rand.v[3]); - printf("Random expected: %lu %lu %lu %lu\n", result.v[0], result.v[1], result.v[2], result.v[3]); + printf("Random generated: %llu %llu %llu %llu\n", rand.v[0], rand.v[1], rand.v[2], rand.v[3]); + printf("Random expected: %llu %llu %llu %llu\n", result.v[0], result.v[1], result.v[2], result.v[3]); //abort(); } else @@ -143,8 +143,8 @@ void threefry4x64_test_(int verbose) if ((rand.v[0] != result.v[0]) || (rand.v[1] != result.v[1]) || (rand.v[2] != result.v[2]) || (rand.v[3] != result.v[3])) { printf("Serious error occured !!!!!!!!!! Random generator is not working correctly \n"); - printf("Random generated: %lu %lu %lu %lu\n", rand.v[0], rand.v[1], rand.v[2], rand.v[3]); - printf("Random expected: %lu %lu %lu %lu\n", result.v[0], result.v[1], result.v[2], result.v[3]); + printf("Random generated: %llu %llu %llu %llu\n", rand.v[0], rand.v[1], rand.v[2], rand.v[3]); + printf("Random expected: %llu %llu %llu %llu\n", result.v[0], result.v[1], result.v[2], result.v[3]); //abort(); } else @@ -176,7 +176,7 @@ void set_panphasia_key_(int verbose) verbose = 0; //ARJ if (verbose) - printf("Setting the threefry4x64 key to\n(%0lu %0lu %0lu %0lu)\n\n", + printf("Setting the threefry4x64 key to\n(%0llu %0llu %0llu %0llu)\n\n", panphasia_key.v[0], panphasia_key.v[1], panphasia_key.v[2], panphasia_key.v[3]); panphasia_key_initialised = 999; @@ -237,10 +237,10 @@ void check_panphasia_key_(int verbose) if (panphasia_check_key.v[0] != panphasia_key.v[0] || panphasia_check_key.v[1] != panphasia_key.v[1] || panphasia_check_key.v[2] != panphasia_key.v[2] || panphasia_check_key.v[2] != panphasia_key.v[2]) { printf("A serious error has happened - the threefry4x64 key has become corrupted!\n"); - printf("Should be: (%0lu %0lu %0lu %0lu)\n", panphasia_check_key.v[0], + printf("Should be: (%0llu %0llu %0llu %0llu)\n", panphasia_check_key.v[0], panphasia_check_key.v[1], panphasia_check_key.v[2], panphasia_check_key.v[3]); - printf("But now is: (%0lu %0lu %0lu %0lu)\n", panphasia_key.v[0], + printf("But now is: (%0llu %0llu %0llu %0llu)\n", panphasia_key.v[0], panphasia_key.v[1], panphasia_key.v[2], panphasia_key.v[3]); printf("The fact that it has changed suggests the key has been overwritten in memory.\n"); abort(); From 819be9d48d7d68a09ebc67c563dc88320b2cd713 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Wed, 9 Feb 2022 17:56:56 +0100 Subject: [PATCH 05/21] moved warning that was in incorrect place --- include/particle_generator.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/particle_generator.hh b/include/particle_generator.hh index febd478..37bb946 100644 --- a/include/particle_generator.hh +++ b/include/particle_generator.hh @@ -217,8 +217,6 @@ namespace particle if (lattice_type >= 0) // These are the Bravais lattices { - music::wlog << "Glass ICs will currently be incorrect due to disabled ghost zone updates! "; - // number of modes present in the field const size_t num_p_in_load = field.local_size(); // unless SC lattice is used, particle number is a multiple of the number of modes (=num_p_in_load): @@ -330,6 +328,8 @@ namespace particle } else if( lattice_type == lattice_glass ) { + music::wlog << "Glass ICs will currently be incorrect due to disabled ghost zone updates! "; + glass_ptr_ = std::make_unique( cf, field ); particles_.allocate(glass_ptr_->size(), b64reals, b64ids, false); From 8281f0bed612245f1243a669f1a992644c865f08 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Fri, 25 Mar 2022 18:17:10 +0100 Subject: [PATCH 06/21] added customization to particle masking --- example.conf | 3 +++ include/particle_generator.hh | 30 ++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/example.conf b/example.conf index 9781316..76f3a1d 100644 --- a/example.conf +++ b/example.conf @@ -23,6 +23,9 @@ ParticleLoad = sc # particle load, can be 'sc' (1x), 'bcc' (2x) or 'fcc # (increases number of particles by given factor!), # or 'glass' or 'masked' +## if `ParticleLoad = masked' then you can specify here how masking should take place +# ParticleMaskType = 3 # bit mask for particle mask (0=center,1=center+edges,2=center+faces,3=center+edges+faces) + ## if `ParticleLoad = glass' then specify here where to load the glass distribution from # GlassFileName = glass128.hdf5 # GlassTiles = 1 diff --git a/include/particle_generator.hh b/include/particle_generator.hh index 37bb946..b0c1a1b 100644 --- a/include/particle_generator.hh +++ b/include/particle_generator.hh @@ -38,11 +38,11 @@ namespace particle lattice_rsc = 3, // RSC: refined simple cubic }; - const std::vector> lattice_masks = - { - // mask from Richings et al. https://arxiv.org/pdf/2005.14495.pdf - {true,true,true,true,true,true,true,false}, - }; + // const std::vector> lattice_masks = + // { + // // mask from Richings et al. https://arxiv.org/pdf/2005.14495.pdf + // {true,true,true,true,true,true,true,false}, + // }; const std::vector>> lattice_shifts = { @@ -266,11 +266,25 @@ namespace particle // set the particle mask if( cf.get_value_safe("setup","DoBaryons",false) ) { + unsigned mask_type = cf.get_value_safe("setup","ParticleMaskType",3); // mask everywehere 0, except the last element - for( auto& m : particle_type_mask_) m = 0; - particle_type_mask_[7] = 1; + for( auto& m : particle_type_mask_) m = -1; + particle_type_mask_[0] = 0; // CDM at corner of unit cube + if( mask_type & 1<<0 ) { + // edge centers + particle_type_mask_[1] = 0; // CDM + particle_type_mask_[2] = 0; // CDM + particle_type_mask_[4] = 0; // CDM + } + if( mask_type & 1<<1 ){ + // face centers + particle_type_mask_[3] = 0; // CDM + particle_type_mask_[5] = 0; // CDM + particle_type_mask_[6] = 0; // CDM + } + particle_type_mask_[7] = 1; // baryon at cell center (aka opposite corner) }else{ - // mask everywehere 0 + // mask everywhere 0, all particle locations are occupied by CDM for( auto& m : particle_type_mask_) m = 0; } From 82237a0c1c38352160451c9463cd59e0d6cf1290 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Thu, 10 Nov 2022 11:16:28 +0100 Subject: [PATCH 07/21] removed compilation problems with GCC 12 --- include/general.hh | 1 + include/math/vec3.hh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/general.hh b/include/general.hh index 05feb0a..dcf4388 100644 --- a/include/general.hh +++ b/include/general.hh @@ -20,6 +20,7 @@ #include #include +#include #if defined(USE_MPI) #include diff --git a/include/math/vec3.hh b/include/math/vec3.hh index bbaffbc..593c725 100644 --- a/include/math/vec3.hh +++ b/include/math/vec3.hh @@ -30,7 +30,7 @@ public: //! empty constructor vec3_t() - : x(data_[0]),y(data_[1]),z(data_[2]){} + : data_{{T(0),T(0),T(0)}},x(data_[0]),y(data_[1]),z(data_[2]){} //! copy constructor vec3_t( const vec3_t &v) From a6e148ed0005012a85dbd46b591c18e172f91ab5 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Thu, 10 Nov 2022 19:59:22 +0100 Subject: [PATCH 08/21] fixed compiler warning --- src/plugins/output_grafic2.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/output_grafic2.cc b/src/plugins/output_grafic2.cc index 03b2841..702a813 100644 --- a/src/plugins/output_grafic2.cc +++ b/src/plugins/output_grafic2.cc @@ -212,7 +212,7 @@ void grafic2_output_plugin::write_grid_data(const Grid_FFT &g, const cos unlink(file_name.c_str()); } - std::ofstream *pofs; + std::ofstream *pofs = nullptr; // write header or seek to end of file if (CONFIG::MPI_task_rank == 0) From 15be8f4b4fe42b3deb475b7d015e3bddce37d45c Mon Sep 17 00:00:00 2001 From: Lukas Winkler Date: Thu, 15 Dec 2022 11:45:44 +0100 Subject: [PATCH 09/21] put infomation about the gadget4 cosmology part of param.txt in output --- src/plugins/output_gadget_hdf5.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/plugins/output_gadget_hdf5.cc b/src/plugins/output_gadget_hdf5.cc index 32c7fd2..a9144bd 100644 --- a/src/plugins/output_gadget_hdf5.cc +++ b/src/plugins/output_gadget_hdf5.cc @@ -2,17 +2,17 @@ // This file is part of monofonIC (MUSIC2) // A software package to generate ICs for cosmological simulations // Copyright (C) 2020 by Oliver Hahn -// +// // monofonIC is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// +// // monofonIC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program. If not, see . #ifdef USE_HDF5 @@ -122,8 +122,8 @@ public: // use destructor to write header post factum ~gadget_hdf5_output_plugin() { - if (!std::uncaught_exception()) - { + if (!std::uncaught_exception()) + { HDFCreateGroup(this_fname_, "Header"); HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_ThisFile", from_6array(header_.npart)); HDFWriteGroupAttribute(this_fname_, "Header", "MassTable", from_6array(header_.mass)); @@ -144,6 +144,14 @@ public: HDFWriteGroupAttribute(this_fname_, "Header", "Flag_Entropy_ICs", from_value(header_.flag_entropy_instead_u)); music::ilog << "Wrote Gadget-HDF5 file(s) to " << this_fname_ << std::endl; + + music::ilog << "You can use the following values in param.txt:" << std::endl; + music::ilog << "Omega0 " << header_.Omega0 << std::endl; + music::ilog << "OmegaLambda " << header_.OmegaLambda << std::endl; + music::ilog << "OmegaBaryon " << pcc_->cosmo_param_["Omega_b"] << std::endl; + music::ilog << "HubbleParam " << header_.HubbleParam << std::endl; + music::ilog << "Hubble 100.0" << std::endl; + music::ilog << "BoxSize " << header_.BoxSize << std::endl; } } @@ -239,4 +247,4 @@ output_plugin_creator_concrete> creator3("gadg #endif } // namespace -#endif \ No newline at end of file +#endif From d1fc6a2e673727e88728869dd10931adc065b4ba Mon Sep 17 00:00:00 2001 From: Lukas Winkler Date: Tue, 3 Jan 2023 16:20:47 +0100 Subject: [PATCH 10/21] fix compiler error and warnings in clang --- include/HDF_IO.hh | 2 +- include/cosmology_calculator.hh | 4 ++-- include/grid_interpolate.hh | 5 +++-- include/math/vec3.hh | 15 +++++++++------ include/particle_plt.hh | 4 ++-- src/ic_generator.cc | 12 ++++++------ src/output_plugin.cc | 2 +- src/plugins/random_music.cc | 4 ++-- src/plugins/transfer_CLASS.cc | 2 +- src/random_plugin.cc | 2 +- src/transfer_function_plugin.cc | 2 +- 11 files changed, 29 insertions(+), 25 deletions(-) diff --git a/include/HDF_IO.hh b/include/HDF_IO.hh index b7a61ee..99f744f 100755 --- a/include/HDF_IO.hh +++ b/include/HDF_IO.hh @@ -226,7 +226,7 @@ template inline void HDFReadSelect( const std::string Filename, const std::string ObjName, const std::vector& ii, std::vector &Data ){ hid_t HDF_Type, HDF_FileID, HDF_DatasetID, HDF_DataspaceID, HDF_MemspaceID; - hsize_t HDF_StorageSize; +// hsize_t HDF_StorageSize; HDF_Type = GetDataType(); diff --git a/include/cosmology_calculator.hh b/include/cosmology_calculator.hh index dcd3e61..9ad5dcf 100644 --- a/include/cosmology_calculator.hh +++ b/include/cosmology_calculator.hh @@ -179,7 +179,7 @@ public: music::ilog << "Linear growth factors: D+_target = " << Dplus_target_ << ", D+_start = " << Dplus_start_ << std::endl; // set up transfer functions and compute normalisation - transfer_function_ = std::move(select_TransferFunction_plugin(cf, cosmo_param_)); + transfer_function_ = select_TransferFunction_plugin(cf, cosmo_param_); transfer_function_->intialise(); if( !transfer_function_->tf_isnormalised_ ){ cosmo_param_.set("pnorm", this->compute_pnorm_from_sigma8() ); @@ -449,4 +449,4 @@ public: // return pow(6.0 * mass / M_PI * std::sqrt(rho) * std::pow(G, 1.5), 1.0 / 3.0); // } -} // namespace cosmology \ No newline at end of file +} // namespace cosmology diff --git a/include/grid_interpolate.hh b/include/grid_interpolate.hh index 5ede310..29560f1 100644 --- a/include/grid_interpolate.hh +++ b/include/grid_interpolate.hh @@ -175,13 +175,14 @@ struct grid_interpolate MPI_Alltoall(&sendcounts[0], 1, MPI_INT, &recvcounts[0], 1, MPI_INT, MPI_COMM_WORLD); - size_t tot_receive = recvcounts[0], tot_send = sendcounts[0]; + size_t tot_receive = recvcounts[0]; +// size_t tot_send = sendcounts[0]; for (int i = 1; i < MPI::get_size(); ++i) { sendoffsets[i] = sendcounts[i - 1] + sendoffsets[i - 1]; recvoffsets[i] = recvcounts[i - 1] + recvoffsets[i - 1]; tot_receive += recvcounts[i]; - tot_send += sendcounts[i]; +// tot_send += sendcounts[i]; } std::vector recvbuf(tot_receive/3,{0.,0.,0.}); diff --git a/include/math/vec3.hh b/include/math/vec3.hh index 593c725..c5ffe9f 100644 --- a/include/math/vec3.hh +++ b/include/math/vec3.hh @@ -45,12 +45,15 @@ public: : data_(std::move(v.data_)), x(data_[0]), y(data_[1]), z(data_[2]){} //! construct vec3_t from initializer list - template - vec3_t(E&&...e) - : data_{{std::forward(e)...}}, x{data_[0]}, y{data_[1]}, z{data_[2]} - {} - // vec3_t( T a, T b, T c ) - // : data_{{a,b,c}}, x(data_[0]), y(data_[1]), z(data_[2]){} +// template +// vec3_t(E&&...e) +// : data_{{std::forward(e)...}}, x{data_[0]}, y{data_[1]}, z{data_[2]} +// {} + vec3_t( T a, T b, T c ) + : data_{{a,b,c}}, x(data_[0]), y(data_[1]), z(data_[2]){} + + explicit vec3_t( T a) + : data_{{a,a,a}}, x(data_[0]), y(data_[1]), z(data_[2]){} //! bracket index access to vector components T &operator[](size_t i) noexcept{ return data_[i];} diff --git a/include/particle_plt.hh b/include/particle_plt.hh index dd75600..ecb81ed 100644 --- a/include/particle_plt.hh +++ b/include/particle_plt.hh @@ -421,7 +421,7 @@ private: if( !is_in(i,j,k,mat_invrecip) ){ auto average_lv = [&]( const auto& t1, const auto& t2, const auto& t3, vec3_t& v, vec3_t& l ) { - v = real_t(0.0); l = real_t(0.0); + v = vec3_t(0.0); l = vec3_t(0.0); int count(0); auto add_lv = [&]( auto it ) -> void { @@ -586,4 +586,4 @@ public: }; -} \ No newline at end of file +} diff --git a/src/ic_generator.cc b/src/ic_generator.cc index 9e5e907..72bdecf 100644 --- a/src/ic_generator.cc +++ b/src/ic_generator.cc @@ -62,9 +62,9 @@ std::unique_ptr the_cosmo_calc; */ int initialise( config_file& the_config ) { - the_random_number_generator = std::move(select_RNG_plugin(the_config)); + the_random_number_generator = select_RNG_plugin(the_config); the_cosmo_calc = std::make_unique(the_config); - the_output_plugin = std::move(select_output_plugin(the_config, the_cosmo_calc)); + the_output_plugin = select_output_plugin(the_config, the_cosmo_calc); return 0; } @@ -150,12 +150,12 @@ int run( config_file& the_config ) //-------------------------------------------------------------------------------------------------------- //! add beyond box tidal field modes following Schmidt et al. (2018) [https://arxiv.org/abs/1803.03274] bool bAddExternalTides = the_config.contains_key("cosmology", "LSS_aniso_lx") - & the_config.contains_key("cosmology", "LSS_aniso_ly") - & the_config.contains_key("cosmology", "LSS_aniso_lz"); + && the_config.contains_key("cosmology", "LSS_aniso_ly") + && the_config.contains_key("cosmology", "LSS_aniso_lz"); if( bAddExternalTides && !( the_config.contains_key("cosmology", "LSS_aniso_lx") - | the_config.contains_key("cosmology", "LSS_aniso_ly") - | the_config.contains_key("cosmology", "LSS_aniso_lz") )) + || the_config.contains_key("cosmology", "LSS_aniso_ly") + || the_config.contains_key("cosmology", "LSS_aniso_lz") )) { music::elog << "Not all dimensions of LSS_aniso_l{x,y,z} specified! Will ignore external tidal field!" << std::endl; bAddExternalTides = false; diff --git a/src/output_plugin.cc b/src/output_plugin.cc index cfad290..e27d7fc 100644 --- a/src/output_plugin.cc +++ b/src/output_plugin.cc @@ -74,7 +74,7 @@ std::unique_ptr select_output_plugin( config_file& cf, std::uniqu music::ilog << std::setw(32) << std::left << "Output plugin" << " : " << formatname << std::endl; } - return std::move(the_output_plugin_creator->create( cf, pcc )); + return the_output_plugin_creator->create( cf, pcc ); } diff --git a/src/plugins/random_music.cc b/src/plugins/random_music.cc index 5b59fae..675c318 100644 --- a/src/plugins/random_music.cc +++ b/src/plugins/random_music.cc @@ -180,7 +180,7 @@ void RNG_music::parse_random_parameters(void) //... generate some dummy seed which only depends on the level, negative so we know it's not //... an actual seed and thus should not be used as a constraint for coarse levels // rngseeds_.push_back( -abs((unsigned)(ltemp-i)%123+(unsigned)(ltemp+827342523521*i)%123456789) ); - rngseeds_.push_back(-abs((long)(ltemp - i) % 123 + (long)(ltemp + 7342523521 * i) % 123456789)); + rngseeds_.push_back(-std::abs((long)(ltemp - i) % 123 + (long)(ltemp + 7342523521 * i) % 123456789)); else { if (ltemp <= 0) @@ -357,4 +357,4 @@ void RNG_music::compute_random_numbers(void) namespace { RNG_plugin_creator_concrete creator("MUSIC1"); -} \ No newline at end of file +} diff --git a/src/plugins/transfer_CLASS.cc b/src/plugins/transfer_CLASS.cc index f80bba0..f748e22 100644 --- a/src/plugins/transfer_CLASS.cc +++ b/src/plugins/transfer_CLASS.cc @@ -163,7 +163,7 @@ private: music::ilog << "Computing transfer function via ClassEngine..." << std::endl; double wtime = get_wtime(); - the_ClassEngine_ = std::move(std::make_unique(pars_, false)); + the_ClassEngine_ = std::make_unique(pars_, false); wtime = get_wtime() - wtime; music::ilog << "CLASS took " << wtime << " s." << std::endl; diff --git a/src/random_plugin.cc b/src/random_plugin.cc index 958b08b..489e0af 100644 --- a/src/random_plugin.cc +++ b/src/random_plugin.cc @@ -77,5 +77,5 @@ std::unique_ptr select_RNG_plugin(config_file &cf) music::ilog << std::setw(32) << std::left << "Random number generator plugin" << " : " << rngname << std::endl; } - return std::move(the_RNG_plugin_creator->Create(cf)); + return the_RNG_plugin_creator->Create(cf); } diff --git a/src/transfer_function_plugin.cc b/src/transfer_function_plugin.cc index 2dd4cef..b9f465a 100644 --- a/src/transfer_function_plugin.cc +++ b/src/transfer_function_plugin.cc @@ -75,5 +75,5 @@ std::unique_ptr select_TransferFunction_plugin(config_f music::ilog << std::setw(32) << std::left << "Transfer function plugin" << " : " << tfname << std::endl; } - return std::move(the_TransferFunction_plugin_creator->create(cf, cosmo_param)); + return the_TransferFunction_plugin_creator->create(cf, cosmo_param); } From 0c978f7ce32f4bd37cd5ab6ede1d937871e6da1a Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Sun, 26 Mar 2023 18:09:46 +0200 Subject: [PATCH 11/21] fixed monofonic compilation problem. main branch now pulls old CLASS version from tag --- external/class.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/class.cmake b/external/class.cmake index ea6a8f5..2b8cd24 100644 --- a/external/class.cmake +++ b/external/class.cmake @@ -3,7 +3,7 @@ include(FetchContent) FetchContent_Declare( class GIT_REPOSITORY https://github.com/ohahn/class_public.git - GIT_TAG master + GIT_TAG monofonic_v1 GIT_SHALLOW YES GIT_PROGRESS TRUE USES_TERMINAL_DOWNLOAD TRUE # <---- this is needed only for Ninja From c9cfbf37218eecab8a28716912f77e2cf7f66e1d Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Tue, 28 Mar 2023 00:18:46 +0200 Subject: [PATCH 12/21] added extra check on valid range of transfer functions --- include/cosmology_calculator.hh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/cosmology_calculator.hh b/include/cosmology_calculator.hh index 9ad5dcf..e4f58a9 100644 --- a/include/cosmology_calculator.hh +++ b/include/cosmology_calculator.hh @@ -192,8 +192,13 @@ public: music::ilog << std::setw(32) << std::left << "TF supports distinct CDM+baryons" << " : " << (transfer_function_->tf_is_distinct() ? "yes" : "no") << std::endl; + music::ilog << std::setw(32) << std::left << "TF minimum wave number" + << " : " << transfer_function_->get_kmin() << " h/Mpc" << std::endl; music::ilog << std::setw(32) << std::left << "TF maximum wave number" << " : " << transfer_function_->get_kmax() << " h/Mpc" << std::endl; + if( std::sqrt(3.0)* 2.0*M_PI / cf.get_value("setup","BoxLength") * cf.get_value("setup","GridRes")/2 >= transfer_function_->get_kmax() ){ + music::elog << "Simulation nyquist mode kny = " << std::sqrt(3.0)* 2.0*M_PI / cf.get_value("setup","BoxLength") * cf.get_value("setup","GridRes")/2 << " h/Mpc is beyond valid range of transfer function!" << std::endl; + } m_n_s_ = cosmo_param_["n_s"]; m_sqrtpnorm_ = cosmo_param_["sqrtpnorm"]; From 8b267f07be06aa49bd99697867aa0943c9a2ebf6 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Tue, 4 Apr 2023 00:48:38 +0200 Subject: [PATCH 13/21] added reporting of memory high marks --- include/general.hh | 2 + include/memory_stat.hh | 125 +++++++++++++++++++++++++++++++++++++++++ src/grid_fft.cc | 19 +++++++ src/ic_generator.cc | 24 ++++---- src/main.cc | 21 ++++++- 5 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 include/memory_stat.hh diff --git a/include/general.hh b/include/general.hh index dcf4388..573ae6c 100644 --- a/include/general.hh +++ b/include/general.hh @@ -185,6 +185,8 @@ inline void multitask_sync_barrier(void) #endif } +extern size_t global_mem_high_mark, local_mem_high_mark; + namespace CONFIG { extern int MPI_thread_support; diff --git a/include/memory_stat.hh b/include/memory_stat.hh new file mode 100644 index 0000000..f0561f2 --- /dev/null +++ b/include/memory_stat.hh @@ -0,0 +1,125 @@ +/* + * Author: David Robert Nadeau + * Site: http://NadeauSoftware.com/ + * License: Creative Commons Attribution 3.0 Unported License + * http://creativecommons.org/licenses/by/3.0/deed.en_US + */ +#pragma once + +namespace memory +{ + +#if defined(_WIN32) +#include +#include + +#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) +#include +#include + +#if defined(__APPLE__) && defined(__MACH__) +#include + +#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) +#include +#include + +#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) +#include + +#endif + +#else +#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS." +#endif + + +/** + * Returns the peak (maximum so far) resident set size (physical + * memory use) measured in bytes, or zero if the value cannot be + * determined on this OS. + */ +inline size_t getPeakRSS( ) +{ +#if defined(_WIN32) + /* Windows -------------------------------------------------- */ + PROCESS_MEMORY_COUNTERS info; + GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) ); + return (size_t)info.PeakWorkingSetSize; + +#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__))) + /* AIX and Solaris ------------------------------------------ */ + struct psinfo psinfo; + int fd = -1; + if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 ) + return (size_t)0L; /* Can't open? */ + if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) ) + { + close( fd ); + return (size_t)0L; /* Can't read? */ + } + close( fd ); + return (size_t)(psinfo.pr_rssize * 1024L); + +#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) + /* BSD, Linux, and OSX -------------------------------------- */ + struct rusage rusage; + getrusage( RUSAGE_SELF, &rusage ); +#if defined(__APPLE__) && defined(__MACH__) + return (size_t)rusage.ru_maxrss; +#else + return (size_t)(rusage.ru_maxrss * 1024L); +#endif + +#else + /* Unknown OS ----------------------------------------------- */ + return (size_t)0L; /* Unsupported. */ +#endif +} + + + + + +/** + * Returns the current resident set size (physical memory use) measured + * in bytes, or zero if the value cannot be determined on this OS. + */ +inline size_t getCurrentRSS( ) +{ +#if defined(_WIN32) + /* Windows -------------------------------------------------- */ + PROCESS_MEMORY_COUNTERS info; + GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) ); + return (size_t)info.WorkingSetSize; + +#elif defined(__APPLE__) && defined(__MACH__) + /* OSX ------------------------------------------------------ */ + struct mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO, + (task_info_t)&info, &infoCount ) != KERN_SUCCESS ) + return (size_t)0L; /* Can't access? */ + return (size_t)info.resident_size; + +#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__) + /* Linux ---------------------------------------------------- */ + long rss = 0L; + FILE* fp = NULL; + if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL ) + return (size_t)0L; /* Can't open? */ + if ( fscanf( fp, "%*s%ld", &rss ) != 1 ) + { + fclose( fp ); + return (size_t)0L; /* Can't read? */ + } + fclose( fp ); + return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE); + +#else + /* AIX, BSD, Solaris, and Unknown OS ------------------------ */ + return (size_t)0L; /* Unsupported. */ +#endif +} + +}; diff --git a/src/grid_fft.cc b/src/grid_fft.cc index 0668029..f2767af 100644 --- a/src/grid_fft.cc +++ b/src/grid_fft.cc @@ -19,6 +19,24 @@ #include #include +#include "memory_stat.hh" + +void memory_report(void) +{ + //... report memory usage + size_t curr_mem_high_mark = 0; + local_mem_high_mark = memory::getCurrentRSS(); +#if defined(USE_MPI) + MPI_Allreduce(&local_mem_high_mark, &curr_mem_high_mark, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX, MPI_COMM_WORLD); +#else + curr_mem_high_mark = local_mem_high_mark; +#endif + if( curr_mem_high_mark > 1.1*global_mem_high_mark ){ + music::ilog << "----mem-> new memory high mark: " << curr_mem_high_mark/(1ull<<20) << " MBytes / task" << std::endl; + global_mem_high_mark = curr_mem_high_mark; + } +} + template void Grid_FFT::allocate(void) { @@ -175,6 +193,7 @@ void Grid_FFT::allocate(void) #endif //// of #ifdef #else USE_MPI //////////////////////////////////////////////////////////////////////////////////// } ballocated_ = true; + memory_report(); } template diff --git a/src/ic_generator.cc b/src/ic_generator.cc index 72bdecf..5308fae 100644 --- a/src/ic_generator.cc +++ b/src/ic_generator.cc @@ -354,10 +354,10 @@ int run( config_file& the_config ) // phi = - delta / k^2 music::ilog << "-------------------------------------------------------------------------------" << std::endl; - music::ilog << "Generating LPT fields...." << std::endl; + music::ilog << "\n>>> Generating LPT fields.... <<<\n" << std::endl; double wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << "Computing phi(1) term" << std::flush; + music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing phi(1) term" << std::endl; phi.FourierTransformForward(false); phi.assign_function_of_grids_kdep([&](auto k, auto wn) { @@ -368,7 +368,7 @@ int run( config_file& the_config ) phi.zero_DC_mode(); - music::ilog << std::setw(20) << std::setfill(' ') << std::right << "took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << "----cpu-> phi(1) took " << get_wtime() - wtime << "s" << std::endl; //====================================================================== //... compute 2LPT displacement potential .... @@ -379,7 +379,7 @@ int run( config_file& the_config ) phi2.FourierTransformForward(false); wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << "Computing phi(2) term" << std::flush; + music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing phi(2) term" << std::endl; Conv.convolve_SumOfHessians(phi, {0, 0}, phi, {1, 1}, {2, 2}, op::assign_to(phi2)); Conv.convolve_Hessians(phi, {1, 1}, phi, {2, 2}, op::add_to(phi2)); Conv.convolve_Hessians(phi, {0, 1}, phi, {0, 1}, op::subtract_from(phi2)); @@ -398,7 +398,7 @@ int run( config_file& the_config ) } phi2.apply_InverseLaplacian(); - music::ilog << std::setw(20) << std::setfill(' ') << std::right << "took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << "----cpu-> phi(2) took " << get_wtime() - wtime << "s" << std::endl; if (bAddExternalTides) { @@ -419,19 +419,18 @@ int run( config_file& the_config ) //... phi3 = phi3a - 10/7 phi3b //... 3a term ... wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << "Computing phi(3a) term" << std::flush; + music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing phi(3a) term" << std::endl; Conv.convolve_Hessians(phi, {0, 0}, phi, {1, 1}, phi, {2, 2}, op::assign_to(phi3)); Conv.convolve_Hessians(phi, {0, 1}, phi, {0, 2}, phi, {1, 2}, op::multiply_add_to(phi3,2.0)); Conv.convolve_Hessians(phi, {1, 2}, phi, {1, 2}, phi, {0, 0}, op::subtract_from(phi3)); Conv.convolve_Hessians(phi, {0, 2}, phi, {0, 2}, phi, {1, 1}, op::subtract_from(phi3)); Conv.convolve_Hessians(phi, {0, 1}, phi, {0, 1}, phi, {2, 2}, op::subtract_from(phi3)); // phi3a.apply_InverseLaplacian(); - music::ilog << std::setw(20) << std::setfill(' ') << std::right << "took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << "----cpu-> phi(3a) took " << get_wtime() - wtime << "s" << std::endl; //... 3b term ... wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << "Computing phi(3b) term" << std::flush; - // phi3b.FourierTransformForward(false); + music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing phi(3b) term" << std::endl; Conv.convolve_SumOfHessians(phi, {0, 0}, phi2, {1, 1}, {2, 2}, op::multiply_add_to(phi3,-5.0/7.0)); Conv.convolve_SumOfHessians(phi, {1, 1}, phi2, {2, 2}, {0, 0}, op::multiply_add_to(phi3,-5.0/7.0)); Conv.convolve_SumOfHessians(phi, {2, 2}, phi2, {0, 0}, {1, 1}, op::multiply_add_to(phi3,-5.0/7.0)); @@ -439,12 +438,11 @@ int run( config_file& the_config ) Conv.convolve_Hessians(phi, {0, 2}, phi2, {0, 2}, op::multiply_add_to(phi3,+10.0/7.0)); Conv.convolve_Hessians(phi, {1, 2}, phi2, {1, 2}, op::multiply_add_to(phi3,+10.0/7.0)); phi3.apply_InverseLaplacian(); - //phi3b *= 0.5; // factor 1/2 from definition of phi(3b)! - music::ilog << std::setw(20) << std::setfill(' ') << std::right << "took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << "----cpu-> phi(3b) took " << get_wtime() - wtime << "s" << std::endl; //... transversal term ... wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << "Computing A(3) term" << std::flush; + music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing A(3) term" << std::endl; for (int idim = 0; idim < 3; ++idim) { // cyclic rotations of indices @@ -457,7 +455,7 @@ int run( config_file& the_config ) Conv.convolve_DifferenceOfHessians(phi2, {idimp, idimpp}, phi, {idimp, idimp}, {idimpp, idimpp}, op::subtract_from(*A3[idim])); A3[idim]->apply_InverseLaplacian(); } - music::ilog << std::setw(20) << std::setfill(' ') << std::right << "took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << "----cpu-> A(3) took " << get_wtime() - wtime << "s" << std::endl; } ///... scale all potentials with respective growth factors diff --git a/src/main.cc b/src/main.cc index eb38c10..381b170 100644 --- a/src/main.cc +++ b/src/main.cc @@ -43,8 +43,11 @@ bool FFTW_threads_ok = false; int num_threads = 1; } +size_t global_mem_high_mark, local_mem_high_mark; #include "system_stat.hh" +#include "memory_stat.hh" + #include #include @@ -76,6 +79,8 @@ int main( int argc, char** argv ) music::logger::set_level(music::log_level::debug); #endif + global_mem_high_mark = local_mem_high_mark = 0; + //------------------------------------------------------------------------------ // initialise MPI //------------------------------------------------------------------------------ @@ -259,13 +264,25 @@ int main( int argc, char** argv ) ic_generator::reset(); /////////////////////////////////////////////////////////////////////// + music::ilog << "-------------------------------------------------------------------------------" << std::endl; + size_t peak_mem = memory::getPeakRSS(); +#if defined(USE_MPI) + size_t peak_mem_max{0}; + MPI_Allreduce(&peak_mem, &peak_mem_max, 1, MPI_UNSIGNED_LONG_LONG, MPI_MAX, MPI_COMM_WORLD); + peak_mem = peak_mem_max; +#endif + + if( peak_mem > (1ull<<30) ) + music::ilog << "----mem-> peak memory usage was " << peak_mem /(1ull<<30) << " GBytes / task" << std::endl; + else + music::ilog << "----mem-> peak memory usage was " << peak_mem /(1ull<<20) << " MBytes / task" << std::endl; + #if defined(USE_MPI) MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); #endif - - music::ilog << "-------------------------------------------------------------------------------" << std::endl; + music::ilog << "Done. Have a nice day!\n" << std::endl; return 0; From 69f8b1243c103fa6f6a088b3a3440e9e198af793 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Tue, 4 Apr 2023 01:08:26 +0200 Subject: [PATCH 14/21] reformatted mem+time output --- src/grid_fft.cc | 2 +- src/ic_generator.cc | 20 ++++++++++---------- src/main.cc | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/grid_fft.cc b/src/grid_fft.cc index f2767af..24b52f1 100644 --- a/src/grid_fft.cc +++ b/src/grid_fft.cc @@ -32,7 +32,7 @@ void memory_report(void) curr_mem_high_mark = local_mem_high_mark; #endif if( curr_mem_high_mark > 1.1*global_mem_high_mark ){ - music::ilog << "----mem-> new memory high mark: " << curr_mem_high_mark/(1ull<<20) << " MBytes / task" << std::endl; + music::ilog << std::setw(57) << std::setfill(' ') << std::right << "mem high: " << std::setw(8) << curr_mem_high_mark/(1ull<<20) << " MBytes / task" << std::endl; global_mem_high_mark = curr_mem_high_mark; } } diff --git a/src/ic_generator.cc b/src/ic_generator.cc index 5308fae..6f941f0 100644 --- a/src/ic_generator.cc +++ b/src/ic_generator.cc @@ -357,7 +357,7 @@ int run( config_file& the_config ) music::ilog << "\n>>> Generating LPT fields.... <<<\n" << std::endl; double wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing phi(1) term" << std::endl; + music::ilog << std::setw(79) << std::setfill('.') << std::left << ">> Computing phi(1) term" << std::endl; phi.FourierTransformForward(false); phi.assign_function_of_grids_kdep([&](auto k, auto wn) { @@ -368,7 +368,7 @@ int run( config_file& the_config ) phi.zero_DC_mode(); - music::ilog << "----cpu-> phi(1) took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << std::setw(70) << std::setfill(' ') << std::right << "took : " << std::setw(8) << get_wtime() - wtime << "s" << std::endl; //====================================================================== //... compute 2LPT displacement potential .... @@ -379,7 +379,7 @@ int run( config_file& the_config ) phi2.FourierTransformForward(false); wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing phi(2) term" << std::endl; + music::ilog << std::setw(79) << std::setfill('.') << std::left << ">> Computing phi(2) term" << std::endl; Conv.convolve_SumOfHessians(phi, {0, 0}, phi, {1, 1}, {2, 2}, op::assign_to(phi2)); Conv.convolve_Hessians(phi, {1, 1}, phi, {2, 2}, op::add_to(phi2)); Conv.convolve_Hessians(phi, {0, 1}, phi, {0, 1}, op::subtract_from(phi2)); @@ -398,7 +398,7 @@ int run( config_file& the_config ) } phi2.apply_InverseLaplacian(); - music::ilog << "----cpu-> phi(2) took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << std::setw(70) << std::setfill(' ') << std::right << "took : " << std::setw(8) << get_wtime() - wtime << "s" << std::endl; if (bAddExternalTides) { @@ -419,18 +419,18 @@ int run( config_file& the_config ) //... phi3 = phi3a - 10/7 phi3b //... 3a term ... wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing phi(3a) term" << std::endl; + music::ilog << std::setw(79) << std::setfill('.') << std::left << ">> Computing phi(3a) term" << std::endl; Conv.convolve_Hessians(phi, {0, 0}, phi, {1, 1}, phi, {2, 2}, op::assign_to(phi3)); Conv.convolve_Hessians(phi, {0, 1}, phi, {0, 2}, phi, {1, 2}, op::multiply_add_to(phi3,2.0)); Conv.convolve_Hessians(phi, {1, 2}, phi, {1, 2}, phi, {0, 0}, op::subtract_from(phi3)); Conv.convolve_Hessians(phi, {0, 2}, phi, {0, 2}, phi, {1, 1}, op::subtract_from(phi3)); Conv.convolve_Hessians(phi, {0, 1}, phi, {0, 1}, phi, {2, 2}, op::subtract_from(phi3)); // phi3a.apply_InverseLaplacian(); - music::ilog << "----cpu-> phi(3a) took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << std::setw(70) << std::setfill(' ') << std::right << "took : " << std::setw(8) << get_wtime() - wtime << "s" << std::endl; //... 3b term ... wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing phi(3b) term" << std::endl; + music::ilog << std::setw(71) << std::setfill('.') << std::left << ">> Computing phi(3b) term" << std::endl; Conv.convolve_SumOfHessians(phi, {0, 0}, phi2, {1, 1}, {2, 2}, op::multiply_add_to(phi3,-5.0/7.0)); Conv.convolve_SumOfHessians(phi, {1, 1}, phi2, {2, 2}, {0, 0}, op::multiply_add_to(phi3,-5.0/7.0)); Conv.convolve_SumOfHessians(phi, {2, 2}, phi2, {0, 0}, {1, 1}, op::multiply_add_to(phi3,-5.0/7.0)); @@ -438,11 +438,11 @@ int run( config_file& the_config ) Conv.convolve_Hessians(phi, {0, 2}, phi2, {0, 2}, op::multiply_add_to(phi3,+10.0/7.0)); Conv.convolve_Hessians(phi, {1, 2}, phi2, {1, 2}, op::multiply_add_to(phi3,+10.0/7.0)); phi3.apply_InverseLaplacian(); - music::ilog << "----cpu-> phi(3b) took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << std::setw(70) << std::setfill(' ') << std::right << "took : " << std::setw(8) << get_wtime() - wtime << "s" << std::endl; //... transversal term ... wtime = get_wtime(); - music::ilog << std::setw(40) << std::setfill('.') << std::left << ">> Computing A(3) term" << std::endl; + music::ilog << std::setw(71) << std::setfill('.') << std::left << ">> Computing A(3) term" << std::endl; for (int idim = 0; idim < 3; ++idim) { // cyclic rotations of indices @@ -455,7 +455,7 @@ int run( config_file& the_config ) Conv.convolve_DifferenceOfHessians(phi2, {idimp, idimpp}, phi, {idimp, idimp}, {idimpp, idimpp}, op::subtract_from(*A3[idim])); A3[idim]->apply_InverseLaplacian(); } - music::ilog << "----cpu-> A(3) took " << get_wtime() - wtime << "s" << std::endl; + music::ilog << std::setw(70) << std::setfill(' ') << std::right << "took : " << std::setw(8) << get_wtime() - wtime << "s" << std::endl; } ///... scale all potentials with respective growth factors diff --git a/src/main.cc b/src/main.cc index 381b170..4668964 100644 --- a/src/main.cc +++ b/src/main.cc @@ -273,9 +273,9 @@ int main( int argc, char** argv ) #endif if( peak_mem > (1ull<<30) ) - music::ilog << "----mem-> peak memory usage was " << peak_mem /(1ull<<30) << " GBytes / task" << std::endl; + music::ilog << "Peak memory usage was " << peak_mem /(1ull<<30) << " GBytes / task" << std::endl; else - music::ilog << "----mem-> peak memory usage was " << peak_mem /(1ull<<20) << " MBytes / task" << std::endl; + music::ilog << "Peak memory usage was " << peak_mem /(1ull<<20) << " MBytes / task" << std::endl; #if defined(USE_MPI) From 039b68bea0ce3cc0f356ea28a48d861f08984550 Mon Sep 17 00:00:00 2001 From: Lukas Winkler Date: Mon, 24 Apr 2023 14:55:14 +0200 Subject: [PATCH 15/21] add monofonic metadata to Gadget-HDF5 output --- src/plugins/output_gadget_hdf5.cc | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/plugins/output_gadget_hdf5.cc b/src/plugins/output_gadget_hdf5.cc index a9144bd..4f18225 100644 --- a/src/plugins/output_gadget_hdf5.cc +++ b/src/plugins/output_gadget_hdf5.cc @@ -117,6 +117,46 @@ public: unlink(this_fname_.c_str()); HDFCreateFile(this_fname_); + + // Write MUSIC configuration header + int order = cf_.get_value("setup", "LPTorder"); + std::string load = cf_.get_value("setup", "ParticleLoad"); + std::string tf = cf_.get_value("cosmology", "transfer"); + std::string cosmo_set = cf_.get_value("cosmology", "ParameterSet"); + std::string rng = cf_.get_value("random", "generator"); + int do_fixing = cf_.get_value("setup", "DoFixing"); + int do_invert = cf_.get_value("setup", "DoInversion"); + int do_baryons = cf_.get_value("setup", "DoBaryons"); + int do_baryonsVrel = cf_.get_value("setup", "DoBaryonVrel"); + int L = cf_.get_value("setup", "GridRes"); + + HDFCreateGroup(fname_, "ICs_parameters"); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Code", std::string("MUSIC2 - monofonIC")); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Git Revision", std::string(GIT_REV)); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Git Tag", std::string(GIT_TAG)); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Git Branch", std::string(GIT_BRANCH)); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Precision", std::string(CMAKE_PRECISION_STR)); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Convolutions", std::string(CMAKE_CONVOLVER_STR)); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "PLT", std::string(CMAKE_PLT_STR)); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "LPT Order", order); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Particle Load", load); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Transfer Function", tf); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Cosmology Parameter Set", cosmo_set); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Random Generator", rng); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Mode Fixing", do_fixing); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Mode inversion", do_invert); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Baryons", do_baryons); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Baryons Relative Velocity", do_baryonsVrel); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Grid Resolution", L); + + if (tf == "CLASS") { + double ztarget = cf_.get_value("cosmology", "ztarget"); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Target Redshift", ztarget); + } + if (rng == "PANPHASIA") { + std::string desc = cf_.get_value("random", "descriptor"); + HDFWriteGroupAttribute(fname_, "ICs_parameters", "Descriptor", desc); + } } // use destructor to write header post factum From 6d4aa3c4f9babde483b4e51a7855873c392d18b0 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Wed, 7 Jun 2023 15:02:15 +0200 Subject: [PATCH 16/21] add error when grid size is not even for nLPT>1, added some more verbosity --- src/ic_generator.cc | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/ic_generator.cc b/src/ic_generator.cc index 6f941f0..c243f6c 100644 --- a/src/ic_generator.cc +++ b/src/ic_generator.cc @@ -108,6 +108,20 @@ int run( config_file& the_config ) //! order of the LPT approximation const int LPTorder = the_config.get_value_safe("setup","LPTorder",100); + #if defined(USE_CONVOLVER_ORSZAG) + //! check if grid size is even for Orszag convolver + if( (ngrid%2 != 0) && (LPTorder>1) ){ + music::elog << "ERROR: Orszag convolver for LPTorder>1 requires even grid size!" << std::endl; + throw std::runtime_error("Orszag convolver for LPTorder>1 requires even grid size!"); + return 0; + } + #else + //! warn if Orszag convolver is not used + if( LPTorder>1 ){ + music::wlog << "WARNING: LPTorder>1 requires USE_CONVOLVER_ORSZAG to be enabled to avoid aliased results!" << std::endl; + } + #endif + //-------------------------------------------------------------------------------------------------------- //! initialice particles on a bcc or fcc lattice instead of a standard sc lattice (doubles and quadruples the number of particles) std::string lattice_str = the_config.get_value_safe("setup","ParticleLoad","sc"); @@ -119,17 +133,23 @@ int run( config_file& the_config ) : ((lattice_str=="masked")? particle::lattice_masked : particle::lattice_sc))))); + music::ilog << "Using " << lattice_str << " lattice for particle load." << std::endl; + //-------------------------------------------------------------------------------------------------------- //! apply fixing of the complex mode amplitude following Angulo & Pontzen (2016) [https://arxiv.org/abs/1603.05253] const bool bDoFixing = the_config.get_value_safe("setup", "DoFixing", false); + music::ilog << "Fixing of complex mode amplitudes is " << (bDoFixing?"enabled":"disabled") << std::endl; + const bool bDoInversion = the_config.get_value_safe("setup", "DoInversion", false); - + music::ilog << "Inversion of the phase field is " << (bDoInversion?"enabled":"disabled") << std::endl; //-------------------------------------------------------------------------------------------------------- //! do baryon ICs? const bool bDoBaryons = the_config.get_value_safe("setup", "DoBaryons", false ); + music::ilog << "Baryon ICs are " << (bDoBaryons?"enabled":"disabled") << std::endl; //! enable also back-scaled decaying relative velocity mode? only first order! const bool bDoLinearBCcorr = the_config.get_value_safe("setup", "DoBaryonVrel", false); + music::ilog << "Baryon linear relative velocity mode is " << (bDoLinearBCcorr?"enabled":"disabled") << std::endl; // compute mass fractions std::map< cosmo_species, double > Omega; if( bDoBaryons ){ From 251ef81094caa7fd826c966a6a0541d4d2a81a47 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Wed, 7 Jun 2023 15:17:27 +0200 Subject: [PATCH 17/21] made particle numbers in gadget-hdf5 output 64bit, kept 32 bit version for legacy Gadget-2 compatibility via Gadgget2Compatibility=yes flag --- src/plugins/output_gadget_hdf5.cc | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/plugins/output_gadget_hdf5.cc b/src/plugins/output_gadget_hdf5.cc index 4f18225..17a24da 100644 --- a/src/plugins/output_gadget_hdf5.cc +++ b/src/plugins/output_gadget_hdf5.cc @@ -38,12 +38,14 @@ class gadget_hdf5_output_plugin : public output_plugin struct header_t { unsigned npart[6]; + size_t npart64[6]; double mass[6]; double time; double redshift; int flag_sfr; int flag_feedback; unsigned int npartTotal[6]; + size_t npartTotal64[6]; int flag_cooling; int num_files; double BoxSize; @@ -62,6 +64,7 @@ protected: header_t header_; real_t lunit_, vunit_, munit_; bool blongids_; + bool bgadget2_compatibility_; std::string this_fname_; public: @@ -84,11 +87,15 @@ public: blongids_ = cf_.get_value_safe("output", "UseLongids", false); num_simultaneous_writers_ = cf_.get_value_safe("output", "NumSimWriters", num_files_); + bgadget2_compatibility_ = cf_.get_value_safe("output", "Gadget2Compatibility", false); + for (int i = 0; i < 6; ++i) { header_.npart[i] = 0; + header_.npart64[i] = 0; header_.npartTotal[i] = 0; header_.npartTotalHighWord[i] = 0; + header_.npartTotal64[i] = 0; header_.mass[i] = 0.0; } @@ -165,13 +172,19 @@ public: if (!std::uncaught_exception()) { HDFCreateGroup(this_fname_, "Header"); - HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_ThisFile", from_6array(header_.npart)); + if( bgadget2_compatibility_ ){ + HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_ThisFile", from_6array(header_.npart)); + HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_Total", from_6array(header_.npartTotal)); + HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_Total_HighWord", from_6array(header_.npartTotalHighWord)); + }else{ + HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_ThisFile", from_6array(header_.npart64)); + HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_Total", from_6array(header_.npartTotal64)); + } HDFWriteGroupAttribute(this_fname_, "Header", "MassTable", from_6array(header_.mass)); HDFWriteGroupAttribute(this_fname_, "Header", "Time", from_value(header_.time)); HDFWriteGroupAttribute(this_fname_, "Header", "Redshift", from_value(header_.redshift)); HDFWriteGroupAttribute(this_fname_, "Header", "Flag_Sfr", from_value(header_.flag_sfr)); HDFWriteGroupAttribute(this_fname_, "Header", "Flag_Feedback", from_value(header_.flag_feedback)); - HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_Total", from_6array(header_.npartTotal)); HDFWriteGroupAttribute(this_fname_, "Header", "Flag_Cooling", from_value(header_.flag_cooling)); HDFWriteGroupAttribute(this_fname_, "Header", "NumFilesPerSnapshot", from_value(header_.num_files)); HDFWriteGroupAttribute(this_fname_, "Header", "BoxSize", from_value(header_.BoxSize)); @@ -180,7 +193,6 @@ public: HDFWriteGroupAttribute(this_fname_, "Header", "HubbleParam", from_value(header_.HubbleParam)); HDFWriteGroupAttribute(this_fname_, "Header", "Flag_StellarAge", from_value(header_.flag_stellarage)); HDFWriteGroupAttribute(this_fname_, "Header", "Flag_Metals", from_value(header_.flag_metals)); - HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_Total_HighWord", from_6array(header_.npartTotalHighWord)); HDFWriteGroupAttribute(this_fname_, "Header", "Flag_Entropy_ICs", from_value(header_.flag_entropy_instead_u)); music::ilog << "Wrote Gadget-HDF5 file(s) to " << this_fname_ << std::endl; @@ -237,10 +249,15 @@ public: assert(sid != -1); + // use 32 bit integers for Gadget-2 compatibility header_.npart[sid] = (pc.get_local_num_particles()); header_.npartTotal[sid] = (uint32_t)(pc.get_global_num_particles()); header_.npartTotalHighWord[sid] = (uint32_t)((pc.get_global_num_particles()) >> 32); + // use 64 bit integers for Gadget >2 compatibility + header_.npart64[sid] = pc.get_local_num_particles(); + header_.npartTotal64[sid] = pc.get_global_num_particles(); + if( pc.bhas_individual_masses_ ) header_.mass[sid] = 0.0; else From 0db13cee68e59dc52ce0a722b6948756fcd0692d Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Wed, 7 Jun 2023 15:26:16 +0200 Subject: [PATCH 18/21] finally fixed Gadget multiple output filename convention to filename.X.hdf5 --- src/plugins/output_gadget_hdf5.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/output_gadget_hdf5.cc b/src/plugins/output_gadget_hdf5.cc index 17a24da..bd6f28b 100644 --- a/src/plugins/output_gadget_hdf5.cc +++ b/src/plugins/output_gadget_hdf5.cc @@ -114,13 +114,20 @@ public: header_.flag_entropy_instead_u = 0; header_.flag_doubleprecision = (typeid(write_real_t) == typeid(double)) ? true : false; - this_fname_ = fname_; + // split fname into prefix and file suffix (at last dot) + std::string::size_type pos = fname_.find_last_of("."); + std::string fname_prefix = fname_.substr(0, pos); + std::string fname_suffix = fname_.substr(pos + 1); + + // add rank to filename if we have more than one file + this_fname_ = fname_prefix; #ifdef USE_MPI int thisrank = 0; MPI_Comm_rank(MPI_COMM_WORLD, &thisrank); if (num_files_ > 1) this_fname_ += "." + std::to_string(thisrank); #endif + this_fname_ += "." + fname_suffix; unlink(this_fname_.c_str()); HDFCreateFile(this_fname_); From a2d83df9b362c999caf641e132b499abb8a44bfe Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Thu, 8 Jun 2023 03:36:24 +0200 Subject: [PATCH 19/21] improved code documentation, added doxygen target --- CMakeLists.txt | 27 +- Doxyfile.in | 1864 +++++++++++++++++++++++++++++++ include/convolution.hh | 151 ++- include/cosmology_calculator.hh | 24 +- include/cosmology_parameters.hh | 1 + include/grid_fft.hh | 43 +- include/grid_ghosts.hh | 21 +- include/math/interpolate.hh | 27 +- include/math/mat3.hh | 80 +- include/math/vec3.hh | 14 +- 10 files changed, 2189 insertions(+), 63 deletions(-) create mode 100644 Doxyfile.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b9297e..69dce44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,19 +183,42 @@ list (APPEND SOURCES endif() endif() +######################################################################################################################## +# DOXYGEN +# This will generate Doxygen documentation when you run make doc_doxygen in your build directory. +option(BUILD_DOCUMENTATION "Build doxygen documentation" OFF) +if(BUILD_DOCUMENTATION) + find_package(Doxygen) + if(DOXYGEN_FOUND) + set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) + set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + + configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY) + + add_custom_target( doc_doxygen ALL + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM ) + endif(DOXYGEN_FOUND) +endif(BUILD_DOCUMENTATION) + +######################################################################################################################## # project configuration header configure_file( ${PROJECT_SOURCE_DIR}/include/cmake_config.hh.in ${PROJECT_SOURCE_DIR}/include/cmake_config.hh ) +######################################################################################################################## +# executable and linking add_executable(${PRGNAME} ${SOURCES} ${PLUGINS}) # target_setup_class(${PRGNAME}) set_target_properties(${PRGNAME} PROPERTIES CXX_STANDARD 14) - -# mpi flags +######################################################################################################################## +# mpi flags and precision set up if(MPI_CXX_FOUND) if(CODE_PRECISION STREQUAL "FLOAT") if(FFTW3_SINGLE_MPI_FOUND) diff --git a/Doxyfile.in b/Doxyfile.in new file mode 100644 index 0000000..aa1ce64 --- /dev/null +++ b/Doxyfile.in @@ -0,0 +1,1864 @@ +# Doxyfile 1.8.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "MUSIC2: monofonIC" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "High-precision initial conditions generator" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = "doxygen" + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. Note that you specify absolute paths here, but also +# relative paths, which will be relative from the directory where doxygen is +# started. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = cassandra{1}="Requires Cassandra: \1" + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, +# and language is one of the parsers supported by doxygen: IDL, Java, +# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, +# C++. For instance to make doxygen treat .inc files as Fortran files (default +# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note +# that for custom extensions you also need to set FILE_PATTERNS otherwise the +# files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented classes, +# or namespaces to their corresponding documentation. Such a link can be +# prevented in individual cases by by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = YES + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. +# +#SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST = YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.cc *.hh + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page (index.html). +# This can be useful if you have a project on for instance GitHub and want reuse +# the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If left blank doxygen will +# generate a default style sheet. Note that it is recommended to use +# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this +# tag will in the future become obsolete. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional +# user-defined cascading style sheet that is included after the standard +# style sheets created by doxygen. Using this option one can overrule +# certain style aspects. This is preferred over using HTML_STYLESHEET +# since it does not replace the standard style sheet and is therefor more +# robust against future updates. Doxygen will copy the style sheet file to +# the output directory. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely +# identify the documentation publisher. This should be a reverse domain-name +# style string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search engine +# library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE = searchdata.xml + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through other +# doxygen projects that are not otherwise connected via tags files, but are +# all added to the same search index. Each project needs to have a tag file set +# via GENERATE_TAGFILE. The search mapping then maps the name of the tag file +# to a relative location where the documentation can be found, +# similar to the +# TAGFILES option but without actually processing the tag file. +# The format is: EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. +# +#XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. +# +#XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/include/convolution.hh b/include/convolution.hh index 48f124d..56675b4 100644 --- a/include/convolution.hh +++ b/include/convolution.hh @@ -22,6 +22,9 @@ #include #include +/// @brief base class for convolutions of two or three fields +/// @tparam data_t +/// @tparam derived_t template class BaseConvolver { @@ -30,23 +33,44 @@ protected: std::array length_; public: + + /// @brief Construct a new Base Convolver object + /// @param N linear grid size + /// @param L physical box size BaseConvolver(const std::array &N, const std::array &L) : np_(N), length_(L) {} + + /// @brief Construct a new Base Convolver object [deleted copy constructor] BaseConvolver( const BaseConvolver& ) = delete; + /// @brief destructor (virtual) virtual ~BaseConvolver() {} - // implements convolution of two Fourier-space fields + /// @brief implements convolution of two Fourier-space fields + /// @tparam kfunc1 field 1 + /// @tparam kfunc2 field 2 + /// @tparam opp output operator template void convolve2(kfunc1 kf1, kfunc2 kf2, opp op) {} - // implements convolution of three Fourier-space fields + /// @brief implements convolution of three Fourier-space fields + /// @tparam kfunc1 field 1 + /// @tparam kfunc2 field 2 + /// @tparam kfunc3 field 3 + /// @tparam opp output operator template void convolve3(kfunc1 kf1, kfunc2 kf2, kfunc3 kf3, opp op) {} public: + /// @brief convolve two gradient fields in Fourier space a_{,i} * b_{,j} + /// @tparam opp output operator type + /// @param inl left input field a + /// @param d1l direction of first gradient (,i) + /// @param inr right input field b + /// @param d1r direction of second gradient (,j) + /// @param output_op output operator template void convolve_Gradients(Grid_FFT &inl, const std::array &d1l, Grid_FFT &inr, const std::array &d1r, @@ -55,19 +79,29 @@ public: // transform to FS in case fields are not inl.FourierTransformForward(); inr.FourierTransformForward(); - // perform convolution of Hessians + // perform convolution of two gradients static_cast(*this).convolve2( + // first gradient [&inl,&d1l](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inl.gradient(d1l[0],{i,j,k}); return grad1*inl.kelem(i, j, k); }, + // second gradient [&inr,&d1r](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inr.gradient(d1r[0],{i,j,k}); return grad1*inr.kelem(i, j, k); }, + // -> output operator output_op); } + /// @brief convolve a gradient and a Hessian field in Fourier space a_{,i} * b_{,jk} + /// @tparam opp output operator type + /// @param inl left input field a + /// @param d1l direction of gradient (,i) + /// @param inr right input field b + /// @param d2r directions of Hessian (,jk) + /// @param output_op output operator template void convolve_Gradient_and_Hessian(Grid_FFT &inl, const std::array &d1l, Grid_FFT &inr, const std::array &d2r, @@ -76,19 +110,29 @@ public: // transform to FS in case fields are not inl.FourierTransformForward(); inr.FourierTransformForward(); - // perform convolution of Hessians + // perform convolution of gradient and Hessian static_cast(*this).convolve2( + // gradient [&](size_t i, size_t j, size_t k) -> ccomplex_t { auto kk = inl.template get_k(i, j, k); return ccomplex_t(0.0, -kk[d1l[0]]) * inl.kelem(i, j, k); }, + // Hessian [&](size_t i, size_t j, size_t k) -> ccomplex_t { auto kk = inr.template get_k(i, j, k); return -kk[d2r[0]] * kk[d2r[1]] * inr.kelem(i, j, k); }, + // -> output operator output_op); } + /// @brief convolve two Hessian fields in Fourier space a_{,ij} * b_{,kl} + /// @tparam opp output operator type + /// @param inl left input field a + /// @param d2l directions of first Hessian (,ij) + /// @param inr right input field b + /// @param d2r directions of second Hessian (,kl) + /// @param output_op output operator template void convolve_Hessians(Grid_FFT &inl, const std::array &d2l, Grid_FFT &inr, const std::array &d2r, @@ -99,19 +143,31 @@ public: inr.FourierTransformForward(); // perform convolution of Hessians static_cast(*this).convolve2( + // first Hessian [&inl,&d2l](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inl.gradient(d2l[0],{i,j,k}); auto grad2 = inl.gradient(d2l[1],{i,j,k}); return grad1*grad2*inl.kelem(i, j, k); }, + // second Hessian [&inr,&d2r](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inr.gradient(d2r[0],{i,j,k}); auto grad2 = inr.gradient(d2r[1],{i,j,k}); return grad1*grad2*inr.kelem(i, j, k); }, + // -> output operator output_op); } + /// @brief convolve three Hessian fields in Fourier space a_{,ij} * b_{,kl} * c_{,mn} + /// @tparam opp output operator + /// @param inl first input field a + /// @param d2l directions of first Hessian (,ij) + /// @param inm second input field b + /// @param d2m directions of second Hessian (,kl) + /// @param inr third input field c + /// @param d2r directions of third Hessian (,mn) + /// @param output_op output operator template void convolve_Hessians(Grid_FFT &inl, const std::array &d2l, Grid_FFT &inm, const std::array &d2m, @@ -124,24 +180,36 @@ public: inr.FourierTransformForward(); // perform convolution of Hessians static_cast(*this).convolve3( + // first Hessian [&inl, &d2l](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inl.gradient(d2l[0],{i,j,k}); auto grad2 = inl.gradient(d2l[1],{i,j,k}); return grad1*grad2*inl.kelem(i, j, k); }, + // second Hessian [&inm, &d2m](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inm.gradient(d2m[0],{i,j,k}); auto grad2 = inm.gradient(d2m[1],{i,j,k}); return grad1*grad2*inm.kelem(i, j, k); }, + // third Hessian [&inr, &d2r](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inr.gradient(d2r[0],{i,j,k}); auto grad2 = inr.gradient(d2r[1],{i,j,k}); return grad1*grad2*inr.kelem(i, j, k); }, + // -> output operator output_op); } + /// @brief convolve Hessian field with sum of two Hessian fields in Fourier space a_{,ij} * (b_{,kl} + c_{,mn}) + /// @tparam opp output operator type + /// @param inl left input field a + /// @param d2l directions of first Hessian (,ij) + /// @param inr right input field b + /// @param d2r1 directions of second Hessian (,kl) + /// @param d2r2 directions of third Hessian (,mn) + /// @param output_op output operator template void convolve_SumOfHessians(Grid_FFT &inl, const std::array &d2l, Grid_FFT &inr, const std::array &d2r1, const std::array &d2r2, @@ -152,11 +220,13 @@ public: inr.FourierTransformForward(); // perform convolution of Hessians static_cast(*this).convolve2( + // first Hessian [&inl, &d2l](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inl.gradient(d2l[0],{i,j,k}); auto grad2 = inl.gradient(d2l[1],{i,j,k}); return grad1*grad2*inl.kelem(i, j, k); }, + // second two Hessian and sum [&inr, &d2r1, &d2r2](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad11 = inr.gradient(d2r1[0],{i,j,k}); auto grad12 = inr.gradient(d2r1[1],{i,j,k}); @@ -164,9 +234,18 @@ public: auto grad22 = inr.gradient(d2r2[1],{i,j,k}); return (grad11*grad12+grad21*grad22)*inr.kelem(i, j, k); }, + // -> output operator output_op); } + /// @brief convolve Hessian field with difference of two Hessian fields in Fourier space a_{,ij} * (b_{,kl} - c_{,mn}) + /// @tparam opp output operator type + /// @param inl left input field a + /// @param d2l directions of first Hessian (,ij) + /// @param inr right input field b + /// @param d2r1 directions of second Hessian (,kl) + /// @param d2r2 directions of third Hessian (,mn) + /// @param output_op output operator template void convolve_DifferenceOfHessians(Grid_FFT &inl, const std::array &d2l, Grid_FFT &inr, const std::array &d2r1, const std::array &d2r2, @@ -177,11 +256,13 @@ public: inr.FourierTransformForward(); // perform convolution of Hessians static_cast(*this).convolve2( + // first Hessian [&inl, &d2l](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad1 = inl.gradient(d2l[0],{i,j,k}); auto grad2 = inl.gradient(d2l[1],{i,j,k}); return grad1*grad2*inl.kelem(i, j, k); }, + // second two Hessian and difference [&inr, &d2r1, &d2r2](size_t i, size_t j, size_t k) -> ccomplex_t { auto grad11 = inr.gradient(d2r1[0],{i,j,k}); auto grad12 = inr.gradient(d2r1[1],{i,j,k}); @@ -189,21 +270,29 @@ public: auto grad22 = inr.gradient(d2r2[1],{i,j,k}); return (grad11*grad12-grad21*grad22)*inr.kelem(i, j, k); }, + // -> output operator output_op); } }; -//! naive convolution class, disrespecting aliasing +//! low-level implementation of convolutions -- naive convolution class, ignoring aliasing (no padding) template class NaiveConvolver : public BaseConvolver> { protected: + /// @brief buffer for Fourier transformed fields Grid_FFT *fbuf1_, *fbuf2_; + /// @brief number of points in each direction using BaseConvolver>::np_; + + /// @brief length of each direction using BaseConvolver>::length_; public: + /// @brief constructor + /// @param N number of points in each direction + /// @param L length of each direction NaiveConvolver(const std::array &N, const std::array &L) : BaseConvolver>(N, L) { @@ -211,12 +300,14 @@ public: fbuf2_ = new Grid_FFT(N, length_, true, kspace_id); } + /// @brief destructor ~NaiveConvolver() { delete fbuf1_; delete fbuf2_; } + /// @brief convolution of two fields template void convolve2(kfunc1 kf1, kfunc2 kf2, opp output_op) { @@ -249,6 +340,7 @@ public: } + /// @brief convolution of three fields template void convolve3(kfunc1 kf1, kfunc2 kf2, kfunc3 kf3, opp output_op) { @@ -292,7 +384,13 @@ public: } } +//-------------------------------------------------------------------------------------------------------- private: + + /// @brief copy data into a grid + /// @tparam kfunc abstract function type generating data + /// @param kf abstract function generating data + /// @param g grid to copy data into template void copy_in(kfunc kf, Grid_FFT &g) { @@ -310,23 +408,28 @@ private: } }; -//! convolution class, respecting Orszag's 3/2 rule +//! convolution class, respecting Orszag's 3/2 rule (padding in Fourier space to avoid aliasing) template class OrszagConvolver : public BaseConvolver> { private: - Grid_FFT *f1p_, *f2p_; - Grid_FFT *fbuf_; + /// @brief buffer for Fourier transformed fields + Grid_FFT *f1p_, *f2p_, *fbuf_; using BaseConvolver>::np_; using BaseConvolver>::length_; - ccomplex_t *crecvbuf_; - real_t *recvbuf_; - size_t maxslicesz_; - std::vector offsets_, offsetsp_; - std::vector sizes_, sizesp_; + ccomplex_t *crecvbuf_; //!< receive buffer for MPI (complex) + real_t *recvbuf_; //!< receive buffer for MPI (real) + size_t maxslicesz_; //!< maximum size of a slice + std::vector offsets_, offsetsp_; //!< offsets for MPI + std::vector sizes_, sizesp_; //!< sizes for MPI + /// @brief get task index for a given index + /// @param index index + /// @param offsets offsets + /// @param sizes sizes + /// @param ntasks number of tasks int get_task(ptrdiff_t index, const std::vector &offsets, const std::vector &sizes, const int ntasks) { int itask = 0; @@ -336,6 +439,10 @@ private: } public: + + /// @brief constructor + /// @param N grid size + /// @param L grid length OrszagConvolver(const std::array &N, const std::array &L) : BaseConvolver>({3 * N[0] / 2, 3 * N[1] / 2, 3 * N[2] / 2}, L) { @@ -370,6 +477,7 @@ public: #endif } + /// @brief destructor ~OrszagConvolver() { delete f1p_; @@ -380,6 +488,10 @@ public: #endif } + /// @brief convolve two fields + /// @tparam kfunc1 abstract function type generating data for the first field + /// @tparam kfunc2 abstract function type generating data for the second field + /// @tparam opp abstract function type for the output operation template void convolve2(kfunc1 kf1, kfunc2 kf2, opp output_op) { @@ -405,6 +517,11 @@ public: unpad(*f2p_, output_op); } + /// @brief convolve three fields + /// @tparam kfunc1 abstract function type generating data for the first field + /// @tparam kfunc2 abstract function type generating data for the second field + /// @tparam kfunc3 abstract function type generating data for the third field + /// @tparam opp abstract function type for the output operation template void convolve3(kfunc1 kf1, kfunc2 kf2, kfunc3 kf3, opp output_op) { @@ -428,6 +545,10 @@ public: private: + /// @brief unpad the result of a convolution and copy it to a grid + /// @tparam kdep_functor abstract function type generating data for the result + /// @param kfunc abstract function generating data for the result + /// @param fp grid to copy the result to template void pad_insert( kdep_functor kfunc, Grid_FFT &fp) { @@ -472,6 +593,10 @@ private: #endif //defined(USE_MPI) } + /// @brief unpad the result of a convolution and write it to an output operator + /// @tparam operator_t abstract function type for the output operation + /// @param fp grid to copy the result from + /// @param output_op abstract function to write the result to template void unpad( Grid_FFT &fp, operator_t output_op) { diff --git a/include/cosmology_calculator.hh b/include/cosmology_calculator.hh index e4f58a9..b11b1d0 100644 --- a/include/cosmology_calculator.hh +++ b/include/cosmology_calculator.hh @@ -152,8 +152,10 @@ private: public: + //! default constructor [deleted] calculator() = delete; + //! copy constructor [deleted] calculator(const calculator& c) = delete; //! constructor for a cosmology calculator object @@ -204,9 +206,12 @@ public: m_sqrtpnorm_ = cosmo_param_["sqrtpnorm"]; } + //! destructor ~calculator() { } - //! Write out a correctly scaled power spectrum at time a + /// @brief Write out a correctly scaled power spectrum at time a + /// @param a scale factor + /// @param fname file name void write_powerspectrum(real_t a, std::string fname) const { // const real_t Dplus0 = this->get_growth_factor(a); @@ -253,7 +258,8 @@ public: music::ilog << "Wrote power spectrum at a=" << a << " to file \'" << fname << "\'" << std::endl; } - //! Write out a correctly scaled power spectrum at starting time + /// @brief Write out a correctly scaled transfer function at time a + /// @param[in] fname filename to write to void write_transfer( std::string fname ) const { // const real_t Dplus0 = this->get_growth_factor(a); @@ -299,12 +305,16 @@ public: music::ilog << "Wrote input transfer functions at a=" << astart_ << " to file \'" << fname << "\'" << std::endl; } + /// @brief return the cosmological parameter object + /// @return cosmological parameter object const cosmology::parameters &get_parameters(void) const noexcept { return cosmo_param_; } - //! return the value of the Hubble function H(a) = dloga/dt + /// @brief return the value of the Hubble function H(a) = dloga/dt + /// @param[in] a scale factor + /// @return H(a) inline double H_of_a(double a) const noexcept { double HH2 = 0.0; @@ -315,13 +325,17 @@ public: return cosmo_param_["H0"] * std::sqrt(HH2); } - //! Computes the linear theory growth factor D+, normalised to D+(a=1)=1 + /// @brief Computes the linear theory growth factor D+, normalised to D+(a=1)=1 + /// @param[in] a scale factor + /// @return D+(a) real_t get_growth_factor(real_t a) const noexcept { return D_of_a_(a) / Dnow_; } - //! Computes the inverse of get_growth_factor + /// @brief Computes the inverse of get_growth_factor, i.e. a(D+) + /// @param[in] Dplus growth factor + /// @return a(D+) real_t get_a( real_t Dplus ) const noexcept { return a_of_D_( Dplus * Dnow_ ); diff --git a/include/cosmology_parameters.hh b/include/cosmology_parameters.hh index 5a46b95..0089944 100644 --- a/include/cosmology_parameters.hh +++ b/include/cosmology_parameters.hh @@ -29,6 +29,7 @@ namespace cosmology class parameters { public: + //! type for default parameter maps using defaultmmap_t = std::map>; private: diff --git a/include/grid_fft.hh b/include/grid_fft.hh index 608705a..b47cb4c 100644 --- a/include/grid_fft.hh +++ b/include/grid_fft.hh @@ -25,26 +25,27 @@ #include #include -enum space_t -{ - kspace_id, - rspace_id -}; - +/// @brief enum to indicate whether a grid is currently in real or k-space +enum space_t { kspace_id, rspace_id }; #ifdef USE_MPI -template +#define GRID_FFT_DISTRIBUTED true #else -template +#define GRID_FFT_DISTRIBUTED false #endif + +/// @brief class for FFTable grids +/// @tparam data_t_ data type +/// @tparam bdistributed flag to indicate whether this grid is distributed in memory +template class Grid_FFT { public: - using data_t = data_t_; - static constexpr bool is_distributed_trait{bdistributed}; + using data_t = data_t_; ///< data type + static constexpr bool is_distributed_trait{bdistributed}; ///< flag to indicate whether this grid is distributed in memory protected: - using grid_fft_t = Grid_FFT; + using grid_fft_t = Grid_FFT; ///< type of this grid public: std::array n_, nhalf_; @@ -68,7 +69,11 @@ public: ptrdiff_t local_0_start_, local_1_start_; ptrdiff_t local_0_size_, local_1_size_; - //! constructor for FTable grid object + /// @brief constructor for FTable grid object + /// @param N number of grid points in each dimension + /// @param L physical size of the grid in each dimension + /// @param allocate flag to indicate whether to allocate memory for the grid + /// @param initialspace flag to indicate whether the grid is initially in real or k-space Grid_FFT(const std::array &N, const std::array &L, bool allocate = true, space_t initialspace = rspace_id) : n_(N), length_(L), space_(initialspace), data_(nullptr), cdata_(nullptr), plan_(nullptr), iplan_(nullptr), ballocated_( false ) { @@ -77,11 +82,16 @@ public: } } - // avoid implicit copying of data + /// @brief copy constructor [deleted] -- to avoid implicit copying of data Grid_FFT(const grid_fft_t &g) = delete; + /// @brief assignment operator [deleted] -- to avoid implicit copying of data + grid_fft_t &operator=(const grid_fft_t &g) = delete; + + /// @brief destructor ~Grid_FFT() { reset(); } + /// @brief reset grid object (free memory, etc.) void reset() { if (data_ != nullptr) { FFTW_API(free)(data_); data_ = nullptr; } @@ -90,13 +100,18 @@ public: ballocated_ = false; } + /// @brief return the grid object for a given refinement level [dummy implementation for backward compatibility with MUSIC1] const grid_fft_t *get_grid(size_t ilevel) const { return this; } - //! return if grid object is + /// @brief return if grid object is distributed in memory + /// @return true if grid object is distributed in memory bool is_distributed( void ) const noexcept { return bdistributed; } + /// @brief allocate memory for grid object void allocate(); + /// @brief return if grid object is allocated + /// @return true if grid object is allocated bool is_allocated( void ) const noexcept { return ballocated_; } //! return the number of data_t elements that we store in the container diff --git a/include/grid_ghosts.hh b/include/grid_ghosts.hh index be31ede..7cdf300 100644 --- a/include/grid_ghosts.hh +++ b/include/grid_ghosts.hh @@ -18,12 +18,16 @@ #include #include - #include #include #include +/// @brief implements a wrapper class for grids with ghost zones for MPI communication (slab decomposition) +/// @tparam numghosts number of ghost zones on each side +/// @tparam haveleft flag whether to have left ghost zone +/// @tparam haveright flag whether to have right ghost zone +/// @tparam grid_t grid type to wrap template struct grid_with_ghosts { @@ -43,6 +47,9 @@ struct grid_with_ghosts //... determine communication offsets std::vector offsets_, sizes_; + /// @brief get task index for a given index + /// @param index index + /// @return task index int get_task(ptrdiff_t index) const { int itask = 0; @@ -51,6 +58,8 @@ struct grid_with_ghosts return itask; } + /// @brief constructor for grid with ghosts + /// @param g grid to wrap explicit grid_with_ghosts(const grid_t &g) : gridref(g), nx_(g.n_[0]), ny_(g.n_[1]), nz_(g.n_[2]), nzp_(g.n_[2]+2) { @@ -74,6 +83,8 @@ struct grid_with_ghosts } } + /// @brief update ghost zones via MPI communication + /// @param g grid to wrap void update_ghosts_allow_multiple( const grid_t &g ) { #if defined(USE_MPI) @@ -181,11 +192,19 @@ struct grid_with_ghosts #endif } + /// @brief return the element at position (i,j,k) in the grid + /// @param i index in x direction + /// @param j index in y direction + /// @param k index in z direction + /// @return grid element at position (i,j,k) data_t relem(const ptrdiff_t& i, const ptrdiff_t& j, const ptrdiff_t&k ) const noexcept { return this->relem({i,j,k}); } + /// @brief return the element at position (i,j,k) in the grid + /// @param pos position in the grid (array of size 3: {i,j,k}) + /// @return grid element at position (i,j,k) data_t relem(const std::array &pos) const noexcept { const ptrdiff_t ix = pos[0]; diff --git a/include/math/interpolate.hh b/include/math/interpolate.hh index 26e8848..0dd0ea4 100644 --- a/include/math/interpolate.hh +++ b/include/math/interpolate.hh @@ -22,16 +22,22 @@ #include #include + +/// @brief 1D interpolation class +/// @tparam logx static flag to indicate logarithmic interpolation in x +/// @tparam logy static flag to indicate logarithmic interpolation in y +/// @tparam periodic static flag to indicate periodic interpolation in x template class interpolated_function_1d { private: - bool isinit_; - std::vector data_x_, data_y_; - gsl_interp_accel *gsl_ia_; - gsl_spline *gsl_sp_; + bool isinit_; ///< flag to indicate whether the interpolation has been initialized + std::vector data_x_, data_y_; ///< data vectors + gsl_interp_accel *gsl_ia_; ///< GSL interpolation accelerator + gsl_spline *gsl_sp_; ///< GSL spline object + /// @brief deallocate GSL objects void deallocate() { gsl_spline_free(gsl_sp_); @@ -39,10 +45,16 @@ private: } public: + + /// @brief default copy constructor (deleted) interpolated_function_1d(const interpolated_function_1d &) = delete; + /// @brief empty constructor (without data) interpolated_function_1d() : isinit_(false){} + /// @brief constructor with data + /// @param data_x x data vector + /// @param data_y y data vector interpolated_function_1d(const std::vector &data_x, const std::vector &data_y) : isinit_(false) { @@ -50,11 +62,15 @@ public: this->set_data( data_x, data_y ); } + /// @brief destructor ~interpolated_function_1d() { if (isinit_) this->deallocate(); } + /// @brief set data + /// @param data_x x data vector + /// @param data_y y data vector void set_data(const std::vector &data_x, const std::vector &data_y) { data_x_ = data_x; @@ -75,6 +91,9 @@ public: isinit_ = true; } + /// @brief evaluate the interpolation + /// @param x x value + /// @return y value double operator()(double x) const noexcept { assert( isinit_ && !(logx&&x<=0.0) ); diff --git a/include/math/mat3.hh b/include/math/mat3.hh index 31d5d6c..2e69f40 100644 --- a/include/math/mat3.hh +++ b/include/math/mat3.hh @@ -22,18 +22,20 @@ #include -//! class for 3x3 matrix calculations +/// @brief class for 3x3 matrix calculations +/// @tparam T type of matrix elements template class mat3_t{ protected: - std::array data_; - std::array data_double_; - gsl_matrix_view m_; - gsl_vector *eval_; - gsl_matrix *evec_; - gsl_eigen_symmv_workspace * wsp_; - bool bdid_alloc_gsl_; + std::array data_; //< data array + std::array data_double_; //< data array for GSL operations + gsl_matrix_view m_; //< GSL matrix view + gsl_vector *eval_; //< GSL eigenvalue vector + gsl_matrix *evec_; //< GSL eigenvector matrix + gsl_eigen_symmv_workspace * wsp_; //< GSL workspace + bool bdid_alloc_gsl_; //< flag to indicate whether GSL memory has been allocated + /// @brief initialize GSL memory void init_gsl(){ // allocate memory for GSL operations if we haven't done so yet if( !bdid_alloc_gsl_ ) @@ -54,6 +56,7 @@ protected: } } + /// @brief free GSL memory void free_gsl(){ // free memory for GSL operations if it was allocated if( bdid_alloc_gsl_ ) @@ -66,54 +69,76 @@ protected: public: + /// @brief default constructor mat3_t() : bdid_alloc_gsl_(false) {} - //! copy constructor + /// @brief copy constructor + /// @param m matrix to copy mat3_t( const mat3_t &m) : data_(m.data_), bdid_alloc_gsl_(false) {} - //! move constructor + /// @brief move constructor + /// @param m matrix to move mat3_t( mat3_t &&m) : data_(std::move(m.data_)), bdid_alloc_gsl_(false) {} - //! construct mat3_t from initializer list + /// @brief construct mat3_t from initializer list + /// @param e initializer list template mat3_t(E&&...e) : data_{{std::forward(e)...}}, bdid_alloc_gsl_(false) {} + /// @brief assignment operator + /// @param m matrix to copy + /// @return reference to this mat3_t& operator=(const mat3_t& m) noexcept{ data_ = m.data_; return *this; } + /// @brief move assignment operator + /// @param m matrix to move + /// @return reference to this mat3_t& operator=(const mat3_t&& m) noexcept{ data_ = std::move(m.data_); return *this; } - //! destructor + /// @brief destructor ~mat3_t(){ this->free_gsl(); } - //! bracket index access to vector components + /// @brief bracket index access to flattened matrix components + /// @param i index + /// @return reference to i-th component T &operator[](size_t i) noexcept { return data_[i];} - //! const bracket index access to vector components + /// @brief const bracket index access to flattened matrix components + /// @param i index + /// @return const reference to i-th component const T &operator[](size_t i) const noexcept { return data_[i]; } - //! matrix 2d index access + /// @brief matrix 2d index access + /// @param i row index + /// @param j column index + /// @return reference to (i,j)-th component T &operator()(size_t i, size_t j) noexcept { return data_[3*i+j]; } - //! const matrix 2d index access + /// @brief const matrix 2d index access + /// @param i row index + /// @param j column index + /// @return const reference to (i,j)-th component const T &operator()(size_t i, size_t j) const noexcept { return data_[3*i+j]; } - //! in-place addition + /// @brief in-place addition + /// @param rhs matrix to add + /// @return reference to this mat3_t& operator+=( const mat3_t& rhs ) noexcept{ for (size_t i = 0; i < 9; ++i) { (*this)[i] += rhs[i]; @@ -121,7 +146,9 @@ public: return *this; } - //! in-place subtraction + /// @brief in-place subtraction + /// @param rhs matrix to subtract + /// @return reference to this mat3_t& operator-=( const mat3_t& rhs ) noexcept{ for (size_t i = 0; i < 9; ++i) { (*this)[i] -= rhs[i]; @@ -129,10 +156,16 @@ public: return *this; } + /// @brief zeroing of matrix void zero() noexcept{ for (size_t i = 0; i < 9; ++i) data_[i]=0; } + /// @brief compute eigenvalues and eigenvectors + /// @param evals eigenvalues + /// @param evec1 first eigenvector + /// @param evec2 second eigenvector + /// @param evec3 third eigenvector void eigen( vec3_t& evals, vec3_t& evec1, vec3_t& evec2, vec3_t& evec3_t ) { this->init_gsl(); @@ -149,6 +182,11 @@ public: } }; +/// @brief matrix addition +/// @tparam T type of matrix components +/// @param lhs left hand side matrix +/// @param rhs right hand side matrix +/// @return matrix result = lhs + rhs template constexpr const mat3_t operator+(const mat3_t &lhs, const mat3_t &rhs) noexcept { @@ -159,7 +197,11 @@ constexpr const mat3_t operator+(const mat3_t &lhs, const mat3_t &rhs) return result; } -// matrix - vector multiplication +/// @brief matrix - vector multiplication +/// @tparam T type of matrix and vector components +/// @param A matrix +/// @param v vector +/// @return vector result = A*v template inline vec3_t operator*( const mat3_t &A, const vec3_t &v ) noexcept { diff --git a/include/math/vec3.hh b/include/math/vec3.hh index c5ffe9f..f85c39f 100644 --- a/include/math/vec3.hh +++ b/include/math/vec3.hh @@ -17,7 +17,8 @@ #pragma once -//! implements a simple class of 3-vectors of arbitrary scalar type +/// @brief implements a simple class of 3-vectors of arbitrary scalar type +/// @tparam T scalar type template< typename T > class vec3_t{ private: @@ -28,19 +29,22 @@ public: //! expose access to elements via references T &x,&y,&z; - //! empty constructor + /// @brief empty constructor vec3_t() : data_{{T(0),T(0),T(0)}},x(data_[0]),y(data_[1]),z(data_[2]){} - //! copy constructor + /// @brief copy constructor + /// @param v vector to copy from vec3_t( const vec3_t &v) : data_(v.data_), x(data_[0]),y(data_[1]),z(data_[2]){} - //! copy constructor for non-const reference, needed to avoid variadic template being called for non-const reference + /// @brief copy constructor for non-const reference, needed to avoid variadic template being called for non-const reference + /// @param v vector to copy from vec3_t( vec3_t& v) : data_(v.data_), x(data_[0]),y(data_[1]),z(data_[2]){} - //! move constructor + /// @brief move constructor + /// @param v vector to move from vec3_t( vec3_t &&v) : data_(std::move(v.data_)), x(data_[0]), y(data_[1]), z(data_[2]){} From 6940d8f3286d576ffb63ed0a4b7cc81152312be0 Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Tue, 20 Jun 2023 16:16:42 +0200 Subject: [PATCH 20/21] fixed bug where sometimes arepo plugin instead of gadget-4 plugin was called --- src/plugins/output_arepo.cc | 10 +++++----- src/plugins/output_gadget_hdf5.cc | 7 ++++--- src/plugins/output_generic.cc | 2 +- src/plugins/output_genericio.cc | 2 +- src/plugins/output_grafic2.cc | 2 +- src/plugins/output_swift.cc | 2 +- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/plugins/output_arepo.cc b/src/plugins/output_arepo.cc index b847608..73f7f9c 100644 --- a/src/plugins/output_arepo.cc +++ b/src/plugins/output_arepo.cc @@ -33,7 +33,7 @@ std::vector from_value(const T a) } template -class gadget_hdf5_output_plugin : public output_plugin +class arepo_output_plugin : public output_plugin { struct header_t { @@ -73,7 +73,7 @@ protected: public: //! constructor - explicit gadget_hdf5_output_plugin(config_file &cf, std::unique_ptr& pcc) + explicit arepo_output_plugin(config_file &cf, std::unique_ptr& pcc) : output_plugin(cf, pcc, "AREPO-HDF5") { num_files_ = 1; @@ -148,7 +148,7 @@ public: } // use destructor to write header post factum - ~gadget_hdf5_output_plugin() + ~arepo_output_plugin() { HDFCreateGroup(this_fname_, "Header"); HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_ThisFile", from_6array(header_.npart)); @@ -271,9 +271,9 @@ public: namespace { #if !defined(USE_SINGLEPRECISION) -output_plugin_creator_concrete> creator1("AREPO"); +output_plugin_creator_concrete> creator880("AREPO"); #else -output_plugin_creator_concrete> creator1("AREPO"); +output_plugin_creator_concrete> creator881("AREPO"); #endif } // namespace diff --git a/src/plugins/output_gadget_hdf5.cc b/src/plugins/output_gadget_hdf5.cc index bd6f28b..acf2883 100644 --- a/src/plugins/output_gadget_hdf5.cc +++ b/src/plugins/output_gadget_hdf5.cc @@ -70,7 +70,7 @@ protected: public: //! constructor explicit gadget_hdf5_output_plugin(config_file &cf, std::unique_ptr &pcc) - : output_plugin(cf, pcc, "GADGET-HDF5") + : output_plugin(cf, pcc, (std::string("GADGET-HDF5-")+typeid(write_real_t).name()).c_str() ) { num_files_ = 1; #ifdef USE_MPI @@ -88,6 +88,7 @@ public: num_simultaneous_writers_ = cf_.get_value_safe("output", "NumSimWriters", num_files_); bgadget2_compatibility_ = cf_.get_value_safe("output", "Gadget2Compatibility", false); + music::ilog << std::setw(32) << std::left << "Gadget2Compatibility" << " : " << (bgadget2_compatibility_? "yes" : "no") << std::endl; for (int i = 0; i < 6; ++i) { @@ -305,9 +306,9 @@ public: namespace { -output_plugin_creator_concrete> creator1("gadget_hdf5"); +output_plugin_creator_concrete> creator991("gadget_hdf5"); #if !defined(USE_SINGLEPRECISION) -output_plugin_creator_concrete> creator3("gadget_hdf5_double"); +output_plugin_creator_concrete> creator992("gadget_hdf5_double"); #endif } // namespace diff --git a/src/plugins/output_generic.cc b/src/plugins/output_generic.cc index f359e50..682dbbe 100644 --- a/src/plugins/output_generic.cc +++ b/src/plugins/output_generic.cc @@ -123,7 +123,7 @@ void generic_output_plugin::write_grid_data(const Grid_FFT &g, const cos namespace { - output_plugin_creator_concrete creator1("generic"); + output_plugin_creator_concrete creator001("generic"); } // namespace #endif \ No newline at end of file diff --git a/src/plugins/output_genericio.cc b/src/plugins/output_genericio.cc index 773ca0b..b24ca94 100644 --- a/src/plugins/output_genericio.cc +++ b/src/plugins/output_genericio.cc @@ -157,7 +157,7 @@ public: namespace { -output_plugin_creator_concrete creator1("genericio"); +output_plugin_creator_concrete creator101("genericio"); } // namespace #endif // ENABLE_GENERICIO \ No newline at end of file diff --git a/src/plugins/output_grafic2.cc b/src/plugins/output_grafic2.cc index 702a813..893320a 100644 --- a/src/plugins/output_grafic2.cc +++ b/src/plugins/output_grafic2.cc @@ -323,5 +323,5 @@ void grafic2_output_plugin::write_ramses_namelist(void) const namespace { - output_plugin_creator_concrete creator1("grafic2"); + output_plugin_creator_concrete creator201("grafic2"); } // namespace diff --git a/src/plugins/output_swift.cc b/src/plugins/output_swift.cc index c719d8c..9c9abe0 100644 --- a/src/plugins/output_swift.cc +++ b/src/plugins/output_swift.cc @@ -369,7 +369,7 @@ public: namespace { -output_plugin_creator_concrete> creator1("SWIFT"); +output_plugin_creator_concrete> creator301("SWIFT"); } // namespace #endif From 9151f238ebd43d0e3d13657395fc77795514969b Mon Sep 17 00:00:00 2001 From: Lehman Garrison Date: Tue, 21 Nov 2023 16:05:04 -0500 Subject: [PATCH 21/21] output_gadget_hdf5: use this_fname_ instead of fname_ to write to correct file when using parallel IO --- src/plugins/output_gadget_hdf5.cc | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/plugins/output_gadget_hdf5.cc b/src/plugins/output_gadget_hdf5.cc index acf2883..1dcba49 100644 --- a/src/plugins/output_gadget_hdf5.cc +++ b/src/plugins/output_gadget_hdf5.cc @@ -145,32 +145,32 @@ public: int do_baryonsVrel = cf_.get_value("setup", "DoBaryonVrel"); int L = cf_.get_value("setup", "GridRes"); - HDFCreateGroup(fname_, "ICs_parameters"); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Code", std::string("MUSIC2 - monofonIC")); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Git Revision", std::string(GIT_REV)); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Git Tag", std::string(GIT_TAG)); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Git Branch", std::string(GIT_BRANCH)); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Precision", std::string(CMAKE_PRECISION_STR)); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Convolutions", std::string(CMAKE_CONVOLVER_STR)); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "PLT", std::string(CMAKE_PLT_STR)); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "LPT Order", order); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Particle Load", load); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Transfer Function", tf); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Cosmology Parameter Set", cosmo_set); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Random Generator", rng); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Mode Fixing", do_fixing); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Mode inversion", do_invert); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Baryons", do_baryons); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Baryons Relative Velocity", do_baryonsVrel); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Grid Resolution", L); + HDFCreateGroup(this_fname_, "ICs_parameters"); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Code", std::string("MUSIC2 - monofonIC")); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Git Revision", std::string(GIT_REV)); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Git Tag", std::string(GIT_TAG)); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Git Branch", std::string(GIT_BRANCH)); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Precision", std::string(CMAKE_PRECISION_STR)); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Convolutions", std::string(CMAKE_CONVOLVER_STR)); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "PLT", std::string(CMAKE_PLT_STR)); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "LPT Order", order); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Particle Load", load); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Transfer Function", tf); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Cosmology Parameter Set", cosmo_set); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Random Generator", rng); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Mode Fixing", do_fixing); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Mode inversion", do_invert); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Baryons", do_baryons); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Baryons Relative Velocity", do_baryonsVrel); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Grid Resolution", L); if (tf == "CLASS") { double ztarget = cf_.get_value("cosmology", "ztarget"); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Target Redshift", ztarget); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Target Redshift", ztarget); } if (rng == "PANPHASIA") { std::string desc = cf_.get_value("random", "descriptor"); - HDFWriteGroupAttribute(fname_, "ICs_parameters", "Descriptor", desc); + HDFWriteGroupAttribute(this_fname_, "ICs_parameters", "Descriptor", desc); } }