Skip to content

Commit 8793a39

Browse files
committed
Add derivatives to visco-plastic material model
1 parent 198ac85 commit 8793a39

File tree

1 file changed

+140
-4
lines changed

1 file changed

+140
-4
lines changed

source/material_model/visco_plastic.cc

Lines changed: 140 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <aspect/utilities.h>
2323
#include <deal.II/fe/fe_values.h>
2424
#include <deal.II/base/signaling_nan.h>
25+
#include <aspect/newton.h>
2526

2627
namespace aspect
2728
{
@@ -182,7 +183,7 @@ namespace aspect
182183
// The first time this function is called (first iteration of first time step)
183184
// a specified "reference" strain rate is used as the returned value would
184185
// otherwise be zero.
185-
const double edot_ii = ( (this->get_timestep_number() == 0 && strain_rate.norm() <= std::numeric_limits<double>::min())
186+
const double edot_ii = ( (&(this->get_simulator()) != nullptr && this->get_timestep_number() == 0 && strain_rate.norm() <= std::numeric_limits<double>::min())
186187
?
187188
ref_strain_rate
188189
:
@@ -353,13 +354,21 @@ namespace aspect
353354
evaluate(const MaterialModel::MaterialModelInputs<dim> &in,
354355
MaterialModel::MaterialModelOutputs<dim> &out) const
355356
{
357+
// set up additional output for the derivatives
358+
MaterialModel::MaterialModelDerivatives<dim> *derivatives;
359+
derivatives = out.template get_additional_output<MaterialModel::MaterialModelDerivatives<dim> >();
360+
361+
const double derivative_scaling_factor = &(this->get_simulator()) != nullptr ? (this->get_parameters().nonlinear_solver == Parameters<dim>::NonlinearSolver::Newton_Stokes ? this->get_newton_handler().get_newton_derivative_scaling_factor() : 0) : 1;
362+
363+
356364
// Loop through points
357365
for (unsigned int i=0; i < in.temperature.size(); ++i)
358366
{
359367
const double temperature = in.temperature[i];
360368
const double pressure = in.pressure[i];
361369
const std::vector<double> &composition = in.composition[i];
362370
const std::vector<double> volume_fractions = compute_volume_fractions(composition);
371+
const SymmetricTensor<2,dim> strain_rate = in.strain_rate[i];
363372

364373
// Averaging composition-field dependent properties
365374

@@ -396,14 +405,127 @@ namespace aspect
396405
// TODO: This is only consistent with viscosity averaging if the arithmetic averaging
397406
// scheme is chosen. It would be useful to have a function to calculate isostress viscosities.
398407
const std::vector<double> composition_viscosities =
399-
calculate_isostrain_viscosities(volume_fractions, pressure, temperature, composition, in.strain_rate[i],viscous_flow_law,yield_mechanism);
408+
calculate_isostrain_viscosities(volume_fractions, pressure, temperature, composition, strain_rate,viscous_flow_law,yield_mechanism);
409+
410+
std::vector<SymmetricTensor<2,dim> > composition_viscosities_derivatives(volume_fractions.size());
411+
std::vector<double> composition_dviscosities_dpressure(volume_fractions.size());
400412

401413
// The isostrain condition implies that the viscosity averaging should be arithmetic (see above).
402414
// We have given the user freedom to apply alternative bounds, because in diffusion-dominated
403415
// creep (where n_diff=1) viscosities are stress and strain-rate independent, so the calculation
404416
// of compositional field viscosities is consistent with any averaging scheme.
405417
out.viscosities[i] = average_value(composition, composition_viscosities, viscosity_averaging);
406418

419+
// compute derivatives if nessesary
420+
if (derivative_scaling_factor != 0 && derivatives != NULL)
421+
{
422+
const double finite_difference_accuracy = 1e-7;
423+
SymmetricTensor<2,dim> zerozero = SymmetricTensor<2,dim>();
424+
SymmetricTensor<2,dim> onezero = SymmetricTensor<2,dim>();
425+
SymmetricTensor<2,dim> oneone = SymmetricTensor<2,dim>();
426+
427+
zerozero[0][0] = 1;
428+
onezero[1][0] = 0.5; // because symmetry doubles this entry
429+
oneone[1][1] = 1;
430+
431+
SymmetricTensor<2,dim> strain_rate_zero_zero = strain_rate + std::fabs(strain_rate[0][0]) * finite_difference_accuracy * zerozero;
432+
SymmetricTensor<2,dim> strain_rate_one_zero = strain_rate + std::fabs(strain_rate[1][0]) * finite_difference_accuracy * onezero;
433+
SymmetricTensor<2,dim> strain_rate_one_one = strain_rate + std::fabs(strain_rate[1][1]) * finite_difference_accuracy * oneone;
434+
435+
std::vector<double> eta_zero_zero = calculate_isostrain_viscosities(volume_fractions, pressure, temperature, composition, strain_rate_zero_zero,viscous_flow_law,yield_mechanism);
436+
for (unsigned int composition_i = 0; composition_i < eta_zero_zero.size(); composition_i++)
437+
{
438+
double deriv_zero_zero = eta_zero_zero[composition_i] - composition_viscosities[composition_i];
439+
if (deriv_zero_zero != 0)
440+
{
441+
if (strain_rate_zero_zero[0][0] != 0)
442+
{
443+
deriv_zero_zero /= std::fabs(strain_rate_zero_zero[0][0]) * finite_difference_accuracy;
444+
}
445+
else
446+
{
447+
deriv_zero_zero = 0;
448+
}
449+
450+
}
451+
composition_viscosities_derivatives[composition_i][0][0] = deriv_zero_zero;
452+
}
453+
454+
455+
std::vector<double> eta_one_zero = calculate_isostrain_viscosities(volume_fractions, pressure, temperature, composition, strain_rate_one_zero,viscous_flow_law,yield_mechanism);
456+
for (unsigned int composition_i = 0; composition_i < eta_zero_zero.size(); composition_i++)
457+
{
458+
double deriv_one_zero = eta_one_zero[composition_i] - composition_viscosities[composition_i];
459+
if (deriv_one_zero != 0)
460+
{
461+
if (strain_rate_one_zero[1][0] != 0)
462+
{
463+
deriv_one_zero /= std::fabs(strain_rate_one_zero[1][0]) * finite_difference_accuracy;
464+
}
465+
else
466+
{
467+
deriv_one_zero = 0;
468+
}
469+
}
470+
composition_viscosities_derivatives[composition_i][1][0] = deriv_one_zero;
471+
}
472+
473+
std::vector<double> eta_one_one = calculate_isostrain_viscosities(volume_fractions, pressure, temperature, composition, strain_rate_one_one,viscous_flow_law,yield_mechanism);
474+
for (unsigned int composition_i = 0; composition_i < eta_one_one.size(); composition_i++)
475+
{
476+
double deriv_one_one = eta_one_one[composition_i] - composition_viscosities[composition_i];
477+
if (deriv_one_one != 0)
478+
{
479+
if (strain_rate_one_one[1][1] != 0)
480+
{
481+
deriv_one_one /= std::fabs(strain_rate_one_one[1][1]) * finite_difference_accuracy;
482+
}
483+
else
484+
{
485+
deriv_one_one = 0;
486+
}
487+
}
488+
composition_viscosities_derivatives[composition_i][1][1] = deriv_one_one;
489+
}
490+
491+
/**
492+
* Now compute the derivative of the viscoisty to the pressure
493+
*/
494+
double pressure_difference = in.pressure[i] + (std::fabs(in.pressure[i]) * finite_difference_accuracy);
495+
496+
std::vector<double> pressure_difference_eta = calculate_isostrain_viscosities(volume_fractions, pressure_difference, temperature, composition, strain_rate,viscous_flow_law,yield_mechanism);
497+
498+
499+
for (unsigned int composition_i = 0; composition_i < eta_one_one.size(); composition_i++)
500+
{
501+
double deriv_pressure = pressure_difference_eta[composition_i] - composition_viscosities[composition_i];
502+
if (pressure_difference_eta[composition_i] != 0)
503+
{
504+
if (in.pressure[i] != 0)
505+
{
506+
deriv_pressure /= std::fabs(in.pressure[i]) * finite_difference_accuracy;
507+
}
508+
else
509+
{
510+
deriv_pressure = 0;
511+
}
512+
}
513+
composition_dviscosities_dpressure[composition_i] = deriv_pressure;
514+
}
515+
516+
double viscosity_averaging_p = 0; // Geometric
517+
if (viscosity_averaging == harmonic)
518+
viscosity_averaging_p = -1;
519+
if (viscosity_averaging == arithmetic)
520+
viscosity_averaging_p = 1;
521+
if (viscosity_averaging == maximum_composition)
522+
viscosity_averaging_p = 1000;
523+
524+
525+
derivatives->viscosity_derivative_wrt_strain_rate[i] = Utilities::derivative_of_weighted_p_norm_average(out.viscosities[i],volume_fractions, composition_viscosities, composition_viscosities_derivatives, viscosity_averaging_p);
526+
derivatives->viscosity_derivative_wrt_pressure[i] = Utilities::derivative_of_weighted_p_norm_average(out.viscosities[i],volume_fractions, composition_viscosities, composition_dviscosities_dpressure, viscosity_averaging_p);
527+
528+
}
407529
}
408530

409531
out.densities[i] = density;
@@ -431,7 +553,7 @@ namespace aspect
431553
double e_ii = 0.;
432554
if (use_strain_weakening == true && use_finite_strain_tensor == false && this->get_timestep_number() > 0)
433555
{
434-
edot_ii = std::max(sqrt(std::fabs(second_invariant(deviator(in.strain_rate[i])))),min_strain_rate);
556+
edot_ii = std::max(sqrt(std::fabs(second_invariant(deviator(strain_rate)))),min_strain_rate);
435557
e_ii = edot_ii*this->get_timestep();
436558
// Update reaction term
437559
out.reaction_terms[i][0] = e_ii;
@@ -543,6 +665,14 @@ namespace aspect
543665
void
544666
ViscoPlastic<dim>::declare_parameters (ParameterHandler &prm)
545667
{
668+
prm.enter_subsection("Compositional fields");
669+
{
670+
prm.declare_entry ("Number of fields", "0",
671+
Patterns::Integer (0),
672+
"The number of fields that will be advected along with the flow field, excluding "
673+
"velocity, pressure and temperature.");
674+
}
675+
prm.leave_subsection();
546676
prm.enter_subsection("Material model");
547677
{
548678
prm.enter_subsection ("Visco Plastic");
@@ -728,7 +858,13 @@ namespace aspect
728858
ViscoPlastic<dim>::parse_parameters (ParameterHandler &prm)
729859
{
730860
// increment by one for background:
731-
const unsigned int n_fields = this->n_compositional_fields() + 1;
861+
unsigned int n_fields = 0;
862+
prm.enter_subsection("Compositional fields");
863+
{
864+
n_fields = prm.get_integer("Number of fields")+1;//this->n_compositional_fields() + 1;
865+
}
866+
prm.leave_subsection();
867+
732868

733869
// number of required compositional fields for full finite strain tensor
734870
const unsigned int s = Tensor<2,dim>::n_independent_components;

0 commit comments

Comments
 (0)