Computational Structural Engineer

Adnan Almulla

Engineering the intersection of structural analysis, programming, and sustainability. Building digital tools and optimization-driven solutions that enhance both environmental performance and economic viability of structural systems.

Analysis

  • ETABS
  • SAFE
  • RAM Concept
  • Karamba3D

Programming

  • C#
  • Python
  • LINQ
  • API Development

Computational Design

  • Rhino
  • Grasshopper
  • Revit
  • Parametric Modeling

Standards

  • ACI 318-19
  • AISC
  • Eurocode
About

Experience & Education

Driven by a passion for computational design and sustainable engineering solutions.

Current Role

Computational Structural Engineer

Killa Architectural Design • Dubai, UAE

February 2025 – Present

Previous Role

Graduate Engineer

Killa Architectural Design • Dubai, UAE

January 2023 – February 2025

Master's Degree

MSc Civil Engineering: Innovative Structural Materials

Result: Distinction

University of Bath • Bath, UK

October 2021 – August 2022

Bachelor's Degree

BEng (Hons) Civil and Environmental Engineering

Result: First Class Honours

Coventry University • Coventry, UK

September 2018 – June 2021
Projects

Parametric Models & Structural Optimizations

A selection of computational design projects focused on performance optimization and sustainable structural solutions.

Parametric Design

Parametric Tower Facade System

A Grasshopper-driven parametric model for generating optimized facade panels with integrated structural analysis via Karamba3D. Achieved 25% material reduction through form-finding algorithms.

GrasshopperKaramba3DPythonOptimization
Structural Optimization

Structural Optimization Engine

Custom optimization framework for reinforced concrete elements targeting embodied carbon reduction. Successfully implemented on B+G+46 residential building achieving ~20% carbon decrease.

ETABS APIPythonACI 318-19Sustainability
3D Analysis

Non-Linear FEA Visualization

Real-time visualization tool for non-linear finite element analysis results. Integrates with Kangaroo for physics-based form-finding and structural behavior simulation.

KangarooC#RhinoVisualization
Automation Tool

Deflection Contour Generator

Automated workflow for generating long-term concrete deflection contours and inter-drift displacement charts from ETABS models for design review submissions.

ETABSPythonData ProcessingAutomation
Data Visualization

Modal Analysis Dashboard

Interactive dashboard for visualizing modal periods, participating mass ratios, and dynamic response data extracted from structural analysis models.

PythonVisualizationDynamicsAPI
BIM Integration

Rebar Schedule Optimizer

Intelligent rebar scheduling algorithm that optimizes reinforcement layouts for constructability while minimizing material waste and embodied carbon.

C#Revit APIOptimizationBIM
Code Snippets

Computational Workflows & Optimizations

Practical applications of C# and Python to solve complex structural engineering challenges.

Material-Efficient Reinforcement Design

Goal:Identify optimal reinforcement configurations that satisfy structural capacity requirements while minimizing steel volume and material waste through heuristic search.

RebarOptimizer.cs
C#
public static (StationData<string> rebarTexts, StationValues providedAreas) FindStationRebarConfiguration
(int count, StationValues requiredAreas, string designCode, double beamArea)
{
    double minTotalExcess = double.MaxValue;

    // Stores the best configuration found: (Master Sequence, Layers for Left, Layers for Middle, Layers for Right)
    (List<int> masterSequence, int layersL, int layersM, int layersR)? bestConfig = null;
    StationValues bestProvidedAreas = StationValues.Zero;
    StationValues smallestDiameters = StationValues.Zero;
    StationValues largestDiameters = StationValues.Zero;

    // Generate "Master Sequences" of max length 4.
    // These sequences represent the potential deepest stack of rebar.
    var masterSequences = GetPermutations(_rebarDiameters, _maximumLayers);

    foreach (var sequence in masterSequences)
    {
        // For each station, find the minimum number of layers from this sequence
        // needed to satisfy the requirement.
        // The layers MUST be taken from the start of the sequence (continuity).

        var (validL, layersL, providedL) = FindMinLayersForStation(sequence, count, requiredAreas.Left, designCode, beamArea);
        var (validM, layersM, providedM) = FindMinLayersForStation(sequence, count, requiredAreas.Middle, designCode, beamArea);
        var (validR, layersR, providedR) = FindMinLayersForStation(sequence, count, requiredAreas.Right, designCode, beamArea);

        if (validL && validM && validR)
        {
            double totalExcess = (providedL - requiredAreas.Left) +
                                 (providedM - requiredAreas.Middle) +
                                 (providedR - requiredAreas.Right);

            if (totalExcess < minTotalExcess)
            {
                minTotalExcess = totalExcess;
                bestConfig = (sequence, layersL, layersM, layersR);
                bestProvidedAreas = new StationValues(providedL, providedM, providedR);
            }
        }
    }

    if (bestConfig == null)
    {
        return (new StationData<string>("Unable to Satisfy Requirements", "Unable to Satisfy Requirements", 
        "Unable to Satisfy Requirements"), StationValues.Zero, StationValues.Zero, StationValues.Zero);
    }

    var (seq, l, m, r) = bestConfig.Value;

    string TextFor(int numLayers)
    {
        // Take first 'numLayers' from 'seq', sort descending to formatting convention "Big + Small"
        var usedLayers = seq.Take(numLayers).OrderByDescending(d => d);
        return string.Join(" + ", usedLayers.Select(dia => $"{count}T{dia}"));
    }

    return (
        new StationData<string>(TextFor(l), TextFor(m), TextFor(r)),
        bestProvidedAreas,
    );
}

Probabilistic Extreme Wind Analysis

Goal:Calculate extreme design wind speeds for long-term return periods by applying Gumbel distribution theory and numerical root-finding to historical wind datasets.

gumbel_distribution.py
Python
import numpy as np
import scipy  # pyright:ignore

#! Reference youtube video: https://www.youtube.com/watch?v=5csVr2bRKN4
#! Reference documentation: https://help.emd.dk/knowledgebase/content/ReferenceManual/ExtremeWinds.pdf

# ! Value as obtained by AOR.
mean_wind_velocity = 24  # m/s
std_velocity = 4.58  # m/s
eulers_constant = 0.5772

# Find beta and mu:
scale_beta = round((std_velocity * np.sqrt(6)) / np.pi, 2)  # m/s
location_mu = round(mean_wind_velocity - 0.577 * scale_beta, 2)  # m/s


def create_equation(years):
    """
    Creates the equation to solve based on number of years
    """

    def equation(Ue):
        #! The equation in the form where we want to find the root
        #! 1/years = 1 - exp(-exp(-(Ue-location)/scale))
        #! Rearranged to: 1/years - (1 - exp(-exp(-(Ue-location)/scale))) = 0
        return 1 / years - (1 - np.exp(-np.exp(-(Ue - location_mu) / scale_beta)))

    return equation


def solve_wind_speed(years, initial_guess=30):
    """
    Solves for maximum wind speed given a number of years

    Parameters:
    years (int): Number of years to calculate for
    initial_guess (float): Initial guess for the solver

    Returns:
    float: Maximum wind speed in m/s
    """
    equation = create_equation(years)

    # Use scipy's root finder to solve the equation
    solution = scipy.optimize.root(equation, initial_guess)

    if solution.success:
        return solution.x[0]
    else:
        raise ValueError("Failed to find solution")


# Solve for both 50 and 700 year periods
years_to_solve = [50, 700]

for years in years_to_solve:
    Ue = solve_wind_speed(years)
    print(f"Maximum wind speed for {years} years: {Ue:.1f} m/s")

ratio = round(
    solve_wind_speed(years_to_solve[1]) / solve_wind_speed(years_to_solve[0]), 2
)

print(f"Ratio of 700 year to 50 year annual exceedance: {ratio}")
Contact

Get in Touch

Interested in discussing computational structural engineering, optimization workflows, or potential collaborations? Feel free to reach out.