// pde44_eq.swift discretize, build linear equations, solve // solve uxxxx(x,y,z,t) + 2 uyyyy(x,y,z,t) + 3 uzzzz(x,y,z,t) + // 4 utttt(x,y,z,t) + 5 uxyt(x,y,z,t) + 6 uyyzz(x,y,z,t) + // 7 uztt(x,y,z,t) + 8 uxxx(x,y,z,t) + 9 uyyt(x,y,z,t) + // 10 uzt(x,y,z,t) + 11 ut(x,y,z,t) + 12 u(x,y,z,t) = // f(x,y,z,t) // f(x,y,z,t) = 706 + 120 t^2 + 140 y^2z + 768 x + // 180 z^2*t + 200 y^2z*t + 44 t^3 + // 110 y^2z^2t + 66 xy + 12t^4 + // 24 z^4 + 36 y^4 + 48 x^4 + // 60 y^2z^2t^2 + 72 xyt + 84 xz + 96 t // // boundary conditions computed using ub(x,y,z,t) // analytic solution is ub(x,y,z,t) = t^4 + 2 z^4 + 3 y^4 + 4 x^4 + // 5 y^2 z^2 t^2 + 6 x y t + // 7 x z + 8 t + 9 // // replace continuous derivatives with discrete derivatives // solve for Uijkl numerical approximation U(x_i,y_j,z_k,t_l) // A * U = F, solve simultaneous equations for U // // // fourth order numerical difference order=4, npoints=5, term=0 // d^4u/dx^4 = (1/(b4[0]*hx^4))*(a4[0][0]*u(x,y,z,t) + a4[0][1]*u(x+hx,y,z,t) + // a4[0][2]*u(x+2hx,y,z,t) + a4[0][3]*u(x+3hx,y,z,t) +a4[0][4]*u(x+4hx,y,z,t)) // // d^4u/dx^4 using subscripts i,j,k,l for i a minimum subscript of x // d^4u/dx^4 =(1/(b4[0]*hx^4))*(a4[0][0]*u(i,j,k,l) + a4[0][1]*u(i+1,j,k,l) + // a4[0][2]*u(i+2,j,k,l) + a4[0][3]*u(i+3,j,k,l) +a4[0][4]*u(i+4,j,k,l)) // // d^4u/dy^4 using subscripts i,j,k,l for j a minimum subscript of y, etc // d^4u/dy^4 =(1/(b4[0]*hy^4))*(a4[0][0]*u(i,j,k,l) + a4[0][1]*u(i,j+1,k,l) + // a4[0][2]*u(i,j+2,k,l) + a4[0][3]*u(i,j+3,k,l) +a4[0][4]*u(i,j+4,k,l)) // // d^4u/dx^4 using subscripts i,j,k,l for i-2 and i+2 allowed subscripts of x // d^4u/dx^4 =(1/(b4[2]*hx^4))*(a4[2][0]*u(i-2,j,k,l) + a4[2][1]*u(i-1,j,k,l) + // a4[2][2]*u(i,j,k,l) + a4[2][3]*u(i+1,j,k,l) +a4[2][4]*u(i+2,j,k,l)) // // d^4u/dx^4 using subscripts i,j,k,l for i a maximum subscript of x // d^4u/dx^4 =(1/(b4[4]*hx^4))*(a4[4][0]*u(i-4,j,k,l) + a4[4][1]*u(i-3,j,k,l) + // a4[4][2]*u(i-2,j,k,l) + a4[4][3]*u(i-1,j,k,l) +a4[4][4]*u(i,j,k,l)) // // subscripts in code use x[i], y[ii], z[iii], t[iiii] // derivatives are computed with b,hx,a included as in // cx[j] for first derivative of x at point j // cxxxx[j] for fourth derivative of x at point j // cyy[jj]*czz[jjj] for d^4u/dy^2dz^2 at jj, jjj // The subscript versions of the derivatives are substituted into the // equation to be solved. The resulting equation is analytically solved // for u(i,j,k,l) = other u terms with coeficients and + f(xi,yj,zk,tl) // The boundaries xmin..xmax, ymin..ymax, zmin..zmax, tmin..tmax are known // The number of grid points in each dimension is known nx, ny, nz, nt // hx=(xmax-xmin)/(nx-1) // hy=(ymax-ymin)/(ny-1) // hz=(zmax-zmin)/(nz-1) // ht=(tmax-tmin)/(tx-1) // thus xi=xmin+i*hx, yj=ymin+j*hy, zk=zmin+k*hz, tl=tmin+l*ht // then the linear system of equations is built, // nxyzt=(nx-2)*(ny-2)*(nz-2)*(nt-2) equations because the boundary value // is known on each end. // The matrix A is nxyzt rows by (nxyzt+1) columns including F // The forcing function vector F is nxyzt elements adjunct to A // The solution vector U is nxyzt elements. // The building of the A matix requires 4 nested loops for rows // i in 1..nx-1, j in 1..ny-1, k in 1..nz-1, l in 1..nt-1 for rows of A // then each term in the differential equation fills in that row // and cs = (nx-2)*(ny-2)*(nz-2)*(nt-2) the RHS, fills the last column of A // subscripting functions are used to compute linear subscripts of A, U // row=(i-1)*(ny-2)*(nz-2)*(nt-2)+(ii-1)*(nz-2)*(nt-2)+(iii-1)*(nt-2)+(iiii-1) // row*(nxyzt+1)+col for A // // care must be taken to move the negative of boundary elements to // the right hand size of the equation to be solved. These are subtracted // from the computed value of the forcing function, cs, for that row. // tests are j==0 || j==nx-1 ... jjjj==0 || jjjj==nt-1 for boundaries // uses simeqb should be imported // uses nuderiv should be imported // uses inverse should be imported // also other utility functions for pde44_eq below print("pde44_eq.swift running") print("Given uxxxx(x,y,z,t) + 2 uyyyy(x,y,z,t) + 3 uzzzz(x,y,z,t) + ") print(" 4 utttt(x,y,z,t) + 5 uxyt(x,y,z,t) + 6 uyyzz(x,y,z,t) + ") print(" 7 uztt(x,y,z,t) + 8 uxxx(x,y,z,t) + 9 uyyt(x,y,z,t) + ") print(" 10 uzt(x,y,z,t) + 11 ut(x,y,z,t) + 12 u(x,y,z,t) = ") print(" f(x,y,z,t) ") print(" f(x,y,z,t) = 706 + 120 t^2 + 140 y^2z + 768 x + ") print(" 180 z^2*t + 200 y^2z*t + 44 t^3 + ") print(" 110 y^2z^2t + 66 xy + 12t^4 + ") print(" 24 z^4 + 36 y^4 + 48 x^4 + ") print(" 60 y^2z^2t^2 + 72 xyt + 84 xz + 96 t ") print("xmin<=x<=xmax ymin<=y<=ymax zmin<=z<=zmax Boundaries ") print("Analytic solution u(x,y,z,t) = t^4 + 2 z^4 + 3 y^4 + ") print(" 4 x^4 + 5 y^2 z^2 t^2 + 6 x y t + 7 x z + 8 t + 9 ") print(" ") let nx = 6 // problem parameters let ny = 6 let nz = 6 let nt = 6 let nxyzt = (nx-2)*(ny-2)*(nz-2)*(nt-2) print("nx=\(nx), ny=\(ny), nz=\(nz), nt=\(nt), nxyzt=\(nxyzt)") var A = [[Double]](repeating:[Double](repeating:0.0,count:nxyzt+1),count:nxyzt) let cs = (nx-2)*(ny-2)*(nz-2)*(nt-2) // constant RHS column // last column is RHS var U = [Double](repeating:0.0,count:nxyzt) var Ua = [Double](repeating:0.0,count:nxyzt) func s(_ i:Int,_ ii:Int,_ iii:Int,_ iiii:Int) -> Int { // for x,y,z,t return (i-1)*(ny-2)*(nz-2)*(nt-2) + (ii-1)*(nz-2)*(nt-2) + (iii-1)*(nt-2) + (iiii-1) } // end s func sk(_ k:Int,_ i:Int,_ ii:Int,_ iii:Int,_ iiii:Int) -> Int { // for x,y,z,t return k*(nxyzt+1) + (i-1)*(ny-2)*(nz-2)*(nt-2) + (ii-1)*(nz-2)*(nt-2) + (iii-1)*(nt-2) + (iiii-1) } // end sk func ss(_ i:Int,_ ii:Int,_ iii:Int,_ iiii:Int, _ j:Int,_ jj:Int,_ jjj:Int,_ jjjj:Int) -> Int { return s(i,ii,iii,iiii)*(nxyzt+1) + s(j,jj,jjj,jjjj) } // end ss func initialize_A() -> [[Double]] { for i in 1.. Double { let nn = max(nx, max(ny, max(nz, nt))) var p1 = [Double](repeating:0.0,count:nn) var p2 = [Double](repeating:0.0,count:nn) var p3 = [Double](repeating:0.0,count:nn) var discrete = 0.0 let x = xg[i] let y = yg[ii] let z = zg[iii] let t = tg[iiii] cx = nuderiv(xord, nx, i, xg) cy = nuderiv(yord, ny, ii, yg) cz = nuderiv(zord, nz, iii, zg) ct = nuderiv(tord, nt, iiii, tg) discrete = 0.0 // four cases of one partial x, y, z, t to any order if xord != 0 && yord == 0 && zord == 0 && tord == 0 { for j in 0..smaxerr { smaxerr = err if err > 1.0 { print("\(i),\(ii),\(iii),\(iiii),err=\(err)") } } } // end iiii } // end iii } // end ii } // end i print("check_soln maxerr=\(smaxerr)") } // end check_soln var val = 0.0 var err = 0.0 var avgerr = 0.0 var maxerr = 0.0 print("check cxxxx = nuderiv(4,nx,0,xg)") cxxxx = nuderiv(4,nx,0,xg) for i in 0..maxerr { maxerr = err } avgerr = avgerr + err print("ug[\(i),\(ii),\(iii),\(iiii)]=\(U[s(i,ii,iii,iiii)]), Ua=\(Ua[s(i,ii,iii,iiii)])), err=\(err)") } // iiii } // iii } // ii } // i avgerr = avgerr/(Double)(nx*ny*nz*nt) print(" maxerr=\(maxerr) avgerr=\(avgerr)") print(" ") print("end pde44_eq.swift") func simeqb(_ AY: [[Double]]) -> [Double] { // X let n = AY.count let m = n+1 var X = [Double](repeating:0.0,count:n) var B = [[Double]](repeating:[Double](repeating:0.0,count:m),count:n) var ROW = [Int](repeating:0,count:n) // ROW INTERCHANGE INDICIES var HOLD = 0 var I_PIVOT = 0 // PIVOT INDICIES var PIVOT = 0.0 // PIVOT ELEMENT VALUE var ABS_PIVOT = 0.0 // check sizes if m != AY[0].count { print("inconistant size arrays rows=\(n),cols=\(AY[0].count)") return X } // BUILD WORKING DATA STRUCTURE for i in 0.. ABS_PIVOT { I_PIVOT = i PIVOT = B[ROW[i]][k] ABS_PIVOT = abs(PIVOT) } } // HAVE PIVOT, INTERCHANGE ROW POINTERS HOLD = ROW[k] ROW[k] = ROW[I_PIVOT] ROW[I_PIVOT] = HOLD // CHECK FOR NEAR SINGULAR if ABS_PIVOT < 1.0E-32 { for j in k.. [[Double]] { let n = a.count var inv = [[Double]](repeating:[Double](repeating:0.0,count:n),count:n) for i in 0.. abs_pivot { I_pivot = i J_pivot = j pivot = inv[row[i]][col[j]] } } } if abs(pivot) < 1.0E-10 { print("Matrix is singular !") return [[Double]](repeating:[Double](repeating:0.0,count:n),count:n) } hold = row[k] row[k] = row[I_pivot] row[I_pivot] = hold hold = col[k] col[k] = col[J_pivot] col[J_pivot] = hold // reduce about pivot inv[row[k]][col[k]] = 1.0 / pivot for j in 0..[Double] { let n = npoint var B = [[Double]](repeating:[Double](repeating:0.0,count:n),count:n) var fct = [Double](repeating:0,count:n) var c = [Double](repeating:0,count:n) var pwr = 0.0 if order <= 0 { return c } for i in 0.. Double { return t*t*t*t + 2.0*z*z*z*z + 3.0*y*y*y*y + 4.0*x*x*x*x + 5.0*y*y*z*z*t*t + 6.0*x*y*t + 7.0*x*z + 8.0*t + 9.0 } // end uana // problem RHS func f(_ x:Double,_ y:Double,_ z:Double,_ t:Double) -> Double { return 706.0 + 120.0*t*t + 140.0*y*y*z + 768.0*x + 180.0*z*z*t + 200.0*y*y*z*t + 44.0*t*t*t + 110.0*y*y*z*z*t + 66.0*x*y + 12.0*t*t*t*t + 24.0*z*z*z*z + 36.0*y*y*y*y + 48.0*x*x*x*x + 60.0*y*y*z*z*t*t + 72.0*x*y*t + 84.0*x*z + 96.0*t } // end f // end pde44_eq.swift