## 3 Model Details  
### Groundwater Flow Model Parameter Optimization and Calibration  
A preliminary water flow model can be built using Visual Modflow or GMS to speed up the model building and reduce the number of codes. The resultant model can then be loaded using FloPy and coupled with Bayesian optimization methods for parameter optimization. In the preliminary establishment of a flow model, the initial conditions and boundary conditions need to be described in the model. In this study, the initial conditions were the initial water head distribution in the study area; the east-west boundary was described as the confining boundary, and the north-south boundary was described as the general head boundary. The study area was generalized as a heterogeneous isotropic aquifer (1950 m \(\times\) 2330 m) and was discretized into a grid consisting of 911 rectangles of 75.7 m \(\times\) 72.2 m (Figure 5). The hydraulic conductivity of the study area was divided into four zones: \(K_{1}\), \(K_{2}\), \(K_{3}\), and \(K_{4}\), based on the lithology and the measured groundwater flow field. The northern and southern boundaries were set as general head boundaries (GHBs).  
The core code lines and coding logic are shown below:  
_1) mod = flopy.modflow.Modflow.load(Vmod.nam)_  
_2) lpf = flopy.modflow.ModflowLpf(model = mod, hk = New_K)_  
_3) mod.write.input()_  
The first line of code was used to load the water flow model and requires the input of the model's NAM file. In some Python environments, relative paths need to be used in the NAM file to load the model correctly. The NAM file used in this model is in the same format as the input of MODFLOW.  
The second line of code overwrites the LPF file to change the hydraulic conductivity of the model while the optimization program is running. This method requires passing in the loaded model _mod_ and the new hydraulic conductivity matrix _New_K_. The hydraulic conductivity of the model can be overwritten if the groundwater flow model is built with the block-centered flow package (BCF), using the following code:  
_4) bcf = FloPy.modflow.ModflowBcf(model = mod, hy = New_K)_With the third line of code, FloPy recompiles the loaded model into MODFLOW format input files.  
Bayesian optimization using Python is now simply a matter of passing in the objective function and a priori information about the hydraulic conductivity in the code (see line 5). In this paper, Bayesian Optimization was used to build the optimization model. The initial sampling points for Bayesian optimization were set to 4, and the cycle was 1000 times. The hydraulic conductivity at the observation points within each zone determined the prior information of the hydraulic conductivity zone.  
_5) bs_pto = BayesianOptimization(_  
_obj_function,_  
_{'k1': (0.5, 2), 'k2': (1, 5), 'k3': (0.01, 1), 'k4': (5, 15)))_  
The objective function of Bayesian optimization can be a generalized objective function, which only considers the input and output of the function. Json can be used to save the parameters after each run The hydraulic conductivity is the input of the function, and the determinant coefficients (R2) of the observed and measured head values are the output of the function. The closer the R2 value is to 1, the more accurate the predicted hydraulic conductivity value. The programming logic of the target function is shown below:  
_6) def obj_function(K\({}_{1}\), K\({}_{2}\), K\({}_{3}\), K\({}_{4}\)): Load flow model_  
_Change the hydraulic conductivity_  
_Run the model_  
_Read the calculated head value_  
_Calculate R\({}^{2}\)_  
_return R\({}^{2}\)_  
By following the above steps, the hydraulic conductivity of the groundwater flow model can be easily optimized using the Bayesian optimization method. If you want to optimize other parameters, you only need to change the optimized parameters in the above model.  
Figure 5: Model grid diagram.