Note
Go to the end to download the full example code.
LShape#
Damage simulation for a L-part.

/home/docs/checkouts/readthedocs.org/user_builds/easyfea/checkouts/v1.8.1/examples/PhaseField/results/LShape2D/Test/Miehe_AT1_optimMesh nL=50
1 : 0.000 mm, [0.00e+00; 0.00e+00], 1:0.085s, tol=0.00e+00
2 : 0.040 mm, [0.00e+00; 0.00e+00], 1:0.075s, tol=1.00e+00 4.00% -> 1.80s
3 : 0.080 mm, [0.00e+00; 0.00e+00], 1:0.075s, tol=9.95e-01 8.00% -> 1.73s
4 : 0.120 mm, [0.00e+00; 0.00e+00], 1:0.076s, tol=5.56e-01 12.00% -> 1.67s
5 : 0.160 mm, [0.00e+00; 0.00e+00], 1:0.075s, tol=4.38e-01 16.00% -> 1.58s
6 : 0.200 mm, [0.00e+00; 0.00e+00], 1:0.075s, tol=3.60e-01 20.00% -> 1.50s
7 : 0.240 mm, [0.00e+00; 0.00e+00], 1:0.074s, tol=3.06e-01 24.00% -> 1.41s
8 : 0.280 mm, [0.00e+00; 8.98e-03], 1:0.075s, tol=2.65e-01 28.00% -> 1.35s
9 : 0.320 mm, [0.00e+00; 4.57e-02], 1:0.075s, tol=2.32e-01 32.00% -> 1.27s
10 : 0.360 mm, [0.00e+00; 1.10e-01], 1:0.075s, tol=2.07e-01 36.00% -> 1.20s
11 : 0.400 mm, [0.00e+00; 2.07e-01], 1:0.075s, tol=1.86e-01 40.00% -> 1.13s
12 : 0.440 mm, [0.00e+00; 3.48e-01], 1:0.076s, tol=1.69e-01 44.00% -> 1.06s
13 : 0.480 mm, [0.00e+00; 5.46e-01], 1:0.075s, tol=1.55e-01 48.00% -> 979.61ms
14 : 0.520 mm, [0.00e+00; 7.78e-01], 1:0.076s, tol=1.62e-01 52.00% -> 910.84ms
15 : 0.540 mm, [0.00e+00; 9.48e-01], 1:0.076s, tol=2.22e-01 54.00% -> 910.44ms
16 : 0.560 mm, [0.00e+00; 9.93e-01], 1:0.075s, tol=3.80e-01 56.00% -> 887.07ms
17 : 0.580 mm, [0.00e+00; 1.00e+00], 1:0.076s, tol=4.44e-01 58.00% -> 884.39ms
18 : 0.600 mm, [0.00e+00; 1.00e+00], 1:0.075s, tol=3.82e-01 60.00% -> 849.26ms
19 : 0.620 mm, [0.00e+00; 1.00e+00], 1:0.075s, tol=3.28e-01 62.00% -> 829.72ms
20 : 0.640 mm, [0.00e+00; 1.00e+00], 1:0.076s, tol=2.91e-01 64.00% -> 808.62ms
21 : 0.660 mm, [0.00e+00; 1.00e+00], 1:0.075s, tol=2.78e-01 66.00% -> 775.29ms
22 : 0.680 mm, [0.00e+00; 1.00e+00], 1:0.079s, tol=2.54e-01 68.00% -> 777.09ms
23 : 0.700 mm, [0.00e+00; 1.00e+00], 1:0.076s, tol=2.53e-01 70.00% -> 712.60ms
24 : 0.720 mm, [0.00e+00; 1.00e+00], 1:0.089s, tol=2.02e-01 72.00% -> 793.75ms
25 : 0.740 mm, [0.00e+00; 1.00e+00], 1:0.079s, tol=1.76e-01 74.00% -> 663.07ms
26 : 0.760 mm, [0.00e+00; 1.00e+00], 1:0.079s, tol=1.87e-01 76.00% -> 626.86ms
27 : 0.780 mm, [0.00e+00; 1.00e+00], 1:0.085s, tol=1.72e-01 78.00% -> 621.82ms
28 : 0.800 mm, [0.00e+00; 1.00e+00], 1:0.080s, tol=1.65e-01 80.00% -> 541.83ms
29 : 0.820 mm, [0.00e+00; 1.00e+00], 1:0.082s, tol=1.90e-01 82.00% -> 501.46ms
30 : 0.840 mm, [0.00e+00; 1.00e+00], 1:0.081s, tol=1.65e-01 84.00% -> 445.46ms
31 : 0.860 mm, [0.00e+00; 1.00e+00], 1:0.087s, tol=1.51e-01 86.00% -> 424.66ms
32 : 0.880 mm, [0.00e+00; 1.00e+00], 1:0.084s, tol=1.15e-01 88.00% -> 353.98ms
33 : 0.900 mm, [0.00e+00; 1.00e+00], 1:0.079s, tol=1.10e-01 90.00% -> 280.63ms
34 : 0.920 mm, [0.00e+00; 1.00e+00], 1:0.084s, tol=9.93e-02 92.00% -> 239.86ms
35 : 0.940 mm, [0.00e+00; 1.00e+00], 1:0.083s, tol=9.94e-02 94.00% -> 180.18ms
36 : 0.960 mm, [0.00e+00; 1.00e+00], 1:0.083s, tol=9.12e-02 96.00% -> 120.82ms
37 : 0.980 mm, [0.00e+00; 1.00e+00], 1:0.085s, tol=1.02e-01 98.00% -> 62.31ms
38 : 1.000 mm, [0.00e+00; 1.00e+00], 1:0.087s, tol=9.35e-02 100.00% -> -0.00µs
Saved simulation and summary in:
/home/docs/checkouts/readthedocs.org/user_builds/easyfea/checkouts/v1.8.1/examples/PhaseField/results/LShape2D/Test/Miehe_AT1_optimMesh nL=50
Generate movie 01/38 (2.63 %) 3.84 s
Generate movie 02/38 (5.26 %) 3.26 s
Generate movie 03/38 (7.89 %) 3.02 s
Generate movie 04/38 (10.53 %) 3.01 s
Generate movie 05/38 (13.16 %) 2.88 s
Generate movie 06/38 (15.79 %) 2.94 s
Generate movie 07/38 (18.42 %) 2.76 s
Generate movie 08/38 (21.05 %) 2.68 s
Generate movie 09/38 (23.68 %) 2.54 s
Generate movie 10/38 (26.32 %) 2.44 s
Generate movie 11/38 (28.95 %) 2.36 s
Generate movie 12/38 (31.58 %) 2.27 s
Generate movie 13/38 (34.21 %) 2.18 s
Generate movie 14/38 (36.84 %) 2.09 s
Generate movie 15/38 (39.47 %) 2.08 s
Generate movie 16/38 (42.11 %) 1.94 s
Generate movie 17/38 (44.74 %) 1.91 s
Generate movie 18/38 (47.37 %) 1.75 s
Generate movie 19/38 (50.00 %) 1.71 s
Generate movie 20/38 (52.63 %) 1.57 s
Generate movie 21/38 (55.26 %) 1.48 s
Generate movie 22/38 (57.89 %) 1.46 s
Generate movie 23/38 (60.53 %) 1.30 s
Generate movie 24/38 (63.16 %) 1.24 s
Generate movie 25/38 (65.79 %) 1.11 s
Generate movie 26/38 (68.42 %) 1.05 s
Generate movie 27/38 (71.05 %) 961.91 ms
Generate movie 28/38 (73.68 %) 874.44 ms
Generate movie 29/38 (76.32 %) 796.42 ms
Generate movie 30/38 (78.95 %) 699.82 ms
Generate movie 31/38 (81.58 %) 611.57 ms
Generate movie 32/38 (84.21 %) 515.77 ms
Generate movie 33/38 (86.84 %) 433.10 ms
Generate movie 34/38 (89.47 %) 370.64 ms
Generate movie 35/38 (92.11 %) 258.19 ms
Generate movie 36/38 (94.74 %) 174.95 ms
Generate movie 37/38 (97.37 %) 87.42 ms
Generate movie 38/38 (100.00 %) 0.00 µs
13 import matplotlib.pyplot as plt
14 import numpy as np
15
16 from EasyFEA import Display, Folder, Models, ElemType, Simulations, Paraview, PyVista
17 from EasyFEA.Geoms import Point, Points, Domain, Circle
18
19 if __name__ == "__main__":
20 Display.Clear()
21
22 # ----------------------------------------------
23 # Configuration
24 # ----------------------------------------------
25
26 # simu options
27 doSimu = True
28 meshTest = True
29 optimMesh = True
30
31 # outputs
32 folder = Folder.Results_Dir()
33 pltIter = False
34 pltLoad = False
35 makeMovie = True
36 makeParaview = False
37
38 # geom
39 dim = 2
40 L = 250 # mm
41 nL = 50
42 ep = 100
43
44 # model
45 E = 2e4 # MPa
46 v = 0.18
47
48 split = Models.PhaseField.SplitType.Miehe
49 regu = Models.PhaseField.ReguType.AT1
50 Gc = 130 # J/m2
51 Gc *= 1000 / 1e6 # mJ/mm2
52
53 # convergence
54 tolConv = 1e-0
55 convOption = 2
56
57 # load
58 uMax = 1 # mm
59 inc0 = uMax / 25
60 inc1 = inc0 / 2
61
62 config = f"""
63 uMax = {uMax}
64
65 inc0 = {inc0}
66 inc1 = {inc1}
67
68 while ud <= uMax:
69
70 ud += inc0 if simu.damage.max() < 0.6 else inc1
71
72 simu.add_dirichlet(nodes_circle, [0], ['d'], "damage")
73 simu.add_dirichlet(nodes_y0, [0]*dim, simu.Get_dofs())
74 simu.add_dirichlet(nodes_load, [ud], ['y'])
75 """
76
77 # ----------------------------------------------
78 # Mesh
79 # ----------------------------------------------
80 l0 = L / nL
81
82 if meshTest:
83 hC = l0
84 else:
85 hC = 0.5
86 # hC = 0.25
87
88 p1 = Point()
89 p2 = Point(L, 0)
90 p3 = Point(L, L)
91 p4 = Point(2 * L - 30, L)
92 p5 = Point(2 * L, L)
93 p6 = Point(2 * L, 2 * L)
94 p7 = Point(0, 2 * L)
95 if optimMesh:
96 h = 100
97 refineDomain = Domain(Point(0, L - h / 3), Point(L + h / 3, L + h), hC)
98 hD = hC * 5
99 else:
100 refineDomain = None
101 hD = hC
102
103 contour = Points([p1, p2, p3, p4, p5, p6, p7], hD)
104
105 circle = Circle(p5, 100)
106
107 if dim == 2:
108 mesh = contour.Mesh_2D([], ElemType.TRI3, refineGeoms=[refineDomain])
109 else:
110 mesh = contour.Mesh_Extrude(
111 [], [0, 0, -ep], [3], ElemType.HEXA8, refineGeoms=[refineDomain]
112 )
113
114 # Display.Plot_Mesh(mesh)
115 # Display.Plot_Tags(mesh)
116 # from EasyFEA import PyVista
117 # PyVista.Plot_Mesh(mesh).show()
118
119 nodes_y0 = mesh.Nodes_Conditions(lambda x, y, z: y == 0)
120 nodes_load = mesh.Nodes_Conditions(lambda x, y, z: (y == L) & (x >= 2 * L - 30))
121 node3 = mesh.Nodes_Point(p3)
122 node4 = mesh.Nodes_Point(p4)
123 nodes_circle = mesh.Nodes_Cylinder(circle, direction=[0, 0, ep])
124 nodes_edges = mesh.Nodes_Conditions(lambda x, y, z: (x == 0) | (y == 0))
125
126 # ----------------------------------------------
127 # Simulation
128 # ----------------------------------------------
129 material = Models.Elastic.Isotropic(dim, E, v, True, ep)
130 pfm = Models.PhaseField(material, split, regu, Gc, l0)
131
132 folder_save = Simulations.PhaseField.Folder(
133 f"{folder}{dim}D",
134 "",
135 pfm.split,
136 pfm.regularization,
137 "",
138 tolConv,
139 "",
140 meshTest,
141 optimMesh,
142 nL=nL,
143 )
144
145 Display.MyPrint(folder_save, "green", end="\n")
146
147 if doSimu:
148 simu = Simulations.PhaseField(mesh, pfm)
149 simu.Results_Set_Bc_Summary(config)
150
151 dofsY_load = simu.Bc_dofs_nodes(nodes_load, ["y"])
152
153 if pltIter:
154 axIter = Display.Plot_Result(simu, "damage")
155
156 axLoad = Display.Init_Axes()
157 axLoad.set_xlabel("displacement [mm]")
158 axLoad.set_ylabel("load [kN]")
159
160 list_ud = []
161 list_f = []
162 ud = -inc0
163 iter = -1
164
165 while ud <= uMax:
166 # update displacement
167 iter += 1
168 ud += inc0 if simu.damage.max() < 0.6 else inc1
169
170 # update boundary conditions
171 simu.Bc_Init()
172 simu.add_dirichlet(nodes_circle, [0], ["d"], "damage")
173 simu.add_dirichlet(nodes_y0, [0] * dim, simu.Get_unknowns())
174 simu.add_dirichlet(nodes_load, [ud], ["y"])
175
176 # solve
177 u, d, convergence = simu.Solve(tolConv, 500, convOption)
178 # calc load
179 f = np.sum(simu.Calc_Reaction(dofsY_load, "elastic"))
180
181 # saves load and displacement
182 list_ud.append(ud)
183 list_f.append(f)
184
185 # print iter
186 simu.Results_Set_Iteration_Summary(iter, ud, "mm", ud / uMax, True)
187
188 # saves iteration
189 simu.Save_Iter()
190
191 if pltIter:
192 plt.figure(axIter.figure)
193 Display.Plot_Result(simu, "damage", ax=axIter)
194 plt.pause(1e-12)
195
196 plt.figure(axLoad.figure)
197 axLoad.scatter(ud, f / 1000, c="black")
198 plt.pause(1e-12)
199
200 if not convergence or simu.Detect_Damage(nodes_edges):
201 # stops simulation if damage occurs on edges or convergence has not been reached
202 break
203
204 # saves load and displacement
205 Simulations.Save_pickle((list_f, list_ud), folder_save, "force-displacement")
206
207 # saves the simulation
208 simu.Save(folder_save)
209
210 else:
211 simu = Simulations.Load_Simu(folder_save)
212 mesh = simu.mesh
213
214 list_f, list_ud = Simulations.Load_pickle(folder_save, "force-displacement")
215
216 # ----------------------------------------------
217 # Results
218 # ----------------------------------------------
219 Display.Plot_Result(simu, "damage", folder=folder_save)
220 Display.Plot_Mesh(simu)
221 Display.Plot_BoundaryConditions(simu)
222
223 axLoad = Display.Init_Axes()
224 axLoad.set_xlabel("displacement [mm]")
225 axLoad.set_ylabel("load [kN]")
226 axLoad.plot(list_ud, np.abs(list_f) / 1000, c="blue")
227 Display.Save_fig(folder_save, "forcedep")
228
229 Display.Plot_Iter_Summary(simu, folder_save)
230
231 if makeMovie:
232 simu.Set_Iter(-1)
233 deformFactor = L * 0.05 / simu.Result("displacement_norm").max()
234
235 iterations = np.arange(0, simu.Niter, simu.Niter // 20)
236
237 def Func(plotter, iter):
238 simu.Set_Iter(iterations[iter])
239 thresh = PyVista._pvMesh(simu, "damage", deformFactor).threshold((0, 0.8))
240 PyVista.Plot(thresh, "damage", plotMesh=True, plotter=plotter, clim=(0, 1))
241
242 PyVista.Movie_func(Func, iterations.size, folder_save, "damage.gif")
243
244 if makeParaview:
245 Paraview.Save_simu(simu, folder_save)
246
247 plt.show()
Total running time of the script: (0 minutes 9.983 seconds)




