@@ -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