Coverage for C:\src\imod-python\imod\mf6\drn.py: 100%

28 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-08 13:27 +0200

1from typing import Optional, Tuple 

2 

3import numpy as np 

4 

5from imod.logging import init_log_decorator 

6from imod.mf6.boundary_condition import BoundaryCondition 

7from imod.mf6.interfaces.iregridpackage import IRegridPackage 

8from imod.mf6.utilities.regrid import RegridderType 

9from imod.mf6.validation import BOUNDARY_DIMS_SCHEMA, CONC_DIMS_SCHEMA 

10from imod.schemata import ( 

11 AllInsideNoDataSchema, 

12 AllNoDataSchema, 

13 AllValueSchema, 

14 CoordsSchema, 

15 DimsSchema, 

16 DTypeSchema, 

17 IdentityNoDataSchema, 

18 IndexesSchema, 

19 OtherCoordsSchema, 

20) 

21 

22 

23class Drainage(BoundaryCondition, IRegridPackage): 

24 """ 

25 The Drain package is used to simulate head-dependent flux boundaries. 

26 https://water.usgs.gov/ogw/modflow/mf6io.pdf#page=67 

27 

28 Parameters 

29 ---------- 

30 elevation: array of floats (xr.DataArray) 

31 elevation of the drain. (elev) 

32 conductance: array of floats (xr.DataArray) 

33 is the conductance of the drain. (cond) 

34 concentration: array of floats (xr.DataArray, optional) 

35 if this flow package is used in simulations also involving transport, then this array is used 

36 as the concentration for inflow over this boundary. 

37 concentration_boundary_type: ({"AUX", "AUXMIXED"}, optional) 

38 if this flow package is used in simulations also involving transport, then this keyword specifies 

39 how outflow over this boundary is computed. 

40 print_input: ({True, False}, optional) 

41 keyword to indicate that the list of drain information will be written 

42 to the listing file immediately after it is read. Default is False. 

43 print_flows: ({True, False}, optional) 

44 Indicates that the list of drain flow rates will be printed to the 

45 listing file for every stress period time step in which "BUDGET PRINT" 

46 is specified in Output Control. If there is no Output Control option and 

47 PRINT FLOWS is specified, then flow rates are printed for the last time 

48 step of each stress period. 

49 Default is False. 

50 save_flows: ({True, False}, optional) 

51 Indicates that drain flow terms will be written to the file specified 

52 with "BUDGET FILEOUT" in Output Control. Default is False. 

53 observations: [Not yet supported.] 

54 Default is None. 

55 validate: {True, False} 

56 Flag to indicate whether the package should be validated upon 

57 initialization. This raises a ValidationError if package input is 

58 provided in the wrong manner. Defaults to True. 

59 repeat_stress: Optional[xr.DataArray] of datetimes 

60 Used to repeat data for e.g. repeating stress periods such as 

61 seasonality without duplicating the values. The DataArray should have 

62 dimensions ``("repeat", "repeat_items")``. The ``repeat_items`` 

63 dimension should have size 2: the first value is the "key", the second 

64 value is the "value". For the "key" datetime, the data of the "value" 

65 datetime will be used. Can also be set with a dictionary using the 

66 ``set_repeat_stress`` method. 

67 """ 

68 

69 _pkg_id = "drn" 

70 

71 # has to be ordered as in the list 

72 _init_schemata = { 

73 "elevation": [ 

74 DTypeSchema(np.floating), 

75 IndexesSchema(), 

76 CoordsSchema(("layer",)), 

77 BOUNDARY_DIMS_SCHEMA, 

78 ], 

79 "conductance": [ 

80 DTypeSchema(np.floating), 

81 IndexesSchema(), 

82 CoordsSchema(("layer",)), 

83 BOUNDARY_DIMS_SCHEMA, 

84 ], 

85 "concentration": [ 

86 DTypeSchema(np.floating), 

87 IndexesSchema(), 

88 CoordsSchema( 

89 ( 

90 "species", 

91 "layer", 

92 ) 

93 ), 

94 CONC_DIMS_SCHEMA, 

95 ], 

96 "print_flows": [DTypeSchema(np.bool_), DimsSchema()], 

97 "save_flows": [DTypeSchema(np.bool_), DimsSchema()], 

98 } 

99 _write_schemata = { 

100 "elevation": [ 

101 OtherCoordsSchema("idomain"), 

102 AllNoDataSchema(), # Check for all nan, can occur while clipping 

103 AllInsideNoDataSchema(other="idomain", is_other_notnull=(">", 0)), 

104 ], 

105 "conductance": [IdentityNoDataSchema("elevation"), AllValueSchema(">", 0.0)], 

106 "concentration": [IdentityNoDataSchema("elevation"), AllValueSchema(">=", 0.0)], 

107 } 

108 

109 _period_data = ("elevation", "conductance") 

110 _keyword_map = {} 

111 _template = BoundaryCondition._initialize_template(_pkg_id) 

112 _auxiliary_data = {"concentration": "species"} 

113 

114 _regrid_method = { 

115 "elevation": (RegridderType.OVERLAP, "mean"), 

116 "conductance": (RegridderType.RELATIVEOVERLAP, "conductance"), 

117 "concentration": (RegridderType.OVERLAP, "mean"), 

118 } 

119 

120 @init_log_decorator() 

121 def __init__( 

122 self, 

123 elevation, 

124 conductance, 

125 concentration=None, 

126 concentration_boundary_type="aux", 

127 print_input=False, 

128 print_flows=False, 

129 save_flows=False, 

130 observations=None, 

131 validate: bool = True, 

132 repeat_stress=None, 

133 ): 

134 dict_dataset = { 

135 "elevation": elevation, 

136 "conductance": conductance, 

137 "concentration": concentration, 

138 "concentration_boundary_type": concentration_boundary_type, 

139 "print_input": print_input, 

140 "print_flows": print_flows, 

141 "save_flows": save_flows, 

142 "observations": observations, 

143 "repeat_stress": repeat_stress, 

144 } 

145 super().__init__(dict_dataset) 

146 

147 self._validate_init_schemata(validate) 

148 

149 def _validate(self, schemata, **kwargs): 

150 # Insert additional kwargs 

151 kwargs["elevation"] = self["elevation"] 

152 errors = super()._validate(schemata, **kwargs) 

153 

154 return errors 

155 

156 def get_regrid_methods(self) -> Optional[dict[str, Tuple[RegridderType, str]]]: 

157 return self._regrid_method