Skip to content

Commit 198ac85

Browse files
authored
Merge pull request geodynamics#1765 from jdannberg/melt_free_surface
Make melt models work with free surface
2 parents a2457f5 + 3ff1860 commit 198ac85

File tree

18 files changed

+1207
-7
lines changed

18 files changed

+1207
-7
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
New: Aspect now supports using the free surface in models with
2+
melt migration, and with all nonlinear solver schemes.
3+
<br>
4+
(Juliane Dannberg, 2018/01/30)

include/aspect/melt.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,15 @@ namespace aspect
326326
*/
327327
bool is_porosity (const typename Simulator<dim>::AdvectionField &advection_field) const;
328328

329+
/**
330+
* Apply free surface stabilization to a cell of the system matrix when melt
331+
* transport is used in the computation. Called during assembly of the system matrix.
332+
*/
333+
void apply_free_surface_stabilization_with_melt (const double free_surface_theta,
334+
const typename DoFHandler<dim>::active_cell_iterator &cell,
335+
internal::Assembly::Scratch::StokesSystem<dim> &scratch,
336+
internal::Assembly::CopyData::StokesSystem<dim> &data) const;
337+
329338
/**
330339
* The porosity limit for melt migration. For smaller porosities, the equations
331340
* reduce to the Stokes equations and neglect melt transport. In practice, this

source/simulator/assembly.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,9 @@ namespace aspect
237237
{
238238
melt_handler->set_assemblers(*assemblers);
239239

240-
AssertThrow (parameters.free_surface_enabled == false,
241-
ExcMessage("The melt implementation does not support free surface computations."));
240+
// Let the free surface add its assembler:
241+
if (parameters.free_surface_enabled)
242+
free_surface->set_assemblers();
242243
}
243244
else if (!parameters.include_melt_transport
244245
&& assemble_newton_stokes_system)
@@ -437,9 +438,9 @@ namespace aspect
437438

438439
/* The stabilization term for the free surface (Kaus et. al., 2010)
439440
* makes changes to the system matrix which are of the same form as
440-
* boundary stresses. If these stresses are not also added to the
441-
* system_preconditioner_matrix, then if fails to be very good as a
442-
* preconditioner. Instead, we just pass the system_matrix to the
441+
* boundary stresses. If these stresses are not also added to the
442+
* system_preconditioner_matrix, then it fails to be very good as a
443+
* preconditioner. Instead, we just pass the system_matrix to the
443444
* AMG precondition initialization so that it builds the preconditioner
444445
* directly from that. However, we still need the mass matrix for the
445446
* pressure block which is assembled in the preconditioner matrix.

source/simulator/core.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,6 @@ namespace aspect
548548
AssertThrow( !parameters.use_discontinuous_temperature_discretization &&
549549
!parameters.use_discontinuous_composition_discretization,
550550
ExcMessage("Melt transport can not be used with discontinuous elements.") );
551-
AssertThrow( !parameters.free_surface_enabled,
552-
ExcMessage("Melt transport together with a free surface has not been tested.") );
553551
melt_handler->initialize_simulator (*this);
554552
}
555553

source/simulator/free_surface.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <aspect/simulator.h>
2323
#include <aspect/free_surface.h>
2424
#include <aspect/global.h>
25+
#include <aspect/simulator/assemblers/interface.h>
26+
#include <aspect/melt.h>
2527

2628
#include <deal.II/dofs/dof_renumbering.h>
2729
#include <deal.II/dofs/dof_accessor.h>
@@ -52,6 +54,15 @@ namespace aspect
5254
if (!this->get_parameters().free_surface_enabled)
5355
return;
5456

57+
if (this->get_parameters().include_melt_transport)
58+
{
59+
this->get_melt_handler().apply_free_surface_stabilization_with_melt (this->get_free_surface_handler().get_stabilization_term(),
60+
scratch.cell,
61+
scratch,
62+
data);
63+
return;
64+
}
65+
5566
const Introspection<dim> &introspection = this->introspection();
5667
const FiniteElement<dim> &fe = this->get_fe();
5768

source/simulator/melt.cc

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,9 @@ namespace aspect
475475
internal::Assembly::Scratch::StokesSystem<dim> &scratch = dynamic_cast<internal::Assembly::Scratch::StokesSystem<dim>& > (scratch_base);
476476
internal::Assembly::CopyData::StokesSystem<dim> &data = dynamic_cast<internal::Assembly::CopyData::StokesSystem<dim>& > (data_base);
477477

478+
const types::boundary_id boundary_indicator
479+
= scratch.cell->face(scratch.face_number)->boundary_id();
480+
478481
const Introspection<dim> &introspection = this->introspection();
479482
const FiniteElement<dim> &fe = this->get_fe();
480483

@@ -1396,6 +1399,88 @@ namespace aspect
13961399
std_cxx11::shared_ptr<MaterialModel::AdditionalMaterialOutputs<dim> >
13971400
(new MaterialModel::MeltOutputs<dim> (n_points, n_comp)));
13981401
}
1402+
1403+
1404+
template <int dim>
1405+
void
1406+
MeltHandler<dim>::
1407+
apply_free_surface_stabilization_with_melt (const double free_surface_theta,
1408+
const typename DoFHandler<dim>::active_cell_iterator &cell,
1409+
internal::Assembly::Scratch::StokesSystem<dim> &scratch,
1410+
internal::Assembly::CopyData::StokesSystem<dim> &data) const
1411+
{
1412+
if (!this->get_parameters().free_surface_enabled)
1413+
return;
1414+
1415+
const unsigned int n_face_q_points = scratch.face_finite_element_values.n_quadrature_points;
1416+
const unsigned int stokes_dofs_per_cell = data.local_dof_indices.size();
1417+
1418+
// only apply on free surface faces
1419+
if (cell->at_boundary() && cell->is_locally_owned())
1420+
for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell; ++face_no)
1421+
if (cell->face(face_no)->at_boundary())
1422+
{
1423+
const types::boundary_id boundary_indicator
1424+
= cell->face(face_no)->boundary_id();
1425+
1426+
if (this->get_parameters().free_surface_boundary_indicators.find(boundary_indicator)
1427+
== this->get_parameters().free_surface_boundary_indicators.end())
1428+
continue;
1429+
1430+
scratch.face_finite_element_values.reinit(cell, face_no);
1431+
1432+
this->compute_material_model_input_values (this->get_solution(),
1433+
scratch.face_finite_element_values,
1434+
cell,
1435+
true,
1436+
scratch.face_material_model_inputs);
1437+
1438+
this->get_material_model().evaluate(scratch.face_material_model_inputs, scratch.face_material_model_outputs);
1439+
1440+
const unsigned int p_f_component_index = this->introspection().variable("fluid pressure").first_component_index;
1441+
const unsigned int p_c_component_index = this->introspection().variable("compaction pressure").first_component_index;
1442+
1443+
for (unsigned int q_point = 0; q_point < n_face_q_points; ++q_point)
1444+
{
1445+
for (unsigned int i = 0, i_stokes = 0; i_stokes < stokes_dofs_per_cell; /*increment at end of loop*/)
1446+
{
1447+
const unsigned int component_index_i = this->get_fe().system_to_component_index(i).first;
1448+
1449+
if (Assemblers::is_velocity_or_pressures(this->introspection(),p_c_component_index,p_f_component_index,component_index_i))
1450+
{
1451+
scratch.phi_u[i_stokes] = scratch.face_finite_element_values[this->introspection().extractors.velocities].value(i, q_point);
1452+
++i_stokes;
1453+
}
1454+
++i;
1455+
}
1456+
1457+
const Tensor<1,dim>
1458+
gravity = this->get_gravity_model().gravity_vector(scratch.face_finite_element_values.quadrature_point(q_point));
1459+
const double g_norm = gravity.norm();
1460+
1461+
// construct the relevant vectors
1462+
const Tensor<1,dim> n_hat = scratch.face_finite_element_values.normal_vector(q_point);
1463+
const Tensor<1,dim> g_hat = (g_norm == 0.0 ? Tensor<1,dim>() : gravity/g_norm);
1464+
1465+
const double pressure_perturbation = scratch.face_material_model_outputs.densities[q_point] *
1466+
this->get_timestep() * free_surface_theta * g_norm;
1467+
1468+
// see Kaus et al 2010 for details of the stabilization term
1469+
for (unsigned int i=0; i< stokes_dofs_per_cell; ++i)
1470+
for (unsigned int j=0; j< stokes_dofs_per_cell; ++j)
1471+
{
1472+
// The fictive stabilization stress is (phi_u[i].g)*(phi_u[j].n)
1473+
const double stress_value = - pressure_perturbation
1474+
* (scratch.phi_u[i] * g_hat) * (scratch.phi_u[j] * n_hat)
1475+
* scratch.face_finite_element_values.JxW(q_point);
1476+
1477+
data.local_matrix(i,j) += stress_value;
1478+
}
1479+
}
1480+
}
1481+
1482+
1483+
}
13991484
}
14001485

14011486

0 commit comments

Comments
 (0)