-
Notifications
You must be signed in to change notification settings - Fork 18
/
runfailuretest.py
212 lines (165 loc) · 7.11 KB
/
runfailuretest.py
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
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
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
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
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
"""
lamipy project - laminated composites calculations in Python.
Run_FailureTest.py - Module containing functions for testing
composite layups.
Functions:
TestA -- Tests the implementation.
ProgressiveFailureTest -- Produces the Progressive Failure test
and sends for plotting.
Joao Paulo Bernhardt - October 2017
"""
import numpy as np
import clt
import failurecriteria as FC
from plotresults import PlotResults
def TestA():
""" Tests the implementation.
This function receives the material parameters, the applied forces,
and other test characteristics and passes to the _clt.py_ module which
will make calculations and return stress & strain results. Those results are
then passed onto the failure criteria modules in order to calculate the
safety factor of the laminate.
Additionally, the Progressive Failure function is called.
"""
# Material 1 - Dictionary of properties
# All units are in Pa (N/m2)
mat1 = {
"E1" : 69e9,
"E2" : 6e9,
"n12" : 0.354,
"G12" : 3e9,
"Xt" : 47e6,
"Xc" : 14e6,
"Yt" : 24e6,
"Yc" : 18e6,
"S12" : 75e6,
"S32" : 41e6,
"a1" : 2.1e-6,
"a2" : 2.1e-6,
"b1" : 0.01,
"b2" : 0.35}
# Assembles material list
mat = [mat1, []]
# Initializes dictionary of the laminate layup configurations
# thk is thickness; ang is angle; mat_id is material id
lam = {"thk": [], "ang": [], "mat_id" : []}
# Adds 12 layers of 0.127mm thickness and material id 0
for i in range(12):
lam["thk"].append(0.127e-3)
lam["mat_id"].append(0)
# Some layup options below.
#lam["ang"].extend((45, -45, 45, -45, 45, -45, -45, 45, -45, 45, -45, 45))
lam["ang"].extend((0, 30, -30, 30, -30, 90, 90, -30, 30, -30, 30, 0))
#lam["ang"].extend((0, 0, 0, 0, 90, 90, 90, 90, 0, 0, 0, 0))
#lam["ang"].extend((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
# lam["ang"].extend((45, -45, 0, 90, 0, 90, 90, 0, 90, 0, -45, 45))
# Vector F with the applied generalized stress (unit N/m / N.m/m)
F = np.array([ 0e2, # Nx
1e2, # Ny
0e4, # Nxy
0e0, # Mx
0e1, # My
0]) # Mxy
# Temperature and moisture variations
delta_T = -60
delta_M = 0.001
# Calculates stresses and strains based on CLT.
# res = calculated results holder;
# LCS = Laminate System; MCS = Material Coordinate System;
# inf = inferior; sup = superior.
res = clt.calc_stressCLT(mat, lam, F, None, delta_T, delta_M)
sfTsaiWu = FC.tsaiwu_2D( mat,
lam,
res["MCS"]["stress"]["inf"],
res["MCS"]["stress"]["sup"])
sfMaxStress = FC.maxstress_2D(mat,
lam,
res["MCS"]["stress"]["inf"],
res["MCS"]["stress"]["sup"])
sfMaxStrain = FC.maxstrain_2D(mat,
lam,
res["MCS"]["strain"]["inf"],
res["MCS"]["strain"]["sup"])
sfHashin = FC.hashin_2D( mat,
lam,
res["MCS"]["stress"]["inf"],
res["MCS"]["stress"]["sup"])
ProgressiveFailureTest(mat, lam, F, delta_T, delta_M)
def ProgressiveFailureTest(mat, lam, F, dT = 0, dM = 0):
""" Produces the Progressive Failure test and sends for plotting.
Obligatory arguments:
mat -- material properties vector
lam -- laminate layup characteristics
F -- forces vector
Optional arguments:
dT -- delta T (temperature variation)
dM -- delta M (moisture variation)
Progressive failure analysis function - loops through CLT and
failure criteria in order to catch failed layers, which are then
discounted (Ply Discount Method).
Every iteration increases the Load Factor by a small factor, unless there
has been a ply failure in the current load step (in this case, CLT and
failure criteria are recalculated until there is no new failure).
"""
# Gets number of layers
num = len(lam["ang"])
# Holds the analysis data through the loops
fail_status = {"Failed?" : [False] * num,
"Mode" : [""] * num,
"Load Factor" : [0] * num}
failed_count = [0, 0]
# Load factor control
LF = 0.20 # Initial load factor
LS = 1.02 # Load step multiplier
# Holds results data (in order to plot later)
plot_data = []
# Main Load Factor loop (increases when there's no new failure)
while failed_count[0] < num:
# Sends for CLT calculations
res = clt.calc_stressCLT(mat, lam, F*LF, fail_status["Mode"], dT, dM)
# Prepares data pair for entry, then appends data.
data_pair = [LF, res]
#plot_data = np.concatenate((plot_data, data_pair))
plot_data.append(data_pair)
# Sends for SF calculations
SF_list = FC.tsaiwu_2D( mat,
lam,
res["MCS"]["stress"]["inf"],
res["MCS"]["stress"]["sup"])
# Loop for layer failure check
for i in range(num):
# Updates sf values
sf_inf = SF_list["fs_inf"][i][0]
sf_sup = SF_list["fs_sup"][i][0]
sf = min(sf_inf, sf_sup)
# Gets failure mode based on min sf
if sf == SF_list["fs_inf"][i][0]:
mode = SF_list["fs_inf"][i][1]
else:
mode = SF_list["fs_sup"][i][1]
# Checks for new failure; saves results
if sf < 1 and not fail_status["Failed?"][i]:
fail_status["Failed?"][i] = True
fail_status["Mode"][i] = mode
fail_status["Load Factor"][i] = LF
failed_count[1] = failed_count[1] + 1
#print("Layer "+str(i)+" has failed. Mode: " + mode)
# Increases LF if no new failure
if failed_count[1] == failed_count[0]:
LF = LF*LS #increases Load Factor by 5%
#print([int(load) for load in LF*F if load>0])
failed_count[0] = failed_count[1]
# Gets FPF and LPF
fpf = min(fail_status["Load Factor"])
lpf = max(fail_status["Load Factor"])
# Prints results
print("First Ply Failure at LF: " + str(round(fpf)))
print("Last Ply Failure at LF: " + str(round(lpf)))
print("LPF / FPF : " + str(round(lpf/fpf, 1)))
# Sends for plotting
plot_data = np.array(plot_data)
plotr = PlotResults(lam, plot_data, fail_status)
plotr.Options(save=True, display=False)
plotr.ProgAvgStrain()
plotr.Profile("MCS", 1, "strain", 0)
TestA()