Skip to content
4 changes: 2 additions & 2 deletions include/aspect/mesh_deformation/fastscape.h
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ namespace aspect
* otherwise, the units are ${m^(1-2drainage_area_exponent)/s}$. Then a time scale factor will be applied to
* convert it into ${m^(1-2drainage_area_exponent)/yr}$ for Fastscape.
*/
double constant_bedrock_river_incision_rate;
std::vector<double> constant_bedrock_river_incision_rate;

/**
* Sediment river incision rate for the stream power law.
Expand Down Expand Up @@ -509,7 +509,7 @@ namespace aspect
* convert it into ${m^2/yr}$ for Fastscape.
* This function is only used only if use_kf_distribution_function is false.
*/
double constant_bedrock_transport_coefficient;
std::vector<double> constant_bedrock_transport_coefficient;

/**
* Sediment transport coefficient for hillslope diffusion.
Expand Down
136 changes: 100 additions & 36 deletions source/mesh_deformation/fastscape.cc
Original file line number Diff line number Diff line change
Expand Up @@ -685,8 +685,15 @@ namespace aspect
FastScape<dim>::get_aspect_values() const
{

// Get the number of chemical compositions and their names to access their erosion parameters.
const unsigned int n_chemical_composition_fields = this->introspection().get_number_of_fields_of_type(CompositionalFieldDescription::chemical_composition);
AssertThrow(n_chemical_composition_fields <= this->n_compositional_fields(),
ExcMessage("n_chemical_composition_fields exceeds n_compositional_fields."));
std::vector<std::string> compositional_field_names = this->introspection().get_composition_names();


const types::boundary_id relevant_boundary = this->get_geometry_model().translate_symbolic_boundary_name_to_id ("top");
std::vector<std::vector<double>> local_aspect_values(dim+2, std::vector<double>());
std::vector<std::vector<double>> local_aspect_values(dim+4, std::vector<double>());

// Get a quadrature rule that exists only on the corners, and increase the refinement if specified.
const QIterated<dim-1> face_corners (QTrapezoid<1>(),
Expand All @@ -710,6 +717,27 @@ namespace aspect
fe_face_values.reinit(cell, face_no);
fe_face_values[this->introspection().extractors.velocities].get_function_values(this->get_solution(), vel);

// Get compositional erosional parameters from compositional values.
std::vector<std::vector<double>> composition_values_array(this->n_compositional_fields(), std::vector<double>(fe_face_values.n_quadrature_points));
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
std::vector<double> composition_values;
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
double volume_fraction_sum = 0.0;
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
// Go through all compositions, only get the compositional values when the type is chemical composition
for (unsigned int c=0; c<this->n_compositional_fields(); ++c)
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
{
if (this->introspection().get_composition_descriptions()[c].type == CompositionalFieldDescription::chemical_composition)
{
this->introspection().extractors.compositional_fields[c];
fe_face_values[this->introspection().extractors.compositional_fields[c]].get_function_values(this->get_solution(), composition_values_array[c]);
AssertThrow(c < composition_values_array.size(),
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
ExcMessage("composition_values_array too small"));
AssertThrow(composition_values_array[c].size() > 0,
ExcMessage("composition_values_array[c] empty"));
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated

composition_values.push_back(composition_values_array[c][0]);
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
volume_fraction_sum += composition_values_array[c][0];
}
}

for (unsigned int corner = 0; corner < face_corners.size(); ++corner)
{
const Point<dim> vertex = fe_face_values.quadrature_point(corner);
Expand Down Expand Up @@ -752,6 +780,11 @@ namespace aspect
// Always convert to m/yr for FastScape
local_aspect_values[2+d].push_back(vel[corner][d]*year_in_seconds);
}

double bedrock_river_incision_rate_at_point = MaterialModel::MaterialUtilities::average_value (composition_values, constant_bedrock_river_incision_rate, MaterialModel::MaterialUtilities::arithmetic);
Comment thread
anne-glerum marked this conversation as resolved.
Outdated
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
double bedrock_transport_coefficient_at_point = MaterialModel::MaterialUtilities::average_value (composition_values, constant_bedrock_transport_coefficient, MaterialModel::MaterialUtilities::arithmetic);
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
local_aspect_values[dim+2].push_back(bedrock_river_incision_rate_at_point);
local_aspect_values[dim+3].push_back(bedrock_transport_coefficient_at_point);
}
}
// 3D case
Expand All @@ -776,6 +809,11 @@ namespace aspect
{
local_aspect_values[2+d].push_back(vel[corner][d]*year_in_seconds);
}

double bedrock_river_incision_rate_at_point = MaterialModel::MaterialUtilities::average_value (composition_values, constant_bedrock_river_incision_rate, MaterialModel::MaterialUtilities::arithmetic);
double bedrock_transport_coefficient_at_point = MaterialModel::MaterialUtilities::average_value (composition_values, constant_bedrock_transport_coefficient, MaterialModel::MaterialUtilities::arithmetic);
local_aspect_values[dim+2].push_back(bedrock_river_incision_rate_at_point);
local_aspect_values[dim+3].push_back(bedrock_transport_coefficient_at_point);
}
}
}
Expand All @@ -793,6 +831,8 @@ namespace aspect
std::vector<double> &velocity_z,
std::vector<std::vector<double>> &local_aspect_values) const
{
const double time_scaling_factor = (this->convert_output_to_years() ? 1.0 : year_in_seconds);

for (unsigned int i=0; i<local_aspect_values[1].size(); ++i)
{
// In get_aspect_values(), we store an integer value in local_aspect_values[1][...].
Expand All @@ -806,6 +846,9 @@ namespace aspect
velocity_y[index] = 0;
else
velocity_y[index] = local_aspect_values[3][i];

bedrock_river_incision_rate_array[index] = time_scaling_factor * local_aspect_values[dim+2][i];
bedrock_transport_coefficient_array[index] = time_scaling_factor * local_aspect_values[dim+3][i];
}

for (unsigned int p=1; p<Utilities::MPI::n_mpi_processes(this->get_mpi_communicator()); ++p)
Expand Down Expand Up @@ -843,14 +886,29 @@ namespace aspect
velocity_y[index] = 0;
else
velocity_y[index] = local_aspect_values[3][i];

bedrock_river_incision_rate_array[index] = time_scaling_factor * local_aspect_values[dim+2][i];
bedrock_transport_coefficient_array[index] = time_scaling_factor * local_aspect_values[dim+3][i];
}
}

bool fastscape_mesh_filled = true;

std::vector<int> global_to_local(bedrock_transport_coefficient_array.size(),-1);
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
for (unsigned int i = 0; i < local_aspect_values[1].size(); ++i)
{
const int global_index = local_aspect_values[1][i];
Assert(static_cast<std::size_t>(global_index) < global_to_local.size(),
ExcMessage("The index for filling fastscape arrays is out of bounds. This index array is constructed in get_aspect_values() and should contain values only within the bounds of the FastScape mesh. This error may be caused by an improperly set maximum_surface_refinement_level, additional_refinement_levels, and surface_refinement_difference."));
global_to_local[global_index] = i;
}
this->get_pcout() << " Updating FastScape erodibility parameters from distribution functions..." << std::endl;

// Initialize the bedrock river incision rate and transport coefficient,
// and check that there are no empty mesh points due to
// an improperly set maximum_surface_refinement_level, additional_refinement_levels,
// and surface_refinement_difference
bool fastscape_mesh_filled = true;

const unsigned int fastscape_array_size = fastscape_nx*fastscape_ny;
for (unsigned int i=0; i<fastscape_array_size; ++i)
{
Expand All @@ -862,36 +920,36 @@ namespace aspect
const double x = grid_extent[0].first + (ix - use_ghost_nodes) * fastscape_dx;
const double y = grid_extent[1].first + (iy - use_ghost_nodes) * fastscape_dy;

// Set the time scaling factor based on the unit of time, as Fastscape always
// expects units in years, not seconds. Therefore, the factor is used to scale
// the quantities when "Use years instead of seconds" in ASPECT is set to false.
// In that case the transport coefficient has units ${m^2/s}$, and the river
// incision rate units of $m^(1-2drainage_area_exponent)/s}$, so we multiply
// with a year in seconds.
Comment thread
anne-glerum marked this conversation as resolved.
const double time_scaling_factor = (this->convert_output_to_years() ? 1.0 : year_in_seconds);
// Set bedrock transport coefficient kd either from a function or a constant.
bedrock_transport_coefficient_array[i] =
(use_kd_distribution_function
?
time_scaling_factor * kd_distribution_function.value(Point<2>(x, y))
:
time_scaling_factor * constant_bedrock_transport_coefficient);
const int index = global_to_local[i];
double bedrock_river_incision_rate_local = time_scaling_factor * constant_bedrock_river_incision_rate[0];
double bedrock_transport_coefficient_local = time_scaling_factor * constant_bedrock_transport_coefficient[0];
if (index >= 0 && static_cast<std::size_t>(index) < local_aspect_values[dim+3].size())
{
bedrock_river_incision_rate_local = time_scaling_factor * local_aspect_values[dim+2][index];
bedrock_transport_coefficient_local = time_scaling_factor * local_aspect_values[dim+3][index];
}

// Set bedrock river incision rate kf either from a function or a constant.
Comment thread
Wang-yijun marked this conversation as resolved.
bedrock_river_incision_rate_array[i] =
(use_kf_distribution_function)
?
? // update with time scaling
time_scaling_factor * kf_distribution_function.value(Point<2>(x, y))
:
time_scaling_factor * constant_bedrock_river_incision_rate;

bedrock_river_incision_rate_local;
bedrock_transport_coefficient_array[i] =
(use_kd_distribution_function)
? // update with time scaling
time_scaling_factor * kd_distribution_function.value(Point<2>(x, y))
:
bedrock_transport_coefficient_local;

// If this is a boundary node that is a ghost node then ignore that it
// has not filled yet as the ghost nodes haven't been set.
Comment thread
Wang-yijun marked this conversation as resolved.
if (elevation[i] == std::numeric_limits<double>::max() && !is_ghost_node(i,false))
fastscape_mesh_filled = false;
{
fastscape_mesh_filled = false;
}
}

// If this is a boundary node that is a ghost node then ignore that it
// has not filled yet as the ghost nodes haven't been set.
fastscape_mesh_filled = Utilities::MPI::broadcast(this->get_mpi_communicator(), fastscape_mesh_filled, 0);
AssertThrow (fastscape_mesh_filled == true,
ExcMessage("The FastScape mesh is missing data. A likely cause for this is that the "
Expand Down Expand Up @@ -1844,7 +1902,7 @@ namespace aspect
"the parameter ``Bedrock river incision rate''. Units: ${m^(1-2drainage_area_exponent)/yr}$ "
"if ``Use years instead of seconds'' is true; otherwise, the units are ${m^(1-2drainage_area_exponent)/s}$.");
prm.declare_entry("Bedrock river incision rate", "1e-5",
Patterns::Double(),
Patterns::List(Patterns::Double(0.)),
"River incision rate for bedrock in the Stream Power Law. "
"Units: ${m^(1-2drainage_area_exponent)/yr}$ if ``Use years instead of seconds'' is true; "
"otherwise, the units are ${m^(1-2drainage_area_exponent)/s}$.");
Expand All @@ -1867,7 +1925,7 @@ namespace aspect
"``Bedrock diffusivity''. Units: ${m^2/yr}$ if ``Use years instead of seconds'' "
"is true; otherwise, the units are ${m^2/s}$.");
prm.declare_entry("Bedrock diffusivity", "1e-2",
Patterns::Double(),
Patterns::List(Patterns::Double(0.)),
"Transport coefficient (diffusivity) for bedrock. Units: ${m^2/yr}$ if ``Use years instead of seconds'' "
Comment thread
Wang-yijun marked this conversation as resolved.
Outdated
"is true; otherwise, the units are ${m^2/s}$.");
prm.enter_subsection ("kd distribution function");
Expand Down Expand Up @@ -1962,7 +2020,7 @@ namespace aspect
prm.declare_entry("Depth averaging thickness", "1e2",
Patterns::Double(),
"Depth averaging for the sand-silt equation. Units: ${m}$");
prm.declare_entry("Sand transport coefficient", "5e2",
prm.declare_entry("Sand transport coefficient", "2.5e2",
Patterns::Double(),
"Transport coefficient (diffusivity) for sand. Units: ${m^2/yr}$");
prm.declare_entry("Silt transport coefficient", "2.5e2",
Comment thread
anne-glerum marked this conversation as resolved.
Expand Down Expand Up @@ -2070,8 +2128,13 @@ namespace aspect
// with a year in seconds. The bedrock values are scaled when filling the FastScape
// arrays.
const double time_scaling_factor = (this->convert_output_to_years() ? 1.0 : year_in_seconds);

sediment_river_incision_rate = time_scaling_factor * prm.get_double("Sediment river incision rate");
// kf
// Make options file for parsing maps to double arrays for bedrock river incision rate and bedrock transport coefficient
std::vector<std::string> chemical_field_names = this->introspection().chemical_composition_field_names();
Comment thread
Wang-yijun marked this conversation as resolved.
Utilities::MapParsing::Options options(chemical_field_names, "Bedrock river incision rate");
options.list_of_allowed_keys = chemical_field_names;
use_kf_distribution_function = prm.get_bool("Use kf distribution function");
if (use_kf_distribution_function)
{
Expand All @@ -2083,11 +2146,14 @@ namespace aspect
// If using the function description for the kf, no parts of the code
// base should use the constant_bedrock_river_incision_rate variable. Poison it to
// make sure it really isn't used anywhere:
constant_bedrock_river_incision_rate = numbers::signaling_nan<double>();
constant_bedrock_river_incision_rate.assign(
constant_bedrock_river_incision_rate.size(),
numbers::signaling_nan<double>()
);
}
else
{
constant_bedrock_river_incision_rate = prm.get_double("Bedrock river incision rate");
constant_bedrock_river_incision_rate = Utilities::MapParsing::parse_map_to_double_array(prm.get("Bedrock river incision rate"), options);
}
sediment_transport_coefficient = time_scaling_factor * prm.get_double("Sediment diffusivity");
// kd
Expand All @@ -2102,11 +2168,15 @@ namespace aspect
// If using the function description for the kd, no parts of the code
// base should use the constant_bedrock_river_incision_rate variable. Poison it to
// make sure it really isn't used anywhere:
constant_bedrock_transport_coefficient = numbers::signaling_nan<double>();
constant_bedrock_transport_coefficient.assign(
constant_bedrock_transport_coefficient.size(),
numbers::signaling_nan<double>()
);
}
else
{
constant_bedrock_transport_coefficient = prm.get_double("Bedrock diffusivity");
options.property_name = "Bedrock diffusivity";
constant_bedrock_transport_coefficient = Utilities::MapParsing::parse_map_to_double_array(prm.get("Bedrock diffusivity"), options);
}
bedrock_deposition_g = prm.get_double("Bedrock deposition coefficient");
sediment_deposition_g = prm.get_double("Sediment deposition coefficient");
Expand Down Expand Up @@ -2168,12 +2238,6 @@ namespace aspect
sand_silt_averaging_depth = prm.get_double("Depth averaging thickness");
sand_transport_coefficient = prm.get_double("Sand transport coefficient");
silt_transport_coefficient = prm.get_double("Silt transport coefficient");

if (!this->convert_output_to_years())
{
sand_transport_coefficient *= year_in_seconds;
silt_transport_coefficient *= year_in_seconds;
}
}
Comment thread
Wang-yijun marked this conversation as resolved.
prm.leave_subsection();
}
Expand Down
Loading