# This text is a Python program (http://www.python.org). # The first part calculates failure probabilities and redundancies. # The second part calculates sizes of the convergent assembly stages. # The third part calculates coolant flow and pressure drop # If Appendix A is copied to a file and executed with a Python interpreter # it will print the following: """ Assuming a failure rate of 0.03 per micron^3 per year... And an acceptable factory failure rate of 0.03 per year... Nanoblock (0.2 micron) failure rate is 2.44e-004 per year If 2^54 0.4-micron stages all have to work, each stage needs a failure rate of 1.69x10^-18 That requires substage redundancy of 5 (plus the 8 required) If 2^51 0.8-micron stages all have to work, each stage needs a failure rate of 1.35x10^-17 That requires substage redundancy of 7 (plus the 8 required) If 2^48 1.6-micron stages all have to work, each stage needs a failure rate of 1.08x10^-16 That requires substage redundancy of 11 (plus the 8 required) If the first three stages are 9-in-8 redundant [1,1,1,0,0,0...] The chance of factory failure is 2.73x10^-4 If the first three stages are 9-in-8 redundant and nanoblocks fail 2X as often The chance of factory failure is 6.71x10^-2 If the first four stages are 9-in-8 redundant The chance of factory failure is 1.19x10^-21 If the first four stages are 9-in-8 redundant and nanoblocks fail 10X as often The chance of factory failure is 1.09x10^-5 If the first stage isn't and the next 4 are [0,1,1,1,1,0,0...] The chance of factory failure is 3.86x10^-8 If the first 2 aren't and the next 5 are [0,0,1,1,1,1,1,0,0...] The chance of factory failure is 9.57x10^-1 If the first 2 aren't and the next 5 are [0,0,1,1,1,1,1,0,0...] and nanoblocks fail 1/2 as often The chance of factory failure is 1.92x10^-9 If the first 2 aren't and the next 6 are The chance of factory failure is 6.51x10^-10 If the first 3 aren't and the next 16 are The chance of factory failure is 1.00x10^0 For example, failure rates at each stage for [0,1,1,1,1,0,0...] Stage 0.2 p 2.44x10^-4 Stage 0.4 p 1.95x10^-3 Stage 0.8 p 1.35x10^-4 Stage 1.6 p 6.59x10^-7 Stage 3.2 p 1.56x10^-11 Stage 6.4 p 8.78x10^-21 Stage 12.8 p 7.02x10^-20 Stage 25.6 p 5.62x10^-19 Stage 51.2 p 4.50x10^-18 Stage 102.4 p 3.60x10^-17 Stage 204.8 p 2.88x10^-16 Stage 409.6 p 2.30x10^-15 Stage 819.2 p 1.84x10^-14 Stage 1638.4 p 1.47x10^-13 Stage 3276.8 p 1.18x10^-12 Stage 6553.6 p 9.43x10^-12 Stage 13107.2 p 7.54x10^-11 Stage 26214.4 p 6.03x10^-10 Stage 52428.8 p 4.83x10^-9 Stage 104857.6 p 3.86x10^-8 Factory sizes... Small cooling gap volume = 4.673892e-003 m^3 Level 1, width 3.63e-005 height 1.62e-005 depth 2.54e-005 product size 3.2e-006 4.39805e+012 copies, volume of tube 0.00138414, surface of tube 1392.74 Volume of cooling 4.986e-003 m^3, surface area of walls 3.259e+003 Level 2, width 6.07e-005 height 3.63e-005 depth 6.48e-005 product size 6.4e-006 5.49756e+011 copies, volume of tube 0.00350565, surface of tube 1368.53 Volume of cooling 9.330e-003 m^3, surface area of walls 2.498e+003 Level 3, width 0.000149 height 6.07e-005 depth 1.45e-004 product size 1.28e-005 6.87195e+010 copies, volume of tube 0.00392979, surface of tube 769.778 Volume of cooling 8.097e-003 m^3, surface area of walls 1.167e+003 Level 4, width 0.00033 height 0.000149 depth 2.43e-004 product size 2.56e-005 8.58993e+009 copies, volume of tube 0.00328492, surface of tube 319.882 Volume of cooling 9.087e-003 m^3, surface area of walls 6.010e+002 Level 5, width 0.000565 height 0.00033 depth 5.98e-004 product size 5.12e-005 1.07374e+009 copies, volume of tube 0.00404231, surface of tube 198.116 Volume of cooling 1.278e-002 m^3, surface area of walls 4.127e+002 Level 6, width 0.00135 height 0.000565 depth 1.32e-003 product size 0.000102 1.34218e+008 copies, volume of tube 0.00446645, surface of tube 109.747 Volume of cooling 1.144e-002 m^3, surface area of walls 1.948e+002 Level 7, width 0.00296 height 0.00135 depth 2.26e-003 product size 0.000205 1.67772e+007 copies, volume of tube 0.00382159, surface of tube 46.7477 Volume of cooling 1.248e-002 m^3, surface area of walls 9.990e+001 Level 8, width 0.00516 height 0.00296 depth 5.42e-003 product size 0.00041 2.09715e+006 copies, volume of tube 0.00457898, surface of tube 28.1457 Volume of cooling 1.676e-002 m^3, surface area of walls 6.583e+001 Level 9, width 0.0121 height 0.00516 depth 1.18e-002 product size 0.000819 262144 copies, volume of tube 0.00500312, surface of tube 15.409 Volume of cooling 1.531e-002 m^3, surface area of walls 3.129e+001 Level 10, width 0.0262 height 0.0121 depth 2.06e-002 product size 0.00164 32768 copies, volume of tube 0.00435825, surface of tube 6.68877 Volume of cooling 1.641e-002 m^3, surface area of walls 1.601e+001 Level 11, width 0.0463 height 0.0262 depth 4.84e-002 product size 0.00328 4096 copies, volume of tube 0.00511565, surface of tube 3.94087 Volume of cooling 2.129e-002 m^3, surface area of walls 1.022e+001 Level 12, width 0.107 height 0.0463 depth 1.05e-001 product size 0.00655 512 copies, volume of tube 0.00553979, surface of tube 2.13745 Volume of cooling 1.972e-002 m^3, surface area of walls 4.886e+000 Level 13, width 0.23 height 0.107 depth 1.85e-001 product size 0.0131 64 copies, volume of tube 0.00489492, surface of tube 0.941759 Volume of cooling 2.088e-002 m^3, surface area of walls 2.494e+000 Level 14, width 0.411 height 0.23 depth 4.28e-001 product size 0.0262 8 copies, volume of tube 0.00565231, surface of tube 0.54544 Volume of cooling 2.635e-002 m^3, surface area of walls 1.553e+000 Level 15, width 0.937 height 0.411 depth 9.20e-001 product size 0.0524 1 copies, volume of tube 0.00607645, surface of tube 0.293597 Volume of cooling 2.467e-002 m^3, surface area of walls 7.458e-001 Total volumes: cooling 0.234276 tubes 0.0656543 modules 0.0546845 total 0.354615 Total surface: tubes 4263.64 walls 8365.56 Max path length 1.72919; total tube length 1.60277e+008 Pressure for 16384 blocks is 36120197 Pa (356.5 atm), flow 0.066602 m/s Pressure for 2048 blocks is 564378 Pa (5.6 atm), flow 0.008325 m/s Pressure for 512 blocks is 35273 Pa (0.3 atm), flow 0.002081 m/s """ from math import * ################################## # Part 1: Failure Probability ################################## # Due to extremely large numbers, this section does most of its bookkeeping # with logarithms of numbers. For many functions, both versions are given. # log(a*b) = log(a)+log(b). log(a^b) = log(a)*b. # Log base 10 of x (Not in math library) def exp10(x): return exp(x*log(10)) # Add two log'd numbers without taking antilog of larger number def addLogs(a, b): "Log of sum of two #'s, where a and b are their logs" if (a < b): return b+log10(exp10(a-b)+1) else: return a+log10(exp10(b-a)+1) # Multiply two log'd numbers (just add logs) def mulLogs(a, b): "just add" return a+b # Factorial of n 1x2x...xn def fact(n): "n!" ans = 1 for i in range(2,n+1): ans=ans*i return ans # Log of factorial of n def logfact(n): "log10(n!)" ans = log10(1) for i in range(2,n+1): ans=mulLogs(ans, log10(i)) return ans # Print the exponent of logs of very large or small numbers def StrExp(x): "Print log'd number" basis = floor(x) return "%.2fx10^%.0f"%(exp10(x-basis), basis) # Invert probability, e.g. success->failure def LogInvLogP(lps): "Given lps = log(p), return log(1-p)" # Floating point arithmetic can represent 0.00...01 with dozens of zeros, # but can't represent 0.99....99 with dozens of nines. The log of such a # number looks like -4.3x10^-75, which floating point can represent. # For x extremely close to 0 or 1, an approximation # of 1-x good to several decimal places can be obtained by simply # multiplying log(x) by a constant. if lps < -10: #close to 0 res = exp10(lps)*(log10(0.9999999999)/0.0000000001) return res elif lps < -1e-10: #in the middle (normal math) return log10(1-exp10(lps)) elif lps < 0: #close to 1 return log10(lps/(log10(0.9999999999)/0.0000000001)) else: #very close to 1 return -1000 def ScaleFail(vScale, pFail): "multiply success probabilities: return 1-(1-p)^n" return 1-pow(1-pFail,vScale) def LengthScaleFail(lScale, pFail): "just cube the length to get the scale" return ScaleFail(pow(lScale, 3), pFail) def logScaleFail(vScale, pFail): "scale failure prob, then return the log of that" return LogInvLogP(log10(1-pFail)*vScale) """ Binomial formula: n! X n-X P(X successes in n trials) = ________ p q X!(n-X!) """ def pSucXNP(x, n, p): "Trial has success prob. p, return prob of exactly x success in n trials" return fact(n)/(fact(x)*fact(n-x))*pow(p,x)*pow(1-p,n-x) def pSucXNPfail(x, n, p): "Trial has fail prob. p, return prob of exactly x success in n trials" return fact(n)/(fact(x)*fact(n-x))*pow(1-p,x)*pow(p,n-x) def logpSucXNlogP(x,n,logp): "Trial has success prob. logp, return logprob of exactly x success in n trials" return logfact(n)-logfact(x)-logfact(n-x)+logp*x+LogInvLogP(logp)*(n-x) def logpSucXNlogPfail(x,n,logp): "Trial has fail prob. logp, return logprob of exactly x success in n trials" return logfact(n)-logfact(x)-logfact(n-x)+LogInvLogP(logp)*x+logp*(n-x) def pNotXleftNtrialPfail(x,n,p): "sum the binomial: return P(fewer than x left out of n with failure p)" pTooFew = 0 for i in range(0, x): pSucNow = pSucXNPfail(i, n, p) pTooFew = pTooFew + pSucNow return pTooFew def logpNotXleftNtrialLogPfail(x,n,logp): "sum the binomial: return logP(fewer than x left out of n with failure logp)" logpTooFew = logpSucXNlogPfail(x-1, n, logp) for i in range(0, x-1): logpSucNow = logpSucXNlogPfail(i, n, logp) logpTooFew = addLogs(logpTooFew, logpSucNow) return logpTooFew def RedundantXP(x, p): "Just for testing" for i in range(0,30) + range(30,100,10): logpxf = logpNotXleftNtrialLogPfail(x,x+i,log10(p)) print "%d redundant, %f log fail %s fail"% \ (i, logpxf, StrExp(logpxf)) def NeedRedundantPlus8(pFailOne, logpFailRequired): "See how many redundant units (plus 8 required) I need for desired failure rate" i = 0 while 1: logFailI = logpNotXleftNtrialLogPfail(8,8+i,log10(pFailOne)) if logFailI < logpFailRequired: return i i=i+1 def logMultistageRedundancy(list, pInit, show=0): "Cumulative of redundant and nonredundant stages; list has # of redundant" list = list + [0]*(19-len(list)) logpFail = log10(pInit) s = 0.2 if show: print "Stage %.1f p %s"%(s, StrExp(logpFail)) for n in list: logpFail = logpNotXleftNtrialLogPfail(8, 8+n, logpFail) s=s*2 if show: print "Stage %.1f p %s"%(s, StrExp(logpFail)) return logpFail # Print the answers... print MicronPerYear = OKFail = 0.03 print "Assuming a failure rate of %.2f per micron^3 per year..."%MicronPerYear print "And an acceptable factory failure rate of %.2f per year..."%OKFail NanoblockPerYear = LengthScaleFail(0.2,MicronPerYear) print "Nanoblock (0.2 micron) failure rate is %.2e per year"%NanoblockPerYear LogFailRate2e54 = logScaleFail(1/(2.0**54), OKFail) print "If 2^54 0.4-micron stages all have to work, each stage needs" print " a failure rate of %s"%StrExp(LogFailRate2e54) print "That requires substage redundancy of %d (plus the 8 required)"%\ NeedRedundantPlus8(NanoblockPerYear, LogFailRate2e54) Stage1PerYear = LengthScaleFail(0.4,MicronPerYear) LogFailRate2e51 = logScaleFail(1/(2.0**51), OKFail) print "If 2^51 0.8-micron stages all have to work, each stage needs" print " a failure rate of %s"%StrExp(LogFailRate2e51) print "That requires substage redundancy of %d (plus the 8 required)"%\ NeedRedundantPlus8(Stage1PerYear, LogFailRate2e51) Stage2PerYear = LengthScaleFail(0.8,MicronPerYear) LogFailRate2e48 = logScaleFail(1/(2.0**48), OKFail) print "If 2^48 1.6-micron stages all have to work, each stage needs" print " a failure rate of %s"%StrExp(LogFailRate2e48) print "That requires substage redundancy of %d (plus the 8 required)"%\ NeedRedundantPlus8(Stage2PerYear, LogFailRate2e48) print print "If the first three stages are 9-in-8 redundant [1,1,1,0,0,0...]" print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([1,1,1], NanoblockPerYear)) print "If the first three stages are 9-in-8 redundant" print " and nanoblocks fail 2X as often" print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([1,1,1], NanoblockPerYear*2)) print "If the first four stages are 9-in-8 redundant" print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([1,1,1,1], NanoblockPerYear)) print "If the first four stages are 9-in-8 redundant" print " and nanoblocks fail 10X as often" print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([1,1,1,1], NanoblockPerYear*10)) print "If the first stage isn't and the next 4 are [0,1,1,1,1,0,0...]" print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([0,1,1,1,1], NanoblockPerYear)) print "If the first 2 aren't and the next 5 are [0,0,1,1,1,1,1,0,0...]" print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([0,0,1,1,1,1,1], NanoblockPerYear)) print "If the first 2 aren't and the next 5 are [0,0,1,1,1,1,1,0,0...]" print " and nanoblocks fail 1/2 as often" print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([0,0,1,1,1,1,1], NanoblockPerYear/2)) print "If the first 2 aren't and the next 6 are " print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([0,0,1,1,1,1,1,1], NanoblockPerYear)) print "If the first 3 aren't and the next 16 are" print " The chance of factory failure is %s"%\ StrExp(logMultistageRedundancy([0,0,0]+[1]*16, NanoblockPerYear)) print print "For example, failure rates at each stage for [0,1,1,1,1,0,0...]" logMultistageRedundancy([0,1,1,1,1], NanoblockPerYear, 1) ####################################### # Part 2: Sizes and volumes at each stage ####################################### # Stage 0: 16.2 x 16.4 x 11.7 plus 1 micron cooling gap L0Width = 16.2e-6 L0Height = 11.7e-6 # Height should be smallest; that's how they stack. L0Depth = 16.4e-6 L0Gap = 1.0e-6 #cooling gap between production modules L0BlockSize = 3.2e-6 #Basic module produces 3.2 micron product # Assume CA manipulator takes 0.1 times the size of the subproduct cube HandlingGapFrac = 0.1 class Dimensions: def __init__(self, nLevels): "Set and compute dimensions and volumes for Production Module" self.nLevels = nLevels self.thisLevel = 0 self.width = L0Width self.height = L0Height+L0Gap #Leave space for cooling when you stack'em self.modHeight = L0Height #Used only in level 0 self.depth = L0Depth self.blockSize = L0BlockSize self.nCopies = 8.0**nLevels / 2 #Each module produces 2 blocks self.coolingVolume = self.nCopies * self.width * self.depth * L0Gap print "Small cooling gap volume = %e m^3"%self.coolingVolume def NextLevel(self): self.thisLevel = self.thisLevel + 1 self.nCopies = 8.0**(self.nLevels - self.thisLevel) # Remember dimensions of sublevel subWidth, subHeight, subDepth, subBlockSize = \ self.width, self.height, self.depth, self.blockSize # Special cases for first level if self.thisLevel == 1: #No assembly, just transport self.blockSize = subBlockSize self.tubeWidth = subBlockSize*(1+HandlingGapFrac) self.depth = subHeight*2 # Only 4 basic modules, 2 each side of tube inPortArea = 4 * subBlockSize**2 #ports for sub-blocks to enter else: # Assemble, then transport; needs bigger tube, more modules self.blockSize = subBlockSize * 2 self.tubeWidth = subBlockSize*(3+HandlingGapFrac) self.depth = subHeight*4 # 8 sublevels, 4 on each side of tube inPortArea = 8 * subBlockSize**2 #Compute the rest of the basic dimensions self.width = subDepth*2+self.tubeWidth self.height = subWidth # Compute the derived dimensions (for all copies) tubeVolume = self.tubeWidth**2 * self.depth self.tubesVolume = self.nCopies * tubeVolume tubeArea = 4*(self.depth * self.tubeWidth) - inPortArea self.tubesArea = self.nCopies * tubeArea self.coolingVolume = self.nCopies * self.tubeWidth*self.depth*self.height \ - self.tubesVolume # Face of sub-levels adjacent to tubes needs to be walled off. # This is an over-estimate. self.wallArea = (self.depth * self.height - inPortArea) * 2 * self.nCopies # Print numbers for this level... print "Level %d, width %.3g height %.3g depth %.2e "\ "product size %.3g"% \ (self.thisLevel, self.width, self.height, self.depth, self.blockSize) print " %g copies, volume of tube %g, surface of tube %g"% \ (self.nCopies, self.tubesVolume, self.tubesArea) print " Volume of cooling %.3e m^3, surface area of walls %.3e"% \ (self.coolingVolume, self.wallArea) def PrintDimensions(MaxLevel): "print width, height, depth, product size of stage, volumes, etc" #Initialize dimensions for production module dims = Dimensions(MaxLevel) #Set up summing variables TotalModuleVolume = dims.nCopies * dims.width * dims.depth * dims.modHeight TotalCoolingVolume = dims.coolingVolume TotalGapSurface = 0 TotalTubeVolume = 0 # No tubes yet at level 0 TotalTubeArea = 0 TotalTubeLength = 0 # Total for all tubes in system PathLength = 0 #Single path through all levels TotalWallArea = 0 #Area of wall adjacent to tubes; Level 0 wall is computers while dims.thisLevel < MaxLevel: dims.NextLevel() TotalTubeLength = TotalTubeLength + dims.depth * dims.nCopies PathLength = PathLength + dims.depth TotalTubeVolume = TotalTubeVolume + dims.tubesVolume TotalTubeArea = TotalTubeArea + dims.tubesArea TotalCoolingVolume = TotalCoolingVolume + dims.coolingVolume TotalWallArea = TotalWallArea + dims.wallArea print "Total volumes: cooling %g tubes %g modules %g total %g"% \ (TotalCoolingVolume, TotalTubeVolume, TotalModuleVolume, \ TotalCoolingVolume+TotalTubeVolume+TotalModuleVolume) print "Total surface: tubes %g walls %g"%(TotalTubeArea, TotalWallArea) print "Max path length %g; total tube length %g"% \ (PathLength, TotalTubeLength) # Print the answers... print print "Factory sizes..." PrintDimensions(15) ####################################### # Part 3: Coolant flow ####################################### # Coolant viscosity, Ns/m^2 VisNSpM2 = 8e-4 # Heat capacity, J/m^3 CoolJpM3 = 1.2e8 # Heat per block, W HeatBlkW = 8e-9 # Length per block, m LengthBlkM = 16.2e-6 # Cooling channel width, m WidthBlkM = 16.4e-6 # Cooling channel height (gap between modules), m HeightChanM = 1e-6 # Formula for rectangular flow, from # http://www.geocities.com/invitation21/DPZT_flow.htm # a, b = 1/2 width, height of the duct, a >> b def fa_b(a, b): # Dimensionless return 1 - (192*a / (pi**5 * b) * tanh(pi*b / (2*a))) def DeltaP(width, height, length, velocity): # Make sure units match! a = 0.5*width b = 0.5*height return 3*VisNSpM2*length*velocity/(a*a * fa_b(a,b)) def PascalToAtm(pres): return pres/101325 def PascalToPSI(pres): return PascalToAtm(pres)*14.2 def FlowRateNBlocks(n): # Flow velocity power = n*HeatBlkW volume = n*WidthBlkM*LengthBlkM*HeightChanM timeToHeat = volume*CoolJpM3/power # The fluid must flow the length of the channel in timeToHeat return n*LengthBlkM/timeToHeat def DeltaPNBlocks(n): return DeltaP(WidthBlkM, HeightChanM, n*LengthBlkM, FlowRateNBlocks(n)) print for i in [16384, 2048, 512]: pPa = DeltaPNBlocks(i) print "Pressure for %d blocks is %d Pa (%.1f atm), flow %f m/s" %\ (i, pPa, PascalToAtm(pPa), FlowRateNBlocks(i))