<commit_before>#include "sn_sweeper.hpp"

#include <algorithm>
#include <string>

#include "pugixml.hpp"

#include "files.hpp"
#include "string_utils.hpp"


namespace {
    using namespace mocc;
    BC_Size_t boundary_helper( const Mesh &mesh ) {
        BC_Size_t bc_size = { (int)mesh.ny()*(int)mesh.nz(),
                              (int)mesh.nx()*(int)mesh.nz(),
                              (int)mesh.nx()*(int)mesh.ny() };
        return bc_size;
    }
}


namespace mocc {
namespace sn {
    SnSweeper::SnSweeper( const pugi::xml_node &input, const CoreMesh& mesh ):
            TransportSweeper( input ),
            timer_( RootTimer.new_timer("Sn Sweeper", true) ),
            timer_init_( timer_.new_timer("Initialization", true) ),
            timer_sweep_( timer_.new_timer("Sweep", false) ),
            mesh_( mesh ),
            bc_type_( mesh.boundary() ),
            flux_1g_( ),
            xstr_( mesh.n_pin() ),
            bc_in_( mesh.mat_lib().n_group(), ang_quad_, bc_type_,
                    boundary_helper(mesh) ),
            bc_out_( 1, ang_quad_, bc_type_, boundary_helper(mesh) ),
            gs_boundary_( true )
    {
        LogFile << "Constructing a base Sn sweeper" << std::endl;

        // Set up the cross-section mesh. If there is <data> specified, try to
        // use that, otherwise generate volume-weighted cross sections
        if( input.child("data").empty() ) {
            xs_mesh_ = SP_XSMesh_t( new XSMeshHomogenized(mesh) );
        } else {
            try {
                xs_mesh_ = SP_XSMesh_t( new XSMeshHomogenized(mesh, input) );
            }
            catch( Exception e ) {
                std::cerr << e.what() << std::endl;
                throw EXCEPT("Failed to create XSMesh for Sn Sweeper.");
            }
        }

        core_mesh_ = &mesh;
        n_reg_ = mesh.n_pin();
        n_group_ = xs_mesh_->n_group();
        flux_.resize( n_reg_, n_group_ );
        flux_old_.resize( n_reg_, n_group_ );
        vol_.resize( n_reg_ );

        // Set the mesh volumes. Same as the pin volumes
        int ipin = 0;
        for( auto &pin: mesh_ ) {
            int i = mesh_.coarse_cell( mesh_.pin_position(ipin) );
            vol_[i] = pin->vol();
            ipin++;
        }

        // Make sure we have input from the XML
        if( input.empty() ) {
            throw EXCEPT("No input specified to initialize Sn sweeper.");
        }

        // Parse the number of inner iterations
        int int_in = input.attribute("n_inner").as_int(-1);
        if( int_in < 0 ) {
            throw EXCEPT("Invalid number of inner iterations specified "
                    "(n_inner).");
        }
        n_inner_ = int_in;

        // Try to read boundary update option
        if( !input.attribute("boundary_update").empty() ) {
            std::string in_string =
                input.attribute("boundary_update").value();
            sanitize(in_string);

            if( (in_string == "gs") || (in_string == "gauss-seidel") ) {
                gs_boundary_ = true;
            } else if ( (in_string == "jacobi") || (in_string == "j") ) {
                gs_boundary_ = false;
            } else {
                throw EXCEPT("Unrecognized option for BC update!");
            }

            // For now, the BC doesnt support parallel boundary updates, so
            // disable Gauss-Seidel boundary update if we are using multiple
            // threads.
            /// \todo Add support for multi-threaded G-S boundary update in Sn
            if( (omp_get_max_threads() > 1) && gs_boundary_ ) {
                gs_boundary_ = false;
                LogScreen << "WARNING: Disabling Gauss-Seidel boundary update "
                    "in parallel Sn" << std::endl;
            }
        }

        timer_.toc();
        timer_init_.toc();

        return;
    }

    void SnSweeper::output( H5Node &node ) const {
        auto dims = mesh_.dimensions();
        std::reverse( dims.begin(), dims.end() );

        // Make a group in the file to store the flux
        node.create_group("flux");

        ArrayB2 flux = this->get_pin_flux();
        Normalize( flux.begin(), flux.end() );

        for( unsigned int ig=0; ig<n_group_; ig++ ) {<commit_msg>Fix bug in Sn bc update restrictions for OpenMP<commit_after>#include "sn_sweeper.hpp"

#include <algorithm>
#include <string>

#include "pugixml.hpp"

#include "files.hpp"
#include "string_utils.hpp"


namespace {
    using namespace mocc;
    BC_Size_t boundary_helper( const Mesh &mesh ) {
        BC_Size_t bc_size = { (int)mesh.ny()*(int)mesh.nz(),
                              (int)mesh.nx()*(int)mesh.nz(),
                              (int)mesh.nx()*(int)mesh.ny() };
        return bc_size;
    }
}


namespace mocc {
namespace sn {
    SnSweeper::SnSweeper( const pugi::xml_node &input, const CoreMesh& mesh ):
            TransportSweeper( input ),
            timer_( RootTimer.new_timer("Sn Sweeper", true) ),
            timer_init_( timer_.new_timer("Initialization", true) ),
            timer_sweep_( timer_.new_timer("Sweep", false) ),
            mesh_( mesh ),
            bc_type_( mesh.boundary() ),
            flux_1g_( ),
            xstr_( mesh.n_pin() ),
            bc_in_( mesh.mat_lib().n_group(), ang_quad_, bc_type_,
                    boundary_helper(mesh) ),
            bc_out_( 1, ang_quad_, bc_type_, boundary_helper(mesh) ),
            gs_boundary_( true )
    {
        LogFile << "Constructing a base Sn sweeper" << std::endl;

        // Set up the cross-section mesh. If there is <data> specified, try to
        // use that, otherwise generate volume-weighted cross sections
        if( input.child("data").empty() ) {
            xs_mesh_ = SP_XSMesh_t( new XSMeshHomogenized(mesh) );
        } else {
            try {
                xs_mesh_ = SP_XSMesh_t( new XSMeshHomogenized(mesh, input) );
            }
            catch( Exception e ) {
                std::cerr << e.what() << std::endl;
                throw EXCEPT("Failed to create XSMesh for Sn Sweeper.");
            }
        }

        core_mesh_ = &mesh;
        n_reg_ = mesh.n_pin();
        n_group_ = xs_mesh_->n_group();
        flux_.resize( n_reg_, n_group_ );
        flux_old_.resize( n_reg_, n_group_ );
        vol_.resize( n_reg_ );

        // Set the mesh volumes. Same as the pin volumes
        int ipin = 0;
        for( auto &pin: mesh_ ) {
            int i = mesh_.coarse_cell( mesh_.pin_position(ipin) );
            vol_[i] = pin->vol();
            ipin++;
        }

        // Make sure we have input from the XML
        if( input.empty() ) {
            throw EXCEPT("No input specified to initialize Sn sweeper.");
        }

        // Parse the number of inner iterations
        int int_in = input.attribute("n_inner").as_int(-1);
        if( int_in < 0 ) {
            throw EXCEPT("Invalid number of inner iterations specified "
                    "(n_inner).");
        }
        n_inner_ = int_in;

        // Try to read boundary update option
        if( !input.attribute("boundary_update").empty() ) {
            std::string in_string =
                input.attribute("boundary_update").value();
            sanitize(in_string);

            if( (in_string == "gs") || (in_string == "gauss-seidel") ) {
                gs_boundary_ = true;
            } else if ( (in_string == "jacobi") || (in_string == "j") ) {
                gs_boundary_ = false;
            } else {
                throw EXCEPT("Unrecognized option for BC update!");
            }
        }
        // For now, the BC doesnt support parallel boundary updates, so
        // disable Gauss-Seidel boundary update if we are using multiple
        // threads.
        /// \todo Add support for multi-threaded G-S boundary update in Sn
        LogScreen << omp_get_max_threads() << " " << gs_boundary_ << std::endl;
        if( (omp_get_max_threads() > 1) && gs_boundary_ ) {
            gs_boundary_ = false;
            LogScreen << "WARNING: Disabling Gauss-Seidel boundary update "
                "in parallel Sn" << std::endl;
        }

        timer_.toc();
        timer_init_.toc();

        return;
    }

    void SnSweeper::output( H5Node &node ) const {
        auto dims = mesh_.dimensions();
        std::reverse( dims.begin(), dims.end() );

        // Make a group in the file to store the flux
        node.create_group("flux");

        ArrayB2 flux = this->get_pin_flux();
        Normalize( flux.begin(), flux.end() );

        for( unsigned int ig=0; ig<n_group_; ig++ ) {
{'fraction_non_alphanumeric': 0.12288481736492006, 'fraction_numerical': 0.0021005951686311124, 'mean_word_length': 1.8043193717277486, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4127578', 'n_tokens_mistral': 2630, 'n_tokens_neox': 2503, 'n_words': 646}