update groundwater head with Darcy law and mass conservation in two dimensions, with a macrocopic cellular automata approach
+-----+
| N |
+-----+-----+-----+
| W | C | E |
+-----+-----+-----+
| S |
+-----+
References: Ravazzani, G., Rametta, D., & Mancini, M.. (2011). Macroscopic cellular automata for groundwater modelling: a first approach. Environmental modelling & software, 26(5), 634–643.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(DateTime), | intent(in) | :: | time | |||
type(grid_real), | intent(in) | :: | hillslopeFlux |
flux from hillslope (m3/s) |
||
type(grid_real), | intent(in) | :: | percolation |
depp infiltration from soil balance (m/s) |
||
type(grid_real), | intent(in) | :: | capflux |
capillary flux from soil balance (m/s) |
Type | Visibility | Attributes | Name | Initial | |||
---|---|---|---|---|---|---|---|
real(kind=float), | public | :: | areaOfCell |
cell area (m2) |
|||
real(kind=float), | public | :: | fluxEC |
flux East-Centre (m3/s) |
|||
real(kind=float), | public | :: | fluxNC |
flux North-Centre (m3/s) |
|||
real(kind=float), | public | :: | fluxNESW |
total flux from the 4 directions (m3/s) |
|||
real(kind=float), | public | :: | fluxSC |
flux South-Centre (m3/s) |
|||
real(kind=float), | public | :: | fluxWC |
flux West-Centre (m3/s) |
|||
real(kind=float), | public | :: | gToR |
groundwater to river discharge (m3/s) |
|||
integer(kind=short), | public | :: | i | ||||
integer(kind=short), | public | :: | j | ||||
integer(kind=short), | public | :: | k | ||||
real(kind=float), | public | :: | rToG |
river to groundwater discharge (m3/s) |
|||
real(kind=float), | public | :: | rechargeQ |
vertical recharge (m3/s) |
|||
real(kind=float), | public | :: | transEC |
mean transmissivity East-Centre (m2/s) |
|||
real(kind=float), | public | :: | transNC |
mean transmissivity North-Centre (m2/s) |
|||
real(kind=float), | public | :: | transSC |
mean transmissivity South-Centre (m2/s) |
|||
real(kind=float), | public | :: | transWC |
mean transmissivity West-Centre (m2/s) |
SUBROUTINE GroundwaterUpdate & ! ( time, hillslopeFlux, percolation, capflux ) IMPLICIT NONE !Arguments with intent(in): TYPE (DateTime), INTENT(IN) :: time TYPE (grid_real), INTENT(IN) :: hillslopeFlux !!flux from hillslope (m3/s) TYPE (grid_real), INTENT(IN) :: percolation !! depp infiltration from soil balance (m/s) TYPE (grid_real), INTENT(IN) :: capflux !! capillary flux from soil balance (m/s) !local declarations: INTEGER (KIND = short) :: i, j, k REAL (KIND = float) :: rechargeQ !!vertical recharge (m3/s) REAL (KIND = float) :: transNC !!mean transmissivity North-Centre (m2/s) REAL (KIND = float) :: transEC !!mean transmissivity East-Centre (m2/s) REAL (KIND = float) :: transSC !!mean transmissivity South-Centre (m2/s) REAL (KIND = float) :: transWC !!mean transmissivity West-Centre (m2/s) REAL (KIND = float) :: fluxNC !!flux North-Centre (m3/s) REAL (KIND = float) :: fluxEC !!flux East-Centre (m3/s) REAL (KIND = float) :: fluxSC !!flux South-Centre (m3/s) REAL (KIND = float) :: fluxWC !!flux West-Centre (m3/s) REAL (KIND = float) :: fluxNESW !! total flux from the 4 directions (m3/s) REAL (KIND = float) :: areaOfCell !! cell area (m2) REAL (KIND = float) :: rToG !!river to groundwater discharge (m3/s) REAL (KIND = float) :: gToR !!groundwater to river discharge (m3/s) !-------------------------------------end of declarations---------------------- !reset counter variables volumeNeumann = 0. volumeDirichlet = 0. volumeRecharge = 0. volumeChange = 0. volumeResidual = 0. !update boundary condition CALL GroundwaterParameterUpdate (time) !save head1 into head0 DO k = 1, basin % nAquifers basin % aquifer (k) % head0 = basin % aquifer (k) % head1 END DO !update flux from hillslope of first (surface) aquifer DO i = 1, basin % aquifer (1) % domainBC % idim DO j = 1, basin % aquifer (1) % domainBC % jdim IF ( basin % aquifer (1) % domainBC % mat (i,j) == & BC_NEUMANN ) THEN basin % aquifer (1) % valueBC % mat (i,j) = & hillslopeFlux % mat (i,j) END IF END DO END DO !update aquifers head DO k = 1, basin % nAquifers !compute local transmissivity DO i = 1, basin % aquifer (k) % domainBC % idim DO j = 1, basin % aquifer (k) % domainBC % jdim IF ( basin % aquifer (k) % domainBC % mat(i,j) /= & basin % aquifer (k) % domainBC % nodata ) THEN !transmissivity: for confined aquifer = ks * aquifer depth transmissivity % mat (i,j) = MIN ( & basin % aquifer (k) % Ks % mat (i,j) * & ( basin % aquifer (k) % head0 % mat (i,j) - & basin % aquifer (k) % bottom % mat (i,j) ) , & basin % aquifer (k) % Ks % mat (i,j) * & ( basin % aquifer (k) % top % mat (i,j) - & basin % aquifer (k) % bottom % mat (i,j) ) & ) IF ( transmissivity % mat (i,j) <= 0. ) THEN transmissivity % mat (i,j) = 0.01 END IF END IF END DO END DO !update head1 DO i = 1, basin % aquifer (k) % domainBC % idim DO j = 1, basin % aquifer (k) % domainBC % jdim IF ( basin % aquifer (k) % domainBC % mat(i,j) == & ACTIVE_CELL ) THEN !harmonic mean transmissivity transNC = 2.0 * transmissivity % mat(i-1,j) * & transmissivity % mat(i,j) / & ( transmissivity %mat(i-1,j) + & transmissivity %mat(i,j) ) transSC = 2.0 * transmissivity % mat(i+1,j) * & transmissivity % mat(i,j) / & ( transmissivity % mat(i+1,j) + & transmissivity % mat(i,j) ) transEC = 2.0 * transmissivity % mat(i,j+1) * & transmissivity % mat(i,j) / & ( transmissivity % mat(i,j+1) + & transmissivity % mat(i,j) ) transWC = 2.0 * transmissivity % mat(i,j-1) * & transmissivity % mat(i,j) / & ( transmissivity % mat(i,j-1) + & transmissivity % mat(i,j) ) !flux from North IF ( basin % aquifer (k) % domainBC % mat(i-1,j) == & BC_NEUMANN ) THEN fluxNC = basin % aquifer (k) % valueBC % mat(i-1,j) volumeNeumann = volumeNeumann + fluxNC * dtGroundwater ELSE fluxNC = transNC * & ( basin % aquifer (k) % head0 % mat (i-1,j) - & basin % aquifer (k) % head0 % mat (i,j) ) IF ( basin % aquifer (k) % domainBC % mat(i-1,j) == & BC_DIRICHLET ) THEN volumeDirichlet = volumeDirichlet + & fluxNC * dtGroundwater END IF END IF !flux from East IF ( basin % aquifer (k) % domainBC % mat(i,j+1) == & BC_NEUMANN ) THEN fluxEC = basin % aquifer (k) % valueBC % mat(i,j+1) volumeNeumann = volumeNeumann + fluxEC * dtGroundwater ELSE fluxEC = transEC * & ( basin % aquifer (k) % head0 % mat (i,j+1) - & basin % aquifer (k) % head0 % mat (i,j) ) IF ( basin % aquifer (k) % domainBC % mat(i,j+1) == & BC_DIRICHLET ) THEN volumeDirichlet = volumeDirichlet + & fluxEC * dtGroundwater END IF END IF !flux from South IF ( basin % aquifer (k) % domainBC % mat(i+1,j) == & BC_NEUMANN ) THEN fluxSC = basin % aquifer (k) % valueBC % mat(i+1,j) volumeNeumann = volumeNeumann + fluxSC * dtGroundwater ELSE fluxSC = transSC * & ( basin % aquifer (k) % head0 % mat (i+1,j) - & basin % aquifer (k) % head0 % mat (i,j) ) IF ( basin % aquifer (k) % domainBC % mat(i+1,j) == & BC_DIRICHLET ) THEN volumeDirichlet = volumeDirichlet + & fluxSC * dtGroundwater END IF END IF !flux from West IF ( basin % aquifer (k) % domainBC % mat(i,j-1) == & BC_NEUMANN ) THEN fluxWC = basin % aquifer (k) % valueBC % mat(i,j-1) volumeNeumann = volumeNeumann + fluxWC * dtGroundwater ELSE fluxWC = transWC * & ( basin % aquifer (k) % head0 % mat (i,j-1) - & basin % aquifer (k) % head0 % mat (i,j) ) IF ( basin % aquifer (k) % domainBC % mat(i,j-1) == & BC_DIRICHLET ) THEN volumeDirichlet = volumeDirichlet + & fluxWC * dtGroundwater END IF END IF !total flux fluxNESW = fluxNC + fluxEC + fluxSC + fluxWC !area of the cell areaOfCell = CellArea (transmissivity, i, j) !vertical recharge IF ( ALLOCATED (percolation % mat ) ) THEN IF ( k == 1 .AND. percolation % mat (i,j) /= & percolation % nodata ) THEN rechargeQ = ( percolation % mat (i,j) - & capflux % mat (i,j) ) * areaOfCell volumeRecharge = volumeRecharge + & rechargeQ * dtGroundwater ELSE rechargeQ = 0. END IF ELSE rechargeQ = 0. END IF !upward flux from lower aquifer IF (k /= basin % nAquifers ) THEN fluxUpward % mat(i,j) = & basin % aquifer (k) % ksAquitard % mat(i,j) * & ( ( basin % aquifer (k+1) % head0 % mat(i,j) - & basin % aquifer (k) % head0 % mat(i,j) ) / & ( basin % aquifer (k) % bottom % mat(i,j) - & basin % aquifer (k+1) % top % mat(i,j) ) ) ELSE fluxUpward % mat (i,j) = 0.0 END IF !update head1 IF ( k == 1) THEN fluxDownward % mat (i,j) = 0. IF ( riverGroundwaterInteract ) THEN rToG = riverToGroundwater % mat (i,j) gToR = - groundwaterToRiver % mat (i,j) ELSE rToG = 0. gToR = 0. END IF ELSE rToG = 0. gToR = 0. END IF basin % aquifer (k) % head1 % mat(i,j) = & basin % aquifer (k) % head0 % mat(i,j) + & ( fluxNESW + rechargeQ + rToG + gToR ) * & dtGroundwater / areaOfCell / & basin % aquifer (k) % sy % mat(i,j) + & ( fluxUpward % mat(i,j) + fluxDownward % mat(i,j) ) * & dtGroundwater / basin % aquifer (k) % sy % mat(i,j) IF ( ISNAN ( basin % aquifer (k) % head1 % mat(i,j) ) ) THEN basin % aquifer (k) % head1 % mat(i,j) = & basin % aquifer (k) % head0 % mat(i,j) volumeChange = 0. ELSE !volume change volumeChange = volumeChange + & ( basin % aquifer (k) % head1 % mat(i,j) - & basin % aquifer (k) % head0 % mat(i,j) ) * & basin % aquifer (k) % sy % mat(i,j) * areaOfCell END IF !swap fluxUpward and fluxDownward fluxDownward % mat (i,j) = - fluxUpward % mat (i,j) !update vadose zone depth IF ( k == 1) THEN vadoseDepth % mat (i,j) = & basin % aquifer (k) % top % mat(i,j) - & basin % aquifer (k) % head1 % mat(i,j) END IF END IF END DO END DO END DO !compute balance error volumeResidual = volumeRecharge + volumeDirichlet + & volumeNeumann + volumeRiverToGroundwater - & volumeGroundwaterToRiver - volumeChange !write point data IF ( time == timePointExport ) THEN CALL GroundwaterPointExport ( time ) END IF RETURN END SUBROUTINE GroundwaterUpdate