def implementationOne(): # constants u0 = 1.0 C_f = 1.0 C_s = 1.0 # create the blocks, with no parameters or parameter functions b0 = b.Block( '0', # name {'u': u0}) # boundary state, this is fixed b1 = b.Block( '1', # name { 'u': 0, 'v': 0 }) # states, and their initial guesses b2 = b.Block( '2', # name {'u': 0}) # states, and their initial guesses # create the fluxes # flux from 0 to 1 F_P = {'C_f': C_f} # dictionary of parameters for the flux # flux is from b0, function is F_u f_u01 = f.Flux(b0, F_u, F_P, 'f_u01') # flux is from b1, function is F_u f_u12 = f.Flux(b1, F_u, F_P, 'f_u12') # flux is from b2, function is F_v # parameter argument is optional, if not used # we don't technically need a name, they really exist # for debugging, and if we want to do something that # requires us to remove the flux, here it is defaulted to '' f_v21 = f.Flux(b2, F_v) # add these fluxes to the right blocks b1.addFlux(f_u01) b1.addFlux(f_v21) b2.addFlux(f_u12) # create the sources S_uP = {'C_s': C_s} S_vP = {'g': g} s_u1 = s.Source(S_u, S_uP, 's_u1') s_u2 = s.Source(S_u, S_uP, 's_u2') # again name argument is optional s_v1 = s.Source(S_v, S_vP) b1.addSource(s_u1) b2.addSource(s_u2) # create and solve the problem problem = p.Problem([b1, b2]) problem.solve() # the blocks now contain their own values, # which are the correct values print "Running first implementation of example code" print b1 print b2
def implementationTwo(): # constants u0 = 1.0 C_f = 1.0 C_s = 1.0 # create the blocks, with no parameters or parameter functions b1 = b.Block( '1', # name { 'u': 0, 'v': 0 }) # states, and their initial guesses b2 = b.Block( '2', # name {'u': 0}) # states, and their initial guesses # create the fluxes # flux from 0 to 1 F_P = {'C_f': C_f} # dictionary of parameters for the flux # flux is from b1, function is F_u f_u12 = f.Flux(b1, F_u, F_P, 'f_u12') # flux is from b2, function is F_v # name argument is optional # parameter argument is optional too, if not used f_v21 = f.Flux(b2, F_v) # add these fluxes to the right blocks b1.addFlux(f_v21) b2.addFlux(f_u12) # create the sources # these are parameters for the new boundary source S_0P = {'C_f': C_f, 'u_0': u0} S_uP = {'C_s': C_s} S_vP = {'g': g} s_u0 = s.Source(S_0, S_0P, 'boundary') s_u1 = s.Source(S_u, S_uP, 's_u1') s_u2 = s.Source(S_u, S_uP, 's_u2') # again name argument is optional s_v1 = s.Source(S_v, S_vP) # add the boundary source in with the other ones b1.addSource(s_u0) b1.addSource(s_u1) b2.addSource(s_u2) # create and solve the problem problem = p.Problem([b1, b2]) problem.solve() # the blocks now contain their own values, # which are the correct values print "Running second implementation of example code" print b1 print b2
def diffusion2D(N): d = 2./float(N) # spacing, delta # initialize with exact solution at t = 0 B = [] for i in range(-1,N+1): for j in range(-1,N+1): x = (i*d+d/2) y = (j*d+d/2) # block has a simple name name = '('+str(i)+','+str(j)+')' B.append(b.Block(name, # initialize to exact solution {'u':math.sin(u_a*math.pi*x)*math.sin(u_b*math.pi*y), 'v':math.sin(v_a*math.pi*x)*math.sin(v_b*math.pi*y)}, None, # no parameter functions {'x':x,'y':y})) # Flux geometry P = {'d':d*d} n = N+2 # add two for the boundaries for i in range(1,n-1): for j in range(1,n-1): # Add fluxes, looping around the edges for k in [(i-1)*n+j, i*n+j-1,(i+1)*n+j, i*n+j+1]: B[i*n+j].addFlux(f.Flux(B[k],difference,P)) interiorBlocks = [B[i*n+j] for i in range(1,n-1) for j in range(1,n-1)] # sort out the boundary blocks boundaryBlocks = [] bcRange = [j for j in range(1,n-1)] + \ [(n-1)*n+j for j in range(1,n-1)] + \ [i*n for i in range(0,n)] + \ [i*n+n-1 for i in range(0,n)] for k in bcRange: B[k].addSource(s.Source(time,None,B[k].name)) boundaryBlocks.append(B[k]) # solve the problem on the interior blocks, # pass in the boundary blocks so they can be updated # at each needed time. # solve the unstead problem at the following timesteps P = p.Problem(interiorBlocks,boundaryBlocks) P.solveUnst(np.linspace(0,tf,10)) # calculate the error for accuracy checking Eu = 0 Ev = 0 for bb in interiorBlocks: (x,y) = (bb.p['x'],bb.p['y']) ue = math.exp(-nu_u*math.pi*math.pi*(u_a*u_a+u_b*u_b)*tf)*math.sin(u_a*math.pi*x)*math.sin(u_b*math.pi*y) ve = math.exp(-nu_v*math.pi*math.pi*(v_a*v_a+v_b*v_b)*tf)*math.sin(v_a*math.pi*x)*math.sin(v_b*math.pi*y) Eu += (bb['u']-ue)**2 Ev += (bb['v']-ve)**2 return (math.sqrt(Eu/(n-2)/(n-2)),math.sqrt(Ev)/(n-2)/(n-2))
def poisson2D(N): """ lets define a uniform square mesh on [-1, 1] x [1, 1] and create boundary blocks as we go, initializing based on the exact solution, and naming the block by its coordinates """ d = 2. / float(N) # spacing, delta X B = [ b.Block('(' + str(i * d - d / 2 - 1) + ',' + str(j * d - d / 2 - 1) + ')', None, u=math.exp((i * d - d / 2 - 1) * (j * d - d / 2 - 1)), v=math.exp((i * d - d / 2 - 1)**2 + (j * d - d / 2 - 1)**2)) for i in range(0, N + 2) for j in range(0, N + 2) ] # interior sources # use the name to get the source values for block in B: (x, y) = eval(block.name) block.addSource( s.Source('const', u=-(x * x + y * y) * math.exp(x * y), v=-4.0 * (x * x + y * y + 1.0) * math.exp(x * x + y * y))) # Flux geometry G = {'type': 'edge', 'd': d * d, 'm': []} n = N + 2 # add two for the boundaries for i in range(1, n - 1): for j in range(1, n - 1): # Add fluxes, no "normals" so we cheat and define them cleverly for k in [(i - 1) * n + j, i * n + j - 1, (i + 1) * n + j, i * n + j + 1]: B[i * n + j].addFlux(f.Flux(B[k], 'difference', G)) B[i * n + j].state['u'] = 0. B[i * n + j].state['v'] = 0. interiorBlocks = [ B[i * n + j] for i in range(1, n - 1) for j in range(1, n - 1) ] # solve the problem on the interior blocks P = p.Problem(interiorBlocks) P.solve() Eu = math.sqrt( sum([(math.exp(eval(block.name)[0] * eval(block.name)[1]) - block.state['u'])**2 for block in interiorBlocks]) / (n - 2) / (n - 2)) Ev = math.sqrt( sum([(math.exp(eval(block.name)[0]**2 + eval(block.name)[1]**2) - block.state['v'])**2 for block in interiorBlocks]) / (n - 2) / (n - 2)) return (Eu, Ev)
def diff2D(N): """ lets define a uniform square mesh on [-1, 1] x [1, 1] and create boundary blocks as we go, initializing based on the exact solution, and naming the block by its coordinates """ u_a = 1 u_b = 1 nu_u = 1 v_a = 1 v_b = 1 nu_v = 0.5 tf = 1 d = 2. / float(N) # spacing, delta # initialize with exact solution at t = 0 B = [b.Block('('+str(i*d-d/2-1)+','+str(j*d-d/2-1)+')',None, u = math.sin(u_a*math.pi*(i*d-d/2-1))*math.sin(u_b*math.pi*(j*d-d/2-1)), v = math.sin(v_a*math.pi*(i*d-d/2-1))*math.sin(v_b*math.pi*(j*d-d/2-1))) \ for i in range(0,N+2) for j in range(0,N+2)] # Flux geometry G = {'type': 'edge', 'd': d * d, 'm': []} n = N + 2 # add two for the boundaries for i in range(1, n - 1): for j in range(1, n - 1): # Add fluxes, no "normals" so we cheat and define them cleverly for k in [(i - 1) * n + j, i * n + j - 1, (i + 1) * n + j, i * n + j + 1]: B[i * n + j].addFlux(f.Flux(B[k], 'difference', G)) B[i * n + j].state['u'] = 0. B[i * n + j].state['v'] = 0. interiorBlocks = [ B[i * n + j] for i in range(1, n - 1) for j in range(1, n - 1) ] boundaryBlocks = [] bcRange = [j for j in range(1,n-1)] + \ [(n-1)*n+j for j in range(1,n-1)] + \ [i*n for i in range(0,n)] + \ [i*n+n-1 for i in range(0,n)] for k in bcRange: (x, y) = eval(B[k].name) B[k].addSource(s.Source('time', \ u = lambda t: math.exp(-nu_u*math.pi*math.pi*(u_a*u_a+u_b*u_b)*t)*math.sin(u_a*math.pi*x)*math.sin(u_b*math.pi*y), \ v = lambda t: math.exp(-nu_v*math.pi*math.pi*(v_a*v_a+v_b*v_b)*t)*math.sin(v_a*math.pi*x)*math.sin(v_b*math.pi*y))) boundaryBlocks.append(B[k]) # solve the problem on the interior blocks P = p.Problem(interiorBlocks, boundaryBlocks) P.solveUnst(0, tf, 10) # P.printSolution() Eu = 0 Ev = 0 t = tf for bb in interiorBlocks: (x, y) = eval(bb.name) ue = math.exp(-nu_u * math.pi * math.pi * (u_a * u_a + u_b * u_b) * t) * math.sin( u_a * math.pi * x) * math.sin(u_b * math.pi * y) ve = math.exp(-nu_v * math.pi * math.pi * (v_a * v_a + v_b * v_b) * t) * math.sin( v_a * math.pi * x) * math.sin(v_b * math.pi * y) Eu += (bb.state['u'] - ue)**2 Ev += (bb.state['v'] - ve)**2 # Eu = math.sqrt(sum([(math.exp(-nu_u*math.pi*math.pi*(u_a*u_a+u_b*u_b)*tf)*math.sin(u_a*math.pi*block.name[0])*math.sin(u_b*math.pi*block.name[1]) \ # -block.state['u'])**2 for block in interiorBlocks])/(n-2)/(n-2)) # Ev = math.sqrt(sum([(math.exp(-nu_v*math.pi*math.pi*(v_a*v_a+v_b*v_b)*tf)*math.sin(v_a*math.pi*block.name[0])*math.sin(v_b*math.pi*block.name[1]) \ # -block.state['v'])**2 for block in interiorBlocks])/(n-2)/(n-2)) return (math.sqrt(Eu / (n - 2) / (n - 2)), math.sqrt(Ev) / (n - 2) / (n - 2))
""" Block Initialization """ w1 = b.Block('water1', 'constWater', T=13) w2 = b.Block('water2', 'constWater', T=13) a1 = b.Block('air1', 'constAir', T=20) a2 = b.Block('air2', 'constAir', T=20) w1.mdot = w0.mdot w2.mdot = w1.mdot a1.mdot = a0.mdot a2.mdot = a1.mdot a2.addSource(Sa) w2.addSource(Sw) a1.addFlux(f.Flux(aExt, 'heatCondSimple', extGeom)) a1.addFlux(f.Flux(aInt, 'heatCondSimple', intGeom)) a1.addFlux(f.Flux(w1, 'heatCondSimple', tubeGeom)) a1.addFlux(f.Flux(a0, 'heatConvection')) w1.addFlux(f.Flux(a1, 'heatCondSimple', tubeGeom)) w1.addFlux(f.Flux(w0, 'heatConvection')) a2.addFlux(f.Flux(a1, 'heatConvection')) w2.addFlux(f.Flux(w1, 'heatConvection')) """ Problem Initialization """ # Start the problem with solvable blocks, which # are all the blocks except the first two ICSolar = p.Problem([a1, a2, w1, w2]) ICSolar.solve() ICSolar.printSolution()
def implementationThree(): # constants u0 = 1.0 C_f = 1.0 C_s = 1.0 # create the blocks, with no parameters or parameter functions b0 = b.Block( '0', # name {'u': u0}) # boundary state, this is fixed b1 = b.Block( '1', # name { 'u': 0, 'v': 0 }, # states, and their initial guesses {'g': g}, # parameter functions { 'C_f': C_f, 'C_s': C_s }) # parameter constants b2 = b.Block( '2', # name {'u': 0}, # states, and their initial guesses None, # no parameter functions are needed in this block { 'C_f': C_f, 'C_s': C_s }) # parameter constants # create the fluxes # flux from 0 to 1 # flux is from b0, function is F_u # no parameter dictionaries needed f_u01 = f.Flux(b0, F_u3) # flux is from b1, function is F_u f_u12 = f.Flux(b1, F_u3) # flux is from b2, function is F_v # name argument is optional # parameter argument is optional too, if not used f_v21 = f.Flux(b2, F_v) # add these fluxes to the right blocks b1.addFlux(f_u01) b1.addFlux(f_v21) b2.addFlux(f_u12) # create the sources # no parameters or names needed, # they come from the plots s_u1 = s.Source(S_u3) s_u2 = s.Source(S_u3) s_v1 = s.Source(S_v3) b1.addSource(s_u1) b2.addSource(s_u2) # create and solve the problem problem = p.Problem([b1, b2]) problem.solve() # the blocks now contain their own values, # which are the correct values print "Running third implementation of example code" print b1 print b2
def poisson2D(N): """ lets define a uniform square mesh on [-1, 1] x [1, 1] and create boundary blocks as we go, initializing based on the exact solution, and naming the block by its coordinates """ d = 2. / float(N) # spacing, Delta x = Delta y # For N blocks in each direction, N+2 blocks since we have a constant block on each end surrounding the domain # a ghost cell approach, there are no parameters in this case, or parameter functions needed # the center of the cell is at (i*d+d/2,j*d+d/2) B = [] for i in range(-1, N + 1): for j in range(-1, N + 1): x = (i * d + d / 2) y = (j * d + d / 2) # block has a simple name name = '(' + str(i) + ',' + str(j) + ')' B.append( b.Block( name, { 'u': math.exp(x * y), 'v': math.exp(x**2 + y**2) }, # initialize to exact solution None, # no parameter functions { 'x': x, 'y': y })) # parameter of coordinates # interior sources, -f['u'] and -f['v'] for block in B: (x, y) = (block.p['x'], block.p['y']) block.addSource( s.Source( s.constant, # standard function defined in source.py { 'u': -(x * x + y * y) * math.exp(x * y), 'v': -4.0 * (x * x + y * y + 1.0) * math.exp(x * x + y * y) }, # parameters 'constant')) # name # Flux geometry P = {'d': d * d} # divide by delta x^2 in the end n = N + 2 # add two for the boundaries for i in range(1, N + 1): for j in range(1, N + 1): # Add fluxes, figuring out which neighbors to connect to for k in [(i - 1) * n + j, i * n + j - 1, (i + 1) * n + j, i * n + j + 1]: B[i * n + j].addFlux(f.Flux(B[k], difference, P)) interiorBlocks = [ B[i * n + j] for i in range(1, N + 1) for j in range(1, N + 1) ] # solve the problem on the interior blocks P = p.Problem(interiorBlocks) P.solve() # compute the L-2 error against the exact solution for both variables Eu = math.sqrt( sum([(math.exp(block.p['x'] * block.p['y']) - block['u'])**2 for block in interiorBlocks]) / (n - 2) / (n - 2)) Ev = math.sqrt( sum([(math.exp(block.p['x']**2 + block.p['y']**2) - block['v'])**2 for block in interiorBlocks]) / (n - 2) / (n - 2)) return (Eu, Ev)
# add in the inflow block to make it easy to connect blocks # These blocks are not used in the solve water.append(w0) air.append(a0) #### Initialize the blocks we will solve on for i in range(1, 2 * n + 2): # Every block is named for its material in this case water.append(b.Block('water' + str(i), 'water')) air.append(b.Block('air' + str(i), 'air')) if (i % 2 == 1): # odd regions are "tube" regions # Water tube has one flux for heat conduction water[i].addFlux( f.Flux(water[i], air[i], 'heatConduction', tubeGeom)) # Air has three, corresponding to the windows and the water-tube air[i].addFlux(f.Flux(water[i], air[i], 'heatConduction', tubeGeom)) air[i].addFlux(f.Flux(aInt, air[i], 'heatConduction', IGUGeom)) air[i].addFlux(f.Flux(aExt, air[i], 'heatConduction', windowGeom)) else: # These are "module" region water[i].addSource(Sw) air[i].addSource(Sa) # These are the connectivity between regions, each block takes heat # from the block "below" it air[i].addFlux(f.Flux(air[i - 1], air[i], 'heatConvection')) water[i].addFlux(f.Flux(water[i - 1], water[i], 'heatConvection')) # Initialize the state of every block to be the same for now