Merge branch 'maint'
[hoomd-blue.git] / libhoomd / system / System.cc
blob90c404037032240f2f6ab94407124be203a17415
1 /*
2 Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
3 (HOOMD-blue) Open Source Software License Copyright 2009-2014 The Regents of
4 the University of Michigan All rights reserved.
6 HOOMD-blue may contain modifications ("Contributions") provided, and to which
7 copyright is held, by various Contributors who have granted The Regents of the
8 University of Michigan the right to modify and/or distribute such Contributions.
10 You may redistribute, use, and create derivate works of HOOMD-blue, in source
11 and binary forms, provided you abide by the following conditions:
13 * Redistributions of source code must retain the above copyright notice, this
14 list of conditions, and the following disclaimer both in the code and
15 prominently in any materials provided with the distribution.
17 * Redistributions in binary form must reproduce the above copyright notice, this
18 list of conditions, and the following disclaimer in the documentation and/or
19 other materials provided with the distribution.
21 * All publications and presentations based on HOOMD-blue, including any reports
22 or published results obtained, in whole or in part, with HOOMD-blue, will
23 acknowledge its use according to the terms posted at the time of submission on:
24 http://codeblue.umich.edu/hoomd-blue/citations.html
26 * Any electronic documents citing HOOMD-Blue will link to the HOOMD-Blue website:
27 http://codeblue.umich.edu/hoomd-blue/
29 * Apart from the above required attributions, neither the name of the copyright
30 holder nor the names of HOOMD-blue's contributors may be used to endorse or
31 promote products derived from this software without specific prior written
32 permission.
34 Disclaimer
36 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' AND
37 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR ANY
39 WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.
41 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
43 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
46 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
47 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 // Maintainer: joaander
52 /*! \file System.cc
53 \brief Defines the System class
56 #ifdef WIN32
57 #pragma warning( push )
58 #pragma warning( disable : 4103 4244 )
59 #endif
61 #include "System.h"
62 #include "SignalHandler.h"
64 #include <boost/python.hpp>
65 using namespace boost::python;
67 #include <stdexcept>
69 #ifdef ENABLE_MPI
70 #include "Communicator.h"
71 #endif
73 using namespace std;
75 /*! \param sysdef SystemDefinition for the system to be simulated
76 \param initial_tstep Initial time step of the simulation
78 \post The System is constructed with no attached computes, updaters,
79 analyzers or integrators. Profiling defaults to disabled and
80 statistics are printed every 10 seconds.
82 System::System(boost::shared_ptr<SystemDefinition> sysdef, unsigned int initial_tstep)
83 : m_sysdef(sysdef), m_start_tstep(initial_tstep), m_end_tstep(0), m_cur_tstep(initial_tstep),
84 m_last_status_time(0), m_last_status_tstep(initial_tstep), m_quiet_run(false),
85 m_profile(false), m_stats_period(10)
87 // sanity check
88 assert(m_sysdef);
89 m_exec_conf = m_sysdef->getParticleData()->getExecConf();
91 #ifdef ENABLE_MPI
92 // the initial time step is defined on the root processor
93 if (m_sysdef->getParticleData()->getDomainDecomposition())
95 bcast(m_start_tstep, 0, m_exec_conf->getMPICommunicator());
96 bcast(m_cur_tstep, 0, m_exec_conf->getMPICommunicator());
97 bcast(m_last_status_tstep, 0, m_exec_conf->getMPICommunicator());
99 #endif
102 /*! \param analyzer Shared pointer to the Analyzer to add
103 \param name A unique name to identify the Analyzer by
104 \param period Analyzer::analyze() will be called for every time step that is a multiple
105 of \a period.
107 All Analyzers will be called, in the order that they are added, and with the specified
108 \a period during time step calculations performed when run() is called. An analyzer
109 can be prevented from running in future runs by removing it (removeAnalyzer()) before
110 calling run()
112 void System::addAnalyzer(boost::shared_ptr<Analyzer> analyzer, const std::string& name, unsigned int period)
114 // sanity check
115 assert(analyzer);
116 assert(period != 0);
118 // first check that the name is unique
119 vector<analyzer_item>::iterator i;
120 for (i = m_analyzers.begin(); i != m_analyzers.end(); ++i)
122 if (i->m_name == name)
124 m_exec_conf->msg->error() << "Analyzer " << name << " already exists" << endl;
125 throw runtime_error("System: cannot add Analyzer");
129 // if we get here, we can add it
130 m_analyzers.push_back(analyzer_item(analyzer, name, period, m_cur_tstep));
133 /*! \param name Name of the Analyzer to find in m_analyzers
134 \returns An iterator into m_analyzers of the found Analyzer
136 std::vector<System::analyzer_item>::iterator System::findAnalyzerItem(const std::string &name)
138 // search for the analyzer
139 vector<analyzer_item>::iterator i;
140 for (i = m_analyzers.begin(); i != m_analyzers.end(); ++i)
142 if (i->m_name == name)
144 return i;
148 m_exec_conf->msg->error() << "Analyzer " << name << " not found" << endl;
149 throw runtime_error("System: cannot find Analyzer");
150 // dummy return
151 return m_analyzers.begin();
154 /*! \param name Name of the Analyzer to be removed
155 \sa addAnalyzer()
157 void System::removeAnalyzer(const std::string& name)
159 vector<analyzer_item>::iterator i = findAnalyzerItem(name);
160 m_analyzers.erase(i);
163 /*! \param name Name of the Analyzer to retrieve
164 \returns A shared pointer to the requested Analyzer
166 boost::shared_ptr<Analyzer> System::getAnalyzer(const std::string& name)
168 vector<System::analyzer_item>::iterator i = findAnalyzerItem(name);
169 return i->m_analyzer;
172 /*! \param name Name of the Analyzer to modify
173 \param period New period to set
175 void System::setAnalyzerPeriod(const std::string& name, unsigned int period)
177 // sanity check
178 assert(period != 0);
180 vector<System::analyzer_item>::iterator i = findAnalyzerItem(name);
181 i->setPeriod(period, m_cur_tstep);
184 /*! \param name Name of the Updater to modify
185 \param update_func A python callable function taking one argument that returns an integer value of the next time step to analyze at
187 void System::setAnalyzerPeriodVariable(const std::string& name, boost::python::object update_func)
189 vector<System::analyzer_item>::iterator i = findAnalyzerItem(name);
190 i->setVariablePeriod(update_func, m_cur_tstep);
194 /*! \param name Name of the Analyzer to get the period of
195 \returns Period of the Analyzer
197 unsigned int System::getAnalyzerPeriod(const std::string& name)
199 vector<System::analyzer_item>::iterator i = findAnalyzerItem(name);
200 return i->m_period;
204 // -------------- Updater get/set methods
205 /*! \param name Name of the Updater to find in m_updaters
206 \returns An iterator into m_updaters of the found Updater
208 std::vector<System::updater_item>::iterator System::findUpdaterItem(const std::string &name)
210 // search for the analyzer
211 vector<System::updater_item>::iterator i;
212 for (i = m_updaters.begin(); i != m_updaters.end(); ++i)
214 if (i->m_name == name)
216 return i;
220 m_exec_conf->msg->error() << "Updater " << name << " not found" << endl;
221 throw runtime_error("System: cannot find Updater");
222 // dummy return
223 return m_updaters.begin();
227 /*! \param updater Shared pointer to the Updater to add
228 \param name A unique name to identify the Updater by
229 \param period Updater::update() will be called for every time step that is a multiple
230 of \a period.
232 All Updaters will be called, in the order that they are added, and with the specified
233 \a period during time step calculations performed when run() is called. An updater
234 can be prevented from running in future runs by removing it (removeUpdater()) before
235 calling run()
237 void System::addUpdater(boost::shared_ptr<Updater> updater, const std::string& name, unsigned int period)
239 // sanity check
240 assert(updater);
241 assert(period != 0);
243 // first check that the name is unique
244 vector<updater_item>::iterator i;
245 for (i = m_updaters.begin(); i != m_updaters.end(); ++i)
247 if (i->m_name == name)
249 m_exec_conf->msg->error() << "Updater " << name << " already exists" << endl;
250 throw runtime_error("System: cannot add Updater");
254 // if we get here, we can add it
255 m_updaters.push_back(updater_item(updater, name, period, m_cur_tstep));
258 /*! \param name Name of the Updater to be removed
259 \sa addUpdater()
261 void System::removeUpdater(const std::string& name)
263 vector<updater_item>::iterator i = findUpdaterItem(name);
264 m_updaters.erase(i);
267 /*! \param name Name of the Updater to retrieve
268 \returns A shared pointer to the requested Updater
270 boost::shared_ptr<Updater> System::getUpdater(const std::string& name)
272 vector<System::updater_item>::iterator i = findUpdaterItem(name);
273 return i->m_updater;
276 /*! \param name Name of the Updater to modify
277 \param period New period to set
279 void System::setUpdaterPeriod(const std::string& name, unsigned int period)
281 // sanity check
282 assert(period != 0);
284 vector<System::updater_item>::iterator i = findUpdaterItem(name);
285 i->setPeriod(period, m_cur_tstep);
288 /*! \param name Name of the Updater to modify
289 \param update_func A python callable function taking one argument that returns an integer value of the next time step to update at
291 void System::setUpdaterPeriodVariable(const std::string& name, boost::python::object update_func)
293 vector<System::updater_item>::iterator i = findUpdaterItem(name);
294 i->setVariablePeriod(update_func, m_cur_tstep);
297 /*! \param name Name of the Updater to get the period of
298 \returns Period of the Updater
300 unsigned int System::getUpdaterPeriod(const std::string& name)
302 vector<System::updater_item>::iterator i = findUpdaterItem(name);
303 return i->m_period;
307 // -------------- Compute get/set methods
309 /*! \param compute Shared pointer to the Compute to add
310 \param name Unique name to assign to this Compute
312 Computes are added to the System only as a convenience for naming,
313 saving to restart files, and to activate profiling. They are never
314 directly called by the system.
316 void System::addCompute(boost::shared_ptr<Compute> compute, const std::string& name)
318 // sanity check
319 assert(compute);
321 // check if the name is unique
322 map< string, boost::shared_ptr<Compute> >::iterator i = m_computes.find(name);
323 if (i == m_computes.end())
324 m_computes[name] = compute;
325 else
327 m_exec_conf->msg->error() << "Compute " << name << " already exists" << endl;
328 throw runtime_error("System: cannot add compute");
333 /*! \param name Name of the Compute to remove
335 void System::removeCompute(const std::string& name)
337 // see if the compute exists to be removed
338 map< string, boost::shared_ptr<Compute> >::iterator i = m_computes.find(name);
339 if (i == m_computes.end())
341 m_exec_conf->msg->error() << "Compute " << name << " not found" << endl;
342 throw runtime_error("System: cannot remove compute");
344 else
345 m_computes.erase(i);
348 /*! \param name Name of the compute to access
349 \returns A shared pointer to the Compute as provided previosly by addCompute()
351 boost::shared_ptr<Compute> System::getCompute(const std::string& name)
353 // see if the compute even exists first
354 map< string, boost::shared_ptr<Compute> >::iterator i = m_computes.find(name);
355 if (i == m_computes.end())
357 m_exec_conf->msg->error() << "Compute " << name << " not found" << endl;
358 throw runtime_error("System: cannot retrieve compute");
359 return boost::shared_ptr<Compute>();
361 else
362 return m_computes[name];
365 // -------------- Integrator methods
367 /*! \param integrator Updater to set as the Integrator for this System
369 void System::setIntegrator(boost::shared_ptr<Integrator> integrator)
371 m_integrator = integrator;
374 /*! \returns A shared pointer to the Integrator for this System
376 boost::shared_ptr<Integrator> System::getIntegrator()
378 return m_integrator;
381 #ifdef ENABLE_MPI
382 // -------------- Methods for communication
383 void System::setCommunicator(boost::shared_ptr<Communicator> comm)
385 m_comm = comm;
387 #endif
389 // -------------- Methods for running the simulation
391 /*! \param nsteps Number of simulation steps to run
392 \param limit_hours Number of hours to run for (0.0 => infinity)
393 \param cb_frequency Modulus of timestep number when to call the callback (0 = at end)
394 \param callback Python function to be called periodically during run.
395 \param limit_multiple Only allow \a limit_hours to break the simulation at steps that are a multiple of
396 \a limit_multiple .
398 During each simulation step, all added Analyzers and
399 Updaters are called, then the Integrator to move the system
400 forward one step in time. This is repeated \a nsteps times,
401 or until a \a limit_hours hours have passed.
403 run() can be called as many times as the user wishes:
404 each time, it will continue at the time step where it left off.
407 void System::run(unsigned int nsteps, unsigned int cb_frequency,
408 boost::python::object callback, double limit_hours,
409 unsigned int limit_multiple)
412 m_start_tstep = m_cur_tstep;
413 m_end_tstep = m_cur_tstep + nsteps;
415 // initialize the last status time
416 int64_t initial_time = m_clk.getTime();
417 m_last_status_time = initial_time;
418 setupProfiling();
420 // preset the flags before the run loop so that any analyzers/updaters run on step 0 have the info they need
421 // but set the flags before prepRun, as prepRun may remove some flags that it cannot generate on the first step
422 m_sysdef->getParticleData()->setFlags(determineFlags(m_cur_tstep));
424 #ifdef ENABLE_MPI
425 if (m_comm)
427 //! Set communicator in all Updaters
428 vector<updater_item>::iterator updater;
429 for (updater = m_updaters.begin(); updater != m_updaters.end(); ++updater)
430 updater->m_updater->setCommunicator(m_comm);
432 // Set communicator in all Computes
433 map< string, boost::shared_ptr<Compute> >::iterator compute;
434 for (compute = m_computes.begin(); compute != m_computes.end(); ++compute)
435 compute->second->setCommunicator(m_comm);
437 // Set communicator in all Analyzers
438 vector<analyzer_item>::iterator analyzer;
439 for (analyzer = m_analyzers.begin(); analyzer != m_analyzers.end(); ++analyzer)
440 analyzer->m_analyzer->setCommunicator(m_comm);
442 // Set communicator in Integrator
443 if (m_integrator)
444 m_integrator->setCommunicator(m_comm);
446 #endif
448 resetStats();
450 // Prepare the run
451 if (!m_integrator)
452 m_exec_conf->msg->warning() << "You are running without an integrator" << endl;
453 else
454 m_integrator->prepRun(m_cur_tstep);
456 #ifdef ENABLE_MPI
457 if (m_comm)
459 // make sure we start off with a migration substep, so that
460 // any old ghost particles are invalidated
461 m_comm->forceMigrate();
463 #endif
465 // catch exceptions during simulation
468 // handle time steps
469 for ( ; m_cur_tstep < m_end_tstep; m_cur_tstep++)
471 // check the clock and output a status line if needed
472 uint64_t cur_time = m_clk.getTime();
474 // check if the time limit has exceeded
475 if (limit_hours != 0.0f)
477 if (m_cur_tstep % limit_multiple == 0)
479 unsigned int end_run = 0;
480 int64_t time_limit = int64_t(limit_hours * 3600.0 * 1e9);
481 if (int64_t(cur_time) - initial_time > time_limit)
482 end_run = 1;
484 #ifdef ENABLE_MPI
485 // if any processor wants to end the run, end it on all processors
486 if (m_comm)
487 MPI_Allreduce(MPI_IN_PLACE, &end_run, 1, MPI_INT, MPI_SUM, m_exec_conf->getMPICommunicator());
488 #endif
490 if (end_run)
492 m_exec_conf->msg->notice(2) << "Ending run at time step " << m_cur_tstep << " as " << limit_hours << " hours have passed" << endl;
493 break;
497 // execute python callback, if present and needed
498 // a negative return value indicates immediate end of run.
499 if (callback && (cb_frequency > 0) && (m_cur_tstep % cb_frequency == 0))
501 boost::python::object rv = callback(m_cur_tstep);
502 extract<int> extracted_rv(rv);
503 if (extracted_rv.check() && extracted_rv() < 0)
505 m_exec_conf->msg->notice(2) << "End of run requested by python callback at step "
506 << m_cur_tstep << " / " << m_end_tstep << endl;
507 break;
511 if (cur_time - m_last_status_time >= uint64_t(m_stats_period)*uint64_t(1000000000))
513 if (!m_quiet_run)
514 generateStatusLine();
515 m_last_status_time = cur_time;
516 m_last_status_tstep = m_cur_tstep;
518 // check for any CUDA errors
519 #ifdef ENABLE_CUDA
520 if (m_exec_conf->isCUDAEnabled())
522 CHECK_CUDA_ERROR();
524 #endif
527 // execute analyzers
528 vector<analyzer_item>::iterator analyzer;
529 for (analyzer = m_analyzers.begin(); analyzer != m_analyzers.end(); ++analyzer)
531 if (analyzer->shouldExecute(m_cur_tstep))
532 analyzer->m_analyzer->analyze(m_cur_tstep);
535 // execute updaters
536 vector<updater_item>::iterator updater;
537 for (updater = m_updaters.begin(); updater != m_updaters.end(); ++updater)
539 if (updater->shouldExecute(m_cur_tstep))
540 updater->m_updater->update(m_cur_tstep);
543 // look ahead to the next time step and see which analyzers and updaters will be executed
544 // or together all of their requested PDataFlags to determine the flags to set for this time step
545 m_sysdef->getParticleData()->setFlags(determineFlags(m_cur_tstep+1));
547 // execute the integrator
548 if (m_integrator)
549 m_integrator->update(m_cur_tstep);
551 // quit if cntrl-C was pressed
552 if (g_sigint_recvd)
554 g_sigint_recvd = 0;
555 return;
558 } // end try
559 catch (std::exception const & ex)
561 #ifdef ENABLE_MPI
562 if (m_sysdef->getParticleData()->getDomainDecomposition() && m_exec_conf->msg->isLocked())
564 // tear down other ranks in a controlled way, but only if we are the rank that displayed an error
565 // so that eventual error messages are flushed correctly
566 if (m_exec_conf->msg->hasLock())
567 MPI_Abort(m_exec_conf->getMPICommunicator(), MPI_ERR_OTHER);
568 else
569 // otherwise just wait
570 MPI_Barrier(m_exec_conf->getMPICommunicator());
572 else
573 #endif
575 // re-throw original exception
576 throw ex;
580 #ifdef ENABLE_MPI
581 if (m_comm)
583 // migrate particles back into domains and remove all ghost atoms
584 m_comm->migrateParticles();
586 #endif
588 // generate a final status line
589 if (!m_quiet_run)
590 generateStatusLine();
591 m_last_status_tstep = m_cur_tstep;
593 // execute python callback, if present and needed
594 if (callback && (cb_frequency == 0))
596 callback(m_cur_tstep);
599 // calculate averate TPS
600 Scalar TPS = Scalar(m_cur_tstep - m_start_tstep) / Scalar(m_clk.getTime() - initial_time) * Scalar(1e9);
602 m_last_TPS = TPS;
604 #ifdef ENABLE_MPI
605 // make sure all ranks return the same TPS
606 if (m_comm)
607 bcast(m_last_TPS, 0, m_exec_conf->getMPICommunicator());
608 #endif
610 if (!m_quiet_run)
611 m_exec_conf->msg->notice(1) << "Average TPS: " << m_last_TPS << endl;
613 // write out the profile data
614 if (m_profiler)
615 m_exec_conf->msg->notice(1) << *m_profiler;
617 if (!m_quiet_run)
618 printStats();
622 /*! \param enable Set to true to enable profiling during calls to run()
624 void System::enableProfiler(bool enable)
626 m_profile = enable;
629 /*! \param logger Logger to register computes and updaters with
630 All computes and updaters registered with the system are also registerd with the logger.
632 void System::registerLogger(boost::shared_ptr<Logger> logger)
634 // set the profiler on everything
635 if (m_integrator)
636 logger->registerUpdater(m_integrator);
638 // updaters
639 vector<updater_item>::iterator updater;
640 for (updater = m_updaters.begin(); updater != m_updaters.end(); ++updater)
641 logger->registerUpdater(updater->m_updater);
643 // computes
644 map< string, boost::shared_ptr<Compute> >::iterator compute;
645 for (compute = m_computes.begin(); compute != m_computes.end(); ++compute)
646 logger->registerCompute(compute->second);
649 /*! \param seconds Period between statistics ouptut in seconds
651 void System::setStatsPeriod(unsigned int seconds)
653 m_stats_period = seconds;
656 /*! \param enable Enable/disable autotuning
657 \param period period (approximate) in time steps when returning occurs
659 void System::setAutotunerParams(bool enabled, unsigned int period)
661 // set the autotuner parameters on everything
662 if (m_integrator)
663 m_integrator->setAutotunerParams(enabled, period);
665 // analyzers
666 vector<analyzer_item>::iterator analyzer;
667 for (analyzer = m_analyzers.begin(); analyzer != m_analyzers.end(); ++analyzer)
668 analyzer->m_analyzer->setAutotunerParams(enabled, period);
670 // updaters
671 vector<updater_item>::iterator updater;
672 for (updater = m_updaters.begin(); updater != m_updaters.end(); ++updater)
673 updater->m_updater->setAutotunerParams(enabled, period);
675 // computes
676 map< string, boost::shared_ptr<Compute> >::iterator compute;
677 for (compute = m_computes.begin(); compute != m_computes.end(); ++compute)
678 compute->second->setAutotunerParams(enabled, period);
680 #ifdef ENABLE_MPI
681 if (m_comm)
682 m_comm->setAutotunerParams(enabled, period);
683 #endif
686 // --------- Steps in the simulation run implemented in helper functions
688 void System::setupProfiling()
690 if (m_profile)
691 m_profiler = boost::shared_ptr<Profiler>(new Profiler("Simulation"));
692 else
693 m_profiler = boost::shared_ptr<Profiler>();
695 // set the profiler on everything
696 if (m_integrator)
697 m_integrator->setProfiler(m_profiler);
698 m_sysdef->getParticleData()->setProfiler(m_profiler);
699 m_sysdef->getBondData()->setProfiler(m_profiler);
701 // analyzers
702 vector<analyzer_item>::iterator analyzer;
703 for (analyzer = m_analyzers.begin(); analyzer != m_analyzers.end(); ++analyzer)
704 analyzer->m_analyzer->setProfiler(m_profiler);
706 // updaters
707 vector<updater_item>::iterator updater;
708 for (updater = m_updaters.begin(); updater != m_updaters.end(); ++updater)
709 updater->m_updater->setProfiler(m_profiler);
711 // computes
712 map< string, boost::shared_ptr<Compute> >::iterator compute;
713 for (compute = m_computes.begin(); compute != m_computes.end(); ++compute)
714 compute->second->setProfiler(m_profiler);
716 #ifdef ENABLE_MPI
717 // communicator
718 if (m_comm)
719 m_comm->setProfiler(m_profiler);
720 #endif
723 void System::printStats()
725 m_exec_conf->msg->notice(1) << "---------" << endl;
726 // print the stats for everything
727 if (m_integrator)
728 m_integrator->printStats();
730 // analyzers
731 vector<analyzer_item>::iterator analyzer;
732 for (analyzer = m_analyzers.begin(); analyzer != m_analyzers.end(); ++analyzer)
733 analyzer->m_analyzer->printStats();
735 // updaters
736 vector<updater_item>::iterator updater;
737 for (updater = m_updaters.begin(); updater != m_updaters.end(); ++updater)
738 updater->m_updater->printStats();
740 // computes
741 map< string, boost::shared_ptr<Compute> >::iterator compute;
742 for (compute = m_computes.begin(); compute != m_computes.end(); ++compute)
743 compute->second->printStats();
746 void System::resetStats()
748 if (m_integrator)
749 m_integrator->resetStats();
751 // analyzers
752 vector<analyzer_item>::iterator analyzer;
753 for (analyzer = m_analyzers.begin(); analyzer != m_analyzers.end(); ++analyzer)
754 analyzer->m_analyzer->resetStats();
756 // updaters
757 vector<updater_item>::iterator updater;
758 for (updater = m_updaters.begin(); updater != m_updaters.end(); ++updater)
759 updater->m_updater->resetStats();
761 // computes
762 map< string, boost::shared_ptr<Compute> >::iterator compute;
763 for (compute = m_computes.begin(); compute != m_computes.end(); ++compute)
764 compute->second->resetStats();
767 void System::generateStatusLine()
769 // a status line consists of
770 // elapsed time
771 // current timestep / end time step
772 // time steps per second
773 // ETA
775 // elapsed time
776 int64_t cur_time = m_clk.getTime();
777 string t_elap = ClockSource::formatHMS(cur_time);
779 // time steps per second
780 Scalar TPS = Scalar(m_cur_tstep - m_last_status_tstep) / Scalar(cur_time - m_last_status_time) * Scalar(1e9);
782 // estimated time to go (base on current TPS)
783 string ETA = ClockSource::formatHMS(int64_t((m_end_tstep - m_cur_tstep) / TPS * Scalar(1e9)));
785 // write the line
786 m_exec_conf->msg->notice(1) << "Time " << t_elap << " | Step " << m_cur_tstep << " / " << m_end_tstep << " | TPS " << TPS << " | ETA " << ETA << endl;
789 /*! \param tstep Time step for which to determine the flags
791 The flags needed are determiend by peeking to \a tstep and then using bitwise or to combine all of the flags from the
792 analyzers and updaters that are to be executed on that step.
794 PDataFlags System::determineFlags(unsigned int tstep)
796 PDataFlags flags(0);
797 if (m_integrator)
798 flags = m_integrator->getRequestedPDataFlags();
800 vector<analyzer_item>::iterator analyzer;
801 for (analyzer = m_analyzers.begin(); analyzer != m_analyzers.end(); ++analyzer)
803 if (analyzer->peekExecute(tstep))
804 flags |= analyzer->m_analyzer->getRequestedPDataFlags();
807 vector<updater_item>::iterator updater;
808 for (updater = m_updaters.begin(); updater != m_updaters.end(); ++updater)
810 if (updater->peekExecute(tstep))
811 flags |= updater->m_updater->getRequestedPDataFlags();
814 return flags;
817 void export_System()
819 class_< System, boost::shared_ptr<System>, boost::noncopyable > ("System", init< boost::shared_ptr<SystemDefinition>, unsigned int >())
820 .def("addAnalyzer", &System::addAnalyzer)
821 .def("removeAnalyzer", &System::removeAnalyzer)
822 .def("getAnalyzer", &System::getAnalyzer)
823 .def("setAnalyzerPeriod", &System::setAnalyzerPeriod)
824 .def("setAnalyzerPeriodVariable", &System::setAnalyzerPeriodVariable)
825 .def("getAnalyzerPeriod", &System::getAnalyzerPeriod)
827 .def("addUpdater", &System::addUpdater)
828 .def("removeUpdater", &System::removeUpdater)
829 .def("getUpdater", &System::getUpdater)
830 .def("setUpdaterPeriod", &System::setUpdaterPeriod)
831 .def("setUpdaterPeriodVariable", &System::setUpdaterPeriodVariable)
832 .def("getUpdaterPeriod", &System::getUpdaterPeriod)
834 .def("addCompute", &System::addCompute)
835 .def("removeCompute", &System::removeCompute)
836 .def("getCompute", &System::getCompute)
838 .def("setIntegrator", &System::setIntegrator)
839 .def("getIntegrator", &System::getIntegrator)
841 .def("registerLogger", &System::registerLogger)
842 .def("setStatsPeriod", &System::setStatsPeriod)
843 .def("setAutotunerParams", &System::setAutotunerParams)
844 .def("enableProfiler", &System::enableProfiler)
845 .def("enableQuietRun", &System::enableQuietRun)
846 .def("run", &System::run)
848 .def("getLastTPS", &System::getLastTPS)
849 .def("getCurrentTimeStep", &System::getCurrentTimeStep)
850 #ifdef ENABLE_MPI
851 .def("setCommunicator", &System::setCommunicator)
852 .def("getCommunicator", &System::getCommunicator)
853 #endif
857 #ifdef WIN32
858 #pragma warning( pop )
859 #endif