Guest User

solver_burgers_model

a guest
Dec 7th, 2023
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.77 KB | None | 0 0
  1. import numpy as np
  2. from numpy.linalg import norm
  3.  
  4. def newton_system(fnon, jacobian, x0, tolerance, max_iterations, *fnonargs):
  5.  
  6.     k = 0
  7.     x = x0
  8.  
  9.     F = eval(fnon)(x,*fnonargs)
  10.     n = F.size
  11.  
  12.     print(' k    f(xk)')
  13.  
  14.     while (norm(F,2) > tolerance and k <= max_iterations):
  15.         J = eval(jacobian)(x,n,fnon,F,*fnonargs)
  16.  
  17.         delta = np.linalg.solve(J,-F)
  18.         x = x + delta
  19.  
  20.         F = eval(fnon)(x,*fnonargs)
  21.  
  22.         print('{0:2.0f}  {1:2.2e}'.format(k, norm(F,2)))
  23.         k += 1
  24.  
  25.     if (k >= max_iterations):
  26.         print('Failed to converged')
  27.     else:
  28.         return x
  29.    
  30. import numpy as np
  31. import copy
  32.  
  33. def calcJacobian(x,n,fnon,F0,*fnonargs):
  34.   J = np.zeros((n,n), dtype=np.float64)
  35.   h = 10e-8
  36.  
  37.   for k in range(0,n):
  38.     xb = copy.copy(x)
  39.     xb[k] = xb[k] + h
  40.  
  41.     F = eval(fnon)(xb,*fnonargs)
  42.  
  43.     for i in range(0,n):
  44.         J[i,k] = (F[i] - F0[i]) / h
  45.  
  46.   return J
  47.  
  48. def step_function(x):
  49.         if x <= 0.1:
  50.             return 1
  51.         else:
  52.             return 0
  53.  
  54. # this is just to display the step function
  55. from matplotlib import pyplot as plt
  56. x_xis = np.linspace(0, 1, 400)
  57. y = np.zeros(400)
  58. for i in range(400):
  59.     y[i] = step_function(x_xis[i])
  60.  
  61. plt.plot(xxis, y)
  62. plt.title('Step Function')
  63. plt.xlabel('Spatial coordinate x')
  64. plt.ylabel('Solution u')
  65. plt.grid(True)
  66. plt.show()
  67.  
  68.  
  69.  
  70. def setupInitialData( m ):
  71.     xL = 0
  72.     xR = 1
  73.    
  74.     h = (xR - xL) / (m-1)                      # mesh size
  75.     x = np.linspace(xL, xR, m).reshape((m, 1)) # grid points
  76.     v = np.zeros(len(x))
  77.     for i in range(len(x)):
  78.         v[i] = step_function(x[i]) # initial data
  79.    
  80.     return v
  81.  
  82. def discreteBurgers(uk, ukp, dt, h, nu, ua, ub):
  83.     # ua is boundary condition
  84.     # ub is boundary condition
  85.     # nu is kinematic viscosity
  86.     m = uk.size
  87.     # f to store values of the function for each point uk in space
  88.     f = np.zeros((m-2, 1))
  89.  
  90.     # boundary conditions
  91.     uL = ua
  92.     uR = ub
  93.  
  94.     # left boundary (ERROR OCCURS HERE)
  95.     f[0] = (uk[0] - ukp[1])/dt + uk[0] * (uk[0] - uL)/h - nu * (uk[1] - 2*uk[0] + uL)/h**2
  96.  
  97.     # Difference equations at each internal node
  98.     for i in range(1, m-3):
  99.         f[i] = (uk[i] - ukp[i+1])/dt + uk[i] * (uk[i] - uk[i-1])/h - nu * (uk[i+1] - 2*uk[i] + uk[i-1])/h**2
  100.  
  101.     # right boundary
  102.     f[m-3] = (uk[m-3] - ukp[m-2])/dt + uk[m-3] * (uk[m-3] - uk[m-4])/h - nu * (uR - 2*uk[m-3] + uk[m-4])/h**2
  103.  
  104.     return f
  105.  
  106.  
  107. def burgersModel( dtIn, nTimeSteps, mIn ):
  108.  
  109.   # Input:  dtIn       - time step size
  110.   #         nTimeSteps - number of time steps
  111.   #         mIn        - grid dimension
  112.   # Output: sols       - array of solution vectors u^k
  113.  
  114.   dt = dtIn   # time step size
  115.   m = mIn     # dimension of spatial mesh for [X1,X2]
  116.   n = m-2     # number of nonlinear equations (excluding boundary condition)
  117.   h = 1/(m-1) # grid size
  118.  
  119.   # Initial and boundary conditions
  120.   uOld = initialData( m )
  121.   u0 = np.zeros( (n,1) )
  122.  
  123.   # store solutions in time
  124.   sols = []
  125.   sols.append(uOld)
  126.  
  127.   for k in range( 0, nTimeSteps ):
  128.     print('Time step: {0:1.0f}'.format(k))
  129.  
  130.     # Use previous time step as the initial guess for Newton
  131.     u0 = uOld[1:n+1] # take the values in the middle, ignoring left and right boundary values
  132.  
  133.     # Call the Newton solver
  134.     #uk, ukp, dt, h, nu, ua, ub
  135.     nu = 0.01
  136.     ua = 1 #u(0,t) = 1
  137.     ub = 0 #u(1,t) = 0
  138.  
  139.     u = newton_system("discreteBurgers", "calcJacobian", u0, 1e-6, 10, uOld, dt, h, nu, ua, ub)
  140.  
  141.     # Update the previous time step
  142.     uOld[1:n+1] = u[0:n] # insert new values as old now into the middle, not updating left and right boundaries
  143.  
  144.     # Store vector of solutions
  145.     sols.append(copy.copy(uOld))
  146.  
  147.   return sols;
  148.  
  149. mPts = 101
  150. tPts = 10
  151. sols = burgersModel( 0.01, tPts, mPts )
Advertisement
Add Comment
Please, Sign In to add comment