KratosMPMApplication 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/KratosMPMApplication.so +0 -0
- KratosMultiphysics/.libs/libKratosMPMCore.dylib +0 -0
- KratosMultiphysics/MPMApplication/__init__.py +6 -0
- KratosMultiphysics/MPMApplication/apply_mpm_3d_rotating_dirichlet_condition_process.py +147 -0
- KratosMultiphysics/MPMApplication/apply_mpm_coupling_interface_dirichlet_condition_process.py +132 -0
- KratosMultiphysics/MPMApplication/apply_mpm_coupling_interface_neumann_condition_process.py +101 -0
- KratosMultiphysics/MPMApplication/apply_mpm_particle_dirichlet_condition_process.py +207 -0
- KratosMultiphysics/MPMApplication/apply_mpm_particle_neumann_condition_process.py +169 -0
- KratosMultiphysics/MPMApplication/apply_mpm_slip_boundary_process.py +62 -0
- KratosMultiphysics/MPMApplication/assign_gravity_to_material_point_process.py +66 -0
- KratosMultiphysics/MPMApplication/assign_gravity_to_particle_process.py +13 -0
- KratosMultiphysics/MPMApplication/assign_initial_velocity_to_material_point_process.py +77 -0
- KratosMultiphysics/MPMApplication/assign_initial_velocity_to_particle_process.py +13 -0
- KratosMultiphysics/MPMApplication/kratos_main_mpm.py +17 -0
- KratosMultiphysics/MPMApplication/mpm_analysis.py +196 -0
- KratosMultiphysics/MPMApplication/mpm_explicit_solver.py +129 -0
- KratosMultiphysics/MPMApplication/mpm_from_json_check_result_process.py +426 -0
- KratosMultiphysics/MPMApplication/mpm_gid_output_process.py +260 -0
- KratosMultiphysics/MPMApplication/mpm_implicit_dynamic_solver.py +70 -0
- KratosMultiphysics/MPMApplication/mpm_json_output_process.py +220 -0
- KratosMultiphysics/MPMApplication/mpm_quasi_static_solver.py +22 -0
- KratosMultiphysics/MPMApplication/mpm_solver.py +529 -0
- KratosMultiphysics/MPMApplication/mpm_static_solver.py +21 -0
- KratosMultiphysics/MPMApplication/mpm_vtk_output_process.py +91 -0
- KratosMultiphysics/MPMApplication/mpm_write_energy_output_process.py +90 -0
- KratosMultiphysics/MPMApplication/particle_from_json_check_result_process.py +12 -0
- KratosMultiphysics/MPMApplication/particle_gid_output_process.py +15 -0
- KratosMultiphysics/MPMApplication/particle_json_output_process.py +12 -0
- KratosMultiphysics/MPMApplication/particle_mechanics_analysis.py +33 -0
- KratosMultiphysics/MPMApplication/particle_vtk_output_process.py +11 -0
- KratosMultiphysics/MPMApplication/python_solvers_wrapper_mpm.py +56 -0
- kratosmpmapplication-10.4.4.dist-info/METADATA +155 -0
- kratosmpmapplication-10.4.4.dist-info/RECORD +38 -0
- kratosmpmapplication-10.4.4.dist-info/WHEEL +6 -0
- kratosmpmapplication.dylibs/libKratosCore.dylib +4 -0
- kratosmpmapplication.dylibs/libgcc_s.1.1.dylib +0 -0
- kratosmpmapplication.dylibs/libgomp.1.dylib +0 -0
- kratosmpmapplication.dylibs/libstdc++.6.dylib +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import KratosMultiphysics
|
|
2
|
+
from KratosMultiphysics.deprecation_management import DeprecationManager
|
|
3
|
+
import KratosMultiphysics.MPMApplication as KratosMPM
|
|
4
|
+
from KratosMultiphysics.MPMApplication.apply_mpm_particle_dirichlet_condition_process import ApplyMPMParticleDirichletConditionProcess
|
|
5
|
+
|
|
6
|
+
import math
|
|
7
|
+
|
|
8
|
+
def Factory(settings, Model):
|
|
9
|
+
if(not isinstance(settings, KratosMultiphysics.Parameters)):
|
|
10
|
+
raise Exception("expected input shall be a Parameters object, encapsulating a json string")
|
|
11
|
+
return ApplyMPM3DRotatingDirichletConditionProcess(Model, settings["Parameters"])
|
|
12
|
+
|
|
13
|
+
## All the processes python should be derived from "Process"
|
|
14
|
+
class ApplyMPM3DRotatingDirichletConditionProcess(ApplyMPMParticleDirichletConditionProcess):
|
|
15
|
+
def __init__(self, Model, settings ):
|
|
16
|
+
|
|
17
|
+
default_parameters = KratosMultiphysics.Parameters( """
|
|
18
|
+
{
|
|
19
|
+
"model_part_name" : "PLEASE_SPECIFY_MODEL_PART_NAME",
|
|
20
|
+
"material_points_per_condition" : 0,
|
|
21
|
+
"imposition_type" : "penalty",
|
|
22
|
+
"penalty_coefficient" : 0,
|
|
23
|
+
"constrained" : "fixed",
|
|
24
|
+
"option" : "",
|
|
25
|
+
"rotation_center" : [0.0, 0.0, 0.0],
|
|
26
|
+
"rotation_velocity" : [0.0, 0.0, 0.0],
|
|
27
|
+
"compute_rotation_center" : false,
|
|
28
|
+
"rotation_option" : ""
|
|
29
|
+
} """ )
|
|
30
|
+
|
|
31
|
+
context_string = type(self).__name__
|
|
32
|
+
old_name = 'particles_per_condition'
|
|
33
|
+
new_name = 'material_points_per_condition'
|
|
34
|
+
if DeprecationManager.HasDeprecatedVariable(context_string, settings, old_name, new_name):
|
|
35
|
+
DeprecationManager.ReplaceDeprecatedVariableName(settings, old_name, new_name)
|
|
36
|
+
|
|
37
|
+
context_string = type(self).__name__
|
|
38
|
+
old_name = 'penalty_factor'
|
|
39
|
+
new_name = 'penalty_coefficient'
|
|
40
|
+
if DeprecationManager.HasDeprecatedVariable(context_string, settings, old_name, new_name):
|
|
41
|
+
DeprecationManager.ReplaceDeprecatedVariableName(settings, old_name, new_name)
|
|
42
|
+
|
|
43
|
+
settings.ValidateAndAssignDefaults(default_parameters)
|
|
44
|
+
self.model = Model
|
|
45
|
+
self.model_part_name = settings["model_part_name"].GetString()
|
|
46
|
+
|
|
47
|
+
# Private process variables
|
|
48
|
+
self.rotation_center = settings["rotation_center"].GetVector()
|
|
49
|
+
self.rotation_velocity = settings["rotation_velocity"].GetVector()
|
|
50
|
+
self.compute_rotation_center = settings["compute_rotation_center"].GetBool()
|
|
51
|
+
self.rotation_option = settings["rotation_option"].GetString()
|
|
52
|
+
|
|
53
|
+
settings.RemoveValue("rotation_center")
|
|
54
|
+
settings.RemoveValue("rotation_velocity")
|
|
55
|
+
settings.RemoveValue("compute_rotation_center")
|
|
56
|
+
settings.RemoveValue("rotation_option")
|
|
57
|
+
|
|
58
|
+
# Initiate base class - Dirichlet condition
|
|
59
|
+
super().__init__(Model, settings)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def ExecuteBeforeSolutionLoop(self):
|
|
63
|
+
# Get updated model_part
|
|
64
|
+
if (self.model_part_name.startswith('Background_Grid.')):
|
|
65
|
+
self.model_part_name = self.model_part_name.replace('Background_Grid.','')
|
|
66
|
+
mpm_material_model_part_name = "MPM_Material." + self.model_part_name
|
|
67
|
+
self.model_part = self.model[mpm_material_model_part_name]
|
|
68
|
+
|
|
69
|
+
# If compute rotation center automatically is needed
|
|
70
|
+
if self.compute_rotation_center:
|
|
71
|
+
self._ComputeCenterRotation()
|
|
72
|
+
|
|
73
|
+
# Initial Quaternion, its increment, and rotation_matrix
|
|
74
|
+
self._InitializeRotationVariables()
|
|
75
|
+
|
|
76
|
+
def ExecuteInitializeSolutionStep(self):
|
|
77
|
+
|
|
78
|
+
# If compute rotation center automatically is needed and if the center is moved
|
|
79
|
+
if self.compute_rotation_center and self.rotation_option == "moving_center":
|
|
80
|
+
self._ComputeCenterRotation()
|
|
81
|
+
|
|
82
|
+
# Compute delta quaternion
|
|
83
|
+
self._ComputeDeltaQuaternion(self.rotation_velocity)
|
|
84
|
+
|
|
85
|
+
self._quaternion = self._quaternion.MultiplyQuaternion(self._delta_quaternion, self._quaternion)
|
|
86
|
+
|
|
87
|
+
# Normalize quaternion
|
|
88
|
+
self._quaternion.Normalize()
|
|
89
|
+
|
|
90
|
+
# Compute rotation matrix
|
|
91
|
+
new_rotation_matrix = KratosMultiphysics.Matrix(3,3)
|
|
92
|
+
self._quaternion.ToRotationMatrix(new_rotation_matrix)
|
|
93
|
+
|
|
94
|
+
for mpc in self.model_part.Conditions:
|
|
95
|
+
# Compute current radius
|
|
96
|
+
mpc_coord = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_COORD,self.model_part.ProcessInfo)[0]
|
|
97
|
+
radius = mpc_coord - self.rotation_center
|
|
98
|
+
|
|
99
|
+
# Update impose_displacement
|
|
100
|
+
imposed_disp = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_IMPOSED_DISPLACEMENT,self.model_part.ProcessInfo)[0]
|
|
101
|
+
|
|
102
|
+
imposed_disp += new_rotation_matrix * (self._rotation_matrix.transpose() * radius) - radius
|
|
103
|
+
mpc.SetValuesOnIntegrationPoints(KratosMPM.MPC_IMPOSED_DISPLACEMENT,[imposed_disp],self.model_part.ProcessInfo)
|
|
104
|
+
|
|
105
|
+
# Update normal vector
|
|
106
|
+
normal = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_NORMAL,self.model_part.ProcessInfo)[0]
|
|
107
|
+
modified_normal = new_rotation_matrix * (self._rotation_matrix.transpose() * normal)
|
|
108
|
+
mpc.SetValuesOnIntegrationPoints(KratosMPM.MPC_NORMAL,[modified_normal],self.model_part.ProcessInfo)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
# Copy rotation matrix
|
|
112
|
+
self._rotation_matrix = new_rotation_matrix
|
|
113
|
+
|
|
114
|
+
### Protected functions
|
|
115
|
+
def _ComputeCenterRotation(self):
|
|
116
|
+
auto_rc = KratosMultiphysics.Vector(3)
|
|
117
|
+
for mpc in self.model_part.Conditions:
|
|
118
|
+
auto_rc += mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_COORD,self.model_part.ProcessInfo)[0]
|
|
119
|
+
|
|
120
|
+
auto_rc = auto_rc / self.model_part.NumberOfConditions()
|
|
121
|
+
self.rotation_center = auto_rc
|
|
122
|
+
|
|
123
|
+
def _InitializeRotationVariables(self):
|
|
124
|
+
self._quaternion = KratosMultiphysics.Quaternion()
|
|
125
|
+
self._quaternion = self._quaternion.Identity()
|
|
126
|
+
|
|
127
|
+
self._delta_quaternion = KratosMultiphysics.Quaternion()
|
|
128
|
+
self._delta_quaternion = self._delta_quaternion.Identity()
|
|
129
|
+
|
|
130
|
+
self._rotation_matrix = KratosMultiphysics.Matrix(3,3)
|
|
131
|
+
self._rotation_matrix.fill_identity()
|
|
132
|
+
|
|
133
|
+
def _ComputeDeltaQuaternion(self, rot_velocity):
|
|
134
|
+
if (not isinstance(rot_velocity, KratosMultiphysics.Vector)) and rot_velocity.Size() != 3:
|
|
135
|
+
raise Exception("expected input shall be a KratosMultiphysics.Vector object with size 3")
|
|
136
|
+
|
|
137
|
+
omega = math.sqrt(rot_velocity[0]*rot_velocity[0] + rot_velocity[1]*rot_velocity[1] + rot_velocity[2]*rot_velocity[2])
|
|
138
|
+
if omega < 1.e-12:
|
|
139
|
+
omega = 1.e-12
|
|
140
|
+
|
|
141
|
+
dt = self.model_part.ProcessInfo[KratosMultiphysics.DELTA_TIME]
|
|
142
|
+
|
|
143
|
+
self._delta_quaternion = KratosMultiphysics.Quaternion()
|
|
144
|
+
self._delta_quaternion.W = math.cos(omega * dt / 2.0)
|
|
145
|
+
self._delta_quaternion.X = math.sin(omega * dt / 2.0) * rot_velocity[0] / omega
|
|
146
|
+
self._delta_quaternion.Y = math.sin(omega * dt / 2.0) * rot_velocity[1] / omega
|
|
147
|
+
self._delta_quaternion.Z = math.sin(omega * dt / 2.0) * rot_velocity[2] / omega
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import KratosMultiphysics
|
|
2
|
+
from KratosMultiphysics.deprecation_management import DeprecationManager
|
|
3
|
+
import KratosMultiphysics.MPMApplication as KratosMPM
|
|
4
|
+
from KratosMultiphysics.MPMApplication.apply_mpm_particle_dirichlet_condition_process import ApplyMPMParticleDirichletConditionProcess
|
|
5
|
+
|
|
6
|
+
from math import sqrt
|
|
7
|
+
|
|
8
|
+
def Factory(settings, Model):
|
|
9
|
+
if(not isinstance(settings, KratosMultiphysics.Parameters)):
|
|
10
|
+
raise Exception("expected input shall be a Parameters object, encapsulating a json string")
|
|
11
|
+
return ApplyMPMCouplingInterfaceDirichletConditionProcess(Model, settings["Parameters"])
|
|
12
|
+
|
|
13
|
+
## All the processes python should be derived from "Process"
|
|
14
|
+
class ApplyMPMCouplingInterfaceDirichletConditionProcess(ApplyMPMParticleDirichletConditionProcess):
|
|
15
|
+
def __init__(self, Model, settings ):
|
|
16
|
+
|
|
17
|
+
default_parameters = KratosMultiphysics.Parameters( """
|
|
18
|
+
{
|
|
19
|
+
"model_part_name" : "PLEASE_SPECIFY_MODEL_PART_NAME",
|
|
20
|
+
"material_points_per_condition" : 0,
|
|
21
|
+
"imposition_type" : "penalty",
|
|
22
|
+
"penalty_coefficient" : 0,
|
|
23
|
+
"constrained" : "fixed",
|
|
24
|
+
"option" : "",
|
|
25
|
+
"is_equal_distributed" : false
|
|
26
|
+
} """ )
|
|
27
|
+
|
|
28
|
+
context_string = type(self).__name__
|
|
29
|
+
old_name = 'particles_per_condition'
|
|
30
|
+
new_name = 'material_points_per_condition'
|
|
31
|
+
if DeprecationManager.HasDeprecatedVariable(context_string, settings, old_name, new_name):
|
|
32
|
+
DeprecationManager.ReplaceDeprecatedVariableName(settings, old_name, new_name)
|
|
33
|
+
|
|
34
|
+
context_string = type(self).__name__
|
|
35
|
+
old_name = 'penalty_factor'
|
|
36
|
+
new_name = 'penalty_coefficient'
|
|
37
|
+
if DeprecationManager.HasDeprecatedVariable(context_string, settings, old_name, new_name):
|
|
38
|
+
DeprecationManager.ReplaceDeprecatedVariableName(settings, old_name, new_name)
|
|
39
|
+
|
|
40
|
+
settings.ValidateAndAssignDefaults(default_parameters)
|
|
41
|
+
self.model = Model
|
|
42
|
+
self.model_part_name = settings["model_part_name"].GetString()
|
|
43
|
+
|
|
44
|
+
# Initiate base class - Dirichlet condition
|
|
45
|
+
super(ApplyMPMCouplingInterfaceDirichletConditionProcess, self).__init__(Model, settings)
|
|
46
|
+
|
|
47
|
+
# Set INTERFACE flag active
|
|
48
|
+
KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, self.model_part.Conditions)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def ExecuteBeforeSolutionLoop(self):
|
|
52
|
+
# Get updated model_part
|
|
53
|
+
if (self.model_part_name.startswith('Background_Grid.')):
|
|
54
|
+
self.model_part_name = self.model_part_name.replace('Background_Grid.','')
|
|
55
|
+
mpm_material_model_part_name = "MPM_Material." + self.model_part_name
|
|
56
|
+
self.model_part = self.model[mpm_material_model_part_name]
|
|
57
|
+
|
|
58
|
+
# Create additional nodes for Lagrange dofs in case of Lagrange or Perturbed Lagranian method
|
|
59
|
+
if self.boundary_condition_type==2 or self.boundary_condition_type==3:
|
|
60
|
+
is_restarted = self.model_part.ProcessInfo[KratosMultiphysics.IS_RESTARTED]
|
|
61
|
+
if not is_restarted:
|
|
62
|
+
grid_model_part=self.model.GetModelPart("Background_Grid")
|
|
63
|
+
|
|
64
|
+
KratosMPM.GenerateLagrangeNodes(grid_model_part)
|
|
65
|
+
|
|
66
|
+
### Translate conditions with INTERFACE flag into a new model part "MPM_Coupling_Dirichlet_Interface" responsible for coupling with structure
|
|
67
|
+
# Create coupling model part
|
|
68
|
+
if not self.model.HasModelPart("MPM_Coupling_Dirichlet_Interface"):
|
|
69
|
+
self.model.CreateModelPart("MPM_Coupling_Dirichlet_Interface")
|
|
70
|
+
self.coupling_model_part = self.model.GetModelPart("MPM_Coupling_Dirichlet_Interface").CreateSubModelPart(self.model_part_name)
|
|
71
|
+
|
|
72
|
+
# Prepare coupling model part
|
|
73
|
+
self._prepare_coupling_model_part(self.coupling_model_part)
|
|
74
|
+
|
|
75
|
+
# Create nodes and fill coupling model part
|
|
76
|
+
for mpc in self.model_part.Conditions:
|
|
77
|
+
if (mpc.Is(KratosMultiphysics.INTERFACE)):
|
|
78
|
+
node_id = mpc.Id
|
|
79
|
+
node_coordinate = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_COORD, self.model_part.ProcessInfo)[0]
|
|
80
|
+
coupling_node = self.coupling_model_part.CreateNewNode(node_id, node_coordinate[0], node_coordinate[1], node_coordinate[2])
|
|
81
|
+
|
|
82
|
+
## Set Displacement and Normal
|
|
83
|
+
normal = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_NORMAL, self.model_part.ProcessInfo)[0]
|
|
84
|
+
coupling_node.SetSolutionStepValue(KratosMultiphysics.NORMAL,0,normal)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def ExecuteInitializeSolutionStep(self):
|
|
88
|
+
### Clone delta time
|
|
89
|
+
self.coupling_model_part.ProcessInfo[KratosMultiphysics.DELTA_TIME] = self.model_part.ProcessInfo[KratosMultiphysics.DELTA_TIME]
|
|
90
|
+
|
|
91
|
+
### Send displacement from coupling_mp to mp
|
|
92
|
+
for coupling_node in self.coupling_model_part.Nodes:
|
|
93
|
+
coupling_id = coupling_node.Id
|
|
94
|
+
|
|
95
|
+
## IMPOSED DISPLACEMENT
|
|
96
|
+
total_displacement = coupling_node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT,0)
|
|
97
|
+
old_displacement = self.model_part.GetCondition(coupling_id).CalculateOnIntegrationPoints(KratosMPM.MPC_DISPLACEMENT, self.model_part.ProcessInfo)[0]
|
|
98
|
+
incremental_displacement = total_displacement - old_displacement
|
|
99
|
+
self.model_part.GetCondition(coupling_id).SetValuesOnIntegrationPoints(KratosMPM.MPC_IMPOSED_DISPLACEMENT, [incremental_displacement], self.model_part.ProcessInfo)
|
|
100
|
+
|
|
101
|
+
## ADD VELOCITY
|
|
102
|
+
current_velocity = coupling_node.GetSolutionStepValue(KratosMultiphysics.VELOCITY,0)
|
|
103
|
+
self.model_part.GetCondition(coupling_id).SetValuesOnIntegrationPoints(KratosMPM.MPC_VELOCITY, [current_velocity], self.model_part.ProcessInfo)
|
|
104
|
+
|
|
105
|
+
## ADD NORMAL
|
|
106
|
+
normal = coupling_node.GetSolutionStepValue(KratosMultiphysics.NORMAL,0)
|
|
107
|
+
# Check and see whether the normal is not zero
|
|
108
|
+
norm_normal = sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2])
|
|
109
|
+
if norm_normal > 1.e-10:
|
|
110
|
+
self.model_part.GetCondition(coupling_id).SetValuesOnIntegrationPoints(KratosMPM.MPC_NORMAL, [normal], self.model_part.ProcessInfo)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def ExecuteFinalizeSolutionStep(self):
|
|
114
|
+
### Get contact force from mp to coupling_mp
|
|
115
|
+
for mpc in self.model_part.Conditions:
|
|
116
|
+
if (mpc.Is(KratosMultiphysics.INTERFACE)):
|
|
117
|
+
coupling_id = mpc.Id
|
|
118
|
+
contact_force = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_CONTACT_FORCE, self.model_part.ProcessInfo)[0]
|
|
119
|
+
self.coupling_model_part.GetNode(coupling_id).SetSolutionStepValue(KratosMultiphysics.CONTACT_FORCE,0,contact_force)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# Local functions
|
|
123
|
+
def _prepare_coupling_model_part(self, coupling_model_part):
|
|
124
|
+
# Define domain size
|
|
125
|
+
domain_size = self.model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE]
|
|
126
|
+
coupling_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] = domain_size
|
|
127
|
+
|
|
128
|
+
# Add variables
|
|
129
|
+
coupling_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.DISPLACEMENT)
|
|
130
|
+
coupling_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VELOCITY)
|
|
131
|
+
coupling_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.CONTACT_FORCE)
|
|
132
|
+
coupling_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.NORMAL)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import KratosMultiphysics
|
|
2
|
+
from KratosMultiphysics.deprecation_management import DeprecationManager
|
|
3
|
+
import KratosMultiphysics.MPMApplication as KratosMPM
|
|
4
|
+
from KratosMultiphysics.MPMApplication.apply_mpm_particle_neumann_condition_process import ApplyMPMParticleNeumannConditionProcess
|
|
5
|
+
|
|
6
|
+
def Factory(settings, Model):
|
|
7
|
+
if(not isinstance(settings, KratosMultiphysics.Parameters)):
|
|
8
|
+
raise Exception("expected input shall be a Parameters object, encapsulating a json string")
|
|
9
|
+
return ApplyMPMCouplingInterfaceNeumannConditionProcess(Model, settings["Parameters"])
|
|
10
|
+
|
|
11
|
+
## All the processes python should be derived from "Process"
|
|
12
|
+
class ApplyMPMCouplingInterfaceNeumannConditionProcess(ApplyMPMParticleNeumannConditionProcess):
|
|
13
|
+
def __init__(self, Model, settings ):
|
|
14
|
+
|
|
15
|
+
default_parameters = KratosMultiphysics.Parameters( """
|
|
16
|
+
{
|
|
17
|
+
"model_part_name" : "PLEASE_SPECIFY_MODEL_PART_NAME",
|
|
18
|
+
"material_points_per_condition" : 0,
|
|
19
|
+
"variable_name" : "POINT_LOAD",
|
|
20
|
+
"constrained" : "fixed",
|
|
21
|
+
"option" : ""
|
|
22
|
+
} """ )
|
|
23
|
+
|
|
24
|
+
context_string = type(self).__name__
|
|
25
|
+
old_name = 'particles_per_condition'
|
|
26
|
+
new_name = 'material_points_per_condition'
|
|
27
|
+
if DeprecationManager.HasDeprecatedVariable(context_string, settings, old_name, new_name):
|
|
28
|
+
DeprecationManager.ReplaceDeprecatedVariableName(settings, old_name, new_name)
|
|
29
|
+
|
|
30
|
+
settings.ValidateAndAssignDefaults(default_parameters)
|
|
31
|
+
self.model = Model
|
|
32
|
+
self.model_part_name = settings["model_part_name"].GetString()
|
|
33
|
+
|
|
34
|
+
# Initiate base class - Neumann condition
|
|
35
|
+
super(ApplyMPMCouplingInterfaceNeumannConditionProcess, self).__init__(Model, settings)
|
|
36
|
+
|
|
37
|
+
# Set INTERFACE flag active
|
|
38
|
+
KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.INTERFACE, True, self.model_part.Conditions)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def ExecuteBeforeSolutionLoop(self):
|
|
42
|
+
# Get updated model_part
|
|
43
|
+
if (self.model_part_name.startswith('Background_Grid.')):
|
|
44
|
+
self.model_part_name = self.model_part_name.replace('Background_Grid.','')
|
|
45
|
+
mpm_material_model_part_name = "MPM_Material." + self.model_part_name
|
|
46
|
+
self.model_part = self.model[mpm_material_model_part_name]
|
|
47
|
+
|
|
48
|
+
### Translate conditions with INTERFACE flag into a new model part "MPM_Coupling_Neumann_Interface" responsible for coupling
|
|
49
|
+
# Create coupling model part
|
|
50
|
+
if not self.model.HasModelPart("MPM_Coupling_Neumann_Interface"):
|
|
51
|
+
self.model.CreateModelPart("MPM_Coupling_Neumann_Interface")
|
|
52
|
+
self.coupling_model_part = self.model.GetModelPart("MPM_Coupling_Neumann_Interface").CreateSubModelPart(self.model_part_name)
|
|
53
|
+
|
|
54
|
+
# Prepare coupling model part
|
|
55
|
+
self._prepare_coupling_model_part(self.coupling_model_part)
|
|
56
|
+
|
|
57
|
+
# Create nodes and fill coupling model part
|
|
58
|
+
for mpc in self.model_part.Conditions:
|
|
59
|
+
if (mpc.Is(KratosMultiphysics.INTERFACE)):
|
|
60
|
+
node_id = mpc.Id
|
|
61
|
+
node_coordinate = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_COORD, self.model_part.ProcessInfo)[0]
|
|
62
|
+
self.coupling_model_part.CreateNewNode(node_id, node_coordinate[0], node_coordinate[1], node_coordinate[2])
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def ExecuteInitializeSolutionStep(self):
|
|
66
|
+
### Clone delta time
|
|
67
|
+
self.coupling_model_part.ProcessInfo[KratosMultiphysics.DELTA_TIME] = self.model_part.ProcessInfo[KratosMultiphysics.DELTA_TIME]
|
|
68
|
+
|
|
69
|
+
# ### Send Point Load from coupling node to condition
|
|
70
|
+
|
|
71
|
+
for coupling_node in self.coupling_model_part.Nodes:
|
|
72
|
+
coupling_id = coupling_node.Id
|
|
73
|
+
point_load = coupling_node.GetSolutionStepValue(KratosMultiphysics.CONTACT_FORCE)
|
|
74
|
+
|
|
75
|
+
self.model_part.GetCondition(coupling_id).SetValuesOnIntegrationPoints(KratosMPM.POINT_LOAD, [point_load], self.model_part.ProcessInfo)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def ExecuteFinalizeSolutionStep(self):
|
|
80
|
+
### Get kinematic variables from mp to coupling_mp
|
|
81
|
+
for mpc in self.model_part.Conditions:
|
|
82
|
+
if (mpc.Is(KratosMultiphysics.INTERFACE)):
|
|
83
|
+
coupling_id = mpc.Id
|
|
84
|
+
|
|
85
|
+
displacement = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_DISPLACEMENT, self.model_part.ProcessInfo)[0]
|
|
86
|
+
velocity = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_VELOCITY, self.model_part.ProcessInfo)[0]
|
|
87
|
+
|
|
88
|
+
self.coupling_model_part.GetNode(coupling_id).SetSolutionStepValue(KratosMultiphysics.VELOCITY,0,velocity)
|
|
89
|
+
self.coupling_model_part.GetNode(coupling_id).SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT,0,displacement)
|
|
90
|
+
|
|
91
|
+
# Local functions
|
|
92
|
+
def _prepare_coupling_model_part(self, coupling_model_part):
|
|
93
|
+
# Define domain size
|
|
94
|
+
domain_size = self.model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE]
|
|
95
|
+
coupling_model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] = domain_size
|
|
96
|
+
|
|
97
|
+
# Add variables
|
|
98
|
+
coupling_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.DISPLACEMENT)
|
|
99
|
+
coupling_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.VELOCITY)
|
|
100
|
+
coupling_model_part.AddNodalSolutionStepVariable(KratosMultiphysics.CONTACT_FORCE)
|
|
101
|
+
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import KratosMultiphysics
|
|
2
|
+
from KratosMultiphysics.deprecation_management import DeprecationManager
|
|
3
|
+
import KratosMultiphysics.MPMApplication as KratosMPM
|
|
4
|
+
|
|
5
|
+
def Factory(settings, Model):
|
|
6
|
+
if(not isinstance(settings, KratosMultiphysics.Parameters)):
|
|
7
|
+
raise Exception("expected input shall be a Parameters object, encapsulating a json string")
|
|
8
|
+
return ApplyMPMParticleDirichletConditionProcess(Model, settings["Parameters"])
|
|
9
|
+
|
|
10
|
+
## All the processes python should be derived from "Process"
|
|
11
|
+
class ApplyMPMParticleDirichletConditionProcess(KratosMultiphysics.Process):
|
|
12
|
+
def __init__(self, Model, settings ):
|
|
13
|
+
KratosMultiphysics.Process.__init__(self)
|
|
14
|
+
|
|
15
|
+
default_parameters = KratosMultiphysics.Parameters( """
|
|
16
|
+
{
|
|
17
|
+
"model_part_name" : "PLEASE_SPECIFY_MODEL_PART_NAME",
|
|
18
|
+
"material_points_per_condition" : 0,
|
|
19
|
+
"imposition_type" : "penalty",
|
|
20
|
+
"penalty_coefficient" : 0,
|
|
21
|
+
"variable_name" : "DISPLACEMENT",
|
|
22
|
+
"constrained" : "fixed",
|
|
23
|
+
"value" : [0.0, "0*t", 0.0],
|
|
24
|
+
"interval" : [0.0, 1e30],
|
|
25
|
+
"option" : "",
|
|
26
|
+
"is_equal_distributed" : false,
|
|
27
|
+
"local_axes" : {}
|
|
28
|
+
} """ )
|
|
29
|
+
|
|
30
|
+
# Assign this here since it will change the "interval" prior to validation
|
|
31
|
+
self.interval = KratosMultiphysics.IntervalUtility(settings)
|
|
32
|
+
|
|
33
|
+
context_string = type(self).__name__
|
|
34
|
+
old_name = 'particles_per_condition'
|
|
35
|
+
new_name = 'material_points_per_condition'
|
|
36
|
+
if DeprecationManager.HasDeprecatedVariable(context_string, settings, old_name, new_name):
|
|
37
|
+
DeprecationManager.ReplaceDeprecatedVariableName(settings, old_name, new_name)
|
|
38
|
+
|
|
39
|
+
context_string = type(self).__name__
|
|
40
|
+
old_name = 'penalty_factor'
|
|
41
|
+
new_name = 'penalty_coefficient'
|
|
42
|
+
if DeprecationManager.HasDeprecatedVariable(context_string, settings, old_name, new_name):
|
|
43
|
+
DeprecationManager.ReplaceDeprecatedVariableName(settings, old_name, new_name)
|
|
44
|
+
|
|
45
|
+
settings.ValidateAndAssignDefaults(default_parameters)
|
|
46
|
+
|
|
47
|
+
self.model_part = Model[settings["model_part_name"].GetString()]
|
|
48
|
+
self.model_part_name = settings["model_part_name"].GetString()
|
|
49
|
+
self.model = Model
|
|
50
|
+
self.material_points_per_condition = settings["material_points_per_condition"].GetInt()
|
|
51
|
+
self.imposition_type = settings["imposition_type"].GetString()
|
|
52
|
+
self.is_neumann_boundary = False
|
|
53
|
+
self.option = settings["option"].GetString()
|
|
54
|
+
|
|
55
|
+
#is_equal_distributed = false (material point conditions at Gauss Point Positions)
|
|
56
|
+
#is_equal_distributed = true (material point conditions equally distributed; also at nodes; only 2D)
|
|
57
|
+
self.is_equal_distributed = settings["is_equal_distributed"].GetBool()
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
Set boundary_condition_type:
|
|
61
|
+
1. penalty
|
|
62
|
+
2. Lagrange multiplier
|
|
63
|
+
3. perturbed Lagrangian (Lagrange with Penalty coefficient >0 )
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
# set type of boundary
|
|
67
|
+
if (self.imposition_type == "penalty" or self.imposition_type == "Penalty"):
|
|
68
|
+
self.boundary_condition_type = 1
|
|
69
|
+
self.penalty_coefficient = settings["penalty_coefficient"].GetDouble()
|
|
70
|
+
elif (self.imposition_type == "lagrange"):
|
|
71
|
+
self.boundary_condition_type = 2
|
|
72
|
+
self.penalty_coefficient = 0.0
|
|
73
|
+
elif (self.imposition_type == "perturbed_lagrange"):
|
|
74
|
+
self.boundary_condition_type = 3
|
|
75
|
+
self.penalty_coefficient = settings["penalty_coefficient"].GetDouble()
|
|
76
|
+
else:
|
|
77
|
+
err_msg = "The requested type of Dirichlet boundary imposition: \"" + self.imposition_type + "\" is not available!\n"
|
|
78
|
+
err_msg += "Available option is: \"penalty\", \"perturbed_lagrange\" or \"lagrange\"."
|
|
79
|
+
raise Exception(err_msg)
|
|
80
|
+
|
|
81
|
+
# check for positive Penalty coefficient
|
|
82
|
+
if self.penalty_coefficient < 0.0:
|
|
83
|
+
err_msg = '\n::[ApplyMPMParticleDirichletConditionProcess]:: W-A-R-N-I-N-G: You have specified invalid "penalty_coefficient", '
|
|
84
|
+
err_msg += 'and assigned negative values. \nPlease assign: "penalty_coefficient" > 0 or = 0!\n'
|
|
85
|
+
raise Exception(err_msg)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# check constraint
|
|
89
|
+
self.constrained = settings["constrained"].GetString()
|
|
90
|
+
self.is_slip_boundary = False
|
|
91
|
+
self.is_contact_boundary = False
|
|
92
|
+
if (self.constrained == "fixed"):
|
|
93
|
+
pass
|
|
94
|
+
elif (self.constrained == "contact"):
|
|
95
|
+
self.is_contact_boundary = True
|
|
96
|
+
elif (self.constrained == "slip"):
|
|
97
|
+
self.is_slip_boundary = True
|
|
98
|
+
elif (self.constrained == "contact_slip"):
|
|
99
|
+
self.is_contact_boundary = True
|
|
100
|
+
self.is_slip_boundary = True
|
|
101
|
+
else:
|
|
102
|
+
err_msg = "The requested type of constrain: \"" + self.constrained + "\" is not available!\n"
|
|
103
|
+
err_msg += "Available options are: \"fixed\", \"contact\" and \"slip\"."
|
|
104
|
+
raise Exception(err_msg)
|
|
105
|
+
|
|
106
|
+
# get variable imposed and check
|
|
107
|
+
variable_name = settings["variable_name"].GetString()
|
|
108
|
+
variable_name_list = ["DISPLACEMENT","VELOCITY","ACCELERATION"]
|
|
109
|
+
if(variable_name in variable_name_list):
|
|
110
|
+
self.variable = KratosMultiphysics.KratosGlobals.GetVariable(variable_name)
|
|
111
|
+
else:
|
|
112
|
+
err_msg = "The given variable \"" + variable_name + "\" is not available to be imposed with this process.\n"
|
|
113
|
+
err_msg += "Available options are: " + ", ".join(variable_name_list)
|
|
114
|
+
raise Exception(err_msg)
|
|
115
|
+
|
|
116
|
+
self.value_is_numeric = [False, False, False]
|
|
117
|
+
self.value = KratosMultiphysics.Vector(3)
|
|
118
|
+
self.aux_function = ["0.0","0.0","0.0"]
|
|
119
|
+
self.name = ["0.0","0.0","0.0"]
|
|
120
|
+
# Loop over components X, Y and Z
|
|
121
|
+
for i, variable in enumerate(["_X", "_Y", "_Z"]):
|
|
122
|
+
self.name[i] = settings["variable_name"].GetString() + variable
|
|
123
|
+
if settings["value"][i].IsNumber():
|
|
124
|
+
self.value_is_numeric[i] = True
|
|
125
|
+
self.value[i] = settings["value"][i].GetDouble()
|
|
126
|
+
else:
|
|
127
|
+
self.function_string = settings["value"][i].GetString()
|
|
128
|
+
self.aux_function[i] = KratosMultiphysics.GenericFunctionUtility(self.function_string, settings["local_axes"])
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# Compute the normal on the nodes of interest
|
|
132
|
+
KratosMultiphysics.NormalCalculationUtils().CalculateOnSimplex(self.model_part, self.model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE])
|
|
133
|
+
self.modified_normal = False
|
|
134
|
+
if self.option == "flip_normal":
|
|
135
|
+
self.modified_normal = True
|
|
136
|
+
|
|
137
|
+
# Set Flag BOUNDARY and variables MATERIAL_POINTS_PER_CONDITION
|
|
138
|
+
if self.material_points_per_condition >= 0:
|
|
139
|
+
KratosMultiphysics.VariableUtils().SetFlag(KratosMultiphysics.BOUNDARY, True, self.model_part.Nodes)
|
|
140
|
+
|
|
141
|
+
for condition in self.model_part.Conditions:
|
|
142
|
+
condition.Set(KratosMultiphysics.BOUNDARY, True)
|
|
143
|
+
condition.Set(KratosMultiphysics.SLIP, self.is_slip_boundary)
|
|
144
|
+
condition.Set(KratosMultiphysics.CONTACT, self.is_contact_boundary)
|
|
145
|
+
condition.Set(KratosMultiphysics.MODIFIED, self.modified_normal)
|
|
146
|
+
condition.SetValue(KratosMPM.MATERIAL_POINTS_PER_CONDITION, self.material_points_per_condition)
|
|
147
|
+
condition.SetValue(KratosMPM.IS_EQUAL_DISTRIBUTED, self.is_equal_distributed)
|
|
148
|
+
condition.SetValue(KratosMPM.MPC_IS_NEUMANN, self.is_neumann_boundary)
|
|
149
|
+
condition.SetValue(KratosMPM.MPC_BOUNDARY_CONDITION_TYPE, self.boundary_condition_type)
|
|
150
|
+
|
|
151
|
+
### Set necessary essential BC variables
|
|
152
|
+
if self.boundary_condition_type==1 or self.boundary_condition_type==2 or self.boundary_condition_type==3:
|
|
153
|
+
condition.SetValue(KratosMultiphysics.PENALTY_COEFFICIENT, self.penalty_coefficient)
|
|
154
|
+
else:
|
|
155
|
+
err_msg = '\n::[ApplyMPMParticleDirichletConditionProcess]:: W-A-R-N-I-N-G: You have specified invalid "material_points_per_condition", '
|
|
156
|
+
err_msg += 'or assigned negative values. \nPlease assign: "material_points_per_condition" > 0 or = 0 (for automatic value)!\n'
|
|
157
|
+
raise Exception(err_msg)
|
|
158
|
+
|
|
159
|
+
def ExecuteBeforeSolutionLoop(self):
|
|
160
|
+
""" This method is executed in before initialize the solution step
|
|
161
|
+
|
|
162
|
+
Keyword arguments:
|
|
163
|
+
self -- It signifies an instance of a class.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
# Get updated model_part
|
|
167
|
+
if (self.model_part_name.startswith('Background_Grid.')):
|
|
168
|
+
self.model_part_name = self.model_part_name.replace('Background_Grid.','')
|
|
169
|
+
mpm_material_model_part_name = "MPM_Material." + self.model_part_name
|
|
170
|
+
self.model_part = self.model[mpm_material_model_part_name]
|
|
171
|
+
|
|
172
|
+
# Create additional nodes for Lagrange dofs in case of Lagrange or Perturbed Lagranian method
|
|
173
|
+
if self.boundary_condition_type==2 or self.boundary_condition_type==3:
|
|
174
|
+
is_restarted = self.model_part.ProcessInfo[KratosMultiphysics.IS_RESTARTED]
|
|
175
|
+
if not is_restarted:
|
|
176
|
+
grid_model_part=self.model.GetModelPart("Background_Grid")
|
|
177
|
+
|
|
178
|
+
KratosMPM.GenerateLagrangeNodes(grid_model_part)
|
|
179
|
+
|
|
180
|
+
self.ExecuteInitializeSolutionStep()
|
|
181
|
+
|
|
182
|
+
def ExecuteInitializeSolutionStep(self):
|
|
183
|
+
""" This method is executed in order to initialize the current step
|
|
184
|
+
|
|
185
|
+
Keyword arguments:
|
|
186
|
+
self -- It signifies an instance of a class.
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
for mpc in self.model_part.Conditions:
|
|
190
|
+
current_time = self.model_part.ProcessInfo[KratosMultiphysics.TIME]
|
|
191
|
+
mpc_coord = mpc.CalculateOnIntegrationPoints(KratosMPM.MPC_COORD,self.model_part.ProcessInfo)[0]
|
|
192
|
+
|
|
193
|
+
if self.interval.IsInInterval(current_time):
|
|
194
|
+
|
|
195
|
+
self.step_is_active = True
|
|
196
|
+
|
|
197
|
+
# Loop over components X, Y and Z
|
|
198
|
+
for i in range(3):
|
|
199
|
+
self.variable = self.name[i]
|
|
200
|
+
if not self.value_is_numeric[i]:
|
|
201
|
+
if self.aux_function[i].DependsOnSpace() == False: #depends on time only
|
|
202
|
+
self.value[i] = self.aux_function[i].CallFunction(0.0,0.0,0.0,current_time,0.0,0.0,0.0)
|
|
203
|
+
else: #most general case - space varying function (possibly also time varying)
|
|
204
|
+
self.value[i] = self.aux_function[i].CallFunction(mpc_coord[0],mpc_coord[1],mpc_coord[2],current_time,0.0,0.0,0.0)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
mpc.SetValuesOnIntegrationPoints(KratosMPM.MPC_IMPOSED_DISPLACEMENT,[self.value],self.model_part.ProcessInfo)
|