Single span girder#

See also

Visual Basic for Applications - Examples

Problem Description#

In this example a single span girder will be designed according to EN 1992-2004. The input (geometry, materials, sections…) will be written in Teddy, the design will be done by using the programming interface. We will use other modules and the sof_cdb_get() to create our ‘’own AQB module’’.

Hint

Please note that the algorithm for the cross-section design is just an example, it is simplified as much as possible (we use the simplified stress-strain curve). Do NOT compare AQB with this example, because by using this code sample you will get just approximate results.

The problem consists of a single span girder. The cross-section is designed for an ultimate moment MEd and the required reinforcement is determined.

../../_images/vba_single_span_girder_1.png

In the workbook/project example the value of σsd = fyd for ε ≥ εyd (as shown in figure). AQB uses the second curve.

To show how to get the data and manipulate with it, through the example, next values will be read from the CDB:

  • fck is the characteristic compressive strength of concrete,

  • fyd is the characteristic yield strength of concrete reinforcement,

  • h is the height of the cross-section,

  • b is the width of the cross-section,

  • SU d is the offset of bottom reinforcement,

  • MEd is the design value of applied bending moment,

  • NEd is the design value of applied axial force.

../../_images/stress_strain.svg../../_images/single_span_girder_cross_section.svg

To read the mentioned values, next keys are necessary:

  • fck @Rec:(1/NR) m_FCK

  • fyk @Rec:(1/NR) m_FY

  • h @Rec:(9/NR) m_H

  • b @Rec:(9/NR) m_B

  • SU @Rec:(9/NR) m_SU

  • MEd @Rec:(102/LC) m_MY

  • NEd @Rec:(102/LC) m_N

Problem Solution#

The following example can be found in the SOFiSTiK directory:

C:\<sofistik_installation>\2023\SOFiSTiK 2023\interfaces\examples\c++\single_span_girder

Note

Please run the single_span_girder.dat file to generate the CDB.

In the C++ example folder, the main files are:

  • single_span_girder.sln (the solution)

  • main.cpp (main .CPP file)

  • single_span_girder.dat (.DAT file to generate the CDB)

  • single_span_girder.vcxproj (Visual Studio Project file)

The main.cpp#

The code from the main.cpp will be explained in details. First we need to include the libraries and define the functions.

#include <iostream>
#include <Windows.h>
#include <iomanip>

// Include the SOFiSTiK Libraries
#include "cdbase.h"
#include "cdbtypeall.h"
#include "cdbtypecon.h"
#include "cdbtypegeo.h"
#include "cdbtypelfc.h"
#include "cdbtypemat.h"
#include "cdbtypesct.h"
#include "cdbtypesys.h"
#include "cdbtypeten.h"

using namespace std;

Next step is to connect to the CDB, please check the fileName variable and the CDB path:

// ******************************************************
// * Connect to CDB                                     *
// * int sof_cdb_init  ( char* FileName, int Index);    *
// ******************************************************

/*
Index = 0     initialise CDBASE and open scratch data base only
Index > 0     open an existing data base with exactly tis index
                  (STATUS=UNKNOWN) = somehow obsolete call, use 99!
Index = 99    test if NAME is a valid database and open the base
                  if possible. Return with the assigned index.
                  If the file does not exist, it will be created.
Index = 97    open the database via pvm
                  Return with the assigned index.
Index = 96    open a scratch database, filename is the path to
                  use or NULL.
Index = 95    open in read-only mode
Index = 94    create a new data base (STATUS=NEW)
*/
int index = 99;

// cdb path
char* fileName = "S:\\test\\simple_span_girder.cdb";
int ie = sof_cdb_init(fileName, index);
if (ie < 0)
{
   cout << "ERROR: Index= " << ie << " < 0 - see clib1.h for meaning of error codes" << endl;
   cout << "Press any <key> to close the program";
   system("pause");
   return(0);
}
else if(ie == 0)
{
   cout << "ERROR: Index= " << ie << " - The File is not a database" << endl;
   cout << "Press any <key> to close the program";
   system("pause");
   return(0);
}

Read the fck value#

Now we are going to read the data from CDB:

// -----------------------------
// Read the f_ck value
// -----------------------------
double fck = 0.0;
datalen = sizeof(tagCDB_MAT_CONC);
datalenptr = &datalen;
tagCDB_MAT_CONC c_mat_conc;
while (sof_cdb_get(ie, 1, 1, &c_mat_conc, &datalen, 1) < 2)
{
   if (c_mat_conc.m_id == 1)
      fck = c_mat_conc.m_fck / 1000; // devide with 1000 because of units kN/m^2 -> MN/m^2
   datalen = sizeof(tagCDB_MAT_CONC);
}

// Release all locks. All memory for directories and data is released.
// Only after this call the directory structure is reread which allows the access to newly defined keys.
sof_cdb_flush(ie);

The program calls the sof_cdb_get function while the return value is < 2 (if return value = 2 then end is reached).

Hint

It is necessary to call datalen = sizeof() always before sof_cdb_get() is called.

Read the fyk value#

// -----------------------------
// Read the f_y value
// -----------------------------
double fy = 0.0;
datalen = sizeof(tagCDB_MAT_STEE);
datalenptr = &datalen;
tagCDB_MAT_STEE c_mat_stee;

// kwh = 1, kwl = 2
while (sof_cdb_get(ie, 1, 2, &c_mat_stee, &datalen, 1) < 2)
{
   if (c_mat_stee.m_id == 1)
      fy = c_mat_stee.m_fy / 1000; // devide with 1000 because of units kN/m^2 -> MN/m^2

   datalen = sizeof(tagCDB_MAT_STEE);
}

// Release all locks. All memory for directories and data is released.
// Only after this call the directory structure is re-read which allows the access to newly defined keys.
sof_cdb_flush(ie);

The kwh value = 1 and the kwl value = 2 (in this case kwl is the material number defined in the .dat file). If the material number is changed in the .dat file, then it must be also changed in the code.

Next step is to read the cross-section properties (h , b, su, so). The key where the values are stored is kwh=9 and kwl=1 (please see database_help_small ‘’CDBase Help’’ for further information.)

Read the b, h, so, su values#

// -----------------------------
// Read the b, h, so, su values
// -----------------------------
double b = 0.0;
double h = 0.0;
double so = 0.0;
double su = 0.0;
datalen = sizeof(tagCDB_SECT_REC);
datalenptr = &datalen;
tagCDB_SECT_REC c_sect_rec;

// kwh = 9, kwl = 1
while (sof_cdb_get(ie, 9, 1, &c_sect_rec, &datalen, 1) < 2)
{
   if (c_sect_rec.m_id == 10)
   {
      b = c_sect_rec.m_b;
      h = c_sect_rec.m_h;
      so = c_sect_rec.m_so;
      su = c_sect_rec.m_su;
   }
   datalen = sizeof(tagCDB_SECT_REC);
}

// Release all locks. All memory for directories and data is released.
// Only after this call the directory structure is reread which allows the access to newly defined keys.
sof_cdb_flush(ie);

Read the internal forces#

// -----------------------------
// READ THE INTERNAL FORCES N, M
// -----------------------------
double Ned = 0.0;
double Med = 0.0;
datalen = sizeof(typeCDB_BEAM_FOC);
datalenptr = &datalen;
typeCDB_BEAM_FOC c_beam_foc;

// kwh = 102, kwl = 1001
while (sof_cdb_get(ie, 102, 1001, &c_beam_foc, &datalen, 1) < 2)
{
   if (c_beam_foc.m_id == 0)
   {
      if (abs(Ned) < abs(c_beam_foc.m_n) && (abs(c_beam_foc.m_n) < 1e35))
         Ned = c_beam_foc.m_n / 1000;

      if (abs(Med) < abs(c_beam_foc.m_my) && (abs(c_beam_foc.m_my) < 1e35))
         Med = c_beam_foc.m_my / 1000;
   }
   datalen = sizeof(typeCDB_BEAM_FOC);
}

// Release all locks. All memory for directories and data is released.
// Only after this call the directory structure is reread which allows the access to newly defined keys.
sof_cdb_flush(ie);

The iteration starts from εs1 = 25 ‰ and εc2 = 0 ‰. First the εs1 is modified and iterated. When it reaches the minimum the program iterates εc2 value from 0 to 3.5 ‰.

As shown above the μ value must be μ < 0.296 to avoid additional symmetrical reinforcement (x/d ≤ 0.45):

fyd = fyks

γs = 1.15

The formulas for fcd:

fcd = αcc·(fckc)

where: αcc = 0.85 and γc = 1.50

The d value can not be read from the CDB but can be calculated by reading the su value (representing d1) d = h - su.

The conditions for the calculations are:

ΣM = 0 Myd = Fc·z = Fs1·z

ΣH = 0 Fc = Fs1

// **************************************************
// * CROSS SECTION DESIGN                           *
// * iterating the reinforcement to get equilibrium *
// **************************************************

// declaring variables

double epss = 25;
double epsc = 0;
double Mrd = 0;
double mu = 0;
double alpha = 0;
double xi = 0;
double x = 0;
double d = h - su;
double ka = 0;
double z = 0;
double zeta = 0;
double omega = 0;
double fcd = (fck * 0.85) / 1.5;
double fyd = fy / 1.15;
double As1 = 0;
double Meds;

Meds = Med - Ned * (h / 2 - su);

// iterate the reinforcement
while (Mrd <= Meds && mu <= 0.296)
{
   if (epsc > 0 && epsc <= 2)
      alpha = epsc / 12 * (6 - epsc);
   else if (epsc > 2 && epsc <= 3.5)
      alpha = (3 * epsc - 2) / (3 * epsc);

   // Calculate the Xi Value
   xi = epsc / (epss + epsc);

   // Calculate x
   x = xi * d;

   // Calculate ka
   if (epsc > 0 && epsc <= 2)
      ka = (8 - epsc) / (4 * (6 - epsc));
   else if (epsc > 2 && epsc <= 3.5)
      ka = (epsc * (3 * epsc - 4) + 2) / (2 * epsc * (3 * epsc - 2));

   // Calculate z
   z = d - ka * x;

   // Calculate zeta
   zeta = 1 - ka * xi;

   // Calculate omega
   omega = alpha * xi;

   // Calculate mu
   // mu = alpha * xi * d * gv.b * Convert.ToSingle(fcd);
   mu = alpha * xi * zeta;

   // Calculate the Mrd resistance moment
   Mrd = alpha * xi * d * b * fcd * zeta * d;

   // Required reinforcement
   As1 = (1 / fyd) * (omega * b * d * fcd + Ned);

   if (epsc >= 3.5)
   {
      while (Mrd <= Meds && epss >= 0 && mu < 0.296)
      {
         if (epsc > 0 && epsc <= 2)
            alpha = epsc / 12 * (6 - epsc);
         else if (epsc > 2 && epsc <= 3.5)
            alpha = (3 * epsc - 2) / (3 * epsc);

         // Calculate the Xi Value
         xi = epsc / (epss + epsc);

         // Calculate x
         x = xi * d;

         // Calculate ka
         if (epsc > 0 && epsc <= 2)
            ka = (8 - epsc) / (4 * (6 - epsc));
         else if (epsc > 2 && epsc <= 3.5)
            ka = (epsc * (3 * epsc - 4) + 2) / (2 * epsc * (3 * epsc - 2));

         // Calculate z
         z = d - ka * x;

         // Calculate zeta
         zeta = 1 - ka * xi;

         // Calculate omega
         omega = alpha * xi;

         // Calculate mu
         mu = alpha * xi * zeta;

         // Calculate the Mrd resistance moment
         Mrd = alpha * xi * d * b * fcd * zeta * d;

         // Required reinforcement
         As1 = (1 / fyd) * (omega * b * d * fcd + Ned);

         if (epss == 0)
            cout << "Reinforced reached 0 [o/oo]";

         // Iterate epss
         epss = epss - 0.001;
      }
   }
   // Iterate epsc
   epsc = epsc + 0.001;
}

At end the CDB must be closed (0 - close to all CDBs):

// Close the CDB
// int sof_cdb_close  (int ie);
sof_cdb_close(0);
cout << "The CDB Status after closing: " << sof_cdb_status(ie) << endl;