diff --git a/tests/composite_viscous_outputs_isostress.cc b/tests/composite_viscous_outputs_isostress.cc
new file mode 100644
index 00000000000..d7be34de6aa
--- /dev/null
+++ b/tests/composite_viscous_outputs_isostress.cc
@@ -0,0 +1,239 @@
+/*
+ Copyright (C) 2022 - 2023 by the authors of the ASPECT code.
+
+ This file is part of ASPECT.
+
+ ASPECT is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ ASPECT is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with ASPECT; see the file LICENSE. If not see
+ .
+*/
+
+#include
+#include
+#include
+#include
+
+template
+void f(const aspect::SimulatorAccess &simulator_access,
+ aspect::Assemblers::Manager &)
+{
+ // This function tests whether the composite creep rheology is producing
+ // the correct composite viscosity and partial strain rates corresponding to
+ // the different creep mechanisms incorporated into the rheology.
+ // It is assumed that each individual creep mechanism has already been tested.
+
+ using namespace aspect::MaterialModel;
+
+ // First, we set up a few objects which are used by the rheology model.
+ aspect::ParameterHandler prm;
+
+ const std::vector list_of_composition_names = simulator_access.introspection().get_composition_names();
+ auto n_phases = std::make_unique>(1); // 1 phase per composition
+ const unsigned int composition = 0;
+ const std::vector volume_fractions = {0.6, 0.4};
+ const std::vector phase_function_values = std::vector();
+ const std::vector n_phase_transitions_per_composition = std::vector(1);
+
+ // Next, we initialise instances of the composite rheology and
+ // individual creep mechanisms.
+ std::unique_ptr> composite_creep;
+ composite_creep = std::make_unique>();
+ composite_creep->initialize_simulator (simulator_access.get_simulator());
+ composite_creep->declare_parameters(prm);
+
+ prm.set("Viscosity averaging scheme", "isostress");
+ prm.set("Include diffusion creep in composite rheology", "true");
+ prm.set("Include dislocation creep in composite rheology", "true");
+ prm.set("Include Peierls creep in composite rheology", "true");
+ prm.set("Include Drucker Prager plasticity in composite rheology", "true");
+ prm.set("Peierls creep flow law", "viscosity approximation");
+ prm.set("Maximum yield stress", "5e8");
+ composite_creep->parse_parameters(prm);
+
+ std::unique_ptr> diffusion_creep;
+ diffusion_creep = std::make_unique>();
+ diffusion_creep->initialize_simulator (simulator_access.get_simulator());
+ diffusion_creep->declare_parameters(prm);
+ diffusion_creep->parse_parameters(prm);
+
+ std::unique_ptr> dislocation_creep;
+ dislocation_creep = std::make_unique>();
+ dislocation_creep->initialize_simulator (simulator_access.get_simulator());
+ dislocation_creep->declare_parameters(prm);
+ dislocation_creep->parse_parameters(prm);
+
+ std::unique_ptr> peierls_creep;
+ peierls_creep = std::make_unique>();
+ peierls_creep->initialize_simulator (simulator_access.get_simulator());
+ peierls_creep->declare_parameters(prm);
+ peierls_creep->parse_parameters(prm);
+
+ std::unique_ptr> drucker_prager_power;
+ drucker_prager_power = std::make_unique>();
+ drucker_prager_power->initialize_simulator (simulator_access.get_simulator());
+ drucker_prager_power->declare_parameters(prm);
+ prm.set("Maximum yield stress", "5e8");
+ drucker_prager_power->parse_parameters(prm);
+ Rheology::DruckerPragerParameters p = drucker_prager_power->compute_drucker_prager_parameters(composition, phase_function_values, n_phase_transitions_per_composition);
+
+ // The creep components are arranged in series with each other.
+ // This package of components is then arranged in parallel with
+ // a strain rate limiter with a constant viscosity lim_visc.
+ // The whole system is then arranged in series with a viscosity limiter with
+ // viscosity max_visc.
+ // lim_visc is equal to (min_visc*max_visc)/(max_visc - min_visc)
+ double min_visc = prm.get_double("Minimum viscosity");
+ double max_visc = prm.get_double("Maximum viscosity");
+ double lim_visc = (min_visc*max_visc)/(max_visc - min_visc);
+
+ // Assign values to the variables which will be passed to compute_viscosity
+ // The test involves pure shear calculations at 1 GPa and variable temperature
+ double temperature;
+ const double pressure = 1.e9;
+ const double grain_size = 1.e-3;
+ SymmetricTensor<2,dim> strain_rate;
+ strain_rate[0][0] = -1e-11;
+ strain_rate[0][1] = 0.;
+ strain_rate[1][1] = 1e-11;
+ strain_rate[2][0] = 0.;
+ strain_rate[2][1] = 0.;
+ strain_rate[2][2] = 0.;
+
+ std::cout << "temperature (K) eta (Pas) creep stress (Pa) edot_ii (/s) edot_ii fractions (diff, disl, prls, drpr, max)" << std::endl;
+
+ // Loop through strain rates, tracking whether there is a discrepancy in
+ // the decomposed strain rates.
+ bool error = false;
+ double viscosity;
+ double total_strain_rate;
+ double creep_strain_rate;
+ double creep_stress;
+ double diff_stress;
+ double disl_stress;
+ double prls_stress;
+ double drpr_stress;
+ std::vector partial_strain_rates(5, 0.);
+
+ for (unsigned int i=0; i <= 10; i++)
+ {
+ temperature = 1000. + i*100.;
+
+ // Compute the viscosity
+ viscosity = composite_creep->compute_isostress_viscosity(pressure, temperature, grain_size, volume_fractions, strain_rate, partial_strain_rates);
+ total_strain_rate = std::accumulate(partial_strain_rates.begin(), partial_strain_rates.end(), 0.);
+
+ // The creep strain rate is calculated by subtracting the strain rate
+ // of the max viscosity dashpot from the total strain rate
+ // The creep stress is then calculated by subtracting the stress running
+ // through the strain rate limiter from the total stress
+ creep_strain_rate = total_strain_rate - partial_strain_rates[4];
+ creep_stress = 2.*(viscosity*total_strain_rate - lim_visc*creep_strain_rate);
+
+ // Print the output
+ std::cout << temperature << ' ' << viscosity << ' ' << creep_stress << ' ' << total_strain_rate;
+ for (unsigned int i=0; i < partial_strain_rates.size(); ++i)
+ {
+ std::cout << ' ' << partial_strain_rates[i]/total_strain_rate;
+ }
+ std::cout << std::endl;
+
+ // The following lines test that each individual creep mechanism
+ // experiences the same creep stress
+
+ // Each creep mechanism should experience the same stress
+ diff_stress = 2.*partial_strain_rates[0]*diffusion_creep->compute_viscosity(pressure, temperature, grain_size, composition);
+ disl_stress = 2.*partial_strain_rates[1]*dislocation_creep->compute_viscosity(partial_strain_rates[1], pressure, temperature, composition);
+ prls_stress = 2.*partial_strain_rates[2]*peierls_creep->compute_viscosity(partial_strain_rates[2], pressure, temperature, composition);
+ if (partial_strain_rates[3] > 0.)
+ {
+ drpr_stress = 2.*partial_strain_rates[3]*drucker_prager_power->compute_viscosity(p.cohesion,
+ p.angle_internal_friction,
+ pressure,
+ partial_strain_rates[3],
+ p.max_yield_stress);
+ }
+ else
+ {
+ drpr_stress = creep_stress;
+ }
+
+ if ((std::fabs((diff_stress - creep_stress)/creep_stress) > 1e-6)
+ || (std::fabs((disl_stress - creep_stress)/creep_stress) > 1e-6)
+ || (std::fabs((prls_stress - creep_stress)/creep_stress) > 1e-6)
+ || (std::fabs((drpr_stress - creep_stress)/creep_stress) > 1e-6))
+ {
+ error = true;
+ std::cout << " creep stress: " << creep_stress;
+ std::cout << " diffusion stress: " << diff_stress;
+ std::cout << " dislocation stress: " << disl_stress;
+ std::cout << " peierls stress: " << prls_stress;
+ std::cout << " drucker prager stress: " << drpr_stress << std::endl;
+ }
+ }
+
+ if (error)
+ {
+ std::cout << " Error: The individual creep stresses differ by more than the required tolerance." << std::endl;
+ std::cout << "Some parts of the test were not successful." << std::endl;
+ }
+ else
+ {
+ std::cout << "OK" << std::endl;
+ }
+
+}
+
+template <>
+void f(const aspect::SimulatorAccess<2> &,
+ aspect::Assemblers::Manager<2> &)
+{
+ AssertThrow(false,dealii::ExcInternalError());
+}
+
+template
+void signal_connector (aspect::SimulatorSignals &signals)
+{
+ using namespace dealii;
+ std::cout << "* Connecting signals" << std::endl;
+ signals.set_assemblers.connect (std::bind(&f,
+ std::placeholders::_1,
+ std::placeholders::_2));
+}
+
+
+using namespace aspect;
+
+
+void declare_parameters(const unsigned int dim,
+ ParameterHandler &prm)
+{
+ prm.enter_subsection("Compositional fields");
+ {
+ prm.declare_entry("Number of fields","1", Patterns::Integer());
+ }
+ prm.leave_subsection();
+}
+
+
+
+void parameter_connector ()
+{
+ SimulatorSignals<2>::declare_additional_parameters.connect (&declare_parameters);
+ SimulatorSignals<3>::declare_additional_parameters.connect (&declare_parameters);
+}
+
+
+
+ASPECT_REGISTER_SIGNALS_CONNECTOR(signal_connector<2>,
+ signal_connector<3>)
+ASPECT_REGISTER_SIGNALS_PARAMETER_CONNECTOR(parameter_connector)
diff --git a/tests/composite_viscous_outputs_isostress.prm b/tests/composite_viscous_outputs_isostress.prm
new file mode 100644
index 00000000000..bc3f9c01c5e
--- /dev/null
+++ b/tests/composite_viscous_outputs_isostress.prm
@@ -0,0 +1,80 @@
+# This test checks whether the composite viscous rheology
+# plugin produces the correct composite viscosity and
+# decomposed strain rates.
+
+set Additional shared libraries = tests/libcomposite_viscous_outputs_isostress.so
+set Dimension = 3
+set End time = 0
+set Use years in output instead of seconds = true
+set Nonlinear solver scheme = no Advection, no Stokes
+
+# Model geometry (100x100 km, 10 km spacing)
+subsection Geometry model
+ set Model name = box
+
+ subsection Box
+ set X repetitions = 10
+ set Y repetitions = 10
+ set X extent = 100e3
+ set Y extent = 100e3
+ end
+end
+
+# Mesh refinement specifications
+subsection Mesh refinement
+ set Initial adaptive refinement = 0
+ set Initial global refinement = 0
+ set Time steps between mesh refinement = 0
+end
+
+# Boundary classifications (fixed T boundaries, prescribed velocity)
+
+# Temperature boundary and initial conditions
+subsection Boundary temperature model
+ set Fixed temperature boundary indicators = bottom, top, left, right
+ set List of model names = box
+
+ subsection Box
+ set Bottom temperature = 273
+ set Left temperature = 273
+ set Right temperature = 273
+ set Top temperature = 273
+ end
+end
+
+# Velocity on boundaries characterized by functions
+subsection Boundary velocity model
+ set Prescribed velocity boundary indicators = bottom y: function, top y: function, left x: function, right x: function
+
+ subsection Function
+ set Variable names = x,y,z
+ set Function constants = m=0.0005, year=1
+ set Function expression = if (x<50e3 , -1*m/year, 1*m/year); if (y<50e3 , 1*m/year, -1*m/year);0
+ end
+end
+
+subsection Initial temperature model
+ set Model name = function
+
+ subsection Function
+ set Function expression = 273
+ end
+end
+
+# Material model
+subsection Material model
+ set Model name = visco plastic
+
+ subsection Visco Plastic
+ set Angles of internal friction = 30.
+ end
+end
+
+# Gravity model
+subsection Gravity model
+ set Model name = vertical
+
+ subsection Vertical
+ set Magnitude = 10.0
+ end
+end
diff --git a/tests/composite_viscous_outputs_isostress/screen-output b/tests/composite_viscous_outputs_isostress/screen-output
new file mode 100644
index 00000000000..545da023131
--- /dev/null
+++ b/tests/composite_viscous_outputs_isostress/screen-output
@@ -0,0 +1,28 @@
+
+Loading shared library <./libcomposite_viscous_outputs_isostress.debug.so>
+
+* Connecting signals
+temperature (K) eta (Pas) creep stress (Pa) edot_ii (/s) edot_ii fractions (diff, disl, prls, drpr, max)
+1000 3.45602e+19 6.89205e+08 1e-11 1.29846e-06 0.00363514 0.0654305 0.930933 3.45602e-09
+1100 2.98863e+19 5.95725e+08 1e-11 7.23285e-05 0.835897 0.163395 0.0006365 2.98863e-09
+1200 7.70568e+18 1.52114e+08 1e-11 0.000594407 0.999399 6.44893e-06 1.44515e-33 7.70568e-10
+1300 2.39282e+18 4.58564e+07 1e-11 0.00338081 0.996619 3.19443e-09 1.32277e-59 2.39282e-10
+1400 9.18168e+17 1.63634e+07 1e-11 0.0149609 0.985039 1.26589e-11 5.56077e-82 9.18169e-11
+1500 4.32083e+17 6.64167e+06 1e-11 0.0538305 0.94617 2.09885e-13 1.4634e-101 4.32084e-11
+1600 2.47246e+17 2.94493e+06 1e-11 0.161077 0.838923 8.74429e-15 3.2006e-119 2.47246e-11
+1700 1.67379e+17 1.34758e+06 1e-11 0.397345 0.602655 5.42942e-16 3.38184e-136 1.67378e-11
+1800 1.28447e+17 568948 1e-11 0.749975 0.250025 2.2682e-17 6.38432e-155 1.28447e-11
+1900 1.09563e+17 191256 1e-11 0.962698 0.0373021 2.59166e-19 1.35594e-178 1.09563e-11
+2000 1.02964e+17 59280.1 1e-11 0.99654 0.00345962 2.26225e-21 4.97674e-204 1.02965e-11
+OK
+Number of active cells: 100 (on 1 levels)
+Number of degrees of freedom: 6,857 (3,969+242+1,323+1,323)
+
+*** Timestep 0: t=0 years, dt=0 years
+
+ Postprocessing:
+
+Termination requested by criterion: end time
+
+
+