|
| 1 | +"""Generate an ensemble of drawdowns with ogs5py and GSTools.""" |
| 2 | +import os |
| 3 | +import numpy as np |
| 4 | +from ogs5py import OGS, specialrange, generate_time, by_id |
| 5 | +from gstools import SRF, Gaussian, transform as tf |
| 6 | +from mpi4py import MPI |
| 7 | + |
| 8 | +# rank is the actual core-number, size is total number of cores |
| 9 | +rank = MPI.COMM_WORLD.Get_rank() |
| 10 | +size = MPI.COMM_WORLD.Get_size() |
| 11 | + |
| 12 | +# size of the ensembles |
| 13 | +ens_size = 1000 |
| 14 | +# pumping rate |
| 15 | +prate = -1e-4 |
| 16 | +# parameter lists to generate the para_set (single one) |
| 17 | +TG = [1e-4] # mu = log(TG) |
| 18 | +var = [2.25] |
| 19 | +len_scale = [10] |
| 20 | +S = [1e-4] |
| 21 | +para_set = np.array( |
| 22 | + [[t, v, l, s] for t in TG for v in var for l in len_scale for s in S] |
| 23 | +) |
| 24 | + |
| 25 | +# ogs configuration |
| 26 | +task_root = os.path.abspath(os.path.join("..", "results", "ext_theis2d")) |
| 27 | +pcs_type_flow = "GROUNDWATER_FLOW" |
| 28 | +var_name_flow = "HEAD" |
| 29 | +model = OGS(task_root=task_root, task_id="model") |
| 30 | + |
| 31 | +# spatio-temporal configuration |
| 32 | +# define the time stepping: 2 h with 32 steps and increasing stepsize |
| 33 | +time = specialrange(0, 7200, 32, typ="cub") |
| 34 | +# radial discretization: 1000 m with 100 steps and increasing stepsize |
| 35 | +rad = specialrange(0, 1000, 100, typ="cub") |
| 36 | +# 64 angles for discretization |
| 37 | +angles = 64 |
| 38 | + |
| 39 | +# generate mesh and gli |
| 40 | +model.msh.generate("radial", dim=2, angles=angles, rad=rad) |
| 41 | +model.gli.generate("radial", dim=2, angles=angles, rad_out=rad[-1]) |
| 42 | +# add the pumping well |
| 43 | +model.gli.add_points(points=[0.0, 0.0, 0.0], names="pwell") |
| 44 | + |
| 45 | +# --------------generate different ogs input classes------------------------- # |
| 46 | + |
| 47 | +model.pcs.add_block( # set the process type |
| 48 | + PCS_TYPE=pcs_type_flow, NUM_TYPE="NEW" |
| 49 | +) |
| 50 | +model.mpd.add(name="conductivity") |
| 51 | +model.mpd.add_block( # edit recent mpd file |
| 52 | + MSH_TYPE=pcs_type_flow, MMP_TYPE="PERMEABILITY", DIS_TYPE="ELEMENT", |
| 53 | +) |
| 54 | +model.mmp.add_block( # permeability, storage and porosity |
| 55 | + GEOMETRY_DIMENSION=2, |
| 56 | + STORAGE=[1, 1.0e-04], |
| 57 | + PERMEABILITY_TENSOR=["ISOTROPIC", 1.0], |
| 58 | + PERMEABILITY_DISTRIBUTION=model.mpd.file_name, |
| 59 | +) |
| 60 | +model.bc.add_block( # set boundary condition |
| 61 | + PCS_TYPE=pcs_type_flow, |
| 62 | + PRIMARY_VARIABLE=var_name_flow, |
| 63 | + GEO_TYPE=["POLYLINE", "boundary"], |
| 64 | + DIS_TYPE=["CONSTANT", 0.0], |
| 65 | +) |
| 66 | +model.ic.add_block( # set the initial condition |
| 67 | + PCS_TYPE=pcs_type_flow, |
| 68 | + PRIMARY_VARIABLE=var_name_flow, |
| 69 | + GEO_TYPE="DOMAIN", |
| 70 | + DIS_TYPE=["CONSTANT", 0.0], |
| 71 | +) |
| 72 | +model.st.add_block( # set pumping condition at the pumpingwell |
| 73 | + PCS_TYPE=pcs_type_flow, |
| 74 | + PRIMARY_VARIABLE=var_name_flow, |
| 75 | + GEO_TYPE=["POINT", "pwell"], |
| 76 | + DIS_TYPE=["CONSTANT_NEUMANN", prate], |
| 77 | +) |
| 78 | +model.num.add_block( # set the parameters for the solver |
| 79 | + PCS_TYPE=pcs_type_flow, LINEAR_SOLVER=[2, 5, 1.0e-14, 1000, 1.0, 100, 4], |
| 80 | +) |
| 81 | +model.tim.add_block( # set the TIMESTEPS |
| 82 | + PCS_TYPE=pcs_type_flow, **generate_time(time) |
| 83 | +) |
| 84 | +model.out.add_block( # set the outputformat for the whole domain |
| 85 | + PCS_TYPE=pcs_type_flow, |
| 86 | + NOD_VALUES=var_name_flow, |
| 87 | + GEO_TYPE="DOMAIN", |
| 88 | + DAT_TYPE="PVD", |
| 89 | + TIM_TYPE=["STEPS", 1], |
| 90 | +) |
| 91 | + |
| 92 | +# --------------run OGS simulation------------------------------------------- # |
| 93 | + |
| 94 | +print("write files") |
| 95 | +model.write_input() |
| 96 | +np.savetxt(os.path.join(model.task_root, "time.txt"), time) |
| 97 | +np.savetxt(os.path.join(model.task_root, "rad.txt"), rad) |
| 98 | +np.savetxt(os.path.join(model.task_root, "angles.txt"), [angles]) |
| 99 | + |
| 100 | +for para_no, para in enumerate(para_set): |
| 101 | + print("PARA_SET {:04}".format(para_no)) |
| 102 | + model.mmp.update_block(STORAGE=[1, para[3]]) |
| 103 | + cov_model = Gaussian(dim=2, var=para[1], len_scale=para[2]) |
| 104 | + srf = SRF(cov_model, mean=np.log(para[0]), upscaling="coarse_graining") |
| 105 | + # save the current parameter set |
| 106 | + np.savetxt( |
| 107 | + os.path.join(model.task_root, "para{:04}".format(para_no), "para.txt"), |
| 108 | + para, |
| 109 | + ) |
| 110 | + # run the ensemble |
| 111 | + # for i in [196, 735]: |
| 112 | + for i in range(ens_size): |
| 113 | + # parallel running the right jobs on each core |
| 114 | + if (para_no * ens_size + i) % size != rank: |
| 115 | + continue |
| 116 | + # generate new transmissivity field |
| 117 | + srf.mesh(model.msh, seed=i, point_volumes=model.msh.volumes_flat) |
| 118 | + # transfrom to log-normal field |
| 119 | + tf.normal_to_lognormal(srf) |
| 120 | + # add the transmissivity to the ogs project |
| 121 | + model.mpd.update_block(DATA=by_id(srf.field)) |
| 122 | + # write the new mpd file |
| 123 | + model.mpd.write_file() |
| 124 | + # set the new output-directory |
| 125 | + model.output_dir = os.path.join( |
| 126 | + model.task_root, "para{:04}".format(para_no), "seed{:04}".format(i) |
| 127 | + ) |
| 128 | + print(" run model {:04}".format(i), end=" ") |
| 129 | + success = model.run_model(print_log=False) |
| 130 | + print(" ...success") if success else print(" ...error!") |
| 131 | + # export the generated transmissivity field as vtk |
| 132 | + model.msh.export_mesh( |
| 133 | + os.path.join(model.output_dir, "field.vtu"), |
| 134 | + file_format="vtk", |
| 135 | + cell_data_by_id={"transmissivity": srf.field}, |
| 136 | + ) |
0 commit comments