def standard_run(args): """ High-level function to run a standard analysis Args: :args: (obj) Instance of form 'StdRunArgs' Returns: :results: (dict) Results from static analysis """ # ===== Logging ===== hlogger.init(log_filename="log.txt", level=args) logger = logging.getLogger() logger.info(hlogger.decorate(f"{__prog_name__} {__version__}")) # ===== Initialise ===== settings = Settings(root_dir=args.dest) cfd_wrapper, stru_wrapper = settings.get_wrappers() # ===== Clean up before running a new analysis ===== if args.clean or args.clean_only: logger.info("Removing old files...") cfd_wrapper.clean() stru_wrapper.clean() if args.clean_only: logger.info("Exiting...") return # ===== Run the aeroelastic analysis ===== settings_static = settings.settings.get('general_settings', {}).get('static_loop', {}) static = StaticAeroelasticity(cfd_wrapper, stru_wrapper, **settings_static) results = static.find_equilibrium() return results
def find_equilibrium(self): """ Find a static equilibrium Note: This function iteratively computes deflections and loads until the deflection has converged or a maximum number of iterations is reached Returns: :results: dictionary with results provided by the CFD and structure modules """ logger.info("Initialising loop...") logger.info("Load analysis without deformation...") self.cfd.run_analysis(turn_off_deform=True) n = 1 has_converged = False while True: logger.info(decorate(f"===== Loop {n} =====", '\n', 3, 2)) logger.info("--> Structure analysis...") self.stru.run_analysis() # Check convergence after the structure analysis max_abs_def_diff = self.stru.get_max_abs_diff() logger.info( f"The maximum abs. difference is {(max_abs_def_diff):.5f}") logger.info("--> Load analysis...") self.cfd.run_analysis() n += 1 if abs(max_abs_def_diff) < self.abs_conv_lim: logger.info(f"Solution has converged (loop {n})...") has_converged = True break elif n > self.max_iters: logger.warning( f"Maximum number of iterations ({self.max_iters}) reached. Aborting." ) break results = { "loop": n - 1, "has_converged": has_converged, "cfd": self.cfd.last_solution, "structure": self.stru.last_solution, } return results
def standard_run(args): """ Run a standard analysis Args: :args: arguments (see StdRunArgs()) """ # ===== Setup ===== settings = get_settings(settings_filepath=args.run) hlogger.init(settings.paths('f_log'), level=args) logger = logging.getLogger(__name__) logger.info(hlogger.decorate(f"{__prog_name__} {__version__}")) # ===== Setup aircraft model and flight state ===== aircraft = io.cpacs.aircraft.load( settings) if settings.aircraft_is_cpacs else io.native.aircraft.load( settings) state = io.cpacs.state.load( settings) if settings.state_is_cpacs else io.native.state.load( settings) # TODO: load as part of aircraft definition if settings.settings['deformation']: io.native.deformation.load(aircraft, settings) # ===== Generate lattice ===== vlmdata = VLMData() vlm.set_autopanels(aircraft, settings) # ----- Iterate through the flight states ----- for i, cur_state in enumerate(state.iter_states()): settings.paths.counter = i ########################################################## # TODO: Temporary workaround! settings.paths('d_results', make_dirs=True, is_dir=True) settings.paths('d_plots', make_dirs=True, is_dir=True) ########################################################## ########################################################## # TODO: Don't set refs here. Find better solution! cur_state.refs = aircraft.refs ########################################################## ########################################################## # TODO: Find better solution for pre_panelling() function make_new_subareas = True if i == 0 else False ########################################################## lattice = vlm.gen_lattice(aircraft, cur_state, settings, make_new_subareas) # ===== VLM ===== vlm.calc_downwash(lattice, vlmdata) vlm.calc_boundary(lattice, cur_state, vlmdata) # right-hand side terms vlm.solver(vlmdata) vlm.calc_results(lattice, cur_state, vlmdata) # ===== Create plots and result files ===== io.native.results.save_all(settings, aircraft, cur_state, vlmdata) makeplots.make_all(settings, aircraft, cur_state, vlmdata, lattice) ############################################### # TODO: Find better solution ############################################### # Save AeroPerformance map results state.results['Fx'].append(vlmdata.forces['x']) state.results['Fy'].append(vlmdata.forces['y']) state.results['Fz'].append(vlmdata.forces['z']) state.results['FD'].append(vlmdata.forces['D']) state.results['FC'].append(vlmdata.forces['C']) state.results['FL'].append(vlmdata.forces['L']) state.results['Mx'].append(vlmdata.forces['l']) state.results['My'].append(vlmdata.forces['m']) state.results['Mz'].append(vlmdata.forces['n']) #### state.results['Cx'].append(vlmdata.coeffs['x']) state.results['Cy'].append(vlmdata.coeffs['y']) state.results['Cz'].append(vlmdata.coeffs['z']) state.results['CD'].append(vlmdata.coeffs['D']) state.results['CC'].append(vlmdata.coeffs['C']) state.results['CL'].append(vlmdata.coeffs['L']) state.results['Cl'].append(vlmdata.coeffs['l']) state.results['Cm'].append(vlmdata.coeffs['m']) state.results['Cn'].append(vlmdata.coeffs['n']) ############################################### # ---------- Save aeroperformance map ---------- if settings.aircraft_is_cpacs and settings.state_is_cpacs: io.cpacs.results.save_aeroperformance_map(state, settings) if settings.settings['save_results']['aeroperformance']: io.native.results.save_aeroperformance_map(state, settings) logger.info(f"{__prog_name__} {__version__} terminated") # ---------- Return data to caller ---------- results = { "lattice": lattice, "vlmdata": vlmdata, "state": state, "settings": settings, } return results
def standard_run(args=None, filestructure=None, model=None): """ Standard procedure Args: :args: arguments (see class 'StdRunArgs') :filestructure: file structure """ # ===== Initialise ===== filecheck = True if args is None: args = StdRunArgs() if args.filename is None: args.filename = DEFAULT_MODEL_FILENAME filecheck = False if filestructure is None: filestructure = get_filestructure(args.filename, filecheck) # TODO : MAKE BETTER if args.no_plots: make_plots = False else: make_plots = True # ===== Logging ===== hlogger.init(filestructure.files['log'], level=args) logger = logging.getLogger(__name__) # ===== LOAD THE MODEL ===== logger.info(hlogger.decorate(f"{__prog_name__} {__version__}")) if model is None: model = fmodel.load(filestructure.files['main'], validate_infile=args.no_schema_check) # ===== LOAD AND CREATE THE MODEL ===== material_db = Materials.from_model_entry(model['materialdata']) profile_db = Profiles.from_model_entry(model['profildata']) frame = Frame(model['beamlines'], model['boundary_conditions'], model['acceleration'], material_db, profile_db) # ===== SOLVE SYSTEM OF EQUATIONS ===== analyses = model.get('analysis', None) if analyses.get('static', False): U, F_react = static_load_analysis(frame) frame.deformation.U = U # ===== POSTPROCESSING ===== # ----- Save results ----- save_results = model.get('postproc', {}).get('save_results', False) if save_results: save.save_all(frame, save_results, filestructure) # ----- Create plots ----- plots = model.get('postproc', {}).get('plots', False) if plots and make_plots: plot.plot_all(frame, plots, filestructure) # ===== RETURN DATA TO CALLER ===== return_dict = {} return_dict['frame'] = frame return return_dict