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.
- KratosMultiphysics/.libs/KratosDemStructuresCouplingApplication.so +0 -0
- KratosMultiphysics/.libs/libKratosDemStructuresCouplingCore.dylib +0 -0
- KratosMultiphysics/DemStructuresCouplingApplication/__init__.py +7 -0
- KratosMultiphysics/DemStructuresCouplingApplication/control_module_fem_dem_utility.py +109 -0
- KratosMultiphysics/DemStructuresCouplingApplication/control_module_process.py +29 -0
- KratosMultiphysics/DemStructuresCouplingApplication/dem_fem_coupling_algorithm.py +251 -0
- KratosMultiphysics/DemStructuresCouplingApplication/dem_fem_launcher.py +10 -0
- KratosMultiphysics/DemStructuresCouplingApplication/dem_main_script_ready_for_coupling_with_fem.py +29 -0
- KratosMultiphysics/DemStructuresCouplingApplication/dem_poromechanics_coupling_analysis_stage.py +424 -0
- KratosMultiphysics/DemStructuresCouplingApplication/dem_structures_coupling_gid_output.py +201 -0
- KratosMultiphysics/DemStructuresCouplingApplication/multiaxial_control_module_fem_dem_generalized_2d_utility.py +141 -0
- KratosMultiphysics/DemStructuresCouplingApplication/sand_production_post_process_tool.py +135 -0
- KratosMultiphysics/DemStructuresCouplingApplication/sp_dem_fem_coupling_algorithm.py +303 -0
- KratosMultiphysics/DemStructuresCouplingApplication/sp_dem_fem_launcher.py +10 -0
- KratosMultiphysics/DemStructuresCouplingApplication/sp_statistics.py +143 -0
- KratosMultiphysics/DemStructuresCouplingApplication/sp_statistics_2.py +139 -0
- KratosMultiphysics/DemStructuresCouplingApplication/stress_failure_check_utility.py +36 -0
- kratosdemstructurescouplingapplication-10.4.4.dist-info/METADATA +17 -0
- kratosdemstructurescouplingapplication-10.4.4.dist-info/RECORD +27 -0
- kratosdemstructurescouplingapplication-10.4.4.dist-info/WHEEL +6 -0
- kratosdemstructurescouplingapplication.dylibs/libKratosCore.dylib +4 -0
- kratosdemstructurescouplingapplication.dylibs/libKratosDEMCore.dylib +0 -0
- kratosdemstructurescouplingapplication.dylibs/libKratosPoromechanicsCore.dylib +0 -0
- kratosdemstructurescouplingapplication.dylibs/libKratosStructuralMechanicsCore.dylib +0 -0
- kratosdemstructurescouplingapplication.dylibs/libgcc_s.1.1.dylib +0 -0
- kratosdemstructurescouplingapplication.dylibs/libgomp.1.dylib +0 -0
- kratosdemstructurescouplingapplication.dylibs/libstdc++.6.dylib +0 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import KratosMultiphysics
|
|
2
|
+
import KratosMultiphysics.DEMApplication as Dem
|
|
3
|
+
import KratosMultiphysics.DemStructuresCouplingApplication as DemFem
|
|
4
|
+
from KratosMultiphysics.DEMApplication.multiaxial_control_module_generalized_2d_utility import MultiaxialControlModuleGeneralized2DUtility
|
|
5
|
+
|
|
6
|
+
class MultiaxialControlModuleFEMDEMGeneralized2DUtility(MultiaxialControlModuleGeneralized2DUtility):
|
|
7
|
+
def __init__(self, Model, settings):
|
|
8
|
+
|
|
9
|
+
#NOTE: Negative target_stress means compression
|
|
10
|
+
|
|
11
|
+
self.spheres_model_part = Model["SpheresPart"]
|
|
12
|
+
self.fem_model_part = Model["Structure"]
|
|
13
|
+
|
|
14
|
+
self.parameters = settings["multiaxial_control_module_fem_dem_generalized_2d_utility"]
|
|
15
|
+
|
|
16
|
+
self.cm_step = 0
|
|
17
|
+
self.output_interval = self.parameters["Parameters"]["output_interval"].GetInt()
|
|
18
|
+
|
|
19
|
+
self.cm_utility = DemFem.MultiaxialControlModuleFEMDEMGeneralized2DUtilities(self.spheres_model_part,
|
|
20
|
+
self.fem_model_part,
|
|
21
|
+
self.parameters)
|
|
22
|
+
|
|
23
|
+
def ExecuteFinalizeSolutionStep(self):
|
|
24
|
+
self.cm_utility.ExecuteFinalizeSolutionStep()
|
|
25
|
+
|
|
26
|
+
if self.output_interval == 0:
|
|
27
|
+
return
|
|
28
|
+
self.FillPrintVariables()
|
|
29
|
+
|
|
30
|
+
self.PrintResults()
|
|
31
|
+
|
|
32
|
+
def FillPrintVariables(self):
|
|
33
|
+
time = self.fem_model_part.ProcessInfo[KratosMultiphysics.TIME]
|
|
34
|
+
self.times.append(time)
|
|
35
|
+
|
|
36
|
+
# Pa to psi
|
|
37
|
+
unit_trans = 0.000145038
|
|
38
|
+
|
|
39
|
+
for name in self.actuator_names:
|
|
40
|
+
if name == 'Z':
|
|
41
|
+
for node in self.fem_submodelparts[name][0].Nodes:
|
|
42
|
+
self.reactions[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.REACTION_STRESS_Z))*unit_trans)
|
|
43
|
+
self.target_reactions[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.TARGET_STRESS_Z))*unit_trans)
|
|
44
|
+
self.velocities[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.LOADING_VELOCITY_Z))*unit_trans)
|
|
45
|
+
break
|
|
46
|
+
elif name == 'X':
|
|
47
|
+
for node in self.fem_submodelparts[name][0].Nodes:
|
|
48
|
+
self.reactions[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.REACTION_STRESS_X))*unit_trans)
|
|
49
|
+
self.target_reactions[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.TARGET_STRESS_X))*unit_trans)
|
|
50
|
+
self.velocities[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.LOADING_VELOCITY_X))*unit_trans)
|
|
51
|
+
break
|
|
52
|
+
elif name == 'Y':
|
|
53
|
+
for node in self.fem_submodelparts[name][0].Nodes:
|
|
54
|
+
self.reactions[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.REACTION_STRESS_Y))*unit_trans)
|
|
55
|
+
self.target_reactions[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.TARGET_STRESS_Y))*unit_trans)
|
|
56
|
+
self.velocities[name].append(abs(node.GetValue(KratosMultiphysics.DEMApplication.LOADING_VELOCITY_Y))*unit_trans)
|
|
57
|
+
break
|
|
58
|
+
elif name == 'Radial':
|
|
59
|
+
for node in self.fem_submodelparts[name][0].Nodes:
|
|
60
|
+
value_x = abs(node.GetValue(KratosMultiphysics.DEMApplication.REACTION_STRESS_X))*unit_trans
|
|
61
|
+
value_y = abs(node.GetValue(KratosMultiphysics.DEMApplication.REACTION_STRESS_Y))*unit_trans
|
|
62
|
+
norm = (value_x**2 + value_y**2)**0.5
|
|
63
|
+
self.reactions[name].append(norm)
|
|
64
|
+
value_x = abs(node.GetValue(KratosMultiphysics.DEMApplication.TARGET_STRESS_X))*unit_trans
|
|
65
|
+
value_y = abs(node.GetValue(KratosMultiphysics.DEMApplication.TARGET_STRESS_Y))*unit_trans
|
|
66
|
+
norm = (value_x**2 + value_y**2)**0.5
|
|
67
|
+
self.target_reactions[name].append(norm)
|
|
68
|
+
value_x = abs(node.GetValue(KratosMultiphysics.DEMApplication.LOADING_VELOCITY_X))*unit_trans
|
|
69
|
+
value_y = abs(node.GetValue(KratosMultiphysics.DEMApplication.LOADING_VELOCITY_Y))*unit_trans
|
|
70
|
+
norm = (value_x**2 + value_y**2)**0.5
|
|
71
|
+
self.velocities[name].append(norm)
|
|
72
|
+
break
|
|
73
|
+
|
|
74
|
+
def PrintResults(self):
|
|
75
|
+
self.cm_step += 1
|
|
76
|
+
|
|
77
|
+
if self.output_interval == 0:
|
|
78
|
+
return
|
|
79
|
+
if self.cm_step % self.output_interval != 0:
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
import matplotlib
|
|
83
|
+
matplotlib.use('agg')
|
|
84
|
+
import matplotlib.pyplot as plt
|
|
85
|
+
|
|
86
|
+
f = plt.figure()
|
|
87
|
+
|
|
88
|
+
for name in self.actuator_names:
|
|
89
|
+
plt.plot(self.times,
|
|
90
|
+
self.reactions[name],
|
|
91
|
+
color=self.colors[name],
|
|
92
|
+
linestyle=self.reactions['linestyle'],
|
|
93
|
+
linewidth=self.reactions['linewidth'],
|
|
94
|
+
label='reaction_' + name)
|
|
95
|
+
plt.plot(self.times,
|
|
96
|
+
self.target_reactions[name],
|
|
97
|
+
color=self.colors[name],
|
|
98
|
+
linestyle=self.target_reactions['linestyle'],
|
|
99
|
+
linewidth=self.target_reactions['linewidth'],
|
|
100
|
+
label='target_reaction_' + name)
|
|
101
|
+
|
|
102
|
+
# plt.legend(bbox_to_anchor=(1.05, 1.0), loc='upper left')
|
|
103
|
+
plt.legend()
|
|
104
|
+
max_stress = 0
|
|
105
|
+
for name in self.actuator_names:
|
|
106
|
+
max_stress = max(max(abs(min(self.target_reactions[name])),max(self.target_reactions[name])), max_stress)
|
|
107
|
+
plt.ylim(-0.1*max_stress,1.1*max_stress)
|
|
108
|
+
|
|
109
|
+
plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0))
|
|
110
|
+
|
|
111
|
+
# naming the x axis
|
|
112
|
+
plt.xlabel('Time (s)')
|
|
113
|
+
# naming the y axis
|
|
114
|
+
plt.ylabel('Stress (Psi)')
|
|
115
|
+
# giving a title to my graph
|
|
116
|
+
plt.title('Reaction vs target stresses')
|
|
117
|
+
|
|
118
|
+
f.savefig("reactions.pdf", bbox_inches='tight')
|
|
119
|
+
plt.close()
|
|
120
|
+
|
|
121
|
+
f = plt.figure()
|
|
122
|
+
|
|
123
|
+
for name in self.actuator_names:
|
|
124
|
+
plt.plot(self.times,
|
|
125
|
+
self.velocities[name],
|
|
126
|
+
color=self.colors[name],
|
|
127
|
+
label='velocity_' + name)
|
|
128
|
+
|
|
129
|
+
plt.legend()
|
|
130
|
+
|
|
131
|
+
plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0))
|
|
132
|
+
|
|
133
|
+
# naming the x axis
|
|
134
|
+
plt.xlabel('Time (s)')
|
|
135
|
+
# naming the y axis
|
|
136
|
+
plt.ylabel('velocity (m/s)')
|
|
137
|
+
# giving a title to my graph
|
|
138
|
+
plt.title('Loading velocity')
|
|
139
|
+
|
|
140
|
+
f.savefig("velocities.pdf", bbox_inches='tight')
|
|
141
|
+
plt.close()
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Import system python
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import h5py
|
|
6
|
+
import KratosMultiphysics as Kratos
|
|
7
|
+
import KratosMultiphysics.DEMApplication as Dem
|
|
8
|
+
import KratosMultiphysics.DemStructuresCouplingApplication as DemFem
|
|
9
|
+
|
|
10
|
+
def Norm(vector):
|
|
11
|
+
return np.sqrt(sum(v**2 for v in vector))
|
|
12
|
+
|
|
13
|
+
class SandProductionPostProcessTool():
|
|
14
|
+
def __init__(self, fem_model_part, dem_model_part, test_number):
|
|
15
|
+
|
|
16
|
+
if not test_number:
|
|
17
|
+
return
|
|
18
|
+
|
|
19
|
+
self.parameters = Kratos.Parameters( """
|
|
20
|
+
{
|
|
21
|
+
"file_name": "sp_data.hdf5",
|
|
22
|
+
"target_porosity" : 0.3,
|
|
23
|
+
"probe_height" : 0.2032
|
|
24
|
+
} """ )
|
|
25
|
+
|
|
26
|
+
if test_number == 1: # CTW16
|
|
27
|
+
test_id = "CTW16"
|
|
28
|
+
elif test_number == 2: # CTW10
|
|
29
|
+
test_id = "CTW10"
|
|
30
|
+
else: # Blind test
|
|
31
|
+
test_id = "BlindTest"
|
|
32
|
+
|
|
33
|
+
self.parameters.AddEmptyValue("test_id")
|
|
34
|
+
self.parameters["test_id"].SetString(test_id)
|
|
35
|
+
|
|
36
|
+
self.dem_model_part = dem_model_part
|
|
37
|
+
self.fem_model_part = fem_model_part
|
|
38
|
+
|
|
39
|
+
self.post_process_utility = DemFem.PostProcessUtilities(self.dem_model_part)
|
|
40
|
+
|
|
41
|
+
self.internal_radius, self.external_radius, self.interface_radius, self.thickness, self.volume, self.average_radius = self.GetProbeDimensions()
|
|
42
|
+
for elem in self.dem_model_part.Elements:
|
|
43
|
+
self.density = elem.Properties[Dem.PARTICLE_DENSITY]
|
|
44
|
+
break
|
|
45
|
+
self.porosity = self.CalculatePorosity()
|
|
46
|
+
self.problem_path = os.getcwd()
|
|
47
|
+
self.file_path = os.path.join(str(self.problem_path),self.parameters["file_name"].GetString())
|
|
48
|
+
self.target_porosity = self.parameters["target_porosity"].GetDouble()
|
|
49
|
+
self.real_probe_height = self.parameters["probe_height"].GetDouble()
|
|
50
|
+
|
|
51
|
+
self.dtype = np.float64
|
|
52
|
+
self.compression_type = 'gzip'
|
|
53
|
+
self.number_of_readings = 0
|
|
54
|
+
self.last_time = - float('inf')
|
|
55
|
+
|
|
56
|
+
# This assumes annulus centered at the origin
|
|
57
|
+
with h5py.File(self.file_path, 'w') as f:
|
|
58
|
+
f.attrs['test_id'] = self.parameters["test_id"].GetString()
|
|
59
|
+
f.attrs['internal_radius'] = self.internal_radius
|
|
60
|
+
f.attrs['external_radius'] = self.external_radius
|
|
61
|
+
f.attrs['interface_radius'] = self.interface_radius
|
|
62
|
+
f.attrs['thickness'] = self.thickness
|
|
63
|
+
f.attrs['volume'] = self.volume
|
|
64
|
+
f.attrs['real_probe_height'] = self.real_probe_height
|
|
65
|
+
f.attrs['target_porosity'] = self.target_porosity
|
|
66
|
+
f.attrs['porosity'] = self.porosity
|
|
67
|
+
f.attrs['density'] = self.density
|
|
68
|
+
|
|
69
|
+
def CalculateAverageRadius(self):
|
|
70
|
+
radii_array = np.array([node.GetSolutionStepValue(Kratos.RADIUS) for node in self.dem_model_part.Nodes])
|
|
71
|
+
return sum(radii_array)/len(radii_array)
|
|
72
|
+
|
|
73
|
+
def GetProbeDimensions(self):
|
|
74
|
+
average_radius = self.CalculateAverageRadius()
|
|
75
|
+
internal_radius = min(Norm([node.X, node.Y]) for node in self.dem_model_part.Nodes) - average_radius
|
|
76
|
+
external_radius = max(Norm([node.X, node.Y]) for node in self.fem_model_part.Nodes)
|
|
77
|
+
interface_radius = max(Norm([node.X, node.Y]) for node in self.dem_model_part.Nodes) + average_radius
|
|
78
|
+
min_z = min(node.Z for node in self.fem_model_part.Nodes)
|
|
79
|
+
max_z = max(node.Z for node in self.fem_model_part.Nodes)
|
|
80
|
+
thickness = max_z - min_z
|
|
81
|
+
area = np.pi * (external_radius**2 - internal_radius**2)
|
|
82
|
+
volume = thickness * area
|
|
83
|
+
return internal_radius, external_radius, interface_radius, thickness, volume, average_radius
|
|
84
|
+
|
|
85
|
+
def CalculatePorosity(self):
|
|
86
|
+
volume = 0.
|
|
87
|
+
for node in self.dem_model_part.Nodes:
|
|
88
|
+
volume += 4/3 * np.pi * node.GetSolutionStepValue(Kratos.RADIUS) ** 3
|
|
89
|
+
volume_dem_part = np.pi * self.thickness * (self.interface_radius**2 - self.internal_radius**2)
|
|
90
|
+
porosity = volume / volume_dem_part
|
|
91
|
+
return porosity
|
|
92
|
+
|
|
93
|
+
def WriteData(self):
|
|
94
|
+
time = self.dem_model_part.ProcessInfo[Kratos.TIME]
|
|
95
|
+
name = str(self.number_of_readings)
|
|
96
|
+
with h5py.File(self.file_path, 'r+') as f:
|
|
97
|
+
f.create_group(name = name)
|
|
98
|
+
f[name].attrs['time'] = time
|
|
99
|
+
column_shape = (len(self.dem_model_part.Nodes), )
|
|
100
|
+
self.ids_array = np.array([node.Id for node in self.dem_model_part.Nodes])
|
|
101
|
+
self.radii_array = np.array([node.GetSolutionStepValue(Kratos.RADIUS) for node in self.dem_model_part.Nodes])
|
|
102
|
+
self.x_array = np.array([node.X for node in self.dem_model_part.Nodes])
|
|
103
|
+
self.y_array = np.array([node.Y for node in self.dem_model_part.Nodes])
|
|
104
|
+
self.z_array = np.array([node.Z for node in self.dem_model_part.Nodes])
|
|
105
|
+
is_sticky_list = []
|
|
106
|
+
self.post_process_utility.GetStickyStatus(is_sticky_list)
|
|
107
|
+
self.is_sticky_array = np.array(is_sticky_list)
|
|
108
|
+
initial_continuum_bonds_list = []
|
|
109
|
+
self.post_process_utility.GetInitialContinuumBonds(initial_continuum_bonds_list)
|
|
110
|
+
self.initial_continuum_bonds_array = np.array(initial_continuum_bonds_list)
|
|
111
|
+
current_continuum_bonds_list = []
|
|
112
|
+
self.post_process_utility.GetCurrentContinuumBonds(current_continuum_bonds_list)
|
|
113
|
+
self.current_continuum_bonds_array = np.array(current_continuum_bonds_list)
|
|
114
|
+
|
|
115
|
+
if not self.last_time == time:
|
|
116
|
+
with h5py.File(self.file_path, 'r+') as f:
|
|
117
|
+
f.create_dataset(name + '/id', compression = self.compression_type, shape = column_shape, dtype = self.dtype) # TODO: change type as int
|
|
118
|
+
f[name + '/id'][:] = self.ids_array[:]
|
|
119
|
+
f.create_dataset(name + '/radius', compression = self.compression_type, shape = column_shape, dtype = self.dtype)
|
|
120
|
+
f[name + '/radius'][:] = self.radii_array[:]
|
|
121
|
+
f.create_dataset(name + '/x', compression = self.compression_type, shape = column_shape, dtype = self.dtype)
|
|
122
|
+
f[name + '/x'][:] = self.x_array[:]
|
|
123
|
+
f.create_dataset(name + '/y', compression = self.compression_type, shape = column_shape, dtype = self.dtype)
|
|
124
|
+
f[name + '/y'][:] = self.y_array[:]
|
|
125
|
+
f.create_dataset(name + '/z', compression = self.compression_type, shape = column_shape, dtype = self.dtype)
|
|
126
|
+
f[name + '/z'][:] = self.z_array[:]
|
|
127
|
+
f.create_dataset(name + '/is_sticky', compression = self.compression_type, shape = column_shape, dtype = self.dtype)
|
|
128
|
+
f[name + '/is_sticky'][:] = self.is_sticky_array[:]
|
|
129
|
+
f.create_dataset(name + '/initial_continuum_bonds', compression = self.compression_type, shape = column_shape, dtype = self.dtype)
|
|
130
|
+
f[name + '/initial_continuum_bonds'][:] = self.initial_continuum_bonds_array[:]
|
|
131
|
+
f.create_dataset(name + '/current_continuum_bonds', compression = self.compression_type, shape = column_shape, dtype = self.dtype)
|
|
132
|
+
f[name + '/current_continuum_bonds'][:] = self.current_continuum_bonds_array[:]
|
|
133
|
+
|
|
134
|
+
self.last_time = time
|
|
135
|
+
self.number_of_readings += 1
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import time as timer
|
|
2
|
+
import os
|
|
3
|
+
import KratosMultiphysics as Kratos
|
|
4
|
+
from Kratos import Logger
|
|
5
|
+
from KratosMultiphysics.deprecation_management import DeprecationManager
|
|
6
|
+
|
|
7
|
+
import KratosMultiphysics.DEMApplication as Dem
|
|
8
|
+
Logger.Print("Running under OpenMP........", label="DEM")
|
|
9
|
+
import KratosMultiphysics.StructuralMechanicsApplication as Structural
|
|
10
|
+
import KratosMultiphysics.DemStructuresCouplingApplication as DemFem
|
|
11
|
+
from KratosMultiphysics.DemStructuresCouplingApplication.dem_fem_coupling_algorithm import Algorithm
|
|
12
|
+
|
|
13
|
+
class SPAlgorithm(Algorithm):
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
super(SPAlgorithm,self).__init__()
|
|
17
|
+
|
|
18
|
+
sp_parameters_file_name = "SPParameters.json"
|
|
19
|
+
|
|
20
|
+
with open(sp_parameters_file_name,'r') as parameter_file:
|
|
21
|
+
self.sp_parameters = Kratos.Parameters(parameter_file.read())
|
|
22
|
+
|
|
23
|
+
self.ValidateSettings()
|
|
24
|
+
|
|
25
|
+
self.test_number = self.sp_parameters["problem_data"]["test_number"].GetInt()
|
|
26
|
+
# Test types (4 different options):
|
|
27
|
+
# Test number 0: no test simulation
|
|
28
|
+
# Test number 1: CTW16 specimen
|
|
29
|
+
# Test number 2: CTW10 specimen
|
|
30
|
+
# Test number 3: Blind test specimen
|
|
31
|
+
|
|
32
|
+
self.post_process_step_count = 0
|
|
33
|
+
self.post_process_frequency = self.sp_parameters["post_process_tool"]["output_interval"].GetInt()
|
|
34
|
+
self.use_post_process_tool = self.sp_parameters["post_process_tool"]["use_post_process_tool"].GetBool()
|
|
35
|
+
if not self.use_post_process_tool:
|
|
36
|
+
self.post_process_frequency = 0
|
|
37
|
+
self.post_process_write_count = self.post_process_frequency
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def GetDefaultParameters(cls):
|
|
41
|
+
"""This function returns the default-settings used by this class
|
|
42
|
+
"""
|
|
43
|
+
return Kratos.Parameters("""{
|
|
44
|
+
"problem_data" : {
|
|
45
|
+
"test_number" : 1,
|
|
46
|
+
"center" : [0.0,0.0,0.0],
|
|
47
|
+
"axis" : [0.0,0.0,1.0],
|
|
48
|
+
"sp_radius": 0.042
|
|
49
|
+
},
|
|
50
|
+
"post_process_tool":{
|
|
51
|
+
"use_post_process_tool": false,
|
|
52
|
+
"output_interval": 0
|
|
53
|
+
},
|
|
54
|
+
"multiaxial_control_module_fem_dem_generalized_2d_utility" : {
|
|
55
|
+
"Parameters" : {
|
|
56
|
+
"control_module_delta_time": 2.0e-6,
|
|
57
|
+
"perturbation_tolerance": 1.0e-3,
|
|
58
|
+
"perturbation_period": 10,
|
|
59
|
+
"max_reaction_rate_factor": 10.0,
|
|
60
|
+
"stiffness_averaging_time_interval": 2.0e-6,
|
|
61
|
+
"velocity_averaging_time_interval": 2.0e-6,
|
|
62
|
+
"reaction_averaging_time_interval": 2.0e-8,
|
|
63
|
+
"output_interval": 0
|
|
64
|
+
},
|
|
65
|
+
"list_of_actuators" : []
|
|
66
|
+
}
|
|
67
|
+
}""")
|
|
68
|
+
|
|
69
|
+
# This function can be extended with new deprecated variables as they are generated
|
|
70
|
+
def TranslateLegacyVariablesAccordingToCurrentStandard(self, settings):
|
|
71
|
+
# Defining a string to help the user understand where the warnings come from (in case any is thrown)
|
|
72
|
+
context_string = type(self).__name__
|
|
73
|
+
|
|
74
|
+
if settings.Has('post_process_tool'):
|
|
75
|
+
sub_settings_where_var_is = settings['post_process_tool']
|
|
76
|
+
old_name = 'output_frequency'
|
|
77
|
+
new_name = 'output_interval'
|
|
78
|
+
|
|
79
|
+
if DeprecationManager.HasDeprecatedVariable(context_string, sub_settings_where_var_is, old_name, new_name):
|
|
80
|
+
DeprecationManager.ReplaceDeprecatedVariableName(sub_settings_where_var_is, old_name, new_name)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def ValidateSettings(self):
|
|
84
|
+
"""This function validates the settings of the solver
|
|
85
|
+
"""
|
|
86
|
+
default_settings = self.GetDefaultParameters()
|
|
87
|
+
self.TranslateLegacyVariablesAccordingToCurrentStandard(self.sp_parameters)
|
|
88
|
+
self.sp_parameters.ValidateAndAssignDefaults(default_settings)
|
|
89
|
+
|
|
90
|
+
def Initialize(self):
|
|
91
|
+
super(SPAlgorithm,self).Initialize()
|
|
92
|
+
|
|
93
|
+
self.InitializeAdditionalProcessInfoVars()
|
|
94
|
+
|
|
95
|
+
from KratosMultiphysics.DemStructuresCouplingApplication.multiaxial_control_module_fem_dem_generalized_2d_utility import MultiaxialControlModuleFEMDEMGeneralized2DUtility
|
|
96
|
+
self.multiaxial_control_module = MultiaxialControlModuleFEMDEMGeneralized2DUtility(self.model, self.sp_parameters)
|
|
97
|
+
self.multiaxial_control_module.ExecuteInitialize()
|
|
98
|
+
# if self.test_number:
|
|
99
|
+
# from KratosMultiphysics.DemStructuresCouplingApplication.control_module_fem_dem_utility import ControlModuleFemDemUtility
|
|
100
|
+
# self.control_module_fem_dem_utility = ControlModuleFemDemUtility(self.model, self.dem_solution.spheres_model_part, self.test_number)
|
|
101
|
+
# self.control_module_fem_dem_utility.ExecuteInitialize()
|
|
102
|
+
|
|
103
|
+
self.CreateSPMeasuringRingSubmodelpart()
|
|
104
|
+
|
|
105
|
+
# Create Postprocess tool for SP
|
|
106
|
+
if self.use_post_process_tool:
|
|
107
|
+
from KratosMultiphysics.DemStructuresCouplingApplication.sand_production_post_process_tool import SandProductionPostProcessTool
|
|
108
|
+
self.sp_post_process_tool = SandProductionPostProcessTool(self.structural_solution._GetSolver().GetComputingModelPart(),
|
|
109
|
+
self.dem_solution.spheres_model_part,
|
|
110
|
+
self.test_number)
|
|
111
|
+
|
|
112
|
+
from KratosMultiphysics.DemStructuresCouplingApplication import stress_failure_check_utility
|
|
113
|
+
self.stress_failure_check_utility = stress_failure_check_utility.StressFailureCheckUtility(self.dem_solution.spheres_model_part, self.test_number)
|
|
114
|
+
|
|
115
|
+
def CreateSPMeasuringRingSubmodelpart(self):
|
|
116
|
+
|
|
117
|
+
if not self.dem_solution.spheres_model_part.HasSubModelPart("RingSubmodelPart"):
|
|
118
|
+
self.dem_solution.spheres_model_part.CreateSubModelPart('RingSubmodelPart')
|
|
119
|
+
self.ring_submodelpart = self.dem_solution.spheres_model_part.GetSubModelPart('RingSubmodelPart')
|
|
120
|
+
|
|
121
|
+
zone_radius_to_measure_2d_sp = self.sp_parameters["problem_data"]["sp_radius"].GetDouble()
|
|
122
|
+
nodes_in_zone_radius_list = []
|
|
123
|
+
elements_in_zone_radius_list = []
|
|
124
|
+
|
|
125
|
+
for element in self.dem_solution.spheres_model_part.Elements:
|
|
126
|
+
node = element.GetNode(0)
|
|
127
|
+
x = node.X
|
|
128
|
+
y = node.Y
|
|
129
|
+
|
|
130
|
+
if (x * x + y * y) < zone_radius_to_measure_2d_sp * zone_radius_to_measure_2d_sp:
|
|
131
|
+
nodes_in_zone_radius_list.append(node.Id)
|
|
132
|
+
elements_in_zone_radius_list.append(element.Id)
|
|
133
|
+
|
|
134
|
+
self.ring_submodelpart.AddNodes(nodes_in_zone_radius_list)
|
|
135
|
+
self.ring_submodelpart.AddElements(elements_in_zone_radius_list)
|
|
136
|
+
|
|
137
|
+
def InitializeAdditionalProcessInfoVars(self):
|
|
138
|
+
self.dem_solution.spheres_model_part.ProcessInfo.SetValue(Dem.SIGMA_3_AVERAGE, 0.0)
|
|
139
|
+
|
|
140
|
+
def _TransferStructuresSkinToDem(self):
|
|
141
|
+
self.structural_mp = self.structural_solution._GetSolver().GetComputingModelPart()
|
|
142
|
+
self.skin_mp = self.structural_mp.GetSubModelPart("DetectedByProcessSkinModelPart")
|
|
143
|
+
# dem_walls_mp = self.dem_solution.rigid_face_model_part.CreateSubModelPart("SkinTransferredFromStructure")
|
|
144
|
+
dem_walls_mp = self.dem_solution.rigid_face_model_part
|
|
145
|
+
max_prop_id = 0
|
|
146
|
+
for prop in dem_walls_mp.Properties:
|
|
147
|
+
if prop.Id > max_prop_id:
|
|
148
|
+
max_prop_id = prop.Id
|
|
149
|
+
props = Kratos.Properties(max_prop_id + 1)
|
|
150
|
+
# NOTE: this should be more general
|
|
151
|
+
props[Dem.STATIC_FRICTION] = 0.2
|
|
152
|
+
props[Dem.DYNAMIC_FRICTION] = 0.2
|
|
153
|
+
props[Dem.WALL_COHESION] = 0.0
|
|
154
|
+
props[Dem.COMPUTE_WEAR] = False
|
|
155
|
+
props[Dem.SEVERITY_OF_WEAR] = 0.001
|
|
156
|
+
props[Dem.IMPACT_WEAR_SEVERITY] = 0.001
|
|
157
|
+
props[Dem.BRINELL_HARDNESS] = 200.0
|
|
158
|
+
props[Kratos.YOUNG_MODULUS] = 7e9
|
|
159
|
+
props[Kratos.POISSON_RATIO] = 0.16
|
|
160
|
+
dem_walls_mp.AddProperties(props)
|
|
161
|
+
DemFem.DemStructuresCouplingUtilities().TransferStructuresSkinToDem(self.skin_mp, dem_walls_mp, props)
|
|
162
|
+
|
|
163
|
+
def RunSolutionLoop(self):
|
|
164
|
+
|
|
165
|
+
self.dem_solution.step = 0
|
|
166
|
+
self.dem_solution.time = 0.0
|
|
167
|
+
self.dem_solution.time_old_print = 0.0
|
|
168
|
+
self.time_dem = 0.0
|
|
169
|
+
self.Dt_structural = self.structural_solution._GetSolver().settings["time_stepping"]["time_step"].GetDouble()
|
|
170
|
+
|
|
171
|
+
while self.structural_solution.time < self.structural_solution.end_time:
|
|
172
|
+
|
|
173
|
+
portion_of_the_force_which_is_new = 0.1
|
|
174
|
+
DemFem.DemStructuresCouplingUtilities().SmoothLoadTrasferredToFem(self.dem_solution.rigid_face_model_part, portion_of_the_force_which_is_new)
|
|
175
|
+
|
|
176
|
+
self.structural_solution.time = self.structural_solution._GetSolver().AdvanceInTime(self.structural_solution.time)
|
|
177
|
+
|
|
178
|
+
# if self.test_number:
|
|
179
|
+
# self.control_module_fem_dem_utility.ExecuteInitializeSolutionStep()
|
|
180
|
+
self.multiaxial_control_module.ExecuteInitializeSolutionStep()
|
|
181
|
+
self.structural_solution.InitializeSolutionStep()
|
|
182
|
+
self.structural_solution._GetSolver().Predict()
|
|
183
|
+
self.structural_solution._GetSolver().SolveSolutionStep()
|
|
184
|
+
|
|
185
|
+
time_final_DEM_substepping = self.structural_solution.time
|
|
186
|
+
|
|
187
|
+
self.Dt_DEM = self.dem_solution.spheres_model_part.ProcessInfo.GetValue(Kratos.DELTA_TIME)
|
|
188
|
+
|
|
189
|
+
DemFem.InterpolateStructuralSolutionForDEM().SaveStructuralSolution(self.structural_mp)
|
|
190
|
+
|
|
191
|
+
DemFem.ComputeDEMFaceLoadUtility().ClearDEMFaceLoads(self.skin_mp)
|
|
192
|
+
|
|
193
|
+
for self.dem_solution.time_dem in self.yield_DEM_time(self.dem_solution.time, time_final_DEM_substepping, self.Dt_DEM):
|
|
194
|
+
self.dem_solution.time = self.dem_solution.time + self.dem_solution._GetSolver().dt
|
|
195
|
+
|
|
196
|
+
self.dem_solution.step += 1
|
|
197
|
+
|
|
198
|
+
self.dem_solution.DEMFEMProcedures.UpdateTimeInModelParts(self.dem_solution.all_model_parts, self.dem_solution.time, self.dem_solution._GetSolver().dt, self.dem_solution.step)
|
|
199
|
+
|
|
200
|
+
self.dem_solution.InitializeSolutionStep()
|
|
201
|
+
|
|
202
|
+
self.dem_solution._GetSolver().Predict()
|
|
203
|
+
|
|
204
|
+
DemFem.InterpolateStructuralSolutionForDEM().InterpolateStructuralSolution(self.structural_mp, self.Dt_structural, self.structural_solution.time, self.dem_solution._GetSolver().dt, self.dem_solution.time)
|
|
205
|
+
|
|
206
|
+
self.dem_solution.SolverSolve()
|
|
207
|
+
|
|
208
|
+
self.dem_solution.FinalizeSolutionStep()
|
|
209
|
+
|
|
210
|
+
DemFem.ComputeDEMFaceLoadUtility().CalculateDEMFaceLoads(self.skin_mp, self.dem_solution._GetSolver().dt, self.Dt_structural)
|
|
211
|
+
|
|
212
|
+
#### PRINTING GRAPHS ####
|
|
213
|
+
os.chdir(self.dem_solution.graphs_path)
|
|
214
|
+
self.dem_solution.post_utils.ComputeMeanVelocitiesInTrap("Average_Velocity.txt", self.dem_solution.time, self.dem_solution.graphs_path)
|
|
215
|
+
|
|
216
|
+
#old function, we can not use them now #TODO:update it
|
|
217
|
+
#self.dem_solution.materialTest.MeasureForcesAndPressure()
|
|
218
|
+
#self.dem_solution.materialTest.PrintGraph(self.dem_solution.time)
|
|
219
|
+
|
|
220
|
+
self.dem_solution.DEMFEMProcedures.PrintGraph(self.dem_solution.time)
|
|
221
|
+
self.dem_solution.DEMFEMProcedures.PrintBallsGraph(self.dem_solution.time)
|
|
222
|
+
|
|
223
|
+
self.dem_solution.DEMEnergyCalculator.CalculateEnergyAndPlot(self.dem_solution.time)
|
|
224
|
+
|
|
225
|
+
self.dem_solution.BeforePrintingOperations(self.dem_solution.time)
|
|
226
|
+
|
|
227
|
+
#### GiD IO ##########################################
|
|
228
|
+
if self.dem_solution.IsTimeToPrintPostProcess():
|
|
229
|
+
self.dem_solution._GetSolver().PrepareElementsForPrinting()
|
|
230
|
+
if self.dem_solution.DEM_parameters["ContactMeshOption"].GetBool():
|
|
231
|
+
self.dem_solution._GetSolver().PrepareContactElementsForPrinting()
|
|
232
|
+
self.dem_solution.PrintResultsForGid(self.dem_solution.time)
|
|
233
|
+
self.SPPostProcessResults(self.dem_solution.time)
|
|
234
|
+
self.dem_solution.demio.PrintMultifileLists(self.dem_solution.time, self.dem_solution.post_path)
|
|
235
|
+
self.dem_solution.time_old_print = self.dem_solution.time
|
|
236
|
+
|
|
237
|
+
if self.test_number:
|
|
238
|
+
self.stress_failure_check_utility.ExecuteFinalizeSolutionStep()
|
|
239
|
+
|
|
240
|
+
DemFem.InterpolateStructuralSolutionForDEM().RestoreStructuralSolution(self.structural_mp)
|
|
241
|
+
|
|
242
|
+
# if self.test_number:
|
|
243
|
+
# self.control_module_fem_dem_utility.ExecuteFinalizeSolutionStep()
|
|
244
|
+
self.multiaxial_control_module.ExecuteFinalizeSolutionStep()
|
|
245
|
+
self.structural_solution.FinalizeSolutionStep()
|
|
246
|
+
self.structural_solution.OutputSolutionStep()
|
|
247
|
+
|
|
248
|
+
# Write SP data
|
|
249
|
+
if self.IsPostProcessWriteStep():
|
|
250
|
+
self.sp_post_process_tool.WriteData()
|
|
251
|
+
|
|
252
|
+
def IsPostProcessWriteStep(self):
|
|
253
|
+
self.post_process_step_count += 1
|
|
254
|
+
if self.post_process_step_count == self.post_process_write_count:
|
|
255
|
+
self.post_process_write_count += self.post_process_frequency
|
|
256
|
+
return True
|
|
257
|
+
else:
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
def SPPostProcessResults(self,time):
|
|
261
|
+
DemFem.DemStructuresCouplingUtilities().MarkBrokenSpheres(self.ring_submodelpart)
|
|
262
|
+
|
|
263
|
+
center = Kratos.Array3()
|
|
264
|
+
center[0] = self.sp_parameters["problem_data"]["center"][0].GetDouble()
|
|
265
|
+
center[1] = self.sp_parameters["problem_data"]["center"][1].GetDouble()
|
|
266
|
+
center[2] = self.sp_parameters["problem_data"]["center"][2].GetDouble()
|
|
267
|
+
axis = Kratos.Array3()
|
|
268
|
+
axis[0] = self.sp_parameters["problem_data"]["axis"][0].GetDouble()
|
|
269
|
+
axis[1] = self.sp_parameters["problem_data"]["axis"][1].GetDouble()
|
|
270
|
+
axis[2] = self.sp_parameters["problem_data"]["axis"][2].GetDouble()
|
|
271
|
+
|
|
272
|
+
radius = 0
|
|
273
|
+
if self.test_number == 1:
|
|
274
|
+
radius = 0.0036195; #95% of the real hole. CTW16 specimen
|
|
275
|
+
elif self.test_number == 2:
|
|
276
|
+
radius = 0.012065; #95% of the real hole. CTW10 specimen
|
|
277
|
+
elif self.test_number == 3:
|
|
278
|
+
radius = 0.036195; #95% of the real hole. Blind Test
|
|
279
|
+
|
|
280
|
+
self.dem_solution.creator_destructor.MarkParticlesForErasingGivenCylinder(self.ring_submodelpart, center, axis, radius)
|
|
281
|
+
|
|
282
|
+
if self.test_number == 1 or self.test_number == 2:
|
|
283
|
+
if self.structural_solution._GetSolver().main_model_part.ProcessInfo[Kratos.DOMAIN_SIZE] == 2:
|
|
284
|
+
self.outer_walls_model_part = self.model["Structure.LinePressure2D_Outer_line"]
|
|
285
|
+
else:
|
|
286
|
+
self.outer_walls_model_part = self.model["Structure.SurfacePressure3D_lateral_pressure"]
|
|
287
|
+
DemFem.DemStructuresCouplingUtilities().ComputeSandProductionWithDepthFirstSearchNonRecursiveImplementation(self.ring_submodelpart, self.outer_walls_model_part, time)
|
|
288
|
+
DemFem.DemStructuresCouplingUtilities().ComputeSandProduction(self.ring_submodelpart, self.outer_walls_model_part, time)
|
|
289
|
+
elif self.test_number == 3:
|
|
290
|
+
if self.structural_solution._GetSolver().main_model_part.ProcessInfo[Kratos.DOMAIN_SIZE] == 2:
|
|
291
|
+
self.outer_walls_model_part_1 = self.model["Structure.LinePressure2D_Left_line"]
|
|
292
|
+
# self.outer_walls_model_part_2 = self.model["Structure.LinePressure2D_Bot_line"]
|
|
293
|
+
else:
|
|
294
|
+
self.outer_walls_model_part_1 = self.model["Structure.SurfacePressure3D_sigmaXpos"]
|
|
295
|
+
# self.outer_walls_model_part_2 = self.model["Structure.SurfacePressure3D_sigmaYpos"]
|
|
296
|
+
# NOTE: The stress printed in this case will also be the SigmaZ, but probably SigmaX is more appropriate
|
|
297
|
+
DemFem.DemStructuresCouplingUtilities().ComputeSandProductionWithDepthFirstSearchNonRecursiveImplementation(self.ring_submodelpart, self.outer_walls_model_part_1, time)
|
|
298
|
+
DemFem.DemStructuresCouplingUtilities().ComputeSandProduction(self.ring_submodelpart, self.outer_walls_model_part_1, time)
|
|
299
|
+
# DemFem.DemStructuresCouplingUtilities().ComputeTriaxialSandProduction(self.ring_submodelpart, self.outer_walls_model_part_1, self.outer_walls_model_part_2, time)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
if __name__ == "__main__":
|
|
303
|
+
SPAlgorithm().Run()
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import KratosMultiphysics as Kratos
|
|
3
|
+
from Kratos import Logger
|
|
4
|
+
import KratosMultiphysics.DEMApplication as Dem
|
|
5
|
+
import KratosMultiphysics.StructuralMechanicsApplication as Structural
|
|
6
|
+
import KratosMultiphysics.DemStructuresCouplingApplication as DemFem
|
|
7
|
+
|
|
8
|
+
from KratosMultiphysics.DemStructuresCouplingApplication.sp_dem_fem_coupling_algorithm import SPAlgorithm
|
|
9
|
+
|
|
10
|
+
SPAlgorithm().Run()
|