| 860 | |
| 861 | extern bool user_requested_exit; |
| 862 | int Solver::call_monitors(BoutReal simtime, int iter, int NOUT) { |
| 863 | bool abort; |
| 864 | bout::globals::mpi->MPI_Allreduce(&user_requested_exit, &abort, 1, MPI_C_BOOL, MPI_LOR, |
| 865 | BoutComm::get()); |
| 866 | if (abort) { |
| 867 | NOUT = iter + 1; |
| 868 | } |
| 869 | if (mms) { |
| 870 | // Calculate MMS errors |
| 871 | calculate_mms_error(simtime); |
| 872 | } |
| 873 | |
| 874 | try { |
| 875 | // We need to write each time dimension a maximum of once per |
| 876 | // timestep. The set of unique time dimensions may be the same |
| 877 | // size or smaller than the set of monitors, so we need to keep |
| 878 | // track of the unique dimensions each timestep. |
| 879 | std::set<std::string> seen_time_dimensions; |
| 880 | |
| 881 | // Call monitors |
| 882 | for (const auto& monitor : monitors) { |
| 883 | if ((iter % monitor.monitor->period) == 0) { |
| 884 | // Call each monitor one by one |
| 885 | const int ret = |
| 886 | monitor.monitor->call(this, simtime, iter / monitor.monitor->period, |
| 887 | NOUT / monitor.monitor->period); |
| 888 | if (ret != 0) { |
| 889 | throw BoutException(_("Monitor signalled to quit (return code {})"), ret); |
| 890 | } |
| 891 | // Write the monitor's diagnostics to the main output file |
| 892 | Options monitor_dump; |
| 893 | monitor.monitor->outputVars(monitor_dump, monitor.time_dimension); |
| 894 | model->writeOutputFile(monitor_dump, monitor.time_dimension); |
| 895 | // This monitor's time dimension needs writing out |
| 896 | seen_time_dimensions.insert(monitor.time_dimension); |
| 897 | } |
| 898 | } |
| 899 | // Write all the unique time dimensions that were advanced this timestep |
| 900 | for (const auto& time_dimension : seen_time_dimensions) { |
| 901 | Options time_dump; |
| 902 | time_dump[time_dimension].assignRepeat(simtime, time_dimension); |
| 903 | model->writeOutputFile(time_dump, time_dimension); |
| 904 | } |
| 905 | |
| 906 | model->finishOutputTimestep(); |
| 907 | } catch (const BoutException& e) { |
| 908 | for (const auto& monitor : monitors) { |
| 909 | monitor.monitor->cleanup(); |
| 910 | } |
| 911 | output_error.write(_("Monitor signalled to quit (exception {})\n"), e.what()); |
| 912 | throw; |
| 913 | } |
| 914 | |
| 915 | // Check if any of the monitors has asked to quit |
| 916 | bout::globals::mpi->MPI_Allreduce(&user_requested_exit, &abort, 1, MPI_C_BOOL, MPI_LOR, |
| 917 | BoutComm::get()); |
| 918 | |
| 919 | if (iter == NOUT || abort) { |