From f7fb80f3681173fff47ebff7588ae0fcc8be7cce Mon Sep 17 00:00:00 2001 From: Joseph Chang Date: Wed, 18 Jun 2025 17:03:32 -0500 Subject: [PATCH 01/27] accert setup confirmation --- src/Main.py | 10 +++++----- src/{accertdb.sql => accert_db.sql} | 0 src/setup_accert.sh | 16 +++++++--------- src/workbench.sh | 2 +- 4 files changed, 13 insertions(+), 15 deletions(-) rename src/{accertdb.sql => accert_db.sql} (100%) diff --git a/src/Main.py b/src/Main.py index 37bebc3..6a2c33d 100755 --- a/src/Main.py +++ b/src/Main.py @@ -1377,7 +1377,7 @@ def process_reference_model(self, c, ut, accert): print('[USER_INPUT]', 'Reference model is', str(accert.ref_model.value), '\n') self.setup_table_names(accert) - ut.setup_table_names(c, Accert) + ut.setup_table_names(c, self) # if ref.model is not fusion or user defined then process cost elements: if self.cel_tabl: ut.print_user_request_parameter(c) @@ -1748,7 +1748,7 @@ def generate_results(self, c, ut, accert): accert : ACCERT xml2obj class instantiates objects that can parse the ACCERT XML file. """ - model = Accert.ref_model + model = self.ref_model if model: # generate results for the models in the future we can add more models self._generate_common_results(c, ut, accert, model) @@ -1949,11 +1949,11 @@ def generate_results_table(self, c, conn, level=3): c = conn.cursor() ut = Utility_methods() accert_path = os.path.abspath(os.path.join(code_folder, os.pardir)) - user_input = sys.argv[2] + user_input = sys.argv[1] if os.path.exists(user_input): input_path = os.path.abspath(user_input) else: print('ACCERT did not find the input file {}'.format(user_input)) raise SystemExit - Accert = Accert(input_path,accert_path) - Accert.execute_accert(c,ut) \ No newline at end of file + accert_instance = Accert(input_path,accert_path) + accert_instance.execute_accert(c,ut) \ No newline at end of file diff --git a/src/accertdb.sql b/src/accert_db.sql similarity index 100% rename from src/accertdb.sql rename to src/accert_db.sql diff --git a/src/setup_accert.sh b/src/setup_accert.sh index 0556548..627276c 100755 --- a/src/setup_accert.sh +++ b/src/setup_accert.sh @@ -28,8 +28,8 @@ fi # 4) Find conda conda_path="${workbench_path}/rte/conda" if [ ! -d "$conda_path" ]; then - echo -e "${RED}Error: conda directory not found in workbench_path${NC}" - exit 1 + echo -e "${YELLOW}Warning: conda directory not found in workbench_path, skipping conda-based installation${NC}" + echo -e "${YELLOW}Using system pip instead${NC}" else echo -e "${GREEN}conda directory found: $conda_path${NC}" fi @@ -40,18 +40,16 @@ ACCERT_DIR=$(pwd) echo -e "${GREEN}ACCERT_DIR set to: $ACCERT_DIR${NC}" # 6) Use the pip in conda/bin to install requirement.txt located in the parent folder of this shell script -echo -e "${GREEN}Installing requirements from $ACCERT_DIR/../requirement.txt...${NC}" -if [ -x "$conda_path/bin/pip" ]; then +echo -e "${GREEN}Installing requirements from $ACCERT_DIR/../requirements.txt...${NC}" +if [ -d "$conda_path" ] && [ -x "$conda_path/bin/pip" ]; then "$conda_path/bin/pip" install -r "$ACCERT_DIR/../requirements.txt" -elif [ -x "$conda_path/Scripts/pip" ]; then +elif [ -d "$conda_path" ] && [ -x "$conda_path/Scripts/pip" ]; then "$conda_path/Scripts/pip" install -r "$ACCERT_DIR/../requirements.txt" else - print_color "$RED" "Error: pip executable not found in conda directory" + echo -e "${YELLOW}Using system pip to install requirements${NC}" + pip install -r "$ACCERT_DIR/../requirements.txt" fi -echo -e "${GREEN}Installing requirements from $ACCERT_DIR/../requirement.txt...${NC} using system pip" -pip install -r "$ACCERT_DIR/../requirements.txt" - # 7) Create another file called 'install.conf' in current folder echo -e "${GREEN}Creating install.conf...${NC}" cat > install.conf << EOL diff --git a/src/workbench.sh b/src/workbench.sh index fb9bb24..773ac8d 100644 --- a/src/workbench.sh +++ b/src/workbench.sh @@ -4,4 +4,4 @@ ######################################################################## # Provide path to workbench-.app/Contents for macOS -workbench_path="/Applications/Workbench-5.4.0.app/Contents" \ No newline at end of file +workbench_path="/Applications/Workbench-5.5.1.app/Contents" \ No newline at end of file From fa15661525bd6d13b23c3ee43565835117e87b36 Mon Sep 17 00:00:00 2001 From: Joseph Chang Date: Thu, 19 Jun 2025 14:55:31 -0500 Subject: [PATCH 02/27] Update setup_accert.sh --- src/setup_accert.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/setup_accert.sh b/src/setup_accert.sh index 627276c..06d5cb8 100755 --- a/src/setup_accert.sh +++ b/src/setup_accert.sh @@ -7,7 +7,7 @@ YELLOW='\033[0;33m' NC='\033[0m' # No color # 1) Gather workbench_path from workbench.sh -workbench_path=$(grep "workbench_path" workbench.sh | cut -d '=' -f 2 | tr -d '"') +workbench_path=$(grep "workbench_path" "$(dirname "$0")/workbench.sh" | cut -d '=' -f 2 | tr -d '"') # 2) Check that workbench_path was retrieved if [ -z "$workbench_path" ]; then @@ -54,7 +54,7 @@ fi echo -e "${GREEN}Creating install.conf...${NC}" cat > install.conf << EOL [INSTALL] -PASSWD = yourpassword +PASSWD = Wkdeogh0711# # NOTE: ALL OTHER information should be set up later # INSTALL_PATH = /usr/local From 36c36274697fe1f01084b4e29c21c71dd8c4027a Mon Sep 17 00:00:00 2001 From: Joseph Chang Date: Thu, 19 Jun 2025 15:13:56 -0500 Subject: [PATCH 03/27] Refactor file paths in tests to use os.path for better portability --- test/conftest.py | 2 +- test/test_integration.py | 8 ++++++-- test/test_main.py | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index 0696730..ff02ab0 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -8,7 +8,7 @@ @pytest.fixture def input_params_data(): - input_params_file = "./OT01A_i1_r5_rev6.csv" + input_params_file = os.path.join(os.path.dirname(__file__), "OT01A_i1_r5_rev6.csv") return pd.read_csv(input_params_file).set_index("var_name").transpose() diff --git a/test/test_integration.py b/test/test_integration.py index 6fac3b9..41306f0 100644 --- a/test/test_integration.py +++ b/test/test_integration.py @@ -6,7 +6,11 @@ def run_accert_and_check_output(input_file, expected_output_file): """Helper function to run ACCERT, check output file, and compare with expected result.""" # Define the command to run the ACCERT script - command = ["python", "../src/Main.py", "-i", input_file] + main_py_path = os.path.join(os.path.dirname(__file__), '..', 'src', 'Main.py') + input_file_path = os.path.join(os.path.dirname(__file__), '..', 'tutorial', os.path.basename(input_file)) + expected_output_file_path = os.path.join(os.path.dirname(__file__), expected_output_file) + + command = ["python", main_py_path, input_file_path] # Run the command result = subprocess.run(command, capture_output=True, text=True) @@ -18,7 +22,7 @@ def run_accert_and_check_output(input_file, expected_output_file): # Compare output.out content with expected output with open("output.out", "r") as output_file: output_content = output_file.read() - with open(expected_output_file, "r") as expected_output: + with open(expected_output_file_path, "r") as expected_output: expected_output_content = expected_output.read() # compare the content of the output.out file with the expected output diff --git a/test/test_main.py b/test/test_main.py index a7dc4a3..f56ff5a 100644 --- a/test/test_main.py +++ b/test/test_main.py @@ -9,8 +9,8 @@ ut = Utility_methods() -accert_path = os.path.dirname(os.getcwd()) -input_path = os.path.join(os.getcwd(), 'accert_unit_test_input.son') +accert_path = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) +input_path = os.path.join(os.path.dirname(__file__), 'accert_unit_test_input.son') accert = Accert(input_path, accert_path) accert.ref_model = 'pwr12-be' accert.acc_tabl = 'account' From def5e7f2c8fa53084c6379430a2fb9c6cfc97d52 Mon Sep 17 00:00:00 2001 From: Joseph Chang Date: Thu, 19 Jun 2025 15:54:41 -0500 Subject: [PATCH 04/27] msr model add (placeholder) --- src/Algorithm/MsrFunc.py | 319 ++++++++++++++++++++++++++++++++++++++ src/Algorithm/__init__.py | 1 + src/Main.py | 8 + src/etc/accert.sch | 2 +- tutorial/MSR.son | 18 +++ 5 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 src/Algorithm/MsrFunc.py create mode 100644 tutorial/MSR.son diff --git a/src/Algorithm/MsrFunc.py b/src/Algorithm/MsrFunc.py new file mode 100644 index 0000000..55760ad --- /dev/null +++ b/src/Algorithm/MsrFunc.py @@ -0,0 +1,319 @@ +import numpy as np +from .Algorithm import Algorithm + +class MsrFunc(Algorithm): + def __init__(self, ind, alg_name, alg_for, alg_description, alg_formulation, alg_units, variables, constants): + super().__init__(ind, alg_name, alg_for, alg_description, alg_formulation, alg_units, variables, constants) + + def run(self, inputs: dict) -> float: + """ + Executes the algorithm specified by the name in the instance variables. + + Parameters: + inputs (dict): Dictionary of input variables required for the algorithm. + + Returns: + float: Result of the algorithm computation. + """ + # run the algorithm use self.name not self.alg_name + return self._run_algorithm(self.name, [inputs[var] for var in self.variables.split(",")]) + + def _run_algorithm(self, alg_name: str, variables: list) -> float: + """ + Runs the specified algorithm with given variables. + + Parameters: + alg_name (str): The name of the algorithm to run. + variables (list): List of input variables for the algorithm. + + Returns: + float: Result of the algorithm computation. + """ + try: + algorithm = getattr(self, alg_name) + return algorithm(*variables) + except AttributeError: + raise ValueError(f"Algorithm {alg_name} not found") + + @staticmethod + #acc211: SITE IMPROVEMENTS, FACILITES, LAND + def acc211(csi, lsa, cland): + lsa=int(lsa) + cmlsa=[0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc211 = csi * cmlsa[lsa - 1] + cland + return acc211 + + @staticmethod + #acc212: REACTOR BUILDING COST + def acc212(ucrb, rbvol, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc212 = (1.0e-6 * ucrb * rbvol) ** exprb * cmlsa[lsa - 1] + return acc212 + + @staticmethod + #acc213: TURBINE BUILDING COST + def acc213(ireactor, cturbb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + if ireactor == 1: + acc213 = cturbb * cmlsa[lsa - 1] + else: + acc213 = 0.0e0 + return acc213 + + @staticmethod + #acc2141: REACTOR MAINTENANCE BUILDING COST + def acc2141(ucmb, rmbvol, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc2141 = 1.0e-6 * ucmb * rmbvol ** exprb * cmlsa[lsa - 1] + return acc2141 + + @staticmethod + #acc2142: WARM SHOP COST + def acc2142(ucws, wsvol, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc2142 = (1.0e-6 * ucws * wsvol) ** exprb * cmlsa[lsa - 1] + return acc2142 + + @staticmethod + #acc215: TRITIUM BUILDING COST + def acc215(uctr, triv, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc215 = ((1.0e-6 * uctr * triv) * exprb) * cmlsa[lsa - 1] + return acc215 + + @staticmethod + #acc216: ELECTICAL EQUIPMENT BUILDING COST + def acc216(ucel, elevol, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc216 = 1.0e-6 * ucel * elevol ** exprb * cmlsa[lsa - 1] + return acc216 + + @staticmethod + #acc2171: ADDITIONAL BUILDINGS COST + def acc2171(ucad, admvol, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc2171 = 1.0e-6 * ucad * admvol ** exprb * cmlsa[lsa - 1] + return acc2171 + + @staticmethod + #acc2172: CONTROLROOM BUILDINGS COST + def acc2172(ucconc, convol, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc2172 = 1.0e-6 * ucconc * convol ** exprb * cmlsa[lsa - 1] + return acc2172 + + @staticmethod + #acc2173: SHOP AND WAREHOUSES COST + def acc2173(ucsh, shovol, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc2173 = 1.0e-6 * ucsh * shovol ** exprb * cmlsa[lsa - 1] + return acc2173 + + @staticmethod + #acc2174: CRYOGENIC BUILDING COST + def acc2174(uccr, cryvol, exprb, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc2174 = 1.0e-6 * uccr * cryvol ** exprb * cmlsa[lsa - 1] + return acc2174 + + @staticmethod + #acc2211: FIRST WALL COST (MSR specific - simplified) + def acc2211(ife, ucfwa, ucfws, fwarea, ucfwps, ucblss, fwmatm, uccarb, ucblli2o, ucconc, ifueltyp, fwallcst, lsa): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + if ife == 1: + acc2211 = (1.0e-6 * cmlsa[lsa - 1] * (ucblss * (fwmatm(1, 1) + fwmatm(2, 1) + fwmatm(3, 1)) + + uccarb * (fwmatm(1, 2) + fwmatm(2, 2) + fwmatm(3, 2)) + + ucblli2o * (fwmatm(1, 4) + fwmatm(2, 4) + fwmatm(3, 4)) + + ucconc * (fwmatm(1, 5) + fwmatm(2, 5) + fwmatm(3, 5)))) + else: + acc2211 = (1.0e-6 * cmlsa[lsa - 1] * ((ucfwa + ucfws) * fwarea + ucfwps)) + acc2211 = acc2211 + if ifueltyp == 1: + acc2211 = 0 + acc2211 = fwallcst + elif ifueltyp == 2: + fwallcst = acc2211 + else: + fwallcst = 0.0e0 + return acc2211 + + @staticmethod + #acc22121: BLANKET BERYLLIUM COST + def acc22121(ife, wtbllipb, ucbllipb, whtblbe, ucblbe, iblanket, lsa): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + if ife == 1: + acc22121 = 0 + else: + if iblanket == 4: + acc22121 = 1.0e-6 * wtbllipb * ucbllipb + else: + acc22121 = 1.0e-6 * whtblbe * ucblbe + acc22121 = acc22121 * cmlsa[lsa - 1] + return acc22121 + + @staticmethod + #acc22122: BLANKET BREEDER MATERIAL COST + def acc22122(whtblli, ucblli, whtblbreed, ucblbreed, wtblli2o, ucblli2o, iblanket, lsa, ife): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + if ife == 1: + if iblanket == 4: + acc22122 = 1.0e-6 * whtblli * ucblli + else: + if iblanket == 2: + acc22122 = 1.0e-6 * whtblbreed * ucblbreed + else: + acc22122 = 1.0e-6 * wtblli2o * ucblli2o + else: + acc22122 = 1.0e-6 * wtblli2o * ucblli2o + acc22122 = acc22122 * cmlsa[lsa - 1] + return acc22122 + + @staticmethod + #acc22123: BLANKET STAINLESS STEEL COST + def acc22123(whtblss, ucblss, lsa): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + acc22123 = 1.0e-6 * whtblss * ucblss + acc22123 = acc22123 * cmlsa[lsa - 1] + return acc22123 + + @staticmethod + #acc22124: BLANKET VANADIUM COST + def acc22124(whtblvd, ucblvd, ife, lsa): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + if ife == 1: + acc22124 = 1.0e-6 * whtblvd * ucblvd + else: + acc22124 = 0 + acc22124 = acc22124 * cmlsa[lsa - 1] + return acc22124 + + @staticmethod + #acc22131: BULK SHIELD COST + def acc22131(ife, whtshld, ucshld, lsa, shmatm, uccarb, ucblli2o, ucconc): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + if ife == 1: + acc22131 = 1.0e-6 * cmlsa[lsa - 1] * ucshld * (shmatm(1, 0) + shmatm(2, 0) + shmatm(3, 0)) + uccarb * (shmatm(1, 1) + shmatm(2, 1) + shmatm(3, 1)) + ucblli2o * (shmatm(1, 1) + shmatm(2, 1) + shmatm(3, 1)) + ucconc * (shmatm(1, 1) + shmatm(2, 1) + shmatm(3, 1)) + else: + acc22131 = 1.0e-6 * whtshld * ucshld * cmlsa[lsa - 1] + acc22131 = acc22131 + return acc22131 + + @staticmethod + #acc22132: PENETRATION SHIELDING COST + def acc22132(ife, wpenshld, ucpens, lsa): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + if ife == 1: + acc22132 = 1.0e-6 * wpenshld * ucpens * cmlsa[lsa - 1] + else: + acc22132 = 1.0e-6 * wpenshld * ucpens * cmlsa[lsa - 1] + acc22132 = acc22132 + return acc22132 + + @staticmethod + #acc2214: TOTAL SUPPORT STRUCTURE COST + def acc2214(gsmass, ucgss, lsa): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + acc2214 = 1.0e-6 * gsmass * ucgss * cmlsa[lsa - 1] + acc2214 = acc2214 + return acc2214 + + @staticmethod + #acc2215: DIVERTOR COST + def acc2215(ife, divsur, ucdiv, ifueltyp, divcst, lsa): + lsa=int(lsa) + cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] + if ife == 1: + acc2215 = 1.0e-6 * divsur * ucdiv * cmlsa[lsa - 1] + else: + acc2215 = 1.0e-6 * divsur * ucdiv * cmlsa[lsa - 1] + acc2215 = acc2215 + if ifueltyp == 1: + acc2215 = 0 + acc2215 = divcst + elif ifueltyp == 2: + divcst = acc2215 + else: + divcst = 0.0e0 + return acc2215 + + # Add more MSR-specific algorithms as needed... + # For now, we'll use the same structure as fusion but with MSR-specific modifications + + @staticmethod + #acc241: SWITCHYARD EQUIPMENT COST + def acc241(ucswyd, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc241 = 1.0e-6 * ucswyd * cmlsa[lsa - 1] + return acc241 + + @staticmethod + #acc242: TRANSFORMERS COST + def acc242(ucpp, pacpmw, expepe, ucap, fcsht, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc242 = 1.0e-6 * ((ucpp * (pacpmw * 1.0e3) ** expepe) + ucap * (fcsht * 1.0e3)) + acc242 = acc242 * cmlsa[lsa - 1] + return acc242 + + @staticmethod + #acc243: LOW VOLTAGE EQUIPMENT COST + def acc243(uclv, tlvpmw, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc243 = 1.0e-6 * uclv * tlvpmw * cmlsa[lsa - 1] + return acc243 + + @staticmethod + #acc244: DIESEL BACKUP EQUIPMENT COST + def acc244(ucdgen, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc244 = 1.0e-6 * ucdgen * 4.0e0 * cmlsa[lsa - 1] + return acc244 + + @staticmethod + #acc245: AUXILIARY FACILITIES COST + def acc245(ucaf, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc245 = 1.0e-6 * ucaf * cmlsa[lsa - 1] + return acc245 + + @staticmethod + #acc25: MISCELLANEOUS PLANT EQUIPMENT COST + def acc25(ucmisc, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + acc25 = 1.0e-6 * ucmisc * cmlsa[lsa - 1] + return acc25 + + @staticmethod + #acc26: HEAT REJECTION SYSTEM COST + def acc26(ireactor, powfmw, pinjwp, tfcmw, pthermmw, pgrossmw, uchrs, lsa): + lsa=int(lsa) + cmlsa = [0.6800e0, 0.8400e0, 0.9200e0, 1.0000e0] + if ireactor == 0: + pwrrej = powfmw + pinjwp + tfcmw + else: + pwrrej = pthermmw - pgrossmw + acc26 = (1.0e-6 * uchrs * pwrrej) / 2300.0e0 * cmlsa[lsa - 1] + return acc26 \ No newline at end of file diff --git a/src/Algorithm/__init__.py b/src/Algorithm/__init__.py index d04cbef..5af7ac7 100644 --- a/src/Algorithm/__init__.py +++ b/src/Algorithm/__init__.py @@ -1,3 +1,4 @@ from .Algorithm import Algorithm from .FusionFunc import FusionFunc from .user_defined_func import user_defined_func +from .MsrFunc import MsrFunc diff --git a/src/Main.py b/src/Main.py index 6a2c33d..9b86c19 100755 --- a/src/Main.py +++ b/src/Main.py @@ -95,6 +95,14 @@ def setup_table_names(self,xml2obj): self.alg_tabl = 'fusion_alg' self.esc_tabl = 'escalation' self.fac_tabl = 'facility' + elif "msr" in str(xml2obj.ref_model.value).lower(): + self.ref_model = 'msr' + self.acc_tabl = 'msr_acco' + self.cel_tabl = None + self.var_tabl = 'msr_varv' + self.alg_tabl = 'msr_alg' + self.esc_tabl = 'escalation' + self.fac_tabl = 'facility' elif "user_defined" in str(xml2obj.ref_model.value).lower(): self.ref_model = 'user_defined' self.acc_tabl = 'user_defined_account' diff --git a/src/etc/accert.sch b/src/etc/accert.sch index 80894e5..c71d95b 100644 --- a/src/etc/accert.sch +++ b/src/etc/accert.sch @@ -495,7 +495,7 @@ accert{ } EndOfSchema{} -ref_models = [ "PWR12-BE" "ABR1000" "LFR", "heatpipe","fusion"] +ref_models = [ "PWR12-BE" "ABR1000" "LFR", "heatpipe","fusion" "msr"] power_type = ["Thermal" "Electric"] power_unit = ["W" "kWW" "MW"] total_cost_unit = ["million" "dollar"] diff --git a/tutorial/MSR.son b/tutorial/MSR.son new file mode 100644 index 0000000..40c8229 --- /dev/null +++ b/tutorial/MSR.son @@ -0,0 +1,18 @@ +% ACCERT Test input file for MSR +% Author: Assistant +% Last updated: 06/19/2024 + + +accert{ + ref_model = "msr" + l0COA(2){ + l1COA(21){ + l2COA("211"){ + alg("acc211"){ + var("csi"){value = 16 unit = million} + var("lsa"){value = 4 unit = 1} + } + } + } + } +} \ No newline at end of file From d18ebe78c78df4d4133a9064aeca7d3727fa42fd Mon Sep 17 00:00:00 2001 From: Joseph Chang Date: Thu, 19 Jun 2025 16:07:06 -0500 Subject: [PATCH 05/27] Initial commit MSR model Set up project structure and add initial files. --- tutorial/MSR.son | 4 +- tutorial/ref_tables/fusion_acc.csv | 171 +++++++++++++++-------------- tutorial/ref_tables/fusion_alg.csv | 144 ++++++++++++------------ 3 files changed, 161 insertions(+), 158 deletions(-) diff --git a/tutorial/MSR.son b/tutorial/MSR.son index 40c8229..977e34e 100644 --- a/tutorial/MSR.son +++ b/tutorial/MSR.son @@ -1,10 +1,12 @@ % ACCERT Test input file for MSR -% Author: Assistant +% Author: Daeho Chang (daeho.chang@anl.gov) % Last updated: 06/19/2024 accert{ ref_model = "msr" + power( Thermal ){ value = 2000 unit = MW } + power( Electric ){ value = 800 unit = MW } l0COA(2){ l1COA(21){ l2COA("211"){ diff --git a/tutorial/ref_tables/fusion_acc.csv b/tutorial/ref_tables/fusion_acc.csv index 705d63f..90ec5b3 100644 --- a/tutorial/ref_tables/fusion_acc.csv +++ b/tutorial/ref_tables/fusion_acc.csv @@ -1,91 +1,92 @@ ind,code_of_account,account description,total_cost,level,supaccount,review_status,prn,alg_name,fun_unit,variables 1,2,Plant direct cost,5523932823,0,,Unchanged,1,acc2,million, 2,21,Total account 21 cost,778648283.5,1,2,Unchanged,0.140959043,acc21,million, -3,211,"Site improvements, facilities, land",35200000,2,21,Unchanged,0.006372272,acc211,million,"csi, lsa, cland" -4,212,Reactor building cost,452161853.1,2,21,Unchanged,0.08185506,acc212,million,"ucrb, rbvol, exprb, lsa" -5,213,Turbine building cost,38000000,2,21,Unchanged,0.006879157,acc213,million,"ireactor, cturbb, lsa" -6,214,Reactor maintenance and warm shop buildings cost,160708943.7,2,21,Unchanged,0.029093211,acc214,million, -7,2141,Reactor maintenance building cost,103067666.8,3,214,Unchanged,0.018658385,acc2141,million,"ucmb, rmbvol, exprb, lsa" -8,2142,Warm shop cost,57641276.92,3,214,Unchanged,0.010434826,acc2142,million,"ucws, wsvol, exprb, lsa" -9,215,Tritium building cost,14800000,2,21,Unchanged,0.002679251,acc215,million,"uctr, triv, exprb, lsa" -10,216,Electrical equipment building cost,19706763.56,2,21,Unchanged,0.003567524,acc216,million,"ucel, elevol, exprb, lsa" -11,217,Other buildings cost,58070723.2,2,21,Unchanged,0.010512569,acc217,million, -12,2171,Additional buildings cost,18000000,3,217,Unchanged,0.003258548,acc2171,million,"ucad, admvol, exprb, lsa" -13,2172,Control room buildings cost,21000000,3,217,Unchanged,0.003801639,acc2172,million,"ucco, convol, exprb, lsa" -14,2173,Shop and warehouses cost,11500000,3,217,Unchanged,0.00208185,acc2173,million,"ucsh, shovol, exprb, lsa" -15,2174,Cryogenic building cost,7570723.2,3,217,Unchanged,0.001370531,acc2174,million,"uccr, cryvol, exprb, lsa" -16,22,Total account 22 cost,4450975680,1,2,Unchanged,0.805762094,acc22,million, +3,211,"Site improvements, facilities, land",35200000,2,21,Unchanged,0.006372272,acc211,million, +4,212,Reactor building cost,452161853.1,2,21,Unchanged,0.08185506,acc212,million,"csi, lsa, cland" +5,213,Turbine building cost,38000000,2,21,Unchanged,0.006879157,acc213,million,"ucrb, rbvol, exprb, lsa" +6,214,Reactor maintenance and warm shop buildings cost,160708943.7,2,21,Unchanged,0.029093211,acc214,million,"ireactor, cturbb, lsa" +7,2141,Reactor maintenance building cost,103067666.8,3,214,Unchanged,0.018658385,acc2141,million, +8,2142,Warm shop cost,57641276.92,3,214,Unchanged,0.010434826,acc2142,million,"ucmb, rmbvol, exprb, lsa" +9,215,Tritium building cost,14800000,2,21,Unchanged,0.002679251,acc215,million,"ucws, wsvol, exprb, lsa" +10,216,Electrical equipment building cost,19706763.56,2,21,Unchanged,0.003567524,acc216,million,"uctr, triv, exprb, lsa" +11,217,Other buildings cost,58070723.2,2,21,Unchanged,0.010512569,acc217,million,"ucel, elevol, exprb, lsa" +12,2171,Additional buildings cost,18000000,3,217,Unchanged,0.003258548,acc2171,million, +13,2172,Control room buildings cost,21000000,3,217,Unchanged,0.003801639,acc2172,million,"ucad, admvol, exprb, lsa" +14,2173,Shop and warehouses cost,11500000,3,217,Unchanged,0.00208185,acc2173,million,"ucco, convol, exprb, lsa" +15,2174,Cryogenic building cost,7570723.2,3,217,Unchanged,0.001370531,acc2174,million,"ucsh, shovol, exprb, lsa" +16,22,Total account 22 cost,4450975680,1,2,Unchanged,0.805762094,acc22,million,"uccr, cryvol, exprb, lsa" 17,221,Total account 221 cost,1413062555,2,22,Unchanged,0.255807339,acc221,million, -18,2211,First wall cost,191300792.1,3,221,Unchanged,0.034631267,acc2211,million,"ife, ucfwa, ucfws, fwarea, ucfwps, ucblss, fwmatm, uccarb, ucblli2o, ucconc, ifueltyp, fwallcst" -19,2212,Blanket total cost,981664978.6,3,221,Unchanged,0.177711245,acc2212,million, -20,22121,Blanket beryllium cost,261092739.8,4,2212,Unchanged,0.047265734,acc22121,million,"ife, wtbllipb, ucbllipb, whtblbe, ucblbe, iblanket, lsa" -21,22122,Blanket breeder material cost,639846060.7,4,2212,Unchanged,0.115831615,acc22122,million,"whtblli, ucblli, whtblbreed, ucblbreed, wtblli2o, ucblli2o, iblanket, lsa, ife" -22,22123,Blanket stainless steel cost,80726178.24,4,2212,Unchanged,0.014613896,acc22123,million,"whtblss, ucblss, lsa" -23,22124,Blanket vanadium cost,0,4,2212,Unchanged,0,acc22124,million,"whtblvd, ucblvd, ife, lsa" -24,2213,Total shield cost,156788405.4,3,221,Unchanged,0.028383474,acc2213,million, -25,22131,Bulk shield cost,78394202.68,4,2213,Unchanged,0.014191737,acc22131,million,"ife, whtshld, ucshld, lsa, shmatm, uccarb, ucblli2o, ucconc" -26,22132,Penetration shielding cost,78394202.68,4,2213,Unchanged,0.014191737,acc22132,million,"ife, wpenshld, ucpens, lsa" -27,2214,Total support structure cost,41648347.22,3,221,Unchanged,0.007539619,acc2214,million,"gsmass, ucgss, lsa" -28,2215,Divertor cost,41660031.86,3,221,Unchanged,0.007541734,acc2215,million,"ife, divsur, ucdiv, ifueltyp, divcst" -29,222,Total account 222 cost,1755392733,2,22,Unchanged,0.317779522,acc222,million, +18,2211,First wall cost,191300792.1,3,221,Unchanged,0.034631267,acc2211,million, +19,2212,Blanket total cost,981664978.6,3,221,Unchanged,0.177711245,acc2212,million,"ife, ucfwa, ucfws, fwarea, ucfwps, ucblss, fwmatm, uccarb, ucblli2o, ucconc, ifueltyp, fwallcst" +20,22121,Blanket beryllium cost,261092739.8,4,2212,Unchanged,0.047265734,acc22121,million, +21,22122,Blanket breeder material cost,639846060.7,4,2212,Unchanged,0.115831615,acc22122,million,"ife, wtbllipb, ucbllipb, whtblbe, ucblbe, iblanket, lsa" +22,22123,Blanket stainless steel cost,80726178.24,4,2212,Unchanged,0.014613896,acc22123,million,"whtblli, ucblli, whtblbreed, ucblbreed, wtblli2o, ucblli2o, iblanket, lsa, ife" +23,22124,Blanket vanadium cost,0,4,2212,Unchanged,0,acc22124,million,"whtblss, ucblss, lsa" +24,2213,Total shield cost,156788405.4,3,221,Unchanged,0.028383474,acc2213,million,"whtblvd, ucblvd, ife, lsa" +25,22131,Bulk shield cost,78394202.68,4,2213,Unchanged,0.014191737,acc22131,million, +26,22132,Penetration shielding cost,78394202.68,4,2213,Unchanged,0.014191737,acc22132,million,"ife, whtshld, ucshld, lsa, shmatm, uccarb, ucblli2o, ucconc" +27,2214,Total support structure cost,41648347.22,3,221,Unchanged,0.007539619,acc2214,million,"ife, wpenshld, ucpens, lsa" +28,2215,Divertor cost,41660031.86,3,221,Unchanged,0.007541734,acc2215,million,"gsmass, ucgss, lsa" +29,222,Total account 222 cost,1755392733,2,22,Unchanged,0.317779522,acc222,million,"ife, divsur, ucdiv, ifueltyp, divcst" 30,2221,TF magnet assemblies cost,820550431.9,3,222,Unchanged,0.148544607,acc2221,million, -31,22211,TF coil conductor cost,130258092.5,4,2221,Unchanged,0.02358068,acc22211,million,"whtcp, uccpcl1, itart, ifueltyp, cpstcst, ucsc_4, whtconsc, tfleng, n_tf_turn, uccu, whtconcu, cconshtf, cconfix, n_tf, lsa, i_tf_sup" -32,22212,TF coil winding cost,55700223.23,4,2221,Unchanged,0.010083436,acc22212,million,"whttflgs, uccpclb, lsa, ucwindtf, n_tf, tfleng, n_tf_turn, i_tf_sup" -33,22213,TF coil case cost,439106666.3,4,2221,Unchanged,0.079491674,acc22213,million,"whtcas, uccase, n_tf, lsa, i_tf_sup" -34,22214,TF intercoil structure cost,150045051.6,4,2221,Unchanged,0.027162722,acc22214,million,"aintmass, ucint, lsa, i_tf_sup" -35,22215,TF coil gravity support structure,45440398.23,4,2221,Unchanged,0.008226095,acc22215,million,"clgsmass, ucgss, lsa, i_tf_sup" -36,2222,PF magnet assemblies cost,680800177,3,222,Unchanged,0.123245557,acc2222,million, -37,22221,PF coil conductor cost,466068431.2,4,2222,Unchanged,0.084372574,acc22221,million,"ipfres, cconshpf, iohcl, nohc, ucsc_0, ucsc_1, ucsc_2, ucsc_3, ucsc_4, ucsc_5, ucsc_6, ucsc_7, ucsc_8, isumatpf, fcupfsu, vf, ric_0, ric_1, ric_2, ric_3, ric_4, ric_5, ric_6, turns_0, turns_1, turns_2, turns_3, turns_4, turns_5, turns_6, rjconpf_0, rjconpf_1, rjconpf_2, rjconpf_3, rjconpf_4, rjconpf_5, rjconpf_6, rjconpf_7, dcond_0, dcond_1, dcond_2, dcond_3, dcond_4, dcond_5, dcond_6, dcond_7, dcond_8, uccu, dcopper, cconfix, twopi, rpf_0, rpf_1, rpf_2, rpf_3, rpf_4, rpf_5, rpf_6, lsa, isumatoh, awpoh, vfohc, fcuohsu" -38,22222,PF coil winding cost,77130237.29,4,2222,Unchanged,0.013962921,acc22222,million,"ucwindpf, lsa, twopi, rpf_0, rpf_1, rpf_2, rpf_3, rpf_4, rpf_5, rpf_6, turns_0, turns_1, turns_2, turns_3, turns_4, turns_5, turns_6, nohc" -39,22223,PF coil case cost,129551313.8,4,2222,Unchanged,0.023452732,acc22223,million,"uccase, whtpfs, lsa" -40,22224,PF coil support structure cost,8050194.63,4,2222,Unchanged,0.00145733,acc22224,million,"ucfnc, fncmass, lsa" -41,2223,Vacuum vessel assembly cost,254042123.8,3,222,Unchanged,0.045989358,acc2223,million,"vvmass, uccryo, lsa" -42,223,Total account 223 cost,241046837.7,2,22,Unchanged,0.043636816,acc223,million, -43,2231,ECH system cost,241046837.7,3,223,Unchanged,0.043636816,acc2231,million,"ucech, echpwr, exprf, ifedrv, dcdrv1, dcdrv2, cdriv1, mcdriv, edrive, etadrv, dcdrv0, cdriv0 ,cdriv3, fcdfuel" -44,2232,Lower hybrid system cost,0,3,223,Unchanged,0,acc2232,million,"iefrf, uclh, plhybd, exprf, ucich" -45,2233,Neutral beam system cost,0,3,223,Unchanged,0,acc2233,million,"ucnbi, exprf, fcdfuel" -46,224,Total account 224 cost,26934799.04,2,22,Unchanged,0.004876019,acc224,million, -47,2241,High vacuum pumps cost,12480000,3,224,Unchanged,0.00225926,acc2241,million,"vpumpn, uccpmp, uctpmp, ntype" -48,2242,Backing pumps cost,4680000,3,224,Unchanged,0.000847222,acc2242,million,"nvduct, ucbpmp" -49,2243,Vacuum duct cost,2590254.5,3,224,Unchanged,0.000468915,acc2243,million,"nvduct, dlscal, ucduct" -50,2244,Valves cost,5884544.54,3,224,Unchanged,0.001065282,acc2244,million,"nvduct, vcdimax, ucvalv" -51,2245,Duct shielding cost,0,3,224,Unchanged,0,acc2245,million,"nvduct, vacdshm, ucvdsh" -52,2246,Instrumentation cost,1300000,3,224,Unchanged,0.00023534,acc2246,million,ucviac -53,225,Total account 225 cost,154876266,2,22,Unchanged,0.028037319,acc225,million, +31,22211,TF coil conductor cost,130258092.5,4,2221,Unchanged,0.02358068,acc22211,million, +32,22212,TF coil winding cost,55700223.23,4,2221,Unchanged,0.010083436,acc22212,million,"whtcp, uccpcl1, itart, ifueltyp, cpstcst, ucsc_4, whtconsc, tfleng, n_tf_turn, uccu, whtconcu, cconshtf, cconfix, n_tf, lsa, i_tf_sup" +33,22213,TF coil case cost,439106666.3,4,2221,Unchanged,0.079491674,acc22213,million,"whttflgs, uccpclb, lsa, ucwindtf, n_tf, tfleng, n_tf_turn, i_tf_sup" +34,22214,TF intercoil structure cost,150045051.6,4,2221,Unchanged,0.027162722,acc22214,million,"whtcas, uccase, n_tf, lsa, i_tf_sup" +35,22215,TF coil gravity support structure,45440398.23,4,2221,Unchanged,0.008226095,acc22215,million,"aintmass, ucint, lsa, i_tf_sup" +36,2222,PF magnet assemblies cost,680800177,3,222,Unchanged,0.123245557,acc2222,million,"clgsmass, ucgss, lsa, i_tf_sup" +37,22221,PF coil conductor cost,466068431.2,4,2222,Unchanged,0.084372574,acc22221,million, +38,22222,PF coil winding cost,77130237.29,4,2222,Unchanged,0.013962921,acc22222,million,"ipfres, cconshpf, iohcl, nohc, ucsc_0, ucsc_1, ucsc_2, ucsc_3, ucsc_4, ucsc_5, ucsc_6, ucsc_7, ucsc_8, isumatpf, fcupfsu, vf, ric_0, ric_1, ric_2, ric_3, ric_4, ric_5, ric_6, turns_0, turns_1, turns_2, turns_3, turns_4, turns_5, turns_6, rjconpf_0, rjconpf_1, rjconpf_2, rjconpf_3, rjconpf_4, rjconpf_5, rjconpf_6, rjconpf_7, dcond_0, dcond_1, dcond_2, dcond_3, dcond_4, dcond_5, dcond_6, dcond_7, dcond_8, uccu, dcopper, cconfix, twopi, rpf_0, rpf_1, rpf_2, rpf_3, rpf_4, rpf_5, rpf_6, lsa, isumatoh, awpoh, vfohc, fcuohsu" +39,22223,PF coil case cost,129551313.8,4,2222,Unchanged,0.023452732,acc22223,million,"ucwindpf, lsa, twopi, rpf_0, rpf_1, rpf_2, rpf_3, rpf_4, rpf_5, rpf_6, turns_0, turns_1, turns_2, turns_3, turns_4, turns_5, turns_6, nohc" +40,22224,PF coil support structure cost,8050194.63,4,2222,Unchanged,0.00145733,acc22224,million,"uccase, whtpfs, lsa" +41,2223,Vacuum vessel assembly cost,254042123.8,3,222,Unchanged,0.045989358,acc2223,million,"ucfnc, fncmass, lsa" +42,223,Total account 223 cost,241046837.7,2,22,Unchanged,0.043636816,acc223,million,"vvmass, uccryo, lsa" +43,2231,ECH system cost,241046837.7,3,223,Unchanged,0.043636816,acc2231,million, +44,2232,Lower hybrid system cost,0,3,223,Unchanged,0,acc2232,million,"ucech, echpwr, exprf, ifedrv, dcdrv1, dcdrv2, cdriv1, mcdriv, edrive, etadrv, dcdrv0, cdriv0 ,cdriv3, fcdfuel" +45,2233,Neutral beam system cost,0,3,223,Unchanged,0,acc2233,million,"iefrf, uclh, plhybd, exprf, ucich" +46,224,Total account 224 cost,26934799.04,2,22,Unchanged,0.004876019,acc224,million,"ucnbi, exprf, fcdfuel" +47,2241,High vacuum pumps cost,12480000,3,224,Unchanged,0.00225926,acc2241,million, +48,2242,Backing pumps cost,4680000,3,224,Unchanged,0.000847222,acc2242,million,"vpumpn, uccpmp, uctpmp, ntype" +49,2243,Vacuum duct cost,2590254.5,3,224,Unchanged,0.000468915,acc2243,million,"nvduct, ucbpmp" +50,2244,Valves cost,5884544.54,3,224,Unchanged,0.001065282,acc2244,million,"nvduct, dlscal, ucduct" +51,2245,Duct shielding cost,0,3,224,Unchanged,0,acc2245,million,"nvduct, vcdimax, ucvalv" +52,2246,Instrumentation cost,1300000,3,224,Unchanged,0.00023534,acc2246,million,"nvduct, vacdshm, ucvdsh" +53,225,Total account 225 cost,154876266,2,22,Unchanged,0.028037319,acc225,million,ucviac 54,2251,"Total, TF coil power costs",98208291.45,3,225,Unchanged,0.01777869,acc2251,million, -55,22511,TF coil power supplies cost,3967323.07,4,2251,Unchanged,0.000718206,acc22511,million,"uctfps, tfckw, tfcmw, expel" -56,22512,TF coil breakers cost,34112697.55,4,2251,Unchanged,0.006175437,acc22512,million,"uctfbr, n_tf, cpttf, vtfskv, expel, uctfsw" -57,22513,TF coil dump resistors cost,21125590.34,4,2251,Unchanged,0.003824375,acc22513,million,"uctfdr, estotftgj, uctfgr, n_tf" -58,22514,TF coil instrumentation and control,4800000,4,2251,Unchanged,0.000868946,acc22514,million,"uctfic, n_tf, " -59,22515,TF coil bussing cost,34202680.49,4,2251,Unchanged,0.006191726,acc22515,million,"uctfbus, tfbusmas, ucbus, cpttf, tfbusl" -60,2252,"Total, PF coil power costs",39768511.04,3,225,Unchanged,0.007199311,acc2252,million, -61,22521,PF coil power supplies cost,2932371.33,4,2252,Unchanged,0.000530848,acc22521,million,"ucpfps, peakmva" -62,22522,PF coil instrumentation and control,3600000,4,2252,Unchanged,0.00065171,acc22522,million,"ucpfic, pfckts" -63,22523,PF coil bussing cost,11995200,4,2252,Unchanged,0.002171496,acc22523,million,"ucpfb, spfbusl, acptmax" -64,22524,PF coil burn power supplies cost,1267929.14,4,2252,Unchanged,0.000229534,acc22524,million,"ucpfbs, pfckts, srcktpm" -65,22525,PF coil breakers cost,14709370.28,4,2252,Unchanged,0.002662844,acc22525,million,"ucpfbk, pfckts, acptmax, vpfskv" -66,22526,PF coil dump resistors cost,4363640.29,4,2252,Unchanged,0.000789952,acc22526,million,"ucpfdr1, ensxpfm" -67,22527,PF coil ac breakers cost,900000,4,2252,Unchanged,0.000162927,acc22527,million,"ucpfcb, pfckts" -68,2253,"Total, energy storage cost",16899463.51,3,225,Unchanged,0.003059317,acc2253,million,"lpulse, istore, ucblss, pthermmw, tdown, dtstor, pnetelmw" -69,226,Total account 226 cost,332122997.5,2,22,Unchanged,0.060124373,acc226,million,"cal_acc2261, cal_acc2262, cal_acc2263" -70,2261,"Total, reactor cooling system cost",109472365.6,3,226,Unchanged,0.019817831,acc2261,million, -71,22611,Pumps and piping system cost,37134735.98,4,2261,Unchanged,0.006722518,acc22611,million,"uchts, coolwh, pfwdiv, exphts, pnucblkt, pnucshld, lsa" -72,22612,Primary heat exchanger cost,72337629.6,4,2261,Unchanged,0.013095313,acc22612,million,"ucphx, nphx, pthermmw, exphts, lsa" -73,2262,"Pumps, piping cost",29300032.53,3,226,Unchanged,0.005304198,acc2262,million,"ucahts, pinjht, exphts, crypmw, vachtmw, trithtmw, fachtmw, ife, tdspmw, tfacmw, lsa" -74,2263,"Total, cryogenic system cost",193350599.4,3,226,Unchanged,0.035002344,acc2263,million,"uccry, tmpcry, helpow, lsa, expcry" -75,227,Total account 227 cost,252539491.6,2,22,Unchanged,0.045717336,acc227,million, -76,2271,Fuelling system cost,22300000,3,227,Unchanged,0.004036979,acc2271,million,ucf1 -77,2272,Fuel processing and purification cost,103001575.3,3,227,Unchanged,0.018646421,acc2272,million,"ife, rndfuel, afuel, umass, gain, edrive, fburn, reprat, ucfpr" -78,2273,Atmospheric recovery systems cost,58061674.55,3,227,Unchanged,0.010510931,acc2273,million,"ftrit, ucdtc, volrci, wsvol" -79,2274,Nuclear building ventilation cost,69176241.77,3,227,Unchanged,0.012523006,acc2274,million,"ucnbv, volrci, wsvol" -80,228,Instrumentation and control cost,150000000,2,22,Unchanged,0.027154566,acc228,million,uciac -81,229,Maintenance equipment cost,125000000,2,22,Unchanged,0.022628805,acc229,million,ucme -82,23,Turbine plant equipment cost,178012556.3,1,2,Unchanged,0.032225692,acc23,million,"ireactor, ucturb, coolwh, pgrossmw, exptpe" -83,24,Total account 24 cost,40776153.7,1,2,Unchanged,0.007381725,acc24,million, -84,241,Switchyard equipment cost,18400000,2,24,Unchanged,0.00333096,acc241,million,"ucswyd, lsa" -85,242,Transformers cost,7502814.23,2,24,Unchanged,0.001358238,acc242,million,"ucpp, pacpmw, expepe, ucap, fcsht, lsa" -86,243,Low voltage equipment cost,6573339.47,2,24,Unchanged,0.001189975,acc243,million,"uclv, tlvpmw, lsa" -87,244,Diesel backup equipment cost,6800000,2,24,Unchanged,0.001231007,acc244,million,"ucdgen, lsa" -88,245,Auxiliary facilities cost,1500000,2,24,Unchanged,0.000271546,acc245,million,"ucaf, lsa" -89,25,Miscellaneous plant equipment cost,25000000,1,2,Unchanged,0.004525761,acc25,million,"ucmisc, lsa" -90,26,Heat rejection system cost,50520149.78,1,2,Unchanged,0.009145685,acc26,million,"ireactor, powfmw, pinjwp, tfcmw, pthermmw, pgrossmw, uchrs, lsa" \ No newline at end of file +55,22511,TF coil power supplies cost,3967323.07,4,2251,Unchanged,0.000718206,acc22511,million, +56,22512,TF coil breakers cost,34112697.55,4,2251,Unchanged,0.006175437,acc22512,million,"uctfps, tfckw, tfcmw, expel" +57,22513,TF coil dump resistors cost,21125590.34,4,2251,Unchanged,0.003824375,acc22513,million,"uctfbr, n_tf, cpttf, vtfskv, expel, uctfsw" +58,22514,TF coil instrumentation and control,4800000,4,2251,Unchanged,0.000868946,acc22514,million,"uctfdr, estotftgj, uctfgr, n_tf" +59,22515,TF coil bussing cost,34202680.49,4,2251,Unchanged,0.006191726,acc22515,million,"uctfic, n_tf, " +60,2252,"Total, PF coil power costs",39768511.04,3,225,Unchanged,0.007199311,acc2252,million,"uctfbus, tfbusmas, ucbus, cpttf, tfbusl" +61,22521,PF coil power supplies cost,2932371.33,4,2252,Unchanged,0.000530848,acc22521,million, +62,22522,PF coil instrumentation and control,3600000,4,2252,Unchanged,0.00065171,acc22522,million,"ucpfps, peakmva" +63,22523,PF coil bussing cost,11995200,4,2252,Unchanged,0.002171496,acc22523,million,"ucpfic, pfckts" +64,22524,PF coil burn power supplies cost,1267929.14,4,2252,Unchanged,0.000229534,acc22524,million,"ucpfb, spfbusl, acptmax" +65,22525,PF coil breakers cost,14709370.28,4,2252,Unchanged,0.002662844,acc22525,million,"ucpfbs, pfckts, srcktpm" +66,22526,PF coil dump resistors cost,4363640.29,4,2252,Unchanged,0.000789952,acc22526,million,"ucpfbk, pfckts, acptmax, vpfskv" +67,22527,PF coil ac breakers cost,900000,4,2252,Unchanged,0.000162927,acc22527,million,"ucpfdr1, ensxpfm" +68,2253,"Total, energy storage cost",16899463.51,3,225,Unchanged,0.003059317,acc2253,million,"ucpfcb, pfckts" +69,226,Total account 226 cost,332122997.5,2,22,Unchanged,0.060124373,acc226,million,"lpulse, istore, ucblss, pthermmw, tdown, dtstor, pnetelmw" +70,2261,"Total, reactor cooling system cost",109472365.6,3,226,Unchanged,0.019817831,acc2261,million,"cal_acc2261, cal_acc2262, cal_acc2263" +71,22611,Pumps and piping system cost,37134735.98,4,2261,Unchanged,0.006722518,acc22611,million, +72,22612,Primary heat exchanger cost,72337629.6,4,2261,Unchanged,0.013095313,acc22612,million,"uchts, coolwh, pfwdiv, exphts, pnucblkt, pnucshld, lsa" +73,2262,"Pumps, piping cost",29300032.53,3,226,Unchanged,0.005304198,acc2262,million,"ucphx, nphx, pthermmw, exphts, lsa" +74,2263,"Total, cryogenic system cost",193350599.4,3,226,Unchanged,0.035002344,acc2263,million,"ucahts, pinjht, exphts, crypmw, vachtmw, trithtmw, fachtmw, ife, tdspmw, tfacmw, lsa" +75,227,Total account 227 cost,252539491.6,2,22,Unchanged,0.045717336,acc227,million,"uccry, tmpcry, helpow, lsa, expcry" +76,2271,Fuelling system cost,22300000,3,227,Unchanged,0.004036979,acc2271,million, +77,2272,Fuel processing and purification cost,103001575.3,3,227,Unchanged,0.018646421,acc2272,million,ucf1 +78,2273,Atmospheric recovery systems cost,58061674.55,3,227,Unchanged,0.010510931,acc2273,million,"ife, rndfuel, afuel, umass, gain, edrive, fburn, reprat, ucfpr" +79,2274,Nuclear building ventilation cost,69176241.77,3,227,Unchanged,0.012523006,acc2274,million,"ftrit, ucdtc, volrci, wsvol" +80,228,Instrumentation and control cost,150000000,2,22,Unchanged,0.027154566,acc228,million,"ucnbv, volrci, wsvol" +81,229,Maintenance equipment cost,125000000,2,22,Unchanged,0.022628805,acc229,million,uciac +82,23,Turbine plant equipment cost,178012556.3,1,2,Unchanged,0.032225692,acc23,million,ucme +83,24,Total account 24 cost,40776153.7,1,2,Unchanged,0.007381725,acc24,million,"ireactor, ucturb, coolwh, pgrossmw, exptpe" +84,241,Switchyard equipment cost,18400000,2,24,Unchanged,0.00333096,acc241,million, +85,242,Transformers cost,7502814.23,2,24,Unchanged,0.001358238,acc242,million,"ucswyd, lsa" +86,243,Low voltage equipment cost,6573339.47,2,24,Unchanged,0.001189975,acc243,million,"ucpp, pacpmw, expepe, ucap, fcsht, lsa" +87,244,Diesel backup equipment cost,6800000,2,24,Unchanged,0.001231007,acc244,million,"uclv, tlvpmw, lsa" +88,245,Auxiliary facilities cost,1500000,2,24,Unchanged,0.000271546,acc245,million,"ucdgen, lsa" +89,25,Miscellaneous plant equipment cost,25000000,1,2,Unchanged,0.004525761,acc25,million,"ucaf, lsa" +90,26,Heat rejection system cost,50520149.78,1,2,Unchanged,0.009145685,acc26,million,"ucmisc, lsa" +,,,,,,,,,,"ireactor, powfmw, pinjwp, tfcmw, pthermmw, pgrossmw, uchrs, lsa" \ No newline at end of file diff --git a/tutorial/ref_tables/fusion_alg.csv b/tutorial/ref_tables/fusion_alg.csv index af1245f..80c8eba 100644 --- a/tutorial/ref_tables/fusion_alg.csv +++ b/tutorial/ref_tables/fusion_alg.csv @@ -1,17 +1,17 @@ -ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units -1,acc211,c,"Site_improvements,_facilities,_land_(M$)",FusionFunc,"acc211= csi*cmlsa[lsa-1] + cland",million -2,acc212,c,Reactor_building_cost_(M$),FusionFunc,"acc212= (1.0e-6*ucrb*rbvol)**exprb* cmlsa[lsa - 1]",million +ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units +1,acc211,c,"Site_improvements,_facilities,_land_(M$)",FusionFunc,acc211= csi*cmlsa[lsa-1] + cland,million +2,acc212,c,Reactor_building_cost_(M$),FusionFunc,acc212= (1.0e-6*ucrb*rbvol)**exprb* cmlsa[lsa - 1],million 3,acc213,c,Turbine_building_cost_(M$),FusionFunc," if ireactor == 1: acc213 = cturbb * cmlsa[lsa - 1] - else: acc213 = 0.0e0",million -4,acc2141,c,Reactor_maintenance_building_cost_(M$),FusionFunc,"acc2142 = 1.0e-6*ucmb*rmbvol**exprb*cmlsa[lsa - 1]",million -5,acc2142,c,Warm_shop_cost_(M$),FusionFunc,"acc2142 = (1.0e-6*ucws*wsvol)**exprb*cmlsa[lsa - 1]",million -6,acc215,c,Tritium_building_cost_(M$),FusionFunc,"acc215 = ((1.0e-6*uctr*triv)*exprb)*cmlsa[lsa - 1]",million -7,acc216,c,Electrical_equipment_building_cost_(M$),FusionFunc,"acc216 = 1.0e-6*ucel*elevol**exprb*cmlsa[lsa - 1]",million -8,acc2171,c,Additional_buildings_cost_(M$),FusionFunc,"acc2171 = 1.0e-6*ucad*admvol**exprb* cmlsa[lsa - 1]",million -9,acc2172,c,Control_room_buildings_cost_(M$),FusionFunc,"acc2172 = 1.0e-6*ucconc*convol**exprb* cmlsa[lsa - 1]",million -10,acc2173,c,Shop_and_warehouses_cost_(M$),FusionFunc,"acc2173 = 1.0e-6*ucsh*shovol**exprb*cmlsa[lsa - 1]",million -11,acc2174,c,Cryogenic_building_cost_(M$),FusionFunc,"acc2174 = 1.0e-6*uccr*cryvol**exprb*cmlsa[lsa - 1]",million + else: acc213 = 0.0e0",million +4,acc2141,c,Reactor_maintenance_building_cost_(M$),FusionFunc,acc2142 = 1.0e-6*ucmb*rmbvol**exprb*cmlsa[lsa - 1],million +5,acc2142,c,Warm_shop_cost_(M$),FusionFunc,acc2142 = (1.0e-6*ucws*wsvol)**exprb*cmlsa[lsa - 1],million +6,acc215,c,Tritium_building_cost_(M$),FusionFunc,acc215 = ((1.0e-6*uctr*triv)*exprb)*cmlsa[lsa - 1],million +7,acc216,c,Electrical_equipment_building_cost_(M$),FusionFunc,acc216 = 1.0e-6*ucel*elevol**exprb*cmlsa[lsa - 1],million +8,acc2171,c,Additional_buildings_cost_(M$),FusionFunc,acc2171 = 1.0e-6*ucad*admvol**exprb* cmlsa[lsa - 1],million +9,acc2172,c,Control_room_buildings_cost_(M$),FusionFunc,acc2172 = 1.0e-6*ucconc*convol**exprb* cmlsa[lsa - 1],million +10,acc2173,c,Shop_and_warehouses_cost_(M$),FusionFunc,acc2173 = 1.0e-6*ucsh*shovol**exprb*cmlsa[lsa - 1],million +11,acc2174,c,Cryogenic_building_cost_(M$),FusionFunc,acc2174 = 1.0e-6*uccr*cryvol**exprb*cmlsa[lsa - 1],million 12,acc2211,c,First_wall_cost_(M$),FusionFunc,"if ife == 1: acc2211 = (1.0e-6*cmlsa[lsa - 1] * (ucblss*(fwmatm(1, 1)+ fwmatm(2, 1)+ fwmatm(3, 1)) @@ -27,7 +27,7 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units elif ifueltyp == 2: fwallcst = acc2211 else: - fwallcst = 0.0e0",million + fwallcst = 0.0e0",million 13,acc22121,c,Blanket_beryllium_cost_(M$),FusionFunc,"if ife == 1: acc22121 = 0 else: @@ -35,7 +35,7 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units acc22121 = 1.0e-6*wtbllipb*ucbllipb else: acc22121 = 1.0e-6*whtblbe*ucblbe - acc22121 = fkind*acc22121*cmlsa[lsa-1]",million + acc22121 = fkind*acc22121*cmlsa[lsa-1]",million 14,acc22122,c,Blanket_breeder_material_cost_(M$),FusionFunc,"if ife == 1: if iblanket == 4: acc22122 = 1.0e-6*whtblli*ucblli @@ -46,15 +46,15 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units acc22122 = 1.0e-6*wtblli2o*ucblli2o else: acc22122 = 1.0e-6*wtblli2o*ucblli2o - acc22122 =fkind*acc22122*cmlsa[lsa - 1]",million + acc22122 =fkind*acc22122*cmlsa[lsa - 1]",million 15,acc22123,c,Blanket_stainless_steel_cost_(M$),FusionFunc,"acc22123 = acc22123 = 1.0e-6*whtblss*ucblss - acc22123 = fkind*acc22123*cmlsa[lsa - 1]",million + acc22123 = fkind*acc22123*cmlsa[lsa - 1]",million 16,acc22124,c,Blanket_vanadium_cost_(M$),FusionFunc,"if ife == 1: acc22124 = 1.0e-6*whtblvd*ucblvd else: acc22124 = 0 acc22124 = fkind*acc22124*cmlsa[lsa-1] - return acc22124",million + return acc22124",million 17,acc22131,c,Bulk_shield_cost_(M$),FusionFunc,"if ife == 1: acc22131 = 1.0e-6*cmlsa[lsa - 1]*ucshld*(shmatm[1, 0] + shmatm[2, 0]+shmatm[3, 0]) + uccarb*(shmatm[1, 1]+ shmatm[2, 1]+ shmatm[3, 1]) @@ -62,14 +62,14 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units + ucconc* (shmatm[1, 1] + shmatm[2, 1]+ shmatm[3, 1]) else: acc22131 = 1.0e-6*whtshld*ucshld*cmlsa[lsa - 1] - acc22131 = fkind*acc22131",million + acc22131 = fkind*acc22131",million 18,acc22132,c,Penetration_shielding_cost_(M$),FusionFunc,"if ife == 1: acc22132 = 1.0e-6*wpenshld*ucpens* cmlsa[lsa - 1] else: acc22132 = 1.0e-6*wpenshld*ucpens* cmlsa[lsa - 1] - acc22132 = fkind*acc22132",million + acc22132 = fkind*acc22132",million 19,acc2214,c,Total_support_structure_cost_(M$),FusionFunc,"acc2214 = 1.0e-6*gsmass*ucgss*cmlsa[lsa - 1] - acc2214 = fkind*acc2214",million + acc2214 = fkind*acc2214",million 20,acc2215,c,Divertor_cost_(M$),FusionFunc,"if ife == 1: acc2215 = 0 divcst = 0 @@ -82,7 +82,7 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units elif ifueltyp == 2: divcst = acc2215 else: - divcst = 0.0e0 ",million + divcst = 0.0e0 ",million 21,acc22211,c,TF_coil_conductor_cost_(M$),FusionFunc,"if i_tf_sup == 1: costtfsc = ucsc[i_tf_sc_mat - 1]*whtconsc/(tfleng*n_tf_turn) costtfcu = uccu*whtconcu/(tfleng*n_tf_turn) @@ -97,40 +97,40 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units acc22211 = cpstcst accc22211 = 0.0e0 elif (itart == 1) and (ifueltyp == 2): - acc22211 = cpstcst",million + acc22211 = cpstcst",million 22,acc22212,c,TF_coil_winding_cost_(M$),FusionFunc,"if i_tf_sup == 1: acc22212 = 1.0e-6*ucwindtf*n_tf*tfleng*n_tf_turn acc22212 = fkind*acc22212*cmlsa[lsa-1] else: acc22212 = 1.0e-6*whttflgs*uccpclb*cmlsa[lsa - 1] - acc22212 = fkind*acc22212",million + acc22212 = fkind*acc22212",million 23,acc22213,c,TF_coil_case_cost_(M$),FusionFunc," if i_tf_sup == 1: acc22213 = 1.0e-6*(whtcas*uccase)*n_tf acc22213 = fkind*acc22213*cmlsa[lsa - 1] else: - acc22213 = 0",million + acc22213 = 0",million 24,acc22214,c,TF_intercoil_structure_cost_(M$),FusionFunc,"if i_tf_sup == 1: acc22214 = 1.0e-6*aintmass*ucint acc22214 = fkind*acc22214*cmlsa[lsa - 1] else: - acc22214 = 0",million + acc22214 = 0",million 25,acc22215,c,TF_coil_gravity_support_structure_(M$),FusionFunc,"if i_tf_sup == 1: acc22215 = 1.0e-6*clgsmass*ucgss acc22215 = fkind*acc22215*cmlsa[lsa - 1] else: - acc22215 = 0",million -26,acc22221,c,PF_coil_conductor_cost_(M$),FusionFunc,,million + acc22215 = 0",million +26,acc22221,c,PF_coil_conductor_cost_(M$),FusionFunc,,million 27,acc22222,c,PF_coil_winding_cost_(M$),FusionFunc,"for i in range(0, nohc): pfwndl = pfwndl +(twopi*rpf[i] *turns[i]) acc22222 = 1.0e-6*ucwindpf*pfwndl - acc22222 = fkind*acc22222*cmlsa[lsa - 1]",million + acc22222 = fkind*acc22222*cmlsa[lsa - 1]",million 28,acc22223,c,PF_coil_case_cost_(M$),FusionFunc,"acc22223 = 1.0e-6*uccase*whtpfs - acc22223 = fkind*acc22223*cmlsa[lsa - 1]",million + acc22223 = fkind*acc22223*cmlsa[lsa - 1]",million 29,acc22224,c,PF_coil_support_structure_cost_(M$),FusionFunc,"acc22224 = 1.0e-6*ucfnc*fncmass - acc22224 = fkind*acc22224*cmlsa[lsa - 1]",million + acc22224 = fkind*acc22224*cmlsa[lsa - 1]",million 30,acc2223,c,Vacuum_vessel_assembly_cost_(M$),FusionFunc,"acc2223 = 1.0e-6*vvmass*uccryo - acc2223 = fkind*acc2223*cmlsa[lsa - 1]",million -31,acc2231,c,ECH_system_cost_(M$),FusionFunc,,million + acc2223 = fkind*acc2223*cmlsa[lsa - 1]",million +31,acc2231,c,ECH_system_cost_(M$),FusionFunc,,million 32,acc2232,c,Lower_hybrid_system_cost_(M$),FusionFunc,"if ife == 1: if iefrf == 2: acc2232 = (1.0e-6*uclh*(1.0e6*plhybd)**exprf) @@ -141,7 +141,7 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units acc2232 = fkind * acc2232 else: if ifueltyp == 1: - acc2232 = 0.0e0",million + acc2232 = 0.0e0",million 33,acc2233,c,Neutral_beam_system_cost_(M$),FusionFunc,"if ife == 1: acc2233 = (1.0e-6*ucnbi*(1.0e6*pnbitot)**exprf) if ifueltyp == 1: @@ -149,53 +149,53 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units acc2233 = fkind*acc2233 else: if ifedrv == 2: - acc2233 = 0.0e0",million + acc2233 = 0.0e0",million 34,acc2241,c,High_vacuum_pumps_cost_(M$),FusionFunc,"if ntype == 1: acc2241 = 1.0e-6*vpumpn*uccpmp else: acc2241 = 1.0e-6*vpumpn*uctpmp - acc2241 = fkind*acc2241",million + acc2241 = fkind*acc2241",million 35,acc2242,c,Backing_pumps_cost_(M$),FusionFunc,"acc2242 = 1.0e-6*nvduct*ucbpmp - acc2242 = fkind*acc2242 ",million -36,acc2243,c,Vacuum_duct_cost_(M$),FusionFunc,,million + acc2242 = fkind*acc2242 ",million +36,acc2243,c,Vacuum_duct_cost_(M$),FusionFunc,,million 37,acc2244,c,Valves_cost_(M$),FusionFunc,"acc2244 = 1.0e-6*2.0e0*nvduct*((vcdimax*1.2e0)**1.4e0)*ucvalv - acc2244 = fkind*acc2244",million + acc2244 = fkind*acc2244",million 38,acc2245,c,Duct_shielding_cost_(M$),FusionFunc,"acc2245 = 1.0e-6*nvduct*vacdshm*ucvdsh - acc2245 = fkind*acc2245",million + acc2245 = fkind*acc2245",million 39,acc2246,c,Instrumentation_cost_(M$),FusionFunc,"acc2246 = 1.0e-6*ucviac - acc2246 = fkind*acc2246",million + acc2246 = fkind*acc2246",million 40,acc22511,c,TF_coil_power_supplies_cost_(M$),FusionFunc,"acc22511 = 1.0e-6*uctfps*(tfckw*1.0e3+tfcmw*1.0e6)**expel - acc22511 = fkind*acc22511",million + acc22511 = fkind*acc22511",million 41,acc22512,c,TF_coil_breakers_cost_(M$),FusionFunc," if i_tf_sup == 1: acc22512 = 1.0e-6*(uctfbr*n_tf*(cpttf*vtfskv*1.0e3)**expel+uctfsw*cpttf) else: acc22512 = 0.0e0 - acc22512 = fkind*acc22512",million + acc22512 = fkind*acc22512",million 42,acc22513,c,TF_coil_dump_resistors_cost_(M$),FusionFunc,"acc22513 = 1.0e-6*(1.0e9*uctfdr*estotftgj+uctfgr*0.5e0*n_tf) - acc22513 = fkind*acc22513",million + acc22513 = fkind*acc22513",million 43,acc22514,c,TF_coil_instrumentation_and_control_(M$),FusionFunc,"acc22514 = 1.0e-6*uctfic*(30.0e0*n_tf) - acc22514 = fkind*acc22514 ",million + acc22514 = fkind*acc22514 ",million 44,acc22515,c,TF_coil_bussing_cost_(M$),FusionFunc," if i_tf_sup == 1: acc22515 = 1.0e-6*ucbus*cpttf*tfbusl else: acc22515 = 1.0e-6*uctfbus*tfbusmas - acc22515 = fkind*acc22515",million -45,acc22521,c,PF_coil_power_supplies_cost_(M$),FusionFunc,,million + acc22515 = fkind*acc22515",million +45,acc22521,c,PF_coil_power_supplies_cost_(M$),FusionFunc,,million 46,acc22522,c,PF_coil_instrumentation_and_control_(M$),FusionFunc,"acc22522 = 1.0e-6*ucpfic*pfckts*30.0e0 - acc22522 = fkind*acc22522",million + acc22522 = fkind*acc22522",million 47,acc22523,c,PF_coil_bussing_cost_(M$),FusionFunc,"acc22523 = 1.0e-6*ucpfb*spfbusl*acptmax - acc22523 = fkind*acc22523",million + acc22523 = fkind*acc22523",million 48,acc22524,c,PF_coil_burn_power_supplies_cost_(M$),FusionFunc,"if pfckts == 0: acc22524 = 0.0e0 else: acc22524 = 1.0e-6*ucpfbs*pfckts*(srcktpm/pfckts)**0.7e0 - acc22524 = fkind*acc22524",million + acc22524 = fkind*acc22524",million 49,acc22525,c,PF_coil_breakers_cost_(M$),FusionFunc,"acc22525 = 1.0e-6*ucpfbk*pfckts*((acptmax*vpfskv)**0.7e0) - acc22525 = fkind*acc22525",million + acc22525 = fkind*acc22525",million 50,acc22526,c,PF_coil_dump_resistors_cost_(M$),FusionFunc,"acc22526 = 1.0e-6*ucpfdr1*ensxpfm - acc22526 = fkind*acc22526",million + acc22526 = fkind*acc22526",million 51,acc22527,c,PF_coil_ac_breakers_cost_(M$),FusionFunc," acc22527 = 1.0e-6*ucpfcb*pfckts - acc22527 = fkind*acc22527",million + acc22527 = fkind*acc22527",million 52,acc2253,c,"Total,_energy_storage_cost_(M$)",FusionFunc,"if lpulse == 1: if istore == 1: acc2253 = 0.1e0 @@ -218,51 +218,51 @@ ind,alg_name,alg_for,alg_description,alg_python,alg_formulation,alg_units acc2253 = ucblss*(pthermmw * 1.0e6)*tdown/(shcss*dtstor) if istore < 3: acc2253 = acc2253*pnetelmw / 1200.0e0 - acc2253 = acc2253*1.36e0",million + acc2253 = acc2253*1.36e0",million 53,accpp,c,Pumps_and_piping_system_cost_(M$),FusionFunc,"accpp = 1.0e-6*uchts[coolwh-1]*((1.0e6*pfwdiv)**exphts+ (1.0e6*pnucblkt)**exphts+(1.0e6*pnucshld)**exphts) - accpp =fkind*accpp*cmlsa[lsa - 1]",million + accpp =fkind*accpp*cmlsa[lsa - 1]",million 54,acchx,c,Primary_heat_exchanger_cost_(M$),FusionFunc,"acchx = 1.0e-6*ucphx*nphx*(1.0e6*pthermmw/nphx)**exphts - acchx =fkind*acchx*cmlsa[lsa - 1]",million + acchx =fkind*acchx*cmlsa[lsa - 1]",million 55,accppa,c,"Pumps,_piping_cost_(M$)",FusionFunc,"acccppa = (1.0e-6*ucahts*((1.0e6*pinjht)**exphts+(1.0e6*crypmw)**exphts+ (1.0e6*vachtmw)**exphts+(1.0e6*trithtmw)**exphts+(1.0e6*fachtmw)**exphts)) if ife == 1: acccppa = acccppa+1.0e-6*ucahts*((1.0e6*tdspmw)**exphts + (1.0e6*tfacmw)**exphts) - acccppa =fkind*acccppa*cmlsa[lsa - 1]",million -56,acc2262,c,"Total,_auxiliary_cooling_system_cost_(M$)",FusionFunc,"cal_acc2262 = cal_accppa",million -57,acc2263,c,"Total,_cryogenic_system_cost_(M$)",FusionFunc,,million + acccppa =fkind*acccppa*cmlsa[lsa - 1]",million +56,acc2262,c,"Total,_auxiliary_cooling_system_cost_(M$)",FusionFunc,cal_acc2262 = cal_accppa,million +57,acc2263,c,"Total,_cryogenic_system_cost_(M$)",FusionFunc,,million 58,acc2271,c,Fuelling_system_cost_(M$),FusionFunc,"acc2271 = 1.0e-6*ucf1 - acc2271 = fkind*acc2271",million + acc2271 = fkind*acc2271",million 59,acc2272,c,Fuel_processing_and_purification_cost_(M$),FusionFunc,"if ife == 1: targtm = (gain*edrive*3.0e0*1.67e-27*1.0e3)/(1.602e-19 * 17.6e6 * fburn) wtgpd = targtm*reprat*86400.0e0 else: wtgpd = 2.0e0*rndfuel*afuel*umass*1000.0e0*86400.0e0 acc2272 = 1.0e-6*ucfpr*(0.5e0+0.5e0*(wtgpd/60.0e0)**0.67e0) - acc2272 = fkind*acc2272",million + acc2272 = fkind*acc2272",million 60,acc2273,c,Atmospheric_recovery_systems_cost_(M$),FusionFunc,"if ftrit > 1.0e-3: acc2273 = (1.0e-6*ucdtc*((cfrht / 1.0e4) ** 0.6e0*(volrci+wsvol))) else: acc2273 = 0.0e0 - acc2273 = fkind*acc2273",million + acc2273 = fkind*acc2273",million 61,acc2274,c,Nuclear_building_ventilation_cost_(M$),FusionFunc,"acc2274 = 1.0e-6*ucnbv*(volrci+wsvol)**0.8e0 - acc2274 =fkind*acc2274",million + acc2274 =fkind*acc2274",million 62,acc228,c,Instrumentation_and_control_cost_(M$),FusionFunc,"acc228 = 1.0e-6*uciac - acc228 = fkind*acc228",million + acc228 = fkind*acc228",million 63,acc229,c,Maintenance_equipment_cost_(M$),FusionFunc,"acc229 = 1.0e-6*ucme - acc229 = fkind*acc229",million + acc229 = fkind*acc229",million 64,acc23,c,Turbine_plant_equipment_cost_(M$),FusionFunc,"if ireactor == 1: - acc23 = (1.0e-6*ucturb[coolwh - 1]*(pgrossmw / 1200.0e0)**exptpe)",million -65,acc241,c,Switchyard_equipment_cost_(M$),FusionFunc,"acc241 = 1.0e-6*ucswyd*cmlsa[lsa - 1]",million + acc23 = (1.0e-6*ucturb[coolwh - 1]*(pgrossmw / 1200.0e0)**exptpe)",million +65,acc241,c,Switchyard_equipment_cost_(M$),FusionFunc,acc241 = 1.0e-6*ucswyd*cmlsa[lsa - 1],million 66,acc242,c,Transformers_cost_(M$),FusionFunc,"acc242 = 1.0e-6*((ucpp*(pacpmw* 1.0e3)**expepe)+ucap*(fcsht * 1.0e3)) - acc242 = acc242 * cmlsa[lsa - 1]",million -67,acc243,c,Low_voltage_equipment_cost_(M$),FusionFunc,,million -68,acc244,c,Diesel_backup_equipment_cost_(M$),FusionFunc,"acc244 = 1.0e-6*ucdgen*4.0e0*cmlsa[lsa - 1]",million -69,acc245,c,Auxiliary_facilities_cost_(M$),FusionFunc,"acc245 = 1.0e-6*ucaf*cmlsa[lsa - 1]",million -70,acc25,c,Miscellaneous_plant_equipment_cost_(M$),FusionFunc,"acc25 = 1.0e-6*ucmisc*cmlsa[lsa - 1]",million + acc242 = acc242 * cmlsa[lsa - 1]",million +67,acc243,c,Low_voltage_equipment_cost_(M$),FusionFunc,,million +68,acc244,c,Diesel_backup_equipment_cost_(M$),FusionFunc,acc244 = 1.0e-6*ucdgen*4.0e0*cmlsa[lsa - 1],million +69,acc245,c,Auxiliary_facilities_cost_(M$),FusionFunc,acc245 = 1.0e-6*ucaf*cmlsa[lsa - 1],million +70,acc25,c,Miscellaneous_plant_equipment_cost_(M$),FusionFunc,acc25 = 1.0e-6*ucmisc*cmlsa[lsa - 1],million 71,acc26,c,Heat_rejection_system_cost_(M$),FusionFunc,"if ireactor == 0: pwrrej = powfmw+pinjwp+tfcmw else: pwrrej = pthermmw - pgrossmw - acc26 = (1.0e-6*uchrs*pwrrej)/ 2300.0e0*cmlsa[lsa - 1]",million + acc26 = (1.0e-6*uchrs*pwrrej)/ 2300.0e0*cmlsa[lsa - 1]",million \ No newline at end of file From 7e98d796d24aa12848cc73c25ead0caffc4cdfe1 Mon Sep 17 00:00:00 2001 From: Joseph Chang Date: Mon, 30 Jun 2025 10:24:44 -0500 Subject: [PATCH 06/27] webhost post processing created a web GUI interface, for post processing data and data output visualization --- src/Main.py | 33 +- src/webhost/accel_2214_output_excel.csv | 91 ++ src/webhost/csv_extractor.py | 88 ++ src/webhost/debug_table.html | 97 ++ src/webhost/index.html | 89 ++ src/webhost/requirements.txt | 2 + src/webhost/server.py | 87 ++ src/webhost/start_server.bat | 15 + src/webhost/table_display.html | 1222 +++++++++++++++++++++++ src/webhost/upload_processor.html | 295 ++++++ 10 files changed, 2012 insertions(+), 7 deletions(-) create mode 100644 src/webhost/accel_2214_output_excel.csv create mode 100644 src/webhost/csv_extractor.py create mode 100644 src/webhost/debug_table.html create mode 100644 src/webhost/index.html create mode 100644 src/webhost/requirements.txt create mode 100644 src/webhost/server.py create mode 100644 src/webhost/start_server.bat create mode 100644 src/webhost/table_display.html create mode 100644 src/webhost/upload_processor.html diff --git a/src/Main.py b/src/Main.py index 9b86c19..8498bc4 100755 --- a/src/Main.py +++ b/src/Main.py @@ -1944,13 +1944,32 @@ def generate_results_table(self, c, conn, level=3): ins.read(initfile) passwd = ins.get("INSTALL","PASSWD") - conn = mysql.connector.connect( - host="localhost", - user="root", - password=passwd, - database="accert_db", - auth_plugin="mysql_native_password" - ) + try: + conn = mysql.connector.connect( + host="localhost", + user="root", + password=passwd, + database="accert_db", + use_pure=True, + autocommit=True + ) + except mysql.connector.Error as err: + print(f"MySQL connection failed: {err}") + print("Trying alternative connection method...") + try: + conn = mysql.connector.connect( + host="localhost", + user="root", + password=passwd, + database="accert_db", + auth_plugin="caching_sha2_password", + use_pure=True, + autocommit=True + ) + except mysql.connector.Error as err2: + print(f"Alternative connection also failed: {err2}") + print("Please check your MySQL installation and credentials.") + sys.exit(1) # conn.commit() # NOTE: cursor is a class that instantiates objects that can execute MySQL statements # only commit when you are sure that the transaction is complete diff --git a/src/webhost/accel_2214_output_excel.csv b/src/webhost/accel_2214_output_excel.csv new file mode 100644 index 0000000..aada136 --- /dev/null +++ b/src/webhost/accel_2214_output_excel.csv @@ -0,0 +1,91 @@ +code_of_account,account_description,total_cost,level,review_status +2,Plant direct cost,"5,523.93",0,Updated +21,Total account 21 cost,778.65,1,Updated +211,"Site improvements, facilities, land",35.20,2,User Input +212,Reactor building cost,452.16,2,User Input +213,Turbine building cost,38.00,2,User Input +214,Reactor maintenance and warm shop buildings cost,160.71,2,Updated +2141,Reactor maintenance building cost,103.07,3,User Input +2142,Warm shop cost,57.64,3,User Input +215,Tritium building cost,14.80,2,User Input +216,Electrical equipment building cost,19.71,2,User Input +217,Other buildings cost,58.07,2,Updated +2171,Additional buildings cost,18.00,3,User Input +2172,Control room buildings cost,21.00,3,User Input +2173,Shop and warehouses cost,11.50,3,User Input +2174,Cryogenic building cost,7.57,3,User Input +22,Total account 22 cost,"4,450.97",1,Updated +221,Total account 221 cost,"1,413.06",2,Updated +2211,First wall cost,191.30,3,Unchanged +2212,Blanket total cost,981.66,3,Updated +22121,Blanket beryllium cost,261.09,4,User Input +22122,Blanket breeder material cost,639.85,4,User Input +22123,Blanket stainless steel cost,80.73,4,User Input +22124,Blanket vanadium cost,0.00,4,User Input +2213,Total shield cost,156.79,3,Updated +22131,Bulk shield cost,78.39,4,User Input +22132,Penetration shielding cost,78.39,4,User Input +2214,Total support structure cost,41.65,3,User Input +2215,Divertor cost,41.66,3,Unchanged +222,Total account 222 cost,"1,755.39",2,Updated +2221,TF magnet assemblies cost,820.55,3,Updated +22211,TF coil conductor cost,130.26,4,User Input +22212,TF coil winding cost,55.70,4,User Input +22213,TF coil case cost,439.11,4,User Input +22214,TF intercoil structure cost,150.04,4,User Input +22215,TF coil gravity support structure,45.44,4,User Input +2222,PF magnet assemblies cost,680.80,3,Updated +22221,PF coil conductor cost,466.07,4,User Input +22222,PF coil winding cost,77.13,4,User Input +22223,PF coil case cost,129.55,4,User Input +22224,PF coil support structure cost,8.05,4,User Input +2223,Vacuum vessel assembly cost,254.04,3,User Input +223,Total account 223 cost,241.05,2,Updated +2231,ECH system cost,241.05,3,Unchanged +2232,Lower hybrid system cost,0.00,3,Unchanged +2233,Neutral beam system cost,0.00,3,Unchanged +224,Total account 224 cost,26.93,2,Updated +2241,High vacuum pumps cost,12.48,3,Unchanged +2242,Backing pumps cost,4.68,3,Unchanged +2243,Vacuum duct cost,2.59,3,Unchanged +2244,Valves cost,5.88,3,Unchanged +2245,Duct shielding cost,0.00,3,Unchanged +2246,Instrumentation cost,1.30,3,Unchanged +225,Total account 225 cost,154.88,2,Updated +2251,"Total, TF coil power costs",98.21,3,Updated +22511,TF coil power supplies cost,3.97,4,Unchanged +22512,TF coil breakers cost,34.11,4,Unchanged +22513,TF coil dump resistors cost,21.13,4,Unchanged +22514,TF coil instrumentation and control,4.80,4,Unchanged +22515,TF coil bussing cost,34.20,4,Unchanged +2252,"Total, PF coil power costs",39.77,3,Updated +22521,PF coil power supplies cost,2.93,4,Unchanged +22522,PF coil instrumentation and control,3.60,4,Unchanged +22523,PF coil bussing cost,12.00,4,Unchanged +22524,PF coil burn power supplies cost,1.27,4,Unchanged +22525,PF coil breakers cost,14.71,4,Unchanged +22526,PF coil dump resistors cost,4.36,4,Unchanged +22527,PF coil ac breakers cost,0.90,4,Unchanged +2253,"Total, energy storage cost",16.90,3,Unchanged +226,Total account 226 cost,332.12,2,Updated +2261,"Total, reactor cooling system cost",109.47,3,Updated +22611,Pumps and piping system cost,37.13,4,Unchanged +22612,Primary heat exchanger cost,72.34,4,Unchanged +2262,"Pumps, piping cost",29.30,3,User Input +2263,"Total, cryogenic system cost",193.35,3,User Input +227,Total account 227 cost,252.54,2,Updated +2271,Fuelling system cost,22.30,3,Unchanged +2272,Fuel processing and purification cost,103.00,3,Unchanged +2273,Atmospheric recovery systems cost,58.06,3,Unchanged +2274,Nuclear building ventilation cost,69.18,3,Unchanged +228,Instrumentation and control cost,150.00,2,Unchanged +229,Maintenance equipment cost,125.00,2,Unchanged +23,Turbine plant equipment cost,178.01,1,Unchanged +24,Total account 24 cost,40.78,1,Updated +241,Switchyard equipment cost,18.40,2,User Input +242,Transformers cost,7.50,2,User Input +243,Low voltage equipment cost,6.58,2,User Input +244,Diesel backup equipment cost,6.80,2,User Input +245,Auxiliary facilities cost,1.50,2,User Input +25,Miscellaneous plant equipment cost,25.00,1,User Input +26,Heat rejection system cost,50.52,1,User Input diff --git a/src/webhost/csv_extractor.py b/src/webhost/csv_extractor.py new file mode 100644 index 0000000..9628832 --- /dev/null +++ b/src/webhost/csv_extractor.py @@ -0,0 +1,88 @@ +import csv +import os +import argparse + +# Author: Daeho Chang +# Email: daeho.chang@anl.gov +# Created: June 30, 2025 +# Description: Extracts a markdown-style table from a text file and saves it as a CSV file. + +def extract_table_to_csv(input_file_path): + """ + Extracts a markdown-style table from a text file and saves it as a CSV file. + + The script identifies the table based on a header containing 'code_of_account'. + It assumes the table is formatted with '|' as column separators and '+--' as + horizontal rule. + + Args: + input_file_path (str): The path to the input .out file. + """ + output_filename = "accel_2214_output_excel.csv" + + if not os.path.isfile(input_file_path): + print(f"Error: Input file not found at '{input_file_path}'") + return + + with open(input_file_path, 'r', encoding='utf-8') as f: + lines = f.readlines() + + header = [] + data_rows = [] + + header_keyword = 'code_of_account' + header_index = -1 + for i, line in enumerate(lines): + if header_keyword in line and '|' in line: + header_index = i + break + + if header_index == -1: + print(f"Error: Could not find table header with keyword '{header_keyword}'") + return + + header_line = lines[header_index] + header = [h.strip() for h in header_line.split('|') if h.strip()] + + # Table data starts 2 lines after the header (skipping the separator line) + for i in range(header_index + 2, len(lines)): + line = lines[i].strip() + if line.startswith('+--'): # End of table + break + + if '|' in line: + row = [item.strip() for item in line.split('|') if item.strip()] + # Ensure the row has the same number of columns as the header + if len(row) == len(header): + data_rows.append(row) + + if not data_rows: + print("Warning: No data rows were found for the table.") + return + + # Save output in the same directory as the script + script_dir = os.path.dirname(os.path.abspath(__file__)) + output_filepath = os.path.join(script_dir, output_filename) + + try: + with open(output_filepath, 'w', newline='', encoding='utf-8') as csvfile: + writer = csv.writer(csvfile) + writer.writerow(header) + writer.writerows(data_rows) + print(f"Successfully created CSV file at: {os.path.abspath(output_filepath)}") + except IOError as e: + print(f"Error: Could not write to file '{output_filepath}'. Reason: {e}") + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='Extracts a table from a text file and saves it as a CSV file.', + formatter_class=argparse.RawTextHelpFormatter + ) + parser.add_argument( + 'input_file', + help='Path to the input file (e.g., output.out).' + ) + + args = parser.parse_args() + + extract_table_to_csv(args.input_file) \ No newline at end of file diff --git a/src/webhost/debug_table.html b/src/webhost/debug_table.html new file mode 100644 index 0000000..ccbc7e3 --- /dev/null +++ b/src/webhost/debug_table.html @@ -0,0 +1,97 @@ + + + + + + + Debug - ACCEL 2214 Output + + + + +

Debug - ACCEL 2214 Output Data

+
Loading...
+ + + +
+ + + + \ No newline at end of file diff --git a/src/webhost/index.html b/src/webhost/index.html new file mode 100644 index 0000000..68dc064 --- /dev/null +++ b/src/webhost/index.html @@ -0,0 +1,89 @@ + + + + + + + ACCERT Output Processor + + + +

ACCERT Output Processor

+ +
+

Upload & Process ACCERT Output

+

+ Upload your output.out file from ACCERT and automatically extract the table data for interactive viewing. +

+ Upload & Process File +
+ +
+

View Results Table

+

+ View the processed data in an interactive table with search, sort, and export capabilities. +

+ View Table +
+ +
+

Debug Table

+

+ Debug version with detailed information about the CSV loading process. +

+ Debug Table +
+ + \ No newline at end of file diff --git a/src/webhost/requirements.txt b/src/webhost/requirements.txt new file mode 100644 index 0000000..0acdf5f --- /dev/null +++ b/src/webhost/requirements.txt @@ -0,0 +1,2 @@ +Flask==2.3.3 +Werkzeug==2.3.7 \ No newline at end of file diff --git a/src/webhost/server.py b/src/webhost/server.py new file mode 100644 index 0000000..7da346e --- /dev/null +++ b/src/webhost/server.py @@ -0,0 +1,87 @@ +from flask import Flask, request, jsonify, send_from_directory, render_template_string +import os +import tempfile +import subprocess +import sys +from werkzeug.utils import secure_filename + +# Author: Daeho Chang +# Email: daeho.chang@anl.gov +# Created: June 30, 2025 +# Description: Flask server for ACCERT Output Processor + +app = Flask(__name__) +app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size + +# Ensure the dev directory is in the Python path +current_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, current_dir) + +@app.route('/') +def index(): + return send_from_directory('.', 'index.html') + +@app.route('/upload_processor.html') +def upload_processor(): + return send_from_directory('.', 'upload_processor.html') + +@app.route('/table_display.html') +def table_display(): + return send_from_directory('.', 'table_display.html') + +@app.route('/debug_table.html') +def debug_table(): + return send_from_directory('.', 'debug_table.html') + +@app.route('/process_output', methods=['POST']) +def process_output(): + try: + if 'file' not in request.files: + return jsonify({'error': 'No file uploaded'}), 400 + + file = request.files['file'] + if file.filename == '': + return jsonify({'error': 'No file selected'}), 400 + + # Create a temporary file to store the uploaded content + with tempfile.NamedTemporaryFile(mode='w+b', delete=False, suffix='.out') as temp_file: + file.save(temp_file.name) + temp_file_path = temp_file.name + + try: + # Import and run the CSV extractor + from csv_extractor import extract_table_to_csv + + # Process the file + extract_table_to_csv(temp_file_path) + + # Check if the CSV was created + csv_path = os.path.join(current_dir, 'accel_2214_output_excel.csv') + if os.path.exists(csv_path): + return jsonify({ + 'success': True, + 'filename': 'accel_2214_output_excel.csv', + 'message': 'File processed successfully' + }) + else: + return jsonify({'error': 'CSV file was not created'}), 500 + + finally: + # Clean up temporary file + if os.path.exists(temp_file_path): + os.unlink(temp_file_path) + + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/') +def serve_file(filename): + """Serve static files""" + return send_from_directory('.', filename) + +if __name__ == '__main__': + print("Starting ACCERT Output Processor Server...") + print("Access the application at: http://localhost:3000") + print("Upload page: http://localhost:3000") + print("Table display: http://localhost:3000/table_display.html") + app.run(debug=True, host='0.0.0.0', port=3000) \ No newline at end of file diff --git a/src/webhost/start_server.bat b/src/webhost/start_server.bat new file mode 100644 index 0000000..b14e314 --- /dev/null +++ b/src/webhost/start_server.bat @@ -0,0 +1,15 @@ +@echo off +echo Installing Flask dependencies... +pip install -r requirements.txt + +echo. +echo Starting ACCERT Output Processor Server... +echo. +echo Access the application at: http://localhost:5000 +echo Upload page: http://localhost:5000 +echo Table display: http://localhost:5000/table_display.html +echo. +echo Press Ctrl+C to stop the server +echo. + +python server.py \ No newline at end of file diff --git a/src/webhost/table_display.html b/src/webhost/table_display.html new file mode 100644 index 0000000..7742dd4 --- /dev/null +++ b/src/webhost/table_display.html @@ -0,0 +1,1222 @@ + + + + + + + ACCERT Output Data + + + + + + + +

ACCERT Output Data

+
+
+ +
+
+ + + + +
+
+ +
+
+ + + + + + + + +
+
+ + + + + + No accounts selected +
+
+ Select a level and accounts to generate a chart showing cost distribution. +
+
+ +
+
+ + + + +
+ + + + + diff --git a/src/webhost/upload_processor.html b/src/webhost/upload_processor.html new file mode 100644 index 0000000..02f65c8 --- /dev/null +++ b/src/webhost/upload_processor.html @@ -0,0 +1,295 @@ + + + + + + + ACCERT Output Processor + + + +

ACCERT Output Processor

+ +
+

How to use:

+
    +
  1. Upload your output.out file from ACCERT
  2. +
  3. Click "Process File" to extract the table data
  4. +
  5. View the results in the interactive table
  6. +
+
+ +
+

Upload ACCERT Output File

+ +
+

Drag and drop your output.out file here

+

or

+ + +
+ +
+

File Information

+

Name:

+

Size:

+

Type:

+
+ + + +
+ + +
+ + + + \ No newline at end of file From b544510f767fae7a095d072f0873cb591cd87f7b Mon Sep 17 00:00:00 2001 From: Joseph Chang Date: Mon, 30 Jun 2025 10:34:38 -0500 Subject: [PATCH 07/27] cross platform compatability windows/ mac os compatability patch script naming scheme update --- src/webhost/csv_extractor.py | 2 +- src/webhost/debug_table.html | 2 +- .../{accel_2214_output_excel.csv => init_process_data.csv} | 0 src/webhost/server.py | 4 ++-- src/webhost/table_display.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename src/webhost/{accel_2214_output_excel.csv => init_process_data.csv} (100%) diff --git a/src/webhost/csv_extractor.py b/src/webhost/csv_extractor.py index 9628832..2202195 100644 --- a/src/webhost/csv_extractor.py +++ b/src/webhost/csv_extractor.py @@ -18,7 +18,7 @@ def extract_table_to_csv(input_file_path): Args: input_file_path (str): The path to the input .out file. """ - output_filename = "accel_2214_output_excel.csv" + output_filename = "init_process_data.csv" if not os.path.isfile(input_file_path): print(f"Error: Input file not found at '{input_file_path}'") diff --git a/src/webhost/debug_table.html b/src/webhost/debug_table.html index ccbc7e3..c7e516a 100644 --- a/src/webhost/debug_table.html +++ b/src/webhost/debug_table.html @@ -37,7 +37,7 @@

Debug - ACCEL 2214 Output Data

debugDiv.innerHTML = 'Starting to fetch CSV...'; // Fetch and parse CSV with PapaParse - fetch('accel_2214_output_excel.csv') + fetch('init_process_data.csv') .then(response => { debugDiv.innerHTML += '
Response received: ' + response.status + ' ' + response.statusText; if (!response.ok) { diff --git a/src/webhost/accel_2214_output_excel.csv b/src/webhost/init_process_data.csv similarity index 100% rename from src/webhost/accel_2214_output_excel.csv rename to src/webhost/init_process_data.csv diff --git a/src/webhost/server.py b/src/webhost/server.py index 7da346e..1cd6b64 100644 --- a/src/webhost/server.py +++ b/src/webhost/server.py @@ -56,11 +56,11 @@ def process_output(): extract_table_to_csv(temp_file_path) # Check if the CSV was created - csv_path = os.path.join(current_dir, 'accel_2214_output_excel.csv') + csv_path = os.path.join(current_dir, 'init_process_data.csv') if os.path.exists(csv_path): return jsonify({ 'success': True, - 'filename': 'accel_2214_output_excel.csv', + 'filename': 'init_process_data.csv', 'message': 'File processed successfully' }) else: diff --git a/src/webhost/table_display.html b/src/webhost/table_display.html index 7742dd4..ef863c4 100644 --- a/src/webhost/table_display.html +++ b/src/webhost/table_display.html @@ -1180,7 +1180,7 @@

ACCERT Output Data

}); // Fetch and parse CSV with PapaParse - fetch('accel_2214_output_excel.csv') + fetch('init_process_data.csv') .then(response => response.text()) .then(csvText => { const results = Papa.parse(csvText, { header: true, skipEmptyLines: true }); From 02eb08b987dc61c561446acbf1de234ddced9d80 Mon Sep 17 00:00:00 2001 From: Joseph Chang Date: Mon, 30 Jun 2025 10:51:08 -0500 Subject: [PATCH 08/27] tutorial instructions instructions for the webhost pages --- docs/source/user/webhost_output.rst | 250 ++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 docs/source/user/webhost_output.rst diff --git a/docs/source/user/webhost_output.rst b/docs/source/user/webhost_output.rst new file mode 100644 index 0000000..2f5b135 --- /dev/null +++ b/docs/source/user/webhost_output.rst @@ -0,0 +1,250 @@ +Webhost Output Visualization +============================ + +The ACCERT webhost module provides a web-based interface for processing and visualizing ACCERT output data. This tool allows you to upload output files, extract tabular data, and view interactive tables and charts through your web browser. + +Installation Requirements +------------------------- + +Prerequisites +~~~~~~~~~~~~~ + +- Python 3.7 or higher +- Web browser (Chrome, Firefox, Safari, or Edge) + +Installing Dependencies +~~~~~~~~~~~~~~~~~~~~~~~ + +1. Navigate to the webhost directory: + + .. code-block:: bash + + cd src/webhost + +2. Install the required Python packages: + + .. code-block:: bash + + pip install -r requirements.txt + + This will install: + + - Flask 2.3.3 (web framework) + - Werkzeug 2.3.7 (WSGI utility library) + +Starting the Local Server +-------------------------- + +Method 1: Using Python (Recommended) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Open a terminal/command prompt and navigate to the webhost directory: + + .. code-block:: bash + + cd src/webhost + +2. Start the Flask server: + + .. code-block:: bash + + python server.py + +3. You should see output similar to: + + .. code-block:: text + + Starting ACCERT Output Processor Server... + Access the application at: http://localhost:3000 + Upload page: http://localhost:3000 + Table display: http://localhost:3000/table_display.html + * Running on all addresses (0.0.0.0) + * Running on http://127.0.0.1:3000 + * Running on http://[::]:3000 + +Method 2: Using Windows Batch File +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On Windows systems, you can use the provided batch file: + +1. Double-click ``start_server.bat`` in the webhost directory +2. The server will start automatically in a command prompt window + +Accessing the Web Interface +---------------------------- + +Once the server is running, open your web browser and navigate to: + +- **Main page**: http://localhost:3000 +- **Upload processor**: http://localhost:3000/upload_processor.html +- **Table display**: http://localhost:3000/table_display.html +- **Debug viewer**: http://localhost:3000/debug_table.html + +Using the Webhost Application +------------------------------ + +Step 1: Upload and Process Output Files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Go to the **Upload Processor** page (http://localhost:3000) +2. Click "Choose File" and select your ACCERT output file (``.out`` extension) +3. Click "Process File" to extract the tabular data +4. The system will process the file and create ``init_process_data.csv`` +5. You'll see a success message when processing is complete + +Step 2: View Processed Data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Navigate to the **Table Display** page (http://localhost:3000/table_display.html) +2. The page will automatically load the processed CSV data +3. Use the available features: + + **Search and Filter:** + + - Use the search box to filter rows by any column content + - Results update in real-time as you type + + **Data Grouping:** + + - Toggle "Group by Level" to organize data hierarchically + - Select different account levels (0-4) using the dropdown + - Filter accounts by code or description + + **Interactive Charts:** + + - Click "Show Charts" to enable visualization + - Select specific accounts to chart using the multi-select dropdown + - Use "Select All" or "Clear Selection" for quick selection + - Refresh charts with updated data using "Refresh Chart" + + **Data Export:** + + - Click "Download CSV" to save the current filtered data + +Step 3: Debug Data Issues +~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you encounter issues with data processing: + +1. Visit the **Debug Table** page (http://localhost:3000/debug_table.html) +2. This page shows: + + - CSV file loading status + - Parse errors (if any) + - Column information + - First 5 rows of data + - Detailed error messages + +File Structure and Processing +----------------------------- + +Input File Requirements +~~~~~~~~~~~~~~~~~~~~~~~ + +The webhost application expects ACCERT output files with: + +- Markdown-style table format +- Column separator: ``|`` (pipe character) +- Header containing ``code_of_account`` +- Horizontal rules with ``+--`` pattern + +Output File Location +~~~~~~~~~~~~~~~~~~~~ + +Processed CSV files are saved as: + +- **Filename**: ``init_process_data.csv`` +- **Location**: Same directory as the webhost application (``src/webhost/``) + +Command Line Processing +~~~~~~~~~~~~~~~~~~~~~~~ + +You can also process files directly using the command line: + +.. code-block:: bash + + cd src/webhost + python csv_extractor.py /path/to/your/output_file.out + +This will create ``init_process_data.csv`` in the webhost directory. + +Troubleshooting +--------------- + +Common Issues +~~~~~~~~~~~~~ + +**Server won't start:** + +- Check if Python is installed: ``python --version`` +- Verify dependencies are installed: ``pip list | grep Flask`` +- Try a different port if 3000 is busy + +**File upload fails:** + +- Ensure file size is under 16MB +- Check file format (should be plain text with table structure) +- Verify the file contains a table with ``code_of_account`` header + +**CSV not displaying:** + +- Check if ``init_process_data.csv`` exists in the webhost directory +- Try the debug page to see detailed error information +- Refresh the browser page + +**Charts not showing:** + +- Enable "Group by Level" first +- Click "Show Charts" button +- Select at least one account from the dropdown +- Try "Refresh Chart" if data seems stale + +Cross-Platform Compatibility +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The webhost application works on: + +- **Windows**: Use ``start_server.bat`` or ``python server.py`` +- **macOS**: Use ``python server.py`` in Terminal +- **Linux**: Use ``python server.py`` in terminal + +All file paths and operations are cross-platform compatible. + +Stopping the Server +-------------------- + +To stop the webhost server: + +1. Return to the terminal/command prompt where the server is running +2. Press ``Ctrl+C`` (Windows/Linux) or ``Cmd+C`` (macOS) +3. The server will shut down gracefully + +Advanced Configuration +---------------------- + +Port Configuration +~~~~~~~~~~~~~~~~~~ + +To change the default port (3000), modify ``server.py``: + +.. code-block:: python + + app.run(debug=True, host='0.0.0.0', port=YOUR_PORT_NUMBER) + +File Size Limits +~~~~~~~~~~~~~~~~ + +To modify the maximum upload file size, edit ``server.py``: + +.. code-block:: python + + app.config['MAX_CONTENT_LENGTH'] = SIZE_IN_BYTES + +Development Mode +~~~~~~~~~~~~~~~~ + +The server runs in debug mode by default. For production use, change: + +.. code-block:: python + + app.run(debug=False, host='0.0.0.0', port=3000) From 100be80b231474e765db9856540b20793127db53 Mon Sep 17 00:00:00 2001 From: Joseph Chang <31267839+electroaria7@users.noreply.github.com> Date: Sat, 19 Jul 2025 21:37:30 -0500 Subject: [PATCH 09/27] update workbench --- src/workbench.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/workbench.sh b/src/workbench.sh index 773ac8d..c91e3bd 100644 --- a/src/workbench.sh +++ b/src/workbench.sh @@ -4,4 +4,8 @@ ######################################################################## # Provide path to workbench-.app/Contents for macOS -workbench_path="/Applications/Workbench-5.5.1.app/Contents" \ No newline at end of file +<<<<<<< Updated upstream +workbench_path="/Applications/Workbench-5.5.1.app/Contents" +======= +workbench_path="B:\Workbench-5.5.1.app/Contents" +>>>>>>> Stashed changes From dce61d63b1848ceb9f3bdfea0ba7fefdbb761d45 Mon Sep 17 00:00:00 2001 From: Joseph Chang <31267839+electroaria7@users.noreply.github.com> Date: Sat, 19 Jul 2025 21:41:21 -0500 Subject: [PATCH 10/27] updated intructions to documentation --- ...5-07-19 at 21-26-54 ACCERT Output Data.png | Bin 0 -> 86832 bytes ...19 at 21-27-05 ACCERT Output Processor.png | Bin 0 -> 56175 bytes ...19 at 21-27-07 ACCERT Output Processor.png | Bin 0 -> 14113 bytes ...19 at 21-27-13 ACCERT Output Processor.png | Bin 0 -> 47661 bytes ...19 at 21-27-17 ACCERT Output Processor.png | Bin 0 -> 22329 bytes ...19 at 21-27-23 ACCERT Output Processor.png | Bin 0 -> 34421 bytes ...19 at 21-27-28 ACCERT Output Processor.png | Bin 0 -> 38941 bytes ...5-07-19 at 21-27-39 ACCERT Output Data.png | Bin 0 -> 519000 bytes ...5-07-19 at 21-27-47 ACCERT Output Data.png | Bin 0 -> 4734 bytes ...5-07-19 at 21-27-55 ACCERT Output Data.png | Bin 0 -> 92235 bytes docs/source/user/webhost_output.rst | 83 +++++++++++++++++- 11 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-26-54 ACCERT Output Data.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-05 ACCERT Output Processor.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-07 ACCERT Output Processor.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-13 ACCERT Output Processor.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-17 ACCERT Output Processor.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-23 ACCERT Output Processor.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-28 ACCERT Output Processor.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-39 ACCERT Output Data.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-47 ACCERT Output Data.png create mode 100644 docs/source/user/screenshots/Screenshot 2025-07-19 at 21-27-55 ACCERT Output Data.png diff --git a/docs/source/user/screenshots/Screenshot 2025-07-19 at 21-26-54 ACCERT Output Data.png b/docs/source/user/screenshots/Screenshot 2025-07-19 at 21-26-54 ACCERT Output Data.png new file mode 100644 index 0000000000000000000000000000000000000000..3425d219050f0b1ab174c083eff1a2b5fa72209e GIT binary patch literal 86832 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