@@ -34,7 +34,8 @@ namespace aspect
3434 {
3535 DruckerPragerParameters::DruckerPragerParameters ()
3636 : angle_internal_friction (numbers::signaling_nan<double >()),
37- cohesion (numbers::signaling_nan<double >()),
37+ angle_dilation (numbers::signaling_nan<double >()),
38+ cohesion (numbers::signaling_nan<double >()),
3839 max_yield_stress (numbers::signaling_nan<double >())
3940 {}
4041
@@ -58,6 +59,7 @@ namespace aspect
5859 {
5960 // no phases
6061 drucker_prager_parameters.angle_internal_friction = angles_internal_friction[composition];
62+ drucker_prager_parameters.angle_dilation = angles_dilation[composition];
6163 drucker_prager_parameters.cohesion = cohesions[composition];
6264 drucker_prager_parameters.max_yield_stress = max_yield_stresses[composition];
6365 }
@@ -66,6 +68,8 @@ namespace aspect
6668 // Average among phases
6769 drucker_prager_parameters.angle_internal_friction = MaterialModel::MaterialUtilities::phase_average_value (phase_function_values, n_phase_transitions_per_composition,
6870 angles_internal_friction, composition);
71+ drucker_prager_parameters.angle_dilation = MaterialModel::MaterialUtilities::phase_average_value (phase_function_values, n_phase_transitions_per_composition,
72+ angles_dilation, composition);
6973 drucker_prager_parameters.cohesion = MaterialModel::MaterialUtilities::phase_average_value (phase_function_values, n_phase_transitions_per_composition,
7074 cohesions, composition);
7175 drucker_prager_parameters.max_yield_stress = MaterialModel::MaterialUtilities::phase_average_value (phase_function_values, n_phase_transitions_per_composition,
@@ -220,6 +224,38 @@ namespace aspect
220224
221225
222226
227+ template <int dim>
228+ std::pair<double ,double >
229+ DruckerPrager<dim>::compute_dilation_terms_for_stokes_system(const DruckerPragerParameters &drucker_prager_parameters,
230+ const double non_yielding_viscosity,
231+ const double effective_strain_rate) const
232+ {
233+ const double sin_phi = std::sin (drucker_prager_parameters.angle_internal_friction );
234+ const double sin_psi = std::sin (drucker_prager_parameters.angle_dilation );
235+
236+ double alpha;
237+ double alpha_bar;
238+ if (dim == 2 )
239+ {
240+ alpha = sin_phi;
241+ alpha_bar = sin_psi;
242+ }
243+ else if (dim == 3 )
244+ {
245+ alpha = 6.0 * sin_phi / (std::sqrt (3.0 ) * (3.0 + sin_phi));
246+ alpha_bar = 6.0 * sin_psi / (std::sqrt (3.0 ) * (3.0 + sin_psi));
247+ }
248+ else
249+ AssertThrow (false ,ExcNotImplemented ());
250+
251+ const double dilation_lhs_term = alpha_bar * alpha / non_yielding_viscosity;
252+ const double dilation_rhs_term = alpha_bar * (2 . * effective_strain_rate - drucker_prager_parameters.cohesion / non_yielding_viscosity);
253+
254+ return std::make_pair (dilation_lhs_term, dilation_rhs_term);
255+ }
256+
257+
258+
223259 template <int dim>
224260 void
225261 DruckerPrager<dim>::declare_parameters (ParameterHandler &prm)
@@ -231,6 +267,13 @@ namespace aspect
231267 " those corresponding to chemical compositions. "
232268 " For a value of zero, in 2d the von Mises criterion is retrieved. "
233269 " Angles higher than 30 degrees are harder to solve numerically. Units: degrees." );
270+ prm.declare_entry (" Angles of dilation" , " 0." ,
271+ Patterns::Anything (),
272+ " List of angles of plastic dilation, $\\ psi$, for background material and compositional fields, "
273+ " for a total of N+1 values, where N is the number of all compositional fields or only "
274+ " those corresponding to chemical compositions. "
275+ " For a value of zero, the von Mises flow rule is retrieved. "
276+ " The dilation angle should never exceed the internal friction angle." );
234277 prm.declare_entry (" Cohesions" , " 1e20" ,
235278 Patterns::Anything (),
236279 " List of cohesions, $C$, for background material and compositional fields, "
@@ -290,9 +333,26 @@ namespace aspect
290333 angles_internal_friction = Utilities::MapParsing::parse_map_to_double_array (prm.get (" Angles of internal friction" ),
291334 options);
292335
336+ options.property_name = " Angles of dilation" ;
337+ angles_dilation = Utilities::MapParsing::parse_map_to_double_array (prm.get (" Angles of dilation" ),
338+ options);
339+
293340 // Convert angles from degrees to radians
294- for (double &angle : angles_internal_friction)
295- angle *= constants::degree_to_radians;
341+ for (unsigned int i = 0 ; i < angles_internal_friction.size (); ++i)
342+ {
343+ angles_internal_friction[i] *= constants::degree_to_radians;
344+ angles_dilation[i] *= constants::degree_to_radians;
345+
346+ AssertThrow (angles_dilation[i] <= angles_internal_friction[i],
347+ ExcMessage (" The dilation angle is greater than the internal friction angle for "
348+ " composition " + Utilities::to_string (i) + " ." ));
349+
350+ if (angles_dilation[i] > 0.0 )
351+ AssertThrow (this ->get_parameters ().enable_prescribed_dilation == true ,
352+ ExcMessage (" ASPECT detected a nonzero dilation angle, but dilation is "
353+ " not enabled. Please set parameter entry 'Enable prescribed "
354+ " dilation' to 'true'." ));
355+ }
296356
297357 options.property_name = " Cohesions" ;
298358 cohesions = Utilities::MapParsing::parse_map_to_double_array (prm.get (" Cohesions" ),
0 commit comments