In the realm of civil engineering, the strength and stability of structures like dams, bridges, and buildings are heavily reliant on a crucial element known as the foundation. These foundations are designed by civil engineers, often with the assistance of expensive and complex software. In this article, we will explore how you can create your very own web-based application for designing pad footing foundations using Python and Viktor SDK(software development kit). This innovative approach not only simplifies the design process but also facilitates easy sharing and collaboration among colleagues.
You can play with the app here
Engineers have been utilizing Python scripts to tackle various engineering design and analysis challenges. However, the ability to transform these scripts into user-friendly applications is a game-changer. Viktor is a platform that empowers engineers to expedite the development of engineering applications using Python programming language.
In the realm of civil engineering, foundations serve as the linchpin connecting a structure to the earth, responsible for transmitting the structural loads and stresses to the underlying ground. They are diverse in types, each tailored to specific project requirements.
These are among the types of foundation common in civil engineering:
1. Pad Footing foundation: These are frequently employed for shallow foundations, designed to distribute concentrated loads, typically associated with columns. The size may vary based on whether reinforcement is incorporated.
Combined Footing foundation: Engineers resort to combined footings when dealing with closely spaced columns, merging footings to create a continuous base.
Strap Footing foundation: Strap footings are utilized when an exterior column must not extend beyond the property line. Strap beams bridge between the exterior and adjacent interior footings to counteract load eccentricities.
Strip Footing foundation: Ideal for foundations supporting walls or closely spaced columns, strip footings are also a preferred choice in the presence of weak ground conditions to increase the foundation's bearing area.
Raft Foundation: Covering the entire building, a raft foundation provides support for all walls and columns. It proves especially valuable when dealing with heavy column loads or low-bearing capacity soils.
Pile Foundation: Pile foundations come into play when a solid-bearing stratum, such as rock, is located deep beneath the surface. Piles transfer loads either to a firm layer below or through friction along their length. Soil surveys play a pivotal role in determining pile length and load capacity.
Foundation design refers to the systematic process of determining and specifying the type, dimensions, and construction details of a foundation for a structure, taking into consideration the soil conditions and structural requirements. This process ensures that the foundation is designed to safely support the loads imposed by the structure and distribute those loads to the underlying soil or rock in a manner that prevents excessive settlement or structural failure
The design of a foundation in geotechnical engineering typically involves the following key steps:
The design of a foundation is guided by various factors that determine both its depth and type:
Geotechnical design to determine the safe bearing strength of the soil The Eurocode governing the geotechnical aspects of foundation design is BS EN 1997-1:2004: Eurocode 7: Geotechnical Design —Part 1: General Rules. Spread foundations are covered in section 6 and in Appendix D. Pile foundations are covered in section 7 of the code.
Structural design of the foundation using reinforced concrete. The Eurocode governing the structural aspects of foundation design is BS EN 1992-1-1:2004: Eurocode 2: Design of Concrete Structures Part 1: General Rules and Rules for Buildings. For the vast majority of simple foundations, the two aspects can be treated separately. However for some types of foundations, for example, raft foundations, the interaction between the structure and foundation might need to be taken into Account.
Isolated pad footing is a type of foundation that is normally square or rectangular slabs provided under individual columns. They spread the concentrated column load safely to the ground and may be axially or eccentrically loaded. Mass concrete can be used or a reinforced concrete pad is required.
Due to little guidance in Eurocode 2 for the design of pad footings, the following procedure is normally used.
When the base is axially loaded the load may be assumed to be uniformly distributed. The pressure distribution dependent on the type of soil.
When the base is eccentrically loaded, the reactions may be assumed to vary linearly across the base.
Designing a pad footing involves the following steps:
In this article, the check for shear will not covered
The first thing is to install and import a Python library called FoundationDesign which is written to implement the Eurocode 2 method of reinforced concrete designs for foundations.
from FoundationDesign import PadFoundation,padFoundationDesign
# Create the pad foundation object
# Since the foundation is concentric the column position in x and y direction is foundation length and width divided by two
fdn = PadFoundation(
foundation_length=3000,
foundation_width=3000,
column_length=300,
column_width=300,
col_pos_xdir=1500,
col_pos_ydir=1500,
soil_bearing_capacity=150,
)
fdn.plot_geometry(show_plot=False)
fdn.column_axial_loads(permanent_axial_load=600,imposed_axial_load=400)
fdn.foundation_loads(foundation_thickness=450,soil_depth_abv_foundation=0,soil_unit_weight=18,concrete_unit_weight=25)
z=fdn.pad_base_pressures_sls()
print(z)
#output
(122.361, 122.361, 122.361, 122.361)
fdn.bearing_pressure_check_sls()['status']
#This shows that the foundation size is adequate
#Output
PASS - Presumed bearing capacity exceeds design base pressure
area = fdn.minimum_area_required()
print(f'The minimum area requried for the pad foundation is {area}m\u00b2')
# Output
The minimum area required for the pad foundation is 7.29m²
fdn_design = padFoundationDesign(
fdn, fck=25, fyk=500, concrete_cover=35, bar_diameterX=12, bar_diameterY=12)
z = fdn_design.area_of_steel_reqd_X_dir()
print(f'The area of steel required in the x direction is {z}mm\u00b2/m')
#output
The area of steel required in the x direction is 845mm²/m
11.Show the reinforcement area provided along the X axis
fdn_design.reinforcement_provision_flexure_X_dir()['status']
#Output
Provide H12mm bars spaced at 125.0mm c/c bottom. The area provided is 905mm²/m parallel to the 3.0m side
It will be cool if we can convert our Python script into a working application that runs from our browser without the need for complex installation processes and which can be used by others.
This is where Viktor SDK shines, which supports 100 percent Python script conversion into a web application.
Our application can have an input field for typing our desired size of the foundation, thickness, column thickness, and material properties like concrete strength, and steel yield strength.
Furthermore, our application should be able to return results to the user.
1. Create a VIKTOR app project.
To create a new VIKTOR application project, use the viktor-cli to generate a project file structure automatically. The command to use is:
viktor-cli create-app --app-type editor<name-of-your-project>
2. Collect all requirements of the Python script
Add these packages to the requirements.txt file.
3. Convert script to a function
Now, we will convert our script into a web app using Viktor SDK. This can be achieved by rewriting our script which can be run by calling a function and the calculation result we want to get will be what the function will be returning.
In our own case, the function is to plot the geometry of the created foundation, bearing capacity check, area of steel required, and the area of steel provided.
def create_Model(fdn_length,fdn_width,cL,cW,CpX,CpY,
sB,PL,IL,fdn_thickness,
Soil_unit,Conc_unit):
fdn = PadFoundation(
foundation_length=fdn_length,
foundation_width=fdn_width,
column_length=cL,
column_width=cW,
col_pos_xdir=CpX,
col_pos_ydir=CpY,
soil_bearing_capacity=sB,
)
fdn_Img=fdn.plot_geometry(show_plot=False)
fdn.column_axial_loads(permanent_axial_load=PL,
imposed_axial_load=IL)
z = fdn.foundation_loads
(foundation_thickness=fdn_thickness,soil_depth_abv_foundation=0,
soil_unit_weight=Soil_unit,concrete_unit_weight=Conc_unit)
pres=fdn.pad_base_pressures_sls()
#Check Service Soil Bearing Capacity
bear=fdn.bearing_pressure_check_sls()['status']
#This Check the minimum area required for the pad Fdn
area = fdn.minimum_area_required()
# Show the base pressures
return fdn_Img, pres, bear,area
4. Create a View To display our result
In this step, we will create an interface for displaying our results.
Here are the steps :
To use the newly created function in my VIKTOR app, import the function into the app.py file where the bare-bones VIKTOR app code structure resides. But in my own case may function reside in the app.py file.
These are the steps for creating visualization:
class ModelController(ViktorController):
label = 'Model'
parametrization = Parametrization
@PlotlyView("Footing plan", duration_guess=100)
def get_plotly_view(self, params, **kwargs):
foundation, foundation_img = create_foundation(
params.fdn_length, params.fdn_width, params.col_length, params.col_width,
params.col_pos_xdir, params.col_pos_ydir, params.soil_bearing_capacity
)
return DataResult(foundation_img.to_json())
@DataView("Analysis result", duration_guess=1)
def visualize_data(self, params, **kwargs):
foundation, _ = create_foundation(
params.fdn_length, params.fdn_width, params.col_length, params.col_width,
params.col_pos_xdir, params.col_pos_ydir, params.soil_bearing_capacity
)
pressure, soil_bearing_capacity_status, minimum_area_required = calculate_foundation_loads(
foundation, params.fdn_thickness, params.soil_unit_weight, params.concrete_unit_weight
)
data_group = DataGroup(
DataItem('Pressure', pressure),
DataItem('Soil Bearing Capacity Status', soil_bearing_capacity_status),
DataItem('Minimum Area Required', minimum_area_required),
)
return DataResult(data_group)
@DataView("Design", duration_guess=1)
def visualize_design_data(self, params, **kwargs):
foundation, _ = create_foundation(
params.fdn_length, params.fdn_width, params.col_length, params.col_width,
params.col_pos_xdir, params.col_pos_ydir, params.soil_bearing_capacity
)
area_of_steel_required_X_dir, reinforcement_provision_flexure_X_dir, punching_shear_status = foundation_design(
foundation, params.fck, params.fyk, params.concrete_cover, params.bar_diameterX, params.bar_diameterY
)
data_group = DataGroup(
DataItem('Area of Steel Required in X Direction', area_of_steel_required_X_dir),
DataItem('Reinforcement Provision in X Direction', reinforcement_provision_flexure_X_dir),
)
return DataResult(data_group)
5. Create fields as input for the pad footing design app.
We’ve created a visualization, but ideally, we would like to make the app dynamic based on input. To do this, the following steps can be followed:
class Parametrization(ViktorParametrization):
fdn_length = NumberField('foundation length')
fdn_width = NumberField('foundation width')
col_length = NumberField('column width')
col_width = NumberField('column breadth')
col_pos_xdir = NumberField('column position_X')
col_pos_ydir = NumberField('column position_Y')
soil_bearing_capacity = NumberField('soil_bearing_capacity')
permanent_axial_load = NumberField('Dead Load')
imposed_axial_load = NumberField('Imposed load')
fdn_thickness = NumberField('foundation thickness')
soil_unit_weight = NumberField('soil unit_weight')
concrete_unit_weight = NumberField('concrete_unit_weight')
fck = NumberField('Concrete strength')
fyk = NumberField('steel yield_strength')
concrete_cover = NumberField('conc_cover')
bar_diameterX = NumberField('Bar_dia_X')
bar_diameterY = NumberField('Bar_dia_Y')
Complete code:
from FoundationDesign import PadFoundation,padFoundationDesign
from viktor import ViktorController
from viktor.geometry import Point, Sphere
from viktor.parametrization import ViktorParametrization, NumberField, DownloadButton
from viktor.result import DownloadResult
from viktor.views import GeometryView, GeometryResult, DataView, DataResult, DataGroup, DataItem,PlotlyView, PlotlyResult
# Create the pad foundation object
# Since the foundation is concentric the column position in x and y direction is foundation length and width divided by two
# Assuming that your function is within this project
def create_Model(fdn_length,fdn_width,cL,cW,CpX,CpY,
sB,PL,IL,fdn_thickness,Soil_unit,Conc_unit):
fdn = PadFoundation(
foundation_length=fdn_length,
foundation_width=fdn_width,
column_length=cL,
column_width=cW,
col_pos_xdir=CpX,
col_pos_ydir=CpY,
soil_bearing_capacity=sB,
)
fdn_Img=fdn.plot_geometry(show_plot=False)
fdn.column_axial_loads(permanent_axial_load=PL,imposed_axial_load=IL)
z = fdn.foundation_loads(foundation_thickness=fdn_thickness,soil_depth_abv_foundation=0,
soil_unit_weight=Soil_unit,concrete_unit_weight=Conc_unit)
pres=fdn.pad_base_pressures_sls()
#Check Service Soil Bearing Capacity
bear=fdn.bearing_pressure_check_sls()['status']
#This Check the minimum area required for the pad foundation
area = fdn.minimum_area_required()
# Show the base pressures
return fdn_Img, pres, bear,area
def foundation_Design(fdn_length,fdn_width,cL,cW,CpX,CpY,sB,PL,IL,fdn_thickness,Soil_unit,Conc_unit,
fck,fyk,cc,bDX,bdY):
fdn = PadFoundation(
foundation_length=fdn_length,
foundation_width=fdn_width,
column_length=cL,
column_width=cW,
col_pos_xdir=CpX,
col_pos_ydir=CpY,
soil_bearing_capacity=sB,
)
fdn.column_axial_loads(permanent_axial_load=PL,imposed_axial_load=IL)
fdn.foundation_loads(foundation_thickness=fdn_thickness,soil_depth_abv_foundation=0,
soil_unit_weight=Soil_unit,concrete_unit_weight=Conc_unit)
fdn_design = padFoundationDesign(
fdn, fck=fck,
fyk=fyk,
concrete_cover=cc,
bar_diameterX=bDX,
bar_diameterY=bdY
)
# show reinforcement area required
asreq= fdn_design.area_of_steel_reqd_X_dir()
# reinforcememt area provided
asprov=fdn_design.reinforcement_provision_flexure_X_dir()['status']
# Check for Punching shear stress at the column face
fdn_design.punching_shear_column_face()['status']
#Check for Punching shear at 1d from column face
return asreq, asprov
class Parametrization(ViktorParametrization):
fdn_length=NumberField('foundation length')
fdn_width=NumberField('foundation width')
column_length=NumberField('col width')
column_width=NumberField('col breadth')
col_pos_xdir=NumberField('col position_X')
col_pos_ydir=NumberField('col position_Y')
soil_bearing_capacity=NumberField('soil_bearing_cpty')
permanent_axial_load=NumberField('Dead Load')
imposed_axial_load=NumberField('Imposed load')
foundation_thickness=NumberField('foundation thickness')
soil_unit_weight=NumberField('soil unit_weight')
concrete_unit_weight=NumberField('concrete_unit_weight')
fck=NumberField('Concrete strength')
fyk=NumberField('steel yield_strgth')
concrete_cover=NumberField('conc_cover')
bar_diameterX=NumberField('Bar_dia_X')
bar_diameterY=NumberField('Bar_dia_Y')
class ModelController(ViktorController):
label = 'Model'
parametrization = Parametrization
@PlotlyView("Footing plan", duration_guess=100)
def get_plotly_view(self, params, **kwargs):
img,pres, bear, area=create_Model(params.fdn_length,
params.fdn_width,
params.column_length,
params.column_width,
params.col_pos_xdir,
params.col_pos_ydir,
params.soil_bearing_capacity,
params.permanent_axial_load,
params.imposed_axial_load,
params.foundation_thickness,
params.soil_unit_weight,
params.concrete_unit_weight
)
return PlotlyResult(img.to_json())
@DataView("Analysis result", duration_guess=1)
def visualize_data(self, params, **kwargs):
img,pres, bear, area=create_Model(params.fdn_length,
params.fdn_width,
params.column_length,
params.column_width,
params.col_pos_xdir,
params.col_pos_ydir,
params.soil_bearing_capacity,
params.permanent_axial_load,
params.imposed_axial_load,
params.foundation_thickness,
params.soil_unit_weight,
params.concrete_unit_weight
)
data_group = DataGroup(
DataItem('base pressure @sls',pres),
DataItem('bearing capacity check', bear),
DataItem('Minimum area of foundation required', area),
)
return DataResult(data_group)
@DataView("Design", duration_guess=1)
def visualize_desigb_data(self, params, **kwargs):
Asreq, Asprov = foundation_Design(params.fdn_length,
params.fdn_width,
params.column_length,
params.column_width,
params.col_pos_xdir,
params.col_pos_ydir,
params.soil_bearing_capacity,
params.permanent_axial_load,
params.imposed_axial_load,
params.foundation_thickness,
params.soil_unit_weight,
params.concrete_unit_weight,
params.fck,
params.fyk,
params.concrete_cover,
params.bar_diameterX,
params.bar_diameterY
)
a=f'The area of steel required in the x direction is {Asreq}mm\u00b2/m)'
data_group = DataGroup(
DataItem('',a),
DataItem('', Asprov)
)
return DataResult(data_group)
In conclusion, we have created a pad footing design app that is dynamic based on input. The app can be used to design pad footings for a variety of structures. The app is easy to use and can be customized to meet the specific needs of the user