static void _MDWTempSurfRunoffPool (int itemID) { float SurfRunoffT; float SurfRunoffPoolT; float SurfRunoff; float SurfRunoffPool; SurfRunoffT = MFVarGetFloat (_MDInWTempSurfRunoffID, itemID, 0.0); SurfRunoffPoolT = MFVarGetFloat (_MDOutWTempSurfRunoffPoolID, itemID, 0.0); SurfRunoff = MFVarGetFloat (_MDInRainSurfRunoffID, itemID, 0.0); SurfRunoffPool = MFVarGetFloat (_MDInRunoffPoolID, itemID, 0.0); SurfRunoff = MDMaximum(0, SurfRunoff); SurfRunoffPool = MDMaximum(0, SurfRunoffPool); if (!isnan(SurfRunoffPool) && !isnan(SurfRunoff) && ((SurfRunoffPool + SurfRunoff) > 0) && !isnan(SurfRunoffPoolT) && !isnan(SurfRunoffT)){ SurfRunoffPoolT = MDMaximum(((SurfRunoffPool * SurfRunoffPoolT) + (SurfRunoff * SurfRunoffT)) / (SurfRunoffPool + SurfRunoff), 0.0); MFVarSetFloat (_MDOutWTempSurfRunoffPoolID, itemID, SurfRunoffPoolT); } else{ MFVarSetMissingVal(_MDOutWTempSurfRunoffPoolID,itemID); } }
static void _MDWTempRiver (int itemID) { float RechargeT; float GrdWaterT; // float SurfaceRO; // comment out 082812 float TotalSurfRunoff; // RJS 082812 float GrdWaterRO; float TemperatureRO; RechargeT = MFVarGetFloat (_MDInWTempSurfRunoffPoolID, itemID, 0.0); // RJS 060512 GrdWaterT = MFVarGetFloat (_MDInWTempGrdWaterID, itemID, 0.0); // SurfaceRO = MFVarGetFloat (_MDInSurfRunoffID, itemID, 0.0); // comment out 082812 TotalSurfRunoff = MFVarGetFloat (_MDInTotalSurfRunoffID, itemID, 0.0); // RJS 082812 GrdWaterRO = MFVarGetFloat (_MDInBaseFlowID, itemID, 0.0); // SurfaceRO = MDMaximum(0, SurfaceRO); // comment out 082812 GrdWaterRO = MDMaximum(0, GrdWaterRO); TotalSurfRunoff = MDMaximum(0, TotalSurfRunoff); // RJS 082812 // TemperatureRO = MDMaximum((((SurfaceRO * RechargeT) + (GrdWaterRO * GrdWaterT)) / (SurfaceRO + GrdWaterRO)),0.0); // commented out 082812 TemperatureRO = MDMaximum((((TotalSurfRunoff * RechargeT) + (GrdWaterRO * GrdWaterT)) / (TotalSurfRunoff + GrdWaterRO)),0.0); // RJS 082812 MFVarSetFloat(_MDOutWTempRiverID,itemID,TemperatureRO); }
static void _MDWTempGrdWater (int itemID) { float airT; float RechargeT; float GrdWaterT; float RainRechargeIn; float IrrReturnFlow; float GrdWaterStorage; airT = MFVarGetFloat (_MDInAirTempID, itemID, 0.0); RechargeT = MFVarGetFloat (_MDInWTempSurfRunoffID, itemID, 0.0); RainRechargeIn = MFVarGetFloat (_MDInRainRechargeID, itemID, 0.0); if (_MDInIrrReturnFlowID != MFUnset){ IrrReturnFlow = MFVarGetFloat (_MDInIrrReturnFlowID, itemID, 0.0); } else { IrrReturnFlow = 0; } GrdWaterStorage = MFVarGetFloat (_MDOutGrdWaterID, itemID, 0.0); GrdWaterT = MFVarGetFloat (_MDOutWTempGrdWaterID, itemID, 0.0); //if (itemID == 233){ // printf("Stop itemID %d day %d \n", itemID, MFDateGetCurrentDay()); // } //TODO: why is RainRechargeIn < 0 sometimes? RainRechargeIn = MDMaximum(0, RainRechargeIn); IrrReturnFlow = MDMaximum(0, IrrReturnFlow); GrdWaterStorage = MDMaximum(0, GrdWaterStorage); if (!isnan(GrdWaterStorage) && !isnan(RainRechargeIn) && !isnan(IrrReturnFlow) && ((GrdWaterStorage + RainRechargeIn + IrrReturnFlow) > 0) && !isnan(GrdWaterT) && !isnan(RechargeT) && !isnan(airT)){ GrdWaterT = MDMaximum( (((GrdWaterStorage * GrdWaterT) + (RainRechargeIn * RechargeT) + (IrrReturnFlow * airT)) / (GrdWaterStorage + RainRechargeIn + IrrReturnFlow)), 0.0); // if (GrdWaterT > 30){ // printf("Stop itemID %d day %d \n", itemID, MFDateGetCurrentDay()); // } // GrdWaterT = MDMinimum(GrdWaterT, 40); //does this need to be properly mass balanced? GRdwater T might just keep going up. MFVarSetFloat (_MDOutWTempGrdWaterID,itemID,GrdWaterT); } else{ MFVarSetMissingVal(_MDOutWTempGrdWaterID,itemID); } if (GrdWaterT > 100) printf("m = %d, d = %d, itemID = %d, GrdWaterT = %f, RainRechargeIn = %f\n", MFDateGetCurrentMonth (), MFDateGetCurrentDay (), itemID, GrdWaterT, RainRechargeIn); // if (itemID == 486) printf("y = %d, m = %d, d = %d, GwT = %f, ReT = %f, AirT = %f, Recharge = %f, GW = %f\n", MFDateGetCurrentYear(), MFDateGetCurrentMonth(), MFDateGetCurrentDay(), GrdWaterT, RechargeT, airT, RainRechargeIn, GrdWaterStorage); }
float *VGalpha(float pctSand[], float pctClay[],float bulkD[],int numSoilLayers){ //Verreecken Method float *a; int i; a = malloc(numSoilLayers*sizeof *a); for (i=0;i<numSoilLayers;i++){ float lna = -2.486+0.025 * pctSand[i]*100 -0.351* pctClay[i]*100 - 2.617 * bulkD[i]/1000 -0.023 * pctClay[i]*100; a[i]=exp(lna); a[i] = MDMaximum (0.001, a[i]); } return a; }
static void _MDRainSMoistChg (int itemID) { float initialSoilMoisture=0.9; float precip; // Precipitation [mm/dt] float potETP; // Potential evapotranspiration [mm/dt] float snowpackChg; // Snow pack change [mm/dt] float irrAreaFrac = 0.0; // Irrigated area fraction float meanSmoist = 0.0; // Averaged over all layers Soil moisture [mm/dt] float meanSmoistChange = 0.0; // Soil moisture change averaged over all layers [mm/dt] float waterTableDepthParameter =1.0; int i; float isInitial = MFVarGetFloat(_MDInIsInitialID,itemID,0.0); float rootDepth; //in mm to be consistent with old WBMstable data! // Local float liquidIn; int numSoilLayers; numSoilLayers = _MDNumberOfSoilMoistureLayers; precip = MFVarGetFloat (_MDInPrecipID, itemID, 0.0); snowpackChg = MFVarGetFloat (_MDInSPackChgID, itemID, 0.0); potETP = MFVarGetFloat (_MDInPotETID, itemID, 0.0); //intercept = _MDInInterceptID != MFUnset ? MFVarGetFloat (_MDInInterceptID, itemID, 0.0) : 0.0; //irrAreaFrac = _MDInIrrAreaFracID != MFUnset ? MFVarGetFloat (_MDInIrrAreaFracID, itemID, 0.0) : 0.0; rootDepth = MFVarGetFloat (_MDInSoilRootingDepthID, itemID, 0.0); float snowMelt; if (snowpackChg > 0.0) //Snow Accumulation, no liquid precipitation snowMelt = 0.0; liquidIn= precip - fabs(snowpackChg); if (snowpackChg <= 0.0){ snowMelt = fabs(snowpackChg); //Add Snowmelt liquidIn = precip + snowMelt; } int dt; float soilDepth [numSoilLayers]; float accumSoilDepth [numSoilLayers]; float vertFlow [numSoilLayers-1]; float ice [numSoilLayers]; float satExcess [numSoilLayers]; float _liq [numSoilLayers]; float _previousLiq [numSoilLayers]; float bulkDensity [numSoilLayers]; float pctSand [numSoilLayers]; float pctSilt [numSoilLayers]; float pctClay [numSoilLayers]; float pctOrganicM [numSoilLayers]; float inf2LowestLayer=0; float *actETP; float *VanGn; float *VanGa; float *VanGm; float *permWP; float *fieldCap; float *residSoilMoist; float *maxSoilMoist; float baseflow=0; float dt_inflow =0; float surfaceRO=0; float waterTableDepth; float activeLayerDepth; float waterInAllLayers=0; float iceInAllLayers=0; float waterIN=0; float waterOUT=0; float smPrevious=0; float smCurrent=0; float actualET=0; float dt_surfaceRO=0; float balance; float K1;float K1Sat; float K2;float K2Sat; waterTableDepth= MFVarGetFloat(_MDOutWaterTableDepthID,itemID,0.0); for (i=0;i<numSoilLayers;i++){ soilDepth[i] = 1000 * MFVarGetFloat( _MDInSoilDepthIDs[i], itemID,0.0); // in mm! if (soilDepth[i]==0) soilDepth[i]=10; //set soilDepth to 10 mm if no data. pctSand[i]= MFVarGetFloat( _MDInSoilpctSandIDs[i], itemID,0.0); pctSilt[i]= MFVarGetFloat( _MDInSoilpctSiltIDs[i], itemID,0.0); pctClay[i]= MFVarGetFloat( _MDInSoilpctClayIDs[i], itemID,0.0); pctOrganicM[i]=2.5; bulkDensity[i]=1600; _previousLiq[i]=MFVarGetFloat( _MDOutSMLiquidIDs[i], itemID,0.0); // if (itemID == 200)printf("PrevSM = smPrevious %f lowestLayer %f \n",smPrevious, _previousLiq[numSoilLayers-1]); ice[i]=0.0; } if(soilTemperatureID==1){ // activeLayerDepth= MFVarGetFloat( _MDActiveLayerDepthID, itemID,0.0); // printf ("ActiveLayerDepth = %f\n", activeLayerDepth); } residSoilMoist= ResidSoilMoisture(pctOrganicM, pctClay,numSoilLayers, soilDepth); // for (i=0;i<numSoilLayers;i++){ accumSoilDepth[i] =soilDepth[i]; // if (_previousLiq[i]< 0 ) printf("SM prolbme\n"); //ice[i]=MFVarGetFloat( _MDOutSMIceDs[i], itemID,0.0); if (i < numSoilLayers-1)smPrevious+=_previousLiq[i]+ice[i]-residSoilMoist[i];//do not incldue changes in lowest layer in balance } accumSoilDepth[0]=soilDepth[0]; for (i=1;i<numSoilLayers;i++){accumSoilDepth[i] +=accumSoilDepth[i-1]+soilDepth[i];} float prevLowestLayerLiq = _previousLiq[numSoilLayers-1]; float lowestLayerChange=0; maxSoilMoist = SaturatedSoilMoist(pctSand,pctClay,pctOrganicM,soilDepth,numSoilLayers); //maxSoilMoist[numSoilLayers -1] = 1e20; //last layer is runoff pool... infinite capactity // VanGn=VGn(pctSand, pctClay, numSoilLayers); fieldCap = FieldCapacity(pctSand,pctClay,pctOrganicM,soilDepth,numSoilLayers); permWP= WiltingPoint(pctSand,pctClay,pctOrganicM,soilDepth, numSoilLayers); // // kSat=SatConductivity (pctSand,pctClay,pctOrganicM,numSoilLayers); // mm/timeStep VanGa= VGalpha (pctSand, pctClay, bulkDensity,numSoilLayers); // VanGm = VGm(VanGn,numSoilLayers); // printf ("PWP1 %f PWP2 %f PWP3 %f PWP4 %f\n", permWP[0], permWP[1], permWP[2], permWP[3]); // printf ("Doy = %i FC1 %f FC2 %f FC3 %f FC4 %f\n", MFDateGetDayOfYear(),fieldCap[0], fieldCap[1], fieldCap[2], fieldCap[3]); // if (itemID==300) printf ("max1 %f max2 %f max3 %f max4 %f soilDph%f \n", maxSoilMoist[0], maxSoilMoist[1], maxSoilMoist[2], maxSoilMoist[3], soilDepth[3]); // printf ("resSM1 %f resSM2 %f resSM3 %f resSM4 %f soilDph%f \n", residSoilMoist[0], residSoilMoist[1], residSoilMoist[2], residSoilMoist[3], soilDepth[3]); //TODO FieldCapacity(pctSand,pctClay,pctOrganicM,numSoilLayers); //time step limit courant number.. //dt < dz/Ksat if (itemID ==124){ int j; for (j =0; j < numSoilLayers;j++){ // printf ("SoilDepth for layer %i : %f\n", j, soilDepth[j]); } } potETP=MFVarGetFloat (_MDInPotETID, itemID, 0.0)/_MDTimeSteps; //DEBUG //liquidIn=0; //if (MFDateGetDayOfYear ()== 1) liquidIn =10; float gamma = 0.8; dt_inflow = (liquidIn / _MDTimeSteps)* (gamma); dt_surfaceRO = liquidIn - dt_inflow; //// printf ("hier\n"); for (dt = 0;dt<_MDTimeSteps; dt ++){ surfaceRO += dt_surfaceRO; actETP= ActETP ( _previousLiq, fieldCap, permWP, potETP, numSoilLayers, rootDepth,accumSoilDepth,activeLayerDepth); // if (itemID==606)printf ("ItemID = %i MFDateGetDayOfYear %i prevLiq = %f maxSM %f soilDepth %f \n",itemID,MFDateGetDayOfYear(), _previousLiq[0], maxSoilMoist[0], soilDepth[0]); if (isInitial <1.0) _previousLiq[numSoilLayers-1]= initialSoilMoisture * maxSoilMoist[i]; for (i=0;i<numSoilLayers-1;i++){ // if (_previousLiq[i] > maxSoilMoist[i]) printf ("Previous SM =%f maxSM =%f \n", _previousLiq[i] , maxSoilMoist[i]); if (isInitial <1.0){ _previousLiq[i] = initialSoilMoisture * maxSoilMoist[i]; // if (itemID==139)printf ("ItemID = %i MFDateGetDayOfYear %i Is Initial prevLiq = %f maxSM %f soilDepth %f \n",itemID,MFDateGetDayOfYear(), _previousLiq[0], maxSoilMoist[0], soilDepth[0]); } _previousLiq[i]=MDMaximum(residSoilMoist[i],_previousLiq[i]); if (i==0) { _liq[i]= _previousLiq[i]+dt_inflow-actETP[i]; // initialSoilMoisture * maxSoilMoist[i]; }else{ _liq[i]= _previousLiq[i]- actETP[i]+vertFlow[i-1]; if (_liq[i]< 0){ //printf ("liq < 0: %f at item %i layer %i \n", _liq[i], itemID, i); _liq[i]=0; } } //// K1 = UnsaturatedConductivity (pctSand[i], pctClay[i],pctOrganicM[i], _liq[i],maxSoilMoist[i]); K2= UnsaturatedConductivity (pctSand[i+1], pctClay[i+1],pctOrganicM[i+1], _liq[i],maxSoilMoist[i+1]); K1Sat = SaturatedConductivity (pctSand[i], pctClay[i],pctOrganicM[i], _liq[i],maxSoilMoist[i]); K2Sat= SaturatedConductivity (pctSand[i+1], pctClay[i+1],pctOrganicM[i+1], _liq[i],maxSoilMoist[i+1]); float meanKS = (K1 + K2) / 2; meanKS = MDMaximum (K1Sat, meanKS); meanKS = MDMaximum (K2Sat, meanKS); float matrHead1; float matrHead2; matrHead1= MatrixPotential( VanGa[i], _liq[i], VanGm[i], VanGn[i], residSoilMoist[i], maxSoilMoist[i] ); matrHead2 = MatrixPotential( VanGa[i+1], _liq[i+1], VanGm[i+1], VanGn[i+1], residSoilMoist[i+1], maxSoilMoist[i+1] ); float Grad = (matrHead1 - matrHead2) / ((soilDepth[i] + soilDepth[i+1])/2); vertFlow[i]=-Grad * meanKS ; vertFlow[i]=MDMinimum(vertFlow[i],_liq[i]); vertFlow[i]=MDMaximum(vertFlow[i],0); // printf ("Vert %f vertSimple %f \n", vertFlow[i], junk); // printf ("i = %i LIQ = %f K1 = %f K2 = %f meanKS %f matrHEAD1 %F matrHead2 %f soilDepth1 %f soilDepth2 %f Grad %f vertFlow %f \n",i, _liq[i],K1, K2, meanKS, matrHead1, matrHead2,soilDepth[i],soilDepth[i+1],Grad,vertFlow[i]); // if (itemID ==3) printf ("i+1 = %i LIQ = %f K1 = %f K2 = %f meanKS %f matrHEAD1 %F matrHead2 %f soilDepth1 %f soilDepth2 %f Grad %f vertFlow %f \n",i, _liq[i+1],K1, K2, meanKS, matrHead1, matrHead2,soilDepth[i],soilDepth[i+1],Grad,vertFlow[i]); // if (itemID ==3) printf ("i = %i VanGA = %f Vangm = %f Vangn = %f resid %f max %f \n",i, VanGa[i],VanGm[i],VanGn[i], residSoilMoist[i], maxSoilMoist[i]); // if (itemID ==200)printf("LAYTER %i, vertflow %f \n",i,vertFlow[i]); _liq[i]=_liq[i]-vertFlow[i]; // if (itemID ==139 && _liq[i] < 0 )printf ("Liq < 0 = %f \n", _liq[i]); // if (itemID ==139 && _liq[i] > maxSoilMoist[i] )printf ("Liq = %f .. maxSoilMoist = %f for item %i at layer %i \n", _liq[i],maxSoilMoist[i], itemID, i); } //numSoilLayers //// //// // no drainage from lowest layr ..now taken care of in VGHydrConductivity vertFlow[i]=MDMaximum(0,vertFlow[i]); //// satExcess[numSoilLayers-1]=0.0; //// // if (itemID==130)printf ("============Day number %i\n",MFDateGetDayOfYear ()); for (i=numSoilLayers-2;i>-1;i--){ // from bottom !! // if (itemID==626) printf("itemID %i Day %i Layer %i liq[0]=%f liq[1]=%f liq[2]=%f liq[3]=%f liq[4]=%f liq[5]=%f liq[6]=%f\n",itemID,MFDateGetDayOfYear(), i,_liq[0], _liq[1], _liq[2],_liq[3], _liq[4], _liq[5] ,_liq[6]); if (_liq[i] + ice[i] + satExcess[i+1] >= maxSoilMoist[i]){ satExcess[i]= _liq[i]+ice[i]+satExcess[i+1] - maxSoilMoist[i]; if (i==0){ // if (itemID==200)printf ("satExcess[i] %f _liq[i] %f ice[i] %f satExcess[i+1] %f maxSoilMoist[i] %f \n",satExcess[i],_liq[i],ice[i],satExcess[i+1], maxSoilMoist[i]); surfaceRO+= satExcess[i]; }else{ // if (itemID==139)printf (" liqvorher %f for layer %i vert1 %f vert2 %f itemID %i \n", _liq[i],i, vertFlow[i], vertFlow[i+1],itemID); // _liq[i]= maxSoilMoist[i]-ice[i]; // vertFlow[i]=0; // if (itemID==139)printf (" liqnachher %f for layer %i vert1 %f vert2 %f itemID %i maxSM %f ice %f stEXcess %f maxSM %f \n", _liq[i],i, vertFlow[i], vertFlow[i+1],itemID, maxSoilMoist[i],ice[i],satExcess[i], maxSoilMoist[i] ); } //////// //////// }else{ ////// satExcess[i]=0; } if (i>=1) _liq[i]= _previousLiq[i]-satExcess[i]+satExcess[i+1]- vertFlow[i]- actETP[i]+vertFlow[i-1]; if (0==i) _liq[i]= _previousLiq[i]-surfaceRO+satExcess[i+1]- vertFlow[i]- actETP[i]+liquidIn; // if (_liq[i]<0)printf ("Liq < 0 at item %i Layer %i Liq %fsatExcess %f\n",itemID,i,_liq[i], satExcess[i]); //// if (itemID==200)printf ("i%i satExcess%f surfRO%f\n", i,satExcess[i], surfaceRO); ////// // water balance for each layer if (i >0)waterIN = vertFlow[i-1] + satExcess[i+1]; if (i>0)waterOUT = actETP[i] +vertFlow[i]+(_liq[i]-_previousLiq[i])+satExcess[i]; balance =waterIN-waterOUT; if (fabs(balance) >= 0.001 && i >0 ){ printf("Delta = %f waterIN = %f itemID %i Layer %i vertFlow[i-1] %f satExcess[i+1] %f maxSM %f\n",balance, waterIN,itemID, i, vertFlow[i-1] , satExcess[i+1], maxSoilMoist[i]); printf("Deltad = %f waterOUT = %f itemID %i Layer %i actETP[i] %f vertFlow[i] %f (_liq[i] %f ,_previousLiq[i]) %f satExcess[i]%f \n",balance,waterOUT,itemID, i, actETP[i] ,vertFlow[i],_liq[i],_previousLiq[i], satExcess[i]); if (itemID==139)printf("Delta = %f waterIN = %f itemID %i Layer %i vertFlow[i-1] %f satExcess[i+1] %f maxSM %f\n",balance, waterIN,itemID, i, vertFlow[i-1] , satExcess[i+1], maxSoilMoist[i]); if (itemID==139)printf("Deltad = %f waterOUT = %f itemID %i Layer %i actETP[i] %f vertFlow[i] %f (_liq[i] %f ,_previousLiq[i]) %f satExcess[i]%f \n",balance,waterOUT,itemID, i, actETP[i] ,vertFlow[i],_liq[i],_previousLiq[i], satExcess[i]); // accumSoilDepth[i-1] // printf("WaterBalanceError in Layer %i Depth=%f at item %i waterOUT = %f actETP[i] %f satExcess[i] %f vertFlow[i] %f deltaS %f\n",i,soilDepth[i],itemID, waterOUT,actETP[i], satExcess[i], vertFlow[i], (_liq[i]-_previousLiq[i])); //if (itemID==200)printf ("waterIN = %f\n",waterIN); //if (itemID==200)printf ("waterOUT = %f\n",waterOUT); } } //for looop form bottom layer //// //// if (itemID==200)printf ("i%i liqnacher %f \n", i,_liq[0]); //// //// // if (itemID==200) printf("itemID %i max0 =%f max1 =%f max2=%f max3=%f\n",itemID, maxSoilMoist[0],maxSoilMoist[1],maxSoilMoist[2],maxSoilMoist[3]); //// // //// //Last layer is runoff detention pool ! float beta = 0.0167; inf2LowestLayer +=vertFlow[numSoilLayers-2]; baseflow = beta* _liq[numSoilLayers-1]; _liq[numSoilLayers-1]=_previousLiq[numSoilLayers-1] + vertFlow[numSoilLayers-2] -baseflow; // if (itemID==139) printf("itemID %i Day %i TimEStp%i IN=%f et = %f liq0 = %f liq1 = %f liq2=%f liq3=%f liq4 %f surfaceRO %f dt_inflow %f EXCESS[1] %f \n",itemID,MFDateGetDayOfYear(), dt,liquidIn,actETP[0], _liq[0], _liq[1], _liq[2], _liq[3],_liq[4], surfaceRO,dt_inflow, satExcess[1]); //// //// //// } // time step loop // //float watbal0; //float in0 = dt_inflow; ////float out0=vertFlow[0]; float soilMoist= 0; // float iceInAllLayers=0; for (i=0;i<numSoilLayers-1;i++){ // exclude lowest layer from calculation smCurrent+=_liq[i]+ice[i]-residSoilMoist[i]; // if (itemID==626) printf ("i %i ice[i] %f residSoilMoist[i] %f _liq[i] %f\n", itemID,ice[i],residSoilMoist[i],_liq[i]); _previousLiq[i]=_liq[i]-residSoilMoist[i]; actualET +=actETP[i]; // if (_liq[i]<0)printf ("SM negative! %f\n", _liq[i]); waterInAllLayers+=_liq[i]+ice[i]-residSoilMoist[i]; // if (itemID==200)printf("waterinAllLayers %f\n", waterInAllLayers); iceInAllLayers+=ice[i]; soilMoist += (_liq[i]+ice[i])/maxSoilMoist[i] * soilDepth[i] ; MFVarSetFloat (_MDOutSMLiquidIDs[i], itemID, _liq[i]); MFVarSetFloat (_MDOutSMIceDs[i], itemID, 0); MFVarSetFloat (_MDSoilRelativeSoilMoistIDs[i], itemID, (_liq[i]+ice[i])/maxSoilMoist[i]); } MFVarSetFloat (_MDOutSMLiquidIDs[numSoilLayers-1], itemID, _liq[numSoilLayers-1]); // waterTableDepth = waterTableDepthParameter* (accumSoilDepth[numSoilLayers-1] - soilMoist); // if (itemID==200)printf ("WaterTableDepth = %f Param %f depth %f moist %f \n", waterTableDepth, waterTableDepthParameter, accumSoilDepth[numSoilLayers-1], soilMoist); // if (itemID==200) printf("itemID %i Day %i TimEStp%i IN=%f et = %f ice1 = %f ice2 = %f ice3=%f ice4=%f surfaceRO %f dt_inflow %f WP %f\n",itemID,MFDateGetDayOfYear(), dt,liquidIn,actETP[1], ice[0], ice[1], ice[2], ice[3], surfaceRO,dt_inflow,permWP[1]); // // if (itemID==200) printf("WaterInAllLayers %f\n", waterInAllLayers); lowestLayerChange= _liq[numSoilLayers-1]-prevLowestLayerLiq-residSoilMoist[numSoilLayers-1]; // // if (itemID==267)printf("waterin all layers = %f ice %f inFlow %f surfRO %f dSLowestLayer%f \n",waterInAllLayers, iceInAllLayers,liquidIn, surfaceRO,baseflow); // meanSmoistChange= smCurrent-smPrevious; // if (meanSmoistChange > 200)printf ("meanSmoistChange= %f smCurrent = %f smPrevious = %f\n",meanSmoistChange, smCurrent,smPrevious ); // waterIN = liquidIn; waterOUT = meanSmoistChange + surfaceRO + actualET +lowestLayerChange ; balance= waterIN - waterOUT; // if (itemID==200) printf ("WaterINAllLayers %f TimeSteps %i OUT =%f meanSmoistChange= %f surfaceRO %f actualET %f lowestLayerChange %f\n",waterInAllLayers+_liq[numSoilLayers-1], _MDTimeSteps,waterOUT,meanSmoistChange,surfaceRO,actualET,lowestLayerChange); // if (fabs(balance) > 0.001 && isInitial > 0){ // printf (" ====WaterBalance for item %i %f in MDRainSolMoisLayered!in =%f out%f item%i surfRO %f maxSoil%f baseFlowDelta %f item %i lowestLayerChange %f\n",itemID, balance, waterIN, waterOUT,itemID, surfaceRO, maxSoilMoist[0], _liq[numSoilLayers-1], itemID,lowestLayerChange); // if (itemID==200) printf (" ====WaterBalance in MDRainSolMoisLayered!in =%f out%f item%i surfRO %f maxSoil%f baseFlowDelta %f item %i\n", waterIN, waterOUT,itemID, surfaceRO, maxSoilMoist[0], _liq[numSoilLayers-1], itemID); // if (itemID==200) printf ("PrevSMLowest %f liqIN = %f deltaS = %f surfaceRO %f actualET %f currentSM%f previousSM%f \n", prevLowestLayerLiq, waterIN, meanSmoistChange, surfaceRO,actualET, smCurrent, smPrevious); //if (itemID==200) printf ("PrevSMLowest %f liqIN = %f deltaS = %f surfaceRO %f actualET %f currentSM%f previousSM%f \n", prevLowestLayerLiq, waterIN, meanSmoistChange, surfaceRO,actualET, smCurrent, smPrevious); // if (itemID==200) printf ("maxSM 1 %f maxSM 2 %f maxSM 3 %f maxSM %f \n",maxSoilMoist[0],maxSoilMoist[1],maxSoilMoist[2],maxSoilMoist[3]); } // if (itemID==200) printf("itemID %i Day %i TimEStp%i IN=%f et = %f liq1 = %f liq2 = %f liq3=%f liq4=%f liq5 %f surfaceRO %f dt_inflow %f \n",itemID,MFDateGetDayOfYear(), dt,liquidIn,actETP[0], _liq[0], _liq[1], _liq[2], _liq[3],_liq[4], surfaceRO,dt_inflow); // MFVarSetFloat (_MDOutSoilMoistCellID, itemID, meanSmoist); MFVarSetFloat (_MDOutEvaptrsID, itemID, actualET * (1.0 - irrAreaFrac)); MFVarSetFloat (_MDOutSoilMoistID, itemID, meanSmoist * (1.0 - irrAreaFrac)); MFVarSetFloat (_MDOutRainInfiltrationID, itemID, inf2LowestLayer * (1.0 - irrAreaFrac)); MFVarSetFloat (_MDOutSatExcessFlowID, itemID, surfaceRO * (1.0 - irrAreaFrac)); MFVarSetFloat (_MDOutSMoistChgID, itemID, meanSmoistChange * (1.0 - irrAreaFrac)); MFVarSetFloat (_MDOutSoilDebugID, itemID, K1Sat); MFVarSetFloat (_MDOutWaterTableDepthID, itemID, waterTableDepth); MFVarSetFloat (_MDInIsInitialID, itemID, 1.0); //printf ("SatExcessFlow = %f\n", MFVarGetFloat(_MDOutSatExcessFlowID,itemID,0.0)); free(actETP);// c sucks c sucks c totally sucks free (VanGn); free(fieldCap); free (permWP); free(residSoilMoist); free(maxSoilMoist); free(VanGa); free(VanGm); //free(kSat); //// printf ("hier2\n"); }
static void _MDWTempRiverRoute (int itemID) { float Q; float Q_incoming; float RO_Vol; float RO_WTemp; float QxT_input; float QxT; float QxTnew = 0; float QxTout = 0; float Q_WTemp; float Q_WTemp_new; float StorexT; float StorexT_new; float DeltaStorexT; float SnowPack; //processing variables float channelWidth; float waterStorageChange; float waterStorage; float ResWaterStorageChange = 0; float ResWaterStorage = 0; float solarRad; float windSpeed; float cloudCover; float Tair; float Tequil = 0; float HeatLoss_int = 4396.14; // is intercept assuming no wind and clouds float HeatLoss_slope = 1465.38; // is slope assuming no wind and clouds float deltaT; float ReservoirArea; float ReservoirDepth; float ReservoirVelocity; // conservative mixing variables (parallel to those above_ float QxT_mix; float QxTnew_mix = 0; float QxTout_mix = 0; float Q_WTemp_mix; float StorexT_mix; float StorexT_new_mix; float DeltaStorexT_mix; float QxTRemoval; int day; int month; float resCapacity; //RJS 071511 Reservoir capacity [km3] float QxT_postThermal; //RJS 081311 float QxT_mix_postThermal; //RJS 081311 float Q_WTemp_postThermal; //RJS 081311 float Q_WTemp_mix_postThermal; //RJS 081311 float warmingTemp; //RJS 081311 float wdl_QxT; //RJS 081311 float thermal_wdl; //RJS 081311 float StorexT_postThermal; //RJS 081711 float DeltaStorexT_postThermal; //RJS 081711 float StorexT_mix_postThermal; //RJS 081711 float DeltaStorexT_mix_postThermal; //RJS 081711 float deltaT_postThermal; //RJS 081711 day = MFDateGetCurrentDay(); month = MFDateGetCurrentMonth(); Q = MFVarGetFloat (_MDInDischargeID, itemID, 0.0); Q_incoming = MFVarGetFloat (_MDInDischargeIncomingID, itemID, 0.0); // already includes local runoff RO_Vol = MFVarGetFloat (_MDInRunoffVolumeID, itemID, 0.0); RO_WTemp = MFVarGetFloat (_MDInWTempRiverID, itemID, 0.0); SnowPack = MFVarGetFloat (_MDInSnowPackID, itemID, 0.0); if (_MDInResStorageID != MFUnset){ ResWaterStorageChange = MFVarGetFloat ( _MDInResStorageChangeID, itemID, 0.0) * pow(1000,3); // convert to m3/ ResWaterStorage = MFVarGetFloat ( _MDInResStorageID, itemID, 0.0) * pow(1000,3); // convert to m3 resCapacity = MFVarGetFloat (_MDInResCapacityID, itemID, 0.0); //RJS 071511 } else { ResWaterStorageChange = ResWaterStorage = resCapacity = 0.0; //RJS 071511 } waterStorageChange = MFVarGetFloat ( _MDInRiverStorageChgID, itemID, 0.0); waterStorage = MFVarGetFloat ( _MDInRiverStorageID, itemID, 0.0); channelWidth = MFVarGetFloat ( _MDInRiverWidthID, itemID, 0.0); solarRad = MFVarGetFloat ( _MDInSolarRadID, itemID, 0.0); //MJ/m2/d - CHECK UNITS windSpeed = MFVarGetFloat ( _MDInWindSpeedID, itemID, 0.0); cloudCover = MFVarGetFloat ( _MDInCloudCoverID, itemID, 0.0); Tair = MFVarGetFloat ( _MDInAirTemperatureID, itemID, 0.0); QxT = MFVarGetFloat (_MDFlux_QxTID, itemID, 0.0); StorexT = MFVarGetFloat (_MDStorage_QxTID, itemID, 0.0); QxT_mix = MFVarGetFloat (_MDFluxMixing_QxTID, itemID, 0.0); StorexT_mix = MFVarGetFloat (_MDStorageMixing_QxTID, itemID, 0.0); warmingTemp = MFVarGetFloat (_MDInWarmingTempID, itemID, 0.0); //RJS 072011 wdl_QxT = MFVarGetFloat (_MDInWdl_QxTID, itemID, 0.0); //RJS 072011 thermal_wdl = MFVarGetFloat (_MDInThermalWdlID, itemID, 0.0)* 1000000 / 365 / 86400; //RJS 072011 // if (itemID == 5132){ // printf("Stop itemID %d day %d \n", itemID, MFDateGetCurrentDay()); // } //TODO: combine with reservoir check above - also make reservoir hydraulics generally accessible //TODO: add effect of water withdrawals if(Q < 0.0) Q = 0.0; //RJS 120409 if(Q_incoming < 0.0) Q_incoming = 0.0; //RJS 120409 // if(RO_Vol < 0.0) RO_Vol = 0.0; //RJS 071511 if(resCapacity > 0.0){ waterStorage = waterStorage + ResWaterStorage; waterStorageChange = waterStorageChange + ResWaterStorageChange; ReservoirArea = pow(((ResWaterStorage / pow(10,6)) / 9.208),(1 / 1.114)) * 1000 * 1000; // m2, from Takeuchi 1997 - original equation has V in 10^6 m3 and A in km2 ReservoirDepth = (ResWaterStorage / ReservoirArea); //m ReservoirVelocity = Q / (ReservoirArea); // m/s channelWidth = MDMaximum(channelWidth, (Q / (ReservoirDepth * ReservoirVelocity))); // m QxT_input = RO_Vol * RO_WTemp * 86400.0; //RJS 071511 //m3*degC/d QxTnew = QxT + QxT_input + StorexT; //RJS 071511 //m3*degC/d QxTnew_mix = QxT_mix + QxT_input + StorexT_mix; //RJS 071511 if (Q_incoming > 0.000001) { Q_WTemp = QxTnew / ((Q_incoming) * 86400 + (waterStorage - waterStorageChange)); //RJS 071511 //degC Q_WTemp_mix = QxTnew_mix / ((Q_incoming) * 86400 + (waterStorage - waterStorageChange)); //RJS 071511 //degC // if (itemID == 25014) printf("Q_incoming > 0.000001\n"); } else { if (waterStorage > 0) { Q_WTemp = StorexT / waterStorage; // RJS 071511 //degC Q_WTemp_mix = StorexT_mix / waterStorage; // RJS 071511 //degC // if (itemID == 25014) printf("waterStorage > 0\n"); } else { Q_WTemp = 0.0; //RJS 071511 Q_WTemp_mix = 0.0; //RJS 071511 // if (itemID == 25014) printf("else\n"); } } Q_WTemp_new = Q_WTemp; //RJS 071511 StorexT_new = waterStorage * Q_WTemp_new; //RJS 071511 //m3*degC DeltaStorexT = StorexT_new - StorexT; //RJS 071511 QxTout = Q * 86400.0 * Q_WTemp_new ; //RJS 071511 //m3*degC/d QxTRemoval = QxTnew - (StorexT_new + QxTout); //RJS 071511 //m3*degC/d StorexT_new_mix = waterStorage * Q_WTemp_mix; //RJS 071511 //m3*degC DeltaStorexT_mix = StorexT_new_mix - StorexT_mix; //RJS 071511 QxTout_mix = Q * 86400.0 * Q_WTemp_mix; //RJS 071511 //m3*degC/s // if (itemID == 5033) printf("m = %d, d = %d, itemID = %d, QxTout = %f, QxTout_mix = %f, Q = %f, Q_WTemp_new = %f\n", MFDateGetCurrentMonth (), MFDateGetCurrentDay (), itemID, QxTout, QxTout_mix, Q, Q_WTemp_new); // if (itemID == 4704) printf("m = %d, d = %d, itemID = %d, QxTout = %f, QxTout_mix = %f, Q = %f, Q_WTemp_new = %f\n", MFDateGetCurrentMonth (), MFDateGetCurrentDay (), itemID, QxTout, QxTout_mix, Q, Q_WTemp_new); //New experimental QxT_postThermal = thermal_wdl > Q ? 86400 * Q * (Q_WTemp_new + warmingTemp) : 86400 * ((thermal_wdl * (Q_WTemp_new + warmingTemp)) + ((Q - thermal_wdl) * Q_WTemp_new)); QxT_mix_postThermal = thermal_wdl > Q ? 86400 * Q * (Q_WTemp_mix + warmingTemp) : 86400 * ((thermal_wdl * (Q_WTemp_mix + warmingTemp)) + ((Q - thermal_wdl) * Q_WTemp_mix)); Q_WTemp_postThermal = Q > 0.000001 ? QxT_postThermal / (Q * 86400) : 0.0; Q_WTemp_mix_postThermal = Q > 0.000001 ? QxT_mix_postThermal / (Q * 86400) : 0.0; StorexT_postThermal = waterStorage * Q_WTemp_postThermal; DeltaStorexT_postThermal = StorexT_postThermal - StorexT; StorexT_mix_postThermal = waterStorage * Q_WTemp_mix_postThermal; DeltaStorexT_mix_postThermal = StorexT_mix_postThermal - StorexT_mix; deltaT_postThermal = Q_WTemp_postThermal - Q_WTemp; // if (itemID == 5033) printf("QxT_pt = %f, Q_WTemp_pt = %f\n", QxT_postThermal, Q_WTemp_postThermal); //if (itemID == 4704) printf("QxT_pt = %f, Q_WTemp_pt = %f\n", QxT_postThermal, Q_WTemp_postThermal); //end MFVarSetFloat(_MDLocalIn_QxTID, itemID, QxT_input); // MFVarSetFloat(_MDRemoval_QxTID, itemID, QxTRemoval); // MFVarSetFloat(_MDFlux_QxTID, itemID, QxTout); MFVarSetFloat(_MDFlux_QxTID, itemID, QxT_postThermal); //RJS new // MFVarSetFloat(_MDStorage_QxTID, itemID, StorexT_new); MFVarSetFloat(_MDStorage_QxTID, itemID, StorexT_postThermal); //RJS new // MFVarSetFloat(_MDDeltaStorage_QxTID, itemID, DeltaStorexT); MFVarSetFloat(_MDDeltaStorage_QxTID, itemID, DeltaStorexT_postThermal); //RJS new // MFVarSetFloat(_MDWTemp_QxTID, itemID, Q_WTemp_new); MFVarSetFloat(_MDWTemp_QxTID, itemID, Q_WTemp_postThermal); //RJS new // MFVarSetFloat(_MDWTempDeltaT_QxTID, itemID, deltaT); // MFVarSetFloat(_MDWTempDeltaT_QxTID, itemID, deltaT_postThermal); //RJS new // MFVarSetFloat(_MDFluxMixing_QxTID, itemID, QxTout_mix); MFVarSetFloat(_MDFluxMixing_QxTID, itemID, QxT_mix_postThermal); //RJS new // MFVarSetFloat(_MDStorageMixing_QxTID, itemID, StorexT_new_mix); MFVarSetFloat(_MDStorageMixing_QxTID, itemID, StorexT_mix_postThermal); //RJS new // MFVarSetFloat(_MDDeltaStorageMixing_QxTID, itemID, DeltaStorexT_mix); MFVarSetFloat(_MDDeltaStorageMixing_QxTID, itemID, DeltaStorexT_mix_postThermal); //RJS new // MFVarSetFloat(_MDWTempMixing_QxTID, itemID, Q_WTemp_mix); MFVarSetFloat(_MDWTempMixing_QxTID, itemID, Q_WTemp_mix_postThermal); //RJS new // MFVarSetFloat(_MDLocalIn_QxTID, itemID, QxT_input); //RJS 071511 //// MFVarSetFloat(_MDRemoval_QxTID, itemID, QxTRemoval); //RJS 071511 // MFVarSetFloat(_MDFlux_QxTID, itemID, QxTout); //RJS 071511 // MFVarSetFloat(_MDStorage_QxTID, itemID, StorexT_new); //RJS 071511 // MFVarSetFloat(_MDDeltaStorage_QxTID, itemID, DeltaStorexT); //RJS 071511 // MFVarSetFloat(_MDWTemp_QxTID, itemID, Q_WTemp_new); //RJS 071511 //// MFVarSetFloat(_MDWTempDeltaT_QxTID, itemID, deltaT); //RJS 071511 // MFVarSetFloat(_MDFluxMixing_QxTID, itemID, QxTout_mix); //RJS 071511 // MFVarSetFloat(_MDStorageMixing_QxTID, itemID, StorexT_new_mix); //RJS 071511 // MFVarSetFloat(_MDDeltaStorageMixing_QxTID, itemID, DeltaStorexT_mix); //RJS 071511 // MFVarSetFloat(_MDWTempMixing_QxTID, itemID, Q_WTemp_mix); //RJS 071511 } else{ ReservoirArea = 0.0; ReservoirVelocity = 0.0; ReservoirDepth = 0.0; // } = %f //RJS commented out 071511 //TODO: RO_Vol has been set to never be less than 0 in MDWRunoff QxT_input = RO_Vol * RO_WTemp * 86400.0; //m3*degC/d //if (itemID == 188 && month == 5 && day == 1){ // printf("Stop: Q %f RO_Vol %f QxT %f QxT_input %f \n", Q, RO_Vol, QxT, QxT_input); //} //note: calculation for input concentration is changed from previous iterations // to use incoming Q. Also use WaterStorage from previous time step/ // TODO: Need to include a variable that accounts for losses due to discharge disappearing (Drying) // TODO: Make all these changes for other bgc flux models // Q_incoming includes local runoff!!! if((Q_incoming) > 0.000001) { //do not include water storage in this check - will screw up mixing estimates QxTnew = QxT + QxT_input + StorexT; //m3*degC/d QxTnew_mix = QxT_mix + QxT_input + StorexT_mix; Q_WTemp = QxTnew / ((Q_incoming) * 86400 + (waterStorage - waterStorageChange)); //degC Q_WTemp_mix = QxTnew_mix / ((Q_incoming) * 86400 + (waterStorage - waterStorageChange)); //degC ///Temperature Processing using Dingman 1972 if (cloudCover < 95){ // clear skies, assume cloud cover < 95% convertcalories / cm2 /d to kJ/m2/d HeatLoss_int = (105 + 23 * windSpeed) * 4.1868 / 1000 * 100 * 100; // kJ/m2/d HeatLoss_slope = (35 + 4.2 * windSpeed) * 4.1868 / 1000 * 100 * 100;// kJ/m2/d/degC } else{ // cloudy skies, assume cloud cover > 95% HeatLoss_int = (-73 + 9.1 * windSpeed) * 4.1868 / 1000 * 100 * 100; HeatLoss_slope = (37 + 4.6 * windSpeed) * 4.1868 / 1000 * 100 * 100; } Tequil = Tair + (((solarRad * 1000) - HeatLoss_int) / HeatLoss_slope); //solar rad converted from MJ to kJ/m2/d // use exponential form //TODO channelWidth can equal 0 when waterStorage > 0.0, so need to check here // Apply model only to large enough discharges, otherwise assume temperature equils equilibrium // if (channelWidth > 0 && Q > 0.001){ if (channelWidth > 0){ Q_WTemp_new = MDMaximum(0, (((Q_WTemp - Tequil) * exp((-HeatLoss_slope * MFModelGetLength(itemID)) / (999.73 * 4.1922 * (Q * 86400.0 / channelWidth)))) + Tequil)); } else { Q_WTemp_new = MDMaximum(0, Tequil); } //if cell has reservoir, assume reservoir exchange dominates //if(ResWaterStorage > 0){ // Q_WTemp_new = MDMaximum(0, (((Q_WTemp - Tequil) * exp((-HeatLoss_slope * ReservoirArea) / (999.73 * 4.1922 * (Q * 86400.0)))) + Tequil)); //} deltaT = Q_WTemp_new - Q_WTemp; //if (Q_WTemp_new > 50){ // if (Q_WTemp_mix > 30){ // printf("Toggle"); // printf("Stop WaterTemp > 50 itemID %d XCoord %f YCoord %f month %d day %d Q %f Q_incoming %f waterStorage %f " // "RO_Vol %f RO_WTemp %f QxT %f QxT_mix %f StorexT %f Storext_mix %f QxT_input %f QxTnew %f Q_WTemp %f Q_WTemp_mix %f Q_WTemp_new %f Tequil %f \n", // itemID, MFModelGetXCoord(itemID),MFModelGetYCoord(itemID), month, day, Q, Q_incoming, waterStorage, // RO_Vol, RO_WTemp, QxT, QxT_mix, StorexT, StorexT_mix, QxT_input, QxTnew, Q_WTemp, Q_WTemp_mix, Q_WTemp_new, Tequil); // } StorexT_new = waterStorage * Q_WTemp_new; //m3*degC DeltaStorexT = StorexT_new - StorexT; // QxTout = Q * 86400.0 * Q_WTemp_new ; //m3*degC/d QxTRemoval = QxTnew - (StorexT_new + QxTout); //m3*degC/d StorexT_new_mix = waterStorage * Q_WTemp_mix; //m3*degC DeltaStorexT_mix = StorexT_new_mix - StorexT_mix; QxTout_mix = Q * 86400.0 * Q_WTemp_mix; //m3*degC/s // if (itemID == 5033) printf("m = %d, d = %d, itemID = %d, QxTout = %f, QxTout_mix = %f, Q = %f, Q_WTemp_new = %f\n", MFDateGetCurrentMonth (), MFDateGetCurrentDay (), itemID, QxTout, QxTout_mix, Q, Q_WTemp_new); // if (itemID == 4704) printf("m = %d, d = %d, itemID = %d, QxTout = %f, QxTout_mix = %f, Q = %f, Q_WTemp_new = %f\n", MFDateGetCurrentMonth (), MFDateGetCurrentDay (), itemID, QxTout, QxTout_mix, Q, Q_WTemp_new); // if (QxT_input > 1000) printf("m = %d, d = %d, itemID = %d, QxT_input = %f, RO_Vol = %f, RO_WTemp = %f, QxT = %f, QxT_mix = %f\n, QxTout = %f, QxTout_mix = %f, Q = %f\n", MFDateGetCurrentMonth (), MFDateGetCurrentDay (), itemID, QxT_input, RO_Vol, RO_WTemp, QxT, QxT_mix, QxTout, QxTout_mix, Q); // if (Q_WTemp_new > 50) printf("m = %d, d = %d, itemID = %d, QxT_input = %f, RO_Vol = %f, RO_WTemp = %f\n channelWidth = %f, Q_WTemp = %f, Q_WTemp_new = %f, Q_WTemp_mix = %f, Tair = %f, Q = %f, Q_incoming = %f\n", MFDateGetCurrentMonth (), MFDateGetCurrentDay (), itemID, QxT_input, RO_Vol, RO_WTemp, channelWidth, Q_WTemp, Q_WTemp_new, Q_WTemp_mix, Tair, Q, Q_incoming); //New experimental QxT_postThermal = thermal_wdl > Q ? 86400 * Q * (Q_WTemp_new + warmingTemp) : 86400 * ((thermal_wdl * (Q_WTemp_new + warmingTemp)) + ((Q - thermal_wdl) * Q_WTemp_new)); QxT_mix_postThermal = thermal_wdl > Q ? 86400 * Q * (Q_WTemp_mix + warmingTemp) : 86400 * ((thermal_wdl * (Q_WTemp_mix + warmingTemp)) + ((Q - thermal_wdl) * Q_WTemp_mix)); Q_WTemp_postThermal = Q > 0.000001 ? QxT_postThermal / (Q * 86400) : 0.0; Q_WTemp_mix_postThermal = Q > 0.000001 ? QxT_mix_postThermal / (Q * 86400) : 0.0; StorexT_postThermal = waterStorage * Q_WTemp_postThermal; DeltaStorexT_postThermal = StorexT_postThermal - StorexT; StorexT_mix_postThermal = waterStorage * Q_WTemp_mix_postThermal; DeltaStorexT_mix_postThermal = StorexT_mix_postThermal - StorexT_mix; deltaT_postThermal = Q_WTemp_postThermal - Q_WTemp; // if (itemID == 5033) printf("QxT_pt = %f, Q_WTemp_pt = %f\n", QxT_postThermal, Q_WTemp_postThermal); //if (itemID == 4704) printf("QxT_pt = %f, Q_WTemp_pt = %f\n", QxT_postThermal, Q_WTemp_postThermal); //end MFVarSetFloat(_MDLocalIn_QxTID, itemID, QxT_input); MFVarSetFloat(_MDRemoval_QxTID, itemID, QxTRemoval); // MFVarSetFloat(_MDFlux_QxTID, itemID, QxTout); MFVarSetFloat(_MDFlux_QxTID, itemID, QxT_postThermal); //RJS new // MFVarSetFloat(_MDStorage_QxTID, itemID, StorexT_new); MFVarSetFloat(_MDStorage_QxTID, itemID, StorexT_postThermal); //RJS new // MFVarSetFloat(_MDDeltaStorage_QxTID, itemID, DeltaStorexT); MFVarSetFloat(_MDDeltaStorage_QxTID, itemID, DeltaStorexT_postThermal); //RJS new // MFVarSetFloat(_MDWTemp_QxTID, itemID, Q_WTemp_new); MFVarSetFloat(_MDWTemp_QxTID, itemID, Q_WTemp_postThermal); //RJS new // MFVarSetFloat(_MDWTempDeltaT_QxTID, itemID, deltaT); MFVarSetFloat(_MDWTempDeltaT_QxTID, itemID, deltaT_postThermal); //RJS new // MFVarSetFloat(_MDFluxMixing_QxTID, itemID, QxTout_mix); MFVarSetFloat(_MDFluxMixing_QxTID, itemID, QxT_mix_postThermal); //RJS new // MFVarSetFloat(_MDStorageMixing_QxTID, itemID, StorexT_new_mix); MFVarSetFloat(_MDStorageMixing_QxTID, itemID, StorexT_mix_postThermal); //RJS new // MFVarSetFloat(_MDDeltaStorageMixing_QxTID, itemID, DeltaStorexT_mix); MFVarSetFloat(_MDDeltaStorageMixing_QxTID, itemID, DeltaStorexT_mix_postThermal); //RJS new // MFVarSetFloat(_MDWTempMixing_QxTID, itemID, Q_WTemp_mix); MFVarSetFloat(_MDWTempMixing_QxTID, itemID, Q_WTemp_mix_postThermal); //RJS new } else{ if (waterStorage > 0){ QxTnew = QxT_input + StorexT; //m3*degC QxTnew_mix = QxT_input + StorexT_mix; } else{ QxTnew = 0; QxTnew_mix = 0; } StorexT_new = 0.0; //m3*degC DeltaStorexT = StorexT_new - StorexT; // QxTout = 0.0; //m3*degC/dStorexT_new_mix = 0; //m3*degC QxTRemoval = 0.0; //m3*degC/d StorexT_new_mix = 0.0; //m3*degC DeltaStorexT_mix = StorexT_new_mix - StorexT_mix; QxTout_mix = 0.0; //m3*degC/s // printf("m = %d, d = %d, itemID = %d, QxT_input = %f, RO_Vol = %f, RO_WTemp = %f\n Q_WTemp = %f, Q_WTemp_new = %f, Q_WTemp_mix = %f, Q = %f, Q_incoming = %f\n", MFDateGetCurrentMonth (), MFDateGetCurrentDay (), itemID, QxT_input, RO_Vol, RO_WTemp, Q_WTemp, Q_WTemp_new, Q_WTemp_mix, Q, Q_incoming); MFVarSetFloat(_MDLocalIn_QxTID, itemID, 0.0); MFVarSetFloat(_MDRemoval_QxTID, itemID, QxTRemoval); MFVarSetFloat(_MDFlux_QxTID, itemID, QxTout); MFVarSetFloat(_MDStorage_QxTID, itemID, StorexT_new); MFVarSetFloat(_MDDeltaStorage_QxTID, itemID, DeltaStorexT); MFVarSetFloat(_MDFluxMixing_QxTID, itemID, QxTout_mix); MFVarSetFloat(_MDStorageMixing_QxTID, itemID, StorexT_new_mix); MFVarSetFloat(_MDDeltaStorageMixing_QxTID, itemID, DeltaStorexT_mix); MFVarSetMissingVal(_MDWTemp_QxTID, itemID); MFVarSetMissingVal(_MDWTempDeltaT_QxTID, itemID); MFVarSetMissingVal(_MDWTempMixing_QxTID, itemID); } float mb; float mbmix; mb = QxT_input + QxT - QxTRemoval - QxTout - DeltaStorexT; mbmix = (QxT_input + QxT_mix - QxTout_mix - DeltaStorexT_mix); } //RJS 071511 //if (mbmix > 100000){ //printf("mass balance = mb %f mbmix %f \n", mb, mbmix); //} // if (itemID == 25014) printf("Q_WTemp_new = %f, QxTnew = %f, Q_incoming = %f, Q_m3 = %f, waterStorage = %f, waterStorageChange = %f, \n", Q_WTemp_new, QxTnew, Q_incoming, Q_incoming * 86400, waterStorage, waterStorageChange); // if (itemID == 25014) printf("T_river = %f, T_runoff = %f, T_storage = %f\n", QxT/Q_incoming, RO_WTemp, StorexT/(waterStorage - waterStorageChange)); // if (itemID == 25014) printf("*** m = %d, d = %d, resCapacity = %f, waterStorage = %f, waterStorageChange = %f\n", MFDateGetCurrentMonth(), MFDateGetCurrentDay(), resCapacity, waterStorage, waterStorageChange); // if (itemID == 25014) printf("Q_incoming = %f, Q = %f, RO_vol = %f\n", Q_incoming, Q, RO_Vol); // if (itemID == 25014) printf("m = %d, d = %d, m3 degC: QxT = %f, StorexT = %f, QxT_input = %f\n", MFDateGetCurrentMonth(), MFDateGetCurrentDay(), QxT, StorexT, QxT_input); // if (itemID == 25014) printf("volume: Q_incoming = %f, waterStorage - change = %f, RO_Vol = %f\n", Q_incoming * 86400, waterStorage - waterStorageChange, RO_Vol * 86400); // if (itemID == 25014) printf("flux = %f, storage = %f, RO_WTemp = %f\n", QxT / (Q_incoming * 86400), StorexT / (waterStorage - waterStorageChange), RO_WTemp); // if (itemID == 5033) printf("END: itemID = %d, m = %d, d= %d, Q = %f, QxT_pt = %f, Q_WTemp_pt = %f, QxTout = %f, \n", itemID, MFDateGetCurrentMonth(), MFDateGetCurrentDay(), Q, QxT_postThermal, Q_WTemp_postThermal, QxTout); // if (itemID == 4704) printf("END: itemID = %d, m = %d, d= %d, Q = %f, QxT_pt = %f, Q_WTemp_pt = %f, QxTout = %f, \n", itemID, MFDateGetCurrentMonth(), MFDateGetCurrentDay(), Q, QxT_postThermal, Q_WTemp_postThermal, QxTout); }
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); }
static void _MDRiverGPP (int itemID) { float channelWidth; //GPP drivers/parameters float par2bottom; //MJ / m2 /d float DIN = 1; //mg/l float DIP = 0.05; //mg/l float Ks_N = 0.1; float Ks_P = 0.01; float Km = 0.01; // algal mortality d-1 float Ks = 0.01; // algal sloughing d-1 float Ben_C2CHL = 50; //Benthic Carbon variables float uEinsteinperm2stoWattperm2 = 0.2174; //see websitehttp://www.seabird.com/application_notes/AN11General.htm based on Morel and Smith 1974, valid for sun altitudes > 22 degrees float daylength = 12; //hours of light per day needed to convert daily par to per second float Ed; float Ek = 100; // PAR in microEinsteins / m2/s at onset of saturation - in Table 10.1 of Kirk, ueinsteins / m2 / s float Ben_GPPmax; //g C / h / g chl at light saturation float Ben_GPP; // g C / m2 /d float Ben_MORTALITY; float Ben_Ra; float Ben_NPP; float Ben_AlgaeC; float Ben_AlgaeCHL; float Ben_AlgaeC_REACH; float Ben_GPP_REACH; float Ben_Ra_REACH; float Ben_NPP_REACH; float Ben_Mortality_REACH; float day; day = MFDateGetCurrentDay(); float month; month = MFDateGetCurrentMonth(); channelWidth = MFVarGetFloat ( _MDInRiverWidthID, itemID, 0.0); par2bottom = MFVarGetFloat ( _MDInPAR2BottomID, itemID, 0.0); Ben_AlgaeCHL = MFVarGetFloat ( _MDBenthicAlgaeCHLID, itemID, 0.0); // g Chl / m2 Ben_AlgaeC = MFVarGetFloat ( _MDBenthicAlgaeCID, itemID, 0.0); // g C / m2 //TODO: How to get Chl spun up - uptake depends on CHL, but CHL starts at 0. The following is a place holder: Ben_AlgaeC = ((day == 1 && Ben_AlgaeC == 0.0) ? 0.1 : Ben_AlgaeC); Ben_AlgaeCHL = ((day == 1 && Ben_AlgaeC == 0.0) ? 0.1 * Ben_C2CHL : Ben_AlgaeCHL); Ed = (par2bottom / (daylength * 60 * 60)) * pow(10,6) * 1 * (1 / uEinsteinperm2stoWattperm2); // uEinsteins / m2 / s, average for day assuming daylight hours and converted from radiation units of MJ/m2/d Ben_GPPmax = MDMaximum(0.0, MDMaximum(1, (3.7 - (0.1 * Ben_AlgaeCHL)))); //g C / hr / g chl at light saturation Ryther and Yentsch 1957, but add a self shading control //refs for the eqn Ryther and Yentsch 1957; Kirk 1994 (EQN 10.4) Ben_GPP = Ben_AlgaeCHL * Ben_GPPmax * daylength * DIN / (DIN + Ks_N) * DIP / (DIP + Ks_P) * (1 - exp(-Ed / Ek)); //g C / m2 / d // N limitation P limitation decay from light saturation float Ben_RespRate = 0.1; //d-1 Ben_Ra = MDMinimum(Ben_AlgaeC * 0.9, Ben_AlgaeC * Ben_RespRate); // g C / m2 / day autotrophic respiration Ks = 0.05 + 0.01 * (Ben_AlgaeC + Ben_GPP - Ben_Ra); Ben_MORTALITY = MDMinimum((Ben_AlgaeC - Ben_Ra), (Ben_AlgaeC - Ben_Ra) * (Km + Ks)); //gC / m2 / day; Ben_NPP = Ben_GPP - Ben_Ra; Ben_AlgaeC = Ben_AlgaeC + Ben_GPP - Ben_MORTALITY - Ben_Ra ; // g C / m2 / day Ben_AlgaeCHL = Ben_AlgaeC / Ben_C2CHL; //g Chl / m2 //if (par2bottom > 0.0){ if (itemID == 175){ printf("itemID %d month %f day %f par2bottom %f Ed %f Ben_GPP %f Ben_Ra %f Ben_NPP %f Ben_Mortality %f Ben_AlgaeC %f Ben_AlgaeCHL %f \n", itemID, month, day, par2bottom, Ed, Ben_GPP, Ben_Ra, Ben_NPP, Ben_MORTALITY, Ben_AlgaeC, Ben_AlgaeCHL ); } Ben_AlgaeC_REACH = Ben_AlgaeC * channelWidth * MFModelGetLength(itemID); Ben_GPP_REACH = Ben_GPP * channelWidth * MFModelGetLength(itemID); Ben_Ra_REACH = Ben_Ra * channelWidth * MFModelGetLength(itemID); Ben_NPP_REACH = Ben_NPP * channelWidth * MFModelGetLength(itemID); Ben_Mortality_REACH = Ben_MORTALITY * channelWidth * MFModelGetLength(itemID); MFVarSetFloat(_MDBenthicAlgaeCHLID, itemID, Ben_AlgaeCHL); MFVarSetFloat(_MDBenthicAlgaeCID, itemID, Ben_AlgaeC); MFVarSetFloat(_MDBenthicGPPID, itemID, Ben_GPP); MFVarSetFloat(_MDBenthicRaID, itemID, Ben_Ra); MFVarSetFloat(_MDBenthicNPPID, itemID, Ben_NPP); MFVarSetFloat(_MDBenthicMortalityID, itemID, Ben_MORTALITY); MFVarSetFloat(_MDBenthicAlgaeC_REACHID, itemID, Ben_AlgaeC_REACH); MFVarSetFloat(_MDBenthicGPP_REACHID, itemID, Ben_GPP_REACH); MFVarSetFloat(_MDBenthicRa_REACHID, itemID, Ben_Ra_REACH); MFVarSetFloat(_MDBenthicNPP_REACHID, itemID, Ben_NPP_REACH); MFVarSetFloat(_MDBenthicMortality_REACHID, itemID, Ben_Mortality_REACH); }