static void _MDDischRouteMuskingumCoeff (int itemID) { // Input float yMean; // Average depth at mean discharge [m] float wMean; // River width at mean discharge [m] float vMean; // Mean velocity float beta; // Riverbed shape exponent [] float slope; // Riverbed slope [m/km] // Output float C0; // Muskingum C0 coefficient (current inflow) float C1; // Muskingum C1 coefficient (previous inflow) float C2; // MUskingum C2 coefficient (previous outflow) // Local float xi; // Flood-wave/flow velocity ratio float C; // Cell Courant number; float D; // Cell Reynolds number; float dt; // time step length [s] float dL; // Cell length [m] dL = MFModelGetLength (itemID); slope = MFVarGetFloat (_MDInRiverbedSlopeID, itemID, 0.0) / 1000.0; yMean = MFVarGetFloat (_MDInRiverbedAvgDepthMeanID, itemID, 0.0); wMean = MFVarGetFloat (_MDInRiverbedWidthMeanID, itemID, 0.0); vMean = MFVarGetFloat (_MDInRiverbedVelocityMeanID, itemID, 0.0); beta = MFVarGetFloat (_MDInRiverbedShapeExponentID, itemID, 0.0); if (CMmathEqualValues (vMean, 0.0)) { MFVarSetFloat (_MDOutMuskingumC0ID, itemID, 0.0); MFVarSetFloat (_MDOutMuskingumC1ID, itemID, 0.0); MFVarSetFloat (_MDOutMuskingumC2ID, itemID, 0.0); MFVarSetFloat (_MDOutCourantID, itemID, 0.0); return; } if (CMmathEqualValues (dL, 0.0) || CMmathEqualValues (slope, 0.0) || CMmathEqualValues (yMean, 0.0) || CMmathEqualValues (wMean, 0.0) || (beta < 0.0)) { // Falling back to flow-accumulation MFVarSetFloat (_MDOutMuskingumC0ID, itemID, 1.0); MFVarSetFloat (_MDOutMuskingumC1ID, itemID, 0.0); MFVarSetFloat (_MDOutMuskingumC2ID, itemID, 0.0); MFVarSetFloat (_MDOutCourantID, itemID, 0.0); return; } dt = MFModelGet_dt (); xi = 1 + beta * (2.0 / 3.0) / (beta + 1); C = xi * vMean * dt / dL; D = yMean / (dL * slope * xi); C0 = (-1 + C + D) / (1 + C + D); C1 = ( 1 + C - D) / (1 + C + D); C2 = ( 1 - C + D) / (1 + C + D); // if ((C0 < 0.0) || (C1 < 0.0) || (C2 < 0.0)) { C0 = 1.0; C1 = 0; C2 = 0; } // According to Pounce C1 and C2 can be negative MFVarSetFloat (_MDOutMuskingumC0ID, itemID, C0); MFVarSetFloat (_MDOutMuskingumC1ID, itemID, C1); MFVarSetFloat (_MDOutMuskingumC2ID, itemID, C2); MFVarSetFloat (_MDOutCourantID, itemID, C); }
static void _MDRunoffVolume (int itemID) { // Input float runoff; runoff = MFVarGetFloat (_MDInRunoffID, itemID, 0.0) * MFModelGetArea (itemID) / (MFModelGet_dt () * 1000.0); // if((itemID == 25014) && (runoff * 86400 < -0.000009)) printf("############ runoff = %f\n", runoff * 86400); //runoff = 0.0; //RJS 071511 MFVarSetFloat (_MDOutRunoffVolumeID, itemID, runoff); }
static void _MDReservoirDW (int itemID) { // Input float discharge; // Current discharge [m3/s] float meanDischarge; // Long-term mean annual discharge [m3/s] float resCapacity; // Reservoir capacity [km3] // Output float resStorage; // Reservoir storage [km3] float resStorageChg; // Reservoir storage change [km3/dt] float resRelease; // Reservoir release [m3/s] // local float prevResStorage; // Reservoir storage from the previous time step [km3] float dt; // Time step length [s] float balance; // water balance [m3/s] // Parameters float drySeasonPct = 0.60; // RJS 071511 float wetSeasonPct = 0.16; // RJS 071511 float year = 0; // RJS 082311 discharge = MFVarGetFloat (_MDInDischargeID, itemID, 0.0); meanDischarge = MFVarGetFloat (_MDInDischMeanID, itemID, discharge); year = MFDateGetCurrentYear(); if ((resCapacity = MFVarGetFloat (_MDInResCapacityID, itemID, 0.0)) <= 0.0) { MFVarSetFloat (_MDOutResStorageID, itemID, 0.0); MFVarSetFloat (_MDOutResStorageChgID, itemID, 0.0); MFVarSetFloat (_MDOutResReleaseID, itemID, discharge); return; } dt = MFModelGet_dt (); prevResStorage = MFVarGetFloat(_MDOutResStorageID, itemID, 0.0); resRelease = discharge > meanDischarge ? wetSeasonPct * discharge : drySeasonPct * discharge + (meanDischarge - discharge); resStorage = prevResStorage + (discharge - resRelease) * 86400.0 / 1e9; if (resStorage > resCapacity) { resRelease = discharge * dt / 1e9 + prevResStorage - resCapacity; resRelease = resRelease * 1e9 / dt; resStorage = resCapacity; } else if (resStorage < 0.0) { resRelease = prevResStorage + discharge * dt / 1e9; resRelease = resRelease * 1e9 / dt; resStorage=0; } resStorageChg = resStorage - prevResStorage; balance = discharge - resRelease - (resStorageChg / 86400 * 1e9); // water balance MFVarSetFloat (_MDOutResStorageID, itemID, resStorage); MFVarSetFloat (_MDOutResStorageChgID, itemID, resStorageChg); }
static void _MDReservoir (int itemID) { // Input float discharge; // Current discharge [m3/s] float meanDischarge; // Long-term mean annual discharge [m3/s] float resCapacity; // Reservoir capacity [km3] // Output float resStorage; // Reservoir storage [km3] float resStorageChg; // Reservoir storage change [km3/dt] float resRelease; // Reservoir release [m3/s] // local float prevResStorage; // Reservoir storage from the previous time step [km3] float dt; // Time step length [s] float beta; // Residence time [a] // wet { -0.19 B + 0.88 Q_t } & {Q_t > Q_m } // dry {0.47 B + 1.12 Q_t } & {Q_t \le Q_m } discharge = MFVarGetFloat (_MDInDischargeID, itemID, 0.0); meanDischarge = MFVarGetFloat (_MDInDischMeanID, itemID, discharge); if ((resCapacity = MFVarGetFloat (_MDInResCapacityID, itemID, 0.0)) <= 0.0) { MFVarSetFloat (_MDOutResStorageID, itemID, 0.0); MFVarSetFloat (_MDOutResStorageChgID, itemID, 0.0); MFVarSetFloat (_MDOutResReleaseID, itemID, discharge); return; } beta = resCapacity /(meanDischarge * 3600 * 24 * 365/1e9); dt = MFModelGet_dt (); prevResStorage = MFVarGetFloat(_MDOutResStorageID, itemID, 0.0); resRelease = discharge > meanDischarge ? - 0.19 * beta + 0.88 * discharge : 0.47 * beta + 1.12 * discharge; resStorage = prevResStorage + (discharge - resRelease) * 86400.0 / 1e9; if (resStorage > resCapacity) { resRelease = discharge * dt / 1e9 + prevResStorage - resCapacity; resRelease = resRelease * 1e9 / dt; resStorage = resCapacity; } else if (resStorage < 0.0) { resRelease = prevResStorage + discharge * dt / 1e9; resRelease = resRelease * 1e9 / dt; resStorage=0; } resStorageChg = resStorage - prevResStorage; MFVarSetFloat (_MDOutResStorageID, itemID, resStorage); MFVarSetFloat (_MDOutResStorageChgID, itemID, resStorageChg); MFVarSetFloat (_MDOutResReleaseID, itemID, resRelease); }
static void _MDSpecCond (int itemID) { float stormflowVol = 0.0; float baseflowVol = 0.0; float runoffpoolreleaseVol = 0.0; float discharge = 0.0; float waterStorage = 0.0; // New Variables // float Developed = 0.0; float preFlux_SC = 0.0; float postFlux_SC = 0.0; float storeWater_SC = 0.0; float postStoreWater_SC = 0.0; float SCTotalIn = 0.0; float postConc_SC = 0.0; float massBalance_SC = 0.0; float localLoad_SC = 0.0; float baseflowConc_SC = 0.0; float stormflowConc_SC = 0.0; float surfflowConc_SC = 0.0; float clean_intrcp = 0.0; float airTemperature = 0.0; baseflowVol = MFVarGetFloat (_MDInBaseFlowID, itemID,0.0) * MFModelGetArea (itemID) / (MFModelGet_dt () * 1000.0); // TODO: Either need to define BaseFlowVolumeDef or calculate internally here. stormflowVol = MFVarGetFloat (_MDInStormRunoffTotalID, itemID,0.0) * MFModelGetArea (itemID) / (MFModelGet_dt () * 1000.0); runoffpoolreleaseVol = MFVarGetFloat (_MDInRunoffPoolReleaseID, itemID,0.0) * MFModelGetArea (itemID) / (MFModelGet_dt () * 1000.0); discharge = MFVarGetFloat (_MDInDischargeID, itemID, 0.0); // m3/sec, discharge leaving the grid cell, after routing! waterStorage = MFVarGetFloat (_MDInRiverStorageID, itemID, 0.0); // m3/sec, storage rate remaining in grid cell at end of timestep - routed to retention airTemperature = MFVarGetFloat (_MDInAirTemperatureID, itemID, 0.0); // degrees C // New Variables // Developed = MFVarGetFloat (_MDInSubFractionID, itemID, 0.0); // proportion developed land // DEFINE IONIC CONTENT: ic = m3*(uS/cm) // Assumes that ionic strength behaves linearly and conservatively. Strictly this is only valid when // ionic strength is controlled by a few conservative ions. Therefore, this is valid for salt impacted // streams; however, this breaks down at low ionic strength waters. Therefore - this deep in the chloride analysis // we are operating with the understanding that we are only really looking at chloride impacts - not chloride itself. - SZ 6/12/2014 preFlux_SC = MFVarGetFloat (_MDOutFlux_SCID, itemID, 0.0); // ic/day storeWater_SC = MFVarGetFloat (_MDOutStoreWater_SCID, itemID, 0.0); // ic/day /// BASEFLOW LOADING OF SPECIFIC CONDUCTANCE /// /// attributed to the groundwater and surface runoff pools - impervious runof is attributed with clean water /// [email protected] for details on loading estimation /// //baseflowConc_SC = 25.94 + 13.32 * (Developed); // Baseflow_SC relation (0.9 Quantile based) to Developed area. Developed should already be in PER clean_intrcp = 21.72;//25.94; baseflowConc_SC = clean_intrcp + 9.602 * (Developed); // Baseflow SC relation (regression to zero storm flow) to Devloped area. // Predicting dilution rate based on AWC and Ksat does not help time-series predictions. Though there is an apparent dependence on these factors in the lovotecs data. surfflowConc_SC = MDMaximum(0.64 * baseflowConc_SC,clean_intrcp); // 0.8244 // Average fraction of baseflow SC exhibited during storm events (at daily flow exceedance of 1% P1) stormflowConc_SC = (airTemperature < 2.0) ? 15.0*Developed/100.*baseflowConc_SC : MDMaximum(0.20 * baseflowConc_SC,0.8*clean_intrcp); // Winter-time salting. // Calculate input loadings localLoad_SC = (baseflowConc_SC * baseflowVol + surfflowConc_SC * runoffpoolreleaseVol + stormflowVol*stormflowConc_SC ) * 86400 ; // ic/day SCTotalIn = localLoad_SC + preFlux_SC + storeWater_SC; // ic/day if (discharge > 0.0000001) { // Calculate pre-tranformation concentration - for cells with accumulated discharge postConc_SC = SCTotalIn / (discharge * 86400.); // uS/cm } else { // Force concentrations to local values for minimal accumulation / dessicated cells postConc_SC = baseflowConc_SC; // Force negligible discharge to the baseflow concentration } //Calculates the fluxes/storage for the mixing (appropriate for speccond) case postFlux_SC = (discharge * MDConst_m3PerSecTOm3PerDay) * postConc_SC ; // ic/day postStoreWater_SC = (waterStorage ) * postConc_SC ; // ic/day // Calculates the mass balances massBalance_SC = (SCTotalIn - (postFlux_SC + postStoreWater_SC )) / SCTotalIn; // Print mass balance errors if (MFDateGetCurrentYear() > 0){ if ( (massBalance_SC > 0.001)) { printf("itemID = %d, %d-%d-%d, MB_SC = %f\n",itemID, MFDateGetCurrentYear(), MFDateGetCurrentMonth(), MFDateGetCurrentDay(), massBalance_SC); printf("\tTotalIn: %f, Local: %f , UpFlux: %f, InStore: %f\n",SCTotalIn,localLoad_SC,preFlux_SC,storeWater_SC); printf("\tDownFlux: %f, discharge; %f, OutStore: %f , storage: %f\n",postFlux_SC,discharge, postStoreWater_SC,waterStorage); } // Debug prints //if ((itemID == 8310)) { //printf("itemID = %d, order %f, Store_SC %f, Store %f Store2 %f StoreDelta %f StorePrev %f StoreSCconc %f \n ",itemID, order, storeWater_SC, waterStorage*86400.,(discharge - dischargePre)*86400.,waterStorageChange*86400.,waterStoragePrev, storeWater_SC / waterStoragePrev ) ; //} //if (postConc_SC < 21.70){ //printf("itemID = %d, order %f, Store_SC %f, Store %f Store2 %f StoreDelta %f StorePrev %f StoreSCconc %f \n ",itemID, order, storeWater_SC, waterStorage*86400.,(discharge - dischargePre)*86400.,waterStorageChange*86400.,waterStoragePrev, storeWater_SC / waterStoragePrev ) ; // printf("itemID %d ro %f bf %f srf %f str %f bfSC %f srfSC %f strSC %f \n",itemID,runoffVol,baseflowVol,runoffpoolreleaseVol,stormflowVol,baseflowConc_SC,stormflowConc_SC,clean_intrcp); //} } // Set Output MFVarSetFloat (_MDOutFlux_SCID, itemID, postFlux_SC); MFVarSetFloat (_MDOutLocalLoadSCID, itemID, localLoad_SC); MFVarSetFloat (_MDOutPostConc_SCID, itemID, postConc_SC); MFVarSetFloat (_MDOutStoreWater_SCID, itemID, postStoreWater_SC); }