Dear all,
I would be most grateful for your help on the following matter. I am
solving a combined stokes-laplace problem (have a vector valued solution).
I am trying to calculate the hdiv norm on the first two components of my
solution (i.e. the two components of the velocity), cellwise. The
implementation of my combined problem is from tutorial 46. The
integrate_difference is from tutorial 20 since I needed the mask for the
velocity components. However, I get an error saying 'no matching function
for the call to integrate difference'. Admittedly, the version of the
function i am using (i.e. with the component mask as the last included
argument) is not in vector_tools.h which is where all the other versions
of the integrate_differnce are I think. I include the file for your
consideration. I would be most grateful for your input. For succesful
implementations of this version of integrate_difference please refer to
tutorials 20, 55 and 56.
Kind regards,
Georgios
--
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see
https://groups.google.com/d/forum/dealii?hl=en
---
You received this message because you are subscribed to the Google Groups
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
/* ---------------------------------------------------------------------
*
* Copyright (C) 2011 - 2015 by the deal.II authors
*
* This file is part of the deal.II library.
*
* The deal.II library is free software; you can use it, redistribute
* it, and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* The full text of the license can be found in the file LICENSE at
* the top level of the deal.II distribution.
*
* ---------------------------------------------------------------------
*
* Author: Wolfgang Bangerth, Texas A&M University, 2011
*/
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/function.h>
#include <deal.II/base/utilities.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/sparse_direct.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/fe_nothing.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/hp/dof_handler.h>
#include <deal.II/hp/fe_collection.h>
#include <deal.II/hp/fe_values.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>
#include <deal.II/base/convergence_table.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <deal.II/lac/block_vector.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/lac/block_sparse_matrix.h>
namespace Step46
{
using namespace dealii;
template <int dim>
class FluidStructureProblem
{
public:
FluidStructureProblem (const unsigned int stokes_degree,
const unsigned int laplace_degree);
void run ();
private:
enum
{
stokes_domain_id,
laplace_domain_id
};
static bool
cell_is_in_stokes_domain (const typename hp::DoFHandler<dim>::cell_iterator &cell);
static bool
cell_is_in_laplace_domain (const typename hp::DoFHandler<dim>::cell_iterator &cell);
void make_grid ();
void set_active_fe_indices ();
void setup_dofs ();
void assemble_system ();
void assemble_interface_term (const FEFaceValuesBase<dim> &laplace_fe_face_values,
const FEFaceValuesBase<dim> &stokes_fe_face_values,
std::vector<Tensor<1,dim> > &laplace_phi,
std::vector<Tensor<2,dim> > &laplace_grad_phi,
std::vector<SymmetricTensor<2,dim> > &stokes_symgrad_phi_u,
std::vector<double> &stokes_phi_p,
FullMatrix<double> &local_interface_matrix) const;
// void assemble_interface_term (const FEFaceValuesBase<dim> &elasticity_fe_face_values,
// const FEFaceValuesBase<dim> &stokes_fe_face_values,
// std::vector<Tensor<1,dim> > &elasticity_phi,
// std::vector<SymmetricTensor<2,dim> > &stokes_symgrad_phi_u,
// std::vector<double> &stokes_phi_p,
// FullMatrix<double> &local_interface_matrix) const;
void solve ();
void output_results (const unsigned int refinement_cycle) const;
void compute_errors (const unsigned int refinement_cycle);
void refine_mesh ();
const unsigned int stokes_degree;
const unsigned int laplace_degree;
Triangulation<dim> triangulation;
FESystem<dim> stokes_fe;
FESystem<dim> laplace_fe;
hp::FECollection<dim> fe_collection;
hp::DoFHandler<dim> dof_handler;
ConstraintMatrix constraints;
SparsityPattern sparsity_pattern;
SparseMatrix<double> system_matrix;
ConvergenceTable convergence_table;
Vector<double> solution;
Vector<double> system_rhs;
const double viscosity;
// const double lambda;
// const double mu;
};
template <int dim>
class StokesBoundaryValues : public Function<dim>
{
public:
StokesBoundaryValues () : Function<dim>(dim+1) {}
virtual double value (const Point<dim> &p,
const unsigned int component = 0) const;
virtual void vector_value (const Point<dim> &p,
Vector<double> &value) const;
};
template <int dim>
double
StokesBoundaryValues<dim>::value (const Point<dim> &p,
const unsigned int component) const
{
Assert (component < this->n_components,
ExcIndexRange (component, 0, this->n_components));
if (component == dim-1)
switch (dim)
{
case 2:
return 0; //std::sin(numbers::PI*p[0]);
case 3:
return 0; //std::sin(numbers::PI*p[0]) * std::sin(numbers::PI*p[1]);
default:
Assert (false, ExcNotImplemented());
}
return 0;
}
template <int dim>
void
StokesBoundaryValues<dim>::vector_value (const Point<dim> &p,
Vector<double> &values) const
{
for (unsigned int c=0; c<this->n_components; ++c)
values(c) = 0;// StokesBoundaryValues<dim>::value (p, c);
}
template <int dim>
class RightHandSide : public Function<dim>
{
public:
RightHandSide () : Function<dim>(dim+1) {}
virtual double value (const Point<dim> &p,
const unsigned int component = 0) const;
virtual void vector_value (const Point<dim> &p,
Vector<double> &value) const;
};
template <int dim>
double
RightHandSide<dim>::value (const Point<dim> &/*p*/,
const unsigned int /*component*/) const
{
return 0;
}
template <int dim>
void
RightHandSide<dim>::vector_value (const Point<dim> &p,
Vector<double> &values) const
{
// values(0) = 1;
// values(1) = 1;
// values(2) = 1;
if (p[dim-1]>=0.5){
values(0) = - 400.0 * (pow(p[0],4) * (6*p[1] - 3) + pow(p[0],3) * (6 - 12 * p[1])
+ 3 * pow(p[0],2) * (4 * pow(p[1],3) - 6 * pow(p[1],2) + 4* p[1] -1)
- 6 * p[0] * p[1] * (2 * pow(p[1],2) - 3 * p[1] + 1)
+ p[1] * (2 * pow(p[1],2) - 3 * p[1] + 1))
+ 30 * pow(p[0] - 0.5,2)* pow(p[1]-0.5,2) - 3 * pow(1-p[0] , 2) * pow(p[1] - 0.5, 3);
values(1) = + 400.0 * (pow(p[1],4) * (6*p[0] - 3) + pow(p[1],3) * (6 - 12 * p[0])
+ 3 * pow(p[1],2) * (4 * pow(p[0],3) - 6 * pow(p[0],2) + 4* p[0] -1)
- 6 * p[1] * p[0] * (2 * pow(p[0],2) - 3 * p[0] + 1)
+ p[0] * (2 * pow(p[0],2) - 3 * p[0] + 1))
+ 20 * pow(p[0] - 0.5,3)* (p[1]-0.5) + 3 * pow(1-p[0] , 3) * pow(p[1] - 0.5, 2);
values(2) = 0.0;
}
else {
values(0) = - 400.0 * (pow(p[0],4) * (6*p[1] - 3) + pow(p[0],3) * (6 - 12 * p[1])
+ 3 * pow(p[0],2) * (4 * pow(p[1],3) - 6 * pow(p[1],2) + 4* p[1] -1)
- 6 * p[0] * p[1] * (2 * pow(p[1],2) - 3 * p[1] + 1)
+ p[1] * (2 * pow(p[1],2) - 3 * p[1] + 1));
//+ 30 * pow(p[0] - 0.5,2)* pow(p[1]-0.5,2) - 3 * pow(1-p[0] , 2) * pow(p[1] - 0.5, 3);
values(1) = + 400.0 * (pow(p[1],4) * (6*p[0] - 3) + pow(p[1],3) * (6 - 12 * p[0])
+ 3 * pow(p[1],2) * (4 * pow(p[0],3) - 6 * pow(p[0],2) + 4* p[0] -1)
- 6 * p[1] * p[0] * (2 * pow(p[0],2) - 3 * p[0] + 1)
+ p[0] * (2 * pow(p[0],2) - 3 * p[0] + 1));
//+ 20 * pow(p[0] - 0.5,3)* (p[1]-0.5) + 3 * pow(1-p[0] , 3) * pow(p[1] - 0.5, 2);
values(2) = 0.0;
}
}
template <int dim>
FluidStructureProblem<dim>::
FluidStructureProblem (const unsigned int stokes_degree,
const unsigned int laplace_degree)
:
stokes_degree (stokes_degree),
laplace_degree (laplace_degree),
triangulation (Triangulation<dim>::maximum_smoothing),
stokes_fe (FE_Q<dim>(stokes_degree+1), dim,
FE_Q<dim>(stokes_degree), 1),
laplace_fe (FE_Q<dim>(stokes_degree+1), dim,
FE_Nothing<dim>(), 1),
dof_handler (triangulation),
viscosity (1)//,
// lambda (1),
// mu (1)
{
fe_collection.push_back (stokes_fe);
fe_collection.push_back (laplace_fe);
}
template <int dim>
bool
FluidStructureProblem<dim>::
cell_is_in_stokes_domain (const typename hp::DoFHandler<dim>::cell_iterator &cell)
{
return (cell->material_id() == stokes_domain_id);
}
template <int dim>
bool
FluidStructureProblem<dim>::
cell_is_in_laplace_domain (const typename hp::DoFHandler<dim>::cell_iterator &cell)
{
return (cell->material_id() == laplace_domain_id);
}
template <int dim>
void
FluidStructureProblem<dim>::make_grid ()
{
GridGenerator::subdivided_hyper_cube (triangulation, 8, 0, 1);
for (typename Triangulation<dim>::active_cell_iterator
cell = triangulation.begin_active();
cell != triangulation.end(); ++cell)
for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
if (cell->face(f)->at_boundary()
&&
(cell->face(f)->center()[dim-1] >= 0.0))
cell->face(f)->set_all_boundary_ids(1);
for (typename Triangulation<dim>::active_cell_iterator
cell = dof_handler.begin_active();
cell != dof_handler.end(); ++cell)
if (cell->center()[dim-1] >= 0.5)
cell->set_material_id (stokes_domain_id);
else
cell->set_material_id (laplace_domain_id);
}
template <int dim>
void
FluidStructureProblem<dim>::set_active_fe_indices ()
{
for (typename hp::DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active();
cell != dof_handler.end(); ++cell)
{
if (cell_is_in_stokes_domain(cell))
cell->set_active_fe_index (0);
else if (cell_is_in_laplace_domain(cell))
cell->set_active_fe_index (1);
else
Assert (false, ExcNotImplemented());
}
}
template <int dim>
void
FluidStructureProblem<dim>::setup_dofs ()
{
set_active_fe_indices ();
dof_handler.distribute_dofs (fe_collection);
{
constraints.clear ();
DoFTools::make_hanging_node_constraints (dof_handler,
constraints);
const FEValuesExtractors::Vector velocities(0);
VectorTools::interpolate_boundary_values (dof_handler,
1,
StokesBoundaryValues<dim>(),
constraints,
fe_collection.component_mask(velocities));
// const FEValuesExtractors::Vector displacements(dim+1);
// VectorTools::interpolate_boundary_values (dof_handler,
// 0,
// ZeroFunction<dim>(dim+1+),
// constraints,
// fe_collection.component_mask(displacements));
}
// {
// std::vector<types::global_dof_index> local_face_dof_indices (stokes_fe.dofs_per_face);
// for (typename hp::DoFHandler<dim>::active_cell_iterator
// cell = dof_handler.begin_active();
// cell != dof_handler.end(); ++cell)
// if (cell_is_in_fluid_domain (cell))
// for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
// if (!cell->at_boundary(f))
// {
// bool face_is_on_interface = false;
// if ((cell->neighbor(f)->has_children() == false)
// &&
// (cell_is_in_solid_domain (cell->neighbor(f))))
// face_is_on_interface = true;
// else if (cell->neighbor(f)->has_children() == true)
// {
// for (unsigned int sf=0; sf<cell->face(f)->n_children(); ++sf)
// if (cell_is_in_solid_domain (cell->neighbor_child_on_subface
// (f, sf)))
// {
// face_is_on_interface = true;
// break;
// }
// }
// if (face_is_on_interface)
// {
// cell->face(f)->get_dof_indices (local_face_dof_indices, 0);
// for (unsigned int i=0; i<local_face_dof_indices.size(); ++i)
// if (stokes_fe.face_system_to_component_index(i).first < dim)
// constraints.add_line (local_face_dof_indices[i]);
// }
// }
// }
constraints.close ();
std::cout << " Number of active cells: "
<< triangulation.n_active_cells()
<< std::endl
<< " Number of degrees of freedom: "
<< dof_handler.n_dofs()
<< std::endl;
{
DynamicSparsityPattern dsp (dof_handler.n_dofs(),
dof_handler.n_dofs());
Table<2,DoFTools::Coupling> cell_coupling (fe_collection.n_components(),
fe_collection.n_components());
Table<2,DoFTools::Coupling> face_coupling (fe_collection.n_components(),
fe_collection.n_components());
for (unsigned int c=0; c<fe_collection.n_components(); ++c)
for (unsigned int d=0; d<fe_collection.n_components(); ++d)
{
if (((c<dim+1) && (d<dim+1)
&& !((c==dim) && (d==dim))))
cell_coupling[c][d] = DoFTools::always;
if (((c<dim+1) && (d<dim+1)
&& !((c==dim) && (d==dim))))
face_coupling[c][d] = DoFTools::always;
}
// DoFTools::make_flux_sparsity_pattern (dof_handler, dsp);
DoFTools::make_flux_sparsity_pattern (dof_handler, dsp,
cell_coupling, face_coupling);
constraints.condense (dsp);
sparsity_pattern.copy_from (dsp);
}
system_matrix.reinit (sparsity_pattern);
solution.reinit (dof_handler.n_dofs());
system_rhs.reinit (dof_handler.n_dofs());
}
template <int dim>
void FluidStructureProblem<dim>::assemble_system ()
{
system_matrix=0;
system_rhs=0;
const QGauss<dim> stokes_quadrature(stokes_degree+2);
const QGauss<dim> laplace_quadrature(laplace_degree+2);
hp::QCollection<dim> q_collection;
q_collection.push_back (stokes_quadrature);
q_collection.push_back (laplace_quadrature);
hp::FEValues<dim> hp_fe_values (fe_collection, q_collection,
update_values |
update_second_derivatives |
update_quadrature_points |
update_JxW_values |
update_gradients);
const QGauss<dim-1> common_face_quadrature(std::max (stokes_degree+2,
laplace_degree+2));
FEFaceValues<dim> stokes_fe_face_values (stokes_fe,
common_face_quadrature,
update_JxW_values |
update_values |
update_normal_vectors |
update_gradients);
FEFaceValues<dim> laplace_fe_face_values (laplace_fe,
common_face_quadrature,
update_values |
update_normal_vectors |
update_gradients);
FESubfaceValues<dim> stokes_fe_subface_values (stokes_fe,
common_face_quadrature,
update_JxW_values |
update_normal_vectors |
update_gradients);
FESubfaceValues<dim> laplace_fe_subface_values (laplace_fe,
common_face_quadrature,
update_values |
update_normal_vectors |
update_gradients);
const unsigned int stokes_dofs_per_cell = stokes_fe.dofs_per_cell;
const unsigned int laplace_dofs_per_cell = laplace_fe.dofs_per_cell;
const unsigned int stokes_n_q_points = stokes_quadrature.size();
const unsigned int laplace_n_q_points = laplace_quadrature.size();
FullMatrix<double> local_matrix;
FullMatrix<double> local_interface_matrix (laplace_dofs_per_cell,
stokes_dofs_per_cell);
Vector<double> local_rhs;
std::vector<types::global_dof_index> local_dof_indices;
std::vector<types::global_dof_index> neighbor_dof_indices (stokes_dofs_per_cell);
const RightHandSide<dim> right_hand_side;
std::vector<Vector<double>> rhs_values (stokes_n_q_points,
Vector<double>(dim+1)); // I put this here
std::vector<Vector<double>> Laplacian_values (stokes_n_q_points,
Vector<double>(dim+1)); // I put this here
const FEValuesExtractors::Vector velocities (0);
const FEValuesExtractors::Scalar pressure (dim);
// const FEValuesExtractors::Vector displacements (dim+1);
std::vector<SymmetricTensor<2,dim> > stokes_symgrad_phi_u (stokes_dofs_per_cell);
std::vector<Tensor<2,dim> > stokes_grad_phi_u (laplace_dofs_per_cell);
std::vector<double> stokes_div_phi_u (stokes_dofs_per_cell);
std::vector<double> stokes_phi_p (stokes_dofs_per_cell);
std::vector<Tensor<2,dim> > laplace_grad_phi (laplace_dofs_per_cell);
// std::vector<double> laplace_div_phi (laplace_dofs_per_cell);
std::vector<Tensor<1,dim> > laplace_phi (laplace_dofs_per_cell);
typename hp::DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active(),
endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
hp_fe_values.reinit (cell);
const FEValues<dim> &fe_values = hp_fe_values.get_present_fe_values();
local_matrix.reinit (cell->get_fe().dofs_per_cell,
cell->get_fe().dofs_per_cell);
local_rhs.reinit (cell->get_fe().dofs_per_cell);
if (cell_is_in_stokes_domain (cell))
{
const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
Assert (dofs_per_cell == stokes_dofs_per_cell,
ExcInternalError());
right_hand_side.vector_value_list(fe_values.get_quadrature_points(), rhs_values);
for (unsigned int q=0; q<fe_values.n_quadrature_points; ++q)
{
for (unsigned int k=0; k<dofs_per_cell; ++k)
{
stokes_symgrad_phi_u[k] = fe_values[velocities].symmetric_gradient (k, q);
stokes_div_phi_u[k] = fe_values[velocities].divergence (k, q);
stokes_phi_p[k] = fe_values[pressure].value (k, q);
// Laplacian_values[k] = fe_values[velocities].get
}
for (unsigned int i=0; i<dofs_per_cell; ++i){
for (unsigned int j=0; j<dofs_per_cell; ++j){
local_matrix(i,j) += (2 * viscosity * stokes_symgrad_phi_u[i] * stokes_symgrad_phi_u[j]
- stokes_div_phi_u[i] * stokes_phi_p[j]
- stokes_phi_p[i] * stokes_div_phi_u[j])
* fe_values.JxW(q);
}
const unsigned int component_i =
stokes_fe.system_to_component_index(i).first;//fe_values.shape_value(i,q)
if (component_i<dim){
double r = rhs_values[q](component_i);
local_rhs(i) += fe_values[velocities].value(i,q)[component_i] *
rhs_values[q](component_i) *
fe_values.JxW(q);
}
}
}
}
else
{
const unsigned int dofs_per_cell = cell->get_fe().dofs_per_cell;
Assert (dofs_per_cell == laplace_dofs_per_cell,
ExcInternalError());
right_hand_side.vector_value_list(fe_values.get_quadrature_points(), rhs_values);
for (unsigned int q=0; q<fe_values.n_quadrature_points; ++q)
{
for (unsigned int k=0; k<dofs_per_cell; ++k)
{
laplace_grad_phi[k] = fe_values[velocities].gradient (k, q);
// elasticity_div_phi[k] = fe_values[displacements].divergence (k, q);
}
for (unsigned int i=0; i<dofs_per_cell; ++i){
for (unsigned int j=0; j<dofs_per_cell; ++j)
{
local_matrix(i,j)
+= (
scalar_product(laplace_grad_phi[i], laplace_grad_phi[j])
)
*
fe_values.JxW(q);
// local_matrix(i,j)
// += (
// lambda *
// elasticity_div_phi[i] * elasticity_div_phi[j]
// +
// mu *
// scalar_product(elasticity_grad_phi[i], elasticity_grad_phi[j])
// +
// mu *
// scalar_product(elasticity_grad_phi[i], transpose(elasticity_grad_phi[j]))
// )
// *
// fe_values.JxW(q);
}
const unsigned int component_i =
laplace_fe.system_to_component_index(i).first;
local_rhs(i) += fe_values[velocities].value(i,q)[component_i] *
rhs_values[q](component_i) *
fe_values.JxW(q);
}
}
}
local_dof_indices.resize (cell->get_fe().dofs_per_cell);
cell->get_dof_indices (local_dof_indices);
constraints.distribute_local_to_global (local_matrix, local_rhs,
local_dof_indices,
system_matrix, system_rhs);
if (cell_is_in_laplace_domain (cell))
for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
if (cell->at_boundary(f) == false)
{
if ((cell->neighbor(f)->level() == cell->level())
&&
(cell->neighbor(f)->has_children() == false)
&&
cell_is_in_stokes_domain (cell->neighbor(f)))
{
laplace_fe_face_values.reinit (cell, f);
stokes_fe_face_values.reinit (cell->neighbor(f),
cell->neighbor_of_neighbor(f));
assemble_interface_term (laplace_fe_face_values, stokes_fe_face_values,
laplace_phi, laplace_grad_phi, stokes_symgrad_phi_u, stokes_phi_p,
local_interface_matrix);
cell->neighbor(f)->get_dof_indices (neighbor_dof_indices);
constraints.distribute_local_to_global(local_interface_matrix,
local_dof_indices,
neighbor_dof_indices,
system_matrix);
}
else if ((cell->neighbor(f)->level() == cell->level())
&&
(cell->neighbor(f)->has_children() == true))
{
for (unsigned int subface=0;
subface<cell->face(f)->n_children();
++subface)
if (cell_is_in_stokes_domain (cell->neighbor_child_on_subface
(f, subface)))
{
laplace_fe_subface_values.reinit (cell,
f,
subface);
stokes_fe_face_values.reinit (cell->neighbor_child_on_subface (f, subface),
cell->neighbor_of_neighbor(f));
assemble_interface_term (laplace_fe_subface_values,
stokes_fe_face_values,
laplace_phi, laplace_grad_phi,
stokes_symgrad_phi_u, stokes_phi_p,
local_interface_matrix);
cell->neighbor_child_on_subface (f, subface)
->get_dof_indices (neighbor_dof_indices);
constraints.distribute_local_to_global(local_interface_matrix,
local_dof_indices,
neighbor_dof_indices,
system_matrix);
}
}
else if (cell->neighbor_is_coarser(f)
&&
cell_is_in_stokes_domain(cell->neighbor(f)))
{
laplace_fe_face_values.reinit (cell, f);
stokes_fe_subface_values.reinit (cell->neighbor(f),
cell->neighbor_of_coarser_neighbor(f).first,
cell->neighbor_of_coarser_neighbor(f).second);
assemble_interface_term (laplace_fe_face_values,
stokes_fe_subface_values,
laplace_phi, laplace_grad_phi,
stokes_symgrad_phi_u, stokes_phi_p,
local_interface_matrix);
cell->neighbor(f)->get_dof_indices (neighbor_dof_indices);
constraints.distribute_local_to_global(local_interface_matrix,
local_dof_indices,
neighbor_dof_indices,
system_matrix);
}
}
}
}
template <int dim>
void
FluidStructureProblem<dim>::
assemble_interface_term (const FEFaceValuesBase<dim> &laplace_fe_face_values,
const FEFaceValuesBase<dim> &stokes_fe_face_values,
std::vector<Tensor<1,dim> > &laplace_phi,
std::vector<Tensor<2,dim> > &laplace_grad_phi,
std::vector<SymmetricTensor<2,dim> > &stokes_symgrad_phi_u,
std::vector<double> &stokes_phi_p,
FullMatrix<double> &local_interface_matrix) const
{
Assert (stokes_fe_face_values.n_quadrature_points ==
laplace_fe_face_values.n_quadrature_points,
ExcInternalError());
const unsigned int n_face_quadrature_points
= laplace_fe_face_values.n_quadrature_points;
const FEValuesExtractors::Vector velocities (0);
const FEValuesExtractors::Scalar pressure (dim);
//const FEValuesExtractors::Vector displacements (dim+1);
local_interface_matrix = 0;
for (unsigned int q=0; q<n_face_quadrature_points; ++q)
{
const Tensor<1,dim> normal_vector_stokes = stokes_fe_face_values.normal_vector(q);
const Tensor<1,dim> normal_vector_laplace = laplace_fe_face_values.normal_vector(q);
for (unsigned int k=0; k<stokes_fe_face_values.dofs_per_cell; ++k){
stokes_symgrad_phi_u[k] = stokes_fe_face_values[velocities].symmetric_gradient (k, q);
// stokes_grad_phi_u[k] = stokes_fe_face_values[velocities].gradient (k, q);
// stokes_phi_p[k] = stokes_fe_face_values[pressure].value(k,q);
}
for (unsigned int k=0; k<laplace_fe_face_values.dofs_per_cell; ++k){
laplace_phi[k] = laplace_fe_face_values[velocities].value (k,q);
// laplace_grad_phi[k] = laplace_fe_face_values[velocities].gradient(k,q);
}
for (unsigned int i=0; i<laplace_fe_face_values.dofs_per_cell; ++i)
for (unsigned int j=0; j<stokes_fe_face_values.dofs_per_cell; ++j)
local_interface_matrix(i,j) += 0;
// -((
// (stokes_symgrad_phi_u[j] *
// normal_vector_stokes)
// -
// stokes_phi_p[j] *
// normal_vector_stokes
// +
// laplace_grad_phi[j] *
// normal_vector_laplace) *
// laplace_phi[i] *
// stokes_fe_face_values.JxW(q));
}
}
template <int dim>
void
FluidStructureProblem<dim>::solve ()
{
SparseDirectUMFPACK direct_solver;
direct_solver.initialize (system_matrix);
direct_solver.vmult (solution, system_rhs);
constraints.distribute (solution);
}
template <int dim>
void
FluidStructureProblem<dim>::
output_results (const unsigned int refinement_cycle) const
{
std::vector<std::string> solution_names (dim, "velocity");
solution_names.push_back ("pressure");
// for (unsigned int d=0; d<dim; ++d)
// solution_names.push_back ("displacement");
std::vector<DataComponentInterpretation::DataComponentInterpretation>
data_component_interpretation
(dim, DataComponentInterpretation::component_is_part_of_vector);
data_component_interpretation
.push_back (DataComponentInterpretation::component_is_scalar);
for (unsigned int d=0; d<dim; ++d)
data_component_interpretation
.push_back (DataComponentInterpretation::component_is_part_of_vector);
DataOut<dim,hp::DoFHandler<dim> > data_out;
data_out.attach_dof_handler (dof_handler);
data_out.add_data_vector (solution, solution_names,
DataOut<dim,hp::DoFHandler<dim> >::type_dof_data,
data_component_interpretation);
data_out.build_patches ();
std::ostringstream filename;
filename << "/Users/gs1511/dealii_out/solutiongs-"
<< Utilities::int_to_string (refinement_cycle, 2)
<< ".vtk";
std::ofstream output (filename.str().c_str());
data_out.write_vtk (output);
}
template <int dim>
void
FluidStructureProblem<dim>::refine_mesh ()
{
Vector<float>
stokes_estimated_error_per_cell (triangulation.n_active_cells());
Vector<float>
laplace_estimated_error_per_cell (triangulation.n_active_cells());
Vector<float>
model_error_per_cell (triangulation.n_active_cells());
Vector<float>
discretization_error_per_cell (triangulation.n_active_cells());
const QGauss<dim-1> stokes_face_quadrature(stokes_degree+2);
const QGauss<dim-1> laplace_face_quadrature(laplace_degree+2);
hp::QCollection<dim-1> face_q_collection;
face_q_collection.push_back (stokes_face_quadrature);
face_q_collection.push_back (laplace_face_quadrature);
const FEValuesExtractors::Vector velocities(0);
const FEValuesExtractors::Scalar pressure (dim);
KellyErrorEstimator<dim>::estimate (dof_handler,
face_q_collection,
typename FunctionMap<dim>::type(),
solution,
stokes_estimated_error_per_cell,
fe_collection.component_mask(velocities));
//const FEValuesExtractors::Vector velocities(0);
KellyErrorEstimator<dim>::estimate (dof_handler,
face_q_collection,
typename FunctionMap<dim>::type(),
solution,
laplace_estimated_error_per_cell,
fe_collection.component_mask(velocities));
stokes_estimated_error_per_cell
*= 4. / stokes_estimated_error_per_cell.l2_norm();
laplace_estimated_error_per_cell
*= 4. / laplace_estimated_error_per_cell.l2_norm();
Vector<float>
estimated_error_per_cell (triangulation.n_active_cells());
estimated_error_per_cell += stokes_estimated_error_per_cell;
estimated_error_per_cell += laplace_estimated_error_per_cell;
// // Make the terms for the laplace a-posteriori indicator (see pg 243 of Verfurth).
//
system_matrix=0;
system_rhs=0;
const QGauss<dim> stokes_quadrature(stokes_degree+2);
const QGauss<dim> laplace_quadrature(laplace_degree+2);
hp::QCollection<dim> q_collection;
q_collection.push_back (stokes_quadrature);
q_collection.push_back (laplace_quadrature);
hp::FEValues<dim> hp_fe_values (fe_collection, q_collection,
update_values |
update_quadrature_points |
update_JxW_values |
update_gradients);
const QGauss<dim-1> common_face_quadrature(std::max (stokes_degree+2,
laplace_degree+2));
// cell face calculations
FEFaceValues<dim> stokes_fe_face_values (stokes_fe,
common_face_quadrature,
update_JxW_values |
update_values |
update_normal_vectors |
update_gradients);
FEFaceValues<dim> laplace_fe_face_values (laplace_fe,
common_face_quadrature,
update_values |
update_normal_vectors |
update_gradients);
FESubfaceValues<dim> stokes_fe_subface_values (stokes_fe,
common_face_quadrature,
update_JxW_values |
update_normal_vectors |
update_gradients);
FESubfaceValues<dim> laplace_fe_subface_values (laplace_fe,
common_face_quadrature,
update_values |
update_normal_vectors |
update_gradients);
// neighbor of the cell face calculations
FEFaceValues<dim> stokes_fe_face_values_neighbor (stokes_fe,
common_face_quadrature,
update_JxW_values |
update_values |
update_normal_vectors |
update_gradients);
FEFaceValues<dim> laplace_fe_face_values_neighbor (laplace_fe,
common_face_quadrature,
update_values |
update_normal_vectors |
update_gradients);
FESubfaceValues<dim> stokes_fe_subface_values_neighbor (stokes_fe,
common_face_quadrature,
update_JxW_values |
update_normal_vectors |
update_gradients);
FESubfaceValues<dim> laplace_fe_subface_values_neighbor (laplace_fe,
common_face_quadrature,
update_values |
update_normal_vectors |
update_gradients);
const unsigned int stokes_dofs_per_cell = stokes_fe.dofs_per_cell;
const unsigned int laplace_dofs_per_cell = laplace_fe.dofs_per_cell;
const unsigned int stokes_n_q_points = stokes_quadrature.size();
const unsigned int laplace_n_q_points = laplace_quadrature.size();
const RightHandSide<dim> right_hand_side;
std::vector<Vector<double>> rhs_values (stokes_n_q_points,
Vector<double>(dim+1)); // I put this here
double cell_contribution;
double face_contribution;
std::vector<Tensor<2, dim> > cell_velocity_grads(stokes_n_q_points);
std::vector<Tensor<2, dim> > cell_neighbor_velocity_grads(stokes_n_q_points);
std::vector<Tensor<1,dim>> cell_laplacians(stokes_n_q_points);
std::vector<Tensor<1,dim>> cell_pressure_gradients(stokes_n_q_points);
std::vector<double> cell_values_pressure(stokes_n_q_points);
std::vector<double> cell_values_divergence(stokes_n_q_points);
std::vector<double> cell_neighbor_values_pressure(stokes_n_q_points);
// (1) : first term is ||f- Δu_T ||_{L^2}
for (typename hp::DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active();
cell != dof_handler.end(); ++cell){
cell_contribution = 0;
hp_fe_values.reinit (cell);
const FEValues<dim> &fe_values = hp_fe_values.get_present_fe_values();
fe_values[pressure].get_function_gradients(solution, cell_pressure_gradients);
fe_values[velocities].get_function_laplacians(solution, cell_laplacians);
fe_values[velocities].get_function_divergences(solution, cell_values_divergence);
right_hand_side.vector_value_list(fe_values.get_quadrature_points(), rhs_values);
// for (unsigned int q=0; q<fe_values.n_quadrature_points; ++q){
// for (unsigned int d = 0; d<dim; ++d){
// cell_contribution += pow(cell->diameter(),2) * pow(rhs_values[q][d] + cell_laplacians[q][d]-cell_pressure_gradients[q][d],2) * fe_values.JxW(q);
// }
// }
for (unsigned int q=0; q<fe_values.n_quadrature_points; ++q){
cell_contribution += pow(cell_values_divergence[q] , 2) * fe_values.JxW(q);
}
// face stuff here
// for (unsigned int face_no=0; face_no<GeometryInfo<dim>::faces_per_cell; ++face_no){
// face_contribution = 0;
// if (!( (cell_is_in_stokes_domain(cell) && cell_is_in_stokes_domain(cell->neighbor(face_no))) ||
// (cell_is_in_laplace_domain(cell) && cell_is_in_laplace_domain(cell->neighbor(face_no)))))
// {
// face_contribution = 0;
// }
//
//
// if (cell->face(face_no)->at_boundary())
// {
// face_integrals[cell->face(face_no)] = 0; // cell_contribution = 0;
// continue;
// }
// if ((cell->neighbor(face_no)->has_children() == false) &&
// (cell->neighbor(face_no)->level() == cell->level()) &&
// (cell->neighbor(face_no)->index() < cell->index()))
// continue;
// if (cell->at_boundary(face_no) == false)
// if (cell->neighbor(face_no)->level() < cell->level())
// continue;
//
//
// if (cell->face(face_no)->has_children() == false){
//// Integration over regular face (same level of refinement as the neighbour
// Assert (cell->neighbor(face_no).state() == IteratorState::valid, ExcInternalError());
//
// const unsigned int neighbor_neighbor = cell->neighbor_of_neighbor (face_no);
// const active_cell_iterator neighbor = cell->neighbor(face_no);
//
// if (cell_is_in_stokes_domain(cell) && cell_is_in_stokes_domain(cell->neighbor(face_no))){
//
// stokes_fe_face_values.reinit(cell,face_no);
// stokes_fe_face_values[velocities].get_function_gradients(solution, cell_velocity_grads);
// stokes_fe_face_values[pressure].get_function_gradients(solution, cell_values_pressure);
//
// stokes_fe_face_values.reinit(cell->neighbor(face_no) , cell->neighbor_of_neighbor(face_no));
// stokes_fe_face_values[velocities].get_function_gradients(solution, cell_neighbor_velocity_grads);
// stokes_fe_face_values[pressure].get_function_gradients(solution, cell_neighbor_values_pressure);
//
// for (unsigned int q; q<stokes_fe_face_values.n_quadrature_points; ++q){
// const Tensor<1,dim> normal_vector_stokes = stokes_fe_face_values.normal_vector(q);
//
// face_contribution += pow(cell->diameter(),-0.5) * pow(((-cell_values_pressure[q] * normal_vector_stokes + cell_velocity_grads[q] * normal_vector_stokes)-(-cell_neighbor_values_pressure[q] * normal_vector_stokes + cell_neighbor_velocity_grads[q] * normal_vector_stokes)),2)* stokes_fe_face_values.JxW(q);
//
// }
// }
// else if (cell_is_in_laplace_domain(cell) && cell_is_in_laplace_domain(cell->neighbor(face_no))){
// laplace_fe_face_values.reinit(cell,face_no);
// laplace_fe_face_values[velocities].get_function_gradients(solution, cell_velocity_grads);
//
// laplace_fe_face_values.reinit(cell->neighbor(face_no) , cell->neighbor_of_neighbor(face_no));
// laplace_fe_face_values[velocities].get_function_gradients(solution, cell_neighbor_velocity_grads);
//
// for (unsigned int q; q<laplace_fe_face_values.n_quadrature_points; ++q){
// const Tensor<1,dim> normal_vector_laplace = laplace_fe_face_values.normal_vector(q);
//
// const Tensor<1,dim> normal_vector_laplace = laplace_fe_face_values.normal_vector(q);
// face_contribution += pow(cell->diameter(),-0.5) * pow(((cell_velocity_grads[q] * normal_vector_laplace)-(cell_neighbor_velocity_grads[q] * normal_vector_laplace)),2)* laplace_fe_face_values.JxW(q);
//
// }
// }
//
//
// }
//
// else
//// integrate_over_irregular_face (cell, face_no,
//// scratch_data.primal_solution,
//// scratch_data.dual_weights,
//// scratch_data.face_data,
//// face_integrals);
// }
// cell_contribution += face_contribution;
estimated_error_per_cell(cell->active_cell_index()) += (float) cell_contribution;
}
GridRefinement::refine_and_coarsen_fixed_number (triangulation,
estimated_error_per_cell,
0.3, 0.0);
triangulation.execute_coarsening_and_refinement ();
}
template <int dim>
void FluidStructureProblem<dim>::run ()
{
make_grid ();
for (unsigned int refinement_cycle = 0; refinement_cycle<8;
++refinement_cycle)
{
std::cout << "Refinement cycle " << refinement_cycle << std::endl;
if (refinement_cycle > 0)
refine_mesh ();
setup_dofs ();
std::cout << " Assembling..." << std::endl;
assemble_system ();
std::cout << " Solving..." << std::endl;
solve ();
std::cout << " Writing output..." << std::endl;
output_results (refinement_cycle);
compute_errors (refinement_cycle);
std::cout << std::endl;
}
}
template <int dim>
void FluidStructureProblem<dim>::compute_errors(const unsigned int refinement_cycle)
{
const ComponentSelectFunction<dim> pressure_mask (dim, dim+1);
const ComponentSelectFunction<dim> velocity_mask(std::make_pair(0, dim), dim+1);
Vector<double> cellwise_errors (triangulation.n_active_cells());
QTrapez<1> q_trapez;
QIterated<dim> quadrature (q_trapez, stokes_degree+2);
// VectorTools::integrate_difference (dof_handler, solution, exact_solution,
// cellwise_errors, quadrature,
// VectorTools::L2_norm,
// &pressure_mask);
// const double p_l2_error = VectorTools::compute_global_error(triangulation,
// cellwise_errors,
// VectorTools::L2_norm);
//
// VectorTools::integrate_difference (dof_handler, solution, exact_solution,
// cellwise_errors, quadrature,
// VectorTools::L2_norm,
// &velocity_mask);
// const double u_l2_error = VectorTools::compute_global_error(triangulation,
// cellwise_errors,
// VectorTools::L2_norm);
//
// VectorTools::integrate_difference (dof_handler, solution, exact_solution,
// cellwise_errors, quadrature,
// VectorTools::H1_norm,
// &velocity_mask);
// const double u_h1_error = VectorTools::compute_global_error(triangulation,
// cellwise_errors,
// VectorTools::H1_norm);
VectorTools::integrate_difference (dof_handler, solution, ZeroFunction<dim>(),
cellwise_errors, quadrature,
VectorTools::L2_norm,
&velocity_mask);
const double u_hdiv = VectorTools::compute_global_error(triangulation,
cellwise_errors,
VectorTools::Hdiv_seminorm);
const unsigned int n_active_cells=triangulation.n_active_cells();
const unsigned int n_dofs=dof_handler.n_dofs();
std::cout << "Cycle " << refinement_cycle << ':'
<< std::endl
<< " Number of active cells: "
<< n_active_cells
<< std::endl
<< " Number of degrees of freedom: "
<< n_dofs
<< std::endl;
std::cout << "Divergence of u_h: ||u_h||_Hdiv = " << u_hdiv
// << ", ||e_u||_L2 = " << u_l2_error
// << ", ||e_u||_H1 = " << u_h1_error
// << ", ||div(u_h)||_Hdiv = " << u_hdiv
<< std::endl;
convergence_table.add_value("refinement cycle", refinement_cycle);
convergence_table.add_value("cells", n_active_cells);
convergence_table.add_value("dofs", n_dofs);
// convergence_table.add_value("$||p-p_h||_{L^2}$", p_l2_error);
// convergence_table.add_value("$||u-u_h||_{L^2}$", u_l2_error);
// convergence_table.add_value("$||u-u_h||_{H^1}$", u_h1_error);
convergence_table.add_value("$||u_h||_{Hdiv}$", u_hdiv);
// convergence_table.set_scientific("$||p-p_h||_{L^2}$", true);
// convergence_table.set_scientific("$||u-u_h||_{L^2}$", true);
// convergence_table.set_scientific("$||u-u_h||_{H^1}$", true);
convergence_table.set_scientific("$||u_h||_{Hdiv}$", true);
std::cout << std::scientific<< std::endl;
convergence_table.write_text(std::cout<< std::scientific);
std::string error_filename = "/Users/gs1511/dealii_out/combined_gs_error-adaptive.tex";
std::ofstream error_table_file(error_filename.c_str());
convergence_table.write_tex(error_table_file);
std::string error_filename2 = "/Users/gs1511/dealii_out/combined_gs_error-adaptive.text";
std::ofstream error_table_file2(error_filename2.c_str());
convergence_table.write_text(error_table_file2);
}
}
int main ()
{
try
{
using namespace dealii;
using namespace Step46;
FluidStructureProblem<2> flow_problem(1, 1);
flow_problem.run ();
}
catch (std::exception &exc)
{
std::cerr << std::endl << std::endl
<< "----------------------------------------------------"
<< std::endl;
std::cerr << "Exception on processing: " << std::endl
<< exc.what() << std::endl
<< "Aborting!" << std::endl
<< "----------------------------------------------------"
<< std::endl;
return 1;
}
catch (...)
{
std::cerr << std::endl << std::endl
<< "----------------------------------------------------"
<< std::endl;
std::cerr << "Unknown exception!" << std::endl
<< "Aborting!" << std::endl
<< "----------------------------------------------------"
<< std::endl;
return 1;
}
return 0;
}