Hi all,
This may seem like a very obvious question/mistake on my part so please do
excuse me if I've overseen something very simple.
I'm trying to solve a stokes system with some funny boundary conditions so
I've stripped the code to make sure I was getting the correct answers to a
very simple system as follows:
governing equations are:
div grad u + grad p = f
div u = 0
i'm setting u=0 on the boundaries, giving u=0 (or close enough) everywhere.
setting f = -(0,1), i should get a linear profile with pressure increasing
with depth at the same rate going downwards.
I'm clearly not understanding how to use
VectorTools::interpolate_boundary_values correctly, and I would appreciate
some clarification on it.
I'm imposing a zero pressure at the top of my rectangle with height of 10,
which means I should get 10 at the bottom for pressure.
I'm using VectorTools::interpolate_boundary_values with component mask to
do this, like in step-22 but I seem to get an odd result, where there is a
factor of 22 that is multiplied for the pressure.
This way just generally doesn't seem to work, eg. if i set the boundary
value as 10.0 using the same way, I don't get 10.0 for pressure at the top,
I still get 0.0 for the top, but at the bottom, instead of 220 which i get
with 0.0 condition at the top, i get 230.
Similarly, when i try (or think i am) setting u=1 on the boundaries (and
therefore u=1 everywhere), the output is showing 1 everywhere EXCEPT on the
boundaries, which seems very odd
Could anyone possibly tell me what I'm doing wrong to with interpolating
the boundary values? seems like such a simple issue but i can't seem to
figure it out
code is attached - boundary id 0 are the sides, 1 the top and 2 the bottom.
NB i am just using a direct solver for now - the rest is taken mostly from
step-22.
Many thanks
--
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) 2008 - 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, 2008
*/
#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/block_vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/block_sparse_matrix.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.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/tria_boundary_lib.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_renumbering.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>
#include <deal.II/lac/sparse_direct.h>
#include <deal.II/lac/sparse_ilu.h>
#include <iostream>
#include <fstream>
#include <sstream>
namespace Step22
{
using namespace dealii;
namespace data
{
const double rho_B = 1.0;
const double eta = 1.0;
const double top = 10.0;
const double bottom = 0.0;
const int dimension = 2;
}
template <int dim>
class StokesProblem
{
public:
StokesProblem (const unsigned int degree);
void run ();
private:
void setup_dofs ();
void assemble_system ();
void solve ();
void output_results (const unsigned int refinement_cycle) const;
void refine_mesh ();
const unsigned int degree;
Triangulation<dim> triangulation;
FESystem<dim> fe;
DoFHandler<dim> dof_handler;
ConstraintMatrix constraints;
BlockSparsityPattern sparsity_pattern;
BlockSparseMatrix<double> system_matrix;
BlockVector<double> solution;
BlockVector<double> system_rhs;
};
template <int dim>
class BoundaryValues : public Function<dim>
{
public:
BoundaryValues () : 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
BoundaryValues<dim>::value (const Point<dim> &p,
const unsigned int component) const
{
return 1.0;
}
template <int dim>
void
BoundaryValues<dim>::vector_value (const Point<dim> &p,
Vector<double> &values) const
{
for (unsigned int c=0; c<this->n_components; ++c)
values(c) = BoundaryValues<dim>::value (p, c);
}
template <int dim>
class BoundaryValuesP1 : public Function<dim>
{
public:
BoundaryValuesP1 () : 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
BoundaryValuesP1<dim>::value (const Point<dim> &p,
const unsigned int component) const
{
return 0.0;
}
template <int dim>
void
BoundaryValuesP1<dim>::vector_value (const Point<dim> &p,
Vector<double> &values) const
{
for (unsigned int c=0; c<this->n_components; ++c)
values(c) = BoundaryValuesP1<dim>::value (p, c);
}
template <int dim>
StokesProblem<dim>::StokesProblem (const unsigned int degree)
:
degree (degree),
triangulation (Triangulation<dim>::maximum_smoothing),
fe (FE_Q<dim>(degree+1), dim,
FE_Q<dim>(degree), 1),
dof_handler (triangulation)
{}
template <int dim>
void StokesProblem<dim>::setup_dofs ()
{
system_matrix.clear ();
dof_handler.distribute_dofs (fe);
DoFRenumbering::Cuthill_McKee (dof_handler);
std::vector<unsigned int> block_component (dim+1,0);
block_component[dim] = 1;
DoFRenumbering::component_wise (dof_handler, block_component);
{
constraints.clear ();
FEValuesExtractors::Vector velocities(0);
FEValuesExtractors::Scalar pressure (dim);
DoFTools::make_hanging_node_constraints (dof_handler,
constraints);
VectorTools::interpolate_boundary_values (dof_handler,
1,
BoundaryValues<dim>(),
constraints,
fe.component_mask(velocities));
VectorTools::interpolate_boundary_values (dof_handler,
0,
BoundaryValues<dim>(),
constraints,
fe.component_mask(velocities));
VectorTools::interpolate_boundary_values (dof_handler,
2,
BoundaryValues<dim>(),
constraints,
fe.component_mask(velocities));
VectorTools::interpolate_boundary_values (dof_handler,
1,
BoundaryValuesP1<dim>(),
constraints,
fe.component_mask(pressure));
}
constraints.close ();
std::vector<types::global_dof_index> dofs_per_block (2);
DoFTools::count_dofs_per_block (dof_handler, dofs_per_block, block_component);
const unsigned int n_u = dofs_per_block[0],
n_p = dofs_per_block[1];
std::cout << " Number of active cells: "
<< triangulation.n_active_cells()
<< std::endl
<< " Number of degrees of freedom: "
<< dof_handler.n_dofs()
<< " (" << n_u << '+' << n_p << ')'
<< std::endl;
{
BlockDynamicSparsityPattern dsp (2,2);
dsp.block(0,0).reinit (n_u, n_u);
dsp.block(1,0).reinit (n_p, n_u);
dsp.block(0,1).reinit (n_u, n_p);
dsp.block(1,1).reinit (n_p, n_p);
dsp.collect_sizes();
DoFTools::make_sparsity_pattern (dof_handler, dsp, constraints, false);
sparsity_pattern.copy_from (dsp);
}
system_matrix.reinit (sparsity_pattern);
solution.reinit (2);
solution.block(0).reinit (n_u);
solution.block(1).reinit (n_p);
solution.collect_sizes ();
system_rhs.reinit (2);
system_rhs.block(0).reinit (n_u);
system_rhs.block(1).reinit (n_p);
system_rhs.collect_sizes ();
}
template <int dim>
void StokesProblem<dim>::assemble_system ()
{
system_matrix=0;
system_rhs=0;
QGauss<dim> quadrature_formula(degree+2);
QGauss<dim-1> face_quadrature_formula(degree+2);
FEValues<dim> fe_values (fe, quadrature_formula,
update_values |
update_quadrature_points |
update_JxW_values |
update_gradients);
FEFaceValues<dim> fe_face_values ( fe, face_quadrature_formula,
update_values |
update_normal_vectors |
update_quadrature_points |
update_JxW_values
);
const unsigned int dofs_per_cell = fe.dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
const unsigned int n_face_q_points = face_quadrature_formula.size();
FullMatrix<double> local_matrix (dofs_per_cell, dofs_per_cell);
Vector<double> local_rhs (dofs_per_cell);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
std::vector<double> boundary_values (n_face_q_points);
const FEValuesExtractors::Vector velocities (0);
const FEValuesExtractors::Scalar pressure (dim);
std::vector<Tensor<1,dim> > phi_u (dofs_per_cell);
std::vector<Tensor<2,dim> > grad_phi_u (dofs_per_cell);
std::vector<double> div_phi_u (dofs_per_cell);
std::vector<double> phi_p (dofs_per_cell);
typename DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active(),
endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
fe_values.reinit (cell);
local_matrix = 0;
local_rhs = 0;
for (unsigned int q=0; q<n_q_points; ++q)
{
for (unsigned int k=0; k<dofs_per_cell; ++k)
{
phi_u[k] = fe_values[velocities].value (k, q);
grad_phi_u[k] = fe_values[velocities].gradient (k, q);
div_phi_u[k] = fe_values[velocities].divergence (k, q);
phi_p[k] = fe_values[pressure].value (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) += (2 * data::eta *
scalar_product
(grad_phi_u[i] ,grad_phi_u[j])
- div_phi_u[i] * phi_p[j]
- phi_p[i] * div_phi_u[j] )
* fe_values.JxW(q);
}
const Point<dim> gravity = ( (dim == 2) ? (Point<dim> (0,1)) :
(Point<dim> (0,0,1)) );
for (unsigned int i=0; i<dofs_per_cell; ++i)
local_rhs(i) += (-data::rho_B *
gravity * phi_u[i] )*
fe_values.JxW(q);
}
}
cell->get_dof_indices (local_dof_indices);
constraints.distribute_local_to_global (local_matrix, local_rhs,
local_dof_indices,
system_matrix, system_rhs);
}
}
template <int dim>
void StokesProblem<dim>::solve ()
{
SparseDirectUMFPACK A_direct;
A_direct.initialize(system_matrix);
A_direct.vmult (solution, system_rhs);
}
template <int dim>
void
StokesProblem<dim>::output_results (const unsigned int refinement_cycle) const
{
std::vector<std::string> solution_names (dim, "velocity");
solution_names.push_back ("pressure");
std::vector<DataComponentInterpretation::DataComponentInterpretation>
data_component_interpretation
(dim, DataComponentInterpretation::component_is_part_of_vector);
data_component_interpretation
.push_back (DataComponentInterpretation::component_is_scalar);
DataOut<dim> data_out;
data_out.attach_dof_handler (dof_handler);
data_out.add_data_vector (solution, solution_names,
DataOut<dim>::type_dof_data,
data_component_interpretation);
data_out.build_patches ();
std::ostringstream filename;
filename << "solution-"
<< Utilities::int_to_string (refinement_cycle, 2)
<< ".vtk";
std::ofstream output (filename.str().c_str());
data_out.write_vtk (output);
}
template <int dim>
void StokesProblem<dim>::run ()
{
{
std::vector<unsigned int> subdivisions (dim, 1);
subdivisions[0] = 4;
const Point<dim> bottom_left = (dim == 2 ?
Point<dim>(0,data::bottom) :
Point<dim>(-2,0,-1));
const Point<dim> top_right = (dim == 2 ?
Point<dim>(40,data::top) :
Point<dim>(0,1,0));
GridGenerator::subdivided_hyper_rectangle (triangulation,
subdivisions,
bottom_left,
top_right);
}
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)->center()[dim-1] == data::top)
cell->face(f)->set_all_boundary_ids(1);
else if (cell->face(f)->center()[dim-1] == data::bottom)
cell->face(f)->set_all_boundary_ids(2);
triangulation.refine_global (4);
setup_dofs ();
std::cout << " Assembling..." << std::endl << std::flush;
assemble_system ();
std::cout << " Solving..." << std::flush;
solve ();
output_results (1);
std::cout << std::endl;
}
}
int main ()
{
try
{
using namespace dealii;
using namespace Step22;
StokesProblem<data::dimension> flow_problem(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;
}