{"id":830,"date":"2019-04-26T14:40:47","date_gmt":"2019-04-26T14:40:47","guid":{"rendered":"https:\/\/www.bcta.group\/attma\/?page_id=830"},"modified":"2025-01-17T14:34:24","modified_gmt":"2025-01-17T14:34:24","slug":"fan-calibration-variable-calculator","status":"publish","type":"page","link":"https:\/\/www.bcta.group\/attma\/fan-calibration-variable-calculator\/","title":{"rendered":"Fan Calibration Variable Calculator"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"830\" class=\"elementor elementor-830\" data-elementor-settings=\"{&quot;ha_cmc_init_switcher&quot;:&quot;no&quot;}\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-dab8a57 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"dab8a57\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\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-32fb8d4\" data-id=\"32fb8d4\" 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-6c7d539 elementor-widget elementor-widget-heading\" data-id=\"6c7d539\" 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<h2 class=\"elementor-heading-title elementor-size-default\">Fan Calibration Variable Calculator<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-52493a0d elementor-widget elementor-widget-text-editor\" data-id=\"52493a0d\" 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>The ATTMA Trade Association has developed the following Fan Calibration Variable tool to calculate fan calibration variables, particularly useful for new Retrotec Fans which use Polynomial variables.<\/p>\n<p><!-- \/wp:paragraph --><!-- wp:paragraph --><\/p>\n<p><\/p>\n<p><!-- \/wp:paragraph --><!-- wp:shortcode --><!-- \/wp:shortcode --><\/p>\t\t\t\t\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<div class=\"elementor-element elementor-element-2469a51 e-flex e-con-boxed e-con e-parent\" data-id=\"2469a51\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;_ha_eqh_enable&quot;:false}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-4b01f3b elementor-widget elementor-widget-shortcode\" data-id=\"4b01f3b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><!DOCTYPE html>\r\n<html lang=\"en-US\">\r\n<head>\r\n<meta charset=\"UTF-8\"\/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n<title>Fan Calibration Variables &#8211; ATTMA<\/title>\r\n<link rel='stylesheet' id='colormag_google_fonts-css'  href='\/\/fonts.googleapis.com\/css?family=Open+Sans%3A400%2C600&#038;ver=e38ce6b073c46d678695d0d339d3a93d' type='text\/css' media='all' \/>\r\n<link rel='stylesheet' id='colormag_style-css'  href='https:\/\/www.attma.org\/wp-content\/themes\/colormag\/style.css?ver=e38ce6b073c46d678695d0d339d3a93d' type='text\/css' media='all' \/>\r\n<link rel='stylesheet' id='colormag-fontawesome-css'  href='https:\/\/www.attma.org\/wp-content\/themes\/colormag\/fontawesome\/css\/font-awesome.css?ver=4.2.1' type='text\/css' media='all' \/>\r\n<link rel=\"icon\" href=\"https:\/\/i1.wp.com\/www.attma.org\/wp-content\/uploads\/2015\/12\/cropped-ATTMA-logo-Fan1.png?fit=32%2C32&#038;ssl=1\" sizes=\"32x32\" \/>\r\n<!-- ATTMA Internal Styles -->        \r\n<style type=\"text\/css\"> \r\n\t.colormag-button,blockquote,button,input[type=reset],input[type=button],input[type=submit], #masthead.colormag-header-clean #site-navigation.main-small-navigation .menu-toggle{background-color:#275ac6}\r\n<\/style>\r\n<\/head>\r\n<body class=\"page-template-default page page-id-2 wp-custom-logo wide better-responsive-menu\">\r\n<div id=\"page\" class=\"hfeed site\">\r\n<div id=\"main\" class=\"clearfix\">\r\n\t\t<div class=\"inner-wrap clearfix\">\r\n\t<div id=\"primary\">\r\n\t\t<div id=\"content\" class=\"clearfix\">\r\n<!-- #custom page content starts here -->\r\n\r\n<p>The ATTMA Trade Association has developed the following Fan Calibration Variable tool to calculate fan calibration variables, particularly useful for new Retrotec Fans which use Polynomial variables.<\/p>\r\n<p>Enter appropriate numbers and units from your calibration certificate and the unit of measure you wish the calibration variables to be displayed for entry into your air tightness testing software. For the vast majority of fans leave the Polynomial check box unticked as this is specifically for the B4 and smaller range plates on the Retrotec 5000 and 6000 series fans.<\/p>\r\n<style type=\"text\/css\">\r\ninput.fanC, input.fanC:hover input.fanC:active, input.fanC:focus, button.fanC {margin: 0px; border: 4px solid #EFEFEF; border-radius: 8px; box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.2) inset; outline: medium none; padding: 4px 0px 4px 4px; font-size: 80%; font-family: \"Lucida Grande\",Tahoma,Arial,Verdana,sans-serif;}\r\ninput.fanC:focus {background: #ffffff;}\r\n#fanCalCertVars table {border: 1px solid #EAEAEA;}\r\n#fanCalCertVars table td {border-width: 0px 1px;}\r\n<\/style>\r\n<script type=\"text\/javascript\">\r\n\/***************************************************************************\r\nCopyright (C) 2018, Air Tightness Testing and Measurement Association\r\n\r\nThis code is not to be redistributed or modified without written permission from ATTMA.\r\nPlease visit www.attma.org for contact details.\r\n ***************************************************************************\/\r\n\t\r\n\t\/\/ global variables\r\n\tvar ranges = 0; var readings = 0; var uIn = 0; var uOut = 0; var madeForm = 0; var minRanges = 1; var maxRanges = 15; var minReadings = 3; var maxReadings = 15;\r\n\t\/\/convert a number to a log\r\n\tfunction ln(a){return Math.log(Math.abs(a));}\r\n\t\/\/adjust the decimal places of a number\r\n\tfunction dp(a, b){return parseFloat(Math.round(a * Math.pow(10, b)) \/ Math.pow(10, b)).toFixed(b);}\r\n\t\/\/linear flow calculation\r\n\tfunction calFlowLS(a, b, c){return a * (Math.pow(b, c));}\r\n\t\/\/polynomial flow calculation\r\n\tfunction calFlowPoly(a, b, c, d, e){return (a * Math.pow(e, 3)) + (b * Math.pow(e, 2)) + (c * e) + d;}\r\n\t\/\/unit conversion\r\n\tfunction convUnit(a){return (a \/ uIn) * uOut;}\r\n\t\/\/unit text\r\n\tfunction unitText(a){if(a==1){return '(m&#179;\/s)';} else if(a==3600){return '(m&#179;\/h)';}else{return '(ft&#179;\/min)';}}\r\n\t\/\/return selected radio button for IE\r\n\tfunction getRadio(a){for(var i=0; i<a.length; i++){if(a[i].checked == true){return(a[i].value);}}}\r\n\t\/\/create inputs for each range\r\n\tfunction makeInput(){\r\n\t\t\/\/ set variables for ranges and reading and sense check the inputs\r\n\t\tranges = document.getElementById('fanCalCertVars').nRanges.value;\r\n\t\treadings = document.getElementById('fanCalCertVars').nReadings.value;\r\n\t\tvar s = '';\r\n\t\ts += checkRanges(ranges);\r\n\t\ts += checkReadings(readings);\r\n\t\tif(s.length >0){\r\n\t\t\tdocument.getElementById('frer').innerHTML = '<strong>Errors:<\/strong><br \/>' + s;\r\n\t\t\tdocument.getElementById('frer').style.display = 'block';\r\n\t\t}\r\n\t\telse{\r\n\t\t\tdocument.getElementById('frer').innerHTML = '';\r\n\t\t\tdocument.getElementById('frer').style.display = 'none';\r\n\t\t}\r\n\t\tif(ranges > maxRanges){ranges = maxRanges;}else if(ranges < minRanges){ranges = minRanges;} else if(isNaN(ranges)){ranges = minRanges;}\r\n\t\tif(readings > maxReadings){readings = maxReadings;}else if(readings < minReadings){readings = minReadings;} else if(isNaN(readings)){readings = minReadings;}\r\n\t\t\/\/ make ranges visible and setup the inputs in each range div\r\n\t\tif(ranges > 0){document.getElementById('frdocalc').style.display = 'block';}\r\n\t\t\/\/setup unit conversion based on form input\r\n\t\tuIn = getRadio(document.getElementById('fanCalCertVars').iUnit);\r\n\t\tuOut = getRadio(document.getElementById('fanCalCertVars').oUnit);\r\n\t\tif(madeForm == 0){\r\n\t\t\tfor (var i = 0; i < ranges; i++){\r\n\t\t\t\tdocument.getElementById('fr' + i).innerHTML = makeInputTable(i);;\r\n\t\t\t\tdocument.getElementById('fr' + i).style.display = 'block';\r\n\t\t\t}\r\n\t\t\tmadeForm = 1;\r\n\t\t}\r\n\t}\r\n\tfunction makeInputTable(i){\r\n\t\tvar s = '';\r\n\t\ts += '<table id=\"r' + i + '\"><tr><th width=\"20%\">Ring\/Range ' + (i + 1) + '<\/th>';\r\n\t\ts += '<th width=\"16%\">Polynomial?<\/th>';\r\n\t\ts += '<th width=\"16%\">Flow Pressure (Pa)<\/th>';\r\n\t\ts += '<th width=\"16%\" id=\"r' + i + 'vfrt\">Volume Flow Rate ' + unitText(uIn) + '<\/th>';\r\n\t\ts += '<th width=\"16%\" id=\"r' + i + 'cfrt\">Calculated Flow ' + unitText(uOut) + '<\/th>';\r\n\t\ts += '<th width=\"16%\">Error Rate<\/th><\/tr>';\r\n\t\ts += '<tr style=\"vertical-align: top\"><td rowspan=\"' + readings + '\"><input type=\"text\" name=\"r' + i + 'name\" class=\"fanC\"><\/td>';\r\n\t\ts += '<td rowspan=\"' + readings + '\"><input type=\"checkbox\" name=\"r' + i + 'poly\" class=\"fanC\"><\/td>';\r\n\t\tfor (var j = 0; j < readings; j++){\r\n\t\t\ts += '<td><input type=\"text\" name=\"r' + i + 'fp' + j + '\" class=\"fanC\"><\/td>';\r\n\t\t\ts += '<td><input type=\"text\" name=\"r' + i + 'vfr' + j + '\" class=\"fanC\"><\/td>';\r\n\t\t\ts += '<td id=\"r' + i + 'cvfr' + j + '\">&nbsp;<\/td>';\r\n\t\t\ts += '<td id=\"r' + i + 'er' + j + '\">&nbsp;<\/td><\/tr>';\r\n\t\t\tif(j<(readings-1)){\r\n\t\t\t\t\/\/start a new row except for the last row\r\n\t\t\t\ts += '<tr>';\r\n\t\t\t}\r\n\t\t}\r\n\t\ts += '<\/table>';\r\n\t\treturn s;\r\n\t}\r\n\tfunction checkRanges(a){\r\n\t\tvar er = [];\r\n\t\tvar s = '';\r\n\t\tif(a >= 15){a = 15; er.push('- More than 15 ranges has been specified so this has been capped at 15');} \r\n\t\telse if(a <=0){a = 1; er.push('- Less than 0 ranges has been specified so this has been set to 1');} \r\n\t\telse if(isNaN(a)){a = 1; er.push('- The number of ranges entered is not a number so this has been set to 1');}\r\n\t\tif(er.length >0){\r\n\t\t\tfor (i = 0; i < er.length; i++){\r\n\t\t\t\ts += er[i];\r\n\t\t\t\tif(i < er.length){s += '<br \/>';}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn s;\r\n\t}\r\n\tfunction checkReadings(a){\r\n\t\tvar er = [];\r\n\t\tvar s = '';\r\n\t\tif(a >= 16){er.push('- More than 15 readings per range has been specified this has been capped at 15');} \r\n\t\telse if(a <=2){er.push('- Less than 3 readings has been specified so this has been set to 3 as a minimum.  For polynomial ranges raise this to the minimum of 4 readings per range');} \r\n\t\telse if(isNaN(a)){er.push('- The number of readings entered is not a number so this has been set to 3 as a minimum.  For polynomial ranges raise this to the minimum of 4 readings per range');}\r\n\t\tif(er.length >0){\r\n\t\t\tfor (i = 0; i < er.length; i++){\r\n\t\t\t\ts += er[i];\r\n\t\t\t\tif(i < er.length){s += '<br \/>';}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn s;\r\n\t}\r\n\tfunction calVar(){\r\n\t\t\/\/clear previous calcs\r\n\t\tfor (var i = 0; i < ranges; i++){ \r\n\t\t\tfor (var j = 0; j < readings; j++){ \r\n\t\t\t\tdocument.getElementById('r' + i + 'cvfr' + j).innerHTML = '';\r\n\t\t\t\tdocument.getElementById('r' + i + 'er' + j).innerHTML = '';\r\n\t\t\t}\r\n\t\t}\r\n\t\tdocument.getElementById('calVarLSResults').innerHTML = '';\r\n\t\tdocument.getElementById('calVarPolyResults').innerHTML = '';\r\n\t\t\/\/setup arrays for ls and poly ranges\r\n\t\tvar lsRanges = [];\r\n\t\tvar polyRanges = [];\r\n\t\tfor (var i = 0; i < ranges; i++){\r\n\t\t\tif(document.getElementById('fanCalCertVars')['r' + i + 'poly'].checked){polyRanges.push(i);}\r\n\t\t\telse{lsRanges.push(i);}\r\n\t\t}\r\n\t\t\/\/create table of results and add LS calc data\r\n\t\tif (lsRanges.length > 0){\r\n\t\t\tvar s = '<h3>Standard Ranges<\/h3>';\r\n\t\t\ts += \t'<table id=\"lsResults\"><tr><th width=\"20%\">Ring\/Range<\/th><th width=\"40%\">Coefficient ' + unitText(uOut) + '<\/th><th width=\"40%\">Exponent<\/th><\/tr>';\r\n\t\t\tfor(var i = 0; i < lsRanges.length; i++){\r\n\t\t\t\ts+= calLS(lsRanges[i]);\r\n\t\t\t}\r\n\t\t\ts += '<\/table>';\r\n\t\t\tdocument.getElementById('calVarLSResults').innerHTML = s;\r\n\t\t}\r\n\t\t\/\/create table of results and add Poly calc data\r\n\t\tif(polyRanges.length > 0){\r\n\t\t\tif (readings > 3){\r\n\t\t\t\tvar s = '<h3>Polynomial Ranges<\/strong><\/h3>';\r\n\t\t\t\ts += \t'<table id=\"polyResults\"><tr><th width=\"20%\">Ring\/Range<\/th><th width=\"20%\">A ' + unitText(uOut) + '<\/th><th width=\"20%\">B ' + unitText(uOut) + '<\/th><th width=\"20%\">C ' + unitText(uOut) + '<\/th><th width=\"20%\">D ' + unitText(uOut) + '<\/th><\/tr>';\r\n\t\t\t\tif (readings > 3){\r\n\t\t\t\t\tfor(var i = 0; i < polyRanges.length; i++){\r\n\t\t\t\t\t\ts += calPoly(polyRanges[i]);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse{\r\n\t\t\t\t\ts += '<tr><td colspan=\"5\">A minimum of 4 readings are required to calculate a third order polynomial and at least 5 readings are required to also calculate an error rate from the trendline.<\/td><\/tr>'\r\n\t\t\t\t}\r\n\t\t\t\ts += '<\/table>';\r\n\t\t\t\tdocument.getElementById('calVarPolyResults').innerHTML = s;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfunction calLS(a){\r\n\t\tvar f = document.getElementById('fanCalCertVars');\r\n\t\tvar fanRange = f['r' + a + 'name'].value;\r\n\t\tvar x = new Array(); for (var i = 0; i < readings; i++){x[i] = f['r' + a + 'fp' + i].value;}\r\n\t\tvar y = new Array(); for (var i = 0; i < readings; i++){y[i] = f['r' + a + 'vfr' + i].value;}\r\n\t\tvar m = 0, b = 0, c = 0;\r\n\t\tvar dSumx = 0, dSumy = 0, dSumxx = 0, dSumxy = 0;\r\n\t\tvar s = '';\r\n\t\tfor (var i = 0; i < readings; i++){\r\n\t\t\tdSumx = dSumx + ln(x[i]);\r\n\t\t\tdSumy = dSumy + ln(y[i]);\r\n\t\t\tdSumxy = dSumxy + (ln(x[i]) * ln(y[i]));\r\n\t\t\tdSumxx = dSumxx + (ln(x[i]) * ln(x[i]));\r\n\t\t}\r\n\t\r\n\t\tm = ((dSumx * dSumy) - (readings * dSumxy)) \/ ((dSumx * dSumx) - (readings * dSumxx));\r\n\t\tb = ((dSumx * dSumxy) - (dSumxx * dSumy)) \/ ((dSumx * dSumx) - (readings * dSumxx));\r\n\t\tc = convUnit(Math.exp(b));\r\n\t\t\r\n\t\tvar dpfr = 0;\r\n\t\tif (uOut == 1){dpfr = 4;}\r\n\t\telse if(uOut == 3600){dpfr = 1;}\r\n\t\telse {dpfr = 1;}\r\n\t\t\r\n\t\tfor (var i = 0; i < readings; i++){\r\n\t\t\tvar fr = calFlowLS(c, x[i], m);\r\n\t\t\tvar frText = '';\r\n\t\t\tif(isNaN(fr)){frText='';} \r\n\t\t\telse{frText = dp(fr, dpfr);}\r\n\t\t\tdocument.getElementById('r' + a + 'cvfr' + i).innerHTML = frText;\r\n\t\t\tvar erRate = dp((fr*10 - convUnit(y[i])*10)\/ fr*10, 3);\r\n\t\t\tvar erText = '';\r\n\t\t\tif(erRate > 2 || erRate < -2){erText = '<span style=\"color: red;\">' + erRate + '%<\/span>';}\r\n\t\t\telse if (isNaN(erRate)){erText='';}\r\n\t\t\telse {erText = erRate + '%';}\r\n\t\t\tdocument.getElementById('r' + a + 'er' + i).innerHTML = erText;\r\n\t\t}\r\n\t\tif(isNaN(c)){c = '<span style=\"color: red;\">Check input<\/span>';}else{c = dp(c, dpfr);}\r\n\t\tif(isNaN(m)){m = '<span style=\"color: red;\">Check input<\/span>';}else{m = dp(m, 4);}\r\n\t\ts += '<tr><td>' + fanRange + '<\/td>';\r\n\t\ts += '<td>' + c + '<\/td>';\r\n\t\ts += '<td>' + m + '<\/td><\/tr>';\r\n\t\treturn s;\r\n\t}\r\n\tfunction calPoly(a){\r\n\t\tvar s = '';\r\n\t\t\/\/setup the variables needed to create the matrices\r\n\t\tvar f = document.getElementById('fanCalCertVars');\r\n\t\tvar fanRange = f['r' + a + 'name'].value;\r\n\t\tvar x = new Array(); for (var i = 0; i < readings; i++){x.push(f['r' + a + 'fp' + i].value);}\r\n\t\tvar y = new Array(); for (var i = 0; i < readings; i++){y.push(f['r' + a + 'vfr' + i].value);}\r\n\t\tvar dSumx1 = 0, dSumx2 = 0, dSumx3 = 0, dSumx4 = 0, dSumx5 = 0, dSumx6 = 0, dSumy = 0, dSumx1y = 0, dSumx2y = 0, dSumx3y = 0;\r\n\t\tfor (var i = 0; i < readings; i++){\r\n\t\t\tdSumx1 = dSumx1 + x[i]*1;\r\n\t\t\tdSumx2 = dSumx2 + Math.pow(x[i], 2);\r\n\t\t\tdSumx3 = dSumx3 + Math.pow(x[i], 3);\r\n\t\t\tdSumx4 = dSumx4 + Math.pow(x[i], 4);\r\n\t\t\tdSumx5 = dSumx5 + Math.pow(x[i], 5);\r\n\t\t\tdSumx6 = dSumx6 + Math.pow(x[i], 6);\t\t\t\t\r\n\t\t\tdSumy = dSumy + y[i]*1;\r\n\t\t\tdSumx1y = dSumx1y + x[i]*y[i];\r\n\t\t\tdSumx2y = dSumx2y + Math.pow(x[i], 2)*y[i];\r\n\t\t\tdSumx3y = dSumx3y + Math.pow(x[i], 3)*y[i];\t\r\n\t\t}\r\n\t\t\/\/setup the columns that form each of the five variants of the 4 x 4 matrices with each item in an array representing the row of the matrix \r\n\t\t\/\/For example with a 4x4 matrix with col0, col1, col2 and col3 you have col0[0] as the top left of the matrix and col3[3] as the bottom right\r\n\t\tvar col0 = new Array(readings, dSumx1, dSumx2, dSumx3);\r\n\t\tvar col1 = new Array(dSumx1, dSumx2, dSumx3, dSumx4);\r\n\t\tvar col2 = new Array(dSumx2, dSumx3, dSumx4, dSumx5);\r\n\t\tvar col3 = new Array(dSumx3, dSumx4, dSumx5, dSumx6);\r\n\t\tvar coly = new Array(dSumy, dSumx1y, dSumx2y, dSumx3y);\r\n\t\t\/\/function to get the determinants of each matrix within a 4x4 matrix.  The variables are the columns used in the matrix.\r\n\t\tfunction getDet(a, b, c, d){\r\n\t\t\t\/\/determinants of 2x2 matrices for 1st column\r\n\t\t\tvar m00 = b[1] * ((c[2] * d[3]) - (d[2] * c[3])); \r\n\t\t\tvar m01 = c[1] * -1 * (b[2] * d[3] - b[3] * d[2]); \r\n\t\t\tvar m02 = d[1] * (b[2] * c[3] - b[3] * c[2]); \r\n\t\t\t\/\/determinants of 2x2 matrices for 2nd column\r\n\t\t\tvar m10 = a[1] * (c[2] * d[3] - d[2] * c[3]);\r\n\t\t\tvar m11 = c[1] * -1 * (a[2] * d[3] - a[3] * d[2]);\r\n\t\t\tvar m12 = d[1] * (a[2] * c[3] - a[3]*c[2]);\r\n\t\t\t\/\/determinants of 2x2 matrices for 3rd column\r\n\t\t\tvar m20 = a[1] * (b[2] * d[3] - b[3] * d[2]);\r\n\t\t\tvar m21 = b[1] * -1 * (a[2] * d[3] - a[3] * d[2]);\r\n\t\t\tvar m22 = d[1] * (a[2] * b[3] - a[3] * b[2]);\r\n\t\t\t\/\/determinants of 2x2 matrices for 4th column\r\n\t\t\tvar m30 = a[1] * (b[2] * c[3] - b[3] * c[2]);\r\n\t\t\tvar m31 = b[1] * -1 *  (a[2] * c[3] - c[2] * a[3]);\r\n\t\t\tvar m32 = c[1] * (a[2] * b[3] - a[3] * b[2]);\r\n\t\t\t\/\/determinants of 3x3 matrices\r\n\t\t\tvar m0 = a[0] * (m00 + m01 + m02);\r\n\t\t\tvar m1 = b[0] * -1 * (m10 + m11 + m12);\r\n\t\t\tvar m2 = c[0] * (m20 + m21 + m22);\r\n\t\t\tvar m3 = d[0] * -1 * (m30 + m31 + m32);\r\n\t\t\t\/\/determinant of 4x4 matrix\r\n\t\t\treturn(m0 + m1 + m2 + m3);\r\n\t\t}\r\n\t\t\/\/get the determinants for each 4x4 matrix\r\n\t\tvar ma  = getDet(col0, col1, col2, col3);\r\n\t\tvar ma0 = getDet(coly, col1, col2, col3);\r\n\t\tvar ma1 = getDet(col0, coly, col2, col3);\r\n\t\tvar ma2 = getDet(col0, col1, coly, col3);\r\n\t\tvar ma3 = getDet(col0, col1, col2, coly);\r\n\t\t\/\/calculate the variables for the polynomial with a0 being the constant D, a1-a3 being variables to the power of (a2 is to the power of 2 so variable B)\r\n\t\tvar a0 = ma0 \/ ma;\r\n\t\tvar a1 = ma1 \/ ma;\r\n\t\tvar a2 = ma2 \/ ma;\r\n\t\tvar a3 = ma3 \/ ma;\r\n\t\ta0 = convUnit(a0);\r\n\t\ta1 = convUnit(a1);\r\n\t\ta2 = convUnit(a2);\r\n\t\ta3 = convUnit(a3);\r\n\t\t\r\n\t\tvar dp0 = 0, dp1 = 0, dp2 = 0, dp3 = 0;\r\n\t\tif (uOut == 1){dp0 = 4; dp1 = 5; dp2 = 7; dp3 = 10;}\r\n\t\telse if(uOut == 3600){dp0 = 1; dp1 = 2; dp2 = 4; dp3 = 6;}\r\n\t\telse {dp0 = 2; dp1 =3; dp2 = 4; dp3 = 6;}\r\n\t\t\r\n\t\tfor (var i = 0; i < readings; i++){\r\n\t\t\tvar fr = calFlowPoly(a3, a2, a1, a0, x[i]);\r\n\t\t\tvar dpfr = 0;\r\n\t\t\tif (uOut == 1){dpfr = 4;}\r\n\t\t\telse if(uOut == 3600){dpfr = 0;}\r\n\t\t\telse {dpfr = 0;}\r\n\t\t\tvar frText = '';\r\n\t\t\tif(isNaN(fr)){frText='';} \r\n\t\t\telse{frText = dp(fr, dpfr);}\r\n\t\t\tdocument.getElementById('r' + a + 'cvfr' + i).innerHTML = frText;\r\n\t\t\tvar erRate = dp((fr*10 - convUnit(y[i])*10)\/ fr*10, 3);\r\n\t\t\tvar erText = '';\r\n\t\t\tif(erRate > 2){erText = '<span style=\"color: red;\">' + erRate + '%<\/span>';}\r\n\t\t\telse if (isNaN(erRate)){ erText='';}\r\n\t\t\telse {erText = erRate + '%';}\r\n\t\t\tdocument.getElementById('r' + a + 'er' + i).innerHTML = erText;\r\n\t\t}\r\n\t\tif(isNaN(a0)){a0 = '<span style=\"color: red;\">Check input<\/span>';}else{a0 = dp(a0, dp0);}\r\n\t\tif(isNaN(a1)){a1 = '<span style=\"color: red;\">Check input<\/span>';}else{a1 = dp(a1, dp1);}\r\n\t\tif(isNaN(a2)){a2 = '<span style=\"color: red;\">Check input<\/span>';}else{a2 = dp(a2, dp2);}\r\n\t\tif(isNaN(a3)){a3 = '<span style=\"color: red;\">Check input<\/span>';}else{a3 = dp(a3, dp3);}\t\r\n\t\ts = \t'';\r\n\t\ts += \t'<tr><td>' +fanRange + '<\/td><td>'+ a3 + ' <\/td><td>' + a2 + '<\/td><td>' + a1 + '<\/td><td>' + a0 + '<\/td><\/tr>';\r\n\t\treturn(s);\r\n\t}\r\n\t\/\/function to update page when either the input flow or output flow unit of measure us changed\r\n\tfunction changeUnits(){\r\n\t\tif(madeForm == 1){\r\n\t\t\tuIn = getRadio(document.getElementById('fanCalCertVars').iUnit);\r\n\t\t\tuOut = getRadio(document.getElementById('fanCalCertVars').oUnit);\r\n\t\t\t\/\/change text in input tables for all ranges to shows the changes in units\r\n\t\t\tfor (var i = 0; i < ranges; i++){ \r\n\t\t\t\tdocument.getElementById('r' + i + 'vfrt').innerHTML = '<strong>Volume Flow Rate ' + unitText(uIn) + '<\/strong>';\r\n\t\t\t\tdocument.getElementById('r' + i + 'cfrt').innerHTML = '<strong>Calculated Flow ' + unitText(uOut) + '<\/strong>';\r\n\t\t\t}\r\n\t\t\tif(document.getElementById('calVarLSResults').contains(document.getElementById('lsResults'))){\r\n\t\t\t\tdocument.getElementById('lsResults').rows[0].cells[1].innerHTML = '<strong>Coefficient ' + unitText(uOut) + '<\/strong>';\r\n\t\t\t}\r\n\t\t\tif(document.getElementById('calVarPolyResults').contains(document.getElementById('polyResults'))){\r\n\t\t\t\tdocument.getElementById('polyResults').rows[0].cells[1].innerHTML = '<strong>A ' + unitText(uOut) + '<\/strong>';\r\n\t\t\t\tdocument.getElementById('polyResults').rows[0].cells[2].innerHTML = '<strong>B ' + unitText(uOut) + '<\/strong>';\r\n\t\t\t\tdocument.getElementById('polyResults').rows[0].cells[3].innerHTML = '<strong>C ' + unitText(uOut) + '<\/strong>';\r\n\t\t\t\tdocument.getElementById('polyResults').rows[0].cells[4].innerHTML = '<strong>D ' + unitText(uOut) + '<\/strong>';\r\n\t\t\t}\r\n\t\t\t\/\/recalculate the flows to show the new output units\r\n\t\t\tcalVar();\r\n\t\t}\r\n\t}\r\n\t\/\/function to change the number of readings in the form for each range\r\n\tfunction changeReadings(){\r\n\t\tif(madeForm == 1){\r\n\t\t\tvar oldReadings = readings;\r\n\t\t\tvar newReadings = document.getElementById('fanCalCertVars').nReadings.value;\r\n\t\t\tvar s = checkReadings(newReadings);\r\n\t\t\tif(s.length >0){\r\n\t\t\t\tdocument.getElementById('frer').innerHTML = s;\r\n\t\t\t\tdocument.getElementById('frer').style.display = \"block\";\r\n\t\t\t}\r\n\t\t\telse{\r\n\t\t\t\tdocument.getElementById('frer').innerHTML = '';\r\n\t\t\t\tdocument.getElementById('frer').style.display = \"none\";\r\n\t\t\t}\r\n\t\t\tif(newReadings > maxReadings){newReadings = maxReadings;}else if(newReadings < minReadings){newReadings = minReadings;} else if(isNaN(newReadings)){newReadings = minReadings;}\r\n\t\t\tvar diffReadings = newReadings - oldReadings;\r\n\t\t\t\/\/removing readings\r\n\t\t\tif(diffReadings < 0){\r\n\t\t\t\tif(newReadings >= minReadings){\r\n\t\t\t\t\t\/\/loop through all the ranges on the form\r\n\t\t\t\t\tfor (var i = 0; i < ranges; i++){ \r\n\t\t\t\t\t\tfor (var j = 0; j < (diffReadings * -1); j++){\r\n\t\t\t\t\t\t\t\/\/delete rows and adjust rowspans accordingly\r\n\t\t\t\t\t\t\tdocument.getElementById('r' + i).deleteRow(-1);\r\n\t\t\t\t\t\t\tdocument.getElementById('r' + i).rows[1].cells[0].rowSpan=newReadings;\r\n\t\t\t\t\t\t\tdocument.getElementById('r' + i).rows[1].cells[1].rowSpan=newReadings;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\/\/reset readings to correct value\r\n\t\t\t\t\treadings = newReadings;\r\n\t\t\t\t}\r\n\t\t\t\t\/\/when deleting there is still data in the form so run the variable calc again\r\n\t\t\t\tcalVar();\r\n\t\t\t}\r\n\t\t\t\/\/adding readings\r\n\t\t\telse if(diffReadings > 0){\r\n\t\t\t\t\/\/loop through the ranges on the form\r\n\t\t\t\tfor(var i = 0; i < ranges; i++){\r\n\t\t\t\t\tvar t = document.getElementById('r' + i);\r\n\t\t\t\t\tfor(var j = 0; j < diffReadings; j++){\r\n\t\t\t\t\t\t\/\/create rows and cells\r\n\t\t\t\t\t\tvar r = t.insertRow(oldReadings*1+j+1);\r\n\t\t\t\t\t\tvar c1 = r.insertCell(0);\r\n\t\t\t\t\t\tvar c2 = r.insertCell(1);\r\n\t\t\t\t\t\tvar c3 = r.insertCell(2);\r\n\t\t\t\t\t\tvar c4 = r.insertCell(3);\r\n\t\t\t\t\t\t\/\/populate cells and add ID values where needed\r\n\t\t\t\t\t\tc1.innerHTML = '<input type=\"text\" name=\"r' + i + 'fp' + ((oldReadings*1)+j) + '\" class=\"fanC\">';\r\n\t\t\t\t\t\tc2.innerHTML = '<input type=\"text\" name=\"r' + i + 'vfr' + ((oldReadings*1)+j) + '\" class=\"fanC\">';\r\n\t\t\t\t\t\tc3.innerHTML = '&nbsp;';\r\n\t\t\t\t\t\tc4.innerHTML = '&nbsp;';\r\n\t\t\t\t\t\tc3.id = 'r' + i + 'cvfr' + ((oldReadings*1)+j);\r\n\t\t\t\t\t\tc4.id = 'r' + i + 'er' + ((oldReadings*1)+j);\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\/\/adjust the rowspans accordingly\r\n\t\t\t\t\tdocument.getElementById('r' + i).rows[1].cells[0].rowSpan=newReadings;\r\n\t\t\t\t\tdocument.getElementById('r' + i).rows[1].cells[1].rowSpan=newReadings;\t\r\n\t\t\t\t}\r\n\t\t\t\treadings = newReadings;\r\n\t\t\t\t\/\/don't run calc as there will be some blank form inputs\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfunction changeRanges(){\r\n\t\tif(madeForm == 1){\r\n\t\t\tvar oldRanges = ranges;\r\n\t\t\tvar newRanges = document.getElementById('fanCalCertVars').nRanges.value;\r\n\t\t\t\/\/do an error check based on input in form\r\n\t\t\tvar s = checkRanges(newRanges);\r\n\t\t\tif(s.length >0){\r\n\t\t\t\tdocument.getElementById('frer').innerHTML = s;\r\n\t\t\t\tdocument.getElementById('frer').style.display = \"block\";\r\n\t\t\t}\r\n\t\t\telse{\r\n\t\t\t\tdocument.getElementById('frer').innerHTML = '';\r\n\t\t\t\tdocument.getElementById('frer').style.display = \"none\";\r\n\t\t\t}\r\n\t\t\t\/\/error check the input\r\n\t\t\tif(newRanges > maxRanges){newRanges = maxRanges;}\r\n\t\t\telse if(newRanges < minRanges){newRanges = minRanges;} \r\n\t\t\telse if(isNaN(newRanges)){newRanges = minRanges;}\r\n\t\t\r\n\t\t\tvar diffRanges = newRanges - oldRanges;\r\n\t\t\t\/\/remove ranges\r\n\t\t\tif(diffRanges < 0){\r\n\t\t\t\tif(newRanges >0){\r\n\t\t\t\t\t\/\/loop through all the ranges on the form\r\n\t\t\t\t\tfor (var i = 0; i < (diffRanges * -1); i++){\r\n\t\t\t\t\t\t\/\/delete ranges\r\n\t\t\t\t\t\tdocument.getElementById('r' + (newRanges*1 + i)).innerHTML = '';\r\n\t\t\t\t\t\tdocument.getElementById('r' + (newRanges*1 + i)).style.display = 'none';\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\/\/reset readings to correct value\r\n\t\t\t\t\tranges = newRanges;\r\n\t\t\t\t}\r\n\t\t\t\tcalVar();\t\t\r\n\t\t\t}\r\n\t\t\t\/\/add ranges\r\n\t\t\telse if(diffRanges > 0){\r\n\t\t\t\t\/\/loop through the ranges on the form\r\n\t\t\t\tfor(var i = 0; i < diffRanges; i++){\r\n\t\t\t\t\tdocument.getElementById('fr' + (oldRanges*1 +i)).innerHTML = makeInputTable(oldRanges*1+i);\r\n\t\t\t\t\tdocument.getElementById('fr' + (oldRanges*1 +i)).style.display = 'block';\r\n\t\t\t\t}\r\n\t\t\t\tranges = newRanges;\r\n\t\t\t\t\/\/don't run calc as there will be some blank form inputs\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n<\/script>\r\n<header class=\"entry-header\">\r\n\t<h1 class=\"entry-title\">Fan Calibration Variable Calculator<\/h1>\r\n<\/header>\r\n<div class=\"entry-content clearfix\">\r\n<p>Enter appropriate numbers and units from your calibration certificate and the unit of measure you wish the calibration variables to be displayed for entry into your air tightness testing software. For the vast majority of fans leave the Polynomial check box unticked as this is specifically for the B4 and smaller range plates on the Retrotec 5000 and 6000 series fans.<\/p>\r\n<form id=\"fanCalCertVars\">\r\n\t<table>\r\n\t<tr>\r\n\t\t<th style=\"text-align: center; width: 25%;\" rowspan=\"2\">No. of Rings\/Ranges<\/th>\r\n\t\t<th style=\"text-align: center; width: 25%;\" rowspan=\"2\">No. Readings<\/th>\r\n\t\t<th style=\"text-align: center; width: 36%;\" colspan=\"2\">Volume Flow Rate<\/th>\r\n\t\t<th rowspan=\"3\" style=\"width: 14%; vertical-align: bottom; border: 0px;\"><input type=\"button\" name=\"Create\" value=\"Create\" onclick=\"makeInput(all)\"><\/th>\r\n\t<\/tr>\r\n\t<tr>\r\n\t\t<th style=\"text-align: center; width: 18%;\">Certificate<\/th>\r\n\t\t<th style=\"text-align: center; width: 18%;\">Software<\/th>\r\n\t<\/tr>\r\n\t<tr>\r\n\t<td><input type=\"text\" name=\"nRanges\" class=\"fanC\"  value=\"1\" onchange=\"changeRanges()\"><\/td>\r\n\t<td><input type=\"text\" name=\"nReadings\" class=\"fanC\" value=\"5\" onchange=\"changeReadings()\"><\/td>\r\n\t<td>\r\n\t\t<input type=\"radio\" id=\"iUnit1\" name=\"iUnit\" value=\"3600\" onchange=\"changeUnits()\" checked=\"checked\"><label for=\"iUnit1\">m&#179;\/h<\/label><br \/>\r\n\t\t<input type=\"radio\" id=\"iUnit2\" name=\"iUnit\" value=\"1\" onchange=\"changeUnits()\"><label for=\"iUnit2\">m&#179;\/s<\/label><br \/>\r\n\t\t<input type=\"radio\" id=\"iUnit3\" name=\"iUnit\" value=\"2118.88\" onchange=\"changeUnits()\"><label for=\"iUnit3\">ft&#179;\/min<\/label>\r\n\t<\/td>\r\n\t<td>\r\n\t\t<input type=\"radio\" id=\"oUnit1\" name=\"oUnit\" value=\"3600\" onchange=\"changeUnits()\" checked=\"checked\"><label for=\"oUnit1\">m&#179;\/h<\/label><br \/>\r\n\t\t<input type=\"radio\" id=\"oUnit2\" name=\"oUnit\" value=\"1\" onchange=\"changeUnits()\"><label for=\"oUnit2\">m&#179;\/s<\/label><br \/>\r\n\t\t<input type=\"radio\" id=\"oUnit3\" name=\"oUnit\" value=\"2118.88\" onchange=\"changeUnits()\"><label for=\"oUnit3\">ft&#179;\/min<\/label>\r\n\t<\/td>\r\n\t<\/tr>\r\n\t<\/table>\r\n\t<div id=\"frer\" style=\"display: none; color: red; margin: 0px 0px 1.5em;\"><\/div>\r\n\t<div id=\"fr0\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr1\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr2\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr3\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr4\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr5\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr6\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr7\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr8\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr9\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr10\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr11\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr12\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr13\" style=\"display: none;\"><\/div>\r\n\t<div id=\"fr14\" style=\"display: none;\"><\/div>\r\n\t<div id=\"frdocalc\" style=\"display: none;\"><input type=\"button\" name=\"doCalc\" value=\"Calculate\" onclick=\"calVar()\" \/><\/div>\r\n<\/form>\r\n\t<div id=\"calVarLSResults\"><\/div>\r\n\t<div id=\"calVarPolyResults\"><\/div>\r\n<\/div>\r\nThis tool has been designed for use when the calibration variables have not been provided by your calibration laboratory.  An assumed air density of 1.2kg\/m<sup>3<\/sup> has been used within the calculator.  ATTMA takes no responsibility for errors.\r\n\t<\/div>\r\n<!-- #custom page content ends here -->\r\n\t\t<\/div>\r\n\t<\/div>\r\n\t<\/div>\r\n<\/div>\r\n<\/body>\r\n<\/html><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Fan Calibration Variable Calculator The ATTMA Trade Association has developed the following Fan Calibration Variable tool to calculate fan calibration<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-830","page","type-page","status-publish","hentry"],"publishpress_future_action":{"enabled":false,"date":"2026-06-02 02:24:20","action":"change-status","newStatus":"draft","terms":[],"taxonomy":"","extraData":[]},"publishpress_future_workflow_manual_trigger":{"enabledWorkflows":[]},"_links":{"self":[{"href":"https:\/\/www.bcta.group\/attma\/wp-json\/wp\/v2\/pages\/830","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bcta.group\/attma\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.bcta.group\/attma\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.bcta.group\/attma\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bcta.group\/attma\/wp-json\/wp\/v2\/comments?post=830"}],"version-history":[{"count":22,"href":"https:\/\/www.bcta.group\/attma\/wp-json\/wp\/v2\/pages\/830\/revisions"}],"predecessor-version":[{"id":5198,"href":"https:\/\/www.bcta.group\/attma\/wp-json\/wp\/v2\/pages\/830\/revisions\/5198"}],"wp:attachment":[{"href":"https:\/\/www.bcta.group\/attma\/wp-json\/wp\/v2\/media?parent=830"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}