Homog4#

Conduct 3d homogenization. # Warning: Verify that the periodic boundary conditions have been correctly applied.

Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
Homog4
C_hom =
 5.793e+00  3.569e+00  3.512e+00  3.532e-16 -5.546e-15 -1.519e-04
 3.569e+00  5.857e+00  3.537e+00  3.884e-15 -7.533e-16  1.315e-04
 3.512e+00  3.537e+00  2.300e+01  1.235e-15 -1.707e-15 -7.543e-06
 5.712e-17  2.133e-16  6.665e-15  1.539e+00  3.430e-07  7.187e-18
 2.110e-16 -7.865e-17  2.774e-14  3.430e-07  1.557e+00 -4.734e-17
-1.519e-04  1.315e-04 -7.543e-06 -3.702e-15 -1.614e-15  1.282e+00

 13 from EasyFEA import Display, Models, plt, np, ElemType, Simulations, PyVista
 14 from EasyFEA.Geoms import Points, Circle
 15 from EasyFEA.fem import Mesh, LagrangeCondition, FeArray
 16 from typing import Optional
 17
 18
 19 def Compute_ukl(
 20     simu: Simulations.ElasticSimu,
 21     nodes_border: np.ndarray,
 22     Ekl: np.ndarray,
 23     paired_nodes: Optional[np.ndarray] = None,
 24     pltSol=False,
 25 ):
 26     simu.Bc_Init()
 27     mesh = simu.mesh
 28     coord = mesh.coord
 29
 30     usePER = paired_nodes is not None
 31
 32     def func_ux(x, y, z):
 33         return Ekl.dot([x, y, z])[0]
 34
 35     def func_uy(x, y, z):
 36         return Ekl.dot([x, y, z])[1]
 37
 38     def func_uz(x, y, z):
 39         return Ekl.dot([x, y, z])[2]
 40
 41     directions = ["x", "y", "z"]
 42
 43     simu.add_dirichlet(nodes_border, [func_ux, func_uy, func_uz], directions)
 44
 45     if usePER:
 46         for n0, n1 in paired_nodes:
 47             nodes = np.array([n0, n1])
 48
 49             for d, direction in enumerate(directions):
 50                 dofs = simu.Bc_dofs_nodes(nodes, [direction])
 51
 52                 values = Ekl @ [
 53                     coord[n0, 0] - coord[n1, 0],
 54                     coord[n0, 1] - coord[n1, 1],
 55                     coord[n0, 2] - coord[n1, 2],
 56                 ]
 57                 value = values[d]
 58
 59                 condition = LagrangeCondition(
 60                     "elastic", nodes, dofs, [direction], [value], [1, -1]
 61                 )
 62                 simu._Bc_Add_Lagrange(condition)
 63
 64     ukl = simu.Solve()
 65
 66     simu.Save_Iter()
 67
 68     if pltSol:
 69         PyVista.Plot(simu, "ux", deformFactor=0.3).show()
 70         PyVista.Plot(simu, "uy", deformFactor=0.3).show()
 71
 72         PyVista.Plot(simu, "Sxx", deformFactor=0.3).show()
 73         PyVista.Plot(simu, "Syy", deformFactor=0.3).show()
 74         PyVista.Plot(simu, "Sxy", deformFactor=0.3).show()
 75
 76     return ukl
 77
 78
 79 def Get_nodes(mesh: Mesh, dimElem: int):
 80     """Returns\n
 81     nodesLeft, nodesRight, nodesUpper, nodesLower, nodesFront, nodesBack"""
 82
 83     coord = mesh.coord
 84
 85     conditions = {
 86         "left": lambda x, y, z: x == coord[:, 0].min(),
 87         "right": lambda x, y, z: x == coord[:, 0].max(),
 88         "lower": lambda x, y, z: y == coord[:, 1].min(),
 89         "upper": lambda x, y, z: y == coord[:, 1].max(),
 90         "back": lambda x, y, z: z == coord[:, 2].min(),
 91         "front": lambda x, y, z: z == coord[:, 2].max(),
 92     }
 93
 94     # get nodes
 95     nodes = {key: [] for key in conditions}
 96     for groupElem in mesh.Get_list_groupElem(dimElem):
 97         for key, condition in conditions.items():
 98             nodes[key].extend(groupElem.Get_Nodes_Conditions(condition))
 99
100     return tuple(np.asarray(nodes[key]) for key in conditions)
101
102
103 def Get_kubc_nodes(mesh: Mesh, dimElem: int = 0):
104     """Returns nodes_kubc"""
105
106     coord = mesh.coord
107
108     # conditions to get nodes on x and y faces
109     conditions = [
110         lambda x, y, z: x == coord[:, 0].min(),
111         lambda x, y, z: x == coord[:, 0].max(),
112         lambda x, y, z: y == coord[:, 1].min(),
113         lambda x, y, z: y == coord[:, 1].max(),
114         # lambda x, y, z: z == coord[:, 2].min(),
115         # lambda x, y, z: z == coord[:, 2].max(),
116     ]
117
118     # get nodes
119     nodes_kubc: set[int] = set()
120     for groupElem in mesh.Get_list_groupElem(dimElem):
121         for condition in conditions:
122             nodes = groupElem.Get_Nodes_Conditions(condition)
123             nodes_kubc = nodes_kubc.union(nodes)
124
125     return np.asarray(list(nodes_kubc), dtype=int)
126
127
128 if __name__ == "__main__":
129     Display.Clear()
130
131     # ----------------------------------------------
132     # Configuration
133     # ----------------------------------------------
134
135     # use Periodic boundary conditions ?
136     usePBC = True
137     plotPBC = True
138     plotSurfaces = False
139
140     # ----------------------------------------------
141     # Mesh
142     # ----------------------------------------------
143     meshSize = 1 / 10
144
145     p0 = (-1 / 2, -1 / 2)
146     p1 = (1 / 2, -1 / 2)
147     p2 = (1 / 2, 1 / 2)
148     p3 = (-1 / 2, 1 / 2)
149     pts = [p0, p1, p2, p3]
150     contour = Points(pts, meshSize)
151
152     # inclusion
153     f = 0.4
154     r = 1 * np.sqrt(f / np.pi)
155     inclusion = Circle((0, 0), 2 * r, meshSize, isHollow=False)
156     # contour.Plot_Geoms([contour, inclusion])
157
158     elemType = ElemType.PRISM6
159     mesh = contour.Mesh_Extrude([inclusion], [0, 0, 1], [1 / meshSize], elemType)
160
161     plotter = PyVista.Plot_Mesh(mesh)
162     plotter.add_title("RVE")
163     plotter.show()
164
165     # ----------------------------------------------
166     # Get paired nodes
167     # ----------------------------------------------
168
169     # PyVista.Plot_Tags(mesh).show()
170
171     nodesLeft, nodesRight, nodesLower, nodesUpper, nodesFront, nodesBack = Get_nodes(
172         mesh, dimElem=2
173     )
174
175     if plotSurfaces:
176         plotter = PyVista.Plot(mesh, alpha=0.1)
177         colors = plt.get_cmap("tab10").colors
178
179         dict_nodes = {
180             f"{nodesLeft=}".split("=")[0]: nodesLeft,
181             f"{nodesRight=}".split("=")[0]: nodesRight,
182             f"{nodesLower=}".split("=")[0]: nodesLower,
183             f"{nodesUpper=}".split("=")[0]: nodesUpper,
184             f"{nodesFront=}".split("=")[0]: nodesFront,
185             f"{nodesBack=}".split("=")[0]: nodesBack,
186         }
187
188         for i, (name, nodes) in enumerate(dict_nodes.items()):
189             PyVista.Plot_Elements(
190                 mesh, nodes, 2, color=colors[i], label=name, plotter=plotter
191             )
192         plotter.add_legend()
193         plotter.show()
194
195     if usePBC:
196         # Hybrid PBC setup
197         nodes_kubc = Get_kubc_nodes(mesh, dimElem=0)
198         # PyVista.Plot_Nodes(mesh, nodes_kubc).show()
199
200         # get nodes along x, y and z directions
201         nodes_x = set(nodesLeft).union(nodesRight)
202         nodes_y = set(nodesLower).union(nodesUpper)
203         nodes_z = set(nodesFront).union(nodesBack)
204
205         # get nodes along ij directions
206         nodes_xy = nodes_x.union(nodes_y)
207         nodes_xz = nodes_x.union(nodes_z)
208         nodes_yz = nodes_y.union(nodes_z)
209
210         # Get nodes along the y-axis without nodes along x axis.
211         nodesLower = np.array([node for node in nodesLower if node not in nodes_x])
212         nodesUpper = np.array([node for node in nodesUpper if node not in nodes_x])
213
214         # Get nodes along the z-axis without nodes along x and y axis.
215         nodesFront = np.array([node for node in nodesFront if node not in nodes_xy])
216         nodesBack = np.array([node for node in nodesBack if node not in nodes_xy])
217
218         paired_surfaces = [
219             (nodesLeft, nodesRight),  # x
220             (nodesLower, nodesUpper),  # y
221             (nodesFront, nodesBack),  # z
222         ]
223
224         # get paired nodes
225         for i, (nodes1, nodes2) in enumerate(paired_surfaces):
226
227             # remove kubc nodes
228             nodes1 = np.array(list(set(nodes1) - set(nodes_kubc)))
229             nodes2 = np.array(list(set(nodes2) - set(nodes_kubc)))
230
231             # sort nodes
232             sorted_nodes2 = np.zeros_like(nodes1)
233             coord = mesh.coord
234             for n, node in enumerate(nodes1):
235                 dist = np.linalg.norm(coord[nodes2] - coord[node], axis=1)
236                 sorted_nodes2[n] = nodes2[dist.argmin()]
237             nodes2 = sorted_nodes2
238
239             if plotPBC:
240                 plotter = PyVista.Plot_Mesh(mesh, alpha=0.1)
241                 PyVista.Plot_Nodes(mesh, nodes1, plotter=plotter)
242                 PyVista.Plot_Nodes(mesh, nodes2, plotter=plotter)
243                 plotter.add_lines(
244                     np.concatenate(
245                         (mesh.coord[nodes1], mesh.coord[nodes2]), axis=1
246                     ).reshape(-1, 3),
247                     color="k",
248                 )
249                 plotter.add_title(f"paired nodes along {['x','y','z'][i]} axis.")
250                 plotter.show()
251
252             # set new paired nodes
253             newPairedNodes = np.array([nodes1, nodes2]).T
254             if i == 0:
255                 paired_nodes = newPairedNodes
256             else:
257                 paired_nodes = np.concatenate((paired_nodes, newPairedNodes))
258
259     else:
260         nodes_kubc = set(
261             np.concatenate(
262                 [nodesLeft, nodesRight, nodesUpper, nodesLower, nodesBack, nodesFront]
263             )
264         )
265         nodes_kubc = list(nodes_kubc)
266         paired_nodes = None
267
268     # ----------------------------------------------
269     # Material and Simulation
270     # ----------------------------------------------
271     elements_inclusion = mesh.Elements_Tags(["V1"])
272     elements_matrix = mesh.Elements_Tags(["V0"])
273
274     E = np.zeros_like(mesh.groupElem.elements, dtype=float)
275     v = np.zeros_like(mesh.groupElem.elements, dtype=float)
276
277     E[elements_matrix] = 1  # MPa
278     v[elements_matrix] = 0.45
279
280     if elements_inclusion.size > 0:
281         E[elements_inclusion] = 50
282         v[elements_inclusion] = 0.3
283
284     material = Models.ElasIsot(3, E, v)
285
286     simu = Simulations.ElasticSimu(mesh, material)
287
288     PyVista.Plot(simu, E, nodeValues=False, colorbarTitle="E [MPa]").show()
289     PyVista.Plot(simu, v, nodeValues=False, colorbarTitle="v").show()
290
291     # ----------------------------------------------
292     # Homogenization
293     # ----------------------------------------------
294     r2 = np.sqrt(2)
295     E11 = np.array(
296         [
297             [1, 0, 0],
298             [0, 0, 0],
299             [0, 0, 0],
300         ]
301     )
302     E22 = np.array(
303         [
304             [0, 0, 0],
305             [0, 1, 0],
306             [0, 0, 0],
307         ]
308     )
309     E33 = np.array(
310         [
311             [0, 0, 0],
312             [0, 0, 0],
313             [0, 0, 1],
314         ]
315     )
316     E12 = np.array(
317         [
318             [0, 1 / r2, 0],
319             [1 / r2, 0, 0],
320             [0, 0, 0],
321         ]
322     )
323     E13 = np.array(
324         [
325             [0, 0, 1 / r2],
326             [0, 0, 0],
327             [1 / r2, 0, 0],
328         ]
329     )
330     E23 = np.array(
331         [
332             [0, 0, 0],
333             [0, 0, 1 / r2],
334             [0, 1 / r2, 0],
335         ]
336     )
337
338     u11 = Compute_ukl(simu, nodes_kubc, E11, paired_nodes, True)
339     u22 = Compute_ukl(simu, nodes_kubc, E22, paired_nodes)
340     u33 = Compute_ukl(simu, nodes_kubc, E33, paired_nodes)
341     u12 = Compute_ukl(simu, nodes_kubc, E12, paired_nodes, True)
342     u13 = Compute_ukl(simu, nodes_kubc, E13, paired_nodes)
343     u23 = Compute_ukl(simu, nodes_kubc, E23, paired_nodes)
344
345     u11_e = mesh.Locates_sol_e(u11, asFeArray=True)
346     u22_e = mesh.Locates_sol_e(u22, asFeArray=True)
347     u33_e = mesh.Locates_sol_e(u33, asFeArray=True)
348     u12_e = mesh.Locates_sol_e(u12, asFeArray=True)
349     u13_e = mesh.Locates_sol_e(u13, asFeArray=True)
350     u23_e = mesh.Locates_sol_e(u23, asFeArray=True)
351
352     # ----------------------------------------------
353     # Effective elasticity tensor (C_hom)
354     # ----------------------------------------------
355     U_e = FeArray.zeros(*u11_e.shape, 6)
356
357     U_e[..., 0] = u11_e
358     U_e[..., 1] = u22_e
359     U_e[..., 2] = u33_e
360     U_e[..., 3] = u23_e
361     U_e[..., 4] = u13_e
362     U_e[..., 5] = u12_e
363
364     matrixType = "mass"
365     wJ_e_pg = mesh.Get_weightedJacobian_e_pg(matrixType)
366     B_e_pg = mesh.Get_B_e_pg(matrixType)
367
368     C_Mat = Models.Reshape_variable(material.C, *B_e_pg.shape[:2])
369
370     # Be careful here you have to use all the volume even if there are holes
371     # if you use the mesh volume, multiply C_hom by the porosity (1-f)
372     C_hom = (wJ_e_pg * C_Mat @ B_e_pg @ U_e).sum((0, 1)) / mesh.volume
373
374     if inclusion.isHollow:
375         C_hom *= 1 - f
376
377     formatted_array = ""
378     for i in range(6):
379         formatted_array += "\n"
380         for j in range(6):
381             formatted_array += f"{C_hom[i,j]:10.3e} "
382
383     print("C_hom =", formatted_array)
384
385     plt.show()

Total running time of the script: (0 minutes 9.564 seconds)

Gallery generated by Sphinx-Gallery