/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2011-2013 by M. Ferrero, O. Parcollet * * TRIQS 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. * * TRIQS 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 * TRIQS. If not, see . * ******************************************************************************/ #pragma once #include #include #include #include #include #include "./mc_measure_aux_set.hpp" #include "./mc_measure_set.hpp" #include "./mc_move_set.hpp" #include "./mc_basic_step.hpp" #include "./random_generator.hpp" namespace triqs { namespace mc_tools { /** * \brief Generic Monte Carlo class. */ template > class mc_generic { public: /** * Constructor from a set of parameters */ mc_generic(uint64_t N_Cycles, uint64_t Length_Cycle, uint64_t N_Warmup_Cycles, std::string Random_Name, int Random_Seed, int Verbosity, std::function AfterCycleDuty = std::function() ) : RandomGenerator(Random_Name, Random_Seed), AllMoves(RandomGenerator), AllMeasures(),AllMeasuresAux(), report(&std::cout, Verbosity), Length_MC_Cycle(Length_Cycle), NWarmIterations(N_Warmup_Cycles), NCycles(N_Cycles), after_cycle_duty(AfterCycleDuty), sign_av(0) {} /** * Constructor from a dictionnary * \param[in] P dictionary parameters * \param[in] AfterCycleDuty a function bool() to be called after each QMC cycle */ mc_generic(utility::parameters const & P, std::function AfterCycleDuty = std::function() ) : RandomGenerator(std::string(P["random_name"]), long(P["random_seed"])), report(&std::cout,int(P["verbosity"])), AllMoves(RandomGenerator), AllMeasures(),AllMeasuresAux(), Length_MC_Cycle(long(P["length_cycle"])), /// NOT NICE THIS EXPLICIT CAST : no unsigned in parameters, really ?? NWarmIterations(long(P["n_warmup_cycles"])), NCycles(long(P["n_cycles"])), after_cycle_duty(AfterCycleDuty), sign_av(0) {} /** * Register move M with its probability of being proposed. * NB : the proposition_probability needs to be >0 but does not need to be * normalized. Normalization is automatically done with all the added moves * before starting the run */ template void add_move (MoveType && M, std::string name, double proposition_probability = 1.0) { static_assert( !std::is_pointer::value, "add_move in mc_generic takes ONLY values !"); AllMoves.add(std::forward(M), name, proposition_probability); } /** * Register the Measure M */ template void add_measure (MeasureType && M, std::string name) { static_assert( !std::is_pointer::value, "add_measure in mc_generic takes ONLY values !"); AllMeasures.insert(std::forward(M), name); } /** * Register the precomputation */ template void add_measure_aux(std::shared_ptr p) { AllMeasuresAux.emplace_back(p); } /// get the average sign (to be called after collect_results) MCSignType average_sign() const { return sign_av; } /// get the current percents done uint64_t percent() const { return done_percent; } // An access to the random number generator random_generator & rng(){ return RandomGenerator;} /// Start the Monte Carlo bool start(MCSignType sign_init, std::function const & stop_callback) { assert(stop_callback); Timer.start(); sign = sign_init; done_percent = 0; nmeasures = 0; sum_sign = 0; bool stop_it=false, finished = false; uint64_t NCycles_tot = NCycles+ NWarmIterations; report << std::endl << std::flush; for (NC =0; !stop_it; ++NC) { for (uint64_t k=1; (k<=Length_MC_Cycle); k++) { MCStepType::do_it(AllMoves,RandomGenerator,sign); } if (after_cycle_duty) {after_cycle_duty();} if (thermalized()) { nmeasures++; sum_sign += sign; for (auto &x : AllMeasuresAux) x(); AllMeasures.accumulate(sign); } // recompute fraction done uint64_t dp = uint64_t(floor( ( NC*100.0) / (NCycles_tot-1))); if (dp>done_percent) { done_percent=dp; report << done_percent; report<<"%; "; report <= NCycles_tot -1) || converged () ); stop_it = (stop_callback() || finished); } report << std::endl << std::endl << std::flush; Timer.stop(); return finished; } /// Reduce the results of the measures, and reports some statistics void collect_results(boost::mpi::communicator const & c) { uint64_t nmeasures_tot; MCSignType sum_sign_tot; boost::mpi::reduce(c, nmeasures, nmeasures_tot, std::plus(), 0); boost::mpi::reduce(c, sum_sign, sum_sign_tot, std::plus(), 0); report(3) << "[Node "< MeasureType & get_measure(std::string const & name) { return AllMeasures.template get_measure (name); } template MeasureType const & get_measure(std::string const & name) const { return AllMeasures.template get_measure (name); } template MoveType & get_move (std::string const & name) { return AllMoves.template get_move (name); } template MoveType const & get_move (std::string const & name) const { return AllMoves.template get_move (name); } /// HDF5 interface friend void h5_write (h5::group g, std::string const & name, mc_generic const & mc){ auto gr = g.create_group(name); h5_write(gr,"moves", mc.AllMoves); h5_write(gr,"measures", mc.AllMeasures); h5_write(gr,"length_monte_carlo_cycle", mc.Length_MC_Cycle); h5_write(gr,"number_cycle_requested", mc.NCycles); h5_write(gr,"number_warming_cycle_requested", mc.NWarmIterations); h5_write(gr,"number_cycle_done", mc.NC); h5_write(gr,"number_measure_done", mc.nmeasures); h5_write(gr,"sign", mc.sign); h5_write(gr,"sum_sign", mc.sum_sign); } /// HDF5 interface friend void h5_read (h5::group g, std::string const & name, mc_generic & mc){ auto gr = g.open_group(name); h5_read(gr,"moves", mc.AllMoves); h5_read(gr,"measures", mc.AllMeasures); h5_read(gr,"length_monte_carlo_cycle", mc.Length_MC_Cycle); h5_read(gr,"number_cycle_requested", mc.NCycles); h5_read(gr,"number_warming_cycle_requested", mc.NWarmIterations); h5_read(gr,"number_cycle_done", mc.NC); h5_read(gr,"number_measure_done", mc.nmeasures); h5_read(gr,"sign", mc.sign); h5_read(gr,"sum_sign", mc.sum_sign); } private: random_generator RandomGenerator; move_set AllMoves; measure_set AllMeasures; std::vector AllMeasuresAux; utility::report_stream report; uint64_t Length_MC_Cycle;/// Length of one Monte-Carlo cycle between 2 measures uint64_t NWarmIterations, NCycles; uint64_t nmeasures; MCSignType sum_sign; utility::timer Timer; std::function after_cycle_duty; MCSignType sign, sign_av; uint64_t NC,done_percent;// NC = number of the cycle bool thermalized() const { return (NC>= NWarmIterations);} bool converged() const { return false;} }; /// Retrieve a Measure given name and type. NB : the type is checked at runtime template M & get_measure(mc_generic & s, std::string const & name) { return s.template get_measure (name); } template M const & get_measure(mc_generic const & s, std::string const & name) { return s.template get_measure (name); } /// Retrieve a Measure given name and type. NB : the type is checked at runtime template M * get_measure_aux(mc_generic & s, std::string const & name) { return s.template get_measure_aux (name); } template M const * get_measure_aux(mc_generic const & s, std::string const & name) { return s.template get_measure_aux (name); } /// Retrieve a Move given name and type. NB : the type is checked at runtime template M & get_move(mc_generic & s, std::string const & name) { return s.template get_move (name); } template M const & get_move(mc_generic const & s, std::string const & name) { return s.template get_move (name); } }}// end namespace