Coverage for steam_pysigma\MainPySIGMA.py: 47%

59 statements  

« prev     ^ index     » next       coverage.py v7.4.3, created at 2024-12-16 17:09 +0100

1# STEAM PySigma is a python wrapper of STEAM-SIGMA written in Java. 

2# Copyright (C) 2023, CERN, Switzerland. All rights reserved. 

3# 

4# This program is free software: you can redistribute it and/or modify 

5# it under the terms of the GNU General Public License as published by 

6# the Free Software Foundation, version 3 of the License. 

7# 

8# This program is distributed in the hope that it will be useful, 

9# but WITHOUT ANY WARRANTY; without even the implied warranty of 

10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

11# GNU General Public License for more details. 

12# 

13# You should have received a copy of the GNU General Public License 

14# along with this program. If not, see <https://www.gnu.org/licenses/>. 

15 

16import os 

17from pathlib import Path 

18import logging 

19import subprocess 

20 

21from steam_pysigma.comsol.BuildComsolModel import BuildComsolModel 

22from steam_pysigma.data import DataPySIGMA as dS 

23from steam_pysigma.utils.Utils import get_user_settings, read_data_from_yaml 

24from steam_pysigma.utils.Utils import make_folder_if_not_existing 

25 

26class MainPySIGMA: 

27 """ 

28 Class to generate SIGMA models 

29 """ 

30 

31 def __init__(self, model_folder: str = None, verbose: bool = False): 

32 """ 

33 

34 :param input_file_path: path to input yaml file 

35 :param input_coordinates_path: path to file with coordinates to evaluate B_field 

36 :param model_folder: Output path of java files and mph model. 

37 :param path_to_results: location of comsol-generated results 

38 :param verbose: 

39 """ 

40 

41 logger = logging.getLogger() 

42 if verbose: 

43 logger.setLevel(logging.INFO) 

44 else: 

45 logger.setLevel(logging.DEBUG) 

46 

47 self.model_folder = model_folder 

48 make_folder_if_not_existing(self.model_folder) 

49 

50 def build(self, input_yaml_file_path: str = None, input_coordinates_path=None, results_folder_name=None, settings=None): 

51 """ 

52 Triggers building of Comsol model 

53 """ 

54 dm = read_data_from_yaml(input_yaml_file_path, dS.DataPySIGMA) 

55 input_folder_path = os.path.dirname(input_yaml_file_path) 

56 sdm = read_data_from_yaml(f'{os.path.splitext(input_yaml_file_path)[0]}.set', dS.MultipoleSettings) 

57 roxie_data = read_data_from_yaml(f'{os.path.splitext(input_yaml_file_path)[0]}.geom', dS.SIGMAGeometry) 

58 bh_curve_database = Path(input_folder_path, dm.Sources.bh_curve_source).resolve() 

59 if not os.path.exists(bh_curve_database): 

60 raise Exception(f'Path to bh_curve_source specified in the input file {input_yaml_file_path} is: {bh_curve_database}, but it does not exist!') 

61 if results_folder_name: 

62 path_to_results = os.path.join(self.model_folder, results_folder_name) 

63 else: 

64 path_to_results = self.model_folder 

65 make_folder_if_not_existing(path_to_results) 

66 if not settings: 

67 settings_folder = os.path.join(Path(__file__).parent.parent, 'tests') 

68 settings = get_user_settings(settings_folder) 

69 BuildComsolModel(model_data=dm, input_conductor_params=sdm, settings=settings, 

70 output_path=self.model_folder, path_to_results=path_to_results, 

71 input_coordinates_path=input_coordinates_path, roxie_data=roxie_data, 

72 bh_curve_database=bh_curve_database) 

73 

74 def run_pysigma(self, magnet_name): 

75 # Establish necessary paths 

76 batch_file_path = os.path.join(self.model_folder, f"{magnet_name}_Model_Compile_and_Open.bat") 

77 print(f'Running Comsol model via: {batch_file_path}') 

78 current_path = os.getcwd() 

79 os.chdir(self.model_folder) # must change path to the folder with .bat file otherwise it does not work 

80 proc = subprocess.Popen([batch_file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, 

81 universal_newlines=True) 

82 (stdout, stderr) = proc.communicate() 

83 log_file_path = os.path.join(self.model_folder, "log_bat_file.txt") 

84 error = False 

85 if proc.returncode != 0: 

86 print(stderr) 

87 raise ValueError( 

88 f"Batch file throws an error, COMSOL model could not be completed! Review error at {log_file_path}.") 

89 else: 

90 print(stdout) 

91 error_lines = [] 

92 for line in stdout.split('\n'): 

93 if "error" in line.lower(): 

94 error = True 

95 if error: 

96 error_lines.append(line) 

97 with open(log_file_path, 'w') as logfile: 

98 logfile.write(stdout) 

99 os.chdir(current_path) 

100 if error: 

101 # Additional code to format error_lines into a readable message 

102 error_message = '\n'.join(error_lines) 

103 error_message = error_message[:200] # Limit error_message to 200 characters 

104 raise ValueError( 

105 f"Batch file throws an error, COMSOL model could not be completed! Error message:\n{error_message}...\nReview full log at {log_file_path}.") 

106 else: 

107 print(f"Running batch file passes! See log file at {log_file_path}.")