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

25 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-08 14:15 +0200

1from typing import Optional, Tuple 

2 

3import numpy as np 

4 

5from imod.logging import init_log_decorator 

6from imod.mf6.interfaces.iregridpackage import IRegridPackage 

7from imod.mf6.package import Package 

8from imod.mf6.utilities.regrid import RegridderType 

9from imod.mf6.validation import PKG_DIMS_SCHEMA 

10from imod.schemata import ( 

11 AllValueSchema, 

12 DTypeSchema, 

13 IdentityNoDataSchema, 

14 IndexesSchema, 

15) 

16 

17 

18class MobileStorageTransfer(Package, IRegridPackage): 

19 """ 

20 Mobile Storage. 

21 

22 Parameters 

23 ---------- 

24 porosity: array of floats (xr.DataArray) 

25 volume of interconnected voids per volume of rock (percentage). 

26 decay : array of floats (xr.DataArray, optional) 

27 is the rate coefficient for first or zero-order decay for the aqueous phase of the mobile domain. 

28 A negative value indicates solute production. The dimensions of decay for first-order decay is one 

29 over time. The dimensions of decay for zero-order decay is mass per length cubed per time. decay will 

30 have no effect on simulation results unless either first- or zero-order decay is specified in the 

31 options block. 

32 decay_sorbed : array of floats (xr.DataArray, optional) 

33 is the rate coefficient for first or zero-order decay for the sorbed phase of the mobile domain. 

34 A negative value indicates solute production. The dimensions of decay_sorbed for first-order decay 

35 is one over time. The dimensions of decay_sorbed for zero-order decay is mass of solute per mass of 

36 aquifer per time. If decay_sorbed is not specified and both decay and sorption are active, then the 

37 program will terminate with an error. decay_sorbed will have no effect on simulation results unless 

38 the SORPTION keyword and either first- or zero-order decay are specified in the options block. 

39 bulk_density : array of floats (xr.DataArray, optional) 

40 is the bulk density of the aquifer in mass per length cubed. bulk_density is not required unless 

41 the SORPTION keyword is specified. 

42 distcoef : array of floats (xr.DataArray, optional) 

43 is the distribution coefficient for the equilibrium-controlled linear sorption isotherm in dimensions 

44 of length cubed per mass. distcoef is not required unless the SORPTION keyword is specified. 

45 sp2 : array of floats (xr.DataArray, optional) 

46 is the exponent for the Freundlich isotherm and the sorption capacity for the Langmuir isotherm. 

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

48 Indicates that recharge flow terms will be written to the file specified 

49 with "BUDGET FILEOUT" in Output Control. 

50 Default is False. 

51 zero_order_decay: bool, optional 

52 Requires decay to be specified 

53 first_order_decay: bool, optional 

54 Requires decay to be specified 

55 sorption: ({linear, freundlich, langmuir}, optional) 

56 Type of sorption, if any. 

57 validate: {True, False} 

58 Flag to indicate whether the package should be validated upon 

59 initialization. This raises a ValidationError if package input is 

60 provided in the wrong manner. Defaults to True. 

61 """ 

62 

63 _grid_data = { 

64 "porosity": np.float64, 

65 "decay": np.float64, 

66 "decay_sorbed": np.float64, 

67 "bulk_density": np.float64, 

68 "distcoef": np.float64, 

69 "sp2": np.float64, 

70 } 

71 

72 _pkg_id = "mst" 

73 _template = Package._initialize_template(_pkg_id) 

74 _keyword_map = {} 

75 _init_schemata = { 

76 "porosity": [DTypeSchema(np.floating), IndexesSchema(), PKG_DIMS_SCHEMA], 

77 "decay": [DTypeSchema(np.floating), IndexesSchema(), PKG_DIMS_SCHEMA], 

78 "decay_sorbed": [DTypeSchema(np.floating), IndexesSchema(), PKG_DIMS_SCHEMA], 

79 "bulk_density": [DTypeSchema(np.floating), IndexesSchema(), PKG_DIMS_SCHEMA], 

80 "distcoef": [DTypeSchema(np.floating), IndexesSchema(), PKG_DIMS_SCHEMA], 

81 "sp2": [DTypeSchema(np.floating), IndexesSchema(), PKG_DIMS_SCHEMA], 

82 "zero_order_decay": [DTypeSchema(np.bool_)], 

83 "first_order_decay": [DTypeSchema(np.bool_)], 

84 } 

85 

86 _write_schemata = { 

87 "porosity": ( 

88 AllValueSchema(">=", 0.0), 

89 AllValueSchema("<", 1.0), 

90 IdentityNoDataSchema(other="idomain", is_other_notnull=(">", 0)), 

91 ), 

92 "decay": (IdentityNoDataSchema(other="idomain", is_other_notnull=(">", 0)),), 

93 "decay_sorbed": ( 

94 IdentityNoDataSchema(other="idomain", is_other_notnull=(">", 0)), 

95 ), 

96 "bulk_density": ( 

97 IdentityNoDataSchema(other="idomain", is_other_notnull=(">", 0)), 

98 ), 

99 "distcoef": (IdentityNoDataSchema(other="idomain", is_other_notnull=(">", 0)),), 

100 "sp2": (IdentityNoDataSchema(other="idomain", is_other_notnull=(">", 0)),), 

101 } 

102 

103 _regrid_method = { 

104 "porosity": (RegridderType.OVERLAP, "mean"), 

105 "decay": (RegridderType.OVERLAP, "mean"), 

106 "decay_sorbed": ( 

107 RegridderType.OVERLAP, 

108 "mean", 

109 ), 

110 "bulk_density": (RegridderType.OVERLAP, "mean"), 

111 "distcoef": (RegridderType.OVERLAP, "mean"), 

112 "sp2": (RegridderType.OVERLAP, "mean"), 

113 } 

114 

115 @init_log_decorator() 

116 def __init__( 

117 self, 

118 porosity, 

119 decay=None, 

120 decay_sorbed=None, 

121 bulk_density=None, 

122 distcoef=None, 

123 sp2=None, 

124 save_flows=False, 

125 zero_order_decay: bool = False, 

126 first_order_decay: bool = False, 

127 sorption=None, 

128 validate: bool = True, 

129 ): 

130 if zero_order_decay and first_order_decay: 

131 raise ValueError( 

132 "zero_order_decay and first_order_decay may not both be True" 

133 ) 

134 dict_dataset = { 

135 "porosity": porosity, 

136 "decay": decay, 

137 "decay_sorbed": decay_sorbed, 

138 "bulk_density": bulk_density, 

139 "distcoef": distcoef, 

140 "sp2": sp2, 

141 "save_flows": save_flows, 

142 "sorption": sorption, 

143 "zero_order_decay": zero_order_decay, 

144 "first_order_decay": first_order_decay, 

145 } 

146 super().__init__(dict_dataset) 

147 self._validate_init_schemata(validate) 

148 

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

150 return self._regrid_method