@@ -358,7 +358,21 @@ namespace aspect
358358 MaterialModel::MaterialModelDerivatives<dim> *derivatives;
359359 derivatives = out.template get_additional_output <MaterialModel::MaterialModelDerivatives<dim> >();
360360
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 ;
361+ // When there is no simulator, we are in a test, so make sure we use the derivatives.
362+ double derivative_scaling_factor = 1 ;
363+ if (&(this ->get_simulator ()) != nullptr )
364+ {
365+ // If do not use use the Newton solver, get the derivative scaling factor,
366+ // otherwise set it to zero.
367+ if (this ->get_parameters ().nonlinear_solver == Parameters<dim>::NonlinearSolver::Newton_Stokes)
368+ {
369+ derivative_scaling_factor = this ->get_newton_handler ().get_newton_derivative_scaling_factor ();
370+ }
371+ else
372+ {
373+ derivative_scaling_factor = 0 ;
374+ }
375+ }
362376
363377
364378 // Loop through points
@@ -420,72 +434,27 @@ namespace aspect
420434 if (derivative_scaling_factor != 0 && derivatives != NULL )
421435 {
422436 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;
434437
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 ++)
438+ // For each independent component, compute the derivative.
439+ for (unsigned int independent_component_k = 0 ; independent_component_k < SymmetricTensor< 2 ,dim>::n_independent_components; independent_component_k ++)
437440 {
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- }
441+ const TableIndices<2 > indices_ij = SymmetricTensor<2 ,dim>::unrolled_to_component_indices (independent_component_k);
442+ SymmetricTensor<2 ,dim> strain_rate_component = strain_rate + std::max (std::fabs (strain_rate[indices_ij]), min_strain_rate) * finite_difference_accuracy
443+ * Utilities::symmetric_independent_component_matrix<dim>(independent_component_k);
444+ std::vector<double > eta_component = calculate_isostrain_viscosities (volume_fractions, pressure, temperature, composition, strain_rate_component,viscous_flow_law,yield_mechanism);
449445
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 )
446+ // For each composition of the independent component, compute the derivative.
447+ for (unsigned int composition_i = 0 ; composition_i < eta_component.size (); composition_i++)
478448 {
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
449+ // compute the difference between the viscosity with and without the strain-rate difference.
450+ double derivative_component = eta_component[composition_i] - composition_viscosities[composition_i];
451+ if (derivative_component != 0 )
484452 {
485- deriv_one_one = 0 ;
453+ // when the difference is non-zero, divide by the difference.
454+ derivative_component /= std::max (std::fabs (strain_rate_component[indices_ij]), min_strain_rate) * finite_difference_accuracy;
486455 }
456+ composition_viscosities_derivatives[composition_i][indices_ij] = derivative_component;
487457 }
488- composition_viscosities_derivatives[composition_i][1 ][1 ] = deriv_one_one;
489458 }
490459
491460 /* *
@@ -496,7 +465,7 @@ namespace aspect
496465 std::vector<double > pressure_difference_eta = calculate_isostrain_viscosities (volume_fractions, pressure_difference, temperature, composition, strain_rate,viscous_flow_law,yield_mechanism);
497466
498467
499- for (unsigned int composition_i = 0 ; composition_i < eta_one_one .size (); composition_i++)
468+ for (unsigned int composition_i = 0 ; composition_i < pressure_difference_eta .size (); composition_i++)
500469 {
501470 double deriv_pressure = pressure_difference_eta[composition_i] - composition_viscosities[composition_i];
502471 if (pressure_difference_eta[composition_i] != 0 )
0 commit comments