Davout 0.1.1.dev182__py3-none-any.whl → 0.1.1.dev183__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. Davout/CuboidGmsh/aa_tests/solids/notch_mesh.py +250 -0
  2. Davout/DeepMech/aa_tests/SVD_framework/kinematics_surrogate_model.py +16 -9
  3. Davout/MultiMech/aa_tests_and_examples/physics_prototypes/compressible_hyperelasticity.py +14 -8
  4. Davout/MultiMech/aa_tests_and_examples/physics_prototypes/incompressible_hyperelasticity.py +8 -3
  5. Davout/MultiMech/aa_tests_and_examples/physics_prototypes/infinitesimal_plasticity.py +239 -0
  6. Davout/MultiMech/constitutive_models/hyperelasticity/infinitesimal_elasticity.py +146 -0
  7. Davout/MultiMech/constitutive_models/plasticity/isotropic_infinitesimal_plasticity.py +636 -0
  8. Davout/MultiMech/tool_box/boundary_conditions_tools.py +51 -8
  9. Davout/MultiMech/tool_box/constitutive_tools.py +42 -14
  10. Davout/MultiMech/tool_box/functional_tools.py +293 -22
  11. Davout/MultiMech/tool_box/mesh_handling_tools.py +14 -5
  12. Davout/MultiMech/tool_box/newton_raphson_tools.py +310 -0
  13. Davout/MultiMech/tool_box/projection_tools.py +652 -0
  14. Davout/MultiMech/tool_box/pseudotime_stepping_tools.py +6 -6
  15. Davout/MultiMech/tool_box/read_write_tools.py +371 -113
  16. Davout/MultiMech/tool_box/surface_loading_tools.py +10 -4
  17. Davout/MultiMech/tool_box/variational_tools.py +1 -179
  18. {davout-0.1.1.dev182.dist-info → davout-0.1.1.dev183.dist-info}/METADATA +1 -1
  19. {davout-0.1.1.dev182.dist-info → davout-0.1.1.dev183.dist-info}/RECORD +22 -16
  20. {davout-0.1.1.dev182.dist-info → davout-0.1.1.dev183.dist-info}/WHEEL +0 -0
  21. {davout-0.1.1.dev182.dist-info → davout-0.1.1.dev183.dist-info}/licenses/LICENSE +0 -0
  22. {davout-0.1.1.dev182.dist-info → davout-0.1.1.dev183.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,250 @@
1
+ # Routine to generate an interchangeble mesh both for thrird medium
2
+ # contact and for notch-based crack propagation.
3
+ #
4
+ # Mesh made by Bianca Grahl Reyes
5
+
6
+ import h5py
7
+
8
+ import numpy as np
9
+
10
+ from .....Davout.CuboidGmsh.solids import cuboid_prisms as prisms
11
+
12
+ from .....Davout.CuboidGmsh.tool_box import meshing_tools as tools
13
+
14
+ from .....Davout.PythonicUtilities.path_tools import get_parent_path_of_file
15
+
16
+ # Defines a function to generate the mesh from a set of geometrical pa-
17
+ # rametres. L is the length of the box, W is the width of the box, H is
18
+ # the height of the box, theta is the notch opening angle, and
19
+ # half_W_notch is the notch width.
20
+
21
+ def generate_mesh(L, W, H, theta, half_W_notch, L_notch, transfinite_x,
22
+ transfinite_y, transfinite_z, transfinite_radial, mesh_file_name,
23
+ bias_x, bias_y, bias_z, bias_radial, include_drittes_medium=True,
24
+ verbose=True):
25
+
26
+ # Verifies whether the notch opening angle of the notch is between 0
27
+ # and 90 degrees
28
+
29
+ if theta<0.0 or theta>90.0:
30
+
31
+ raise ValueError("The notch opening angle should be between 0 "+
32
+ "and 90 degrees. Currently, 'theta' is "+str(theta))
33
+
34
+ # Converts the theta angle to radians
35
+
36
+ theta = theta*(np.pi/180.0)
37
+
38
+ # Verifies whether the notch width is confined within the box width
39
+
40
+ if (2*half_W_notch*np.sin(theta))>=W:
41
+
42
+ raise ValueError("The notch width, 'half_W_notch', and the not"+
43
+ "ch opening angle, 'theta', should be such that 2*half_W_notch"+
44
+ "*sin(theta) < W. So that the notch fits into the width of the"+
45
+ " box")
46
+
47
+ # Verifies whether the notch length is confined within the box length
48
+
49
+ # Defines the surfaces and volumes regions names for imposition of
50
+ # boundary conditions and integration of constitutive models
51
+
52
+ surfaces_regions_names = ["top", "front_solid", "front_third", "back", "bottom"]
53
+
54
+ volumes_regions_names = ["third medium", "solid"]
55
+
56
+ # Initializes the mesh
57
+
58
+ geometric_data = tools.gmsh_initialization(surface_regionsNames=
59
+ surfaces_regions_names, volume_regionsNames=volumes_regions_names)
60
+
61
+ # Creates the upper half of the notch (filled with third medium)
62
+
63
+ # Sets the corner points
64
+
65
+ corner_points = np.array([[L-L_notch, 0.5*W, 0.0], [L, 0.5*W, 0.0],
66
+ [L, (0.5*W)+(half_W_notch*np.sin(theta)), 0.0], [L-L_notch+(
67
+ half_W_notch*np.cos(theta)), (0.5*W)+(half_W_notch*np.sin(theta)),
68
+ 0.0],
69
+ [L-L_notch, 0.5*W, H], [L, 0.5*W, H],
70
+ [L, (0.5*W)+(half_W_notch*np.sin(theta)), H], [L-L_notch+(
71
+ half_W_notch*np.cos(theta)), (0.5*W)+(half_W_notch*np.sin(theta)),
72
+ H]])
73
+
74
+ # Generates this cuboid
75
+
76
+ if include_drittes_medium:
77
+
78
+ geometric_data = prisms.hexahedron_from_corners(corner_points,
79
+ transfinite_directions = [transfinite_y, transfinite_x,
80
+ transfinite_z], geometric_data=geometric_data,
81
+ explicit_volume_physical_group_name = "third medium",
82
+ explicit_surface_physical_group_name = {3: "front_third"},
83
+ bias_directions = {"x": bias_y, "y": bias_x, "z": bias_z})
84
+
85
+ # Creates the upper section of the solid
86
+
87
+ # Sets the corner points
88
+
89
+ corner_points = np.array([[L-L_notch+(half_W_notch*np.cos(theta)),
90
+ (0.5*W)+(half_W_notch*np.sin(theta)), 0.0],
91
+ [L, (0.5*W)+(half_W_notch*np.sin(theta)), 0.0],
92
+ [L, W, 0.0], [0.0, W, 0.0],
93
+ [L-L_notch+(half_W_notch*np.cos(theta)),
94
+ (0.5*W)+(half_W_notch*np.sin(theta)), H],
95
+ [L, (0.5*W)+(half_W_notch*np.sin(theta)), H],
96
+ [L, W, H], [0.0, W, H]])
97
+
98
+ # Generates this cuboid
99
+
100
+ geometric_data = prisms.hexahedron_from_corners(corner_points,
101
+ transfinite_directions = [transfinite_radial, transfinite_x,
102
+ transfinite_z], geometric_data=geometric_data,
103
+ explicit_volume_physical_group_name = "solid",
104
+ explicit_surface_physical_group_name = {3: "front_solid", 4: "top"},
105
+ bias_directions = {"x": bias_radial, "y": bias_x, "z": bias_z})
106
+
107
+ # Creates the upper section of the back of the solid
108
+
109
+ # Sets the corner points
110
+
111
+ corner_points = np.array([[0.0, 0.5*W, 0.0], [L-L_notch, 0.5*W, 0.0],
112
+ [L-L_notch+(half_W_notch*np.cos(theta)), (0.5*W)+(half_W_notch*
113
+ np.sin(theta)), 0.0], [0.0, W, 0.0],
114
+ [0.0, 0.5*W, H], [L-L_notch, 0.5*W, H],
115
+ [L-L_notch+(half_W_notch*np.cos(theta)), (0.5*W)+(half_W_notch*
116
+ np.sin(theta)), H], [0.0, W, H]])
117
+
118
+ # Generates this cuboid
119
+
120
+ geometric_data = prisms.hexahedron_from_corners(corner_points,
121
+ transfinite_directions = [transfinite_y, transfinite_x,
122
+ transfinite_z], geometric_data=geometric_data,
123
+ explicit_volume_physical_group_name = "solid",
124
+ explicit_surface_physical_group_name = {5: "back"},
125
+ bias_directions = {"x": bias_y, "y": bias_radial, "z": bias_z})
126
+
127
+ # Creates the botton section of the back of the solid (6)
128
+
129
+ # Sets the corner points
130
+
131
+ corner_points = np.array([[0.0, 0.0, 0.0], [(L-L_notch)+(
132
+ half_W_notch*np.cos(theta)), 0.5*W-(half_W_notch*np.sin(theta)), 0.0],
133
+ [L-L_notch, 0.5*W, 0.0], [0.0, 0.5*W, 0.0],
134
+ [0.0, 0.0, H], [(L-L_notch)+(half_W_notch*np.cos(theta)),
135
+ 0.5*W-(half_W_notch*np.sin(theta)), H],
136
+ [L-L_notch, 0.5*W, H], [0.0, 0.5*W, H]])
137
+
138
+ # Generates this cuboid
139
+
140
+ geometric_data = prisms.hexahedron_from_corners(corner_points,
141
+ transfinite_directions = [transfinite_y, transfinite_radial,
142
+ transfinite_z], geometric_data=geometric_data,
143
+ explicit_volume_physical_group_name = "solid",
144
+ explicit_surface_physical_group_name = {5: "back"},
145
+ bias_directions = {"x": -bias_y, "y": bias_radial, "z": bias_z})
146
+
147
+ # Creates the botton part of the third medium (2)
148
+
149
+ # Sets the corner points
150
+
151
+ corner_points = np.array([[(L-L_notch)+(half_W_notch*np.cos(theta)),
152
+ 0.5*W-(half_W_notch*np.sin(theta)), 0.0], [L, 0.5*W-(half_W_notch*
153
+ np.sin(theta)), 0.0], [L, 0.5*W, 0.0], [L-L_notch, 0.5*W, 0.0],
154
+ [(L-L_notch)+(half_W_notch*np.cos(theta)), 0.5*W-(half_W_notch*
155
+ np.sin(theta)), H], [L, 0.5*W-(half_W_notch*np.sin(theta)), H],
156
+ [L, 0.5*W, H], [L-L_notch, 0.5*W, H]])
157
+
158
+ # Generates this cuboid
159
+
160
+ if include_drittes_medium:
161
+
162
+ geometric_data = prisms.hexahedron_from_corners(corner_points,
163
+ transfinite_directions = [transfinite_y, transfinite_x,
164
+ transfinite_z], geometric_data=geometric_data,
165
+ explicit_volume_physical_group_name = "third medium",
166
+ explicit_surface_physical_group_name = {3: "front_third"},
167
+ bias_directions = {"x": -bias_y, "y": bias_x, "z": bias_z})
168
+
169
+ # Creates the botton part of the solid (4)
170
+
171
+ # Sets the corner points
172
+
173
+ corner_points = np.array([[0.0, 0.0, 0.0], [L, 0.0, 0.0],
174
+ [L, (0.5*W)-(half_W_notch*np.sin(theta)), 0.0], [L-L_notch+(
175
+ half_W_notch*np.cos(theta)), (0.5*W)-(half_W_notch*np.sin(theta)), 0.0],
176
+ [0.0, 0.0, H], [L, 0.0, H], [L, (0.5*W)-(half_W_notch*np.sin(theta)),
177
+ H], [L-L_notch+(half_W_notch*np.cos(theta)), (0.5*W)-(half_W_notch*
178
+ np.sin(theta)), H]])
179
+
180
+ # Generates this cuboid
181
+
182
+ geometric_data = prisms.hexahedron_from_corners(corner_points,
183
+ transfinite_directions = [transfinite_y, transfinite_x,
184
+ transfinite_z], geometric_data=geometric_data,
185
+ explicit_volume_physical_group_name = "solid",
186
+ explicit_surface_physical_group_name = {3: "front_solid", 2: "bottom"},
187
+ bias_directions = {"x": -bias_radial, "y": bias_x, "z": bias_z})
188
+
189
+ ####################################################################
190
+ # Mesh generation #
191
+ ####################################################################
192
+
193
+ tools.gmsh_finalize(geometric_data=geometric_data, file_name=
194
+ mesh_file_name, file_directory="", verbose=verbose)
195
+
196
+ # Testing block
197
+
198
+ if __name__ == "__main__":
199
+
200
+ # Example parameters for the mesh generation
201
+
202
+ L = 10.0
203
+
204
+ W = 5.0
205
+
206
+ H = 3.0
207
+
208
+ theta = 30.0
209
+
210
+ half_W_notch = 1.0
211
+
212
+ L_notch = 8.0
213
+
214
+ # Sets the number of elements of each direction
215
+
216
+ transfinite_x = 10
217
+
218
+ transfinite_y = 4
219
+
220
+ transfinite_z = 5
221
+
222
+ transfinite_radial = 5
223
+
224
+ # Sets the bias factors. When the bias is 1.0, nothing happens and
225
+ # the finite elements are uniformly distributed
226
+
227
+ bias_x = 1.1
228
+
229
+ bias_y = 1.2
230
+
231
+ bias_z = 1.0
232
+
233
+ bias_radial = -1.5
234
+
235
+ # Defines the name of the mesh and appends the whole path to it.
236
+ # Uses a function from Davout to automatically retrieve the path to
237
+ # this file (notch_mesh.py)
238
+
239
+ mesh_file_name = get_parent_path_of_file()+"//notch_mesh"
240
+
241
+ # Sets a flag to add or not the mesh of the third medium
242
+
243
+ include_drittes_medium = True
244
+
245
+ # Calls the mesh generation function
246
+
247
+ generate_mesh(L, W, H, theta, half_W_notch, L_notch, transfinite_x,
248
+ transfinite_y, transfinite_z, transfinite_radial, mesh_file_name,
249
+ bias_x, bias_y, bias_z, bias_radial, include_drittes_medium=
250
+ include_drittes_medium)
@@ -361,9 +361,13 @@ class RVEKinematicsSurrogateModel:
361
361
 
362
362
  if __name__=="__main__":
363
363
 
364
- # Sets the number of transfinite divisions in the RVE mesh
364
+ # Sets the number of transfinite divisions in the RVE mesh
365
365
 
366
- n_divisions = 6
366
+ n_divisions = 10
367
+
368
+ # Sets component to be learnt
369
+
370
+ component_to_be_learnt = "Y"
367
371
 
368
372
  # Sets a dictionary for the number of DOFs in the mesh for each num-
369
373
  # ber of divisions
@@ -372,8 +376,11 @@ if __name__=="__main__":
372
376
 
373
377
  # Defines the array with the DOFs to be learnt
374
378
 
375
- subdofs_to_learn = np.arange(0, dofs_per_number_of_divisions[
376
- n_divisions], 3)
379
+ components_dictionary = {"X": 0, "Y": 1, "Z": 2}
380
+
381
+ subdofs_to_learn = np.arange(components_dictionary[
382
+ component_to_be_learnt], dofs_per_number_of_divisions[n_divisions],
383
+ 3)
377
384
 
378
385
  # Defines the number of input neurons of the main network. Remember
379
386
  # that the data matrix is a tensor [n_samples, n_input_variables].
@@ -399,7 +406,7 @@ if __name__=="__main__":
399
406
  1.0}},
400
407
  {"quadratic": {"number of neurons": min(n_neurons_per_layer[0],
401
408
  n_neurons_per_layer[1]), "a2": 1.0}},
402
- {"quadratic": {"number of neurons": min(n_neurons_per_layer[1],
409
+ {"quadratic": {"number of neurons": min(n_neurons_per_layer[1],
403
410
  n_neurons_per_layer[2])}}]
404
411
 
405
412
  # Sets the modulating function for the weights matrices
@@ -416,11 +423,11 @@ if __name__=="__main__":
416
423
 
417
424
  verbose_delta_iterations = 50
418
425
 
419
- n_monte_carlo_realizations = 10
426
+ n_monte_carlo_realizations = 1000
420
427
 
421
- n_best_models = 5
428
+ n_best_models = 30
422
429
 
423
- n_best_samples = 10
430
+ n_best_samples = 20
424
431
 
425
432
  loss_metric = "MeanSquaredError"
426
433
 
@@ -429,7 +436,7 @@ if __name__=="__main__":
429
436
 
430
437
  parameters_dtype = "float32"
431
438
 
432
- saved_model_file = "RVE_kinematics_model.keras"
439
+ saved_model_file = "RVE_kinematics_model_"+str(component_to_be_learnt)
433
440
 
434
441
  # Sets the path for the data
435
442
 
@@ -1,4 +1,4 @@
1
- # Routine to experiment with incompressible hyperelasticity
1
+ # Routine to experiment with compressible hyperelasticity
2
2
 
3
3
  from dolfin import *
4
4
 
@@ -6,7 +6,7 @@ from .....Davout.PythonicUtilities.path_tools import get_parent_path_of_file
6
6
 
7
7
  from .....Davout.MultiMech.tool_box.mesh_handling_tools import read_mshMesh
8
8
 
9
- from .....Davout.MultiMech.constitutive_models.hyperelasticity.isotropic_hyperelasticity import Neo_Hookean
9
+ from .....Davout.MultiMech.constitutive_models.hyperelasticity.isotropic_hyperelasticity import NeoHookean
10
10
 
11
11
  from .....Davout.MultiMech.tool_box import functional_tools
12
12
 
@@ -31,21 +31,27 @@ E = 1E6
31
31
 
32
32
  poisson = 0.3
33
33
 
34
- constitutive_models = {"volume 1": Neo_Hookean({"E": E, "nu": poisson})}
34
+ constitutive_models = {"volume 1": NeoHookean({"E": E, "nu": poisson})}
35
+
36
+ # Checks the constitutive models
37
+
38
+ for constitutive_model in constitutive_models.values():
39
+
40
+ constitutive_model.check_model({})
35
41
 
36
42
  # Sets the function space
37
43
 
38
44
  functional_data_class = functional_tools.construct_monolithicFunctionSpace(
39
45
  {"Displacement": {"field type": "vector", "interpolation function": "C"+
40
- "G", "polynomial degree": 2}, "Pressure": {"field type": "scalar", "in"+
41
- "terpolation function": "CG", "polynomial degree": 1}}, mesh_data_class)
46
+ "G", "polynomial degree": 2}}, mesh_data_class)
42
47
 
43
48
  # Dirichlet boundary conditions
44
49
 
45
- bc, dirichlet_loads, functional_data_class, elements_dictionary, variational_form = (
50
+ (bc, dirichlet_loads, functional_data_class, elements_dictionary,
51
+ variational_form, post_processes, post_processesSubmesh, solution_name) = (
46
52
  functional_tools.construct_DirichletBCs({"bottom":
47
- {"BC case": "FixedSupportDirichletBC", "sub_fieldsToApplyBC": "Displac"+
48
- "ement"}}, functional_data_class, mesh_data_class))
53
+ {"BC case": "FixedSupportDirichletBC"}}, functional_data_class,
54
+ mesh_data_class))
49
55
 
50
56
  # Variational form of the exterior work using an uniform referential
51
57
  # traction
@@ -6,7 +6,7 @@ from .....Davout.PythonicUtilities.path_tools import get_parent_path_of_file
6
6
 
7
7
  from .....Davout.MultiMech.tool_box.mesh_handling_tools import read_mshMesh
8
8
 
9
- from .....Davout.MultiMech.constitutive_models.hyperelasticity.isotropic_hyperelasticity import Neo_Hookean
9
+ from .....Davout.MultiMech.constitutive_models.hyperelasticity.isotropic_hyperelasticity import NeoHookean
10
10
 
11
11
  from .....Davout.MultiMech.tool_box import functional_tools
12
12
 
@@ -31,7 +31,11 @@ E = 1E6
31
31
 
32
32
  poisson = 0.3
33
33
 
34
- constitutive_model = Neo_Hookean({"E": E, "nu": poisson})
34
+ constitutive_model = NeoHookean({"E": E, "nu": poisson})
35
+
36
+ # Checks the constitutive models
37
+
38
+ constitutive_model.check_model({})
35
39
 
36
40
  # Sets the function space
37
41
 
@@ -42,7 +46,8 @@ functional_data_class = functional_tools.construct_monolithicFunctionSpace(
42
46
 
43
47
  # Dirichlet boundary conditions
44
48
 
45
- bc, dirichlet_loads, functional_data_class, elements_dictionary, variational_form = (
49
+ (bc, dirichlet_loads, functional_data_class, elements_dictionary,
50
+ variational_form, post_processes, post_processesSubmesh, solution_name) = (
46
51
  functional_tools.construct_DirichletBCs({"bottom":
47
52
  {"BC case": "FixedSupportDirichletBC", "sub_fieldsToApplyBC": "Displac"+
48
53
  "ement"}}, functional_data_class, mesh_data_class))
@@ -0,0 +1,239 @@
1
+ # Routine to experiment with quadrature elements to allow for implemen-
2
+ # tations concerned with algorithmic procedures in the quadrature points
3
+
4
+ from dolfin import *
5
+
6
+ from .....Davout.PythonicUtilities.path_tools import get_parent_path_of_file
7
+
8
+ from .....Davout.MultiMech.tool_box.mesh_handling_tools import read_mshMesh
9
+
10
+ from .....Davout.MultiMech.constitutive_models.plasticity.isotropic_infinitesimal_plasticity import ExponentialHardeningElastoPlasticWithBackStress
11
+
12
+ from .....Davout.MultiMech.constitutive_models.hyperelasticity.infinitesimal_elasticity import LinearIsotropicElastic
13
+
14
+ from .....Davout.MultiMech.tool_box import functional_tools
15
+
16
+ from .....Davout.MultiMech.tool_box import variational_tools
17
+
18
+ from .....Davout.MultiMech.tool_box.newton_raphson_tools import NewtonRaphson
19
+
20
+ from .....Davout.MultiMech.tool_box.read_write_tools import write_field_to_xdmf
21
+
22
+ # Creates a box mesh using gmsh
23
+
24
+ shape_function_degree = 3
25
+
26
+ quadrature_degree = int(2*(shape_function_degree-1))
27
+
28
+ mesh_data_class = read_mshMesh({"length x": 0.3, "length y": 0.2, "len"+
29
+ "gth z": 3.0, "number of divisions in x": 5, "number of divisions in y":
30
+ 5, "number of divisions in z": 40, "verbose": False, "mesh file name":
31
+ "box_mesh", "mesh file directory": get_parent_path_of_file()},
32
+ quadrature_degree=quadrature_degree)
33
+
34
+ # Neumann boundary conditions
35
+
36
+ maximum_load = 1.5E3
37
+
38
+ plastic_material = False
39
+
40
+ # Sets the number of load steps (pseudo-time steps)
41
+
42
+ n_load_steps = 5
43
+
44
+ # Sets the constitutive model
45
+
46
+ E = 1E6
47
+
48
+ poisson = 0.3
49
+
50
+ # Sets the coefficients of the plastic behavior
51
+
52
+ sigma_y = 2E3
53
+
54
+ H_back_stress = 0.0
55
+
56
+ K_1 = E*0.02
57
+
58
+ K_2 = 0.0
59
+
60
+ theta = 0.0
61
+
62
+ constitutive_models = None
63
+
64
+ if plastic_material:
65
+
66
+ constitutive_models = {"volume 1":
67
+ ExponentialHardeningElastoPlasticWithBackStress({"E": E, "nu":
68
+ poisson, "sigma_y": sigma_y, "H": H_back_stress, "K_1": K_1, "K_2":
69
+ K_2, "theta": theta}, newton_raphson_tolerance=1E-4)}
70
+
71
+ else:
72
+
73
+ constitutive_models = {"volume 1": LinearIsotropicElastic({"E": E,
74
+ "nu": poisson})}
75
+
76
+ # Checks the constitutive models and ensures that the supplied param-
77
+ # eters are correct
78
+
79
+ for constitutive_model in constitutive_models.values():
80
+
81
+ constitutive_model.check_model({"mesh_data_class": mesh_data_class})
82
+
83
+ # Sets the function space
84
+
85
+ functional_data_class = functional_tools.construct_monolithicFunctionSpace(
86
+ {"Displacement": {"field type": "vector", "interpolation function": "C"+
87
+ "G", "polynomial degree": shape_function_degree}}, mesh_data_class,
88
+ verbose=True)
89
+
90
+ # Dirichlet boundary conditions
91
+
92
+ (bc, dirichlet_loads, functional_data_class, elements_dictionary,
93
+ variational_form, post_processes, post_processesSubmesh, solution_name) = (
94
+ functional_tools.construct_DirichletBCs({"bottom": {"BC case": "Simple"+
95
+ "SupportDirichletBC", "bc_informationsDict": {"list_of_constrained_dofs":
96
+ [2]}}, "right": {"BC case": "SimpleSupportDirichletBC", "bc_information"+
97
+ "sDict": {"list_of_constrained_dofs": [1]}}, "back": {"BC case": "Simp"+
98
+ "leSupportDirichletBC", "bc_informationsDict": {"list_of_constrained_d"+
99
+ "ofs": [0]}}}, functional_data_class, mesh_data_class))
100
+
101
+ # Variational form of the exterior work using an uniform referential
102
+ # traction
103
+
104
+ external_work, neumann_loads = variational_tools.traction_work({"top": {
105
+ "load case": "UniformReferentialTraction", "amplitude_tractionX":
106
+ 0.0, "amplitude_tractionY": 0.0, "amplitude_tractionZ": maximum_load,
107
+ "parametric_load_curve": "linear", "t": 0.0, "t_final": 1.0}},
108
+ "Displacement", functional_data_class, mesh_data_class, [])
109
+
110
+ # Computes the elements necessary to pull-back the Cauchy stress to the
111
+ # first Piola-Kirchhoff stress tensor using Nanson's formula
112
+
113
+ I = Identity(functional_data_class.solution_fields["Displacement"
114
+ ].geometric_dimension())
115
+
116
+ F = grad(functional_data_class.solution_fields["Displacement"])+I
117
+
118
+ F_invT = inv(F).T
119
+
120
+ J = det(F)
121
+
122
+ # Gets the variational form of the inner work
123
+
124
+ internal_work = 0.0
125
+
126
+ for physical_group, constitutive_model in constitutive_models.items():
127
+
128
+ print("\nUpdates the constitutive model at '"+str(physical_group)+
129
+ "'")
130
+
131
+ # Updates the internal variables and the tangent modulus. The second
132
+ # argument is false, because this update is not inside a Newton-
133
+ # Raphson iteration
134
+
135
+ if plastic_material:
136
+
137
+ constitutive_model.update_internal_variables(
138
+ functional_data_class.solution_fields["Displacement"],
139
+ flag_newton_raphson_iteration=False)
140
+
141
+ # Gets the Cauchy stress tensor from the linear elastic constitutive
142
+ # relation and pulls it back to the first Piola-Kirchhoff stress
143
+ # tensor. This way, a formulation of large displacements and infini-
144
+ # tesimal strains can be accomplished, since the linearization of
145
+ # the first Piola-Kirchhoff stress tensor will carry the geometric
146
+ # nonlinearities
147
+
148
+ sigma = constitutive_model.cauchy_stress(
149
+ functional_data_class.solution_fields["Displacement"])
150
+
151
+ P = J*sigma*F_invT
152
+
153
+ internal_work += (inner(P, (grad(
154
+ functional_data_class.variation_fields["Displacement"])))*
155
+ mesh_data_class.dx(mesh_data_class.domain_physicalGroupsNameToTag[
156
+ physical_group]))
157
+
158
+ # Defines a function to update the variational form
159
+
160
+ verbose = True
161
+
162
+ def variational_form_update_function(pseudo_time,
163
+ flag_newton_raphson_iteration, verbose=verbose):
164
+
165
+ # Update the load class
166
+
167
+ neumann_loads[0].update_load(pseudo_time, verbose=verbose)
168
+
169
+ if verbose:
170
+
171
+ print("\nUpdates the constitutive model at '"+str(physical_group
172
+ )+"'")
173
+
174
+ # Updates the internal variables and the tangent modulus
175
+
176
+ if plastic_material:
177
+
178
+ constitutive_models["volume 1"].update_internal_variables(
179
+ functional_data_class.solution_fields["Displacement"],
180
+ flag_newton_raphson_iteration=flag_newton_raphson_iteration,
181
+ verbose=verbose)
182
+
183
+ # Defines a class to perform post-processes. In this case, simply sa-
184
+ # ving the output field
185
+
186
+ class PostProcesses:
187
+
188
+ def __init__(self, visualization_copy):
189
+
190
+ self.xdmf_file = None
191
+
192
+ self.visualization_copy_file = None
193
+
194
+ self.visualization_copy = visualization_copy
195
+
196
+ def __call__(self, pseudo_time, time_step):
197
+
198
+ # Saves this pseudo-time step in a xdmf file
199
+
200
+ if self.visualization_copy:
201
+
202
+ self.xdmf_file, self.visualization_copy_file = write_field_to_xdmf(
203
+ functional_data_class, explicit_file_name=
204
+ get_parent_path_of_file()+"//displacement_finite_deformat"+
205
+ "ion_with_infinitesimal_strain.xdmf", file=self.xdmf_file,
206
+ time=pseudo_time, time_step=time_step, visualization_copy=
207
+ self.visualization_copy, visualization_copy_file=
208
+ self.visualization_copy_file,
209
+ flag_read_copy=True, close_file=False)
210
+
211
+ else:
212
+
213
+ self.xdmf_file = write_field_to_xdmf(functional_data_class,
214
+ explicit_file_name=get_parent_path_of_file()+"//displaceme"+
215
+ "nt_finite_deformation_with_infinitesimal_strain.xdmf",
216
+ file=self.xdmf_file, time=pseudo_time, time_step=time_step)
217
+
218
+ post_processes = PostProcesses(True)
219
+
220
+ # Sets the Newton-Raphson solver
221
+
222
+ newton_raphson_class = NewtonRaphson(n_load_steps, variational_form=(
223
+ internal_work-external_work), functional_data_class=
224
+ functional_data_class, boundary_conditions_list=bc,
225
+ variational_form_update_function=variational_form_update_function,
226
+ post_processing_function=post_processes, use_custom_newton=True)
227
+
228
+ # Calls the loading procedure
229
+
230
+ newton_raphson_class()
231
+
232
+ if plastic_material:
233
+
234
+ print("\nEvaluates the internal variables after the full load hist"+
235
+ "ory")
236
+
237
+ constitutive_models["volume 1"].update_internal_variables(
238
+ functional_data_class.solution_fields["Displacement"],
239
+ flag_newton_raphson_iteration=False, verbose=True)