Thursday 12 October 2023

Saithe Fish UDF (ANSYS Fluent)

     This post is about Fish Simulation in ANSYS Fluent using a User Defined Function (UDF). The UDF is mentioned below. The flow conditions are taken from [1]. This goes with the videos shown in Fig. 1-2. The CAD files for t=0 are available here (for UDF 01).

Fig. 1, Animation of motion achieved through the UDF 01.

 
 Fig. 2, Animation of motion achieved through the UDF 02 (Validated).

     The results of present simulations are compared with [1]. The results are in excellent agreement as the Cl, max from [1] is at 1.57 while the maximum Cl, max from present simulation is at 1.6. The drag coefficient [1], Cd, max in [1] is at 0.164; while from the present simulations I got, 0.151. The Cd, avg comes out to be 0.072 [1] form the present simulations. I got a value of 0.064 from he present simulation. These would gradually become more accurate with mesh refinement, which I will certainly do if I send some ideas I have for peer review.

UDF 01:

#include "udf.h"
#include "unsteady.h"
#include "dynamesh_tools.h"
#include "math.h"


DEFINE_GRID_MOTION(dynamic,domain,dt,time,dtime)
{
 Thread *tf = DT_THREAD(dt);
 face_t f;
 Node *v;
 int n;
 double x, y, y_ref_previous, y_ref;
 SET_DEFORMING_THREAD_FLAG(THREAD_T0(tf));  
 begin_f_loop(f,tf) {
  f_node_loop(f,tf,n) {
   v = F_NODE(f,tf,n);
   if (NODE_POS_NEED_UPDATE(v)) {
    NODE_POS_UPDATED(v);
    x = NODE_X(v);
    real amplitude = 0.02 + 0.01*x + 0.1*x*x;
    y_ref_previous = amplitude * cos(2*M_PI*x + 2*M_PI*0.8*(PREVIOUS_TIME));
    y_ref = amplitude * cos(2*M_PI*x + 2*M_PI*0.8*(CURRENT_TIME));
     
if (NODE_Y(v) > y_ref_previous){
     NODE_Y(v) = y_ref+fabs(NODE_Y(v)-y_ref_previous);
    }
    else 
     if (NODE_Y(v) < y_ref_previous){
      NODE_Y(v) = y_ref-fabs(NODE_Y(v)-y_ref_previous);
     }
     else {
      NODE_Y(v) = y_ref;
     }
    }
   }
  }
 }
 end_f_loop(f,tf);

UDF 02 (Validated):

#include "udf.h"

DEFINE_GRID_MOTION(dynamic,domain,dt,time,dtime)
{
 Thread *tf = DT_THREAD(dt);
 face_t f;
 Node *v;
 int n;
 double x, y_ref_previous, y_ref, amplitude, fr;
 SET_DEFORMING_THREAD_FLAG(THREAD_T0(tf));  
 begin_f_loop(f,tf) {
  f_node_loop(f,tf,n) {
   v = F_NODE(f,tf,n);
   if (NODE_POS_NEED_UPDATE(v)) {
    NODE_POS_UPDATED(v);
    x = fabs(NODE_X(v));
    amplitude = 0.02 - 0.0825 * x + 0.1625 * x * x;
    fr = 2;
    y_ref_previous = amplitude * cos(2 * M_PI * x - 2 * M_PI * fr * (PREVIOUS_TIME));
    y_ref = amplitude * cos(2 * M_PI * x - 2 * M_PI * fr * (CURRENT_TIME));
     
if (NODE_Y(v) > y_ref_previous){
     NODE_Y(v) = y_ref + fabs(NODE_Y(v) - y_ref_previous);
    }
    else 
     if (NODE_Y(v) < y_ref_previous){
      NODE_Y(v) = y_ref - fabs(NODE_Y(v) - y_ref_previous);
     }
     else {
      NODE_Y(v) = y_ref;
     }
    }
   }
  }
 }
 end_f_loop(f,tf);

If you want to hire me as you next shining PhD/Master student or collaborate in research, please reach out! Thank you for reading!

References

[1] Gen-Jin Dong, Xi-Yun Lu; Characteristics of flow over traveling wavy foils in a side-by-side arrangement. Physics of Fluids 1 May 2007; 19 (5): 057107. https://doi.org/10.1063/1.2736083

Thursday 21 September 2023

Lid-Driven Cavity MATLAB Code

     MATLAB code for 2D Lid-Driven Cavity. Includes labeled commands, plotting and is less than 100 lines of code. Resume possible, to resume comment close all, clear, clc, u, v, p and then run the code. Results are available here:


%% clear and close

close all

clear

clc


%% define spatial and temporal grids

h = 1/10; % grid spacing

cfl = h; % cfl number

L = 1; % cavity length

D = 1; % cavity depth

Nx = round((L/h)+1); % grid points in x-axis

Ny = round((D/h)+1); % grid points in y-axis

nu = 0.000015111; % kinematic viscosity

Uinf = 0.0015111; % free stream velocity / lid velocity

dt = h * cfl / Uinf; % time step

travel = 2; % times the disturbance travels entire length of computational domain

TT = travel * L / Uinf; % total time

ns = TT / dt; % number of time steps

l_square = 1; % length of square

Re = l_square * Uinf / nu; % Reynolds number

rho = 1.2047; % fluid density


%% initialize flowfield

u = zeros(Nx,Ny); % x-velocity

v = zeros(Nx,Ny); % y-velocity

p = zeros(Nx,Ny); % pressure

i = 2:Nx-1; % spatial interior nodes in x-axis

j = 2:Ny-1; % spatial interior nodes in y-axis

[X, Y] = meshgrid(0:h:L, 0:h:D); % spatial grid

maxNumCompThreads('automatic'); % select CPU cores


%% solve 2D Navier-Stokes equations

for nt = 1:ns

    pn = p;

    p(i, j) = ((pn(i+1, j) + pn(i-1, j)) * h^2 + (pn(i, j+1) + pn(i, j-1)) * h^2) ./ (2 * (h^2 + h^2)) ...

        - h^2 * h^2 / (2 * (h^2 + h^2)) * (rho * (1 / dt * ((u(i+1, j) - u(i-1, j)) / (2 * h) + (v(i, j+1) - v(i, j-1)) / (2 * h)))); % pressure poisson

    p(1, :) = p(2, :); % dp/dx = 0 at x = 0

    p(Nx, :) = p(Nx-1, :); % dp/dx = 0 at x = L

    p(:, 1) = p(:, 2); % dp/dy = 0 at y = 0

    p(:, Ny) = 0; % p = 0 at y = D 

    un = u;

    vn = v;

    u(i, j) = un(i, j) - un(i, j) * dt / (2 * h) .* (un(i+1, j) - un(i-1, j)) ...

        - vn(i, j) * dt / (2 * h) .* (un(i, j+1) - un(i, j-1)) - dt / (2 * rho * h) * (p(i+1, j) - p(i-1, j)) ...

        + nu * (dt / h^2 * (un(i+1, j) - 2 * un(i, j) + un(i-1, j)) + dt / h^2 * (un(i, j+1) - 2 * un(i, j) + un(i, j-1))); % x-momentum

    u(1, :) = 0; % u = 0 at x = 0

    u(Nx, :) = 0; % u = 0 at x = L

    u(:, 1) = 0; % u = 0 at y = 0

    u(:, Ny) = Uinf; % u = Uinf at y = D

    v(i, j) = vn(i, j) - un(i, j) * dt / (2 * h) .* (vn(i+1, j) - vn(i-1, j)) ...

        - vn(i, j) * dt / (2 * h) .* (vn(i, j+1) - vn(i, j-1)) - dt / (2  * rho * h) * (p(i, j+1) - p(i, j-1)) ...

        + nu * (dt / h^2 * (vn(i+1, j) - 2 * vn(i, j) + vn(i-1, j)) + dt / h^2 * (vn(i, j+1) - 2 * vn(i, j) + vn(i, j-1))); % y-momentum

    v(1, :) = 0; % v = 0 at x = 0

    v(Nx, :) = 0; % v = 0 at x = L

    v(:, 1) = 0; % v = 0 at y = 0

    v(:, Ny) = 0; % v = 0 at y = D

end


%% post-processing

velocity_magnitude = sqrt(u.^2 + v.^2); % velocity magnitude


% Visualize velocity vectors and pressure contours

hold on

contourf(X, Y, velocity_magnitude', 64, 'LineColor', 'none'); % contour plot

set(gca,'FontSize',40)

% skip = 20;

% quiver(X(1:skip:end, 1:skip:end), Y(1:skip:end, 1:skip:end),... % Velocity vectors

%     u1(1:skip:end, 1:skip:end)', v1(1:skip:end, 1:skip:end)', 1, 'k','LineWidth', 0.1);

hh = streamslice(X, Y, u', v', 5); % Streamlines

set(hh, 'Color', 'k','LineWidth', 0.1);

colorbar; % Add color bar

colormap hsv % Set color map

axis equal % Set true scale

xlim([0 L]); % Set axis limits

ylim([0 D]);

xticks([0 L]) % Set ticks

yticks([0 D]) % Set ticks

clim([0 0.95*max(velocity_magnitude(:))]) % Legend limits

title('Velocity [m/s]');

xlabel('x [m]');

ylabel('y [m]');


Cite as: Fahad Butt (2023). Lid-Driven Cavity (https://fluiddynamicscomputer.blogspot.com/2023/09/lid-driven-cavity-matlab-code.html), Blogger. Retrieved Month Date, Year

Saturday 26 August 2023

Open - Source coded 3D Navier–Stokes equations in C++

     Here are 3D Navier–Stokes equations configured for lid-driven cavity flow. The syntax is C++. The results from this code are shown in Fig. 1. From the pressure-Poisson equation, I removed mixed derivative terms to improve solution stability. 😆

p[i][j][k] = ((p[i+1][j][k] + p[i-1][j][k]) * h * h + (p[i][j+1][k] + p[i][j-1][k]) * h * h + (p[i][j][k+1] + p[i][j][k-1]) * h * h) / (2 * (h * h + h * h + h * h)) - h * h * h * h * h * h / (2 * (h * h + h * h + h * h)) * (rho * (1 / dt * ((u(i+1, j, k) - u(i-1, j, k)) / (2 * h) + (v(i, j+1, k) - v(i, j-1, k)) / (2 * h) + (w(i, j, k+1) - w(i, j, k-1)) / (2 * h))));

p[0][j][k] = p[1][j][k];

p[num_i - 1][j][k] = p[num_i - 2][j][k];

p[i][0][k] = p[i][1][k];

p[i][num_j - 1][k] = p[i][num_j - 2][k];

p[i][j][0] = p[i][j][1];

p[i][j][num_k - 1] = 0.0;

u[i][j][k] = u[i][j][k] - u[i][j][k] * dt / (2 * h) * (u[i+1][j][k] - u[i-1][j][k]) - v[i][j][k] * dt / (2 * h) * (u[i][j+1][k] - u[i][j-1][k]) - w[i][j][k] * dt / (2 * h) * (u[i][j][k+1] - u[i][j][k-1]) - dt / (2 * rho * h) * (p[i+1][j][k] - p[i-1][j][k]) + nu * (dt / (h * h) * (u[i+1][j][k] - 2 * u[i][j][k] + u[i-1][j][k]) + dt / (h * h) * (u[i][j+1] [k] - 2 * u[i][j][k] + u[i][j-1][k]) + dt / (h * h) * (u[i][j][k+1] - 2 * u[i][j][k] + u[i][j][k-1]));

u[0][j][k] = 0.0;

u[num_i - 1][j][k] = 0.0;

u[i][0][k] = 0.0;

u[i][num_j - 1][k] = 0.0;

u[i][j][0] = 0.0;

u[i][j][num_k - 1] = -Uinf;

v[i][j][k] = v[i][j][k] - u[i][j][k] * dt / (2 * h) * (v[i+1][j][k] - v[i-1][j][k]) - v[i][j][k] * dt / (2 * h) * (v[i][j+1][k] - v[i][j-1][k]) - w[i][j][k] * dt / (2 * h) * (v[i][j][k+1] - v[i][j][k-1]) - dt / (2 * rho * h) * (p[i][j+1][k] - p[i][j-1][k]) + nu * (dt / (h * h) * (v[i+1][j][k] - 2 * v[i][j][k] + v[i-1][j][k]) + dt / (h * h) * (v[i][j+1][k] - 2 * v[i][j][k] + v[i][j-1][k]) + dt / (h * h) * (v[i][j][k+1] - 2 * v[i][j][k] + v[i][j][k-1]));

v[0][j][k] = 0.0;

v[num_i - 1][j][k] = 0.0;

v[i][0][k] = 0.0;

v[i][num_j - 1][k] = 0.0;

v[i][j][0] = 0.0;

v[i][j][num_k - 1] = 0.0;

w[i][j][k] = w[i][j][k] - u[i][j][k] * dt / (2 * h) * (w[i+1][j][k] - w[i-1][j][k]) - v[i][j][k] * dt / (2 * h) * (w[i][j+1][k] - w[i][j-1][k]) - w[i][j][k] * dt / (2 * h) * (w[i][j][k+1] - w[i][j][k-1]) - dt / (2 * rho * h) * (p[i][j][k+1] - p[i][j][k-1]) + nu * (dt / (h * h) * (w[i+1][j][k] - 2 * w[i][j][k] + w[i-1][j][k]) + dt / (h * h) * (w[i][j+1][k] - 2 * w[i][j][k] + w[i][j-1][k]) + dt / (h * h) * (w[i][j][k+1] - 2 * w[i][j][k] + w[i][j][k-1]));

w[0][j][k] = 0.0;

w[num_i - 1][j][k] = 0.0;

w[i][0][k] = 0.0;

w[i][num_j - 1][k] = 0.0;

w[i][j][0] = 0.0;

w[i][j][num_k - 1] = 0.0;


Fig. 1, Velocity and pressure iso-surfaces


     Of course constants need to be defined, such as grid spacing in space and time, density, kinematic viscosity. These equations have been validated, as you might have read and here already! Happy coding!

     If you want to hire me as your PhD student in the research projects related to turbo-machinery, aerodynamics, renewable energy, please reach out. Thank you very much for reading.

Monday 14 August 2023

Heaving Flat Plate Computational Fluid Dynamics (CFD) Simulation (In-House CFD Code)

     The adventure 🏕 🚵 I started a while ago to make my own CFD 🌬 code / software 💻 for my digital CV and to make a shiny new turbulence mode (one-day perhaps) is going along nicely. This post is about a 2D 10% flat plate undergoing forced heaving motion. Heaving motion is achieved by Eqn. 1.


hy = Ho*sin(2*π*fh*t)                                              Eqn. 1

     w.r.t. Eqn. 1 reduced frequency is defined as (fh*Ho/U∞)), fh is the frequency of oscillations, while t is the instantaneous time. Ho is the heaving amplitude and U∞ is the free stream velocity. hy is the position of the flat plate. The animation is shown in Fig. 1.

     The Strouhal number is 0.228 and Reynolds number is at 500. As we can see, the in-house CFD code works very well for this complex CFD simulation. Validation of this work will never be completed 😆. As soon, I will move on to the next project without completing this one. Anyway, discretized Navier-Stokes equations are available here, in both C++ and MATLAB formats if you want to validate this non sense yourself! Good Luck!

The animation from in-house CFD simulation

     If you want to hire me as your PhD student in the research projects related to turbo-machinery, aerodynamics, renewable energy, please reach out. Thank you very much for reading.

Saturday 22 July 2023

Home-Made Computational Fluid Dynamics (CFD), (Includes CFD code)

     One fine morning, I decided to code the Navier–Stokes equations using the finite-difference method. This post has the results of this adventure 🏞️ (so-far). As is customary with all my CFD work using commercial and home-made CFD codes, this too is inspired by the free lectures of Dr. Lorena Barba.

Internal / External Fluid Dynamics - Lid-Driven Cavity

     I started using Lid-Driven Cavity example. Just because everyone else uses it to validate the code they write. The lid-driven cavity case is giving correct results up to ~Re 1,000 without any turbulence models or wall functions.

     The results shown in Fig. 1 correspond to at Re 1,000. It can be seen that the present code which is just vanilla Navier–Stokes; captures the vortices at both bottom edges well as compared to published data. But why would you want to use a vanilla CFD code which solved only ~Re 1,000?, anyways... Some validation... u-velocity at (0.5, 0.1719) is at -0.3869 m/s as compared to -0.38289 m/s [1]. Meanwhile, v-velocity at (0.2266, 0.5) is 0.3252 as compared to 0.30203. Furthermore, v-velocity at (0.8594, 0.5) is at -0.4128 m/s as compared to -0.44993 m/s. All in all, a good agreement with published data. An animation is uploaded here.  Fig. 1a shows a different variation of lid driven cavity.


Fig. 1, Lid driven cavity post-processing


Fig. 1a, Heated lid driven cavity post-processing

Internal / External Aerodynamics - Backward-Facing Step (BFS)

     The next example is the case of Backward Facing Step (BFS). This case is analogues to flow around a building or a pipe with different diameter or anything with sharp edge along the flow. Let's be honest, flow around a building 🏢 is at much higher Re than the measly ~1,000 this code solves. But for validation, here we are.
 
     The cases are self validating as the re-attachment length of the vortex just after the step is very well documented [4]. Fig. 2 compares the results from the vanilla code with published data. It can be seen that the results are in good agreement.

Fig. 2, Backward Facing Step (BFS) post processing at Re 200


Internal Fluid Dynamics - Aero-Thermal Pipe Flow

     This is the first case I ran as it is self validating. The product of area and velocity should be same at  the outlet as given at the inlet as a boundary condition, which it is! Furthermore, density calculated should be proportional to the temperature calculated, which it is! The results at Re ~3300 are shown in Fig. 3. This case is relevant to bio medical field as Reynolds number in human blood 🩸flow is around same flow regime. Moreover, flow through heated pipes etc. is also relevant.

Fig. 3, Flow through heated pipe / between flat plates

Clot Flow

     Fig. 4 shows an example of flow where a clot appears in a blood 🩸 vessel. Done on this same 🏡made CFD 🌬️ code used throughout this blog. Or in a pipe where oil 🛢️ flows. It can be seen how smooth /less chaotic the flow is without clot (less work for heart ❤️ ). Eat 🦐 🥑 🥙 🥕 🥒 🍲 healthy! Mechanical properties of fluid are taken as follows. 5 ltr/min flowrate. Blood vessel diameter 40 mm. Fluid density at 1,070 Kg/m3 and dynamic viscosity at 4.5 cP.

Fig. 4, Flow inside a blood vessel with and without clot


External Aerodynamics - Flow around a Square Cylinder

     Why not circular cylinder you ask? I am very lazy 😂. It is hard work to draw a circle using code. I am used to CAD. 😇. Again, low Reynolds number are very rare in practical applications but for the sake of completeness, I added this case as well. Fig. 5 shows flow around the cylinder at Re 100. Vorticity is shown in Fig. 5. The results are compared with experimental data. The Strouhal number from the home-made CFD code is at 0.158 as compared to a value of 0.148. The results are within 7%  of published literature [2-3].


Fig. 5, Post-processing

Thank you for reading! If you want to hire me as your most awesome PhD student, please reach out!

Code:

     I present to you the code-able discretized equations for solving fluid flow problems. At first, C++ version is presented followed by the MATLAB version. Equation 1-2 are Poisson equations for pressure. Equation 3 and 4 are x-momentum equations (without source). Equations 5 and 6 are y-momentum equations.

double p_ij = ((pn(i + 1, j) + pn(i - 1, j)) * dy * dy + (pn(i, j + 1) + pn(i, j - 1)) * dx * dx) / (2 * (dx * dx + dy * dy)) - dx * dx * dy * dy / (2 * (dx * dx + dy * dy)) * (rho * (1 / dt * ((u(i + 1, j) - u(i - 1, j)) / (2 * dx) + (v(i, j + 1) - v(i, j - 1)) / (2 * dy)) - ((u(i + 1, j) - u(i - 1, j)) / (2 * dx)) * ((u(i + 1, j) - u(i - 1, j)) / (2 * dx)) - 2 * ((u(i, j + 1) - u(i, j - 1)) / (2 * dy) * (v(i + 1, j) - v(i - 1, j)) / (2 * dx)) - ((v(i, j + 1) - v(i, j - 1)) / (2 * dy)) * ((v(i, j + 1) - v(i, j - 1)) / (2 * dy))));                (1)

p(i, j) = ((pn(i+1, j) + pn(i-1, j)) * dy^2 + (pn(i, j+1) + pn(i, j-1)) * dx^2) ./ (2 * (dx^2 + dy^2)) - dx^2 * dy^2 / (2 * (dx^2 + dy^2)) * (rho * (1/dt * ((u(i+1, j) - u(i-1, j)) / (2 * dx) + (v(i, j+1) - v(i, j-1)) / (2 * dy)) - ((u(i+1, j) - u(i-1, j)) / (2 * dx)).^2 - 2 * ((u(i, j+1) - u(i, j-1)) / (2 * dy) .* (v(i+1, j) - v(i-1, j)) / (2 * dx)) - ((v(i, j+1) - v(i, j-1)) / (2 * dy)).^2));                (2)

double u_ij = un(i, j) - un(i, j) * dt / dx * (un(i, j) - un(i - 1, j)) - vn(i, j) * dt / dy * (un(i, j) - un(i, j - 1)) - dt / (2 * rho * dx) * (p(i + 1, j) - p(i - 1, j)) + nu * (dt / (dx * dx) * (un(i + 1, j) - 2 * un(i, j) + un(i - 1, j)) + dt / (dy * dy) * (un(i, j + 1) - 2 * un(i, j) + un(i, j - 1)));                (3)


u(i, j) = un(i, j) - un(i, j) * dt/dx .* (un(i, j) - un(i-1, j)) - vn(i, j) * dt/dy .* (un(i, j) - un(i, j-1)) - dt / (2 * rho * dx) * (p(i+1, j) - p(i-1, j)) + nu * (dt/dx^2 * (un(i+1, j) - 2 * un(i, j) + un(i-1, j)) + (dt/dy^2 * (un(i, j+1) - 2 * un(i, j) + un(i, j-1))));                (4)


double v_ij = vn(i, j) - un(i, j) * dt / dx * (vn(i, j) - vn(i - 1, j)) - vn(i, j) * dt / dy * (vn(i, j) - vn(i, j - 1)) - dt / (2 * rho * dy) * (p(i, j + 1) - p(i, j - 1)) + nu * (dt / (dx * dx) * (vn(i + 1, j) - 2 * vn(i, j) + vn(i - 1, j)) + dt / (dy * dy) * (vn(i, j + 1) - 2 * vn(i, j) + vn(i, j - 1)));                (5)

v(i, j) = vn(i, j) - un(i, j) * dt/dx .* (vn(i, j) - vn(i-1, j)) - vn(i, j) * dt/dy .* (vn(i, j) - vn(i, j-1)) - dt / (2 * rho * dy) * (p(i, j+1) - p(i, j-1)) + nu * (dt/dx^2 * (vn(i+1, j) - 2 * vn(i, j) + vn(i-1, j)) + (dt/dy^2 * (vn(i, j+1) - 2 * vn(i, j) + vn(i, j-1))));                (6)
    

     Of course constants need to be defined, such as grid spacing in space and time, density, kinematic viscosity. These equations have been validated, as you might have read already! Happy coding!


     If you want to hire me as your PhD student in the research projects related to turbo-machinery, aerodynamics, renewable energy, please reach out. Thank you very much for reading.


References

[1] U Ghia, K.N Ghia, C.T Shin, "High-Re solutions for incompressible flow using the Navier-Stokes equations and a multigrid method", Journal of Computational Physics, Volume 48, Issue 3, 1982, Pages 387-411, ISSN 0021-9991, https://doi.org/10.1016/0021-9991(82)90058-4
[2] Khademinejad, Taha & Talebizadeh Sardari, Pouyan & Rahimzadeh, Hassan. (2015). Numerical Study of Unsteady Flow around a Square Cylinder in Compare with Circular Cylinder
[3] Ávila, Ítalo & Santos, Gabriel & Ribeiro Neto, Hélio & Neto, Aristeu. (2019). Physical Mathematical and Computational Modeling of the Two-Dimensional Flow Over a Heated Porous Square Cylinder. 10.26678/ABCM.COBEM2019.COB2019-0854
[4] Irisarri, Diego & Hauke, Guillermo. (2019). Stabilized virtual element methods for the unsteady incompressible Navier–Stokes equations. Calcolo. 56. 10.1007/s10092-019-0332-5. 

Monday 10 July 2023

CFD Basics: Code Vectorization

     This post is about comparing 2 codes to solve the 2D Laplace equation using finite difference method. A sample code mentioned under "Code 01" uses nested loops. We must, wherever possible avoid nested loops. The solution to the code is shown in Fig. 1. The second code uses vectorization instead of the nested loops. The vectorized version is mentioned under  "Code 02".

Code 01

clear
clc
close all
%% Parameters
Lx = 1; % Length of the domain in the x-direction
Ly = 1; % Length of the domain in the y-direction
Nx = 201; % Number of grid points in the x-direction
Ny = 201; % Number of grid points in the y-direction
dx = Lx / (Nx - 1); % Grid spacing in the x-direction
dy = Ly / (Ny - 1); % Grid spacing in the y-direction
%% Initialize temperature matrix
T = zeros(Nx, Ny);
T(:, 1) = 100;
T(:, Nx) = 0;
T(1, :) = 25;
T(Ny, :) = 50;
%% Gauss-Seidel iteration
max_iter = 50000; % Maximum number of iterations
tolerance = 1e-10; % Convergence tolerance
error = inf; % Initialize error
iter = 0; % Iteration counter
while error > tolerance && iter < max_iter
T_old = T;
% Solve Laplace equation using Gauss-Seidel iterations
for i = 2:Nx-1
for j = 2:Ny-1
T(i, j) = ((T(i+1, j) + T(i-1, j))*dy^2 + (T(i, j+1) + T(i, j-1))*dx^2) / (2*(dx^2 + dy^2));
end
end
% Compute error
error = max(abs(T(:) - T_old(:)));
% Increment iteration counter
iter = iter + 1;
end
%% plotting
[X, Y] = meshgrid(0:dx:Lx, 0:dy:Ly);
contourf(X, Y, T')
axis equal
colormap jet
colorbar
clim([0 100])
title('Temperature Distribution Non Vec')
xlabel('x')
ylabel('y')
zlabel('Temperature (T)')
colorbar

Code 02

clear
clc
close all
%% Parameters
Lx = 1; % Length of the domain in the x-direction
Ly = 1; % Length of the domain in the y-direction
Nx = 201; % Number of grid points in the x-direction
Ny = 201; % Number of grid points in the y-direction
dx = Lx / (Nx - 1); % Grid spacing in the x-direction
dy = Ly / (Ny - 1); % Grid spacing in the y-direction
i = 2:Nx-1;
j = 2:Ny-1;
%% Initialize temperature matrix
T = zeros(Nx, Ny);
T(:, 1) = 100;
T(:, Nx) = 0;
T(1, :) = 25;
T(Ny, :) = 50;
%% Gauss-Seidel iteration
max_iter = 50000; % Maximum number of iterations
tolerance = 1e-10; % Convergence tolerance
error = inf; % Initialize error
iter = 0; % Iteration counter
while error > tolerance && iter < max_iter
T_old = T;
% Solve Laplace equation using Gauss-Seidel iterations
T(i, j) = ((T(i+1, j) + T(i-1, j))*dy^2 + (T(i, j+1) + T(i, j-1))*dx^2) / (2*(dx^2 + dy^2));
% Compute error
error = max(abs(T(:) - T_old(:)));
% Increment iteration counter
iter = iter + 1;
end
%% plotting
[X, Y] = meshgrid(0:dx:Lx, 0:dy:Ly);
contourf(X, Y, T')
axis equal
colormap jet
colorbar
clim([0 100])
title('Temperature Distribution Vec')
xlabel('x')
ylabel('y')
zlabel('Temperature (T)')
colorbar

Result

Results say that vectorized code is ~1.5x faster than nested looped code for 200x200 matrix. Simulation results are now presented.

Fig. 1, Vectorized VS Nested Loops


Thank you for reading! I hope you learned something new! If you like this blog and want to hire me as your PhD student, please get in touch!

Monday 17 April 2023

Executive transport aircraft with truss-braced wing (World's First)

     To explore large-er aspect ratio wings; one fine morning, I just thought it would be fun to put a truss-braced wing in a Piaggio P.180 "Avanti". The modified design CAD files are is available here. A comparison is shown in Fig. 1. I am too lazy to make 2 separate airplanes so I modified half of it so I can run a CFD analysis using one model and one mesh 🤣. A slight modification about which I will write later is the positioning of the flaps and ailerons. These are moved to the truss part from the main wing in the original design. The aspect ratio is of the truss-braced section is double the original. With a foldable wing, storage shouldn't be a problem?


Fig. 1, Row 1, L-R Top, bottom; Row 2, L-R front, back; Row 3 L-R, left, right views

     Cruise conditions are taken from [1] i.e. ~12,500 m and ~163.6 m/s. The CFD mesh has 4,892,425 cells out of those, 449,732 are the the surface of the jet. I compare lift/drag of both halves. The modified section produces 36.15% more drag (force) as compared to the original design. The modified section however, produces 49% more lift (force) than the original design. L/D for truss-winged section is at 6.72 as compared to 6.14 for the original design. In terms of L/D, the truss-braced wing section produced 🥁 ... 9.45% more Lift/Drag. A resounding success 😁, I'd say. For validation of CFD, read this and this.

     Some post processing I did, is shown in Fig. 2. Velocity iso-lines with vectors are shown around the wings. Vorticity is shown in the wake of the jet(s). Tip vortex is smaller and less intense behind the truss-braced wing portion but there is another vortex where the truss meets with the main wing. In the main wing, for the trussed-braced portion; on the pressure side; the high pressure zones extend for a longer portion of the span in the span-wise direction as compared to the original design. Same is true for low pressure zones on the suction side of the main wing. Some day I will write a nice little paper and sent it to an AIAA conference, till then 𝌗.



Fig. 2, Colorful Fluid Dynamics 🌈

     Stream-wise vorticity is shown in Fig. 3. It is clear from Fig. 3 that the vorticity is less intense on the side with truss-braced wing as compared to the original design. Fig. 3 is colored by stream-wise velocity. The aircraft appears blue due to no slip condition.

Fig. 3, Some more Colorful Fluid Dynamics (CFD) 🌈

     Thank you for reading, if you would like to hire me as your master's / PhD student / post-doc / collaborate on research projects, please reach out! 😌

References

[1] "Operations Planning Guide". Business & Commercial Aviation. Aviation Week. May 2016. [https://web.archive.org/web/20160815060134/http://www.sellajet.com/adpages/BCA-2016.pdf]

Saturday 1 April 2023

Turbulent Fluid Structure Interaction (FSI) - Benchmark Case

     After weeks spent self-learning about this type of simulation and countless nights spent troubleshooting this complex problem, I am pleased to share results. 😇 This post is about the FSI analysis of the FSI-PfS-2a. A case designed by Dr. Breuer. The geometry is shown in Fig. 1. The geometry details are available in ref. [1]. The geometry is made in SolidWorks CAD package and then imported to ANSYS via .STEP file. FSI combines Computational Fluid Dynamics (CFD) and structural analysis, i.e. the Finite Element Method (FEM).

Fig. 1, The geometry

     A combination of ANSYS Fluent, Mechanical and System Coupling are used for the analysis. Fig. 2 shows post-processing animation from the simulation. The top left shows stress while the displacements of the material are shown in top right. Bottom left and right show fluid velocity and vorticity, respectively. The vorticity is plotted along the axis perpendicular to the both lift and drag forces. the image in the center of animation shows fluid pressure acting on the cylinder and plate. Stagnation pressure is observed to change with time.

Fig. 2, The animation

     The boundary conditions from Mechanical are shown in Fig. 3. The condition A refers to gravity at 9.8066 m/s2 while B refers to fixed-support condition applied to the edge touching the cylinder. Boundary condition C refers to the fluid-solid interface. It is at these regions forces and displacements are exchanged. The structural mesh has 180 elements and 1,156 nodes. It is to be noted that the fluid regions are not meshed in mechanical and vice-versa. Furthermore, the number of mesh elements is limited by the system memory. The steel and rubber portions are connected via 4 connections i.e. edge/edge and edge/face contacts. The unmarked regions within Fig. 3 (top) are made symmetric. The  steel and rubber are considered linear elastic. No external force is applied in mechanical so this case can also be called as a case of vortex-induced vibrations. The direct sparse FEM solver is used for the Structural-FSI simulation.

Fig. 3, The boundary conditions and mesh

     The CFD mesh is shown in Fig. 4. The mesh is created using sweep method. Refinements are applied in areas of interest, i.e. wake and around the structure, using bodies of influence. Moreover, inflation mesh for y+ of 7.55 is applied on the cylinder to properly capture the boundary layer. The FSI-CFD simulation is initialized with data from static transient analysis using k–ω SST DES turbulence model. The k–ω DES model is initialized using static steady-state k–ω SST model. The flow parameters include a velocity of 1.385 m/s [1] corresponding to a Reynolds number of 30,470. The mesh has 79,305 cells. The dynamic mesh is handled through remeshing and smoothing via the radial basis function. Water is taken as a fluid for this simulation, same as [1]. Symmetry is applied to the walls facing perpendicular to flow. Top and bottom walls of the structure are considered adiabatic and with no shear. The SIMPLE algorithm is used. 2nd order accurate discretization schemes are used.

Fig. 4, The computational domain and the mesh

     It should be noted that for this simulations only 20 mm section of the whole geometry is simulated. This is because of computational resources limitations. The simulations took ~12 hours to solve 0.268 s of physical time with 32 GB RAM and 6 core CPU. The mesh motion along with vorticity iso-surfaces are shown in Fig. 5.

Fig. 5, The mesh and vorticity animation

     Thank you for reading, if you would like to hire me as your PhD student / post-doc  / collaborate on projects, please reach out.

References

[1] A. Kalmbach and M. Breuer, "Experimental PIV/V3Vmeasurementsofvortex-induced fluid–structure interaction in turbulent flow—A new benchmark FSI-PfS-2a", Journal of Fluids and Structures, Vol. 42, pp 369–387, 2013