void ReservoirMethod::Get1DData(const char *key, int *nRows, float **data) { initialOutputs(); string sk(key); if (StringMatch(sk, VAR_REVAP)) { *data = m_D_Revap; *nRows = m_nCells; } else if (StringMatch(sk, VAR_RG)) { *data = m_T_RG; *nRows = m_nSubbasins + 1; } else if (StringMatch(sk, VAR_SBQG)) { *data = m_T_QG; *nRows = m_nSubbasins + 1; } else if (StringMatch(sk, VAR_SBGS)) { *data = m_gwStore; *nRows = m_nSubbasins + 1; } else if (StringMatch(sk, VAR_SBPET)) { *data = m_petSubbasin; *nRows = m_nSubbasins + 1; } else throw ModelException(MID_GWA_RE, "Get1DData", "Parameter " + sk + " does not exist."); }
int MUSLE_AS::Execute() { CheckInputData(); initialOutputs(); #pragma omp parallel for for (int i = 0; i < m_nCells; i++) { if (m_surfaceRunoff[i] < 0.0001f || m_streamLink[i] > 0) m_sedimentYield[i] = 0.f; else { float q = getPeakRunoffRate(i); //equation 2 in memo, peak flow float Y = 11.8f * pow(m_surfaceRunoff[i] * m_cellAreaKM * 1000.0f * q, 0.56f) * m_usle_k[i][0] * m_usle_ls[i] * m_usle_c[i] * m_usle_p[i]; //equation 1 in memo, sediment yield if (m_snowAccumulation[i] > 0.0001f) Y /= exp(3.f * m_snowAccumulation[i] / 25.4f); //equation 4 in memo, the snow pack effect m_sedimentYield[i] = Y * 1000.f; /// kg } //if(i == 1000) cout << m_sedimentYield[i] << "," << m_surfaceRunoff[i] << endl; /// particle size distribution of sediment yield m_sandYield[i] = m_sedimentYield[i] * m_detachSand[i]; m_siltYield[i] = m_sedimentYield[i] * m_detachSilt[i]; m_clayYield[i] = m_sedimentYield[i] * m_detachClay[i]; m_smaggreYield[i] = m_sedimentYield[i] * m_detachSmAggre[i]; m_lgaggreYield[i] = m_sedimentYield[i] * m_detachLgAggre[i]; } return 0; }
void ReservoirMethod::Get2DData(const char *key, int *nRows, int *nCols, float ***data) { initialOutputs(); string sk(key); if (StringMatch(sk, VAR_GWWB)) { *data = m_T_GWWB; *nRows = m_nSubbasins + 1; *nCols = 6; } else throw ModelException(MID_GWA_RE, "Get2DData", "Parameter " + sk + " does not exist in current module."); }
void DepressionFSDaily::Get1DData(const char *key, int *n, float **data) { initialOutputs(); string sk(key); *n = m_nCells; if (StringMatch(sk, VAR_DPST)) *data = m_sd; else if (StringMatch(sk, VAR_DEET)) *data = m_ed; else if (StringMatch(sk, VAR_SURU)) *data = m_sr; else throw ModelException(MID_DEP_LINSLEY, "Get1DData", "Output " + sk+" does not exist."); }
void MUSLE_AS::Get1DData(const char *key, int *n, float **data) { initialOutputs(); string sk(key); if (StringMatch(sk, VAR_SOER)) *data = m_sedimentYield; else if (StringMatch(sk, VAR_USLE_LS)) *data = m_usle_ls; else if (StringMatch(sk, VAR_SANDYLD)) *data = m_sandYield; else if (StringMatch(sk, VAR_SILTYLD)) *data = m_siltYield; else if (StringMatch(sk, VAR_CLAYYLD)) *data = m_clayYield; else if (StringMatch(sk, VAR_SAGYLD)) *data = m_smaggreYield; else if (StringMatch(sk, VAR_LAGYLD)) *data = m_lgaggreYield; else throw ModelException(MID_MUSLE_AS, "Get1DData", "Result " + sk + " does not exist."); *n = m_nCells; }
int YLD::Execute() { CheckInputData(); initialOutputs(); struct tm timeinfo; LocalTime(m_date, &timeinfo); timeinfo.tm_mon = 0; timeinfo.tm_mday = 0; timeinfo.tm_hour = 0; timeinfo.tm_min = 0; timeinfo.tm_sec = 0; timeinfo.tm_isdst = false; time_t tYear = mktime(&timeinfo); time_t harvestDate = tYear + m_harvestDate; #pragma omp parallel for for (int i = 0; i < m_nCells; i++) { if (m_date > harvestDate && !m_harvested) { m_harvested = true; m_common->m_classification = (int) (m_classification[i]); //Harvest index //float harvestIndex = 0.0f;// potential harvest index for a given day //float totalPlantET = 0.0f;//actual ET simulated during life of plant //float totalPlantPET = 0.0f;//potential ET simulated during life of plant ////get total ET and PET(see grow.f Line 289-292) from zhiqiang if (m_frPHU[i] > 0.5 && m_frPHU[i] < m_frDeclineLAI[i]) { m_totalPlantET[i] += m_totalWaterUptake[i] + m_soilET[i]; m_totalPlantPET[i] += m_PET[i]; } // water deficiency factor m_wur[i] = 100.0f; if (m_totalPlantPET[i] > 10) m_wur[i] *= m_totalPlantET[i] / m_totalPlantPET[i]; //get optimal harvest index, p309 5:2.4.1 m_HI[i] = m_HiOpt[i] * 100.0f * m_frPHU[i] / (100.0f * m_frPHU[i] + exp(11.1f - 10.0f * m_frPHU[i])); m_Hiact[i] = m_HI[i] - m_HiMin[i] * (m_wur[i] / (m_wur[i] + exp(6.13f - 0.0883f * m_wur[i]))) + m_HiMin[i]; m_HI[i] = min(m_HI[i], m_Hiact[i]); //float yield = 0.0f; if (m_HiOpt[i] > 1.001) m_yield[i] = m_biomass[i] * (1.0f - 1.0f / (1.0f + m_HI[i])); else m_yield[i] = m_biomassAG[i] * m_HI[i]; m_yield[i] = max(0.0f, m_yield[i]); m_harvestEfficiency[i] = 0.5f; //harvestEfficiency read from database //IsGrain should read from database if (m_common->IsGrain())//grain harvest, no residue, see harvgrainop.f { m_yield[i] *= m_harvestEfficiency[i]; m_yieldN[i] = max(0.0f, min(m_yield[i] * m_frNyld[i], 0.85f * m_biomassN[i])); m_yieldP[i] = max(0.0f, min(m_yield[i] * m_frPyld[i], 0.85f * m_biomassP[i])); m_biomass[i] -= m_yield[i]; } else //biomass harvest, has residue, residue redistribute to soil layer, see harvestop.f { //divide yield to two parts:clip and yield m_clip[i] = m_yield[i] * (1 - m_harvestEfficiency[i]); m_yield[i] -= m_clip[i]; m_clip[i] = max(0.0f, m_clip[i]); m_yield[i] = max(0.0f, m_yield[i]); //harvest index override read from database //get N&P in clip and yield[i] m_yieldN[i] = max(0.0f, min(m_yield[i] * m_frNyld[i], 0.8f * (m_biomassN[i]))); m_yieldP[i] = max(0.0f, min(m_yield[i] * m_frPyld[i], 0.8f * (m_biomassP[i]))); m_clipN[i] = max(0.0f, min(m_clip[i] * m_frNyld[i], m_biomassN[i] - m_yieldN[i])); //N in clip residual,needed by nitrient cycling module m_clipP[i] = max(0.0f, min(m_clip[i] * m_frPyld[i], m_biomassP[i] - m_yieldP[i])); //P in clip residual,needed by nitrient cycling module //reset LAI, frPHU and root fraction m_removeFraction[i] = 1.0f; //the fraction of remove part to aboveground part if (m_biomass[i] - m_biomassRoot[i] > 1.0e-6) m_removeFraction[i] = (m_yield[i] + m_clip[i]) / (m_biomass[i] - m_biomassRoot[i]); m_removeFraction[i] = min(1.0f, m_removeFraction[i]); //root part m_rootFraction[i] = m_biomassRoot[i] / m_biomass[i]; m_rootLeft[i] = (m_biomass[i] - m_biomassRoot[i]) * (1 - m_removeFraction[i]) * m_rootFraction[i] / (1.0f - m_rootFraction[i]); m_rootRemove[i] = m_biomassRoot[i] - m_rootLeft[i]; //removed root as residual m_rootRemoveFraction[i] = 0.0f; if (m_biomassRoot[i] > 1.0e-6) m_rootRemoveFraction[i] = m_rootRemove[i] / (m_biomassRoot[i]); m_rootRemoveN[i] = m_rootRemoveFraction[i] * (m_biomassN[i]); m_rootRemoveP[i] = m_rootRemoveFraction[i] * (m_biomassP[i]); //remove aboveground and root biomass from total biomass //change the LAI and growth step if (m_biomass[i] > 0.001) { m_LAI[i] *= 1.0f - m_removeFraction[i]; if (m_frPHU[i] < 0.999) m_frPHU[i] *= 1.0f - m_removeFraction[i]; m_biomass[i] -= m_yield[i] + m_clip[i] + m_rootRemove[i]; m_biomassN[i] -= m_yieldN[i] + m_clipN[i] + m_rootRemoveN[i]; m_biomassP[i] -= m_yieldP[i] + m_clipP[i] + m_rootRemoveP[i]; m_biomass[i] = min(0.0f, m_biomass[i]); m_biomassN[i] = min(0.0f, m_biomassP[i]); m_biomassP[i] = min(0.0f, m_biomassP[i]); m_biomassRoot[i] = m_biomass[i] * (0.4f - 0.2f * m_frPHU[i]); } else { m_biomass[i] = 0.0f; m_biomassN[i] = 0.0f; m_biomassP[i] = 0.0f; m_biomassRoot[i] = 0.0f; m_LAI[i] = 0.0f; m_frPHU[i] = 0.0f; } } } } //m_lastSWE = m_swe; return 0; }
int PER_PI::Execute() { CheckInputData(); initialOutputs(); //#pragma omp parallel for for (int i = 0; i < m_nCells; i++) { float k = 0.f, maxSoilWater = 0.f, fcSoilWater = 0.f; float swater = 0.f;//, wpSoilWater = 0.f; /// firstly, assume all infiltrated water is added to the first soil layer. m_soilStorage[i][0] += m_infil[i]; /// secondly, model water percolation across layers for (int j = 0; j < (int)m_nSoilLayers[i]; j++) { // for the upper two layers, soil may be frozen // No movement if soil moisture is below field capacity if (j == 0 && m_soilT[i] <= m_frozenT) continue; swater = m_soilStorage[i][j]; maxSoilWater = m_sat[i][j]; fcSoilWater = m_fc[i][j]; //wpSoilWater = m_wp[i][j]; if (swater > fcSoilWater) { //the moisture content can exceed the porosity in the way the algorithm is implemented if (swater > maxSoilWater) k = m_ks[i][j]; else { float dcIndex = 2.f / m_poreIndex[i][j] + 3.f; // pore disconnectedness index k = m_ks[i][j] * pow(swater / maxSoilWater, dcIndex); } m_perc[i][j] = k * m_dt / 3600.f; /// mm if (swater - m_perc[i][j] > maxSoilWater) m_perc[i][j] = swater - maxSoilWater; else if (swater - m_perc[i][j] < fcSoilWater) m_perc[i][j] = swater - fcSoilWater; //Adjust the moisture content in the current layer, and the layer immediately below it m_soilStorage[i][j] -= m_perc[i][j];// / m_soilThick[i][j]; if (j < m_nSoilLayers[i] - 1) m_soilStorage[i][j + 1] += m_perc[i][j];// / m_soilThick[i][j + 1]; //if (m_soilStorage[i][j] != m_soilStorage[i][j] || m_soilStorage[i][j] < 0.f) //{ // cout << MID_PER_PI << " CELL:" << i << ", Layer: " << j << "\tPerco:" << swater << "\t" << // fcSoilWater << "\t" << m_perc[i][j] << "\t" << m_soilThick[i][j] << "\tValue:" << m_soilStorage[i][j] << // endl; // throw ModelException(MID_PER_PI, "Execute", "moisture is less than zero."); //} } else { for (int j = 0; j < (int)m_nSoilLayers[i]; j++) m_perc[i][j] = 0.f; } /// update total soil water content m_soilStorageProfile[i] = 0.f; for (int ly = 0; ly < (int)m_nSoilLayers[i]; ly++) m_soilStorageProfile[i] += m_soilStorage[i][ly]; } } return 0; }
int PER_STR::Execute() { CheckInputData(); initialOutputs(); /*if (m_perc == NULL) { m_perc = new float *[m_nCells]; #pragma omp parallel for for (int i = 0; i < m_nCells; i++) { m_perc[i] = new float[m_nSoilLayers]; for (int j = 0; j < m_nSoilLayers; j++) m_perc[i][j] = 0.f; } }*/ #pragma omp parallel for for (int i = 0; i < m_nCells; i++) { float maxSoilWater = 0.f, fcSoilWater = 0.f; float swater = 0.f, wpSoilWater = 0.f; //// Update soil layers from solid two layers to multi-layers by m_nSoilLayers. By LJ //int curSoilLayers = -1, j; //m_upSoilDepth[0] = m_soilDepth[i][0]; //for (j = 1; j < m_nSoilLayers; j++) //{ // if (!FloatEqual(m_soilDepth[i][j], NODATA_VALUE)) // m_upSoilDepth[j] = m_soilDepth[i][j] - m_soilDepth[i][j - 1]; // else // break; //} //curSoilLayers = j; //float depth[3]; //depth[0] = m_upSoilDepth; //depth[1] = m_rootDepth[i] - m_upSoilDepth; //if(depth[1] < 0) //{ // ostringstream oss; // oss << "The root depth at cell(" << i << ") is " << m_rootDepth[i] << ", and is less than the upper soil depth (" << m_upSoilDepth << endl; // throw ModelException(MID_PER_STR, "Execute", oss.str()); //} m_somo[i][0] += m_infil[i] / m_soilThick[i][0]; for (int j = 0; j < (int)m_soilLayers[i]; j++) { //No movement if soil moisture is below field capacity m_perc[i][j] = 0.f; // for the upper two layers, soil may be frozen if (j == 0 && m_soilT[i] <= m_frozenT) continue; if (m_somo[i][j] > m_fc[i][j]) { maxSoilWater = m_soilThick[i][j] * m_porosity[i][j]; swater = m_soilThick[i][j] * m_somo[i][j]; fcSoilWater = m_soilThick[i][j] * m_fc[i][j]; wpSoilWater = m_soilThick[i][j] * m_wp[i][j]; ////////////////////////////////////////////////////////////////////////// // method from swat float tt = 3600.f * (m_porosity[i][j] - m_fc[i][j]) * m_soilThick[i][j] / m_ks[i][j]; m_perc[i][j] = swater * (1.f - exp(-m_dt / tt)); if (swater - m_perc[i][j] > maxSoilWater) m_perc[i][j] = swater - maxSoilWater; else if (swater - m_perc[i][j] < fcSoilWater) m_perc[i][j] = swater - fcSoilWater; else if (swater - m_perc[i][j] < wpSoilWater) m_perc[i][j] = swater - wpSoilWater; else /// percolation is not allowed! m_perc[i][j] = 0.f; //Adjust the moisture content in the current layer, and the layer immediately below it m_somo[i][j] -= m_perc[i][j] / m_soilThick[i][j]; if (j < m_nSoilLayers - 1) m_somo[i][j + 1] += m_perc[i][j] / m_soilThick[i][j + 1]; //if (m_somo[i][j] != m_somo[i][j] || m_somo[i][j] < 0.f) //{ // cout << "PER_STR CELL:" << i << ", Layer: " << j << "\tPerco:" << soilWater << "\t" << // fcSoilWater << "\t" << m_perc[i][j] << "\t" << m_soilThick[i][j] << "\tValue:" << m_somo[i][j] << // endl; // throw ModelException(MID_PER_STR, "Execute", "moisture is less than zero."); //} } else { for (int j = 0; j < (int)m_soilLayers[i]; j++) m_perc[i][j] = 0.f; } for (int j = (int)m_soilLayers[i]; j < m_nSoilLayers; j++) m_perc[i][j] = NODATA_VALUE; } } return 0; }
int ReservoirMethod::Execute() { if (!CheckInputData()) return -1; initialOutputs(); float QGConvert = 1.f * m_CellWidth * m_CellWidth / (m_TimeStep) / 1000.f; // mm ==> m3/s for (vector<int>::iterator it = m_subbasinIDs.begin(); it!=m_subbasinIDs.end();it++) { int subID = *it; Subbasin *curSub = m_subbasinsInfo->GetSubbasinByID(subID); // get percolation from the bottom soil layer at the subbasin scale int curCellsNum = curSub->getCellCount(); int *curCells = curSub->getCells(); float perco = 0.f; #pragma omp parallel for reduction(+:perco) for (int i = 0; i < curCellsNum; i++) { int index = 0; index = curCells[i]; perco += m_perc[index][(int)m_soilLayers[index]-1]; } perco /= curCellsNum; // mean mm /// percolated water ==> vadose zone ==> shallow aquifer ==> deep aquifer /// currently, for convenience, we assume a small portion of the percolated water /// will enter groundwater. By LJ. 2016-9-2 float ratio2gw = 1.f; perco *= ratio2gw; curSub->setPerco(perco); //if (perco > 0.f) //{ // cout << "subID: "<<subID<<", perco mean: "<<perco << endl; //} //calculate EG, i.e. Revap float revap = 0.f; float fPET = 0.f; float fEI = 0.f; float fED = 0.f; float fES = 0.f; float plantEP = 0.f; fPET = Sum(curCellsNum, curCells, m_D_PET) / curCellsNum; fEI = Sum(curCellsNum, curCells, m_D_EI) / curCellsNum; fED = Sum(curCellsNum, curCells, m_D_ED) / curCellsNum; fES = Sum(curCellsNum, curCells, m_D_ES) / curCellsNum; plantEP = Sum(curCellsNum, curCells, m_plantEP) / curCellsNum; curSub->setPET(fPET); //if percolation < 0.01, EG will be 0. if percolation >= 0.01, EG will be calculated by equation (why? this is not used currently. Junzhi Liu 2016-08-14). //if (perco >= 0.01f) //{ revap = (fPET - fEI - fED - fES - plantEP) * m_gwStore[subID] / m_GWMAX; if (revap != revap) cout <<"fPET: "<<fPET<<", fEI: "<<fEI<<", fED: "<<fED<<", fES: "<<fES<<", plantEP: "<<plantEP <<"gwStore: "<<subID<<","<<m_gwStore[subID]<<endl; revap = max(revap, 0.f); revap = min(revap, perco); //} //float prevRevap = curSub->getEG(); //if (prevRevap != revap) //{ // curSub->setEG(revap); // curSub->setIsRevapChanged(true); //} //else // curSub->setIsRevapChanged(false); curSub->setEG(revap); //deep percolation float percoDeep = perco * m_dp_co; curSub->setPerde(percoDeep); // groundwater runoff (mm) float slopeCoef = curSub->getSlopeCoef(); float kg = m_Kg * slopeCoef; float groundRunoff = kg * pow(m_gwStore[subID], m_Base_ex); //mm if (groundRunoff != groundRunoff ) cout << groundRunoff; float groundQ = groundRunoff * curCellsNum * QGConvert; // groundwater discharge (m3/s) float groundStorage = m_gwStore[subID]; groundStorage += (perco - revap - percoDeep - groundRunoff); //add the ground water from bank storage, 2011-3-14 float gwBank = 0.f; // at the first time step m_VgroundwaterFromBankStorage is NULL if (m_VgroundwaterFromBankStorage != NULL) gwBank = m_VgroundwaterFromBankStorage[subID]; groundStorage += gwBank / curSub->getArea() * 1000.f; groundStorage = max(groundStorage, 0.f); if (groundStorage > m_GWMAX) { groundRunoff += (groundStorage - m_GWMAX); groundQ = groundRunoff * curCellsNum * QGConvert; // groundwater discharge (m3/s) groundStorage = m_GWMAX; } curSub->setRG(groundRunoff); curSub->setGW(groundStorage); curSub->setQG(groundQ); if (groundStorage != groundStorage) { ostringstream oss; oss << perco << "\t" << revap << "\t" << percoDeep << "\t" << groundRunoff << "\t" << m_gwStore[subID] << "\t" << m_Kg << "\t" << m_Base_ex << "\t" << slopeCoef << endl; throw ModelException("Subbasin", "setInputs", oss.str()); } m_T_Perco[subID] = curSub->getPerco(); m_T_Revap[subID] = curSub->getEG(); m_T_PerDep[subID] = curSub->getPerde(); m_T_RG[subID] = curSub->getRG(); //get rg of specific subbasin m_T_QG[subID] = curSub->getQG(); //get qg of specific subbasin m_petSubbasin[subID] = curSub->getPET(); m_gwStore[subID] = curSub->getGW(); } m_T_Perco[0] = m_subbasinsInfo->subbasin2basin(VAR_PERCO); m_T_Revap[0] = m_subbasinsInfo->subbasin2basin(VAR_REVAP); m_T_PerDep[0] = m_subbasinsInfo->subbasin2basin(VAR_PERDE); m_T_RG[0] = m_subbasinsInfo->subbasin2basin(VAR_RG); // get rg of entire watershed m_gwStore[0] = m_subbasinsInfo->subbasin2basin(VAR_GW_Q); m_T_QG[0] = m_subbasinsInfo->subbasin2basin(VAR_QG); // get qg of entire watershed // output to GWWB for (int i = 0; i <= m_nSubbasins; i++) { m_T_GWWB[i][0] = m_T_Perco[i]; m_T_GWWB[i][1] = m_T_Revap[i]; m_T_GWWB[i][2] = m_T_PerDep[i]; m_T_GWWB[i][3] = m_T_RG[i]; m_T_GWWB[i][4] = m_gwStore[i]; m_T_GWWB[i][5] = m_T_QG[i]; } // update soil moisture for (vector<int>::iterator it = m_subbasinIDs.begin(); it!=m_subbasinIDs.end();it++) { Subbasin *sub = m_subbasinsInfo->GetSubbasinByID(*it); int *cells = sub->getCells(); int nCells = sub->getCellCount(); int index = 0; for (int i = 0; i < nCells; i++) { index = cells[i]; m_soilStorage[index][(int)m_soilLayers[index] - 1] += sub->getEG(); // TODO: Is it need to allocate revap to each soil layers??? By LJ } } return 0; }
int DepressionFSDaily::Execute() { //check the data CheckInputData(); initialOutputs(); #pragma omp parallel for for (int i = 0; i < m_nCells; ++i) { ////////////////////////////////////////////////////////////////////////// // runoff if (m_depCap[i] < 0.001f) { m_sr[i] = m_pe[i]; m_sd[i] = 0.f; } else if (m_pe[i] > 0.f) { float pc = m_pe[i] - m_depCap[i] * log(1.f - m_sd[i] / m_depCap[i]); float deltaSd = m_pe[i] * exp(-pc / m_depCap[i]); if (deltaSd > m_depCap[i] - m_sd[i]) deltaSd = m_depCap[i] - m_sd[i]; m_sd[i] += deltaSd; m_sr[i] = m_pe[i] - deltaSd; } else { m_sd[i] += m_pe[i]; m_sr[i] = 0.f; } ////////////////////////////////////////////////////////////////////////// // evaporation if (m_sd[i] > 0) { /// TODO: Is this logically right? PET is just potential, which include /// not only ET from surface water, but also from plant and soil. /// Please Check the corresponding theory. By LJ. // evaporation from depression storage if (m_pet[i] - m_ei[i] < m_sd[i]) { m_ed[i] = m_pet[i] - m_ei[i]; } else { m_ed[i] = m_sd[i]; } m_sd[i] -= m_ed[i]; } else { m_ed[i] = 0.f; m_sd[i] = 0.f; } if (m_impoundTriger != NULL && FloatEqual(m_impoundTriger[i], 0.f)){ if (m_potVol != NULL) { m_potVol[i] += m_sr[i]; m_potVol[i] += m_sd[i]; m_sr[i] = 0.f; m_sd[i] = 0.f; } } } return true; }