<jupyter_start><jupyter_text>Question 3 Consider Problem. 2, in order to reduce the computational domain and cost, assume a proper boundary condition in the given domain that leads to optimum computational domain and cost of the given problem and determine the temperature distribution. Compare the results with the results of Problem. 2.<jupyter_code># Importing the relevant Python modules
import numpy as np
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>Taking the heat conduction equation as the Laplace equation:$$ \frac{d^2T}{dx^2} + \frac{d^2T}{dy^2} = 0$$ Since taking $\Delta x = \Delta y = 0.01$ does not reduce the accuracy that much, but reduces the computational cost quite a bit, we can consider it.<jupyter_code># Initializing the variables

x = 0.5                 # x-length of the plate in m
y = 0.5                 # y-length of the plate in m
dx = 0.01 
nx = int(x/dx + 1)      # Total number of divisions in the x-direction
dy = 0.01
ny = int(y/dy + 1)      # Total number of divisions in the y-direction

q = 1E5                 # Heat flux in the top wall in W/m^2
k = 41                  # Thermal conductivity in W/mK

print(nx, ny, q)
# Forming the grid

xarr = np.linspace(0, x, nx)     # 1-D Array of Xs
yarr = np.linspace(0, y, ny)     # 1-D Array of Ys

T = np.zeros((nx, ny))           # 2-D array of temperature in the plate<jupyter_output><empty_output><jupyter_text>Boundary ConditionsInstead of considering the top wall to have a constant heat flux of $10^5 W/m^2$, let us consider an isothermal condition of T = $-450°C$. This temperature is chosen based on the previous question, where we can see from the contour plot that the temperature at the top boundary is approximately $-450°C$.<jupyter_code># Applying the boundary conditions

T[0, :] = -450     # New boundary condition for the top
T[:, 0] = 0        # Vertical side
T[:, -1] = 0       # Vertical side
T[-1, :] = 0       # Insulated bottom

print(T)           # This is the initial temperature distribution in the square plate<jupyter_output>[[   0. -450. -450. ... -450. -450.    0.]
 [   0.    0.    0. ...    0.    0.    0.]
 [   0.    0.    0. ...    0.    0.    0.]
 ...
 [   0.    0.    0. ...    0.    0.    0.]
 [   0.    0.    0. ...    0.    0.    0.]
 [   0.    0.    0. ...    0.    0.    0.]]<jupyter_text>Discretizing the Laplace Equation (Finite Difference Method) The discretized Laplace equation is: $$ \frac{T_{i+1, j} - 2T_{i, j} + T_{i-1, j}}{\Delta x^2} + \frac{T_{i, j+1} - 2T_{i, j} + T_{i, j-1}}{\Delta y^2} = 0 $$This becomes,$$ T_{i, j} = 0.25(T_{i+1, j} + T_{i-1, j} + T_{i, j+1} + T_{i, j-1}) $$  Using the Successive Over-Relaxation MethodTo improve the rate of convergence of the solution, we can use the successive over-relaxation method. This method requires a relaxation parameter $\omega$ where $1 < \omega < 2$. This parameter allows for an increased rate of convergence so that it takes lesser number of iterations.Using the SOR method, the discretized equation now becomes:$$ T_{i, j} = 0.25\omega (T_{i+1, j} + T_{i-1, j} + T_{i, j+1} + T_{i, j-1}) + (1 - \omega)T_{i,j}^{old}$$<jupyter_code>def T_dist(T, nt, err, w):
    """
    T_dist is the function that calculates the temperature distribution in the plate by applying the conditions given. 
    It is solved using the Successive Over-Relaxation (SOR) iterative method.
    
    Here, T is the initial temperature distribution of the plate.
    nt is the maximum number of iterations.
    err is the maximum permissible error. 
    w is the relaxation parameter for the SOR method.
    
    This function iterates according to the discretization of the Laplace equation and the constant temperature across the top wall.
    It returns the final temperature distribution of the plate once it satisfies the convergence criterion.
    
    """
    for t in range(1, nt+1):           # t is a single iteration of the maximum number of iterations i.e. nt iterations
        Tn = T.copy()             # A copy of the previous iteration is made to check for the error
        
        # The SOR iteration
        for i in range(1, nx-1):
            for j in range(1, ny-1):
                T[i,j] = 0.25*w*(T[i+1,j] + T[i-1,j] + T[i,j+1] + T[i,j-1]) + (1-w)*Tn[i,j]
        
        if t%200 == 0:                 # The temperature distribution is printed every 200 iterations to check
            print(T)
        
        # Here, the error is calculated by finding the difference between the current iteration and the previous iteration 
        # and ensuring that the difference of all the nodes in the 2-D array are less than the max permissible error.
        
        if (abs(T - Tn) < err).all():
            print('\n')
            print("Iteration number: ", t)       # If the condition is satisfied, the number of iterations taken is printed
            print("The temperature distribution: ", T)  # The final temperature distribution is printed
            return T
        
    return T<jupyter_output><empty_output><jupyter_text>We need to find the optimum relaxation parameter so as to perform the calculation efficiently i.e. with the least amount of iterations possible. I conducted several trials with multiple relaxation parameters to find the most optimum one. The results are as below: | **$\omega$** | **Iterations** | |--------------|----------------| | 1.1 | 2346  |   | 1.2 | 1943 | |1.3 | 1595 | |1.4 | 1290 | |1.5 | 1019 | |1.6 | 776 | |1.7 | 552 | |1.8 | 341 | |1.9 | 170 | |1.95 | 326 |From the table, we can see that $\omega = 1.9$ is an optimum relaxation parameter as it takes only 170 iterations.<jupyter_code># The calculation is carried out with the initial array T, a max iterations of 10,000, an error of 10^-5 and a relaxation
# parameter w = 1.9, the most optimum one.

T_final = T_dist(T, 10000, 1E-5, 1.9)
# The function is now plotted. The plot displays the contours of the temperature distribution.

# The parameters of the contour plot are initialized
colorinterpolation = 50
colourMap = plt.cm.jet

# Setting the meshgrid
X, Y = np.meshgrid(np.arange(0, nx), np.arange(0, ny))

final_T = np.flip(T_final, axis=0)  

#Plotting the contour
fig, ax = plt.subplots(1,1)
cp = ax.contourf(X, Y, final_T, colorinterpolation, cmap=colourMap)
fig.colorbar(cp)

# Adding formatting to the plot
ax.set_xticklabels([0,0.1,0.2,0.3,0.4,0.5])
ax.set_yticklabels([0,0.1,0.2,0.3,0.4,0.5])
ax.set_title("Temperature Distribution in the plate")
plt.show()

#Saving the plot
plt.savefig("contourplot_3.jpg")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11300380228136882, 'fraction_numerical': 0.03878326996197719, 'mean_word_length': 2.779310344827586, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '148713', 'license': 'MIT', 'n_tokens_mistral': 2221, 'n_tokens_neox': 2052, 'n_words': 841, 'path': 'Assignment 1/ME317_Assignment1_Q3.ipynb', 'repo_name': 'drkndl/Everything-CFD', 'size': '6575'}