Skip to content

Commit 12c5e2d

Browse files
authored
Merge pull request #2934 from boutproject/flush-frequency-netcdf
Add `output:flush_frequency` for `OptionsNetCDF`
2 parents 31df873 + 4c9b456 commit 12c5e2d

7 files changed

Lines changed: 84 additions & 59 deletions

File tree

.git-blame-ignore-revs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ c8f38049359170a34c915e209276238ea66b9a1e
1414
8d5cb39e03c2644715a50684f8cd0318b4e82676
1515
ec69e8838be2dde140a915e50506f8e1ce3cb534
1616
f2bc0488a298f136294c523bc5ab4086d090059b
17+
1b4707187a3a85126338303dc766280b8fb2dc56

include/bout/options_io.hxx

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
#pragma once
2+
3+
#ifndef OPTIONS_IO_H
4+
#define OPTIONS_IO_H
5+
6+
#include "bout/build_defines.hxx"
7+
#include "bout/generic_factory.hxx"
8+
#include "bout/options.hxx"
9+
10+
#include <memory>
11+
#include <string>
12+
13+
class Mesh;
14+
15+
namespace bout {
16+
117
/// Parent class for IO to binary files and streams
218
///
319
///
@@ -36,30 +52,14 @@
3652
///
3753
/// if mesh is omitted, no grid information is added.
3854
///
39-
40-
#pragma once
41-
42-
#ifndef OPTIONS_IO_H
43-
#define OPTIONS_IO_H
44-
45-
#include "bout/build_defines.hxx"
46-
#include "bout/generic_factory.hxx"
47-
#include "bout/mesh.hxx"
48-
#include "bout/options.hxx"
49-
50-
#include <memory>
51-
#include <string>
52-
53-
namespace bout {
54-
5555
class OptionsIO {
5656
public:
5757
/// No default constructor, as settings are required
5858
OptionsIO() = delete;
5959

6060
/// Constructor specifies the kind of file, and options to control
6161
/// the name of file, mode of operation etc.
62-
OptionsIO(Options&) {}
62+
OptionsIO(Options& /*unused*/) {}
6363

6464
virtual ~OptionsIO() = default;
6565

@@ -81,6 +81,9 @@ public:
8181
/// ADIOS: Indicate completion of an output step.
8282
virtual void verifyTimesteps() const = 0;
8383

84+
/// NetCDF: Flush file to disk
85+
virtual void flush() {}
86+
8487
/// Create an OptionsIO for I/O to the given file.
8588
/// This uses the default file type and default options.
8689
static std::unique_ptr<OptionsIO> create(const std::string& file);

include/bout/physicsmodel.hxx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class PhysicsModel;
4848
#include "bout/utils.hxx"
4949

5050
#include <chrono>
51+
#include <cstddef>
5152
#include <thread>
5253
#include <type_traits>
5354
#include <vector>
@@ -378,6 +379,9 @@ protected:
378379
PhysicsModel* model;
379380
};
380381

382+
/// Set timestep counter for flushing file
383+
void setFlushCounter(std::size_t iteration) { flush_counter = iteration; }
384+
381385
private:
382386
/// State for outputs
383387
Options output_options;
@@ -401,6 +405,10 @@ private:
401405
bool initialised{false};
402406
/// write restarts and pass outputMonitor method inside a Monitor subclass
403407
PhysicsModelMonitor modelMonitor{this};
408+
/// How often to flush to disk
409+
std::size_t flush_frequency{1};
410+
/// Current timestep counter
411+
std::size_t flush_counter{0};
404412
};
405413

406414
/*!

manual/sphinx/user_docs/bout_options.rst

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -554,42 +554,42 @@ may be useful anyway. See :ref:`sec-output` for more details.
554554
Input and Output
555555
----------------
556556

557-
The output (dump) files with time-history are controlled by settings
558-
in a section called output. Restart files contain a single
559-
time-slice, and are controlled by a section called restart. The
560-
options available are listed in table :numref:`tab-outputopts`.
557+
The output (dump) files with time-history are controlled by settings in a
558+
section called ``"output"``. Restart files contain a single time-slice, and are
559+
controlled by a section called ``"restart"``. The options available are listed
560+
in table :numref:`tab-outputopts`.
561561

562562
.. _tab-outputopts:
563563
.. table:: Output file options
564564

565-
+-------------+----------------------------------------------------+--------------+
566-
| Option | Description | Default |
567-
| | | value |
568-
+-------------+----------------------------------------------------+--------------+
569-
| enabled | Writing is enabled | true |
570-
+-------------+----------------------------------------------------+--------------+
571-
| type | File type e.g. "netcdf" or "adios" | "netcdf" |
572-
+-------------+----------------------------------------------------+--------------+
573-
| prefix | File name prefix | "BOUT.dmp" |
574-
+-------------+----------------------------------------------------+--------------+
575-
| path | Directory to write the file into | ``datadir`` |
576-
+-------------+----------------------------------------------------+--------------+
577-
| floats | Write floats rather than doubles | false |
578-
+-------------+----------------------------------------------------+--------------+
579-
| flush | Flush the file to disk after each write | true |
580-
+-------------+----------------------------------------------------+--------------+
581-
| guards | Output guard cells | true |
582-
+-------------+----------------------------------------------------+--------------+
583-
| openclose | Re-open the file for each write, and close after | true |
584-
+-------------+----------------------------------------------------+--------------+
565+
+----------------------+-----------------------------------------+----------------+
566+
| Option | Description | Default value |
567+
+======================+=========================================+================+
568+
| ``append`` | Append to existing file if true, | ``false`` |
569+
| | otherwise overwrite | |
570+
+----------------------+-----------------------------------------+----------------+
571+
| ``enabled`` | Writing is enabled | ``true`` |
572+
+----------------------+-----------------------------------------+----------------+
573+
| ``flush_frequency`` | How many output timesteps between | ``1`` |
574+
| | writing output to disk (NetCDF only) | |
575+
+----------------------+-----------------------------------------+----------------+
576+
| ``prefix`` | File name prefix | ``"BOUT.dmp"`` |
577+
+----------------------+-----------------------------------------+----------------+
578+
| ``path`` | Directory to write the file into | ``datadir`` |
579+
+----------------------+-----------------------------------------+----------------+
580+
| ``type`` | File type, either ``"netcdf"`` or | ``"netcdf"`` |
581+
| | ``"adios"`` | |
582+
+----------------------+-----------------------------------------+----------------+
585583

586584
|
587585
588-
**enabled** is useful mainly for doing performance or scaling tests, where you
589-
want to exclude I/O from the timings. **floats** can be used to reduce the size
590-
of the output files: files are stored as double by default, but setting
591-
**floats = true** changes the output to single-precision floats.
592-
586+
- ``enabled`` is useful mainly for doing performance or scaling tests, where you
587+
want to exclude I/O from the timings.
588+
- If you find that IO is taking more and more time as your simulation goes on,
589+
try setting ``flush_frequency`` to a larger value such as ``10``. This can
590+
workaround an issue with NetCDF where subsequent writes take longer and
591+
longer. However, larger values risk losing more data in the event of a crash
592+
or the simulation being killed early.
593593

594594
Implementation
595595
--------------

src/physics/physicsmodel.cxx

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,14 @@
3434

3535
#include "bout/version.hxx"
3636
#include <bout/mesh.hxx>
37+
#include <bout/options.hxx>
3738
#include <bout/sys/timer.hxx>
3839
#include <bout/vector2d.hxx>
3940
#include <bout/vector3d.hxx>
4041

4142
#include <fmt/core.h>
4243

44+
#include <cstddef>
4345
#include <string>
4446
using namespace std::literals;
4547

@@ -67,9 +69,10 @@ PhysicsModel::PhysicsModel()
6769
.withDefault(true)),
6870
restart_enabled(Options::root()["restart_files"]["enabled"]
6971
.doc("Write restart files")
70-
.withDefault(true))
71-
72-
{
72+
.withDefault(true)),
73+
flush_frequency(Options::root()["output"]["flush_frequency"]
74+
.doc("How often to flush to disk")
75+
.withDefault<std::size_t>(1)) {
7376
if (output_enabled) {
7477
output_file = bout::OptionsIOFactory::getInstance().createOutput();
7578
}
@@ -188,7 +191,7 @@ int PhysicsModel::postInit(bool restarting) {
188191
}
189192

190193
void PhysicsModel::outputVars(Options& options) {
191-
Timer time("io");
194+
const Timer time("io");
192195
for (const auto& item : dump.getData()) {
193196
bout::utils::visit(bout::OptionsConversionVisitor{options, item.name}, item.value);
194197
if (item.repeat) {
@@ -198,7 +201,7 @@ void PhysicsModel::outputVars(Options& options) {
198201
}
199202

200203
void PhysicsModel::restartVars(Options& options) {
201-
Timer time("io");
204+
const Timer time("io");
202205
for (const auto& item : restart.getData()) {
203206
bout::utils::visit(bout::OptionsConversionVisitor{options, item.name}, item.value);
204207
if (item.repeat) {
@@ -216,9 +219,7 @@ void PhysicsModel::writeRestartFile() {
216219
void PhysicsModel::writeOutputFile() { writeOutputFile(output_options); }
217220

218221
void PhysicsModel::writeOutputFile(const Options& options) {
219-
if (output_enabled) {
220-
output_file->write(options, "t");
221-
}
222+
writeOutputFile(options, "t");
222223
}
223224

224225
void PhysicsModel::writeOutputFile(const Options& options,
@@ -229,13 +230,19 @@ void PhysicsModel::writeOutputFile(const Options& options,
229230
}
230231

231232
void PhysicsModel::finishOutputTimestep() const {
232-
if (output_enabled) {
233+
const Timer timer("io");
234+
235+
if (output_enabled and (flush_counter % flush_frequency == 0)) {
236+
output_file->flush();
233237
output_file->verifyTimesteps();
234238
}
235239
}
236240

237241
int PhysicsModel::PhysicsModelMonitor::call(Solver* solver, BoutReal simtime,
238242
int iteration, int nout) {
243+
244+
model->setFlushCounter(static_cast<std::size_t>(iteration));
245+
239246
// Restart file variables
240247
solver->outputVars(model->restart_options, false);
241248
model->restartVars(model->restart_options);
@@ -254,5 +261,8 @@ int PhysicsModel::PhysicsModelMonitor::call(Solver* solver, BoutReal simtime,
254261
model->outputVars(model->output_options);
255262
model->writeOutputFile();
256263

264+
// Reset output options, this avoids rewriting time-independent data
265+
model->output_options = Options{};
266+
257267
return monitor_result;
258268
}

src/sys/options/options_netcdf.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -791,10 +791,10 @@ void OptionsNetCDF::write(const Options& options, const std::string& time_dim) {
791791
}
792792

793793
writeGroup(options, *data_file, time_dim);
794-
795-
data_file->sync();
796794
}
797795

796+
void OptionsNetCDF::flush() { data_file->sync(); }
797+
798798
} // namespace bout
799799

800800
#endif // BOUT_HAS_NETCDF

src/sys/options/options_netcdf.hxx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public:
3939
/// - "append" File mode, default is false
4040
OptionsNetCDF(Options& options);
4141

42-
~OptionsNetCDF() {}
42+
~OptionsNetCDF() override = default;
4343

4444
OptionsNetCDF(const OptionsNetCDF&) = delete;
4545
OptionsNetCDF(OptionsNetCDF&&) noexcept = default;
@@ -58,6 +58,9 @@ public:
5858
/// any differences, otherwise is silent
5959
void verifyTimesteps() const override;
6060

61+
/// Flush file to disk
62+
void flush() override;
63+
6164
private:
6265
enum class FileMode {
6366
replace, ///< Overwrite file when writing
@@ -74,7 +77,7 @@ private:
7477
};
7578

7679
namespace {
77-
RegisterOptionsIO<OptionsNetCDF> registeroptionsnetcdf("netcdf");
80+
const inline RegisterOptionsIO<OptionsNetCDF> registeroptionsnetcdf("netcdf");
7881
}
7982

8083
} // namespace bout

0 commit comments

Comments
 (0)