KratosDemStructuresCouplingApplication 10.4.4__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 (27) hide show
  1. KratosMultiphysics/.libs/KratosDemStructuresCouplingApplication.so +0 -0
  2. KratosMultiphysics/.libs/libKratosDemStructuresCouplingCore.dylib +0 -0
  3. KratosMultiphysics/DemStructuresCouplingApplication/__init__.py +7 -0
  4. KratosMultiphysics/DemStructuresCouplingApplication/control_module_fem_dem_utility.py +109 -0
  5. KratosMultiphysics/DemStructuresCouplingApplication/control_module_process.py +29 -0
  6. KratosMultiphysics/DemStructuresCouplingApplication/dem_fem_coupling_algorithm.py +251 -0
  7. KratosMultiphysics/DemStructuresCouplingApplication/dem_fem_launcher.py +10 -0
  8. KratosMultiphysics/DemStructuresCouplingApplication/dem_main_script_ready_for_coupling_with_fem.py +29 -0
  9. KratosMultiphysics/DemStructuresCouplingApplication/dem_poromechanics_coupling_analysis_stage.py +424 -0
  10. KratosMultiphysics/DemStructuresCouplingApplication/dem_structures_coupling_gid_output.py +201 -0
  11. KratosMultiphysics/DemStructuresCouplingApplication/multiaxial_control_module_fem_dem_generalized_2d_utility.py +141 -0
  12. KratosMultiphysics/DemStructuresCouplingApplication/sand_production_post_process_tool.py +135 -0
  13. KratosMultiphysics/DemStructuresCouplingApplication/sp_dem_fem_coupling_algorithm.py +303 -0
  14. KratosMultiphysics/DemStructuresCouplingApplication/sp_dem_fem_launcher.py +10 -0
  15. KratosMultiphysics/DemStructuresCouplingApplication/sp_statistics.py +143 -0
  16. KratosMultiphysics/DemStructuresCouplingApplication/sp_statistics_2.py +139 -0
  17. KratosMultiphysics/DemStructuresCouplingApplication/stress_failure_check_utility.py +36 -0
  18. kratosdemstructurescouplingapplication-10.4.4.dist-info/METADATA +17 -0
  19. kratosdemstructurescouplingapplication-10.4.4.dist-info/RECORD +27 -0
  20. kratosdemstructurescouplingapplication-10.4.4.dist-info/WHEEL +6 -0
  21. kratosdemstructurescouplingapplication.dylibs/libKratosCore.dylib +4 -0
  22. kratosdemstructurescouplingapplication.dylibs/libKratosDEMCore.dylib +0 -0
  23. kratosdemstructurescouplingapplication.dylibs/libKratosPoromechanicsCore.dylib +0 -0
  24. kratosdemstructurescouplingapplication.dylibs/libKratosStructuralMechanicsCore.dylib +0 -0
  25. kratosdemstructurescouplingapplication.dylibs/libgcc_s.1.1.dylib +0 -0
  26. kratosdemstructurescouplingapplication.dylibs/libgomp.1.dylib +0 -0
  27. kratosdemstructurescouplingapplication.dylibs/libstdc++.6.dylib +0 -0
@@ -0,0 +1,424 @@
1
+ import KratosMultiphysics as Kratos
2
+ from KratosMultiphysics.python_solver import PythonSolver
3
+ import KratosMultiphysics.analysis_stage
4
+
5
+ import KratosMultiphysics.DEMApplication as DEM
6
+ import KratosMultiphysics.PoromechanicsApplication as Poromechanics
7
+ import KratosMultiphysics.PoromechanicsApplication.poromechanics_analysis
8
+ import KratosMultiphysics.DemStructuresCouplingApplication as DemStructuresCouplingApplication
9
+ from sp_2d_rigid_fem_algorithm import DEMAnalysisStage2DSpRigidFem
10
+ from KratosMultiphysics.DEMApplication.DEM_analysis_stage import DEMAnalysisStage
11
+ import os
12
+ import math
13
+
14
+ class PoroMechanicsCouplingWithDemRadialMultiDofsControlModuleAnalysisStage(Kratos.analysis_stage.AnalysisStage):
15
+ def __init__(self, model, parameters):
16
+
17
+ self.parameters = parameters
18
+ self.poromechanics_solution = Poromechanics.poromechanics_analysis.PoromechanicsAnalysis(model, parameters["poromechanics_parameters"])
19
+ self.dem_solution = DEMAnalysisStage2DSpRigidFem(model, parameters["dem_parameters"])
20
+ self.dem_solution.ReadModelParts = super(DEMAnalysisStage2DSpRigidFem, self.dem_solution).ReadModelParts
21
+ super().__init__(model, parameters)
22
+
23
+ self._CheckCoherentInputs()
24
+ self.creator_destructor = DEM.ParticleCreatorDestructor()
25
+ self.case_dir = os.getcwd()
26
+ graph_folder_name = self.parameters["dem_parameters"]["problem_name"].GetString() + '_Graphs'
27
+ graph_folder_path = os.path.join(self.case_dir, graph_folder_name)
28
+ images_folder_name = 'dem_poro_coupling_images'
29
+ self.images_folder_path = os.path.join(graph_folder_path, images_folder_name)
30
+ if not os.path.isdir(self.images_folder_path):
31
+ os.mkdir(self.images_folder_path)
32
+
33
+ # General analysis settings
34
+ self.number_of_DEM_steps_between_steadiness_checks = 25
35
+ self.stationarity_measuring_tolerance = 5e1 #5e1 converges with GD 0.8 and CR 0.3 (case poro_dem_64b8)
36
+ self.ignore_isolated_particles = False
37
+ self.remove_isolated_particles = True
38
+ self.breakable_material_after_first_dem_solution_steadiness_achieved = True
39
+ self.use_precompression = True
40
+ self.create_stress_ratio_animation = False
41
+ # Casing settings
42
+ self.add_casing = False
43
+ self.casing_radius = 0.1
44
+ self.casing_element_size = 0.003
45
+ if not self.dem_solution.rigid_face_model_part.HasSubModelPart("Casing"):
46
+ self.dem_solution.rigid_face_model_part.CreateSubModelPart('Casing')
47
+ self.dem_solution.casing_submodelpart = self.dem_solution.rigid_face_model_part.GetSubModelPart('Casing')
48
+ self.dem_solution.casing_submodelpart.SetValue(DEM.RIGID_BODY_OPTION, 1)
49
+
50
+ file1 = os.path.join(os.getcwd(), "poro_solution_time_vs_sp_chunks.txt")
51
+ file2 = os.path.join(os.getcwd(), "poro_solution_time_vs_sp_standard.txt")
52
+ file3 = os.path.join(os.getcwd(), "poro_solution_time_vs_dem_time_vs_dems_steps.txt")
53
+ file4 = os.path.join(os.getcwd(), "radial_normal_and_smoothed_reaction_stresses_values.txt")
54
+ if os.path.exists(file1):
55
+ os.remove(file1)
56
+ if os.path.exists(file2):
57
+ os.remove(file2)
58
+ if os.path.exists(file3):
59
+ os.remove(file3)
60
+ if os.path.exists(file4):
61
+ os.remove(file4)
62
+
63
+ self.CreateInitialStressTensorFile()
64
+
65
+ def FindSubModelPartWithExternalWalls(self):
66
+
67
+ modelpart = self.model.GetModelPart('RigidFacePart')
68
+ submodelpart_with_external_walls = modelpart.GetSubModelPart('1')
69
+
70
+ return submodelpart_with_external_walls
71
+
72
+ def CreateInitialStressTensorFile(self):
73
+
74
+ total_sigma_X = self.parameters["case_parameters"]["total_sigma_X"].GetDouble()
75
+ total_sigma_Y = self.parameters["case_parameters"]["total_sigma_Y"].GetDouble()
76
+ pore_pressure = self.parameters["case_parameters"]["pore_pressure"].GetDouble()
77
+ biot_coefficient = self.parameters["case_parameters"]["biot_coefficient"].GetDouble()
78
+ porosity = self.parameters["case_parameters"]["porosity"].GetDouble()
79
+ permeability = self.parameters["case_parameters"]["permeability"].GetDouble()
80
+ self.initial_effective_stress_X = -total_sigma_X + biot_coefficient * pore_pressure
81
+ self.initial_effective_stress_Y = -total_sigma_Y + biot_coefficient * pore_pressure
82
+ case_filename = self.parameters["poromechanics_parameters"]["problem_data"]["problem_name"].GetString()
83
+ case_filename_plus_extension = case_filename + ".mdpa"
84
+ file = open(case_filename_plus_extension, 'r')
85
+ Xmin = Ymin = Xmax = Ymax = 0.0
86
+ for line in file:
87
+ if line.startswith("Begin Nodes"):
88
+ while True:
89
+ nextline=next(file)
90
+ if nextline.startswith("End Nodes"):
91
+ break
92
+ data = nextline.split()
93
+ info = [float(data[1]), float(data[2])]
94
+ Xmin = info[0] if info[0] < Xmin else Xmin
95
+ Ymin = info[1] if info[1] < Ymin else Ymin
96
+ Xmax = info[0] if info[0] > Xmax else Xmax
97
+ Ymax = info[1] if info[1] > Ymax else Ymax
98
+ file.close()
99
+ initial_effective_sigmas_filename = self.parameters["poromechanics_parameters"]["problem_data"]["initial_stress_utility_settings"]["initial_input_filename"].GetString()
100
+ initial_effective_sigmas_filename_plus_extension = initial_effective_sigmas_filename + ".mdpa"
101
+ #TODO: print stresses in engineering format?
102
+ effective_sigmas_datafile = open(initial_effective_sigmas_filename_plus_extension, 'w')
103
+ effective_sigmas_datafile.write("Begin Properties 0\n")
104
+ effective_sigmas_datafile.write("End Properties\n\n")
105
+ effective_sigmas_datafile.write("Begin Nodes\n")
106
+ effective_sigmas_datafile.write("1 " + str(Xmin) + " " + str(Ymin) + " 0\n")
107
+ effective_sigmas_datafile.write("2 " + str(Xmax) + " " + str(Ymin) + " 0\n")
108
+ effective_sigmas_datafile.write("3 " + str(Xmax) + " " + str(Ymax) + " 0\n")
109
+ effective_sigmas_datafile.write("4 " + str(Xmin) + " " + str(Ymax) + " 0\n")
110
+ effective_sigmas_datafile.write("End Nodes\n\n")
111
+ effective_sigmas_datafile.write("Begin Elements Element2D3N\n")
112
+ effective_sigmas_datafile.write("1 0 1 2 3\n")
113
+ effective_sigmas_datafile.write("2 0 1 3 4\n")
114
+ effective_sigmas_datafile.write("End Elements\n\n")
115
+ effective_sigmas_datafile.write("Begin NodalData INITIAL_STRESS_TENSOR\n")
116
+ effective_sigmas_datafile.write("1 0 [2,2] ((" + str(self.initial_effective_stress_X) + ",0),(0," + str(self.initial_effective_stress_Y) + "))\n")
117
+ effective_sigmas_datafile.write("2 0 [2,2] ((" + str(self.initial_effective_stress_X) + ",0),(0," + str(self.initial_effective_stress_Y) + "))\n")
118
+ effective_sigmas_datafile.write("3 0 [2,2] ((" + str(self.initial_effective_stress_X) + ",0),(0," + str(self.initial_effective_stress_Y) + "))\n")
119
+ effective_sigmas_datafile.write("4 0 [2,2] ((" + str(self.initial_effective_stress_X) + ",0),(0," + str(self.initial_effective_stress_Y) + "))\n")
120
+ effective_sigmas_datafile.write("End NodalData\n")
121
+ effective_sigmas_datafile.close()
122
+
123
+ def Initialize(self):
124
+ self.poromechanics_solution.Initialize()
125
+ self.dem_solution.Initialize()
126
+ super().Initialize()
127
+ self.submodelpart_with_external_walls = self.FindSubModelPartWithExternalWalls()
128
+ self.effective_stresses_communicator = DemStructuresCouplingApplication.EffectiveStressesCommunicatorUtility(self.poromechanics_solution._GetSolver().main_model_part, self.submodelpart_with_external_walls)
129
+ self.effective_stresses_communicator.Initialize()
130
+ self.pore_pressure_communicator_utility = DemStructuresCouplingApplication.PorePressureCommunicatorUtility(self.poromechanics_solution._GetSolver().main_model_part, self.dem_solution.spheres_model_part)
131
+ self.pore_pressure_communicator_utility.Initialize()
132
+
133
+ if self.use_precompression:
134
+ self.ApplyPreCompression()
135
+
136
+ def ApplyPreCompression(self):
137
+
138
+ initial_effective_stress_matrix = Kratos.Matrix()
139
+ initial_effective_stress_matrix.Resize(2,2)
140
+ initial_effective_stress_matrix[0, 0] = self.initial_effective_stress_X
141
+ initial_effective_stress_matrix[1, 0] = 0.0
142
+ initial_effective_stress_matrix[0, 1] = 0.0
143
+ initial_effective_stress_matrix[1, 1] = self.initial_effective_stress_Y
144
+
145
+ self.effective_stresses_communicator.CommunicateGivenRadialEffectiveStressesToDemWalls(initial_effective_stress_matrix)
146
+ self.dem_solution._GetSolver().cplusplus_strategy.BreakAllBonds()
147
+
148
+ self.stationarity_checking_is_activated = False
149
+ print("\n************************************ Solving DEM for the first time...\n", flush=True)
150
+ self.DEM_steps_counter = 0
151
+ self.dem_time_steps_per_fem_time_step = 0
152
+ self.dem_solution.time = self.poromechanics_solution.time
153
+
154
+ while not self.DEMSolutionIsSteady():
155
+ self.dem_solution.time = self.dem_solution._GetSolver().AdvanceInTime(self.dem_solution.time)
156
+ self.dem_solution.InitializeSolutionStep()
157
+ self.dem_solution._GetSolver().Predict()
158
+ self.dem_solution._GetSolver().SolveSolutionStep()
159
+ self.dem_solution.FinalizeSolutionStep()
160
+ self.AdditionalDEMOperationsToFinalizeDEMSolutionStep()
161
+ self.dem_solution.OutputSolutionStep()
162
+
163
+ self.dem_solution._GetSolver().cplusplus_strategy.HealAllBonds()
164
+ DEM.ParallelBondUtilities().SetCurrentIndentationAsAReferenceInParallelBonds(self.dem_solution.spheres_model_part)
165
+
166
+ if self.remove_isolated_particles:
167
+ self.creator_destructor.MarkIsolatedParticlesForErasing(self.dem_solution.spheres_model_part)
168
+ self.dem_solution.AdjustHoleInnerRadius()
169
+ DEM.PreUtilities().ResetSkinParticles(self.dem_solution.spheres_model_part)
170
+ self.dem_solution._GetSolver().cplusplus_strategy.ComputeSkin(self.dem_solution.spheres_model_part, 1.5)
171
+ if self.add_casing:
172
+ self.AddCasing()
173
+
174
+ def AddCasing(self):
175
+
176
+ max_FEM_node_Id = self.creator_destructor.FindMaxNodeIdInModelPart(self.dem_solution.rigid_face_model_part)
177
+ max_FEM_elem_Id = self.creator_destructor.FindMaxConditionIdInModelPart(self.dem_solution.rigid_face_model_part)
178
+ casing_length = 2.0 * math.pi * self.casing_radius
179
+ number_of_casing_elems = casing_length / self.casing_element_size
180
+ number_of_casing_elems = round(number_of_casing_elems)
181
+ delta_angle_in_radians = 2.0 * math.pi / number_of_casing_elems
182
+ for cond in self.submodelpart_with_external_walls.Conditions:
183
+ props = cond.Properties
184
+ break
185
+
186
+ for i in range(number_of_casing_elems):
187
+ Xi = self.casing_radius * math.cos(delta_angle_in_radians * i)
188
+ Yi = self.casing_radius * math.sin(delta_angle_in_radians * i)
189
+ self.dem_solution.casing_submodelpart.CreateNewNode(max_FEM_node_Id + i + 1, Xi, Yi, 0.0)
190
+ for i in range(number_of_casing_elems - 1):
191
+ self.dem_solution.casing_submodelpart.CreateNewCondition("RigidEdge2D2N", max_FEM_elem_Id + i + 1, [max_FEM_node_Id + i + 1, max_FEM_node_Id + i + 2], props)
192
+ self.dem_solution.casing_submodelpart.CreateNewCondition("RigidEdge2D2N", max_FEM_elem_Id + number_of_casing_elems, [max_FEM_node_Id + number_of_casing_elems, max_FEM_node_Id + 1], props)
193
+
194
+ def RunSolutionLoop(self):
195
+
196
+ self.stationarity_checking_is_activated = False
197
+ first_dem_solution_steadiness_achieved = False
198
+
199
+ while self.poromechanics_solution.KeepAdvancingSolutionLoop():
200
+ print("\n************************************ Solving FEM...\n", flush=True)
201
+ self.poromechanics_solution.time = self.poromechanics_solution._GetSolver().AdvanceInTime(self.poromechanics_solution.time)
202
+ self.poromechanics_solution.InitializeSolutionStep()
203
+ self.poromechanics_solution._GetSolver().Predict()
204
+ self.poromechanics_solution._GetSolver().SolveSolutionStep()
205
+ self.poromechanics_solution.FinalizeSolutionStep()
206
+ self.poromechanics_solution.OutputSolutionStep()
207
+
208
+ self.effective_stresses_communicator.CopyWallCurrentEffectiveStressesToOldEffectiveStresses()
209
+ self.effective_stresses_communicator.CommunicateCurrentRadialEffectiveStressesToDemWalls()
210
+ self.pore_pressure_communicator_utility.ComputeForceOnParticlesDueToPorePressureGradient()
211
+
212
+ print("\n************************************ Now solving DEM...\n", flush=True)
213
+ self.DEM_steps_counter = 0
214
+ self.dem_time_steps_per_fem_time_step = 0
215
+ self.dem_solution.time = self.poromechanics_solution.time
216
+
217
+ if first_dem_solution_steadiness_achieved and self.breakable_material_after_first_dem_solution_steadiness_achieved:
218
+ for elem in self.dem_solution.spheres_model_part.Elements:
219
+ elem.Properties.GetSubProperties(elem.Properties.Id)[DEM.IS_UNBREAKABLE] = False
220
+ break
221
+
222
+ while not self.DEMSolutionIsSteady():
223
+ self.dem_solution.time = self.dem_solution._GetSolver().AdvanceInTime(self.dem_solution.time)
224
+ self.center = KratosMultiphysics.Array3()
225
+ self.center[0] = 0; # self.sp_parameters["problem_data"]["center"][0].GetDouble()
226
+ self.center[1] = 0; # self.sp_parameters["problem_data"]["center"][1].GetDouble()
227
+ self.center[2] = 0; # self.sp_parameters["problem_data"]["center"][2].GetDouble()
228
+ self.axis = KratosMultiphysics.Array3()
229
+ self.axis[0] = 0; # self.sp_parameters["problem_data"]["axis"][0].GetDouble()
230
+ self.axis[1] = 0; # self.sp_parameters["problem_data"]["axis"][1].GetDouble()
231
+ self.axis[2] = 1; # self.sp_parameters["problem_data"]["axis"][2].GetDouble()
232
+ self.radius_to_delete_sp = 0.075
233
+ self.creator_destructor.MarkParticlesForErasingGivenCylinder(self.dem_solution.spheres_model_part, self.center, self.axis, self.radius_to_delete_sp)
234
+
235
+ self.dem_solution.InitializeSolutionStep()
236
+ self.dem_solution._GetSolver().Predict()
237
+ self.dem_solution._GetSolver().SolveSolutionStep()
238
+ self.dem_solution.FinalizeSolutionStep()
239
+ self.AdditionalDEMOperationsToFinalizeDEMSolutionStep()
240
+ self.dem_solution.OutputSolutionStep()
241
+
242
+ first_dem_solution_steadiness_achieved = True
243
+
244
+ def AdditionalDEMOperationsToFinalizeDEMSolutionStep(self):
245
+
246
+ if self.dem_solution.IsTimeToPrintPostProcess():
247
+
248
+ os.chdir(self.images_folder_path)
249
+
250
+ filename = 'radial_normal_and_smoothed_reaction_stresses_values_' + str(self.dem_solution.time) + '.txt'
251
+
252
+ try:
253
+ os.remove(filename)
254
+ except OSError:
255
+ pass
256
+
257
+ radial_normal_and_smoothed_reaction_stresses_file = open(filename, 'a')
258
+
259
+ average_ratio = 0.0
260
+
261
+ for node in self.dem_solution.rigid_face_model_part.Nodes:
262
+ total_radial_normal_stress_value = node.GetValue(DEM.RADIAL_NORMAL_STRESS_COMPONENT)
263
+ A = node.GetValue(DEM.SMOOTHED_REACTION_STRESS_X)
264
+ B = node.GetValue(DEM.SMOOTHED_REACTION_STRESS_Y)
265
+ C = node.GetValue(DEM.SMOOTHED_REACTION_STRESS_Z)
266
+ total_smoothed_reaction_stress_value = math.sqrt(A*A + B*B + C*C)
267
+ if abs(total_radial_normal_stress_value) > 0.0:
268
+ this_node_applied_stress_ratio = -total_smoothed_reaction_stress_value / total_radial_normal_stress_value
269
+ else:
270
+ this_node_applied_stress_ratio = 0.0
271
+ average_ratio += this_node_applied_stress_ratio
272
+ displ = node.GetSolutionStepValue(Kratos.DISPLACEMENT)
273
+ displ_norm = math.sqrt(displ[0]*displ[0]+displ[1]*displ[1]+displ[2]*displ[2])
274
+ vel = node.GetSolutionStepValue(Kratos.VELOCITY)
275
+ vel_norm = math.sqrt(vel[0]*vel[0]+vel[1]*vel[1]+vel[2]*vel[2])
276
+ radial_normal_and_smoothed_reaction_stresses_file.write(str(node.Id) + " " + str(node.X) + " " + str(node.Y) + " " + str(node.Z) + " " + str(total_radial_normal_stress_value) + " " + str(total_smoothed_reaction_stress_value) + " " + str(displ_norm) + " " + str(vel_norm) + '\n')
277
+
278
+ radial_normal_and_smoothed_reaction_stresses_file.close()
279
+ average_ratio = average_ratio / self.dem_solution.rigid_face_model_part.NumberOfNodes()
280
+ self.dem_solution.KratosPrintInfo("-------- Averaged loading ratio (average quotient current stress/ target stress) is " + str(average_ratio) + " ------------ \n")
281
+
282
+ os.chdir(self.case_dir)
283
+
284
+ '''total_average_target_radial_normal_stress = 0.0
285
+ total_forces_modulus = 0.0
286
+
287
+ for node in self.dem_solution.rigid_face_model_part.Nodes:
288
+
289
+ total_radial_normal_stress_value = node.GetValue(DEM.RADIAL_NORMAL_STRESS_COMPONENT)
290
+ nodal_area = node.GetSolutionStepValue(DEM.DEM_NODAL_AREA)
291
+ total_average_target_radial_normal_stress += nodal_area * total_radial_normal_stress_value
292
+
293
+ for element in self.dem_solution.spheres_model_part.Elements:
294
+
295
+ total_force_X = element.GetNode(0).GetSolutionStepValue(Kratos.EXTERNAL_APPLIED_FORCE_X)
296
+ total_force_Y = element.GetNode(0).GetSolutionStepValue(Kratos.EXTERNAL_APPLIED_FORCE_Y)
297
+ total_force_Z = element.GetNode(0).GetSolutionStepValue(Kratos.EXTERNAL_APPLIED_FORCE_Z)
298
+ forces_modulus = math.sqrt(total_force_X * total_force_X + total_force_Y * total_force_Y + total_force_Z * total_force_Z)
299
+ total_forces_modulus += forces_modulus'''
300
+
301
+ def DEMSolutionIsSteady(self):
302
+
303
+ self.dem_time_steps_per_fem_time_step += 1
304
+
305
+ if self.DEM_steps_counter == self.number_of_DEM_steps_between_steadiness_checks:
306
+
307
+ self.DEM_steps_counter = 0
308
+
309
+ print("\n*** DEM stationarity will now be checked...", flush=True)
310
+
311
+ if not DEM.StationarityChecker().CheckIfVariableIsNullInModelPart(self.dem_solution.spheres_model_part, Kratos.TOTAL_FORCES_X, self.stationarity_measuring_tolerance, self.ignore_isolated_particles):
312
+ print(" F_X is larger than the desired maximum\n", flush=True)
313
+ self.stationarity_checking_is_activated = True
314
+ return False
315
+ if not DEM.StationarityChecker().CheckIfVariableIsNullInModelPart(self.dem_solution.spheres_model_part, Kratos.TOTAL_FORCES_Y, self.stationarity_measuring_tolerance, self.ignore_isolated_particles):
316
+ print(" F_Y is larger than the desired maximum\n", flush=True)
317
+ self.stationarity_checking_is_activated = True
318
+ return False
319
+ if not DEM.StationarityChecker().CheckIfVariableIsNullInModelPart(self.dem_solution.spheres_model_part, Kratos.TOTAL_FORCES_Z, self.stationarity_measuring_tolerance, self.ignore_isolated_particles):
320
+ print(" F_Z is larger than the desired maximum\n", flush=True)
321
+ self.stationarity_checking_is_activated = True
322
+ return False
323
+
324
+ if self.stationarity_checking_is_activated:
325
+ print("\n ********** DEM solution is steady! ********** \n", flush=True)
326
+ with open('poro_solution_time_vs_dem_time_vs_dems_steps.txt', 'a') as time_and_steps_file:
327
+ time_and_steps_file.write(str(self.poromechanics_solution.time) + " " + str(self.dem_solution.time) + " " + str(self.dem_time_steps_per_fem_time_step) + '\n')
328
+ return True
329
+ else:
330
+ return False
331
+ else:
332
+ self.DEM_steps_counter += 1
333
+ return False
334
+
335
+ def Finalize(self):
336
+ self.poromechanics_solution.Finalize()
337
+ self.dem_solution.Finalize()
338
+ super().Finalize()
339
+ if self.create_stress_ratio_animation:
340
+ self.CreateReactionStressToTargetRatioAnimation()
341
+
342
+ def CreateReactionStressToTargetRatioAnimation(self):
343
+ # Use 'pip install opencv-python' at the command line in Windows to obtain cv2
344
+ import cv2
345
+ import matplotlib.pyplot as plt
346
+ print_one_out_of_n_results = 1
347
+ frames_per_second = 5
348
+ n = 0
349
+ list_of_pngs = []
350
+ os.chdir(self.images_folder_path)
351
+
352
+ for filename in os.listdir(self.images_folder_path):
353
+ n = n + 1
354
+
355
+ if n % print_one_out_of_n_results:
356
+ continue
357
+
358
+ if filename.endswith(".txt"):
359
+ X, Y = [], []
360
+ for line in open(filename, 'r'):
361
+ values = [float(s) for s in line.split()]
362
+ if values[4]:
363
+ X.append(values[1])
364
+ Y.append(-values[5]/values[4])
365
+
366
+ plt.axis((-1.5,1.5,0,2))
367
+ plt.xlabel("Xcoord (m)")
368
+ plt.ylabel("radial effective stress to target ratio")
369
+ plt.plot(X, Y, '.', color='blue')
370
+ plt.grid()
371
+ printfile = filename[:-4]
372
+ printfilename = os.path.join(self.images_folder_path, printfile + '.png')
373
+ list_of_pngs.append(printfilename)
374
+ plt.savefig(printfilename)
375
+ plt.close()
376
+
377
+ video_name = 'video.avi'
378
+ images = [img for img in os.listdir(self.images_folder_path) if img.endswith(".png")]
379
+ frame = cv2.imread(os.path.join(self.images_folder_path, images[0]))
380
+ height, width, layers = frame.shape
381
+ video = cv2.VideoWriter(video_name, 0, frames_per_second, (width,height))
382
+
383
+ for image in images:
384
+ video.write(cv2.imread(os.path.join(self.images_folder_path, image)))
385
+
386
+ cv2.destroyAllWindows()
387
+ video.release()
388
+ os.chdir(self.case_dir)
389
+
390
+ def _CreateSolver(self):
391
+ return DemPoroMechanicsCouplingSolver(self.poromechanics_solution._GetSolver(), self.dem_solution._GetSolver(), self.parameters)
392
+
393
+ def _CheckCoherentInputs(self):
394
+ variables_exported_from_gauss_points_to_nodes = self.parameters["poromechanics_parameters"]["solver_settings"]["gp_to_nodal_variable_list"].GetStringArray()
395
+ if not "LIQUID_PRESSURE_GRADIENT" in variables_exported_from_gauss_points_to_nodes or not "EFFECTIVE_STRESS_TENSOR" in variables_exported_from_gauss_points_to_nodes:
396
+ raise Exception("Coupling DEM with Poromechanics Error: [\"poromechanics_parameters\"][\"solver_settings\"][\"gp_to_nodal_variable_list\"] must contain \"LIQUID_PRESSURE_GRADIENT\" and \"EFFECTIVE_STRESS_TENSOR\"\n")
397
+
398
+ def _YieldDEMTime(self, current_time, current_time_plus_increment, delta_time):
399
+ current_time += delta_time
400
+ tolerance = 0.0001
401
+ while current_time < (current_time_plus_increment - tolerance * delta_time):
402
+ yield current_time
403
+ current_time += delta_time
404
+
405
+ current_time = current_time_plus_increment
406
+ yield current_time
407
+
408
+ class DemPoroMechanicsCouplingSolver(PythonSolver):
409
+ def __init__(self, poromechanics_solver, dem_solver, parameters):
410
+ self.poromechanics_solver = poromechanics_solver
411
+ self.dem_solver = dem_solver
412
+
413
+ def ImportModelPart(self):
414
+ pass
415
+
416
+ def GetComputingModelPart(self):
417
+ return self.poromechanics_solver.GetComputingModelPart()
418
+
419
+ if __name__ == "__main__":
420
+ with open("ProjectParameters.json", 'r') as parameter_file:
421
+ project_parameters = Kratos.Parameters(parameter_file.read())
422
+
423
+ model = Kratos.Model()
424
+ PoroMechanicsCouplingWithDemRadialMultiDofsControlModuleAnalysisStage(model, project_parameters).Run()
@@ -0,0 +1,201 @@
1
+ import os
2
+ import KratosMultiphysics as Kratos
3
+ from KratosMultiphysics import MultiFileFlag
4
+ from KratosMultiphysics import GiDPostMode
5
+ from KratosMultiphysics import Logger
6
+ from KratosMultiphysics import DEMApplication
7
+ from KratosMultiphysics import DemStructuresCouplingApplication
8
+ from KratosMultiphysics import StructuralMechanicsApplication
9
+ from KratosMultiphysics import gid_output # this is deprecated
10
+
11
+
12
+ class DemStructuresCouplingGiDOutput(gid_output.GiDOutput):
13
+
14
+ def __init__(self,
15
+ file_name,
16
+ vol_output,
17
+ post_mode,
18
+ multifile,
19
+ deformed_mesh,
20
+ write_conditions,
21
+ structures_model_part,
22
+ balls_model_part,
23
+ clusters_model_part,
24
+ rigid_faces_model_part,
25
+ contact_model_part,
26
+ mixed_model_part
27
+ ):
28
+ gid_output.GiDOutput.__init__(self,
29
+ file_name,
30
+ vol_output,
31
+ post_mode,
32
+ multifile,
33
+ deformed_mesh,
34
+ write_conditions)
35
+
36
+ self.GiDMultiFileFlag = multifile
37
+
38
+ self.outerlistfilename = os.path.join("..", self.listfilename)
39
+
40
+ self.structures_model_part = structures_model_part
41
+ self.balls_model_part = balls_model_part
42
+ self.clusters_model_part = clusters_model_part
43
+ self.rigid_faces_model_part = rigid_faces_model_part
44
+ self.contact_model_part = contact_model_part
45
+ self.mixed_model_part = mixed_model_part
46
+
47
+ self.structures_nodal_results = []
48
+ self.dem_nodal_results = []
49
+ self.clusters_nodal_results = []
50
+ self.rigid_faces_nodal_results = []
51
+ self.contact_gauss_points_results = []
52
+ self.mixed_nodal_results = []
53
+ self.structures_gauss_points_results = []
54
+
55
+ def initialize_dem_fem_results(self,
56
+ structures_nodal_results,
57
+ dem_nodal_results,
58
+ clusters_nodal_results,
59
+ rigid_faces_nodal_results,
60
+ contact_gauss_points_results,
61
+ mixed_nodal_results,
62
+ structures_gauss_points_results):
63
+ self.structures_nodal_results = structures_nodal_results
64
+ self.dem_nodal_results = dem_nodal_results
65
+ self.clusters_nodal_results = clusters_nodal_results
66
+ self.rigid_faces_nodal_results = rigid_faces_nodal_results
67
+ self.contact_gauss_points_results = contact_gauss_points_results
68
+ self.mixed_nodal_results = mixed_nodal_results
69
+ self.structures_gauss_points_results = structures_gauss_points_results
70
+
71
+ if self.multi_file == MultiFileFlag.SingleFile:
72
+ print("Singlefile option is not available for the DEM-Structures Coupling application!")
73
+ mesh_name = 0.0
74
+ self.io.InitializeMesh(mesh_name)
75
+ self.io.WriteSphereMesh(self.balls_model_part.GetMesh())
76
+ self.io.WriteMesh(self.clusters_model_part.GetMesh())
77
+ self.io.WriteMesh(self.rigid_faces_model_part.GetMesh())
78
+ self.io.WriteMesh(self.contact_model_part.GetMesh())
79
+ self.io.WriteMesh(self.mixed_model_part.GetMesh())
80
+ self.io.FinalizeMesh()
81
+ self.io.InitializeResults(mesh_name, self.mixed_model_part.GetMesh())
82
+
83
+ # Initialize list file
84
+ with open(self.listfilename, "w") as listfile:
85
+
86
+ if self.multi_file == MultiFileFlag.MultipleFiles:
87
+ listfile.write("Multiple\n")
88
+
89
+ elif self.multi_file == MultiFileFlag.SingleFile:
90
+ listfile.write("Single\n")
91
+
92
+ if self.multi_file == MultiFileFlag.SingleFile:
93
+
94
+ if self.post_mode == GiDPostMode.GiD_PostBinary:
95
+ self.write_step_to_list()
96
+
97
+ else:
98
+ self.write_step_to_list(0)
99
+
100
+
101
+ def write_step_to_list(self, step_label):
102
+
103
+ if self.post_mode == GiDPostMode.GiD_PostBinary:
104
+ ext = ".post.bin"
105
+ elif self.post_mode == GiDPostMode.GiD_PostAscii:
106
+ ext = ".post.res"
107
+ elif self.post_mode == GiDPostMode.GiD_PostAsciiZipped:
108
+ ext = ".post.res"
109
+
110
+ with open(self.listfilename, "a") as listfile:
111
+ listfile.write("Multiple\n")
112
+ listfile.write(self.filename+"_"+"%.12g"%step_label+ext+"\n")
113
+
114
+ def write_step_to_outer_list(self, step_label):
115
+
116
+ if self.post_mode == GiDPostMode.GiD_PostBinary:
117
+ ext = ".post.bin"
118
+ elif self.post_mode == GiDPostMode.GiD_PostAscii:
119
+ ext = ".post.res"
120
+ elif self.post_mode == GiDPostMode.GiD_PostAsciiZipped:
121
+ ext = ".post.res"
122
+
123
+ with open(self.outerlistfilename, "a") as listfile:
124
+ listfile.write("Multiple\n")
125
+ folder_name = self.filename + "_Post_Files"
126
+ full_string_to_write = os.path.join(folder_name,self.filename+"_"+"%.12g"%step_label+ext)
127
+ listfile.write(full_string_to_write+"\n")
128
+
129
+
130
+ def Writeresults(self, time):
131
+
132
+ Logger.PrintInfo("DEM-Struct","")
133
+ Logger.PrintInfo("DEM-Struct","******************* PRINTING RESULTS FOR GID ***************************")
134
+ Logger.Flush()
135
+
136
+ if self.GiDMultiFileFlag == "Multiples":
137
+ self.mixed_model_part.Elements.clear()
138
+ self.mixed_model_part.Nodes.clear()
139
+ # here order is important!
140
+ DEMApplication.PostUtilities().AddModelPartToModelPart(self.mixed_model_part, self.balls_model_part)
141
+ DEMApplication.PostUtilities().AddModelPartToModelPart(self.mixed_model_part, self.rigid_faces_model_part)
142
+ DEMApplication.PostUtilities().AddModelPartToModelPart(self.mixed_model_part, self.contact_model_part)
143
+ DEMApplication.PostUtilities().AddModelPartToModelPart(self.mixed_model_part, self.structures_model_part)
144
+
145
+ self.write_dem_fem_results(time)
146
+
147
+
148
+ def write_dem_fem_results(self, label):
149
+ # label = str(label) #it should be a C double
150
+ # update cut data if necessary
151
+ out_model_part = self.get_out_model_part(self.structures_model_part)
152
+
153
+ # update cut data if necessary
154
+ if not self.volume_output:
155
+ self.cut_app.UpdateCutData(out_model_part, self.structures_model_part)
156
+
157
+ if self.multi_file == MultiFileFlag.MultipleFiles:
158
+ self.io.InitializeMesh(label)
159
+ self.io.WriteSphereMesh(self.balls_model_part.GetMesh())
160
+ self.io.WriteMesh(self.mixed_model_part.GetMesh())
161
+ self.io.WriteMesh(self.rigid_faces_model_part.GetMesh())
162
+ self.io.WriteMesh(self.contact_model_part.GetMesh())
163
+ self.io.FinalizeMesh()
164
+ self.io.InitializeResults(label, self.mixed_model_part.GetMesh())
165
+
166
+ for var in self.structures_nodal_results:
167
+ kratos_variable = Kratos.KratosGlobals.GetVariable(var)
168
+ self._write_nodal_results(label, self.structures_model_part, kratos_variable)
169
+
170
+ for var in self.dem_nodal_results:
171
+ kratos_variable = Kratos.KratosGlobals.GetVariable(var)
172
+ self._write_nodal_results(label, self.balls_model_part, kratos_variable)
173
+
174
+ for var in self.clusters_nodal_results:
175
+ kratos_variable = Kratos.KratosGlobals.GetVariable(var)
176
+ self._write_nodal_results(label, self.clusters_model_part, kratos_variable)
177
+
178
+ for var in self.rigid_faces_nodal_results:
179
+ kratos_variable = Kratos.KratosGlobals.GetVariable(var)
180
+ self._write_nodal_results(label, self.rigid_faces_model_part, kratos_variable)
181
+
182
+ for var in self.contact_gauss_points_results:
183
+ kratos_variable = Kratos.KratosGlobals.GetVariable(var)
184
+ self._write_gp_results(label, self.contact_model_part, kratos_variable)
185
+
186
+ for var in self.mixed_nodal_results:
187
+ kratos_variable = Kratos.KratosGlobals.GetVariable(var)
188
+ self._write_nodal_results(label, self.mixed_model_part, kratos_variable)
189
+
190
+ for var in self.structures_gauss_points_results:
191
+ kratos_variable = Kratos.KratosGlobals.GetVariable(var)
192
+ self._write_gp_results(label, self.structures_model_part, kratos_variable)
193
+
194
+ if self.multi_file == MultiFileFlag.MultipleFiles:
195
+ self._finalize_results()
196
+
197
+ with open(self.listfilename, "a") as listfile:
198
+ self.write_step_to_list(label)
199
+
200
+ self.write_step_to_outer_list(label)
201
+