Materials¶
General¶
The material classes in StructuralCodes are the natural starting point when building any structural design workflow. The material classes are specific to each design code, and they contain attributes that represent common properties from the design code. A material object also contains a constitutive law. The constitutive law is accessed from the section calculator when integrating the strain response in a section.
StructuralCodes contains material classes for representing concrete and reinforcement, in addition to a collection of basic materials for representing arbitrary materials with given constitutive laws.
To create concrete and reinforcement objects, we can either directly import specific classes as shown in the sections below, or we can set an active design code and use the factory functions.
Syntax
from structuralcodes import set_design_code
from structuralcodes.codes import ec2_2004
from structuralcodes.materials.concrete import create_concrete
from structuralcodes.materials.reinforcement import create_reinforcement
fck = 45
fyk = 500
Es = 200000
ductility_class = 'C'
set_design_code('ec2_2004')
concrete = create_concrete(fck=45, alpha_cc=0.85, gamma_c=1.5)
reinforcement = create_reinforcement(
fyk=fyk,
Es=Es,
gamma_s=1.15,
**ec2_2004.reinforcement_duct_props(
fyk=fyk, ductility_class=ductility_class
),
)
Notice how the factory functions accept the same keyword arguments as the constructors of the specific classes. This allows us to pass e.g. gamma_c
and alpha_cc
to create_concrete
. Also notice how we are using reinforcement_duct_props()
to get a dictionary with properties related to the specified ductility class of reinforcement.
After creating a material object, its properties are easily accessed, e.g. concrete.Ecm
. Most notably, the .constitutive_law
attribute reveals the constitutive law of the material.
Tip
All material classes are subclasses of the Material
base class, and all constitutive laws are subclasses of the ConstitutiveLaw
base class. These base classes define interfaces. This means that we can create our own custom classes as subclasses of these base classes, and as long as we implement the necessary methods defined by the interface, we can swap the builtin classes with our custom ones. This opens for a lot of flexibility inside StructuralCodes.
Attention
The material objects in StructuralCodes are immutable. This means that as soon as a material object is created, the attributes of the object cannot be changed.
Concrete materials¶
There are classes for representing concrete according to the current version of Eurocode 2, fib Model Code 2010, and the next generation of Eurocode 2.
Import ConcreteEC2_2004
to create an object representing concrete according to Eurocode 2 (2004).
Syntax
from structuralcodes.materials.concrete import ConcreteEC2_2004
concrete = ConcreteEC2_2004(fck=45)
Notice how it is possible to override the default values of the properties by passing these to the constructor.
Syntax
concrete = ConcreteEC2_2004(fck=45, fcm=50, constitutive_law='sargin')
To override the constitutive law, we can also pass a constitutive law object valid for concrete.
Syntax
from structuralcodes.materials.concrete import ConcreteEC2_2004
from structuralcodes.materials.constitutive_laws import Sargin
constitutive_law = Sargin(fc=53, eps_c1=-0.002, eps_cu1=-0.003, k=2)
concrete = ConcreteEC2_2004(fck=45, constitutive_law=constitutive_law)
Reinforcement materials¶
Reinforcement objects are created and used in a similar manner as the concrete objects, and there are reinforcement classes according to the current version of Eurocode 2, fib Model Code 2010, and the next generation of Eurocode 2.
Import ReinforcementEC2_2004
to create a reinforcement object according to Eurocode 2 (2004).
Syntax
from structuralcodes.materials.reinforcement import ReinforcementEC2_2004
reinforcement = ReinforcementEC2_2004(fyk=500, Es=200000, ftk=510, epsuk=0.06)
Constitutive laws¶
When initializing a material object it will include a constitutive law object as well. The purpose of the constitutive law object is to provide a relation between stresses and strains, or modulus and strain. Therefore all constitutive law objects implement the .get_stress()
, .get_tangent()
, and .get_secant()
methods. As shown above, the concrete and reinforcement classes define default constitutive laws, that can be overridden by the constructor.
The example below shows how to access the ultimate strains of the constitutive law, create an array of linearly spaced strain values, and passing these strain values to the .get_stress()
method to get corresponding stresses. Note that only compressive strains and stresses are computed in this example. In this example we are passing an array of strain values to .get_stress()
, but the method also accepts a scalar argument.
Syntax
import numpy as np
from structuralcodes.materials.concrete import ConcreteEC2_2004
# Create a concrete object
concrete = ConcreteEC2_2004(fck=45, gamma_c=1.5, alpha_cc=0.85)
# Create an array of strain values based on the ultimate compressive strain,
# and compute corresponding stresses
strains = np.linspace(concrete.constitutive_law.get_ultimate_strain()[0], 0)
stresses = concrete.constitutive_law.get_stress(strains)
Tip
Use your favourite plotting library to visualize the computed stresses. The code below shows how to produce the figure below with Matplotlib.
Syntax
import matplotlib.pyplot as plt
# Plot stress-strain relation
fig, ax = plt.subplots()
ax.plot(strains, stresses, '-k')
ax.set_xlim(xmax=0)
ax.set_ylim(ymax=0)
ax.grid()
ax.set_xlabel(r'$\epsilon$ [-]')
ax.set_ylabel(r'$\sigma$ [MPa]')

The parabola-rectangle distribution computed with the code above.¶
To create a constitutive law, you can either use the constitutive law factory, or directly import a specific constitutive law class as shown in the example above. You can call get_constitutive_laws_list()
to get a list of all the available constitutive laws.
The constitutive law factory takes a name and a material object as arguments, and returns a constitutive law object. For it to work, the material object which is used as argument needs to implement a dunder method related to the specified constitutive law, in order to provide the relevant parameters for the constitutive law.
The example below shows how we can use the constitutive law factory to create a BilinearCompression
object based on a ConcreteEC2_2004
object. Since the ConcreteEC2_2004
object implements the __bilinearcompression__
method, the constitutive law factory can call this method to get a dictionary with the relevant parameters to create the constitutive law. This workflow can be used if you wish to compare several constitutive laws that are based on the same material.
Syntax
from structuralcodes.materials.concrete import ConcreteEC2_2004
from structuralcodes.materials.constitutive_laws import create_constitutive_law
# Create a concrete object, and a constitutive law
concrete = ConcreteEC2_2004(fck=45, gamma_c=1.5, alpha_cc=0.85)
constitutive_law = create_constitutive_law(
constitutive_law_name='bilinearcompression', material=concrete
)
Customize the material behaviour
There are a few ways to customize constitutive laws in StructuralCodes.
The first is to simply provide user values to the parameters of the available constitutive laws.
The second is to use the special UserDefined
constitutive laws which allows you to provide two arrays in the constructor: one for strains and one for stresses, i.e. representing any arbitrary uniaxial relation between stresses and strains.
The third is to create a new subclass of ConstitutiveLaw
that represents your custom constitutive law. As long as you implement the .get_stress()
, .get_tangent()
, and .get_ultimate_strain()
methods, you can use it in a material as basis for a geometry in a section calculation.
Basic materials¶
To simplify creating materials with simple constitutive laws, StructuralCodes contains a set of basic materials, including ElasticMaterial
, ElasticPlasticMaterial
, and GenericMaterial
.
The GenericMaterial
is a material class that accepts any constitutive law.
The ElasticMaterial
and the ElasticPlasticMaterial
are materials that are initialized with just the necessary data to also initialize an Elastic
and an ElasticPlastic
constitutive law, respectively. The example below shows how to create an ElasticPlasticMaterial
.
Syntax
from structuralcodes.materials.basic import ElasticPlasticMaterial
material = ElasticPlasticMaterial(
E=200000, fy=500, density=7850, Eh=0, eps_su=0.03
)
Note how you can use .from_material()
on ElasticMaterial
to create an elastic representation of any other material on the fly. This method makes use of the constitutive law of the other material to get the tangent modulus at zero strain, and passes this value to the constructor of the elastic material. See the example code below. This feature is used for example in calculate_elastic_cracked_properties()
to represent the materials in a reinforced concrete geometry with elastic materials.
Syntax
from structuralcodes.materials.basic import ElasticMaterial
from structuralcodes.materials.concrete import ConcreteEC2_2004
concrete = ConcreteEC2_2004(fck=45, alpha_cc=0.85, gamma_c=1.5)
elastic_concrete = ElasticMaterial.from_material(concrete)