diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index 0ce10cbe33..3aa31a7e4c 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr3467-9212-976cc3b + baseline: integratedTests/baseline_integratedTests-pr3480-9217-caaecb8 allow_fail: all: '' streak: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index 8f34487782..acbeb39e38 100644 --- a/BASELINE_NOTES.md +++ b/BASELINE_NOTES.md @@ -6,6 +6,10 @@ This file is designed to track changes to the integrated test baselines. Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining. These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD). +PR #3480 (2024-12-06) +===================== +Add "logLevel" parameter under /Problem/Outputs in baseline files + PR #3361 (2024-12-03) ===================== Revert default gravity treatment to old version. Make the way introduced in #3337 optional. diff --git a/src/coreComponents/fileIO/Outputs/BlueprintOutput.cpp b/src/coreComponents/fileIO/Outputs/BlueprintOutput.cpp index 21457e7796..cad26fcbb5 100644 --- a/src/coreComponents/fileIO/Outputs/BlueprintOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/BlueprintOutput.cpp @@ -129,53 +129,57 @@ BlueprintOutput::BlueprintOutput( string const & name, } /////////////////////////////////////////////////////////////////////////////////////////////////// -bool BlueprintOutput::execute( real64 const time, - real64 const, - integer const cycle, - integer const, - real64 const, +bool BlueprintOutput::execute( real64 const time_n, + real64 const GEOS_UNUSED_PARAM( dt ), + integer const cycleNumber, + integer const GEOS_UNUSED_PARAM( eventCounter ), + real64 const GEOS_UNUSED_PARAM( eventProgress ), DomainPartition & domain ) { GEOS_MARK_FUNCTION; - MeshLevel const & meshLevel = domain.getMeshBody( 0 ).getBaseDiscretization(); + { + Timer timer( m_outputTimer ); - conduit::Node meshRoot; - conduit::Node & mesh = meshRoot[ "mesh" ]; - conduit::Node & coordset = mesh[ "coordsets/nodes" ]; - conduit::Node & topologies = mesh[ "topologies" ]; + MeshLevel const & meshLevel = domain.getMeshBody( 0 ).getBaseDiscretization(); - mesh[ "state/time" ] = time; - mesh[ "state/cycle" ] = cycle; + conduit::Node meshRoot; + conduit::Node & mesh = meshRoot[ "mesh" ]; + conduit::Node & coordset = mesh[ "coordsets/nodes" ]; + conduit::Node & topologies = mesh[ "topologies" ]; - addNodalData( meshLevel.getNodeManager(), coordset, topologies, mesh[ "fields" ] ); + mesh[ "state/time" ] = time_n; + mesh[ "state/cycle" ] = cycleNumber; - dataRepository::Group averagedElementData( "averagedElementData", this ); - addElementData( meshLevel.getElemManager(), coordset, topologies, mesh[ "fields" ], averagedElementData ); + addNodalData( meshLevel.getNodeManager(), coordset, topologies, mesh[ "fields" ] ); - /// The Blueprint will complain if the fields node is present but empty. - if( mesh[ "fields" ].number_of_children() == 0 ) - { - mesh.remove( "fields" ); - } + dataRepository::Group averagedElementData( "averagedElementData", this ); + addElementData( meshLevel.getElemManager(), coordset, topologies, mesh[ "fields" ], averagedElementData ); + + /// The Blueprint will complain if the fields node is present but empty. + if( mesh[ "fields" ].number_of_children() == 0 ) + { + mesh.remove( "fields" ); + } - /// Verify that the mesh conforms to the Blueprint. - conduit::Node info; - GEOS_ASSERT_MSG( conduit::blueprint::verify( "mesh", meshRoot, info ), info.to_json() ); + /// Verify that the mesh conforms to the Blueprint. + conduit::Node info; + GEOS_ASSERT_MSG( conduit::blueprint::verify( "mesh", meshRoot, info ), info.to_json() ); - /// Generate the Blueprint index. - conduit::Node fileRoot; - conduit::Node & index = fileRoot[ "blueprint_index/mesh" ]; - conduit::blueprint::mesh::generate_index( mesh, "mesh", MpiWrapper::commSize(), index ); + /// Generate the Blueprint index. + conduit::Node fileRoot; + conduit::Node & index = fileRoot[ "blueprint_index/mesh" ]; + conduit::blueprint::mesh::generate_index( mesh, "mesh", MpiWrapper::commSize(), index ); - /// Verify that the index conforms to the Blueprint. - info.reset(); - GEOS_ASSERT_MSG( conduit::blueprint::mesh::index::verify( index, info ), info.to_json() ); + /// Verify that the index conforms to the Blueprint. + info.reset(); + GEOS_ASSERT_MSG( conduit::blueprint::mesh::index::verify( index, info ), info.to_json() ); - /// Write out the root index file, then write out the mesh. - string const completePath = GEOS_FMT( "{}/blueprintFiles/cycle_{:07}", OutputBase::getOutputDirectory(), cycle ); - string const filePathForRank = dataRepository::writeRootFile( fileRoot, completePath ); - conduit::relay::io::save( meshRoot, filePathForRank, "hdf5" ); + /// Write out the root index file, then write out the mesh. + string const completePath = GEOS_FMT( "{}/blueprintFiles/cycle_{:07}", OutputBase::getOutputDirectory(), cycleNumber ); + string const filePathForRank = dataRepository::writeRootFile( fileRoot, completePath ); + conduit::relay::io::save( meshRoot, filePathForRank, "hdf5" ); + } return false; } @@ -307,7 +311,19 @@ void BlueprintOutput::writeOutConstitutiveData( dataRepository::Group const & co } ); } +namespace logInfo +{ +struct BlueprintOutputTimer : public OutputTimerBase +{ + std::string_view getDescription() const override { return "Blueprint output timing"; } +}; +} +logInfo::OutputTimerBase const & BlueprintOutput::getTimerCategory() const +{ + static logInfo::BlueprintOutputTimer timer; + return timer; +} REGISTER_CATALOG_ENTRY( OutputBase, BlueprintOutput, string const &, dataRepository::Group * const ) diff --git a/src/coreComponents/fileIO/Outputs/BlueprintOutput.hpp b/src/coreComponents/fileIO/Outputs/BlueprintOutput.hpp index 7d17570d47..fd963698c3 100644 --- a/src/coreComponents/fileIO/Outputs/BlueprintOutput.hpp +++ b/src/coreComponents/fileIO/Outputs/BlueprintOutput.hpp @@ -36,6 +36,12 @@ class ElementRegionManager; */ class BlueprintOutput : public OutputBase { +protected: + /** + * @copydoc OutputBase::getTimerCategory + */ + logInfo::OutputTimerBase const & getTimerCategory() const override; + public: /** diff --git a/src/coreComponents/fileIO/Outputs/ChomboIO.cpp b/src/coreComponents/fileIO/Outputs/ChomboIO.cpp index 674f1e4eac..26f73a9eb4 100644 --- a/src/coreComponents/fileIO/Outputs/ChomboIO.cpp +++ b/src/coreComponents/fileIO/Outputs/ChomboIO.cpp @@ -30,6 +30,20 @@ namespace geos using namespace dataRepository; +namespace logInfo +{ +struct ChomboOutputTimer : public OutputTimerBase +{ + std::string_view getDescription() const override { return "Chombo output timing"; } +}; +} + +logInfo::OutputTimerBase const & ChomboIO::getTimerCategory() const +{ + static logInfo::ChomboOutputTimer timer; + return timer; +} + ChomboIO::ChomboIO( string const & name, Group * const parent ): OutputBase( name, parent ), m_coupler( nullptr ), diff --git a/src/coreComponents/fileIO/Outputs/ChomboIO.hpp b/src/coreComponents/fileIO/Outputs/ChomboIO.hpp index c483f06696..c9e60cf2f7 100644 --- a/src/coreComponents/fileIO/Outputs/ChomboIO.hpp +++ b/src/coreComponents/fileIO/Outputs/ChomboIO.hpp @@ -89,6 +89,12 @@ class ChomboIO final : public OutputBase } viewKeys; /// @endcond +protected: + /** + * @copydoc OutputBase::getTimerCategory + */ + logInfo::OutputTimerBase const & getTimerCategory() const override; + private: ChomboCoupler * m_coupler; string m_outputPath; diff --git a/src/coreComponents/fileIO/Outputs/OutputBase.cpp b/src/coreComponents/fileIO/Outputs/OutputBase.cpp index 0733dd38cc..54dcab668e 100644 --- a/src/coreComponents/fileIO/Outputs/OutputBase.cpp +++ b/src/coreComponents/fileIO/Outputs/OutputBase.cpp @@ -29,6 +29,7 @@ using namespace dataRepository; OutputBase::OutputBase( string const & name, Group * const parent ): ExecutableGroup( name, parent ), + m_outputTimer(), m_childDirectory(), m_parallelThreads( 1 ) { @@ -43,6 +44,8 @@ OutputBase::OutputBase( string const & name, setInputFlag( InputFlags::OPTIONAL ). setDescription( "Number of plot files." ); + // Add the Timers log level + addLogLevel< logInfo::OutputTimers >(); } OutputBase::~OutputBase() @@ -106,5 +109,23 @@ void OutputBase::setupDirectoryStructure() } } +void OutputBase::cleanup( real64 const GEOS_UNUSED_PARAM( time_n ), + integer const GEOS_UNUSED_PARAM( cycleNumber ), + integer const GEOS_UNUSED_PARAM( eventCounter ), + real64 const GEOS_UNUSED_PARAM( eventProgress ), + DomainPartition & GEOS_UNUSED_PARAM( domain ) ) +{ + // Report timing statistics + real64 const time = std::chrono::duration< double >( m_outputTimer ).count(); + real64 const minTime = MpiWrapper::min( time ); + real64 const maxTime = MpiWrapper::max( time ); + if( maxTime > 0 ) + { + GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::OutputTimers, + GEOS_FMT( "{}: file writing time = {} s (min), {} s (max)", + getName(), minTime, maxTime ) ); + } +} + } /* namespace geos */ diff --git a/src/coreComponents/fileIO/Outputs/OutputBase.hpp b/src/coreComponents/fileIO/Outputs/OutputBase.hpp index f4129433f7..ae957e2221 100644 --- a/src/coreComponents/fileIO/Outputs/OutputBase.hpp +++ b/src/coreComponents/fileIO/Outputs/OutputBase.hpp @@ -21,11 +21,50 @@ #include "dataRepository/Group.hpp" #include "dataRepository/ExecutableGroup.hpp" - +#include "dataRepository/LogLevelsInfo.hpp" // For logInfo namespace +#include "common/Timer.hpp" namespace geos { +namespace logInfo +{ +/** + * @brief Base timer category for output operations + * @details Provides configuration for logging output operation timing information + */ +struct OutputTimers +{ + /** + * @brief Get the description of this timer + * @return String view containing the timer description + */ + static std::string_view getDescription() { return "Output timing information"; } + + /** + * @brief Get the minimum log level for this timer + * @return Integer representing the minimum log level + */ + static constexpr int getMinLogLevel() { return 1; } +}; + +/** + * @brief Base interface for specific output type timers + * @details Each output type (VTK, Silo, etc.) implements this interface to provide + * its own timing category. This is used in conjunction with OutputTimers: + * - OutputTimerBase: For polymorphic behavior in derived output classes + * - OutputTimers: For the general output timing logging infrastructure + */ +struct OutputTimerBase +{ + /** + * @brief Get the description of this timer + * @return String view containing the timer description + */ + virtual std::string_view getDescription() const = 0; +}; +} + /** * @class OutputBase * @@ -102,6 +141,22 @@ class OutputBase : public ExecutableGroup **/ virtual void initializePreSubGroups() override; + /// Timer used to track duration of file writing operations for this specific output type + std::chrono::system_clock::duration m_outputTimer; + + /** + * @brief Get the timer category for this output type + * @return Reference to the output timer base for timing statistics + */ + virtual logInfo::OutputTimerBase const & getTimerCategory() const = 0; + + /// @copydoc geos::ExecutableGroup::cleanup + virtual void cleanup( real64 const time_n, + integer const cycleNumber, + integer const eventCounter, + real64 const eventProgress, + DomainPartition & domain ) override; + private: string m_childDirectory; integer m_parallelThreads; diff --git a/src/coreComponents/fileIO/Outputs/PythonOutput.cpp b/src/coreComponents/fileIO/Outputs/PythonOutput.cpp index e78f8835a0..5891fe55e2 100644 --- a/src/coreComponents/fileIO/Outputs/PythonOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/PythonOutput.cpp @@ -18,6 +18,20 @@ namespace geos { +namespace logInfo +{ +struct PythonOutputTimer : public OutputTimerBase +{ + std::string_view getDescription() const override { return "Python output timing"; } +}; +} + +logInfo::OutputTimerBase const & PythonOutput::getTimerCategory() const +{ + static logInfo::PythonOutputTimer timer; + return timer; +} + REGISTER_CATALOG_ENTRY( OutputBase, PythonOutput, string const &, dataRepository::Group * const ) } // namespace geos diff --git a/src/coreComponents/fileIO/Outputs/PythonOutput.hpp b/src/coreComponents/fileIO/Outputs/PythonOutput.hpp index 0e6c3cebb8..a73b678165 100644 --- a/src/coreComponents/fileIO/Outputs/PythonOutput.hpp +++ b/src/coreComponents/fileIO/Outputs/PythonOutput.hpp @@ -75,6 +75,9 @@ class PythonOutput : public OutputBase GEOS_UNUSED_VAR( domain ); return true; } + +protected: + logInfo::OutputTimerBase const & getTimerCategory() const override; }; diff --git a/src/coreComponents/fileIO/Outputs/RestartOutput.cpp b/src/coreComponents/fileIO/Outputs/RestartOutput.cpp index 6fb7a2c6b1..6eb07281cf 100644 --- a/src/coreComponents/fileIO/Outputs/RestartOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/RestartOutput.cpp @@ -24,6 +24,14 @@ namespace geos using namespace dataRepository; +namespace logInfo +{ +struct RestartOutputTimer : public OutputTimerBase +{ + std::string_view getDescription() const override { return "Restart output timing"; } +}; +} + RestartOutput::RestartOutput( string const & name, Group * const parent ): OutputBase( name, parent ) @@ -41,19 +49,24 @@ bool RestartOutput::execute( real64 const GEOS_UNUSED_PARAM( time_n ), { GEOS_MARK_FUNCTION; - Group & rootGroup = this->getGroupByPath( "/Problem" ); + { + Timer timer( m_outputTimer ); - // Ignoring the eventProgress indicator for now to be compliant with the integrated test repo - // integer const eventProgressPercent = static_cast(eventProgress * 100.0); - string const fileName = GEOS_FMT( "{}_restart_{:09}", getFileNameRoot(), cycleNumber ); - - rootGroup.prepareToWrite(); - writeTree( joinPath( OutputBase::getOutputDirectory(), fileName ), *(rootGroup.getConduitNode().parent()) ); - rootGroup.finishWriting(); + Group & rootGroup = this->getGroupByPath( "/Problem" ); + string const fileName = GEOS_FMT( "{}_restart_{:09}", getFileNameRoot(), cycleNumber ); + rootGroup.prepareToWrite(); + writeTree( joinPath( OutputBase::getOutputDirectory(), fileName ), *(rootGroup.getConduitNode().parent()) ); + rootGroup.finishWriting(); + } return false; } +logInfo::OutputTimerBase const & RestartOutput::getTimerCategory() const +{ + static logInfo::RestartOutputTimer timer; + return timer; +} REGISTER_CATALOG_ENTRY( OutputBase, RestartOutput, string const &, Group * const ) } /* namespace geos */ diff --git a/src/coreComponents/fileIO/Outputs/RestartOutput.hpp b/src/coreComponents/fileIO/Outputs/RestartOutput.hpp index a2a12be781..11c8715ed7 100644 --- a/src/coreComponents/fileIO/Outputs/RestartOutput.hpp +++ b/src/coreComponents/fileIO/Outputs/RestartOutput.hpp @@ -78,6 +78,12 @@ class RestartOutput : public OutputBase dataRepository::ViewKey writeFEMFaces = { "writeFEMFaces" }; } viewKeys; /// @endcond + +protected: + /** + * @copydoc OutputBase::getTimerCategory + */ + logInfo::OutputTimerBase const & getTimerCategory() const override; }; diff --git a/src/coreComponents/fileIO/Outputs/SiloOutput.cpp b/src/coreComponents/fileIO/Outputs/SiloOutput.cpp index 756facc2da..ba03ceead5 100644 --- a/src/coreComponents/fileIO/Outputs/SiloOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/SiloOutput.cpp @@ -28,6 +28,20 @@ namespace geos using namespace dataRepository; +namespace logInfo +{ +struct SiloOutputTimer : public OutputTimerBase +{ + std::string_view getDescription() const override { return "Silo output timing"; } +}; +} + +logInfo::OutputTimerBase const & SiloOutput::getTimerCategory() const +{ + static logInfo::SiloOutputTimer timer; + return timer; +} + SiloOutput::SiloOutput( string const & name, Group * const parent ): OutputBase( name, parent ), @@ -122,31 +136,35 @@ bool SiloOutput::execute( real64 const time_n, { GEOS_MARK_FUNCTION; - SiloFile silo; - - int const size = MpiWrapper::commSize( MPI_COMM_GEOS ); - int const rank = MpiWrapper::commRank( MPI_COMM_GEOS ); - MpiWrapper::barrier( MPI_COMM_GEOS ); - - integer const numFiles = parallelThreads() == 0 ? size : parallelThreads(); - - // TODO set this during initialization - // silo.setOutputDirectory( getGlobalState().getCommandLineOptions().outputDirectory ), - silo.setOutputDirectory( getOutputDirectory() ), - silo.setPlotLevel( m_plotLevel ); - silo.setWriteEdgeMesh( m_writeEdgeMesh ); - silo.setWriteFaceMesh( m_writeFaceMesh ); - silo.setWriteCellElementMesh( m_writeCellElementMesh ); - silo.setWriteFaceElementMesh( m_writeFaceElementMesh ); - silo.setOnlyPlotSpecifiedFieldNamesFlag( m_onlyPlotSpecifiedFieldNames ); - silo.setFieldNames( m_fieldNames.toViewConst() ); - silo.setPlotFileRoot( m_plotFileRoot ); - silo.initialize( numFiles ); - silo.waitForBatonWrite( rank, cycleNumber, eventCounter, false ); - silo.writeDomainPartition( domain, cycleNumber, time_n + dt * eventProgress, 0 ); - silo.handOffBaton(); - silo.clearEmptiesFromMultiObjects( cycleNumber ); - silo.finish(); + { + Timer timer( m_outputTimer ); + + SiloFile silo; + + int const size = MpiWrapper::commSize( MPI_COMM_GEOS ); + int const rank = MpiWrapper::commRank( MPI_COMM_GEOS ); + MpiWrapper::barrier( MPI_COMM_GEOS ); + + integer const numFiles = parallelThreads() == 0 ? size : parallelThreads(); + + // TODO set this during initialization + // silo.setOutputDirectory( getGlobalState().getCommandLineOptions().outputDirectory ), + silo.setOutputDirectory( getOutputDirectory() ), + silo.setPlotLevel( m_plotLevel ); + silo.setWriteEdgeMesh( m_writeEdgeMesh ); + silo.setWriteFaceMesh( m_writeFaceMesh ); + silo.setWriteCellElementMesh( m_writeCellElementMesh ); + silo.setWriteFaceElementMesh( m_writeFaceElementMesh ); + silo.setOnlyPlotSpecifiedFieldNamesFlag( m_onlyPlotSpecifiedFieldNames ); + silo.setFieldNames( m_fieldNames.toViewConst() ); + silo.setPlotFileRoot( m_plotFileRoot ); + silo.initialize( numFiles ); + silo.waitForBatonWrite( rank, cycleNumber, eventCounter, false ); + silo.writeDomainPartition( domain, cycleNumber, time_n + dt * eventProgress, 0 ); + silo.handOffBaton(); + silo.clearEmptiesFromMultiObjects( cycleNumber ); + silo.finish(); + } return false; } diff --git a/src/coreComponents/fileIO/Outputs/SiloOutput.hpp b/src/coreComponents/fileIO/Outputs/SiloOutput.hpp index bb3574f374..6b0a371974 100644 --- a/src/coreComponents/fileIO/Outputs/SiloOutput.hpp +++ b/src/coreComponents/fileIO/Outputs/SiloOutput.hpp @@ -85,6 +85,12 @@ class SiloOutput : public OutputBase } siloOutputViewKeys; /// @endcond +protected: + /** + * @copydoc OutputBase::getTimerCategory + */ + logInfo::OutputTimerBase const & getTimerCategory() const override; + private: void postInputInitialization() override; diff --git a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp index d01edac3dc..7e1299aac5 100644 --- a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp @@ -25,6 +25,20 @@ namespace geos { using namespace dataRepository; +namespace logInfo +{ +struct TimeHistoryOutputTimer : public OutputTimerBase +{ + std::string_view getDescription() const override { return "Time history output timing"; } +}; +} + +logInfo::OutputTimerBase const & TimeHistoryOutput::getTimerCategory() const +{ + static logInfo::TimeHistoryOutputTimer timer; + return timer; +} + TimeHistoryOutput::TimeHistoryOutput( string const & name, Group * const parent ): OutputBase( name, parent ), @@ -166,12 +180,18 @@ bool TimeHistoryOutput::execute( real64 const GEOS_UNUSED_PARAM( time_n ), DomainPartition & GEOS_UNUSED_PARAM( domain ) ) { GEOS_MARK_FUNCTION; - localIndex newBuffered = m_io.front()->getBufferedCount( ); - for( auto & th_io : m_io ) + { - th_io->write( ); + Timer timer( m_outputTimer ); + + localIndex newBuffered = m_io.front()->getBufferedCount( ); + for( auto & th_io : m_io ) + { + th_io->write( ); + } + m_recordCount += newBuffered; } - m_recordCount += newBuffered; + return false; } diff --git a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.hpp b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.hpp index d7793943d9..e2846f7c31 100644 --- a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.hpp +++ b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.hpp @@ -114,6 +114,12 @@ class TimeHistoryOutput : public OutputBase virtual PyTypeObject * getPythonType() const override; #endif +protected: + /** + * @copydoc OutputBase::getTimerCategory + */ + logInfo::OutputTimerBase const & getTimerCategory() const override; + private: /** diff --git a/src/coreComponents/fileIO/Outputs/VTKOutput.cpp b/src/coreComponents/fileIO/Outputs/VTKOutput.cpp index 15e4b1dac1..b6f4348899 100644 --- a/src/coreComponents/fileIO/Outputs/VTKOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/VTKOutput.cpp @@ -29,6 +29,20 @@ namespace geos using namespace dataRepository; +namespace logInfo +{ +struct VTKOutputTimer : public OutputTimerBase +{ + std::string_view getDescription() const override { return "VTK output timing"; } +}; +} + +logInfo::OutputTimerBase const & VTKOutput::getTimerCategory() const +{ + static logInfo::VTKOutputTimer timer; + return timer; +} + VTKOutput::VTKOutput( string const & name, Group * const parent ): OutputBase( name, parent ), @@ -80,7 +94,7 @@ VTKOutput::VTKOutput( string const & name, registerWrapper( viewKeysStruct::fieldNames, &m_fieldNames ). setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Names of the fields to output. If this attribute is specified, GEOSX outputs all the fields specified by the user, regardless of their `plotLevel`" ); + setDescription( "Names of the fields to output. If this attribute is specified, GEOS outputs all the fields specified by the user, regardless of their `plotLevel`" ); registerWrapper( viewKeysStruct::levelNames, &m_levelNames ). setInputFlag( InputFlags::OPTIONAL ). @@ -159,14 +173,20 @@ bool VTKOutput::execute( real64 const time_n, real64 const GEOS_UNUSED_PARAM ( eventProgress ), DomainPartition & domain ) { - GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "{}: writing {} at time {} s (cycle number {})", getName(), m_fieldNames, time_n + dt, cycleNumber )); - - m_writer.setWriteGhostCells( m_writeGhostCells ); - m_writer.setWriteFaceElementsAs3D ( m_writeFaceElementsAs3D ); - m_writer.setOutputMode( m_writeBinaryData ); - m_writer.setOutputRegionType( m_outputRegionType ); - m_writer.setPlotLevel( m_plotLevel ); - m_writer.write( time_n, cycleNumber, domain ); + GEOS_MARK_FUNCTION; + + GEOS_LOG_LEVEL_RANK_0( 2, GEOS_FMT( "{}: writing {} at time {} s (cycle number {})", getName(), m_fieldNames, time_n + dt, cycleNumber )); + + { + Timer timer( m_outputTimer ); + + m_writer.setWriteGhostCells( m_writeGhostCells ); + m_writer.setWriteFaceElementsAs3D ( m_writeFaceElementsAs3D ); + m_writer.setOutputMode( m_writeBinaryData ); + m_writer.setOutputRegionType( m_outputRegionType ); + m_writer.setPlotLevel( m_plotLevel ); + m_writer.write( time_n, cycleNumber, domain ); + } return false; } diff --git a/src/coreComponents/fileIO/Outputs/VTKOutput.hpp b/src/coreComponents/fileIO/Outputs/VTKOutput.hpp index 5b167dc66d..bf36e900ea 100644 --- a/src/coreComponents/fileIO/Outputs/VTKOutput.hpp +++ b/src/coreComponents/fileIO/Outputs/VTKOutput.hpp @@ -77,6 +77,9 @@ class VTKOutput : public OutputBase DomainPartition & domain ) override { execute( time_n, 0, cycleNumber, eventCounter, eventProgress, domain ); + + // Call parent class cleanup to get the timing statistics + OutputBase::cleanup( time_n, cycleNumber, eventCounter, eventProgress, domain ); } /** @@ -109,6 +112,12 @@ class VTKOutput : public OutputBase virtual PyTypeObject * getPythonType() const override; #endif +protected: + /** + * @copydoc OutputBase::getTimerCategory + */ + logInfo::OutputTimerBase const & getTimerCategory() const override; + private: string m_plotFileRoot;