From 7fe02cf010a94d36c22dde274b1201a4c8bd5e32 Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:34:29 +0000 Subject: [PATCH 1/5] unify costing interface --- process/caller.py | 9 +- process/costs.py | 1312 +++++++++++++++++++--------------------- process/costs_2015.py | 17 +- process/ife.py | 5 +- process/main.py | 41 +- process/output.py | 10 +- process/stellarator.py | 5 +- 7 files changed, 653 insertions(+), 746 deletions(-) diff --git a/process/caller.py b/process/caller.py index d0be83720a..d4ac6287b8 100644 --- a/process/caller.py +++ b/process/caller.py @@ -153,13 +153,8 @@ def call_models(self, xc): ---- | ------ 0 | 1990 costs model 1 | 2015 Kovari model - 2 | 2019 STEP model + 2 | Custom model """ - if ft.cost_variables.cost_model == 0: - self.models.costs.run(output=False) - elif ft.cost_variables.cost_model == 1: - self.models.costs_2015.run(output=False) - elif ft.cost_variables.cost_model == 2: - self.models.costs_step.run() + self.models.costs.run() # FISPACT and LOCA model (not used)- removed diff --git a/process/costs.py b/process/costs.py index e5de3b3b85..ed5b96c4a9 100644 --- a/process/costs.py +++ b/process/costs.py @@ -46,111 +46,30 @@ def __init__(self): float, 0.0, docstring="ccont account cost", units="M$" ) - # Account 226 - Heat transport system - self.c226 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2261 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2262 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2263 = AnnotatedVariable(float, 0.0, docstring="", units="") - - # Account 227 - Fuel handling - self.c227 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2271 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2272 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2273 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2274 = AnnotatedVariable(float, 0.0, docstring="", units="") - - # Account 24 - electrical plant equipment - self.c24 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c241 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c242 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c243 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c244 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c245 = AnnotatedVariable(float, 0.0, docstring="", units="") - - # Module Variables - self.c21 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c211 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c212 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c213 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c214 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2141 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2142 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c215 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c216 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c217 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2171 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2172 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2173 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2174 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2211 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2212 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22121 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22122 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22123 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22124 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22125 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22126 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22127 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2213 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22131 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22132 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2214 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2215 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2221 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22211 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22212 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22213 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22214 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22215 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2222 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22221 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22222 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22223 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22224 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2223 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c223 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2231 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2232 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2233 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2234 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c224 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2241 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2242 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2243 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2244 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2245 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2246 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c225 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2251 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22511 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22512 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22513 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22514 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22515 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2252 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22521 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22522 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22523 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22524 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22525 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22526 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22527 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c2253 = AnnotatedVariable(float, 0.0, docstring="", units="") - self.chx = AnnotatedVariable(float, 0.0, docstring="", units="") - self.cpp = AnnotatedVariable(float, 0.0, docstring="", units="") - self.cppa = AnnotatedVariable(float, 0.0, docstring="", units="") - self.c22128 = AnnotatedVariable(float, 0.0, docstring="", units="") - - def run(self, output: bool = False): - self.costs(output) - - def costs(self, output: bool): + for names in ( + (f"c226{no}" for no in ("", 1, 2, 3)), # Accnt 226: Heat transport system + (f"c227{no}" for no in ("", 1, 2, 3, 4)), # Accnt 227: Fuel handling + (f"c24{no}" for no in ("", 1, 2, 3, 4, 5)), # Accnt 24: elec equipment + (f"c21{no}" for no in ("", 1, 2, 3, 4, 41, 42, 5, 6, 7, 71, 72, 73, 74)), + ("c22",), + (f"c221{no}" for no in (1, 2, 21, 22, 23, 24, 25, 26, 27, 3, 31, 32, 4, 5)), + (f"c222{no}" for no in (1, 11, 12, 13, 14, 15, 2, 21, 22, 23, 24, 3)), + (f"c223{no}" for no in ("", 1, 2, 3, 4)), + (f"c224{no}" for no in ("", 1, 2, 3, 4, 5, 6)), + ( + f"c225{no}" + for no in ("", 1, 11, 12, 13, 14, 15, 2, 21, 22, 23, 24, 25, 26, 27, 3) + ), + ("chx", "cpp", "cppa", "c22128"), + ): + for i in names: + setattr(self, i, AnnotatedVariable(float, 0.0, docstring="", units="")) + + def run(self): """ Cost accounting for a fusion power plant author: P J Knight, CCFE, Culham Science Centre - outfile : input integer : output file unit - iprint : input integer : switch for writing to output file (1=yes) + This routine performs the cost accounting for a fusion power plant. The direct costs are calculated based on parameters input from other sections of the code. @@ -196,636 +115,736 @@ def costs(self, output: bool): # Cost of electricity if (cost_variables.ireactor == 1) and (cost_variables.ipnet == 0): - self.coelc(output) + self.coelc() - if output and cost_variables.output_costs == 1: + def output(self): + if cost_variables.output_costs == 0: + return - po.oheadr(self.outfile, "Detailed Costings (1990 US$)") - po.ovarre( - self.outfile, - "Acc.22 multiplier for Nth of a kind", - "(fkind)", - cost_variables.fkind, - ) - po.ovarin( - self.outfile, "Level of Safety Assurance", "(lsa)", cost_variables.lsa - ) - po.oblnkl(self.outfile) - po.oshead(self.outfile, "Structures and Site Facilities") - po.ocosts( - self.outfile, - "(c211)", - "Site improvements, facilities, land (M$)", - self.c211, - ) - po.ocosts(self.outfile, "(c212)", "Reactor building cost (M$)", self.c212) - po.ocosts(self.outfile, "(c213)", "Turbine building cost (M$)", self.c213) - po.ocosts( - self.outfile, - "(c2141)", - "Reactor maintenance building cost (M$)", - self.c2141, - ) - po.ocosts(self.outfile, "(c2142)", "Warm shop cost (M$)", self.c2142) - po.ocosts(self.outfile, "(c215)", "Tritium building cost (M$)", self.c215) - po.ocosts( - self.outfile, - "(c216)", - "Electrical equipment building cost (M$)", - self.c216, - ) - po.ocosts( - self.outfile, - "(c2171)", - "Additional buildings cost (M$)", - self.c2171, - ) - po.ocosts( + po.oheadr(self.outfile, "Power Reactor Costs (1990 US$)") + + po.ovarrf( + self.outfile, + "First wall / blanket life (years)", + "(fwbllife)", + fwbs_variables.bktlife, + ) + + if ife_variables.ife != 1: + po.ovarrf( self.outfile, - "(c2172)", - "Control room buildings cost (M$)", - self.c2172, + "Divertor life (years)", + "(divlife.)", + cost_variables.divlife, ) - po.ocosts( + if physics_variables.itart == 1: + po.ovarrf( + self.outfile, + "Centrepost life (years)", + "(cplife.)", + cost_variables.cplife, + ) + + po.ovarrf( + self.outfile, "Cost of electricity (m$/kWh)", "(coe)", cost_variables.coe + ) + + po.osubhd(self.outfile, "Power Generation Costs :") + # TODO: Convert fortran format to Python + # if ((annfwbl != annfwbl) or (annfwbl > 1.0e10) or (annfwbl < 0.0e0)) : + # write(outfile,*)'Problem with annfwbl' + # write(outfile,*)'fwallcst=', fwallcst, ' blkcst=', cost_variables.blkcst + # write(outfile,*)'crffwbl=', crffwbl, ' fcap0cp=', cost_variables.fcap0cp + # write(outfile,*)'feffwbl=', feffwbl, ' fwbllife=', fwbllife + + # write(outfile,200) # anncap,coecap, # annoam,coeoam, # anndecom,coedecom, # annfwbl,coefwbl, # anndiv,coediv, # anncp,coecp, # anncdr,coecdr, # annfuel,coefuel, # annwst,coewst, # annfuelt,coefuelt, # anntot,coe + + # 200 format( # t76,'Annual Costs, M$ COE, m$/kWh'// # 1x,'Capital Investment',t80,f10.2,10x,f10.2/ # 1x,'Operation & Maintenance',t80,f10.2,10x,f10.2/ # 1x,'Decommissioning Fund',t80,f10.2,10x,f10.2/ # 1x,'Fuel Charge Breakdown'// # 5x,'Blanket & first wall',t72,f10.2,10x,f10.2/ # 5x,'Divertors',t72,f10.2,10x,f10.2/ # 5x,'Centrepost (TART only)',t72,f10.2,10x,f10.2/ # 5x,'Auxiliary Heating',t72,f10.2,10x,f10.2/ # 5x,'Actual Fuel',t72,f10.2,10x,f10.2/ # 5x,'Waste Disposal',t72,f10.2,10x,f10.2/ # 1x,'Total Fuel Cost',t80,f10.2,10x,f10.2// # 1x,'Total Cost',t80,f10.2,10x,f10.2 ) + + if cost_variables.ifueltyp == 1: + po.oshead(self.outfile, "Replaceable Components Direct Capital Cost") + po.ovarrf( self.outfile, - "(c2173)", - "Shop and warehouses cost (M$)", - self.c2173, + "First wall direct capital cost (M$)", + "(fwallcst)", + cost_variables.fwallcst, ) - po.ocosts( + po.ovarrf( self.outfile, - "(c2174)", - "Cryogenic building cost (M$)", - self.c2174, + "Blanket direct capital cost (M$)", + "(blkcst)", + cost_variables.blkcst, ) - po.oblnkl(self.outfile) - po.ocosts(self.outfile, "(c21)", "Total account 21 cost (M$)", self.c21) - - po.oshead(self.outfile, "Reactor Systems") - po.ocosts(self.outfile, "(c2211)", "First wall cost (M$)", self.c2211) if ife_variables.ife != 1: - if fwbs_variables.iblanket == 4: - po.ocosts( - self.outfile, - "(c22121)", - "Blanket lithium-lead cost (M$)", - self.c22121, - ) - po.ocosts( - self.outfile, - "(c22122)", - "Blanket lithium cost (M$)", - self.c22122, - ) - else: - po.ocosts( - self.outfile, - "(c22121)", - "Blanket beryllium cost (M$)", - self.c22121, - ) - po.ocosts( + po.ovarrf( + self.outfile, + "Divertor direct capital cost (M$)", + "(divcst)", + cost_variables.divcst, + ) + if physics_variables.itart == 1: + po.ovarrf( self.outfile, - "(c22122)", - "Blanket breeder material cost (M$)", - self.c22122, + "Centrepost direct capital cost (M$)", + "(cpstcst)", + cost_variables.cpstcst, ) - po.ocosts( - self.outfile, - "(c22123)", - "Blanket stainless steel cost (M$)", - self.c22123, - ) - po.ocosts( - self.outfile, - "(c22124)", - "Blanket vanadium cost (M$)", - self.c22124, - ) - else: # IFE - po.ocosts( + po.ovarrf( self.outfile, - "(c22121)", - "Blanket beryllium cost (M$)", - self.c22121, + "Plasma heating/CD system cap cost (M$)", + "", + cost_variables.cdcost + * cost_variables.fcdfuel + / (1.0e0 - cost_variables.fcdfuel), ) - po.ocosts( + po.ovarrf( self.outfile, - "(c22122)", - "Blanket lithium oxide cost (M$)", - self.c22122, + "Fraction of CD cost --> fuel cost", + "(fcdfuel)", + cost_variables.fcdfuel, ) - po.ocosts( + else: + po.ovarrf( self.outfile, - "(c22123)", - "Blanket stainless steel cost (M$)", - self.c22123, + "IFE driver system direct cap cost (M$)", + "", + cost_variables.cdcost + * cost_variables.fcdfuel + / (1.0e0 - cost_variables.fcdfuel), ) - po.ocosts( + po.ovarrf( self.outfile, - "(c22124)", - "Blanket vanadium cost (M$)", - self.c22124, + "Fraction of driver cost --> fuel cost", + "(fcdfuel)", + cost_variables.fcdfuel, ) + + po.oheadr(self.outfile, "Detailed Costings (1990 US$)") + po.ovarre( + self.outfile, + "Acc.22 multiplier for Nth of a kind", + "(fkind)", + cost_variables.fkind, + ) + po.ovarin( + self.outfile, "Level of Safety Assurance", "(lsa)", cost_variables.lsa + ) + po.oblnkl(self.outfile) + po.oshead(self.outfile, "Structures and Site Facilities") + po.ocosts( + self.outfile, + "(c211)", + "Site improvements, facilities, land (M$)", + self.c211, + ) + po.ocosts(self.outfile, "(c212)", "Reactor building cost (M$)", self.c212) + po.ocosts(self.outfile, "(c213)", "Turbine building cost (M$)", self.c213) + po.ocosts( + self.outfile, + "(c2141)", + "Reactor maintenance building cost (M$)", + self.c2141, + ) + po.ocosts(self.outfile, "(c2142)", "Warm shop cost (M$)", self.c2142) + po.ocosts(self.outfile, "(c215)", "Tritium building cost (M$)", self.c215) + po.ocosts( + self.outfile, + "(c216)", + "Electrical equipment building cost (M$)", + self.c216, + ) + po.ocosts( + self.outfile, + "(c2171)", + "Additional buildings cost (M$)", + self.c2171, + ) + po.ocosts( + self.outfile, + "(c2172)", + "Control room buildings cost (M$)", + self.c2172, + ) + po.ocosts( + self.outfile, + "(c2173)", + "Shop and warehouses cost (M$)", + self.c2173, + ) + po.ocosts( + self.outfile, + "(c2174)", + "Cryogenic building cost (M$)", + self.c2174, + ) + po.oblnkl(self.outfile) + po.ocosts(self.outfile, "(c21)", "Total account 21 cost (M$)", self.c21) + + po.oshead(self.outfile, "Reactor Systems") + po.ocosts(self.outfile, "(c2211)", "First wall cost (M$)", self.c2211) + if ife_variables.ife != 1: + if fwbs_variables.iblanket == 4: po.ocosts( self.outfile, - "(c22125)", - "Blanket carbon cloth cost (M$)", - self.c22125, + "(c22121)", + "Blanket lithium-lead cost (M$)", + self.c22121, ) po.ocosts( self.outfile, - "(c22126)", - "Blanket concrete cost (M$)", - self.c22126, + "(c22122)", + "Blanket lithium cost (M$)", + self.c22122, ) + else: po.ocosts( self.outfile, - "(c22127)", - "Blanket FLiBe cost (M$)", - self.c22127, + "(c22121)", + "Blanket beryllium cost (M$)", + self.c22121, ) po.ocosts( self.outfile, - "(c22128)", - "Blanket lithium cost (M$)", - self.c22128, + "(c22122)", + "Blanket breeder material cost (M$)", + self.c22122, ) - po.ocosts(self.outfile, "(c2212)", "Blanket total cost (M$)", self.c2212) - po.ocosts(self.outfile, "(c22131)", "Bulk shield cost (M$)", self.c22131) po.ocosts( self.outfile, - "(c22132)", - "Penetration shielding cost (M$)", - self.c22132, + "(c22123)", + "Blanket stainless steel cost (M$)", + self.c22123, ) - po.ocosts(self.outfile, "(c2213)", "Total shield cost (M$)", self.c2213) po.ocosts( self.outfile, - "(c2214)", - "Total support structure cost (M$)", - self.c2214, + "(c22124)", + "Blanket vanadium cost (M$)", + self.c22124, ) - po.ocosts(self.outfile, "(c2215)", "Divertor cost (M$)", self.c2215) - # TODO: Convert fortran format to Python - # if (cost_variables.ifueltyp == 1) : - # po.oblnkl(self.outfile) - # write(self.outfile,20) - # 20 format(t2, 'First wall, total blanket and divertor direct costs',/, t2,'are zero as they are assumed to be fuel costs.') - # elif (cost_variables.ifueltyp == 2) : - # po.oblnkl(self.outfile) - # write(self.outfile,31) - # 21 format(t2, 'Initial First wall, total blanket and divertor direct costs',/, t2,'are in capital and replacemnet are in cost of electricity') - - po.oblnkl(self.outfile) + else: # IFE po.ocosts( self.outfile, - "(c221)", - "Total account 221 cost (M$)", - cost_variables.c221, + "(c22121)", + "Blanket beryllium cost (M$)", + self.c22121, ) + po.ocosts( + self.outfile, + "(c22122)", + "Blanket lithium oxide cost (M$)", + self.c22122, + ) + po.ocosts( + self.outfile, + "(c22123)", + "Blanket stainless steel cost (M$)", + self.c22123, + ) + po.ocosts( + self.outfile, + "(c22124)", + "Blanket vanadium cost (M$)", + self.c22124, + ) + po.ocosts( + self.outfile, + "(c22125)", + "Blanket carbon cloth cost (M$)", + self.c22125, + ) + po.ocosts( + self.outfile, + "(c22126)", + "Blanket concrete cost (M$)", + self.c22126, + ) + po.ocosts( + self.outfile, + "(c22127)", + "Blanket FLiBe cost (M$)", + self.c22127, + ) + po.ocosts( + self.outfile, + "(c22128)", + "Blanket lithium cost (M$)", + self.c22128, + ) + + po.ocosts(self.outfile, "(c2212)", "Blanket total cost (M$)", self.c2212) + po.ocosts(self.outfile, "(c22131)", "Bulk shield cost (M$)", self.c22131) + po.ocosts( + self.outfile, + "(c22132)", + "Penetration shielding cost (M$)", + self.c22132, + ) + po.ocosts(self.outfile, "(c2213)", "Total shield cost (M$)", self.c2213) + po.ocosts( + self.outfile, + "(c2214)", + "Total support structure cost (M$)", + self.c2214, + ) + po.ocosts(self.outfile, "(c2215)", "Divertor cost (M$)", self.c2215) + # TODO: Convert fortran format to Python + # if (cost_variables.ifueltyp == 1) : + # po.oblnkl(self.outfile) + # write(self.outfile,20) + # 20 format(t2, 'First wall, total blanket and divertor direct costs',/, t2,'are zero as they are assumed to be fuel costs.') + # elif (cost_variables.ifueltyp == 2) : + # po.oblnkl(self.outfile) + # write(self.outfile,31) + # 21 format(t2, 'Initial First wall, total blanket and divertor direct costs',/, t2,'are in capital and replacemnet are in cost of electricity') + + po.oblnkl(self.outfile) + po.ocosts( + self.outfile, + "(c221)", + "Total account 221 cost (M$)", + cost_variables.c221, + ) - if ife_variables.ife != 1: - - po.oshead(self.outfile, "Magnets") - - if tfcoil_variables.i_tf_sup != 1: # Resistive TF coils - if physics_variables.itart == 1: - po.ocosts( - self.outfile, - "(c22211)", - "Centrepost costs (M$)", - self.c22211, - ) - else: - po.ocosts( - self.outfile, - "(c22211)", - "Inboard leg cost (M$)", - self.c22211, - ) + if ife_variables.ife != 1: + po.oshead(self.outfile, "Magnets") - po.ocosts( - self.outfile, - "(c22212)", - "Outboard leg cost (M$)", - self.c22212, - ) - po.ocosts( - self.outfile, - "(c2221)", - "TF magnet assemblies cost (M$)", - self.c2221, - ) - else: # Superconducting TF coils + if tfcoil_variables.i_tf_sup != 1: # Resistive TF coils + if physics_variables.itart == 1: po.ocosts( self.outfile, "(c22211)", - "TF coil conductor cost (M$)", + "Centrepost costs (M$)", self.c22211, ) + else: po.ocosts( self.outfile, - "(c22212)", - "TF coil winding cost (M$)", - self.c22212, - ) - po.ocosts( - self.outfile, - "(c22213)", - "TF coil case cost (M$)", - self.c22213, - ) - po.ocosts( - self.outfile, - "(c22214)", - "TF intercoil structure cost (M$)", - self.c22214, - ) - po.ocosts( - self.outfile, - "(c22215)", - "TF coil gravity support structure (M$)", - self.c22215, - ) - po.ocosts( - self.outfile, - "(c2221)", - "TF magnet assemblies cost (M$)", - self.c2221, + "(c22211)", + "Inboard leg cost (M$)", + self.c22211, ) po.ocosts( self.outfile, - "(c22221)", - "PF coil conductor cost (M$)", - self.c22221, - ) - po.ocosts( - self.outfile, - "(c22222)", - "PF coil winding cost (M$)", - self.c22222, + "(c22212)", + "Outboard leg cost (M$)", + self.c22212, ) po.ocosts( self.outfile, - "(c22223)", - "PF coil case cost (M$)", - self.c22223, + "(c2221)", + "TF magnet assemblies cost (M$)", + self.c2221, ) + else: # Superconducting TF coils po.ocosts( self.outfile, - "(c22224)", - "PF coil support structure cost (M$)", - self.c22224, + "(c22211)", + "TF coil conductor cost (M$)", + self.c22211, ) po.ocosts( self.outfile, - "(c2222)", - "PF magnet assemblies cost (M$)", - self.c2222, + "(c22212)", + "TF coil winding cost (M$)", + self.c22212, ) po.ocosts( self.outfile, - "(c2223)", - "Vacuum vessel assembly cost (M$)", - self.c2223, + "(c22213)", + "TF coil case cost (M$)", + self.c22213, ) - # TODO: Convert fortran format to Python - # if ((physics_variables.itart == 1)and(cost_variables.ifueltyp == 1)) : - # po.oblnkl(self.outfile) - # write(self.outfile,30) - # 30 format(t2, 'Centrepost direct cost is zero, as it ', 'is assumed to be a fuel cost.') - # elif ((physics_variables.itart == 1)and(cost_variables.ifueltyp == 2)) : - # po.oblnkl(self.outfile) - # write(self.outfile,31) - # 31 format(t2, 'Initial centrepost direct cost in included in capital ', 'cost and replacements are assumed to be a fuel cost.') - - po.oblnkl(self.outfile) po.ocosts( self.outfile, - "(c222)", - "Total account 222 cost (M$)", - cost_variables.c222, + "(c22214)", + "TF intercoil structure cost (M$)", + self.c22214, ) - - po.oshead(self.outfile, "Power Injection") - - if ife_variables.ife == 1: po.ocosts( self.outfile, - "(c2231)", - "IFE driver system cost (M$)", - self.c2231, + "(c22215)", + "TF coil gravity support structure (M$)", + self.c22215, ) - else: - po.ocosts(self.outfile, "(c2231)", "ECH system cost (M$)", self.c2231) po.ocosts( self.outfile, - "(c2232)", - "Lower hybrid system cost (M$)", - self.c2232, + "(c2221)", + "TF magnet assemblies cost (M$)", + self.c2221, ) - po.ocosts( - self.outfile, - "(c2233)", - "Neutral beam system cost (M$)", - self.c2233, - ) - - po.oblnkl(self.outfile) - po.ocosts(self.outfile, "(c223)", "Total account 223 cost (M$)", self.c223) - po.oshead(self.outfile, "Vacuum Systems") po.ocosts( self.outfile, - "(c2241)", - "High vacuum pumps cost (M$)", - self.c2241, - ) - po.ocosts(self.outfile, "(c2242)", "Backing pumps cost (M$)", self.c2242) - po.ocosts(self.outfile, "(c2243)", "Vacuum duct cost (M$)", self.c2243) - po.ocosts(self.outfile, "(c2244)", "Valves cost (M$)", self.c2244) - po.ocosts(self.outfile, "(c2245)", "Duct shielding cost (M$)", self.c2245) - po.ocosts(self.outfile, "(c2246)", "Instrumentation cost (M$)", self.c2246) - po.oblnkl(self.outfile) - po.ocosts(self.outfile, "(c224)", "Total account 224 cost (M$)", self.c224) - - if ife_variables.ife != 1: - po.oshead(self.outfile, "Power Conditioning") - po.ocosts( - self.outfile, - "(c22511)", - "TF coil power supplies cost (M$)", - self.c22511, - ) - po.ocosts( - self.outfile, - "(c22512)", - "TF coil breakers cost (M$)", - self.c22512, - ) - po.ocosts( - self.outfile, - "(c22513)", - "TF coil dump resistors cost (M$)", - self.c22513, - ) - po.ocosts( - self.outfile, - "(c22514)", - "TF coil instrumentation and control (M$)", - self.c22514, - ) - po.ocosts( - self.outfile, - "(c22515)", - "TF coil bussing cost (M$)", - self.c22515, - ) - po.ocosts( - self.outfile, - "(c2251)", - "Total, TF coil power costs (M$)", - self.c2251, - ) - po.ocosts( - self.outfile, - "(c22521)", - "PF coil power supplies cost (M$)", - self.c22521, - ) - po.ocosts( - self.outfile, - "(c22522)", - "PF coil instrumentation and control (M$)", - self.c22522, - ) - po.ocosts( - self.outfile, - "(c22523)", - "PF coil bussing cost (M$)", - self.c22523, - ) - po.ocosts( - self.outfile, - "(c22524)", - "PF coil burn power supplies cost (M$)", - self.c22524, - ) - po.ocosts( - self.outfile, - "(c22525)", - "PF coil breakers cost (M$)", - self.c22525, - ) - po.ocosts( - self.outfile, - "(c22526)", - "PF coil dump resistors cost (M$)", - self.c22526, - ) - po.ocosts( - self.outfile, - "(c22527)", - "PF coil ac breakers cost (M$)", - self.c22527, - ) - po.ocosts( - self.outfile, - "(c2252)", - "Total, PF coil power costs (M$)", - self.c2252, - ) - po.ocosts( - self.outfile, - "(c2253)", - "Total, energy storage cost (M$)", - self.c2253, - ) - po.oblnkl(self.outfile) - po.ocosts( - self.outfile, - "(c225)", - "Total account 225 cost (M$)", - self.c225, - ) - - po.oshead(self.outfile, "Heat Transport System") + "(c22221)", + "PF coil conductor cost (M$)", + self.c22221, + ) po.ocosts( self.outfile, - "(cpp)", - "Pumps and piping system cost (M$)", - self.cpp, + "(c22222)", + "PF coil winding cost (M$)", + self.c22222, ) po.ocosts( self.outfile, - "(chx)", - "Primary heat exchanger cost (M$)", - self.chx, + "(c22223)", + "PF coil case cost (M$)", + self.c22223, ) po.ocosts( self.outfile, - "(c2261)", - "Total, reactor cooling system cost (M$)", - self.c2261, + "(c22224)", + "PF coil support structure cost (M$)", + self.c22224, ) - po.ocosts(self.outfile, "(cppa)", "Pumps, piping cost (M$)", self.cppa) po.ocosts( self.outfile, - "(c2262)", - "Total, auxiliary cooling system cost (M$)", - self.c2262, + "(c2222)", + "PF magnet assemblies cost (M$)", + self.c2222, ) po.ocosts( self.outfile, - "(c2263)", - "Total, cryogenic system cost (M$)", - self.c2263, + "(c2223)", + "Vacuum vessel assembly cost (M$)", + self.c2223, ) + # TODO: Convert fortran format to Python + # if ((physics_variables.itart == 1)and(cost_variables.ifueltyp == 1)) : + # po.oblnkl(self.outfile) + # write(self.outfile,30) + # 30 format(t2, 'Centrepost direct cost is zero, as it ', 'is assumed to be a fuel cost.') + # elif ((physics_variables.itart == 1)and(cost_variables.ifueltyp == 2)) : + # po.oblnkl(self.outfile) + # write(self.outfile,31) + # 31 format(t2, 'Initial centrepost direct cost in included in capital ', 'cost and replacements are assumed to be a fuel cost.') + po.oblnkl(self.outfile) - po.ocosts(self.outfile, "(c226)", "Total account 226 cost (M$)", self.c226) + po.ocosts( + self.outfile, + "(c222)", + "Total account 222 cost (M$)", + cost_variables.c222, + ) + + po.oshead(self.outfile, "Power Injection") - po.oshead(self.outfile, "Fuel Handling System") - po.ocosts(self.outfile, "(c2271)", "Fuelling system cost (M$)", self.c2271) + if ife_variables.ife == 1: po.ocosts( self.outfile, - "(c2272)", - "Fuel processing and purification cost (M$)", - self.c2272, + "(c2231)", + "IFE driver system cost (M$)", + self.c2231, ) + else: + po.ocosts(self.outfile, "(c2231)", "ECH system cost (M$)", self.c2231) po.ocosts( self.outfile, - "(c2273)", - "Atmospheric recovery systems cost (M$)", - self.c2273, + "(c2232)", + "Lower hybrid system cost (M$)", + self.c2232, ) po.ocosts( self.outfile, - "(c2274)", - "Nuclear building ventilation cost (M$)", - self.c2274, + "(c2233)", + "Neutral beam system cost (M$)", + self.c2233, ) - po.oblnkl(self.outfile) - po.ocosts(self.outfile, "(c227)", "Total account 227 cost (M$)", self.c227) - po.oshead(self.outfile, "Instrumentation and Control") + po.oblnkl(self.outfile) + po.ocosts(self.outfile, "(c223)", "Total account 223 cost (M$)", self.c223) + + po.oshead(self.outfile, "Vacuum Systems") + po.ocosts( + self.outfile, + "(c2241)", + "High vacuum pumps cost (M$)", + self.c2241, + ) + po.ocosts(self.outfile, "(c2242)", "Backing pumps cost (M$)", self.c2242) + po.ocosts(self.outfile, "(c2243)", "Vacuum duct cost (M$)", self.c2243) + po.ocosts(self.outfile, "(c2244)", "Valves cost (M$)", self.c2244) + po.ocosts(self.outfile, "(c2245)", "Duct shielding cost (M$)", self.c2245) + po.ocosts(self.outfile, "(c2246)", "Instrumentation cost (M$)", self.c2246) + po.oblnkl(self.outfile) + po.ocosts(self.outfile, "(c224)", "Total account 224 cost (M$)", self.c224) + + if ife_variables.ife != 1: + po.oshead(self.outfile, "Power Conditioning") po.ocosts( self.outfile, - "(c228)", - "Instrumentation and control cost (M$)", - self.c228, + "(c22511)", + "TF coil power supplies cost (M$)", + self.c22511, ) - - po.oshead(self.outfile, "Maintenance Equipment") po.ocosts( self.outfile, - "(c229)", - "Maintenance equipment cost (M$)", - self.c229, + "(c22512)", + "TF coil breakers cost (M$)", + self.c22512, ) - - po.oshead(self.outfile, "Total Account 22 Cost") - po.ocosts(self.outfile, "(c22)", "Total account 22 cost (M$)", self.c22) - - po.oshead(self.outfile, "Turbine Plant Equipment") po.ocosts( self.outfile, - "(c23)", - "Turbine plant equipment cost (M$)", - self.c23, + "(c22513)", + "TF coil dump resistors cost (M$)", + self.c22513, ) - - po.oshead(self.outfile, "Electric Plant Equipment") po.ocosts( self.outfile, - "(c241)", - "Switchyard equipment cost (M$)", - self.c241, + "(c22514)", + "TF coil instrumentation and control (M$)", + self.c22514, ) - po.ocosts(self.outfile, "(c242)", "Transformers cost (M$)", self.c242) po.ocosts( self.outfile, - "(c243)", - "Low voltage equipment cost (M$)", - self.c243, + "(c22515)", + "TF coil bussing cost (M$)", + self.c22515, ) po.ocosts( self.outfile, - "(c244)", - "Diesel backup equipment cost (M$)", - self.c244, + "(c2251)", + "Total, TF coil power costs (M$)", + self.c2251, ) po.ocosts( self.outfile, - "(c245)", - "Auxiliary facilities cost (M$)", - self.c245, + "(c22521)", + "PF coil power supplies cost (M$)", + self.c22521, ) - po.oblnkl(self.outfile) - po.ocosts(self.outfile, "(c24)", "Total account 24 cost (M$)", self.c24) - - po.oshead(self.outfile, "Miscellaneous Plant Equipment") po.ocosts( self.outfile, - "(c25)", - "Miscellaneous plant equipment cost (M$)", - self.c25, + "(c22522)", + "PF coil instrumentation and control (M$)", + self.c22522, ) - - po.oshead(self.outfile, "Heat Rejection System") po.ocosts( self.outfile, - "(c26)", - "Heat rejection system cost (M$)", - self.c26, + "(c22523)", + "PF coil bussing cost (M$)", + self.c22523, ) - - po.oshead(self.outfile, "Plant Direct Cost") po.ocosts( - self.outfile, "(cdirt)", "Plant direct cost (M$)", cost_variables.cdirt + self.outfile, + "(c22524)", + "PF coil burn power supplies cost (M$)", + self.c22524, + ) + po.ocosts( + self.outfile, + "(c22525)", + "PF coil breakers cost (M$)", + self.c22525, + ) + po.ocosts( + self.outfile, + "(c22526)", + "PF coil dump resistors cost (M$)", + self.c22526, + ) + po.ocosts( + self.outfile, + "(c22527)", + "PF coil ac breakers cost (M$)", + self.c22527, + ) + po.ocosts( + self.outfile, + "(c2252)", + "Total, PF coil power costs (M$)", + self.c2252, ) - - po.oshead(self.outfile, "Reactor Core Cost") po.ocosts( self.outfile, - "(crctcore)", - "Reactor core cost (M$)", - cost_variables.crctcore, + "(c2253)", + "Total, energy storage cost (M$)", + self.c2253, ) + po.oblnkl(self.outfile) + po.ocosts( + self.outfile, + "(c225)", + "Total account 225 cost (M$)", + self.c225, + ) + + po.oshead(self.outfile, "Heat Transport System") + po.ocosts( + self.outfile, + "(cpp)", + "Pumps and piping system cost (M$)", + self.cpp, + ) + po.ocosts( + self.outfile, + "(chx)", + "Primary heat exchanger cost (M$)", + self.chx, + ) + po.ocosts( + self.outfile, + "(c2261)", + "Total, reactor cooling system cost (M$)", + self.c2261, + ) + po.ocosts(self.outfile, "(cppa)", "Pumps, piping cost (M$)", self.cppa) + po.ocosts( + self.outfile, + "(c2262)", + "Total, auxiliary cooling system cost (M$)", + self.c2262, + ) + po.ocosts( + self.outfile, + "(c2263)", + "Total, cryogenic system cost (M$)", + self.c2263, + ) + po.oblnkl(self.outfile) + po.ocosts(self.outfile, "(c226)", "Total account 226 cost (M$)", self.c226) + + po.oshead(self.outfile, "Fuel Handling System") + po.ocosts(self.outfile, "(c2271)", "Fuelling system cost (M$)", self.c2271) + po.ocosts( + self.outfile, + "(c2272)", + "Fuel processing and purification cost (M$)", + self.c2272, + ) + po.ocosts( + self.outfile, + "(c2273)", + "Atmospheric recovery systems cost (M$)", + self.c2273, + ) + po.ocosts( + self.outfile, + "(c2274)", + "Nuclear building ventilation cost (M$)", + self.c2274, + ) + po.oblnkl(self.outfile) + po.ocosts(self.outfile, "(c227)", "Total account 227 cost (M$)", self.c227) + + po.oshead(self.outfile, "Instrumentation and Control") + po.ocosts( + self.outfile, + "(c228)", + "Instrumentation and control cost (M$)", + self.c228, + ) - po.oshead(self.outfile, "Indirect Cost") - po.ocosts(self.outfile, "(c9)", "Indirect cost (M$)", self.cindrt) + po.oshead(self.outfile, "Maintenance Equipment") + po.ocosts( + self.outfile, + "(c229)", + "Maintenance equipment cost (M$)", + self.c229, + ) + + po.oshead(self.outfile, "Total Account 22 Cost") + po.ocosts(self.outfile, "(c22)", "Total account 22 cost (M$)", self.c22) + + po.oshead(self.outfile, "Turbine Plant Equipment") + po.ocosts( + self.outfile, + "(c23)", + "Turbine plant equipment cost (M$)", + self.c23, + ) - po.oshead(self.outfile, "Total Contingency") - po.ocosts(self.outfile, "(ccont)", "Total contingency (M$)", self.ccont) + po.oshead(self.outfile, "Electric Plant Equipment") + po.ocosts( + self.outfile, + "(c241)", + "Switchyard equipment cost (M$)", + self.c241, + ) + po.ocosts(self.outfile, "(c242)", "Transformers cost (M$)", self.c242) + po.ocosts( + self.outfile, + "(c243)", + "Low voltage equipment cost (M$)", + self.c243, + ) + po.ocosts( + self.outfile, + "(c244)", + "Diesel backup equipment cost (M$)", + self.c244, + ) + po.ocosts( + self.outfile, + "(c245)", + "Auxiliary facilities cost (M$)", + self.c245, + ) + po.oblnkl(self.outfile) + po.ocosts(self.outfile, "(c24)", "Total account 24 cost (M$)", self.c24) + + po.oshead(self.outfile, "Miscellaneous Plant Equipment") + po.ocosts( + self.outfile, + "(c25)", + "Miscellaneous plant equipment cost (M$)", + self.c25, + ) + + po.oshead(self.outfile, "Heat Rejection System") + po.ocosts( + self.outfile, + "(c26)", + "Heat rejection system cost (M$)", + self.c26, + ) + + po.oshead(self.outfile, "Plant Direct Cost") + po.ocosts( + self.outfile, "(cdirt)", "Plant direct cost (M$)", cost_variables.cdirt + ) + + po.oshead(self.outfile, "Reactor Core Cost") + po.ocosts( + self.outfile, + "(crctcore)", + "Reactor core cost (M$)", + cost_variables.crctcore, + ) - po.oshead(self.outfile, "Constructed Cost") + po.oshead(self.outfile, "Indirect Cost") + po.ocosts(self.outfile, "(c9)", "Indirect cost (M$)", self.cindrt) + + po.oshead(self.outfile, "Total Contingency") + po.ocosts(self.outfile, "(ccont)", "Total contingency (M$)", self.ccont) + + po.oshead(self.outfile, "Constructed Cost") + po.ocosts( + self.outfile, + "(concost)", + "Constructed cost (M$)", + cost_variables.concost, + ) + + if cost_variables.ireactor == 1: + po.oshead(self.outfile, "Interest during Construction") po.ocosts( self.outfile, - "(concost)", - "Constructed cost (M$)", - cost_variables.concost, + "(moneyint)", + "Interest during construction (M$)", + cost_variables.moneyint, ) - if cost_variables.ireactor == 1: - po.oshead(self.outfile, "Interest during Construction") - po.ocosts( - self.outfile, - "(moneyint)", - "Interest during construction (M$)", - cost_variables.moneyint, - ) - - po.oshead(self.outfile, "Total Capital Investment") - po.ocosts( - self.outfile, - "(capcost)", - "Total capital investment (M$)", - cost_variables.capcost, - ) + po.oshead(self.outfile, "Total Capital Investment") + po.ocosts( + self.outfile, + "(capcost)", + "Total capital investment (M$)", + cost_variables.capcost, + ) def acc22(self): """ @@ -963,7 +982,6 @@ def acc225(self): if ife_variables.ife == 1: self.c225 = 0.0e0 else: - # Account 225.1 : TF coil power conditioning self.acc2251() @@ -1179,7 +1197,6 @@ def acc2212(self): cmlsa = [0.5000e0, 0.7500e0, 0.8750e0, 1.0000e0] if ife_variables.ife != 1: - # iblanket=4 is used for KIT HCLL model. iblanket<4 are all # HCPB (CCFE, KIT and CCFE + Shimwell TBR calculation). @@ -1208,7 +1225,6 @@ def acc2212(self): self.c22127 = 0.0e0 else: - # IFE blanket; materials present are Li2O, steel, carbon, concrete, # FLiBe and lithium @@ -1398,7 +1414,6 @@ def acc2221(self): cmlsa = [0.6900e0, 0.8450e0, 0.9225e0, 1.0000e0] if tfcoil_variables.i_tf_sup != 1: # Resistive TF coils - # Account 222.1.1 : Inboard TF coil legs self.c22211 = ( @@ -1431,7 +1446,6 @@ def acc2221(self): self.c2221 = self.c22211 + self.c22212 else: # Superconducting TF coils - # Account 222.1.1 : Conductor # Superconductor ($/m) @@ -1563,7 +1577,6 @@ def acc2222(self): self.c22221 = 0.0e0 for i in range(0, npf): - # Superconductor ($/m) if pfcoil_variables.ipfres == 0: costpfsc = ( @@ -1620,7 +1633,6 @@ def acc2222(self): # Central Solenoid if build_variables.iohcl == 1: - # Superconductor ($/m) # Issue #328 Use CS conductor cross-sectional area (m2) if pfcoil_variables.ipfres == 0: @@ -1727,7 +1739,6 @@ def acc223(self): exprf = 1.0e0 if ife_variables.ife != 1: - # Account 223.1 : ECH self.c2231 = ( @@ -1775,7 +1786,6 @@ def acc223(self): self.c2233 = cost_variables.fkind * self.c2233 else: - # IFE driver costs (depends on driver type) # Assume offset linear form for generic and SOMBRERO types, # or one of two offset linear forms for OSIRIS type @@ -2477,9 +2487,7 @@ def acc2253(self): # See F/MPE/MOD/CAG/PROCESS/PULSE/0008 and 0014 if pulse_variables.lpulse == 1: - if pulse_variables.istore == 1: - # Option 1 from ELECTROWATT report # Pulsed Fusion Reactor Study : AEA FUS 205 @@ -2502,7 +2510,6 @@ def acc2253(self): self.c2253 = self.c2253 + 29.0e0 elif pulse_variables.istore == 2: - # Option 2 from ELECTROWATT report # Pulsed Fusion Reactor Study : AEA FUS 205 @@ -2532,7 +2539,6 @@ def acc2253(self): self.c2253 = self.c2253 + 18.0e0 elif pulse_variables.istore == 3: - # Simplistic approach that assumes that a large stainless steel # block acts as the thermal storage medium. No account is taken # of the cost of the piping within the block, etc. @@ -2555,7 +2561,6 @@ def acc2253(self): error_handling.report_error(125) if pulse_variables.istore < 3: - # Scale self.c2253 with net electric power self.c2253 = self.c2253 * heat_transport_variables.pnetelmw / 1200.0e0 @@ -2568,12 +2573,12 @@ def acc2253(self): self.c2253 = cost_variables.fkind * self.c2253 - def coelc(self, iprint): + def coelc(self): """ Routine to calculate the cost of electricity for a fusion power plant author: P J Knight, CCFE, Culham Science Centre outfile : input integer : output file unit - iprint : input integer : switch for writing to output file (1=yes) + This routine performs the calculation of the cost of electricity for a fusion power plant.

Annual costs are in megadollars/year, electricity costs are in @@ -2663,7 +2668,6 @@ def coelc(self, iprint): anndiv = 0.0e0 coediv = 0.0e0 else: - # Compound interest factor fefdiv = (1.0e0 + cost_variables.discount_rate) ** cost_variables.divlife @@ -2694,7 +2698,6 @@ def coelc(self, iprint): # =============================== if (physics_variables.itart == 1) and (ife_variables.ife != 1): - # Compound interest factor fefcp = (1.0e0 + cost_variables.discount_rate) ** cost_variables.cplife @@ -2880,104 +2883,3 @@ def coelc(self, iprint): + cost_variables.coeoam + coedecom ) - - if (iprint == 0) or (cost_variables.output_costs == 0): - return - - # Output section - - po.oheadr(self.outfile, "Power Reactor Costs (1990 US$)") - - po.ovarrf( - self.outfile, "First wall / blanket life (years)", "(fwbllife)", fwbllife - ) - - if ife_variables.ife != 1: - po.ovarrf( - self.outfile, - "Divertor life (years)", - "(divlife.)", - cost_variables.divlife, - ) - if physics_variables.itart == 1: - po.ovarrf( - self.outfile, - "Centrepost life (years)", - "(cplife.)", - cost_variables.cplife, - ) - - po.ovarrf( - self.outfile, "Cost of electricity (m$/kWh)", "(coe)", cost_variables.coe - ) - - po.osubhd(self.outfile, "Power Generation Costs :") - # TODO: Convert fortran format to Python - # if ((annfwbl != annfwbl) or (annfwbl > 1.0e10) or (annfwbl < 0.0e0)) : - # write(outfile,*)'Problem with annfwbl' - # write(outfile,*)'fwallcst=', fwallcst, ' blkcst=', cost_variables.blkcst - # write(outfile,*)'crffwbl=', crffwbl, ' fcap0cp=', cost_variables.fcap0cp - # write(outfile,*)'feffwbl=', feffwbl, ' fwbllife=', fwbllife - - # write(outfile,200) # anncap,coecap, # annoam,coeoam, # anndecom,coedecom, # annfwbl,coefwbl, # anndiv,coediv, # anncp,coecp, # anncdr,coecdr, # annfuel,coefuel, # annwst,coewst, # annfuelt,coefuelt, # anntot,coe - - # 200 format( # t76,'Annual Costs, M$ COE, m$/kWh'// # 1x,'Capital Investment',t80,f10.2,10x,f10.2/ # 1x,'Operation & Maintenance',t80,f10.2,10x,f10.2/ # 1x,'Decommissioning Fund',t80,f10.2,10x,f10.2/ # 1x,'Fuel Charge Breakdown'// # 5x,'Blanket & first wall',t72,f10.2,10x,f10.2/ # 5x,'Divertors',t72,f10.2,10x,f10.2/ # 5x,'Centrepost (TART only)',t72,f10.2,10x,f10.2/ # 5x,'Auxiliary Heating',t72,f10.2,10x,f10.2/ # 5x,'Actual Fuel',t72,f10.2,10x,f10.2/ # 5x,'Waste Disposal',t72,f10.2,10x,f10.2/ # 1x,'Total Fuel Cost',t80,f10.2,10x,f10.2// # 1x,'Total Cost',t80,f10.2,10x,f10.2 ) - - if cost_variables.ifueltyp == 1: - po.oshead(self.outfile, "Replaceable Components Direct Capital Cost") - po.ovarrf( - self.outfile, - "First wall direct capital cost (M$)", - "(fwallcst)", - cost_variables.fwallcst, - ) - po.ovarrf( - self.outfile, - "Blanket direct capital cost (M$)", - "(blkcst)", - cost_variables.blkcst, - ) - if ife_variables.ife != 1: - po.ovarrf( - self.outfile, - "Divertor direct capital cost (M$)", - "(divcst)", - cost_variables.divcst, - ) - if physics_variables.itart == 1: - po.ovarrf( - self.outfile, - "Centrepost direct capital cost (M$)", - "(cpstcst)", - cost_variables.cpstcst, - ) - - po.ovarrf( - self.outfile, - "Plasma heating/CD system cap cost (M$)", - "", - cost_variables.cdcost - * cost_variables.fcdfuel - / (1.0e0 - cost_variables.fcdfuel), - ) - po.ovarrf( - self.outfile, - "Fraction of CD cost --> fuel cost", - "(fcdfuel)", - cost_variables.fcdfuel, - ) - else: - po.ovarrf( - self.outfile, - "IFE driver system direct cap cost (M$)", - "", - cost_variables.cdcost - * cost_variables.fcdfuel - / (1.0e0 - cost_variables.fcdfuel), - ) - po.ovarrf( - self.outfile, - "Fraction of driver cost --> fuel cost", - "(fcdfuel)", - cost_variables.fcdfuel, - ) diff --git a/process/costs_2015.py b/process/costs_2015.py index 2a47dbc2d3..ce62516a4a 100644 --- a/process/costs_2015.py +++ b/process/costs_2015.py @@ -23,7 +23,6 @@ def __init__(self): self.outfile = constants.nout # Initialise module variables - self.ip = AnnotatedVariable(float, 0.0, docstring="", units="") self.ofile = AnnotatedVariable(float, 0.0, docstring="", units="") self.total_costs = AnnotatedVariable(float, 0.0, docstring="", units="") self.mean_electric_output = AnnotatedVariable( @@ -33,7 +32,6 @@ def __init__(self): float, 0.0, docstring="", units="" ) self.maintenance = AnnotatedVariable(float, 0.0, docstring="", units="") - self.ip = AnnotatedVariable(float, 0.0, docstring="", units="") self.ofile = AnnotatedVariable(float, 0.0, docstring="", units="") self.total_costs = AnnotatedVariable(float, 0.0, docstring="", units="") @@ -85,7 +83,7 @@ def __init__(self): units="", ) - def run(self, output: bool): + def run(self): """ Cost accounting for a fusion power plant author: J Morris, CCFE, Culham Science Centre @@ -94,7 +92,6 @@ def run(self, output: bool): This routine performs the cost accounting for a fusion power plant. PROCESS Costs Paper (M. Kovari, J. Morris) """ - self.ip = int(output) self.outfile = self.outfile # ############################################### @@ -196,14 +193,6 @@ def run(self, output: bool): return - # Output costs # - # ############### - - if (self.ip == 0) or (cost_variables.output_costs == 0): - return - - self.write_costs_to_output() - def calc_fwbs_costs(self): """ Function to calculate the cost of the first wall, blanket and shield @@ -232,7 +221,7 @@ def calc_fwbs_costs(self): tail_li6 = feed_li6 * 0.75e0 # Built-in test - if (self.ip == 1) and (global_variables.run_tests == 1): + if global_variables.run_tests == 1: product_li6 = 0.3 feed_to_product_mass_ratio = (product_li6 - tail_li6) / ( feed_li6 - tail_li6 @@ -383,7 +372,7 @@ def calc_fwbs_costs(self): for j in range(21, 26): self.s_cost[26] = self.s_cost[26] + self.s_cost[j] - def write_costs_to_output(self): + def output(self): """ Function to output the costs calculations author: J Morris, CCFE, Culham Science Centre diff --git a/process/ife.py b/process/ife.py index 31d9d1cea4..c442f81b71 100644 --- a/process/ife.py +++ b/process/ife.py @@ -45,7 +45,8 @@ def run(self, output: bool): # write to output file if output: # Costs - self.costs.costs(output=True) + self.costs.run() + self.costs.output() # Plant availability self.availability.avail(output=True) @@ -118,4 +119,4 @@ def run(self, output: bool): self.availability.avail(output=False) # Costs - self.costs.costs(output=False) + self.costs.run() diff --git a/process/main.py b/process/main.py index daeb38f89c..b282c26afe 100644 --- a/process/main.py +++ b/process/main.py @@ -41,6 +41,8 @@ Box file F/MI/PJK/PROCESS and F/PL/PJK/PROCESS (15/01/96 to 24/01/12) Box file T&M/PKNIGHT/PROCESS (from 24/01/12) """ + +from typing import Protocol from process import fortran from process.buildings import Buildings from process.costs import Costs @@ -92,7 +94,6 @@ from process.water_use import WaterUse from process.sctfcoil import Sctfcoil -from process.fortran import cost_variables os.environ["PYTHON_PROCESS_ROOT"] = os.path.join(os.path.dirname(__file__)) @@ -545,11 +546,18 @@ def validate_user_model(self): Ensures that the corresponding model variable in Models is defined and that any relevant switches are set correctly. """ + # try and get costs model + self.models.costs - if cost_variables.cost_model == 2 and self.models.costs_step is None: - raise NotImplementedError( - f"cost_model = {cost_variables.cost_model} and costs_step = {self.models.costs_step}. Please provide cost model or change switch value." - ) + +class CostsProtocol(Protocol): + """Protocol layout for costs models""" + + def run(self): + """Run the model""" + + def output(self): + """write model output""" class Models: @@ -564,7 +572,7 @@ def __init__(self): This also initialises module variables in the Fortran for that module. """ - self.costs_step = None + self._costs_custom = None self.cs_fatigue = CsFatigue() self.pfcoil = PFCoil(cs_fatigue=self.cs_fatigue) self.power = Power() @@ -579,7 +587,7 @@ def __init__(self): self.vacuum = Vacuum() self.water_use = WaterUse() self.pulse = Pulse() - self.costs = Costs() + self._costs_old = Costs() self.ife = IFE(availability=self.availability, costs=self.costs) self.plasma_profile = PlasmaProfile() self.fw = Fw() @@ -596,12 +604,29 @@ def __init__(self): hcpb=self.ccfe_hcpb, current_drive=self.current_drive, ) - self.costs_2015 = Costs2015() + self._costs_2015 = Costs2015() self.physics = Physics( plasma_profile=self.plasma_profile, current_drive=self.current_drive ) self.dcll = DCLL(blanket_library=self.blanket_library) + @property + def costs(self) -> CostsProtocol: + if fortran.cost_variables.cost_model == 0: + return self._costs_old + if fortran.cost_variables.cost_model == 1: + return self._costs_2015 + if fortran.cost_variables.cost_model == 2: + if self._costs_custom is not None: + return self._costs_custom + raise ValueError("Custom costs model not initialised") + # Probably overkill but makes typing happy + raise ValueError("Unknown costs model") + + @costs.setter + def costs(self, value: CostsProtocol): + self._costs_custom = value + def main(args=None): """Run Process. diff --git a/process/output.py b/process/output.py index 46cdbabd2b..8214e7cc17 100644 --- a/process/output.py +++ b/process/output.py @@ -33,14 +33,8 @@ def write(models, outfile): # ---- | ------ # 0 | 1990 costs model # 1 | 2015 Kovari model - # 2 | 2019 STEP model - - if ft.cost_variables.cost_model == 0: - models.costs.run(output=True) - elif ft.cost_variables.cost_model == 1: - models.costs_2015.run(output=True) - elif ft.cost_variables.cost_model == 2: - models.costs_step.output() + # 2 | Custom model + models.costs.output() # Availability model models.availability.run(output=True) diff --git a/process/stellarator.py b/process/stellarator.py index 2cbfa5ade9..263bcf5dfe 100644 --- a/process/stellarator.py +++ b/process/stellarator.py @@ -107,7 +107,8 @@ def run(self, output: bool): """ if output: - self.costs.costs(output=True) + self.costs.run() + self.costs.output() self.availability.run(output=True) ph.outplas(self.outfile) self.stigma() @@ -154,7 +155,7 @@ def run(self, output: bool): # TODO: should availability.run be called # rather than availability.avail? self.availability.avail(output=False) - self.costs.costs(output=False) + self.costs.run() if any(numerics.icc == 91): # This call is comparably time consuming.. From 1131b8f40632ab70cdca5339f14373da8c4525fe Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:57:31 +0000 Subject: [PATCH 2/5] fix tests --- process/main.py | 4 ++-- tests/unit/test_costs_1990.py | 44 ++--------------------------------- tests/unit/test_costs_2015.py | 21 +---------------- 3 files changed, 5 insertions(+), 64 deletions(-) diff --git a/process/main.py b/process/main.py index b282c26afe..f1f532fd25 100644 --- a/process/main.py +++ b/process/main.py @@ -573,6 +573,8 @@ def __init__(self): This also initialises module variables in the Fortran for that module. """ self._costs_custom = None + self._costs_old = Costs() + self._costs_2015 = Costs2015() self.cs_fatigue = CsFatigue() self.pfcoil = PFCoil(cs_fatigue=self.cs_fatigue) self.power = Power() @@ -587,7 +589,6 @@ def __init__(self): self.vacuum = Vacuum() self.water_use = WaterUse() self.pulse = Pulse() - self._costs_old = Costs() self.ife = IFE(availability=self.availability, costs=self.costs) self.plasma_profile = PlasmaProfile() self.fw = Fw() @@ -604,7 +605,6 @@ def __init__(self): hcpb=self.ccfe_hcpb, current_drive=self.current_drive, ) - self._costs_2015 = Costs2015() self.physics = Physics( plasma_profile=self.plasma_profile, current_drive=self.current_drive ) diff --git a/tests/unit/test_costs_1990.py b/tests/unit/test_costs_1990.py index 30edc9f65a..f3a55ad0d7 100644 --- a/tests/unit/test_costs_1990.py +++ b/tests/unit/test_costs_1990.py @@ -1,4 +1,5 @@ """Unit tests for costs.f90.""" + from process.fortran import cost_variables from process.fortran import fwbs_variables as fv from process.fortran import heat_transport_variables as htv @@ -706,7 +707,6 @@ def test_acc9(monkeypatch, costs): class Acc21Param(NamedTuple): - shovol: Any = None triv: Any = None @@ -992,7 +992,6 @@ def test_acc21(acc21param, monkeypatch, costs): class Acc2211Param(NamedTuple): - fwarea: Any = None ucblss: Any = None @@ -1130,7 +1129,6 @@ def test_acc2211(acc2211param, monkeypatch, costs): class Acc2212Param(NamedTuple): - ucblss: Any = None ucblbreed: Any = None @@ -1418,7 +1416,6 @@ def test_acc2212(acc2212param, monkeypatch, costs): class Acc2213Param(NamedTuple): - ucpens: Any = None ucshld: Any = None @@ -1580,7 +1577,6 @@ def test_acc2213(acc2213param, monkeypatch, costs): class Acc2214Param(NamedTuple): - fkind: Any = None lsa: Any = None @@ -1644,7 +1640,6 @@ def test_acc2214(acc2214param, monkeypatch, costs): class Acc2215Param(NamedTuple): - ifueltyp: Any = None divcst: Any = None @@ -1726,7 +1721,6 @@ def test_acc2215(acc2215param, monkeypatch, costs): class Acc2221Param(NamedTuple): - uccpclb: Any = None uccase: Any = None @@ -1964,7 +1958,6 @@ def test_acc2221(acc2221param, monkeypatch, costs): class Acc2222Param(NamedTuple): - iohcl: Any = None uccase: Any = None @@ -2522,7 +2515,6 @@ def test_acc2222(acc2222param, monkeypatch, costs): class Acc2223Param(NamedTuple): - uccryo: Any = None lsa: Any = None @@ -2592,7 +2584,6 @@ def test_acc2223(acc2223param, monkeypatch, costs): class Acc223Param(NamedTuple): - ucich: Any = None fkind: Any = None @@ -2818,7 +2809,6 @@ def test_acc223(acc223param, monkeypatch, costs): class Acc224Param(NamedTuple): - fkind: Any = None dlscal: Any = None @@ -2972,7 +2962,6 @@ def test_acc224(acc224param, monkeypatch, costs): class Acc2251Param(NamedTuple): - uctfsw: Any = None fkind: Any = None @@ -3174,7 +3163,6 @@ def test_acc2251(acc2251param, monkeypatch, costs): class Acc2252Param(NamedTuple): - ucpfcb: Any = None ucpfbk: Any = None @@ -3376,7 +3364,6 @@ def test_acc2252(acc2252param, monkeypatch, costs): class Acc2253Param(NamedTuple): - ucblss: Any = None fkind: Any = None @@ -3476,7 +3463,6 @@ def test_acc2253(acc2253param, monkeypatch, costs): class Acc226Param(NamedTuple): - c226: Any = None c2261: Any = None @@ -3540,7 +3526,6 @@ def test_acc226(acc226param, monkeypatch, costs): class Acc2261Param(NamedTuple): - uchts: Any = None lsa: Any = None @@ -3676,7 +3661,6 @@ def test_acc2261_rut(acc2261param, monkeypatch, costs): class Acc2262Param(NamedTuple): - lsa: Any = None fkind: Any = None @@ -3806,7 +3790,6 @@ def test_acc2262_rut(acc2262param, monkeypatch, costs): class Acc2263Param(NamedTuple): - uccry: Any = None lsa: Any = None @@ -3888,7 +3871,6 @@ def test_acc2263_rut(acc2263param, monkeypatch, costs): class Acc227Param(NamedTuple): - c227: Any = None c2271: Any = None @@ -3958,7 +3940,6 @@ def test_acc227(acc227param, monkeypatch, costs): class Acc2271Param(NamedTuple): - ucf1: Any = None fkind: Any = None @@ -4022,7 +4003,6 @@ def test_acc2271_rut(acc2271param, monkeypatch, costs): class Acc2272Param(NamedTuple): - fkind: Any = None fburn: Any = None @@ -4134,7 +4114,6 @@ def test_acc2272_rut(acc2272param, monkeypatch, costs): class Acc2273Param(NamedTuple): - wsvol: Any = None volrci: Any = None @@ -4210,7 +4189,6 @@ def test_acc2273_rut(acc2273param, monkeypatch, costs): class Acc2274Param(NamedTuple): - wsvol: Any = None volrci: Any = None @@ -4280,7 +4258,6 @@ def test_acc2274_rut(acc2274param, monkeypatch, costs): class Acc228Param(NamedTuple): - uciac: Any = None fkind: Any = None @@ -4338,7 +4315,6 @@ def test_acc228_rut(acc228param, monkeypatch, costs): class Acc229Param(NamedTuple): - ucme: Any = None fkind: Any = None @@ -4396,7 +4372,6 @@ def test_acc229_rut(acc229param, monkeypatch, costs): class Acc23Param(NamedTuple): - ucturb: Any = None ireactor: Any = None @@ -4464,7 +4439,6 @@ def test_acc23_rut(acc23param, monkeypatch, costs): class Acc24Param(NamedTuple): - c24: Any = None c241: Any = None @@ -4534,7 +4508,6 @@ def test_acc24(acc24param, monkeypatch, costs): class Acc241Param(NamedTuple): - lsa: Any = None c24: Any = None @@ -4586,7 +4559,6 @@ def test_acc241_rut(acc241param, monkeypatch, costs): class Acc242Param(NamedTuple): - lsa: Any = None pacpmw: Any = None @@ -4656,7 +4628,6 @@ def test_acc242_rut(acc242param, monkeypatch, costs): class Acc243Param(NamedTuple): - lsa: Any = None tlvpmw: Any = None @@ -4714,7 +4685,6 @@ def test_acc243_rut(acc243param, monkeypatch, costs): class Acc244Param(NamedTuple): - lsa: Any = None c24: Any = None @@ -4766,7 +4736,6 @@ def test_acc244_rut(acc244param, monkeypatch, costs): class Acc245Param(NamedTuple): - lsa: Any = None c24: Any = None @@ -4818,7 +4787,6 @@ def test_acc245_rut(acc245param, monkeypatch, costs): class Acc25Param(NamedTuple): - ucmisc: Any = None lsa: Any = None @@ -4870,7 +4838,6 @@ def test_acc25_rut(acc25param, monkeypatch, costs): class Acc26Param(NamedTuple): - ireactor: Any = None uchrs: Any = None @@ -4958,7 +4925,6 @@ def test_acc26_rut(acc26param, monkeypatch, costs): class Acc9Param(NamedTuple): - fcontng: Any = None lsa: Any = None @@ -5062,7 +5028,6 @@ def test_acc9_rut(acc9param, monkeypatch, costs): class Acc2253Param(NamedTuple): - ucblss: Any = None fkind: Any = None @@ -5162,7 +5127,6 @@ def test_acc2253_urt(acc2253param, monkeypatch, costs, initialise_error_module): class CoelcParam(NamedTuple): - fcdfuel: Any = None uche3: Any = None @@ -5249,8 +5213,6 @@ class CoelcParam(NamedTuple): tburn: Any = None - iprint: Any = None - outfile: Any = None expected_coeoam: Any = None @@ -5341,7 +5303,6 @@ class CoelcParam(NamedTuple): fhe3=0, tcycle=10864.426139387357, tburn=0, - iprint=0, outfile=11, expected_coeoam=4.4099029328740929e20, expected_coecap=4.9891775218979061e21, @@ -5422,7 +5383,6 @@ class CoelcParam(NamedTuple): fhe3=0, tcycle=864.42613938735622, tburn=10230.533336387549, - iprint=0, outfile=11, expected_coeoam=1.2419424614419636, expected_coecap=15.547404530833255, @@ -5532,7 +5492,7 @@ def test_coelc(coelcparam, monkeypatch, costs): monkeypatch.setattr(times_variables, "tburn", coelcparam.tburn) - costs.coelc(iprint=coelcparam.iprint) + costs.coelc() assert cost_variables.coeoam == pytest.approx(coelcparam.expected_coeoam) diff --git a/tests/unit/test_costs_2015.py b/tests/unit/test_costs_2015.py index 0c4235e5d5..9934b94666 100644 --- a/tests/unit/test_costs_2015.py +++ b/tests/unit/test_costs_2015.py @@ -1,4 +1,5 @@ """Unit tests for costs_2015.f90.""" + import pytest import numpy from typing import NamedTuple, Any @@ -26,7 +27,6 @@ def costs2015(): class CalcBuildingCostsParam(NamedTuple): - pwpnb: Any = None pfrmax: Any = None @@ -2359,7 +2359,6 @@ def test_calc_building_costs(calcbuildingcostsparam, monkeypatch, costs2015): class CalcLandCostsParam(NamedTuple): - dr_tf_inner_bore: Any = None dh_tf_inner_bore: Any = None @@ -4631,7 +4630,6 @@ def test_calc_land_costs(calclandcostsparam, monkeypatch, costs2015): class CalcTfCoilCostsParam(NamedTuple): - n_tf: Any = None tfleng: Any = None @@ -6907,7 +6905,6 @@ def test_calc_tf_coil_costs(calctfcoilcostsparam, monkeypatch, costs2015): class CalcRemoteHandlingCostsParam(NamedTuple): - armour_fw_bl_mass: Any = None cost_factor_rh: Any = None @@ -6916,8 +6913,6 @@ class CalcRemoteHandlingCostsParam(NamedTuple): num_rh_systems: Any = None - ip: Any = None - s_kref: Any = None s_k: Any = None @@ -6947,7 +6942,6 @@ class CalcRemoteHandlingCostsParam(NamedTuple): cost_factor_rh=1, costexp=0.80000000000000004, num_rh_systems=4, - ip=0, s_kref=numpy.array( numpy.array( ( @@ -8034,7 +8028,6 @@ class CalcRemoteHandlingCostsParam(NamedTuple): cost_factor_rh=1, costexp=0.80000000000000004, num_rh_systems=4, - ip=0, s_kref=numpy.array( numpy.array( ( @@ -9149,8 +9142,6 @@ def test_calc_remote_handling_costs( cost_variables, "num_rh_systems", calcremotehandlingcostsparam.num_rh_systems ) - monkeypatch.setattr(costs2015, "ip", calcremotehandlingcostsparam.ip) - monkeypatch.setattr(costs2015, "s_kref", calcremotehandlingcostsparam.s_kref) monkeypatch.setattr(costs2015, "s_k", calcremotehandlingcostsparam.s_k) @@ -9185,7 +9176,6 @@ def test_calc_remote_handling_costs( class CalcNPlantAndVvCostsParam(NamedTuple): - rsldo: Any = None d_vv_out: Any = None @@ -11451,7 +11441,6 @@ def test_calc_n_plant_and_vv_costs(calcnplantandvvcostsparam, monkeypatch, costs class CalcEnergyConversionSystemParam(NamedTuple): - pgrossmw: Any = None cost_factor_bop: Any = None @@ -13719,7 +13708,6 @@ def test_calc_energy_conversion_system( class CalcRemainingSubsystemsParam(NamedTuple): - pinjmw: Any = None pdivt: Any = None @@ -13748,8 +13736,6 @@ class CalcRemainingSubsystemsParam(NamedTuple): costexp: Any = None - ip: Any = None - s_kref: Any = None s_k: Any = None @@ -13789,7 +13775,6 @@ class CalcRemainingSubsystemsParam(NamedTuple): zdewex=15.118436894660423, cost_factor_misc=1, costexp=0.80000000000000004, - ip=0, s_kref=numpy.array( numpy.array( ( @@ -14886,7 +14871,6 @@ class CalcRemainingSubsystemsParam(NamedTuple): zdewex=15.165858901796364, cost_factor_misc=1, costexp=0.80000000000000004, - ip=0, s_kref=numpy.array( numpy.array( ( @@ -16033,8 +16017,6 @@ def test_calc_remaining_subsystems( monkeypatch.setattr(cost_variables, "costexp", calcremainingsubsystemsparam.costexp) - monkeypatch.setattr(costs2015, "ip", calcremainingsubsystemsparam.ip) - monkeypatch.setattr(costs2015, "s_kref", calcremainingsubsystemsparam.s_kref) monkeypatch.setattr(costs2015, "s_k", calcremainingsubsystemsparam.s_k) @@ -16069,7 +16051,6 @@ def test_calc_remaining_subsystems( class ValueFunctionParam(NamedTuple): - x: Any = None expected_v: Any = None From 18c7bbc0fd0b324272ac84a92f0fc5549d581e8e Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Mon, 5 Feb 2024 08:28:35 +0000 Subject: [PATCH 3/5] rename and respect cost model is rerun before _every_ output command --- process/costs_2015.py | 2 +- process/main.py | 4 ++-- process/output.py | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/process/costs_2015.py b/process/costs_2015.py index ce62516a4a..ccb1a5d47a 100644 --- a/process/costs_2015.py +++ b/process/costs_2015.py @@ -173,7 +173,7 @@ def run(self): if (abs(cost_variables.concost) > 9.99e99) or ( cost_variables.concost != cost_variables.concost ): - self.write_costs_to_output() + self.output() for i in range(100): # noqa: E741 diff --git a/process/main.py b/process/main.py index f1f532fd25..506e5dfb03 100644 --- a/process/main.py +++ b/process/main.py @@ -573,7 +573,7 @@ def __init__(self): This also initialises module variables in the Fortran for that module. """ self._costs_custom = None - self._costs_old = Costs() + self._costs_1990 = Costs() self._costs_2015 = Costs2015() self.cs_fatigue = CsFatigue() self.pfcoil = PFCoil(cs_fatigue=self.cs_fatigue) @@ -613,7 +613,7 @@ def __init__(self): @property def costs(self) -> CostsProtocol: if fortran.cost_variables.cost_model == 0: - return self._costs_old + return self._costs_1990 if fortran.cost_variables.cost_model == 1: return self._costs_2015 if fortran.cost_variables.cost_model == 2: diff --git a/process/output.py b/process/output.py index 8214e7cc17..71f60f9d1a 100644 --- a/process/output.py +++ b/process/output.py @@ -34,6 +34,7 @@ def write(models, outfile): # 0 | 1990 costs model # 1 | 2015 Kovari model # 2 | Custom model + models.costs.run() models.costs.output() # Availability model From 90b809d209db4fe495cfd3b04674cb11c3867c0f Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Mon, 5 Feb 2024 08:30:17 +0000 Subject: [PATCH 4/5] WIP injection of model into run, unify SingleRun and VaryRun run --- process/main.py | 10 ++++------ tests/unit/test_main.py | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/process/main.py b/process/main.py index 506e5dfb03..51f50e841e 100644 --- a/process/main.py +++ b/process/main.py @@ -201,7 +201,7 @@ def run_mode(self): self.run = VaryRun(self.args.varyiterparamsconfig, self.args.solver) else: self.run = SingleRun(self.args.input, self.args.solver) - self.run.run() + self.run.run() def post_process(self): """Perform post-run actions, like plotting the mfile.""" @@ -253,13 +253,11 @@ def __init__(self, config_file, solver="vmcon"): # Store the absolute path to the config file immediately: various # dir changes happen in old run_process code self.config_file = Path(config_file).resolve() - self.run(solver) + self.solver = solver - def run(self, solver): + def run(self): """Perform a VaryRun by running multiple SingleRuns. - :param solver: which solver to use, as specified in solver.py - :type solver: str :raises FileNotFoundError: if input file doesn't exist """ # The input path for the varied input file @@ -301,7 +299,7 @@ def run(self, solver): # TODO Don't do this; remove stop statements from Fortran and # handle error codes # Run process on an IN.DAT file - config.run_process(input_path, solver) + config.run_process(input_path, self.solver) check_input_error(wdir=wdir) diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index c910d61eab..d584f4fc46 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -108,6 +108,7 @@ def test_run_mode(process_obj, monkeypatch): # Mock VaryRun() (don't want it to actually run), then assert run type is # VaryRun monkeypatch.setattr(VaryRun, "__init__", mock_init) + monkeypatch.setattr(VaryRun, "run", mock_run) process_obj.run_mode() assert isinstance(process_obj.run, VaryRun) From 3e52e95d03fb749c4f50e5849c45ab1522b11f86 Mon Sep 17 00:00:00 2001 From: Jack Foster Date: Tue, 6 Feb 2024 15:00:23 +0000 Subject: [PATCH 5/5] Tidied up references to STEP --- process/buildings.py | 4 +- source/fortran/buildings_variables.f90 | 28 +++--- source/fortran/physics_variables.f90 | 6 +- tests/integration/ref_dicts.json | 92 +++--------------- utilities/costs_bar.py | 128 ------------------------- utilities/costs_pie.py | 102 -------------------- 6 files changed, 34 insertions(+), 326 deletions(-) diff --git a/process/buildings.py b/process/buildings.py index 6427e87958..4ddaf6ec69 100644 --- a/process/buildings.py +++ b/process/buildings.py @@ -51,7 +51,7 @@ def run(self, output: bool = False): # Calculate building areas and volumes if buildings_variables.i_bldgs_size == 1: - # STEP building estimates + # Updated building estimates self.bldgs_sizes(output, tf_radial_dim, tf_vertical_dim) else: @@ -831,7 +831,7 @@ def bldgs_sizes(self, output, tf_radial_dim, tf_vertical_dim): # As proposed by R. Gowland, based on assessment of 18 existing fission power plants: # turbine hall size is largely independent of plant output power. # The default footprint used here represents a weighted mean of those plants - # and the design of a Steam Rankine cycle turbine building suitable for STEP, + # and the design of a Steam Rankine cycle turbine building, # produced by Morsons as part of the Year 1 work. turbine_hall_area = ( buildings_variables.turbine_hall_l * buildings_variables.turbine_hall_w diff --git a/source/fortran/buildings_variables.f90 b/source/fortran/buildings_variables.f90 index ff0ac959f2..82b8c3084d 100644 --- a/source/fortran/buildings_variables.f90 +++ b/source/fortran/buildings_variables.f90 @@ -123,7 +123,7 @@ module buildings_variables !! hazardous waste storage building length, width, height (m) integer :: i_bldgs_size - !! switch between routines estimating building sizes (0 = default; 1 = STEP-derived) + !! switch between routines estimating building sizes (0 = default; 1 = updated) integer :: i_bldgs_v !! switch to select verbose output for buildings (1 = verbose) @@ -272,43 +272,43 @@ module buildings_variables real(dp) :: a_reactor_bldg - !! Floor area of reactor building in m^2, used as GIFA in costs_step + !! Floor area of reactor building in m^2 real(dp) :: a_ee_ps_bldg - !! Floor area of electrical equipment and power supply building in m^2, used as GIFA in costs_step + !! Floor area of electrical equipment and power supply building in m^2 real(dp) :: a_aux_services_bldg - !! Floor area of auxiliary services building in m^2, used as GIFA in costs_step + !! Floor area of auxiliary services building in m^2 real(dp) :: a_hot_cell_bldg - !! Floor area of hot cell building in m^2, used as GIFA in costs_step + !! Floor area of hot cell building in m^2 real(dp) :: a_reactor_service_bldg - !! Floor area of reactor service building in m^2, used as GIFA in costs_step + !! Floor area of reactor service building in m^2 real(dp) :: a_service_water_bldg - !! Floor area of service water building in m^2, used as GIFA in costs_step + !! Floor area of service water building in m^2 real(dp) :: a_fuel_handling_bldg - !! Floor area of fuel handling and storage building in m^2, used as GIFA in costs_step + !! Floor area of fuel handling and storage building in m^2 real(dp) :: a_control_room_bldg - !! Floor area of controlroom building in m^2, used as GIFA in costs_step + !! Floor area of controlroom building in m^2 real(dp) :: a_ac_ps_bldg - !! Floor area of AC power supply building in m^2, used as GIFA in costs_step + !! Floor area of AC power supply building in m^2 real(dp) :: a_admin_bldg - !! Floor area of admin building in m^2, used as GIFA in costs_step + !! Floor area of admin building in m^2 real(dp) :: a_site_service_bldg - !! Floor area of site service building in m^2, used as GIFA in costs_step + !! Floor area of site service building in m^2 real(dp) :: a_cryo_inert_gas_bldg - !! Floor area of cryogenics and inert gas storage building in m^2, used as GIFA in costs_step + !! Floor area of cryogenics and inert gas storage building in m^2 real(dp) :: a_security_bldg - !! Floor area of security building in m^2, used as GIFA in costs_step + !! Floor area of security building in m^2 contains diff --git a/source/fortran/physics_variables.f90 b/source/fortran/physics_variables.f90 index b771407eaf..0cb54664fb 100644 --- a/source/fortran/physics_variables.f90 +++ b/source/fortran/physics_variables.f90 @@ -147,7 +147,7 @@ module physics_variables !! high Z ion density (/m3) real(dp) :: gradient_length_ne - !! Max. normalized gradient length in el. density (ipedestal==0 only) + !! Max. normalized gradient length in el. density (ipedestal==0 only) real(dp) :: gradient_length_te !! Max. normalized gradient length in el. temperature (ipedestal==0 only) @@ -386,7 +386,7 @@ module physics_variables integer :: iradloss !! switch for radiation loss term usage in power balance (see User Guide): !! - !! - =0 total power lost is scaling power plus radiation + !! - =0 total power lost is scaling power plus radiation !! - =1 total power lost is scaling power plus core radiation only !! - =2 total power lost is scaling power only, with no additional !! allowance for radiation. This is not recommended for power plant models. @@ -513,7 +513,7 @@ module physics_variables !! - =6 use input kappa, triang to calculate 95% values based on MAST scaling (ST) !! - =7 use input kappa95, triang95 to calculate separatrix values based on fit to FIESTA (ST) !! - =8 use input kappa, triang to calculate 95% values based on fit to FIESTA (ST) - !! - =9 set kappa to the natural elongation value (PROCESS-STEP issue #70), triang input + !! - =9 set kappa to the natural elongation value, triang input !! - =10 set kappa to maximum stable value at a given aspect ratio (2.6\n

  • =1 all power from MGF (motor-generator flywheel) units
  • \n
  • =2 all pulsed power from line
  • \n
  • =3 PF power from MGF, heating from line
  • \n", "iscrp": "switch for plasma-first wall clearances:\n", "iscz": "", - "ishape": "switch for plasma cross-sectional shape calculation:\n", + "ishape": "switch for plasma cross-sectional shape calculation:\n", "istell": "Switch for stellarator option (set via `device.dat`):\n", "isthtr": "Switch for stellarator auxiliary heating method:\n", "istore": "Switch for thermal storage method:\n", @@ -10679,19 +10666,6 @@ "startuppwr": "cost associated with additional HCD system power required on start-up ($)", "startupratio": "ratio of additional HCD power for start-up to flat-top operational requirements", "stcl": "clearance above crane to roof (m)", - "step20": "M$", - "step21": "M$", - "step22": "M$", - "step23": "M$", - "step24": "M$", - "step25": "M$", - "step27": "M$", - "step91": "M$", - "step91_per": "Percentage of cdirt used in calculating step91 (3.0D-1 = 30%)", - "step92": "M$", - "step92_per": "Percentage of cdirt used in calculating step92 (3.0D-1 = 30%)", - "step93": "M$", - "step93_per": "Percentage of cdirt used in calculating step93 (3.0D-1 = 30%)", "str_cs_con_res": "Residual manufacturing strain in CS superconductor material", "str_pf_con_res": "Residual manufacturing strain in PF superconductor material", "str_tf_con_res": "Residual manufacturing strain in TF superconductor material\n If `i_str_wp == 0`, used to compute the critical surface.\n Otherwise, the self-consistent winding pack `str_wp` is used.", @@ -14376,18 +14350,6 @@ "lb": 0.0, "ub": 10.0 }, - "step91_per": { - "lb": 1.0, - "ub": 100.0 - }, - "step92_per": { - "lb": 1.0, - "ub": 100.0 - }, - "step93_per": { - "lb": 1.0, - "ub": 100.0 - }, "str_cs_con_res": { "lb": -0.02, "ub": 0.02 @@ -17616,9 +17578,6 @@ "discount_rate", "startupratio", "startuppwr", - "step91_per", - "step92_per", - "step93_per", "tlife", "ucad", "ucaf", @@ -17819,24 +17778,6 @@ "cppa", "c22128" ], - "costs_step": [ - "pth", - "ptherm_star", - "rmajor_star", - "rminor_star", - "step20", - "step21", - "step22", - "step23", - "step24", - "step25", - "step27", - "step91", - "step92", - "step93", - "vfi", - "vfi_star" - ], "current_drive_module": [], "current_drive_variables": [ "beamwd", @@ -20794,9 +20735,6 @@ "staff_buildings_h": "real_variable", "startupratio": "real_variable", "stcl": "real_variable", - "step91_per": "real_variable", - "step92_per": "real_variable", - "step93_per": "real_variable", "str_cs_con_res": "real_variable", "str_pf_con_res": "real_variable", "str_tf_con_res": "real_variable", diff --git a/utilities/costs_bar.py b/utilities/costs_bar.py index ef13702ec0..edb17acacf 100644 --- a/utilities/costs_bar.py +++ b/utilities/costs_bar.py @@ -220,126 +220,6 @@ def comp_new(): plt.show() -def comp_step(): - """ - - Plot bar chart for the STEP cost model. - Two plots produced: (1) Breakdown of the direct costs and (2) Direct, indirect, etc. - - """ - # Setup figures - labels = [ - "Site and\n Buildings", - "Blanket and\n First Wall", - "Shield", - "Magnets", - "Other Reactor\n Equipment", - "Heat Transfer\n System", - "Other Reactor\n Plant Equipment", - "Turbine Plant\n Equipment", - "Electric Plant\n Equipment", - "Miscellaneous\n Plant Equipment", - ] - labels2 = [ - "Plant Direct\n Cost", - "Construction Facilities,\n Equipment and\n Services", - "Engineering and\n Costruction Management\n Services", - "Other Costs", - "Interest during\n Construction", - ] - index = np.arange(len(labels)) - index2 = np.arange(len(labels2)) - bar_width = 0.7 / len(mfile_list) - fig, ax = plt.subplots() - fig2, ax2 = plt.subplots() - - # Read cost data - for id, item in enumerate(mfile_list): - cost = np.zeros(19) - cost[0] = item.data["step20"].get_scan(-1) # Land and Rights - cost[1] = item.data["step21"].get_scan( - -1 - ) # Building and Site Service Infrastructure - cost[2] = item.data["step2201"].get_scan(-1) # Reactor Equipment - cost[3] = item.data["step220101"].get_scan(-1) # Blanket and First Wall - cost[4] = item.data["step220102"].get_scan(-1) # Shield - cost[5] = item.data["step22010301"].get_scan(-1) # TF Coils - cost[6] = item.data["step22010302"].get_scan(-1) # PF Coils - cost[7] = item.data["step22010303"].get_scan(-1) # Central Solenoid - cost[8] = item.data["step22010304"].get_scan(-1) # Control Coils - cost[9] = item.data["step2202"].get_scan(-1) # Heat Transfer System - cost[10] = item.data["step22"].get_scan(-1) # Reactor Plant Equipment - cost[11] = item.data["step23"].get_scan(-1) # Turbine Plant Equipment - cost[12] = item.data["step24"].get_scan(-1) # Electric Plant Equipment - cost[13] = item.data["step25"].get_scan(-1) # Miscellaneous Plant Equipment - cost[14] = item.data["cdirt"].get_scan(-1) # Plant Direct Cost - cost[15] = item.data["step91"].get_scan( - -1 - ) # Construction Facilities, Equipment and Services - cost[16] = item.data["step92"].get_scan( - -1 - ) # Engineering and Costruction Management Services - cost[17] = item.data["step93"].get_scan(-1) # Other Costs - cost[18] = item.data["moneyint"].get_scan(-1) # Interest during Construction - - # Explain why moneyint is missing - if "moneyint" not in item.data.keys(): - print( - "Interest during construction (moneyint) is only calculated for ireactor = 1" - ) - - # Inflate costs using value parsed if specified - if args.inf: - cost = inflate * cost - - # Simplify grouping - sizes = [ - cost[0] + cost[1], - cost[3], - cost[4], - cost[5] + cost[6] + cost[7] + cost[8], - cost[2] - cost[3] - cost[4] - cost[5] - cost[6] - cost[7] - cost[8], - cost[9], - cost[10] - cost[2] - cost[9], - cost[11], - cost[12], - cost[13], - ] - - # Direct, indirect costs etc. for second plot - sizes2 = [cost[14], cost[15], cost[16], cost[17], cost[18]] - - # Plot bar charts - ax.bar(index + id * bar_width, sizes, bar_width, label=args.f[id]) - ax2.bar(index2 + id * bar_width, sizes2, bar_width, label=args.f[id]) - - # Plot labels - ax.set_xticks(index + (len(mfile_list) - 1) * 0.5 * bar_width) - ax2.set_xticks(index2 + (len(mfile_list) - 1) * 0.5 * bar_width) - ax.set_xticklabels(labels, rotation=90) - ax2.set_xticklabels(labels2, rotation=90) - ax.legend() - ax2.legend() - - # Adjust axis label depending on if inflation factor is used - if args.inf: - ax.set_ylabel("%.2f x (1980 M$)" % inflate) - ax2.set_ylabel("%.2f x (1980 M$)" % inflate) - else: - ax.set_ylabel("1980 M$") - ax2.set_ylabel("1980 M$") - - fig.tight_layout() - fig2.tight_layout() - - # Save plots if option selected - if args.save: - fig.savefig("direct_cost_bar.pdf") - fig2.savefig("cost_bar.pdf") - - plt.show() - - # Main code if __name__ == "__main__": # Setup command line arguments @@ -385,13 +265,5 @@ def comp_step(): comp_new() - elif "step20" in mfile_list[0].data.keys(): - # Check all MFILEs use new cost model - for item in mfile_list: - if "step20" not in item.data.keys(): - sys.exit("ERROR: Inconsistent cost models used between MFILEs!") - - comp_step() - else: print("ERROR: Failed to identify cost data, check MFILE!") diff --git a/utilities/costs_pie.py b/utilities/costs_pie.py index 3984ccaa53..994b103d06 100644 --- a/utilities/costs_pie.py +++ b/utilities/costs_pie.py @@ -186,106 +186,6 @@ def new_cost_model(): plt.show() -def step_cost_model(): - """ - - Plot pie chart for the STEP cost model. - Two plots produced: (1) Breakdown of the direct costs and (2) Direct, indirect, etc. - - """ - # Read Cost Values - step20 = m_file.data["step20"].get_scan(-1) # Land and Rights - step21 = m_file.data["step21"].get_scan( - -1 - ) # Building and Site Service Infrastructure - step2201 = m_file.data["step2201"].get_scan(-1) # Reactor Equipment - step220101 = m_file.data["step220101"].get_scan(-1) # Blanket and First Wall - step220102 = m_file.data["step220102"].get_scan(-1) # Shield - step22010301 = m_file.data["step22010301"].get_scan(-1) # TF Coils - step22010302 = m_file.data["step22010302"].get_scan(-1) # PF Coils - step22010303 = m_file.data["step22010303"].get_scan(-1) # Central Solenoid - step22010304 = m_file.data["step22010304"].get_scan(-1) # Control Coils - step220103 = step22010301 + step22010302 + step22010303 + step22010304 # Magnets - step2202 = m_file.data["step2202"].get_scan(-1) # Heat Transfer System - step22 = m_file.data["step22"].get_scan(-1) # Reactor Plant Equipment - step23 = m_file.data["step23"].get_scan(-1) # Turbine Plant Equipment - step24 = m_file.data["step24"].get_scan(-1) # Electric Plant Equipment - step25 = m_file.data["step25"].get_scan(-1) # Miscellaneous Plant Equipment - - cdirt = m_file.data["cdirt"].get_scan(-1) # Plant Direct Cost - step91 = m_file.data["step91"].get_scan( - -1 - ) # Construction Facilities, Equipment and Services - step92 = m_file.data["step92"].get_scan( - -1 - ) # Engineering and Costruction Management Services - step93 = m_file.data["step93"].get_scan(-1) # Other Costs - - # Interest during construction is linked to ireactor = 1 - if "moneyint" in m_file.data.keys(): - moneyint = m_file.data["moneyint"].get_scan(-1) # Interest during Construction - labels2 = [ - "Plant Direct Cost", - "Construction Facilities,\n Equipment and\n Services", - "Engineering and\n Costruction Management\n Services", - "Other Costs", - "Interest during Construction", - ] - sizes2 = [cdirt, step91, step92, step93, moneyint] - else: - labels2 = [ - "Plant Direct Cost", - "Construction Facilities,\n Equipment and\n Services", - "Engineering and\n Costruction Management\n Services", - "Other Costs", - ] - sizes2 = [cdirt, step91, step92, step93] - - # Direct Cost Breakdown - labels = [ - "Site and Buildings", - "Blanket and First Wall", - "Shield", - "Magnets", - "Other Reactor Equipment", - "Heat Transfer System", - "Other Reactor Plant Equipment", - "Turbine Plant Equipment", - "Electric Plant Equipment", - "Miscellaneous Plant Equipment", - ] - - sizes = [ - step20 + step21, - step220101, - step220102, - step220103, - step2201 - step220101 - step220102 - step220103, - step2202, - step22 - step2201 - step2202, - step23, - step24, - step25, - ] - - # Setup figures - # Plot direct cost items - fig1, ax1 = plt.subplots(figsize=(9, 5)) - ax1.pie(sizes, labels=labels, autopct="%1.1f%%") - ax1.axis("equal") # Equal aspect ratio ensures that pie is drawn as a circle. - - # Plot overall breakdown - fig2, ax2 = plt.subplots(figsize=(8, 5)) - ax2.pie(sizes2, labels=labels2, autopct="%1.1f%%") - ax2.axis("equal") # Equal aspect ratio ensures that pie is drawn as a circle. - - # Save figures if option selected - if args.save: - fig1.savefig("direct_cost_pie.pdf") - fig2.savefig("cost_pie.pdf") - plt.show() - - # Main code if __name__ == "__main__": # Setup command line arguments @@ -313,7 +213,5 @@ def step_cost_model(): orig_cost_model() elif "s01" in m_file.data.keys(): new_cost_model() - elif "step20" in m_file.data.keys(): - step_cost_model() else: print("ERROR: Cannot identify cost data, check MFILE!")