-- pde_nl13.adb solve non linear second order, third degree PDE -- improvement: compute nlin and Var's based on nx -- this finds one of multiple solutions, not the expected -- -- solve u^2 u'' + 2 u u' + 3u = f(x) -- f(x) = (41/3)-(2116/9)x+(4780/3)x^2-(48976/9)x^3+ -- (48976.0/9.0)*x*x*x + 9984.0*x*x*x*x - -- (88064.0/9.0)*x*x*x*x*x + (14336.0/3.0)*x*x*x*x*x*x - -- 9984x^4-(88064/9)x^5+(14336/3)x^6-(8192/9)x^7 -- with boundary U(1)=1, U(2)=1 0 < x < 1 -- set up system of equations, use specialized Jacobian, simeq_newton5 -- solution U(x) = 1.0 -(20.0/3.0)*x +12.0*x*x -(16.0/3.0)*x*x*x -- -- with Ada.Text_IO; use Ada.Text_IO; with Ada.Numerics.Long_Elementary_Functions; use Ada.Numerics.Long_Elementary_Functions; with Real_Arrays; -- types real, real_vector, real_matrix use Real_Arrays; with Integer_Arrays; -- types integer_vector use Integer_Arrays; with deriv; with rderiv; with Simeq_Newton5; procedure pde_nl13 is nx : Integer := 5; -- number of coefficients for discrete derivative neqn : Integer := nx; -- number of equations and number of linear unknowns nlin : Integer := 15; -- number of nonlinear terms, specific to this PDE, nx ntot : Integer := neqn+nlin; -- total number of terms k : Real_Matrix(1..neqn,1..ntot); -- nonlinear system of equations xg : Real_Vector(1..nx); -- x grid f : Real_Vector(1..neqn); -- RHS of equations u : Real_Vector(1..ntot); -- solution being computed Ua : Real_Vector(1..neqn); cx : Real_Vector(1..nx); -- numerical first derivative cxx : Real_Vector(1..Nx); -- numerical second derivative hx : real; err, avgerr, Maxerr, x : real; eps : real := 1.0e-6; xmin : Real := 0.0; xmax : Real := 1.0; i, j : Integer; -- linear, then nonlinear terms Var1 : Integer_vector(1..Ntot) := ( 1, 2, 3, 4, 5, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4); Var2 : Integer_Vector(1..Ntot) := ( 0, 0, 0, 0, 0, 2, 3, 4, 3, 4, 2, 2, 3, 4, 2, 3, 4, 2, 3, 4); Var3 : Integer_vector(1..Ntot) := ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 3, 3, 4, 4, 4); Vari1 : Integer_vector(1..Ntot) := ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); Vari2 : Integer_vector(1..Ntot) := ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); -- definition of PDE to be solved function FF(x:real) return real is -- forcing function begin return (41.0/3.0)-(2116.0/9.0)*x +(4780.0/3.0)*x*x - (48976.0/9.0)*x*x*x + 9984.0*x*x*x*x - (88064.0/9.0)*x*x*x*x*x + (14336.0/3.0)*x*x*x*x*x*x - (8192.0/9.0)*x*x*x*x*x*x*x; end FF; function uana(x:real) return real is -- analytic solution and boundary begin return 1.0 -(20.0/3.0)*x +12.0*x*x -(16.0/3.0)*x*x*x; end uana; procedure Print_Equations(n : integer; nlin : integer; Var1 : integer_vector; Var2 : integer_vector; Var3 : integer_vector; Vari1 : integer_vector; Vari2 : Integer_Vector) is Xnames : array(1..5) of String(1..2) := ("X1", "X2", "X3", "X4", "X5"); begin Put_Line("system of equations to be solved, i=1.."&Integer'Image(n)); for j in 1..n loop Put_line("k(i,"&Integer'Image(j)&")*"&Xnames(j)&"+"); end loop; for j in n+1..n+nlin loop Put("k(i,"&Integer'Image(J)&")"); if Var1(J)>0 then Put("*"&Xnames(Var1(J))); end if; if Var2(J)>0 then Put("*"&Xnames(Var2(J))); end if; if Var3(J)>0 then Put("*"&Xnames(Var3(J))); end if; if Vari1(J)>0 then Put("/("&Xnames(Vari1(J))); end if; if Vari2(J)>0 then Put("*"&Xnames(Vari2(J))); end if; if Vari1(J)>0 or Vari2(J)>0 then Put(")"); end if; if J /= n+nlin then Put_Line("+"); else New_Line; end if; end loop; Put_Line(" = f(i)"); New_Line; end Print_Equations; procedure check_soln(U : Real_Vector) is -- check when solution unknown -- u^2 u'' + 2 u u' + 3u = f(x) check for each xg inside boundary xi, err, Smaxerr : real; begin Put_line("check_soln"); smaxerr := 0.0; for I in 2..neqn-1 loop xi := xg(i); rderiv(1, nx, i, hx, cx); rderiv(2, nx, i, hx, cxx); err := 3.0*U(i)-FF(xi); for J in 1..nx loop err := err + U(i)*U(i)*cxx(j)*U(j); err := err + 2.0*U(i)*cx(j)*U(j); end loop; -- j if abs(err)>smaxerr then Smaxerr := abs(err); end if; Put_line("i="&Integer'Image(I)&", err="&Real'Image(err)); end loop; -- i Put_line("check_soln max error="&Real'Image(smaxerr)); end Check_Soln; package Real_IO is new Float_IO(Real); use Real_IO; begin Put_Line("pde_nl13.adb running "); Put_Line("solve u^2 u'' + 2 u u' + 3u = f(x)"); Put_Line(" f(x) = (41/3)-(2116/9)x+(4780/3)x^2-(48976/9)x^3+"); Put_Line(" (48976.0/9.0)*x*x*x + 9984.0*x*x*x*x -"); Put_Line(" (88064.0/9.0)*x*x*x*x*x + (14336.0/3.0)*x*x*x*x*x*x -"); Put_Line(" 9984x^4-(88064/9)x^5+(14336/3)x^6-(8192/9)x^7"); Put_Line(" "); Put_Line(" 0maxerr then maxerr := err; end if; avgerr := avgerr + err; Put("U("&Integer'Image(I)&")="); Put(U(i),3,5,0); Put(", Ua="); Put(Ua(i),3,5,0); Put(", err="); Put(U(i)-Ua(i),3,5,0); New_Line; end loop; Put_Line(" maxerr="& Real'Image(maxerr)&", avgerr="& Real'image(avgerr/Real(neqn))); New_Line; Put_line("check_soln on computed solution against PDE"); check_soln(u); -- for use when analytic solution is not known Put_line("just checking check_soln when given correct solution"); check_soln(Ua); -- checking on checker New_Line; -- try giving the correct solution, to check on solver Put_line("just checking simeq_newton5 when given correct solution \n"); for i in 1..neqn loop U(i) := uana(xg(i)); end loop; simeq_newton5(neqn, nlin, k, f, Var1, Var2, Var3, Vari1, Vari2, U, 6, 0.00001, 1); Put_Line("pde_nl13.adb finished"); end pde_nl13;