From b4c924ad0ceac07e6edecc041de2e1e5892184fd Mon Sep 17 00:00:00 2001 From: Guillaume Giudicelli Date: Wed, 20 Dec 2023 01:36:41 +0100 Subject: [PATCH 1/6] Rename CSVReader to CSVReaderVPP XYZReaders are user objects reading a file type. Many different systems could want to have a 'csvreader', vpps are not unique to claim the name refs #25956 --- .../dirackernels/ReporterPointSource.md | 4 ++-- .../doc/content/source/utils/MooseUtils.md | 8 +++---- .../source/vectorpostprocessors/CSVReader.md | 23 +------------------ .../CSVReaderVectorPostprocessor.md | 22 ++++++++++++++++++ ...eader.h => CSVReaderVectorPostprocessor.h} | 4 ++-- ...eader.C => CSVReaderVectorPostprocessor.C} | 10 ++++---- .../source/functions/ParameterMeshFunction.md | 2 +- .../samplers/VectorPostprocessorSampler.md | 2 +- .../vectorpostprocessors/csv_reader/read.i | 2 +- .../csv_reader/read_preic.i | 2 +- .../vectorpostprocessors/csv_reader/tests | 2 +- .../csv_reader/transfer/tests | 8 +++---- .../least_squares_fit_csv_data.i | 2 +- .../least_squares_fit/tests | 14 +++++------ 14 files changed, 54 insertions(+), 51 deletions(-) mode change 100644 => 120000 framework/doc/content/source/vectorpostprocessors/CSVReader.md create mode 100644 framework/doc/content/source/vectorpostprocessors/CSVReaderVectorPostprocessor.md rename framework/include/vectorpostprocessors/{CSVReader.h => CSVReaderVectorPostprocessor.h} (83%) rename framework/src/vectorpostprocessors/{CSVReader.C => CSVReaderVectorPostprocessor.C} (89%) diff --git a/framework/doc/content/source/dirackernels/ReporterPointSource.md b/framework/doc/content/source/dirackernels/ReporterPointSource.md index 37b1595228fc..d9ff69d403e6 100644 --- a/framework/doc/content/source/dirackernels/ReporterPointSource.md +++ b/framework/doc/content/source/dirackernels/ReporterPointSource.md @@ -6,7 +6,7 @@ A `ReporterPointSource` reads in multiple point sources from a `Reporter`. The Duplicated points, i.e. points with the same xyz coordinates, are dropped by [DiracKernels](/DiracKernels/index.md) and applied as a single point. The input parameter [!param](/DiracKernels/ReporterPointSource/combine_duplicates) combines the values and weights of duplicated points when set to `True`. Reporters containing duplicate points will produce an error when set to `False`. The parameter `drop_duplicate_points` used by other DiracKernels to handle duplicate points is suppressed for the `ReporterPointSource` because it is expected that every duplicate point in a `ReporterPointSource` will have different value and weight and are not just multiples of the sames value. An example of a `ReporterPointSource` using a [ConstantReporter](/ConstantReporter.md) -and a `VectorPostprocessor` of type [CSVReader](/CSVReader.md) is given by: +and a `VectorPostprocessor` of type [CSVReaderVectorPostprocessor](/CSVReaderVectorPostprocessor.md) is given by: !listing test/tests/dirackernels/reporter_point_source/2d_vpp.i block=reporter_point_source @@ -14,7 +14,7 @@ The ConstantReporter provides the following data: !listing test/tests/dirackernels/reporter_point_source/2d_vpp.i block=Reporters/reporterData -The `CSVReader` VectorPostprocessor is given by: +The `CSVReaderVectorPostprocessor` is given by: !listing test/tests/dirackernels/reporter_point_source/2d_vpp.i block=VectorPostprocessors diff --git a/framework/doc/content/source/utils/MooseUtils.md b/framework/doc/content/source/utils/MooseUtils.md index 627241bd6a23..e70e3dd4f21c 100644 --- a/framework/doc/content/source/utils/MooseUtils.md +++ b/framework/doc/content/source/utils/MooseUtils.md @@ -16,7 +16,7 @@ outside of the header, is numeric and can be converted to a C++ double. Addition assumed that the first row or column defines the number of columns for the entire file, if the number of columns differs from the first row an error will be produced. -Within MOOSE this utility is utilized by the [CSVReader](/CSVReader.md), which is part of +Within MOOSE this utility is utilized by the [CSVReaderVectorPostprocessor](/CSVReaderVectorPostprocessor.md), which is part of the [VectorPostprocessors] system. This object will be used to explain the use of the utility. Using the DelimitedFileReader is very simple and requires three steps. First, include the @@ -30,7 +30,7 @@ is instantiated and read method is called, as shown in the unit test snippet bel This class is required to include the filename upon construction. Optionally, a second argument providing a pointer to a [libMesh] Communicator object may be provided. This argument should be used when the reader is used within a MooseObject. For example, as shown in [csv_reader_ctor], -the CSVReader object passes a Communicator object to the reader. If not provided the reader will +the `CSVReaderVectorPostprocessor` object passes a Communicator object to the reader. If not provided the reader will read the data on all processors. If provided it will only read on single processor and broadcast the data to the others. @@ -63,8 +63,8 @@ The set methods must be called prior to the read method. character(s) will be ignored and all characters on a line that follow the character(s) will also be ignored. - !listing framework/src/vectorpostprocessors/CSVReader.C - start=CSVReader:: + !listing framework/src/vectorpostprocessors/CSVReaderVectorPostprocessor.C + start=CSVReaderVectorPostprocessor:: end=&_communicator include-end=True id=csv_reader_ctor caption=Construction of DelimitedFileReader object within a MooseObject initialization list. diff --git a/framework/doc/content/source/vectorpostprocessors/CSVReader.md b/framework/doc/content/source/vectorpostprocessors/CSVReader.md deleted file mode 100644 index 84b864924433..000000000000 --- a/framework/doc/content/source/vectorpostprocessors/CSVReader.md +++ /dev/null @@ -1,22 +0,0 @@ -# CSVReader - -The CSVReader reads [CSV](https://en.wikipedia.org/wiki/Comma-separated_values) data from a file and -converts each column into a VectorPostprocessor vector. This object uses the -[DelimitedFileReader](MooseUtils.md#delimitedfilereader) utility to perform the reading of the file. - -The names of the vectors declared by the `CSVReader` are the names of the columns in the CSV file. - -## Example Input Syntax - -In this example, the `example.csv` file containing data for year/month/day is being read by -the `CSVReader`. - -!listing test/tests/vectorpostprocessors/csv_reader/read.i block=VectorPostprocessors - -!listing test/tests/vectorpostprocessors/csv_reader/example.csv - -!syntax parameters /VectorPostprocessors/CSVReader - -!syntax inputs /VectorPostprocessors/CSVReader - -!syntax children /VectorPostprocessors/CSVReader diff --git a/framework/doc/content/source/vectorpostprocessors/CSVReader.md b/framework/doc/content/source/vectorpostprocessors/CSVReader.md new file mode 120000 index 000000000000..2cd18d516c23 --- /dev/null +++ b/framework/doc/content/source/vectorpostprocessors/CSVReader.md @@ -0,0 +1 @@ +CSVReaderVectorPostprocessor.md \ No newline at end of file diff --git a/framework/doc/content/source/vectorpostprocessors/CSVReaderVectorPostprocessor.md b/framework/doc/content/source/vectorpostprocessors/CSVReaderVectorPostprocessor.md new file mode 100644 index 000000000000..1a821b48cfc6 --- /dev/null +++ b/framework/doc/content/source/vectorpostprocessors/CSVReaderVectorPostprocessor.md @@ -0,0 +1,22 @@ +# CSVReaderVectorPostprocessor + +The CSVReaderVectorPostprocessor reads [CSV](https://en.wikipedia.org/wiki/Comma-separated_values) data from a file and +converts each column into a VectorPostprocessor vector. This object uses the +[DelimitedFileReader](MooseUtils.md#delimitedfilereader) utility to perform the reading of the file. + +The names of the vectors declared by the `CSVReaderVectorPostprocessor` are the names of the columns in the CSV file. + +## Example Input Syntax + +In this example, the `example.csv` file containing data for year/month/day is being read by +the `CSVReaderVectorPostprocessor`. + +!listing test/tests/vectorpostprocessors/csv_reader/read.i block=VectorPostprocessors + +!listing test/tests/vectorpostprocessors/csv_reader/example.csv + +!syntax parameters /VectorPostprocessors/CSVReaderVectorPostprocessor + +!syntax inputs /VectorPostprocessors/CSVReaderVectorPostprocessor + +!syntax children /VectorPostprocessors/CSVReaderVectorPostprocessor diff --git a/framework/include/vectorpostprocessors/CSVReader.h b/framework/include/vectorpostprocessors/CSVReaderVectorPostprocessor.h similarity index 83% rename from framework/include/vectorpostprocessors/CSVReader.h rename to framework/include/vectorpostprocessors/CSVReaderVectorPostprocessor.h index 29a33fbd8ed8..264f3e788793 100644 --- a/framework/include/vectorpostprocessors/CSVReader.h +++ b/framework/include/vectorpostprocessors/CSVReaderVectorPostprocessor.h @@ -13,11 +13,11 @@ #include "GeneralVectorPostprocessor.h" #include "DelimitedFileReader.h" -class CSVReader : public GeneralVectorPostprocessor +class CSVReaderVectorPostprocessor : public GeneralVectorPostprocessor { public: static InputParameters validParams(); - CSVReader(const InputParameters & parameters); + CSVReaderVectorPostprocessor(const InputParameters & parameters); virtual void initialize() override {} virtual void execute() override {} diff --git a/framework/src/vectorpostprocessors/CSVReader.C b/framework/src/vectorpostprocessors/CSVReaderVectorPostprocessor.C similarity index 89% rename from framework/src/vectorpostprocessors/CSVReader.C rename to framework/src/vectorpostprocessors/CSVReaderVectorPostprocessor.C index 8d9d1f19a36c..756721e762f7 100644 --- a/framework/src/vectorpostprocessors/CSVReader.C +++ b/framework/src/vectorpostprocessors/CSVReaderVectorPostprocessor.C @@ -11,13 +11,14 @@ #include // MOOSE includes -#include "CSVReader.h" +#include "CSVReaderVectorPostprocessor.h" #include "MooseUtils.h" -registerMooseObject("MooseApp", CSVReader); +registerMooseObject("MooseApp", CSVReaderVectorPostprocessor); +registerMooseObjectRenamed("MooseApp", CSVReader, "06/30/2024 24:00", CSVReaderVectorPostprocessor); InputParameters -CSVReader::validParams() +CSVReaderVectorPostprocessor::validParams() { InputParameters params = GeneralVectorPostprocessor::validParams(); params.addClassDescription( @@ -51,7 +52,8 @@ CSVReader::validParams() return params; } -CSVReader::CSVReader(const InputParameters & params) : GeneralVectorPostprocessor(params) +CSVReaderVectorPostprocessor::CSVReaderVectorPostprocessor(const InputParameters & params) + : GeneralVectorPostprocessor(params) { /// The MOOSE delimited file reader. MooseUtils::DelimitedFileReader csv_reader(getParam("csv_file"), &_communicator); diff --git a/modules/optimization/doc/content/source/functions/ParameterMeshFunction.md b/modules/optimization/doc/content/source/functions/ParameterMeshFunction.md index 048b366ef534..214d80a9aae2 100644 --- a/modules/optimization/doc/content/source/functions/ParameterMeshFunction.md +++ b/modules/optimization/doc/content/source/functions/ParameterMeshFunction.md @@ -22,7 +22,7 @@ First step is to define a mesh for the parameters, which is most easily done by !listing parameter_mesh/create_mesh.i -Running this input will create a `create_mesh_out.e` exodus file and `create_mesh_out_param_vec_0001.csv` CSV file. The CSV file is read by a [CSVReader.md] to create a vector-postprocessor of the parameter data. A ParameterMeshFunction then reads in the exodus file and retrieves the vector for the interpolation. +Running this input will create a `create_mesh_out.e` exodus file and `create_mesh_out_param_vec_0001.csv` CSV file. The CSV file is read by a [CSVReaderVectorPostprocessor.md] to create a vector-postprocessor of the parameter data. A ParameterMeshFunction then reads in the exodus file and retrieves the vector for the interpolation. !listing parameter_mesh/parameter_mesh.i block=VectorPostprocessors Functions diff --git a/modules/stochastic_tools/doc/content/source/samplers/VectorPostprocessorSampler.md b/modules/stochastic_tools/doc/content/source/samplers/VectorPostprocessorSampler.md index efe23c24de27..7847411e8447 100644 --- a/modules/stochastic_tools/doc/content/source/samplers/VectorPostprocessorSampler.md +++ b/modules/stochastic_tools/doc/content/source/samplers/VectorPostprocessorSampler.md @@ -7,7 +7,7 @@ The sampler generates samples from [vector-postprocessor](VectorPostprocessors/i ## Example Input Syntax -In the example below, a vectorpostprocessor (`[csv]`) are formed using [CSVReader](/CSVReader.md): +In the example below, a vectorpostprocessor (`[csv]`) are formed using [CSVReaderVectorPostprocessor](/CSVReaderVectorPostprocessor.md): !listing modules/stochastic_tools/test/tests/samplers/vectorpostprocessor/vectorpostprocessor.i block=VectorPostprocessors diff --git a/test/tests/vectorpostprocessors/csv_reader/read.i b/test/tests/vectorpostprocessors/csv_reader/read.i index a71ff6073540..c203a5bde06e 100644 --- a/test/tests/vectorpostprocessors/csv_reader/read.i +++ b/test/tests/vectorpostprocessors/csv_reader/read.i @@ -23,7 +23,7 @@ [VectorPostprocessors] [./reader] - type = CSVReader + type = CSVReaderVectorPostprocessor csv_file = example.csv [../] [] diff --git a/test/tests/vectorpostprocessors/csv_reader/read_preic.i b/test/tests/vectorpostprocessors/csv_reader/read_preic.i index b47856b19640..3cae2ca9666a 100644 --- a/test/tests/vectorpostprocessors/csv_reader/read_preic.i +++ b/test/tests/vectorpostprocessors/csv_reader/read_preic.i @@ -13,7 +13,7 @@ [VectorPostprocessors] [./reader] - type = CSVReader + type = CSVReaderVectorPostprocessor csv_file = 'example.csv' force_preic = true [../] diff --git a/test/tests/vectorpostprocessors/csv_reader/tests b/test/tests/vectorpostprocessors/csv_reader/tests index fe079311560d..5a063ad4049a 100644 --- a/test/tests/vectorpostprocessors/csv_reader/tests +++ b/test/tests/vectorpostprocessors/csv_reader/tests @@ -1,5 +1,5 @@ [Tests] - design = 'CSVReader.md' + design = 'CSVReaderVectorPostprocessor.md' [read] type = CSVDiff diff --git a/test/tests/vectorpostprocessors/csv_reader/transfer/tests b/test/tests/vectorpostprocessors/csv_reader/transfer/tests index 52d3e7a60fcd..67768a7fbf94 100644 --- a/test/tests/vectorpostprocessors/csv_reader/transfer/tests +++ b/test/tests/vectorpostprocessors/csv_reader/transfer/tests @@ -1,14 +1,14 @@ [Tests] [./csv_reader_in_transfer] - # A user was looking for an example of how to use CSVReader with MultiAppUserObjectTransfer, - # this provide an example. It is an error because the CSVReader will need to override the + # A user was looking for an example of how to use CSVReaderVectorPostprocessor with MultiAppUserObjectTransfer, + # this provide an example. It is an error because the CSVReaderVectorPostprocessor will need to override the # spatialValue method. type = RunException input = parent.i expect_err = 'data does not satisfy the Spatial UserObject interface!' issues = '#9860' - design = 'CSVReader.md' - requirement = 'The system shall issue an error if the CSVReader is used in a UserObjectTransfer because the former does not have any notion of "spatial" information.' + design = 'CSVReaderVectorPostprocessor.md' + requirement = 'The system shall issue an error if the CSVReaderVectorPostprocessor is used in a UserObjectTransfer because the former does not have any notion of "spatial" information.' [../] [] diff --git a/test/tests/vectorpostprocessors/least_squares_fit/least_squares_fit_csv_data.i b/test/tests/vectorpostprocessors/least_squares_fit/least_squares_fit_csv_data.i index 471fe1e97eca..2413165c0205 100644 --- a/test/tests/vectorpostprocessors/least_squares_fit/least_squares_fit_csv_data.i +++ b/test/tests/vectorpostprocessors/least_squares_fit/least_squares_fit_csv_data.i @@ -16,7 +16,7 @@ [VectorPostprocessors] [./csv_data] - type = CSVReader + type = CSVReaderVectorPostprocessor csv_file = fit_data_0.csv header = true outputs = none diff --git a/test/tests/vectorpostprocessors/least_squares_fit/tests b/test/tests/vectorpostprocessors/least_squares_fit/tests index 3d6c00fbdbd4..a4656f365464 100644 --- a/test/tests/vectorpostprocessors/least_squares_fit/tests +++ b/test/tests/vectorpostprocessors/least_squares_fit/tests @@ -9,8 +9,8 @@ [../] [./least_squares_csv0] issues = '#13498' - requirement = 'The LeastSquaresFit vectorpostprocessor shall compute a least squares fit of a zeroth-rder polynomial with data provided by a CSVReader' - design = 'LeastSquaresFit.md CSVReader.md' + requirement = 'The LeastSquaresFit vectorpostprocessor shall compute a least squares fit of a zeroth-order polynomial with data provided by a CSVReaderVectorPostprocessor' + design = 'LeastSquaresFit.md CSVReaderVectorPostprocessor.md' type = 'CSVDiff' input = 'least_squares_fit_csv_data.i' csvdiff = 'csv0_least_squares_fit_coeffs_0000.csv' @@ -18,8 +18,8 @@ [../] [./least_squares_csv1] issues = '#13498' - requirement = 'The LeastSquaresFit vectorpostprocessor shall compute a least squares fit of a first-rder polynomial with data provided by a CSVReader' - design = 'LeastSquaresFit.md CSVReader.md' + requirement = 'The LeastSquaresFit vectorpostprocessor shall compute a least squares fit of a first-order polynomial with data provided by a CSVReaderVectorPostprocessor' + design = 'LeastSquaresFit.md CSVReaderVectorPostprocessor.md' type = 'CSVDiff' input = 'least_squares_fit_csv_data.i' cli_args = 'VectorPostprocessors/csv_data/csv_file=fit_data_1.csv VectorPostprocessors/least_squares_fit_coeffs/order=1 Outputs/file_base=csv1' @@ -28,8 +28,8 @@ [../] [./least_squares_csv2] issues = '#13498' - requirement = 'The LeastSquaresFit vectorpostprocessor shall compute a least squares fit of a second-rder polynomial with data provided by a CSVReader' - design = 'LeastSquaresFit.md CSVReader.md' + requirement = 'The LeastSquaresFit vectorpostprocessor shall compute a least squares fit of a second-order polynomial with data provided by a CSVReaderVectorPostprocessor' + design = 'LeastSquaresFit.md CSVReaderVectorPostprocessor.md' type = 'CSVDiff' input = 'least_squares_fit_csv_data.i' cli_args = 'VectorPostprocessors/csv_data/csv_file=fit_data_2.csv VectorPostprocessors/least_squares_fit_coeffs/order=2 Outputs/file_base=csv2' @@ -39,7 +39,7 @@ [./least_squares_csv3_order_err] issues = '#13498' requirement = 'The LeastSquaresFit vectorpostprocessor shall generate an error if a fit for a third-order polynomial is requested and only three data points are provided' - design = 'LeastSquaresFit.md CSVReader.md' + design = 'LeastSquaresFit.md CSVReaderVectorPostprocessor.md' type = 'RunException' expect_err = 'PolynomialFit requires an order less than the size of the input vector' input = 'least_squares_fit_csv_data.i' From 7116870c71176b110dddf6bef1b26246826854ee Mon Sep 17 00:00:00 2001 From: Guillaume Giudicelli Date: Thu, 21 Dec 2023 23:35:23 +0100 Subject: [PATCH 2/6] Add support for reading multiple files in PropertyFileReader - read a new file on every execution - once all are read, stick with last one refs #25955 --- .../include/userobjects/PropertyReadFile.h | 6 +- framework/include/utils/DelimitedFileReader.h | 5 +- framework/src/userobjects/PropertyReadFile.C | 58 ++++++++++++++++--- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/framework/include/userobjects/PropertyReadFile.h b/framework/include/userobjects/PropertyReadFile.h index 85263f3d2c8b..ed6ba4bebbeb 100644 --- a/framework/include/userobjects/PropertyReadFile.h +++ b/framework/include/userobjects/PropertyReadFile.h @@ -32,7 +32,7 @@ class PropertyReadFile : public GeneralUserObject PropertyReadFile(const InputParameters & parameters); virtual ~PropertyReadFile() {} - virtual void initialize() {} + virtual void initialize(); virtual void execute() {} virtual void finalize() {} @@ -119,7 +119,9 @@ class PropertyReadFile : public GeneralUserObject protected: /// Name of file containing property values - const std::string _prop_file_name; + const std::vector _prop_file_names; + /// Index of the file we last read + unsigned int & _current_file_index; /// Use DelimitedFileReader to read and store data from file MooseUtils::DelimitedFileReader _reader; diff --git a/framework/include/utils/DelimitedFileReader.h b/framework/include/utils/DelimitedFileReader.h index d92ddbc234f3..1d36dd0e0643 100644 --- a/framework/include/utils/DelimitedFileReader.h +++ b/framework/include/utils/DelimitedFileReader.h @@ -92,6 +92,9 @@ class DelimitedFileReader const std::string & getComment() const { return _row_comment; } ///@} + /// Set the file name, used to change the file to read from + void setFileName(const std::string & new_file) { _filename = new_file; } + /** * Return the column/row names. */ @@ -134,7 +137,7 @@ class DelimitedFileReader protected: /// The supplied filename. - const std::string _filename; + std::string _filename; /// Flag indicating if the file contains a header. HeaderFlag _header_flag; diff --git a/framework/src/userobjects/PropertyReadFile.C b/framework/src/userobjects/PropertyReadFile.C index 0add1f75153f..d61c85c36231 100644 --- a/framework/src/userobjects/PropertyReadFile.C +++ b/framework/src/userobjects/PropertyReadFile.C @@ -24,8 +24,11 @@ PropertyReadFile::validParams() { InputParameters params = GeneralUserObject::validParams(); params.addClassDescription("User Object to read property data from an external file and assign " - "to elements."); - params.addRequiredParam("prop_file_name", "Name of the property file name"); + "it to elements / nodes / subdomains etc."); + params.addRequiredParam>( + "prop_file_name", + "Name(s) of the property file name. If specifying multiple files, the next file will be read " + "at initialization right before every execution"); params.addRequiredParam("nprop", "Number of tabulated property values"); params.addParam( "nvoronoi", 0, "Number of voronoi tesselations/grains/nearest neighbor regions"); @@ -50,14 +53,23 @@ PropertyReadFile::validParams() "Periodic or non-periodic grain distribution: Default is non-periodic"); params.addParam( "use_zero_based_block_indexing", true, "Are the blocks numbered starting at zero?"); + + // Set an execution schedules to what makes sense currently + // We do not allow INITIAL because we read the file at construction + ExecFlagEnum & exec_enum = params.set("execute_on", true); + exec_enum.removeAvailableFlags(EXEC_INITIAL, EXEC_FINAL, EXEC_LINEAR, EXEC_NONLINEAR); + params.setDocString("execute_on", exec_enum.getDocString()); + return params; } PropertyReadFile::PropertyReadFile(const InputParameters & parameters) : GeneralUserObject(parameters), - _prop_file_name(getParam("prop_file_name")), - _reader(_prop_file_name), - + _prop_file_names(getParam>("prop_file_name")), + _current_file_index(declareRestartableData("file_index", 0)), + // index of files must be capped if restarting after having read all files + _reader( + _prop_file_names[std::min(_current_file_index, (unsigned int)_prop_file_names.size() - 1)]), _read_type(getParam("read_type").getEnum()), _use_random_tesselation(getParam("use_random_voronoi")), _rand_seed(getParam("rand_seed")), @@ -84,6 +96,24 @@ PropertyReadFile::PropertyReadFile(const InputParameters & parameters) _bounding_box = MooseUtils::buildBoundingBox(mesh_min, mesh_max); readData(); + _current_file_index++; + if (_prop_file_names.size() > 1 && _app.isRestarting()) + mooseError("Multiple files not supported with restart/recover"); +} + +void +PropertyReadFile::initialize() +{ + // Set then read new file, only if we have not reached the last file + if (_current_file_index < _prop_file_names.size()) + { + _reader.setFileName(_prop_file_names[_current_file_index]); + readData(); + _current_file_index++; + } + else if (_current_file_index == _prop_file_names.size()) + mooseDoOnce( + mooseInfo("Last file specified has been read. The file will no longer be updated.")); } void @@ -91,6 +121,8 @@ PropertyReadFile::readData() { if (_read_type == ReadTypeEnum::ELEMENT && _mesh.getMesh().allow_renumbering()) mooseWarning("CSV data is sorted by element, but mesh element renumbering is on, be careful!"); + if (_read_type == ReadTypeEnum::NODE && _mesh.getMesh().allow_renumbering()) + mooseWarning("CSV data is sorted by node, but mesh node renumbering is on, be careful!"); _reader.setFormatFlag(MooseUtils::DelimitedFileReader::FormatFlag::ROWS); _reader.read(); @@ -129,17 +161,25 @@ PropertyReadFile::readData() // make sure the data from file has enough rows and columns if (_reader.getData().size() < nobjects) - mooseError( - "Data in ", _prop_file_name, " does not have enough rows for ", nobjects, " objects."); + mooseError("Data in ", + _prop_file_names[_current_file_index], + " does not have enough rows for ", + nobjects, + " objects."); if (_reader.getData().size() > nobjects) mooseWarning("Data size in ", - _prop_file_name, + _prop_file_names[_current_file_index], " is larger than ", nobjects, " objects, some data will not be used."); for (unsigned int i = 0; i < nobjects; i++) if (_reader.getData(i).size() < _nprop) - mooseError("Row ", i, " in ", _prop_file_name, " has number of data less than ", _nprop); + mooseError("Row ", + i, + " in ", + _prop_file_names[_current_file_index], + " has number of data less than ", + _nprop); if (_read_type == ReadTypeEnum::VORONOI || _read_type == ReadTypeEnum::GRAIN) initVoronoiCenterPoints(); From 695da951c5b125511928d97b6a01344be506682a Mon Sep 17 00:00:00 2001 From: Guillaume Giudicelli Date: Thu, 21 Dec 2023 23:35:53 +0100 Subject: [PATCH 3/6] Add a test for multiple CSV files refs #25955 --- .../data_element_t2.csv | 16 ++++ .../gold/piecewise_constant_elem_multiple.e | Bin 0 -> 42668 bytes .../piecewise_constant_elem_multiple.i | 69 ++++++++++++++++++ .../piecewise_constant_from_csv/tests | 11 ++- 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 test/tests/functions/piecewise_constant_from_csv/data_element_t2.csv create mode 100644 test/tests/functions/piecewise_constant_from_csv/gold/piecewise_constant_elem_multiple.e create mode 100644 test/tests/functions/piecewise_constant_from_csv/piecewise_constant_elem_multiple.i diff --git a/test/tests/functions/piecewise_constant_from_csv/data_element_t2.csv b/test/tests/functions/piecewise_constant_from_csv/data_element_t2.csv new file mode 100644 index 000000000000..c6a3963487db --- /dev/null +++ b/test/tests/functions/piecewise_constant_from_csv/data_element_t2.csv @@ -0,0 +1,16 @@ +0,0,0.2 +0,0,1.6 +0,0,0.8 +0,0,1.8 +0,0,2 +1,0,2.2 +1,0,4.2 +1,0,6.2 +1,0,34.2 +1,0,48 +1,0,20 +1,0,0.2 +1,0,22 +1,0,34 +1,0,3.6 +1,0,-2 diff --git a/test/tests/functions/piecewise_constant_from_csv/gold/piecewise_constant_elem_multiple.e b/test/tests/functions/piecewise_constant_from_csv/gold/piecewise_constant_elem_multiple.e new file mode 100644 index 0000000000000000000000000000000000000000..207c0b72b2ab123ed49e06dd6cd0e6ceb5ba4c30 GIT binary patch literal 42668 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 IrcQhR58qs6%>V!Z literal 0 HcmV?d00001 diff --git a/test/tests/functions/piecewise_constant_from_csv/piecewise_constant_elem_multiple.i b/test/tests/functions/piecewise_constant_from_csv/piecewise_constant_elem_multiple.i new file mode 100644 index 000000000000..20f22fb90836 --- /dev/null +++ b/test/tests/functions/piecewise_constant_from_csv/piecewise_constant_elem_multiple.i @@ -0,0 +1,69 @@ +[Mesh] + allow_renumbering = false + [cmg] + type = CartesianMeshGenerator + dim = 2 + dx = '1.5 2.4 0.1' + dy = '1.3 0.9' + ix = '2 1 1' + iy = '1 3' + subdomain_id = '0 1 1 + 2 2 2' + [] +[] + +[AuxVariables] + [u] + family = MONOMIAL + order = CONSTANT + [] +[] + +[UserObjects] + [reader_element] + type = PropertyReadFile + prop_file_name = 'data_element.csv data_element_t2.csv' + read_type = 'element' + nprop = 3 # number of columns in CSV + execute_on = TIMESTEP_END + [] +[] + +[Functions] + [element] + type = PiecewiseConstantFromCSV + read_prop_user_object = 'reader_element' + read_type = 'element' + column_number = '2' + [] +[] + +[ICs] + [element] + type = FunctionIC + variable = 'u' + function = 'element' + [] +[] + +[AuxKernels] + [set_elem] + type = FunctionAux + variable = 'u' + function = 'element' + [] +[] + +[Problem] + solve = false + kernel_coverage_check = false +[] + +[Executioner] + type = Transient + num_steps = 2 +[] + +[Outputs] + exodus = true +[] diff --git a/test/tests/functions/piecewise_constant_from_csv/tests b/test/tests/functions/piecewise_constant_from_csv/tests index 271ae637492b..846c181ab868 100644 --- a/test/tests/functions/piecewise_constant_from_csv/tests +++ b/test/tests/functions/piecewise_constant_from_csv/tests @@ -50,11 +50,20 @@ input = 'piecewise_constant.i' exodiff = 'piecewise_constant_block.e' cli_args = 'ICs/active=block Outputs/file_base=piecewise_constant_block' - detail = 'with data sorted by blocks and with constant values on each block.' + detail = 'with data sorted by blocks and with constant values on each block,' recover = false # Function used at nodes allow_warnings = true [] + [multiple_files] + type = 'Exodiff' + input = 'piecewise_constant_elem_multiple.i' + exodiff = 'piecewise_constant_elem_multiple.e' + cli_args = 'Outputs/file_base=piecewise_constant_elem_multiple' + detail = 'with multiple CSV files read on every execution of the user object.' + # Cannot figure it out so it will error + recover = false + [] [] [errors] requirement = 'The system shall error out if' From 85f3ce4f8d824d40571f79a2f1dd12311de74309 Mon Sep 17 00:00:00 2001 From: Guillaume Giudicelli Date: Thu, 21 Dec 2023 23:40:49 +0100 Subject: [PATCH 4/6] Add documentation for multiple CSV files reading Improve function from CSV documentation refs #25955 --- .../source/functions/PiecewiseConstantFromCSV.md | 15 ++++++++++----- .../source/userobjects/PropertyReadFile.md | 8 ++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/framework/doc/content/source/functions/PiecewiseConstantFromCSV.md b/framework/doc/content/source/functions/PiecewiseConstantFromCSV.md index 650fb6dfd439..e9ebfbd88188 100644 --- a/framework/doc/content/source/functions/PiecewiseConstantFromCSV.md +++ b/framework/doc/content/source/functions/PiecewiseConstantFromCSV.md @@ -11,8 +11,9 @@ information from it. It can assume CSV data - is sorted by element-id, in which case, when the function is evaluated at a point, it will locate the element containing it then return the value for that element in the CSV file +- is sorted by node-id, in which case, when the function is evaluated at a point, it will locate the node at that point then return the value for that node in the CSV file - is sorted by blocks, in which case, when the function is evaluated at a point, it will locate the element containing it then return the value for that element's block in the CSV file -- defines an interpolation grid, in which case the function will locate the closest point in that interpolation grid, then return the value for that point in the CSV file +- defines an interpolation grid (voronoi [!param](/Functions/PiecewiseConstantFromCSV/read_type)), in which case the function will locate the closest point in that interpolation grid, then return the value for that point in the CSV file For the latter case, the first columns of the CSV data must define the coordinates of each point forming the interpolation grid. The number of columns used to define these coordinates @@ -22,13 +23,17 @@ must match the dimension of the mesh. When use data by block or by element, if there is multiple possibilities for the element to choose from, for example at a node, the element with the lowest ID will be used. +!alert note +The [!param](/Functions/PiecewiseConstantFromCSV/column_number) parameter assumes 0-based indexing of the columns in the CSV file. If you want the values from the leftmost column in the file, you must use a column number of `0`. + ## Example Input Syntax -In this example, we display three options for using CSV data to compute a function over an unstructured mesh: +In this example, we display four options for using CSV data to compute a function over an unstructured mesh: -- the `element` function, using the `reader_element` user object, assumes the CSV file is sorted by element ID, and returns the value of the element containing each point -- the `nearest` function, using the `reader_nearest` user object, finds the closest point defined in the CSV file, and returns the corresponding value -- the `block` function, using the `reader_block` user object, assumes the data in the CSV file is sorted by block, and returns the value corresponding to the block containing each point +- the `element` Function, using the `reader_element` user object, assumes the CSV file is sorted by element ID, and returns the value of the element containing each point +- the `node` Function, using the `reader_node` user object, assumes the CSV file is sorted by node ID, and returns the corresponding value at those nodes. Outside of these nodes, the function is currently set to error. +- the `nearest` Function, using the `reader_nearest` user object, finds the closest point defined in the CSV file, and returns the corresponding value +- the `block` Function, using the `reader_block` user object, assumes the data in the CSV file is sorted by block, and returns the value corresponding to the block containing each point !listing test/tests/functions/piecewise_constant_from_csv/piecewise_constant.i block=Functions UserObjects diff --git a/framework/doc/content/source/userobjects/PropertyReadFile.md b/framework/doc/content/source/userobjects/PropertyReadFile.md index 42182c71e82a..47fe6b45aef9 100644 --- a/framework/doc/content/source/userobjects/PropertyReadFile.md +++ b/framework/doc/content/source/userobjects/PropertyReadFile.md @@ -29,6 +29,14 @@ to the element centroid. An example of a MOOSE object using the `PropertyReadFile` is the [PiecewiseConstantFromCSV.md] function. +If specifying multiple files to the [!param](/UserObjects/PropertyReadFile/prop_file_name) +parameter, a new file will be read every time the object is initialized, which happens right before +user objects are executed. The [!param](/UserObjects/PropertyReadFile/execute_on) parameter should be used to control the frequency of these executions. The user object will always read the first file at construction time. During a restart, the user object will read the next file available. +If all data files have been read, the last file specified is used. + +!alert note +When using multiple files, please not the data from the files is not concatenated. Every time a new file is read, the old data is removed from consideration. + ## Example input syntax In this example input file, the `PropertyReadFile` user object is used to load data from a CSV file From 93338113fa4f2813f74e37962228cb67b60e76dc Mon Sep 17 00:00:00 2001 From: Guillaume Giudicelli Date: Tue, 2 Jan 2024 23:13:34 +0100 Subject: [PATCH 5/6] Address Daniel review mooseInfo is doonce already --- framework/src/userobjects/PropertyReadFile.C | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/userobjects/PropertyReadFile.C b/framework/src/userobjects/PropertyReadFile.C index d61c85c36231..d3a6c979ff4a 100644 --- a/framework/src/userobjects/PropertyReadFile.C +++ b/framework/src/userobjects/PropertyReadFile.C @@ -112,8 +112,7 @@ PropertyReadFile::initialize() _current_file_index++; } else if (_current_file_index == _prop_file_names.size()) - mooseDoOnce( - mooseInfo("Last file specified has been read. The file will no longer be updated.")); + mooseInfo("Last file specified has been read. The file will no longer be updated."); } void From 74fbb5b1c0bf6e7739d3f412fb41f10fc1e2fbdc Mon Sep 17 00:00:00 2001 From: Guillaume Giudicelli Date: Fri, 5 Jan 2024 14:15:17 +0100 Subject: [PATCH 6/6] Address Alex's review - keep track of file index within readData - dont read the file twice at construction then on initial Co-authored-by: Alex Lindsay Update framework/include/userobjects/PropertyReadFile.h Co-authored-by: Alex Lindsay --- .../functions/PiecewiseConstantFromCSV.md | 2 +- .../source/userobjects/PropertyReadFile.md | 4 ++-- .../include/userobjects/PropertyReadFile.h | 3 +++ framework/src/userobjects/PropertyReadFile.C | 20 +++++++++++++------ .../piecewise_constant_from_csv/tests | 2 -- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/framework/doc/content/source/functions/PiecewiseConstantFromCSV.md b/framework/doc/content/source/functions/PiecewiseConstantFromCSV.md index e9ebfbd88188..18730a393f88 100644 --- a/framework/doc/content/source/functions/PiecewiseConstantFromCSV.md +++ b/framework/doc/content/source/functions/PiecewiseConstantFromCSV.md @@ -13,7 +13,7 @@ It can assume CSV data - is sorted by element-id, in which case, when the function is evaluated at a point, it will locate the element containing it then return the value for that element in the CSV file - is sorted by node-id, in which case, when the function is evaluated at a point, it will locate the node at that point then return the value for that node in the CSV file - is sorted by blocks, in which case, when the function is evaluated at a point, it will locate the element containing it then return the value for that element's block in the CSV file -- defines an interpolation grid (voronoi [!param](/Functions/PiecewiseConstantFromCSV/read_type)), in which case the function will locate the closest point in that interpolation grid, then return the value for that point in the CSV file +- defines an interpolation grid, with the voronoi [!param](/Functions/PiecewiseConstantFromCSV/read_type), in which case the function will locate the closest point in that interpolation grid, then return the value for that point in the CSV file For the latter case, the first columns of the CSV data must define the coordinates of each point forming the interpolation grid. The number of columns used to define these coordinates diff --git a/framework/doc/content/source/userobjects/PropertyReadFile.md b/framework/doc/content/source/userobjects/PropertyReadFile.md index 47fe6b45aef9..318f20e871e1 100644 --- a/framework/doc/content/source/userobjects/PropertyReadFile.md +++ b/framework/doc/content/source/userobjects/PropertyReadFile.md @@ -31,11 +31,11 @@ An example of a MOOSE object using the `PropertyReadFile` is the [PiecewiseConst If specifying multiple files to the [!param](/UserObjects/PropertyReadFile/prop_file_name) parameter, a new file will be read every time the object is initialized, which happens right before -user objects are executed. The [!param](/UserObjects/PropertyReadFile/execute_on) parameter should be used to control the frequency of these executions. The user object will always read the first file at construction time. During a restart, the user object will read the next file available. +user objects are executed. The [!param](/UserObjects/PropertyReadFile/execute_on) parameter should be used to control the frequency of these executions. The user object will always read the first file at construction time, and, as an exception, will not read a new file on its first execution. If all data files have been read, the last file specified is used. !alert note -When using multiple files, please not the data from the files is not concatenated. Every time a new file is read, the old data is removed from consideration. +When using multiple files, please note the data from the files is not concatenated. Every time a new file is read, the old data is removed from consideration. ## Example input syntax diff --git a/framework/include/userobjects/PropertyReadFile.h b/framework/include/userobjects/PropertyReadFile.h index ed6ba4bebbeb..416196b367c9 100644 --- a/framework/include/userobjects/PropertyReadFile.h +++ b/framework/include/userobjects/PropertyReadFile.h @@ -155,4 +155,7 @@ class PropertyReadFile : public GeneralUserObject const unsigned int _nvoronoi; /// Number of blocks (for reading a CSV file with properties ordered by blocks) const unsigned int _nblock; + + /// To keep track of initialization to avoid reading the files twice + bool & _initialize_called_once; }; diff --git a/framework/src/userobjects/PropertyReadFile.C b/framework/src/userobjects/PropertyReadFile.C index d3a6c979ff4a..0b4cd5db3025 100644 --- a/framework/src/userobjects/PropertyReadFile.C +++ b/framework/src/userobjects/PropertyReadFile.C @@ -54,11 +54,13 @@ PropertyReadFile::validParams() params.addParam( "use_zero_based_block_indexing", true, "Are the blocks numbered starting at zero?"); - // Set an execution schedules to what makes sense currently + // Set an execution schedule to what makes sense currently // We do not allow INITIAL because we read the file at construction ExecFlagEnum & exec_enum = params.set("execute_on", true); exec_enum.removeAvailableFlags(EXEC_INITIAL, EXEC_FINAL, EXEC_LINEAR, EXEC_NONLINEAR); params.setDocString("execute_on", exec_enum.getDocString()); + // we must read the files as early as possible + params.set("force_preaux") = true; return params; } @@ -81,7 +83,8 @@ PropertyReadFile::PropertyReadFile(const InputParameters & parameters) _nprop(getParam("nprop")), _nvoronoi(isParamValid("ngrain") ? getParam("ngrain") : getParam("nvoronoi")), - _nblock(getParam("nblock")) + _nblock(getParam("nblock")), + _initialize_called_once(declareRestartableData("initialize_called", false)) { if (!_use_random_tesselation && parameters.isParamSetByUser("rand_seed")) paramError("rand_seed", @@ -96,20 +99,23 @@ PropertyReadFile::PropertyReadFile(const InputParameters & parameters) _bounding_box = MooseUtils::buildBoundingBox(mesh_min, mesh_max); readData(); - _current_file_index++; - if (_prop_file_names.size() > 1 && _app.isRestarting()) - mooseError("Multiple files not supported with restart/recover"); } void PropertyReadFile::initialize() { + // Since we read at construction, no need to re-read the file on first initialize + if (!_initialize_called_once) + { + _initialize_called_once = true; + return; + } + // Set then read new file, only if we have not reached the last file if (_current_file_index < _prop_file_names.size()) { _reader.setFileName(_prop_file_names[_current_file_index]); readData(); - _current_file_index++; } else if (_current_file_index == _prop_file_names.size()) mooseInfo("Last file specified has been read. The file will no longer be updated."); @@ -182,6 +188,8 @@ PropertyReadFile::readData() if (_read_type == ReadTypeEnum::VORONOI || _read_type == ReadTypeEnum::GRAIN) initVoronoiCenterPoints(); + + _current_file_index++; } void diff --git a/test/tests/functions/piecewise_constant_from_csv/tests b/test/tests/functions/piecewise_constant_from_csv/tests index 846c181ab868..a0c9a47fe1d5 100644 --- a/test/tests/functions/piecewise_constant_from_csv/tests +++ b/test/tests/functions/piecewise_constant_from_csv/tests @@ -61,8 +61,6 @@ exodiff = 'piecewise_constant_elem_multiple.e' cli_args = 'Outputs/file_base=piecewise_constant_elem_multiple' detail = 'with multiple CSV files read on every execution of the user object.' - # Cannot figure it out so it will error - recover = false [] [] [errors]