# -*- coding: utf-8 -*-
"""
Created on Thu Apr 26 12:54:15 2018

@author: kevin.stanton

This class initializes an XTRACT model given user defined data ported from
AutoMHB.py
"""

import os
import datetime
import time
import math


class iXTRACT_envelope():

    def __init__(self, aData):

        # Delete xtract and txt file if they exist
        if os.path.exists(str(aData.pSave) + '\\' +
                          str(aData.file_name) + '.txt'):
            os.remove(str(aData.pSave) + '\\' + str(aData.file_name) + '.txt')
        if os.path.exists(str(aData.pSave) + '\\' +
                          str(aData.file_name) + '.xpj'):
            os.remove(str(aData.pSave) + '\\' + str(aData.file_name) + '.xpj')

        # Open a file handle
        self.fwrite = open(str(aData.pSave) + '\\' +
                           str(aData.file_name) + '.xpj', mode='w')

    def __intro__(self, aData):

        # Write intro statements
        self.fwrite.write('\n')
        self.fwrite.write('# Project file generated by Python\n')
        self.fwrite.write('# Created by: %s\n' % aData.author)
        self.fwrite.write('\n')
        self.fwrite.write(
            '# WARNING: When this file is read into XTRACT, data consistency\n')
        self.fwrite.write(
            '# checks are NOT performed. If inappropriate input data is read\n')
        self.fwrite.write(
            '# into the software, unexpected results may ensue. Before modifying\n')
        self.fwrite.write(
            '# this file, it is advised to save a back up copy.\n')
        self.fwrite.write(
            '# The order of the file in not important, nor is the spacing.\n')
        self.fwrite.write(
            '# The file must contain Global data as described below.\n')
        self.fwrite.write(
            '# Note that if this file is saved outside XTRACT, the associated\n')
        self.fwrite.write(
            '# output file will be automatically deleted when the file is opened.\n')
        self.fwrite.write('\n')

    def __global_params__(self, aData,
                          version='3.08',  # Xtract version
                          units='N-m'):  # Analysis units

        # Define datetime stamp
        stamp = datetime.datetime.fromtimestamp(time.time()).\
            strftime('%m/%d/%Y %I:%M:%S %p')

        # Write gloabl parameters
        self.fwrite.write(
            '#---------------------------------------------------------------------\n')
        self.fwrite.write('\n')
        self.fwrite.write('# Define global parameters for the file\n')
        self.fwrite.write('# Version, Units and Name are required.\n')
        self.fwrite.write('Begin_Global\n')
        self.fwrite.write('	NAME = %s\n' % aData.file_name)
        self.fwrite.write('	VER = %s\n' % version)
        self.fwrite.write('	UNITS = %s\n' % units)
        self.fwrite.write('\n')
        self.fwrite.write('	# Optional parameters\n')
        self.fwrite.write('	Author = %s\n' % aData.author)
        self.fwrite.write('	Company = %s\n' % aData.company)
        self.fwrite.write('	Job_Name = %s\n' % aData.job_name)
        self.fwrite.write('	Time_Stamp = %s\n' % stamp)
        self.fwrite.write('End_Global\n')
        self.fwrite.write('\n')
        self.fwrite.write(
            '#---------------------------------------------------------------------\n')
        self.fwrite.write('\n')

    def __mater_conu__(self, aData):

        # Write material definitions for unconfined concrete
        self.fwrite.write('# Begin unconfined concrete material definition\n')
        self.fwrite.write('Begin_Material\n')
        self.fwrite.write('	NAME = %s\n' % aData.mat_name_unc)
        self.fwrite.write('	TYPE = Unconfined Concrete\n')
        self.fwrite.write('	Fc = %s\n' % str(round(float(aData.Fc) * 1e6, 1)))
        self.fwrite.write('	Ft = %s\n' % str(round(float(aData.Ft) * 1e6, 1)))
        self.fwrite.write('	ey = %s\n' % str(round(float(aData.ey), 5)))
        self.fwrite.write('	ecu = %s\n' % str(round(float(aData.ecu), 5)))
        self.fwrite.write('	esp = %s\n' % str(round(float(aData.esp), 5)))
        self.fwrite.write('	ef = %s\n' % str(round(float(aData.ef), 5)))
        self.fwrite.write('	Ec = %s\n' % str(round(float(aData.Ec) * 1e6, 1)))
        self.fwrite.write('End_Material\n')
        self.fwrite.write('\n')
        self.fwrite.write(
            '#---------------------------------------------------------------------\n')
        self.fwrite.write('\n')

    def __mater_conc__(self, aData):

        # Write material definitions for confined concrete
        self.fwrite.write('# Begin confined concrete material definition\n')
        self.fwrite.write('Begin_Material\n')
        self.fwrite.write('	NAME = %s\n' % aData.mat_name_conc)
        self.fwrite.write('	TYPE = Confined Concrete\n')
        self.fwrite.write('	Fc = %s\n' % str(round(float(aData.Fc) * 1e6, 1)))
        self.fwrite.write('	Ft = %s\n' % str(round(float(aData.Ft) * 1e6, 1)))
        self.fwrite.write('	ey = %s\n' % str(round(float(aData.ey), 5)))
        self.fwrite.write('	ecu = %s\n' % str(round(float(aData.ecu), 5)))
        self.fwrite.write('	Fl = %s\n' % str(round(float(aData.Fc) * 1e6, 1)))
        self.fwrite.write('	Ec = %s\n' % str(round(float(aData.Ec) * 1e6, 1)))
        self.fwrite.write('\n')
        self.fwrite.write(
            '	# Optional parameters for confinement calculators\n')
        self.fwrite.write('	compStrength = %s\n' %
                          str(round(float(aData.Fc) * 1e6, 1)))
        self.fwrite.write('End_Material\n')
        self.fwrite.write('\n')
        self.fwrite.write(
            '#---------------------------------------------------------------------\n')
        self.fwrite.write('\n')

    def __mater_ste__(self, aData):

        # Write material definitions for steel
        self.fwrite.write('# Begin steel material definition\n')
        self.fwrite.write('Begin_Material\n')
        self.fwrite.write('	NAME = %s\n' % aData.mat_name_steel)
        self.fwrite.write('	TYPE = Strain Hardening Steel\n')
        self.fwrite.write('	Fy = %s\n' % str(round(float(aData.Fy) * 1e6, 1)))
        self.fwrite.write('	Fu = %s\n' % str(round(float(aData.Fu) * 1e6, 1)))
        self.fwrite.write('	esh = %s\n' % str(round(float(aData.esh), 5)))
        self.fwrite.write('	esu = %s\n' % str(round(float(aData.esu), 5)))
        self.fwrite.write('	Es = %s\n' % str(round(float(aData.Es) * 1e6, 1)))
        self.fwrite.write('End_Material\n')
        self.fwrite.write('\n')
        self.fwrite.write(
            '#---------------------------------------------------------------------\n')
        self.fwrite.write('\n')

    def __sect__(self, aData, concrete_strainlim, steel_strainlim):

        # Begin section definition
        self.fwrite.write('# Begin section definitions.\n')
        self.fwrite.write('Begin_Section\n')
        envelope_name = aData.section_name + '-C' + \
            str(concrete_strainlim) + '-S' + str(steel_strainlim * aData.esy)

        # Write section builder properties for circular section
        if aData.section_type == 'Circular':
            section_area = 3.14 * pow(float(aData.diameter_circ) / 2000, 2.0)
            mesh = str(round(float(aData.diameter_circ) / 1000 * 0.05, 5))
            min_triangle_area = str(round(pow(float(mesh), 2) / 3.0, 5))
            max_n_fiber = round(1000 * section_area /
                                pow(float(mesh) * 1000, 2) * 2000)

            self.fwrite.write('	Begin_Builder\n')
            self.fwrite.write('  NAME = %s\n' % envelope_name)
            self.fwrite.write('  NAME = %s\n' % envelope_name)
            self.fwrite.write('  Boundary_Bottom = -%s\n' %
                              str(round(float(aData.diameter_circ) / 1000 * 2, 5)))
            self.fwrite.write('  Boundary_Left = -%s\n' %
                              str(round(float(aData.diameter_circ) / 1000 * 2, 5)))
            self.fwrite.write('  Boundary_Right = %s\n' %
                              str(round(float(aData.diameter_circ) / 1000 * 2, 5)))
            self.fwrite.write('  Boundary_Top = %s\n' %
                              str(round(float(aData.diameter_circ) / 1000 * 2, 5)))
            self.fwrite.write('  Min_Triangle_Area = %s\n' %
                              min_triangle_area)
            self.fwrite.write('  Max_Number_of_Fibers = %s\n' %
                              str(max_n_fiber))
            self.fwrite.write(
                '  Window_Left = %s\n' % str(
                    round(
                        float(
                            aData.diameter_circ) / 1000 * 2.5,
                        5)))
            self.fwrite.write('  Window_Bottom = %s\n' % str(
                round(float(aData.diameter_circ) / 1000 * 1.25, 5)))
            self.fwrite.write('  Window_Height = %s\n' % str(
                round(float(aData.diameter_circ) / 1000 * 2.5, 5)))
            self.fwrite.write(' End_Builder\n')
            self.fwrite.write('\n')

        # Write section builder properties for rectangular beam section
        elif aData.section_type == 'Rectangular Beam':
            section_area = float(aData.rect_width) / 1000 * \
                float(aData.rect_height) / 1000
            # mesh length in m
            mesh = str(min(round(
                ((float(aData.rect_height) + float(aData.rect_width)) / 2000) * 0.05, 5), 0.028))
            min_triangle_area = str(round(pow(float(mesh), 2) / 3.0, 5))
            max_n_fiber = round(1000 * section_area /
                                pow(float(mesh) * 1000, 2) * 2000)

            self.fwrite.write('	Begin_Builder\n')
            self.fwrite.write('  NAME = %s\n' % envelope_name)
            self.fwrite.write('		NAME = %s\n' % envelope_name)
            self.fwrite.write('		Boundary_Bottom = -%s\n' %
                              str(round(float(aData.rect_height) / 1000 / 2 + 50 / 1000, 5)))
            self.fwrite.write('		Boundary_Left = -%s\n' %
                              str(round(float(aData.rect_width) / 1000 / 2 + 50 / 1000, 5)))
            self.fwrite.write('		Boundary_Right = %s\n' % str(
                round(float(aData.rect_width) / 1000 / 2 + 50 / 1000, 5)))
            self.fwrite.write(
                '		Boundary_Top = %s\n' % str(
                    round(
                        float(
                            aData.rect_height) / 1000 / 2 + 50 / 1000,
                        5)))
            self.fwrite.write('		Min_Triangle_Area = %s\n' %
                              min_triangle_area)
            self.fwrite.write('		Max_Number_of_Fibers = %s\n'
                              % str(max_n_fiber))
            self.fwrite.write(
                '		Window_Left = %s\n' % str(
                    round(
                        float(
                            aData.rect_width) / 1000 * 2 - 100 / 1000,
                        5)))
            self.fwrite.write(
                '		Window_Bottom = %s\n' % str(
                    round(
                        float(
                            aData.rect_height) / 1000 / 2 + 100 / 1000,
                        5)))
            self.fwrite.write('		Window_Height = %s\n' % str(
                round(float(aData.rect_height) / 1000 + 200 / 1000, 5)))
            self.fwrite.write('	End_Builder\n')
            self.fwrite.write('\n')

        # Write section builder properties for rectangular column section
        elif aData.section_type == 'Rectangular Column':
            # mesh length in m
            mesh = str(min(round(
                ((float(aData.rect_height) + float(aData.rect_width)) / 2000) * 0.05, 5), 0.028))
            section_area = round((float(aData.rect_width) / 1000)
                                 * float(aData.rect_height) / 1000, 5)
            # triangle size in m^2
            min_triangle_area = str(round(pow(float(mesh), 2) / 3.0, 5))
            max_n_fiber = round(1000 * section_area /
                                pow(float(mesh) * 1000, 2) * 2000)

            self.fwrite.write('	Begin_Builder\n')
            self.fwrite.write('  NAME = %s\n' % envelope_name)
            self.fwrite.write('		NAME = %s\n' % envelope_name)
            self.fwrite.write('		Boundary_Bottom = -%s\n' %
                              str(round(float(aData.rect_height) / 1000 / 2 + 50 / 1000, 5)))
            self.fwrite.write('		Boundary_Left = -%s\n' %
                              str(round(float(aData.rect_width) / 1000 / 2 + 50 / 1000, 5)))
            self.fwrite.write('		Boundary_Right = %s\n' % str(
                round(float(aData.rect_width) / 1000 / 2 + 50 / 1000, 5)))
            self.fwrite.write(
                '		Boundary_Top = %s\n' % str(
                    round(
                        float(
                            aData.rect_height) / 1000 / 2 + 50 / 1000,
                        5)))
            self.fwrite.write('		Min_Triangle_Area = %s\n' %
                              min_triangle_area)
            self.fwrite.write('		Max_Number_of_Fibers = %s\n'
                              % str(max_n_fiber))
            self.fwrite.write(
                '		Window_Left = %s\n' % str(
                    round(
                        float(
                            aData.rect_width) / 1000 * 2 - 0.1,
                        5)))
            self.fwrite.write('		Window_Bottom = %s\n' % str(
                round(float(aData.rect_height) / 1000 / 2 + 0.1, 5)))
            self.fwrite.write('		Window_Height = %s\n' %
                              str(round(float(aData.rect_height) / 1000 + 0.1, 5)))
            self.fwrite.write('	End_Builder\n')
            self.fwrite.write('\n')

        # Write section builder properties for T Beam section
        elif aData.section_type == 'T Beam':
            section_area = (float(aData.f_width) / 1000) * float(aData.f_thick) / 1000 + float(
                aData.t_width) / 1000 * (float(aData.t_height) / 1000 - float(aData.f_thick) / 1000)
            mesh = str(round(min(float(aData.t_height) / 1000,
                                 float(aData.f_width) / 1000) * 0.05, 5))
            max_n_fiber = round(1000 * section_area /
                                pow(float(mesh) * 1000, 2) * 2000) * 5
            # triangle size in m^2
            min_triangle_area = str(pow(float(mesh), 2) / 3.0)

            self.fwrite.write('	Begin_Builder\n')
            self.fwrite.write('  NAME = %s\n' % envelope_name)
            self.fwrite.write('		NAME = %s\n' % envelope_name)
            self.fwrite.write('		Boundary_Bottom = -%s\n' %
                              str(float(aData.t_height) / 1000 + 100 / 1000))
            self.fwrite.write('		Boundary_Left = -%s\n' %
                              str(float(aData.f_width) / 1000 + 100 / 1000))
            self.fwrite.write('		Boundary_Right = %s\n' %
                              str(float(aData.f_width) / 1000 + 100 / 1000))
            self.fwrite.write('		Boundary_Top = %s\n' %
                              str(float(aData.t_height) / 1000 + 100 / 1000))
            self.fwrite.write('		Min_Triangle_Area = %s\n' %
                              min_triangle_area)
            self.fwrite.write('		Max_Number_of_Fibers = %s\n'
                              % str(max_n_fiber))
            self.fwrite.write(
                '		Window_Left = %s\n' % str(
                    round(
                        float(
                            aData.t_width) / 1000 + 200 / 1000,
                        5)))
            self.fwrite.write(
                '		Window_Bottom = %s\n' % str(
                    round(
                        float(
                            aData.t_height) / 1000 / 2 + 100 / 1000,
                        5)))
            self.fwrite.write('		Window_Height = %s\n' % str(
                round(float(aData.t_height) / 1000 + 200 / 1000, 5)))
            self.fwrite.write('	End_Builder\n')
            self.fwrite.write('\n')

        # Write section builder properties for Cruciform section
        elif aData.section_type == 'Cruciform':
            section_area = round(((float(aData.tX) *
                                   float(aData.bY) +
                                   float(aData.tY) *
                                   float(aData.bX) -
                                   float(aData.tX) *
                                   float(aData.tY)) /
                                  (1000**2)), 5)
            mesh = str(round(min(float(aData.tX) / 1000,
                                 float(aData.tY) / 1000) * 0.05, 5))
            max_n_fiber = round(1000 * section_area /
                                pow(float(mesh) * 1000, 2) * 2000) * 5
            # Min triangle size in m^2
            min_triangle_area = str(round(pow(float(mesh), 2) / 3.0, 5))

            self.fwrite.write('	Begin_Builder\n')
            self.fwrite.write('  NAME = %s\n' % envelope_name)
            self.fwrite.write('		NAME = %s\n' % envelope_name)
            self.fwrite.write('		Boundary_Bottom = -%s\n' %
                              str(float(aData.bY) / 1000 + 100 / 1000))
            self.fwrite.write('		Boundary_Left = -%s\n' %
                              str(round(float(aData.bX) / 1000 + 100 / 1000, 2)))
            self.fwrite.write('		Boundary_Right = %s\n' %
                              str(round(float(aData.bX) / 1000 + 100 / 1000, 2)))
            self.fwrite.write('		Boundary_Top = %s\n' %
                              str(round(float(aData.bY) / 1000 + 100 / 1000, 2)))
            self.fwrite.write('		Min_Triangle_Area = %s\n' %
                              min_triangle_area)
            self.fwrite.write('		Max_Number_of_Fibers = %s\n'
                              % str(max_n_fiber))
            self.fwrite.write('		Window_Left = %s\n' %
                              str(round(float(aData.bX) / 1000 + 200 / 1000, 5)))
            self.fwrite.write('		Window_Bottom = %s\n' % str(
                round(float(aData.bY) / 1000 / 2 + 100 / 1000, 5)))
            self.fwrite.write('		Window_Height = %s\n' %
                              str(round(float(aData.bY) / 1000 + 200 / 1000, 5)))
            self.fwrite.write('	End_Builder\n')
            self.fwrite.write('\n')

        # Write section shape for circular section
        if aData.section_type == 'Circular':
            radius = str(float(aData.diameter_circ) / 2000)
            mesh = str(round(float(aData.diameter_circ) / 1000 * 0.05, 5))
            self.fwrite.write('	Begin_Shape\n')
            self.fwrite.write('		MATERIAL = %s\n' % aData.material_cover)
            self.fwrite.write('		MESH = %s\n' % mesh)
            self.fwrite.write('		COVER = %s\n' %
                              str(round(float(aData.cover) / 1000, 5)))
            self.fwrite.write('		MATERIAL_CORE = %s\n' % aData.material_core)
            self.fwrite.write('		Begin_Arc\n')
            self.fwrite.write('			0, -%s\n' % radius)
            self.fwrite.write('			%s, 0\n' % radius)
            self.fwrite.write('			0, %s\n' % radius)
            self.fwrite.write('			-%s, 0\n' % radius)
            self.fwrite.write('			0, -%s\n' % radius)
            self.fwrite.write('		End_Arc\n')
            self.fwrite.write('	End_Shape\n')
            self.fwrite.write('\n')

        # Write section shape for rectangular section
        elif aData.section_type == 'Rectangular Beam':
            # mesh length in m
            mesh = str(
                round(
                    ((float(
                        aData.rect_height) +
                        float(
                        aData.rect_width)) /
                        2000) *
                    0.05,
                    5))
            self.fwrite.write('	Begin_Shape\n')
            self.fwrite.write('		MATERIAL = %s\n' % aData.material_cover)
            self.fwrite.write('		MESH = %s\n' % mesh)
            self.fwrite.write('		COVER = %s\n' %
                              str(round(float(aData.cover) / 1000, 5)))
            self.fwrite.write('		MATERIAL_CORE = %s\n' % aData.material_core)
            self.fwrite.write('		Begin_Line\n')
            self.fwrite.write('			-%s, -%s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('			%s, -%s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('			-%s, %s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('			-%s, -%s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('		End_Line\n')
            self.fwrite.write('	End_Shape\n')
            self.fwrite.write('\n')

        # Write section shape for rectangular column section
        elif aData.section_type == 'Rectangular Column':
            # mesh length in m
            mesh = str(
                round(
                    ((float(
                        aData.rect_height) +
                        float(
                        aData.rect_width)) /
                        2000) *
                    0.05,
                    5))
            self.fwrite.write('	Begin_Shape\n')
            self.fwrite.write('		MATERIAL = %s\n' % aData.material_cover)
            self.fwrite.write('		MESH = %s\n' % mesh)
            self.fwrite.write('		COVER = %s\n' %
                              str(round(float(aData.cover) / 1000, 5)))
            self.fwrite.write('		MATERIAL_CORE = %s\n' % aData.material_core)
            self.fwrite.write('		Begin_Line\n')
            self.fwrite.write('			-%s, -%s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('			%s, -%s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('			-%s, %s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('			-%s, -%s\n' %
                              (str(round(float(aData.rect_width) / 1000 / 2, 5)),
                               str(round(float(aData.rect_height) / 1000 / 2, 5))))
            self.fwrite.write('		End_Line\n')
            self.fwrite.write('	End_Shape\n')
            self.fwrite.write('\n')

        # Write section shape for T Beam section
        elif aData.section_type == 'T Beam':
            mesh = str(round(min(float(aData.t_height) / 1000,
                                 float(aData.f_width) / 1000) * 0.05, 5))
            self.fwrite.write('	Begin_Shape\n')
            self.fwrite.write('		MATERIAL = %s\n' % aData.material_cover)
            self.fwrite.write('		MESH = %s\n' % mesh)
            self.fwrite.write('		COVER = %s\n' %
                              str(round(float(aData.cover) / 1000, 5)))
            self.fwrite.write('		MATERIAL_CORE = %s\n' % aData.material_core)
            self.fwrite.write('		Begin_Line\n')
            self.fwrite.write('			-%s, -%s\n' %
                              (str(round(float(aData.t_width) / 1000 / 2, 5)),
                               str(round(float(aData.t_height) / 1000 / 2, 5))))
            self.fwrite.write('			%s, -%s\n' %
                              (str(round(float(aData.t_width) / 1000 / 2, 5)),
                               str(round(float(aData.t_height) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.t_width) /
                                         1000 /
                                         2, 5)), str(round(float(aData.t_height) /
                                                           1000 /
                                                           2 -
                                                           float(aData.f_thick) /
                                                           1000, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.f_width) /
                                         1000 /
                                         2, 5)), str(round(float(aData.t_height) /
                                                           1000 /
                                                           2 -
                                                           float(aData.f_thick) /
                                                           1000, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.f_width) / 1000 / 2, 5)),
                               str(round(float(aData.t_height) / 1000 / 2, 5))))
            self.fwrite.write('			-%s, %s\n' %
                              (str(round(float(aData.f_width) / 1000 / 2, 5)),
                               str(round(float(aData.t_height) / 1000 / 2, 5))))
            self.fwrite.write('			-%s, %s\n' %
                              (str(round(float(aData.f_width) /
                                         1000 /
                                         2, 5)), str(round(float(aData.t_height) /
                                                           1000 /
                                                           2 -
                                                           float(aData.f_thick) /
                                                           1000, 5))))
            self.fwrite.write('			-%s, %s\n' %
                              (str(round(float(aData.t_width) /
                                         1000 /
                                         2, 5)), str(round(float(aData.t_height) /
                                                           1000 /
                                                           2 -
                                                           float(aData.f_thick) /
                                                           1000, 5))))
            self.fwrite.write('			-%s, -%s\n' %
                              (str(round(float(aData.t_width) / 1000 / 2, 5)),
                               str(round(float(aData.t_height) / 1000 / 2, 5))))
            self.fwrite.write('		End_Line\n')
            self.fwrite.write('	End_Shape\n')
            self.fwrite.write('\n')

        # Write section shape for Cruciform section
        elif aData.section_type == 'Cruciform':
            mesh = str(round(min(float(aData.tY) / 1000,
                                 float(aData.tX) / 1000) * 0.05, 5))
            self.fwrite.write('	Begin_Shape\n')
            self.fwrite.write('		MATERIAL = %s\n' % aData.material_cover)
            self.fwrite.write('		MESH = %s\n' % mesh)
            self.fwrite.write('		COVER = %s\n' %
                              str(round(float(aData.cover) / 1000, 5)))
            self.fwrite.write('		MATERIAL_CORE = %s\n' % aData.material_core)
            self.fwrite.write('		Begin_Line\n')
            self.fwrite.write('			%s, %s\n' %
                              (str(round(-1 * (float(aData.bX) / 2 + float(aData.cX)) / 1000, 5)),
                               str(round(float(aData.tY) * (-1) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.tX) * (-1) / 1000 / 2, 5)),
                               str(round(float(aData.tY) * (-1) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.tX) * (-1) / 1000 / 2, 5)),
                               str(round(-1 * (float(aData.bY) / 2 + float(aData.cY)) / 1000, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.tX) / 1000 / 2, 5)),
                               str(round(-1 * (float(aData.bY) / 2 + float(aData.cY)) / 1000, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.tX) / 1000 / 2, 5)),
                               str(round(float(aData.tY) * (-1) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round((float(aData.bX) / 2 - float(aData.cX)) / 1000, 5)),
                               str(round(float(aData.tY) * (-1) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round((float(aData.bX) /
                                          2 -
                                          float(aData.cX)) /
                                         1000, 5)), str(round(float(aData.tY) /
                                                              1000 /
                                                              2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.tX) / 1000 / 2, 5)),
                               str(round(float(aData.tY) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.tX) /
                                         1000 /
                                         2, 5)), str(round((float(aData.bY) /
                                                            2 -
                                                            float(aData.cY)) /
                                                           1000, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.tX) * (-1) / 1000 / 2, 5)),
                               str(round((float(aData.bY) / 2 - float(aData.cY)) / 1000, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(float(aData.tX) * (-1) / 1000 / 2, 5)),
                               str(round(float(aData.tY) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(-1 * (float(aData.bX) / 2 + float(aData.cX)) / 1000, 5)),
                               str(round(float(aData.tY) / 1000 / 2, 5))))
            self.fwrite.write('			%s, %s\n' %
                              (str(round(-1 * (float(aData.bX) / 2 + float(aData.cX)) / 1000, 5)),
                               str(round(float(aData.tY) * (-1) / 1000 / 2, 5))))
            self.fwrite.write('		End_Line\n')
            self.fwrite.write('	End_Shape\n')
            self.fwrite.write('\n')

        return section_area

    def __bars_circ__(self, aData):

        # Calculate bar coordinates for circular section
        radius = float(aData.diameter_circ) / 2000
        area_bar = str(
            round(math.pi * (float(aData.bar_diam_circ) / 2000)**2, 5))
        rein_rad = radius - float(aData.cover) / 1000 - float(
            aData.d_shear) / 1000 - float(aData.bar_diam_circ) / 2000
        angles = [i * 2 * math.pi / float(aData.num_bars_circ)
                  for i in range(int(aData.num_bars_circ))]
        rein_x = [str(round(rein_rad * math.cos(angles[i]), 5))
                  for i in range(int(aData.num_bars_circ))]
        rein_y = [str(round(rein_rad * math.sin(angles[i]), 5))
                  for i in range(int(aData.num_bars_circ))]

        # Round to remove excess digits
        rein_x = [str(round(float(i), 5)) for i in rein_x]
        rein_y = [str(round(float(i), 5)) for i in rein_y]

        # Return bar coordinates and area
        return (rein_x, rein_y), area_bar

    def __bars_rect_beam__(self, aData):

        # Calculate bar coordinates for rectangular section
        area_bar = [str(round(math.pi * (float(aData.db_t) / 1000)**2 / 4, 5))] *\
            int(aData.n_t)
        area_bar.extend([str(round(math.pi * (float(aData.db_b) / 1000)**2 / 4, 5))] *
                        int(aData.n_b))
        rein_xlt = [-(float(aData.rect_width) / 1000 / 2 - float(aData.cover) /
                      1000 - float(aData.db_t) / 1000 / 2 - 6 / 1000)]
        rein_xmt = [rein_xlt[0] + (-2 * rein_xlt[0]) / (int(aData.n_t) - 1) * i
                    for i in range(1, int(aData.n_t) - 1)]
        rein_xrt = [
            float(
                aData.rect_width) /
            1000 /
            2 -
            float(
                aData.cover) /
            1000 -
            float(
                aData.db_t) /
            1000 /
            2 -
            6 /
            1000]
        rein_xt = rein_xlt + rein_xmt + rein_xrt
        rein_xlb = [-(float(aData.rect_width) / 1000 / 2 - float(aData.cover) /
                      1000 - float(aData.db_b) / 1000 / 2 - 6 / 1000)]
        rein_xmb = [rein_xlb[0] + (-2 * rein_xlb[0]) / (int(aData.n_b) - 1) * i
                    for i in range(1, int(aData.n_b) - 1)]
        rein_xrb = [
            float(
                aData.rect_width) /
            1000 /
            2 -
            float(
                aData.cover) /
            1000 -
            float(
                aData.db_b) /
            1000 /
            2 -
            6 /
            1000]
        rein_xb = rein_xlb + rein_xmb + rein_xrb
        rein_x = rein_xt + rein_xb
        rein_yt = [float(aData.rect_height) / 1000 / 2 - float(aData.cover) / 1000 -
                   float(aData.db_t) / 1000 / 2 - 6 / 1000] * int(aData.n_t)
        rein_yb = [-(float(aData.rect_height) / 1000 / 2 - float(aData.cover) /
                     1000 - float(aData.db_b) / 1000 / 2 - 6 / 1000)] * int(aData.n_b)
        rein_y = rein_yt + rein_yb
        rein_y = [str(i) for i in rein_y]

        # Round to remove excess digits
        rein_x = [str(round(float(i), 5)) for i in rein_x]
        rein_y = [str(round(float(i), 5)) for i in rein_y]

        # Return bar coordinates and area
        return (rein_x, rein_y), area_bar

    def __bars_rect_col__(self, aData):

        # Check that rebar and cover dimensions are reasonable
        if float(aData.cover) / 1000 + float(aData.bar_diam_col) / \
                1000 >= min(float(aData.rect_height) / 1000, float(aData.rect_width) / 1000):
            raise AssertionError(
                "Rebar diameter too large for given section geometry.")

        # Calculate bar coordinates for rectangular section
        area_bar = [str(round(math.pi * (float(aData.bar_diam_col) / 2000)**2, 5))] *\
            int(aData.num_bars_col)
        rein_xl = -(float(aData.rect_width) / 1000 / 2 - float(aData.cover) / 1000 -
                    float(aData.bar_diam_col) / 1000 / 2)
        rein_xr = float(aData.rect_width) / 1000 / 2 - float(aData.cover) / \
            1000 - float(aData.bar_diam_col) / 1000 / 2

        if str(aData.num_bars_col) == '8':
            rein_xm = rein_xl + (rein_xr - rein_xl) / 2
            rein_x = [rein_xl, rein_xm, rein_xr, rein_xl,
                      rein_xr, rein_xl, rein_xm, rein_xr]
        elif str(aData.num_bars_col) == '4':
            rein_x = [rein_xl, rein_xr, rein_xl, rein_xr]
        elif str(aData.num_bars_col) == '6':
            rein_x = [rein_xl, rein_xl, rein_xl,
                      rein_xr, rein_xr, rein_xr]
        elif str(aData.num_bars_col) == '10':
            xSpace = (rein_xr - rein_xl) / 4
            rein_x = [rein_xl, rein_xl + xSpace, 0, rein_xr - xSpace, rein_xr,
                      rein_xl, rein_xl + xSpace, 0, rein_xr - xSpace, rein_xr]
        elif str(aData.num_bars_col) == '12':
            xSpace = (rein_xr - rein_xl) / 3
            rein_x = [rein_xl, rein_xl + xSpace, rein_xr - xSpace, rein_xr,
                      rein_xl, rein_xr, rein_xl, rein_xr,
                      rein_xl, rein_xl + xSpace, rein_xr - xSpace, rein_xr]
        elif str(aData.num_bars_col) == '14':
            xSpace = (rein_xr - rein_xl) / 3
            rein_x = [rein_xl, rein_xl + xSpace, rein_xr - xSpace, rein_xr,
                      rein_xl, rein_xr, rein_xl, rein_xr, rein_xl, rein_xr,
                      rein_xl, rein_xl + xSpace, rein_xr - xSpace, rein_xr]

        rein_yt = float(aData.rect_height) / 1000 / 2 - float(aData.cover) / 1000 -\
            float(aData.bar_diam_col) / 1000 / 2
        rein_yb = -(float(aData.rect_height) / 1000 / 2 -
                    float(aData.cover) / 1000 - float(aData.bar_diam_col) / 1000 / 2)

        if str(aData.num_bars_col) == '8':
            rein_ym = rein_yb + (rein_yt - rein_yb) / 2
            rein_y = [rein_yt, rein_yt, rein_yt, rein_ym,
                      rein_ym, rein_yb, rein_yb, rein_yb]
        elif str(aData.num_bars_col) == '4':
            rein_y = [rein_yt, rein_yt, rein_yb, rein_yb]
        elif str(aData.num_bars_col) == '6':
            # middle reinforcement y-axis position for 6 bars
            rein_ym = 0.0
            rein_y = [rein_yt, rein_ym, rein_yb,
                      rein_yt, rein_ym, rein_yb]
        elif str(aData.num_bars_col) == '10':
            rein_y = [rein_yt, rein_yt, rein_yt, rein_yt, rein_yt,
                      rein_yb, rein_yb, rein_yb, rein_yb, rein_yb]
        elif str(aData.num_bars_col) == '12':
            ySpace = (rein_yt - rein_yb) / 3
            rein_y = [rein_yt, rein_yt, rein_yt, rein_yt,
                      rein_yt - ySpace, rein_yt - ySpace,
                      rein_yb + ySpace, rein_yb + ySpace,
                      rein_yb, rein_yb, rein_yb, rein_yb]
        elif str(aData.num_bars_col) == '14':
            rein_ym = 0.0
            ySpace = (rein_yt - rein_yb) / 4
            rein_y = [rein_yt, rein_yt, rein_yt, rein_yt,
                      rein_yt - ySpace, rein_yt - ySpace,
                      rein_ym, rein_ym,
                      rein_yb + ySpace, rein_yb + ySpace,
                      rein_yb, rein_yb, rein_yb, rein_yb]

        # Round to remove excess digis
        rein_x = [str(round(float(i), 5)) for i in rein_x]
        rein_y = [str(round(float(i), 5)) for i in rein_y]

        # Return bar coordinates and area
        return (rein_x, rein_y), area_bar

    def __bars_t_beam__(self, aData):

        # Calculate bar coordinates for T beam section
        area_bar = [str(round(math.pi * (float(aData.t_tbar) / 1000)**2 / 4, 5))] *\
            int(aData.t_nt) + [str(round(math.pi *
                                         (float(aData.t_bbar) / 1000)**2 / 4, 5))] * int(aData.t_nb) +\
            [str(round(math.pi * (float(aData.f_bar) / 1000)**2 / 4, 5))] *\
            int(int((float(aData.f_width) / 2000 - float(aData.t_width) / 2000) /
                    float(aData.f_spac) / 1000) * (float(aData.f_lay) / 1000) * 2)

        # Calculate reinforcement layout for the web
        rein_xtl = -(float(aData.t_width) / 1000 / 2 - float(aData.cover) /
                     1000 - float(aData.t_tbar) / 1000 / 2 - 6 / 1000)
        rein_xtr = float(aData.t_width) / 1000 / 2 - float(aData.cover) / \
            1000 - float(aData.t_tbar) / 1000 / 2 - 6 / 1000
        rein_xtm = [rein_xtl + (-2 * rein_xtl) / (int(aData.t_nt) - 1) * i
                    for i in range(1, int(aData.t_nt) - 1)]
        rein_xt = [rein_xtl] + rein_xtm + [rein_xtr]
        rein_xbl = -(float(aData.t_width) / 1000 / 2 - float(aData.cover) /
                     1000 - float(aData.t_bbar) / 1000 / 2 - 6 / 1000)
        rein_xbr = float(aData.t_width) / 1000 / 2 - float(aData.cover) / \
            1000 - float(aData.t_bbar) / 1000 / 2 - 6 / 1000
        rein_xbm = [rein_xbl + (-2 * rein_xbl) / (int(aData.t_nb) - 1) * i
                    for i in range(1, int(aData.t_nb) - 1)]
        rein_xb = [rein_xbl] + rein_xbm + [rein_xbr]
        rein_xw = rein_xt + rein_xb
        rein_yt = [float(aData.t_height) / 1000 / 2 - float(aData.cover) / 1000 -
                   float(aData.t_tbar) / 1000 / 2 - 6 / 1000] * int(aData.t_nt)
        rein_yb = [-(float(aData.t_height) / 1000 / 2 - float(aData.cover) / 1000 -
                     float(aData.t_bbar) / 1000 / 2 - 6 / 1000)] * int(aData.t_nb)
        rein_yw = rein_yt + rein_yb

        # Calculate reinforcement layout for the flanges
        n_barf = int(round((float(aData.f_width) /
                            1000 /
                            2 -
                            float(aData.t_width) /
                            1000 /
                            2) /
                           (float(aData.f_spac) /
                            1000), 0))
        if n_barf == 1:
            rein_flx = [(-float(aData.f_width) / 1000 / 2 -
                         float(aData.t_width) / 1000 / 2) / 2]
            rein_frx = [(float(aData.f_width) / 1000 / 2 +
                         float(aData.t_width) / 1000 / 2) / 2]
        else:
            s_barf = (float(aData.f_width) / 1000 / 2 -
                      float(aData.t_width) / 1000 / 2) / (n_barf)
            rein_flx = [-float(aData.f_width) / 1000 / 2 + s_barf / 2]
            rein_frx = [float(aData.f_width) / 1000 / 2 - s_barf / 2]
            for i in range(n_barf - 1):
                rein_flx.append(round(-float(aData.f_width) / 1000 / 2 +
                                      s_barf / 2 + s_barf * (i + 1), 1))
                rein_frx.append(round(float(aData.f_width) / 1000 / 2 -
                                      s_barf / 2 - s_barf * (i + 1), 1))
        if int(aData.f_lay) == 1:
            rein_fyt = []  # [float(aData.t_height) - float(aData.f_thick)]
            rein_fyb = [float(aData.t_height) / 1000 / 2 -
                        float(aData.f_thick) / 1000 / 2] * n_barf
            rein_fx = rein_flx + rein_frx
        elif int(aData.f_lay) == 2:
            rein_fyt = [float(aData.t_height) / 1000 / 2 - float(aData.cover) /
                        1000 - float(aData.f_bar) / 1000 / 2 - 6 / 1000] * n_barf
            rein_fyb = [float(aData.t_height) / 1000 / 2 - float(aData.f_thick) / 1000 + float(
                aData.cover) / 1000 + float(aData.f_bar) / 1000 / 2 + 6 / 1000] * n_barf
            rein_fx = rein_flx + rein_frx + rein_flx + rein_frx
        else:
            raise AssertionError("Error: Please select either 1 or 2 layers.")

        rein_fy = rein_fyt + rein_fyt + rein_fyb + rein_fyb

        # Combine reinforcement coordinate data
        rein_x = rein_xw + rein_fx
        rein_y = rein_yw + rein_fy

        # Round to remove excess digits
        rein_x = [str(round(float(i), 5)) for i in rein_x]
        rein_y = [str(round(float(i), 5)) for i in rein_y]

        # Return bar coordinates and area
        return (rein_x, rein_y), area_bar

    def __bars_cruciform__(self, aData):

        # Check that rebar and cover dimensions are reasonable
        if float(aData.cover) / 1000 + float(aData.cBar_rows[1]) * max(float(aData.cBar_vFlangeD),
                                                                       float(aData.cBar_centerD)) / 1000 >= float(aData.tX) / 1000 or \
                float(aData.cover) / 1000 + float(aData.cBar_rows[0]) *\
                max(float(aData.cBar_hFlangeD), float(aData.cBar_centerD)) / 1000\
                >= float(aData.tY) / 1000:
            raise AssertionError(
                "Rebar diameter too large for given section geometry!")
        if int(aData.cBar_rows[1]) <= 0 or int(aData.cBar_rows[0]) <= 0:
            raise AssertionError(
                "Number of rebar rows cannot be less than 2 in either direction for cruciform sections!")
        if min(int(aData.cBar_vFlangeN), int(aData.cBar_hFlangeN)) < 4 or int(
                aData.cBar_vFlangeN) % 2 != 0 or int(aData.cBar_hFlangeN) % 2 != 0:
            raise AssertionError(
                "Total of rebars in each flange of a cruciform must be an even number greater than 4!")

        ### Calculate bar areas, spacings, associated coordinates ###
        # Areas
        aBar_vFlange = [str(round(math.pi * (float(aData.cBar_vFlangeD) / 2000)**2, 5))] *\
            int(aData.cBar_vFlangeN)
        aBar_hFlange = [str(round(math.pi * (float(aData.cBar_hFlangeD) / 2000)**2, 5))] *\
            int(aData.cBar_hFlangeN)
        nBar_center = int(aData.cBar_rows[0]) * int(aData.cBar_rows[1])
        aBar_center = [
            str(round(math.pi * (float(aData.cBar_centerD) / 2000)**2, 5))] * nBar_center

        # Spacings
        spacingH_vFlange = ((float(aData.tX) - 2 * float(aData.cover) -
                             float(aData.cBar_vFlangeD)) / 1000) / (int(aData.cBar_rows[1]) - 1)
        spacingV_hFlange = ((float(aData.tY) - 2 * float(aData.cover) -
                             float(aData.cBar_hFlangeD)) / 1000) / (int(aData.cBar_rows[0]) - 1)
        nRows_vFlange = int(float(aData.cBar_vFlangeN)) / \
            (int(aData.cBar_rows[1]))
        nRows_hFlange = int(float(aData.cBar_hFlangeN)) / \
            (int(aData.cBar_rows[0]))
        spacingV_vFlange = (float(aData.bY) - float(aData.tY) -
                            2 * float(aData.cover)) / (1000 * nRows_vFlange)
        spacingH_hFlange = (float(aData.bX) - float(aData.tX) -
                            2 * float(aData.cover)) / (1000 * nRows_hFlange)

        # Coordinates
        rein_vFlange_x = [round(-(float(aData.tX) / 2 - float(aData.cover) - float(aData.cBar_vFlangeD) / 2) /
                                1000 + i * spacingH_vFlange, 5) for i in range(0, int(aData.cBar_rows[1]))]
        rein_vFlange_y = [
            round(
                ((float(
                    aData.bY) /
                    2 -
                    float(
                    aData.cover) -
                    float(
                    aData.cY) -
                    float(
                    aData.cBar_vFlangeD) /
                    2) /
                    1000) -
                i *
                spacingV_vFlange,
                5) for i in range(
                0,
                int(nRows_vFlange))]
        for i in range(0, len(rein_vFlange_y)):
            if i + 1 > len(rein_vFlange_y) / 2:
                rein_vFlange_y[i] = -1 * rein_vFlange_y[int(
                    i - len(rein_vFlange_y) / 2)] - 2 * float(aData.cY) / 1000

        rein_hFlange_y = [round(-(float(aData.tY) / 2 - float(aData.cover) - float(aData.cBar_hFlangeD) / 2) /
                                1000 + i * spacingV_hFlange, 5) for i in range(0, int(aData.cBar_rows[0]))]
        rein_hFlange_x = [round(-((float(aData.bX) / 2 - float(aData.cover) + float(aData.cX) - float(
            aData.cBar_hFlangeD) / 2) / 1000) + i * spacingH_hFlange, 5) for i in range(0, int(nRows_hFlange))]
        for i in range(0, len(rein_hFlange_x)):
            if i + 1 > len(rein_hFlange_x) / 2:
                rein_hFlange_x[i] = -1 * rein_hFlange_x[int(
                    i - len(rein_hFlange_x) / 2)] - 2 * float(aData.cX) / 1000

        # Combine data
        rein_hFlange_xF = [rein_hFlange_x for i in range(
            0, int(aData.cBar_rows[0]))]
        rein_center_xF = [rein_vFlange_x for i in range(
            0, int(aData.cBar_rows[0]))]
        rein_vFlange_xF = [
            rein_vFlange_x for i in range(0, int(nRows_vFlange))]
        rein_hFlange_yF = [
            rein_hFlange_y for i in range(0, int(nRows_hFlange))]
        rein_center_yF = [rein_hFlange_y for i in range(
            0, int(aData.cBar_rows[1]))]
        rein_vFlange_yF = [rein_vFlange_y for i in range(
            0, int(aData.cBar_rows[1]))]
        rein_x = sorted(sum(rein_hFlange_xF, [])) + \
            sorted(sum(rein_center_xF, [])) + sorted(sum(rein_vFlange_xF, []))
        rein_y = sum(rein_hFlange_yF, []) + \
            sum(rein_center_yF, []) + sum(rein_vFlange_yF, [])

        # Assign areas to each bar
#        area_bar = [aBar_hFlange for i in range(0,int(aData.cBar_hFlangeN))] + [aBar_center for i in range(0,nBar_center)]  + [aBar_vFlange for i in range(0,int(aData.cBar_vFlangeN))]
        area_bar = aBar_hFlange + aBar_center + aBar_vFlange

        # Round to remove excess digits
        rein_x = [str(round(float(i), 5)) for i in rein_x]
        rein_y = [str(round(float(i), 5)) for i in rein_y]

        # Return bar coordinates and area
        return (rein_x, rein_y), area_bar

    def __bars__(self, aData, prestress='0'):

        # Write section bars for circular section
        if aData.section_type == 'Circular':
            self.fwrite.write('	Begin_Rebar\n')
            rein, area_bar = self.__bars_circ__(aData)
            for i in range(int(aData.num_bars_circ)):
                self.fwrite.write('		%s, %s, %s, %s, %s\n' %
                                  (rein[0][i], rein[1][i], area_bar,
                                   prestress, aData.material_steel))
            self.fwrite.write('	End_Rebar\n')
            self.fwrite.write('\n')

        # Write section bars for rectangular beam section
        elif aData.section_type == 'Rectangular Beam':
            self.fwrite.write('	Begin_Rebar\n')
            rein, area_bar = self.__bars_rect_beam__(aData)
            for i in range(int(aData.n_t) + int(aData.n_b)):
                self.fwrite.write('		%s, %s, %s, %s, %s\n' %
                                  (rein[0][i], rein[1][i], area_bar[i],
                                   prestress, aData.material_steel))
            self.fwrite.write('	End_Rebar\n')
            self.fwrite.write('\n')

        # Write section bars for rectangular column section
        elif aData.section_type == 'Rectangular Column':
            self.fwrite.write('	Begin_Rebar\n')
            rein, area_bar = self.__bars_rect_col__(aData)
            for i in range(int(aData.num_bars_col)):
                self.fwrite.write('		%s, %s, %s, %s, %s\n' %
                                  (rein[0][i], rein[1][i], area_bar[i],
                                   prestress, aData.material_steel))
            self.fwrite.write('	End_Rebar\n')
            self.fwrite.write('\n')

        # Write section bars for T beam section
        elif aData.section_type == 'T Beam':
            self.fwrite.write('	Begin_Rebar\n')
            rein, area_bar = self.__bars_t_beam__(aData)
            t_fb = (int((float(aData.f_width) /
                         1000 /
                         2 -
                         float(aData.t_width) /
                         1000 /
                         2) /
                        float(aData.f_spac) /
                        1000) *
                    float(aData.f_lay) /
                    1000 *
                    2)
            for i in range(int(int(aData.t_nt) + int(aData.t_nb) + t_fb)):
                self.fwrite.write('		%s, %s, %s, %s, %s\n' %
                                  (rein[0][i], rein[1][i], area_bar[i],
                                   prestress, aData.material_steel))
            self.fwrite.write('	End_Rebar\n')
            self.fwrite.write('\n')

        # Write section bars for Cruciform section
        elif aData.section_type == 'Cruciform':
            self.fwrite.write('	Begin_Rebar\n')
            rein, area_bar = self.__bars_cruciform__(aData)
            for i in range(0, len(area_bar)):
                self.fwrite.write('		%s, %s, %s, %s, %s\n' %
                                  (rein[0][i], rein[1][i], area_bar[i],
                                   prestress, aData.material_steel))
            self.fwrite.write('	End_Rebar\n')
            self.fwrite.write('\n')

    def __load__(
            self,
            aData,
            concrete_strainlim,
            steel_strainlim,
            laststrain=False,
            mphimethod='BiSection'):

        # Convert axial load from kN to N
        sN_load = str(1000 * float(aData.N_load))

        # Write P-M Interaction load case on the x-axis
        self.fwrite.write('	Begin_Loading\n')
        self.fwrite.write('		NAME = PM_load_X\n')
        self.fwrite.write('		TYPE = PM Interaction\n')
        if not aData.showPlots:
            self.fwrite.write('		Include_Graph = False\n')
            self.fwrite.write('		Include_Animation = False\n')
        self.fwrite.write('		N_PM_Points = 100\n')
        self.fwrite.write('		Full_PM_Diagram = True\n')
        self.fwrite.write('		Generate_Code_PM_Diagram = True\n')
        self.fwrite.write('		Include_PM_Curve_Fit = True\n')
        self.fwrite.write('		Angle_of_Loading = 0\n')
        self.fwrite.write('		Axial0 = 0\n')
        self.fwrite.write('		Axial1 = 0\n')
        self.fwrite.write('		Axial_Cap = 0\n')
        self.fwrite.write('		AxialR0 = 0\n')
        self.fwrite.write('		AxialR1 = 0\n')
        self.fwrite.write('		Moment0 = 0\n')
        self.fwrite.write('		Moment1 = 0\n')
        self.fwrite.write('		Moment2 = 0\n')
        self.fwrite.write('		Angle_of_Loading = 0\n')
        self.fwrite.write('\n')
        self.fwrite.write('		Begin_LimitStrains\n')
        self.fwrite.write('		' + aData.mat_name_unc + ', -' +
                          str(concrete_strainlim) + ', 1\n')  # limiting strain
        self.fwrite.write('		' + aData.mat_name_steel +
                          ', -1, ' + str(aData.esy * steel_strainlim) + '\n')
        self.fwrite.write('		' + aData.mat_name_conc +
                          ', -' + str(concrete_strainlim) + ', 1\n')
        self.fwrite.write('		End_LimitStrains\n')
        self.fwrite.write('\n')
        self.fwrite.write('		Begin_LoadUserComments\n')
        self.fwrite.write('		User Comments \n')
        self.fwrite.write('		End_LoadUserComments\n')
        self.fwrite.write('	End_Loading\n')
        self.fwrite.write('\n')

        # Write P-M Interaction load case on the y-axis
        self.fwrite.write('	Begin_Loading\n')
        self.fwrite.write('		NAME = PM_load_Y\n')
        self.fwrite.write('		TYPE = PM Interaction\n')
        if not aData.showPlots:
            self.fwrite.write('		Include_Graph = False\n')
            self.fwrite.write('		Include_Animation = False\n')
        self.fwrite.write('		N_PM_Points = 100\n')
        self.fwrite.write('		Full_PM_Diagram = True\n')
        self.fwrite.write('		Generate_Code_PM_Diagram = True\n')
        self.fwrite.write('		Include_PM_Curve_Fit = True\n')
        self.fwrite.write('		Angle_of_Loading = 90\n')
        self.fwrite.write('		Axial0 = 0\n')
        self.fwrite.write('		Axial1 = 0\n')
        self.fwrite.write('		Axial_Cap = 0\n')
        self.fwrite.write('		AxialR0 = 0\n')
        self.fwrite.write('		AxialR1 = 0\n')
        self.fwrite.write('		Moment0 = 0\n')
        self.fwrite.write('		Moment1 = 0\n')
        self.fwrite.write('		Moment2 = 0\n')
        self.fwrite.write('		Angle_of_Loading = 0\n')
        self.fwrite.write('\n')
        self.fwrite.write('		Begin_LimitStrains\n')
        self.fwrite.write('		' + aData.mat_name_unc + ', -' +
                          str(concrete_strainlim) + ', 1\n')  # limiting strain
        self.fwrite.write('		' + aData.mat_name_steel +
                          ', -1, ' + str(aData.esy * steel_strainlim) + '\n')
        self.fwrite.write('		' + aData.mat_name_conc +
                          ', -' + str(concrete_strainlim) + ', 1\n')
        self.fwrite.write('		End_LimitStrains\n')
        self.fwrite.write('\n')
        self.fwrite.write('		Begin_LoadUserComments\n')
        self.fwrite.write('		User Comments \n')
        self.fwrite.write('		End_LoadUserComments\n')
        self.fwrite.write('	End_Loading\n')
        self.fwrite.write('\n')

        if laststrain:
            # Write M-φ Interaction load case on the x-axis
            self.fwrite.write('	Begin_Loading\n')
            self.fwrite.write('		NAME = M-phi_Load_X\n')
            self.fwrite.write('		TYPE = Moment Curvature\n')
            if not aData.showPlots:
                self.fwrite.write('		Include_Graph = False\n')
                self.fwrite.write('		Include_Animation = False\n')
            self.fwrite.write('		ConstAxial = -%s\n' % sN_load)
            self.fwrite.write('		IncMxx = 113.0\n')
            self.fwrite.write('		Use_Best_Fit = True\n')
            self.fwrite.write('		Calc_Moment_Rot = False\n')
            self.fwrite.write('		Method = %s\n' % mphimethod)
            self.fwrite.write('		N_Steps_Before_Yield = 10\n')
            self.fwrite.write('		N_Steps_After_Yield = 20\n')
            self.fwrite.write('		Multiple_On_First_Yield = 2\n')
            self.fwrite.write('		BS_Tol = 4448\n')
            self.fwrite.write('		BS_Max_Itter = 40\n')
            self.fwrite.write('	End_Loading\n')

            # Write M-φ Interaction load case on the y-axis
            self.fwrite.write('	Begin_Loading\n')
            self.fwrite.write('		NAME = M-phi_Load_Y\n')
            self.fwrite.write('		TYPE = Moment Curvature\n')
            if not aData.showPlots:
                self.fwrite.write('		Include_Graph = False\n')
                self.fwrite.write('		Include_Animation = False\n')
            self.fwrite.write('		ConstAxial = -%s\n' % sN_load)
            self.fwrite.write('		IncMyy = 113.0\n')
            self.fwrite.write('		Use_Best_Fit = True\n')
            self.fwrite.write('		Calc_Moment_Rot = False\n')
            self.fwrite.write('		Method = %s\n' % mphimethod)
            self.fwrite.write('		N_Steps_Before_Yield = 10\n')
            self.fwrite.write('		N_Steps_After_Yield = 20\n')
            self.fwrite.write('		Multiple_On_First_Yield = 2\n')
            self.fwrite.write('		BS_Tol = 4448\n')
            self.fwrite.write('		BS_Max_Itter = 40\n')
            self.fwrite.write('	End_Loading\n')

        # Close section definition
        self.fwrite.write('End_Section\n')
        self.fwrite.write(
            '#---------------------------------------------------------------------\n')

    def __close__(self):

        # Close file handle
        self.fwrite.close()

    # This will now take a vector of strain limits
    def write_EnvelopeXtract(
            self,
            aData,
            concrete_strainlim,
            steel_strainlim,
            mphimethod='BiSection'):

        # Write input XTRACT file
        self.__intro__(aData)
        self.__global_params__(aData)
        self.__mater_conu__(aData)
        self.__mater_conc__(aData)
        self.__mater_ste__(aData)
        print('   Strain limits considered:')
        instance = 1
        for j in range(0, len(steel_strainlim)):
            for i in range(0, len(concrete_strainlim)):
                print('         ' + str(instance) +
                      ' - Concrete = ' + str(concrete_strainlim[i]))
                print('         ' + str(instance) + ' - Steel = ' +
                      str(float(aData.esy) * steel_strainlim[j]))
                instance = instance + 1
                laststrain = (bool(i == len(concrete_strainlim) - 1)
                              and bool(j == len(steel_strainlim) - 1))
                section_area = self.__sect__(
                    aData, concrete_strainlim[i], steel_strainlim[j])
                self.__bars__(aData)
                self.__load__(
                    aData,
                    concrete_strainlim[i],
                    steel_strainlim[j],
                    laststrain,
                    mphimethod)
        self.__close__()
        return section_area
