Skip to content

Latest commit

 

History

History
557 lines (503 loc) · 17.6 KB

enrichment.md

File metadata and controls

557 lines (503 loc) · 17.6 KB
title description author layout date image
Enrichment SWU calculator
Interactive nuclear enrichment and SWU calculator where you can enter a given feed or product mass and a product enrichment and it will tell you how much feed and SWU you need. Also plots results interactively as you go.
nick
default
2022-10-27
/img/enrichment-ss.png

Use this to calculate how much natural uranium and separative work you need to get a given amount of enriched uranium at a certain enrichment, and so on. Learn more about [isotopes here]({% link isotopes.md %}).

Tails assay (wt %)
Feed assay (wt %)
Product Enrichment (wt %)
Choose Enrichment Preset Natural Uranium (0.711%) LEU (4%) HALEU (20%) Weapons-grade (90%)
LEU

Compute product mass from given feed mass
Compute feed mass from given product mass
Feed mass (kg or tonne)
Product mass (kg or tonne)
Tails mass (kg or tonne)
SWU (kg-SWU or tonne-SWU)

Copy current settings to clipboard


Economics inputs:

Cost of Feed U3O8 ($/kgU)
Cost of Conversion to UF6 ($/kgU)
Cost of SWU ($/kgSWU)
Fabrication cost ($/kgHM)
Average discharge burnup (MWd/kgHM)
Choose burnup preset CANDU (7 MWd/kg) Typical LWR (50 MWd/kg) Deep burn open cycle (200 MWd/kg) Multi-recycle breeder (800 MWd/kg)
Thermal efficiency (%)
Choose efficiency preset Thermionic (6%) Typical LWR (32%) Sodium-cooled reactor (39%) High-temperature gas-cooled reactor (43%)

Outputs

Reload total (¢/kWh)
Reload SWU (¢/kWh)
Reload feed (¢/kWh)
Conversion (¢/kWh)
Fabrication (¢/kWh)
Required mined material (gU/MWh)
High-level waste (gHM/MWh)

Abbrevs:

  • U - Uranium
  • HM - Heavy Metal (e.g. Uranium, Neptunium, Pu, Cm, etc.)
  • kWh - Kilowatt-hour electric
  • MWh - Megawatt-hour electric
  • MWd - Megawatt-day thermal
  • SWU - Separative Work Unit
<script src='https://cdn.plot.ly/plotly-2.16.1.min.js'></script> <script> let range=document.getElementById("enrich"); let number=document.getElementById('enrich-text') let select=document.getElementById('enrich-select') let tails_assay=document.getElementById('tails-assay') let feed_assay=document.getElementById('feed-assay') let feed_mass=document.getElementById('feed-mass') let product_mass=document.getElementById('product-mass') let tails_mass=document.getElementById('tails-mass') let swu=document.getElementById('swu-mass') let mode=document.getElementById('mode') let prod_const=document.getElementById('productConstant') let save=document.getElementById('save') let burange=document.getElementById("burnup"); let bunumber=document.getElementById('burnup-text') let buselect=document.getElementById('burnup-select') let effrange=document.getElementById("eff"); let effnumber=document.getElementById('eff-text') let effselect=document.getElementById('eff-select') let powerrange=document.getElementById("power"); let powernumber=document.getElementById('power-text') let powerselect=document.getElementById('power-select') let feedcost=document.getElementById('feed-cost') let swucost=document.getElementById('swu-cost') let fabcost=document.getElementById('fab-cost') let convcost=document.getElementById('conversion-cost') let reload_total_cost=document.getElementById('reload-total-cost') let reload_swu_cost=document.getElementById('reload-swu-cost') let reload_feed_cost=document.getElementById('reload-feed-cost') let reload_fab_cost=document.getElementById('reload-fab-cost') let reload_conv_cost=document.getElementById('reload-conv-cost') let reload_waste=document.getElementById('waste-per-kwh') let reload_feed_mass=document.getElementById('reload-feed-mass') tails_assay.addEventListener("input",(e)=>{ computeFeed(); }) feed_assay.addEventListener("input",(e)=>{ computeFeed(); }) product_mass.addEventListener("input",(e)=>{ computeFeed(); }) feed_mass.addEventListener("input",(e)=>{ computeFeed(); }) range.addEventListener("input",(e)=>{ let val = parseFloat(e.target.value); if (val{ range.value=e.target.value; select.value="" setRange(e.target.value); computeFeed(); }) select.addEventListener("change",(e)=>{ if (!e.target.value) { return; } number.value=e.target.value; range.value=e.target.value; setRange(e.target.value); computeFeed(); }) save.addEventListener("click", (e) => { copySettingsToClipboard(); }) // burnup burange.addEventListener("input",(e)=>{ let val = parseFloat(e.target.value); bunumber.value=val; buselect.value="" computeCost(); }) bunumber.addEventListener("input",(e)=>{ burange.value=e.target.value; buselect.value="" computeCost(); }) buselect.addEventListener("change",(e)=>{ if (!e.target.value) { return; } bunumber.value=e.target.value; burange.value=e.target.value; computeCost(); }) // efficiency effrange.addEventListener("input",(e)=>{ let val = parseFloat(e.target.value); effnumber.value=val; effselect.value="" computeCost(); }) effnumber.addEventListener("input",(e)=>{ effrange.value=e.target.value; effselect.value="" computeCost(); }) effselect.addEventListener("change",(e)=>{ if (!e.target.value) { return; } effnumber.value=e.target.value; effrange.value=e.target.value; computeCost(); }) /* // power powerrange.addEventListener("input",(e)=>{ let val = parseFloat(e.target.value); powernumber.value=val; powerselect.value="" }) powernumber.addEventListener("input",(e)=>{ powerrange.value=e.target.value; powerselect.value="" }) powerselect.addEventListener("change",(e)=>{ if (!e.target.value) { return; } powernumber.value=e.target.value; powerrange.value=e.target.value; }) */ function setRange(val) { let label=document.getElementById("enrich-label"); if (val>=0.0 && val<0.7) { label.innerHTML="Depleted"; } else if (val==0.7) { label.innerHTML="Natural"; } else if (val>0.7 && val<=5) { label.innerHTML="LEU"; } else if (val>5 && val<=20.0) { label.innerHTML="HALEU"; } else if (val>20.0 && val<=99.0) { label.innerHTML="HEU"; } else if (val>99.0 && val<=100.0) { label.innerHTML="😲"; } else { label.innerHTML="Impossible"; } } function computeFeed() { // Compute feed and SWU given desired product and enrichment // compute MF/MP = feed factor let mode = document.querySelector('input[name="mode"]:checked').value let feed_factor= get_feed_factor(); if (mode=="1") { feed_mass.value = (feed_factor * product_mass.value).toFixed(3); } else { product_mass.value = (feed_mass.value/feed_factor).toFixed(3); } let swu_factor=get_swu_factor(feed_factor) swu.value = (swu_factor * product_mass.value).toFixed(3); tails_mass.value = (feed_mass.value - product_mass.value).toFixed(3); // update plot data let u238 = { x: ['Feed', 'Product', 'Tails'], y: [feed_mass.value*(1-feed_assay.value/100.0), product_mass.value*(1-number.value/100.0), tails_mass.value*(1-tails_assay.value/100.0) ], name: 'U238', type: 'bar' }; let u235 = { x: ['Feed', 'Product', 'Tails'], y: [feed_mass.value*(feed_assay.value/100.0), product_mass.value*(number.value/100.0), tails_mass.value*(tails_assay.value/100.0) ], name: 'U235', type: 'bar' }; var data=[u238, u235]; Plotly.react('plot', data, layout); computeCost(); } function computeCost() { // we want to know $SWU/kWh, $Feed/kWh, $Fab/kWh and total cost for plotting // so we need SWU = SWUfactor*product * swu cost // product = how much fuel is needed to make a kWh // kg = 1 kWe * 1 hour * 1/eff [MWt/MWe] * 1/24 [day/hour] * 1/burnup [kg/(MWt*day)] * 1000 kW/MW) let feed_factor = get_feed_factor(); let swu_factor = get_swu_factor(feed_factor) let prod_kg_per_kwe = 100.0/(effnumber.value * 24.0 * burnup.value * 1000.0); let swu_per_kwe = prod_kg_per_kwe * swu_factor; let feed_per_kwe = prod_kg_per_kwe * feed_factor; // convert to cents let swu_cost_per_kwe = swu_per_kwe * swucost.value*100; let feed_cost_per_kwe = feed_per_kwe * feedcost.value*100 let fab_cost_per_kwe = prod_kg_per_kwe*fabcost.value*100 let conv_cost_per_kwe = feed_per_kwe*convcost.value*100 let tcost = swu_cost_per_kwe + feed_cost_per_kwe + conv_cost_per_kwe + fab_cost_per_kwe; reload_total_cost.value = tcost.toFixed(3); reload_swu_cost.value = swu_cost_per_kwe.toFixed(3); reload_feed_cost.value = feed_cost_per_kwe.toFixed(3); reload_fab_cost.value = fab_cost_per_kwe.toFixed(3); reload_conv_cost.value = conv_cost_per_kwe.toFixed(3); reload_waste.value = (prod_kg_per_kwe*1000000).toFixed(3); reload_feed_mass.value = (feed_per_kwe*1000000).toFixed(3); } function vx(x) { // value function: gotta convert percentages to fraction let xn = Number(x/100.0); return (1.0-2*xn) * Math.log((1.0-xn)/xn); } function get_feed_factor(){ // feed factor = F/P return (number.value - tails_assay.value)/(feed_assay.value-tails_assay.value); } function get_swu_factor(feed_factor) { // swufactor= SWU/MP let vxt = vx(tails_assay.value) return (vx(number.value) - vxt) - feed_factor*(vx(feed_assay.value)-vxt); } function setInputVals() { // These can all be passed in as query params const input = new URLSearchParams(window.location.search); tails_assay.value = input.get("tails-assay") || 0.25; feed_assay.value = input.get("feed-assay") || 0.711; number.value = input.get("enrich") || 4.0; range.value = number.value; setRange(number.value); feed_mass.value = input.get("feed-mass") || 0; product_mass.value = input.get("product-mass") || 1; feed_mass.value = input.get("feed-mass") || 1; if (input.get("mode") == "0") { // check a checkbox prod_const.checked=true }; } function copySettingsToClipboard() { let params = new URLSearchParams([ ["tails-assay", tails_assay.value], ["feed-assay", feed_assay.value], ["enrich", number.value], ["feed-mass", feed_mass.value], ["product-mass", product_mass.value], ["mode", prod_const.checked ? "0" : "1"], ]); let text = new URL(`${location.protocol + '//' + location.host + location.pathname}?${params}`); navigator.clipboard.writeText(text); } var trace1 = { x: ['Feed', 'Product', 'Tails'], y: [20, 14, 23], name: 'U238', type: 'bar' }; var trace2 = { x: ['Feed', 'Product', 'Tails'], y: [12, 18, 29], name: 'U235', type: 'bar' }; var data = [trace1, trace2]; var layout = {barmode: 'stack', yaxis: { type: 'log', autorange: true, }, autosize: true, margin: { t: 0 }, }; Plotly.newPlot('plot', data, layout); window.onresize = function() { Plotly.relayout('plot', {}) } // compute initial values setInputVals(); computeFeed(); </script>