64 views

Original Title: Lab09wsolns

Uploaded by Naimun Siraj

- main-20130724
- Algebra 2 with Trigonometry Syllabus
- applicationsoflinearalgebra.pdf
- Examples NLS
- Linear Algebra NYC
- GMAT Workbook & Error Log
- lessonplans 2
- c2-0
- Solving Linear Systems Using Interval Arithmetic Approach
- 6th Grade Unit 1 Study Guide
- Constraints
- MATLAB Coursework
- 06FMA393AMidterm2
- english 313- lesson plan
- Pi Voting
- Unit 1
- ece syll effective 2011
- Pure Mathematics Unit 1 Module 2 Worksheetdocx
- Ch01_SE 1.6
- linear equation

You are on page 1of 21

1.1 Matrix Inversion (Lab #8)

Solve for :

Substitute

* Notes based on Chapters 9 and 11 from Applied Numerical Methods with MATLAB for Engineers and Scientists, Steven C. Chapra, 3rd Edition, McGraw-Hill, 2012.

, where:

where

and

and

and

are:

Sequential process of removing unknowns using forward elimination and back substitution.

For a system in the form , express as:

For each row, subtract multiples of previous rows to eliminate coefficients until you get an upper triangular matrix. i. Eliminate from row 2:

where:

ii. Eliminate

from row 3:

where:

iii. Eliminate

from row 3:

where:

Coding Gauss Elimination from numpy import size,append,zeros from sys import exit def GaussNaive(A,B): # GaussNaive: Naive Gauss Elimination # X = GaussNaive(A,B): Gauss elimination without pivoting. # input: # A = coefficient matrix # B = constant matrix # output: # X = solution vector # Check that coefficient matrix is square m = size(A,0) n = size(A,1) if m != n: print '\nMatrix A must be square.\n' exit(0) # Concatenate A and B Aug = append(A,B,1) nB = n+1 # Forward elimination for k in range(0,n-1): for i in range(k+1,n): factor = Aug[i,k]/Aug[k,k] for j in range(k,nB): Aug[i,j] = Aug[i,j]-factor*Aug[k,j] # Back substitution X = zeros((n,1))

X[n-1] = Aug[n-1,n]/Aug[n-1,n-1] for i in range(n-2,-1,-1): X[i] = Aug[i,n] for j in range(i+1,n): X[i] = X[i]-Aug[i,j]*X[j] X[i] = X[i]/Aug[i,i] # Return solution return X

Generate the coefficient matrix , and vector , and feed to the GaussNaive function shown above: from GaussNaive import GaussNaive from numpy import array # For same problem that we solved with other methods: # 2x + 3y = 14 # -4x + y = 28 A = array([[2.,3.],[-4.,1.]]) B = array([[14.],[28.]]) X = GaussNaive(A,B) print X The output is: [[-5.] [ 8.]] 1.5.3 Pivoting

What happens if a coefficient along the diagonal of the matrix is zero? Example: Solve

In matrix form:

Zeros in the diagonal will cause division by zero in the forward elimination step.

The solution to this is to switch rows such that the largest element in the column end up in the diagonal (pivoting). In this example, switch rows 1 and 2:

Coding Gauss Elimination with Pivoting from numpy import size,append,zeros,argmax from sys import exit def GaussPivot(A,B): # GaussNaive: Naive Gauss Elimination # X = GaussNaive(A,B): Gauss elimination without pivoting. # input: # A = coefficient matrix # B = constant matrix # output: # X = solution vector # Check that coefficient matrix is square m = size(A,0) n = size(A,1) if m != n: print '\nMatrix A must be square.\n' exit(0) # Concatenate A and B Aug = append(A,B,1) nB = n+1 # Forward elimination for k in range(0,n-1): # partial pivoting # i is the index of max value in column k (within # the k to n-1 rows) i = argmax(abs(Aug[k:n-1,k])) ipr = i+k # find the true index if ipr != k: print 'Exchanging rows %i and %i\n' % (k,ipr) Aug[[k,ipr],:] = Aug[[ipr,k],:]

only difference

for i in range(k+1,n): factor = Aug[i,k]/Aug[k,k] for j in range(k,nB): Aug[i,j] = Aug[i,j]-factor*Aug[k,j] # Back substitution X = zeros((n,1)) X[n-1] = Aug[n-1,n]/Aug[n-1,n-1]

for i in range(n-2,-1,-1): X[i] = Aug[i,n] for j in range(i+1,n): X[i] = X[i]-Aug[i,j]*X[j] X[i] = X[i]/Aug[i,i] # Return solution return X Solve example problem using this code: from GaussNaive import GaussNaive from GaussPivot import GaussPivot from numpy import array # Problem for Gauss elimination with pivoting: # 2y + z = -8 # x - 2y - 3z = 0 # -x + y + 2z = 3 A = array([[0.,2.,1.],[1.,-2.,-3.],[-1.,1.,2.]]) B = array([[-8.],[0.],[3.]]) XN = GaussNaive(A,B) XP = GaussPivot(A,B) print 'X_naive:' print XN print 'X_pivot:' print XP x = XP[0] y = XP[1] z = XP[2] print 'vector B:' print 2.*y+z, x-2.*y-3.*z, -x+y+2.*z The output from this script is: Exchanging rows 0 and 1 X_naive: [[ nan] [ nan] [ nan]] X_pivot: [[-4.] [-5.] [ 2.]] vector B: [-8.] [ 0.] [ 3.]

1.6 Example: Model of a Heated Rod For a long thin rod positioned between two walls that are held at constant temperature, the steadystate energy conservation equation is written as:

where = temperature (C), = distance along the rod (m), = a heat transfer coefficient between the rod and the surrounding air (m-2), and = air temperature (C).

when

= 0.01,

= 20,

= 40 and

= 200.

But another way of solving it, is by using finite differences to transform the differential equation into a system of linear algebraic equations, and use any of the methods described so far to solve for the unknowns. Step 1: Divide the rod into a series of discrete segments separated by nodes for which we will find the temperature. As seen in the figure, the tube has a total length of 10 m, and we will divide it into five segments, each with a length = 10/5 = 2 m. This discretization defines six nodes (0 to 5) at the boundaries between the different segments. Step 2: Substitute derivatives in the original equation by finite difference approximations. Note: Remember from Lab #4,

Substituting the finite difference approximation for the second derivative in the equation gives:

Step 3: Apply the resulting equation to each of the interior nodes: = 0.01*22+2 = 2.04 = 0.01*22*20 = 0.8 For node 1: For node 2: For node 3: For node 4: Substitute the values for For node 1: For node 2: For node 3: For node 4: Step 4: Solve the system of linear algebraic equations: from numpy import matrix,arange,exp,append from numpy.linalg import inv from pylab import figure,plot,xlabel,ylabel,legend h = 0.01 # in m^(-2) Ta = 20. # in C L = 10. # in m N = 6 # number of nodes T0 = 40. # in C T5 = 200. # in C dx = L/(N-1) q1 = h*dx*dx+2. q2 = h*dx*dx*Ta A = matrix([[ q1,-1., 0., 0.], [-1., q1,-1., 0.], [ 0.,-1., q1,-1.], [ 0., 0.,-1., q1]]) and , which we already know:

B = matrix([[q2+T0], [q2], [q2], [q2+T5]]) T = inv(A)*B T = append(T0,T) T = append(T,T5) x = arange(0.,L+1.,dx) T_exact = 73.4523*exp(0.1*x)-53.4523*exp(-0.1*x)+20. figure() plot(x,T,'p',x,T_exact) xlabel('distance along the rod (m)') ylabel('Temperature (C)') legend(('approximation', 'exact soln.'), loc='upper left') And the output is:

2.1 Response and Stimulus For systems that can be expressed as:

or

response

stimulus

Example: If you want to know how This also works with changes.

affects

, you look at

changes

2.2 Ill-conditioned systems Three ways in which we can use the coefficient matrix to identify an ill-conditioned system: - Scale such that largest element in each row has a value of 1. If any , then the system is ill-conditioned. - If , then the system is ill-conditioned. - If , then the system is ill-conditioned. 2.3 Example: Indoor Air Pollution Analyze the ventilation system for a restaurant near a freeway.

Step 1 Write steady-state mass balances for each room and solve the resulting linear algebraic equations for the concentration of carbon monoxide in each room. To arrive at the mass balances for the different rooms, one needs to consider that in the figure, the one-way arrows represent volumetric flows, while the two-way arrows represent diffusive mixing only. This means that we need to solve for the flows occurring between rooms ( , and ). A balance on room 1 gives:

Note that, in my equation, I assumed that was going from room 2 to room 4, but the value turned out to be negative, so is actually going from room 4 into room 2 ( ). Now that we know all the flows, we can solve for the mass balances. For room 1:

For room 2:

For room 3:

For room 4:

through

from numpy import matrix from numpy.linalg import inv # Enter data ca = 2. # mg/m3 cb = 2. # mg/m3 Qa = 200. # m3/hr Qb = 50. # m3/hr Qc = 150. # m3/hr Qd = 100. # m3/hr E13 = 25. # m3/hr E24 = 25. # m3/hr E34 = 50. # m3/hr Wsmoker = 1000. # mg/hr Wgrill = 2000. # mg/hr

# Setup coefficient matrix and stimuli vector A = matrix([[Qa+E13 ,0. ,-E13 ,0. ], [0. ,Qc+E24,0. ,-Qa+Qd-E24], [-Qa-E13,0. ,Qa+E13+E34,-E34 ], [0. ,-E24 ,-Qa-E34 ,Qa+E34+E24]]) B = matrix([[Wsmoker+Qa*ca], [Qb*cb ], [Wgrill ], [0. ]]) # Solve for concentrations C = inv(A)*B print C The output is: [[ 8.09961686] [ 12.34482759] [ 16.89655172] [ 16.48275862]] Step 2 Generate the matrix inverse and use it to analyze how the various sources affect the kids room. For example, determine what percent of the carbon monoxide in the kids section is due to (1) the smokers, (2) the grill and (3) the intake vents. In addition, compute the improvement in the kids section concentration if the carbon monoxide load is decreased by banning smoking and fixing the grill. Once we have the inverse of the coefficient matrix, we can express the solution as:

Where the coefficients of the inverse of function) and the solution (response).

),

), we

To get the concentration of carbon monoxide in the kids section ( ), we look at and :

In addition, because the model is linear, superposition holds and the impact of banning smoking and fixing the grill can be determined individually and summed:

Adding this calculation to the script results in: from numpy import matrix from numpy.linalg import inv # Enter data ca = 2 # mg/m3 cb = 2 # mg/m3 Qa = 200 # m3/hr Qb = 50 # m3/hr Qc = 150 # m3/hr Qd = 100 # m3/hr E13 = 25 # m3/hr E24 = 25 # m3/hr E34 = 50 # m3/hr Wsmoker = 1000 # mg/hr Wgrill = 2000 # mg/hr # Setup coefficient matrix and stimuli vector A = matrix([[Qa+E13 ,0. ,-E13 ,0. ], [0. ,Qc+E24,0. ,-Qa+Qd-E24], [-Qa-E13,0. ,Qa+E13+E34,-E34 ], [0. ,-E24 ,-Qa-E34 ,Qa+E34+E24]]) B = matrix([[Wsmoker+Qa*ca], [Qb*cb ], [Wgrill ], [0. ]]) # Solve for concentrations C = inv(A)*B # Take the inverse of the coefficient matrix Ainv = inv(A) # Contributions from smokers, grill and intakes to kid's section per_smokers = Ainv[1,0]*Wsmoker/C[1]*100. print 'per_smokers = ',per_smokers per_grill = Ainv[1,2]*Wgrill/C[1]*100. print 'per_grill = ',per_grill

per_intakes = (Ainv[1,0]*Qa*ca+Ainv[1,1]*Qb*cb)/C[1]*100. print 'per_intakes = ',per_intakes # Change in kid's section due to banning smoking and fixing the grill dC2 = -Ainv[1,0]*Wsmoker-Ainv[1,2]*Wgrill print 'dC2 = ',dC2 C2_new = C[1]+dC2 print 'C2_new = ',C2_new The output from this script is: per_smokers = [[ 27.93296089]] per_grill = [[ 55.86592179]] per_intakes = [[ 16.20111732]] dC2 = -10.3448275862 C2_new = [[ 2.]] Step 3 Analyze how the concentration in the kids area would change if a screen is constructed so that the mixing between areas 2 and 4 is decreased to 5 m3/hr. This change involves changing the value for from 25 to 5 m3/hr, which is one of the inputs for the coefficient matrix. It makes things clearer and cleaner if we now generate the coefficient matrix in a separate function: from numpy import matrix def ventilation(Qa,E13,Qc,E24,Qd,E34,Wsmoker,ca,Qb,cb,Wgrill): A = matrix([[Qa+E13,0.,-E13,0.], [0.,Qc+E24,0.,-Qa+Qd-E24], [-Qa-E13,0.,Qa+E13+E34,-E34], [0.,-E24,-Qa-E34,Qa+E34+E24]]) B = matrix([[Wsmoker+Qa*ca], [Qb*cb], [Wgrill], [0.]]) return A,B This makes it easier to regenerate the coefficient matrix everytime we change the input. The script for this section looks now like: from numpy.linalg import inv from ventilation import ventilation # Enter data ca = 2 # mg/m3 cb = 2 # mg/m3 Qa = 200 # m3/hr Qb = 50 # m3/hr

Qc = 150 # m3/hr Qd = 100 # m3/hr E13 = 25 # m3/hr E24 = 25 # m3/hr E34 = 50 # m3/hr Wsmoker = 1000 # mg/hr Wgrill = 2000 # mg/hr # Setup coefficient matrix and stimuli vector [A,B] = ventilation(Qa,E13,Qc,E24,Qd,E34,Wsmoker,ca,Qb,cb,Wgrill) # Solve for concentrations C1 = inv(A)*B # Install screen E24 = 5 # m3/hr # Setup new coefficient matrix and stimuli vector [A,B] = ventilation(Qa,E13,Qc,E24,Qd,E34,Wsmoker,ca,Qb,cb,Wgrill) # Solve for new concentrations C2 = inv(A)*B # Take the difference in the kid's section concentration dC2 = C2[1]-C1[1] print 'dC2 = ',dC2

dC2 =

[[-0.26482759]]

The decrease in the concentration of carbon monoxide in the kids section due to installation of the screen is 0.2648 mg/m3.

3. Practice Problems

Problem 1:

A furnace wall is made up of three separate materials. Let represent the thermal conductivity of material , let represent the corresponding thickness ( ), and let and represent the convective heat transfer coefficients of the outer surfaces. If , then the following steady-state heat transfer equations apply:

Typically, the outer temperatures ( and ), the thermal conductivities, the material thicknesses, and the convective heat transfer coefficients are known. The objective is to determine the temperatures at the surfaces ( and ) and the temperatures at the interfaces ( and ). (a) Rearrange these equations into a more traditional form as four equations in four unknowns. (b) Write a script to solve for the unknown temperatures, based upon the following given information: = 0.5 cm = 0.01 cal/(cm)(s)(C) = 0.3 cm = 0.15 cal/(cm)(s)(C) = 0.2 cm = 0.03 cal/(cm)(s)(C) = 200 C = 1.0 cal/(cm2)(s)(C) = 20 C = 0.8 cal/(cm2)(s)(C) (c) Use the results in part (b) to determine the heat flux, in cal/(cm2)(s). The heat flux is represented by either the left-hand side or the right-hand side of any of the above four equations.

Problem 2: Using the same approach, develop steady state mass balances for the room configuration depicted in the figure below.

a) Determine the matrix inverse and use it to calculate the resulting concentrations in the rooms. b) Use the matrix inverse to determine how much the room 4 load must be reduced to maintain a concentration of 20 mg/m3 in room 2.

4. Solution:

Problem 1: a)

b) and c)

from numpy import matrix from numpy.linalg import inv dx1 = 0.5 # in cm dx2 = 0.3 # in cm dx3 = 0.2 # in cm Ta = 200. # in C Tb = 20. # in C k1 = 0.01 # in cal/(cm k2 = 0.15 # in cal/(cm k3 = 0.03 # in cal/(cm h1 = 1.0 # in cal/(cm2 h2 = 0.8 # in cal/(cm2

s s s s s

C) C) C) C) C)

A = matrix([[k1/dx1+h1,-k1/dx1, 0., 0. ], [k1/dx1, -(k1/dx1+k2/dx2),k2/dx2, 0. ], [0., k2/dx2, -(k2/dx2+k3/dx3),k3/dx3 ], [0., 0., -k3/dx3, k3/dx3+h2]]) B = matrix([[h1*Ta], [0. ], [0. ], [h2*Tb]]) T = inv(A)*B print 'T0, T1, T2, and T3 are: %.1f %.1f %.1f %.1f' % tuple(T) print 'Flux is %.2f cal/(cm^2 s)' % (h1*(Ta-T[0]))

The output is: T0, T1, T2, and T3 are: 197.0 49.3 43.4 23.7 Flux is 2.95 cal/(cm^2 s)

Also, let us identify the different loads on each of the rooms: load on Room 1 load on Room 2 load on Room 4 Then the steady-state mass balances can be written for the rooms as

The concentration in Room 2 as a function of the change in load to the Room 4 can be formulated in terms of the matrix inverse as

The matrix system is saved as a function: from numpy import matrix def ventilation2(Q12,Q13,E13,Q23,E23,Q34,Q3out,E34,Q4out,W1,W2,W4): A = matrix([[Q12+Q13+E13,0.,-E13,0.], [-Q12,Q23+E23,-E23,0.], [-Q13-E13,-Q23-E23,Q34+Q3out+E13+E23+E34,-E34], [0.,0.,-Q34-E34,Q4out+E34]]) B = matrix([[W1], [W2], [0.], [W4]]) return A,B Then the main script is written to call the function with the matrix to solve for the unknowns: from ventilation2 import ventilation2 from numpy import transpose from numpy.linalg import inv # Enter data Q12 = 50. # m3/hr Q13 = 100. # m3/hr Q23 = 100. # m3/hr Q34 = 150. # m3/hr Q3out = 50. # m3/hr Q4out = 150. # m3/hr E13 = 50. # m3/hr E23 = 50. # m3/hr E34 = 90. # m3/hr W1 = 150. # mg/hr W2 = 2000. # mg/hr W4 = 5000. # mg/hr # Setup coefficient matrix and stimuli vector [A,B] = ventilation2(Q12,Q13,E13,Q23,E23,Q34,Q3out,E34,Q4out,W1,W2,W4) # Solve for concentrations C = inv(A)*B print 'concentrations are: ', transpose(C) # Calculate resuction in room 4 load to get C2 to 20mg/m3 Ainv = inv(A) delta_W4 = (20.-C[1])/Ainv[1,3] print 'delta_W4 = ',delta_W4 The results are: concentrations are: [[ 40.95833333]] delta_W4 = [[-2520.]]

5.78125

21.96875

20.125

- main-20130724Uploaded byPpham
- Algebra 2 with Trigonometry SyllabusUploaded byNicholas Yates
- applicationsoflinearalgebra.pdfUploaded byAlbertoAlcalá
- Examples NLSUploaded byKirti Deo Mishra
- Linear Algebra NYCUploaded byimisn00b
- GMAT Workbook & Error LogUploaded byRushil Surapaneni
- lessonplans 2Uploaded byapi-341209699
- c2-0Uploaded byAmit Pandey
- Solving Linear Systems Using Interval Arithmetic ApproachUploaded byInternational Journal of Science and Engineering Investigations
- 6th Grade Unit 1 Study GuideUploaded by504mathletes
- ConstraintsUploaded byRaúl Sánchez
- MATLAB CourseworkUploaded bySagar Mehta
- 06FMA393AMidterm2Uploaded byEka Harris
- english 313- lesson planUploaded byapi-386054746
- Pi VotingUploaded byRavindra Desai
- Unit 1Uploaded bykchhang
- ece syll effective 2011Uploaded byParveen Goel
- Pure Mathematics Unit 1 Module 2 WorksheetdocxUploaded bySadharshan Singh
- Ch01_SE 1.6Uploaded byGeorge
- linear equationUploaded byapi-253901565
- Differential Equations CookbookUploaded byAugustinZ
- Heat Transfer Homework, Engineering Project, Mechanical Project, Heat Transfer Project, Engineering Dissertation, Heat Transfer Dissertation, Mass Transfer Project, Mass Transfer DissertationUploaded byiWanttutor.com
- 1-s2.0-0893965996000614-main.pdfUploaded bywahabmaths
- 9801_01_pef_20100818Uploaded bySCZ28
- Epfl Chapter 7Uploaded byioanciornei
- baker-r-sped841-virtual learning unitUploaded byapi-325030256
- 2010 Yjc h2ma Prelim p1Uploaded bycjcsucks
- 9709_s10_qp_21Uploaded byroukaiya_peerkhan
- reflective writing for project 1Uploaded byapi-229410609

- 465HW2-05Uploaded byNaimun Siraj
- 5 CalculationsUploaded byNaimun Siraj
- Wittig ReactionUploaded byNaimun Siraj
- MIT Lec InheritUploaded byNaimun Siraj
- Project 03Uploaded byNaimun Siraj
- Plant SchematicUploaded byNaimun Siraj
- 349_1Uploaded byNaimun Siraj
- Lab05wsolnsUploaded byNaimun Siraj
- Lab05wsolnsUploaded byNaimun Siraj
- French Presentation Final (News Anchor)Uploaded byNaimun Siraj
- French Presentation Final (News Anchor)Uploaded byNaimun Siraj
- UntitledUploaded byNaimun Siraj
- MathUploaded byNaimun Siraj
- 7 ReagentsUploaded byNaimun Siraj
- Lab08wsolnsUploaded byNaimun Siraj
- SequestrationUploaded byNaimun Siraj
- 03RBFUploaded byNaimun Siraj
- GEORGE BERNARD SHAW on islam.pdfUploaded byIslamicfaith Introspection
- Boot Camp InstallationUploaded byDougNew
- Direct Carbonation PaperUploaded byNaimun Siraj
- Blast Furnace ReportUploaded byNaimun Siraj
- Force Laws Cartoon RubricUploaded byNaimun Siraj
- SimaProLicense_Through01Nov13Uploaded byNaimun Siraj
- OrgChemLabSyl_S3543DQUploaded byNaimun Siraj
- Physics Lab Report 1 (Version 1)Uploaded byNaimun Siraj
- Blog 6 - Ex.cred KH CloudsUploaded byNaimun Siraj
- Econ MidtermsUploaded byNaimun Siraj
- hw1Uploaded byNaimun Siraj
- hw1Uploaded byNaimun Siraj

- g2o kuemmerle11icraUploaded byDanilo Djordjevic
- stochasticdesUploaded byAbraham Sauvingnon
- ReportGodunov Method and Related Schemes for Nonlinear Hyperbolic ProblemsUploaded bybernardo.favini6840
- Ias Main 2012 Math Paper IIUploaded bysausar10
- Math CelineUploaded byEvan Charl Moraleda
- Laplace_Table.pdfUploaded byvafdeleon
- 2007 Metro Bank MTAP(Math IV)Uploaded byJoe Titular
- Stolz CesaroUploaded byNguyễn Duy Quang
- Townsend, Quantum Physics, CHAP_5, Ppios of QMUploaded byElcan Diogenes
- Maths Spm SyllabusUploaded byJunior Blade
- CSC4212 Lecture 2 - 3D ViewingUploaded byaadatti
- Analysis of Cross-ply Laminate composite under UD load based on CLPT by Ansys APDLUploaded byAnonymous 7VPPkWS8O
- Doc. 3. the Quantum Space Time Fractal Harmonic Codex. the Mars Sidereal and PhiUploaded byCarlos Marighella
- Eglash Ron African Fractals Modern Computing and Indigenous DesignUploaded bySylvia Sánchez
- 9-3Uploaded bysarasmile2009
- SupplementUploaded byMassolo Roy
- AdamsUploaded byawaashish
- Ansys and Laminated Paltes Macro CodeUploaded byJL Mantari
- Problems on Properties of DeterminantsUploaded by666667
- EQUATION_07-02-16Uploaded byAl Johnston
- Boussinesq Models and Their Application to Coastal Processes across a Wide Range of ScalesUploaded byClemente Gotelli Alvial
- Tie-decay temporal networks in continuous time and eigenvector-based centralitiesUploaded byFábio Duarte
- matematik-tambahan-skemaUploaded byNornaziha Najwa
- 0879422378Uploaded byPanneer Selvam
- 10_BirthDeathUploaded byChetan B Arkasali
- C3 June 2013 - Withdrawn Paper Mark SchemeUploaded byShwan Hasan
- Forward–backward algorithm.pdfUploaded bySandro Ernesto Ruiz Samaniego
- PROJECT DIFFERENTIAL CALCULUS.pdfUploaded byCarlos Javier Sánchez Fraguas
- Time Series ARMAUploaded bySamanthi Manawadu
- EssayUploaded byKyle Byrne