def taylor_test(function, gradient, m, delta_m=None, verbose=False, ratio_tol=1.90): """ Apply a 'Taylor test' to verify that the provided `gradient` function is a consistent approximation to the provided `function` at point `m`. This is done by choosing a random search direction and constructing a sequence of finite difference approximations. If the gradient is consistent then the associated Taylor remainder will decrease quadratically. :arg function: a scalar valued function with a single vector argument. :arg gradient: proposed gradient of above function, to be tested. :arg m: vector at which to perform the test. :arg delta_m: search direction in which to perform the test. :kwarg verbose: toggle printing to screen. :kwarg ratio_tol: value which must be exceeded for convergence. """ if verbose: print_output(24 * "=" + "TAYLOR TEST" + 24 * "=") m = np.array(m).flatten() if delta_m is None: delta_m = np.random.normal(loc=0.0, scale=1.0, size=m.shape) assert len(m) == len(delta_m) # Evaluate the reduced functional and gradient at the specified control value Jm = function(m) dJdm = gradient(m).flatten() assert len(m) == len(dJdm) # Check that the Taylor remainders decrease quadratically remainders = np.zeros(4) epsilons = [0.01 * 0.5**i for i in range(4)] rates = np.zeros(3) passed = True for i in range(4): h = epsilons[i] if verbose: print_output("h = {:.4e}".format(h)) J_step = function(m + h * delta_m) remainders[i] = np.abs(J_step - Jm - h * np.dot(dJdm, delta_m)) if i == 0: if verbose: print_output("remainder = {:.4e}".format(remainders[i])) elif i > 0: rates[i - 1] = np.log(remainders[i] / remainders[i - 1]) / np.log( epsilons[i] / epsilons[i - 1]) if verbose: msg = "remainder = {:.4e} convergence rate = {:.2f}" print_output(msg.format(remainders[i], rates[i - 1])) passed = passed and (rates[i - 1] > ratio_tol) if verbose: print_output( 20 * "=" + "TAYLOR TEST {:s}!".format("PASSED" if passed else "FAILED") + 20 * "=") return min(rates)
def export_final_state( inputdir, uv, elev, ): """ Export fields to be used in a subsequent simulation """ if not os.path.exists(inputdir): os.makedirs(inputdir) th.print_output("Exporting fields for subsequent simulation") chk = th.DumbCheckpoint(inputdir + "/velocity", mode=th.FILE_CREATE) chk.store(uv, name="velocity") th.File(inputdir + '/velocityout.pvd').write(uv) chk.close() chk = th.DumbCheckpoint(inputdir + "/elevation", mode=th.FILE_CREATE) chk.store(elev, name="elevation") th.File(inputdir + '/elevationout.pvd').write(elev) chk.close()
parser.add_argument("-debug", help="Print all debugging statements") parser.add_argument("-debug_mode", help="Choose debugging mode from 'basic' and 'full'") args = parser.parse_args() # --- Set parameters approach = 'fixed_mesh' level = int(args.level or 0) kwargs = { 'approach': approach, 'level': level, 'num_meshes': int(args.num_meshes or 1), 'plot_pvd': True, 'debug': bool(args.debug or False), 'debug_mode': args.debug_mode or 'basic', } op = IdealisedDesalinationOutfallOptions(**kwargs) # --- Run model tp = AdaptiveDesalinationProblem(op) cpu_timestamp = perf_counter() tp.solve_adjoint() cpu_time = perf_counter() - cpu_timestamp logstr = "Total CPU time: {:.1f} seconds / {:.1f} minutes / {:.3f} hours\n" logstr = logstr.format(cpu_time, cpu_time/60, cpu_time/3600) print_output(logstr)
def to_latlon(easting, northing, zone_number, zone_letter=None, northern=None, force_longitude=False, coords=None): """ Convert UTM coordinates to latitude-longitude, courtesy of Tobias Bieniek, 2012 (with some minor edits). :arg easting: eastward-measured Cartesian geographic distance. :arg northing: northward-measured Cartesian geographic distance. :arg zone_number: UTM zone number (increasing eastward). :param zone_letter: UTM zone letter (increasing alphabetically northward). :param northern: specify northern or southern hemisphere. :param coords: coordinate field of mesh (used to check validity of coordinates). :return: latitude-longitude coordinate pair. """ if not zone_letter and northern is None: raise ValueError('either zone_letter or northern needs to be set') elif zone_letter and northern is not None: raise ValueError('set either zone_letter or northern, but not both') if not force_longitude: if not 100000 <= easting < 1000000: raise OutOfRangeError( 'easting {:f} out of range (must be between 100,000 m and 999,999 m)' .format(easting)) msg = 'northing out of range (must be between 0 m and 10,000,000 m)' if isinstance(northing, ufl.indexed.Indexed): from firedrake import sin, cos, sqrt if coords is None: if os.environ.get('WARNINGS', '0') != '0': print_output("WARNING: Cannot check validity of coordinates.") else: minval, maxval = coords.dat.data[:, 1].min( ), coords.dat.data[:, 1].max() if not (0 <= minval and maxval <= 10000000): raise OutOfRangeError(msg) elif isinstance(northing, np.ndarray): from numpy import sin, cos, sqrt minval, maxval = northing.min(), northing.max() if not (0 <= minval and maxval <= 10000000): raise OutOfRangeError(msg) else: from math import sin, cos, sqrt if not 0 <= northing <= 10000000: raise OutOfRangeError(msg) if not 1 <= zone_number <= 60: raise OutOfRangeError( 'zone number out of range (must be between 1 and 60)') if zone_letter: zone_letter = zone_letter.upper() if not 'C' <= zone_letter <= 'X' or zone_letter in ['I', 'O']: raise OutOfRangeError( 'zone letter out of range (must be between C and X)') northern = zone_letter >= 'N' x = easting - 500000 y = northing if not northern: y -= 10000000 m = y / K0 mu = m / R / M1 p_rad = (mu + P2 * sin(2 * mu) + P3 * sin(4 * mu) + P4 * sin(6 * mu) + P5 * sin(8 * mu)) p_sin = sin(p_rad) p_sin2 = p_sin * p_sin p_cos = cos(p_rad) p_tan = p_sin / p_cos p_tan2 = p_tan * p_tan p_tan4 = p_tan2 * p_tan2 ep_sin = 1 - E * p_sin2 ep_sin_sqrt = sqrt(1 - E * p_sin2) n = R / ep_sin_sqrt r = (1 - E) / ep_sin c = _E * p_cos**2 c2 = c * c d = x / n / K0 d2 = d * d d3 = d2 * d d4 = d3 * d d5 = d4 * d d6 = d5 * d latitude = ( p_rad - p_tan / r * (d2 / 2 - d4 / 24 * (5 + 3 * p_tan2 + 10 * c - 4 * c2 - 9 * E_P2)) + d6 / 720 * (61 + 90 * p_tan2 + 298 * c + 45 * p_tan4 - 252 * E_P2 - 3 * c2)) longitude = ( d - d3 / 6 * (1 + 2 * p_tan2 + c) + d5 / 120 * (5 - 2 * c + 28 * p_tan2 - 3 * c2 + 8 * E_P2 + 24 * p_tan4)) / p_cos return degrees(latitude), degrees( longitude) + zone_number_to_central_longitude(zone_number)
def from_latlon(latitude, longitude, force_zone_number=None, zone_info=False, coords=None): """ Convert latitude-longitude coordinates to UTM, courtesy of Tobias Bieniek, 2012. :arg latitude: northward anglular position, origin at the Equator. :arg longitude: eastward angular position, with origin at the Greenwich Meridian. :param force_zone_number: force coordinates to fall within a particular UTM zone. :param zone_info: output zone letter and number. :param coords: coordinate field of mesh (used to check validity of coordinates). :return: UTM coordinate 4-tuple. """ lat_msg = 'latitude out of range (must be between 80 deg S and 84 deg N)' lon_msg = 'longitude out of range (must be between 180 deg W and 180 deg E)' if isinstance(latitude, ufl.indexed.Indexed): from firedrake import sin, cos, sqrt if coords is None: if os.environ.get('WARNINGS', '0') != '0': print_output("WARNING: Cannot check validity of coordinates.") else: minval, maxval = coords.dat.data[:, 0].min( ), coords.dat.data[:, 0].max() if not (-80.0 <= minval and maxval <= 84.0): raise OutOfRangeError(lon_msg) minval, maxval = coords.dat.data[:, 1].min( ), coords.dat.data[:, 1].max() if not (-180.0 <= minval and maxval <= 180.0): raise OutOfRangeError(lat_msg) elif isinstance(latitude, np.ndarray): from numpy import sin, cos, sqrt minval, maxval = longitude.min(), longitude.max() if not (-180.0 <= minval and maxval <= 180.0): raise OutOfRangeError(lon_msg) minval, maxval = latitude.min(), latitude.max() if not (-80.0 <= minval and maxval <= 84.0): raise OutOfRangeError(lat_msg) else: from math import sin, cos, sqrt if not -180.0 <= longitude <= 180.0: raise OutOfRangeError(lon_msg) if not -80.0 <= latitude <= 84.0: raise OutOfRangeError(lat_msg) lat_rad = radians(latitude) lat_sin = sin(lat_rad) lat_cos = cos(lat_rad) lat_tan = lat_sin / lat_cos lat_tan2 = lat_tan * lat_tan lat_tan4 = lat_tan2 * lat_tan2 if force_zone_number is None: zone_number = latlon_to_zone_number(latitude, longitude) else: zone_number = force_zone_number lon_rad = radians(longitude) central_lon_rad = radians(zone_number_to_central_longitude(zone_number)) n = R / sqrt(1 - E * lat_sin**2) c = E_P2 * lat_cos**2 a = lat_cos * (lon_rad - central_lon_rad) a2 = a * a a3 = a2 * a a4 = a3 * a a5 = a4 * a a6 = a5 * a m = R * (M1 * lat_rad - M2 * sin(2 * lat_rad) + M3 * sin(4 * lat_rad) - M4 * sin(6 * lat_rad)) easting = K0 * n * ( a + a3 / 6 * (1 - lat_tan2 + c) + a5 / 120 * (5 - 18 * lat_tan2 + lat_tan4 + 72 * c - 58 * E_P2)) + 500000 northing = K0 * (m + n * lat_tan * (a2 / 2 + a4 / 24 * (5 - lat_tan2 + 9 * c + 4 * c**2) + a6 / 720 * (61 - 58 * lat_tan2 + lat_tan4 + 600 * c - 330 * E_P2))) if isinstance(latitude, ufl.indexed.Indexed): if coords.dat.data[:, 1].min() < 0: northing += 10000000 elif isinstance(latitude, np.ndarray): if latitude.min() < 0: northing += 10000000 else: if latitude < 0: northing += 10000000 if zone_info: return easting, northing, zone_number, latitude_to_zone_letter( latitude) else: return easting, northing
'locations': locations, # I/O and debugging 'debug': bool(args.debug or False), 'debug_mode': args.debug_mode or 'basic', } levels = int(args.levels or 5) di = create_directory( os.path.join(os.path.dirname(__file__), 'outputs', 'qmesh')) # --- Loop over mesh hierarchy qois = [] num_cells = [] for level in range(levels): print_output("Running qmesh convergence on level {:d}".format(level)) # Set parameters kwargs['level'] = level op = TohokuHazardOptions(**kwargs) kwargs.pop('level') # Solve swp = AdaptiveTsunamiProblem(op, nonlinear=nonlinear, print_progress=False) swp.solve_forward() qoi = swp.quantity_of_interest() print_output("Quantity of interest: {:.8e}".format(qoi)) # Diagnostics qois.append(qoi) num_cells.append(swp.num_cells[0][0])
def hydrodynamics_only(boundary_conditions_fn, mesh2d, bathymetry_2d, uv_init, elev_init, average_size, dt, t_end, wetting_and_drying=False, wetting_alpha=0.1, friction='nikuradse', friction_coef=0, fluc_bcs=False, viscosity=10**(-6), sponge_viscosity=th.Constant(1.0)): """ Sets up a simulation with only hydrodynamics until a quasi-steady state when it can be used as an initial condition for the full morphological model. We update the bed friction at each time step. The actual run of the model are done outside the function Inputs: boundary_consditions_fn - function defining boundary conditions for problem mesh2d - define mesh working on bathymetry2d - define bathymetry of problem uv_init - initial velocity of problem elev_init - initial elevation of problem average_size - average sediment size dt - timestep t_end - end time wetting_and_drying - wetting and drying switch wetting_alpha - wetting and drying parameter friction - choice of friction formulation - nikuradse and manning friction_coef - value of friction coefficient used in manning viscosity - viscosity of hydrodynamics. The default value should be 10**(-6) Outputs: solver_obj - solver which we need to run to solve the problem update_forcings_hydrodynamics - function defining the updates to the model performed at each timestep outputdir - directory of outputs """ def update_forcings_hydrodynamics(t_new): # update boundary conditions if have fluctuating conditions if fluc_bcs: in_fn, out_fn = boundary_conditions_fn(bathymetry_2d, t_new=t_new, state='update') for j in range(len(in_fn)): exec('constant_in' + str(j) + '.assign(' + str(in_fn[j]) + ')') for k in range(len(out_fn)): exec('constant_out' + str(k) + '.assign(' + str(out_fn[k]) + ')') # update bed friction if friction == 'nikuradse': uv1, elev1 = solver_obj.fields.solution_2d.split() if wetting_and_drying: wd_bath_displacement = solver_obj.depth.wd_bathymetry_displacement depth.project(elev1 + wd_bath_displacement(elev1) + bathymetry_2d) else: depth.interpolate(elev1 + bathymetry_2d) # calculate skin friction coefficient cfactor.interpolate(2 * (0.4**2) / ((th.ln(11.036 * depth / (ksp)))**2)) # choose directory to output results ts = time.time() st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') outputdir = 'outputs' + st # export interval in seconds if t_end < 40: t_export = 0.1 else: t_export = np.round(t_end / 40, 0) th.print_output('Exporting to ' + outputdir) # define function spaces V = th.FunctionSpace(mesh2d, 'CG', 1) P1_2d = th.FunctionSpace(mesh2d, 'DG', 1) # define parameters ksp = th.Constant(3 * average_size) # define depth if wetting_and_drying: H = th.Function(V).project(elev_init + bathymetry_2d) depth = th.Function(V).project( H + (0.5 * (th.sqrt(H**2 + wetting_alpha**2) - H))) else: depth = th.Function(V).project(elev_init + bathymetry_2d) # define bed friction cfactor = th.Function(P1_2d).interpolate( 2 * (0.4**2) / ((th.ln(11.036 * depth / (ksp)))**2)) # set up solver solver_obj = th.solver2d.FlowSolver2d(mesh2d, bathymetry_2d) options = solver_obj.options options.simulation_export_time = t_export options.simulation_end_time = t_end options.output_directory = outputdir options.check_volume_conservation_2d = True options.fields_to_export = ['uv_2d', 'elev_2d'] options.solve_tracer = False options.use_lax_friedrichs_tracer = False if friction == 'nikuradse': options.quadratic_drag_coefficient = cfactor elif friction == 'manning': if friction_coef == 0: friction_coef = 0.02 options.manning_drag_coefficient = th.Constant(friction_coef) else: print('Undefined friction') options.horizontal_viscosity = th.Function(P1_2d).interpolate( sponge_viscosity * th.Constant(viscosity)) # crank-nicholson used to integrate in time system of ODEs resulting from application of galerkin FEM options.timestepper_type = 'CrankNicolson' options.timestepper_options.implicitness_theta = 1.0 options.use_wetting_and_drying = wetting_and_drying options.wetting_and_drying_alpha = th.Function(V).interpolate( th.Constant(wetting_alpha)) options.norm_smoother = th.Constant(1.0) if not hasattr(options.timestepper_options, 'use_automatic_timestep'): options.timestep = dt # set boundary conditions swe_bnd, left_bnd_id, right_bnd_id, in_constant, out_constant, left_string, right_string = boundary_conditions_fn( bathymetry_2d, flag='hydro') for j in range(len(in_constant)): exec( 'constant_in' + str(j) + ' = th.Constant(' + str(in_constant[j]) + ')', globals()) str1 = '{' if len(left_string) > 0: for i in range(len(left_string)): str1 += "'" + str(left_string[i]) + "': constant_in" + str(i) + "," str1 = str1[0:len(str1) - 1] + "}" exec('swe_bnd[left_bnd_id] = ' + str1) for k in range(len(out_constant)): exec( 'constant_out' + str(k) + '= th.Constant(' + str(out_constant[k]) + ')', globals()) str2 = '{' if len(right_string) > 0: for i in range(len(right_string)): str2 += "'" + str( right_string[i]) + "': constant_out" + str(i) + "," str2 = str2[0:len(str2) - 1] + "}" exec('swe_bnd[right_bnd_id] = ' + str2) solver_obj.bnd_functions['shallow_water'] = swe_bnd solver_obj.assign_initial_conditions(uv=uv_init, elev=elev_init) return solver_obj, update_forcings_hydrodynamics, outputdir
def morphological(boundary_conditions_fn, morfac, morfac_transport, suspendedload, convectivevel, bedload, angle_correction, slope_eff, seccurrent, mesh2d, bathymetry_2d, input_dir, viscosity_hydro, ks, average_size, dt, final_time, beta_fn, surbeta2_fn, alpha_secc_fn, friction='nikuradse', friction_coef=0, d90=0, fluc_bcs=False, bed_form='meyer', sus_form='vanrijn', diffusivity=0.15): """ Set up a full morphological model simulation using as an initial condition the results of a hydrodynamic only model. Inputs: boundary_consditions_fn - function defining boundary conditions for problem morfac - morphological scale factor morfac_transport - switch to turn on morphological component suspendedload - switch to turn on suspended sediment transport convectivevel - switch on convective velocity correction factor in sediment concentration equation bedload - switch to turn on bedload transport angle_correction - switch on slope effect angle correction slope_eff - switch on slope effect magnitude correction seccurrent - switch on secondary current for helical flow effect mesh2d - define mesh working on bathymetry2d - define bathymetry of problem input_dir - folder containing results of hydrodynamics model which are used as initial conditions here viscosity_hydro - viscosity value in hydrodynamic equations ks - bottom friction coefficient for quadratic drag coefficient average_size - average sediment size dt - timestep final_time - end time beta_fn - magnitude slope effect parameter surbeta2_fn - angle correction slope effect parameter alpha_secc_fn - secondary current parameter friction - choice of friction formulation - nikuradse and manning friction_coef - value of friction coefficient used in manning d90 - sediment size which 90% of the sediment are below fluc_bcs - if true this allows the user to impose boundary conditions which vary with time bed_form - choice of bedload formula between 'meyer' (meyer-peter-muller) and 'soulsby' (soulsby-van-rijn) sus_form - choice of suspended load formula between 'vanrijn' (van Rijn 1984) and 'soulsby' (soulsby-van-rijn) diffusivity - diffusivity value in suspended sediment concentration equation. The default value (found by callibration) should be 0.15 Outputs: solver_obj - solver which we need to run to solve the problem update_forcings_hydrodynamics - function defining the updates to the model performed at each timestep diff_bathy - bedlevel evolution diff_bathy_file - bedlevel evolution file """ t_list = [] def update_forcings_tracer(t_new): # update bathymetry old_bathymetry_2d.assign(bathymetry_2d) # extract new elevation and velocity and project onto CG space uv1, elev1 = solver_obj.fields.solution_2d.split() uv_cg.project(uv1) elev_cg.project(elev1) depth.project(elev_cg + old_bathymetry_2d) horizontal_velocity.interpolate(uv_cg[0]) vertical_velocity.interpolate(uv_cg[1]) # update boundary conditions if have fluctuating conditions if fluc_bcs: in_fn, out_fn = boundary_conditions_fn(orig_bathymetry, flag='morpho', morfac=morfac, t_new=t_new, state='update') for j in range(len(in_fn)): exec('constant_in' + str(j) + '.assign(' + str(in_fn[j]) + ')') for k in range(len(out_fn)): exec('constant_out' + str(k) + '.assign(' + str(out_fn[k]) + ')') # update bedfriction hc.interpolate(th.conditional(depth > 0.001, depth, 0.001)) aux.assign( th.conditional(11.036 * hc / ks > 1.001, 11.036 * hc / ks, 1.001)) qfc.assign(2 / (th.ln(aux) / 0.4)**2) # calculate skin friction coefficient hclip.interpolate(th.conditional(ksp > depth, ksp, depth)) cfactor.interpolate( th.conditional(depth > ksp, 2 * ((2.5 * th.ln(11.036 * hclip / ksp))**(-2)), th.Constant(0.0))) if morfac_transport: # if include tracer solver then update_forcings is run twice but only want to update bathymetry once t_list.append(t_new) double_factor = False if suspendedload: if len(t_list) > 1: if t_list[len(t_list) - 1] == t_list[len(t_list) - 2]: double_factor = True else: # if have no tracer then update_forcings is only run once so update bathymetry at each step double_factor = True if double_factor: z_n.assign(old_bathymetry_2d) # mu - ratio between skin friction and normal friction mu.assign(th.conditional(qfc > 0, cfactor / qfc, 0)) # bed shear stress unorm.interpolate((horizontal_velocity**2) + (vertical_velocity**2)) TOB.interpolate(1000 * 0.5 * qfc * unorm) # calculate gradient of bed (noting bathymetry is -bed) dzdx.interpolate(old_bathymetry_2d.dx(0)) dzdy.interpolate(old_bathymetry_2d.dx(1)) # initialise exner equation f = 0 if suspendedload: # source term # deposition flux - calculating coefficient to account for stronger conc at bed B.interpolate(th.conditional(a > depth, a / a, a / depth)) ustar.interpolate(th.sqrt(0.5 * qfc * unorm)) exp1.assign( th.conditional( (th.conditional( (settling_velocity / (0.4 * ustar)) - 1 > 0, (settling_velocity / (0.4 * ustar)) - 1, -(settling_velocity / (0.4 * ustar)) + 1)) > 10**(-4), th.conditional( (settling_velocity / (0.4 * ustar)) - 1 > 3, 3, (settling_velocity / (0.4 * ustar)) - 1), 0)) coefftest.assign( th.conditional((th.conditional( (settling_velocity / (0.4 * ustar)) - 1 > 0, (settling_velocity / (0.4 * ustar)) - 1, -(settling_velocity / (0.4 * ustar)) + 1)) > 10**(-4), B * (1 - B**exp1) / exp1, -B * th.ln(B))) coeff.assign( th.conditional(coefftest > 0, 1 / coefftest, 0)) if sus_form == 'vanrijn': # erosion flux - above critical velocity bed is eroded s0.assign( (th.conditional(1000 * 0.5 * qfc * unorm * mu > 0, 1000 * 0.5 * qfc * unorm * mu, 0) - taucr) / taucr) ceq.assign(0.015 * (average_size / a) * ((th.conditional(s0 < 0, 0, s0))**(1.5)) / (dstar**0.3)) elif sus_form == 'soulsby': ucr.interpolate(0.19 * (average_size**0.1) * (th.ln(4 * depth / d90) / th.ln(10))) s0.assign( th.conditional((th.sqrt(unorm) - ucr)**2.4 > 0, (th.sqrt(unorm) - ucr)**2.4, 0)) ceq.interpolate(ass * s0 / depth) else: print( 'Unrecognised suspended sediment transport formula. Please choose "vanrijn" or "soulsby"' ) # calculate depth-averaged source term for sediment concentration equation source.interpolate(-(settling_velocity * coeff * solver_obj.fields.tracer_2d / depth) + (settling_velocity * ceq / depth)) # update sediment rate to ensure equilibrium at inflow sediment_rate.assign(ceq.at([0, 0]) / coeff.at([0, 0])) if convectivevel: # correction factor to advection velocity in sediment concentration equation Bconv.interpolate( th.conditional(depth > 1.1 * ksp, ksp / depth, ksp / (1.1 * ksp))) Aconv.interpolate( th.conditional(depth > 1.1 * a, a / depth, a / (1.1 * a))) # take max of value calculated either by ksp or depth Amax.assign(th.conditional(Aconv > Bconv, Aconv, Bconv)) r1conv.assign(1 - (1 / 0.4) * th.conditional( settling_velocity / ustar < 1, settling_velocity / ustar, 1)) Ione.assign( th.conditional( r1conv > 10**(-8), (1 - Amax**r1conv) / r1conv, th.conditional(r1conv < -10**(-8), (1 - Amax**r1conv) / r1conv, th.ln(Amax)))) Itwo.assign( th.conditional( r1conv > 10**(-8), -(Ione + (th.ln(Amax) * (Amax**r1conv))) / r1conv, th.conditional( r1conv < -10**(-8), -(Ione + (th.ln(Amax) * (Amax**r1conv))) / r1conv, -0.5 * th.ln(Amax)**2))) alpha.assign(-(Itwo - (th.ln(Amax) - th.ln(30)) * Ione) / (Ione * ((th.ln(Amax) - th.ln(30)) + 1))) # final correction factor alphatest2.assign( th.conditional( th.conditional(alpha > 1, 1, alpha) < 0, 0, th.conditional(alpha > 1, 1, alpha))) # multiply correction factor by velocity and insert back into sediment concentration equation corrective_velocity.interpolate(alphatest2 * uv1) else: corrective_velocity.interpolate(uv1) if bedload: # calculate angle of flow calfa.interpolate(horizontal_velocity / th.sqrt(unorm)) salfa.interpolate(vertical_velocity / th.sqrt(unorm)) div_function.interpolate(th.as_vector((calfa, salfa))) if slope_eff: # slope effect magnitude correction due to gravity where beta is a parameter normally set to 1.3 # we use z_n1 and equals so that we can use an implicit method in Exner slopecoef = (1 + beta * (z_n1.dx(0) * calfa + z_n1.dx(1) * salfa)) else: slopecoef = th.Constant(1.0) if angle_correction: # slope effect angle correction due to gravity tt1.interpolate( th.conditional( 1000 * 0.5 * qfc * unorm > 10**(-10), th.sqrt(cparam / (1000 * 0.5 * qfc * unorm)), th.sqrt(cparam / (10**(-10))))) # add on a factor of the bed gradient to the normal aa.assign(salfa + tt1 * dzdy) bb.assign(calfa + tt1 * dzdx) norm.assign( th.conditional( th.sqrt(aa**2 + bb**2) > 10**(-10), th.sqrt(aa**2 + bb**2), 10**(-10))) # we use z_n1 and equals so that we can use an implicit method in Exner calfamod = (calfa + (tt1 * z_n1.dx(0))) / norm salfamod = (salfa + (tt1 * z_n1.dx(1))) / norm if seccurrent: # accounts for helical flow effect in a curver channel # again use z_n1 and equals so can use an implicit method in Exner free_surface_dx = depth.dx(0) - z_n1.dx(0) free_surface_dy = depth.dx(1) - z_n1.dx(1) velocity_slide = (horizontal_velocity * free_surface_dy ) - (vertical_velocity * free_surface_dx) tandelta_factor.interpolate( 7 * 9.81 * 1000 * depth * qfc / (2 * alpha_secc * ((horizontal_velocity**2) + (vertical_velocity**2)))) if angle_correction: # if angle has already been corrected we must alter the corrected angle to obtain the corrected secondary current angle t_1 = (TOB * slopecoef * calfamod) + ( vertical_velocity * tandelta_factor * velocity_slide) t_2 = (TOB * slopecoef * salfamod) - ( horizontal_velocity * tandelta_factor * velocity_slide) else: t_1 = (TOB * slopecoef * calfa) + (vertical_velocity * tandelta_factor * velocity_slide) t_2 = ((TOB * slopecoef * salfa) - (horizontal_velocity * tandelta_factor * velocity_slide)) # calculated to normalise the new angles t4 = th.sqrt((t_1**2) + (t_2**2)) # updated magnitude correction and angle corrections slopecoef = t4 / TOB calfanew = t_1 / t4 salfanew = t_2 / t4 if bed_form == 'meyer': # implement meyer-peter-muller bedload transport formula thetaprime.interpolate( mu * (1000 * 0.5 * qfc * unorm) / ((2650 - 1000) * 9.81 * average_size)) # if velocity above a certain critical value then transport occurs phi.assign( th.conditional(thetaprime < thetacr, 0, 8 * (thetaprime - thetacr)**1.5)) # bedload transport flux with magnitude correction qb_total = slopecoef * phi * th.sqrt( g * (2650 / 1000 - 1) * average_size**3) elif bed_form == 'soulsby': abb.interpolate( th.conditional( depth >= average_size, 0.005 * depth * ((average_size / depth)**1.2) / coeff_soulsby, 0.005 * depth / coeff_soulsby)) ucr_bed.interpolate( th.conditional( depth > d90, 0.19 * (average_size**0.1) * (th.ln(4 * depth / d90)) / (th.ln(10)), 0.19 * (average_size**0.1) * (th.ln(4)) / (th.ln(10)))) s0_bed.interpolate( th.conditional((th.sqrt(unorm) - ucr_bed)**2.4 > 0, (th.sqrt(unorm) - ucr_bed)**2.4, 0)) qb_total = slopecoef * abb * s0_bed * th.sqrt(unorm) else: print( 'Unrecognised bedload transport formula. Please choose "meyer" or "soulsby"' ) # add time derivative to exner equation with a morphological scale factor f += (((1 - porosity) * (z_n1 - z_n) / (dt * morfac)) * v) * fire.dx # formulate bedload transport flux with correct angle depending on corrections implemented if angle_correction and seccurrent is False: qbx = qb_total * calfamod qby = qb_total * salfamod elif seccurrent: qbx = qb_total * calfanew qby = qb_total * salfanew else: qbx = qb_total * calfa qby = qb_total * salfa # add bedload transport to exner equation f += -(v * ( (qbx * n[0]) + (qby * n[1]))) * fire.ds(1) - (v * ( (qbx * n[0]) + (qby * n[1]))) * fire.ds(2) + (qbx * (v.dx(0)) + qby * (v.dx(1))) * fire.dx else: # if no bedload transport component initialise exner equation with time derivative f = (((1 - porosity) * (z_n1 - z_n) / (dt * morfac)) * v) * fire.dx if suspendedload: # add suspended sediment transport to exner equation multiplied by depth as the exner equation is not depth-averaged qbsourcedepth.interpolate(source * depth) f += -(qbsourcedepth * v) * fire.dx # solve exner equation using finite element methods fire.solve(f == 0, z_n1) # update bed bathymetry_2d.assign(z_n1) if round(t_new, 2) % t_export == 0: # calculate difference between original bathymetry and new bathymetry diff_bathy.interpolate(-bathymetry_2d + orig_bathymetry) diff_bathy_file.write(diff_bathy) # choose directory to output results ts = time.time() st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') outputdir = 'outputs' + st # final time of simulation t_end = final_time / morfac # export interval in seconds t_export = np.round(t_end / 100, 0) th.print_output('Exporting to ' + outputdir) x, y = th.SpatialCoordinate(mesh2d) # define function spaces P1_2d = th.FunctionSpace(mesh2d, 'DG', 1) vectorP1_2d = th.VectorFunctionSpace(mesh2d, 'DG', 1) V = th.FunctionSpace(mesh2d, 'CG', 1) vector_cg = th.VectorFunctionSpace(mesh2d, 'CG', 1) # define test functions on mesh v = fire.TestFunction(V) n = th.FacetNormal(mesh2d) z_n1 = fire.Function(V, name="z^{n+1}") z_n = fire.Function(V, name="z^{n}") # define original bathymetry before bedlevel changes orig_bathymetry = th.Function(V).interpolate(bathymetry_2d) # calculate bed evolution diff_bathy = th.Function(V).interpolate(-bathymetry_2d + orig_bathymetry) # define output file for bed evolution diff_bathy_file = th.File(outputdir + "/diff_bathy.pvd") diff_bathy_file.write(diff_bathy) # define parameters g = th.Constant(9.81) porosity = th.Constant(0.4) ksp = th.Constant(3 * average_size) a = th.Constant(ks / 2) viscosity = th.Constant(10**(-6)) # magnitude slope effect parameter beta = th.Constant(beta_fn) # angle correction slope effect parameters surbeta2 = th.Constant(surbeta2_fn) cparam = th.Constant((2650 - 1000) * 9.81 * average_size * (surbeta2**2)) # secondary current parameter alpha_secc = th.Constant(alpha_secc_fn) # calculate critical shields parameter thetacr R = th.Constant(2650 / 1000 - 1) dstar = th.Constant(average_size * ((g * R) / (viscosity**2))**(1 / 3)) if max(dstar.dat.data[:] < 1): print('ERROR: dstar value less than 1') elif max(dstar.dat.data[:] < 4): thetacr = th.Constant(0.24 * (dstar**(-1))) elif max(dstar.dat.data[:] < 10): thetacr = th.Constant(0.14 * (dstar**(-0.64))) elif max(dstar.dat.data[:] < 20): thetacr = th.Constant(0.04 * (dstar**(-0.1))) elif max(dstar.dat.data[:] < 150): thetacr = th.Constant(0.013 * (dstar**(0.29))) else: thetacr = th.Constant(0.055) # critical bed shear stress taucr = th.Constant((2650 - 1000) * g * average_size * thetacr) # calculate settling velocity if average_size <= 100 * (10**(-6)): settling_velocity = th.Constant(9.81 * (average_size**2) * ((2650 / 1000) - 1) / (18 * viscosity)) elif average_size <= 1000 * (10**(-6)): settling_velocity = th.Constant( (10 * viscosity / average_size) * (th.sqrt(1 + 0.01 * ((((2650 / 1000) - 1) * 9.81 * (average_size**3)) / (viscosity**2))) - 1)) else: settling_velocity = th.Constant(1.1 * th.sqrt(9.81 * average_size * ((2650 / 1000) - 1))) # initialise velocity, elevation and depth elev_init, uv_init = initialise_fields(mesh2d, input_dir, outputdir) uv_cg = th.Function(vector_cg).interpolate(uv_init) elev_cg = th.Function(V).interpolate(elev_init) depth = th.Function(V).project(elev_cg + bathymetry_2d) old_bathymetry_2d = th.Function(V).interpolate(bathymetry_2d) horizontal_velocity = th.Function(V).interpolate(uv_cg[0]) vertical_velocity = th.Function(V).interpolate(uv_cg[1]) # define bed friction hc = th.Function(P1_2d).interpolate( th.conditional(depth > 0.001, depth, 0.001)) aux = th.Function(P1_2d).interpolate( th.conditional(11.036 * hc / ks > 1.001, 11.036 * hc / ks, 1.001)) qfc = th.Function(P1_2d).interpolate(2 / (th.ln(aux) / 0.4)**2) # skin friction coefficient hclip = th.Function(P1_2d).interpolate( th.conditional(ksp > depth, ksp, depth)) cfactor = th.Function(P1_2d).interpolate( th.conditional(depth > ksp, 2 * ((2.5 * th.ln(11.036 * hclip / ksp))**(-2)), th.Constant(0.0))) # mu - ratio between skin friction and normal friction mu = th.Function(P1_2d).interpolate( th.conditional(qfc > 0, cfactor / qfc, 0)) # calculate bed shear stress unorm = th.Function(P1_2d).interpolate((horizontal_velocity**2) + (vertical_velocity**2)) TOB = th.Function(V).interpolate(1000 * 0.5 * qfc * unorm) # define bed gradient dzdx = th.Function(V).interpolate(old_bathymetry_2d.dx(0)) dzdy = th.Function(V).interpolate(old_bathymetry_2d.dx(1)) if suspendedload: # deposition flux - calculating coefficient to account for stronger conc at bed B = th.Function(P1_2d).interpolate( th.conditional(a > depth, a / a, a / depth)) ustar = th.Function(P1_2d).interpolate(th.sqrt(0.5 * qfc * unorm)) exp1 = th.Function(P1_2d).interpolate( th.conditional( (th.conditional( (settling_velocity / (0.4 * ustar)) - 1 > 0, (settling_velocity / (0.4 * ustar)) - 1, -(settling_velocity / (0.4 * ustar)) + 1)) > 10**(-4), th.conditional((settling_velocity / (0.4 * ustar)) - 1 > 3, 3, (settling_velocity / (0.4 * ustar)) - 1), 0)) coefftest = th.Function(P1_2d).interpolate( th.conditional((th.conditional( (settling_velocity / (0.4 * ustar)) - 1 > 0, (settling_velocity / (0.4 * ustar)) - 1, -(settling_velocity / (0.4 * ustar)) + 1)) > 10**(-4), B * (1 - B**exp1) / exp1, -B * th.ln(B))) coeff = th.Function(P1_2d).interpolate( th.conditional(coefftest > 0, 1 / coefftest, 0)) if sus_form == 'vanrijn': # erosion flux - above critical velocity bed is eroded s0 = th.Function(P1_2d).interpolate( (th.conditional(1000 * 0.5 * qfc * unorm * mu > 0, 1000 * 0.5 * qfc * unorm * mu, 0) - taucr) / taucr) ceq = th.Function(P1_2d).interpolate( 0.015 * (average_size / a) * ((th.conditional(s0 < 0, 0, s0))**(1.5)) / (dstar**0.3)) elif sus_form == 'soulsby': if d90 == 0: # if the value of d90 is unspecified set d90 = d50 d90 = th.Constant(average_size) else: d90 = th.Constant(d90) coeff_soulsby = th.Constant((R * g * average_size)**1.2) ass = th.Constant(0.012 * average_size * (dstar**(-0.6)) / coeff_soulsby) ucr = th.Function(P1_2d).interpolate(0.19 * (average_size**0.1) * (th.ln(4 * depth / d90)) / (th.ln(10))) s0 = th.Function(P1_2d).interpolate( th.conditional((th.sqrt(unorm) - ucr)**2.4 > 0, (th.sqrt(unorm) - ucr)**2.4, 0)) ceq = th.Function(P1_2d).interpolate(ass * s0 / depth) else: print( 'Unrecognised suspended sediment transport formula. Please choose "vanrijn" or "soulsby"' ) # update sediment rate to ensure equilibrium at inflow sediment_rate = th.Constant(ceq.at([0, 0]) / coeff.at([0, 0])) testtracer = th.Function(P1_2d).interpolate(ceq / coeff) # calculate depth-averaged source term for sediment concentration equation source = th.Function(P1_2d).interpolate( -(settling_velocity * coeff * sediment_rate / depth) + (settling_velocity * ceq / depth)) # add suspended sediment transport to exner equation multiplied by depth as the exner equation is not depth-averaged qbsourcedepth = th.Function(V).interpolate(source * depth) if convectivevel: # correction factor to advection velocity in sediment concentration equation Bconv = th.Function(P1_2d).interpolate( th.conditional(depth > 1.1 * ksp, ksp / depth, ksp / (1.1 * ksp))) Aconv = th.Function(P1_2d).interpolate( th.conditional(depth > 1.1 * a, a / depth, a / (1.1 * a))) # take max of value calculated either by ksp or depth Amax = th.Function(P1_2d).interpolate( th.conditional(Aconv > Bconv, Aconv, Bconv)) r1conv = th.Function(P1_2d).interpolate( 1 - (1 / 0.4) * th.conditional(settling_velocity / ustar < 1, settling_velocity / ustar, 1)) Ione = th.Function(P1_2d).interpolate( th.conditional( r1conv > 10**(-8), (1 - Amax**r1conv) / r1conv, th.conditional(r1conv < -10**(-8), (1 - Amax**r1conv) / r1conv, th.ln(Amax)))) Itwo = th.Function(P1_2d).interpolate( th.conditional( r1conv > 10**(-8), -(Ione + (th.ln(Amax) * (Amax**r1conv))) / r1conv, th.conditional( r1conv < -10**(-8), -(Ione + (th.ln(Amax) * (Amax**r1conv))) / r1conv, -0.5 * th.ln(Amax)**2))) alpha = th.Function(P1_2d).interpolate( -(Itwo - (th.ln(Amax) - th.ln(30)) * Ione) / (Ione * ((th.ln(Amax) - th.ln(30)) + 1))) # final correction factor alphatest2 = th.Function(P1_2d).interpolate( th.conditional( th.conditional(alpha > 1, 1, alpha) < 0, 0, th.conditional(alpha > 1, 1, alpha))) # multiply correction factor by velocity and insert back into sediment concentration equation corrective_velocity = th.Function(vectorP1_2d).interpolate( alphatest2 * uv_init) else: corrective_velocity = th.Function(vectorP1_2d).interpolate(uv_init) if bedload: # calculate angle of flow calfa = th.Function(V).interpolate(horizontal_velocity / th.sqrt(unorm)) salfa = th.Function(V).interpolate(vertical_velocity / th.sqrt(unorm)) div_function = th.Function(vector_cg).interpolate( th.as_vector((calfa, salfa))) if slope_eff: # slope effect magnitude correction due to gravity where beta is a parameter normally set to 1.3 slopecoef = th.Function(V).interpolate( 1 + beta * (dzdx * calfa + dzdy * salfa)) else: slopecoef = th.Function(V).interpolate(th.Constant(1.0)) if angle_correction: # slope effect angle correction due to gravity tt1 = th.Function(V).interpolate( th.conditional(1000 * 0.5 * qfc * unorm > 10**(-10), th.sqrt(cparam / (1000 * 0.5 * qfc * unorm)), th.sqrt(cparam / (10**(-10))))) # add on a factor of the bed gradient to the normal aa = th.Function(V).interpolate(salfa + tt1 * dzdy) bb = th.Function(V).interpolate(calfa + tt1 * dzdx) norm = th.Function(V).interpolate( th.conditional( th.sqrt(aa**2 + bb**2) > 10**(-10), th.sqrt(aa**2 + bb**2), 10**(-10))) if seccurrent: # accounts for helical flow effect in a curver channel free_surface_dx = th.Function(V).interpolate(elev_cg.dx(0)) free_surface_dy = th.Function(V).interpolate(elev_cg.dx(1)) velocity_slide = (horizontal_velocity * free_surface_dy) - ( vertical_velocity * free_surface_dx) tandelta_factor = th.Function(V).interpolate( 7 * 9.81 * 1000 * depth * qfc / (2 * alpha_secc * ((horizontal_velocity**2) + (vertical_velocity**2)))) t_1 = (TOB * slopecoef * calfa) + ( vertical_velocity * tandelta_factor * velocity_slide) t_2 = ((TOB * slopecoef * salfa) - (horizontal_velocity * tandelta_factor * velocity_slide)) # calculated to normalise the new angles t4 = th.sqrt((t_1**2) + (t_2**2)) # updated magnitude correction and angle corrections slopecoef = t4 / TOB if bed_form == 'meyer': # implement meyer-peter-muller bedload transport formula thetaprime = th.Function(V).interpolate( mu * (1000 * 0.5 * qfc * unorm) / ((2650 - 1000) * 9.81 * average_size)) # if velocity above a certain critical value then transport occurs phi = th.Function(V).interpolate( th.conditional(thetaprime < thetacr, 0, 8 * (thetaprime - thetacr)**1.5)) elif bed_form == 'soulsby': if d90 == 0: d90 = th.Constant(average_size) coeff_soulsby = th.Constant((R * g * average_size)**1.2) abb = th.Function(P1_2d).interpolate( th.conditional( depth >= average_size, 0.005 * depth * ((average_size / depth)**1.2) / coeff_soulsby, 0.005 * depth / coeff_soulsby)) ucr_bed = th.Function(P1_2d).interpolate( th.conditional( depth > d90, 0.19 * (average_size**0.1) * (th.ln(4 * depth / d90)) / (th.ln(10)), 0.19 * (average_size**0.1) * (th.ln(4)) / (th.ln(10)))) s0_bed = th.Function(P1_2d).interpolate( th.conditional((th.sqrt(unorm) - ucr_bed)**2.4 > 0, (th.sqrt(unorm) - ucr_bed)**2.4, 0)) else: print( 'Unrecognised bedload transport formula. Please choose "meyer" or "soulsby"' ) # set up solver solver_obj = th.solver2d.FlowSolver2d(mesh2d, bathymetry_2d) options = solver_obj.options options.simulation_export_time = t_export options.simulation_end_time = t_end options.output_directory = outputdir options.check_volume_conservation_2d = True if suspendedload: # switch on tracer calculation if using sediment transport component options.solve_tracer = True options.fields_to_export = [ 'uv_2d', 'elev_2d', 'tracer_2d', 'bathymetry_2d' ] options.tracer_advective_velocity = corrective_velocity options.tracer_source_2d = source else: options.solve_tracer = False options.fields_to_export = ['uv_2d', 'elev_2d', 'bathymetry_2d'] options.use_lax_friedrichs_tracer = False # set bed friction if friction == 'nikuradse': options.quadratic_drag_coefficient = cfactor elif friction == 'manning': if friction_coef == 0: friction_coef = 0.02 options.manning_drag_coefficient = th.Constant(friction_coef) else: print('Undefined friction') # set horizontal diffusivity parameter options.horizontal_diffusivity = th.Constant(diffusivity) options.horizontal_viscosity = th.Constant(viscosity_hydro) # crank-nicholson used to integrate in time system of ODEs resulting from application of galerkin FEM options.timestepper_type = 'CrankNicolson' options.timestepper_options.implicitness_theta = 1.0 if not hasattr(options.timestepper_options, 'use_automatic_timestep'): options.timestep = dt # set boundary conditions swe_bnd, left_bnd_id, right_bnd_id, in_constant, out_constant, left_string, right_string = boundary_conditions_fn( orig_bathymetry, flag='morpho') for j in range(len(in_constant)): exec( 'constant_in' + str(j) + ' = th.Constant(' + str(in_constant[j]) + ')', globals()) str1 = '{' for i in range(len(left_string)): str1 += "'" + str(left_string[i]) + "': constant_in" + str(i) + "," str1 = str1[0:len(str1) - 1] + "}" exec('swe_bnd[left_bnd_id] = ' + str1) for k in range(len(out_constant)): exec( 'constant_out' + str(k) + '= th.Constant(' + str(out_constant[k]) + ')', globals()) str2 = '{' for i in range(len(right_string)): str2 += "'" + str(right_string[i]) + "': constant_out" + str(i) + "," str2 = str2[0:len(str2) - 1] + "}" exec('swe_bnd[right_bnd_id] = ' + str2) solver_obj.bnd_functions['shallow_water'] = swe_bnd if suspendedload: solver_obj.bnd_functions['tracer'] = {1: {'value': sediment_rate}} # set initial conditions solver_obj.assign_initial_conditions(uv=uv_init, elev=elev_init, tracer=testtracer) else: # set initial conditions solver_obj.assign_initial_conditions(uv=uv_init, elev=elev_init) return solver_obj, update_forcings_tracer, diff_bathy, diff_bathy_file
# --- Create solver and copy initial solution ep = AdaptiveProblem(CosinePrescribedVelocityOptions(**kwargs)) ep.set_initial_condition() init_sol = ep.fwd_solutions_tracer[0].copy(deepcopy=True) init_norm = norm(init_sol) # --- Eulerian interpretation ep.solve_forward() final_sol_eulerian = ep.fwd_solutions_tracer[-1] relative_error_eulerian = abs(errornorm(init_sol, final_sol_eulerian)/init_norm) print_output("Relative error in Eulerian case: {:.2f}%".format(100*relative_error_eulerian)) # --- Lagrangian interpretation kwargs['approach'] = 'lagrangian' lp = AdaptiveProblem(CosinePrescribedVelocityOptions(**kwargs)) lp.set_initial_condition() init_sol = lp.fwd_solutions_tracer[0].copy(deepcopy=True) init_coords = lp.meshes[0].coordinates.dat.data.copy() lp.solve_forward() final_sol_lagrangian = lp.fwd_solutions_tracer[-1] final_coords = lp.meshes[-1].coordinates.dat.data final_coords[:] -= [10.0, 0.0] # TODO: Implement periodicity if not np.allclose(init_coords, final_coords): # FIXME
) parser.add_argument("-level", help="Mesh resolution level (default 0)") parser.add_argument("-noisy_data", help="Toggle whether to sample noisy data (default False)") # --- Set parameters # Parsed arguments args = parser.parse_args() basis = args.basis level = int(args.level or 0) plot = parser.plotting_args() # Do not attempt to plot in parallel if COMM_WORLD.size > 1: print_output('Will not attempt to plot in parallel.') sys.exit(0) # Setup output directories dirname = os.path.join(os.path.dirname(__file__)) extension = lambda fpath: fpath if args.extension is None else '_'.join([fpath, args.extension]) data_dir = create_directory(os.path.join(dirname, basis, 'outputs', extension('realistic'))) plot_dir = create_directory(os.path.join(dirname, 'plots', extension('realistic'), basis)) # Collect initialisation parameters kwargs = { 'level': level, 'synthetic': False, 'noisy_data': bool(args.noisy_data or False), } if basis == 'box':
parser.add_argument("-debug", help="Print all debugging statements") parser.add_argument("-debug_mode", help="Choose debugging mode from 'basic' and 'full'") args = parser.parse_args() # --- Set parameters approach = 'fixed_mesh' level = int(args.level or 0) kwargs = { 'approach': approach, 'level': level, 'num_meshes': int(args.num_meshes or 1), 'plot_pvd': True, 'debug': bool(args.debug or False), 'debug_mode': args.debug_mode or 'basic', } op = IdealisedDesalinationOutfallOptions(**kwargs) # --- Run model tp = AdaptiveDesalinationProblem(op) cpu_timestamp = perf_counter() tp.solve_forward() cpu_time = perf_counter() - cpu_timestamp logstr = "Total CPU time: {:.1f} seconds / {:.1f} minutes / {:.3f} hours\n" logstr = logstr.format(cpu_time, cpu_time / 60, cpu_time / 3600) print_output(logstr) print_output("Quantity of interest: {:.4e}".format(tp.quantity_of_interest()))
Toggle whether to consider timeseries data which has *not* been sampled (default False). """) parser.add_argument("-continuous_timeseries", help="Toggle discrete or continuous timeseries") parser.add_argument("-plot_initial_guess", help="Plot initial guess timeseries") # --- Set parameters # Parsed arguments args = parser.parse_args() basis = args.basis levels = int(args.levels or 3) plot = parser.plotting_args() if len(plot.extensions) == 0: print_output("Nothing to plot.") sys.exit(0) plot_init = bool(args.plot_initial_guess or False) timeseries_type = 'timeseries' if bool(args.continuous_timeseries or False): timeseries_type = '_'.join([timeseries_type, 'smooth']) # Do not attempt to plot in parallel if COMM_WORLD.size > 1: print_output("Will not attempt to plot in parallel.") sys.exit(0) # Collect initialisation parameters if basis == 'box': from adapt_utils.case_studies.tohoku.options.box_options import TohokuBoxBasisOptions constructor = TohokuBoxBasisOptions
from thetis import print_output, COMM_WORLD from turbine_adapt import * from turbine_adapt.adapt import GoalOrientedTidalFarm from options import ArrayOptions import datetime print_output(f"Start time: {datetime.datetime.now()}") # Parse arguments parser = Parser("test_cases/array/run_adapt.py") parser.add_argument( "config", help="Name defining test case configuration", choices=["aligned", "staggered"], ) parser.add_argument( "-c", "--columns", nargs="+", help="Turbine columns to use in QoI", default=[0, 1, 2, 3, 4], ) parser.add_argument( "--no-final-run", help="Skip the final forward run", action="store_true", ) parser.parse_setup() parser.parse_convergence_criteria() parser.parse_metric_parameters()
parser.add_argument( "-levels", help="Number of mesh resolution levels considered (default 3)") parser.add_argument("-noisy_data", help=""" Toggle whether to consider timeseries data which has *not* been sampled (default False). """) # TODO # --- Set parameters # Parsed arguments args = parser.parse_args() bases = args.bases.split(',') levels = int(args.levels or 3) plot = parser.plotting_args() if len(plot.extensions) == 0 or len(bases) == 0: print_output("Nothing to plot.") sys.exit(0) # Do not attempt to plot in parallel if COMM_WORLD.size > 1: print_output("Will not attempt to plot in parallel.") sys.exit(0) # Plotting parameters fontsize = 22 fontsize_tick = 18 fontsize_legend = 18 kwargs = {'markevery': 5} # Paths dirname = os.path.dirname(__file__)