Comparison of Direct and Iterative Methods to Solve Finite Element Beam Problems Aaron Morrow MEAE-4960H01 April 17, 2001 Table of Contents: List of Symbols Used ………………………………….. 3 Abstract ………………………………….. 3 Introduction ………………………………….. Figure 1: Cantilever beam with a point load…………... 4 4 Problem Description ………………………………….. 4 Figure 2: Discretization of a beam into n-1 finite elements 5 Exact Formulation ………………………………….. Table 1: Variables used in exact solution………………. 6 6 Numerical Formulations ………………………………….. 6 Gauss elimination with back substitution……………… 8 LU factorization………………………...……………… 9 Jacobi Iterative………………………………………….. 10 Gauss-Sidel Iterative……….……………………….. 11 Figure 3: Comparison of the substitution algorithms between the Jacobi and the Gauss-Sidel Iterative………….. 11 Results and Discussion ………………………………….. Figure 4: Error vs. DOF ………………………….. Figure 5: Computation time vs. DOF………………….. Figure 6: Resource usage vs. DOF…………………….. 12 13 14 15 Conclusions…………………………………………………….. 16 References…………………..………………………………….. 17 Appendices…………………………………………………….. Appendix I: Visual Basic code for matrix solvers……. 18 18 Symbols Used M C k x F K m m Fx Mx E I Ln kij Mass matrix Viscous damping matrix Stiffness matrix Deflection vector Force vector Stiffness matrix Linear deflection of beam at node m Angular deflection of beam at node m Force at node x Moment at node x Modulus of elasticity Area Moment of beam Length of beam element n The ij element of the stiffness matrix Abstract This paper will investigate and compare the applicability of four different methods for solving linear systems of equations as they apply to finite element solutions for beams. The four methods will be Gauss elimination, LU factorization, Gauss-Sidel Iteration, and Jacobi Iteration. Of the four methods only three can be adequately applied to beam finite elements, as the formulation of the stiffness matrix does notguarantee a unique solution with the Jacobi iterative. Of the three reaming methods the to direct methods were more accurate and faster but they used a larger number of system resources in order to accomplish the task. Introduction: This paper will examine a finite element beam model's deflections and reactions. These deflections and reactions will be compared against an already derived closed loop solution for a cantilever beam with a point load. The finite element results will be formulated using various direct and iterative techniques including; Gauss elimination, LU factorization, Jacobi iterative, and Gauss-Sidel Iterative. Each of the techniques will used to solve increasing degree of freedom problems in order to compare the accuracy and efficiency od each method as it applies to finite elements. A finite element beam model is used for various reasons: 1. Computer time and cost is always an issue when using finite element codes. The author wanted to investigate various solution techniques in order to determine what might be a cost-effective method for solving these problems. 2. Finite beam elements are not sensitive to mesh density. The beam shown in figure one only needs 1 element to provide a solution that matches the closed loop solution. This is advantageous, because it eliminates an additional variable, mesh density, from Figure 1: Cantilever Beam with a point load the investigation. 3. A beam element is sufficiently complex enough that the number of degrees of freedom can quickly approach larger values (>20). Granted, it is not uncommon for finite element programs to routinely solve problems with tens of thousands or even hundreds of thousands of degrees of freedom, but the author thought that these types of problems might be outside the scope of this investigation. 4. There is an extensive library of closed loop solutions to beam deflection problem solutions that it is very easy to check each of the models to assure that the solution is correct. Problem Description: Newton's second law of motion is shown in equation 2, where [m], [c], and [k] are called the mass, damping, and stiffness matrices respectively. p F n 1 m d2 d dt2 x c dt x k x (2) For a static structure (i.e. no rigid body motion) the first and second derivatives of motion with respect to time go to zero simplifying equation 1 to: F k x (2.1) Equation 2.1 simply states that the sum of the forces acting on a body is equal to the stiffness [k] of the body multiplied by the deflection of the body. This equation is the basis for implicit finite element analysis. Figure 2 shows a beam discretized into an n-1 element finite element beam with n nodes. M or BC F or BC M or BC F or BC F or BC Node 2 M or BC F or BC Element n-1 Element 2 Element 1 Node 1 M or BC Node n-1 Node n Figure 2: Discretization of a beam into n-1 finite elements At each node there is a possibility of 4 boundary conditions: force (F), moment (M), linear displacement (), or angular displacement (). These forces and displacements are represented in the [F] and [x] matrices as shown in equations 3 and 4, where the subscript represents the node that boundary condition is acting upon. 1 1 2 [x]= 2 . . n n F1 M1 F2 M2 (3) . . Fn Mn 1 1 2 [F]= 2 . . n n F1 M1 F2 M2 . . Fn Mn (4) The [k] matrix in equation 5 represents the stiffness matrix of the beam elements that are a function of length (L), modulus (E), and area moment (I). Notice the summation terms along the diagonal, which include terms from two adjacent elements. These summation terms enforce both the displacement and rotation continuity between the adjacent elements. One should also notice that the matrix is symmetric and therefore, the determinate is zero and the inverse is nonexistent. The physical representation of this is the fact that none of the force or, more importantly, the displacement boundary conditions have been applied to the beam. 12E I L 13 6E I L 2 1 12E I 3 L1 6E I [k]= 2 L1 0 0 0 0 L1 L1 4E I 6E I 2E I 0 0 0 0 L1 2 L1 L1 6E I 12E I 12E I 6E I 6E I 12E I 6E I 0 0 2 3 3 2 2 3 2 L1 L1 L2 L1 L2 L2 L2 2E I 6E I 6E I 4E I 4E I 6E I 2E I 0 0 L1 2 2 L1 L2 2 L2 L1 L2 L2 12E I 6E I 12E I 12E I 6E I 6E I 0 . . 3 2 3 3 2 2 L2 L2 L2 L3 L2 L3 6E I 2E I 6E I 6E I 4E I 4E I 0 . . 2 L2 2 2 L2 L3 L2 L2 L3 12E I 12E I 6E I 6E I 0 0 0 . . 3 3 2 2 Lm Ln Lm Ln 6E I 6E I 4E I 4E I 0 0 0 . . 2 2 Lm Ln Lm Ln 6E I 12E I 2 L1 3 6E I 0 2 0 0 0 (5) NOTE: m=n-1 Exact Formulation: The closed loop solution for the deflection of a cantilever beam with a point load on the free end is show in equation 1a. Table 1 lists the variables used in the problem and the values that will be used for this investigation. 3 P L 3 E I (1a) Variable P L E I Description Load (lb) on end of beam Length of beam (in) Modulus of beam (psi) Area moment of beam (in^4) Deflection of beam (in) Value 100 50 1.00E+07 5.3333 0.078125 Table 1: Variables used in exact solution Numerical Formulations: The first thing that must be done to this problem is to impose the proper boundary conditions. Revisiting the beam from figure 1, a 100 pound point load at the right edge and a constraint against rotation and translation at the left edge are applied. For a single beam element with 4 degrees of freedom a simplified version of the {F}=[k]{x} matrix for this condition would look something like equation (6). k 11 k 21 0 0 k 12 0 k 22 k 23 k 32 k 33 0 1 0 1 k 34 2 k 44 2 0 k 43 F1 M 1 F2 M2 (6) Note: kij=kji Notice that there are two problems with this system of equations as it stands: 1. The stiffness matrix is symmetric and non-invertable. 2. Even with the boundary conditions in place the [x] and [F] matrices would both half defined. In the case of a cantilever beam 1 and 1 (the linear and rotational motion at node 1) would be zero while 2 and 2 would be unknown. On the other hand F1 and M1 are unknown while F2 and M2 are the applied force (100 lb.) and moment (0 lb.) at node 2. This is fairly common in finite element problems where a displacement boundary condition is imposed at one location and a force or moment is applied to the structure at a different location. Based on the boundary conditions of the system described above, two more equations exist. These are 1=0 (6.1) 1=0 If these two boundary conditions are substituted into the system of equations and the force boundary conditions are applied the matrix in equation 6 will change to: [k]' 1 0 k 31 k 41 0 0 1 0 k 32 k 33 k 42 k 43 {x} 0 x 1 0 1 k 34 x 2 k 44 2 {F'} 0 0 100 0 (6.2) At this point [k'] can be easily inverted and multiplied by {F'} to solve for {x}, {x} can then be substituted back into equation 6 to readily solve for {F}. For this investigation, however, other direct and iterative techniques will be used to solve [k'] rather than matrix inversion. Gauss Elimination with back substitution: Gauss elimination is a fairly straightforward method to reduce a system of equations to one equation and one unknown. The single unknown is found and then it is back substituted into the system of equation to find the next unknown until all unknowns are found. The Gauss elimination method uses and augmented matrix. If we take equation 6.2 and create an augmented matrix it would look like equation 7: 1 0 ~ 0 1 A= k 31 k 32 k k 41 42 0 0 0 0 0 100 0 0 k 33 k 34 k 43 k 44 (7) Each row is an equation and is designated by the variable Ei where i is the row number. When the following operations are performed: aij Ej a Ei ii Ej (7.1) The augmented matrix will be of the form shown in equation 7.2: k 11 0 ~ A= 0 0 k 12 k 13 k 14 x 1 x3 x4 k 22 k 23 k 24 x 2 0 0 k 33 k 34 0 k 44 7.2 Where all values for k and x are known. From equation 7.2 back substitution can be applied to solve for {F}. While it is fairly straight forward, there are caveats to using Gauss elimination. The primary one is that there can be no zero values on the diagonal. If this happens then equation 7.1 goes to infinity. For a beam finite element problem there will never be a zero value on the diagonal unless the element is formulated incorrectly. L U factorization: L U factorization is a method by which a matrix can be reduced from a single matrix to two matrices [L] and [U] that are lower and upper triangular matrices. The advantage to this is that backwards and forwards substitution can be used to readily solve a linear system of equations. (Note how the matrix in equation 7.2 is upper triangular.) an upper and lower triangular matrix are shown, in relation to the [k] matrix in equation 8: [k] k 11 k 21 k 31 k 41 = k 12 k 13 k 14 k 22 k 23 k 32 k 33 k 42 k 43 k 24 k 34 k 44 [L] 0 0 1 L 1 0 21 L 31 l 32 1 L 41 L 42 L 43 * [U] U 11 U 12 U 13 0 U U 0 22 23 0 0 0 U 33 1 0 0 0 0 U 14 U 34 U 44 U 24 (8) Since [L][U]=[k] equation 7 can be re written as [L][U]{x}={F}. Introducing the substitution {y}=[U]{x} then [L][y]={F}. From this point solving for y through back forward substitution and subsequently solving for {x} with back substitution is readily done. The Jacobi Iterative: The Jacobi iterative is a simple iterative method process that converts, in this case, the equation of the form {F'}=[k']{x} into an equivalent system of the form: (9) {x(k)}=[T]{x(k-1)}+{c} The question is what are [T] and {c}? If one were to take the system of equations represented by equation 6 and solve for each value in {x} it would look like: [T]= 0 0 0 0 0 0 k31 k32 k33 k33 0 k41 k42 k43 k44 k44 k44 0 0 0 0 k34 k31 k33 k33 k41 0 k44 0 0 0 0 0 0 0 And k33k33 k42 0 k43 k44 k44k44 k32 100 0 k34 [c]= k33 0 0 100 k33 0 k44 0 0 (9.1) and (9.2) So that: x1 0 1 0 x2 2 k31 x1 k32 1 k34 2 100 (9.3) k33 k41 x1 k42 1 k43 x2 0 k44 These values are then used in equation 7. Since all values of [T] and {c} are known it is simply a matter of supplying an initial guess for {x} and an acceptable tolerance so that: |{x(k)}-{x(k-1)}|>TOL (9.4) will stop the algorithm. The Gauss-Sidel Iterative: The Gauss-Sidel iterative technique is very similar to the Jacobi iterative technique. The primary difference between the two techniques lies in how the guess values are updated within the {x} vector. Let us revisit equation 9 with a little extra definition added to the problem. In equation 10 the superscripts represent which iteration of x is being used with x(0) being the initial guess and the subsequent numbers being the results of the current iteration (i.e. x1(1) is the result of the first iteration of x1). This is the substitution technique used to solve the Jacobi Iterative. Notice, however, that if the values for the {x} vector are solved from the top down, that there is no reason that one could not use a value that has already been solved for in the current iteration. This is shown in equation 10.1. The Gauss-Sidel iterative should converge faster as it updates the individual values of the {x} vector much sooner than in the Jacobi iterative. (10) ( 1) x1 ( 1) 1 ( 1) 0 x1 0 1 ( 1) ( 0) ( 1) x2 k31 x1 k32 1 ( 0) k34 2 ( 0) 100 k33 ( 0) ( 1) 2 (10.1) k41 x1 k42 1 ( 0) k44 k43 x2 ( 0) 0 0 0 ( 1) ( 1) x2 k31 x1 ( 1) k34 2 ( 0) 100 k43 x2 ( 1) 0 k33 ( 1) ( 1) 2 k32 1 k41 x1 k42 1 ( 1) k44 Figure 3: Comparison of the substitution algorithms between the Jacobi and the Gauss-Sidel Iterative Results and Discussion: Using the four methods described above the author used a finite element cantilever beam with an increasing number of degrees of freedom (4,6,8,and 10) to determine how well each method performed. Three factors will be used to determine how well each method performed: 1. Accuracy. This can be easily measured against the closed form solution to the problem. For the case of the analysis reaction forces and deflections will be the only values that we will compare. 2. Time: With these small degree of freedom problems the amount of time that is taken to solve the problem is minimal. For this reason a loop was inserted into the program to force it to run 100 times. The start and stop times for the various methods were then compared. 3. Disk space: Again with such small problems disk or memory space is hardly an issue. For this case, the sum of the array values was used to determine a relative memory allocation value. Performance: In this category one method quickly ruled itself out as viable for use in solving finite element beam problems. The Jacobi Iterative failed to converge when the problem got larger than 4 DOF. Theorem 7.21 in Burden and Faires1 explains why. "If [A] (in this case [k]) is strictly diagonally dominant then for any choice of x(0), both the jacobi and Gauss-Sidel methods give sequences that converge to a unique solution of Ax=b" For a beam finite element [k] will never be diagonally dominant. It is interesting to note that while the Jacobi iterative did not converge the Gauss sidel iterative converged every time. Figure 4 shows how well the LU decomposition and Gauss elimination did compared to the Gauss-Sidel iterative. Error as aFunction of DOF 0.0350000% 0.0300000% error (%) 0.0250000% 0.0200000% Gauss-Sidel LU decomp Gauss-Elimination 0.0150000% 0.0100000% 0.0050000% 0.0000000% 10 8 6 4 2 0 12 DOF Figure 4: Error vs. DOF Time: In this measure we look at the time it took to solve the problem 100 times on a desktop PC. Figure two shows the comparative growth in calculation time between the three methods. Computation time as a function of DOF 1 0 2 4 6 8 Time (sec) 0.1 Gauss-Sidel It LU Decomp Gauss elimination 0.01 0.001 Number of iterations Figure 5: Computation Time vs. DOF 10 12 Memory Allocation: In this measure the amount of space that is needed to run the algorithm is compared between the three remaining results. This is based on the number of variable slots assigned including temporary swap or placeholder variables: Memory block usage Resource comparison between Iterative (Gauss-Sidel) and direct (LU) Matrix solvers as a function of DOF 500 450 400 350 300 250 200 150 100 50 0 Gauss-Sidel Iter LU Decomp Gauss Elimination 0 2 4 6 8 10 DOF Figure 6: Resource Usage vs. DOF 12 Conclusions: At first glance it seems fairly clear that one would not want to use iterative methods for solving finite element beam problems. The Gauss elimination and the LU factorization methods both are far more accurate than the iterative method and did not show an increase in error as the DOF increased. However one also has to look at allocation space. To a certain extent time is a limitless commodity where as physical memory and disk space are not. One has to look at the time and error values for the methods involved. The time to iteratively solve the beam problem was less than .9 seconds with a fairly high (10-7) tolerance value used in the calculation. The error too was very small (<.03%) even though it looked large compared to the direct methods. So, while the values for the error and time look larger for the iterative solution they still are very small. Additionally this method was not optimized and might be much faster if Successive Over Relaxation methods are used to help the problem converge faster. Bibliography: 1) Timoshenko and Goodier; "Theory of Elasticity", 2nd Edition, McGraw-Hill; New York, 1951. pp 438-444 2) William H .Press, et al, "Numerical Recipes for C", 2nd Edition, Cambridge university press; Boston, 1993 3) Burden and Faires, "Numerical Analysis", 6th Edition, Brooks/Cole; Pacific Grove, 1997. pp 698-704 Appendix A-VBA Code Gauss-Sidel iterative Function Gauss_sidel(k As Range, u As Range, F As Range) Dim start As Variant start = Timer For imain = 1 To 100 Dim Dim Dim Dim Dim Dim Dim finish As Variant krow As Variant kcol As Variant Error As String F1 As Variant u1 As Variant k1 As Variant F1 = F k1 = k u1 = u Nit = 1000000 TOL = 0.0000001 krow = k.Rows.Count kcol = k.Columns.Count urow = u.Rows.Count Frow = F.Rows.Count ucol = u.Columns.Count Fcol = F.Columns.Count Error = "" error2 = "" If ucol > 1 Or Fcol > 1 Then Error = "Displacement or Force vectors are not specified correctly" Else Error = "OK!!" End If test = 0 check2 = 0 check3 = 0 For i = 1 To urow If IsEmpty(u(i, 1)) Then check = 0 Else check = 1 test = test + 1 End If If i Mod 2 <> 0 And check = 1 Then check2 = check2 + 1 End If Next i If test >= 2 And check2 >= 1 Then error2 = "Enough BCs" Else error2 = "Insufficient BCs" End If For i = 1 To urow If IsEmpty(u(i, 1)) Or IsEmpty(F(i, 1)) Then check3 = check3 Else check3 = check3 + 1 End If Next i If check3 >= 1 Then error2 = "Overconstrained" End If For i = 1 To urow If IsEmpty(u(i, 1)) And IsEmpty(F(i, 1)) Then F1(i, 1) = 0 End If If IsEmpty(F1(i, 1)) Then F1(i, 1) = u(i, 1) For j = 1 To kcol If i = j Then k1(i, j) = 1 Else k1(i, j) = 0 End If Next j End If Next i Dim Dim Dim Dim Dim Dim Dim answer As Variant kc As Integer x() As Double XO() As Double term1 As Double term2 As Double Neq As Double kc = 1 Neq = krow 'The variant data type is a chameleon. 'Here it thinks it is a worksheet range. ReDim x(1 To Neq) ReDim XO(1 To Neq) Do While kc < Nit For i = 1 To Neq For j = 1 To i - 1 term1 = (term1 + (k1(i, j) * x(j))) Next j For j2 = i + 1 To Neq term2 = term2 + ((k1(i, j2)) * XO(j2)) Next j2 x(i) = (-term1 - term2 + F(i, 1)) / k1(i, i) term1 = 0 term2 = 0 Next i For i = 1 To Neq If i = 1 Then res = (x(i) - XO(i)) ^ 2 Else res = res + (x(i) - XO(i)) ^ 2 End If Next i If res ^ (0.5) < TOL Then Exit Do Else kc = kc + 1 If kc < Nit Then For i = 1 To Neq XO(i) = x(i) Next i End If End If Loop For i = 1 To F1(i, 1) For j = 1 To F1(i, 1) Next j Next i Neq = 0 Neq = F1(i, 1) + x(j) * k(i, j) finish = Timer finish = finish - start ReDim answer(1 To krow + 1, 1 To 2) For iend = 1 To krow + 1 If iend <= krow Then answer(iend, 1) = answer(iend, 2) = Else answer(iend, 1) = answer(iend, 2) = End If Next iend x(iend) F1(iend, 1) kc finish Next imain Gauss_Sidel answer Jacobi Iterative End Function Function Jacobi(k As Range, u As Range, F As Range) Dim start As Variant start = Timer For imain = 1 To 100 Dim Dim Dim Dim Dim Dim Dim finish As Variant krow As Variant kcol As Variant Error As String F1 As Variant u1 As Variant k1 As Variant F1 = F k1 = k u1 = u Nit = 1000000 TOL = 0.0000001 krow = k.Rows.Count kcol = k.Columns.Count urow = u.Rows.Count Frow = F.Rows.Count ucol = u.Columns.Count Fcol = F.Columns.Count Error = "" error2 = "" If ucol > 1 Or Fcol > 1 Then Error = "Displacement or Force vectors are not specified correctly" Else Error = "OK!!" End If test = 0 check2 = 0 check3 = 0 For i = 1 To urow If IsEmpty(u(i, 1)) Then check = 0 Else check = 1 test = test + 1 End If If i Mod 2 <> 0 And check = 1 Then check2 = check2 + 1 End If Next i If test >= 2 And check2 >= 1 Then error2 = "Enough BCs" Else error2 = "Insufficient BCs" End If For i = 1 To urow If IsEmpty(u(i, 1)) Or IsEmpty(F(i, 1)) Then check3 = check3 Else check3 = check3 + 1 End If Next i If check3 >= 1 Then error2 = "Overconstrained" End If For i = 1 To urow If IsEmpty(u(i, 1)) And IsEmpty(F(i, 1)) Then F1(i, 1) = 0 End If If IsEmpty(F1(i, 1)) Then F1(i, 1) = u(i, 1) For j = 1 To kcol If i = j Then k1(i, j) = 1 Else k1(i, j) = 0 End If Next j End If Next i Dim Dim Dim Dim Dim Dim Dim answer As Variant kc As Integer x() As Double XO() As Double term1 As Double term2 As Double Neq As Double kc = 1 Neq = krow ReDim ReDim XO(1) XO(2) XO(3) XO(4) XO(5) XO(6) 'The variant data type is a chameleon. 'Here it thinks it is a worksheet range. x(1 To Neq) XO(1 To Neq) = 0 = 0 = 0.03 = 0.001 = 0.078 = 0.0023 Do While kc < Nit For i = 1 To Neq For j = 1 To Neq If j = i Then term1 = term1 Else term1 = (term1 + (k1(i, j) * XO(j))) End If Next j x(i) = (-term1 + F(i, 1)) / k1(i, i) term1 = 0 term2 = 0 Next i For i = 1 To Neq If i = 1 Then res = (x(i) - XO(i)) ^ 2 Else res = res + (x(i) - XO(i)) ^ 2 End If Next i If res ^ (0.5) < TOL Then Exit Do Else kc = kc + 1 If kc < Nit Then For i = 1 To Neq XO(i) = x(i) Next i End If End If Loop For i = 1 To F1(i, 1) For j = 1 To F1(i, 1) Next j Next i Neq = 0 Neq = F1(i, 1) + x(j) * k(i, j) finish = Timer finish = finish - start ReDim answer(1 To krow + 1, 1 To 2) For iend = 1 To krow + 1 If iend <= krow Then answer(iend, 1) = answer(iend, 2) = Else answer(iend, 1) = answer(iend, 2) = End If Next iend x(iend) F1(iend, 1) kc finish Next imain Jacobi = answer Gauss-Elimination End Function Function ge(k As Range, u As Range, F As Range) Dim start As Variant start = Timer For imain = 1 To 100 Dim Dim Dim Dim Dim Dim Dim finish As Variant krow As Variant kcol As Variant Error As String F1 As Variant u1 As Variant k1 As Variant F1 = F k1 = k u1 = u Nit = 1000000 TOL = 0.0000001 krow = k.Rows.Count kcol = k.Columns.Count urow = u.Rows.Count Frow = F.Rows.Count ucol = u.Columns.Count Fcol = F.Columns.Count Error = "" error2 = "" If ucol > 1 Or Fcol > 1 Then Error = "Displacement or Force vectors are not specified correctly" Else Error = "OK!!" End If test = 0 check2 = 0 check3 = 0 For i = 1 To urow If IsEmpty(u(i, 1)) Then check = 0 Else check = 1 test = test + 1 End If If i Mod 2 <> 0 And check = 1 Then check2 = check2 + 1 End If Next i If test >= 2 And check2 >= 1 Then error2 = "Enough BCs" Else error2 = "Insufficient BCs" End If For i = 1 To urow If IsEmpty(u(i, 1)) Or IsEmpty(F(i, 1)) Then check3 = check3 Else check3 = check3 + 1 End If Next i If check3 >= 1 Then error2 = "Overconstrained" End If For i = 1 To urow If IsEmpty(u(i, 1)) And IsEmpty(F(i, 1)) Then F1(i, 1) = 0 End If If IsEmpty(F1(i, 1)) Then F1(i, 1) = u(i, 1) For j = 1 To kcol If i = j Then k1(i, j) = 1 Else k1(i, j) = 0 End If Next j End If Next i Dim Dim Dim Dim Dim Dim Dim Dim answer As Variant kc As Integer x() As Double term1 As Double term2 As Double Neq As Double A1 As Variant m() As Double kc = 1 Neq = krow 'The variant data type is a chameleon. 'Here it thinks it is a worksheet range. ReDim m(1 To Neq, 1 To Neq + 1) ReDim x(1 To Neq) A1 = k1 ReDim Preserve A1(1 To Neq, 1 To Neq + 1) For i = 1 To Neq A1(i, Neq + 1) = F1(i, 1) Next i For i = 1 To Neq - 1 For j = i + 1 To Neq m(j, i) = A1(j, i) / A1(i, i) For iE = 1 To Neq + 1 A1(j, iE) = A1(j, iE) - m(j, i) * (A1(i, iE)) Next iE Next j Next i x(Neq) = A1(Neq, Neq + 1) / A1(Neq, Neq) For i = 1 To Neq - 1 For j = Neq - i + 1 To Neq term2 = A1(Neq - i, j) * x(j) Next j x(Neq - i) = (A1(Neq - i, Neq + 1) - term2) / A1(Neq - i, Neq - i) Next i For i = 1 To Neq F1(i, 1) = 0 For j = 1 To Neq F1(i, 1) = F1(i, 1) + x(j) * k(i, j) Next j Next i finish = Timer finish = finish - start ReDim answer(1 To krow + 1, 1 To 2) For iend = 1 To krow + 1 If iend <= krow Then answer(iend, 1) = answer(iend, 2) = Else answer(iend, 1) = answer(iend, 2) = End If Next iend Next imain ge = answer x(iend) F1(iend, 1) kc finish End Function Lower Upper Factorization Function lu(k As Range, u As Range, Fin As Range) Dim start As Variant start = Timer For imain = 1 To 100 Dim Dim Dim Dim Dim Dim Dim finish As Variant krow As Variant kcol As Variant Error As String F1 As Variant u1 As Variant k1 As Variant F1 = Fin k1 = k u1 = u Nit = 1000000 TOL = 0.00001 krow = k.Rows.Count kcol = k.Columns.Count urow = u.Rows.Count Frow = Fin.Rows.Count ucol = u.Columns.Count Fcol = Fin.Columns.Count Error = "" error2 = "" If ucol > 1 Or Fcol > 1 Then Error = "Displacement or Force vectors are not specified correctly" Else Error = "OK!!" End If test = 0 check2 = 0 check3 = 0 For i = 1 To urow If IsEmpty(u(i, 1)) Then check = 0 Else check = 1 test = test + 1 End If If i Mod 2 <> 0 And check = 1 Then check2 = check2 + 1 End If Next i If test >= 2 And check2 >= 1 Then error2 = "Enough BCs" Else error2 = "Insufficient BCs" End If For i = 1 To urow If IsEmpty(u(i, 1)) Or IsEmpty(Fin(i, 1)) Then check3 = check3 Else check3 = check3 + 1 End If Next i If check3 >= 1 Then error2 = "Overconstrained" End If For i = 1 To urow If IsEmpty(u(i, 1)) And IsEmpty(Fin(i, 1)) Then F1(i, 1) = 0 End If If IsEmpty(F1(i, 1)) Then F1(i, 1) = u(i, 1) For j = 1 To kcol If i = j Then k1(i, j) = 1 Else k1(i, j) = 0 End If Next j End If Next i kc = 1 Neq = krow n = Neq Dim F As Variant Dim a As Variant 'The variant data type is a chameleon. 'Here it thinks it is a worksheet range. Dim up As Variant Dim l As Variant ReDim l(1 To n, 1 To n) ReDim up(1 To n, 1 To n) Dim answer As Variant F = F1 a = k1 l(1, 1) = 1 up(1, 1) = a(1, 1) For j = 2 To n up(1, j) = a(1, j) / l(1, 1) l(j, 1) = a(j, 1) / up(1, 1) Next j For i = 2 To n - 1 term1 = 0 For kc = 1 To i - 1 term1 = term1 + l(i, kc) * up(kc, i) Next kc up(i, i) = a(i, i) - term1 l(i, i) = 1 For j = i + 1 To n term2 = 0 For kc = 1 To i - 1 term2 = term2 + l(i, Next kc up(i, j) = (1 / l(i, i)) term3 = 0 For kc = 1 To i - 1 term3 = term3 + l(j, Next kc l(j, i) = (1 / up(i, i)) Next j kc) * up(kc, j) * (a(i, j) - term2) kc) * up(kc, i) * (a(j, i) - term3) Next i term4 = 0 For kc = 1 To n - 1 term4 = term4 + l(n, kc) * up(kc, n) Next kc up(n, n) = a(n, n) - term4 l(n, n) = 1 ReDim answer(1 To n, 1 To n + n + 3) Dim x As Variant Dim y As Variant ReDim x(1 To n) ReDim y(1 To n) y(1) = F(1, 1) / l(1, 1) For i = 2 To n term2 = 0 For j = 1 To i - 1 term2 = term2 + y(j) * l(i, j) Next j y(i) = (F(i, 1) - term2) / l(i, i) Next i x(n) = y(n) / up(n, n) For i = 1 To n - 1 term2 = 0 For j = n - i + 1 To n term2 = term2 + up(n - i, j) * x(j) Next j x(n - i) = (y(n - i) - term2) / up(n - i, n - i) Next i For i = 1 To Neq F1(i, 1) = 0 For j = 1 To Neq F1(i, 1) = F1(i, 1) + x(j) * k(i, j) Next j Next i finish = Timer finish = finish - start For i = 1 To n For j = 1 To answer(i, 1) answer(i, 2) answer(i, 3) Next j Next i Next imain lu = answer End Function n = x(i) = F1(i, 1) = finish