def run_inv(config_file): """Run the inversion part of the simulation""" # Read run config file params = ConfigParser(config_file) inout.setup_logging(params) inout.log_preamble("inverse", params) # Load the static model data (geometry, smb, etc) input_data = inout.InputData(params) # Get the model mesh mesh = fice_mesh.get_mesh(params) mdl = model.model(mesh, input_data, params) # pts_lengthscale = params.obs.pts_len mdl.gen_alpha() # Add random noise to Beta field iff we're inverting for it mdl.bglen_from_data() mdl.init_beta(mdl.bglen_to_beta(mdl.bglen), pert=False) # Next line will output the initial guess for alpha fed into the inversion # File(os.path.join(outdir,'alpha_initguess.pvd')) << mdl.alpha ##################### # Run the Inversion # ##################### slvr = solver.ssa_solver(mdl) slvr.inversion() ############################################## # Write out variables in outdir and # # diagnostics folder # ############################################# phase_name = params.inversion.phase_name phase_suffix = params.inversion.phase_suffix outdir = Path(params.io.output_dir) / phase_name / phase_suffix diag_dir = Path(params.io.diagnostics_dir) # Required for next phase (HDF5): invout_file = params.io.inversion_file phase_suffix = params.inversion.phase_suffix if len(phase_suffix) > 0: invout_file = params.io.run_name + phase_suffix + '_invout.h5' invout = HDF5File(mesh.mpi_comm(), str(outdir / invout_file), 'w') invout.parameters.add("gamma_alpha", slvr.gamma_alpha) invout.parameters.add("delta_alpha", slvr.delta_alpha) invout.parameters.add("gamma_beta", slvr.gamma_beta) invout.parameters.add("delta_beta", slvr.delta_beta) invout.parameters.add("delta_beta_gnd", slvr.delta_beta_gnd) invout.parameters.add("timestamp", str(datetime.datetime.now())) invout.write(mdl.alpha, 'alpha') invout.write(mdl.beta, 'beta') # For visualisation (XML & VTK): if params.io.write_diagnostics: inout.write_variable(slvr.U, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.beta, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) mdl.beta_bgd.rename("beta_bgd", "") inout.write_variable(mdl.beta_bgd, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.bed, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) H = project(mdl.H, mdl.M) H.rename("thick", "") inout.write_variable(H, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) fl_ex = project(slvr.float_conditional(H), mdl.M) inout.write_variable(fl_ex, params, name='float', outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.mask_vel_M, params, name="mask_vel", outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.u_obs_Q, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.v_obs_Q, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.u_std_Q, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.v_std_Q, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) U_obs = project((mdl.v_obs_Q**2 + mdl.u_obs_Q**2)**(1.0 / 2.0), mdl.M) U_obs.rename("uv_obs", "") inout.write_variable(U_obs, params, name="uv_obs", outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.alpha, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) Bglen = project(slvr.beta_to_bglen(slvr.beta), mdl.M) Bglen.rename("Bglen", "") inout.write_variable(Bglen, params, outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(slvr.bmelt, params, name="bmelt", outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(slvr.smb, params, name="smb", outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) inout.write_variable(mdl.surf, params, name="surf", outdir=diag_dir, phase_name=phase_name, phase_suffix=phase_suffix) return mdl
def run_forward(config_file): # Read run config file params = ConfigParser(config_file) log = inout.setup_logging(params) inout.log_preamble("forward", params) outdir = params.io.output_dir diag_dir = params.io.diagnostics_dir phase_name = params.time.phase_name # Load the static model data (geometry, smb, etc) input_data = inout.InputData(params) # Get model mesh mesh = fice_mesh.get_mesh(params) # Define the model mdl = model.model(mesh, input_data, params) mdl.alpha_from_inversion() mdl.beta_from_inversion() # Solve slvr = solver.ssa_solver(mdl, mixed_space=params.inversion.dual) slvr.save_ts_zero() cntrl = slvr.get_control() qoi_func = slvr.get_qoi_func() # TODO here - cntrl now returns a list - so compute_gradient returns a list of tuples # Run the forward model Q = slvr.timestep(adjoint_flag=1, qoi_func=qoi_func) # Run the adjoint model, computing gradient of Qoi w.r.t cntrl dQ_ts = compute_gradient(Q, cntrl) # Isaac 27 # Output model variables in ParaView+Fenics friendly format # Output QOI & DQOI (needed for next steps) inout.write_qval(slvr.Qval_ts, params) inout.write_dqval(dQ_ts, [var.name() for var in cntrl], params) # Output final velocity, surface & thickness (visualisation) inout.write_variable(slvr.U, params, name="U_fwd", outdir=diag_dir, phase_name=phase_name, phase_suffix=params.time.phase_suffix) inout.write_variable(mdl.surf, params, name="surf_fwd", outdir=diag_dir, phase_name=phase_name, phase_suffix=params.time.phase_suffix) H = project(mdl.H, mdl.Q) inout.write_variable(H, params, name="H_fwd", outdir=diag_dir, phase_name=phase_name, phase_suffix=params.time.phase_suffix) return mdl
def main(dd, infile, outfile, noise_sdev, L, seed=0, ls=None): """ Take velocity data from run_momsolve.py and add gaussian noise. This is used for synthetic cases (ismipc/ice_stream) where there is no real velocity observations. dd - (string/path) directory where input is found & where output is written infile - (string/path) input file name (.h5) outfile - (string/path) output file name (.h5) noise_sdev - (float) standard deviation of added noise L - (float) Length of domain seed - (int) Random seed ls - (float [optional]) Spacing between points in a new grid Expects an HDF5 file (containing both mesh & velocity function) as input. In the case of a periodic boundary condition with NxN elements, this produces NxN velocity observations (NOT N+1 x N+1) because otherwise boundary nodes would be doubly constrained. If 'ls' is not provided, data will remain on the input grid. """ assert Path(infile).suffix == ".h5" assert Path(outfile).suffix == ".h5" assert noise_sdev > 0.0 infile = HDF5File(MPI.comm_world, str(Path(dd) / infile), 'r') # Get mesh from file mesh = Mesh() infile.read(mesh, 'mesh', False) periodic_bc = bool(infile.attributes('mesh')['periodic']) if periodic_bc: assert L > 0.0 V = VectorFunctionSpace(mesh, 'Lagrange', 1, dim=2, constrained_domain=model.PeriodicBoundary(L)) else: V = VectorFunctionSpace(mesh, 'Lagrange', 1, dim=2) # Read the velocity U = Function(V) infile.read(U, 'U') infile.close() if ls is not None: # Get the mesh coordinates (only to set bounds) mc = mesh.coordinates() xmin = mc[:, 0].min() xmax = mc[:, 0].max() ymin = mc[:, 1].min() ymax = mc[:, 1].max() # Generate ls-spaced points xc = np.arange(xmin + ls / 2.0, xmax, ls) yc = np.arange(ymin + ls / 2.0, ymax, ls) # Pretty hacky - turn these into a rectangular mesh # because it makes periodic interpolation easier pts_mesh = RectangleMesh(Point(xc[0], yc[0]), Point(xc[-1], yc[-1]), len(xc) - 1, len(yc) - 1) pts_space = VectorFunctionSpace(pts_mesh, 'Lagrange', degree=1, dim=2) U_pts = project(U, pts_space) else: U_pts = U # How many points? ndofs = int(U_pts.vector()[:].shape[0] / 2) # Generate the random noise np.random.seed(seed) u_noise = np.random.normal(scale=noise_sdev, size=ndofs) v_noise = np.random.normal(scale=noise_sdev, size=ndofs) # Grab the two components of the velocity vector, and add noise U_vec = U_pts.vector()[:] U_vec[0::2] += u_noise U_vec[1::2] += v_noise u_array = U_vec[0::2] v_array = U_vec[1::2] # [::2] because tabulate_dof_coordinates produces two copies # (because 2 dofs per node...) x, y = np.hsplit(U_pts.function_space().tabulate_dof_coordinates()[::2], 2) # Produce output as raw points & vel output = h5py.File(Path(dd) / outfile, 'w') output.create_dataset("x", x.shape, dtype=x.dtype, data=x) output.create_dataset("y", x.shape, dtype=x.dtype, data=y) output.create_dataset("u_obs", x.shape, dtype=np.float64, data=u_array) output.create_dataset("v_obs", x.shape, dtype=np.float64, data=v_array) noise_arr = np.zeros_like(x) noise_arr[:] = noise_sdev output.create_dataset("u_std", x.shape, dtype=np.float64, data=noise_arr) output.create_dataset("v_std", x.shape, dtype=np.float64, data=noise_arr) mask_arr = np.ones_like(x) output.create_dataset("mask_vel", x.shape, dtype=np.float64, data=mask_arr)
Qp = fice_mesh.get_periodic_space(params, mesh, dim=1) V = fice_mesh.get_periodic_space(params, mesh, dim=2) U_file = str(next(results_dir.glob("*U.xml"))) alpha_file = str(next(results_dir.glob("*alpha.xml"))) uv_obs_file = str(next(results_dir.glob("*uv_obs.xml"))) alpha_sigma_file = str(next(results_dir.glob("*alpha_sigma.xml"))) U = Function(V, U_file) alpha = Function(Qp, alpha_file) uv_obs = Function(M, uv_obs_file) alpha_sigma = Function(Qp, alpha_sigma_file) # B2 = Function(M, os.path.join(dd,'B2.xml')) u, v = U.split() uv = project(sqrt(u * u + v * v), Q) uv_diff = project(uv_obs - uv, Q) B2 = project(alpha * alpha, M) x = mesh.coordinates()[:, 0] y = mesh.coordinates()[:, 1] t = mesh.cells() fig = plt.figure(figsize=(10, 5)) ax = fig.add_subplot(231) ax.set_aspect('equal') v = B2.compute_vertex_values(mesh) minv = np.min(v) maxv = np.max(v) levels = np.linspace(minv, maxv, numlev)
def main(config_file): print( "===WARNING=== - this code has not been fully adapted to new config format" ) print("Consult TODOs in run_balancemeltrates.py") init_yr = 5 #TODO - where in the config? #Read run config file params = ConfigParser(config_file) log = inout.setup_logging(params) inout.log_preamble("balance meltrates", params) dd = params.io.input_dir outdir = params.io.output_dir run_length = params.time.run_length n_steps = params.time.total_steps assert init_yr < run_length # #Load Data # param = pickle.load( open( os.path.join(dd,'param.p'), "rb" ) ) # param['outdir'] = outdir # param['sliding_law'] = sl # param['picard_params'] = {"nonlinear_solver":"newton", # "newton_solver":{"linear_solver":"umfpack", # "maximum_iterations":25, # "absolute_tolerance":1.0e-3, # "relative_tolerance":5.0e-2, # "convergence_criterion":"incremental", # "error_on_nonconvergence":False, # "lu_solver":{"same_nonzero_pattern":False, "symmetric":False, "reuse_factorization":False}}} #Load Data mesh = Mesh(os.path.join(outdir, 'mesh.xml')) M = FunctionSpace(mesh, 'DG', 0) #TODO - what's the logic here?: Q = FunctionSpace( mesh, 'Lagrange', 1) # if os.path.isfile(os.path.join(dd,'param.p')) else M mask = Function(M, os.path.join(outdir, 'mask.xml')) if os.path.isfile(os.path.join(outdir, 'data_mesh.xml')): data_mesh = Mesh(os.path.join(outdir, 'data_mesh.xml')) Mdata = FunctionSpace(data_mesh, 'DG', 0) data_mask = Function(Mdata, os.path.join(outdir, 'data_mask.xml')) else: data_mesh = mesh data_mask = mask if not params.mesh.periodic_bc: Qp = Q V = VectorFunctionSpace(mesh, 'Lagrange', 1, dim=2) else: Qp = fice_mesh.get_periodic_space(params, mesh, dim=1) V = fice_mesh.get_periodic_space(params, mesh, dim=2) #Load fields U = Function(V, os.path.join(outdir, 'U.xml')) alpha = Function(Qp, os.path.join(outdir, 'alpha.xml')) beta = Function(Qp, os.path.join(outdir, 'beta.xml')) bed = Function(Q, os.path.join(outdir, 'bed.xml')) smb = Function(M, os.path.join(outdir, 'smb.xml')) thick = Function(M, os.path.join(outdir, 'thick.xml')) mask_vel = Function(M, os.path.join(outdir, 'mask_vel.xml')) u_obs = Function(M, os.path.join(outdir, 'u_obs.xml')) v_obs = Function(M, os.path.join(outdir, 'v_obs.xml')) u_std = Function(M, os.path.join(outdir, 'u_std.xml')) v_std = Function(M, os.path.join(outdir, 'v_std.xml')) uv_obs = Function(M, os.path.join(outdir, 'uv_obs.xml')) mdl = model.model(mesh, data_mask, params, init_fields=False) # TODO initialization mdl.init_bed(bed) mdl.init_thick(thick) mdl.gen_surf() mdl.init_mask(mask) mdl.init_vel_obs(u_obs, v_obs, mask_vel, u_std, v_std) mdl.init_lat_dirichletbc() mdl.init_bmelt(Constant(0.0)) mdl.init_alpha(alpha) mdl.init_beta(beta, False) mdl.init_smb(smb) mdl.label_domain() #Solve slvr = solver.ssa_solver(mdl) slvr.save_ts_zero() slvr.timestep(save=1, adjoint_flag=0) #Balance melt rates #Load time series of ice thicknesses hdf = HDF5File(slvr.mesh.mpi_comm(), os.path.join(outdir, 'H_ts.h5'), "r") attr = hdf.attributes("H") nsteps = attr['count'] #model time step dt = params.time.dt #Model iterations to difference between iter_s = np.ceil(init_yr / dt) #Iteration closest to 5yr iter_f = nsteps - 1 #Final iteration dT = dt * (iter_f - iter_s) #Time diff in years between iterations #Read iteration data HS = Function(slvr.M) HF = Function(slvr.M) hdf.read(HS, "H/vector_{0}".format(int(iter_s))) hdf.read(HF, "H/vector_{0}".format(int(iter_f))) #Mask out grounded region rhow = params.constants.rhow rhoi = params.constants.rhoi H_s = -rhow / rhoi * bed fl_ex = conditional(slvr.H_init <= H_s, Constant(1.0), Constant(0.0)) #Calculate bmelt bmelt = project(ufl.Max(fl_ex * (HF - HS) / dT, Constant(0.0)), slvr.M) #Output model variables in ParaView+Fenics friendly format with open(os.path.join(outdir, 'bmeltrate_param.p'), "wb") as bmeltfile: pickle.dump(mdl.param, bmeltfile) # File(os.path.join(outdir,'mesh.xml')) << mdl.mesh vtkfile = File(os.path.join(outdir, 'bmelt.pvd')) xmlfile = File(os.path.join(outdir, 'bmelt.xml')) vtkfile << bmelt xmlfile << bmelt return mdl