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.7.4/examples/PhaseField/results/LShape2D/Test/Miehe_AT1_CP_optimMesh nL=50 1 : 0.000 mm, [0.00e+00; 0.00e+00], 1:0.111 s, tol=0.00e+00
2 : 0.040 mm, [0.00e+00; 0.00e+00], 1:0.099 s, tol=1.00e+00 4.00 % -> 2.38 s
3 : 0.080 mm, [0.00e+00; 0.00e+00], 1:0.099 s, tol=9.95e-01 8.00 % -> 2.29 s
4 : 0.120 mm, [0.00e+00; 0.00e+00], 1:0.099 s, tol=5.56e-01 12.00 % -> 2.19 s
5 : 0.160 mm, [0.00e+00; 0.00e+00], 1:0.099 s, tol=4.38e-01 16.00 % -> 2.08 s
6 : 0.200 mm, [0.00e+00; 0.00e+00], 1:0.099 s, tol=3.60e-01 20.00 % -> 1.99 s
7 : 0.240 mm, [0.00e+00; 0.00e+00], 1:0.099 s, tol=3.06e-01 24.00 % -> 1.88 s
8 : 0.280 mm, [0.00e+00; 8.98e-03], 1:0.100 s, tol=2.65e-01 28.00 % -> 1.79 s
9 : 0.320 mm, [0.00e+00; 4.57e-02], 1:0.099 s, tol=2.32e-01 32.00 % -> 1.69 s
10 : 0.360 mm, [0.00e+00; 1.10e-01], 1:0.099 s, tol=2.07e-01 36.00 % -> 1.59 s
11 : 0.400 mm, [0.00e+00; 2.07e-01], 1:0.100 s, tol=1.86e-01 40.00 % -> 1.50 s
12 : 0.440 mm, [0.00e+00; 3.48e-01], 1:0.099 s, tol=1.69e-01 44.00 % -> 1.39 s
13 : 0.480 mm, [0.00e+00; 5.46e-01], 1:0.100 s, tol=1.55e-01 48.00 % -> 1.30 s
14 : 0.520 mm, [0.00e+00; 7.78e-01], 1:0.099 s, tol=1.62e-01 52.00 % -> 1.19 s
15 : 0.540 mm, [0.00e+00; 9.48e-01], 1:0.100 s, tol=2.22e-01 54.00 % -> 1.19 s
16 : 0.560 mm, [0.00e+00; 9.93e-01], 1:0.100 s, tol=3.80e-01 56.00 % -> 1.18 s
17 : 0.580 mm, [0.00e+00; 1.00e+00], 1:0.100 s, tol=4.44e-01 58.00 % -> 1.16 s
18 : 0.600 mm, [0.00e+00; 1.00e+00], 1:0.100 s, tol=3.82e-01 60.00 % -> 1.13 s
19 : 0.620 mm, [0.00e+00; 1.00e+00], 1:0.112 s, tol=3.28e-01 62.00 % -> 1.23 s
20 : 0.640 mm, [0.00e+00; 1.00e+00], 1:0.100 s, tol=2.91e-01 64.00 % -> 1.07 s
21 : 0.660 mm, [0.00e+00; 1.00e+00], 1:0.100 s, tol=2.78e-01 66.00 % -> 1.03 s
22 : 0.680 mm, [0.00e+00; 1.00e+00], 1:0.104 s, tol=2.54e-01 68.00 % -> 1.02 s
23 : 0.700 mm, [0.00e+00; 1.00e+00], 1:0.101 s, tol=2.53e-01 70.00 % -> 947.95 ms
24 : 0.720 mm, [0.00e+00; 1.00e+00], 1:0.103 s, tol=2.02e-01 72.00 % -> 921.71 ms
25 : 0.740 mm, [0.00e+00; 1.00e+00], 1:0.105 s, tol=1.76e-01 74.00 % -> 882.03 ms
26 : 0.760 mm, [0.00e+00; 1.00e+00], 1:0.104 s, tol=1.87e-01 76.00 % -> 819.12 ms
27 : 0.780 mm, [0.00e+00; 1.00e+00], 1:0.112 s, tol=1.72e-01 78.00 % -> 817.82 ms
28 : 0.800 mm, [0.00e+00; 1.00e+00], 1:0.105 s, tol=1.65e-01 80.00 % -> 709.43 ms
29 : 0.820 mm, [0.00e+00; 1.00e+00], 1:0.107 s, tol=1.90e-01 82.00 % -> 656.09 ms
30 : 0.840 mm, [0.00e+00; 1.00e+00], 1:0.106 s, tol=1.65e-01 84.00 % -> 584.48 ms
31 : 0.860 mm, [0.00e+00; 1.00e+00], 1:0.114 s, tol=1.51e-01 86.00 % -> 555.93 ms
32 : 0.880 mm, [0.00e+00; 1.00e+00], 1:0.110 s, tol=1.15e-01 88.00 % -> 464.55 ms
33 : 0.900 mm, [0.00e+00; 1.00e+00], 1:0.104 s, tol=1.10e-01 90.00 % -> 369.99 ms
34 : 0.920 mm, [0.00e+00; 1.00e+00], 1:0.109 s, tol=9.93e-02 92.00 % -> 313.56 ms
35 : 0.940 mm, [0.00e+00; 1.00e+00], 1:0.108 s, tol=9.94e-02 94.00 % -> 234.71 ms
36 : 0.960 mm, [0.00e+00; 1.00e+00], 1:0.108 s, tol=9.12e-02 96.00 % -> 157.59 ms
37 : 0.980 mm, [0.00e+00; 1.00e+00], 1:0.110 s, tol=1.02e-01 98.00 % -> 80.64 ms
38 : 1.000 mm, [0.00e+00; 1.00e+00], 1:0.114 s, tol=9.35e-02 100.00 % -> -0.00 µs
Saved:
/home/docs/checkouts/readthedocs.org/user_builds/easyfea/checkouts/v1.7.4/examples/PhaseField/results/LShape2D/Test/Miehe_AT1_CP_optimMesh nL=50/force-displacement.pickle
Saved:
/home/docs/checkouts/readthedocs.org/user_builds/easyfea/checkouts/v1.7.4/examples/PhaseField/results/LShape2D/Test/Miehe_AT1_CP_optimMesh nL=50/simulation.pickle
Saved:
/home/docs/checkouts/readthedocs.org/user_builds/easyfea/checkouts/v1.7.4/examples/PhaseField/results/LShape2D/Test/Miehe_AT1_CP_optimMesh nL=50/summary.txt
Loaded:
/home/docs/checkouts/readthedocs.org/user_builds/easyfea/checkouts/v1.7.4/examples/PhaseField/results/LShape2D/Test/Miehe_AT1_CP_optimMesh nL=50/force-displacement.pickle
Generate movie 01/38 (2.63 %) 4.46 s
Generate movie 02/38 (5.26 %) 3.82 s
Generate movie 03/38 (7.89 %) 3.66 s
Generate movie 04/38 (10.53 %) 3.53 s
Generate movie 05/38 (13.16 %) 3.41 s
Generate movie 06/38 (15.79 %) 3.33 s
Generate movie 07/38 (18.42 %) 3.17 s
Generate movie 08/38 (21.05 %) 3.09 s
Generate movie 09/38 (23.68 %) 3.00 s
Generate movie 10/38 (26.32 %) 2.89 s
Generate movie 11/38 (28.95 %) 2.80 s
Generate movie 12/38 (31.58 %) 2.76 s
Generate movie 13/38 (34.21 %) 2.62 s
Generate movie 14/38 (36.84 %) 2.47 s
Generate movie 15/38 (39.47 %) 2.38 s
Generate movie 16/38 (42.11 %) 2.29 s
Generate movie 17/38 (44.74 %) 2.19 s
Generate movie 18/38 (47.37 %) 2.09 s
Generate movie 19/38 (50.00 %) 1.95 s
Generate movie 20/38 (52.63 %) 1.85 s
Generate movie 21/38 (55.26 %) 1.76 s
Generate movie 22/38 (57.89 %) 1.68 s
Generate movie 23/38 (60.53 %) 1.57 s
Generate movie 24/38 (63.16 %) 1.47 s
Generate movie 25/38 (65.79 %) 1.36 s
Generate movie 26/38 (68.42 %) 1.25 s
Generate movie 27/38 (71.05 %) 1.14 s
Generate movie 28/38 (73.68 %) 1.04 s
Generate movie 29/38 (76.32 %) 956.31 ms
Generate movie 30/38 (78.95 %) 831.56 ms
Generate movie 31/38 (81.58 %) 725.01 ms
Generate movie 32/38 (84.21 %) 624.02 ms
Generate movie 33/38 (86.84 %) 521.84 ms
Generate movie 34/38 (89.47 %) 407.24 ms
Generate movie 35/38 (92.11 %) 312.56 ms
Generate movie 36/38 (94.74 %) 206.40 ms
Generate movie 37/38 (97.37 %) 102.21 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 (
17 Display,
18 Folder,
19 Models,
20 Tic,
21 ElemType,
22 Simulations,
23 Paraview,
24 PyVista,
25 )
26 from EasyFEA.Geoms import Point, Points, Domain, Circle
27
28 if __name__ == "__main__":
29 Display.Clear()
30
31 # ----------------------------------------------
32 # Configuration
33 # ----------------------------------------------
34
35 # simu options
36 doSimu = True
37 meshTest = True
38 optimMesh = True
39
40 # outputs
41 folder = Folder.Results_Dir()
42 pltIter = False
43 pltLoad = False
44 makeMovie = True
45 makeParaview = False
46
47 # geom
48 dim = 2
49 L = 250 # mm
50 nL = 50
51 ep = 100
52
53 # model
54 E = 2e4 # MPa
55 v = 0.18
56
57 split = "Miehe"
58 regu = "AT1"
59 Gc = 130 # J/m2
60 Gc *= 1000 / 1e6 # mJ/mm2
61
62 # convergence
63 tolConv = 1e-0
64 convOption = 2
65
66 # load
67 uMax = 1 # mm
68 inc0 = uMax / 25
69 inc1 = inc0 / 2
70
71 config = f"""
72 uMax = {uMax}
73
74 inc0 = {inc0}
75 inc1 = {inc1}
76
77 while ud <= uMax:
78
79 ud += inc0 if simu.damage.max() < 0.6 else inc1
80
81 simu.add_dirichlet(nodes_circle, [0], ['d'], "damage")
82 simu.add_dirichlet(nodes_y0, [0]*dim, simu.Get_dofs())
83 simu.add_dirichlet(nodes_load, [ud], ['y'])
84 """
85
86 # ----------------------------------------------
87 # Mesh
88 # ----------------------------------------------
89 l0 = L / nL
90
91 if meshTest:
92 hC = l0
93 else:
94 hC = 0.5
95 # hC = 0.25
96
97 p1 = Point()
98 p2 = Point(L, 0)
99 p3 = Point(L, L)
100 p4 = Point(2 * L - 30, L)
101 p5 = Point(2 * L, L)
102 p6 = Point(2 * L, 2 * L)
103 p7 = Point(0, 2 * L)
104 if optimMesh:
105 # hauteur zone rafinée
106 h = 100
107 refineDomain = Domain(Point(0, L - h / 3), Point(L + h / 3, L + h), hC)
108 hD = hC * 5
109 else:
110 refineDomain = None
111 hD = hC
112
113 contour = Points([p1, p2, p3, p4, p5, p6, p7], hD)
114
115 circle = Circle(p5, 100)
116
117 if dim == 2:
118 mesh = contour.Mesh_2D([], ElemType.TRI3, refineGeoms=[refineDomain])
119 else:
120 mesh = contour.Mesh_Extrude(
121 [], [0, 0, -ep], [3], ElemType.HEXA8, refineGeoms=[refineDomain]
122 )
123
124 # Display.Plot_Mesh(mesh)
125 # Display.Plot_Tags(mesh)
126 # from EasyFEA import PyVista
127 # PyVista.Plot_Mesh(mesh).show()
128
129 nodes_y0 = mesh.Nodes_Conditions(lambda x, y, z: y == 0)
130 nodes_load = mesh.Nodes_Conditions(lambda x, y, z: (y == L) & (x >= 2 * L - 30))
131 node3 = mesh.Nodes_Point(p3)
132 node4 = mesh.Nodes_Point(p4)
133 nodes_circle = mesh.Nodes_Cylinder(circle, direction=[0, 0, ep])
134 nodes_edges = mesh.Nodes_Conditions(lambda x, y, z: (x == 0) | (y == 0))
135
136 # ----------------------------------------------
137 # Simulation
138 # ----------------------------------------------
139 material = Models.Elastic.Isotropic(dim, E, v, True, ep)
140 pfm = Models.PhaseField(material, split, regu, Gc, l0)
141
142 folder_save = Simulations.PhaseField.Folder(
143 f"{folder}{dim}D",
144 "",
145 pfm.split,
146 pfm.regularization,
147 "CP",
148 tolConv,
149 "",
150 meshTest,
151 optimMesh,
152 nL=nL,
153 )
154
155 Display.MyPrint(folder_save, "green")
156
157 if doSimu:
158 simu = Simulations.PhaseField(mesh, pfm)
159 simu.Results_Set_Bc_Summary(config)
160
161 dofsY_load = simu.Bc_dofs_nodes(nodes_load, ["y"])
162
163 if pltIter:
164 axIter = Display.Plot_Result(simu, "damage")
165
166 axLoad = Display.Init_Axes()
167 axLoad.set_xlabel("displacement [mm]")
168 axLoad.set_ylabel("load [kN]")
169
170 displacement = []
171 force = []
172 ud = -inc0
173 iter = -1
174
175 while ud <= uMax:
176 # update displacement
177 iter += 1
178 ud += inc0 if simu.damage.max() < 0.6 else inc1
179
180 # update boundary conditions
181 simu.Bc_Init()
182 simu.add_dirichlet(nodes_circle, [0], ["d"], "damage")
183 simu.add_dirichlet(nodes_y0, [0] * dim, simu.Get_unknowns())
184 simu.add_dirichlet(nodes_load, [ud], ["y"])
185
186 # solve
187 u, d, Ku, convergence = simu.Solve(tolConv, 500, convOption)
188 # calc load
189 fr = np.sum(Ku[dofsY_load, :] @ u)
190
191 # saves load and displacement
192 displacement.append(ud)
193 force.append(fr)
194
195 # print iter
196 simu.Results_Set_Iteration_Summary(iter, ud, "mm", ud / uMax, True)
197
198 # saves iteration
199 simu.Save_Iter()
200
201 if pltIter:
202 plt.figure(axIter.figure)
203 Display.Plot_Result(simu, "damage", ax=axIter)
204 plt.pause(1e-12)
205
206 plt.figure(axLoad.figure)
207 axLoad.scatter(ud, fr / 1000, c="black")
208 plt.pause(1e-12)
209
210 if not convergence or np.max(d[nodes_edges]) >= 1:
211 # stops simulation if damage occurs on edges or convergence has not been reached
212 break
213
214 # saves load and displacement
215 displacement = np.asarray(displacement)
216 force = np.asarray(force)
217 Simulations.Save_pickle(
218 (force, displacement), folder_save, "force-displacement"
219 )
220
221 # saves the simulation
222 simu.Save(folder_save)
223
224 else:
225 simu = Simulations.Load_Simu(folder_save)
226 mesh = simu.mesh
227
228 force, displacement = Simulations.Load_pickle(folder_save, "force-displacement")
229
230 # ----------------------------------------------
231 # Results
232 # ----------------------------------------------
233 Display.Plot_Result(simu, "damage", folder=folder_save)
234 Display.Plot_Mesh(simu)
235 Display.Plot_BoundaryConditions(simu)
236
237 axLoad = Display.Init_Axes()
238 axLoad.set_xlabel("displacement [mm]")
239 axLoad.set_ylabel("load [kN]")
240 axLoad.plot(displacement, force / 1000, c="blue")
241 Display.Save_fig(folder_save, "forcedep")
242
243 Display.Plot_Iter_Summary(simu, folder_save)
244
245 if makeMovie:
246 simu.Set_Iter(-1)
247 depMax = simu.Result("displacement_norm").max()
248 deformFactor = L * 0.05 / depMax
249
250 iterations = np.arange(0, simu.Niter, simu.Niter // 20)
251
252 def Func(plotter, iter):
253 simu.Set_Iter(iterations[iter])
254
255 grid = PyVista._pvMesh(simu, "damage", deformFactor)
256
257 tresh = grid.threshold((0, 0.8))
258
259 PyVista.Plot(
260 tresh,
261 "damage",
262 deformFactor,
263 plotMesh=True,
264 plotter=plotter,
265 clim=(0, 1),
266 )
267
268 PyVista.Movie_func(Func, iterations.size, folder_save, "damage.gif")
269
270 if makeParaview:
271 Paraview.Save_simu(simu, folder_save)
272
273 if doSimu:
274 Tic.Plot_History(folder_save, False)
275
276 plt.show()
Total running time of the script: (0 minutes 11.287 seconds)





