Skip to main content

Fiber Kit - moment curvature analysis for reinforced concrete, steel, wood, etc.

Project description


logo
Fiber Section Analysis in Python

Define fiber material properties, create section, perform moment-curvature and PM interaction analysis with ease.

demo

Introduction

fkit (fiber-kit) is a section analysis program implemented in Python. It is powerful, flexible, and easy-to-use. Perform moment-curvature and P+M interaction analysis with very few lines of code. Originally meant for reinforced concrete sections, it was later extended to all material type (e.g. wood, steel, FRPs, anything that can be defined by a stress-strain curve).

Notable Features:

  • Large selection of material models (Hognestad, Mander, Todeschini, Ramberg-Osgood, Menegotto-Pinto, Bilinear, Trilinear, Multilinear)
  • Moment curvature analysis
  • P+M interaction analysis
  • Cracked moment of inertia calculations
  • Fast, Intuitive to use, and fully transparent. View stress/strain data of every fiber at each load step
  • Great looking visualizations
demo

[New in v2.0.0] Interactive 3D plot powered by Plotly:

demo
demo

Quick Start

Run main_quickstart.py:

import fiberkit as fkit

# define concrete and steel fibers
fiber_concrete = fkit.patchfiber.Hognestad(fpc=4, take_tension=True)
fiber_steel    = fkit.nodefiber.Bilinear(fy=60, Es=29000)

# create a rectangular beam section with SectionBuilder
section1 = fkit.sectionbuilder.rectangular(width = 18, 
                                           height = 24, 
                                           cover = 2, 
                                           top_bar = [0.6, 4, 1, 0], #[bar_area, nx, ny, y_spacing]
                                           bot_bar = [0.6, 4, 2, 3], #[bar_area, nx, ny, y_spacing] 
                                           concrete_fiber = fiber_concrete, 
                                           steel_fiber = fiber_steel)

# moment curvature
MK_results = section1.run_moment_curvature(phi_target=0.0003)
df_nodefibers, df_patchfibers = section1.get_all_fiber_data()

# cracked moment of inertia
Icr_results = section1.calculate_Icr(Es=29000, Ec=3605)

# PM Interaction surface analysis
PM_results = section1.run_PM_interaction(fpc=4, fy=60, Es=29000)

# plot results
fkit.plotter.plot_MK(section1)
fkit.plotter.plot_PM(section1)
fkit.plotter.plot_Icr(section1)
fkit.plotter.plot_MK_3D(section1) # NEW IN VERSION 2.0.0

The script above uses US imperial unit (kips, in, ksi). You may also use SI units (N, mm, MPa). The quick start script produces the following plots:

demo
demo
demo

Installation

Option 1: Anaconda Python

This is the simplest way to get started.

  1. Download Anaconda python distribution: https://www.anaconda.com/download
  2. Download this package (click the green "Code" button and download zip file or download the latest release)
  3. Open and run "main.py" in Anaconda's Spyder IDE

Option 2: Regular Python

  1. Download python: https://www.python.org/
  2. Download this project to a folder of your choosing
    git clone https://github.com/wcfrobert/fkit.git
    
  3. Change directory into where you downloaded fkit
    cd fkit
    
  4. Create virtual environment
    py -m venv venv
    
  5. Activate virtual environment
    venv\Scripts\activate
    
  6. Install requirements
    pip install -r requirements.txt
    
  7. run fkit
    py main.py
    

Note that pip install is available.

pip install fiberkit

Fiberkit was developed using python 3.12 (any version above 3.7 will probably work as well) with the following dependencies.

  • Numpy
  • Matplotlib
  • Pandas

Usage

main_fiber.py - illustrates the available material models within fkit.

  • Hognestad et al (1951) - General purpose concrete

  • Mander et al (1988) - Recommended for confined concrete

  • Todeschini et al (1964) - Recommended for unconfined concrete

  • Bilinear - Simple bilinear model

  • Multilinear: Rex & Easterling (1996) - Six linear regions tracing out the recognizable steel stress-strain curve

  • RambergOsgood - Smooth power function. Can be used to fit experimental data

  • MenegottoPinto - Smooth power function. Slightly faster and more robust than RambergOsgood as no Newton-Raphson iteration is needed

  • Custom_Trilinear - A highly customizable trilinear model defined by three points

Each of the eight material models above can be assigned to either a Node fiber or a Patch fiber. Patch fibers have 4 vertices and occupies some area geometrically. On the other hand, node fibers are defined by a single point and the user must specify its area (usually used for rebar).

import fiberkit as fkit

# concrete patch fibers
Hognestad_unconfined  = fkit.patchfiber.Hognestad(fpc=4)
Todeschini_unconfined = fkit.patchfiber.Todeschini(fpc=4)
Hognestad_confined    = fkit.patchfiber.Hognestad(fpc=6.7, eo=0.006, emax=0.023)
Mander_confined       = fkit.patchfiber.Mander(fpc=6, eo=0.006, emax=0.023)

fkit.plotter.compare_fibers(fibers = [Hognestad_unconfined,Todeschini_unconfined], 
                            labels = ["Hognestad_unconfined","Todeschini_unconfined"],
                            x_limit = [-0.005, 0.005])

fkit.plotter.compare_fibers(fibers = [Hognestad_confined,Mander_confined], 
                            labels = ["Hognestad_confined","Mander_confined"],
                            x_limit = [-0.03, 0.03])

fkit.plotter.compare_fibers(fibers = [Hognestad_confined,Hognestad_unconfined], 
                            labels = ["Hognestad_confined","Hognestad_unconfined"],
                            x_limit = [-0.03, 0.03])


# steel node fibers
ElasticPlastic  = fkit.nodefiber.Bilinear(fy=60, Es=29000, emax=0.16)
StrainHarden    = fkit.nodefiber.Bilinear(fy=60, fu=90, Es=29000, emax=0.16)
MultiLinear     = fkit.nodefiber.Multilinear(fy=60, fu=90, Es=29000)
RambergOsgood   = fkit.nodefiber.RambergOsgood(fy=60, n=25, Es=29000)
MenegottoPinto  = fkit.nodefiber.MenegottoPinto(fy=60, n=5, b=0.0043, Es=29000)
Trilinear       = fkit.nodefiber.Custom_Trilinear(stress1p=60, strain1p=0.002,
                                                  stress2p=90, strain2p=0.1,
                                                  stress3p=75, strain3p=0.16,
                                                  stress1n=-40, strain1n=-0.001,
                                                  stress2n=-5, strain2n=-0.002,
                                                  stress3n=-0, strain3n=-0.03)

fkit.plotter.compare_fibers(fibers = [ElasticPlastic, StrainHarden, MultiLinear], 
                            labels = ["Elastic-Perfect-Plastic","Strain Hardening", "Multilinear"],
                            x_limit = [-0.05, 0.05])

fkit.plotter.compare_fibers(fibers = [ElasticPlastic, StrainHarden, MultiLinear], 
                            labels = ["Elastic-Perfect-Plastic","Strain Hardening", "Multilinear"],
                            x_limit = [-0.17, 0.17])

fkit.plotter.compare_fibers(fibers = [RambergOsgood , MenegottoPinto , StrainHarden], 
                            labels = ["RambergOsgood" , "MenegottoPinto" , "Bilinear"],
                            x_limit = [-0.05, 0.05])

fkit.plotter.compare_fibers(fibers = [RambergOsgood , MenegottoPinto , StrainHarden], 
                            labels = ["RambergOsgood" , "MenegottoPinto" , "Bilinear"],
                            x_limit = [-0.17, 0.17])

main_sectionbuilder.py - illustrates the sections that can be quickly created with sectionBuilder with a single function call. There are currently 9 parametric sections available. Refer to the documentation for more info.

demo
import fiberkit as fkit


# define some fibers we will use later
fiber_unconfined       = fkit.patchfiber.Todeschini(fpc=5, eo=0.002, emax=0.006, default_color="lightgray")
fiber_confined         = fkit.patchfiber.Mander(fpc=6, eo=0.004, emax=0.014, default_color="gray")
fiber_structural_steel = fkit.patchfiber.Multilinear(fy=50, fu=80, Es=29000, default_color="steelblue")
fiber_rebar            = fkit.nodefiber.Bilinear(fy=60, fu=75, Es=29000, emax=0.16, default_color="black")

# rectangular
section1 = fkit.sectionbuilder.rectangular(
    width = 36,
    height = 12,
    cover = 1.5,
    top_bar = [0.3, 6, 1, 0],
    bot_bar = [0.3, 6, 1, 0],
    concrete_fiber = fiber_unconfined,
    steel_fiber = fiber_rebar)
fkit.plotter.preview_section(section1)

# rectangular_confined
section2 = fkit.sectionbuilder.rectangular_confined(
    width = 15, 
    height = 24, 
    cover = 1.5, 
    top_bar = [0.6, 3, 1, 0], 
    bot_bar = [0.6, 3, 2, 3], 
    core_fiber = fiber_confined, 
    cover_fiber = fiber_unconfined, 
    steel_fiber = fiber_rebar)
fkit.plotter.preview_section(section2)

# circular
section3 = fkit.sectionbuilder.circular(
    diameter = 36,
    cover = 2,
    N_bar = 6,
    A_bar = 1.0,
    core_fiber = fiber_confined, 
    cover_fiber = fiber_unconfined, 
    steel_fiber = fiber_rebar)
fkit.plotter.preview_section(section3)

# flanged
section4 = fkit.sectionbuilder.flanged(
    bw = 24,
    bf = 120,
    h = 48,
    tf = 12,
    cover = 2,
    bot_bar = [0.6, 4, 1, 0],
    top_bar = [0.6, 2, 1, 0],
    slab_bar = [0.2, 12, 2, 9],
    core_fiber = fiber_confined, 
    cover_fiber = fiber_unconfined, 
    steel_fiber = fiber_rebar)
fkit.plotter.preview_section(section4)

# wall
section5 = fkit.sectionbuilder.wall(
    width=12,
    length=120, 
    cover=1.5, 
    wall_bar=[0.31, 12, 2],
    concrete_fiber = fiber_unconfined,
    steel_fiber = fiber_rebar)
fkit.plotter.preview_section(section5)

# wall_BE
section6 = fkit.sectionbuilder.wall_BE(
    width = 18, 
    length = 160, 
    cover = 2, 
    BE_length = 24, 
    wall_bar = [0.31, 6, 2], 
    BE_bar = [1.0, 3, 4],
    concrete_fiber = fiber_unconfined, 
    BE_fiber = fiber_confined, 
    steel_fiber = fiber_rebar)
fkit.plotter.preview_section(section6)

# wall_layered
section7 = fkit.sectionbuilder.wall_layered(
    width1 = 6, 
    width2 = 12, 
    length = 120, 
    cover = 1.5, 
    wall_bar1 = [0.2, 12, 2], 
    wall_bar2 = [0.6, 6, 2],
    concrete_fiber1 = fiber_unconfined, 
    concrete_fiber2 = fiber_confined, 
    steel_fiber1 = fiber_rebar, 
    steel_fiber2 = fiber_rebar)
fkit.plotter.preview_section(section7)

# wall_speedcore
section8 = fkit.sectionbuilder.wall_speedcore(
    length=120,
    width=18, 
    steel_thickness=1,
    concrete_fiber=fiber_confined, 
    steel_fiber=fiber_structural_steel)
fkit.plotter.preview_section(section8)

# wide_flange
section9 = fkit.sectionbuilder.wide_flange(
    bf = 14,
    d = 14,
    tw = 1.0,
    tf = 1.5,
    steel_fiber = fiber_structural_steel)
fkit.plotter.preview_section(section9)

# W_AISC
section10 = fkit.sectionbuilder.W_AISC(
    shape = "W27X307",
    steel_fiber = fiber_structural_steel)
fkit.plotter.preview_section(section10)

main_full.py illustrates all of the major functionalities of fiberkit.

import fiberkit as fkit

#########################################
# Step 1: Define fiber material properties
#########################################
# define patch fiber material properties
fiber_unconfined = fkit.patchfiber.Hognestad(fpc=5)
fiber_confined   = fkit.patchfiber.Mander(fpc=6, eo=0.004, emax=0.014, default_color="gray")

# define node fiber material properties
fiber_steel      = fkit.nodefiber.Bilinear(fy=60, fu=90, Es=30000)

# preview fibers stress-strain curve
fkit.plotter.preview_fiber(fiber_unconfined, x_limit=[-0.008, 0.008])
fkit.plotter.preview_fiber(fiber_confined, x_limit=[-0.03, 0.03])
fkit.plotter.preview_fiber(fiber_steel, x_limit=[-0.03, 0.03])



#########################################
# Step 2: Define sections
#########################################
# Let's reproduce this section: https://opensees.berkeley.edu/wiki/index.php/Moment_Curvature_Example
# Most sections can be defined with SectionBuilder
section1 = fkit.sectionbuilder.rectangular_confined(width = 15, 
                                                    height = 24, 
                                                    cover = 1.5, 
                                                    top_bar = [0.6, 3, 1, 0], #[bar_area, nx, ny, y_spacing]
                                                    bot_bar = [0.6, 3, 1, 0], #[bar_area, nx, ny, y_spacing]
                                                    core_fiber = fiber_confined, 
                                                    cover_fiber = fiber_unconfined, 
                                                    steel_fiber = fiber_steel,
                                                    mesh_nx=0.75,
                                                    mesh_ny=0.75)

# we can build on top of the section generated by SectionBuilder
section1.add_bar(coord = [6, 0], area = 0.6, fiber = fiber_steel)
section1.add_bar(coord = [-6, 0], area = 0.6, fiber = fiber_steel)

# Alternatively, the user can draw sections manually
section2 = fkit.Section()
section2.add_patch(xo=0, yo=0, b=18 ,h=18, nx=25, ny=25, fiber=fiber_unconfined)
section2.add_bar_group(xo=2, yo=2, b=14, h=14, nx=3, ny=3, area=0.6, perimeter_only=True, fiber=fiber_steel)

# preview section
fkit.plotter.preview_section(section1, show_tag=True)
fkit.plotter.preview_section(section2, show_tag=True)


#########################################
# Step 3: Moment curvature analysis
#########################################
# roughly estimate target curvature to which we will push the section
phi_target = 0.00125

# moment-curvature analysis
MK_results = section1.run_moment_curvature(phi_target = phi_target, P=-180)

# calculate cracked moment of inertia at each load step
Icr_results = section1.calculate_Icr(Es=29000, Ec=3605)

# extract all fiber data
df_nodefibers, df_patchfibers = section1.get_all_fiber_data()

# extract data of a specific fiber
fiber_data        = section1.get_patch_fiber_data(location=[0.0, 8.25])
fiber_data_top    = section1.get_patch_fiber_data(location="top")
fiber_data_bottom = section1.get_patch_fiber_data(location="bottom")
fiber_data_rebar3 = section1.get_node_fiber_data(tag=3)

# plot results
fkit.plotter.plot_MK(section1)
fkit.plotter.plot_Icr(section1)

# animate results
#fkit.plotter.animate_MK(section1)

# interactive visualization (new in v2.0.0)
fkit.plotter.plot_MK_3D(section1)

#########################################
# Step 4: PMM interaction analysis
#########################################
# generate PM interaction surface using ACI-318 provisions
PM_results = section1.run_PM_interaction(fpc=6, fy=60, Es=29000)

# plot PM interaction surface
fkit.plotter.plot_PM(section1, P=[50,400], M=[-500,3000])

Documentation

Link to Documentation

The user can access docstrings of any methods using the help() keyword in python:

help(fkit.patchfiber.Hognestad)
fkit.patchfiber.Hognestad?
demo

Here is a comprehensive list of all public methods available to the user.

Fiber Material Models: More Info

  • fiberkit.patchfiber.Hognestad(fpc, Ec="default", eo="default", emax=0.0038, alpha=0, take_tension=False, fr="default", er="default", default_color="lightgray")
  • fiberkit.patchfiber.Todeschini(fpc, Ec="default", eo="default", emax=0.0038, alpha=0, take_tension=False, fr="default", er="default", default_color="lightgray")
  • fiberkit.patchfiber.Mander(fpc, eo, emax, Ec="default", alpha=0, take_tension=False, fr="default", er="default", default_color="lightgray")
  • fiberkit.patchfiber.Bilinear(fy, fu, Es, ey="default", emax=0.1, default_color="black")
  • fiberkit.patchfiber.Multilinear(fy, fu, Es, ey1="default", ey2=0.008, stress1=0.83, stress2=0.98, stress3=1.00, stress4=0.84, strain1=0.03, strain2=0.07, strain3=0.10, strain4=0.16, default_color="black")
  • fiberkit.patchfiber.RambergOsgood(fy, Es, n, emax=0.16, default_color="black")
  • fiberkit.patchfiber.MenegottoPinto(fy, Es, b, n, emax=0.16, default_color="black")
  • fiberkit.patchfiber.Custom_Trilinear(strain1p, strain2p, strain3p, stress1p, stress2p, stress3p, strain1n="default", strain2n="default", strain3n="default", stress1n="default", stress2n="default", stress3n="default", default_color="black")
  • ~
  • fiberkit.nodefiber.Bilinear(fy, fu, Es, ey="default", emax=0.1, default_color="black")
  • fiberkit.nodefiber.Multilinear(fy, fu, Es, ey1="default", ey2=0.008, stress1=0.83, stress2=0.98, stress3=1.00, stress4=0.84, strain1=0.03, strain2=0.07, strain3=0.10, strain4=0.16, default_color="black")
  • fiberkit.nodefiber.RambergOsgood(fy, Es, n, emax=0.16, default_color="black")
  • fiberkit.nodefiber.MenegottoPinto(fy, Es, b, n, emax=0.16, default_color="black")
  • fiberkit.nodefiber.Custom_Trilinear(strain1p, strain2p, strain3p, stress1p, stress2p, stress3p, strain1n="default", strain2n="default", strain3n="default", stress1n="default", stress2n="default", stress3n="default", default_color="black")

Section Definition: More Info

  • fiberkit.section.Section.add_patch(xo, yo, b, h, nx, ny, fiber)
  • fiberkit.section.Section.add_bar_group(xo, yo, b, h, nx, ny, area, perimeter_only, fiber)
  • fiberkit.section.Section.add_bar(coord, area, fiber)
  • fiberkit.section.Section.mesh(rotate=0)

SectionBuilder: More Info

  • fiberkit.sectionbuilder.rectangular(width, height, cover, top_bar, bot_bar, concrete_fiber, steel_fiber, mesh_nx=0.5, mesh_ny=0.5)
  • fiberkit.sectionbuilder.rectangular_confined(width, height, cover, top_bar, bot_bar, core_fiber, cover_fiber, steel_fiber, mesh_nx=0.5, mesh_ny=0.5)
  • fiberkit.sectionbuilder.circular(diameter, cover, N_bar, A_bar, core_fiber, cover_fiber, steel_fiber, mesh_n=0.5)
  • fiberkit.sectionbuilder.flanged(bw, bf, h, tf, cover, bot_bar, top_bar, slab_bar, core_fiber, cover_fiber, steel_fiber, mesh_nx=0.5, mesh_ny=0.5)
  • fiberkit.sectionbuilder.wall(width, length, cover, wall_bar, concrete_fiber, steel_fiber, mesh_nx=0.5, mesh_ny=0.5)
  • fiberkit.sectionbuilder.wall_BE(width, length, cover, BE_length, wall_bar, BE_bar, concrete_fiber, BE_fiber, steel_fiber, mesh_nx=0.5, mesh_ny=0.5)
  • fiberkit.sectionbuilder.wall_layered(width1, width2, length, cover, wall_bar1, wall_bar2, concrete_fiber1, concrete_fiber2, steel_fiber1, steel_fiber2, mesh_nx=0.5, mesh_ny=0.5)
  • fiberkit.sectionbuilder.wall_speedcore(length, width, steel_thickness, concrete_fiber, steel_fiber, mesh_nx=0.5, mesh_ny=0.5)
  • fiberkit.sectionbuilder.wide_flange(bf, d, tw, tf, steel_fiber, mesh_nx=0.5, mesh_ny=0.5)
  • fiberkit.sectionbuilder.W_AISC(shape, steel_fiber, mesh_nx=0.5, mesh_ny=0.5)

Analysis commands: More Info

  • fiberkit.section.Section.run_moment_curvature(phi_target, P=0, N_step=100, show_progress=False)
  • fiberkit.section.Section.calculate_Icr(Es, Ec)
  • fiberkit.section.Section.run_PM_interaction(fpc, fy, Es)
  • fiberkit.section.Section.get_node_fiber_data(tag)
  • fiberkit.section.Section.get_patch_fiber_data(location)
  • fiberkit.section.Section.get_all_fiber_data()
  • fiberkit.section.Section.export_data(save_folder="fkit_result_folder")

Visualizations: More Info

  • fiberkit.plotter.preview_fiber(fiber, xlim=[-0.01, 0.01])
  • fiberkit.plotter.compare_fiber(fibers, labels, xlim=[-0.01, 0.01])
  • fiberkit.plotter.preview_section(section, show_tag=False)
  • fiberkit.plotter.plot_MK(section)
  • fiberkit.plotter.plot_MK_3D(section)
  • fiberkit.plotter.animate_MK(section)
  • fiberkit.plotter.plot_Icr(section)
  • fiberkit.plotter.plot_PM(section, P=None, M=None)

Notes and Assumptions

demo
  • Moment curvature analysis proceeds in the -ve Mx direction, where top fibers are increasingly compressed.
  • Applied axial force and moment follows the right-hand convention:
    • Positive (+) applied axial force P results in tension
    • Positive (+) applied moment Mx results in tension on the top fibers, and compression on bottom fibers.
  • Fiber stress and strain sign conventions:
    • Positive (+) is tensile stress/strain
    • Negative (-) is compressive stress/strain
  • Please ensure consistent unit input:
    • SI Unit: (N, mm, MPa)
    • Imperial Unit: (kips, in, ksi)
  • PM interaction analysis follows ACI 318-19 assumptions (e.g. rectangular stress block, elastic-perfect-plastic steel, spalling strain of 0.003, etc). Solution is independent of user-specified fiber materials as all concrete fibers are converted to exhibit rectangular stress block behavior, and all rebar fibers are converted to elastic-perfect-plastic behavior.
  • Disclaimer: this is not enterprise-grade software. Please do NOT use it for work. Users assume full risk and responsibility for verifying that the results are accurate.

License

MIT License

Copyright (c) 2023 Robert Wang

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fiberkit-2.0.0.tar.gz (11.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fiberkit-2.0.0-py3-none-any.whl (59.1 kB view details)

Uploaded Python 3

File details

Details for the file fiberkit-2.0.0.tar.gz.

File metadata

  • Download URL: fiberkit-2.0.0.tar.gz
  • Upload date:
  • Size: 11.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for fiberkit-2.0.0.tar.gz
Algorithm Hash digest
SHA256 6dd05d50c79dcd68aae3fb02dba9f7b8532b896cf5366b3a14edcf7630ce9019
MD5 02e9e6b507bd328bce04a9037ca9c26f
BLAKE2b-256 94d9445da4114b531e9e6c22ac8853a19731a34ad09b36628fd05e1a8b689587

See more details on using hashes here.

File details

Details for the file fiberkit-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: fiberkit-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 59.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for fiberkit-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d8cac31b3a1b38a7dec7f1a2ddf43cdaa71493d40cd3c41e23d96da744b18829
MD5 37e455f5b20fc6902f751f47c43f2eef
BLAKE2b-256 dc7cd4ce4ffded4ccf54f98f923ac1a902b1f7b937ea883ed902eb854d9f63e4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page