def solve_discrete_adjoint(self): """ Solve the adjoint PDE in the discrete sense, using pyadjoint. """ create_directory('outputs/hdf5/') J = self.quantity_of_interest() compute_gradient(J, Control(self.gradient_field)) tape = get_working_tape() solve_blocks = [block for block in tape._blocks if isinstance(block, SolveBlock) and not isinstance(block, ProjectBlock) and block.adj_sol is not None] N = len(solve_blocks) try: assert N == int(self.end_time/self.dt) except: ValueError("Expected one SolveBlock, but encountered {:d}".format(N)) for i in range(0, N, self.op.dt_per_remesh): self.adjoint_solution.assign(solve_blocks[i].adj_sol) # TODO: annotate in pyadjoint to track progress filename = 'Adjoint2d_{:5s}'.format(index_string(i)) with DumbCheckpoint(os.path.join(self.di, 'hdf5', filename), mode=FILE_CREATE) as sa: sa.store(self.adjoint_solution) sa.close() PETSc.Sys.Print("Storing adjoint solution %d" % i) self.adjoint_solution_file.write(self.adjoint_solution, t=self.op.dt*i) tape.clear_tape()
def __init__(self, mesh, op, finite_element, discrete_adjoint=False, prev_solution=None): self.mesh = op.default_mesh if mesh is None else mesh self.op = op self.finite_element = finite_element self.stab = op.stabilisation self.discrete_adjoint = discrete_adjoint self.prev_solution = prev_solution self.approach = op.approach # Function spaces and mesh quantities self.V = FunctionSpace(self.mesh, self.finite_element) self.P0 = FunctionSpace(self.mesh, "DG", 0) self.P1 = FunctionSpace(self.mesh, "CG", 1) self.P2 = FunctionSpace(self.mesh, "CG", 2) self.P1DG = FunctionSpace(self.mesh, "DG", 1) self.P1_vec = VectorFunctionSpace(self.mesh, "CG", 1) self.P1_ten = TensorFunctionSpace(self.mesh, "CG", 1) self.test = TestFunction(self.V) self.trial = TrialFunction(self.V) self.p0test = TestFunction(self.P0) self.p0trial = TrialFunction(self.P0) self.n = FacetNormal(self.mesh) self.h = CellSize(self.mesh) # Prognostic fields self.solution = Function(self.V, name='Solution') self.adjoint_solution = Function(self.V, name='Adjoint solution') # Outputs self.di = create_directory(self.op.di) self.solution_file = File(self.di + 'solution.pvd') self.adjoint_solution_file = File(self.di + 'adjoint_solution.pvd') self.estimators = {} self.indicators = {}
def __init__(self, problem, op, mesh=None): self.problem = problem self.mesh = mesh assert op is not None self.op = op self.di = create_directory(op.di) # Default tolerances etc self.msg = "Mesh %2d: %7d cells, qoi %.4e, estimator %.4e" self.conv_msg = "Converged after %d iterations due to %s" self.startit = 0 self.minit = 1 self.maxit = 35 self.element_rtol = 0.005 # Following [Power et al 2006] self.qoi_rtol = 0.005 self.estimator_atol = 1e-8 # Logging self.logmsg = '' self.log = True # Data storage self.dat = {'elements': [], 'vertices': [], 'qoi': [], 'estimator': [], 'approach': self.op.approach}
def __init__(self, problem, op, mesh=None): self.problem = problem self.op = op self.mesh = op.default_mesh if mesh is None else mesh self.di = create_directory(self.op.di) # Default tolerances etc self.msg = "{:s} {:.2e} elements {:7d} iter {:2d} time {:6.1f} qoi {:.4e} estimator {:.4e}\n" self.maxit = 35 self.element_rtol = 0.005 # Following [Power et al 2006] self.qoi_rtol = 0.005 self.outer_startit = 0 self.outer_maxit = 4 #self.log = False self.log = True self.base = 10 self.start_error = 1
# Solver 'family': family, 'stabilisation': stabilisation, 'use_wetting_and_drying': False, # QoI 'start_time': float(args.start_time or 1200.0), 'radius': radius, '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)
# 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': from adapt_utils.case_studies.tohoku.options.box_options import TohokuBoxBasisOptions constructor = TohokuBoxBasisOptions elif basis == 'radial': from adapt_utils.case_studies.tohoku.options.radial_options import TohokuRadialBasisOptions constructor = TohokuRadialBasisOptions elif basis == 'okada':
synthetic=False, noisy_data=bool(args.noisy_data or False)) gauges = list(op.gauges.keys()) # Plotting parameters fontsize = 22 fontsize_tick = 18 fontsize_legend = 18 kwargs = {'markevery': 5} # Setup output directories dirname = os.path.join(os.path.dirname(__file__), basis) di = 'realistic' if args.extension is not None: di = '_'.join([di, args.extension]) plot_dir = create_directory( os.path.join(os.path.dirname(__file__), 'plots', di, basis)) di = os.path.join(dirname, 'outputs', di) op.di = os.path.join(di, 'discrete') for fpath in (di, op.di): if not os.path.exists(fpath): raise IOError("Filepath {:s} does not exist.".format(fpath)) # Plot timeseries under initial guess if plot_init: print_output("Plotting initial timeseries against gauge data...") N = int(np.ceil(np.sqrt(len(gauges)))) for level in range(levels): fig, axes = plt.subplots(nrows=N, ncols=N, figsize=(17, 13)) for i, gauge in enumerate(gauges): # Load data
# Solver 'family': family, 'stabilisation': stabilisation, 'use_wetting_and_drying': False, # QoI 'start_time': float(args.start_time or 1200.0), 'radius': radius, 'locations': locations, # I/O and debugging 'debug': bool(args.debug or False), 'debug_mode': args.debug_mode or 'basic', } levels = int(args.levels or 4) di = create_directory( os.path.join(os.path.dirname(__file__), 'outputs', 'uniform')) # --- Loop over mesh hierarchy qois = [] num_cells = [] num_vertices = [] times = [] op = TohokuHazardOptions(level=0, **kwargs) mh = MeshHierarchy(op.default_mesh, levels - 1) for level in range(levels): print_output("Running uniform convergence on level {:d}".format(level)) # Solve swp = AdaptiveTsunamiProblem(op, meshes=mh[level],
l = approach.split("_dwr")[0] l = ["\n".join([config.capitalize(), f"({l})"])] elif len(ext) == 1: l = [f"Column {int(ext)+1}"] else: cols = ", ".join([f"{int(e) + 1}" for e in ext]) l = [f"Columns {cols}"] axes.legend([whiteline], l, loc="upper right", handlelength=0, handletextpad=0, fontsize=18) plt.tight_layout() cmb = "_combined" if parsed_args.combine_plots else "" plot_dir = create_directory(f"plots/{config}/{approach}/{run}") plt.savefig( f"{plot_dir}/{config}_{approach}_power_output_column_{run}_{mode}{cmb}.pdf" ) # Plot legend separately fname = "plots/legend_column.pdf" if not os.path.exists(fname): fig2, axes2 = plt.subplots() legend = axes2.legend(lines, labels, fontsize=18, frameon=False, ncol=5) fig2.canvas.draw() axes2.set_axis_off()
# 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__) extension = lambda fpath: fpath if args.extension is None else '_'.join( [fpath, args.extension]) plot_dir = create_directory( os.path.join(dirname, 'plots', extension('realistic'))) data_dir = os.path.join(dirname, '{:s}', 'outputs', extension('realistic'), 'discrete') # --- Create Options parameter objects options = {basis: {} for basis in bases} kwargs = dict(level=0, noisy_data=bool(args.noisy_data or False)) for basis in bases: if basis == 'box': from adapt_utils.case_studies.tohoku.options.box_options import TohokuBoxBasisOptions options[basis]['op'] = TohokuBoxBasisOptions(**kwargs) options[basis]['label'] = 'Piecewise constant' elif basis == 'radial': from adapt_utils.case_studies.tohoku.options.radial_options import TohokuRadialBasisOptions options[basis]['op'] = TohokuRadialBasisOptions(**kwargs)