A Numerical Approach to the Simplified Laminate Theory of Composite Materials: The Composite Laminate Analysis Tool―CLAT 1D (Advanced Structured Materials, 202) [1st ed. 2024] 3031479831, 9783031479830

A typical approach to treat composite materials, which are composed of layered unidirectional lamina, is the so-called c

107 51 6MB

English Pages 158 Year 2024

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

A Numerical Approach to the Simplified Laminate Theory of Composite Materials: The Composite Laminate Analysis Tool―CLAT 1D (Advanced Structured Materials, 202) [1st ed. 2024]
 3031479831, 9783031479830

Table of contents :
Preface
Contents
Symbols and Abbreviations
Latin Symbols
Latin Symbols
Latin Numbers
Greek Symbols
Mathematical Symbols
Indices, Superscripted
Indices, Subscripted
Abbreviations
1 Introduction
References
2 Simplified Laminate Theory
2.1 Introduction
2.2 Bar Elements
2.2.1 Kinematics
2.2.2 Constitutive Equation
2.2.3 Equilibrium
2.2.4 Differential Equation
2.3 Euler–Bernoulli Beam Elements
2.3.1 Kinematics
2.3.2 Constitutive Equation
2.3.3 Equilibrium
2.3.4 Differential Equation
2.4 Combination of Bar and Beam Elements
2.4.1 Kinematics
2.4.2 Constitutive Equation
2.4.3 Equilibrium
2.4.4 Differential Equations
2.5 Failure Criteria
2.5.1 Maximum Stress Criterion
2.5.2 Maximum Strain Criterion
2.5.3 Tsai-Hill Criterion
2.5.4 Tsai-Wu Criterion
2.6 Simplified Classical Laminate Theory for One-Dimensional Elements
2.6.1 Introduction
2.6.2 Generalized Stress-Strain Relationship
2.6.3 Failure Analysis
References
3 Composite Laminate Analysis Tool—CLAT 1D
3.1 Programming Approach
3.2 Graphical Appearance, Functionality, and Operation
References
4 Application Examples
4.1 Introduction
4.2 Problem 1: Stresses and Strains in a Symmetric Laminate
4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate
4.4 Problem 3: Failure Criteria
4.5 Problem 4: Ply-By-Ply Failure Loads
References
5 Source Codes
5.1 main.py
5.2 Laminates_classes.py
5.3 globalVars.py
5.4 CLATHelpModule.py
5.5 requirements.txt
Index

Citation preview

Advanced Structured Materials

Andreas Öchsner Resam Makvandi

A Numerical Approach to the Simplified Laminate Theory of Composite Materials The Composite Laminate Analysis Tool— CLAT 1D

Advanced Structured Materials Volume 202

Series Editors Andreas Öchsner, Faculty of Mechanical and Systems Engineering, Esslingen University of Applied Sciences, Esslingen, Germany Lucas F. M. da Silva, Department of Mechanical Engineering, Faculty of Engineering, University of Porto, Porto, Portugal Holm Altenbach , Faculty of Mechanical Engineering, Otto von Guericke University Magdeburg, Magdeburg, Sachsen-Anhalt, Germany

Common engineering materials are reaching their limits in many applications, and new developments are required to meet the increasing demands on engineering materials. The performance of materials can be improved by combining different materials to achieve better properties than with a single constituent, or by shaping the material or constituents into a specific structure. The interaction between material and structure can occur at different length scales, such as the micro, meso, or macro scale, and offers potential applications in very different fields. This book series addresses the fundamental relationships between materials and their structure on overall properties (e.g., mechanical, thermal, chemical, electrical, or magnetic properties, etc.). Experimental data and procedures are presented, as well as methods for modeling structures and materials using numerical and analytical approaches. In addition, the series shows how these materials engineering and design processes are implemented and how new technologies can be used to optimize materials and processes. Advanced Structured Materials is indexed in Google Scholar and Scopus.

Andreas Öchsner · Resam Makvandi

A Numerical Approach to the Simplified Laminate Theory of Composite Materials The Composite Laminate Analysis Tool—CLAT 1D

Andreas Öchsner Faculty of Mechanical and Systems Engineering Esslingen University of Applied Science Esslingen am Neckar, Baden-Württemberg Germany

Resam Makvandi Stuttgart, Germany

ISSN 1869-8433 ISSN 1869-8441 (electronic) Advanced Structured Materials ISBN 978-3-031-47983-0 ISBN 978-3-031-47984-7 (eBook) https://doi.org/10.1007/978-3-031-47984-7 © The Editor(s) (if applicable) and The Author(s), under exclusive license to Springer Nature Switzerland AG 2024 This work is subject to copyright. All rights are solely and exclusively licensed by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed. The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication does not imply, even in the absence of a specific statement, that such names are exempt from the relevant protective laws and regulations and therefore free for general use. The publisher, the authors, and the editors are safe to assume that the advice and information in this book are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or the editors give a warranty, expressed or implied, with respect to the material contained herein or for any errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional claims in published maps and institutional affiliations. This Springer imprint is published by the registered company Springer Nature Switzerland AG The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland Paper in this product is recyclable.

Preface

Composite materials, especially fiber-reinforced composites, are gaining increasing importance since they can overcome the limits of many structures based on classical engineering materials. Particularly the combination of a matrix with fibers provides far better properties than the single constituents alone. Despite their importance, many engineering degree programs do not treat the mechanical behavior of this class of advanced structured materials in detail. Thus, some engineers are not able to thoroughly apply and introduce these modern engineering materials in their design process. A typical approach to treat composite materials, which are composed of layered unidirectional lamina, is the so-called classical laminate theory (CLT). This theory is based on the theory for plane elasticity elements and classical (shear-rigid) plate elements under the assumption of orthotropic constitutive equations. The solution of the fundamental equations of the classical laminate theory is connected with extensive matrix operations and many problems require additional iteration loops. This two-dimensional approach and the underlying advanced continuum mechanical modeling might be very challenging for some students, particularly at universities of applied sciences. Thus, a reduced approach, the so-called simplified classical laminate theory (SCLT), has been recently proposed. The idea was to use solely isotropic one-dimensional elements, i.e., a superposition of bar and beam elements, to introduce the major calculation steps of the classical laminate theory. Understanding this simplified theory is much easier and the final step is to highlight the differences when moving to the general two-dimensional case. This monograph first provides a systematic and thorough introduction to the simplified laminate theory based on the theory for bars and classical beam plate elements. The focus is on the stacking of isotropic layers to simplified laminates. In addition to the elastic behavior, failure is investigated based on the maximum stress, maximum strain, Tsai-Hill, and the Tsai-Wu criteria.

v

vi

Preface

We provide a Python-based computational tool, the so-called Composite Laminate Analysis Tool (CLAT 1D) to easily solve some standard questions from the context of fiber-reinforced composites. The tool runs in any standard web browser and offers a user-friendly interface with many post-processing options. The functionality comprises stress and strain analysis of simplified lamina and laminates and the failure analysis based on different criteria. We look forward to receiving some comments and suggestions for the next release of CLAT 1D and the edition of this textbook. Esslingen am Neckar, Germany Stuttgart, Germany August 2023

Andreas Öchsner Resam Makvandi

Contents

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 5

2 Simplified Laminate Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Bar Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 Kinematics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.2 Constitutive Equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.3 Equilibrium . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.4 Differential Equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Euler–Bernoulli Beam Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1 Kinematics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.2 Constitutive Equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.3 Equilibrium . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.4 Differential Equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Combination of Bar and Beam Elements . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 Kinematics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.2 Constitutive Equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.3 Equilibrium . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.4 Differential Equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 Failure Criteria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 Maximum Stress Criterion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.2 Maximum Strain Criterion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.3 Tsai-Hill Criterion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.4 Tsai-Wu Criterion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6 Simplified Classical Laminate Theory for One-Dimensional Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6.2 Generalized Stress-Strain Relationship . . . . . . . . . . . . . . . . . . 2.6.3 Failure Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 7 11 11 13 13 15 17 17 23 26 29 30 30 32 32 35 37 37 37 37 38 38 38 39 42 43

vii

viii

Contents

3 Composite Laminate Analysis Tool—CLAT 1D . . . . . . . . . . . . . . . . . . . 3.1 Programming Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Graphical Appearance, Functionality, and Operation . . . . . . . . . . . . . References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

45 45 46 52

4 Application Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Problem 1: Stresses and Strains in a Symmetric Laminate . . . . . . . . 4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate . . . . . . 4.4 Problem 3: Failure Criteria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5 Problem 4: Ply-By-Ply Failure Loads . . . . . . . . . . . . . . . . . . . . . . . . . . References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53 53 53 65 76 84 88

5 Source Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 5.1 main.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 5.2 Laminates_classes.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 5.3 globalVars.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 5.4 CLATHelpModule.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 5.5 requirements.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

Symbols and Abbreviations

Latin Symbols A A, A A A, B B, B B B, C C C C C* D D, D D D, E F G I L M M N N

Area, cross-sectional area, matrix element of generalized elasticity matrix Matrix element of the inverted generalized elasticity matrix Matrix element Submatrix of the generalized elasticity matrix Submatrix of the inverted generalized elasticity matrix Matrix element of generalized elasticity matrix Matrix element of inverted generalized elasticity matrix Matrix element Submatrix of the generalized elasticity matrix Submatrix of the inverted generalized elasticity matrix Diameter, elasticity constant Element of the transformed elasticity matrix (to the 1-2 system) Elasticity matrix Transformed elasticity matrix (to the 1-2 system) Generalized elasticity matrix Bending stiffness matrix element of generalized elasticity matrix Matrix element of the inverted generalized elasticity matrix Matrix element Elastic compliance matrix submatrix of the generalized elasticity matrix Submatrix of the inverted generalized elasticity matrix Young’s modulus Force Shear modulus Second moment of area Element length Moment Column matrix of internal moments Normal force (internal) Column matrix of internal normal forces ix

x

Q R T U

Symbols and Abbreviations

Shear force (internal) Radius, radius of curvature, strength ratio Transformation matrix Perimeter

Latin Symbols a b e f h k m n n p q q s s t t u u x y z

Geometric dimension (width), coefficient Volume-specific load, geometric dimension Column matrix of generalized strains Body force Geometric dimension Elastic embedding modulus, elastic foundation modulus, strength value Distributed moment Total number of layers Normal vector Distributed load in x-direction Distributed load in y-direction Column matrix of distributed loads Length Column matrix of generalized stresses Geometric dimension (height), traction force Tangential vector Displacement Column matrix of displacements Cartesian coordinate Cartesian coordinate Cartesian coordinate

Latin Numbers 1 2 3

Cartesian coordinate Cartesian coordinate Cartesian coordinate

Symbols and Abbreviations

Greek Symbols α U ε ε0 ε0 ε κ κ σ σ ϕ

Rotation angle Shear strain (engineering definition) Normal strain Normal strain in neutral fiber Column matrix of strains in neutral fiber Column matrix of strain components Curvature Column matrix of curvatures Stress, normal stress Column matrix of stress components Rotation

Mathematical Symbols d…

d(... ) dx

L{. . . } L (…)T |…|

Differential quantity First order derivative with respect to the x-axis Differential operator Matrix of differential operators Transpose Absolute value

Indices, Superscripted …n …ε

Normalized (length-specific) Strain related

Indices, Subscripted …c …k …sym …t …ε …σ

Compression Layer number Symmetric Tensile Strain related Stress related

xi

xii

Symbols and Abbreviations

Abbreviations 1D 2D BEM CLT FDM FEM FVM Mat PDE SCLT

One-dimensional Two-dimensional Boundary element method Classical laminate theory Finite difference method Finite element method Finite volume method Material Partial differential equation Simplified classical laminate theory

Chapter 1

Introduction

Abstract The first chapter introduces the major concept of composite material, i.e., the combination of different components, to obtain in total much better properties than a single component for itself. The focus is many times on fiber-reinforced composites where a single layer has unidirectionally aligned reinforcing fibers. The basic equations of continuum mechanics to model such two-dimensional structures are introduced. A common approach is to avoid to solve the coupled system of differential equations. This is done by the so-called classical laminate theory for two-dimensional orthotropic composite materials. To facilitate the understanding, the idea of a simplified classical laminate theory is outlined. This reduced approach is based on one-dimensional bar/beam elements at which each single layer reveals isotropic properties.

A typical concept to design materials with improved performance is to compose different constituents to a so-called composite material, where the entire composite reveals better properties (sometimes evaluated as a spectrum of different properties) than any of the single constituents. Out of the various types of composite materials, fiber-reinforced plastics are a common choice for high-performance requirements in lightweight applications. A typical basic layer, the so-called lamina, can be composed of unidirectional fibers which are embedded in a matrix, see Fig. 1.1. It is common to describe such a unidirectional lamina based on the .(1, 2, 3) coordinate system where the .1-axis is aligned with the parallel fibers, the .2-axis is in-plane perpendicular to the fibers and the .3-axis stands perpendicular to the .1-.2 plane. The mechanical behavior of such a lamina is many times approximated as a two-dimensional superposition of a plane elasticity element (loading and deformation only in the .1-.2 plane) and a classical plate element (only bending deformation). Furthermore, the constitutive description is based on an orthotropic Hooke’s law in the linear elastic range. In a second step, layers of laminae may be stacked under different fiber angles to a so-called laminate, which reveals—depending on the stacking sequence—different types of anisotropy/isotropy, see Fig. 1.2. The mechanical behavior is now described

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2024 A. Öchsner and R. Makvandi, A Numerical Approach to the Simplified Laminate Theory of Composite Materials, Advanced Structured Materials 202, https://doi.org/10.1007/978-3-031-47984-7_1

1

2

1 Introduction

Fig. 1.1 Schematic representation of a unidirectional lamina

Fig. 1.2 Unbonded view of single laminae forming a 5-layer laminate

with reference to a global .(x, y, z) coordinate system. The orientation of a single layer .k with respect to the global coordinate system is expressed by the rotational angle .αk , which is drawn from the global .x-axis to the .1k -axis of layer .k. The simplified approach, i.e., the simplified classical laminate theory (SCLT), will still consider a layer-wise composition of a mechanical member but is based on the following simplifications, see also Fig. 1.3:

1 Introduction

3

Fig. 1.3 Unbonded view of single bar/beam elements forming a 5-layer composite

• The two-dimensional combination of a plane elasticity and classical plate element is replaced by a superposition of a one-dimensional bar and beam element. Bending occurs only in a single plane. • Each single layer .k is considered as isotropic and homogeneous. The constitutive description is based one the one-dimensional Hooke’s law for linear-elastic material behavior. It is obvious that this simplified approach disregards the transformations of stresses, strains and stiffnesses between the.(1, 2) and.(x, y) coordinate systems. Nevertheless, the continuum mechanical modeling as well as the composition of a composite element by layers is well included. Typical thin laminates composed of orthotropic laminae (plies) can be modeled under particular assumptions as a simple superposition of a plane elasticity and a classical plate element. The same holds for our simplified composite model which consists of the superposition of one-dimensional bar and beam elements. These one-dimensional elements are described separately in Chap. 2 and subsequently composed to a combined bar/beam element. Let us highlight here that the derivations in the following chapter follow a common approach from continuum mechanics [1], see Fig. 1.4. A combination of the kinematics equation (i.e., the relation between the strains and deformations) with the constitutive equation (i.e., the relation between the stresses and strains) and the equilibrium equation (i.e., the equilibrium between the internal reactions and the external loads) results in a partial differential equation, or a corresponding system of differential equations. Limited to simple problems and configurations, analytical solutions are possible. These analytical solutions are then exact

4

1 Introduction

external loads (forces, moments)

deformations (displacements, rotations)

equilibrium

kinematics

stresses

constitutive equation

measure for loading

strains

measure for deformation

partial differential equation(s)

solution - analytical methods - numerical methods (FDM, FEM, FVM, BEM)

Fig. 1.4 Continuum mechanical modeling of structural members

in the frame of the assumptions made. However, the solution of complex problems requires the application of numerical methods such as the finite element method, see [7, 11] for general details on the method and Table 1.1 for specialized literature on finite element simulation of composite materials. These numerical solutions are, in general, no longer exact since the numerical methods provide only an approximate solution. Thus, the major task of an engineer is then to ensure that the approximate solution is as good as possible. This requires a lot of experience and a solid foundation in the basics of applied mechanics, materials science, and mathematics. Chapter 2 presents a simplified approach, the so-called simplified classical laminate theory (SCLT) [12], which is adopted to our one-dimensional bar/beam element. This approach aims to provide a stress and a subsequent strength/failure analysis without the solution of the system of differential equations for the unknown displacements in a two-dimensional plane. This theory provides the solution of the statically indeterminate system based on a generalized stress-strain relationship under consideration of the constitutive relationship and the definition of the so-called stress resultants or

References

5

Table 1.1 Some of the early textbooks which cover the finite element simulation of composite materials (no claim to completeness) Author Title Refs. Year (1st ed.) 1992 1998 2000

2008

O. O. Ochoa, J. N. Reddy L. T. Tenek, J. Argyris F. L. Matthews, G. A. O. Davies, D. Hitchings, C. Soutis E. J. Barbero

Finite element analysis of composite laminates Finite element analysis for composite structures Finite element modelling of composite materials and structures Finite element analysis of composite materials

[5] [15] [4]

[2]

generalized stresses and strains. Details on the classical laminate theory (CLT), i.e., the classical two-dimensional approach under consideration of orthotropic material behavior, can be found, for example, in [3, 9, 14]. It should be noted here that this simplified approach based on one-dimensional members has been already successfully applied in the context of the finite element method [6], lightweight design [10], and structural optimization [8]. Chapter 3 introduces the programming approach for the Python-based computational tool, the so-called Composite Laminate Analysis Tool (CLAT 1D). The choices for the different tools and libraries, particularly for our user interface, are explained in detail. The second part of this chapter covers the graphical user interface, functionality, and the practical handling of CLAT 1D. It should be noted here, that a similar Python tool is available by the same authors for the more general two-dimensional case under consideration of orthotropic material behavior [13]. Chapter 4 presents the use of CLAT 1D for the solution of some standard calculation problems based on the simplified classical laminate theory and Chap. 5 provides the commented and structured source codes of all CLAT 1D modules.

References 1. Altenbach, H., Öchsner, A. (eds.): Encyclopedia of Continuum Mechanics. Springer, Berlin (2020) 2. Barbero, E.J.: Finite Element Analysis of Composite Materials. CRC Press, Boca Raton (1996) 3. Dong, S.B., Pister, K.S., Taylor, R.L.: On the theory of laminated anisotropic shells and plates. J. Aerosp. Sci. 29, 696–975 (1962). https://doi.org/10.2514/8.9668 4. Matthews, F.L., Davies, G.A.O., Hitchings, D., Soutis, C.: Finite Element Modelling of Composite Materials and Structures. Woodhead Publishing Limited, Cambridge (2000) 5. Ochoa, O.O., Reddy, J.N.: Finite Element Analysis of Composite Laminates. Kluwer Academic Publishers, Dordrecht (1992) 6. Öchsner, A., Merkel, M.: One-Dimensional Finite Elements: An Introduction to the FE Method. Springer, Cham (2018)

6

1 Introduction

7. Öchsner, A., Öchsner, M.: A First Introduction to the Finite Element Analysis Program MSC Marc/Mentat. Springer, Cham (2018) 8. Öchsner, A., Makvandi, R.: Numerical Engineering Optimization: Application of the Computer Algebra System Maxima. Springer, Cham (2020) 9. Öchsner, A.: Foundations of Classical Laminate Theory. Springer, Cham (2022) 10. Öchsner, A.: Stoff- und Formleichtbau: Leichter Einstieg mit eindimensionalen Strukturen. Springer, Wiesbaden (2022) 11. Öchsner, A.: Computational Statics and Dynamics: An Introduction Based on the Finite Element Method. Springer, Cham (2023) 12. Öchsner, A.: A Simplified Approach to the Classical Laminate Theory of Composite Materials: Application of Bar and Beam Elements. Springer, Cham (2023) 13. Öchsner, A., Makvandi, R.: A Numerical Approach to the Classical Laminate Theory of Composite Materials: The Composite Laminate Analysis Tool–CLAT v2.0. Springer, Cham (2023) 14. Stravsky, Y.: Bending and stretching of laminated aeolotropic plates. J. Eng. Mech. Div.-ASCE 87, 31–56 (1961). https://doi.org/10.1061/JMCEA3.0000267 15. Tenek, L.T., Argyris, J.: Finite Element Analysis for Composite Structures. Springer, Dordrecht (1998)

Chapter 2

Simplified Laminate Theory

Abstract This chapter starts with the fundamental description of one-dimensional bar and thin beam members. Based on the three basic equations of continuum mechanics, i.e., the kinematics relationship, the constitutive law (here: one-dimensional Hooke’s law for isotropic materials), and the equilibrium equation, the partial differential equations, which describe both mechanical members, are derived. In addition to the separate equations for both members, a formal notation is introduced for the combined bar/beam member. The second part of this chapter focuses on composite bar/beam elements with different layers. Based on a generalized stress-strain relationship, the calculation steps based on the simplified classical laminate theory are introduced. The simplifications come from the application of one-dimensional members and the treatment of each single layer as an isotropic material. Based on the internal reactions, i.e., the internal normal force and the internal bending moment, the strain and stress distribution in each single layer can be evaluated. These values may serve then for a subsequent failure analysis based on different criteria.

2.1 Introduction A bar is defined as a prismatic body whose axial dimension is much larger than its transverse dimensions [16]. This structural member is only loaded in the direction of the main body axes, see Fig. 2.1a. As a result of this loading, the deformation occurs only along its main axis. The following derivations are restricted to some simplifications: • • • •

only applying to straight bars; displacements are (infinitesimally) small; strains are (infinitesimally) small; material is linear-elastic (homogeneous and isotropic).

The ultimate goal of the classical modeling approach is to derive a partial differential equation, which describes at any location .x the deformation (displacement) .u x (x).

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2024 A. Öchsner and R. Makvandi, A Numerical Approach to the Simplified Laminate Theory of Composite Materials, Advanced Structured Materials 202, https://doi.org/10.1007/978-3-031-47984-7_2

7

8

2 Simplified Laminate Theory

Fig. 2.1 General configuration for bar problems: a example of boundary conditions and external loads; b cross-sectional area

(a)

(b)

Fig. 2.2 General configuration for beam problems: a example of boundary conditions and external loads; b cross-sectional area

For simple problems, e.g., constant properties .(E, A) and constant loads, the analytical solution can be obtained from the differential equation by simple integration and adjusting the constants of integration based on the boundary conditions of the problem. It should be noted here that the alternatively used nomenclature “rod” is also found in scientific literature to describe a bar member. Details on the continuum mechanical description of bars can be found in [9, 11], and the basic equations are derived in detail in the following sections. A thin beam is defined as a long prismatic body as schematically shown in Fig. 2.2a. The following derivations are restricted to some simplifications: • • • • • • •

only applying to straight beams, no elongation along the .x-axis, no torsion around the .x-axis, no contribution of the shear force on the deformation, deformations in a single plane, i.e., symmetrical bending, small deformations, and simple cross sections.

2.1 Introduction

9

Table 2.1 Differentiation between bar and beam element; center line parallel to the .x-axis Bar Beam Force unknown

(a)

Along the bar axis displacement along bar axis .u x

Perpendicular to the beam axis displacement perpendicular and rotation perpendicular to the beam axis .u z , .ϕ y

(b)

Fig. 2.3 Different deformation modes of a bending beam: a shear-rigid; b shear-flexible. Adapted from [10]

The external loads, which are considered within this chapter, are single forces . Fz , single moments . M y , distributed loads .qz (x), and distributed moments .m y (x). These loads have in common that their line of action (force) or the direction of the momentum vector are orthogonal to the center line of the beam and cause its bending. This is a different type of deformation compared to the bar element; see Table 2.1. It should be noted here that these basic types of deformation can be superposed to account for more complex loading conditions [4]. The classic theories of beam bending distinguish between shear-rigid and shearflexible models. The shear-rigid beam, also called the Bernoulli beam,1 neglects the shear deformation from the shear forces. This theory implies that a cross-sectional plane which was perpendicular to the beam axis before the deformation remains in the deformed state perpendicular to the beam axis; see Fig. 2.3a. Furthermore, it is assumed that a cross-sectional plane stays plane and unwarped in the deformed state. These two assumptions are also known as Bernoulli’s hypothesis. Altogether, one imagines that cross-sectional planes are rigidly fixed to the center line of the beam2 so that a change of the center line affects the entire deformation. Consequently, it is also assumed that the geometric dimensions3 of the cross-sectional planes do not change. 1

More precisely, this beam is known as the Euler–Bernoulli beam. A historical analysis of the development of the classical beam theory and the contribution of different scientists can be found in [12]. 2 More precisely, this is the neutral fiber or the bending line. 3 Consequently, the width .b and the height .t of a, for example, rectangular cross section remain the same; see Fig. 2.2b.

10

2 Simplified Laminate Theory (a)

(b)

Fig. 2.4 Different stress distributions of a beam with rectangular cross section and linear-elastic material behavior: a normal stress and b shear stress Table 2.2 Analogies between the beam and plate theories Beam theory Dimensionality Shear-rigid Shear-flexible

1D Bernoulli beam Timoshenko beam

Plate theory 2D Kirchhoff plate Reissner-Mindlin plate

In the case of a shear-flexible beam, also called the Timoshenko beam, the shear deformation is considered in addition to the bending deformation, and cross-sectional planes are rotated by an angle.γ compared to the perpendicular line; see Fig. 2.3b. For beams for which the length is 10 to 20 times larger than a characteristic dimension of the cross section, the shear fraction is usually disregarded in the first approximation. The different load types, meaning pure bending moment loading or shear due to shear force, lead to different stress fractions in a beam. In the case of a Bernoulli beam, deformation occurs solely through normal forces, which are linearly distributed over the cross section. Consequently, a tension—alternatively a compression maximum on the bottom face—maximum on the top face occurs; see Fig. 2.4a. In the case of symmetric cross sections, the zero crossing4 occurs in the middle of the cross section. The shear stress distribution for a rectangular cross section is parabolic at which the maximum occurs at the neutral axis and is zero at both the top and bottom surfaces; see Fig. 2.4b. This shear stress distribution can be calculated for the Bernoulli beam but is not considered for the derivation of the deformation. Finally, it needs to be noted that the one-dimensional beam theories have corresponding counterparts in two-dimensional space; see Table 2.2. In plate theories, the Bernoulli beam corresponds to the shear-rigid Kirchhoff plate and the Timoshenko beam corresponds to the shear-flexible Reissner-Mindlin plate, [1, 7, 26]. Further details regarding the beam theory and the corresponding basic definitions and assumptions can be found in Refs. [5, 8, 13, 25]. In the following two chapters, only the Bernoulli beam is considered. Consideration of the shear part is, for example, treated in [16]. The simple superposition of a bar and thin beam element is illustrated in Fig. 2.5. It is assumed for this approach that there is no direct coupling between these two deformation modes, i.e., the tensile and bending mode. This combined bar/beam element is now described by the geometrical properties . L , I y , A and the material 4

The sum of all points with .σ = 0 along the beam axis is called the neutral fiber.

2.2 Bar Elements

11

Fig. 2.5 Superposition of a bar and a thin beam element

property. E. The superposition of the bar and thin beam element is treated in Sect. 2.4, and further details on the approach and the total deformation can be found in [20].

2.2 Bar Elements 2.2.1 Kinematics To derive the strain-displacement relation (kinematics relation), an axially loaded bar is considered as shown in Fig. 2.6. The length of the member is equal to . L and the constant axial tensile stiffness is equal to . E A. The load is either given as a single force . Fx and/or as a distributed load . px (x). This distributed load has the unit of force per unit length. In the case of a body force . f x (unit: force per unit volume), the distributed load takes the form . px (x) = f x (x)A(x) where . A is the cross-sectional area of the bar. A typical example for a body force would be the dead weight, i.e., the mass under the influence of gravity. In the case of a traction force .tx (unit: force per unit area), the distributed load can be written as . px (x) = tx (x)U (x) where .U (x) is the perimeter of the cross section. Typical examples are frictional resistance, viscous drag, and surface shear.

12

2 Simplified Laminate Theory (a)

Fig. 2.6 General configuration of an axially loaded bar: a geometry and material property; b prescribed loads

(b)

Fig. 2.7 Elongation of a differential element of length .dx: a undeformed configuration; b deformed configuration

Let us now consider a differential element .dx of such a bar as shown in Fig. 2.7. Under an acting load, this element deforms as indicated in Fig. 2.7b where the initial point at the position .x is displaced by .u x and the end point at the position .x + dx is displaced by .u x + du x . Thus, the differential element which has a length of .dx in the unloaded state elongates to a length of .dx + (u x + du x ) − u x . The engineering strain, i.e., the increase in length related to the original length, can be expressed as ε =

. x

(dx + (u x + du x ) − u x ) − (dx) , dx

or finally as ε (x) =

. x

du x (x) . dx

(2.1)

(2.2)

The last equation is often expressed in a less mathematical way (non-differential) as where .L is the change in length of the entire bar element. ε = L L ) If we replace the common formulation of the first-order derivative, i.e., . d(... , by a dx formal operator symbol, i.e., .L1 (. . . ), the kinematics relation can be stated in a more formal way as d u x (x) = L1 u x (x). (2.3) .ε x (x) = dx 

. x

L1

2.2 Bar Elements

13 (a)

Fig. 2.8 Axially loaded bar: a strain and b stress distribution

(b)

2.2.2 Constitutive Equation The constitutive equation, i.e., the relation between the stress .σx and the strain .εx , is given in its simplest form as Hooke’s law σ (x) = Eεx (x),

. x

(2.4)

where Young’s modulus . E is in the case of linear elasticity a material constant. For the considered bar element, the normal stress and strain is constant over the cross section as shown in Fig. 2.8. Using a more general notation, Hooke’s law can be written as σ (x) = Cεx (x),

. x

(2.5)

where the scalar constant .C = E transforms in the two- or three-dimensional case the so-called elasticity matrix.

2.2.3 Equilibrium The equilibrium equation between the external forces and internal reactions can be derived for a differential element of length .dx as shown in Fig. 2.9. It is assumed for simplicity that the distributed load . px and the cross-sectional area . A are constant in this figure. The internal reactions . N x are drawn in their positive directions, i.e., at the left-hand face in the negative and at the right-hand face in the positive .x-direction. The force equilibrium in the .x-direction for a static configuration requires that .

− N x (x) + px dx + N x (x + dx) = 0

(2.6)

holds. A first-order Taylor’s series expansion of the normal force . N x (x + dx) around point .x, i.e.,

14

2 Simplified Laminate Theory

Fig. 2.9 Differential element of a bar with internal reactions and constant external distributed load

Table 2.3 Fundamental governing equations of a bar for deformation along the .x-axis Equation Expression du x (x) .εx (x) = Kinematics dx dN x (x) = − px (x) dx

Equilibrium

.

Constitution

.σx (x)

= Eεx (x)

 dN x  . N x (x + dx) ≈ N x (x) +  dx, dx 

(2.7)

x

allows to finally express Eq. (2.6) as .

dN x (x) = − px (x), dx

(2.8)

or with the operator symbol .L as5 LT1 (N x (x)) = − px (x).

(2.9)

.

The three fundamental equations to describe the behavior of a bar element are summarized in Table 2.3. A slightly different derivation of the equilibrium equation is obtained as follows: Eq. (2.6) can be expressed based on the normal stresses as .

− σx (x)A + px dx + σx (x + dx)A = 0.

It should be noted here that the transpose (‘T’), i.e., .LT1 = structures of the equations in the two-dimensional case.

5



d(... ) dx

T

(2.10)

, is only used to show similar

2.2 Bar Elements

15

A first-order Taylor’s series expansion of the stress .σx (x + dx) around point .x, i.e.,  dσx  .σ x (x + dx) ≈ σ x (x) +  dx, dx 

(2.11)

x

allows to finally express Eq. (2.10) as, .

dσx (x) px (x) + = 0. dx A

(2.12)

The last equation with .σx = NAx immediately gives Eq. (2.8). Finally, it should be noted here that the general definition of the internal normal force . N x (x) is based on the normal stress distribution as . N x (x) = σx (x)d A. (2.13) A

In the case of a rectangular cross section of width .a and height .t, this can be written based on Hooke’s law as t

2 .

N x (x) =

a Eεx (x)dz = ta Eεx (x).

(2.14)

t − 2

2.2.4 Differential Equation To derive the governing partial differential equation, the three fundamental equations given in Table 2.3 must be combined. Introducing the kinematics relation (2.2) into Hooke’s law (2.4) gives du x . (2.15) .σ x (x) = E dx Considering in the last equation that a normal stress is defined as an acting force . N x over a cross-sectional area . A: du x Nx =E . . (2.16) A dx The last equation can be differentiated with respect to the .x-coordinate to give dN x d . = dx dx



du x EA , dx

(2.17)

16

2 Simplified Laminate Theory

Table 2.4 Different formulations of the partial differential equation for a bar (.x-axis: right facing) Configuration Partial differential equation .

E, A

d2 u x =0 dx 2

.E A .

d . dx

E(x), A(x) px (x)

du x E(x)A(x) dx



.E A

d2 u x = − px (x) dx 2

.E A

d2 u x = k(x)u x dx 2

k(x)

=0

where the derivative of the normal force can be replaced by the equilibrium equation (2.8) to obtain in the general case: d . dx



du x (x) E(x)A(x) = − px (x). dx

(2.18)

The general case in the formulation with the internal normal force distribution reads: .

E(x)A(x)

du x (x) = N x (x). dx

(2.19)

Thus, to obtain the displacement field .u x (x), one may start from Eq. (2.18) or from Eq. (2.19). The first approach requires to state the distribution of the distributed load . px (x), while for the second approach one requires the internal normal force distribution . N x (x). If the axial tensile stiffness. E A is constant, the formulation (2.18) can be simplified to d2 u x (x) = − px (x). (2.20) .E A dx 2 Some common formulations of the governing partial differential equation are collected in Table 2.4. It should be noted here that some of the different cases given in Table 2.4 can be combined. The last case in Table 2.4 refers to the case of elastic embedding of a bar where the embedding modulus .k has the unit of force per unit area. Analytical solutions for different loading and support conditions can be found, for example, in [16].

2.3 Euler–Bernoulli Beam Elements

17

Table 2.5 Different formulations of the basic equations for a bar (.x-axis along the principal rod axis). . E: Young’s modulus; . A: cross-sectional area; . px : length-specific distributed normal load; d(... ) .L1 = dx : first-order derivative; .b: volume-specific distributed normal load Specific formulation Kinematics du x (x) .εx (x) = dx Constitution = Eεx (x) Equilibrium dσx (x) px (x) . + =0 dx A dN x (x) . + px (x) = 0 dx PDE (. A = const.)

. d du x px (x) . =0 E(x) + dx dx A .σx (x)

General formulation .εx (x)

= L1 (u x (x))

.σx (x)

= Cεx (x)

T (σ

.L1

x (x)) + b

T (N

.L1

x (x)) +

=0

px (x) = 0

T (C L (u (x))) + b 1 x

.L1

=0

or .LT1 (E AL1 (u x (x))) + px = 0

) If we replace the common formulation of the first-order derivative, i.e., . d(... , by dx a formal operator symbol, i.e., .L1 (. . . ), the basic equations can be stated in a more formal way as given in Table 2.5. Such a formulation is advantageous in the twoand three-dimensional cases [3]. It should be noted here that the transpose (‘T’), i.e., T  d(... ) T , is only used to show similar structures of the equations in the two.L1 = dx and three-dimensional cases.

2.3 Euler–Bernoulli Beam Elements 2.3.1 Kinematics For the derivation of the kinematics relation, a beam with length . L under constant moment loading . M y (x) = const., meaning under pure bending, is considered; see Fig. 2.10. One can see that both external single moments at the left- and right-hand boundaries lead to a positive bending moment distribution . M y within the beam. The vertical position of a point with respect to the center line of the beam without action of an external load is described through the .z-coordinate. The vertical displacement of a point on the center line of the beam, meaning for a point with .z = 0, under action of the external load is indicated with .u z . The deformed center line is represented by the sum of these points with .z = 0 and is referred to as the bending line .u z (x).

18

2 Simplified Laminate Theory

(a)

(b)

Fig. 2.10 Beam under pure bending in the .x-.z plane: a moment distribution; b deformed beam. Note that the deformation is exaggerated for better illustration. For the deformations considered in this chapter, the following applies: . R  L

In the case of a deformation in the.x-.z plane, it is important to precisely distinguish between the positive orientation of the internal reactions, the positive rotational angle, and the slope; see Fig. 2.11. The internal reactions at a right-hand boundary are directed in the positive directions of the coordinate axes. Thus, a positive moment at a right-hand boundary is clockwise oriented (as the positive rotational angle); see Fig. 2.11a. However, the slope is negative; see Fig. 2.11b. This difference requires some careful derivations of the corresponding equations. Only the center line of the deformed beam is considered in the following. Through the relation for an arbitrary point .(x, u z ) on a circle with radius . R around the center point .(x0 , z 0 ), meaning (x − x0 )2 + (u z (x) − z 0 )2 = R 2 ,

.

(2.21)

2.3 Euler–Bernoulli Beam Elements

19

(a)

(b)

Fig. 2.11 Positive definition of a internal reactions and b rotation (but negative slope)

one obtains through differentiation with respect to the .x-coordinate du z (x) = 0, dx

(2.22)

d2 u z du z du z + 2(u z (x) − z 0 ) 2 = 0. dx dx dx

(2.23)

2(x − x0 ) + 2(u z (x) − z 0 )

.

alternatively after another differentiation: 2+2

.

Equation (2.23) provides the vertical distance between an arbitrary point on the center line of the beam and the center point of a circle as

1+ (u z − z 0 ) = −

.

du z dx

2

d2 u z dx 2

,

(2.24)

while the difference between the .x-coordinates results from Eq. (2.22): (x − x0 ) = −(u z − z 0 )

.

du z . dx

(2.25)

If the expression according to Eq. (2.24) is used in Eq. (2.25), the following results:

du z .(x − x 0 ) = dx

1+

du z dx

d2 u z dx 2

2 .

(2.26)

20

2 Simplified Laminate Theory

Inserting both expressions for the .x- and .z-coordinate differences according to Eqs. (2.26) and (2.24) in the circle equation according to (2.21) leads to .

R 2 = (x − x0 )2 + (u z − z 0 )2  2 2  2 2 du z

2 1 + du z 1 + dx dx du z + =  2 2  2 2 dx d uz d uz dx 2



.

=⎝

d2 u z dx 2



2

+ 1⎠

 2 2 z 1 + du dx 

2 ⎞3 du z ⎠ ⎝1 + dx . = 2

d2 u z dx 2 ⎛

(2.27)

dx 2

d2 u z dx 2

2



(2.28)

Thus, the radius of curvature is obtained as ⎛



⎝1 +

du z dx

2 ⎞3/2 ⎠

   d2 u  z   2  dx 

|R| =

.

.

(2.29)

To decide if the radius of curvature is positive or negative, let us have a look at Fig. 2.12 where a curve with its tangential and normal vectors is shown. Since the curve in this configuration is bending away from the normal vector .n, it holds that d2 u z < 0 and the radius of curvature is obtained for a positive bending moment as . dx 2 ⎛ ⎝1 + .

R=−



2 ⎞3/2 du z ⎠ dx

d2 u z dx 2

.

(2.30)

Note that the expression curvature, which results as a reciprocal value from the curvature radius, i.e., .κ = R1 , is used as well.

2.3 Euler–Bernoulli Beam Elements

21

Fig. 2.12 Definition of a negative curvature in the .x-.z plane Fig. 2.13 Segment of a beam under pure bending in the .x-.z plane. Note that the deformation is exaggerated for better illustration

z  1 results and Eq. (2.30) For small bending deflections, meaning .u z  L, . du dx simplifies to d2 u z 1 1 = − or κ = .R = − . (2.31) R dx 2 d2 u z dx 2

For the determination of the strain, one refers to its general definition, meaning elongation referring to initial length. Relating to the configuration shown in Fig. 2.13, the longitudinal elongation of a fiber at distance.z to the neutral fiber allows to express the strain as ds − dx . .ε x = (2.32) dx The lengths of the circular arcs .ds and .dx result from the corresponding radii and the enclosed angles in radian measure as dx = Rdϕ y ,

(2.33)

ds = (R + z)dϕ y .

(2.34)

.

.

If these relations for the circular arcs are used in Eq. (2.32), the following results: ε =

. x

dϕ y (R + z)dϕ y − Rdϕ y =z . dx dx

(2.35)

22

2 Simplified Laminate Theory dϕ

It results from Eq. (2.33) that . dxy = can finally be expressed as follows: ε (x, z) = z

. x

1 R

and together with relation (2.31) the strain

1 (2.31) d2 u z (x) (2.31) = −z = zκ. R dx 2

(2.36)

If we replace the common formulation of the second-order derivative, i.e., . d dx(...2 ) , by a formal operator symbol, i.e., .L2 (. . . ), the kinematics relation can be stated in a more formal way as .ε x (x, z) = −zL2 u z (x) = zκ. (2.37) 2

An alternative derivation of the kinematics relation results from consideration of Fig. 2.14. From the relation of the right-angled triangle.0 1 2 , which means6 .sin ϕ y = ux , the following relation results for small angles .(sin ϕ y ≈ ϕ y ): z u = +zϕ y .

. x

(2.38)

Furthermore, it holds that the rotation angle of the slope equals the center line for small angles:

Fig. 2.14 Alternative configuration for the derivation of the kinematics relation. Note that the deformation is exaggerated for better illustration Note that according to the assumptions of the Bernoulli beam the lengths .01 and .0 1 remain unchanged.

6

2.3 Euler–Bernoulli Beam Elements

.

23

tan ϕ y =

− du z (x) ≈ ϕy . dx

(2.39)

If Eqs. (2.39) and (2.38) are combined, the following results: u = −z

. x

du z (x) . dx

(2.40)

The last relation equals .(ds − dx) in Eq. (2.32), and differentiation with respect to the .x-coordinate leads directly to Eq. (2.36).

2.3.2 Constitutive Equation The one-dimensional Hooke’s law according to Eq. (2.4) can also be assumed in the case of the bending beam, since, according to the requirement, only normal stresses are regarded in this section: .σ x = Eε x . (2.41) Using a more general notation, Hooke’s law can be again written as σ (x) = Cεx (x),

(2.42)

. x

where the scalar constant .C = E transforms in the two- or three-dimensional case the so-called elasticity matrix. Through the kinematics relation according to Eq. (2.36), the stress results as a function of the deflection to σ (x, z) = −E z

. x

d2 u z (x) . dx 2

(2.43)

The stress distribution shown in Fig. 2.15a generates the internal bending moment, which acts in this cross section. To calculate this internal moment, the stress is multiplied by a surface element, so that the resulting force is obtained. Multiplication with the corresponding lever arm then gives the internal moment. Since the stress is linearly distributed over the height, the evaluation is done for an infinitesimally small surface element: dM y = (+z)(+σx )dA = zσx dA.

.

(2.44)

Therefore, the entire moment results via integration over the entire surface in .

My =

(2.43)



zσx dA = − A

zEz A

d2 u z (x) dA. dx 2

(2.45)

24

2 Simplified Laminate Theory

(a)

(b)

Fig. 2.15 a Schematic representation of the normal stress distribution .σx = σx (z) of a bending beam; b Definition and position of an infinitesimal surface element for the derivation of the resulting moment action due to the normal stress distribution

Assuming that Young’s modulus is constant, the internal moment around the . y-axis results in d2 u z I y σx . z 2 dA = (2.46) . M y = −E 2 dx z A    Iy

The integral in Eq. (2.46) is the so-called axial second moment of area or axial surface moment of second order in the SI unit m.4 . This factor is only dependent on the geometry of the cross section and is also a measure of the stiffness of a plane cross section against bending. The values of the axial second moment of area for simple geometric cross sections are collected in Table 2.6. Consequently, the internal moment can also be expressed as

.

M y = −E I y

d2 u z (2.31) E I y = E I y κ. = dx 2 R

(2.47)

Equation (2.47) describes the bending line .u z (x) as a function of the bending moment and is therefore also referred to as the bending line-moment relation. The product . E I y in Eq. (2.47) is also called the bending stiffness. If the result from Eq. (2.47) is used in the relation for the bending stress according to Eq. (2.43), the distribution of stress over the cross section results in σ (x, z) = +

. x

M y (x) z(x). Iy

(2.48)

The plus sign in Eq. (2.48) causes that a positive bending moment (see Fig. 2.10) leads to a tensile stress in the upper beam half (meaning for.z > 0). The corresponding equations for a deformation in the .x-. y plane can be found in [16].

2.3 Euler–Bernoulli Beam Elements

25

Table 2.6 Axial second moment of area around the . y- and .z-axes Cross section .Iy . Iz .

π D4 π R4 = 64 4

.

π D4 π R4 = 64 4

.

πba 3 4

.

πab3 4

.

a4 12

.

a4 12

.

bh 3 12

.

hb3 12

.

bh 3 36

.

hb3 36

.

bh 3 36

.

bh 3 48

26

2 Simplified Laminate Theory

Fig. 2.16 Deformation of a beam in the .x-.z plane with . M y (x) = const

In the case of a plane bending with . M y (x) = const., the bending line can be approximated in each case locally through a circle of curvature; see Fig. 2.16. Therefore, the result for pure bending according to Eq. (2.47) can be transferred to the case of plane bending as d2 u z (x) . − E Iy = M y (x). (2.49) dx 2 Let us note at the end of this section that Hooke’s law in the form of Eq. (2.41) is not so easy to apply7 in the case of beams since the stress and strain are linearly changing over the height of the cross section; see Eq. (2.48) and Fig. 2.15. Thus, it might be easier to apply a so-called stress resultant or generalized stress, i.e., a simplified representation of the normal stress state8 based on the acting bending moment: .

M y (x) =

zσx (x, z) d A,

(2.50)

which was already introduced in Eq. (2.44). Using in addition the curvature9 .κ = κ(x) (see Eq. (2.36)) instead of the strain .εx = εx (x, z), the constitutive equation can be easily expressed as shown in Fig. 2.17. The variables . M y and .κ have both the advantage that they are constant for any location .x of the beam.

2.3.3 Equilibrium The equilibrium conditions are derived from an infinitesimal beam element of length dx, which is loaded by a constant distributed load .qz ; see Fig. 2.18. The internal reactions are drawn on both cut faces, i.e., at locations .x and .x + dx. One can see

.

7

However, this formulation works well in the case of rod elements since stress and strain are constant over the cross section, i.e., .σx = σx (x) and .εx = εx (x); see Fig. 2.8. 8 A similar stress resultant can be stated for the shear stress based on the shear force: . Q (x) = z  τx z (x, z) dA. 9 The curvature is then called a generalized strain.

2.3 Euler–Bernoulli Beam Elements

(a)

27

(b)

Fig. 2.17 Formulation of the constitutive law based on a stress and b stress resultant

Fig. 2.18 Infinitesimal beam element in the .x-.z plane with internal reactions and constant distributed load

that a positive shear force is oriented in the positive.z-direction at the right-hand face10 and that a positive bending moment has the same rotational direction as the positive 11 . y-axis (right-hand grip rule ). The orientation of shear force and bending moment is reversed at the left-hand face in order to cancel in sum the effect of the internal reactions at both faces. This convention for the direction of the internal directions is maintained in the following. Furthermore, it can be derived from Fig. 2.18 that an upward directed external force or alternatively a mathematically positive oriented external moment at the right-hand face leads to a positive shear force or alternatively a positive internal moment. In a corresponding way, it results that a downward directed external force or alternatively a mathematically negative oriented external moment at the left-hand face leads to a positive shear force or alternatively a positive internal moment.

10

A positive cut face is defined by the surface normal on the cut plane which has the same orientation as the positive .x-axis. It should be regarded that the surface normal is always directed outward. 11 If the axis is grasped with the right hand in a way so that the spread out thumb points in the direction of the positive axis, the bent fingers then show the direction of the positive rotational direction.

28

2 Simplified Laminate Theory

The equilibrium condition will be determined in the following for the vertical forces. Assuming that forces in the direction of the positive .z-axis are considered positive, the following results: .

− Q z (x) + Q z (x + dx) + qz dx = 0.

(2.51)

If the shear force on the right-hand face is expanded in a Taylor’s series of first order, meaning dQ z (x) dx. . Q z (x + dx) ≈ Q z (x) + (2.52) dx Equation (2.51) results in .

− Q z (x) + Q z (x) +

dQ z (x) dx + qz dx = 0, dx

(2.53)

or alternatively after simplification finally to .

dQ z (x) = −qz . dx

(2.54)

For the special case that no distributed load is acting .(qz = 0), Eq. (2.54) simplifies to dQ z (x) = 0. (2.55) . dx The equilibrium of moments around the reference point at .x + dx gives .

M y (x + dx) − M y (x) − Q z (x)dx +

1 qz dx 2 = 0. 2

(2.56)

If the bending moment on the right-hand face is expanded into a Taylor’s series of first order similar to Eq. %, considering that the term % has an infinitesimal size of higher order and can be disregarded, the following results: .

dM y (x) = Q z (x). dx

(2.57)

The combination of Eqs. (2.54) and (2.57) leads to the relation between the bending moment and the distributed load: .

d2 M y (x) dQ z (x) = −qz (x), = dx 2 dx

(2.58)

2.3 Euler–Bernoulli Beam Elements

29

Table 2.7 Elementary basic equations for the bending of a Bernoulli beam in the .x-.z plane. The differential equations are given under the assumption of constant bending stiffness . E I y Name

Equation

Kinematics

.εx (x, z)

Equilibrium

.

Constitutive equation

.σx (x, z)

= Eεx (x, z)

Stress

.σx (x, z)

=

Diff’equation

.E Iy

d2 u z (x) = −M y (x) dx 2

.E Iy

d3 u z (x) = −Q z (x) dx 3

.E Iy

d4 u z (x) = qz (x) dx 4

= −z

d2 u z (x) dx 2

dQ z (x) dM y (x) = −qz (x) ; . = Q z (x) dx dx

M y (x) z(x) Iy

or with the operator symbol .L as12   LT2 M y (x) = −qz (x).

(2.59)

.

Finally, the elementary basic equations for the bending of a beam in the .x-.z plane for arbitrary moment loading . M y (x) are summarized in Table 2.7.

2.3.4 Differential Equation Two-time differentiation of Eq. (2.47) and consideration of the relation between bending moment and distributed load according to Eq. (2.58) lead to the classical type of differential equation of the bending line,

d2 u z d2 . E I y 2 = qz , dx 2 dx

(2.60)

which is also referred to as the bending line-distributed load relation. For a beam with constant bending stiffness . E I y along the beam axis, the following results: It should be noted here that the transpose (‘T’), i.e.,.LT2 = structures of the equations in the two-dimensional case.

12



d2 (... ) dx 2

T

, is only used to show similar

30

2 Simplified Laminate Theory

.

E Iy

d4 u z = qz . dx 4

(2.61)

The differential equation of the bending line can of course also be expressed through the bending moment or the shear force as d2 u z = −M y or dx 2 d3 u z = −Q z . .E Iy dx 3

.

E Iy

(2.62) (2.63)

Equations (2.62) and (2.63) can be also written in the more general form for variable bending stiffness: d2 u z = −M y (x), 2 dx

d2 u z du z . E(x)I y (x) 2 = −Q z (x) . dx dx .

E(x)I y (x)

(2.64) (2.65)

Depending on the problem and the fact which distribution (.qz (x), . M y (x) or . Q z (x)) is easier to state, one may start from one of the three formulations to derive the displacement field .u z (x). Different formulations of the fourth-order differential equation are collected in Table 2.8 where different types of loadings, geometry, and bedding are differentiated. The last case in Table 2.8 refers to the elastic foundation of a beam which is also know in the literature as Winkler foundation [29]. The elastic foundation or Winkler foundation modulus .k has in the case of beams13 the unit of force per unit area. 2 If we replace the common formulation of the second-order derivative, i.e., . ddx...2 , by a formal operator symbol, i.e., .L2 (. . . ), the basic equations can be stated in a more formal way as given in Table 2.9.

2.4 Combination of Bar and Beam Elements 2.4.1 Kinematics The linear superposition of the normal strain from the tensile deformation (cf. Eq. (2.3)) and the bending deformation (cf. Eq. (2.37)) gives the total normal strain as

13

In the general case, the unit of the elastic foundation modulus is force per unit area per unit length, i.e., . mN2 /m = mN3 .

2.4 Combination of Bar and Beam Elements

31

Table 2.8 Different formulations of the partial differential equation for a Bernoulli beam in the plane (.x-axis: right facing; .z-axis: upward facing) Partial differential equation Configuration

. x-.z

E, Iy

E(x),Iy (x)

. .E Iy . .

d4 u z =0 dx 4

d2 d2 u z E(x)I y (x) 2 2 dx dx

qz (x) .E Iy

d4 u z = qz (x) dx 4

.E Iy

dm y (x) d4 u z = dx 4 dx

.E Iy

d4 u z = −k(x)u z dx 4

my (x)

=0

k(x)

Table 2.9 Different formulations of the basic equations for a Euler–Bernoulli beam (bending in the .x-.z plane; .x-axis along the principal beam axis). . E: Young’s modulus; . I y : second moment of area; .qz : length-specific distributed force; .L2 = Specific formulation

d2 (... ) : dx 2

second-order derivative

General formulation

Kinematics . .εx (x, z)

= −z

. .κ(x)

=−

d2 u z (x) dx 2

d2 u z (x) dx 2

Constitution .σx (x, z) = Eεx (x, z) . M y (x) = E I y κ(x) Equilibrium

.εx (x, z)

.κ(x)

. M y (x)

T

.L2

PDE

d2 u z (x) d2 E I − qz (x) = 0 . y dx 2 dx 2

.L2

.

= −L2 (u z (x))

.σx (x, z)

. 2

d M y (x) . + qz (x) = 0 dx 2

= −z L2 (u z (x))



= Cεx (x, z) = Dκ(x)

 M y (x) + qz (x) = 0

T (D L 2

(u z (x))) − qz (x) = 0

32

2 Simplified Laminate Theory

ε (x) = L1 u x (x) − zL2 u z (x)

. x

.

= L1 u x +zκ y .   

(2.66) (2.67)

ε0x

The last two equations can be differently arranged in matrix form as  .

ε0x

κy



⎤ d   0 ⎥ ux ⎢ dx ⎥ =⎢ , ⎣ d2 ⎦ u z 0 − 2 dx ⎡

or symbolically as .

e = L u,

(2.68)

(2.69)

where the column matrix of generalized strains is expressed as  .

e=

 ε0x . κy

(2.70)

2.4.2 Constitutive Equation The constitutive equation is the same for the bar and beam element (cf. Eqs. (2.4) and (2.41)) and does not require any adjustment: σ (x) = Eεx (x) = Cεx (x).

. x

(2.71)

2.4.3 Equilibrium The equilibrium relation for the rod (cf. Eq. (2.8)) and the thin beam (cf. Eq. (2.58)) can be combined in a single matrix equation to obtain ⎤ d      0 ⎥ ⎢ ⎥ N x (x) ⎢ dx (x) p 0 x ⎥ .⎢ + = . 2 ⎥ ⎢ q y (x) 0 ⎣ 0 d ⎦ M y (x) dx 2 ⎡

(2.72)

2.4 Combination of Bar and Beam Elements

33

In the context of two-dimensional composite layers, it is common to define the internal reactions per unit length (normalized with the corresponding side length of the plate element). The normalized (superscript ‘n’) internal reactions are obtained as N x (x) , a M y (x) n . . M y (x) = a .

N xn (x) =

(2.73) (2.74)

Thus, the combined equilibrium equation can be written as ⎤ ⎤ ⎡ d px (x)    0 ⎥ ⎢ ⎥ ⎢ ⎥ N xn (x) ⎢ dx 0 ⎢ a ⎥ ⎥ ⎢ . +⎢ , ⎥= 2 ⎥ n ⎢ M (x) 0 d ⎣ q y (x) ⎦ y ⎦ ⎣0 dx 2 a ⎡

(2.75)

or in symbolic notation: LT sn + q = 0.

(2.76)

.

Let us note here that the derivation of the internal reactions or stress resultants, i.e., N x (x) and . M y (x), must be revised for the combined bar/beam element (cf. the standalone derivations in Eqs. (2.14) and (2.45)). This comes from the fact that the total strain in the form of Eq. (2.66), i.e., .εx (x) = ε0 + zκ, must be used in the derivation. The derivation for a rectangular cross session (see Fig. 2.19) reads

.

.

t

t



2

N x (x) =

σx (x)d A = A

2 σx (x)adz =



t 2

=



t

2 aC(ε0x + zκ y )dz =

t − 2

Fig. 2.19 Particular configuration of a combined bar/beam element

2 aCε0x dz +

t − 2

(2.77)

t 2

t

t

2 .

aCεx (x)dz

t − 2

aC zκ y dz

(2.78)

34

2 Simplified Laminate Theory

.

.

=

aCε0x



t 2 t − 2

z

N x (x) = taCε0x +

 + aCκ y

z2 2

t

2



(2.79)

t 2

t2 aCκ y . 4

(2.80)

In the same way, the evaluation of the internal bending moment gives t

.

t

2

M y (x) =

zσx (x)dA = A

2 zσx (x)adz =



t 2



= t − 2

.

.

=

M y (x) =

t

2 aC z(ε0x + zκ y )dz = 

aCε0x

z2 2



t

2 t 2 3



2 aC zε0x dz +

t − 2

+ aCκ y

z3 3

(2.81)

t 2

t

t

2 .

aC zεx (x)dz

aC z 2 κ y dz

(2.82)

t − 2

t

2



(2.83)

t 2

t t2 aCε0x + aCκ y . 4 12

(2.84)

Equations (2.80) and (2.84) can be combined to obtain a single matrix representation: ⎡

t2 C aC ⎢ ta  4    ⎢  ⎢ A N x (x) ⎢ B . =⎢ 2 ⎢t M y (x) t3 ⎢ aC aC ⎣ 4    12  B

⎤ ⎥ ⎥  ⎥ 0 ⎥ εx , ⎥ ⎥ κy ⎥ ⎦

(2.85)

D

or based on the internal reactions per unit length (normalized with the corresponding side length of the plate element, see Eqs. (2.73) and (2.74)) ⎤ t2 C ⎥ ⎢ tC 4 ⎥    ⎢   ⎥ 0 ⎢ n A N x (x) ⎥ εx ⎢ B , . =⎢ 2 ⎥ n 3 ⎥ κy ⎢t M y (x) t ⎥ ⎢ C C ⎦ ⎣ 4  12   ⎡

B

D

(2.86)

2.4 Combination of Bar and Beam Elements

or in symbolic notation: .

sn = C ∗ e,

35

(2.87)

where .C ∗ is the generalized elasticity matrix.

2.4.4 Differential Equations Let us start the derivation from the combined equilibrium equation as given in Eq. (2.75) and introduce the representations of the normalized internal reactions according to Eq. (2.86). This procedure results in the following formulation: ⎡

⎤ t2 ⎡ ⎤ tC C ⎥ ⎢  d p (x) ⎢ ⎥ x 4   ⎢ dx 0 ⎥ ⎢ A  ⎥  0  ⎢ ⎥ 0 ⎥ εx ⎢ a ⎥ ⎢ ⎥⎢ B = +⎢ .⎢ . ⎥ ⎥ 2 ⎥⎢ 2 3 d ⎦⎢ t ⎥ κy 0 ⎣ q y (x) ⎦ ⎣ t ⎢ ⎥ 0 C C ⎦ dx 2 ⎣ 4 a  12   ⎡



B

(2.88)

D

Consideration of the kinematics relationship according to Eq. (2.68) in the last equation gives ⎡

⎤ t2 ⎡ ⎤ ⎤ ⎡ tC C ⎥ d d ⎢  p (x) ⎢ ⎥ x 4   0 ⎥  ⎢ 0 ⎥⎢ ⎢ ⎥⎢ ⎥ dx ⎢ ⎥ ⎥ ⎢ A  ⎢ dx 0 u ⎥ ⎥ ⎢ x B ⎥ ⎥ +⎢ a ⎥= .⎢ , ⎥⎢ 2 ⎥ u 2 ⎥⎢ 2 3 ⎢ ⎢ ⎢ ⎥ 0 d d ⎦ ⎣ t t q y (x) ⎦ z ⎦⎢ C ⎣0 ⎥⎣ 0 − C ⎦ dx 2 dx 2 ⎣  4 12 a   ⎤



B

(2.89)

D

or slightly simplified as ⎤ ⎤⎡ ⎤⎡ ⎤ ⎡ d d 0 ⎥   ⎢ px (x)⎥   0 ⎥⎢ A B ⎥⎢ ⎢ ⎥ ux ⎥⎢ ⎢ dx ⎥ ⎢ dx 0 ⎥ ⎢ ⎥ ⎥⎢ ⎥⎢ +⎢ a ⎥= .⎢ . 2 ⎥ u 2 ⎥⎢ ⎢ ⎢ ⎥ 0 ⎣ q y (x) ⎦ ⎣ 0 d ⎦⎣ B C ⎦⎣ 0 − d ⎦ z dx 2 dx 2 a ⎡

(2.90)

A symbolic representation of the last equation reads: LT C ∗ L u + q = 0.

.

(2.91)

36

2 Simplified Laminate Theory

Table 2.10 Different formulations of the basic equations for a combined one-dimensional bar/beam element (bending in the .x-.z plane; .x-axis along the principal element axis). .C = E: elasticity modulus;.C ∗ : generalized elasticity matrix;.t: composite thickness;. s: column matrix of normalized stress resultants; .e: column matrix of generalized strains; .q: column matrix of distributed loads; .L: matrix of differential operators  Kinematics .e = L u ⎤ ⎡ d     ⎢ dx 0 ⎥ u x ε0x ⎥ . =⎢ , ⎣ κy d2 ⎦ u z 0 − 2 dx σx = Cεx sn = C ∗ e .σx (x, z) = Eεx (x, z) ⎤ ⎡ . t2 C⎥ tC ⎢  4 ⎥    ⎢  ⎥ 0 ⎢ A N xn (x) ⎢ B ⎥ εx . =⎢ 2 ⎥ 3 n t ⎥ κy ⎢t M y (x) ⎥ ⎢ C C ⎦ ⎣ 4 12     Constitution

.

D

B

+q =0 ⎤ ⎡ d px (x)     0 ⎥ N xn (x) ⎢ dx ⎥ ⎢ 0 a ⎥ ⎢ ⎥ ⎢ . +⎣ = ⎦ ⎣ ⎦ n 2 q (x) y M y (x) 0 d 0 a dx 2 Equilibrium .LT sn

.⎡



PDE .LT C ∗ L u + q ⎡ . ⎡ ⎤ ⎢  tC d ⎢ 0 ⎢ ⎢ dx ⎥⎢ A ⎥⎢ .⎢ ⎣ 2 t2 d ⎦⎢ ⎢ C 0 4 dx 2 ⎣  B

=0

⎤ t2 ⎤ ⎤ ⎡ C ⎥⎡ px (x) 4 ⎥ d    0 ⎥ u  ⎢ ⎥⎢ ⎥ 0 x a B ⎥ ⎢ dx ⎥ ⎥ ⎢ +⎣ = ⎥ ⎦ ⎦ 2 t3 ⎥ ⎣ q y (x) 0 uz d C⎥ ⎦ 0 − dx 2 a   12 D

Once the solution of the displacements.u in Eq. (2.91) is obtained, for example, based on the finite element method [21] or the finite difference method [18], the kinematics relationships (2.68) and (2.67) provide the strains from which the constitutive equation (2.71) allows the calculation of the stresses. Based on these stress and/or strain values, a subsequent failure analysis can be performed. The basic equations of the combined bar/beam element are summarized in Table 2.10.

2.5 Failure Criteria

37

2.5 Failure Criteria The following subsections present some of the common orthotropic failure criteria for composite materials [23]. However, the formulations were simplified to our onedimensional problem. This means that the orthotropic nature is disregarded. The classical criteria for pure isotropic material behavior can be found, for example, in [17].

2.5.1 Maximum Stress Criterion This criterion assumes that there is no failure in the .x-direction as long as the stress is in the following limits of the corresponding strength values .k: k < σx < kt .

. c

(2.92)

2.5.2 Maximum Strain Criterion The maximum strain criterion is similar to the maximum stress criterion and assumes no interaction between the strain components. No failure occurs as long as the strain components are in the following limits: k ε < εx < ktε ,

. c

(2.93)

where the .k ε represent the corresponding failure strains.

2.5.3 Tsai-Hill Criterion The Tsai-Hill criterion is based on Hill’s three-dimensional yield criterion for orthotropic materials which was applied by Tsai to laminae [14, 27]. This criterion can be stated for the one-dimensional case as follows: .

σx2 < 1, k2

(2.94)

where.k = kt for.σx > 0 or.k = kc for.σx < 0. This criterion reduces in this particular one-dimensional case to the maximum stress criterion; see Sect 2.5.1.

38

2 Simplified Laminate Theory

2.5.4 Tsai-Wu Criterion The Tsai-Wu criterion can be expressed for the particular one-dimensional case as follows [28]: 2 .a1 σ x + a11 σ x < 1, (2.95) where the coefficients .a can be related to the classical failure stresses as follows [2, 15]: 1 1 + , kt kc 1 =− . kt kc

a =

. 1

a

. 11

(2.96) (2.97)

2.6 Simplified Classical Laminate Theory for One-Dimensional Elements 2.6.1 Introduction The procedure outlined in the following follows the description and notation provided in [19, 22]. For the earlier references, the reader may consult the following publications: [6, 24]. Let us consider in the following a composite bar/beam element, which is composed of .n layers; see Fig. 2.20. In our simplified approach, each layer .k is considered as an isotropic and homogeneous material. However, the properties can vary from layer to layer. The global coordinate system .(x, y, z) is used to describe the entire composite bar/beam element.

Fig. 2.20 Geometry of a composite bar/beam element with .n layers

2.6 Simplified Classical Laminate Theory for One-Dimensional Elements

39

The height of a layer .k .(1 ≤ k ≤ n) can be expressed based on the thickness coordinate as .tk = z k − z k−1 , (2.98) and the total height of the laminate results as t=

n !

.

tk .

(2.99)

k =1

2.6.2 Generalized Stress-Strain Relationship Let us focus in the following on the evaluation of the stress resultants as introduced in Eqs. (2.77) and (2.81) for a single layer. The internal normal force can be expressed in the laminate-specific coordinate system .(x, y, z) as t/2 .

Nx = a

σx dz = a

k = 1z

−t/2

.

=a

n z k !

zk n !

σx,k dˆz = a

k = 1z

k−1

.

=a

⎛ ⎝

k =1

.

=a

n ! k =1

Ck εx,k dˆz

zk

zk Ck ε0x dˆz +

z k−1

z k−1

Ck (z k −   Ak

z k−1 ) ε0x 

(2.100)

k−1

  Ck ε0x + zˆ κ y dˆz

k =1 z k−1 n !

n z k !

(2.101) ⎞

Ck zˆ κ y dˆz ⎠

(2.102)

 1 2 2 + Ck (z k ) − (z k−1 ) κ y ,    2

(2.103)

Bk

or with . N xn = N x /a as .

N xn (x) =

n ! k =1

 1 Ck (z k − z k−1 ) ε0x + Ck (z k )2 − (z k−1 )2 κ y .       2 A k

Bk

The corresponding derivation for the internal bending moment gives

(2.104)

40

2 Simplified Laminate Theory

t/2 .

My = a

zσx dz = a

k = 1z

−t/2

.

=a

n !

n z k !

zk

σx,k zˆ dˆz = a

k =1 z

k−1

.

=a

⎛ ⎝

k =1

.

=a

n ! k =1

Ck εx,k zˆ dˆz

zk

(2.106) ⎞

zk

Ck zˆ 2 κ y dˆz ⎠

Ck ε0x zˆ dˆz +

z k−1

(2.105)

k−1

  Ck ε0x zˆ + zˆ 2 κ y dˆz

k =1 z k−1 n !

n z k !

(2.107)

z k−1

  1 Ck (z k )2 − (z k−1 )2 ε0x + Ck (z k )3 − (z k−1 )3 κ y ,      2  3 1

Bk

(2.108)

Dk

or with . M yn = M y /a as n . M y (x)

=

n ! k =1

 0  1 1 2 2 3 3 Ck (z k ) − (z k−1 ) εx + Ck (z k ) − (z k−1 ) κ y . (2.109)      2  3 Bk

Dk

Equations (2.104) and (2.109) can be combined in a single matrix form to give  .

N xn



A

B

B D M yn       C∗

s



 =

ε0x



, κy   

(2.110)

e

where . s is the column matrix of stress resultants (generalized stresses), .C ∗ is the generalized elasticity matrix, and .e is the column matrix of generalized strains. The corresponding scalar elements of .C ∗ are given as follows:

.

.

.

A= B=

D=

n ! k =1 n ! k =1 n ! k =1

Ak = Bk = Dk =

n !

Ck (z k − z k−1 ) ,

k =1 n !

(2.111)

  1 Ck (z k )2 − (z k−1 )2 , 2 k =1

(2.112)

n   1! Ck (z k )3 − (z k−1 )3 . 3 k =1

(2.113)

It should be noted here that the matrix element . B represents the bending-tension coupling.

2.6 Simplified Classical Laminate Theory for One-Dimensional Elements

41

Equation (2.110) can be inverted to obtain the strains and curvatures (generalized strains) as a function of the generalized stresses as  .

ε0x





κy   

=

A

B

B

D

 −1 

N xn



 =

M yn



e

A

B

B

D



(C ∗ )−1



N xn



, M yn    

(2.114)

s

where the elements of the inverse are simply given for a .2 × 2 matrix as follows: D , AD − B B −B  .B = , AD − B B A  . .D = AD − B B .

A =

(2.115) (2.116) (2.117)

Based on the generalized strains obtained from Eq. (2.114), it is now possible to calculate the stresses in each layer .k expressed in the .x-. y coordinate system: σ

. x,k

  (z) = Ck ε0x + zκ y ,

(2.118)

where the vertical coordinate .z ranges for the .kth layer in the following boundaries: z ≤ z ≤ z k . The stresses may be evaluated at the bottom .(z = z k−1 ), middle .(z = (z k + z k−1 )/2), or top .(z = z k ) of each layer. The obtained stress values may serve for a subsequent failure analysis of layer .k (see Sects. 2.5 and 2.6.3). It should be mentioned at the end of this section that the generalized elasticity matrix .C ∗ (see Eq. (2.110)) and the corresponding inverse .(C ∗ )−1 (see (2.114)) take the following simplified forms for composite elements with a symmetric layer composition:

. k−1

 ∗ . C sym

=

A

0

0

D



(C ∗sym )−1

.

1 ⎢A =⎢ ⎣ 0

 ,

⎤ 0 ⎥ ⎥. 1 ⎦ D

(2.119)

(2.120)

42

2 Simplified Laminate Theory

2.6.3 Failure Analysis Let us summarize here the recommended steps for a calculation according to the simplified classical laminate theory; see Table 2.11 for the case that the internal normal force and the internal bending moment are given and Table 2.12 for the case that the generalized strains are given.

Table 2.11 Recommended steps for a calculation according to the simplified classical laminate theory. Case: internal normal force . N xn and internal bending moment . M yn given Nr.

Steps to perform

1 .

Define for each layer .k the material .(E k ) and the geometrical .(z k ; z k−1 ; αk ) properties #T " Define the column matrix of generalized stresses: . s = N xn M yn

2 . 3 . 4 . 5 . 6 .

7 .

Calculate the matrix elements . A, . B, and .C according to Eqs. (2.111)–(2.113). Assemble the generalized elasticity matrix .C ∗ according to Eq. (2.110) Calculate the generalized compliance matrix .(C ∗ )−1 based on Eqs. (2.115)–(2.117) #T " Calculate the generalized strains .e = ε0x κ y according to Eq. (2.114) Calculate the stresses in each layer .k according to Eq. (2.118),  = Ck ε0x + zκ y , in the .x-. y laminate system .(z k−1 ≤ z ≤ z k ). The strains in   the .x-. y laminate system are obtained from . ε0x + zκ y Perform the failure analysis for each layer .k, see Sect. 2.5

.σx,k (z)

Table 2.12 Recommended steps for a calculation according to the simplified classical laminate theory. Case: generalized strains .e = [ε0x κ y ]T given Nr.

Steps to perform

1 .

Define for each lamina .k the material .(E k ) and the geometrical .(z k ; z k−1 ; αk ) properties #T " Define the column matrix of generalized strains: .e = ε0x κ y

2 . 3 .

4 . 5 .

Calculate the matrix elements . A, . B, and .C according to Eqs. (2.111)–(2.113). Assemble the generalized elasticity matrix .C ∗ according to Eq. (2.110) " # Calculate the generalized stresses . s = N xn M yn according to Eq. (2.110) In case that the stresses and strains in each layer are required (e.g., for a failure 6 and . 7 in Table 2.11 analysis), go to Steps .

References

43

References 1. Altenbach, H., Altenbach, J., Naumenko, K.: Ebene Flächentragwerke: Grundlagen der Modellierung und Berechnung von Scheiben und Platten. Springer, Berlin (1998) 2. Altenbach, H., Altenbach, J., Kissing, W.: Mechanics of Composite Structural Elements. Springer Nature, Singapore (2018) 3. Altenbach, H., Öchsner, A. (eds.): Encyclopedia of Continuum Mechanics. Springer, Berlin (2020) 4. Boresi, A.P., Schmidt, R.J.: Advanced Mechanics of Materials. Wiley, New York (2003) 5. Budynas, R.G.: Advanced Strength and Applied Stress Analysis. McGraw-Hill Book, Singapore (1999) 6. Dong, S.B., Pister, K.S., Taylor, R.L.: On the theory of laminated anisotropic shells and plates. J. Aerosp. Sci. 29, 696–975 (1962). https://doi.org/10.2514/8.9668 7. Gould, P.L.: Analysis of Shells and Plates. Springer, New York (1988) 8. Gross, D., Hauger, W., Schröder, J., Wall, W.A.: Technische Mechanik 2: Elastostatik. Springer, Berlin (2009) 9. Gross, D., Hauger, W., Schröder, J., Wall, W.A., Bonet, J.: Engineering Mechanics 2: Mechanics of Materials. Springer, Berlin (2011) 10. Hartmann, F., Katz, C.: Structural Analysis with Finite Elements. Springer, Berlin (2007) 11. Hartsuijker, C., Welleman, J.W.: Engineering Mechanics Volume 2: Stresses, Strains, Displacements. Springer, Dordrecht (2007) 12. Heyman, J.: Structural Analysis: a Historical Approach. Cambridge University Press, Cambridge (1998) 13. Hibbeler, R.C.: Mechanics of Materials. Prentice Hall, Singapore (2008) 14. Hill, R.: The Mathematical Theory of Plasticity. Oxford University Press, London (1950) 15. Kaw, A.K.: Mechanics of Composite Materials. CRC Press, Boca Raton (2006) 16. Öchsner, A.: Elasto-Plasticity of Frame Structure Elements: Modeling and Simulation of Rods and Beams. Springer, Berlin (2014) 17. Öchsner, A.: Continuum Damage and Fracture Mechanics. Springer, Singapore (2016) 18. Öchsner, A.: Structural Mechanics with a Pen: A Guide to Solve Finite Difference Problems. Springer, Cham (2021) 19. Öchsner, A.: Foundations of Classical Laminate Theory. Springer, Cham (2021) 20. Öchsner, A.: Classical Beam Theories of Structural Mechanics. Springer, Cham (2021) 21. Öchsner, A.: Computational Statics and Dynamics: An Introduction Based on the Finite Element Method. Springer, Cham (2023) 22. Öchsner, A.: A Simplified Approach to the Classical Laminate Theory of Composite Materials: Application of Bar and Beam Elements. Springer, Cham (2023) 23. Öchsner, A.: Composite Mechanics. Springer, Cham (2023) 24. Stravsky, Y.: Bending and stretching of laminated aeolotropic plates. J. Eng. Mech. Div-ASCE 87, 31–56 (1961). https://doi.org/10.1061/JMCEA3.0000267 25. Szabó, I.: Einführung in die Technische Mechanik: Nach Vorlesungen István Szabó. Springer, Berlin (2003) 26. Timoshenko, S., Woinowsky-Krieger, S.: Theory of Plates and Shells. McGraw-Hill Book Company, New York (1959) 27. Tsai, S.W.: Strength theories of filamentary structures. In: Schwartz, R.T., Schwartz, H.S. (eds.) Fundamental Aspects of Fiber Reinforced Plastic Composites, pp. 3–12. Wiley Interscience, New York (1968) 28. Tsai, S.W., Wu, E.M.: A general theory of strength for anisotropic materials. J. Compos. Mater. 5, 58–80 (1971). https://doi.org/10.1177/002199837100500106 29. Winkler, E.: Die Lehre von der Elasticität und Festigkeit mit besonderer Rücksicht auf ihre Anwendung in der Technik. H. Dominicus, Prag (1867)

Chapter 3

Composite Laminate Analysis Tool—CLAT 1D

Abstract This chapter describes the programming approach for the Python-based computational tool, the so-called Composite Laminate Analysis Tool (CLAT 1D). The choices for the different tools and libraries, particularly for our user interface, are explained in detail. The second part of this chapter covers the graphical appearance, functionality, and practical handling of CLAT 1D.

3.1 Programming Approach When creating web-based applications, the first question to be answered is on which framework the application will be developed. The answer depends on several criteria, including the technical requirements, planned applications of the final product, and the preferred development programming language. Our framework of choice for CLAT 1D is Plotly Dash (https://dash.plotly.com/) which fully supports Python development and gives us the flexibility we need to provide a seamless experience to the user. We have leveraged the capabilities of Dash using third-party libraries such as Dash Bootstrap Components (https://dash-bootstrap-components. opensource.faculty.ai) and Dash Mantine Components (https://www.dash-mantinecomponents.com) which provide additional tools to the basic framework. We also use the Plotly Open Source Graphing Library for Python (https://plotly.com/python/) to plot the models and the results. Here, we concisely cover the basic ideas and concepts deployed in creating CLAT 1D to acquaint the reader with the program flow. For further development and extension of the current source code, the interested reader is highly encouraged to consult the tutorial materials provided in Plotly Dash’s web portal. Like any other application with a graphical user interface, CLAT 1D consists of two main parts: frontend and backend. The backend is responsible for the calculations done for the composite material and its layers, while the frontend provides a user interface to communicate the input data required for those calculations, and to demonstrate the outcome of the analyses.

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2024 A. Öchsner and R. Makvandi, A Numerical Approach to the Simplified Laminate Theory of Composite Materials, Advanced Structured Materials 202, https://doi.org/10.1007/978-3-031-47984-7_3

45

46

3 Composite Laminate Analysis Tool—CLAT 1D

An object-oriented approach has been used in developing the backend of CLAT 1D; there are two main classes, i.e., laminate and lamina. An object of laminate class is a collection of lamina objects. The relation between the two classes is rather a composition than inheritance; in other words, there is no parent-child relation between the two types of objects. While most of the class methods are exposed to the user to be called inside a developing environment, there are also private methods included, which are only supposed to be called inside class-level definitions. These methods are distinguished from their public counterparts using a “__” prefix (for instance, __getBendingSubmatrix method in the laminate class definition). The main Python file starts with the definitions of some functions used for the graphical user interface which is done by importing the CLATHelpModule.py, followed by initializing the data for a sample composite material and the corresponding loading conditions for the analysis. We use Dash DataTables (https://dash.plotly. com/datatable) to provide a tool to demonstrate and modify the details of the model. An introduction to the Python programming language can be found in the common literature [1–3, 5]. In Dash @app.callback is used to handle events (an event happens, for instance, when a value inside a data table is modified). Each callback consists of input and output data which can be recognized by their tags. In a basic configuration, the input data can be provided in two ways; using input or state tags. The most crucial difference between the two is that an input triggers an event. In contrast, state data is only transmitted without being able to initiate an event. Simply put, a change in a state input will not trigger any event listeners. However, having them as inputs guarantees that the following functions use an actual version of the object. The function name coming immediately after the app.callback decorators gives a hint on what that specific callback/event is supposed to do. We have chosen the function and variable names to be self-explanatory to avoid writing unnecessary comments in the code. In general, it should be easy for the reader to go through the script line by line and understand the flow of the program, see Chap. 5.

3.2 Graphical Appearance, Functionality, and Operation To run CLAT 1D, the following program files should be located in the working directory of the computer: • main.py: The main program code to drive CLAT 1D. • Laminates_classes.py: Contains the two main classes, i.e., laminate and lamina. • globalVars.py: Contains the global variables. • CLATHelpModule: Contains all the additional functions. • requirements.txt: To install the current versions of the required libraries.

3.2 Graphical Appearance, Functionality, and Operation

47

The following command, which must be executed in a command-line interface, should be executed once to install the current versions of the required libraries: pip install -r requirements.txt Then, the command python3 main.py starts the actual CLAT 1D program. After executing this main Python file, the program provides in a shell a standard URL address, which can be copied to any common web browser such as, for example, Safari or Mozilla Firefox (see Fig. 3.1): http://127.0.0.1:8050/ Copying the URL address to a web browser opens the CLAT 1D graphical interface as indicated in Fig. 3.2.

Fig. 3.1 Execution of the main Python file in a command-line interface

Fig. 3.2 CLAT 1D graphical interface: import/export function and definition of material properties

48

3 Composite Laminate Analysis Tool—CLAT 1D

Table 3.1 Variable names used in the CLAT 1D interface for material definition (the provided units form a consistent set of units), see Fig. 3.2 Explanation Variable name Elastic constant Ex Strength parameters kt kc kepst kepsc

Elastic modulus, . E x in MPa Tensile strength, .kt in MPa Compressive strength, .kc in MPa Tensile failure strain, .ktε in – Compressive failure strain, .kcε in –

The upper part of the interface (see Import/Export Model Data) allows to open and save model files. All the models are saved in a classical MS.Excel table format. The Material Models part of the interface allows to define the material properties of each single lamina (layer) of a laminate. The used variables for elastic and strength properties are explained in detail in Table 3.1. It should be noted here that this part can serve as a material library since not all defined material sets must be used for the model definition. This part of the interface also allows a simple addition or deletion of materials. The last column of this table, i.e., Geometrical Properties, indicates an angle. This angle is only an information if the user likes to indicate that a particular material set may represent a rotated layer as in the case of two-dimensional layers with unidirectional fibers, see [4]. The Model Properties part of the interface allows to define the material (by its material ID) and geometrical properties of each single lamina (layer) of a laminate. The used variables for geometrical properties are explained in detail in Table 3.2. This part of the interface also allows a simple adding or deletion of layers or a selective inactivation of certain layers. The Load Matrix part allows the definition of the length-normalized internal reactions, i.e., a normal force and a bending moment. The total thickness of the entire laminate is provided in the Laminate Thickness part. The following options of the main CLAT 1D interface (see Fig. 3.3, very upper part) allow to open saved models, operate the update mode as well as define the computational approach for particular questions1 : • Existing models...: Allows to open saved models in MS.Excel format (see Figs. 3.4 and 3.5 for formatting details). • Regenerate graphs: Allows to manually regenerate all the result graphs.

1

A linear-elastic stress and strain analysis based on the simplified laminate theory does not require the activation of a particular computation mode since it is the default approach and executed in CLAT 1D without additional interaction.

3.2 Graphical Appearance, Functionality, and Operation

49

Table 3.2 Variable names used in the CLAT 1D interface for geometrical properties and load parameters (the provided units form a consistent set of units), see Fig. 3.2 Explanation Variable name Geometrical properties z_KminusOne zK Alpha Thickness Load parameters N_x M_y

Lower .z-coordinate of layer .k (see Fig. 2.20), .z k−1 in mm Upper .z-coordinate of layer .k (see Fig. 2.20), .z k in mm Rotation angle (just as information; not used for calculation), .α in degrees Thickness of the entire laminate (see Fig. 2.20), .t in mm Normalized internal normal force in .x-direction, . N xn in N/mm Normalized internal bending moment (see Fig. 2.18), n . M y in Nmm/mm

Fig. 3.3 CLAT 1D graphical interface: analyses options and laminate representation

• .VAutomatic Update: This default option can be deactivated to reduce the processing time. The user may need to click Regenerate graphs to show updated results. • .▢ Failure Analysis: Allows to calculate the strength ratios . R based on the maximum stress, maximum strain, Tsai-Hill, and Tsai-Wu criteria at the bottom, in the middle and at the top of each lamina of a laminate. A strength ratio of . R ≤ 1 indicates the failure of a particular lamina. • .▢ Ply-By-Ply Analysis: Allows to calculate the successive failure of single lamina in a laminate based on the Tsai-Wu criterion and to repeat the

50

3 Composite Laminate Analysis Tool—CLAT 1D

Fig. 3.4 Model definition in Microsoft Excel: material and geometrical properties of each layer (lamina)

calculation with a “reduced” laminate, i.e., a laminate where the failed lamina/laminae was/were deactivated. The following options of the main CLAT 1D interface (see Fig. 3.3) allow to display the laminate composition and the calculation results: • Sketch: This option shows the layer-wise stacking of the laminate by providing the layer numbers and the assigned material set. • Stresses: Shows graphs of the stress distribution over the laminate thickness in the global (.x-.z) coordinate systems. In addition, a numerical output in table format can be displayed. • Strains: Shows graphs of the strain distribution over the laminate thickness in the global (.x-.z) coordinate systems. In addition, a numerical output in table format can be displayed. • Failure Analysis: Displays a table of the strength ratio. R at the botton, in the middle and at the top of each layer based on the maximum stress, maximum strain, Tsai-Hill, and Tsai-Wu criteria. It requires to set the .V Failure Analysis option. • Ply-by-Ply: Displays the stress and strain distributions in the .x-direction for different steps of the ply-by-ply failure analysis, as well as the macroscopic stressstrain diagram under consideration of the layer-wise failure of single laminae. It requires to set the .V Ply-By-Ply Analysis option. Finally, it should be mentioned here that the model definition or modification can be simply done in the MS.Excel model files. Figure 3.4 shows the defined model of Fig. 3.2 as a classical MS.Excel table. Thus, the user can decide to create and modify models directly in the CLAT interface or in a MS.Excel table. Figure 3.5 shows the corresponding tables for the material sets, the load matrix, and the laminate thickness.

3.2 Graphical Appearance, Functionality, and Operation

51

(a)

(b)

(c)

Fig. 3.5 Model definition in Microsoft Excel: a material sets, b load matrix, and c laminate thickness

52

3 Composite Laminate Analysis Tool—CLAT 1D

References 1. 2. 3. 4.

Bernard, J.: Python Recipes Handbook: A Problem-Solution Approach. Apress, Berkeley (2016) Kalb, I.: Learn to Program with Python. Apress, Berkeley (2016) Lee, K.D.: Python Programming Fundamentals. Springer, London (2011) Öchsner, A., Makvandi, R.: A Numerical Approach to the Classical Laminate Theory of Composite Materials: The Composite Laminate Analysis Tool–CLAT v2.0. Springer, Cham (2023) 5. Pilgrim, M.: Dive into Python. Apress, Berkeley (2004)

Chapter 4

Application Examples

Abstract This chapters presents the solution of some standard calculation problems based on the simplified classical laminate theory. Each solution presents the major result plots or tables obtained in CLAT 1D. The presented problems comprise the calculation of stresses and strains in symmetric and asymmetric laminates, the application of failure criteria, and the ply-by-ply failure of laminates.

4.1 Introduction The following example problems are based on different materials, which are assumed to be isotropic; see Table 4.1. These material definitions were obtained from the real properties of an AS4 carbon/3501-6 epoxy prepreg system [3] by considering the methods of the off-axis transformations outlined in [1]. The last column in Table 4.1 indicates the assumed off-axis angle, i.e., the angle between the aligned fibers and the global .x-axis. All the following example problems are solved using CLAT 1D. The solution procedure without a computational tool is presented in [2].

4.2 Problem 1: Stresses and Strains in a Symmetric Laminate Given is a symmetric 8-layer laminate of thickness .t = 8 mm as shown in Fig. 4.1. Each layer has the same thickness .(t/8) but different material properties, which can be taken from Table 4.1. Consider (a) a pure tensile load case with . N xn = 1000 N/mm (the internal moment is equal to zero), (b) a pure bending load case with . M yn = 1000 Nmm/mm (the internal normal force is equal to zero), and (c) a combined load case with

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2024 A. Öchsner and R. Makvandi, A Numerical Approach to the Simplified Laminate Theory of Composite Materials, Advanced Structured Materials 202, https://doi.org/10.1007/978-3-031-47984-7_4

53

54

4 Application Examples

Table 4.1 Selected mechanical properties of different materials (the angle.α refers to the orientation of a uniaxial lamina with respect to the rod/beam .x-axis) ε ε . E x in MPa .kt in MPa .kc in MPa .kt in – .kc in – (.α in deg) Material Mat1 Mat2 Mat3 Mat4

126000 11340 16380 26586

1950 48 96 182

.−1450 .−200 .−158 .−182

0.013800 0.004360 0.006153 0.008007

◦)

.−0.011750

.(0

.−0.020000

.(90

.−0.016071

.(±45

.−0.011453

◦ .(30 )

◦) ◦)

Fig. 4.1 Cross section of a symmetric composite with 8 layers

.

N xn = 1000 N/mm and . M yn = 1000 to determine the stresses and strains in each layer in the global .x-.z coordinate system.

• Laminate loaded by . N xn .= 1000 N/mm

.

The material definitions of the different material sets in CLAT 1D are shown in Fig. 4.2. It can be seen that each material set is represented by its Young’s modulus, and the corresponding failure stresses and strains under tension and compression. The indicated angle is just provided for information and does not enter any of the following computations. The model definition of the symmetric composite with 8 layers in CLAT 1D is shown in Fig. 4.3. It can be seen that each single layer is represented with its material (repeated from the Material Models table for completeness) and geometrical properties by a single row. The applied load, i.e., . N xn = 1000 N/mm, is represented in the Load Matrix field, and the thickness of the entire laminate .(t = 8 mm) is shown in the Laminate Thickness field. The graphical representation of the symmetric composite with 8 layers in CLAT 1D is given in Fig. 4.4. Layer numbers and material sets are provided, and each different layer is represented by a different color. As a first result option, CLAT 1D can display the stress distribution over the laminate thickness. For this option, the stress is displayed in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. The stress distributions over the composite thickness shown in Fig. 4.5 provides for this particular case, i.e., a symmetric composite and a tensile load case, a symmetric stress distributions. Finally, it can be stated that the considered case results in constant stress values within each single layer.

4.2 Problem 1: Stresses and Strains in a Symmetric Laminate

Fig. 4.2 Material definitions in CLAT 1D for the composite shown in Fig. 4.1

Fig. 4.3 Model definition in CLAT 1D for the composite shown in Fig. 4.1, tensile load case

55

56

4 Application Examples

Fig. 4.4 Layer representation in CLAT 1D for the composite shown in Fig. 4.1

Fig. 4.5 Distribution of selected field quantities over the composite thickness for the tensile load case: normal stress .σx (z)

For post-processing purposes, CLAT provides, in addition to the stress diagram, the numerical stress values over the composite thickness. These values are provided at the bottom, in the middle, and at the top of each layer; see Fig. 4.6. As a second result option, CLAT 1D can display the strain distribution over the composite thickness. For this option, the strain is displayed in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. The strain distribution over the laminate thickness shown in Fig. 4.7 provides for this particular case, i.e., a symmetric composite and tensile load case, a single constant value across the entire composite thickness.

4.2 Problem 1: Stresses and Strains in a Symmetric Laminate

Fig. 4.6 Numerical stress results for the composite shown in Fig. 4.1, tensile load case Fig. 4.7 Distribution of selected field quantities over the laminate thickness for the tensile load case: normal strain .εx (z)

57

58

4 Application Examples

Fig. 4.8 Numerical strain results for the composite shown in Fig. 4.1, tensile load case

As in the case of the stress distribution, numerical values for the strain can be obtained at the bottom, in the middle, and at the top of each layer; see Fig. 4.8. • Laminate loaded by . M yn .= 1000 Nmm/mm

.

The model definition of the second load case in CLAT 1D is shown in Fig. 4.9. Only the applied load (i.e.,. M yn = 1000 Nmm/mm) must be modified in the Load Matrix field, and all other material and geometrical properties remain unchanged. The stress distributions over the composite thickness are shown in Fig. 4.10 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., a symmetric composite and bending load case, an anti-symmetric stress distribution is obtained. For post-processing purposes, the numerical stress values over the composite thickness, i.e., at the bottom, in the middle, and at the top of each layer, are provided in Fig. 4.11. The strain distributions over the laminate thickness are shown in Fig. 4.12 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., a symmetric laminate and bending load case, a perfect straight line through the coordinate origin is seen in the global (.x-.z) coordinate system.

4.2 Problem 1: Stresses and Strains in a Symmetric Laminate

59

Fig. 4.9 Model definition in CLAT 1D for the composite shown in Fig. 4.1, bending load case

Fig. 4.10 Distribution of selected field quantities over the composite thickness for the bending load case: normal stress .σx (z)

60

4 Application Examples

Fig. 4.11 Numerical stress results for the composite shown in Fig. 4.1, bending load case Fig. 4.12 Distribution of selected field quantities over the composite thickness for the bending load case: normal strain .εx (z)

4 3 2 1 0 1 2 3 4 0.002

0

0.002

4.2 Problem 1: Stresses and Strains in a Symmetric Laminate

61

Fig. 4.13 Numerical strain results for the laminate shown in Fig. 4.1, bending load case

For post-processing purposes, the numerical strain values over the composite thickness, i.e., at the bottom, in the middle, and at the top of each layer, are provided in Fig. 4.13. • Laminate loaded by . N xn = 1000 N/mm and . M yn .= 1000 Nmm/mm

.

The model definition of the third load case in CLAT 1D is shown in Fig. 4.14. Only the applied loads (i.e., . N xn = 1000 N/mm and . M yn = 1000 Nmm/mm) must be modified in the Load Matrix field, and all other material and geometrical properties remain unchanged. The stress distributions over the composite thickness are shown in Fig. 4.15 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., a symmetric composite and combined load case, layer-wise inclined lines are obtained. This is simply the superposition of the stress distributions provided in Figs. 4.5 and 4.10. For post-processing purposes, the numerical stress values over the composite thickness, i.e., at the bottom, in the middle, and at the top of each layer, are provided in Fig. 4.16.

62

4 Application Examples

Fig. 4.14 Model definition in CLAT 1D for the composite shown in Fig. 4.1, combined tensile and bending load case Fig. 4.15 Distribution of selected field quantities over the composite thickness for the combined tensile and bending load case: normal stress .σx (z)

4 3 2 1 0 1 2 3 4 500

0

500

4.2 Problem 1: Stresses and Strains in a Symmetric Laminate

63

Fig. 4.16 Numerical stress results for the composite shown in Fig. 4.1, combined tensile and bending load case

The strain distributions over the laminate thickness are shown in Fig. 4.17 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., a symmetric laminate and combined load case, a perfect straight line with a certain offset in regards to the coordinate origin is seen in the global (.x-.z) coordinate system. This is simply the superposition of the strain distributions provided in Figs. 4.7 and 4.12. For post-processing purposes, the numerical strain values over the composite thickness, i.e., at the bottom, in the middle, and at the top of each layer, are provided in Fig. 4.18.

64

4 Application Examples 4 3 2 1 0 1 2 3 4 0.005

0

0.005

Fig. 4.17 Distribution of selected field quantities over the composite thickness for the combined tensile and bending load case: normal strain .εx (z)

Fig. 4.18 Numerical strain results for the laminate shown in Fig. 4.1, combined tensile and bending load case

4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate

65

Fig. 4.19 Cross section of an asymmetric composite with 8 layers

4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate Given is an asymmetric 8-layer laminate of thickness.t = 8 mm as shown in Fig. 4.19. Each layer has the same thickness .(t/8) but different material properties, which can be taken from Table 4.1. Consider (a) a pure tensile load case with . N xn = 1000 N/mm (the internal moment is equal to zero), (b) a pure bending load case with . M yn = 1000 Nmm/mm (the internal normal force is equal to zero), and (c) a combined load case with . N xn = 1000 N/mm and . M yn = 1000 to determine the stresses and strains in each layer in the global .x-.z coordinate system. • Laminate loaded by . N xn .= 1000 N/mm

.

The material definitions of the different material sets in CLAT 1D are shown in Fig. 4.20. It can be seen that each material set is represented by its Young’s modulus, and the corresponding failure stresses and strains under tension and compression. The indicated angle is just provided for information and does not enter any of the following computations. The model definition of the asymmetric composite with 8 layers in CLAT 1D is shown in Fig. 4.21. It can be seen that each single layer is represented with its material (repeated from the Material Models table for completeness) and geometrical properties by a single row. The applied load, i.e., . N xn = 1000 N/mm, is represented in the Load Matrix field and the thickness of the entire laminate .(t = 8 mm) is shown in the Laminate Thickness field. The graphical representation of the asymmetric composite with 8 layers in CLAT 1D is given in Fig. 4.22. Layer numbers and material sets are provided and each different layer is represented by a different color. As a first result option, CLAT 1D can display the stress distribution over the laminate thickness. For this option, the stress is displayed in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. The stress distribution over the composite thickness shown in Fig. 4.23 provides for this particular case, i.e., an asymmetric composite and a tensile load case, layer-wise inclined distributions. Thus, it can be

66

4 Application Examples

Fig. 4.20 Material definitions in CLAT 1D for the composite shown in Fig. 4.19

Fig. 4.21 Model definition in CLAT 1D for the composite shown in Fig. 4.19, tensile load case

4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate Fig. 4.22 Layer representation in CLAT 1D for the composite shown in Fig. 4.19

67

Layer 8 (Mat 3)

Layer 7 (Mat 3)

Layer 6 (Mat 2)

Layer 5 (Mat 1)

Layer 4 (Mat 2)

Layer 3 (Mat 1)

Layer 2 (Mat 3)

Layer 1 (Mat 3)

Fig. 4.23 Distribution of selected field quantities over the composite thickness for the tensile load case: normal stress .σx (z)

4 3 2 1 0 1 2 3 4 400

200

0

200

400

stated that the considered tensile case results in non-constant stress values within each single layer. For post-processing purposes, CLAT provides, in addition to the stress diagram, the numerical stress values over the composite thickness. These values are provided at the bottom, in the middle, and at the top of each layer; see Fig. 4.24.

68

4 Application Examples

Fig. 4.24 Numerical stress results for the composite shown in Fig. 4.19, tensile load case

As a second result option, CLAT 1D can display the strain distribution over the composite thickness. For this option, the strain is displayed in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. The strain distribution over the laminate thickness shown in Fig. 4.25 provides for this particular case, i.e., an asymmetric composite and tensile load case, a single straight line curve across the entire composite thickness. As in the case of the stress distribution, numerical values for the strain can be obtained at the bottom, in the middle, and at the top of each layer; see Fig. 4.26. • Laminate loaded by . M yn .= 1000 Nmm/mm

.

The model definition of the second load case in CLAT 1D is shown in Fig. 4.27. Only the applied load (i.e., . M yn .= 1000 Nmm/mm) must be modified in the Load Matrix field, and all other material and geometrical properties remain unchanged. The stress distributions over the composite thickness are shown in Fig. 4.28 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., a layer-wise linear distribution, with the characteristic that the stress is proportional to the stiffness value of each layer, is obtained.

4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate

69

4 3 2 1 0 1 2 3 4 0.004

0.002

0

0.002

0.004

Fig. 4.25 Distribution of selected field quantities over the laminate thickness for the tensile load case: normal strain .εx (z)

Fig. 4.26 Numerical strain results for the composite shown in Fig. 4.19, tensile load case

70

4 Application Examples

Fig. 4.27 Model definition in CLAT 1D for the composite shown in Fig. 4.19, bending load case Fig. 4.28 Distribution of selected field quantities over the composite thickness for the bending load case: normal stress .σx (z)

4 3 2 1 0 1 2 3 4 200

100

0

100

200

4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate

71

Fig. 4.29 Numerical stress results for the composite shown in Fig. 4.19, bending load case

For post-processing purposes, the numerical stress values over the composite thickness, i.e., at the bottom, in the middle, and at the top of each layer, are provided in Fig. 4.29. The strain distributions over the laminate thickness are shown in Fig. 4.30 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., an asymmetric laminate and bending load case, a perfect straight line with a certain offset in regards to the coordinate origin is seen in the global (.x-.z) coordinate system. This suggests a tension/bending coupling, i.e., a superposition of a constant and linear distribution for the strains. For post-processing purposes, the numerical strain values over the composite thickness, i.e., at the bottom, in the middle, and at the top of each layer, are provided in Fig. 4.31. • Laminate loaded by . N xn = 1000 N/mm and . M yn .= 1000 Nmm/mm

.

The model definition of the third load case in CLAT 1D is shown in Fig. 4.32. Only the applied loads (i.e., . N xn = 1000 N/mm and . M yn .= 1000 Nmm/mm) must be modified

72

4 Application Examples 4 3 2 1 0 1 2 3 4 0.004

0.002

0

0.002

0.004

Fig. 4.30 Distribution of selected field quantities over the composite thickness for the bending load case: normal strain .εx (z)

Fig. 4.31 Numerical strain results for the laminate shown in Fig. 4.19, bending load case

4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate

73

Fig. 4.32 Model definition in CLAT 1D for the composite shown in Fig. 4.1, combined tensile and bending load case

in the Load Matrix field, and all other material and geometrical properties remain unchanged. The stress distributions over the composite thickness are shown in Fig. 4.33 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., an asymmetric composite and combined load case, layer-wise inclined lines are obtained. For post-processing purposes, the numerical stress values over the composite thickness, i.e., at the bottom, in the middle, and at the top of each layer, are provided in Fig. 4.34. The strain distributions over the laminate thickness are shown in Fig. 4.35 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., an asymmetric laminate and combined load case, a perfect straight line with a certain offset in regards to the coordinate origin is seen in the global (.x-.z) coordinate system. For post-processing purposes, the numerical strain values over the composite thickness, i.e., at the bottom, in the middle, and at the top of each layer, are provided in Fig. 4.36.

74

4 Application Examples 4 3 2 1 0 1 2 3 4 500

0

500

Fig. 4.33 Distribution of selected field quantities over the composite thickness for the combined tensile and bending load case: normal stress .σx (z)

Fig. 4.34 Numerical stress results for the composite shown in Fig. 4.19, combined tensile and bending load case

4.3 Problem 2: Stresses and Strains in an Asymmetric Laminate

75

4 3 2 1 0 1 2 3 4 0.01

0.005

0

0.005

0.01

Fig. 4.35 Distribution of selected field quantities over the composite thickness for the combined tensile and bending load case: normal strain .εx (z)

Fig. 4.36 Numerical strain results for the laminate shown in Fig. 4.19, combined tensile and bending load case

76

4 Application Examples

4.4 Problem 3: Failure Criteria Given is an asymmetric 4-layer laminate of thickness.t = 8 mm as shown in Fig. 4.37. Each layer has the same thickness .(t/4) but different material properties, which can be taken from Table 4.1. Consider (a) a tensile load case with . N xn = 1000 N/mm (the internal moment is equal to zero), (b) a bending load case with . M yn = 1000 Nmm/mm (the internal normal force is equal to zero), and (c) a combined load case with . N xn = 1000 N/mm and . M yn = 1000 Nmm/mm to determine the stresses and strains in each layer in the global .x-.z coordinate system. Use these stress and strain values to perform a failure analysis based on the maximum stress, maximum strain, and Tsai-Wu failure criteria. • Laminate loaded by . N xn .= 1000 N/mm

.

The material definitions of the different material sets in CLAT 1D are shown in Fig. 4.38. It can be seen that each material set is represented by its Young’s modulus, and the corresponding failure stresses and strains under tension and compression. The indicated angle is just provided for information and does not enter any of the following computations. The model definition of the asymmetric composite with 4 layers in CLAT 1D is shown in Fig. 4.39. It can be seen that each single layer is represented with its material (repeated from the Material Models table for completeness) and geometrical properties by a single row. The applied load, i.e., . N xn = 1000 N/mm, is represented in the Load Matrix field and the thickness of the entire laminate .(t = 8 mm) is shown in the Laminate Thickness field. The graphical representation of the asymmetric composite with 4 layers in CLAT 1D is given in Fig. 4.40. Layer numbers and material sets are provided, and each different layer is represented by a different color. The stress distributions over the composite thickness are shown in Fig. 4.41 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., an asymmetric composite under tensile loading, a layer-wise linear distribution, with the characteristic that the stress is proportional to the stiffness value of each layer, is obtained. The strain distribution over the laminate thickness is shown in Fig. 4.42 and provides for this particular case, i.e., an asymmetric composite and tensile load case, a single straight line curve with a certain offset to the coordinate origin.

Fig. 4.37 Cross section of an asymmetric composite with 4 layers

4.4 Problem 3: Failure Criteria

77

Fig. 4.38 Material definitions in CLAT 1D for the composite shown in Fig. 4.37

Fig. 4.39 Model definition in CLAT 1D for the composite shown in Fig. 4.37, tensile load case

The strength ratio . R at the bottom, in the middle, and at the top of each layer based on the maximum stress, maximum strain, Tsai-Hill, and Tsai-Wu criteria can be displayed by using the Failure Analysis option; see Fig. 4.43. No critical locations for failure, i.e., with a strength ratio . R ≤ 1, are detected for this case. • Laminate loaded by . M yn = 1000 Nmm/mm

.

The model definition of the second load case in CLAT 1D is shown in Fig. 4.44. Only the applied load (i.e., . M yn .= 1000 Nmm/mm) must be modified in the Load Matrix field, and all other material and geometrical properties remain unchanged.

78

4 Application Examples

Layer 4 (Mat 3)

Layer 3 (Mat 4)

Layer 2 (Mat 1)

Layer 1 (Mat 3)

Fig. 4.40 Layer representation in CLAT 1D for the composite shown in Fig. 4.37 4 3 2 1 0 1 2 3 4 400

200

0

200

400

Fig. 4.41 Distribution of selected field quantities over the composite thickness for the tensile load case: normal stress .σx (z)

4.4 Problem 3: Failure Criteria

79

4 3 2 1 0 1 2 3 4 0.005

0

0.005

Fig. 4.42 Distribution of selected field quantities over the laminate thickness for the tensile load case: normal strain .εx (z)

Fig. 4.43 Numerical . R-values for the laminate shown in Fig. 4.37, tensile load case

The stress distributions over the composite thickness are shown in Fig. 4.45 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., an asymmetric composite under bending loading, a layer-wise linear distribution, with the characteristic that the stress is proportional to the stiffness value of each layer, is obtained. The strain distribution over the laminate thickness is shown in Fig. 4.46 and provides for this particular case, i.e., an asymmetric composite and bending load case, a single straight line curve with a certain offset to the coordinate origin.

80

4 Application Examples

Fig. 4.44 Model definition in CLAT 1D for the composite shown in Fig. 4.37, bending load case Fig. 4.45 Distribution of selected field quantities over the composite thickness for the bending load case: normal stress .σx (z)

4 3 2 1 0 1 2 3 4 200

100

0

100

200

The strength ratio . R at the bottom, in the middle, and at the top of each layer based on the maximum stress, maximum strain, Tsai-Hill, and Tsai-Wu criteria can be displayed by using the Failure Analysis option; see Fig. 4.47. No critical locations for failure, i.e., with a strength ratio . R ≤ 1, are detected for this case.

4.4 Problem 3: Failure Criteria

81

4 3 2 1 0 1 2 3 4 0.005

0

0.005

Fig. 4.46 Distribution of selected field quantities over the laminate thickness for the bending load case: normal strain .εx (z)

Strength Ratio R Layer no.

Position

Direction

Stress Max

Strain Max

Tsai-Hill

1

Bottom

x

2.539

4.231

2.539

Tsai-Wu 2.539

1

Middle

x

3.570

5.948

3.570

3.570 6.009

1

Top

x

6.009

10.011

6.009

2

Bottom

x

7.169

7.320

7.169

7.169

2

Middle

x

22.631

23.107

22.631

22.631

2

Top

x

26.308

23.459

26.308

26.308

3

Bottom

x

11.637

13.611

11.637

11.637

3

Middle

x

4.063

4.752

4.063

4.063

3

Top

x

2.461

2.878

2.461

2.461

4

Bottom

x

2.107

2.212

2.107

2.107

4

Middle

x

1.511

1.586

1.511

1.511

4

Top

x

1.178

1.237

1.178

1.178

Fig. 4.47 Numerical . R-values for the laminate shown in Fig. 4.37, bending load case

• Laminate loaded by . N xn = 1000 N/mm and . M yn = 1000 Nmm/mm

.

The model definition of the third load case in CLAT 1D is shown in Fig. 4.48. Only the applied load (i.e., . N xn = 1000 N/m and . M yn = 1000 Nmm/mm) must be modified in the Load Matrix field and all other material and geometrical properties remain unchanged. The stress distributions over the composite thickness are shown in Fig. 4.49 in the global .x-.z coordinate system (see Fig. 1.2) of the entire composite. It can be seen that for this particular case, i.e., an asymmetric composite under combined loading,

82

4 Application Examples

Fig. 4.48 Model definition in CLAT 1D for the composite shown in Fig. 4.37, combined load case Fig. 4.49 Distribution of selected field quantities over the composite thickness for the combined load case: normal stress .σx (z)

4 3 2 1 0 1 2 3 4 400

200

0

200

400

a layer-wise linear distribution, with the characteristic that the stress is proportional to the stiffness value of each layer, is obtained. The strain distribution over the laminate thickness is shown in Fig. 4.50 and provides for this particular case, i.e., an asymmetric composite and combined load case, a single straight line curve with a certain offset to the coordinate origin.

4.4 Problem 3: Failure Criteria

83

4 3 2 1 0 1 2 3 4 0.01

0.005

0

0.005

0.01

Fig. 4.50 Distribution of selected field quantities over the laminate thickness for the combined load case: normal strain .εx (z)

Strength Ratio R Layer no.

Position

Direction

Stress Max

Strain Max

Tsai-Hill

Tsai-Wu

1

Bottom

x

3.073

5.120

3.073

3.073

1

Middle

x

6.636

11.056

6.636

6.636

1

Top

x

25.330

26.592

25.330

25.330

2

Bottom

x

66.886

59.642

66.886

66.886

2

Middle

x

8.076

7.201

8.076

8.076

2

Top

x

4.297

3.832

4.297

4.297

3

Bottom

x

1.901

2.223

1.901

1.901

3

Middle

x

1.295

1.515

1.295

1.295

3

Top

x

0.982

1.149

0.982

0.982

4

Bottom

x

0.841

0.883

0.841

0.841

4

Middle

x

0.677

0.711

0.677

0.677

4

Top

x

0.567

0.595

0.567

0.567

Fig. 4.51 Numerical . R-values for the laminate shown in Fig. 4.37, combined load case

The strength ratio . R at the bottom, in the middle, and at the top of each layer based on the maximum stress, maximum strain, Tsai-Hill, and Tsai-Wu criteria can be displayed by using the Failure Analysis option; see Fig. 4.47. Critical locations for failure, i.e., with a strength ratio . R ≤ 1, are highlighted with a red background color (Fig. 4.51).

84

4 Application Examples

4.5 Problem 4: Ply-By-Ply Failure Loads Given is a symmetric 3-layer laminate of thickness .t = 9 mm as shown in Fig. 4.52. Each layer has the same thickness .(t/3) but material properties may vary from layer to layer; see Table 4.1. Consider a pure tensile load case with . N xn > 0 (the internal bending moment is equal to zero) to investigate the ply-by-ply failure of this laminate based on the maximum stress criterion. Solution: The material definitions of the different material sets in CLAT 1D are shown in Fig. 4.53. It can be seen that each material set is represented by its Young’s modulus, and the corresponding failure stresses and strains under tension and compression. The indicated angle is just provided for information and does not enter any of the following computations.

Fig. 4.52 Cross section of a symmetric composite with 3 layers

Fig. 4.53 Material definitions in CLAT 1D for the composite shown in Fig. 4.52

4.5 Problem 4: Ply-By-Ply Failure Loads

85

Fig. 4.54 Model definition in CLAT 1D for the composite shown in Fig. 4.52, tensile load case Fig. 4.55 Layer representation in CLAT 1D for the composite shown in Fig. 4.52

Layer 3 (Mat 1)

Layer 2 (Mat 2)

Layer 1 (Mat 1)

The model definition of the symmetric composite with 3 layers in CLAT 1D is shown in Fig. 4.54. It can be seen that each single layer is represented with its material (repeated from the Material Models table for completeness) and geometrical properties by a single row. A unit load, i.e.,. N xn = 1 N/mm, is represented in the Load Matrix field and the thickness of the entire laminate .(t = 9 mm) is shown in the Laminate Thickness field. It is important to note that the solution procedure /Ply-By-Ply Analysis option. requires to set the .▢

86

4 Application Examples

4

4

2

2

0

0

2

2

4

4 0.1

0



0.1

0



Fig. 4.56 Stress and strain distributions in the .x-direction for the laminate shown in Fig. 4.52, ply-by-ply failure (Step 0) 4

4

2

2

0

0

2

2

4

4 0.1

0

0.1



0



Fig. 4.57 Stress and strain distributions in the .x-direction for the laminate shown in Fig. 4.52, ply-by-ply failure (Step 1)

The graphical representation of the symmetric composite with 3 layers in CLAT 1D is given in Fig. 4.55. Layer numbers and material sets are provided, and each different layer is represented by a different color. Figures 4.56, 4.57 and 4.58 display the stress and strain distributions in the .xdirection for different steps of the ply-by-ply failure analysis. Step 0 represents the original configuration at which all layers are in good shape and take part of the load; see Fig. 4.56. Step 1 represents the situation with one layer, i.e., Layer 2 already failed. Thus, the stress and strain distributions are zero in the range of Layer 2, i.e., .−2 ≤ z ≤ +2; see Fig. 4.57.

4.5 Problem 4: Ply-By-Ply Failure Loads

87

4

4

2

2

0

0

2

2

4

4 1

0.5

0

0.5

1

1

0.5

0

0.5

1

Fig. 4.58 Stress and strain distributions in the .x-direction for the laminate shown in Fig. 4.52, ply-by-ply failure (Step 2)

Fig. 4.59 Macroscopic stress-strain diagram to illustrate the ply-by-ply failure of the laminate shown in Fig. 4.52

The final stage with all layers failed is represented by Step 2; see Fig. 4.58. Now the stress and strain is everywhere across the thickness zero. The macroscopic stress-strain diagram under consideration of the layer-wise failure of single laminae is presented in Fig. 4.59.

88

4 Application Examples

References 1. Öchsner, A.: Foundations of Classical Laminate Theory. Springer, Cham (2022) 2. Öchsner, A.: A Simplified Approach to the Classical Laminate Theory of Composite Materials: Application of Bar and Beam Elements. Springer, Cham (2023) 3. Soden, P.D., Hinton, M.J., Kaddour, A.S.: Lamina properties, lay-up configurations and loading conditions for a range of fibre-reinforced composite laminates. Compos. Sci. Technol. 58, 1011– 1022 (1998). https://doi.org/10.1016/S0266-3538(98)00078-5

Chapter 5

Source Codes

Abstract This chapter provides the commented and structured source codes of the Python files which contains all the written routines.

5.1 main.py To easily navigate in the source code of the file main.py, Table 5.1 collects in chronological order all the callbacks and the corresponding line in the source code. Table 5.1 Line numbers of the callbacks in main.py

Callback

Program line

addRowToDataFrame saveModelAsExcel unselectCells styleSelectedRows renderTabContent updateListOfExistingModels generateGraphs

127 192 217 232 268 299 320

main.py (main file) 1 2 3 4 5 6 7 8 9 10 11

""" This is the main Python file of CLAT """ import io import os import fnmatch import dash from dash import Input, Output, State, no_update, ALL, ctx import globalVars from Laminates_classes import Laminate from CLATHelpModule import *

© The Author(s), under exclusive license to Springer Nature Switzerland AG 2024 A. Öchsner and R. Makvandi, A Numerical Approach to the Simplified Laminate Theory of Composite Materials, Advanced Structured Materials 202, https://doi.org/10.1007/978-3-031-47984-7_5

89

90 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

5 Source Codes

# current directory cwd = os.getcwd() # find all the xlsx files in the current directory problemFiles = sorted(fnmatch.filter(os.listdir(cwd), "*.xlsx"))

materials = { 1: { "Ex": 126000.0, "kt": 1950.0, "kc": -1450.0, "kepst": 1.3800e-2, "kepsc": → -1.1750e-2, "alpha": +0.0 }, 2: { "Ex": 11340.0, "kt": 48.0, "kc": -200.0, "kepst": 0.4360e-2, "kepsc": → -2.0000e-2, "alpha": +90.0 }, 3: { "Ex": 16380.0, "kt": 96.0, "kc": -158.0, "kepst": 0.6153e-2, "kepsc": → -1.6071e-2, "alpha": +45.0 }, 4: { "Ex": 26586.0, "kt": 182.0, "kc": -182.0, "kepst": 0.8007e-2, "kepsc": → -1.1453e-2, "alpha": +30.0 } } elasticProperties = {"Ex": 126000.0} strengthParameters = {"kt": 1950.0, "kc": -1450.0, "kepst": 1.38e → -2, "kepsc": -1.175e-2} geometricalProperties = {"zKminusOne": -4.0, "zK": -3.0, "alpha": → +45.0} laminateListOfLayers = { 0: ({"Material": 3} | materials[3] | {"zKminusOne": -4.0, → -3.0, "alpha": +45.0}), 1: ({"Material": 3} | materials[3] | strengthParameters | → zKminusOne": -3.0, "zK": -2.0, "alpha": 45.0}), 2: ({"Material": 1} | materials[1] | strengthParameters | → zKminusOne": -2.0, "zK": -1.0, "alpha": 0.0}), 3: ({"Material": 2} | materials[2] | strengthParameters | → zKminusOne": -1.0, "zK": 0.0, "alpha": 90.0}), 4: ({"Material": 1} | materials[2] | strengthParameters | → zKminusOne": 0.0, "zK": +1.0, "alpha": 0.0}), 5: ({"Material": 2} | materials[1] | strengthParameters | → zKminusOne": +1.0, "zK": +2.0, "alpha": 90.0}), 6: ({"Material": 3} | materials[3] | strengthParameters | → zKminusOne": +2.0, "zK": +3.0, "alpha": 45.0}),

"zK": {" {" {" {" {" {"

5.1 main.py 7: ({"Material": 3} | materials[3] | strengthParameters | {" → zKminusOne": +3.0, "zK": +4.0, "alpha": 45.0})

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

91

} loadMatrix = { 0: {"N_x": 1000.0, "M_y": 0.0} } thickness = { 0: {"Thickness": 8.0} } thicknessDataFrame = pd.DataFrame.from_dict(thickness, orient=’ → index’, columns=["Thickness"]) materialDataFrame = pd.DataFrame.from_dict(materials, orient=’index → ’, columns=["Ex", "kt", "kc", "kepst", "kepsc", "alpha"]) materialDataFrame[’Material’] = np.arange(0, len(materialDataFrame) → ) + 1 globalVars.failureAnalysisFailedPlies = [] globalVars.failedPlies = [] df = pd.DataFrame.from_dict( laminateListOfLayers, orient=’index’, columns=[’Layer’, ’Material’, ’Ex’, ’kt’, ’kc’, ’kepst’, ’kepsc’ → ,’zKminusOne’, ’zK’, ’alpha’, ’thickness’] ) df["id"] = df.index df[’Layer’] = np.arange(0, len(df)) + 1 df[’thickness’] = df[’zK’] - df[’zKminusOne’] loadMatrixDataFrame = pd.DataFrame.from_dict( loadMatrix, orient=’index’, columns=["N_x", "M_y"] ) # initialize the Dash app with a template from Dash Bootstrap dbc_css = "https://cdn.jsdelivr.net/gh/AnnMarieW/dash-bootstrap→ [email protected]" app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP, dbc_css], suppress_callback_exceptions=True ) app.title = "CLAT 1D" app.layout = html.Div( dbc.Container( [ dcc.Store(id="store"), html.H1("Composite Laminate Analysis Tool - CLAT 1D"), html.Hr(), getLoadingOverlay(df, loadMatrixDataFrame, → thicknessDataFrame, materialDataFrame), html.Hr(), getAnalysisOptionsRow(problemFiles), html.Hr(), getAnalysisTabs(), html.Div(id="tab-content", className="p-4") ]

92 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

128 129 130 131 132 133 134 135

136 137 138 139 140 141 142 143 144 145 146

147

5 Source Codes ) )

@app.callback( Output({’type’: ’table’, ’index’: ’myTable’}, ’data’), Output({’type’: ’table’, ’index’: ’myLoadMatrixTable’}, ’data’), Output({’type’: ’table’, ’index’: ’thicknessMatrix’}, ’data’), Output({’type’: ’table’, ’index’: ’myMaterialTable’}, ’data’), Output(’addRowAfterIndex’, ’max’), Output(’addMaterialRowAfterIndex’, ’max’), Input(’editing-rows-button’, ’n_clicks’), Input(’editing-material-rows-button’, ’n_clicks’), Input({’type’: ’table’, ’index’: ’myTable’}, ’data’), Input({’type’: ’table’, ’index’: ’myLoadMatrixTable’}, ’data’), Input({’type’: ’table’, ’index’: ’thicknessMatrix’}, ’data’), Input({’type’: ’table’, ’index’: ’myMaterialTable’}, ’data’), State(’addRowAfterIndex’, ’value’), State(’addMaterialRowAfterIndex’, ’value’), Input(’datatable-upload’, ’contents’), State(’datatable-upload’, ’filename’), Input(’dropdown-menu’, ’value’), prevent_initial_call=True, ) def addRowToDataFrame(n_clicks_ModelDataFrameRowsButton, → n_clicks_MaterialDataFrameRowsButton, modelPropertiesTable, → loadMatrixTable, thicknessMatrixTable, materialTable, → addRowAfterIndex, addMaterialRowAfterIndex, contents, → filename, problemName): if dash.callback_context.triggered[0][’prop_id’] == ’editing→ rows-button.n_clicks’: if n_clicks_ModelDataFrameRowsButton > 0: if addRowAfterIndex is None: modelPropertiesTable.append(copy.copy( → modelPropertiesTable[-1])) else: try: modelPropertiesTable.insert(addRowAfterIndex, → copy.copy(modelPropertiesTable[ → addRowAfterIndex - 1])) except Exception as e: print(e) print(’Wrong value for the layer number!’) if dash.callback_context.triggered[0][’prop_id’] == ’editing→ material-rows-button.n_clicks’: if n_clicks_MaterialDataFrameRowsButton > 0: if addMaterialRowAfterIndex is None: materialTable.append(copy.copy(materialTable[-1])) else: try: materialTable.insert(addMaterialRowAfterIndex, → copy.copy(materialTable[ → addMaterialRowAfterIndex - 1])) except Exception as e:

5.1 main.py 148 149 150 151 152 153 154 155 156

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181

182 183 184 185

93 print(e) print(’Wrong value for the material number!’)

if dash.callback_context.triggered[0][’prop_id’] == ’datatable→ upload.contents’: globalVars.failureAnalysisFailedPlies = [] globalVars.failedPlies = [] if contents is None: raise dash.exceptions.PreventUpdate [newModelProperties, newloadMatrix, newThicknessMatrix, → materialProperties] = parse_contents(contents, → filename) modelPropertiesTable = newModelProperties.to_dict(’records’) materialPropertiesTable = materialProperties.to_dict(’ → records’) loadMatrixTable = newloadMatrix.to_dict(’records’) thicknessMatrixTable = newThicknessMatrix.to_dict(’records’) if dash.callback_context.triggered[0][’prop_id’] == ’dropdown→ menu.value’: if problemName is None: raise dash.exceptions.PreventUpdate modelPropertiesTable = pd.read_excel(problemName, sheet_name → ="ModelProperties").to_dict(’records’) loadMatrixTable = pd.read_excel(problemName, sheet_name=" → LoadMatrix").to_dict(’records’) thicknessMatrixTable = pd.read_excel(problemName, sheet_name → ="thicknessMatrix").to_dict(’records’) # if dash.callback_context.triggered[0][’prop_id’] == ’{"index → ":"myMaterialTable","type":"table"}.data’ \ # or dash.callback_context.triggered[0][’prop_id’] == ’{"index → ":"myTable","type":"table"}.data’: for i in np.arange(0, len(modelPropertiesTable)): layerMaterialModel = modelPropertiesTable[i]["Material"] modelPropertiesTable[i]["Ex"] = materialTable[ → layerMaterialModel-1]["Ex"] modelPropertiesTable[i]["kt"] = materialTable[ → layerMaterialModel-1]["kt"] modelPropertiesTable[i]["kc"] = materialTable[ → layerMaterialModel-1]["kc"] modelPropertiesTable[i]["kepst"] = materialTable[ → layerMaterialModel-1]["kepst"] modelPropertiesTable[i]["kepsc"] = materialTable[ → layerMaterialModel-1]["kepsc"] modelPropertiesTable[i]["alpha"] = materialTable[ → layerMaterialModel-1]["alpha"] updateLayerColumn(modelPropertiesTable, materialTable) return modelPropertiesTable, loadMatrixTable, → thicknessMatrixTable, materialTable, len( → modelPropertiesTable), len(materialTable) @app.callback( Output("download-dataframe-xlsx", "data"), Input("btn_xlsx", "n_clicks"),

94 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

5 Source Codes State({’type’: ’table’, ’index’: State({’type’: ’table’, ’index’: State({’type’: ’table’, ’index’: State({’type’: ’table’, ’index’: prevent_initial_call=True,

"myTable"}, "data"), "myLoadMatrixTable"}, "data"), "thicknessMatrix"}, "data"), "myMaterialTable"}, "data"),

) def saveModelAsExcel(n_clicks, data, loadMat, thicknessMat, → materialData): output = io.BytesIO() excelFileWriter = pd.ExcelWriter(output, engine=’xlsxwriter’) modelPropertiesDataFrame = pd.DataFrame(data) materialModelsDataFrame = pd.DataFrame(materialData) loadMatDataFrame = pd.DataFrame(loadMat) thicknessMatDataFrame = pd.DataFrame(thicknessMat) modelPropertiesDataFrame.to_excel(excelFileWriter, sheet_name=’ → ModelProperties’) materialDataFrame.to_excel(excelFileWriter, sheet_name=’ → MaterialProperties’) loadMatDataFrame.to_excel(excelFileWriter, sheet_name=’ → LoadMatrix’, index=False) thicknessMatDataFrame.to_excel(excelFileWriter, sheet_name=’ → thicknessMatrix’, index=False) excelFileWriter.close() data = output.getvalue() return dcc.send_bytes(data, "problem_data.xlsx")

# read the following page for more info # https://community.plotly.com/t/how-to-reset-dash-datatable→ selected-cells-varaible-to-none-from-within-a-callback → /48588/4 @app.callback( Output({’type’: ’table’, ’index’: ALL}, ’selected_cells’), Output({’type’: ’table’, ’index’: ALL}, ’active_cell’), Input({’type’: ’table’, ’index’: ALL}, ’selected_cells’), State({’type’: ’table’, ’index’: ALL}, ’id’), prevent_initial_call=True ) def unselectCells(cells, tables): table_ids = [t[’index’] for t in tables] trigger = ctx.triggered_id.index # only works if you have dash → >=2.4.0 new_selection = [[] if t != trigger else c for c, t in zip(cells → , table_ids)] new_active = [None if s == [] else s[0] for s in new_selection] return new_selection, new_active

@app.callback( Output({’type’: ’table’, ’index’: "myTable"}, " → style_data_conditional"), Output({’type’: ’table’, ’index’: "myTable"}, " → tooltip_conditional"), Input({’type’: ’table’, ’index’: "myTable"}, " → derived_viewport_selected_row_ids"),

5.1 main.py 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

95

Input({’type’: ’table’, ’index’: "myTable"}, " → style_data_conditional"), Input({’type’: ’table’, ’index’: "myTable"}, "selected_rows"), ) def styleSelectedRows(selRows, styleConditioning, rows): # we only want the "main" style conditioning to stay forever styleConditioning = styleConditioning[0:3] if selRows is None: return dash.no_update new = [ { "if": { "filter_query": "{{id}} ={}".format(i) }, ’backgroundColor’: ’#800000’, ’color’: ’lightgray’, } for i in selRows] styleConditioning.extend(new) tooltip_conditional = [ { ’if’: { ’filter_query’: "{{id}} ={}".format(i) }, ’type’: ’markdown’, ’value’: ’This layer will be **excluded** from the → analyses.’ } for i in selRows ] return styleConditioning, tooltip_conditional

@app.callback( Output("tab-content", "children"), Input("tabs", "active_tab"), Input("store", "data"), Input("failureAnalysis", "value"), Input("plyByPlyAnalysisCheckBox", "value") ) def renderTabContent(active_tab, data, failureAnalysis, → plyByPlyAnalysis): """ This callback takes the ’active_tab’ property as input, as well → as the stored graphs, and renders the tab content depending on what the → value of ’active_tab’ is. """ if active_tab and data is not None: if active_tab == "tabSketch": return getCustomizedGraph(data["sketch"], {"fileName": " → sketch"}) elif active_tab == "tabStresses":

96 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

5 Source Codes return data["stressAnalysis"] elif active_tab == "tabStrains": return data["strainAnalysis"] elif (active_tab == "tabFailureAnalysis") and ("Failure → Analysis" not in failureAnalysis): return dbc.Alert("Failure Analysis is not active.", → color="info") elif (active_tab == "tabFailureAnalysis") and ("Failure → Analysis" in failureAnalysis): return data["failureAnalysis"] elif (active_tab == "tabPlyByPly") and ("Ply-By-Ply Analysis → " not in plyByPlyAnalysis): return dbc.Alert("Ply-By-Ply Analysis is not active.", → color="info") elif (active_tab == "tabPlyByPly") and ("Ply-By-Ply Analysis → " in plyByPlyAnalysis): return data["plyByPly"] return ""

@app.callback( Output("dropdown-menu", "options"), Input("dropdownParent", ’n_clicks’), prevent_initial_call=True, ) def updateListOfExistingModels(n): # current directory # cwd = os.getcwd() # find all the Excel files in the current directory modelFiles = fnmatch.filter(os.listdir(cwd), "*.xlsx") return sorted(modelFiles)

@app.callback(Output("store", "data"), Output("loading-output", "children"), Output({’type’: ’table’, ’index’: ’myTable’}, ’ → selected_rows’), Input("button", "n_clicks"), Input({’type’: ’table’, ’index’: "myTable"}, "data"), Input({’type’: ’table’, ’index’: "myLoadMatrixTable"}, → "data"), Input({’type’: ’table’, ’index’: "thicknessMatrix"}, " → data"), Input({’type’: ’table’, ’index’: "myTable"}, " → derived_virtual_selected_rows"), State("automaticUpdate", "value"), Input("failureAnalysis", "value"), Input("plyByPlyAnalysisCheckBox", "value"), prevent_initial_call=True, ) def generateGraphs(n, rows, loadMat, thicknessMat, → userSelectedFailedPlies, automaticUpdate, failureAnalysis, plyByPlyAnalysis): globalVars.failedPlies = globalVars.failureAnalysisFailedPlies + → userSelectedFailedPlies

5.1 main.py 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362

97

changed_id = [p[’prop_id’] for p in dash.callback_context. → triggered][0] if OR("Automatic Update" in automaticUpdate, "button" in → changed_id): laminateSketch = getLaminateSketch(rows, → userSelectedFailedPlies) laminateObject = Laminate({}) dataFrame = pd.DataFrame(rows) dataFrame = dataFrame.drop([’Layer’], axis=1) laminateObject.addLaminae(dataFrame.to_dict(’index’)) loadMatDataFrame = pd.DataFrame(loadMat) laminateObject.updateLoadMatrix(loadMatDataFrame.to_numpy(). → transpose()) laminateObject.setThickness(pd.DataFrame(thicknessMat)[" → Thickness"]) failureAnalysisContainer = {} if "Failure Analysis" in failureAnalysis: failureAnalysisContainer = getFailureAnalysisContainer( → laminateObject) plyByPlyContainer = {} if "Ply-By-Ply Analysis" in plyByPlyAnalysis: backup = globalVars.failureAnalysisFailedPlies backup2 = globalVars.failedPlies globalVars.failureAnalysisFailedPlies = [] globalVars.failedPlies = [] plyByPlyContainer = getPlyByPlyAnalysis(laminateObject, → userSelectedFailedPlies) globalVars.failedPlies = backup2 globalVars.failureAnalysisFailedPlies = backup return {"sketch": laminateSketch, "stressAnalysis": getStressAnalysisContainer( → laminateObject), "strainAnalysis": getStrainAnalysisContainer( → laminateObject), "failureAnalysis": failureAnalysisContainer, "plyByPly": plyByPlyContainer, }, no_update, userSelectedFailedPlies else: raise dash.exceptions.PreventUpdate

if __name__ == "__main__": app.run_server(debug=True)

98

5 Source Codes

5.2 Laminates_classes.py To easily navigate in the source code of the file Laminates_classes.py, Table 5.2 collects in chronological order all the classes methods and the corresponding line in the source code.

Table 5.2 Line numbers of the classes methods in Laminates_classes.py Classes method

Program line

getLayerNo

13

getElasticityMatrix

16

setProperties

22

getProperties

25

getComplianceMatrix

28

getZK

31

getZKminusOne

34

__concatenateGeneralizedElasticitySubmatrices

50

__getBendingSubmatrix

56

__getCouplingSubmatrix

69

__getExtensionalSubmatrix

82

__updateNumberOfLaminateLayers

93

addLaminae

96

createLamina

101

findLayerIndex

104

getEpsMatrix

112

getGeneralizedComplianceMatrix

115

getGeneralizedElasticityMatrix

118

getGeneralizedStrains

124

getKappaMatrix

127

getLaminate

130

getLaminateLayer

133

getLaminateLayers

136

getLoadMatrix

139

getNumberOfLaminateLayers

142

getStrains

145

getStresses

154

getThickness

165

removeLamina

168

setThickness

172

updateLamina

175

updateLaminate

180

updateLoadMatrix

185

5.2 Laminates_classes.py

99 Laminates_classes.py (laminates classes)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

import numpy as np import globalVars from decimal import *

class Lamina(object): def __init__(self, properties, k): self.Properties = properties self.layerNo = k self.elasticityMatrix = self.getElasticityMatrix() def getLayerNo(self): return self.layerNo def getElasticityMatrix(self): # elastic constants E = self.Properties["Ex"] elasticityMatrix = np.array([E]) return elasticityMatrix def setProperties(self, focusedProperty, newValue): self.Properties[focusedProperty] = newValue def getProperties(self): return self.Properties def getComplianceMatrix(self): return np.linalg.inv(self.getElasticityMatrix()) def getZK(self): return self.Properties["zK"] def getZKminusOne(self): return self.Properties["zKminusOne"]

class Laminate(object): def __init__(self, laminateLayers): self.laminateLayers = laminateLayers self.NumberOfLaminateLayers = len(laminateLayers) self.laminae = [] self.updateLaminate() self.loadMatrix = np.zeros((2, 1)) self.thickness = 9.0 def __iter__(self): return (lamina for lamina in self.laminae) def __concatenateGeneralizedElasticitySubmatrices(self, A, B, D) → : cStarFirstRow = np.concatenate((A, B), axis=1) cStarSecondRow = np.concatenate((B, D), axis=1) cStar = np.concatenate((cStarFirstRow, cStarSecondRow), axis → =0)

100 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

5 Source Codes return cStar def __getBendingSubmatrix(self): D = np.zeros((1, 1)) for k in np.arange(len(self.laminae)): if globalVars.isNotFailed(k): currentLamina = self.laminae[k] elasticityMatrix = currentLamina.getElasticityMatrix → () zK = currentLamina.getZK() zKminusOne = currentLamina.getZKminusOne() D = D + elasticityMatrix*(zK**3 - zKminusOne**3) D = (1.0/3.0)*D return D def __getCouplingSubmatrix(self): B = np.zeros((1, 1)) for k in np.arange(len(self.laminae)): if globalVars.isNotFailed(k): currentLamina = self.laminae[k] elasticityMatrix = currentLamina.getElasticityMatrix → () zK = currentLamina.getZK() zKminusOne = currentLamina.getZKminusOne() B = B + elasticityMatrix*(zK**2 - zKminusOne**2) B = (1.0/2.0)*B return B def __getExtensionalSubmatrix(self): A = np.zeros((1, 1)) for k in np.arange(len(self.laminae)): if globalVars.isNotFailed(k): currentLamina = self.laminae[k] elasticityMatrix = currentLamina.getElasticityMatrix → () zK = currentLamina.getZK() zKminusOne = currentLamina.getZKminusOne() A = A + elasticityMatrix*(zK - zKminusOne) return A def __updateNumberOfLaminateLayers(self): self.NumberOfLaminateLayers = len(self.laminateLayers) def addLaminae(self, newLaminae): self.laminateLayers.update(newLaminae) self.__updateNumberOfLaminateLayers() self.updateLaminate() def createLamina(self, laminateData, k): return Lamina(laminateData, k) def findLayerIndex(self, zCoordinate): for k in np.arange(len(self.laminae)): currentLamina = self.laminae[k]

5.2 Laminates_classes.py 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160

101

zK = currentLamina.getZK() zKminusOne = currentLamina.getZKminusOne() if zKminusOne 0.0) and ’ ’({Strain Max} < 1.0 && { → Strain Max} > 0.0) → and ’ ’({Stress Max} < 1.0 && { → Stress Max} > 0.0)’ → , }, ’backgroundColor’: ’red’, ’color’: ’white’

422 423 424 425

426

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467

}, { "if": {"state": "selected"}, "backgroundColor": "#c8f4ff", "border": "1px solid darkblue", }, ], export_format=’xlsx’, export_headers=’ids’, id=’failureTable’ ), ) )

def getFailureAnalysisDirectionColumn(laminateObject): directionColumn = [] for layerNo in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): for position in np.arange(0, 3): directionColumn.append(’x’) return directionColumn

def getFailureAnalysisLaminaeColumn(laminateObject): laminaeColumn = [] for layerNo in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): for laminaNo in np.arange(0, 3): laminaeColumn.append(layerNo + 1) return laminaeColumn

def getFailureAnalysisMaxStrainColumn(laminateObject): strainValues = getStrainValues(laminateObject) maxStrainColumn = [] for layerNo in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): if globalVars.isNotFailed(layerNo): currentLaminae = laminateObject.getLaminateLayer( → layerNo) kepst = currentLaminae.getProperties()["kepst"]

114 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518

5 Source Codes kepsc = currentLaminae.getProperties()["kepsc"] for position in np.arange(0, 3): strain1 = strainValues[layerNo * 3 + position] if strain1 < 0: keps1 = kepsc else: keps1 = kepst maxStrainColumn.append(keps1 / strain1 if strain1 → else 0.0) else: for position in np.arange(0, 3): maxStrainColumn.append(0.0) return maxStrainColumn

def getFailureAnalysisMaxStressColumn(laminateObject): stressValues = getStressValues(laminateObject) maxStressColumn = [] for layerNo in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): if globalVars.isNotFailed(layerNo): currentLaminae = laminateObject.getLaminateLayer( → layerNo) kt = currentLaminae.getProperties()["kt"] kc = currentLaminae.getProperties()["kc"] for position in np.arange(0, 3): stress1 = stressValues[layerNo * 3 + position] if stress1 < 0: k1 = kc else: k1 = kt maxStressColumn.append(k1 / stress1 if stress1 else → 0.0) else: for position in np.arange(0, 3): maxStressColumn.append(0.0) return maxStressColumn

def getFailureAnalysisPositionColumn(laminateObject): positionColumn = [] positionLabelArray = ["Bottom", "Middle", "Top"] for layerNo in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): for laminaNo in np.arange(0, 3): positionColumn.append(positionLabelArray[laminaNo]) return positionColumn

def getFailureAnalysisTsaiHillColumn(laminateObject): stressValues = getStressValues(laminateObject) tsaiHillColumn = [] for currentLaminae in laminateObject: layerNo = currentLaminae.getLayerNo() if globalVars.isNotFailed(layerNo):

5.4 CLATHelpModule.py 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548

549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566

115

currentLaminae = laminateObject.getLaminateLayer( → layerNo) for position in np.arange(0, 3): stress1 = stressValues[layerNo * 3 + position] tsaiHillColumn.append(getRTsaiHill(currentLaminae, → stress1)) else: for position in np.arange(0, 3): tsaiHillColumn.append(0.0) return tsaiHillColumn

def getFailureAnalysisTsaiWuColumn(laminateObject): stressValues = getStressValues(laminateObject) tsaiWuColumn = [] for layerNo in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): if globalVars.isNotFailed(layerNo): currentLaminae = laminateObject.getLaminateLayer( → layerNo) for position in np.arange(0, 3): stress1 = stressValues[layerNo * 3 + position] tsaiWuColumn.append(getRTsaiWu(currentLaminae, → stress1)) else: for position in np.arange(0, 3): tsaiWuColumn.append(0.0) return tsaiWuColumn

def getLaminateSketch(data, userSelectedFailedPlies): for i in np.arange(0, len(data)): data[i]["thickness"] = data[i]["zK"] - data[i]["zKminusOne" → ] data[i]["materialName"] = "Mat" + str(data[i]["Material"]) data[i][’title’] = ’Layer {0: = 0: k1TsaiHill = kt else: k1TsaiHill = kc R = SympySymbol(’R’, real=True) return float(solve( (R * stress1) ** 2 / k1TsaiHill ** 2 - 1, R

5.4 CLATHelpModule.py 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045

1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056

125

)[-1])

def getRTsaiWu(laminae, stress1): kt = laminae.getProperties()["kt"] kc = laminae.getProperties()["kc"] # Tsai-Wu a1 = (1 / kt) + (1 / kc) a11 = -1 / (kt * kc) R = SympySymbol(’R’, real=True) return float(solve( a1 * (R * stress1) + a11 * (R * stress1) ** 2 - 1, R )[-1])

def getStrainAnalysisContainer(laminateObject): strainValues = getStrainValues(laminateObject) positionColumn = getPositionColumn(laminateObject) layerColumn = getLayerColumn(laminateObject) strainTableValues = getTableDataFrame([pd.DataFrame(layerColumn → ), pd.DataFrame(positionColumn → ), pd.DataFrame(strainValues) → ], [’Layer no.’, ’Position’, ’ → eps_x’]) strainPlotData = { ’strainValues’: strainValues, } plotData = getStrainPlots(laminateObject, strainPlotData) return dbc.Container( [ dbc.Row( [ dbc.Col( getCustomizedGraph(plotData["strains"][" → strainX"], {"fileName": "strainXPlot" → }), width=6 ), ] ), dbc.Row( dbc.Accordion( [ dbc.AccordionItem( dash_table.DataTable( data=strainTableValues,

126

5 Source Codes columns=[ dict(id=’Layer no.’, name=[’Layer → no.’], type=’numeric’, format=Format → ()), dict(id=’Position’, name=[’Position’], type=’text’, format=Format()), dict(id=’eps_x’, name=[’eps_x’], type=’numeric’, format=Format(precision=6, scheme=Scheme. → fixed)), ], style_header={ ’textAlign’: ’center’ }, style_cell={ ’textAlign’: ’center’ }, style_data={ ’color’: ’black’, ’backgroundColor’: ’white’ }, style_data_conditional=[ { ’if’: { # ’row_index’: ’odd’ ’filter_query’: ’{Position} → eq "Bottom"’, }, ’backgroundColor’: ’rgb(220, → 220, 220)’, }, { "if": {"state": "selected"}, # → ’active’ | ’selected’ "backgroundColor": "#c8f4ff", "border": "1px solid darkblue" → , },

1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105

], export_format=’xlsx’, export_headers=’ids’, id=’tbl’ ), title="Strain Table" ) ], start_collapsed=True, ) ),

5.4 CLATHelpModule.py 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156

127

])

def getStrainPlots(laminateObject, strainPlotData={}): if strainPlotData: strainValues = strainPlotData["strainValues"] else: strainValues = getStrainValues(laminateObject) yValues = getYValues(laminateObject) strainValues.insert(0, 0.0) strainValues.append(0.0) yValues.insert(0, yValues[0]) yValues.append(yValues[-1]) strainData = { "strainX": { "xValues": strainValues, "yValues": yValues, "type": r"$\varepsilon_{x} \text{(-)}$" } } strains = makePlot(strainData["strainX"]) return {"strains": {"strainX": strains}}

def getStrainValues(laminateObject): strainValues = [] for laminaeNumber in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): currentLaminae = laminateObject.getLaminateLayer( → laminaeNumber) positionArray = getPositionArray(currentLaminae) for yValue in positionArray: strainAtY = laminateObject.getStrains(yValue).tolist() strainValues.append(strainAtY) return strainValues

def getStrengthRatioDataFrame(laminateObject): strengthRatioValues = getStrengthRatioValues(laminateObject) strengthRatioDataFrame = pd.DataFrame(strengthRatioValues). → transpose() strengthRatioDataFrame.columns = [’Layer no.’, ’Position’, ’ → Direction’, ’Stress Max’, ’Strain Max’, ’Tsai-Hill’, ’Tsai-Wu’] return strengthRatioDataFrame.to_dict(’records’)

def getStrengthRatioValues(laminateObject): laminaeColumn = getFailureAnalysisLaminaeColumn(laminateObject)

128 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190

1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202

5 Source Codes positionColumn = getFailureAnalysisPositionColumn( → laminateObject) directionColumn = getFailureAnalysisDirectionColumn( → laminateObject) maxStressColumn = getFailureAnalysisMaxStressColumn( → laminateObject) maxStrainColumn = getFailureAnalysisMaxStrainColumn( → laminateObject) tsaiHillColumn = getFailureAnalysisTsaiHillColumn( → laminateObject) tsaiWuColumn = getFailureAnalysisTsaiWuColumn(laminateObject) return [laminaeColumn, positionColumn, directionColumn, → maxStressColumn, maxStrainColumn, [float(x) for x in tsaiHillColumn], [float(x) for x in → tsaiWuColumn]]

def getStressAnalysisContainer(laminateObject): stressValues = getStressValues(laminateObject) positionColumn = getPositionColumn(laminateObject) layerColumn = getLayerColumn(laminateObject) stressTableValues = getTableDataFrame( [ pd.DataFrame(layerColumn), pd.DataFrame(positionColumn), pd.DataFrame(stressValues) ], [’Layer no.’, ’Position’, ’sigma_x’] ) stressPlotData = { ’stressValues’: stressValues, } plotData = getStressPlots(laminateObject, stressPlotData) return dbc.Container( [ dbc.Row( [ dbc.Col( getCustomizedGraph(plotData["stresses"][" → stressX"], {"fileName": "stressXPlot" → }), width=6 ), ] ), dbc.Row( dbc.Accordion( [ dbc.AccordionItem( dash_table.DataTable( data=stressTableValues, columns=[

5.4 CLATHelpModule.py

129 dict(id=’Layer no.’, name=[’Layer → no.’], type=’numeric’, format=Format → ()), dict(id=’Position’, name=[’Position’], type=’text’, format=Format()), dict(id=’sigma_x’, name=[’sigma_x’], type=’numeric’, format=Format(precision=3, scheme=Scheme. → fixed))

1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213

], style_header={ ’textAlign’: ’center’ }, style_cell={ ’textAlign’: ’center’ }, style_data={ ’color’: ’black’, ’backgroundColor’: ’white’ }, style_data_conditional=[ { ’if’: { # ’row_index’: ’odd’ ’filter_query’: ’{Position} → eq "Bottom"’, }, ’backgroundColor’: ’rgb(220, → 220, 220)’, }, { "if": {"state": "selected"}, # → ’active’ | ’selected’ "backgroundColor": "#c8f4ff", "border": "1px solid darkblue" → , }, ], export_format=’xlsx’, export_headers=’ids’, id=’tbl’

1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251

), title="Stress Table" ) ], start_collapsed=True, ) ), ])

130 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304

5 Source Codes

def getStressPlots(laminateObject, stressPlotData={}): if stressPlotData: stressValues = stressPlotData["stressValues"] else: stressValues = getStressValues(laminateObject) yValues = getYValues(laminateObject) stressValues.insert(0, 0.0) stressValues.append(0.0) yValues.insert(0, yValues[0]) yValues.append(yValues[-1]) stressData = { "stressX": { "xValues": stressValues, "yValues": yValues, "type": r"$\sigma_{x} \text{(MPa)}$" } } stressesX = makePlot(stressData["stressX"]) return {"stresses": {"stressX": stressesX} }

def getStressValues(laminateObject): stressValues = [] for laminaeNumber in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): currentLaminae = laminateObject.getLaminateLayer( → laminaeNumber) positionArray = getPositionArray(currentLaminae) for yValue in positionArray: stressAtY = laminateObject.getStresses(yValue) stressValues.append(stressAtY) return stressValues

def getTableDataFrame(columnsValues, columnLabels): dataFrame = pd.DataFrame() for column in columnsValues: dataFrame = pd.concat([dataFrame, column], axis=1) dataFrame.columns = columnLabels return dataFrame.to_dict(’records’)

def getUnidirectionalLaminateContainer(laminateObject): firstLaminae = copy.deepcopy(laminateObject.getLaminateLayer(0) → ) E1 = firstLaminae.getProperties()["E1"] G12 = firstLaminae.getProperties()["G12"]

5.4 CLATHelpModule.py 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356

131

alphaValues = np.arange(0, 360, 1).tolist() eXe1PlotValues = [] eYe1PlotValues = [] gXYg12PlotValues = [] v12PlotValues = [] minusNXPlotValues = [] minusNYPlotValues = [] for alpha in alphaValues: firstLaminae.setProperties("alpha", alpha) complianceMatrix = firstLaminae. → getTransformedComplianceMatrix() eXe1PlotValues.append(1 / (E1 * complianceMatrix[0][0])) eYe1PlotValues.append(1 / (E1 * complianceMatrix[1][1])) gXYg12PlotValues.append(1 / (G12 * complianceMatrix[2][2])) v12PlotValues.append((-1 / complianceMatrix[0][0]) * → complianceMatrix[0][1]) sin = np.sin(alpha * np.pi / 180) cos = np.cos(alpha * np.pi / 180) temp = (1229 * cos * sin ** 3 + 4671 * cos ** 3 * sin) / ( 3225 * sin ** 4 + 5221 * cos ** 2 * sin ** 2 + 275 * → cos ** 4) minusNXPlotValues.append(abs(temp)) minusNYPlotValues.append(abs((-1 / complianceMatrix[1][1]) → * complianceMatrix[1][2])) eXe1PlotValues.append(eXe1PlotValues[0]) eYe1PlotValues.append(eXe1PlotValues[0]) gXYg12PlotValues.append(gXYg12PlotValues[0]) v12PlotValues.append(v12PlotValues[0]) minusNXPlotValues.append(minusNXPlotValues[0]) minusNYPlotValues.append(minusNYPlotValues[0]) alphaValues.append(alphaValues[0]) containerRows = [] plotData = { "eXe1": { "title": r"$E_{x}/E_{1}$", "rValues": eXe1PlotValues, "thetaValues": alphaValues, "lineColor": "black" }, "eYe1": { "title": r"$E_{y}/E_{1}$", "rValues": eYe1PlotValues, "thetaValues": alphaValues, "lineColor": "darkred" }, "gXYg12": { "title": r"$G_{xy}/G_{12}$", "rValues": gXYg12PlotValues, "thetaValues": alphaValues, "lineColor": "black" }, "v12": {

132 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404

5 Source Codes "title": r"$\nu_{xy}$", "rValues": v12PlotValues, "thetaValues": alphaValues, "lineColor": "black" }, "minusNX": { "title": r"$\text{abs}(\eta_x)$", "rValues": minusNXPlotValues, "thetaValues": alphaValues, "lineColor": "black" }, "minusNY": { "title": r"$\text{abs}(\eta_y)$", "rValues": minusNYPlotValues, "thetaValues": alphaValues, "lineColor": "darkred" } } exe1Plot = makePolarDiagram([plotData["eXe1"], plotData["eYe1" → ]]) gXYg12Plot = makePolarDiagram([plotData["gXYg12"]]) v12Plot = makePolarDiagram([plotData["v12"]]) nPlots = makePolarDiagram([plotData["minusNX"], plotData[" → minusNY"]]) containerRows.append( dcc.Markdown(’’’##### Pole diagram of the elastic → properties $$E_x / E_1$$ and $$E_y / E_1$$’’’, mathjax=True) ) containerRows.append(getCustomizedGraph(exe1Plot, {"fileName": → "eXeYe1Plot"})) tableData = { "Angle": { "title": "Angle", "precision": 1 }, "eXe1": { "title": "E_x/E_1", "precision": 3 }, "eYe1": { "title": "E_y/E_1", "precision": 3 } } poleDiagramValues = getTableDataFrame([pd.DataFrame(alphaValues → ), pd.DataFrame(eXe1PlotValues → ), pd.DataFrame(eYe1PlotValues → )], [’Angle’, ’E_x/E_1’, ’E_y/ → E_1’])

5.4 CLATHelpModule.py 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452

133

containerRows.append( getAccordionDataTable(tableData, poleDiagramValues) ) containerRows.append(html.Hr()) containerRows.append( dcc.Markdown(’’’##### Pole diagram of the elastic property → $$G_{xy} / G_{12}$$’’’, mathjax=True) ) containerRows.append(getCustomizedGraph(gXYg12Plot, {"fileName" → : "gXYg12Plot"})) tableData = { "Angle": { "title": "Angle", "precision": 1 }, "eXe1": { "title": "G_xy/G_12", "precision": 3 } } poleDiagramValues = getTableDataFrame([pd.DataFrame(alphaValues → ), pd.DataFrame( → gXYg12PlotValues)], [’Angle’, ’G_xy/G_12’]) containerRows.append( getAccordionDataTable(tableData, poleDiagramValues) ) containerRows.append(html.Hr()) containerRows.append( dcc.Markdown(’’’##### Pole diagram of the elastic property → $$v_{xy}$$’’’, mathjax=True) ) containerRows.append(getCustomizedGraph(v12Plot, {"fileName": " → v12Plot"})) tableData = { "Angle": { "title": "Angle", "precision": 1 }, "eXe1": { "title": "_xy", "precision": 3 } } poleDiagramValues = getTableDataFrame([pd.DataFrame(alphaValues → ), pd.DataFrame(v12PlotValues) → ], [’Angle’, ’v_xy’]) containerRows.append( getAccordionDataTable(tableData, poleDiagramValues)

134 1453 1454 1455 1456

1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500

5 Source Codes ) containerRows.append(html.Hr()) containerRows.append( dcc.Markdown(’’’##### Pole diagram of the elastic → properties abs($$\eta_{x}$$) and abs($$\eta_{y}$$) → ’’’, mathjax=True) ) containerRows.append(getCustomizedGraph(nPlots, {"fileName": " → etaPlots"})) tableData = { "Angle": { "title": "Angle", "precision": 1 }, "eXe1": { "title": "abs(eta_x)", "precision": 3 }, "eYe1": { "title": "abs(eta_y)", "precision": 3 } } poleDiagramValues = getTableDataFrame([pd.DataFrame(alphaValues → ), pd.DataFrame( → minusNXPlotValues), pd.DataFrame( → minusNYPlotValues)], [’Angle’, ’abs(eta_x)’, ’abs → (eta_y)’]) containerRows.append( getAccordionDataTable(tableData, poleDiagramValues) ) containerRows.append(html.Hr()) containerRows.append( dcc.Markdown(’’’##### Elastic constants as a function of → the off-axis angle’’’, mathjax=True) ) diagramElasticProperties = { "eXe1": { "xValues": alphaValues[0:91], "yValues": eXe1PlotValues[0:91], "title": r"$E_{x}/E_{1}$", "lineColor": "black", "lineWidth": 1.5, "mode": "lines" }, "eYe1": { "xValues": alphaValues[0:91], "yValues": eYe1PlotValues[0:91], "title": r"$E_{y}/E_{1}$",

5.4 CLATHelpModule.py "lineColor": "darkgreen", "lineWidth": 1.5, "mode": "lines"

1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517

}, "gXYg12": { "xValues": alphaValues[0:91], "yValues": gXYg12PlotValues[0:91], "title": r"$G_{xy}/G_{12}$", "lineColor": "darkred", "lineWidth": 1.5, "secondaryY": True, "yMin": 0, "yMax": max(gXYg12PlotValues[0:91]) * 1.1, "mode": "lines" }, "plotXMax": 90, "plotYMax": max(max(eXe1PlotValues[0:91]), max( → eYe1PlotValues[0:91])) * 1.1, "xType": r"$\text{Off-axis angle} \ \alpha$", "yType": r"$\text{Elastic constants} \ E_{x}/E_{1}, \ E_{y → }/E_{1} \text{ in -}$", "secondaryYType": r"$\text{Elastic constant} \ G_{xy}/G_ → {12} \text{ in -}$",

1518 1519 1520 1521 1522 1523 1524 1525

1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548

135

} containerRows.append( dmc.Center( getCustomizedGraph(makeLinePlot( → diagramElasticProperties), {"fileName": " → diagramElasticPropertiesPlot1"})) ) tableData = { "Angle": { "title": "Angle", "precision": 1 }, "ExE1": { "title": "E_x/E_1", "precision": 3 }, "EyE1": { "title": "E_y/E_1", "precision": 3 }, "GxyG12": { "title": "G_xy/G_12", "precision": 3 } } poleDiagramValues = getTableDataFrame([pd.DataFrame(alphaValues → [0:91]), pd.DataFrame(eXe1PlotValues → [0:91]),

136 1549 1550

1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596

5 Source Codes pd.DataFrame(eYe1PlotValues → [0:91]), pd.DataFrame( → gXYg12PlotValues → [0:91])], [’Angle’, ’E_x/E_1’, ’E_y/ → E_1’, ’G_xy/G_12’]) containerRows.append( getAccordionDataTable(tableData, poleDiagramValues) ) containerRows.append(html.Hr()) containerRows.append( dcc.Markdown(’’’##### Elastic constants as a function of → the off-axis angle’’’, mathjax=True) ) diagramElasticProperties = { "eXe1": { "xValues": alphaValues[0:91], "yValues": v12PlotValues[0:91], "title": r"$\nu_{xy}$", "lineColor": "black", "lineWidth": 1.5, "mode": "lines" }, "eYe1": { "xValues": alphaValues[0:91], "yValues": minusNXPlotValues[0:91], "title": r"$\text{abs}(\eta_x)$", "lineColor": "darkgreen", "lineWidth": 1.5, "secondaryY": True, "yMin": 0, "yMax": max(max(minusNXPlotValues[0:91]), max( → minusNYPlotValues[0:91])) * 1.1, "mode": "lines" }, "gXYg12": { "xValues": alphaValues[0:91], "yValues": minusNYPlotValues[0:91], "title": r"$\text{abs}(\eta_y)$", "lineColor": "darkred", "lineWidth": 1.5, "secondaryY": True, "yMin": 0, "yMax": max(max(minusNXPlotValues[0:91]), max( → minusNYPlotValues[0:91])) * 1.1, "mode": "lines" }, "plotXMax": 90, "plotYMax": max(v12PlotValues[0:91]) * 1.1, "xType": r"$\text{Off-axis angle} \ \alpha$", "yType": r"$\text{Elastic constant} \ \nu_{xy} \text{ in → -}$",

5.4 CLATHelpModule.py "secondaryYType": r"$\text{Elastic constants} \ \text{abs → }(\eta_x), \text{abs}(\eta_y) \text{ in -}$",

1597 1598 1599 1600 1601 1602

1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626

1627

1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642

137

} containerRows.append( dmc.Center( getCustomizedGraph(makeLinePlot( → diagramElasticProperties), {"fileName": " → diagramElasticPropertiesPlot2"})) ) tableData = { "Angle": { "title": "Angle", "precision": 1 }, "v12": { "title": "v_xy", "precision": 3 }, "abs(nx)": { "title": "abs(eta_x)", "precision": 3 }, "abs(ny)": { "title": "abs(eta_y)", "precision": 3 }, } poleDiagramValues = getTableDataFrame([pd.DataFrame(alphaValues → [0:91]), pd.DataFrame(v12PlotValues → [0:91]), pd.DataFrame( → minusNXPlotValues → [0:91]), pd.DataFrame( → minusNYPlotValues → [0:91])], [’Angle’, ’v_xy’, ’abs(eta_x → )’, ’abs(eta_y)’]) containerRows.append( getAccordionDataTable(tableData, poleDiagramValues) ) containerRows.append(html.Hr()) return dbc.Container(containerRows)

def getUploadButtons(): return dcc.Upload( id=’datatable-upload’, children=html.Div([ ’Drag and Drop or ’, html.A(’select an Excel file’),

138

5 Source Codes ’ to load the model data’ ]), style={ ’width’: ’800px’, ’height’: ’60px’, ’lineHeight’: ’60px → ’, ’borderWidth’: ’1px’, ’borderStyle’: ’dashed’, ’borderRadius’: ’5px’, ’textAlign’: ’center’, ’margin’: → ’10px’ }, accept=".xlsx"

1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680

1681

1682

1683

)

def getYValues(laminateObject): yValues = [] for laminaeNumber in np.arange(0, laminateObject. → getNumberOfLaminateLayers()): currentLaminae = laminateObject.getLaminateLayer( → laminaeNumber) positionArray = getPositionArray(currentLaminae) for yValue in positionArray: yValues.append(yValue) return yValues

def makeLinePlot(plotData): plot = make_subplots(specs=[[{"secondary_y": True}]]) plotXMin = plotData["plotXMin"] → 0 plotXMax = plotData["plotXMax"] → 5000.0 plotYMin = plotData["plotYMin"] → 0 plotYMax = plotData["plotYMax"] → 5000.0

if "plotXMin" in plotData else if "plotXMax" in plotData else if "plotYMin" in plotData else if "plotYMax" in plotData else

for subPlot in plotData.keys(): if isinstance(plotData[subPlot], dict): if "secondaryY" in plotData[subPlot]: plot.add_scatter( x=plotData[subPlot]["xValues"], y=plotData[subPlot]["yValues"], name=plotData[subPlot]["title"], mode=plotData[subPlot]["mode"] if "mode" in → plotData[subPlot] else "lines+markers", marker=dict(size=plotData[subPlot]["markerSize"] → if "markerSize" in plotData[subPlot] → else 12), line=dict(color=plotData[subPlot]["lineColor"] → if "lineColor" in plotData[subPlot] else → ’darkgreen’, width=plotData[subPlot]["lineWidth"] if → "lineWidth" in plotData[subPlot → ] else 3), secondary_y=True,

5.4 CLATHelpModule.py 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698

1699

1700

1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732

139

showlegend=True, ) plot.update_yaxes( range=[plotData[subPlot]["yMin"], plotData[subPlot]["yMax"]], gridcolor=’#c0c0c0’, title_text=plotData["secondaryYType"], secondary_y=True) else: plot.add_scatter( x=plotData[subPlot]["xValues"], y=plotData[subPlot]["yValues"], name=plotData[subPlot]["title"], mode=plotData[subPlot]["mode"] if "mode" in → plotData[subPlot] else "lines+markers", marker=dict(size=plotData[subPlot]["markerSize"] → if "markerSize" in plotData[subPlot] → else 12), line=dict(color=plotData[subPlot]["lineColor"] → if "lineColor" in plotData[subPlot] else → ’darkgreen’, width=plotData[subPlot]["lineWidth"] if → "lineWidth" in plotData[subPlot → ] else 3), secondary_y=False, showlegend=True, ) # add axes with arrow heads plot.add_annotation( x=plotXMax, # arrows’ head y=0, # arrows’ head ax=plotXMin, # arrows’ tail ay=0, # arrows’ tail xref=’x’, yref=’y’, axref=’x’, ayref=’y’, text=’’, # if you want only the arrow showarrow=True, arrowhead=3, arrowsize=1, arrowwidth=1, arrowcolor=’black’ ) plot.add_annotation( x=0, # arrows’ head y=plotYMax, # arrows’ head ax=0, # arrows’ tail ay=plotYMin, # arrows’ tail xref=’x’, yref=’y’, axref=’x’, ayref=’y’, text=’’, # if you want only the arrow showarrow=True,

140 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782

5 Source Codes arrowhead=3, arrowsize=1, arrowwidth=1, arrowcolor=’black’ ) plot.update_layout( { # ’title’: plotData["title"], ’template’: None, # ’plot_bgcolor’: ’#f3f6f4’, ’yaxis’: { ’title’: plotData["yType"] if "yType" in plotData → else " - " }, ’xaxis’: { ’title’: plotData["xType"] if "xType" in plotData → else " - " }, ’height’: plotData["height"] if "height" in plotData → else 550, ’width’: plotData["width"] if "width" in plotData else → 850 } ) plot.update_xaxes(range=[plotXMin, plotXMax], gridcolor=’#c0c0c0’) plot.update_yaxes(range=[plotYMin, plotYMax], gridcolor=’# → c0c0c0’, secondary_y=False) if "logY" in plotData: if plotData["logY"]: plot.update_yaxes(type="log") if "logX" in plotData: if plotData["logX"]: plot.update_xaxes(type="log") # plot.update_traces(marker=dict(size=12)) return plot

def makePlot(plotData): axisTolerance = 1.0e-12 plot = go.Figure( go.Scatter( x=plotData["xValues"], y=plotData["yValues"], mode="lines", line=dict(color=’black’, width=2.5), showlegend=False, ) ) plotMargin = 0.1 # 10%

5.4 CLATHelpModule.py 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835

141

plotXMin = -max([abs(x) for x in plotData["xValues"]]) * (1.0 + → plotMargin) if -axisTolerance < plotXMin < axisTolerance: plotXMin = -1.0 plotXMax = max([abs(x) for x in plotData["xValues"]]) * (1.0 + → plotMargin) if -axisTolerance < plotXMax < axisTolerance: plotXMax = 1.0 plotYMin = min(plotData["yValues"]) * (1.0 + plotMargin) plotYMax = max(plotData["yValues"]) * (1.0 + plotMargin) # add axes with arrow heads plot.add_annotation( x=plotXMax, # arrows’ head y=0, # arrows’ head ax=plotXMin, # arrows’ tail ay=0, # arrows’ tail xref=’x’, yref=’y’, axref=’x’, ayref=’y’, text=’’, # if you want only the arrow showarrow=True, arrowhead=3, arrowsize=1, arrowwidth=1, arrowcolor=’black’ ) plot.add_annotation( x=0, # arrows’ head y=plotYMax, # arrows’ head ax=0, # arrows’ tail ay=plotYMin, # arrows’ tail xref=’x’, yref=’y’, axref=’x’, ayref=’y’, text=’’, # if you want only the arrow showarrow=True, arrowhead=3, arrowsize=1, arrowwidth=1, arrowcolor=’black’ ) plot.update_layout( { # ’title’: plotData["title"], # ’plot_bgcolor’: ’#f3f6f4’, ’template’: None, ’yaxis’: { ’title’: r’$z \text{(mm)}$’ }, ’xaxis’: { ’title’: plotData["type"] }, ’height’: 500 } )

142 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885

5 Source Codes plot.update_xaxes(range=[plotXMin, plotXMax], gridcolor=’# → D3D3D3’) plot.update_yaxes(range=[plotYMin, plotYMax], gridcolor=’# → D3D3D3’) return plot

def makePolarDiagram(plotData): plot = go.Figure() for subPlot in plotData: plot.add_scatterpolar( r=subPlot["rValues"], theta=subPlot["thetaValues"], mode="lines", name=subPlot["title"], # line=dict(color=’darkgreen’, width=2), showlegend=True, line=dict(color=subPlot["lineColor"] if "lineColor" in → subPlot else ’darkgreen’, width=subPlot["lineWidth"] if "lineWidth" in → subPlot else 1.5), ) plot.update_traces( hovertemplate=None ) plot.update_layout( template=None, height=550 ) plot.update_layout( template=None, polar=dict(radialaxis=dict(gridwidth=0.5, # range=[0, 3], range=[0, max(plotData[0]["rValues" → ]) * 1.5], showticklabels=True, ticks=’’, → gridcolor="lightgrey"), angularaxis=dict(showticklabels=True, ticks=’’, rotation=0, direction="counterclockwise", gridcolor="grey") ) ) return plot

def makeStressStrainPlot(plotData): plot = go.Figure( go.Scatter( x=plotData["xValues"], y=plotData["yValues"], mode="lines+markers", line=dict(color=’darkgreen’, width=3),

5.4 CLATHelpModule.py 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940

showlegend=False, ) ) plotMargin = 0.1 # 10% plotXMin = 0 plotXMax = max(plotData["xValues"]) * (1.0 + plotMargin) plotYMin = 0 plotYMax = max(plotData["yValues"]) * (1.0 + plotMargin) # add axes with arrow heads plot.add_annotation( x=plotXMax, # arrows’ head y=0, # arrows’ head ax=plotXMin, # arrows’ tail ay=0, # arrows’ tail xref=’x’, yref=’y’, axref=’x’, ayref=’y’, text=’’, # if you want only the arrow showarrow=True, arrowhead=3, arrowsize=1, arrowwidth=1, arrowcolor=’black’ ) plot.add_annotation( x=0, # arrows’ head y=plotYMax, # arrows’ head ax=0, # arrows’ tail ay=plotYMin, # arrows’ tail xref=’x’, yref=’y’, axref=’x’, ayref=’y’, text=’’, # if you want only the arrow showarrow=True, arrowhead=3, arrowsize=1, arrowwidth=1, arrowcolor=’black’ ) plot.update_layout( { # ’title’: plotData["title"], ’plot_bgcolor’: ’#f3f6f4’, ’yaxis’: { ’title’: plotData["yType"] }, ’xaxis’: { ’title’: plotData["xType"] }, ’height’: 500 } ) plot.update_xaxes(range=[plotXMin, plotXMax], gridcolor=’# → c0c0c0’)

143

144

5 Source Codes

1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970

plot.update_yaxes(range=[plotYMin, plotYMax], gridcolor=’# → c0c0c0’) plot.update_traces(marker=dict(size=12, line=dict(width=2, color=’DarkSlateGrey’))) return plot

def parse_contents(contents, filename): content_type, content_string = contents.split(’,’) decoded = base64.b64decode(content_string) if ’xls’ in filename: # Assume that the user uploaded an Excel file return [pd.read_excel(io.BytesIO(decoded), sheet_name=" → ModelProperties"), pd.read_excel(io.BytesIO(decoded), sheet_name=" → LoadMatrix"), pd.read_excel(io.BytesIO(decoded), sheet_name=" → thicknessMatrix"), pd.read_excel(io.BytesIO(decoded), sheet_name=" → MaterialProperties")]

def updateLayerColumn(modelDataTableRows, materialDataTableRows): counter = 0 for i in np.arange(0, len(modelDataTableRows)): counter += 1 modelDataTableRows[i]["Layer"] = counter counter = 0 for i in np.arange(0, len(materialDataTableRows)): counter += 1 materialDataTableRows[i]["Material"] = counter return modelDataTableRows, materialDataTableRows

5.5 requirements.txt requirements.txt (requirements) 1 2 3 4 5 6 7 8 9

dash>=2.6.0 dash_bootstrap_components>=1.0.3 dash_mantine_components>=0.11.1 numpy>=1.22.2 pandas>=1.4.1 plotly>=5.6.0 sympy>=1.10.1 XlsxWriter>=3.0.3 openpyxl>=3.0.10

Index

A Axial second moment of area, 24

B Bar, 7 constitutive equation, 13 differential equation, 15 equilibrium equation, 13 kinematics relation, 11 Bar/beam constitutive equation, 32 differential equation, 35 equilibrium equation, 32 kinematics equation, 30 Bending plane, 26 pure, 17 Bending line, 17 distributed load relation, 29 moment relation, 24 shear force relation, 30 Bending stiffness, 24 Bernoulli beam, 8 constitutive equation, 23 differential equation, 29 equilibrium equation, 26 kinematics relation, 17 Body force, 11

C Classical lamination theory. see classical laminate theory Classical plate element, 1

Composite laminate analysis tool, 45, 46 Composite material, 1 Computational approach, 5 finite element method, 5 Constitutive equation, 3 bar, 13 bar/beam, 32 Bernoulli beam, 23 Continuum mechanical modeling, 4 Curvature, 20 Curvature radius, 20

D Dash, 45 Differential equation bar, 15 bar/beam, 35 Bernoulli beam, 29

E Elasticity matrix, 13 generalized, 40 Equilibrium equation, 3 bar, 13 bar/beam, 32 Bernoulli beam, 26 Euler–Bernoulli beam. see Bernoulli beam Examples, 53

F Failure analysis of laminates, 42, 76, 84 Failure criterion

© The Editor(s) (if applicable) and The Author(s), under exclusive license to Springer Nature Switzerland AG 2024 A. Öchsner and R. Makvandi, A Numerical Approach to the Simplified Laminate Theory of Composite Materials, Advanced Structured Materials 202, https://doi.org/10.1007/978-3-031-47984-7

145

146 maximum strain, 37, 49 maximum stress, 37, 49 Tsai-Hill, 37, 49 Tsai-Wu, 38, 49

G Generalized elasticity matrix, 35, 40 Generalized strains, 26, 32, 40 Generalized stresses, 26, 40, 41

H Hooke’s law, 13 orthotropic, 1

K Kinematics relation, 3 bar, 11 bar/beam, 30 Bernoulli beam, 17 Kirchhoff plate, 10

L Lamina, 1 Laminate, 1 failure analysis, 42, 76, 84

Index P Plane elasticity element, 1 Plotly Dash. see dash Ply, 3 Python, 45, 47, 89

R Reissner-Mindlin plate, 10 Rod. see Bar

S Second moment of area, 24 Simplified classical laminate theory, 2, 4 assumptions, 2 steps for calculation, 42 Source codes, 89 Steps laminate calculation, 42 Strain-displacement relation. see Kinematics relation Strength ratio, 77, 80, 83 Stress resultant, 26

T Thin beam. see Bernoulli beam Traction force, 11

Y Young’s modulus, 13