Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null/Constant Forcing Provider #601

Merged
merged 11 commits into from
Sep 21, 2023

Conversation

stcui007
Copy link
Contributor

@stcui007 stcui007 commented Aug 4, 2023

A "forcing" provider that provides no data. This--primarily--is such that a BMI module can act as the forcing provider, providing time-varying input data from any source that can be packaged and provided in a module.

Additions

  • NullForcingProvider class, implements DataProvider.

Removals

Changes

  • Makes "path" parameter in forcing section of realization config optional, as this is not required for NullForcingProvider.

Testing

  • Automated tests passing

Screenshots

Notes

Todos

  • Might be a documentation update needed to expose this, and perhaps to note that "path" is optional for at least one provider now.

Checklist

  • PR has an informative and human-readable title
  • Changes are limited to a single goal (no scope creep)
  • Code can be automatically merged (no conflicts)
  • Code follows project standards (link if applicable)
  • Passes all existing automated tests
  • Any change in functionality is tested
  • New functions are documented (with a description, list of inputs, and expected output)
  • Placeholder code is flagged / future todos are captured in comments
  • Project documentation has been updated (including the "Unreleased" section of the CHANGELOG)
  • Reviewers requested with the Reviewers tool ➡️

Testing checklist (automated report can be put here)

Target Environment support

  • Linux

Copy link
Contributor

@mattw-nws mattw-nws left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some things to work on here... I will look into the question about the path key a little later.

* @return Whether the param's value is an aggregate sum.
*/
//TODO this function doesn't seem being used
inline bool is_param_sum_over_time_step(const std::string& name) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method should probably throw also, since there are no variables... certainly none of the variables listed below here will be provided.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like it. Will test it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, on review... this function should probably not exist. Move the exception to is_property_sum_over_time_step directly (this is the method actually in the DataProvider interface) and delete is_param_sum_over_time_step (and its documentation comment above).

* @param name The name of the forcing param for which the current value is desired.
* @return Whether the param's value is an aggregate sum.
*/
//TODO this function doesn't seem being used
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this function should never get called if there are no variables to call it on, for sure. I think it gets called for other providers? But it could be put in for future capability. In either case, as mentioned below, in this provider it should probably throw an exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will test. Logically it should not be used on forcing variables retrieved via BMI.

* @param file_name Forcing file name
*/
// No file to read
void read_csv()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think this method should be entirely removed. Is there some reason we need to add a "precip" variable? Is there a need to have time in available_forcings? Unless it breaks things, the idea was that available_forcings (or, rather, whatever is returned from get_available_variable_names) should be empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to remove it entirely. but that cuased a problem. Somehow we need at least one available forcing variable names to the Formulation_Manager to retrieve the start and stop time. Otherwise, it causes a runtime error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. So, if this is the case, then we might need to move to the ZerosDataProvider as discussed in #569. However, I still wonder if this can be avoided. I think I know where that is coming from, let me try to find it.

std::string var_name = "precip";
std::string units = "";
auto wkf = data_access::WellKnownFields.find(var_name);
if(wkf != data_access::WellKnownFields.end()){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, are either time or precip found in WellKnownFields? I think not (AorcForcing.hpp)... so available_forcings probably is empty and this whole block is doing nothing. Right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, by precip I meant to use precip_rate. No sure if time is needed. I am trying to mimic a forcing file with some variable names here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if this provider returns any variables, it should not return one of the standard/AORC ones, because that will just interfere with (or at least confuse) getting the same variables from a BMI forcing provider. If we have to return some variable, it should be named zero or something as discussed in #569 .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. This function now has only one line of codes.

}

std::vector<std::string> available_forcings;
std::unordered_map<std::string, std::string> available_forcings_units;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If read_csv is removed then this variable will be unused and should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot remove read_csv as it stands now. May be a better name is needed. It seems some non-empty string variable is needed in the initialization process.

* @param index The index of the desired forcing time step from which to obtain the value.
* @return The particular param's value at the given forcing time step.
*/
inline double get_value_for_param_name(const std::string& name, int index) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it was only used internally in CsvPerFeatureForcingProvider and isn't used in this class, so should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will test it.

std::vector<time_t> time_epoch_vector;
int forcing_vector_index;

/// \todo: Are these used?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, there are several instance variables here that are no longer used and should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, agree.

@@ -302,12 +302,15 @@ namespace realization {

time_t get_variable_time_begin(const std::string &variable_name) {
std::string var_name = variable_name;
//std::cout << "availableData.size(): = " << availableData.size() << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove all commented-out debug prints from committed code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sure.

include/forcing/NullForcingProvider.hpp Outdated Show resolved Hide resolved
long record_duration() override {
//return time_epoch_vector[1] - time_epoch_vector[0];
//TODO find a more general way to set it
long timestep_size = 3600;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be 1 or even 0? It may not matter, but this provider doesn't really have a timestep.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll probably use 1 but will test 0 to see what it does.

@stcui007
Copy link
Contributor Author

stcui007 commented Aug 7, 2023 via email

@mattw-nws mattw-nws linked an issue Aug 7, 2023 that may be closed by this pull request
@mattw-nws mattw-nws mentioned this pull request Aug 7, 2023
11 tasks
@stcui007
Copy link
Contributor Author

stcui007 commented Aug 7, 2023 via email

@stcui007
Copy link
Contributor Author

stcui007 commented Aug 8, 2023 via email

@mattw-nws
Copy link
Contributor

I merged #624 ... I think this will eliminate the failure that occurs when there are no variables in the NullForcingProvider. Can you rebase on master now and try removing the dummy variable?

@stcui007
Copy link
Contributor Author

stcui007 commented Sep 5, 2023 via email

@stcui007 stcui007 force-pushed the null_forcing_provider branch from abc3b9e to 24bb61b Compare September 5, 2023 17:16
include/forcing/NullForcingProvider.hpp Show resolved Hide resolved
#include <UnitsHelper.hpp>

/**
* @brief Forcing class providing time-series precipiation forcing data to the model.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update this doc string to reflect that this forcing provider does not, in fact, provide any forcing data!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am on it.

@stcui007 stcui007 marked this pull request as ready for review September 8, 2023 17:54
@stcui007
Copy link
Contributor Author

stcui007 commented Sep 8, 2023 via email

Copy link
Contributor

@mattw-nws mattw-nws left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to try to prove that this works with a more real-world case--especially the get_data_begin_time/get_data_end_time return values. I'm getting with @hellkite500 to see if we can try this with the latest forcing modules from that workstream... meanwhile if you get stuck on other things have a look at these comments.

@@ -285,6 +285,7 @@ namespace realization {
for(std::map<std::string,std::shared_ptr<data_access::GenericDataProvider>>::iterator iter = availableData.begin(); iter != availableData.end(); ++iter)
{
var_name = iter->first;
//std::cout << "availableData: var_name = " << var_name << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this function in Bmi_Multi_Formulation almost certainly needs the same change as was done in #624 for the NullForcingProvider to not break things. Once this provider gets used, if Bmi_Multi_Formulation::get_variable_time_end is called, it will probably throw on line 302 here because no forcing variables will be found to return an end time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, agree.
There is also the same codes in record_duration() function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point, I thought I deleted many of the header lines. Don't know why they are still there. Will do.

include/forcing/NullForcingProvider.hpp Show resolved Hide resolved
@PhilMiller
Copy link
Contributor

PhilMiller commented Sep 18, 2023

Ditto my request on your earlier PR - please actually describe the changes, and fix the formatting of the PR description

Will work on it.

@mattw-nws
Copy link
Contributor

I added two minor commits, one just adjusts the example realization config to only use features already used in other realization configs (e.g. SLoTH, CFE, Noah), and the second includes an easy change to make the "path" optional in the realization config. @stcui007 look these over and see if you have any questions or comments.

@stcui007
Copy link
Contributor Author

I added two minor commits, one just adjusts the example realization config to only use features already used in other realization configs (e.g. SLoTH, CFE, Noah), and the second includes an easy change to make the "path" optional in the realization config. @stcui007 look these over and see if you have any questions or comments.

These looks fine to me. The addition of another realization configuration is useful.

@mattw-nws mattw-nws force-pushed the null_forcing_provider branch from 2a9fa2e to 04853cf Compare September 21, 2023 15:32
@mattw-nws mattw-nws self-requested a review September 21, 2023 15:49
@PhilMiller PhilMiller dismissed mattw-nws’s stale review September 21, 2023 16:09

Stale, addressed comments

@PhilMiller PhilMiller merged commit 5243209 into NOAA-OWP:master Sep 21, 2023
18 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NullDataProvider or ZerosDataProvider for forcing-less simulations
4 participants