{"id":7081,"date":"2023-09-26T20:09:56","date_gmt":"2023-09-26T20:09:56","guid":{"rendered":"https:\/\/www.minco.com\/?post_type=resources&#038;p=7081"},"modified":"2024-02-19T18:43:01","modified_gmt":"2024-02-19T18:43:01","slug":"heater-wattage-estimator","status":"publish","type":"resources","link":"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/","title":{"rendered":"Heater Wattage Estimator"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"7081\" class=\"elementor elementor-7081\" data-elementor-post-type=\"resources\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7e86027 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7e86027\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-46b2111\" data-id=\"46b2111\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-6a76875 elementor-widget__width-initial elementor-widget elementor-widget-text-editor\" data-id=\"6a76875\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p class=\"MsoNormal\" style=\"margin-left: .7pt; text-indent: -.7pt; line-height: 107%;\">Etched-foil heaters have gained significant popularity due to their flexibility, uniform heat distribution, and rapid response times. These heaters consist of a resistive heating element etched onto a thin foil substrate, providing excellent thermal conductivity. Accurate estimation of power requirements is essential for designing the electrical circuitry and ensuring optimal performance of the heating system.<\/p><p class=\"MsoNormal\" style=\"margin-left: .7pt; text-indent: -.7pt; line-height: 107%;\">This calculator models the conduction, radiation, and convection losses of a heat sink, as well as process heat requirements, to assist you in determining heater wattage needs.\u00a0 Add input values in the appropriate fields below and the calculator will provide an estimate the minimum heater wattage.\u00a0 See the &#8220;Minco Heater Wattage Estimator&#8221; video for further instruction.<\/p><p class=\"MsoNormal\" style=\"margin-left: .7pt; text-indent: -.7pt; line-height: 107%;\">For more detail on estimating heater wattage, see our corresponding white paper, &#8220;<a href=\"https:\/\/www.minco.com\/wp-content\/uploads\/Minco-thermal-calculator-heater-wattage-estimator-final-white-paper-oct-3-2023.pdf\">Estimating Power Requirements of Etched-Foil Heaters<\/a>&#8220;.<\/p><p class=\"MsoNormal\" style=\"margin-left: .7pt; text-indent: -.7pt; line-height: 107%;\">\u00a0<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-34acddc elementor-widget__width-initial elementor-widget elementor-widget-video\" data-id=\"34acddc\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;video_type&quot;:&quot;hosted&quot;,&quot;controls&quot;:&quot;yes&quot;}\" data-widget_type=\"video.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"e-hosted-video elementor-wrapper elementor-open-inline\">\n\t\t\t\t\t<video class=\"elementor-video\" src=\"https:\/\/www.minco.com\/wp-content\/uploads\/Minco-Heater-Wattage-Estimator.mp4\" controls=\"\" preload=\"metadata\" controlsList=\"nodownload\"><\/video>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bd365da elementor-widget elementor-widget-heading\" data-id=\"bd365da\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h4 class=\"elementor-heading-title elementor-size-default\">Thermal System Example<\/h4>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8c80450 elementor-widget elementor-widget-html\" data-id=\"8c80450\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<p>  <\/p>\n<!-- Started from e2aae4e61fb2a7d9c523f9e41b2ac0595fdf50b0 -->\n\n<img decoding=\"async\" alt=\"Diagram showing heater operating requirements\"\n     src=\"\/wp-content\/uploads\/thermal-calc-header.png\"\/>\n\n<p>We will estimate the steady-state operating requirements and the warm-up requirements. The estimated minimum wattage\n    required will be the\n    greater of the two sets of requirements, plus a small buffer.<\/p>\n\n<hr\/>\n\n<h2>Inputs<\/h2>\n\n<div class=\"inputLossGroupContainer\">\n    <div class=\"inputLossGroup\" id=\"commonInputs\">\n        <div class=\"boxHeader\">\n            <h3>Common<\/h3>\n        <\/div>\n        <div class=\"lossForm\" data-index=\"0\" data-type=\"common\">\n            <div class=\"lossFormBody\">\n                <label for=\"ambientTemperature\">Ambient temperature (\u00b0C):<\/label>\n                <input autocomplete=\"off\" class=\"ambientTemperature\" id=\"ambientTemperature\"\n                       name=\"ambientTemperature\"\n                       oninput=\"handleCommonInput(this)\"\n                       size=\"7\">\n                <label for=\"finalTemperature\">Heat sink final temperature (\u00b0C):<\/label>\n                <input autocomplete=\"off\" class=\"finalTemperature\" id=\"finalTemperature\"\n                       name=\"finalTemperature\"\n                       oninput=\"handleCommonInput(this)\"\n                       size=\"7\">\n            <\/div>\n        <\/div>\n    <\/div>\n    <div class=\"inputLossGroupSpacer\"><\/div>\n    <div class=\"inputLossGroup\" data-type=\"conductiveLoss\">\n        <div class=\"boxHeader\">\n            <h3 class=\"addLossFormHeader\">Conductive Losses<\/h3>\n        <\/div>\n\n        <div class=\"template\" data-index=\"0\">\n            <div class=\"display-contents lossColumn\" data-type=\"conductiveLoss\">\n                <input aria-label=\"Reference ID\"\n                       autocomplete=\"off\"\n                       class=\"referenceId\"\n                       name=\"referenceId\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       placeholder=\"optional\"\n                       size=\"7\">\n                <input autocomplete=\"off\"\n                       class=\"thermalConductivity\"\n                       list=\"thermalConductivityDatalist\"\n                       name=\"thermalConductivity\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\"\n                       class=\"crossSectionalArea\"\n                       name=\"crossSectionalArea\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"heatsinkTemperature\"\n                       name=\"heatsinkTemperature\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"conductivePathLength\"\n                       name=\"conductivePathLength\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"oppositeSurfaceTemperature\"\n                       name=\"oppositeSurfaceTemperature\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\"\n                       class=\"lossResult\"\n                       data-type=\"conductiveLoss\"\n                       disabled\n                       name=\"conductiveLossColumnSubtotal\"\n                       readonly\n                       size=\"7\">\n            <\/div>\n        <\/div>\n\n        <div class=\"lossExplanation\">\n            <p>When speaking of etched-foil heaters, conductive loss generally refers to loss through insulation layers\n                or heat sink mounting hardware. The conductive loss also depends upon the ambient temperature.<\/p>\n        <\/div>\n        <div class=\"lossFormBodyWrapper\">\n            <div class=\"lossFormBody\">\n                <label class=\"labelHeader\" data-for=\"referenceId\">Reference ID:<\/label>\n\n                <label data-for=\"thermalConductivity\"\n                       data-toggletip-content=\"Try tapping or double-tapping the box to get a list of values, or enter your own.\">\n                    Thermal Conductivity of material (w\/mK):\n                    <svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 20 20\" width=\"1em\"\n                         xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                        <path clip-rule=\"evenodd\"\n                              d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM8.94 6.94a.75.75 0 11-1.061-1.061 3 3 0 112.871 5.026v.345a.75.75 0 01-1.5 0v-.5c0-.72.57-1.172 1.081-1.287A1.5 1.5 0 108.94 6.94zM10 15a1 1 0 100-2 1 1 0 000 2z\"\n                              fill-rule=\"evenodd\"\/>\n                    <\/svg>\n                    <div role=\"status\"><\/div>\n                <\/label>\n\n                <label data-for=\"crossSectionalArea\">Cross sectional area of material\n                    (cm<sup>2<\/sup>):<\/label>\n\n                <label data-for=\"heatsinkTemperature\">Heat sink temperature (\u00b0C):<\/label>\n\n                <label data-for=\"conductivePathLength\">Thickness of insulation or length of conductive path\n                    (mm):<\/label>\n\n                <label data-for=\"oppositeSurfaceTemperature\"\n                       data-toggletip-content=\"If the surface temperature of the material opposite the heater is close to ambient, this can be left blank and the ambient temperature will be used. Otherwise, enter the opposite material's surface temperature.\">Opposite material surface temperature (optional): (\u00b0C)\n                    <svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 20 20\" width=\"1em\"\n                         xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                        <path clip-rule=\"evenodd\"\n                              d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM8.94 6.94a.75.75 0 11-1.061-1.061 3 3 0 112.871 5.026v.345a.75.75 0 01-1.5 0v-.5c0-.72.57-1.172 1.081-1.287A1.5 1.5 0 108.94 6.94zM10 15a1 1 0 100-2 1 1 0 000 2z\"\n                              fill-rule=\"evenodd\"\/>\n                    <\/svg>\n                    <div role=\"status\"><\/div>\n                <\/label>\n                <label class=\"lossResultLabel\" data-for=\"conductiveLossColumnSubtotal\">Subtotal (W):<\/label>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"inputLossGroup\" data-type=\"radiationLoss\">\n        <div class=\"boxHeader\">\n            <h3 class=\"addLossFormHeader\">Radiation Losses<\/h3>\n        <\/div>\n        <div class=\"lossExplanation\">\n            <p>Radiation is heat emitted as infrared energy. The radiation losses also depend on the ambient temperature\n                and the final temperature of the heat sink.<\/p>\n        <\/div>\n        <div class=\"template\" data-index=\"0\">\n            <div class=\"display-contents lossColumn\" data-type=\"radiationLoss\">\n\n                <input autocomplete=\"off\"\n                       class=\"referenceId\"\n                       name=\"referenceId\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       placeholder=\"optional\"\n                       size=\"7\">\n\n                <input autocomplete=\"off\" class=\"emissivity\"\n                       list=\"emissivityDatalist\"\n                       name=\"emissivity\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n\n                <input autocomplete=\"off\" class=\"radExposedSurfaceArea\"\n                       name=\"radExposedSurfaceArea\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n\n                <input autocomplete=\"off\"\n                       class=\"lossResult hidden\"\n                       disabled\n                       name=\"radiationLossColumnSubtotal\"\n                       readonly\n                       size=\"7\">\n            <\/div>\n        <\/div>\n\n        <div class=\"lossFormBodyWrapper\">\n            <div class=\"lossFormBody\">\n                <label class=\"labelHeader\">Reference ID:<\/label>\n                <label data-for=\"emissivity\"\n                       data-toggletip-content=\"Try tapping or double-tapping the box to get a list of values, or enter your own.\">\n                    Emissivity of heat sink surface:\n                    <svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 20 20\" width=\"1em\"\n                         xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                        <path clip-rule=\"evenodd\"\n                              d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM8.94 6.94a.75.75 0 11-1.061-1.061 3 3 0 112.871 5.026v.345a.75.75 0 01-1.5 0v-.5c0-.72.57-1.172 1.081-1.287A1.5 1.5 0 108.94 6.94zM10 15a1 1 0 100-2 1 1 0 000 2z\"\n                              fill-rule=\"evenodd\"\/>\n                    <\/svg>\n                    <div role=\"status\"><\/div>\n                <\/label>\n\n                <label data-for=\"radExposedSurfaceArea\">Exposed surface area (cm<sup>2<\/sup>):<\/label>\n\n                <label class=\"lossResultLabel\" data-for=\"radiationLossColumnSubtotal\">Subtotal (W):<\/label>\n            <\/div>\n        <\/div>\n    <\/div>\n    <div class=\"inputLossGroup\" data-type=\"naturalConvectionLoss\">\n        <div class=\"boxHeader\">\n            <h3 class=\"addLossFormHeader\">Natural Convection Losses<\/h3>\n        <\/div>\n        <div class=\"lossExplanation\">\n            <p>Natural convection occurs when heated air rises and creates air currents. The natural convection losses\n                also depend on the ambient temperature and the final temperature of the heat sink.<\/p>\n        <\/div>\n\n        <div class=\"template\" data-index=\"0\">\n            <div class=\"display-contents lossColumn\" data-type=\"naturalConvectionLoss\">\n                <input autocomplete=\"off\"\n                       class=\"referenceId\"\n                       name=\"referenceId\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       placeholder=\"optional\"\n                       size=\"7\">\n                <div class=\"naturalConvectionHelperRadioGroup\">\n                    <div><input id=\"naturalConvectionHelperHorizontalCylinder\" name=\"naturalConvectionHelper\"\n                                onclick=\"handleNaturalConvectionHelperClick(this);\" type=\"radio\"\n                                value=\"horizontal-cylinder\">\n                        <label for=\"naturalConvectionHelperHorizontalCylinder\">Horizontal cylinder<\/label>\n                    <\/div>\n                    <div>\n                        <input id=\"naturalConvectionHelperHorizontalPlateFacingUp\" name=\"naturalConvectionHelper\"\n                               onclick=\"handleNaturalConvectionHelperClick(this);\"\n                               type=\"radio\" value=\"horizontal-plate-facing-up\">\n                        <label for=\"naturalConvectionHelperHorizontalPlateFacingUp\">Horizontal plate,<br>facing\n                            up<\/label>\n                    <\/div>\n                    <div>\n                        <input id=\"naturalConvectionHelperHorizontalPlateFacingDown\" name=\"naturalConvectionHelper\"\n                               onclick=\"handleNaturalConvectionHelperClick(this);\"\n                               type=\"radio\" value=\"horizontal-plate-facing-down\">\n                        <label for=\"naturalConvectionHelperHorizontalPlateFacingDown\">Horizontal plate,<br>facing\n                            down<\/label>\n                    <\/div>\n                    <div>\n                        <input id=\"naturalConvectionHelperRectangularBlock\" name=\"naturalConvectionHelper\"\n                               onclick=\"handleNaturalConvectionHelperClick(this);\" type=\"radio\"\n                               value=\"rectangular-block\">\n                        <label for=\"naturalConvectionHelperRectangularBlock\">Rectangular block<\/label>\n                    <\/div>\n                    <div>\n                        <input id=\"naturalConvectionHelperVerticalCylinder\" name=\"naturalConvectionHelper\"\n                               onclick=\"handleNaturalConvectionHelperClick(this);\" type=\"radio\"\n                               value=\"vertical-cylinder\">\n                        <label for=\"naturalConvectionHelperVerticalCylinder\">Vertical cylinder<\/label>\n                    <\/div>\n                    <div>\n                        <input id=\"naturalConvectionHelperVerticalPlate\" name=\"naturalConvectionHelper\"\n                               onclick=\"handleNaturalConvectionHelperClick(this);\" type=\"radio\"\n                               value=\"vertical-plate\">\n                        <label for=\"naturalConvectionHelperVerticalPlate\">Vertical plate<\/label>\n                    <\/div>\n                    <img decoding=\"async\" src=\"\/wp-content\/uploads\/thermal-calc-horcyl.png\"\/>\n                <\/div>\n\n                <input autocomplete=\"off\" class=\"helper helperHeight gone\"\n                       data-helps=\"rectangular-block vertical-cylinder vertical-plate\"\n                       name=\"helperHeight\"\n                       oninput=\"handleNaturalConvectionHelperChange(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"helper helperLongestSide gone\"\n                       data-helps=\"rectangular-block\"\n                       name=\"helperLongestSide\"\n                       oninput=\"handleNaturalConvectionHelperChange(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"helper helperRadius gone\"\n                       data-helps=\"horizontal-cylinder\"\n                       name=\"helperRadius\"\n                       oninput=\"handleNaturalConvectionHelperChange(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"helper helperArea gone\"\n                       data-helps=\"horizontal-plate-facing-up horizontal-plate-facing-down\"\n                       name=\"helperArea\"\n                       oninput=\"handleNaturalConvectionHelperChange(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"helper helperPerimeter gone\"\n                       data-helps=\"horizontal-plate-facing-up horizontal-plate-facing-down\"\n                       name=\"helperPerimeter\"\n                       oninput=\"handleNaturalConvectionHelperChange(this)\"\n                       size=\"7\">\n\n                <input autocomplete=\"off\" class=\"configurationFactor\"\n                       disabled\n                       name=\"configurationFactor\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       readonly\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"characteristicLength\"\n                       disabled\n                       name=\"characteristicLength\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       readonly\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"nExposedSurfaceArea\"\n                       name=\"nExposedSurfaceArea\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\"\n                       class=\"lossResult hidden\"\n                       disabled\n                       name=\"naturalConvectionLossColumnSubtotal\"\n                       readonly\n                       size=\"7\">\n            <\/div>\n        <\/div>\n\n        <div class=\"lossFormBodyWrapper\">\n            <div class=\"lossFormBody\">\n                <label class=\"labelHeader\">Reference ID:<\/label>\n                <label>Configuration:<\/label>\n                <label class=\"helper helperHeight gone\"\n                       data-helps=\"rectangular-block vertical-cylinder vertical-plate\">Height (cm):<\/label>\n                <label class=\"helper helperLongestSide gone\"\n                       data-helps=\"rectangular-block\">Longest Side (cm):<\/label>\n                <label class=\"helper helperRadius gone\"\n                       data-helps=\"horizontal-cylinder\">Radius (cm):<\/label>\n                <label class=\"helper helperArea gone\"\n                       data-helps=\"horizontal-plate-facing-up horizontal-plate-facing-down\">Area\n                    (cm<sup>2<\/sup>):<\/label>\n                <label class=\"helper helperPerimeter gone\"\n                       data-helps=\"horizontal-plate-facing-up horizontal-plate-facing-down\">Perimeter (cm):<\/label>\n                <label data-for=\"configurationFactor\">Configuration Factor:<\/label>\n                <label data-for=\"characteristicLength\">Characteristic length (cm):<\/label>\n                <label data-for=\"nExposedSurfaceArea\">Exposed surface area (cm<sup>2<\/sup>):<\/label>\n                <label class=\"lossResultLabel\" data-for=\"naturalConvectionLossColumnSubtotal\">Subtotal (W):<\/label>\n            <\/div>\n        <\/div>\n    <\/div>\n    <div class=\"inputLossGroup\" data-type=\"forcedAirConvectionLoss\">\n        <div class=\"boxHeader\">\n            <h3 class=\"addLossFormHeader\">Forced Air Convection Losses<\/h3>\n        <\/div>\n        <div class=\"lossExplanation\">\n            <p>Forced air convection occurs when fans or wind drive air past the heater. The forced air convection\n                losses also depend on the ambient temperature and the final temperature of the heat sink.<\/p>\n        <\/div>\n\n        <div class=\"template\" data-index=\"0\">\n            <div class=\"display-contents lossColumn\" data-type=\"forcedAirConvectionLoss\">\n                <input autocomplete=\"off\"\n                       class=\"referenceId\"\n                       name=\"referenceId\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       placeholder=\"optional\"\n                       size=\"7\">\n\n                <input autocomplete=\"off\" class=\"airVelocity\"\n                       name=\"airVelocity\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"sideLength\"\n                       name=\"sideLength\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"faExposedSurfaceArea\"\n                       name=\"faExposedSurfaceArea\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n\n                <input autocomplete=\"off\"\n                       class=\"lossResult hidden\"\n                       disabled\n                       name=\"forcedAirConvectionLossColumnSubtotal\"\n                       readonly\n                       size=\"7\">\n            <\/div>\n        <\/div>\n        <div class=\"lossFormBodyWrapper\">\n            <div class=\"lossFormBody\">\n                <label class=\"labelHeader\" data-for=\"referenceId\">Reference ID:<\/label>\n                <label data-for=\"airVelocity\">Average air velocity (m\/s):<\/label>\n                <label data-for=\"sideLength\">Length of side parallel to air flow (cm):<\/label>\n                <label data-for=\"faExposedSurfaceArea\">Exposed surface area (cm<sup>2<\/sup>):<\/label>\n                <label class=\"lossResultLabel\" data-for=\"forcedAirConvectionLossColumnSubtotal\">Subtotal (W):<\/label>\n            <\/div>\n        <\/div>\n    <\/div>\n    <div class=\"inputLossGroup\" data-type=\"warmUpHeatLoss\">\n        <div class=\"boxHeader\">\n            <h3 class=\"addLossFormHeader\">Warm-up Heat<\/h3>\n        <\/div>\n        <div class=\"lossExplanation\">\n            <p>Warm-up heat is the heat required to bring the heat sink to temperature in the desired time, plus heat to\n                compensate for conductive, radiant, and convective losses during warm-up.<\/p>\n        <\/div>\n\n        <div class=\"lossFormBodyWrapper\">\n            <div class=\"lossFormBody\">\n                <label data-for=\"mass\">Mass (g):<\/label>\n                <label data-for=\"materialSpecificHeat\"\n                       data-toggletip-content=\"Try tapping or double-tapping the box to get a list of values, or enter your own.\">\n                    Specific heat (J\/kg K):\n                    <svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 20 20\" width=\"1em\"\n                         xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                        <path clip-rule=\"evenodd\"\n                              d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM8.94 6.94a.75.75 0 11-1.061-1.061 3 3 0 112.871 5.026v.345a.75.75 0 01-1.5 0v-.5c0-.72.57-1.172 1.081-1.287A1.5 1.5 0 108.94 6.94zM10 15a1 1 0 100-2 1 1 0 000 2z\"\n                              fill-rule=\"evenodd\"\/>\n                    <\/svg>\n                    <div role=\"status\"><\/div>\n                <\/label>\n                <label data-for=\"initialTemperature\">Heat sink initial temperature (\u00b0C):<\/label>\n                <label data-for=\"warmUpTime\">Desired warm-up time (min):<\/label>\n                <label class=\"lossResultLabel\" data-for=\"warmUpHeatLossColumnSubtotal\">Subtotal (W):<\/label>\n\n                <div class=\"display-contents lossColumn\" data-type=\"warmUpHeatLoss\">\n                    <input autocomplete=\"off\" class=\"mass\"\n                           name=\"mass\"\n                           oninput=\"updateWarmUpHeatLoss(this)\"\n                           size=\"7\">\n\n                    <input autocomplete=\"off\" class=\"materialSpecificHeat\"\n                           list=\"specificHeatDatalist\"\n                           name=\"materialSpecificHeat\"\n                           oninput=\"updateWarmUpHeatLoss(this)\"\n                           size=\"7\"\n                    \/>\n                    <input autocomplete=\"off\" class=\"initialTemperature\"\n                           name=\"initialTemperature\"\n                           oninput=\"updateWarmUpHeatLoss(this)\"\n                           size=\"7\">\n                    <input autocomplete=\"off\" class=\"warmUpTime\"\n                           name=\"warmUpTime\"\n                           oninput=\"updateWarmUpHeatLoss(this)\"\n                           size=\"7\">\n                    <input autocomplete=\"off\"\n                           class=\"lossResult hidden\"\n                           disabled\n                           name=\"warmUpHeatLossColumnSubtotal-0\"\n                           readonly\n                           size=\"7\">\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n    <div class=\"inputLossGroup\" data-type=\"processHeatLoss\">\n        <div class=\"boxHeader\">\n            <h3 class=\"addLossFormHeader\">Process Heat Requirements<\/h3>\n        <\/div>\n        <div class=\"lossExplanation\">\n            <p>Process heat represents work done by the heater to thermally process some material. Examples of process\n                heat are melting a plastic film placed over a heat sink or heating a PCB to a set temperature.<\/p>\n        <\/div>\n        <div class=\"template\" data-index=\"0\">\n            <div class=\"display-contents lossColumn\" data-type=\"processHeatLoss\">\n                <input autocomplete=\"off\"\n                       class=\"referenceId\"\n                       name=\"referenceId\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       placeholder=\"optional\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"materialMass\"\n                       name=\"materialMass\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"cycleTime\"\n                       name=\"cycleTime\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"finalMaterialTemperature\"\n                       name=\"finalMaterialTemperature\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"initialMaterialTemperature\"\n                       name=\"initialMaterialTemperature\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\" class=\"materialSpecificHeat\"\n                       list=\"specificHeatDatalist\"\n                       name=\"materialSpecificHeat\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <div class=\"processHeatLabelSpacer\"><!-- spacer dummy --><\/div>\n                <input autocomplete=\"off\" class=\"stateChangeHeat\"\n                       list=\"latentHeatDatalist\"\n                       name=\"stateChangeHeat\"\n                       oninput=\"updateSpecificLoss(this)\"\n                       size=\"7\">\n                <input autocomplete=\"off\"\n                       class=\"lossResult hidden\"\n                       disabled\n                       name=\"processHeatLossColumnSubtotal\"\n                       readonly\n                       size=\"7\">\n            <\/div>\n        <\/div>\n        <div class=\"lossFormBodyWrapper\">\n            <div class=\"lossFormBody\">\n                <label class=\"labelHeader\" data-for=\"referenceId\">Reference ID:<\/label>\n                <label data-for=\"materialMass\">Mass of material per load (g):<\/label>\n                <label data-for=\"cycleTime\">Cycle time per load (s):<\/label>\n                <label data-for=\"finalMaterialTemperature\">Final temperature of material (\u00b0C):<\/label>\n                <label data-for=\"initialMaterialTemperature\">Initial temperature of material (\u00b0C):<\/label>\n                <label data-for=\"materialSpecificHeat\"\n                       data-toggletip-content=\"Try tapping or double-tapping the box to get a list of values, or enter your own.\">\n                    Specific heat of material (J\/kg K):\n                    <svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 20 20\" width=\"1em\"\n                         xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                        <path clip-rule=\"evenodd\"\n                              d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM8.94 6.94a.75.75 0 11-1.061-1.061 3 3 0 112.871 5.026v.345a.75.75 0 01-1.5 0v-.5c0-.72.57-1.172 1.081-1.287A1.5 1.5 0 108.94 6.94zM10 15a1 1 0 100-2 1 1 0 000 2z\"\n                              fill-rule=\"evenodd\"\/>\n                    <\/svg>\n                    <div role=\"status\"><\/div>\n                <\/label>\n                <div class=\"processHeatStateChangeLabel\">If processed material changes state:<\/div>\n                <label data-for=\"stateChangeHeat\"\n                       data-toggletip-content=\"Try tapping or double-tapping the box to get a list of values, or enter your own.\">\n                    Latent heat of fusion (melting) or vaporization (J\/g):\n                    <svg fill=\"currentColor\" height=\"1em\" viewBox=\"0 0 20 20\" width=\"1em\"\n                         xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                        <path clip-rule=\"evenodd\"\n                              d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM8.94 6.94a.75.75 0 11-1.061-1.061 3 3 0 112.871 5.026v.345a.75.75 0 01-1.5 0v-.5c0-.72.57-1.172 1.081-1.287A1.5 1.5 0 108.94 6.94zM10 15a1 1 0 100-2 1 1 0 000 2z\"\n                              fill-rule=\"evenodd\"\/>\n                    <\/svg>\n                    <div role=\"status\"><\/div>\n                <\/label>\n                <label class=\"lossResultLabel\" data-for=\"processHeatLossColumnSubtotal\">Subtotal (W):<\/label>\n            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n<hr>\n<ul class=\"buttons\">\n    <li>\n        <a class=\"heroicon-mini\"\n           onclick=\"window.print()\"\n           role=\"button\"\n           tabindex=\"0\"\n           title=\"Print\">\n            <svg fill=\"currentColor\" viewBox=\"0 0 20 20\" width=\"1em\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                <path clip-rule=\"evenodd\"\n                      d=\"M5 4v3H4a2 2 0 00-2 2v3a2 2 0 002 2h1v2a2 2 0 002 2h6a2 2 0 002-2v-2h1a2 2 0 002-2V9a2 2 0 00-2-2h-1V4a2 2 0 00-2-2H7a2 2 0 00-2 2zm8 0H7v3h6V4zm0 8H7v4h6v-4z\"\n                      fill-rule=\"evenodd\"\/>\n            <\/svg>\n            Print\n        <\/a>\n\n    <\/li>\n    <li>\n        <a class=\"heroicon-mini\"\n           onclick=\"exportCSV()\"\n           role=\"button\"\n           tabindex=\"0\"\n           title=\"Export CSV\">\n            Export CSV\n        <\/a>\n    <\/li>\n<\/ul>\n\n<div class=\"newResults\">\n    <div class=\"boxHeader\">\n        <h3>Results<\/h3>\n    <\/div>\n    <p>After comparing the warm-up heat and the operating heat, we estimate the minimum heater wattage.<\/p>\n    <div class=\"resultsFormBodyWrapper\">\n        <div class=\"resultsFormBody\">\n            <label class=\"labelHeader\">Minimum Heater Wattage (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"minimumHeaterWattage calculated\"\n                   disabled\n                   name=\"minimumHeaterWattage\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <p>To reach this estimate, we calculate the operating heat.<\/p>\n            <div class=\"calculatedHeader\">Calculation<\/div>\n            <div class=\"overrideHeader\">Overridden Value?<\/div>\n            <label>Conductive Losses (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"lossTotal calculated\"\n                   data-loss=\"0\"\n                   data-type=\"conductiveLoss\"\n                   disabled\n                   name=\"conductiveLossTotal\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideCheckbox\"\n                   data-type=\"conductiveLoss\"\n                   name=\"conductiveLossOverride\"\n                   onclick=\"toggleOverride(this)\"\n                   type=\"checkbox\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideValue hidden\"\n                   data-type=\"conductiveLoss\"\n                   name=\"conductiveLossOverrideValue\"\n                   oninput=\"updateOverride(this)\"\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <label>Radiation Losses (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"lossTotal calculated\"\n                   data-loss=\"0\"\n                   data-type=\"radiationLoss\"\n                   disabled\n                   name=\"radiationLossTotal\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideCheckbox\"\n                   data-type=\"radiationLoss\"\n                   name=\"radiationLossOverride\"\n                   onclick=\"toggleOverride(this)\"\n                   type=\"checkbox\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideValue hidden\"\n                   data-type=\"radiationLoss\"\n                   name=\"radiationLossOverrideValue\"\n                   oninput=\"updateOverride(this)\"\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <label>Natural Convection Losses (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"lossTotal calculated\"\n                   data-loss=\"0\"\n                   data-type=\"naturalConvectionLoss\"\n                   disabled\n                   name=\"naturalConvectionLossTotal\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideCheckbox\"\n                   data-type=\"naturalConvectionLoss\"\n                   name=\"naturalConvectionLossOverride\"\n                   onclick=\"toggleOverride(this)\"\n                   type=\"checkbox\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideValue hidden\"\n                   data-type=\"naturalConvectionLoss\"\n                   name=\"naturalConvectionLossOverrideValue\"\n                   oninput=\"updateOverride(this)\"\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <label>Forced Air Convection Losses (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"lossTotal calculated\"\n                   data-loss=\"0\"\n                   data-type=\"forcedAirConvectionLoss\"\n                   disabled\n                   name=\"forcedAirConvectionLossTotal\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideCheckbox\"\n                   data-type=\"forcedAirConvectionLoss\"\n                   name=\"forcedAirConvectionLossOverride\"\n                   onclick=\"toggleOverride(this)\"\n                   type=\"checkbox\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideValue hidden\"\n                   data-type=\"forcedAirConvectionLoss\"\n                   name=\"forcedAirConvectionLossOverrideValue\"\n                   oninput=\"updateOverride(this)\"\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <label>Process Heat Losses (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"lossTotal calculated\"\n                   data-loss=\"0\"\n                   data-type=\"processHeatLoss\"\n                   disabled\n                   name=\"processHeatLossTotal\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideCheckbox\"\n                   data-type=\"processHeatLoss\"\n                   name=\"processHeatLossOverride\"\n                   onclick=\"toggleOverride(this)\"\n                   type=\"checkbox\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideValue hidden\"\n                   data-type=\"processHeatLoss\"\n                   name=\"processHeatLossOverrideValue\"\n                   oninput=\"updateOverride(this)\"\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <label class=\"operatingHeatLabel\">Operating Heat (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"operatingHeatTotal calculated\"\n                   data-type=\"operatingHeatLoss\"\n                   disabled\n                   name=\"operatingHeatTotal\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideCheckbox\"\n                   data-type=\"operatingHeatLoss\"\n                   name=\"operatingHeatOverride\"\n                   onclick=\"toggleOverride(this)\"\n                   type=\"checkbox\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideValue hidden\"\n                   data-type=\"operatingHeatLoss\"\n                   name=\"operatingHeatOverrideValue\"\n                   oninput=\"updateOverride(this)\"\n                   size=\"7\"\n                   value=\"\"><\/input>\n\n            <p>We compare the operating heat to the warm-up heat.<\/p>\n\n            <label>Warm-up Heat (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"warmUpHeatTotal calculated\"\n                   data-type=\"warmUpHeatLoss\"\n                   disabled\n                   name=\"warmUpHeatTotal\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideCheckbox\"\n                   data-type=\"warmUpHeatLoss\"\n                   name=\"warmUpHeatOverride\"\n                   onclick=\"toggleOverride(this)\"\n                   type=\"checkbox\"\n                   value=\"\"><\/input>\n            <input autocomplete=\"off\"\n                   class=\"overrideValue hidden\"\n                   data-type=\"warmUpHeatLoss\"\n                   name=\"warmUpHeatOverrideValue\"\n                   oninput=\"updateOverride(this)\"\n                   size=\"7\"\n                   value=\"\"><\/input>\n            <p>We add 10% buffer to the greater of the two in order to estimate the minimum heater wattage.<\/p>\n            <label>Buffer (W):<\/label>\n            <input autocomplete=\"off\"\n                   class=\"bufferTotal calculated\"\n                   data-type=\"buffer\"\n                   disabled\n                   name=\"bufferTotal\"\n                   readonly\n                   size=\"7\"\n                   value=\"\"><\/input>\n        <\/div>\n    <\/div>\n<\/div>\n\n<div class=\"finalResultsGate\">\n\n<\/div>\n\n\n<datalist id=\"thermalConductivityDatalist\">\n    <option value=\"0.331\">ABS<\/option>\n    <option value=\"0.166\">Acetone 100%<\/option>\n    <option value=\"0.144\">Acrylic<\/option>\n    <option value=\"221\">Aluminum 1100-0<\/option>\n    <option value=\"121\">Aluminum 2024-T4<\/option>\n    <option value=\"167\">Aluminum 6061-T6<\/option>\n    <option value=\"0.15\">Benzene<\/option>\n    <option value=\"162\">Beryllium<\/option>\n    <option value=\"121\">Brass (70-30)<\/option>\n    <option value=\"138\">Brass (80-20)<\/option>\n    <option value=\"21.3\">Constantan<\/option>\n    <option value=\"394\">Copper<\/option>\n    <option value=\"0.346\">Epoxy<\/option>\n    <option value=\"0.187\">Ethyl Alcohol, 95%<\/option>\n    <option value=\"0.0403\">Fiberglass (Duct Ins.)<\/option>\n    <option value=\"0.0375\">Fiberglass (Spin-Glas)<\/option>\n    <option value=\"0.245\">Fluoroplastics<\/option>\n    <option value=\"1.04\">Glass<\/option>\n    <option value=\"0.284\">Glycerine<\/option>\n    <option value=\"297\">Gold<\/option>\n    <option value=\"2.25\">Ice<\/option>\n    <option value=\"15\">Inconel<\/option>\n    <option value=\"57.1\">Iron (Cast)<\/option>\n    <option value=\"62.2\">Iron (Wrought)<\/option>\n    <option value=\"0.144\">Kerosene<\/option>\n    <option value=\"154\">Magnesium<\/option>\n    <option value=\"8.76\">Mercury<\/option>\n    <option value=\"0.432\">Mica<\/option>\n    <option value=\"141\">Molybdenum<\/option>\n    <option value=\"0.648\">Mylar<\/option>\n    <option value=\"15\">Nichrome (80-20)<\/option>\n    <option value=\"67.4\">Nickel 200<\/option>\n    <option value=\"0.245\">Nylon<\/option>\n    <option value=\"0.259\">Paraffin (Solid)<\/option>\n    <option value=\"0.242\">Paraffin, Melted<\/option>\n    <option value=\"69.2\">Platinum<\/option>\n    <option value=\"0.202\">Polycarbonate<\/option>\n    <option value=\"0.504\">Polyethylene<\/option>\n    <option value=\"0.98\">Polyimides<\/option>\n    <option value=\"86.5\">Silicon<\/option>\n    <option value=\"0.216\">Silicone Rubber<\/option>\n    <option value=\"418\">Silver<\/option>\n    <option value=\"51.2\">Solder (60\/40)<\/option>\n    <option value=\"16.3\">Stainless Steel (300)<\/option>\n    <option value=\"21.6\">Stainless Steel (430)<\/option>\n    <option value=\"65.7\">Steel (Mild Carbon)<\/option>\n    <option value=\"0.259\">Sulfuric Acid, 98%<\/option>\n    <option value=\"67.4\">Tin, Solid<\/option>\n    <option value=\"19.9\">Titanium<\/option>\n    <option value=\"0.13\">Transformer Oils<\/option>\n    <option value=\"0.588\">Water<\/option>\n    <option value=\"27.1\">Zinc<\/option>\n<\/datalist>\n\n<datalist id=\"latentHeatDatalist\">\n    <option value=\"n\/a\">Material not changing state<\/option>\n    <option value=\"523\">Acetone 100%<\/option>\n    <option value=\"393\">Aluminum 1100-0<\/option>\n    <option value=\"388\">Aluminum 2024-T4<\/option>\n    <option value=\"400\">Aluminum 6061-T6<\/option>\n    <option value=\"395\">Benzene<\/option>\n    <option value=\"591\">Butyl Alcohol<\/option>\n    <option value=\"861\">Ethyl Alcohol, 95%<\/option>\n    <option value=\"335\">Ice<\/option>\n    <option value=\"200\">Kerosene<\/option>\n    <option value=\"11.6\">Mercury<\/option>\n    <option value=\"147\">Paraffin (Solid)<\/option>\n    <option value=\"163\">Paraffin (Melted)<\/option>\n    <option value=\"687\">Propyl Alcohol<\/option>\n    <option value=\"65.1\">Solder (60\/40)<\/option>\n    <option value=\"509\">Sulfuric Acid, 98%<\/option>\n    <option value=\"2250\">Water<\/option>\n<\/datalist>\n\n<datalist id=\"specificHeatDatalist\">\n    <option value=\"2090\">ABS<\/option>\n    <option value=\"2150\">Acetone 100%<\/option>\n    <option value=\"1460\">Acrylic<\/option>\n    <option value=\"900\">Aluminum 1100-0<\/option>\n    <option value=\"875\">Aluminum 2024-T4<\/option>\n    <option value=\"896\">Aluminum 6061-T6<\/option>\n    <option value=\"1760\">Benzene<\/option>\n    <option value=\"217\">Beryllium<\/option>\n    <option value=\"418\">Brass (70-30)<\/option>\n    <option value=\"380\">Brass (80-20)<\/option>\n    <option value=\"2870\">Butyl Alcohol<\/option>\n    <option value=\"376\">Constantan<\/option>\n    <option value=\"418\">Copper<\/option>\n    <option value=\"1250\">Epoxy<\/option>\n    <option value=\"2510\">Ethyl Alcohol, 95%<\/option>\n    <option value=\"1170\">Fluoroplastics<\/option>\n    <option value=\"836\">Glass<\/option>\n    <option value=\"2420\">Glycerine<\/option>\n    <option value=\"125\">Gold<\/option>\n    <option value=\"2050\">Ice<\/option>\n    <option value=\"460\">Inconel<\/option>\n    <option value=\"544\">Iron (Cast)<\/option>\n    <option value=\"502\">Iron (Wrought)<\/option>\n    <option value=\"200\">Kerosene<\/option>\n    <option value=\"1050\">Magnesium<\/option>\n    <option value=\"138\">Mercury<\/option>\n    <option value=\"836\">Mica<\/option>\n    <option value=\"255\">Molybdenum<\/option>\n    <option value=\"1130\">Mylar<\/option>\n    <option value=\"460\">Nichrome (80-20)<\/option>\n    <option value=\"460\">Nickel 200<\/option>\n    <option value=\"2090\">Nylon<\/option>\n    <option value=\"1800\">Oil, SAE 10W-30<\/option>\n    <option value=\"2880\">Paraffin (Solid)<\/option>\n    <option value=\"2880\">Paraffin, Melted<\/option>\n    <option value=\"130\">Platinum<\/option>\n    <option value=\"1250\">Polycarbonate<\/option>\n    <option value=\"2260\">Polyethylene<\/option>\n    <option value=\"1300\">Polyimides<\/option>\n    <option value=\"2380\">Propyl Alcohol<\/option>\n    <option value=\"677\">Silicon<\/option>\n    <option value=\"1880\">Silicone Rubber<\/option>\n    <option value=\"234\">Silver<\/option>\n    <option value=\"188\">Solder (60\/40)<\/option>\n    <option value=\"502\">Stainless Steel (300)<\/option>\n    <option value=\"460\">Stainless Steel (430)<\/option>\n    <option value=\"502\">Steel (Mild Carbon)<\/option>\n    <option value=\"1460\">Sulfuric Acid, 98%<\/option>\n    <option value=\"234\">Tin, Solid<\/option>\n    <option value=\"527\">Titanium<\/option>\n    <option value=\"1760\">Transformer Oils<\/option>\n    <option value=\"1800\">Vegetable Oil<\/option>\n    <option value=\"4180\">Water<\/option>\n    <option value=\"397\">Zinc<\/option>\n<\/datalist>\n\n<datalist id=\"emissivityDatalist\">\n    <option value=\"1.00\">Blackbody<\/option>\n    <option value=\"0.07\">Aluminum, bright foil<\/option>\n    <option value=\"0.22\">Aluminum, heavy oxide<\/option>\n    <option value=\"0.82\">Aluminum, anodized<\/option>\n    <option value=\"0.04\">Brass, polished<\/option>\n    <option value=\"0.60\">Brass, heavy oxide<\/option>\n    <option value=\"0.03\">Copper, polished<\/option>\n    <option value=\"0.80\">Copper, heavy oxide<\/option>\n    <option value=\"0.95\">Epoxy<\/option>\n    <option value=\"0.9\">Glass<\/option>\n    <option value=\"0.02\">Gold<\/option>\n    <option value=\"0.85\">Iron, heavy oxide<\/option>\n    <option value=\"0.95\">Plastics (typical)<\/option>\n    <option value=\"0.95\">Silicone Rubber<\/option>\n    <option value=\"0.02\">Silver<\/option>\n    <option value=\"0.17\">Stainless Steel, polished<\/option>\n    <option value=\"0.85\">Stainless Steel, heavy oxide<\/option>\n    <option value=\"0.1\">Steel (mild), polished<\/option>\n    <option value=\"0.85\">Steel (mild), heavy oxide<\/option>\n    <option value=\"0.25\">Zinc<\/option>\n<\/datalist>\n\n<script>\n  function handleNaturalConvectionHelperClick(element) {\n    let image_path;\n    let configurationFactor;\n    let labels;\n    let inputs;\n\n    if (element.value === \"horizontal-cylinder\") {\n      image_path = \"\/wp-content\/uploads\/thermal-calc-horcyl.png\";\n      configurationFactor = 0.90;\n    } else if (element.value === \"horizontal-plate-facing-up\") {\n      image_path = \"\/wp-content\/uploads\/thermal-calc-horplate.png\";\n      configurationFactor = 1.29;\n    } else if (element.value === \"horizontal-plate-facing-down\") {\n      image_path = \"\/wp-content\/uploads\/thermal-calc-horplatedown.png\";\n      configurationFactor = 0.65;\n    } else if (element.value === \"rectangular-block\") {\n      image_path = \"\/wp-content\/uploads\/thermal-calc-rectangularblock.png\";\n      configurationFactor = 0.93;\n    } else if (element.value === \"vertical-cylinder\") {\n      image_path = \"\/wp-content\/uploads\/thermal-calc-vertcyl.png\";\n      configurationFactor = 1;\n    } else if (element.value === \"vertical-plate\") {\n      image_path = \"\/wp-content\/uploads\/thermal-calc-vertplate.png\";\n      configurationFactor = 1;\n    } else {\n      alert(\"Not implemented: \" + element.value + \".\");\n      return;\n    }\n\n    element.parentElement.parentElement.querySelector(\"img\").src = image_path;\n    element.closest(\".lossColumn\").querySelector(\".configurationFactor\").value = configurationFactor;\n\n    \/\/first, expose the elements we need to show\n    let selectedTypes = element.closest(\".inputLossGroup\").querySelectorAll(\"input[type='radio']:checked\");\n    let selectedTypesArray = Array.from(selectedTypes).map(input => input.value);\n\n    \/\/ iterate over all the labels and inputs\n    labels = element.closest(\".inputLossGroup\").querySelectorAll(\"label\");\n    inputs = element.closest(\".inputLossGroup\").querySelectorAll(\"input\");\n    for (let i = 0; i < labels.length; i++) {\n      if (labels[i].dataset.helps) {\n        \/\/ are there any words in common between selectedtypes and helps?\n        if (selectedTypesArray.some(type => labels[i].dataset.helps.includes(type))) {\n          labels[i].classList.remove(\"gone\");\n        } else {\n          labels[i].classList.add(\"gone\");\n        }\n      }\n    }\n\n    for (let i = 0; i < inputs.length; i++) {\n      if (inputs[i].dataset.helps) {\n        \/\/ are there any words in common between selectedtypes and helps?\n        if (selectedTypesArray.some(type => inputs[i].dataset.helps.includes(type))) {\n          inputs[i].classList.remove(\"gone\");\n        } else {\n          inputs[i].classList.add(\"gone\");\n        }\n      }\n    }\n\n\n    \/\/iterate over each column and set the readOnly and disabled attributes\n    var columns = element.closest(\".inputLossGroup\").querySelectorAll(\".lossColumn\");\n\n    for (var i = 0; i < columns.length; i++) {\n      \/\/find which type is selected\n      var selectedType = columns[i].querySelector(\"input[type='radio']:checked\");\n      if (selectedType) {\n        selectedType = selectedType.value;\n      } else {\n        selectedType = null;\n      }\n\n      var columnInputs = columns[i].querySelectorAll(`input.helper`);\n      for (var j = 0; j < columnInputs.length; j++) {\n        let helps = columnInputs[j].dataset.helps;\n        if (helps && helps.includes(selectedType)) {\n          columnInputs[j].readOnly = false;\n          columnInputs[j].disabled = false;\n        } else {\n          columnInputs[j].readOnly = true;\n          columnInputs[j].disabled = true;\n          columnInputs[j].value = \"\";\n          columnInputs[j].dataset.value = \"\";\n          columnInputs[j].classList.remove(\"error\");\n        }\n      }\n    }\n\n    handleNaturalConvectionHelperChange(element);\n  }\n\n  function handleNaturalConvectionHelperChange(element) {\n    \/\/handle the whole column\n    let column = element.closest(\".lossColumn\");\n    let inputs = column.querySelectorAll(\"input.helper\");\n    let errors = [];\n\n    for (let i = 0; i < inputs.length; i++) {\n      let isError;\n      if (inputs[i].value && isNaN(Number(inputs[i].value))) {\n        isError = true;\n      } else if (inputs[i].value && !isNaN(Number(inputs[i].value))) {\n        isError = false;\n      } else if (inputs[i].disabled) {\n        isError = false;\n      } else {\n        isError = true;\n      }\n\n      if (isError) {\n        inputs[i].classList.add(\"error\");\n        errors.push(inputs[i]);\n      } else {\n        inputs[i].classList.remove(\"error\");\n      }\n    }\n\n    if (errors.length > 0) {\n      column.querySelector(\".characteristicLength\").value = \"\";\n      column.querySelector(\".characteristicLength\").dataset.value = \"\";\n    } else {\n      \/\/ try to calculate the charactistic length\n      let characteristicLength;\n      let longestSide, height, radius, area, perimeter;\n      const type = column.querySelector(\"input[type='radio']:checked\");\n      if (!type) {\n        characteristicLength = \"\";\n      } else if (type.value === 'rectangular-block') {\n        longestSide = Number(column.querySelector(\".helperLongestSide\").value);\n        height = Number(column.querySelector(\".helperHeight\").value);\n        characteristicLength = (longestSide * height) \/ (longestSide + height);\n      } else if (type.value === \"vertical-cylinder\" || type.value === \"vertical-plate\") {\n        height = Number(column.querySelector(\".helperHeight\").value);\n        characteristicLength = height;\n      } else if (type.value === \"horizontal-cylinder\") {\n        radius = Number(column.querySelector(\".helperRadius\").value);\n        characteristicLength = 2 * radius;\n      } else if (type.value === \"horizontal-plate-facing-up\" || type.value === \"horizontal-plate-facing-down\") {\n        area = Number(column.querySelector(\".helperArea\").value);\n        perimeter = Number(column.querySelector(\".helperPerimeter\").value);\n        characteristicLength = (4 * area) \/ perimeter;\n      } else {\n        alert(\"Not implemented: \" + type.value + \".\");\n        characteristicLength = \"\";\n      }\n\n      if (isNaN(characteristicLength)) {\n        characteristicLength = \"\";\n      }\n      if (characteristicLength) {\n        column.querySelector(\".characteristicLength\").value = characteristicLength.toFixed(2);\n      } else {\n        column.querySelector(\".characteristicLength\").value = \"\";\n      }\n      column.querySelector(\".characteristicLength\").dataset.value = characteristicLength;\n\n    }\n\n    updateSpecificLoss(element);\n  }\n\n  function handleCommonInput(element) {\n    var form = element.closest(\".lossForm[data-type='common']\")\n    var unknownError = false;\n\n    var errors = getLossInputErrors(form);\n\n    if (form.querySelector(\".finalTemperature\").value && form.querySelector(\".ambientTemperature\").value) {\n      if (Number(form.querySelector(\".finalTemperature\").value) === Number(form.querySelector(\".ambientTemperature\").value)) {\n        errors.push(form.querySelector(\".finalTemperature\"));\n        errors.push(form.querySelector(\".ambientTemperature\"));\n      }\n    }\n\n    let inputs = form.querySelectorAll(\"input\");\n    inputs = Array.from(inputs).filter(input => !input.classList.contains(\"lossNameInput\"));\n    processInputs(inputs, errors); \/\/ adds error class, updates dataset.value, dispatches events\n\n    return errors.length === 0 && !unknownError;\n  }\n\n  function isLocalNetwork(hostname = window.location.hostname) {\n    \/\/Not perfect, but isn't being used for anything security related, and is only being used for initial issue classification\n    return (\n      (['localhost', '127.0.0.1', '', '::1'].includes(hostname))\n      || (hostname.startsWith('192.168.'))\n      || (hostname.startsWith('10.0.'))\n      || (hostname.endsWith('.local'))\n    )\n  }\n\n  let env;\n  if (isLocalNetwork()) {\n    env = \"development\";\n  } else {\n    env = \"production\";\n  }\n\n  const ambientTemperatureInput = document.querySelector(\"#ambientTemperature\");\n  const finalTemperatureInput = document.querySelector(\"#finalTemperature\");\n\n  ambientTemperatureInput.addEventListener(\"fancyChange\", function () {\n    updateWarmUpHeatLoss()\n\n  });\n  finalTemperatureInput.addEventListener(\"fancyChange\", function () {\n    updateWarmUpHeatLoss()\n  });\n\n  function addLossColumn(element) {\n    const lossType = element.dataset.type;\n    var templateColumn = document.querySelector(`.inputLossGroup[data-type=${lossType}] .template > .lossColumn`);\n    const index = templateColumn.closest(\".template\").dataset.index;\n    var clone = templateColumn.cloneNode(true);\n\n    clone.id = lossType + \"Column-\" + index;\n\n    \/\/iterate through the labels and inputs and set the id and name attributes based on the index\n    var inputs = clone.querySelectorAll(\"input\");\n\n    for (var i = 0; i < inputs.length; i++) {\n      inputs[i].setAttribute(\"name\", inputs[i].getAttribute(\"name\") + \"-\" + index);\n      if (inputs[i].id) {\n        inputs[i].id = inputs[i].id + \"-\" + index;\n      }\n    }\n\n    var labels = clone.querySelectorAll(\"label\");\n    for (var i = 0; i < labels.length; i++) {\n      if (labels[i].htmlFor) {\n        labels[i].htmlFor = labels[i].htmlFor + \"-\" + index;\n      }\n    }\n\n    templateColumn.closest(\".template\").dataset.index++;\n\n    const ambientTemperatureInput = document.querySelector(\"#ambientTemperature\");\n    const finalTemperatureInput = document.querySelector(\"#finalTemperature\");\n\n    if (lossType === \"conductiveLoss\") {\n      \/\/add subscription to ambient temperature common input\n      ambientTemperatureInput.addEventListener(\"fancyChange\", function () {\n        updateSpecificLossById(clone.id)\n      });\n      \/\/ updateSpecificLoss(inputs[1]);\n    } else if (lossType === \"radiationLoss\") {\n      ambientTemperatureInput.addEventListener(\"fancyChange\", function () {\n        updateSpecificLossById(clone.id)\n      });\n      finalTemperatureInput.addEventListener(\"fancyChange\", function () {\n        updateSpecificLossById(clone.id)\n      });\n      \/\/ updateSpecificLoss(inputs[1]);\n    } else if (lossType === \"naturalConvectionLoss\") {\n      ambientTemperatureInput.addEventListener(\"fancyChange\", function () {\n        updateSpecificLossById(clone.id)\n      });\n      finalTemperatureInput.addEventListener(\"fancyChange\", function () {\n        updateSpecificLossById(clone.id)\n      });\n      \/\/ updateSpecificLoss(inputs[1]);\n    } else if (lossType === \"forcedAirConvectionLoss\") {\n      ambientTemperatureInput.addEventListener(\"fancyChange\", function () {\n        updateSpecificLossById(clone.id)\n      });\n      finalTemperatureInput.addEventListener(\"fancyChange\", function () {\n        updateSpecificLossById(clone.id)\n      });\n      \/\/ updateSpecificLoss(inputs[1]);\n    } else if (lossType === \"processHeatLoss\") {\n      \/\/ updateSpecificLoss(inputs[1]);\n      addToggletipHandlers(clone);\n    } else {\n      \/\/alert\n      alert(\"Not implemented: \" + lossType + \".\");\n    }\n\n    \/\/add the clone to the DOM\n    document.querySelector(`.inputLossGroup[data-type=\"${lossType}\"] .lossFormBody`).appendChild(clone);\n  }\n\n  function updateLossTotals(lossType) {\n    let lossForms;\n    if (lossType === \"conductiveLoss\") {\n      lossForms = document.querySelectorAll(\".inputLossGroup[data-type=conductiveLoss] .lossFormBody .lossColumn\");\n    } else if (lossType === \"radiationLoss\") {\n      lossForms = document.querySelectorAll(\".inputLossGroup[data-type=radiationLoss] .lossFormBody .lossColumn\");\n    } else if (lossType === \"naturalConvectionLoss\") {\n      lossForms = document.querySelectorAll(\".inputLossGroup[data-type=naturalConvectionLoss] .lossFormBody .lossColumn\");\n    } else if (lossType === \"forcedAirConvectionLoss\") {\n      lossForms = document.querySelectorAll(\".inputLossGroup[data-type=forcedAirConvectionLoss] .lossFormBody .lossColumn\");\n    } else if (lossType === \"processHeatLoss\") {\n      lossForms = document.querySelectorAll(\".inputLossGroup[data-type=processHeatLoss] .lossFormBody .lossColumn\");\n    } else if (lossType === \"warmUpHeatLoss\") {\n      lossForms = document.querySelectorAll(\".inputLossGroup[data-type=warmUpHeatLoss] .lossFormBody .lossColumn\");\n    } else {\n      alert(\"Not implemented: \" + lossType + \".\");\n    }\n\n    updateSpecificLossTotals(lossForms, lossType);\n    if (lossType !== \"warmUpHeatLoss\") {\n      refreshWarmUpHeatLoss();\n    }\n  }\n\n  function getLossInputErrors(column) {\n    \/\/return list of errors for a column\n    var errors = [];\n    var inputs = column.querySelectorAll(\"input:not(.helper):not([type='radio'])\");\n    for (var i = 0; i < inputs.length; i++) {\n      const input = inputs[i];\n\n      \/\/is it the name input?\n      if (input.classList.contains(\"referenceId\") || input.classList.contains(\"lossResult\")) {\n        continue;\n      }\n\n      if (input.classList.contains(\"stateChangeHeat\") && (input.value.length === 0 || input.value === \"n\/a\")) {\n        continue; \/\/ State change heat is optional\n      }\n\n      if (input.classList.contains(\"oppositeSurfaceTemperature\") && (input.value.length === 0)) {\n        continue; \/\/ Conductive opposite surface temperature is optional\n      }\n\n      if (Number.isNaN(Number(input.value)) || input.value.length === 0) {\n        errors.push(input);\n      }\n    }\n    return errors;\n  }\n\n  function checkCommonInputVariable(selector) {\n    const block = document.querySelector(\"#commonInputs\");\n    var element = block.querySelector(selector);\n    if (element.dataset.value) {\n      return element.dataset.value;\n    }\n  }\n\n  function processInputs(inputs, errors) {\n    for (const input of inputs) {\n      if (input.classList.contains(\"referenceId\") || input.classList.contains(\"lossResult\")) {\n        continue;\n      }\n\n      const oldValue = input.dataset.value;\n      let newValue;\n      if (input.classList.contains(\"stateChangeHeat\") && (input.value.length === 0 || input.value === \"n\/a\")) {\n        newValue = 0;\n        input.classList.remove(\"error\");\n      } else if (input.classList.contains(\"oppositeSurfaceTemperature\") && input.value.length === 0 ) {\n        newValue = \"\";\n        input.classList.remove(\"error\");\n      } else if (errors.includes(input)) {\n        input.classList.add(\"error\");\n        newValue = \"\"; \/\/ false?\n      } else {\n        input.classList.remove(\"error\");\n        newValue = Number(input.value).toString();\n      }\n      input.dataset.value = newValue;\n\n      if (oldValue !== newValue) {\n        input.dispatchEvent(new CustomEvent('fancyChange', {detail: newValue}));\n      }\n    }\n  }\n\n  function checkLossInputs(column) {\n    \/\/ Get the ancestor .inputLossGroup, and look for its data-type\n    const lossType = column.closest(\".inputLossGroup\").dataset.type;\n\n    switch (lossType) {\n      case \"conductiveLoss\":\n        return checkConductiveLossInputs(column);\n      case \"radiationLoss\":\n        return checkRadiationLossInputs(column);\n      case \"naturalConvectionLoss\":\n        return checkNaturalConvectionLossInputs(column);\n      case \"forcedAirConvectionLoss\":\n        return checkForcedAirConvectionLossInputs(column);\n      case \"processHeatLoss\":\n        return checkProcessHeatLossInputs(column);\n      default:\n        alert(\"Not implemented: \" + lossType + \".\");\n    }\n  }\n\n  function calculateLoss(column) {\n    const lossType = column.closest(\".inputLossGroup\").dataset.type;\n    switch (lossType) {\n      case \"conductiveLoss\":\n        return calculateConductiveLoss(column);\n      case \"radiationLoss\":\n        return calculateRadiationLoss(column);\n      case \"naturalConvectionLoss\":\n        return calculateNaturalConvectionLoss(column);\n      case \"forcedAirConvectionLoss\":\n        return calculateForcedAirConvectionLoss(column);\n      case \"processHeatLoss\":\n        return calculateProcessHeatLoss(column);\n      default:\n        alert(\"Not implemented: \" + lossType + \".\");\n    }\n  }\n\n  function checkConductiveLossInputs(column) {\n    var unknownError = false;\n\n    var errors = getLossInputErrors(column);\n\n    \/\/ make sure the common variables we need are in place\n    if (!checkCommonInputVariable(\".ambientTemperature\")) {\n      errors.push(document.querySelector(\".ambientTemperature\"));\n    }\n\n    if (column.querySelector(\".conductivePathLength\").value) {\n      if (Number(column.querySelector(\".conductivePathLength\").value) === 0) {\n        errors.push(column.querySelector(\".conductivePathLength\"));\n      }\n    }\n\n    if (errors.length === 0) {\n      \/\/Try it and see!\n      var loss = calculateConductiveLoss(column);\n      if (Number.isNaN(loss)) {\n        unknownError = true;\n      }\n    }\n\n    let inputs = column.querySelectorAll(\"input\");\n    inputs = Array.from(inputs).filter(input => !input.classList.contains(\"referenceId\"));\n    processInputs(inputs, errors); \/\/ adds error class, updates dataset.value, dispatches events\n\n    return errors.length === 0 && !unknownError;\n  }\n\n  function checkRadiationLossInputs(column) {\n    var unknownError = false;\n\n    var errors = getLossInputErrors(column);\n\n    let ambientTemperature;\n    if (!checkCommonInputVariable(\".ambientTemperature\")) {\n      errors.push(document.querySelector(\".ambientTemperature\"));\n    } else {\n      ambientTemperature = Number(document.querySelector(\".ambientTemperature\").dataset.value);\n    }\n\n    if (errors.length === 0) {\n      \/\/Try it and see!\n      var loss = calculateRadiationLoss(column);\n      if (Number.isNaN(loss)) {\n        unknownError = true;\n      }\n    }\n\n    let inputs = column.querySelectorAll(\"input\");\n    inputs = Array.from(inputs).filter(input => !input.classList.contains(\"referenceId\"));\n    processInputs(inputs, errors); \/\/ adds error class, updates dataset.value, dispatches events\n\n    return errors.length === 0 && !unknownError;\n  }\n\n  function checkNaturalConvectionLossInputs(column) {\n    var unknownError = false;\n\n    var errors = getLossInputErrors(column);\n\n    let ambientTemperature;\n    if (!checkCommonInputVariable(\".ambientTemperature\")) {\n      errors.push(document.querySelector(\".ambientTemperature\"));\n    } else {\n      ambientTemperature = Number(document.querySelector(\".ambientTemperature\").dataset.value);\n    }\n\n    if (errors.length === 0) {\n      \/\/Try it and see!\n      var loss = calculateNaturalConvectionLoss(column);\n      if (Number.isNaN(loss)) {\n        unknownError = true;\n      }\n    }\n\n    let inputs = column.querySelectorAll(\"input:not([type=radio]):not(.helper)\");\n    inputs = Array.from(inputs).filter(input => !input.classList.contains(\"referenceId\"));\n    processInputs(inputs, errors); \/\/ adds error class, updates dataset.value, dispatches events\n\n    return errors.length === 0 && !unknownError;\n  }\n\n  function checkForcedAirConvectionLossInputs(column) {\n    var unknownError = false;\n\n    var errors = getLossInputErrors(column);\n\n    let ambientTemperature;\n    if (!checkCommonInputVariable(\".ambientTemperature\")) {\n      errors.push(document.querySelector(\".ambientTemperature\"));\n    } else {\n      ambientTemperature = Number(document.querySelector(\".ambientTemperature\").dataset.value);\n    }\n\n    if (column.querySelector(\".airVelocity\").value && column.querySelector(\".sideLength\").value) {\n      if (Number(column.querySelector(\".airVelocity\").value) < 0) {\n        errors.push(column.querySelector(\".airVelocity\"));\n      }\n      if (Number(column.querySelector(\".sideLength\").value) < 0) {\n        errors.push(column.querySelector(\".sideLength\"));\n      }\n    }\n\n    if (errors.length === 0) {\n      \/\/Try it and see!\n      var loss = calculateForcedAirConvectionLoss(column);\n      if (Number.isNaN(loss)) {\n        unknownError = true;\n      }\n    }\n\n    let inputs = column.querySelectorAll(\"input\");\n    inputs = Array.from(inputs).filter(input => !input.classList.contains(\"referenceId\"));\n    processInputs(inputs, errors); \/\/ adds error class, updates dataset.value, dispatches events\n\n    return errors.length === 0 && !unknownError;\n  }\n\n  function checkProcessHeatLossInputs(column) {\n    var unknownError = false;\n\n    var errors = getLossInputErrors(column);\n\n    if (column.querySelector(\".cycleTime\").value) {\n      if (Number(column.querySelector(\".cycleTime\").value) === 0) {\n        errors.push(column.querySelector(\".cycleTime\"));\n      }\n    }\n\n    if (errors.length === 0) {\n      \/\/Try it and see!\n      var loss = calculateProcessHeatLoss(column);\n      if (Number.isNaN(loss)) {\n        unknownError = true;\n      }\n    }\n\n    let inputs = column.querySelectorAll(\"input\");\n    inputs = Array.from(inputs).filter(input => !input.classList.contains(\"referenceId\"));\n    processInputs(inputs, errors); \/\/ adds error class, updates dataset.value, dispatches events\n\n    return errors.length === 0 && !unknownError;\n  }\n\n  function checkWarmUpHeatLossInputs(column) {\n    var unknownError = false;\n\n    var errors = getLossInputErrors(column);\n\n    let ambientTemperature;\n    if (!checkCommonInputVariable(\".ambientTemperature\")) {\n      errors.push(document.querySelector(\"#ambientTemperature\"));\n    } else {\n      ambientTemperature = Number(document.querySelector(\"#ambientTemperature\").dataset.value);\n    }\n\n    let finalTemperature;\n    if (!checkCommonInputVariable(\".finalTemperature\")) {\n      errors.push(document.querySelector(\"#finalTemperature\"));\n    } else {\n      finalTemperature = Number(document.querySelector(\"#finalTemperature\").dataset.value);\n    }\n\n    \/\/ TODO don't let final and ambient be equal  for division reasons, maybe? but we gotta dot hat back up in common\n    \/\/ if (finalTemperature && ambientTemperature) {\n    \/\/     if (finalTemperature === ambientTemperature) {\n    \/\/         errors.push(form.querySelector(\".finalTemperature\"));\n    \/\/     }\n    \/\/ }\n\n    if (finalTemperature && column.querySelector(\".initialTemperature\").dataset.value) {\n      if (finalTemperature === Number(column.querySelector(\".initialTemperature\").value)) {\n        errors.push(column.querySelector(\".initialTemperature\"));\n      }\n    }\n\n    let materialSpecificHeat = null;\n    let materialSpecificHeatInput = column.querySelector(\".materialSpecificHeat\");\n    if (materialSpecificHeatInput.value && errors.indexOf(materialSpecificHeatInput) === -1) {\n      materialSpecificHeat = Number(column.querySelector(\".materialSpecificHeat\").dataset.value);\n    }\n\n    if (column.querySelector(\".mass\").value && materialSpecificHeat) {\n      if (Number(column.querySelector(\".mass\").value) === 0) {\n        errors.push(column.querySelector(\".mass\"));\n      }\n    }\n\n    if (getSteadyStateLoss() === null || getSteadyStateLoss() === undefined || getSteadyStateLoss() === \"\") {\n      errors.push(column.querySelector(\".steadyStateLoss\"));\n    }\n\n    if (errors.length === 0) {\n      \/\/Try it and see!\n      var loss = calculateWarmUpHeatLoss(column);\n      if (Number.isNaN(loss)) {\n        unknownError = true;\n      }\n    }\n\n    let inputs = column.querySelectorAll(\"input\");\n    inputs = Array.from(inputs).filter(input => !input.classList.contains(\"referenceId\"));\n    processInputs(inputs, errors); \/\/ adds error class, updates dataset.value, dispatches events\n\n    return errors.length === 0 && !unknownError;\n  }\n\n\n  function handleRounding(input) {\n    \/\/Round to 1 decimal place unless the number is 20+, then round to 0 decimal places\n    if (input < 20) {\n      return Math.round(input * 10) \/ 10;\n    } else {\n      return Math.round(input);\n    }\n  }\n\n  function calculateConductiveLoss(column) {\n    var thermalConductivity = Number(column.querySelector(\".thermalConductivity\").dataset.value);\n    var crossSectionalArea = Number(column.querySelector(\".crossSectionalArea\").dataset.value);\n    var heatsinkTemperature = Number(column.querySelector(\".heatsinkTemperature\").dataset.value);\n    var ambientTemperature = Number(document.querySelector(\"#commonInputs .ambientTemperature\").dataset.value);\n    var conductivePathLength = Number(column.querySelector(\".conductivePathLength\").dataset.value);\n\n    var oppositeSurfaceTemperature;\n    if (column.querySelector(\".oppositeSurfaceTemperature\").value !== \"\") {\n      oppositeSurfaceTemperature = Number(column.querySelector(\".oppositeSurfaceTemperature\").dataset.value);\n    }\n\n    var appropriateTemperature = oppositeSurfaceTemperature ? oppositeSurfaceTemperature : ambientTemperature;\n\n    const conductiveLoss = (thermalConductivity * crossSectionalArea \/ 10000 * (heatsinkTemperature - appropriateTemperature)) \/ (conductivePathLength \/ 1000);\n    return conductiveLoss;\n  }\n\n  function calculateRadiationLoss(column) {\n    \/\/ Assumes all inputs are valid (we just checked them)\n    const emissivity = Number(column.querySelector(\".emissivity\").dataset.value);\n    const exposedSurfaceArea = Number(column.querySelector(\".radExposedSurfaceArea\").dataset.value) * 0.0001;\n    const finalTemperature = Number(document.querySelector(\"#finalTemperature\").dataset.value);\n    var ambientTemperature = Number(document.querySelector(\"#commonInputs .ambientTemperature\").dataset.value);\n\n    const finalTemperatureR = finalTemperature + 273.15;\n    const ambientTemperatureR = ambientTemperature + 273.15;\n\n    const radiationLoss = 5.67037442 * Math.pow(10, -8) * (emissivity * exposedSurfaceArea * (Math.pow(finalTemperatureR, 4) - Math.pow(ambientTemperatureR, 4)));\n\n    return radiationLoss;\n  }\n\n  function calculateNaturalConvectionLoss(column) {\n    \/\/ Assumes all inputs are valid (we just checked them)\n\n    const configurationFactor = Number(column.querySelector(\".configurationFactor\").dataset.value);\n    const finalTemperature = Number(document.querySelector(\"#finalTemperature\").dataset.value);\n    const ambientTemperature = Number(document.querySelector(\"#commonInputs .ambientTemperature\").dataset.value);\n    const characteristicLength = Number(column.querySelector(\".characteristicLength\").dataset.value);\n    const exposedSurfaceArea = Number(column.querySelector(\".nExposedSurfaceArea\").dataset.value);\n    const averageTemperature = (finalTemperature - ambientTemperature) \/ 2;\n    const h = 0.3205 * configurationFactor * Math.pow(((finalTemperature - ambientTemperature) * 9 \/ 5) \/ (characteristicLength \/ 30.48), 0.25) * Math.pow(2.716, -1 * averageTemperature * (9.0 \/ 5.0) \/ 2900);\n    const naturalConvectionLoss = (h * exposedSurfaceArea * (finalTemperature - ambientTemperature) * 1.8) \/ 3.412 \/ 929.03;\n\n    return naturalConvectionLoss;\n  }\n\n  function calculateForcedAirConvectionLoss(column) {\n    \/\/ Assumes all inputs are valid (we just checked them)\n    const airVelocity = Number(column.querySelector(\".airVelocity\").dataset.value);\n    const sideLength = Number(column.querySelector(\".sideLength\").dataset.value);\n    const finalTemperature = Number(document.querySelector(\"#finalTemperature\").dataset.value);\n    const ambientTemperature = Number(document.querySelector(\"#commonInputs .ambientTemperature\").dataset.value);\n    const exposedSurfaceArea = Number(column.querySelector(\".faExposedSurfaceArea\").dataset.value);\n    const h = 0.0675 * Math.sqrt((airVelocity * 100) \/ sideLength);\n    const forcedAirConvectionLoss = (h * exposedSurfaceArea * (finalTemperature - ambientTemperature) * 1.8) \/ 3.412 \/ 929.03;\n\n    return forcedAirConvectionLoss;\n  }\n\n\n  function calculateProcessHeatLoss(column) {\n    \/\/ Assumes all inputs are valid (we just checked them)\n    const materialMass = Number(column.querySelector(\".materialMass\").dataset.value);\n    const cycleTime = Number(column.querySelector(\".cycleTime\").dataset.value);\n    const materialSpecificHeat = Number(column.querySelector(\".materialSpecificHeat\").dataset.value);\n    const stateChangeHeat = Number(column.querySelector(\".stateChangeHeat\").dataset.value);\n    const finalMaterialTemperature = Number(column.querySelector(\".finalMaterialTemperature\").dataset.value);\n    const initialMaterialTemperature = Number(column.querySelector(\".initialMaterialTemperature\").dataset.value);\n\n    const processHeatLoss = (materialSpecificHeat \/ 1000 * materialMass * (finalMaterialTemperature - initialMaterialTemperature) + stateChangeHeat * materialMass) \/ cycleTime;\n    return processHeatLoss;\n  }\n\n\n  function calculateWarmUpHeatLoss(column) {\n    \/\/ Assumes all inputs are valid (we just checked them)\n    const mass = Number(column.querySelector(\".mass\").dataset.value);\n    const materialSpecificHeat = Number(column.querySelector(\".materialSpecificHeat\").dataset.value);\n    const finalTemperature = Number(document.querySelector(\"#finalTemperature\").dataset.value);\n    const initialTemperature = Number(column.querySelector(\".initialTemperature\").dataset.value);\n    const ambientTemperature = Number(document.querySelector(\"#commonInputs .ambientTemperature\").dataset.value);\n    const warmUpTime = Number(column.querySelector(\".warmUpTime\").value);\n\n    const steadyStateLoss = getSteadyStateLoss();\n    const warmUpCoefficient = steadyStateLoss \/ (finalTemperature - ambientTemperature);\n    if (warmUpCoefficient === 0) {\n      return 0;\n    }\n    const warmUpHeatLoss = (warmUpCoefficient * (finalTemperature - initialTemperature)) \/ (1 - Math.exp((-1 * warmUpCoefficient * warmUpTime * 60) \/ (mass * materialSpecificHeat \/ 1000))) + (warmUpCoefficient * (initialTemperature - ambientTemperature))\n    return warmUpHeatLoss;\n  }\n\n  function getSteadyStateLoss() {\n    \/\/sum up the conductive heat loss total and the radiation loss total and the natural convection loss total and the forced air convection loss total\n\n    var total = 0;\n\n    const lossTypes = [\"conductiveLoss\", \"radiationLoss\", \"naturalConvectionLoss\", \"forcedAirConvectionLoss\"];\n    let anyErrors = false;\n\n    for (const lossType of lossTypes) {\n      const totalElement = getResultsElement(lossType);\n      const lossText = totalElement.dataset.loss;\n\n      if (totalElement.dataset.lossError === \"true\" || totalElement.dataset.loss === undefined || totalElement.dataset.loss === \"\") {\n        anyErrors = true;\n      }\n\n      if (lossText) {\n        const loss = Number(lossText);\n        total += loss;\n      }\n    }\n\n    if (anyErrors) {\n      return null;\n    } else {\n      return total;\n    }\n  }\n\n  function updateSpecificLossById(id) {\n    updateSpecificLoss(document.querySelector(`#${id}`));\n  }\n\n  function updateSpecificLoss(element) {\n    var column = element.closest(\".lossColumn\");\n    if (column === null) {\n      return;\n    }\n\n    const lossType = column.closest(\".inputLossGroup\").dataset.type;\n\n    \/\/ Is the column valid?\n    const allValid = checkLossInputs(column);\n\n    \/\/ Is the column completely blank?\n    let isBlank = true;\n    for (const input of column.querySelectorAll(\"input:not([type=radio]):not(.helper)\")) {\n      if (input.value) {\n        isBlank = false;\n        break;\n      }\n    }\n    column.dataset.blank = isBlank.toString();\n\n    var loss = \"\";\n\n    if (allValid) {\n      loss = calculateLoss(column);\n    }\n\n    const isError = (!allValid && !isBlank);\n    setLoss(column.querySelector(\".lossResult\"), loss, isError, isError || loss === \"\", !(isError || loss === \"\"));\n    column.dataset.loss = loss;\n    if (isError && !isBlank) {\n      column.dataset.lossError = \"true\";\n    } else {\n      column.dataset.lossError = \"false\";\n    }\n\n    updateLossTotals(lossType);\n    updateResultsBox();\n  }\n\n  function getResultsElement(lossType) {\n    const calculatedBox = document.querySelector(`.newResults input[data-type='${lossType}'].calculated`);\n    const overrideCheckbox = document.querySelector(`.newResults input[data-type='${lossType}'][type='checkbox']`);\n    const overrideValueBox = document.querySelector(`.newResults input[data-type='${lossType}'].overrideValue`);\n\n    if (overrideCheckbox && overrideCheckbox.checked) {\n      return overrideValueBox;\n    } else {\n      return calculatedBox;\n    }\n  }\n\n  function updateResultsBox() {\n    \/\/ The lossTotal boxes have been filled out, but that's it.\n    updateOperatingHeat();\n    \/\/ We have the buffer and minimum wattage to fill out\n\n    let warmUpLoss = \"\";\n    const warmUpLossText = getResultsElement('warmUpHeatLoss').dataset.loss;\n    if (warmUpLossText) {\n      warmUpLoss = Number(warmUpLossText);\n    }\n\n    let operatingHeat = \"\";\n    const operatingHeatText = getResultsElement('operatingHeatLoss').dataset.loss;\n    if (operatingHeatText) {\n      operatingHeat = Number(operatingHeatText);\n    }\n\n    let bufferText = \"\";\n    let minimumWattageText = \"\";\n\n    if (warmUpLoss && operatingHeat) {\n      const largerLoss = Math.max(warmUpLoss, operatingHeat);\n      const buffer = largerLoss * 0.1;\n      bufferText = handleRounding(buffer);\n\n      const minimumWattage = largerLoss + buffer;\n      minimumWattageText = handleRounding(minimumWattage);\n    }\n    document.querySelector(\".newResults .bufferTotal\").value = bufferText;\n    document.querySelector(\".newResults .minimumHeaterWattage\").value = minimumWattageText;\n  }\n\n  function toggleOverride(element) {\n    \/\/ if it is now checked, then we need to cross out the calculated value and unhide the override value\n    const calculatedBox = element.previousElementSibling;\n    const overrideValueBox = element.nextElementSibling;\n\n    if (element.checked) {\n      calculatedBox.classList.add(\"crossedOut\");\n      overrideValueBox.classList.remove(\"hidden\");\n    } else {\n      calculatedBox.classList.remove(\"crossedOut\");\n      overrideValueBox.classList.add(\"hidden\");\n    }\n\n    updateOverride(document.querySelector(`.newResults input[data-type=${element.dataset.type}].overrideValue`));\n\n    if (element.dataset.type === \"operatingHeatLoss\") {\n    } else if (element.dataset.type === \"warmUpHeatLoss\") {\n      updateWarmUpHeatLoss();\n    } else {\n      updateLossTotals(element.dataset.type);\n    }\n\n    updateResultsBox();\n  }\n\n  function updateWarmUpHeatLoss() {\n    \/\/ This method is for handling text entries in the warmup column\n\n    refreshWarmUpHeatLoss();\n\n    \/\/ update the result directly\n    updateResultsBox();\n  }\n\n  function refreshWarmUpHeatLoss() {\n    \/\/ This method does not cascade to update the rest of the refreshbox, outside of loss totals\n    var column = document.querySelector(\".lossColumn[data-type='warmUpHeatLoss']\");\n\n    const allValid = checkWarmUpHeatLossInputs(column);\n\n    var loss = \"\";\n    var textValue = \"\";\n\n    if (allValid) {\n      loss = calculateWarmUpHeatLoss(column);\n      if (Number.isNaN(loss)) {\n        return;\n      }\n      textValue = handleRounding(loss);\n    }\n\n    var resultBox = column.querySelector(\".lossResult\");\n\n    if (textValue) {\n      resultBox.classList.remove(\"hidden\");\n      column.dataset.loss = loss;\n      column.dataset.lossError = \"false\";\n      resultBox.value = textValue;\n    } else {\n      resultBox.classList.add(\"hidden\");\n      column.dataset.loss = \"\";\n      column.dataset.lossError = \"true\";\n      resultBox.value = \"\";\n    }\n\n    updateLossTotals(\"warmUpHeatLoss\");\n  }\n\n\n  function updateSpecificLossTotals(lossForms, lossType) {\n    \/\/ lossType should be like \"conductiveLoss\"\n\n    \/\/Updates results section\n    var lossTotal = 0;\n\n    var anyError = false;\n\n    var allBlank = true;\n\n    for (var i = 0; i < lossForms.length; i++) {\n      var lossForm = lossForms[i];\n      var loss = lossForm.dataset.loss;\n      var lossError = lossForm.dataset.lossError === \"true\";\n      var blank = lossForm.dataset.loss === undefined || lossForm.dataset.loss === \"\" || lossForm.dataset.blank === \"true\";\n\n      if (!blank) {\n        allBlank = false;\n      }\n\n      if (lossError) {\n        anyError = true;\n      }\n\n      if (loss && !lossError) {\n        lossTotal += Number(loss);\n      }\n    }\n\n    var textTotal;\n\n    \/\/ Because the user can override the loss, we are going to put the rounded loss here, so that\n    \/\/ there aren't discrepancies when they override a box saying 55 with a 55\n\n    lossTotal = handleRounding(lossTotal);\n\n    if (allBlank || anyError || lossForms.length === 0) {\n      textTotal = \"\";\n    } else {\n      textTotal = lossTotal;\n    }\n\n    \/\/update the total in the results section\n    const box = document.querySelector(`.newResults input[data-type=${lossType}]`);\n    if (anyError) {\n      box.classList.add(\"error\");\n      box.dataset.lossError = \"true\";\n    } else {\n      box.classList.remove(\"error\");\n      box.dataset.lossError = \"false\";\n    }\n\n    box.value = textTotal;\n    box.dataset.loss = lossTotal;\n  }\n\n  function setLoss(element, value, error = null, makeBlank = null, show = null) {\n    if (error !== null) {\n      if (error) {\n        element.classList.add(\"error\");\n        element.dataset.lossError = \"true\";\n        element.value = \"\";\n        element.dataset.loss = \"\";\n      } else {\n        element.classList.remove(\"error\");\n        element.dataset.lossError = \"false\";\n        element.value = handleRounding(value);\n        element.dataset.loss = value.toString();\n      }\n    }\n\n    if (makeBlank !== null) {\n      if (makeBlank) {\n        element.value = \"\";\n        element.dataset.loss = \"\";\n      }\n    }\n\n    if (show !== null) {\n      if (show) {\n        element.classList.remove(\"hidden\");\n      } else {\n        element.classList.add(\"hidden\");\n      }\n    }\n  }\n\n  function updateOperatingHeat() {\n    const lossTypes = [\"conductiveLoss\", \"radiationLoss\", \"naturalConvectionLoss\", \"forcedAirConvectionLoss\", \"processHeatLoss\"];\n    \/\/ not warmup\n\n    let anyErrors = false;\n    let allBlank = true;\n    let total = 0;\n    for (const lossType of lossTypes) {\n      const totalInput = getResultsElement(lossType); \/\/document.querySelector(`.newResults input[data-type=${lossType}]`);\n\n      if (totalInput.dataset.lossError === \"true\") {\n        anyErrors = true;\n      }\n\n      if (totalInput.dataset.loss !== undefined && totalInput.dataset.loss !== \"\" && totalInput.value !== \"\") {\n        allBlank = false;\n      }\n\n      total += Number(totalInput.dataset.loss);\n    }\n\n    setLoss(document.querySelector(\".newResults input.operatingHeatTotal\"), total, anyErrors, allBlank);\n  }\n\n  function updateOverride(element) {\n    const newValue = Number(element.value);\n    if (Number.isNaN(newValue) || element.value.length === 0) {\n      element.classList.add(\"error\");\n      element.dataset.lossError = \"true\";\n      element.dataset.loss = \"\";\n    } else {\n      element.classList.remove(\"error\");\n      element.dataset.lossError = \"false\";\n      element.dataset.loss = newValue.toString();\n    }\n\n    refreshWarmUpHeatLoss();\n    updateResultsBox();\n  }\n\n  function csvValue(element) {\n    if (!element) {\n      return \"\";\n    }\n\n    if (element.dataset.lossError === \"true\" || element.classList.contains(\"error\")) {\n      return \"\";\n    } else {\n      return element.value;\n    }\n  }\n\n  function exportCSV() {\n\n    var categories = {\n      \"Conductive Loss\": {\n        order: 2,\n        columns: document.querySelectorAll(\".lossFormBody .lossColumn[data-type=conductiveLoss]\")\n      },\n      \"Radiation Loss\": {\n        order: 3,\n        columns: document.querySelectorAll(\".lossFormBody .lossColumn[data-type=radiationLoss]\")\n      },\n      \"Natural Convection Loss\": {\n        order: 4,\n        columns: document.querySelectorAll(\".lossFormBody .lossColumn[data-type=naturalConvectionLoss]\")\n      },\n      \"Forced Air Convection Loss\": {\n        order: 5,\n        columns: document.querySelectorAll(\".lossFormBody .lossColumn[data-type=forcedAirConvectionLoss]\")\n      },\n      \"Process Heat Loss\": {\n        order: 6,\n        columns: document.querySelectorAll(\".lossFormBody .lossColumn[data-type=processHeatLoss]\")\n      },\n      \"Warm Up Heat Loss\": {\n        order: 7,\n        columns: document.querySelectorAll(\".lossFormBody .lossColumn[data-type=warmUpHeatLoss]\")\n      },\n    };\n\n    var cols = [[\"Inputs\"]];\n    var col = [];\n    for (let i = 0; i < 2; i++) {\n      col = [document.querySelectorAll('.lossForm[data-type=common] label')[i].innerText.split(\":\")[0],\n        csvValue(document.querySelectorAll(\".lossForm[data-type=common] input\")[i])];\n      cols.push(col);\n    }\n    for (const categoryName of Object.keys(categories)) {\n      cols.push([categoryName]);\n      col = []\n      for (let colLabel of categories[categoryName].columns[0].querySelectorAll(\"input:not([type=radio]):not(.helper)\")) {\n        let inputName = colLabel.name.split(\"-\")[0];\n        let label = document.querySelector(`label[for=${inputName}]`);\n        if (!label) {\n          label = document.querySelector(`label[data-for=${inputName}]`);\n        }\n\n        if (!label) {\n          console.error(`No label found for ${inputName}`);\n          continue;\n        }\n\n        col = [label.innerText.split(\":\")[0]];\n\n        for (let column of categories[categoryName].columns) {\n          let input = column.querySelector(`input[name^=${inputName}]`);\n          if (input) {\n            col.push(csvValue(input));\n          }\n        }\n        cols.push(col);\n      }\n      cols.push([])\n    }\n\n    cols.push([\"Outputs\"])\n    let minimumHeaterWattageText = document.querySelector(\".newResults label\").innerText.split(\":\")[0];\n    let minimumHeaterWattageValue = csvValue(document.querySelector(\"input.minimumHeaterWattage.calculated\"));\n    col = [minimumHeaterWattageText, minimumHeaterWattageValue]\n    cols.push(col);\n\n    let labelsOfOverrideables = document.querySelectorAll(\".newResults label\");\n\n    for (let i = 1; i < labelsOfOverrideables.length; i++) {\n      let overrideableLabel = labelsOfOverrideables[i];\n      let overrideableText = overrideableLabel.innerText.split(\":\")[0];\n      let calculatedBox = overrideableLabel.nextElementSibling;\n      let calculatedValue = csvValue(calculatedBox);\n      col = [overrideableText, calculatedValue];\n      cols.push(col);\n\n      if (i !== labelsOfOverrideables.length - 1) { \/\/the last one, buffer, isn't overrideable\n        let overriddenText = overrideableText + \" [OVERRIDDEN]\"\n        let overrideCheckbox = calculatedBox.nextElementSibling;\n        let overrideBox = overrideCheckbox.nextElementSibling;\n        let overrideValue = \"\";\n        if (overrideCheckbox.checked) {\n          overrideValue = csvValue(overrideBox);\n        }\n        col = [overriddenText, overrideValue];\n        cols.push(col);\n      }\n    }\n\n    let rows = transposeArray(cols, 4);\n\n    downloadCSV(rows, \"minco-thermal-calc.csv\")\n  }\n\n  function transposeArray(array, arrayLength) {\n    var newArray = [];\n    for (var i = 0; i < arrayLength; i++) {\n      newArray.push([]);\n    }\n\n\n    for (i = 0; i < array.length; i++) {\n      for (var j = 0; j < arrayLength; j++) {\n        let val = array[i][j];\n        if (val === undefined) {\n          val = \"\";\n        }\n        newArray[j].push(val);\n      }\n\n    }\n\n\n    return newArray;\n  }\n\n  function downloadCSV(data, filename) {\n    \/\/ Convert the data to CSV\n    let csv = '';\n    data.forEach((row) => {\n\n      csv += row.join(',');\n      csv += '\\n';\n    });\n\n    \/\/ Create a blob\n    let blob = new Blob([csv], {type: 'text\/csv'});\n\n    \/\/ Create a link\n    let a = document.createElement('a');\n\n    \/\/ Set the link's href to the blob\n    a.href = URL.createObjectURL(blob);\n\n    \/\/ Set the download attribute with the filename\n    a.download = filename;\n\n    \/\/ Append the link to the body\n    document.body.appendChild(a);\n\n    \/\/ Simulate click\n    a.click();\n\n    \/\/ Cleanup the DOM\n    document.body.removeChild(a);\n  }\n\n  function addToggletipHandler(toggletip) {\n    const liveRegion = toggletip.querySelector(\"[role='status']\");\n    const message = toggletip.getAttribute('data-toggletip-content');\n\n    toggletip.addEventListener('click', function () {\n      if (liveRegion.innerHTML !== '') {\n        liveRegion.innerHTML = '';\n\n      } else {\n        window.setTimeout(function () {\n          liveRegion.innerHTML = '<span class=\"toggletip-bubble\">' + message + '<\/span>';\n        }, 100);\n      }\n    });\n  }\n\n  function addToggletipHandlers(section) {\n    var toggletips = section.querySelectorAll('[data-toggletip-content]');\n    if (toggletips) {\n      for (var i = 0; i < toggletips.length; i++) {\n        addToggletipHandler(toggletips[i]);\n      }\n    }\n  }\n\n  for (const section of document.querySelectorAll(\".inputLossGroup\")) {\n    addToggletipHandlers(section);\n  }\n\n  \/* It would be good to bake this first set into the HTML each time there are changes, so we don't get content shift *\/\n  \/\/ iterate 3 times\n  for (let i = 0; i < 3; i++) {\n    addLossColumn(document.querySelector(\".inputLossGroup[data-type=conductiveLoss]\"));\n    addLossColumn(document.querySelector(\".inputLossGroup[data-type=radiationLoss]\"));\n    addLossColumn(document.querySelector(\".inputLossGroup[data-type=naturalConvectionLoss]\"));\n    addLossColumn(document.querySelector(\".inputLossGroup[data-type=forcedAirConvectionLoss]\"));\n    addLossColumn(document.querySelector(\".inputLossGroup[data-type=processHeatLoss]\"));\n  }\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-e2a4f6f elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"e2a4f6f\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-cd530d6\" data-id=\"cd530d6\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-483f129 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"483f129\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-bdb5731\" data-id=\"bdb5731\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Etched-foil heaters have gained significant popularity due to their flexibility, uniform heat distribution, and rapid response times. These heaters consist of a resistive heating element etched onto a thin foil substrate, providing excellent thermal conductivity. Accurate estimation of power requirements is essential for designing the electrical circuitry and ensuring optimal performance of the heating system. [&hellip;]<\/p>\n","protected":false},"featured_media":0,"parent":0,"menu_order":0,"template":"","format":"standard","meta":{"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_links_to":"","_links_to_target":""},"content_type":[],"product":[],"class_list":["post-7081","resources","type-resources","status-publish","format-standard","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Heater Wattage Estimator - Minco<\/title>\n<meta name=\"description\" content=\"This calculator models the conduction, radiation, and convection losses of a heat sink, as well as process heat requirements, to assist you in determining heater wattage needs. Add input values in the appropriate fields below and the calculator will provide an estimate the minimum heater wattage. See the \u201cMinco Heater Wattage Estimator\u201d video for further instruction.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Heater Wattage Estimator - Minco\" \/>\n<meta property=\"og:description\" content=\"This calculator models the conduction, radiation, and convection losses of a heat sink, as well as process heat requirements, to assist you in determining heater wattage needs. Add input values in the appropriate fields below and the calculator will provide an estimate the minimum heater wattage. See the \u201cMinco Heater Wattage Estimator\u201d video for further instruction.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/\" \/>\n<meta property=\"og:site_name\" content=\"Minco\" \/>\n<meta property=\"article:modified_time\" content=\"2024-02-19T18:43:01+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.minco.com\\\/resources\\\/heater-wattage-estimator\\\/\",\"url\":\"https:\\\/\\\/www.minco.com\\\/resources\\\/heater-wattage-estimator\\\/\",\"name\":\"Heater Wattage Estimator - Minco\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.minco.com\\\/#website\"},\"datePublished\":\"2023-09-26T20:09:56+00:00\",\"dateModified\":\"2024-02-19T18:43:01+00:00\",\"description\":\"This calculator models the conduction, radiation, and convection losses of a heat sink, as well as process heat requirements, to assist you in determining heater wattage needs. Add input values in the appropriate fields below and the calculator will provide an estimate the minimum heater wattage. See the \u201cMinco Heater Wattage Estimator\u201d video for further instruction.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.minco.com\\\/resources\\\/heater-wattage-estimator\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.minco.com\\\/resources\\\/heater-wattage-estimator\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.minco.com\\\/resources\\\/heater-wattage-estimator\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.minco.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Heater Wattage Estimator\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.minco.com\\\/#website\",\"url\":\"https:\\\/\\\/www.minco.com\\\/\",\"name\":\"Minco\",\"description\":\"Flex Circuits, Temperature Sensors, Heating Elements and More\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.minco.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.minco.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.minco.com\\\/#organization\",\"name\":\"Minco\",\"url\":\"https:\\\/\\\/www.minco.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.minco.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.minco.com\\\/wp-content\\\/uploads\\\/minco-logo-color.svg\",\"contentUrl\":\"https:\\\/\\\/www.minco.com\\\/wp-content\\\/uploads\\\/minco-logo-color.svg\",\"width\":184,\"height\":44,\"caption\":\"Minco\"},\"image\":{\"@id\":\"https:\\\/\\\/www.minco.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Heater Wattage Estimator - Minco","description":"This calculator models the conduction, radiation, and convection losses of a heat sink, as well as process heat requirements, to assist you in determining heater wattage needs. Add input values in the appropriate fields below and the calculator will provide an estimate the minimum heater wattage. See the \u201cMinco Heater Wattage Estimator\u201d video for further instruction.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/","og_locale":"en_US","og_type":"article","og_title":"Heater Wattage Estimator - Minco","og_description":"This calculator models the conduction, radiation, and convection losses of a heat sink, as well as process heat requirements, to assist you in determining heater wattage needs. Add input values in the appropriate fields below and the calculator will provide an estimate the minimum heater wattage. See the \u201cMinco Heater Wattage Estimator\u201d video for further instruction.","og_url":"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/","og_site_name":"Minco","article_modified_time":"2024-02-19T18:43:01+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/","url":"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/","name":"Heater Wattage Estimator - Minco","isPartOf":{"@id":"https:\/\/www.minco.com\/#website"},"datePublished":"2023-09-26T20:09:56+00:00","dateModified":"2024-02-19T18:43:01+00:00","description":"This calculator models the conduction, radiation, and convection losses of a heat sink, as well as process heat requirements, to assist you in determining heater wattage needs. Add input values in the appropriate fields below and the calculator will provide an estimate the minimum heater wattage. See the \u201cMinco Heater Wattage Estimator\u201d video for further instruction.","breadcrumb":{"@id":"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.minco.com\/resources\/heater-wattage-estimator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.minco.com\/"},{"@type":"ListItem","position":2,"name":"Heater Wattage Estimator"}]},{"@type":"WebSite","@id":"https:\/\/www.minco.com\/#website","url":"https:\/\/www.minco.com\/","name":"Minco","description":"Flex Circuits, Temperature Sensors, Heating Elements and More","publisher":{"@id":"https:\/\/www.minco.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.minco.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.minco.com\/#organization","name":"Minco","url":"https:\/\/www.minco.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.minco.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.minco.com\/wp-content\/uploads\/minco-logo-color.svg","contentUrl":"https:\/\/www.minco.com\/wp-content\/uploads\/minco-logo-color.svg","width":184,"height":44,"caption":"Minco"},"image":{"@id":"https:\/\/www.minco.com\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.minco.com\/wp-json\/wp\/v2\/resources\/7081","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.minco.com\/wp-json\/wp\/v2\/resources"}],"about":[{"href":"https:\/\/www.minco.com\/wp-json\/wp\/v2\/types\/resources"}],"version-history":[{"count":65,"href":"https:\/\/www.minco.com\/wp-json\/wp\/v2\/resources\/7081\/revisions"}],"predecessor-version":[{"id":7329,"href":"https:\/\/www.minco.com\/wp-json\/wp\/v2\/resources\/7081\/revisions\/7329"}],"wp:attachment":[{"href":"https:\/\/www.minco.com\/wp-json\/wp\/v2\/media?parent=7081"}],"wp:term":[{"taxonomy":"content_type","embeddable":true,"href":"https:\/\/www.minco.com\/wp-json\/wp\/v2\/content_type?post=7081"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/www.minco.com\/wp-json\/wp\/v2\/product?post=7081"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}