def test_output_parse_2Darray(self): data = ''' Anchor FREQ DELTA -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 Hz 50. 1.0 30.0 34.8 36.3 36.1 34.6 32.0 28.4 23.9 18.5 12.2 5.0 -3.1 -12.3 -22.5 -34.0 -47.2 -63.7 63. 1.0 36.5 41.3 42.8 42.6 41.1 38.5 34.9 30.4 25.0 18.7 11.5 3.4 -5.8 -16.0 -27.5 -40.7 -57.2 80. 1.0 42.8 47.6 49.1 48.9 47.4 44.8 41.2 36.7 31.3 25.0 17.8 9.7 0.5 -9.7 -21.2 -34.4 -50.9 100. 1.0 48.4 53.1 54.7 54.5 53.0 50.4 46.8 42.3 36.9 30.6 23.3 15.2 6.1 -4.2 -15.7 -28.9 -45.4 125. 1.0 53.6 58.3 59.9 59.6 58.1 55.5 52.0 47.5 42.0 35.7 28.5 20.4 11.2 1.0 -10.5 -23.7 -40.2 160. 1.0 58.9 63.7 65.2 65.0 63.5 60.9 57.3 52.8 47.4 41.0 33.8 25.7 16.5 6.3 -5.2 -18.4 -34.9 200. 1.0 63.4 68.1 69.6 69.4 67.9 65.3 61.7 57.2 51.8 45.5 38.3 30.1 21.0 10.7 -0.8 -14.0 -30.5 250. 1.0 67.5 72.2 73.7 73.5 72.0 69.4 65.8 61.3 55.9 49.5 42.3 34.2 25.0 14.8 3.3 -10.0 -26.5 315. 1.0 71.3 76.1 77.6 77.4 75.8 73.2 69.7 65.1 59.7 53.4 46.1 38.0 28.8 18.6 7.1 -6.2 -22.7 400. 1.0 74.9 79.7 81.2 81.0 79.4 76.8 73.2 68.7 63.2 56.9 49.7 41.5 32.4 22.1 10.6 -2.7 -19.2 500. 1.0 77.9 82.7 84.2 83.9 82.4 79.8 76.2 71.6 66.2 59.8 52.6 44.4 35.3 25.0 13.5 0.2 -16.3 630. 1.0 80.7 85.4 86.9 86.6 85.1 82.4 78.8 74.3 68.8 62.5 55.2 47.0 37.9 27.6 16.1 2.8 -13.7 800. 1.0 83.1 87.8 89.2 89.0 87.4 84.8 81.2 76.6 71.1 64.8 57.5 49.3 40.1 29.9 18.3 5.0 -11.5 1000. 1.0 84.9 89.6 91.1 90.8 89.2 86.6 82.9 78.4 72.9 66.5 59.2 51.0 41.8 31.5 20.0 6.6 -9.9 1250. 1.0 86.4 91.1 92.5 92.2 90.7 88.0 84.3 79.7 74.2 67.8 60.5 52.3 43.1 32.8 21.2 7.9 -8.7 1600. 1.0 87.6 92.3 93.7 93.4 91.8 89.1 85.4 80.8 75.2 68.8 61.5 53.3 44.0 33.7 22.1 8.7 -7.9 2000. 1.0 88.4 93.0 94.4 94.0 92.4 89.6 85.9 81.3 75.7 69.3 61.9 53.7 44.4 34.0 22.4 9.0 -7.6 2500. 1.0 88.7 93.3 94.6 94.2 92.6 89.8 86.1 81.4 75.8 69.3 61.9 53.6 44.3 33.9 22.2 8.8 -7.9 3150. 1.0 88.7 93.2 94.5 94.1 92.4 89.5 85.7 81.0 75.4 68.8 61.4 53.0 43.7 33.3 21.5 8.1 -8.6 4000. 1.0 88.3 92.7 94.0 93.5 91.7 88.8 85.0 80.2 74.5 67.9 60.4 52.0 42.5 32.0 20.2 6.7 -10.0 5000. 1.0 87.5 91.9 93.1 92.5 90.7 87.7 83.8 78.9 73.2 66.5 58.9 50.4 40.9 30.4 18.5 4.9 -11.9 6300. 1.0 86.5 90.8 91.9 91.2 89.3 86.2 82.2 77.3 71.4 64.6 57.0 48.4 38.8 28.1 16.2 2.5 -14.5 8000. 1.0 85.3 89.5 90.4 89.6 87.6 84.4 80.2 75.2 69.2 62.3 54.5 45.8 36.1 25.3 13.2 -0.6 -17.7 10000. 1.0 84.2 88.2 89.0 88.1 85.9 82.5 78.3 73.0 66.9 59.9 51.9 43.1 33.2 22.3 10.1 -3.9 -21.1 ''' outfile = open(self.filename, 'w') outfile.write(data) outfile.close() gen = FileParser() gen.set_file(self.filename) # whitespace delim; with end field gen.set_delimiters(' \t') gen.mark_anchor('Anchor') val = gen.transfer_2Darray(3, 2, 26, 19) self.assertEqual(val[0, 1], 30.0) self.assertEqual(val[0, 17], -63.7) self.assertEqual(val[1, 17], -57.2) self.assertEqual(val[23, 17], -21.1) self.assertEqual(val.shape[0], 24) self.assertEqual(val.shape[1], 18) # whitespace delim; no end field val = gen.transfer_2Darray(3, 2, 26) self.assertEqual(val[0, 1], 30.0) self.assertEqual(val[23, 17], -21.1) self.assertEqual(val.shape[0], 24) self.assertEqual(val.shape[1], 18) # column delim; with end field gen.set_delimiters('columns') val = gen.transfer_2Darray(3, 19, 26, 125) self.assertEqual(val[0, 1], 30.0) self.assertEqual(val[0, 17], -63.7) self.assertEqual(val[1, 17], -57.2) self.assertEqual(val[23, 17], -21.1) self.assertEqual(val.shape[0], 24) self.assertEqual(val.shape[1], 18) # column delim; no end field val = gen.transfer_2Darray(3, 19, 26) self.assertEqual(val[0, 1], 30.0) self.assertEqual(val[0, 17], -63.7) self.assertEqual(val[1, 17], -57.2) self.assertEqual(val[23, 17], -21.1) self.assertEqual(val.shape[0], 24) self.assertEqual(val.shape[1], 18) # make sure single line works gen.set_delimiters(' \t') val = gen.transfer_2Darray(5, 3, 5, 5) self.assertEqual(val[0, 2], 49.1) # Small block read val = gen.transfer_2Darray(7, 3, 9, 6) self.assertEqual(val[0, 0], 53.6) self.assertEqual(val[2, 0], 63.4) # Error messages for bad values try: gen.transfer_2Darray(7, 3, 9, 1) except ValueError as err: msg = "fieldend must be greater than fieldstart" self.assertEqual(str(err), msg) else: self.fail('ValueError expected') try: gen.transfer_2Darray(9, 2, 8, 4) except ValueError as err: msg = "rowend must be greater than rowstart" self.assertEqual(str(err), msg) else: self.fail('ValueError expected')
def test_output_parse_2Darray(self): data = ''' Anchor FREQ DELTA -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 -8.5 Hz 50. 1.0 30.0 34.8 36.3 36.1 34.6 32.0 28.4 23.9 18.5 12.2 5.0 -3.1 -12.3 -22.5 -34.0 -47.2 -63.7 63. 1.0 36.5 41.3 42.8 42.6 41.1 38.5 34.9 30.4 25.0 18.7 11.5 3.4 -5.8 -16.0 -27.5 -40.7 -57.2 80. 1.0 42.8 47.6 49.1 48.9 47.4 44.8 41.2 36.7 31.3 25.0 17.8 9.7 0.5 -9.7 -21.2 -34.4 -50.9 100. 1.0 48.4 53.1 54.7 54.5 53.0 50.4 46.8 42.3 36.9 30.6 23.3 15.2 6.1 -4.2 -15.7 -28.9 -45.4 125. 1.0 53.6 58.3 59.9 59.6 58.1 55.5 52.0 47.5 42.0 35.7 28.5 20.4 11.2 1.0 -10.5 -23.7 -40.2 160. 1.0 58.9 63.7 65.2 65.0 63.5 60.9 57.3 52.8 47.4 41.0 33.8 25.7 16.5 6.3 -5.2 -18.4 -34.9 200. 1.0 63.4 68.1 69.6 69.4 67.9 65.3 61.7 57.2 51.8 45.5 38.3 30.1 21.0 10.7 -0.8 -14.0 -30.5 250. 1.0 67.5 72.2 73.7 73.5 72.0 69.4 65.8 61.3 55.9 49.5 42.3 34.2 25.0 14.8 3.3 -10.0 -26.5 315. 1.0 71.3 76.1 77.6 77.4 75.8 73.2 69.7 65.1 59.7 53.4 46.1 38.0 28.8 18.6 7.1 -6.2 -22.7 400. 1.0 74.9 79.7 81.2 81.0 79.4 76.8 73.2 68.7 63.2 56.9 49.7 41.5 32.4 22.1 10.6 -2.7 -19.2 500. 1.0 77.9 82.7 84.2 83.9 82.4 79.8 76.2 71.6 66.2 59.8 52.6 44.4 35.3 25.0 13.5 0.2 -16.3 630. 1.0 80.7 85.4 86.9 86.6 85.1 82.4 78.8 74.3 68.8 62.5 55.2 47.0 37.9 27.6 16.1 2.8 -13.7 800. 1.0 83.1 87.8 89.2 89.0 87.4 84.8 81.2 76.6 71.1 64.8 57.5 49.3 40.1 29.9 18.3 5.0 -11.5 1000. 1.0 84.9 89.6 91.1 90.8 89.2 86.6 82.9 78.4 72.9 66.5 59.2 51.0 41.8 31.5 20.0 6.6 -9.9 1250. 1.0 86.4 91.1 92.5 92.2 90.7 88.0 84.3 79.7 74.2 67.8 60.5 52.3 43.1 32.8 21.2 7.9 -8.7 1600. 1.0 87.6 92.3 93.7 93.4 91.8 89.1 85.4 80.8 75.2 68.8 61.5 53.3 44.0 33.7 22.1 8.7 -7.9 2000. 1.0 88.4 93.0 94.4 94.0 92.4 89.6 85.9 81.3 75.7 69.3 61.9 53.7 44.4 34.0 22.4 9.0 -7.6 2500. 1.0 88.7 93.3 94.6 94.2 92.6 89.8 86.1 81.4 75.8 69.3 61.9 53.6 44.3 33.9 22.2 8.8 -7.9 3150. 1.0 88.7 93.2 94.5 94.1 92.4 89.5 85.7 81.0 75.4 68.8 61.4 53.0 43.7 33.3 21.5 8.1 -8.6 4000. 1.0 88.3 92.7 94.0 93.5 91.7 88.8 85.0 80.2 74.5 67.9 60.4 52.0 42.5 32.0 20.2 6.7 -10.0 5000. 1.0 87.5 91.9 93.1 92.5 90.7 87.7 83.8 78.9 73.2 66.5 58.9 50.4 40.9 30.4 18.5 4.9 -11.9 6300. 1.0 86.5 90.8 91.9 91.2 89.3 86.2 82.2 77.3 71.4 64.6 57.0 48.4 38.8 28.1 16.2 2.5 -14.5 8000. 1.0 85.3 89.5 90.4 89.6 87.6 84.4 80.2 75.2 69.2 62.3 54.5 45.8 36.1 25.3 13.2 -0.6 -17.7 10000. 1.0 84.2 88.2 89.0 88.1 85.9 82.5 78.3 73.0 66.9 59.9 51.9 43.1 33.2 22.3 10.1 -3.9 -21.1 ''' outfile = open(self.filename, 'w') outfile.write(data) outfile.close() gen = FileParser() gen.set_file(self.filename) # whitespace delim; with end field gen.set_delimiters(' \t') gen.mark_anchor('Anchor') val = gen.transfer_2Darray(3, 2, 26, 19) self.assertEqual(val[0, 1], 30.0) self.assertEqual(val[0, 17], -63.7) self.assertEqual(val[1, 17], -57.2) self.assertEqual(val[23, 17], -21.1) self.assertEqual(val.shape[0], 24) self.assertEqual(val.shape[1], 18) # whitespace delim; no end field val = gen.transfer_2Darray(3, 2, 26) self.assertEqual(val[0, 1], 30.0) self.assertEqual(val[23, 17], -21.1) self.assertEqual(val.shape[0], 24) self.assertEqual(val.shape[1], 18) # column delim; with end field gen.set_delimiters('columns') val = gen.transfer_2Darray(3, 19, 26, 125) self.assertEqual(val[0, 1], 30.0) self.assertEqual(val[0, 17], -63.7) self.assertEqual(val[1, 17], -57.2) self.assertEqual(val[23, 17], -21.1) self.assertEqual(val.shape[0], 24) self.assertEqual(val.shape[1], 18) # column delim; no end field val = gen.transfer_2Darray(3, 19, 26) self.assertEqual(val[0, 1], 30.0) self.assertEqual(val[0, 17], -63.7) self.assertEqual(val[1, 17], -57.2) self.assertEqual(val[23, 17], -21.1) self.assertEqual(val.shape[0], 24) self.assertEqual(val.shape[1], 18) # make sure single line works gen.set_delimiters(' \t') val = gen.transfer_2Darray(5, 3, 5, 5) self.assertEqual(val[0, 2], 49.1) # Small block read val = gen.transfer_2Darray(7, 3, 9, 6) self.assertEqual(val[0, 0], 53.6) self.assertEqual(val[2, 0], 63.4) # Error messages for bad values try: gen.transfer_2Darray(7, 3, 9, 1) except ValueError as err: msg = "fieldend must be greater than fieldstart" self.assertEqual(str(err), msg) else: self.fail('ValueError expected') try: gen.transfer_2Darray(9, 2, 8, 4) except ValueError as err: msg = "rowend must be greater than rowstart" self.assertEqual(str(err), msg) else: self.fail('ValueError expected')
def compute(self, inputs, outputs): # Results Folder creation if needed -------------------------------------------------------- result_folder_path = self.options[OPTION_RESULT_FOLDER_PATH] if result_folder_path != "": os.makedirs(result_folder_path, exist_ok=True) # Creation of the temporary directory ------------------------------------------------------ tmp_dir = TemporaryDirectory() if self.options[OPTION_AVL_EXE_PATH] != "": copy_resource(xfoil_resources, _PROFILE_FILE_NAME, tmp_dir.name) self.options["command"] = [self.options[OPTION_AVL_EXE_PATH]] else: copy_resource(avl336, _AVL_EXE_NAME, tmp_dir.name) copy_resource(xfoil_resources, _PROFILE_FILE_NAME, tmp_dir.name) self.options["command"] = [pth.join(tmp_dir.name, _AVL_EXE_NAME)] self.stdin = pth.join(tmp_dir.name, _STDIN_FILE_NANE) self.stdout = pth.join(tmp_dir.name, _STDOUT_FILE_NAME) self.stderr = pth.join(tmp_dir.name, _STDERR_FILE_NAME) # AVL geometry file (.avl) creation -------------------------------------------------------- input_geom_file = pth.join(tmp_dir.name, _AVL_GEOM_NAME) profile_file = pth.join(tmp_dir.name, _PROFILE_FILE_NAME) self._get_avl_geom_file(inputs, input_geom_file, _PROFILE_FILE_NAME) # AVL session file creation ---------------------------------------------------------------- s_ref = inputs["data:geometry:wing:area"] b_ref = inputs["data:geometry:wing:span"] c_ref = inputs["data:geometry:wing:MAC:length"] mach = inputs["data:aerostructural:load_case:mach"] alt = inputs["data:aerostructural:load_case:altitude"] rho = Atm(alt).density vtas = Atm(alt).speed_of_sound * mach q = 0.5 * rho * vtas ** 2 m_lc = inputs["data:aerostructural:load_case:weight"] nz = inputs["data:aerostructural:load_case:load_factor"] cl = nz * m_lc * g / (q * s_ref) tmp_result_file = pth.join(tmp_dir.name, self.options[OPTION_RESULT_AVL_FILENAME]) parser = InputFileGenerator() with path(ressources, _STDIN_FILE_NANE) as stdin_template: parser.set_template_file(stdin_template) parser.set_generated_file(self.stdin) # Update session file with target values: parser.mark_anchor("LOAD") parser.transfer_var(input_geom_file, 1, 1) parser.mark_anchor("OPER") parser.transfer_var(float(cl), 1, 3) parser.mark_anchor("M") parser.transfer_var(float(mach), 1, 2) parser.transfer_var(float(vtas), 2, 2) parser.transfer_var(float(rho), 3, 2) parser.mark_anchor("W") parser.transfer_var(tmp_result_file, 1, 1) parser.generate() # Check for input and output file presence ------------------------------------------------- self.options["external_input_files"] = [ self.stdin, input_geom_file, profile_file, ] self.options["external_output_files"] = [tmp_result_file] # Launch AVL ------------------------------------------------------------------------------- super().compute(inputs, outputs) # Gather results --------------------------------------------------------------------------- parser_out = FileParser() parser_out.set_file(tmp_result_file) parser_out.mark_anchor("Alpha =") aoa = parser_out.transfer_var(0, 3) parser_out.mark_anchor("CLtot =") outputs["data:aerostructural:aerodynamic:CL"] = parser_out.transfer_var(0, 3) parser_out.mark_anchor("CDind =") outputs["data:aerostructural:aerodynamic:CDi"] = parser_out.transfer_var(0, 6) outputs["data:aerostructural:aerodynamic:Oswald_Coeff"] = parser_out.transfer_var(2, 6) for (comp, sect) in zip(self.options["components"], self.options["components_sections"]): size = sect # default number of section for non symmetric components if comp in ("wing", "horizontal_tail", "strut"): size = sect * 2 # number of sections doubled for symmetric components elif comp == "fuselage": size = 4 # particular case for fuselage due to specific VLM modelling avl_comp = AVL_COMPONENT_NAMES[comp] parser_out.mark_anchor(avl_comp) comp_coef = parser_out.transfer_2Darray(0, 3, size - 1, 8) # Reorganise result array to have coefficient in direct axis order comp_coef[:, :] = comp_coef[:, [1, 3, 0, 5, 2, 4]] # Comvert coefficients into forces and moments comp_coef[:, :3] *= q * s_ref comp_coef[:, [3, 5]] *= q * s_ref * b_ref comp_coef[:, 4] *= q * s_ref * c_ref # Change forces and moment from aerodynamic to body axis r_mat = self._get_rotation_matrix(aoa * degree, axis="y") comp_coef[:, :3] = np.dot(comp_coef[:, :3], r_mat) comp_coef[:, 3:] = np.dot(comp_coef[:, 3:], r_mat) # Moments in std axis ie X fwd outputs["data:aerostructural:aerodynamic:" + comp + ":forces"] = comp_coef # outputs["data:aerostructural:aerodynamic:forces"] = q * s_ref * surface_coef # Store input and result files if necessary ------------------------------------------------ if self.options[OPTION_RESULT_FOLDER_PATH]: if pth.exists(tmp_result_file): forces_file = pth.join(result_folder_path, self.options[OPTION_RESULT_AVL_FILENAME]) shutil.move(tmp_result_file, forces_file) if pth.exists(input_geom_file): geometry_file = pth.join(result_folder_path, _AVL_GEOM_NAME) shutil.move(input_geom_file, geometry_file) if pth.exists(self.stdin): stdin_path = pth.join(result_folder_path, _STDIN_FILE_NANE) shutil.move(self.stdin, stdin_path) if pth.exists(self.stdout): stdout_path = pth.join(result_folder_path, _STDOUT_FILE_NAME) shutil.move(self.stdout, stdout_path) if pth.exists(self.stderr): stderr_path = pth.join(result_folder_path, _STDERR_FILE_NAME) shutil.move(self.stderr, stderr_path) tmp_dir.cleanup()