Friday, 12 December 2025

Implementing a Custom Mathematical Function in the C++ Environment

Topic: Mathematical Functions
Subject: Numerical Methods
Tool: C++ and JetBrains CLion 2025.2.3

By: Gani Comia, December 2025

Illustrative Example

The number of bacteria, \(B\), in a culture that’s subject to refrigeration can be approximated by the formula:

$$\large B = 300000 \; e^{-0.032 \; t}$$

Where:
\(B\) – number of bacteria
\(t\) – time the culture has been refrigerated, \(hours\)

Using the given formula, calculates the number of bacteria in the culture, and display the results after 12, 18, 24, . . ., 72 hours.

Solution

C++ Code 

// Calculating the number of bacterial Growth in specified Time
// Ref. C++ for Engineers and Scientist, page 170
// Gani, 2025-12-12
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

// function prototype
int calcNumBacteria(int time);

int main() {
   
int const minTime = 12;
   
int const maxTime = 72;
   
int const stepTime = 6;
   
cout << "\n";
   
// Table title
   
cout << setw(14) << left << "Time (hours)"
           
<< setw(18) << left << "Number of Bacteria" << endl;
   
// Calculation
   
for (int time = minTime; time <= maxTime; time += stepTime) {
       
int const numBacteria = calcNumBacteria(time);
       
cout << setw(8) << right << time
           
<< setw(18) << right << numBacteria << endl;
    }
   
return 0;
}

// Given function to calculate the number of bacteria
int calcNumBacteria(int const time) {
   
const double A = 300000;                    // constant
   
const double n = 0.032;                     // constant
   
double const result = A * exp(-n * time);
   
// Explicitly round the double to the nearest whole number before
    // returning the int
   
return static_cast<int>(round(result));
}

Console Output

Time (hours)  Number of Bacteria

           12                     204339

           18                     168643

           24                     139182

           30                     114868

           36                       94801

           42                       78240

           48                       64572

           54                       53292

           60                       43982

           66                       36299

           72                       29958

Feel free to comment for inquiry, clarification, correction or suggestion for improvement. Drop your email to make a request to the author.

Disclaimer: The formulas and calculations presented are for technical reference only. Users must verify accuracy and ensure compliance with applicable engineering standards, codes, and safety requirements before practical application.

References

  1. Gary R. Bronson and G.J. Borse. C++ for Engineers & Scientist. 3rd Ed. Course Technology, Cengage Learning, Boston, Massachusetts. 2010.

Saturday, 4 October 2025

Visualization of Mach Number at Supersonic and Sonic Speeds


Topic: Mach Number

Subject: Fluid Mechanics

Tool: Scilab
By: Gani Comia, October 2025

  • Definition of Mach Number

The Mach number is a dimensionless parameter in fluid dynamics that expresses the ratio between the flow velocity and the local speed of sound. It is named in honor of Austrian physicist and philosopher Ernst Mach.

$$M = \frac{u}{c}$$

where:
\(M\) – Mach number
\(u\) – local flow velocity with respect to the boundaries
\(c\) – speed of sound in the medium

The speed of sound depends on the square root of the thermodynamic temperature. By definition, \(\text{Mach} \; 1\) corresponds to a flow velocity \(u\) equal to the local speed of sound. At \(\text{Mach} \; 0.5\), \(u\) is half the speed of sound (subsonic), while at \(\text{Mach} \; 2.0\), \(u\) is twice the speed of sound (supersonic). Flow at \(\text{Mach} \; 5.0\) or higher is classified as hypersonic.

At standard atmospheric conditions – dry air at mean sea level and a temperature of \(15^\circ C\) – the speed of sound is approximately \(340.3 \; m/s\) or \(1,225.1 \; km/h\). The speed of sound is not constant; in gases, it increases in proportion to the square root of the absolute temperature. Since atmospheric temperature generally decreases with altitude above sea level, the speed of sound correspondingly decreases as well. 

Flight can be roughly classified in six speed categories:

  1. Subsonic: Mach < 0.8
  2. Transonic: Mach 0.8 - 1.2
  3. Sonic: Mach 1.0
  4. Supersonic: Mach 1.5 - 5.0
  5. Hypersonic: Mach 5.0 - 10.0
  6. Hypervelocity: Mach > 8.8

When an object moves faster than the speed of sound (Mach 1), a sudden change in air pressure forms in front of it. This change, called a shock wave, spreads backward in a cone shape known as the Mach cone. The shock wave creates the sonic boom we hear when a fast aircraft passes by. As the object goes faster, the cone becomes narrower; just above Mach 1, it looks almost flat.

For further information on the Mach number, refer to the article “Mach number” in Wikipedia: The Free Encyclopedia.

  • Understanding Mach Number Through Visualization

Figure 1 shows a fighter jet flying at a supersonic speed of \(Mach \; 2.0\). The cloud that forms around the aircraft at this speed is called a vapor cone or shock collar. It appears as a visible cloud of condensed water vapor caused by a sudden drop in air pressure and temperature as the jet nears the speed of sound.

Figure 1. Eurofighter Jet at Supersonic Speed Showing Vapor Cone (Shock Collar).

This article provides a Scilab script to visualize the relative speed of an object and the propagation of sound waves, as shown in Figure 2, where the object moves at Mach 2.0. The dashed circle represents the propagation of the shock wave from its center and the object’s previous position.

Figure 2. Supersonic Speed Simulation at Mach 2.0.

For comparison, Figure 3 illustrates an object moving at the speed of sound along with the resulting shock wave propagation.

Figure 3. Sonic Speed Simulation (Mach 1.0).

  • Scilab Code for Figure 2.

// Copyright (C) 2025 - Gani Comia
// Date of creation: 19 Sep 2025
// Script: Supersonic Speed Simulation and Mach Cone
clear;clc;

// primary parameters
M = 2;                      // Mach number (supersonic > 1)
S = 1;                      // speed of sound
mu = asind(S./M);           // angle of mach cone
dist = 1:10;                // object position by a factor of speed of sound
N = length(dist);           // number of positions

// secondary parameters
a = 1:10                    // object position at x-direction
b = 0                       // object position at y-direction

// visualization of object's position and shock wave propagation
clf;
g = gcf()
g.figure_size = [700,700]
for i = 1:N
    plot(dist,0,"ko","linewidth",5)
    theta = 1:360
    r(i) = sind(mu).*(N-i)
    x(i,:) = r(i)*cosd(theta) + a(i);
    y(i,:) = r(i)*sind(theta) + b;  
    plot(x(i,:),y(i,:),"r--") 
    a1 = legend(["Moving Object","Shock Wave"],with_box=%f)
    a1.font_size = 2.5
end

title("Supersonic Speed Simulation at Mach 2.0 in 1D", "fontsize",4)
xlabel("Object Position / Shock Wave Propagation","fontsize",3.5)
ylabel("Shock Wave Propagation","fontsize",3.5)
xgrid(color("grey"),1,7)
a2 = xstring(6.5,4,"https://gani-mech-toolbox.blogspot.com")
a2.font_size = 2.5

// mach cone plot and visualization
x_val = [a(1)+r(1).*cosd(90-mu) a($)]
y_val = [r(1).*sind(90-mu) 0]
slope = diff(y_val)./diff(x_val)
disp(slope)
// straight line using slope-intercept formula, y = mx + b, and
// solve for y-intercept, b, at x = 0
y_int = y_val(1) - slope.*x_val(1)
disp(y_int)

x_val_new = [0 a($)]
y_val_new_1 = [y_int 0]
y_val_new_2 = [-y_int 0]
plot(x_val_new,y_val_new_1,"b-","linewidth",3)
plot(x_val_new,y_val_new_2,"b-","linewidth",3)
a3 = xstring(x_val(1),y_val(1),"Mach Cone",mu-6)
a3.font_size = 3
a4 = xstring(x_val(1),-y_val(1)-0.7,"Mach Cone",mu-56)
a4.font_size = 3

ax = gca()
ax.data_bounds = [0 -5 ; 12 6];
//disp(r)

Feel free to comment for inquiry, clarification, correction or suggestion for improvement. Drop your email to make a request to the author.

Disclaimer: The formulas and calculations presented are for technical reference only. Users must verify the accuracy and ensure compliance with applicable engineering standards, codes, and safety requirements before practical application.

References

  1. “Mach number”. Wikipedia The Free Encyclopedia. 10 September 2025.  https://en.wikipedia.org/wiki/Mach_number
  2. Eurofigther Typhoon Jets at Mach 2. ChatGPT Image. 20 September 2025.

Sunday, 14 September 2025

von Mises Stress Failure Theory in a Spinning Solid Disk

Topic: von Mises Yield Criterion and Rotating Disk

Subject: Machine Design

Tool: Scilab

By: Gani Comia, September 2025

Rotating circular machine elements can be modeled as rotating disks to evaluate stresses. Similar to the theory of thick-walled cylinders, both tangential and radial stresses are present, but in this case, they result from inertial forces within the ring or disk. The tangential and radial stresses are governed by the following conditions.

  1. The outside radius of the disk is significantly larger than its thickness, \(r_o \geq 10 \, t\).
  2. The ring or disk has a uniform thickness.
  3. The stresses are evenly distributed throughout the thickness.

Reference article and derivation of the stresses in the rotating rings and disks can be found in the website https://roymech.org/Useful_Tables/Mechanics/Rotating_cylinders.html.

  • Tangential Stress Equation for Solid Disk

$$\sigma_t = \left(\frac{\rho \, \omega^2}{8}\right) \left[ (3 + \nu) \,  r_o^2 - (1 - 3 \, \nu) \, r^2 \right] \tag{1}$$

Where:
\(\sigma_t\) – tangential stress, \(Pa\)
\(\rho\) - density, \(kg/m^2\)
\(\omega\) – angular velocity, \(rad/s\)
\(\nu\) – Poisson’s Ratio
\(r_o\) – outside radius of cylinder, \(m\)
\(r\) – radius at the point of calculation, \(m\)

  • Radial Stress Equation for Solid Disk

$$\sigma_r = \left( \frac{\rho \, \omega^2}{8} \right) (3 + \nu) (r_o^2 - r^2) \tag{2}$$

Where:
\(\sigma_r\) – radial stress, \(Pa\)

In engineering, the von Mises yield criterion states that yielding begins when the von Mises stress \(\sigma_v\)​, derived from the Cauchy stress tensor, equals the yield strength \(\sigma_y\)​.

The von Mises Equation for a general state of stress is

$$\sigma_{\nu} = \sqrt{\frac{1}{2} \left[ (\sigma_{11} - \sigma_{22})^2 + (\sigma_{22} - \sigma_{33})^2 + (\sigma_{33} - \sigma_{11})^2 \right] + 3 \, (\sigma_{12}^2 + \sigma_{23}^2 + \sigma_{31}^2)} \tag{3}$$

For the boundary conditions,

$$\sigma_{12} = \sigma_{23} = \sigma_{31} = 0 \tag{4}$$

the von Mises defines the equations under principal stress

$$\sigma_{\nu} = \sqrt{\frac{1}{2} \left[ (\sigma_1 - \sigma_2)^2 + (\sigma_2 - \sigma_3)^2 + (\sigma_3 - \sigma_1)^2 \right]} \tag{5}$$

For the 2D multi-axial stress, where \(\sigma_3 = 0\) as boundary condition under principal plane stress, the equivalent von Mises stress, \(\sigma_{\nu}\), becomes

$$\sigma_{\nu} = \sqrt{\sigma_1^2 + \sigma_2^2 - \sigma_1 \, \sigma_2} \tag{6}$$

  • von Mises Yield Criterion and Factor of safety

The use of the von Mises criterion as a yield criterion is only exactly applicable when the material properties are isotropic, there is no considerable dynamic or unpredictable loads, and the ratio of the shear yield strength to the tensile yield strength has the value as in Equation (7).

$$\frac{\sigma_s}{\sigma_y} = \frac{1}{\sqrt{3}} \approx 0.577 \tag{7}$$

In practice it is necessary to use engineering judgement and use the above ratio.

The factor of safety based on yield strength is given by Equation (8).

$$N_y = \frac{\sigma_y}{\sigma_{\nu}} - 1 \tag{8}$$

Critical components suggest a factor of safety of \(\text{2.5}  \leq  N_y  \leq  \text{3.0} \).

  • Application

A solid disk (Figure 1) is analyzed at different rotational speeds to determine safe operating limits. The design factor indicates the maximum speed at which the disk can rotate without failure. Using the von Mises Yield Criterion, the equivalent stress is evaluated from the combined tangential and radial stresses. The design factor, as given by Equation 8, defines the likelihood of structural failure for the specified parameters.

Assumed Parameters:
Material:    Alloy Steel
Density:    7,850 \(kg/m^3\)
Yield Strength:    1,250 \(MPa\)
Poisson’s Ratio:    0.29
Radius:    0.5 \(m\)
Rotational Speed:    2500, 5000, 7500, and 10000 \(rpm\)

Figure 1. Rotating Solid Disk (ChatGPT Image Sep 10, 2025).

Figure 2 presents the equivalent combined stresses according to the von Mises yield criterion. The stress distribution varies radially across the disk, reaching its maximum at the center where \(r = 0\).

Figure 2. von Mises Stress from the Point of Analysis along the Disk Radius.

A contour plot, shown in Figure 3, provides an alternative visualization of the stress distribution for a given rotational speed.

Figure 3. von Mises Stress Distribution

Figure 4 shows the design factor at various rotational speeds. The minimum factor of safety is indicated for each case. Rotational speed of \(7500  \, \text{rpm} \) and above do not satisfy the criteria for critical components.

Figure 4. Design Factor using von Mises Stress for Spinning Disk.

Refer to the following Scilab scripts for figure reproduction.


Scilab Script for Figure 2 and 4

// Copyright (C) 2025 - Gani Comia
// Date of creation: 12 Sep 2025
// Script: von Mises Yield Criterion in a Spinning Disk
clear;clc;

// Primary parameters
rho = 7850;                             // kg/m^3, density of steel
sigmaY = 1250;                          // MPa, yield strength, alloy steel
rpm = [2500 5000 7500 10000];           // rpm, rotational speed      
radps = rpm.*(2*%pi/60);                // rad/s, maximum rotational speed
nu = 0.29;                              // Poisson's ration of carbon steel
r_o = 0.5;                              // m, outer radius of cylinder

// Secondary parameters
R = linspace(0,r_o,100)
n = length(radps)

// von Mises stress distribution for a rotational speed
for i = 1:n
    // tangential stress, Pa
    sigmaT(i,:) = ((rho.*radps(i).^2)/8).*((3+nu).*(r_o).^2 - (1-3*nu).*(R.^2));
    // radial stress, Pa
    sigmaR(i,:) = ((rho.*radps(i).^2)/8).*((3+nu).*((r_o).^2 - (R.^2)));
    // von Mises stress, Pa
    sigmaV(i,:) = sqrt(sigmaT(i,:).^2 + sigmaR(i,:).^2 - (sigmaT(i,:).*sigmaR(i,:)))
    // von Mises stress, MPa
    sigmaV(i,:) = sigmaV(i,:)/1e6
end

// Plot of von Mises stress distribution for a given rotation speed
clf;
scf(0)
f = gcf()
f.figure_size = [800,800]
subplot(2,2,1)
    plot(R,sigmaV(1,:),"g-","linewidth",4.5);
    title("von Mises Stress at 2,500 rpm")
    xlabel("Disk Radius, m","fontsize",3)
    ylabel("Stress, MPa","fontsize",3)
    xgrid(color("grey"),1,7)
    mprintf("Max von Mises #1 : %0.0f\n", max(sigmaV(1,:)))
    legend("$\LARGE \sigma_{Vmax} = \text{55 MPa}$",with_box=%f)
subplot(2,2,2)
    plot(R,sigmaV(2,:),"m-","linewidth",4.5);
    title("von Mises Stress at 5,000 rpm")
    xlabel("Disk Radius, m","fontsize",3)
    ylabel("Stress, MPa","fontsize",3)
    xgrid(color("grey"),1,7)
    mprintf("Max von Mises #3 : %0.0f\n", max(sigmaV(2,:)))
    legend("$\LARGE \sigma_{Vmax} = \text{221 MPa}$",with_box=%f)
subplot(2,2,3)
    plot(R,sigmaV(3,:),"b-","linewidth",4.5);
    title("von Mises Stress at 7,500 rpm")
    xlabel("Disk Radius, m","fontsize",3)
    ylabel("Stress, MPa","fontsize",3)
    xgrid(color("grey"),1,7)
    mprintf("Max von Mises #3 : %0.0f\n", max(sigmaV(3,:)))
    legend("$\LARGE \sigma_{Vmax} = \text{498 MPa}$",with_box=%f)
subplot(2,2,4)
    plot(R,sigmaV(4,:),"r-","linewidth",4.5);
    title("von Mises Stress at 10,000 rpm")
    xlabel("Disk Radius, m","fontsize",3)
    ylabel("Stress, MPa","fontsize",3)
    xgrid(color("grey"),1,7)
    mprintf("Max von Mises #4 : %0.0f\n", max(sigmaV(4,:)))
    legend("$\LARGE \sigma_{Vmax} = \text{885 MPa}$",with_box=%f)
    a1 = xstring(0.25,860,"https://gani-mech-toolbox.blogspot.com")
    a1.font_size = 2
    
// factor-of-safety calculation and plot
for j = 1:n
    Ny(j,:) = (sigmaY./sigmaV(j,:)) - 1
end

scf(1)
g = gcf()
g.figure_size = [700,700]
plot("ln",R,Ny(1,:),"g-","linewidth",4.5)
plot("ln",R,Ny(2,:),"m-","linewidth",4.5)
plot("ln",R,Ny(3,:),"b-","linewidth",4.5)
plot("ln",R,Ny(4,:),"r-","linewidth",4.5)
title("Design Factor using von Mises Stress Criterion for Spinning Disk","fontsize",3.5)
xlabel("Disk Radius, m","fontsize",3.5)
ylabel("Design Factor, Ny","fontsize",3.5)
xgrid(color("grey"),1,7)

// minimum design factor for a given rotation annotation
format(5)
a2 = xstring(0.005,Ny(1,1),["N (min) = ",string(Ny(1,1))," at 2,500 rpm"])
a2.font_size = 3
a3 = xstring(0.005,Ny(2,1),["N (min) = ",string(Ny(2,1))," at 5,000 rpm"])
a3.font_size = 3
a4 = xstring(0.005,Ny(3,1),["N (min) = ",string(Ny(3,1))," at 7,500 rpm"])
a4.font_size = 3
a5 = xstring(0.005,Ny(4,1)-0.2,["N (min) = ",string(Ny(4,1))," at 10,000 rpm"])
a5.font_size = 3

// design parameter annotation
a6 = "$N_y = \frac{\sigma_y}{\sigma_v} - 1$"
a7 = "$\sigma_v = \sqrt{\sigma_1^2 + \sigma_2^2 - \sigma_1 \sigma_2}$"
a8 = "$\frac{\sigma_s}{\sigma_y} = \frac{1}{\sqrt{3}} \; , \; \text{assumption}$"
a9 = xstring(0.0625,10,[a6;a7;a8])
a9.font_size = 4
a11 = xstring(0.05,8,"https://gani-mech-toolbox.blogspot.com")
a11.font_size = 2.5

ax = gca()
ax.data_bounds = [0.005 0; 0.5 25];


Scilab Script for Figure 3

// Copyright (C) 2025 - Gani Comia
// Date of creation: 5 Sep 2025
// Script: von Mises Stress Distribution
clear;clc;

// Primary parameters
rho = 7850;                             // kg/m^3, density of steel
rpm = [2500 5000 7500 10000];           // rpm, rotation speed
radps = max(rpm.*(2*%pi/60));           // rad/s, maximum rotational speed
nu = 0.29;                              // Poisson's ration of carbon steel
r_o = 0.5;                              // m, outer radius of cylinder

// Create meshgrid
n = 250;
x = linspace(-r_o, r_o, n);
y = linspace(-r_o, r_o, n);
[X, Y] = ndgrid(x, y);

// Compute radial distance from center
R = sqrt(X.^2 + Y.^2);

// Define stress distribution at maximum rotational speed
sigmaT = zeros(n, n);
sigmaR = zeros(n, n);
sigmaV = zeros(n, n);

for i = 1:n
    for j = 1:n
        if R(i,j) <= r_o then
            // tangential stress
            sigmaT(i,j) = ((rho.*radps.^2)/8).*((3+nu).*(r_o).^2 - (1-3*nu).*(R(i,j)).^2);
            // radial stress
            sigmaR(i,j) = ((rho.*radps.^2)/8).*((3+nu).*((r_o).^2 - (R(i,j)).^2));
            // von Mises stress
            sigmaV(i,j) = sqrt(sigmaT(i,j).^2 + sigmaR(i,j).^2 - (sigmaT(i,j).*sigmaR(i,j))); 
        else
            sigmaT(i,j) = %nan;     // Outside the circle
            sigmaR(i,j) = %nan;
            sigmaV(i,j) = %nan;
        end
    end
end

// Stress distribution using contour plot
clf;
f = gcf()
f.figure_size = [700,700]

sigmaV = sigmaV./(1e6)
disp(max(sigmaV)); disp(min(sigmaV));

contourf(x, y, sigmaV, 60);
title("von Mises Stress Distribution in Circular Domain at 10K rpm","fontsize",3.5);
xlabel("x-coordinates","fontsize",3)
ylabel("y-coordinates","fontsize",3)
xgrid(color("grey"),1,7)
isoview on;

f.color_map = jet(64)
colorbar(750,900)

ax = gca()
ax.data_bounds = [-0.6 -0.6; 0.6 0.6]
ax.auto_ticks = ["on" "on"]


Feel free to comment for inquiry, clarification, correction or suggestion for improvement. Drop your email to make a request to the author.

Disclaimer: The formulas and calculations presented are for technical reference only. Users must verify the accuracy and ensure compliance with applicable engineering standards, codes, and safety requirements before practical application.

References

  1. “Rotating Disks and Cylinders”. RoyMech.org. 2020. https://roymech.org/Useful_Tables/Mechanics/Rotating_cylinders.html .
  2. “von Mises yield criterion”. Wikipedia The Free Encyclopedia. 18 September 2024. https://en.wikipedia.org/wiki/Von_Mises_yield_criterion .
  3. J.E. Shigley and C.R. Mischke. Mechanical Engineering Design. 5th Ed. New York, New York 10020. McGraw-Hill Publishing Company. 1989. 

Implementing a Custom Mathematical Function in the C++ Environment

Topic: Mathematical Functions Subject: Numerical Methods Tool: C++ and JetBrains CLion 2025.2.3 By: Gani Comia , December 2025...