From 9497d333d2cc6873794b966a65757894ebd68c47 Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:35:01 -0400 Subject: [PATCH 01/16] add builds for macOS and Windows, update actions versions tags to commit hashes, add security hardening --- .github/workflows/first_pull_request.yml | 2 +- .github/workflows/testing.yml | 124 +++++++++++++++++------ 2 files changed, 96 insertions(+), 30 deletions(-) diff --git a/.github/workflows/first_pull_request.yml b/.github/workflows/first_pull_request.yml index a0cb87e..9e155b3 100644 --- a/.github/workflows/first_pull_request.yml +++ b/.github/workflows/first_pull_request.yml @@ -10,7 +10,7 @@ jobs: name: Welcome runs-on: ubuntu-latest steps: - - uses: actions/github-script@v6 + - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | // Get a list of all issues created by the PR opener diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index b824f8f..5a3a689 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -15,48 +15,114 @@ jobs: run: shell: bash steps: - - name: Checkout - uses: actions/checkout@v4 + - name: Harden Runner + uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 + with: + egress-policy: audit + - name: Checkout Repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Install linters run: | sudo apt-get update sudo apt-get install uncrustify cppcheck iwyu - - uses: actions/setup-python@v4 - - name: Install pre-commit + - name: Set up Python3 + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + with: + python-version: '3.x' + - name: Run pre-commit hooks + uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 + + build-netcdf: + name: Build RavenHydroFramework binary (${{ matrix.build_type }}) + runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + build_type: [Debug, Release] + defaults: + run: + shell: bash + steps: + - name: Harden Runner + uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 + with: + egress-policy: audit + - name: Checkout Repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Install dependencies (Linux) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install libnetcdf-dev build-essential cmake + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install netcdf cmake wget + + - name: Fetch NetCDF CMake script + run: | + wget https://raw.githubusercontent.com/Kitware/VTK/master/CMake/FindNetCDF.cmake -P cmake + - name: Build + id: build + continue-on-error: true run: | - python -m pip install --upgrade pip - python -m pip install pre-commit - - name: Run pre-commit + cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + make -j4 + - name: Run tests + if: steps.build.outcome == 'success' run: | - pre-commit run --all-files + ./Raven + ./Raven -v build: name: Build RavenHydroFramework binary (${{ matrix.build_type }}) runs-on: ubuntu-latest strategy: matrix: - build_type: [Debug, Release] + os: [ ubuntu-latest, macos-latest, windows-latest ] + build_type: [ Debug, Release ] defaults: run: shell: bash steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install libnetcdf-dev build-essential cmake - - name: Fetch NetCDF CMake script - run: | - wget https://raw.githubusercontent.com/Kitware/VTK/master/CMake/FindNetCDF.cmake -P cmake - - name: Build - id: build - continue-on-error: true - run: | - cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - make -j4 - - name: Run tests - if: steps.build.outcome == 'success' - run: | - ./Raven - ./Raven -v + - name: Harden Runner + uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 + with: + egress-policy: audit + - name: Checkout Repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Install dependencies (Linux) + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install build-essential cmake + - name: Install dependencies (macOS) + if: matrix.os == 'macos-latest' + run: | + brew install cmake + - name: Install dependencies (Windows) + if: matrix.os == 'windows-latest' + run: | + choco install cmake + choco install ninja + + - name: Build + id: build + continue-on-error: true + run: | + cmake --build . --config {{ matrix.build_type }} -j 3 + + - name: Run tests (Linux and macOS) + if: steps.build.outcome == 'success' && matrix.os != 'windows-latest' + run: | + ./Raven + ./Raven -v + - name: Run tests (Windows) + if: steps.build.outcome == 'success' && matrix.os == 'windows-latest' + run: | + ./Raven.exe + ./Raven.exe -v + + From dec8068a963147cd6e99b4dafe6ed70da929cdbb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:39:19 +0000 Subject: [PATCH 02/16] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .github/workflows/testing.yml | 2 - src/CommonFunctions.cpp | 2 +- src/Decay.cpp | 6 +- src/DemandExpressionHandling.cpp | 294 +++++++++++++++---------------- src/DemandGroups.cpp | 2 +- src/DemandOptimization.cpp | 44 ++--- src/DemandOptimization.h | 162 ++++++++--------- src/Demands.h | 2 +- src/Diagnostics.cpp | 4 +- src/EnergyTransport.cpp | 4 +- src/GracefulEndStandalone.h | 4 +- src/LookupTable.cpp | 4 +- src/LookupTable.h | 4 +- src/OrographicCorrections.cpp | 2 +- src/ParseHRUFile.cpp | 2 +- src/ParseInput.cpp | 4 +- src/ParseManagementFile.cpp | 126 ++++++------- src/Raven.vcxproj | 2 +- src/Solvers.cpp | 4 +- src/StandardOutput.cpp | 4 +- src/SubBasin.cpp | 10 +- src/SubBasin.h | 6 +- 22 files changed, 346 insertions(+), 348 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 5a3a689..6bbe0b9 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -124,5 +124,3 @@ jobs: run: | ./Raven.exe ./Raven.exe -v - - diff --git a/src/CommonFunctions.cpp b/src/CommonFunctions.cpp index a2e8cdc..ebca9d2 100644 --- a/src/CommonFunctions.cpp +++ b/src/CommonFunctions.cpp @@ -520,7 +520,7 @@ int GetJulianDayFromMonthYear (const string &date_str, const int calendar) for (int mon=0;mon<12;mon++){ if (date_str.substr(0,3)==months[mon]){ if (mon<9){fulldate_str="0"; } - if (date_str.length()<=5){ //Apr-1 + if (date_str.length()<=5){ //Apr-1 fulldate_str=fulldate_str+to_string(mon+1)+"-0"+date_str.substr(4, 1); } else{ //Apr-01 or Apr-23 diff --git a/src/Decay.cpp b/src/Decay.cpp index 9d4b63d..70b77b5 100644 --- a/src/Decay.cpp +++ b/src/Decay.cpp @@ -112,7 +112,7 @@ void CmvDecay::GetRatesOfChange(const double *state_vars, { //dm/dt=-km double decay_coeff = _pTransModel->GetGeochemParam(PAR_DECAY_COEFF,_constit_ind,ii,_process_ind,pHRU); - if(decay_coeff!=NOT_SPECIFIED) { + if(decay_coeff!=NOT_SPECIFIED) { rates[q]= decay_coeff*mass; } } @@ -121,7 +121,7 @@ void CmvDecay::GetRatesOfChange(const double *state_vars, { //dm/dt=-J double loss_rate = _pTransModel->GetGeochemParam(PAR_MASS_LOSS_RATE,_constit_ind,ii,_process_ind,pHRU); - if(loss_rate!=NOT_SPECIFIED) { + if(loss_rate!=NOT_SPECIFIED) { rates[q]= min(loss_rate,mass/Options.timestep); } } @@ -140,7 +140,7 @@ void CmvDecay::GetRatesOfChange(const double *state_vars, else if(_dtype==DECAY_DENITRIF) { double decay_coeff = _pTransModel->GetGeochemParam(PAR_DECAY_COEFF,_constit_ind,ii,_process_ind,pHRU); - if(decay_coeff!=NOT_SPECIFIED) { + if(decay_coeff!=NOT_SPECIFIED) { double temp=pHRU->GetForcingFunctions()->temp_ave; double c1 =1.0; diff --git a/src/DemandExpressionHandling.cpp b/src/DemandExpressionHandling.cpp index 5eed1bd..cc82189 100644 --- a/src/DemandExpressionHandling.cpp +++ b/src/DemandExpressionHandling.cpp @@ -10,7 +10,7 @@ const int MAX_TERMS_PER_GROUP=10; ////////////////////////////////////////////////////////////////// /// constructor and destructor of expression term structure // -expressionTerm::expressionTerm() +expressionTerm::expressionTerm() { type =TERM_UNKNOWN; mult =1.0; @@ -25,7 +25,7 @@ expressionTerm::expressionTerm() p_index =DOESNT_EXIST; HRU_index=DOESNT_EXIST; SV_index =DOESNT_EXIST; - + is_nested =false; nested_ind1=DOESNT_EXIST; nested_ind2=DOESNT_EXIST; @@ -66,7 +66,7 @@ manConstraint::manConstraint() penalty_over=1.0; slack_ind1=DOESNT_EXIST; slack_ind2=DOESNT_EXIST; - + penalty_value=0; nOperRegimes=1; @@ -82,7 +82,7 @@ manConstraint::~manConstraint() delete [] pOperRegimes; nOperRegimes=0; } -void manConstraint::AddOperatingRegime(op_regime* pOR, bool first) +void manConstraint::AddOperatingRegime(op_regime* pOR, bool first) { if ((nOperRegimes==1) && (first)){ pOperRegimes[0]->reg_name=pOR->reg_name; @@ -99,7 +99,7 @@ void manConstraint::AddOpCondition(exp_condition* pCond) ExitGracefully("management_constraint::AddOpCondition: adding NULL condition",BAD_DATA_WARN); } } -void manConstraint::AddExpression(expressionStruct* pExp) +void manConstraint::AddExpression(expressionStruct* pExp) { pOperRegimes[nOperRegimes-1]->pExpression=pExp; ExitGracefullyIf(pExp==NULL,"manConstraint::AddExpression: NULL Expression",RUNTIME_ERR); @@ -132,11 +132,11 @@ double CDemandOptimizer::GetControlVariable(const string s) const } ////////////////////////////////////////////////////////////////// -/// \brief retrieves value of decision variable index +/// \brief retrieves value of decision variable index /// \params s [in] - string /// \returns index of named user-specified decision var, or DOESNT_EXIST if not found // -int CDemandOptimizer::GetUserDVIndex(const string s) const +int CDemandOptimizer::GetUserDVIndex(const string s) const { int ct=0; for (int i = 0; i < _nDecisionVars; i++) { @@ -151,14 +151,14 @@ int CDemandOptimizer::GetUserDVIndex(const string s) const /// \brief retrieves index of native decision variable starting with ! /// \params s [in] - string /// \returns index of named decision variable, or DOESNT_EXIST if not found -/// supports !Qxxx, !Q.name, !hxxx, !Ixxx, !Dxxx, !Cxxx +/// supports !Qxxx, !Q.name, !hxxx, !Ixxx, !Dxxx, !Cxxx // int CDemandOptimizer::GetIndexFromDVString(string s) const //String in format !Qxxx or !Q.name but not !Qxx[n] { - if ((s[1] == 'Q') || (s[1] == 'h') || (s[1]=='I')) //Subbasin-indexed - { + if ((s[1] == 'Q') || (s[1] == 'h') || (s[1]=='I')) //Subbasin-indexed + { if (s[2] == '.') { - string name=s.substr(3); + string name=s.substr(3); CSubBasin *pSB; int p; for (int pp = 0; pp < _pModel->GetNumSubBasins(); pp++) { @@ -171,12 +171,12 @@ int CDemandOptimizer::GetIndexFromDVString(string s) const //String in format !Q return DOESNT_EXIST; } else{ - string sbid=s.substr(2); - long SBID=s_to_l(sbid.c_str()); + string sbid=s.substr(2); + long SBID=s_to_l(sbid.c_str()); return _pModel->GetSubBasinIndex(SBID); } } - else if ((s[1]=='D') || (s[1]=='C')) + else if ((s[1]=='D') || (s[1]=='C')) { string demandID; if (s[2] == '.') {demandID=s.substr(3);} //!D.FarmerBobsDemand @@ -186,7 +186,7 @@ int CDemandOptimizer::GetIndexFromDVString(string s) const //String in format !Q return DOESNT_EXIST; } ////////////////////////////////////////////////////////////////// -/// \brief returns number of user-specified decision variables +/// \brief returns number of user-specified decision variables // int CDemandOptimizer::GetNumUserDVs() const{ return _nUserDecisionVars; @@ -194,31 +194,31 @@ int CDemandOptimizer::GetNumUserDVs() const{ ////////////////////////////////////////////////////////////////// /// \brief enum to string routines // -string TermTypeToString(termtype t) +string TermTypeToString(termtype t) { - if (t==TERM_DV ){return "TERM_DV"; } - if (t==TERM_TS ){return "TERM_TS"; } - if (t==TERM_LT ){return "TERM_LT"; } - if (t==TERM_HRU ){return "TERM_HRU";} + if (t==TERM_DV ){return "TERM_DV"; } + if (t==TERM_TS ){return "TERM_TS"; } + if (t==TERM_LT ){return "TERM_LT"; } + if (t==TERM_HRU ){return "TERM_HRU";} if (t==TERM_SB ){return "TERM_SB"; } - if (t==TERM_CONST ){return "TERM_CONST"; } - if (t==TERM_HISTORY){return "TERM_HISTORY"; } - if (t==TERM_MAX ){return "TERM_MAX"; } - if (t==TERM_MIN ){return "TERM_MIN"; } - if (t==TERM_CONVERT){return "TERM_CONVERT"; } + if (t==TERM_CONST ){return "TERM_CONST"; } + if (t==TERM_HISTORY){return "TERM_HISTORY"; } + if (t==TERM_MAX ){return "TERM_MAX"; } + if (t==TERM_MIN ){return "TERM_MIN"; } + if (t==TERM_CONVERT){return "TERM_CONVERT"; } if (t==TERM_CUMUL ){return "TERM_CUMUL";} if (t==TERM_CUMUL_TS){return "TERM_CUMUL_TS";} - if (t==TERM_UNKNOWN){return "TERM_UNKNOWN"; } + if (t==TERM_UNKNOWN){return "TERM_UNKNOWN"; } return "TERM_UNKNOWN"; } -string DVTypeToString(dv_type t) +string DVTypeToString(dv_type t) { - if (t==DV_QOUT ){return "DV_QOUT"; } - if (t==DV_QOUTRES ){return "DV_QOUTRES"; } - if (t==DV_STAGE ){return "DV_STAGE"; } - if (t==DV_DELIVERY){return "DV_DELIVERY"; } - if (t==DV_SLACK ){return "DV_SLACK"; } - if (t==DV_USER ){return "DV_USER"; } + if (t==DV_QOUT ){return "DV_QOUT"; } + if (t==DV_QOUTRES ){return "DV_QOUTRES"; } + if (t==DV_STAGE ){return "DV_STAGE"; } + if (t==DV_DELIVERY){return "DV_DELIVERY"; } + if (t==DV_SLACK ){return "DV_SLACK"; } + if (t==DV_USER ){return "DV_USER"; } return "DV_UNKNOWN"; } ////////////////////////////////////////////////////////////////// @@ -265,9 +265,9 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t size_t i1=s.find("["); size_t i2=s.find("]"); size_t i3=s.find("("); - + if ((i1 != NPOS) && (i2 != NPOS) && (i3==NPOS)) { //array NOT nested within function - string contents=s.substr(i1+1,i2-i1); + string contents=s.substr(i1+1,i2-i1); //cout<<" BRACKET CONTENTS: ["<timeshift=-n; term->p_index=p; return true; - - } + + } } else { warn="ConvertToExpression:: Unparseable term in expression starting with ! - only !Q, !D, or !h currently supported. "+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); - return false; + return false; } } //---------------------------------------------------------------------- - else if (s[0]=='!') //decision variable e.g., !Q234 or !D42a + else if (s[0]=='!') //decision variable e.g., !Q234 or !D42a { - if ((s[1] == 'Q') || (s[1] == 'h') || (s[1]=='I')) //Subbasin-indexed + if ((s[1] == 'Q') || (s[1] == 'h') || (s[1]=='I')) //Subbasin-indexed { int p=GetIndexFromDVString(s); if (p == DOESNT_EXIST) { @@ -338,38 +338,38 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t WriteWarning(warn.c_str(),true); return false; } - if ((s[1]=='Q') && (_aResIndices[p] != DOESNT_EXIST)) + if ((s[1]=='Q') && (_aResIndices[p] != DOESNT_EXIST)) { - term->DV_ind=GetDVColumnInd(DV_QOUTRES, _aResIndices[p]); - } - else if ((s[1]=='Q') && (_aSBIndices[p] != DOESNT_EXIST)) + term->DV_ind=GetDVColumnInd(DV_QOUTRES, _aResIndices[p]); + } + else if ((s[1]=='Q') && (_aSBIndices[p] != DOESNT_EXIST)) { - term->DV_ind=GetDVColumnInd(DV_QOUT, _aSBIndices[p]); - } + term->DV_ind=GetDVColumnInd(DV_QOUT, _aSBIndices[p]); + } else if (s[1]=='I') { - term->DV_ind=GetDVColumnInd(DV_QOUT, _aSBIndices[p]); - } + term->DV_ind=GetDVColumnInd(DV_QOUT, _aSBIndices[p]); + } else if (s[1]=='h') { - term->DV_ind=GetDVColumnInd(DV_STAGE, _aResIndices[p]); + term->DV_ind=GetDVColumnInd(DV_STAGE, _aResIndices[p]); } term->p_index=p;//not needed? - } - else if ((s[1]=='D') || (s[1]=='C')) //demand indexed + } + else if ((s[1]=='D') || (s[1]=='C')) //demand indexed { int d=GetIndexFromDVString(s); if (d == DOESNT_EXIST) { warn = "ConvertToExpressionTerm: invalid demand ID or demand from disabled subbasin used in expression " +warnstring +": goal/constraint will be ignored"; WriteWarning(warn.c_str(),true); - return false; + return false; } if (s[1]=='D') { term->DV_ind=GetDVColumnInd(DV_DELIVERY,d); } - else if (s[1]=='C') + else if (s[1]=='C') { term->type=TERM_CUMUL; term->p_index=d; @@ -380,10 +380,10 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t warn="ConvertToExpression:: Unparseable term in expression starting with ! - only !Q, !I, !D, or !h currently supported. "+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); } - + term->type=TERM_DV; return true; - } + } //---------------------------------------------------------------------- else if (s.find("@ts(") != NPOS) //time series (e.g., @ts(my_time_series,n) { @@ -400,7 +400,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t warn="ConvertToExpressionTerm: missing end parentheses in @ts expression"+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); } - if ((is != NPOS) && (ie != NPOS)) + if ((is != NPOS) && (ie != NPOS)) { bool found=false; name = s.substr(is+4,ie-(is+4)); @@ -411,7 +411,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t term->pTS = _pUserTimeSeries[i]; found=true; } - } + } term->timeshift=index; term->type =TERM_TS; if (!found) { @@ -436,7 +436,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t warn="ConvertToExpressionTerm: missing end parentheses in @cumul expression"+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); } - if ((is != NPOS) && (ie != NPOS)) + if ((is != NPOS) && (ie != NPOS)) { bool found=false; name = s.substr(is+7,ie-(is+7)); @@ -447,7 +447,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t term->pTS = _pUserTimeSeries[i]; found=true; } - } + } term->timeshift=index; term->type =TERM_CUMUL_TS; if (!found) { @@ -472,7 +472,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t warn="ConvertToExpressionTerm: missing end paretheses in @lookup expression"+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); } - if ((is != NPOS) && (ie != NPOS)) + if ((is != NPOS) && (ie != NPOS)) { bool found=false; name = s.substr(is+8,ie-(is+8)); @@ -483,7 +483,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t term->pLT = _pUserLookupTables[i]; found=true; } - } + } term->nested_exp1 =x_in; term->type =TERM_LT; if (!found) { @@ -509,7 +509,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t warn="ConvertToExpressionTerm: missing end paretheses in @HRU_var expression"+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); } - if ((is != NPOS) && (ie != NPOS)) + if ((is != NPOS) && (ie != NPOS)) { bool found=false; sv_name = s.substr(is+9,ie-(is+9)); @@ -528,7 +528,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t return false; } - term->SV_index=_pModel->GetStateVarIndex(sv,lay); + term->SV_index=_pModel->GetStateVarIndex(sv,lay); term->HRU_index=_pModel->GetHRUByID(HRUID)->GetGlobalIndex(); term->type=TERM_HRU; } @@ -549,7 +549,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t warn="ConvertToExpressionTerm: missing end paretheses in @SB_var expression"+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); } - if ((is != NPOS) && (ie != NPOS)) + if ((is != NPOS) && (ie != NPOS)) { bool found=false; sv_name = s.substr(is+8,ie-(is+8)); @@ -557,7 +557,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t int lay=DOESNT_EXIST; sv_type sv=_pModel->GetStateVarInfo()->StringToSVType(sv_name,lay,false); - + if (sv== UNRECOGNIZED_SVTYPE) { warn="ConvertToExpression: requested state variable in in @SB_var command "+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); @@ -568,7 +568,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t ExitGracefully(warn.c_str(), BAD_DATA_WARN); return false; } - term->SV_index=_pModel->GetStateVarIndex(sv,lay); + term->SV_index=_pModel->GetStateVarIndex(sv,lay); term->p_index=_pModel->GetSubBasinByID(SBID)->GetGlobalIndex(); term->type=TERM_SB; } @@ -591,7 +591,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t ExitGracefully(warn.c_str(), BAD_DATA_WARN); return false; } - if ((is != NPOS) && (ie != NPOS)) + if ((is != NPOS) && (ie != NPOS)) { x_in = s.substr(is+5,ie-(is+5)); y_in = s.substr(ie+1,ip-(ie+1)); @@ -618,7 +618,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t ExitGracefully(warn.c_str(), BAD_DATA_WARN); return false; } - if ((is != NPOS) && (ie != NPOS)) + if ((is != NPOS) && (ie != NPOS)) { x_in = s.substr(is+5,ie-(is+5)); y_in = s.substr(ie+1,ip-(ie+1)); @@ -645,7 +645,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t ExitGracefully(warn.c_str(), BAD_DATA_WARN); return false; } - if ((is != NPOS) && (ie != NPOS)) + if ((is != NPOS) && (ie != NPOS)) { bool found=false; x_in = s.substr(is+9,ie-(is+9)); @@ -664,19 +664,19 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t } } //---------------------------------------------------------------------- - else if (GetNamedConstant(s)!=RAV_BLANK_DATA) // named constant + else if (GetNamedConstant(s)!=RAV_BLANK_DATA) // named constant { term->type=TERM_CONST; term->value=GetNamedConstant(s); } //---------------------------------------------------------------------- - else if (GetControlVariable(s) != RAV_BLANK_DATA) // control variable + else if (GetControlVariable(s) != RAV_BLANK_DATA) // control variable { term->type=TERM_CONST; term->value=GetControlVariable(s); } //---------------------------------------------------------------------- - else if (GetUserDVIndex(s)!=DOESNT_EXIST) // user-defined decision variable + else if (GetUserDVIndex(s)!=DOESNT_EXIST) // user-defined decision variable { term->DV_ind=GetDVColumnInd(DV_USER, GetUserDVIndex(s)); term->type=TERM_DV; @@ -700,14 +700,14 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t /// \brief Parses demand constraint expression of form (e.g.,) A * B(x) * C + D * E - F = G * H(t) [NO PARENTHESES!] /// \params s [in] - array of strings of [size: Len] /// \param Len [in] - length of string array -/// \param lineno [in] - line number of original expression in input file filename, referenced in errors -/// \param filename [in] - name of input file, referenced in errors +/// \param lineno [in] - line number of original expression in input file filename, referenced in errors +/// \param filename [in] - name of input file, referenced in errors /// \returns expressionStruct: a 2D array of pointers to grouped terms (e.g., [0]:[A,B,C], [1]:[D,E], [2]:[F], [3]:[G,H] for above example) // -expressionStruct *CDemandOptimizer::ParseExpression(const char **s, +expressionStruct *CDemandOptimizer::ParseExpression(const char **s, const int Len, const int lineno, - const string filename) const + const string filename) const { int rhs_ind=-1; exptype type [MAX_EXP_GROUPS]; @@ -722,17 +722,17 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s, { type[i]=EXP; if ((s[i][0]=='+') || (s[i][0]=='-') || (s[i][0]=='*') || (s[i][0]=='/') || (s[i][0]=='=') || (s[i][0]=='<') || (s[i][0]=='>')){ - type[i] = EXP_OP; + type[i] = EXP_OP; if ((i > 1) && (type[i - 1] == EXP_OP)) { ExitGracefully("ParseExpression: cannot have consecutive math operators in an expression.",BAD_DATA_WARN); } - } + } if (s[i-1][0]=='/'){type[i]=EXP_INV; } if ((s[i][0]=='=') || (s[i][0]=='~')){ comp=COMPARE_IS_EQUAL; rhs_ind=i; nComps++; } - else if (s[i][0]=='<'){//works for <=, too + else if (s[i][0]=='<'){//works for <=, too comp=COMPARE_LESSTHAN; rhs_ind=i; nComps++; } else if (s[i][0]=='>'){ //works for >=, too @@ -746,7 +746,7 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s, ExitGracefully("ParseExpression: missing comparison operator (e.g., <, >, =) in expression",BAD_DATA_WARN); } - //TMP DEBUG + //TMP DEBUG /*cout << "parse expression (2) comparison type = " << comp << " rhs ind= " << rhs_ind << " types="; for (int i = 1; i < Len; i++) //starts at 1 - first term is :Expression or :DefineDecisionVariable { @@ -755,15 +755,15 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s, if (type[i]==EXP_INV){ cout<<" INV"; } } cout<mult=1.0; @@ -771,12 +771,12 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s, if (!valid){ return NULL; } - - //TMP DEBUG + + //TMP DEBUG //cout<<" TERM["<DV_ind << endl; - if ((i>rhs_ind) && (k==0)){terms[j][k]->mult*=-1.0; } //only multiply leading term by -1 to move to LHS - if ((s[i-1][0]=='-') && (k==0)){terms[j][k]->mult*=-1.0; } //and reverse if preceded with minus sign + if ((i>rhs_ind) && (k==0)){terms[j][k]->mult*=-1.0; } //only multiply leading term by -1 to move to LHS + if ((s[i-1][0]=='-') && (k==0)){terms[j][k]->mult*=-1.0; } //and reverse if preceded with minus sign if (terms[j][k]->type == TERM_DV) { DVcount++; @@ -786,8 +786,8 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s, } } terms[j][k]->reciprocal=(type[i] == EXP_INV); - - //Handle nested expressions + + //Handle nested expressions if (terms[j][k]->nested_exp1 != "") { terms[j][k ]->nested_ind1=k+1; @@ -806,13 +806,13 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s, if (terms[j][k]->nested_exp2 != "") { terms[j][k ]->nested_ind2=k+2; - + terms[j][k+2] = new expressionTerm(); terms[j][k+2]->mult=1.0; terms[j][k+2]->is_nested=true; valid=ConvertToExpressionTerm(terms[j][k]->nested_exp2, terms[j][k + 2],lineno, filename); if (!valid){return NULL;} - + if (terms[j][k + 2]->type == TERM_DV) { ExitGracefully("ParseExpression: decision variable found nested in functional expression (min or max). Cannot handle non-linear expressions.",BAD_DATA_WARN); return NULL; @@ -823,15 +823,15 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s, }//end nested expressions k++; } - else if ((i != 1) && (s[i][0]!='*') && (s[i][0]!='/')) { // +, -, or = operator - expression product term finished and expression doesn't start with + or - + else if ((i != 1) && (s[i][0]!='*') && (s[i][0]!='/')) { // +, -, or = operator - expression product term finished and expression doesn't start with + or - termspergrp[j]=k; j++; k=0; DVcount=0; } } - termspergrp[j]=k; //last group + termspergrp[j]=k; //last group j++; - //copy to new expressionStruct structure + //copy to new expressionStruct structure //--------------------------------------------------------------- int nGroups=j; expressionStruct *tmp; @@ -863,7 +863,7 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s, /// \brief writes out explicit details about expressionStructure contents /// called in ParseManagementFile under Noisy mode // -void SummarizeExpression(const char **s, const int Len, expressionStruct* exp) +void SummarizeExpression(const char **s, const int Len, expressionStruct* exp) { if (exp==NULL){return;} cout<<"*"<pOperRegimes[k]->nConditions; j++) + + //Check if conditionals are satisfied + for (int j = 0; j < pC->pOperRegimes[k]->nConditions; j++) { exp_condition *pCond=pC->pOperRegimes[k]->pConditions[j]; if (pCond->pExp != NULL) { @@ -900,7 +900,7 @@ bool CDemandOptimizer::CheckGoalConditions(const int ii, const int k, const time else { dv_value=0.0; - if (pCond->dv_name == "DAY_OF_YEAR") + if (pCond->dv_name == "DAY_OF_YEAR") { dv_value=tt.julian_day; } @@ -908,17 +908,17 @@ bool CDemandOptimizer::CheckGoalConditions(const int ii, const int k, const time { dv_value=(double)(tt.month); } - else if (pCond->dv_name == "DATE") + else if (pCond->dv_name == "DATE") { dv_value=0; //handled below } - else if (pCond->dv_name[0] == '!') //decision variable - { + else if (pCond->dv_name[0] == '!') //decision variable + { char tmp =pCond->dv_name[1]; - long ind=pCond->p_index; - + long ind=pCond->p_index; + if (tmp == 'Q') { dv_value=_pModel->GetSubBasinByID(ind)->GetOutflowRate(); } @@ -934,8 +934,8 @@ bool CDemandOptimizer::CheckGoalConditions(const int ii, const int k, const time else if (tmp == 'D') { dv_value = _pModel->GetSubBasinByID(_aDemandSBIDs[ind])->GetDemandDelivery(_aDemandIndices[ind]); } - //todo: support !q, !d, !B, !E, !F, !T - } + //todo: support !q, !d, !B, !E, !F, !T + } else {//handle user specified DVs and control variables int i=GetUserDVIndex(pCond->dv_name); if (i == DOESNT_EXIST) { @@ -948,7 +948,7 @@ bool CDemandOptimizer::CheckGoalConditions(const int ii, const int k, const time } if (!found){ - ExitGracefully("CheckGoalConditions: Unrecognized varible on left hand side of :Condition statement ",BAD_DATA_WARN); + ExitGracefully("CheckGoalConditions: Unrecognized varible on left hand side of :Condition statement ",BAD_DATA_WARN); return false; } } @@ -974,9 +974,9 @@ bool CDemandOptimizer::CheckGoalConditions(const int ii, const int k, const time } } - if (comp == COMPARE_BETWEEN) + if (comp == COMPARE_BETWEEN) { - if (pCond->dv_name == "DAY_OF_YEAR") { //handles wraparound + if (pCond->dv_name == "DAY_OF_YEAR") { //handles wraparound if ( v2 < v ){ if ((dv_value > v ) && (dv_value < v2)){return false;} } @@ -1002,20 +1002,20 @@ bool CDemandOptimizer::CheckGoalConditions(const int ii, const int k, const time } } } - return true; //all conditionals satisfied + return true; //all conditionals satisfied } ////////////////////////////////////////////////////////////////// -/// adds constraint ii to LP solve problem statement +/// adds constraint ii to LP solve problem statement /// \params ii [in] - index of constraint in _pConstraints array -/// \param k - index of operating regime in _pConstraints[ii] +/// \param k - index of operating regime in _pConstraints[ii] /// \param pLinProg [out] - pointer to valid lpsolve structure to be modified -/// \param tt [in] - time structure -/// \param *col_ind [in] - empty array (with memory reserved) for storing column indices +/// \param tt [in] - time structure +/// \param *col_ind [in] - empty array (with memory reserved) for storing column indices /// \param *row_val [in] - empty array (with memory reserved) for storing row values // #ifdef _LPSOLVE_ -void CDemandOptimizer::AddConstraintToLP(const int ii, const int k, lp_lib::lprec* pLinProg, const time_struct &tt, int *col_ind, double *row_val) const +void CDemandOptimizer::AddConstraintToLP(const int ii, const int k, lp_lib::lprec* pLinProg, const time_struct &tt, int *col_ind, double *row_val) const { double coeff; int i=0; @@ -1029,17 +1029,17 @@ void CDemandOptimizer::AddConstraintToLP(const int ii, const int k, lp_lib::lpre manConstraint *pC=_pConstraints[ii]; expressionStruct *pE= pC->pOperRegimes[k]->pExpression; - + RHS=0.0; for (int j = 0; j < pE->nGroups; j++) { coeff=1.0; group_has_dv=false; DV_ind=DOESNT_EXIST; - + for (int k = 0; k < pE->nTermsPerGrp[j]; k++) { - if (pE->pTerms[j][k]->type == TERM_DV) + if (pE->pTerms[j][k]->type == TERM_DV) { DV_ind=pE->pTerms[j][k]->DV_ind; group_has_dv=true; @@ -1050,11 +1050,11 @@ void CDemandOptimizer::AddConstraintToLP(const int ii, const int k, lp_lib::lpre term=EvaluateTerm(pE->pTerms[j], k, tt.model_time); if (term==RAV_BLANK_DATA){constraint_valid=false;} - if (pE->pTerms[j][k]->reciprocal == true) + if (pE->pTerms[j][k]->reciprocal == true) { coeff /= (pE->pTerms[j][k]->mult) * term; ExitGracefullyIf(term==0.0, "AddConstraintToLP: Divide by zero error in evaluating :Expression with division term",BAD_DATA); - } + } else { coeff *= (pE->pTerms[j][k]->mult) * term; } @@ -1093,12 +1093,12 @@ void CDemandOptimizer::AddConstraintToLP(const int ii, const int k, lp_lib::lpre retval = lp_lib::add_constraintex(pLinProg,i,row_val,col_ind,constr_type,RHS); ExitGracefullyIf(retval==0,"AddConstraintToLP::Error adding user-specified constraint/goal",RUNTIME_ERR); } -#endif +#endif ////////////////////////////////////////////////////////////////// -/// evaluates conditional expression +/// evaluates conditional expression /// \params pE [in] - conditional expression -/// \param t [in] - current model time +/// \param t [in] - current model time /// repeatedly calls EvaluateTerm() /// \returns true if expression is satisfied // @@ -1112,10 +1112,10 @@ bool CDemandOptimizer::EvaluateConditionExp(const expressionStruct* pE,const dou for (int j = 0; j < pE->nGroups; j++) { coeff=1.0; - + for (int k = 0; k < pE->nTermsPerGrp[j]; k++) { - if (pE->pTerms[j][k]->type == TERM_DV) + if (pE->pTerms[j][k]->type == TERM_DV) { ExitGracefully("EvaluateConditionalExp: conditional expressions cannot contain decision variables",BAD_DATA); } @@ -1124,11 +1124,11 @@ bool CDemandOptimizer::EvaluateConditionExp(const expressionStruct* pE,const dou term=EvaluateTerm(pE->pTerms[j], k, t); if (term==RAV_BLANK_DATA){return true;} //condition assumed satisfied if no data in conditional - if (pE->pTerms[j][k]->reciprocal == true) + if (pE->pTerms[j][k]->reciprocal == true) { coeff /= (pE->pTerms[j][k]->mult) * term; ExitGracefullyIf(term==0.0, "EvaluateConditionExp: Divide by zero error in evaluating :Condition expression with division term",BAD_DATA); - } + } else { coeff *= (pE->pTerms[j][k]->mult) * term; } @@ -1144,7 +1144,7 @@ bool CDemandOptimizer::EvaluateConditionExp(const expressionStruct* pE,const dou } ////////////////////////////////////////////////////////////////// -/// evaluates term in constraint/goal expression to numerical value (unless term is DV) +/// evaluates term in constraint/goal expression to numerical value (unless term is DV) /// \params pTerms [in] - pointer to array of terms in expression group (e.g., (A*B*C(D,E) stored as [A,B,C,D,E]) /// \param k [in] index of term to be evaluated (e.g., 2 would correspond to C) /// \param t [in] current model time @@ -1159,12 +1159,12 @@ double CDemandOptimizer::EvaluateTerm(expressionTerm **pTerms,const int k, const int kk; int p; const expressionTerm *pT=pTerms[k]; - - if (pT->type == TERM_DV) + + if (pT->type == TERM_DV) { //do nothing - can't evaluate ExitGracefully("CDemandOptimizer::EvaluateTerm: trying to expand out active decision variable",RUNTIME_ERR); - return -1; + return -1; } else if (pT->type == TERM_TS) { @@ -1174,19 +1174,19 @@ double CDemandOptimizer::EvaluateTerm(expressionTerm **pTerms,const int k, const else if (pT->type == TERM_CUMUL_TS) { duration=(double)(pT->timeshift); - return pT->pTS->GetAvgValue(t-duration,duration)*(duration); //assumes daily timestep + return pT->pTS->GetAvgValue(t-duration,duration)*(duration); //assumes daily timestep } - else if (pT->type == TERM_LT) + else if (pT->type == TERM_LT) { kk=pT->nested_ind1; x=EvaluateTerm(pTerms,kk,t); - return pT->pLT->GetValue(x); //decision variable can't be in lookup table + return pT->pLT->GetValue(x); //decision variable can't be in lookup table } else if (pT->type == TERM_HRU) { int i=pT->SV_index; int k=pT->HRU_index; - return _pModel->GetHydroUnit(k)->GetStateVarValue(i); //This will be start of timestep value + return _pModel->GetHydroUnit(k)->GetStateVarValue(i); //This will be start of timestep value } else if (pT->type == TERM_SB) { @@ -1198,18 +1198,18 @@ double CDemandOptimizer::EvaluateTerm(expressionTerm **pTerms,const int k, const { return pT->value; } - else if (pT->type == TERM_CUMUL) //!C123 + else if (pT->type == TERM_CUMUL) //!C123 { - int d=pT->p_index; //todo - should probably use something else here - misleading code + int d=pT->p_index; //todo - should probably use something else here - misleading code return _aCumDelivery[d]; } else if (pT->type == TERM_HISTORY) //e.g., !Q100[-3] - { + { nshift=pT->timeshift-1; char tmp =pT->origexp[1];//e.g., Q - - p=pT->p_index; - + + p=pT->p_index; + if (tmp=='Q'){return _aQhist[_aSBIndices[p]][nshift]; } else if (tmp=='h'){return _ahhist[_aSBIndices[p]][nshift]; } else if (tmp=='D'){return _aDhist[_aSBIndices[p]][nshift]; } @@ -1226,10 +1226,10 @@ double CDemandOptimizer::EvaluateTerm(expressionTerm **pTerms,const int k, const x=EvaluateTerm(pTerms,pT->nested_ind1,t); y=EvaluateTerm(pTerms,pT->nested_ind2,t); return min(x,y); - } + } else if (pT->type == TERM_CONVERT) { x=EvaluateTerm(pTerms,pT->nested_ind1,t); return x*pT->value; - } + } return 0; -} \ No newline at end of file +} diff --git a/src/DemandGroups.cpp b/src/DemandGroups.cpp index cde52e8..6743250 100644 --- a/src/DemandGroups.cpp +++ b/src/DemandGroups.cpp @@ -46,7 +46,7 @@ int CDemandGroup::GetGlobalIndex () const {return _global_ii;} ////////////////////////////////////////////////////////////////// /// \brief Returns true if demands with ID demandID is in group -/// \param demandID [in] demand id +/// \param demandID [in] demand id /// /// \return true if demand with ID demandID is in group // diff --git a/src/DemandOptimization.cpp b/src/DemandOptimization.cpp index 17cf719..341f1c5 100644 --- a/src/DemandOptimization.cpp +++ b/src/DemandOptimization.cpp @@ -9,7 +9,7 @@ ----------------------------------------------------------------*/ #include "DemandOptimization.h" -void SummarizeExpression(const char **s, const int Len, expressionStruct* exp); //defined in DemandExpressionHandling.cpp +void SummarizeExpression(const char **s, const int Len, expressionStruct* exp); //defined in DemandExpressionHandling.cpp ////////////////////////////////////////////////////////////////// /// \brief Implementation of the Demand optimization constructor @@ -254,15 +254,15 @@ void CDemandOptimizer::AddUserConstant(const string name, const double& val) } ////////////////////////////////////////////////////////////////// -/// \brief adds control variable +/// \brief adds control variable // -void CDemandOptimizer::AddControlVariable(const string name, expressionStruct* pExp) -{ +void CDemandOptimizer::AddControlVariable(const string name, expressionStruct* pExp) +{ if (VariableNameExists(name)) { string warn="CDemandOptimizer::AddControlVariable: control variable name "+name+" is already in use."; ExitGracefully(warn.c_str(),BAD_DATA_WARN); } - + control_var *pCV = new control_var(); pCV->name=name; pCV->pExpression=pExp; @@ -312,7 +312,7 @@ manConstraint *CDemandOptimizer::AddGoalOrConstraint(string name, bool soft_con ////////////////////////////////////////////////////////////////// /// \brief sets demand penalty for demand dname // -void CDemandOptimizer::SetDemandPenalty(const string dname, const double& pen) +void CDemandOptimizer::SetDemandPenalty(const string dname, const double& pen) { int d=GetDemandIndexFromName(dname); @@ -326,9 +326,9 @@ void CDemandOptimizer::SetDemandPenalty(const string dname, const double& pen) } ////////////////////////////////////////////////////////////////// -/// \brief returns true if variable name is already in use +/// \brief returns true if variable name is already in use // -bool CDemandOptimizer::VariableNameExists(const string &name) const +bool CDemandOptimizer::VariableNameExists(const string &name) const { for (int i = 0; i < _nControlVars; i++) { if (_pControlVars[i]->name==name){return true;} @@ -665,7 +665,7 @@ void CDemandOptimizer::InitializePostRVMRead(CModel* pModel, const optStruct& Op { // ASSUMES ALL EXPRESSIONS IN GOAL/CONSTRAINT ARE EITHER == or >/<, NEVER MIXED. if (_pConstraints[j]->is_goal) { - if (_pConstraints[j]->pOperRegimes[0]->pExpression->compare == COMPARE_IS_EQUAL) { + if (_pConstraints[j]->pOperRegimes[0]->pExpression->compare == COMPARE_IS_EQUAL) { _pConstraints[j]->slack_ind1=_nSlackVars; _pConstraints[j]->slack_ind2=_nSlackVars+1; pDV = new decision_var("SL+" + to_string(j), p, DV_SLACK,_nSlackVars); @@ -852,7 +852,7 @@ void CDemandOptimizer::AddReservoirConstraints() else { expString=":Expression !Q" + SBIDs+ " = 0.0"; } - + TokenizeString(expString, s, Len); exp = ParseExpression((const char**)(s), Len, 0, "internal"); pConst=AddGoalOrConstraint(TSname, true); @@ -867,7 +867,7 @@ void CDemandOptimizer::AddReservoirConstraints() pConst->AddOpCondition(pCond); if (GetDebugLevel()>=1){ - SummarizeExpression((const char**)(s),Len,pCond->pExp); + SummarizeExpression((const char**)(s),Len,pCond->pExp); } advice="A :ReservoirMinStage time series for subbasin "+SBIDs+" has been added to the management optimization formulation"; @@ -995,10 +995,10 @@ int CDemandOptimizer::GetDVColumnInd(const dv_type typ, const int counter) const return 0; } ////////////////////////////////////////////////////////////////// -/// \brief Updates control variables +/// \brief Updates control variables /// called every time step by SolveDemandProblem() prior to solve // -void CDemandOptimizer::UpdateControlVariables(const time_struct &tt) +void CDemandOptimizer::UpdateControlVariables(const time_struct &tt) { double t=tt.model_time; for (int i = 0; i < _nControlVars; i++) { @@ -1006,10 +1006,10 @@ void CDemandOptimizer::UpdateControlVariables(const time_struct &tt) } } ////////////////////////////////////////////////////////////////// -/// \brief Updates history arrays +/// \brief Updates history arrays /// called every time step by SolveDemandProblem() prior to solve // -void CDemandOptimizer::UpdateHistoryArrays() +void CDemandOptimizer::UpdateHistoryArrays() { int pp=0; int p; @@ -1060,7 +1060,7 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio double t=tt.model_time; //int nn=tt.nn+1;//end of timestep int nn=static_cast((t+TIME_CORRECTION)/Options.timestep);//+1;//end-of timestep index - + int *col_ind=new int [_nDecisionVars]; //index of column to insert value in current row (1:nDV, not zero-indexed) double *row_val=new double [_nDecisionVars]; //values of row[col_ind] @@ -1068,7 +1068,7 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio double *Q_iter=new double [_pModel->GetNumSubBasins()]; int *lprow =new int [_pModel->GetNumSubBasins()]; //index of goal equation for non-linear reservoir stage discharge curve in subbasin p - // evaluates value of all control variables for this time step + // evaluates value of all control variables for this time step // ---------------------------------------------------------------- UpdateControlVariables(tt); @@ -1262,18 +1262,18 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio if (op_is_active){ _pConstraints[j]->conditions_satisfied=true; _pConstraints[j]->active_regime=k; - _pConstraints[j]->ever_satisfied=true; + _pConstraints[j]->ever_satisfied=true; if (_pConstraints[j]->is_goal) { col_ind[i]=GetDVColumnInd(DV_SLACK,s); row_val[i]=_pConstraints[j]->penalty_over; - i++; + i++; if (_pConstraints[j]->pOperRegimes[k]->pExpression->compare == COMPARE_IS_EQUAL) //two slack variables { col_ind[i]=GetDVColumnInd(DV_SLACK,s+1); row_val[i]=_pConstraints[j]->penalty_under; - i++; + i++; } } @@ -1281,7 +1281,7 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio } } - //ensure counters are properly incremented + //ensure counters are properly incremented s++; if (_pConstraints[j]->pOperRegimes[0]->pExpression->compare == COMPARE_IS_EQUAL) //two slack variables { @@ -1559,7 +1559,7 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio for (int i = 0; i < _nConstraints; i++) { int k=_pConstraints[i]->active_regime; - if (k!=DOESNT_EXIST)//at least one regime has been activated + if (k!=DOESNT_EXIST)//at least one regime has been activated { AddConstraintToLP( i, k, pLinProg, tt, col_ind, row_val); } diff --git a/src/DemandOptimization.h b/src/DemandOptimization.h index 9490844..4ad990f 100644 --- a/src/DemandOptimization.h +++ b/src/DemandOptimization.h @@ -16,47 +16,47 @@ namespace lp_lib { #include "../lib/lp_solve/lp_lib.h" } -#endif +#endif /////////////////////////////////////////////////////////////////// -/// \brief different expression types +/// \brief different expression types // -enum exptype +enum exptype { EXP, //< default expression EXP_OP, //< operator - EXP_INV //< inverse operator + EXP_INV //< inverse operator }; /////////////////////////////////////////////////////////////////// -/// \brief different expression term types +/// \brief different expression term types // enum termtype { - TERM_DV, //< decision variable !Q123 or named - TERM_TS, //< time series @ts(name,n) + TERM_DV, //< decision variable !Q123 or named + TERM_TS, //< time series @ts(name,n) TERM_LT, //< lookup table @lookup(x) TERM_HRU, //< state variable @HRU_var(SNOW,2345) TERM_SB, //< state variable @SB_var(SNOW,234) - TERM_CONST, //< constant - TERM_HISTORY, //< bracketed - !Q123[-2] - TERM_MAX, //< @max(x,y) + TERM_CONST, //< constant + TERM_HISTORY, //< bracketed - !Q123[-2] + TERM_MAX, //< @max(x,y) TERM_MIN, //< @min(x,y) TERM_CONVERT, //< @convert(x,units) TERM_CUMUL_TS, //< @cumul(ts_name,duration) //MAY WANT @cumul(ts_name,duration,n) to handle time shift, e.g., 3 days to 10 days ago? TERM_CUMUL, //< cumulative delivery !C123 - TERM_UNKNOWN //< unknown + TERM_UNKNOWN //< unknown }; /////////////////////////////////////////////////////////////////// -/// \brief decision variable types +/// \brief decision variable types // -enum dv_type +enum dv_type { DV_QOUT, //< outflow from reach - DV_QOUTRES, //< outflow from reservoir + DV_QOUTRES, //< outflow from reservoir DV_STAGE, //< reservoir stage - DV_DELIVERY,//< delivery of water demand + DV_DELIVERY,//< delivery of water demand DV_SLACK, //< slack variable for goal satisfaction - DV_USER //< user specified decision variable + DV_USER //< user specified decision variable }; // ------------------------------------------------------------------- @@ -71,81 +71,81 @@ enum dv_type // ------------------------------------------------------------------- ////////////////////////////////////////////////////////////////// -/// expression term +/// expression term /// individual term in expression -// -struct expressionTerm +// +struct expressionTerm { - termtype type; //< type of expression + termtype type; //< type of expression double mult; //< multiplier of expression (+/- 1, depending upon operator and location in exp) - bool reciprocal; //< true if term is in denominator - + bool reciprocal; //< true if term is in denominator + double value; //< constant value or conversion multiplier CTimeSeries *pTS; //< pointer to time series, if this is a named time series CLookupTable *pLT; //< pointer to lookup table, if this is a named time series - bool is_nested; //< true if nested within (i.e., an argument to) another term - int timeshift; //< for time series (+ or -) or lookback value (+) - int DV_ind; //< index of decision variable + bool is_nested; //< true if nested within (i.e., an argument to) another term + int timeshift; //< for time series (+ or -) or lookback value (+) + int DV_ind; //< index of decision variable int nested_ind1; //< index k of first argument (e.g., for lookup table with term entry) int nested_ind2; //< index k of second argument (e.g., for min/max functions) string nested_exp1; //< contents of first argument to function - can be expression string nested_exp2; //< contents of second argument to function - - string origexp; //< original string expression + + string origexp; //< original string expression int p_index; //< subbasin index p (for history variables, e.g, !Q324[-2] or @SB_var() command ) int HRU_index; //< HRU index k (for @HRU_var command) int SV_index; //< state variable index i (for @SB_var or @HRU_var command) - + expressionTerm(); //defined in DemandExpressionHandling.cpp }; ////////////////////////////////////////////////////////////////// /// expression structure -/// abstraction of (A*B*C)+(D*E)-(F)+(G*H) <= 0 +/// abstraction of (A*B*C)+(D*E)-(F)+(G*H) <= 0 /// parenthetical collections are groups of terms -example has 4 groups with [3,2,1,2] terms per group // -struct expressionStruct //full expression -{ +struct expressionStruct //full expression +{ expressionTerm ***pTerms; //< 2D irregular array of pointers to expression terms size:[nGroups][nTermsPerGrp[j]] - int nGroups; //< total number of terms groups in expression + int nGroups; //< total number of terms groups in expression int *nTermsPerGrp;//< number of terms per group [size: nGroups] comparison compare; //< comparison operator (==, <, >) - string origexp; //< original string expression + string origexp; //< original string expression expressionStruct(); ~expressionStruct(); }; ////////////////////////////////////////////////////////////////// -// decision variable +// decision variable // struct decision_var { - string name; //< decision variable names: Qxxxx or Dxxxx where xxxx is SBID + string name; //< decision variable names: Qxxxx or Dxxxx where xxxx is SBID dv_type dvar_type; //< decision variable type: e.g., DV_QOUT or DV_DELIVERY - int p_index; //< raw subbasin index p (not SBID) of decision variable (or DOESNT_EXIST if not linked to SB) + int p_index; //< raw subbasin index p (not SBID) of decision variable (or DOESNT_EXIST if not linked to SB) int dem_index; //< demand index in subbasin p (or DOESNT_EXIST if type not DV_DELIVERY) (ii..nDemands in SB p_index, usually <=1) - int loc_index; //< local index (rescount or subbasincount or demand count) + int loc_index; //< local index (rescount or subbasincount or demand count) double value; //< solution value for decision variable - double min; //< minimum bound (default=0) + double min; //< minimum bound (default=0) double max; //< maximum bound (default unbounded) decision_var(string nam, int p, dv_type typ, int loc_ind) { - name=nam; - p_index=p; - loc_index=loc_ind; + name=nam; + p_index=p; + loc_index=loc_ind; value=0.0;min=0.0;max=ALMOST_INF;dvar_type=typ;dem_index=DOESNT_EXIST; } }; ////////////////////////////////////////////////////////////////// -// goal/constraint condition +// goal/constraint condition // struct exp_condition { string dv_name; //< decision variable name (e.g., Q1023) or "MONTH" or "DATE" or "DAY_OF_YEAR" - double value; //< conditional value + double value; //< conditional value double value2; //< second conditional (if COMPARE_BETWEEN) string date_string; //< conditional value (if date) string date_string2; //< second conditional (if DATE COMPARE_BETWEEN) @@ -164,15 +164,15 @@ struct exp_condition } }; ////////////////////////////////////////////////////////////////// -// operating regime +// operating regime // -struct op_regime +struct op_regime { - string reg_name; //< regime name + string reg_name; //< regime name expressionStruct *pExpression; //< constraint expression - int nConditions; //< number of conditional statments + int nConditions; //< number of conditional statments exp_condition **pConditions; //< array of pointers to conditional statements op_regime(string name) { @@ -187,8 +187,8 @@ struct op_regime // struct manConstraint { - string name; //< goal or constraint name - + string name; //< goal or constraint name + bool is_goal; //< true if constraint is soft (goal rather than constraint) int priority; //< priority (default==1, for goals only) double penalty_under; //< penalty if under specified value (for goals only) @@ -196,10 +196,10 @@ struct manConstraint int slack_ind1; //< slack index (0.._nSlackVars) of under/over slack index for goal, or DOESNT_EXIST if constraint int slack_ind2; //< slack index (0.._nSlackVars) of over slack index for target goal, or DOESNT_EXIST if constraint - double penalty_value; //< (from solution) penalty incurred by not satisfying goal (or zero for constraint) + double penalty_value; //< (from solution) penalty incurred by not satisfying goal (or zero for constraint) op_regime **pOperRegimes; //< array of pointers to operating regimes, which are chosen from conditionals and determine active expression [size:nOperRegimes] - int nOperRegimes; //< size of operating regime array + int nOperRegimes; //< size of operating regime array int active_regime; //< currently active operating regime (or DOESNT_EXIST if none) bool conditions_satisfied; //< true if any operating regime satisfied during current timestep @@ -208,24 +208,24 @@ struct manConstraint manConstraint(); ~manConstraint(); expressionStruct *GetCurrentExpression() const{return pOperRegimes[nOperRegimes-1]->pExpression; } - void AddOperatingRegime(op_regime *pOR, bool first); + void AddOperatingRegime(op_regime *pOR, bool first); void AddOpCondition(exp_condition *pCondition); //adds to most recent operating regime void AddExpression (expressionStruct *pExp); //adds to most recent operating regime }; ////////////////////////////////////////////////////////////////// -// control variable definition +// control variable definition // struct control_var { - string name; //< control variable name - expressionStruct *pExpression; //< expression defining control variable + string name; //< control variable name + expressionStruct *pExpression; //< expression defining control variable double current_val; //< current value of control variable (evaluated at start of time step) }; /////////////////////////////////////////////////////////////////// -/// \brief Data abstraction for demand optimization +/// \brief Data abstraction for demand optimization // class CDemandOptimizer { @@ -239,38 +239,38 @@ class CDemandOptimizer int _nControlVars; //< total number of control variables considered control_var **_pControlVars; //< array of pointers to control variables [size: _nControlVars] - int _nConstraints; //< number of user-defined enforced constraints/goals in management model + int _nConstraints; //< number of user-defined enforced constraints/goals in management model manConstraint **_pConstraints; //< array of pointers to user-defined enforced constraints/goals in management model - int _nEnabledSubBasins; //< number of enabled subbasins in model + int _nEnabledSubBasins; //< number of enabled subbasins in model int *_aSBIndices; //< local index of enabled subbasins (0:_nEnabledSubBasins) [size: _nSubBasins] - int _nReservoirs; //< local storage of number of simulated lakes/reservoirs - int *_aResIndices; //< storage of enabled reservoir indices (0:_nReservoirs or DOESNT_EXIST) [size:_nSubBasins] + int _nReservoirs; //< local storage of number of simulated lakes/reservoirs + int *_aResIndices; //< storage of enabled reservoir indices (0:_nReservoirs or DOESNT_EXIST) [size:_nSubBasins] //Should probably convert this to a demand class? - //CWaterDemand **_pDemands; //< array of pointers to water demand instances + //CWaterDemand **_pDemands; //< array of pointers to water demand instances int _nDemands; //< local storage of number of demand locations (:IrrigationDemand/:WaterDemand + :ReservoirExtraction time series) int *_aDemandIDs; //< local storage of demand IDs [size:_nDemands] long *_aDemandSBIDs; //< local storage of subbasin IDs for each demand [size: _nDemands] int *_aDemandIndices; //< local storage of demand index ii (counter in each subbasin) [size: _nDemands] - string *_aDemandAliases; //< list of demand aliases [size: _nDemands] + string *_aDemandAliases; //< list of demand aliases [size: _nDemands] double *_aDemandPenalties; //< array of priority weights [size: _nDemands] bool *_aDemandUnrestrict; //< array of restriction status for demands - true if unrestricted, false otherwise [size: _nDemands] double *_aDelivery; //< array of delivered water for each demand [m3/s] [size: _nDemands] - double *_aCumDelivery; //< array of cumulative deliveries of demand since _aCumDivDate of this year [m3] [size: _nDemands] + double *_aCumDelivery; //< array of cumulative deliveries of demand since _aCumDivDate of this year [m3] [size: _nDemands] int *_aCumDelDate; //< julian date to calculate cumulative deliveries from {default: Jan 1)[size: _nDemands] int **_aUpstreamDemands; //< demand indices (d) upstream (inclusive) of subbasin p [size: nSBs][size: _aUpCount] (only restricted demands) int *_aUpCount; //< number of demands upstream (inclusive) of subbasin p [size: nSBs] - - //int _nDemandGroups; //< number of demand groups - //CDemandGroup **_pDemandGroups; //< array of pointers to demand groups - + + //int _nDemandGroups; //< number of demand groups + //CDemandGroup **_pDemandGroups; //< array of pointers to demand groups + double *_aSlackValues; //< array of slack variable values [size: _nSlackVars] - int _nSlackVars; //< number of slack variables + int _nSlackVars; //< number of slack variables - int _nUserDecisionVars; //< number of user-specified decision variables + int _nUserDecisionVars; //< number of user-specified decision variables int _nUserConstants; //< number of user-specified named constants string *_aUserConstNames; //< array of names of user-specified constants @@ -279,8 +279,8 @@ class CDemandOptimizer int _nUserTimeSeries; //< number of user variable time series CTimeSeries **_pUserTimeSeries; //< array of pointers to user variable time series - int _nUserLookupTables; //< number of user variable lookup tables - CLookupTable **_pUserLookupTables; //< array of pointers to user variable lookup tables + int _nUserLookupTables; //< number of user variable lookup tables + CLookupTable **_pUserLookupTables; //< array of pointers to user variable lookup tables int _nHistoryItems; //< size of flow/demand/stage history that needs to be stored (in time steps) (from :LookbackDuration) double **_aQhist; //< history of subbasin discharge [size: _nEnabledSBs * _nHistoryItems] @@ -300,17 +300,17 @@ class CDemandOptimizer double EvaluateTerm(expressionTerm **pTerms,const int k, const double &t) const; bool EvaluateConditionExp(const expressionStruct* pE,const double &t) const; - bool CheckGoalConditions(const int ii, const int k, const time_struct &tt,const optStruct &Options) const; + bool CheckGoalConditions(const int ii, const int k, const time_struct &tt,const optStruct &Options) const; #ifdef _LPSOLVE_ void AddConstraintToLP(const int i, const int k, lp_lib::lprec *pLinProg, const time_struct &tt,int *col_ind, double *row_val) const; -#endif +#endif //Called during initialization bool UserTimeSeriesExists(string TSname) const; void AddReservoirConstraints(); - void IdentifyUpstreamDemands(); + void IdentifyUpstreamDemands(); bool VariableNameExists(const string &name) const; public: /*------------------------------------------------------*/ @@ -323,23 +323,23 @@ class CDemandOptimizer double GetControlVariable (const string s) const; //double GetDemandDelivery (const int p) const; int GetNumUserDVs () const; - int GetDebugLevel () const; + int GetDebugLevel () const; int GetIndexFromDVString (string s) const; void SetHistoryLength (const int n); void SetCumulativeDate (const int julian_date, const string demandID); void SetDebugLevel (const int lev); - void SetDemandAsUnrestricted(const string dname); - + void SetDemandAsUnrestricted(const string dname); + manConstraint *AddGoalOrConstraint (const string name, const bool soft_constraint); - + void AddDecisionVar (const decision_var *pDV); void SetDecisionVarBounds (const string name, const double &min, const double &max); void AddUserConstant (const string name, const double &val); void AddControlVariable (const string name, expressionStruct* pExp); void AddUserTimeSeries (const CTimeSeries *pTS); void AddUserLookupTable (const CLookupTable *pLUT); - + //void MultiplyDemand (const string dname, const double &mult); //void MultiplyGroupDemand (const string groupname, const double &mult); void SetDemandPenalty (const string dname, const double &pen); @@ -348,7 +348,7 @@ class CDemandOptimizer expressionStruct *ParseExpression(const char **s, const int Len, const int lineno, const string filename) const; void Initialize (CModel *pModel, const optStruct &Options); - void InitializePostRVMRead (CModel *pModel, const optStruct &Options); + void InitializePostRVMRead (CModel *pModel, const optStruct &Options); void SolveDemandProblem (CModel *pModel, const optStruct &Options, const double *aSBrunoff, const time_struct &tt); void WriteOutputFileHeaders(const optStruct &Options); @@ -357,4 +357,4 @@ class CDemandOptimizer void Closure (const optStruct &Options); }; -#endif \ No newline at end of file +#endif diff --git a/src/Demands.h b/src/Demands.h index 352b786..52a5e69 100644 --- a/src/Demands.h +++ b/src/Demands.h @@ -36,4 +36,4 @@ class CDemandGroup bool IsDisabled () const; }; -#endif \ No newline at end of file +#endif diff --git a/src/Diagnostics.cpp b/src/Diagnostics.cpp index 6a5d466..655fa75 100644 --- a/src/Diagnostics.cpp +++ b/src/Diagnostics.cpp @@ -377,7 +377,7 @@ double CDiagnostic::CalculateDiagnostic(CTimeSeriesABC *pTSMod, { double avgobs=0.0; N=0; - double pct=_width/100; //"width" is actually percentage. If ==0, reverts to NSE + double pct=_width/100; //"width" is actually percentage. If ==0, reverts to NSE for(nn=nnstart;nnGetForcingFunctions()->SW_subcan_net; //[MJ/m2/d] double LW_in =pHRU->GetForcingFunctions()->LW_incoming; //[MJ/m2/d] double AET =pHRU->GetStateVarValue(iAET)/MM_PER_METER/tstep; //[m/d] - + double temp_bed =_aBedTemp[p]; double temp_lin =GetOutflowConcentration(p)+ZERO_CELSIUS; //[K] @@ -914,7 +914,7 @@ double CEnthalpyModel::ApplyInCatchmentRouting (const int p, beta=max(beta,1e-9); //to avoid divide by zero error double Mout_new_test=0; - + double Mout_new=0.0; double dt=tstep; double term1,term2,term3; diff --git a/src/GracefulEndStandalone.h b/src/GracefulEndStandalone.h index c700cd7..ee8f1b8 100644 --- a/src/GracefulEndStandalone.h +++ b/src/GracefulEndStandalone.h @@ -49,10 +49,10 @@ inline void FinalizeGracefully(const char *statement, exitcode code) string message="Unable to open errors file ("+Options->main_output_dir+"Raven_errors.txt)"; ExitGracefully(message.c_str(),RAVEN_OPEN_ERR); } - if (code!=SIMULATION_DONE) {WARNINGS<<"ERROR : "<< statement << endl; + if (code!=SIMULATION_DONE) {WARNINGS<<"ERROR : "<< statement << endl; cerr <<"ERROR : "<< statement << endl;} else {WARNINGS<<"SIMULATION COMPLETE :)"<0.1) { F.PET*=(1.0-snow_cov); } } - //Suppress open water ET over frozen lakes + //Suppress open water ET over frozen lakes if ((StateVarExists(ICE_THICKNESS)) && (pHRU->IsLake())) { int iIceThick=GetStateVarIndex(ICE_THICKNESS); diff --git a/src/ParseHRUFile.cpp b/src/ParseHRUFile.cpp index 4e87bab..92882d8 100644 --- a/src/ParseHRUFile.cpp +++ b/src/ParseHRUFile.cpp @@ -1620,7 +1620,7 @@ CReservoir *ReservoirParse(CParser *p,string name,const CModel *pModel,long long p->Tokenize(s,Len); //:EndVaryingStageRelations } //---------------------------------------------------------------------------------------------- - else if ((!strcmp(s[0],":DZTRResservoirModel")) || (!strcmp(s[0],":DZTRReservoirModel"))) + else if ((!strcmp(s[0],":DZTRResservoirModel")) || (!strcmp(s[0],":DZTRReservoirModel"))) {/*:DZTRReservoirModel :MaximumStorage Vmax(m3) :MaximumChannelDischarge Qmax(m3/s) diff --git a/src/ParseInput.cpp b/src/ParseInput.cpp index c7ac26a..514c801 100644 --- a/src/ParseInput.cpp +++ b/src/ParseInput.cpp @@ -3191,7 +3191,7 @@ bool ParseMainInputFile (CModel *&pModel, i_stor=pModel->GetStateVarIndex(typ,layer_ind); if (i_stor != DOESNT_EXIST){ int c; - + if (is_temp) { c=pModel->GetTransportModel()->GetConstituentIndex("TEMPERATURE"); } @@ -3224,7 +3224,7 @@ bool ParseMainInputFile (CModel *&pModel, else { ExitGracefully("ParseMainInputFile: invalid constiuent in :FixedConcentration/:FixedTemperature command in .rvi file",BAD_DATA_WARN); } - + } else{ string warn=":FixedConcentration command: invalid state variable name"+to_string(s[2]); diff --git a/src/ParseManagementFile.cpp b/src/ParseManagementFile.cpp index 4caa098..e9e82d8 100644 --- a/src/ParseManagementFile.cpp +++ b/src/ParseManagementFile.cpp @@ -10,7 +10,7 @@ Copyright (c) 2008-2024 the Raven Development Team #include "Demands.h" #include "LookupTable.h" -void SummarizeExpression(const char **s, const int Len, expressionStruct* exp); //defined in DemandExpressionHandling.cpp +void SummarizeExpression(const char **s, const int Len, expressionStruct* exp); //defined in DemandExpressionHandling.cpp void swapWildcards(const char **s,const int Len, string **aWildcards,const int &nWildcards) { @@ -27,7 +27,7 @@ void swapWildcards(const char **s,const int Len, string **aWildcards,const int & tmp = s[i]; for (int j=0;jAddDemandGroup(s[1]); @@ -285,21 +285,21 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) case(21): //---------------------------------------------- { /*:DefineDecisionVariable [name] = [expressionRHS] */ if(Options.noisy) { cout <<"Define Decision Variable"<GetNumUserDVs()); - + pDO->AddDecisionVar(pDV); pExp=pDO->ParseExpression((const char**)(s),Len,pp->GetLineNumber(),pp->GetFilename()); if (pDO->GetDebugLevel()>=1){ - SummarizeExpression((const char**)(s),Len,pExp); + SummarizeExpression((const char**)(s),Len,pExp); } if (pExp!=NULL){ pConst = pDO->AddGoalOrConstraint(s[1], false); - pConst->AddExpression(pExp); - } + pConst->AddExpression(pExp); + } else { string warn ="Invalid expression in :DefineDecisionVariable command at line " + pp->GetLineNumber(); WriteWarning(warn.c_str(),Options.noisy); @@ -313,35 +313,35 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) break; } case(23): //---------------------------------------------- - {/*:ManagementConstraint [name] + {/*:ManagementConstraint [name] :OperatingRegime A :Expression [expression] :Condition [condition] :Condition [condition] - :EndOperatingRegime + :EndOperatingRegime :OperatingRegime B :Expression [expression] - :EndOperatingRegime + :EndOperatingRegime :EndManagementConstraint or - :ManagementGoal [name] + :ManagementGoal [name] :OperatingRegime A :Expression [expression] :Condition [condition] :Condition [condition] :EndOperatingRegime - :Penalty [value] {value2} + :Penalty [value] {value2} :EndManagementGoal - :ManagementGoal [name] + :ManagementGoal [name] :Expression [expression] - :Penalty [value] {value2} + :Penalty [value] {value2} :EndManagementGoal */ if(Options.noisy) { cout <<"Management Constraint or Management Goal"<AddGoalOrConstraint(s[1], is_goal); - expressionStruct *pExp; + expressionStruct *pExp; bool is_first=true; firstword=pp->Peek(); if (firstword == ":Expression") {pp->NextIsMathExp();} @@ -356,19 +356,19 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) if (Len == 0) { if(Options.noisy) { cout << "#" << endl; } }//Do nothing else if (IsComment(s[0],Len)) { if(Options.noisy) { cout << "#" << endl; } } //---------------------------------------------- - else if (!strcmp(s[0], ":OperatingRegime")) - { - op_regime *pOR=new op_regime(s[1]);//[OPUPDATE] + else if (!strcmp(s[0], ":OperatingRegime")) + { + op_regime *pOR=new op_regime(s[1]);//[OPUPDATE] pConst->AddOperatingRegime(pOR,is_first); is_first=false; } //---------------------------------------------- - else if (!strcmp(s[0], ":EndOperatingRegime")) + else if (!strcmp(s[0], ":EndOperatingRegime")) { //does nothing } //---------------------------------------------- - else if(!strcmp(s[0], ":Expression")) + else if(!strcmp(s[0], ":Expression")) { if (pConst->GetCurrentExpression() != NULL) { ExitGracefully("ParseManagementFile: only one :Expression allowed in each :OperatingRegime command block (or only one if no :OperatingRegime blocks used).",BAD_DATA_WARN); @@ -383,23 +383,23 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) WriteWarning(warn.c_str(),Options.noisy); } if (pDO->GetDebugLevel()>=1){ - SummarizeExpression((const char**)(s),Len,pExp); + SummarizeExpression((const char**)(s),Len,pExp); } } //---------------------------------------------- - else if (!strcmp(s[0], ":Condition")) + else if (!strcmp(s[0], ":Condition")) { //TODO: Would it be better to support @date(), @between, @day_of_year() in general expression?? //:Condition !Q32[0] < 300 + @ts(myTs,0) //:Condition DATE IS_BETWEEN 1975-01-02 and 2010-01-02 - //:Condition DATE > @date(1975-01-02) //[NOT YET SUPPORTED] - //:Condition DATE < @date(2010-01-02) //[NOT YET SUPPORTED] + //:Condition DATE > @date(1975-01-02) //[NOT YET SUPPORTED] + //:Condition DATE < @date(2010-01-02) //[NOT YET SUPPORTED] //:Condition MONTH = 2 //:Condition DAY_OF_YEAR IS_BETWEEN 173 and 210 //:Condition DAY_OF_YEAR > 174 //:Condition DAY_OF_YEAR < 210 - //:Condition DAY_OF_YEAR IS_BETWEEN 300 20 //wraps around - //:Condition @is_between(DAY_OF_YEAR,300,20) = 1 //[NOT YET SUPPORTED] + //:Condition DAY_OF_YEAR IS_BETWEEN 300 20 //wraps around + //:Condition @is_between(DAY_OF_YEAR,300,20) = 1 //[NOT YET SUPPORTED] if (pConst!=NULL){ bool badcond=false; exp_condition *pCond = new exp_condition(); @@ -419,7 +419,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) else if (!strcmp(s[2],"IS_GREATER_THAN")){pCond->compare=COMPARE_GREATERTHAN;} else if (!strcmp(s[2],"IS_LESS_THAN" )){pCond->compare=COMPARE_LESSTHAN;} else if (!strcmp(s[2],"IS_EQUAL_TO" )){pCond->compare=COMPARE_IS_EQUAL;} - else if (!strcmp(s[2],"IS_NOT_EQUAL_TO")){pCond->compare=COMPARE_NOT_EQUAL;} + else if (!strcmp(s[2],"IS_NOT_EQUAL_TO")){pCond->compare=COMPARE_NOT_EQUAL;} else { ExitGracefully("ParseManagementFile: unrecognized comparison operator in :Condition statement",BAD_DATA_WARN); break; @@ -435,7 +435,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } } - if (pCond->dv_name[0] == '!') { //decision variable + if (pCond->dv_name[0] == '!') { //decision variable char tmp =pCond->dv_name[1]; string tmp2=pCond->dv_name.substr(2); char code=pCond->dv_name[1]; @@ -454,7 +454,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } } } - else { //demand + else { //demand int d=pDO->GetDemandIndexFromName(tmp2); if (d == DOESNT_EXIST) { ExitGracefully("ParseManagementFile: !D or !C used in :Condition statement has invalid demand ID",BAD_DATA_WARN); @@ -463,15 +463,15 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } if (!badcond) { - pCond->p_index=pDO->GetIndexFromDVString(pCond->dv_name); + pCond->p_index=pDO->GetIndexFromDVString(pCond->dv_name); pConst->AddOpCondition(pCond); } } - } + } else{ ExitGracefully("ParseManagementFile: :Condition statement must appear after valid :Expression in :ManagementConstraint command",BAD_DATA_WARN); } - } + } //---------------------------------------------- else if (!strcmp(s[0], ":Penalty")) { if (!pConst->is_goal) { @@ -485,7 +485,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } //---------------------------------------------- else if (!strcmp(s[0], ":Priority")) { - pConst->priority = s_to_i(s[1]); //for later + pConst->priority = s_to_i(s[1]); //for later } //---------------------------------------------- else if (!strcmp(s[0], ":EndManagementGoal")) { @@ -494,7 +494,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) //---------------------------------------------- else if (!strcmp(s[0], ":EndManagementConstraint")) { break; - } + } else { WriteWarning("ParseManagementFile: Unrecognized command in :ManagementConstraint command block",Options.noisy); } @@ -506,7 +506,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } case(24): //---------------------------------------------- { /*:DeclareDecisionVariable [name] */ - if(Options.noisy) { cout <<"Declare Decision Variable"<GetNumUserDVs()); pDO->AddDecisionVar(pDV); break; @@ -514,16 +514,16 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) case(25): //---------------------------------------------- { /*:DefineControlVariable [name] = [expressionRHS] */ if(Options.noisy) { cout <<"Define Control Variable"<ParseExpression((const char**)(s),Len,pp->GetLineNumber(),pp->GetFilename()); if (pDO->GetDebugLevel()>=1){ - SummarizeExpression((const char**)(s),Len,pExp); + SummarizeExpression((const char**)(s),Len,pExp); } if (pExp!=NULL){ pDO->AddControlVariable(s[1],pExp); - } + } else { string warn ="Invalid expression in :DefineControlVariable command at line " + pp->GetLineNumber(); WriteWarning(warn.c_str(),Options.noisy); @@ -531,16 +531,16 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) break; } case(30): //---------------------------------------------- - {/*:LookupTable [name] - N - x1 y1 + {/*:LookupTable [name] + N + x1 y1 x2 y2 ... - xN yN + xN yN :EndLookupTable */ if(Options.noisy) { cout <<"LookupTable"<Tokenize(s,Len); @@ -548,13 +548,13 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) double *aX = new double[N]; double *aY = new double[N]; - for(int i = 0; i < N; i++) + for(int i = 0; i < N; i++) { pp->Tokenize(s,Len); if(IsComment(s[0],Len)) { i--; } else { if(Len>=2) { - aX[i] = s_to_d(s[0]); + aX[i] = s_to_d(s[0]); aY[i] = s_to_d(s[1]); } else { @@ -572,31 +572,31 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } case(40): //---------------------------------------------- { /*:LoopThrough [SB_GROUP or DEMAND_GROUP] [group name] */ - if(Options.noisy) { cout <<"Start Loop"<GetPosition(); loopStartLine=pp->GetLineNumber(); if (!strcmp(s[1],"SB_GROUP" )){ - + if ((pLoopSBGroup != NULL) || (pLoopDemandGroup !=NULL)){ ExitGracefully("ParseManagementFile: Cannot have nested :LoopThrough statements",BAD_DATA); } pLoopSBGroup=pModel->GetSubBasinGroup(s[2]); if (pLoopSBGroup == NULL) { ExitGracefully("ParseManagementFile: bad subbasin group name in :LoopThrough command",BAD_DATA_WARN); - } + } else { loopCount=0; long SBID = pLoopSBGroup->GetSubBasin(loopCount)->GetID(); string SBName = pLoopSBGroup->GetSubBasin(loopCount)->GetName(); - + aWildcards[0][0] = "$ID$"; aWildcards[0][1] = to_string(SBID); aWildcards[1][0] = "$NAME$"; aWildcards[1][1] = SBName; nWildcards=2; - //look for $SBID$ + //look for $SBID$ } } else if (!strcmp(s[1],"DEMAND_GROUP")){ @@ -610,12 +610,12 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } case(41): //---------------------------------------------- { /*:EndLoopThrough */ - if(Options.noisy) { cout <<"End Loop"<GetNumSubbasins()) { @@ -626,13 +626,13 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) { long SBID = pLoopSBGroup->GetSubBasin(loopCount)->GetID(); string SBName = pLoopSBGroup->GetSubBasin(loopCount)->GetName(); - + aWildcards[0][0] = "$ID$"; aWildcards[0][1] = to_string(SBID); aWildcards[1][0] = "$NAME$"; aWildcards[1][1] = SBName; } } else if (pLoopDemandGroup != NULL) { - + if (loopCount == pLoopDemandGroup->GetNumDemands()){ pLoopDemandGroup=NULL; loopDone=true; @@ -642,7 +642,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } } else { - //shouldnt happen + //shouldnt happen loopDone=true; } @@ -663,7 +663,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } cout<<" LOOP COUNT: "<SetPosition(loopStartPos); pp->SetLineCounter(loopStartLine); } @@ -671,8 +671,8 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } case(42): //---------------------------------------------- { /*:LoopVector $wildcard$ v1 v2 v3 ... vN */ /*vN are strings*/ - if(Options.noisy) { cout <<"Loop Vector Data"<GetNumSubbasins())) { ExitGracefully(":LoopVector: invalid number of terms in vector. Should be equal to size of subbasin group",BAD_DATA_WARN); @@ -763,4 +763,4 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) pp=NULL; return true; -} \ No newline at end of file +} diff --git a/src/Raven.vcxproj b/src/Raven.vcxproj index b7ce97d..329943e 100644 --- a/src/Raven.vcxproj +++ b/src/Raven.vcxproj @@ -1038,4 +1038,4 @@ - \ No newline at end of file + diff --git a/src/Solvers.cpp b/src/Solvers.cpp index 616edfd..7ad490c 100644 --- a/src/Solvers.cpp +++ b/src/Solvers.cpp @@ -556,14 +556,14 @@ void MassEnergyBalance( CModel *pModel, pBasin->UpdateLateralInflow(aRouted[p]/(tstep*SEC_PER_DAY)+down_Q);//[m3/d]->[m3/s] - pBasin->RouteWater (aQoutnew,Options,tt); + pBasin->RouteWater (aQoutnew,Options,tt); irr_Q=pBasin->ApplyIrrigationDemand(t+tstep,aQoutnew[pBasin->GetNumSegments()-1],Options.management_optimization); div_Q_total=0; for(int i=0; iGetNumDiversions();i++) { //downstream of reservoir! div_Q=pBasin->GetDiversionFlow(i,pBasin->GetChannelOutflowRate(),Options,tt,pDivert); //diversions based upon flows at start of timestep (without diversions) - div_Q_total+=div_Q; + div_Q_total+=div_Q; } res_ht=res_outflow=0.0; res_const=RC_NATURAL; diff --git a/src/StandardOutput.cpp b/src/StandardOutput.cpp index c20ab5d..47d2098 100644 --- a/src/StandardOutput.cpp +++ b/src/StandardOutput.cpp @@ -1869,7 +1869,7 @@ void CModel::WriteNetcdfStandardHeaders(const optStruct &Options) int varid_qobs; // variable ID for observed outflows int varid_qin; // variable ID for observed inflows int varid_qloc; - int varid_qnet_in; // variable ID for reservoir net inflows + int varid_qnet_in; // variable ID for reservoir net inflows int retval; // error value for NetCDF routines string tmpFilename; @@ -2323,7 +2323,7 @@ void CModel::WriteNetcdfMinorOutput ( const optStruct &Options, int qsim_id; // variable id in NetCDF for simulated outflow int qobs_id; // variable id in NetCDF for observed outflow int qin_id; // variable id in NetCDF for observed inflow - int qin_net_id; // variable id in NetCDF for simulated net res inflow + int qin_net_id; // variable id in NetCDF for simulated net res inflow // (a) count how many values need to be written for q_obs, q_sim, q_in int iSim, nSim; // current and total # of sub-basins with simulated outflows diff --git a/src/SubBasin.cpp b/src/SubBasin.cpp index c5e80a1..c68e507 100644 --- a/src/SubBasin.cpp +++ b/src/SubBasin.cpp @@ -812,7 +812,7 @@ double CSubBasin::GetOutflowRate () const ////////////////////////////////////////////////////////////////// /// \brief Returns Outflow from channel reach (even if reservoir present) before diversions at start of current timestep (during solution) or end of completed timestep [m^3/s] -/// \note used for calculating flow diversions +/// \note used for calculating flow diversions /// \return Channel outflow at start of current timestep (during solution) or end of completed timestep [m^3/s] // double CSubBasin::GetChannelOutflowRate () const @@ -821,7 +821,7 @@ double CSubBasin::GetChannelOutflowRate () const } ////////////////////////////////////////////////////////////////// /// \brief Returns Outflow from channel reach (even if reservoir present) before diversions at start of current timestep (during solution) or end of completed timestep [m^3/s] -/// \note used for calculating flow diversions +/// \note used for calculating flow diversions /// \return Channel outflow at start of current timestep (during solution) or end of completed timestep [m^3/s] // double CSubBasin::GetLastChannelOutflowRate () const @@ -1990,7 +1990,7 @@ void CSubBasin::UpdateOutflows (const double *aQo, //[m3/s] } double irrQ_act = min(irr_Q, _aQout[_nSegments-1]); _aQout[_nSegments-1]-=irrQ_act; - + double divQ_act = min(Qdiv, _aQout[_nSegments-1]); _aQout[_nSegments-1]-=divQ_act; @@ -2045,9 +2045,9 @@ void CSubBasin::UpdateOutflows (const double *aQo, //[m3/s] //volume change from irrigation dV-=0.5*(_Qirr+_QirrLast)*dt; - //volume change from diversion + //volume change from diversion dV-=0.5*(_Qdiverted+_QdivLast)*dt; - + _channel_storage+=dV;//[m3] //Update rivulet storage diff --git a/src/SubBasin.h b/src/SubBasin.h index 86b7224..feff602 100644 --- a/src/SubBasin.h +++ b/src/SubBasin.h @@ -108,7 +108,7 @@ class CSubBasin double _rivulet_storage; ///< water storage in rivulets [m3] double _QoutLast; ///< Qout from downstream channel segment [m3/s] at start of previous timestep- needed for reporting integrated outflow double _QlatLast; ///< Qlat (after convolution) at start of previous timestep [m3/s] - //double _aQchanLast; ///< channel outflow + //double _aQchanLast; ///< channel outflow double _Qlocal; ///< local contribution to current subbasin outflow [m3/s] (just from in-catchment routing) double _QlocLast; ///< last local contribution [m3/s] @@ -225,7 +225,7 @@ class CSubBasin int GetNumDiversions () const; double GetOutflowRate () const; //[m3/s] from final reach segment OR reservoir, point in time - double GetChannelOutflowRate () const; //[m3/s] from final reach segment (NOT reservoir), point in time, BEFORE diversions included + double GetChannelOutflowRate () const; //[m3/s] from final reach segment (NOT reservoir), point in time, BEFORE diversions included double GetLastChannelOutflowRate() const; //[m3/s] from final reach segment (NOT reservoir), point in time, BEFORE diversions included double GetLastOutflowRate () const; //[m3/s] from final segment, previous timestep double GetLocalOutflowRate () const; //[m3/s] local contribution to outflow @@ -237,7 +237,7 @@ class CSubBasin double GetReservoirLosses (const double &tstep) const;//[m3] from reservoir integrated over timestep double GetIntegratedReservoirInflow (const double &tstep) const;//[m3] from final segment upstream of reservoir integrated over timestep double GetIrrigationLosses (const double &tstep) const;//[m3] from actual irrigation (not just demand) - double GetDiversionLosses (const double &tstep) const;//[m3] from flow diversions + double GetDiversionLosses (const double &tstep) const;//[m3] from flow diversions double GetRivuletStorage () const; //[m3] volume en route to outflow double GetChannelStorage () const; //[m3] volume in channel From 1692dcd3c78ad461f675dfea668d0d9d74c9b1bd Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:41:31 -0400 Subject: [PATCH 03/16] trigger workflows From 999d7e2c7fef9d66175ace99a420e2876cd0a6d1 Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:50:46 -0400 Subject: [PATCH 04/16] update actions and dependencies --- .github/workflows/testing.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 6bbe0b9..e85a23b 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -57,8 +57,10 @@ jobs: sudo apt-get install libnetcdf-dev build-essential cmake - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' - run: | - brew install netcdf cmake wget + uses: tecolicom/actions-use-homebrew-tools@v5c37fd17a71166ce64ee8ba712f6f2b8c4e6089a # v1.2 + with: + tools: cmake + cache: yes - name: Fetch NetCDF CMake script run: | @@ -67,7 +69,7 @@ jobs: id: build continue-on-error: true run: | - cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + cmake . --config ${{ matrix.build_type }} make -j4 - name: Run tests if: steps.build.outcome == 'success' @@ -100,13 +102,13 @@ jobs: sudo apt-get install build-essential cmake - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' - run: | - brew install cmake + uses: tecolicom/actions-use-homebrew-tools@v5c37fd17a71166ce64ee8ba712f6f2b8c4e6089a # v1.2 + with: + tools: cmake + cache: yes - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' - run: | - choco install cmake - choco install ninja + uses: lukka/get-cmake@2bcb1a4c14ab154443cc740dced0f9b6a8fb2b59 # v3.29.6 - name: Build id: build From 65ca748f5a50d5b96d584f5e53395e631e811b12 Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:52:27 -0400 Subject: [PATCH 05/16] typo fix --- .github/workflows/testing.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index e85a23b..d914fa1 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -57,7 +57,7 @@ jobs: sudo apt-get install libnetcdf-dev build-essential cmake - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' - uses: tecolicom/actions-use-homebrew-tools@v5c37fd17a71166ce64ee8ba712f6f2b8c4e6089a # v1.2 + uses: tecolicom/actions-use-homebrew-tools@5c37fd17a71166ce64ee8ba712f6f2b8c4e6089a # v1.2 with: tools: cmake cache: yes @@ -102,7 +102,7 @@ jobs: sudo apt-get install build-essential cmake - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' - uses: tecolicom/actions-use-homebrew-tools@v5c37fd17a71166ce64ee8ba712f6f2b8c4e6089a # v1.2 + uses: tecolicom/actions-use-homebrew-tools@5c37fd17a71166ce64ee8ba712f6f2b8c4e6089a # v1.2 with: tools: cmake cache: yes From add969edf48b82e4c644f5441c4c24e659bf9fef Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 16:57:43 -0400 Subject: [PATCH 06/16] do not use bash --- .github/workflows/testing.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index d914fa1..77446b6 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -33,15 +33,13 @@ jobs: uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 build-netcdf: - name: Build RavenHydroFramework binary (${{ matrix.build_type }}) + name: Build (${{ matrix.build_type }}; ${{ matrix.os }}; NetCDF=True) + needs: lint runs-on: ubuntu-latest strategy: matrix: os: [ubuntu-latest, macos-latest] build_type: [Debug, Release] - defaults: - run: - shell: bash steps: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 @@ -78,15 +76,13 @@ jobs: ./Raven -v build: - name: Build RavenHydroFramework binary (${{ matrix.build_type }}) + name: Build (${{ matrix.build_type }}; ${{ matrix.os }}; NetCDF=False) + needs: lint runs-on: ubuntu-latest strategy: matrix: os: [ ubuntu-latest, macos-latest, windows-latest ] build_type: [ Debug, Release ] - defaults: - run: - shell: bash steps: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 @@ -114,7 +110,7 @@ jobs: id: build continue-on-error: true run: | - cmake --build . --config {{ matrix.build_type }} -j 3 + cmake --build . --config ${{ matrix.build_type }} -j 3 - name: Run tests (Linux and macOS) if: steps.build.outcome == 'success' && matrix.os != 'windows-latest' From de0d4877c39c3c2470bea25088d7bd4491339581 Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:10:56 -0400 Subject: [PATCH 07/16] try try try again --- .github/workflows/testing.yml | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 77446b6..3bbf216 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -55,7 +55,7 @@ jobs: sudo apt-get install libnetcdf-dev build-essential cmake - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' - uses: tecolicom/actions-use-homebrew-tools@5c37fd17a71166ce64ee8ba712f6f2b8c4e6089a # v1.2 + uses: tecolicom/actions-use-homebrew-tools@v1 with: tools: cmake cache: yes @@ -68,7 +68,7 @@ jobs: continue-on-error: true run: | cmake . --config ${{ matrix.build_type }} - make -j4 + cmake --build . -j 3 - name: Run tests if: steps.build.outcome == 'success' run: | @@ -90,19 +90,7 @@ jobs: egress-policy: audit - name: Checkout Repository uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Install dependencies (Linux) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install build-essential cmake - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - uses: tecolicom/actions-use-homebrew-tools@5c37fd17a71166ce64ee8ba712f6f2b8c4e6089a # v1.2 - with: - tools: cmake - cache: yes - - name: Install dependencies (Windows) + - name: Install dependencies if: matrix.os == 'windows-latest' uses: lukka/get-cmake@2bcb1a4c14ab154443cc740dced0f9b6a8fb2b59 # v3.29.6 @@ -110,7 +98,8 @@ jobs: id: build continue-on-error: true run: | - cmake --build . --config ${{ matrix.build_type }} -j 3 + cmake . --config ${{ matrix.build_type }} + cmake --build . -j 3 - name: Run tests (Linux and macOS) if: steps.build.outcome == 'success' && matrix.os != 'windows-latest' From 39da36564c54c3eaa962e279c446a71cb6d9ea29 Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:15:51 -0400 Subject: [PATCH 08/16] remove unnecessary steps --- .github/workflows/testing.yml | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 3bbf216..7257141 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -38,8 +38,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - os: [ubuntu-latest, macos-latest] - build_type: [Debug, Release] + os: [ ubuntu-latest, macos-latest ] + build_type: [ Debug, Release ] steps: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 @@ -47,19 +47,6 @@ jobs: egress-policy: audit - name: Checkout Repository uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Install dependencies (Linux) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt-get update - sudo apt-get install libnetcdf-dev build-essential cmake - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - uses: tecolicom/actions-use-homebrew-tools@v1 - with: - tools: cmake - cache: yes - - name: Fetch NetCDF CMake script run: | wget https://raw.githubusercontent.com/Kitware/VTK/master/CMake/FindNetCDF.cmake -P cmake @@ -67,8 +54,8 @@ jobs: id: build continue-on-error: true run: | - cmake . --config ${{ matrix.build_type }} - cmake --build . -j 3 + cmake . + cmake --build . --config ${{ matrix.build_type }} -j 3 - name: Run tests if: steps.build.outcome == 'success' run: | @@ -90,7 +77,8 @@ jobs: egress-policy: audit - name: Checkout Repository uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Install dependencies + + - name: Install dependencies (Windows) if: matrix.os == 'windows-latest' uses: lukka/get-cmake@2bcb1a4c14ab154443cc740dced0f9b6a8fb2b59 # v3.29.6 @@ -98,8 +86,8 @@ jobs: id: build continue-on-error: true run: | - cmake . --config ${{ matrix.build_type }} - cmake --build . -j 3 + cmake . + cmake --build . --config ${{ matrix.build_type }} -j 3 - name: Run tests (Linux and macOS) if: steps.build.outcome == 'success' && matrix.os != 'windows-latest' From c92bcb1ef65fb23a8efca742bafe02163033489f Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:20:40 -0400 Subject: [PATCH 09/16] final touches --- .github/workflows/testing.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 7257141..a4f8410 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -59,8 +59,8 @@ jobs: - name: Run tests if: steps.build.outcome == 'success' run: | - ./Raven - ./Raven -v + Raven + Raven -v build: name: Build (${{ matrix.build_type }}; ${{ matrix.os }}; NetCDF=False) @@ -87,15 +87,15 @@ jobs: continue-on-error: true run: | cmake . - cmake --build . --config ${{ matrix.build_type }} -j 3 + cmake --build . --config ${{ matrix.build_type }} -j 3 - name: Run tests (Linux and macOS) if: steps.build.outcome == 'success' && matrix.os != 'windows-latest' run: | - ./Raven - ./Raven -v + Raven + Raven -v - name: Run tests (Windows) if: steps.build.outcome == 'success' && matrix.os == 'windows-latest' run: | - ./Raven.exe - ./Raven.exe -v + Raven.exe + Raven.exe -v From a46730e6ca7cd410a81f8ef2feb4e91764a0bb51 Mon Sep 17 00:00:00 2001 From: Zeitsperre <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:24:28 -0400 Subject: [PATCH 10/16] testing --- .github/workflows/testing.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index a4f8410..d459506 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -59,8 +59,8 @@ jobs: - name: Run tests if: steps.build.outcome == 'success' run: | - Raven - Raven -v + ./Raven + ./Raven -v build: name: Build (${{ matrix.build_type }}; ${{ matrix.os }}; NetCDF=False) @@ -92,10 +92,11 @@ jobs: - name: Run tests (Linux and macOS) if: steps.build.outcome == 'success' && matrix.os != 'windows-latest' run: | - Raven - Raven -v + ./Raven + ./Raven -v - name: Run tests (Windows) if: steps.build.outcome == 'success' && matrix.os == 'windows-latest' run: | - Raven.exe - Raven.exe -v + ls + Raven + Raven -v From 16d42b3b5605c456fbb89fad4a754cf416ce6309 Mon Sep 17 00:00:00 2001 From: Trevor James Smith <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:01:06 -0400 Subject: [PATCH 11/16] ensure Raven is run on Windows --- .github/workflows/testing.yml | 4 ++-- CMakeLists.txt | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index d459506..67412ef 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -98,5 +98,5 @@ jobs: if: steps.build.outcome == 'success' && matrix.os == 'windows-latest' run: | ls - Raven - Raven -v + .\Raven.exe + .\Raven.exe -v diff --git a/CMakeLists.txt b/CMakeLists.txt index 13f4051..e9ec65c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # Find NetCDF find_package(NetCDF) + # find header & source file(GLOB HEADER "src/*.h") file(GLOB SOURCE "src/*.cpp") @@ -45,8 +46,6 @@ if(COMPILE_EXE) target_compile_definitions(Raven PUBLIC STANDALONE) set_target_properties(Raven PROPERTIES LINKER_LANGUAGE CXX) endif() -source_group("Header Files" FILES ${HEADER}) -source_group("Source Files" FILES ${SOURCE}) IF(NETCDF_FOUND) add_definitions(-Dnetcdf) @@ -54,6 +53,9 @@ IF(NETCDF_FOUND) target_link_libraries(Raven NetCDF::NetCDF) ENDIF() +source_group("Header Files" FILES ${HEADER}) +source_group("Source Files" FILES ${SOURCE}) + # unset cmake variables to avoid polluting the cache unset(COMPILE_LIB CACHE) unset(COMPILE_EXE CACHE) From f53b6b893a606b20d96a545b47cb9872aa9fcb8a Mon Sep 17 00:00:00 2001 From: Trevor James Smith <10819524+Zeitsperre@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:48:19 -0400 Subject: [PATCH 12/16] try again --- .github/workflows/testing.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 67412ef..d0fcfa7 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -98,5 +98,5 @@ jobs: if: steps.build.outcome == 'success' && matrix.os == 'windows-latest' run: | ls - .\Raven.exe - .\Raven.exe -v + ./Raven.exe + ./Raven.exe -v From 33ddc67c1af29fcd924415149a9ed53ec5c5e7b4 Mon Sep 17 00:00:00 2001 From: Trevor James Smith <10819524+Zeitsperre@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:30:02 -0400 Subject: [PATCH 13/16] add url endpoints --- .github/workflows/testing.yml | 42 ++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index d0fcfa7..5cd6970 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -18,17 +18,29 @@ jobs: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 with: - egress-policy: audit + egress-policy: block + allowed-endpoints: > + azure.archive.ubuntu.com:80 + esm.ubuntu.com:443 + files.pythonhosted.org:443 + github.com:443 + motd.ubuntu.com:443 + packages.microsoft.com:443 + pypi.org:443 + - name: Checkout Repository uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Install linters run: | sudo apt-get update sudo apt-get install uncrustify cppcheck iwyu + - name: Set up Python3 uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: python-version: '3.x' + - name: Run pre-commit hooks uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 @@ -44,18 +56,30 @@ jobs: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 with: - egress-policy: audit + disable-sudo: true + egress-policy: block + allowed-endpoints: > + azure.archive.ubuntu.com:80 + esm.ubuntu.com:443 + github.com:443 + motd.ubuntu.com:443 + packages.microsoft.com:443 + raw.githubusercontent.com:443 + - name: Checkout Repository uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Fetch NetCDF CMake script run: | wget https://raw.githubusercontent.com/Kitware/VTK/master/CMake/FindNetCDF.cmake -P cmake + - name: Build id: build continue-on-error: true run: | cmake . cmake --build . --config ${{ matrix.build_type }} -j 3 + - name: Run tests if: steps.build.outcome == 'success' run: | @@ -70,11 +94,23 @@ jobs: matrix: os: [ ubuntu-latest, macos-latest, windows-latest ] build_type: [ Debug, Release ] + defaults: + run: + shell: bash -l {0} steps: - name: Harden Runner uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 with: - egress-policy: audit + disable-sudo: true + egress-policy: block + allowed-endpoints: > + azure.archive.ubuntu.com:80 + esm.ubuntu.com:443 + github.com:443 + motd.ubuntu.com:443 + objects.githubusercontent.com:443 + packages.microsoft.com:443 + - name: Checkout Repository uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 From 8ef0c09973f7883defb4fa0cf8fcf3e9400f4ae2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:32:33 +0000 Subject: [PATCH 14/16] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/Diagnostics.cpp | 2 +- src/ParseManagementFile.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Diagnostics.cpp b/src/Diagnostics.cpp index 37166b1..0c84fde 100644 --- a/src/Diagnostics.cpp +++ b/src/Diagnostics.cpp @@ -556,7 +556,7 @@ double CDiagnostic::CalculateDiagnostic(CTimeSeriesABC *pTSMod, nnstart += _width; N=0; - + double sum1(0.0); for (nn=nnstart;nnGetLineNumber(); if (!strcmp(s[1],"SB_GROUP" )) - { + { pLoopSBGroup=pModel->GetSubBasinGroup(s[2]); if (pLoopSBGroup == NULL) { ExitGracefully("ParseManagementFile: bad subbasin group name in :LoopThrough command",BAD_DATA_WARN); @@ -593,7 +593,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) loopCount=0; aLoopVector[0]=new string [pLoopSBGroup->GetNumSubbasins()]; aLoopVector[1]=new string [pLoopSBGroup->GetNumSubbasins()]; - for (int p = 0; p < pLoopSBGroup->GetNumSubbasins(); p++) + for (int p = 0; p < pLoopSBGroup->GetNumSubbasins(); p++) { long SBID = pLoopSBGroup->GetSubBasin(p)->GetID(); string SBName = pLoopSBGroup->GetSubBasin(p)->GetName(); @@ -612,15 +612,15 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) //pLoopDemandGroup=pDO->GetDemandGroup(s[2]); if (pLoopDemandGroup == NULL) { ExitGracefully("ParseManagementFile: bad demand group name in :LoopThrough command",BAD_DATA_WARN); - } + } else { loopCount=0; aLoopVector[0]=new string [pLoopDemandGroup->GetNumDemands()]; aLoopVector[1]=new string [pLoopDemandGroup->GetNumDemands()]; - for (int p = 0; p < pLoopDemandGroup->GetNumDemands(); p++) + for (int p = 0; p < pLoopDemandGroup->GetNumDemands(); p++) { long ID = pLoopDemandGroup->GetDemandID(loopCount); - string DName = "";// pLoopDemandGroup->GetDemand(loopCount)->GetName(); //todo: support + string DName = "";// pLoopDemandGroup->GetDemand(loopCount)->GetName(); //todo: support aLoopVector[0][p]=to_string(ID); aLoopVector[1][p]=DName; } @@ -630,7 +630,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) nWildcards=2; } } - else if (!strcmp(s[1], "LIST")) + else if (!strcmp(s[1], "LIST")) { loopListSize=s_to_i(s[2]); loopCount=0; @@ -648,13 +648,13 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) loopCount++; - if ((pLoopSBGroup!=NULL) && (loopCount == pLoopSBGroup->GetNumSubbasins()))//iterating subbasin loop + if ((pLoopSBGroup!=NULL) && (loopCount == pLoopSBGroup->GetNumSubbasins()))//iterating subbasin loop { pLoopSBGroup=NULL; loopDone=true; } else if ((pLoopDemandGroup != NULL) && (loopCount == pLoopDemandGroup->GetNumDemands())) - { + { pLoopDemandGroup=NULL; loopDone=true; } @@ -673,14 +673,14 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) loopListSize =0; pLoopSBGroup =NULL; pLoopDemandGroup=NULL; - } - else //not finished yet - update all wildcards and jump back to start of loop + } + else //not finished yet - update all wildcards and jump back to start of loop { for (int j = 0; j < nWildcards; j++) { aWildcards[j][1]=aLoopVector[j][loopCount]; } - // jump back to start of loop + // jump back to start of loop pp->SetPosition(loopStartPos); pp->SetLineCounter(loopStartLine); } From 883df24be391a742a028fb576f4e590c9f14b790 Mon Sep 17 00:00:00 2001 From: Trevor James Smith <10819524+Zeitsperre@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:35:48 -0400 Subject: [PATCH 15/16] simplify --- .github/workflows/testing.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 5cd6970..fdab5d2 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -125,14 +125,7 @@ jobs: cmake . cmake --build . --config ${{ matrix.build_type }} -j 3 - - name: Run tests (Linux and macOS) - if: steps.build.outcome == 'success' && matrix.os != 'windows-latest' + - name: Run tests run: | ./Raven ./Raven -v - - name: Run tests (Windows) - if: steps.build.outcome == 'success' && matrix.os == 'windows-latest' - run: | - ls - ./Raven.exe - ./Raven.exe -v From 85d154d0340d5651546e57f75fcd8ae523d7aee6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 19:38:32 +0000 Subject: [PATCH 16/16] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/CommonFunctions.cpp | 2 +- src/DemandExpressionHandling.cpp | 4 +-- src/DemandGroups.cpp | 3 +- src/DemandOptimization.cpp | 54 ++++++++++++++++---------------- src/Demands.h | 10 +++--- src/Makefile | 14 ++++----- src/ParseLib.cpp | 2 +- src/ParseManagementFile.cpp | 8 ++--- src/ParseTimeSeriesFile.cpp | 2 +- src/Raven.vcxproj | 2 +- src/Raven.vcxproj.filters | 2 +- src/UpdateForcings.cpp | 6 ++-- src/WaterDemands.cpp | 36 ++++++++++----------- 13 files changed, 72 insertions(+), 73 deletions(-) diff --git a/src/CommonFunctions.cpp b/src/CommonFunctions.cpp index 90c42eb..ed7e3c7 100644 --- a/src/CommonFunctions.cpp +++ b/src/CommonFunctions.cpp @@ -1831,7 +1831,7 @@ void quickSort(double arr[], int left, int right) } ////////////////////////////////////////////////////////////////// /// \brief adds value v to end of integer array a[] of original size n, expands a[] to size n+1 -// +// void pushIntoIntArray(int*&a, const int &v, int &n) { int *tmp=new int [n+1]; diff --git a/src/DemandExpressionHandling.cpp b/src/DemandExpressionHandling.cpp index 0fb8ae9..43847a9 100644 --- a/src/DemandExpressionHandling.cpp +++ b/src/DemandExpressionHandling.cpp @@ -296,7 +296,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t return true; } - } + } else { warn="ConvertToExpression:: Unparseable term in history expression starting with !/$ - only !Q, !D, !h, $B, or $E currently supported. "+warnstring; ExitGracefully(warn.c_str(), BAD_DATA_WARN); @@ -383,7 +383,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t return true; } //---------------------------------------------------------------------- - else if (s[0] == '$') + else if (s[0] == '$') { if ((s[1] == 'B') || (s[1] == 'E')) //Subbasin-indexed { diff --git a/src/DemandGroups.cpp b/src/DemandGroups.cpp index 1cf3e66..bc6eb11 100644 --- a/src/DemandGroups.cpp +++ b/src/DemandGroups.cpp @@ -12,7 +12,7 @@ CDemandGroup::CDemandGroup(string tag, int global_ind) { _name=tag; - _nDemands=0; + _nDemands=0; _pDemands=NULL; _global_ii=global_ind; } @@ -91,4 +91,3 @@ void CDemandGroup::AddDemand(CDemand *pDem) void CDemandGroup::Initialize() { } - diff --git a/src/DemandOptimization.cpp b/src/DemandOptimization.cpp index 3a95ee7..7fb3448 100644 --- a/src/DemandOptimization.cpp +++ b/src/DemandOptimization.cpp @@ -120,7 +120,7 @@ int CDemandOptimizer::GetDemandIndexFromName(const string demand_tag) const return DOESNT_EXIST; } ////////////////////////////////////////////////////////////////// -/// \brief gets demand from index +/// \brief gets demand from index // CDemand* CDemandOptimizer::GetWaterDemand(const int d) { return _pDemands[d]; @@ -132,16 +132,16 @@ int CDemandOptimizer::GetNumWaterDemands() const { return _nDemands; } ////////////////////////////////////////////////////////////////// -/// \brief gets demand group from index +/// \brief gets demand group from index // -CDemandGroup* CDemandOptimizer::GetDemandGroup(const int ii) +CDemandGroup* CDemandOptimizer::GetDemandGroup(const int ii) { return _pDemandGroups[ii]; } ////////////////////////////////////////////////////////////////// -/// \brief gets demand group from name, or NULL if invalid name +/// \brief gets demand group from name, or NULL if invalid name // -CDemandGroup* CDemandOptimizer::GetDemandGroupFromName(const string name) +CDemandGroup* CDemandOptimizer::GetDemandGroupFromName(const string name) { for (int ii=0;ii<_nDemandGroups;ii++){ if (_pDemandGroups[ii]->GetName() == name) { @@ -151,14 +151,14 @@ CDemandGroup* CDemandOptimizer::GetDemandGroupFromName(const string name) return NULL; } ////////////////////////////////////////////////////////////////// -/// \brief gets demand group from index +/// \brief gets demand group from index // -int CDemandOptimizer::GetNumDemandGroups() const +int CDemandOptimizer::GetNumDemandGroups() const { return _nDemandGroups; } ////////////////////////////////////////////////////////////////// -/// \brief returns true if demands have been initialized +/// \brief returns true if demands have been initialized // bool CDemandOptimizer::DemandsAreInitialized() const { @@ -206,7 +206,7 @@ void CDemandOptimizer::SetDebugLevel(const int val) /// \brief assigns a demand 'unrestricted' status, meaning it wont be considered when applying environmental min flow constraints /// \params dname [in] - name of demand // -void CDemandOptimizer::SetDemandAsUnrestricted(const string dname) +void CDemandOptimizer::SetDemandAsUnrestricted(const string dname) { int d = GetDemandIndexFromName(dname); if (d!=DOESNT_EXIST){ @@ -214,7 +214,7 @@ void CDemandOptimizer::SetDemandAsUnrestricted(const string dname) } else{ string warn = "CDemandOptimizer::SetDemandAsUnrestricted: invalid or disabled demand name " + dname +" provided in : DemandIsUnrestricted command. This will be ignored "; - WriteWarning(warn,true); + WriteWarning(warn,true); } } ////////////////////////////////////////////////////////////////// @@ -229,7 +229,7 @@ void CDemandOptimizer::SetDemandPenalty(const string dname, const double& pen) } else { string warn = "CDemandOptimizer::SetDemandPenalty: invalid or disabled demand name " + dname +" provided in : DemandPenalty command. This will be ignored "; - WriteWarning(warn,true); + WriteWarning(warn,true); } } ////////////////////////////////////////////////////////////////// @@ -253,7 +253,7 @@ void CDemandOptimizer::SetCumulativeDate(const int julian_date, const string dem /// \brief adds demand group to array of demand groups /// \params groupname [in] - user-specified demand group name // -void CDemandOptimizer::AddDemandGroup(const string groupname) +void CDemandOptimizer::AddDemandGroup(const string groupname) { CDemandGroup *pDG=new CDemandGroup(groupname,_nDemandGroups); @@ -265,7 +265,7 @@ void CDemandOptimizer::AddDemandGroup(const string groupname) /// \brief adds demand ONLY if subbasin associated with demand is enabled, otherwise tosses out. /// \params pDem [in] - pointer to demand object // -void CDemandOptimizer::AddWaterDemand(CDemand* pDem) +void CDemandOptimizer::AddWaterDemand(CDemand* pDem) { long SBID=pDem->GetSubBasinID(); if (_pModel->GetSubBasinByID(SBID)->IsEnabled()) @@ -548,7 +548,7 @@ void CDemandOptimizer::InitializeDemands(CModel* pModel, const optStruct& Option if (Options.noisy){cout<<"CDemandOptimizer: Demand initialization..."<GetSubBasinByID(_pDemands[d]->GetSubBasinID())->GetGlobalIndex(); pDV=new decision_var(_pDemands[d]->GetName(), p, DV_DELIVERY, d); @@ -613,7 +613,7 @@ void CDemandOptimizer::InitializePostRVMRead(CModel* pModel, const optStruct& Op _aDhist[pp][i]=0.0; } } - + int p; _nSlackVars = 0; CSubBasin *pSB; @@ -854,7 +854,7 @@ void CDemandOptimizer::AddReservoirConstraints() TokenizeString(expString, s, Len); exp = ParseExpression((const char**)(s), Len, 0, "internal"); - + pConst=new manConstraint(); pConst->name=TSname; pConst->is_goal=true; @@ -1116,7 +1116,7 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio for (int d = 0; d < _nDemands; d++) { _pDemands[d]->UpdateDemand(Options,tt); } - + // instantiate linear programming solver // ---------------------------------------------------------------- lp_lib::lprec *pLinProg; @@ -1217,7 +1217,7 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio d=0; // penalties for unmet demand // ---------------------------------------------------------------- - for (int d = 0; d < _nDemands; d++) + for (int d = 0; d < _nDemands; d++) { demand_penalty_sum+=(_pDemands[d]->GetPenalty()*_pDemands[d]->GetDemand()); @@ -1637,7 +1637,7 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio retval = lp_lib::solve(pLinProg); if (retval!=OPTIMAL){ - cout<<"code: "<GetCumulDeliveryDate()){ - _aCumDelivery[d]=0.0; + _aCumDelivery[d]=0.0; } if (!_pDemands[d]->IsReservoirDemand()){ @@ -1913,7 +1913,7 @@ void CDemandOptimizer::WriteMinorOutput(const optStruct &Options,const time_stru int ii; _GOALSAT<GetPenalty();} ii =_pDemands[d]->GetLocalIndex(); @@ -1922,10 +1922,10 @@ void CDemandOptimizer::WriteMinorOutput(const optStruct &Options,const time_stru } int k=_nDemands+2*_nReservoirs; //first slack terms are due to environmental flow constraints (nDemands) and reservoir outflow targets (2*nReservoirs) - for (int i = 0; i < _nConstraints; i++) + for (int i = 0; i < _nConstraints; i++) { if (_pConstraints[i]->is_goal) { - if (_pConstraints[i]->pOperRegimes[0]->pExpression->compare != COMPARE_IS_EQUAL) + if (_pConstraints[i]->pOperRegimes[0]->pExpression->compare != COMPARE_IS_EQUAL) { if (include_pen){mult=_pConstraints[i]->penalty_over;} @@ -1933,7 +1933,7 @@ void CDemandOptimizer::WriteMinorOutput(const optStruct &Options,const time_stru _GOALSAT<<","<penalty_over;} pen =mult*_aSlackValues[k]; diff --git a/src/Demands.h b/src/Demands.h index b7b1323..74debeb 100644 --- a/src/Demands.h +++ b/src/Demands.h @@ -15,11 +15,11 @@ class CDemand { private:/*------------------------------------------------------*/ int _ID; ///< unique integer identifier - string _name; ///< unique name/alias identifier + string _name; ///< unique name/alias identifier - long _SBID; ///< subbasin ID - int _loc_index; ///< local demand index (counter in each subbasin) - bool _is_reservoir; ///< true if withdrawal is from reservoir + long _SBID; ///< subbasin ID + int _loc_index; ///< local demand index (counter in each subbasin) + bool _is_reservoir; ///< true if withdrawal is from reservoir double _penalty; ///< penalty for not satisfying demand [s/m3] @@ -31,7 +31,7 @@ class CDemand //int _irrigHRUGroup; ///< index kk of HRU group on which withdrawn water is applied //double _returnPct; ///< percentage of flow which returns to stream - double _multiplier; ///< multiplies time series or any other means of calculating demand + double _multiplier; ///< multiplies time series or any other means of calculating demand CTimeSeries *_pDemandTS; ///< pointer to time series of demands (or NULL, if calculated elsewise) diff --git a/src/Makefile b/src/Makefile index 99409ab..2483ff9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -11,25 +11,25 @@ # Mar 2017 Juliane Mai - increase stack size to 256 MB from standard 64MB # Jan 2019 Alan J. Barton - added OS name to created exe name # Dec 2023 David Huard - support for python binding -# Jul 2024 James Craig and Bohao Tang - support for lp_solve +# Jul 2024 James Craig and Bohao Tang - support for lp_solve ### # appname := raven_rev$(shell svnversion -n . | sed -e 's/:/-/g')_$(shell uname -o).exe appname := Raven.exe CXX := g++ CXXFLAGS := -Wno-deprecated -LDLIBS := +LDLIBS := LDFLAGS := # OPTION 0) some compilers require the c++11 flag, some may not CXXFLAGS += -std=c++11 -fPIC -# OPTION 1) include netcdf - uncomment following two commands (assumes netCDF path = /usr/local): -#CXXFLAGS += -Dnetcdf -#LDLIBS += -L/usr/local -lnetcdf +# OPTION 1) include netcdf - uncomment following two commands (assumes netCDF path = /usr/local): +#CXXFLAGS += -Dnetcdf +#LDLIBS += -L/usr/local -lnetcdf # OPTION 2) include lp_solve - uncomment following two commands (assumes liblpsolve55.a in ../lib/lp_solve_unix/ folder): -CXXFLAGS += -D_LPSOLVE_ +CXXFLAGS += -D_LPSOLVE_ LDLIBS += -L../lib/lp_solve_unix -llpsolve55 # OPTION 3) if you use a OSX/BSD system, uncomment the LDFLAGS line below @@ -37,7 +37,7 @@ LDLIBS += -L../lib/lp_solve_unix -llpsolve55 # LDFLAGS += -Wl,-stack_size,0x80000000,-stack_addr,0xf0000000 # OPTION 4) uncomment for M1 and newer MacOS -#CXXFLAGS := -Dfinite=isfinite +#CXXFLAGS := -Dfinite=isfinite srcfiles := $(shell ls *.cpp) objects := $(patsubst %.cpp, %.o, $(srcfiles)) diff --git a/src/ParseLib.cpp b/src/ParseLib.cpp index 3720b6a..de44bea 100644 --- a/src/ParseLib.cpp +++ b/src/ParseLib.cpp @@ -138,7 +138,7 @@ bool CParser::Tokenize(char **out, int &numwords){ if (_parsing_math_exp) { string line; - line=AddSpacesBeforeOps(wholeline); + line=AddSpacesBeforeOps(wholeline); strcpy(wholeline,line.c_str()); _parsing_math_exp=false; } diff --git a/src/ParseManagementFile.cpp b/src/ParseManagementFile.cpp index 8ae08a1..ebac7b7 100644 --- a/src/ParseManagementFile.cpp +++ b/src/ParseManagementFile.cpp @@ -566,7 +566,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } } //---------------------------------------------- - else if (!strcmp(s[0], ":Penalty")) + else if (!strcmp(s[0], ":Penalty")) { if (Options.noisy){cout<<" Penalty "<is_goal) { @@ -579,7 +579,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) } } //---------------------------------------------- - else if (!strcmp(s[0], ":Priority")) + else if (!strcmp(s[0], ":Priority")) { if (Options.noisy){cout<<" Priority "<priority = s_to_i(s[1]); //for later @@ -609,7 +609,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) if (!badgoal) { pDO->AddGoalOrConstraint(pConst); } - + break; } case(24): //---------------------------------------------- @@ -895,4 +895,4 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options) pp=NULL; return true; -} \ No newline at end of file +} diff --git a/src/ParseTimeSeriesFile.cpp b/src/ParseTimeSeriesFile.cpp index d661acc..b7ad06d 100644 --- a/src/ParseTimeSeriesFile.cpp +++ b/src/ParseTimeSeriesFile.cpp @@ -627,7 +627,7 @@ bool ParseTimeSeriesFile(CModel *&pModel, const optStruct &Options) pTimeSer->SetIDTag(demand_ID); pSB->GetReservoir()->AddDemandTimeSeries(pTimeSer); - + if (Options.management_optimization){ CDemand *pDem=new CDemand(demand_ID,demand_name,SBID,true,pTimeSer); pDem->SetLocalIndex(ii); diff --git a/src/Raven.vcxproj b/src/Raven.vcxproj index 92ce3c7..fcdfdea 100644 --- a/src/Raven.vcxproj +++ b/src/Raven.vcxproj @@ -1039,4 +1039,4 @@ - \ No newline at end of file + diff --git a/src/Raven.vcxproj.filters b/src/Raven.vcxproj.filters index 0bd614c..e6d21d1 100644 --- a/src/Raven.vcxproj.filters +++ b/src/Raven.vcxproj.filters @@ -715,4 +715,4 @@ Resource Files - \ No newline at end of file + diff --git a/src/UpdateForcings.cpp b/src/UpdateForcings.cpp index 83113be..99eac88 100644 --- a/src/UpdateForcings.cpp +++ b/src/UpdateForcings.cpp @@ -598,13 +598,13 @@ void CModel::UpdateHRUForcingFunctions(const optStruct &Options, //------------------------------------------------------------------- // Irrigation //------------------------------------------------------------------- - F.irrigation=0.0; //FOR NOW + F.irrigation=0.0; //FOR NOW //F.irrigation=GetDemandOptimizer()->EstimateIrrigation(F,_pHydroUnits[k],Options,tt); //------------------------------------------------------------------- - // Direct evaporation of rainfall / irrigation + // Direct evaporation of rainfall / irrigation //------------------------------------------------------------------- - if(Options.direct_evap) + if(Options.direct_evap) { double rainfall=F.precip*(1.0-F.snow_frac); double reduce =min(F.PET,rainfall+F.irrigation); diff --git a/src/WaterDemands.cpp b/src/WaterDemands.cpp index 4a4fa96..f1881c2 100644 --- a/src/WaterDemands.cpp +++ b/src/WaterDemands.cpp @@ -8,7 +8,7 @@ /// \brief Implementation of the water demand constructor /// \details Creates empty instance of the water demand class // -CDemand::CDemand(int ID, string name, long SBID, bool is_res) +CDemand::CDemand(int ID, string name, long SBID, bool is_res) { _ID=ID; _name=name; @@ -18,7 +18,7 @@ CDemand::CDemand(int ID, string name, long SBID, bool is_res) _loc_index=DOESNT_EXIST; _unrestricted=0; _cumDelivDate=0; //Jan-1 - + _penalty=1.0; _multiplier=1.0; @@ -26,22 +26,22 @@ CDemand::CDemand(int ID, string name, long SBID, bool is_res) _currentDemand=0; } -CDemand::CDemand(int ID, string name, long SBID, bool is_res, CTimeSeries* pTS):CDemand(ID,name,SBID,is_res) +CDemand::CDemand(int ID, string name, long SBID, bool is_res, CTimeSeries* pTS):CDemand(ID,name,SBID,is_res) { _pDemandTS=pTS; } -CDemand::~CDemand() +CDemand::~CDemand() { - //delete _pDemandTS; //only copy of time series here - actual is tied to subbasin + //delete _pDemandTS; //only copy of time series here - actual is tied to subbasin } ////////////////////////////////////////////////////////////////// /// \brief Water demand accessors // -int CDemand::GetID() const +int CDemand::GetID() const { return _ID; } -string CDemand::GetName() const +string CDemand::GetName() const { return _name; } @@ -50,7 +50,7 @@ int CDemand::GetLocalIndex() const ExitGracefullyIf(_loc_index==DOESNT_EXIST,"CDemand::GetLocalIndex(): didnt set local index",RUNTIME_ERR); return _loc_index; } -long CDemand::GetSubBasinID() const +long CDemand::GetSubBasinID() const { return _SBID; } @@ -58,11 +58,11 @@ double CDemand::GetPenalty() const { return _penalty; } -bool CDemand::IsUnrestricted() const +bool CDemand::IsUnrestricted() const { return _unrestricted; } -int CDemand::GetCumulDeliveryDate() const +int CDemand::GetCumulDeliveryDate() const { return _cumDelivDate; } @@ -70,26 +70,26 @@ bool CDemand::IsReservoirDemand() const { return _is_reservoir; } -double CDemand::GetDemand() const +double CDemand::GetDemand() const { return _currentDemand; } ////////////////////////////////////////////////////////////////// /// \brief Water demand manipulators // -void CDemand::SetLocalIndex(const int ii) +void CDemand::SetLocalIndex(const int ii) { _loc_index=ii; } -void CDemand::SetDemandPenalty(const double& P) +void CDemand::SetDemandPenalty(const double& P) { _penalty=P; } -void CDemand::SetCumulDeliveryDate(const int date) +void CDemand::SetCumulDeliveryDate(const int date) { _cumDelivDate=date; } -void CDemand::SetAsUnrestricted() +void CDemand::SetAsUnrestricted() { _unrestricted=true; } @@ -100,14 +100,14 @@ void CDemand::SetMultiplier(const double& M) ////////////////////////////////////////////////////////////////// /// \brief re-calculates current demand magnitude (_currentDemand) - called at start of time step // -void CDemand::UpdateDemand(const optStruct &Options,const time_struct& tt) +void CDemand::UpdateDemand(const optStruct &Options,const time_struct& tt) { //if (_demand_type==DEM_TIME_SERIES) if (_pDemandTS!=NULL) { //int nn=tt.nn; int nn=(int)((tt.model_time+TIME_CORRECTION)/Options.timestep);//current timestep index - + double Qirr=_pDemandTS->GetSampledValue(nn); if (Qirr==RAV_BLANK_DATA){Qirr=0.0;} @@ -119,4 +119,4 @@ void CDemand::UpdateDemand(const optStruct &Options,const time_struct& tt) else if (_demand_type == DEM_SOIL_MOISTURE) { }*/ -} \ No newline at end of file +}