def make_bc_fig(inputs_file, ndim=2): inputs = read_inputs(inputs_file) n_cells = string_to_array(inputs['main.num_cells']) nx = n_cells[0] ny = n_cells[1] max_dom_length = max(nx, ny) scaled_nx = nx / max_dom_length scaled_ny = ny / max_dom_length # Start making figure window_width = 9.0 window_height = window_width *0.9* scaled_ny / scaled_nx # window_height=12.0 latexify(fig_width=window_width, fig_height=window_height) fig = plt.figure() # Add domain rectangle ax_width = 0.5 ax_height = ax_width*(scaled_ny/scaled_nx)*(window_width/window_height) ax = fig.add_axes([(1-ax_width)/2.0, 0.25, ax_width, ax_height]) ax.set_axis_off() domain_box = patches.Rectangle((0, 0), 1, 1, fill=False, transform = ax.transAxes, clip_on=False ) ax.add_patch(domain_box) # Add BCs to each side padding = 0.02 for dim in range(0, ndim): for side in range(0, 2): # Defaults horiz_align = 'center' vert_align = 'top' rotate = 0 plus_minus = 1 if side == 0: plus_minus = -1 if dim == 0: # X direction bcs (left/right) # rotate = 90 # ypos = 0.0 rotate = 0 ypos = scaled_ny/2.0 vert_align = 'bottom' if side == 0: horiz_align = 'right' else: horiz_align = 'left' else: ypos = side + padding*plus_minus if dim == 1: # Y direction bcs (top/bottom) xpos = scaled_nx/2.0 rotate = 0 horiz_align = 'center' if side == 0: vert_align = 'top' else: vert_align = 'bottom' else: xpos = side + padding*plus_minus bc_text = make_bc_text(inputs, dim, side) ax.text(xpos, ypos, bc_text, horizontalalignment=horiz_align, verticalalignment=vert_align, rotation = rotate, transform=ax.transAxes) # TODO: label axis extents and add num cells label (e.g 64x64) # Also add dimensionless parameters to the middle of the domain dim_params = 'Dynamics: $Rm_S = %g, Rm_T = %g$ \n $\Pi_H = %g, Da = %g, Pr=%g$, \n ' \ 'Material properties: $Le = %g, c_p = %g, k = %g$, \n' \ 'Thermodynamics: $\mathscr{C}=%g, \mathscr{S}=%g,$ \n'\ 'Phase diagram: $\Gamma=%g, C_i = %g,$ \n $C_e = %g, T_e=%g$ \n' % ( inputs['parameters.rayleighComp'], inputs['parameters.rayleighTemp'], 1.0/inputs['parameters.nonDimReluctance'], inputs['parameters.darcy'], inputs['parameters.prandtl'], inputs['parameters.lewis'], inputs['parameters.specificHeatRatio'], inputs['parameters.heatConductivityRatio'], inputs['parameters.compositionRatio'], inputs['parameters.stefan'], inputs['parameters.liquidusSlope'], inputs['parameters.initialComposition'], inputs['parameters.eutecticComposition'], inputs['parameters.eutecticTemp'] ) if 'heatSource.size' in inputs: dim_params = dim_params + '+ heat source $Q = \\frac{Q_0}{\sigma \sqrt{2 \pi}} \exp\left[ - 0.5 \left( \\frac{x-x_c}{\sigma} \\right)^2 \\right] 0.5 \left( 1 + \\tanh\left[10 (z-(H-h)) \\right]) \\right)$, \n' \ 'where $Q_0=%s,\sigma=%s,x_c=%s,h=%s$' % (inputs['heatSource.size'], inputs['heatSource.width'], inputs['heatSource.xpos'], inputs['heatSource.depth']) ax.text(0.5, 0.4, dim_params, horizontalalignment='center', verticalalignment='center', transform=ax.transAxes) dom_height = float(inputs['main.domain_height']) dom_width = dom_height * n_cells[0]/n_cells[1] ax.text(0.5, 0.85, 'Domain: [%g, %g] with %d x %d cells' % (dom_width, dom_height, n_cells[0], n_cells[1]), horizontalalignment='center', verticalalignment='center', transform=ax.transAxes) figure_full_path = inputs_file + '-auto-generated-visualisation.pdf' print('Saved to %s' % figure_full_path) plt.savefig(figure_full_path, format='pdf') plt.show()
def runTest(base_dir, physical_problem, resolution_specific_params, AMRSetup, num_procs, analysis_command='', extra_params={}, numRestarts=0, params_file='', restart_from_low_res=False): # base_dir should be e.g. # '/network/group/aopp/oceans/AW002_PARKINSON_MUSH/Test/AMRConvergenceTestNoFlow' mushyLayerBaseDir = os.path.abspath(os.pardir) all_params = [] job_ids = [] for setup in AMRSetup: max_level = setup['max_level'] ref_rat = max(setup['ref_rat'], 1) Nzs = setup['Nzs'] runTypes = ['uniform'] if 'run_types' in setup: runTypes = setup['run_types'] # finestRefinement = pow(ref_rat, max_level) maxRefinement = ref_rat**max_level # output_dir = '' Nz_i = -1 # Construct the params files for nz_coarse in Nzs: Nz_i = Nz_i + 1 # Some default options # Use same aspect ratio as already defined # nx_coarse = -1 # if this isn't changed, we'll eventually just use the predetermined aspect ratio # gridFile = '' # defaultParamsFile = os.path.join(mushyLayerBaseDir, '/params/convergenceTest/' + physical_problem + '.parameters') # if os.path.exists(defaultParamsFile): # params = read_inputs(defaultParamsFile) output_dir = '' nx_coarse, params, gridFile = resolution_specific_params( nz_coarse, ref_rat, max_level, maxRefinement) # Default options if nx_coarse == -1: print('Trying to convert to an array: ' + str(params['main.num_cells'])) gridPts = string_to_array(params['main.num_cells']) aspectRatio = gridPts[0] / gridPts[1] nx_coarse = aspectRatio * nz_coarse if not gridFile: gridFile = mushyLayerBaseDir + '/grids/middle/' + str( nz_coarse) + 'x' + str(nz_coarse) # Turn slope limiting off unless we've requested it if 'main.use_limiting' not in params: params['main.use_limiting'] = 'false' # also turn off debug to save disk space, unless we've explicitly asked for it if 'main.debug' not in params: params['main.debug'] = 'false' # Any extra params we may have for k, v in extra_params.iteritems(): params[k] = v #numCellsAMR = str(nx_coarse) + ' ' + str(nz_coarse) + ' 8' numCellsAMR = [int(nx_coarse), int(nz_coarse), 8] gridFileQuarter = mushyLayerBaseDir + '/grids/rightQuarter/' + str( nx_coarse) + 'x' + str(nz_coarse) gridFileThreeLevels = mushyLayerBaseDir + '/grids/rightHalfThreeLevel/' + str( nx_coarse) + 'x' + str(nz_coarse) # numCellsUniform = str(nx_coarse * finestRefinement) + ' ' + str(nz_coarse * finestRefinement) + ' 8' # numCellsUniform = str(nx_coarse) + ' ' + str(nz_coarse) + ' 8' numCellsUniform = [int(nx_coarse), int(nz_coarse), 8] # params['main.gridfile'] = gridFile params['main.num_cells'] = numCellsAMR params['main.max_level'] = str(max_level) params['main.ref_ratio'] = str(ref_rat) + ' ' + str( ref_rat) + ' ' + str(ref_rat) num_proc = num_procs[Nz_i] params['num_proc'] = num_proc if num_proc > 1: optimalGrid = float(nx_coarse) / (float(num_proc) / 2.0) # print('Initial optimal grid guess: %d' % optimalGrid) # increase to next power of 2 while not is_power_of_two(optimalGrid): optimalGrid = optimalGrid + 1 # print('Final optimal grid guess: %d' % optimalGrid) maxGrid = max(16, optimalGrid) # grid size must be greater than the blocking factor maxGrid = max(maxGrid, 2 * int(params['main.block_factor'])) params['main.max_grid_size'] = str(int(maxGrid)) # Now construct vector different param sets param_sets = [] # Run 1: uniform mesh if 'uniform' in runTypes: p0 = dict(params) p0['main.max_level'] = '0' p0['main.num_cells'] = numCellsUniform p0['run_name'] = 'Uniform' p0['concise_run_name'] = 'Uniform' p0['projection.eta'] = 0.0 param_sets.append(p0) # This should do the job for AMR simulations if 'amr' in runTypes: p1 = dict(params) p1['main.reflux_scalar'] = '1' p1['main.use_subcycling'] = '1' p1['main.refluxType'] = '2' p1['projection.eta'] = '0.99' p1['run_name'] = 'AMR-Subcycle-Reflux-Freestream' + str( p1['projection.eta']) + '-MaxLevel' + str(max_level) p1['concise_run_name'] = 'AMR' # p13['main.initialize_VD_corr'] = 'true' # true by default param_sets.append(p1) # Variable mesh if 'variable' in runTypes and max_level == 1: p2 = dict(params) p2['main.reflux_scalar'] = '1' p2['main.use_subcycling'] = '1' p2['main.refluxType'] = '2' p2['projection.eta'] = '0.95' p2['main.gridfile'] = gridFile p2['run_name'] = 'VM-Subcycle-Reflux-Freestream' + str( p2['projection.eta']) + '-MaxLevel' + str(max_level) p2['concise_run_name'] = 'VM' param_sets.append(p2) if 'variable' in runTypes and max_level == 2: p3 = dict(params) p3['main.reflux_scalar'] = '1' p3['main.use_subcycling'] = '1' p3['main.refluxType'] = '2' p3['projection.eta'] = '0.95' p3['main.gridfile'] = gridFileThreeLevels p3['run_name'] = 'VM-Subcycle-Reflux-Freestream' + str( p3['projection.eta']) + '-MaxLevel' + str(max_level) p3['concise_run_name'] = 'VM' param_sets.append(p3) # Do this for all the param sets just made: for p in param_sets: # if num_proc > 1: # p['run_name'] = 'p' + p['run_name'] run_name = p['run_name'] run_name = run_name if int(p['main.max_level']) > 0: run_name = run_name + '-ref' + str(ref_rat) run_name = run_name + '-' + physical_problem + '-' + str( nz_coarse) p['concise_run_name'] = p['concise_run_name'] + str( nz_coarse) + physical_problem p['main.plot_prefix'] = run_name + '-' p['main.chk_prefix'] = 'chk' + p['main.plot_prefix'] # Now add to the full list of param sets all_params.append(p) # Actually run the convergence test #full_output_dir = os.path.join(base_dir, output_dir) full_output_dir = base_dir these_job_ids = amr_convergence_test(all_params, full_output_dir, physical_problem, Nzs, num_procs, numRestarts, analysis_command, restart_from_low_res) # Concatenate lists job_ids = job_ids + these_job_ids # Once all these runs have been submitted, submit the analysis job print('analysis command: %s' % analysis_command) if analysis_command: runAnalysisName = 'runAnalysis.sh' # Don't redo analysis - we may be waiting on runs to finish if os.path.exists(os.path.join(base_dir, runAnalysisName)): print(Fore.YELLOW + 'Analysis job already submitted \n' + Fore.RESET) else: jobName = physical_problem + '-analysis' s = BatchJob(base_dir, jobName, '', 4) s.set_dependency(job_ids) s.set_custom_command(analysis_command) # s.write_slurm_file(runAnalysisName) s.run_task(runAnalysisName) print(Fore.GREEN + 'Submitted analysis job \n' + Fore.RESET) return job_ids
def make_bc_text(inputs, directory, side): scalar_options = ['Dirichlet', 'Neumann', 'InflowOutflow', 'OnlyInflow', 'Robin', 'VariableFlux', 'FixedTemperature', 'TemperatureFlux', 'TemperatureFluxRadation'] scalars = {'enthalpy': 'H', 'bulkConcentration': '\Theta', 'vel': '\mathbf{U}'} BC_TYPES = {'bulkConcentration': scalar_options, 'enthalpy': scalar_options, 'vel': ['$\mathbf{U} = 0$', 'Inflow', 'Outflow', 'OutflowNormal', # only a normal velocity 'InflowOutflow', # both inflow and outflow possible 'noShear', 'Symmetry ($\mathbf{U} \cdot \mathbf{n} = 0$) ', 'Plume inflow', 'Outflow with enforced pressure gradient', 'Pressure head']} sides = ['Lo', 'Hi'] dirs = ['x', 'y'] side_text = sides[side] #bc_text = dirs[dir] + sides[side] variables = ['bulkConcentration', 'enthalpy', 'vel'] var_texts = [] for v in variables: this_var_text = '' bc_type_name = 'bc.%s%s' % (v, side_text) bc_val_name = 'bc.%s%sVal' % (v, side_text) bc_type = string_to_array(inputs[bc_type_name]) bc_type_this_dir = bc_type[directory] bc_type_description = BC_TYPES[v][bc_type_this_dir] # Now we know what the BC is, need to display it sensibly # Default: this_var_text = bc_type_description if v == 'vel': this_var_text = bc_type_description else: bc_val = string_to_array(inputs[bc_val_name], conversion=lambda x: float(x))[directory] perp_dir = directory + 1 if perp_dir > 1: perp_dir = 0 perp_dir_string = dirs[perp_dir] if bc_type_description == 'Dirichlet': this_var_text = 'Fixed: $%s = %.2g$' % (scalars[v], bc_val) elif bc_type_description == 'Neumann': this_var_text = 'No flux: $\mathbf{n} \cdot \\nabla %s = 0$' % scalars[v] elif bc_type_description == 'VariableFlux': this_var_text = 'Variable flux: $\mathbf{n} \cdot \\nabla %s = $ \n $%g (1+\\textrm{tanh}(50(%s-0.75)))$' % (scalars[v], bc_val*0.5, perp_dir_string) elif bc_type_description == 'FixedTemperature': no_flux_limit = string_to_array(inputs['bc.NoFluxLimit%s' % side_text], conversion=lambda x: float(x))[directory] this_var_text = '$ T = %g \; (%s > %g),$ \n $ \mathbf{n} \cdot \\nabla T = 0 \; (%s < %g)$' % ( bc_val, perp_dir_string, no_flux_limit, perp_dir_string, no_flux_limit) elif bc_type_description == 'TemperatureFlux': no_flux_limit = string_to_array(inputs['bc.NoFluxLimit%s' % side_text], conversion=lambda x: float(x))[directory] this_var_text = '$ \mathbf{n} \cdot \\nabla T = %g \; (%s > %g),$ \n $ \mathbf{n} \cdot \\nabla T = 0 \; (%s < %g)$' % ( bc_val, perp_dir_string, no_flux_limit, perp_dir_string, no_flux_limit) var_texts.append(this_var_text) bc_text = ', \n'.join(var_texts) return bc_text