All,
I am having trouble with a 3D geometry/boundary description that I
have modeled after both the half hyper shell and quarter hyper shell
geometries. My geometry is a chunk of the 3D hyper shell (essentially
the 3D hyper shell cut off at z = += sqrt(3)x, z = +- sqrt(3)y) split
into 4 cells for the coarsest mesh, modeled after
GridGenerator::quarter_hyper_shell, including a colorize function. I
also implemented a boundary description based off
HalfHyperShellBoundary since I have two curved faces in my geometry
that I will want to refine and integrate over. I apply the curved
boundary description to only the two curved faces and apply no normal
flux boundary conditions on all six faces.
Unfortunately, when my ConstraintMatrix tries to close, I trigger the
exception "Cycle in constraints detected!" (line 304 of
source/lac/constraint_matrix). After doing some digging, I think the
corners are getting being overconstrained, but I can't figure out
why.
I don't have this problem in 2D, in 3D with Dirichlet boundary
conditions on the flat faces, or even in 3D with using the
quarter_hyper_shell and my own QuarterHyperShellBoundary written in
the same manner as my chunk boundary description. The first two I can
understand working, but the third case should be essentially the same
as my case, which leads me to believe the problem is in my grid or
colorize function. I can view the grid in paraview (switch to
Dirichlet on the flat faces in code below), and visually it looks as
it should, and I don't think I have vertex/cell numbering issues.
I've included a minimal code that will produce this error; a little
bit of the boundary functionality was left in for the visualization,
though it is unnecessary for producing the error. Any assistance in
finding where I'm going wrong would be greatly appreciated. Thanks in
advance,
Jennifer
-----------------------------------
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <grid/tria_boundary_lib.h>
#include <dofs/dof_handler.h>
#include <fe/fe_system.h>
#include <fe/mapping_q1.h>
#include <numerics/vectors.h>
#include <numerics/data_out.h>
#include <base/exceptions.h>
#include <base/function.h>
#include <fstream>
#include <ostream>
using namespace dealii;
template <int dim>
static void
colorize_sixty_deg_hyper_shell(Triangulation<dim> & tria,
const Point<dim>& center,
const double inner_radius,
const double outer_radius);
template<int dim>
static void sixty_deg_hyper_shell (Triangulation<dim> &tria,
const Point<dim> ¢er,
const double inner_radius,
const double outer_radius,
const unsigned int n_cells = 0,
const bool colorize = false);
template <int dim>
class SixtyDegHyperShellBoundary : public HyperShellBoundary<dim>
{
public:
SixtyDegHyperShellBoundary (const Point<dim> ¢er,
const double inner_radius,
const double outer_radius);
private:
const double inner_radius;
const double outer_radius;
};
// Implementation for 3D only
template <>
void
colorize_sixty_deg_hyper_shell(Triangulation<3> & tria,
const Point<3>& center,
const double
inner_radius,
const double
outer_radius)
{
if (tria.n_cells() != 4)
AssertThrow (false, ExcNotImplemented());
double middle = (outer_radius-inner_radius)/2e0 + inner_radius;
double eps = 1e-3*middle;
Triangulation<3>::cell_iterator cell = tria.begin();
for (;cell!=tria.end();++cell)
for(unsigned int f=0; f<GeometryInfo<3>::faces_per_cell; ++f)
{
if(!cell->face(f)->at_boundary())
continue;
double radius = cell->face(f)->center().norm() -
center.norm();
if (std::fabs(cell->face(f)->center()(2) -
sqrt(3.)*cell->face(f)->center()(0)) < eps ) // z = sqrt(3)x set
boundary 2
{
cell->face(f)->set_boundary_indicator(2);
for (unsigned int
j=0;j<GeometryInfo<3>::lines_per_face;++j)
if(cell->face(f)->line(j)->at_boundary())
if
(std::fabs(cell->face(f)->line(j)->vertex(0).norm() -
cell->face(f)->line(j)->vertex(1).norm()) > eps)
cell->face(f)->line(j)->set_boundary_indicator(2);
}
else if (std::fabs(cell->face(f)->center()(2) +
sqrt(3.)*cell->face(f)->center()(0)) < eps) // z = -sqrt(3)x set
boundary 3
{
cell->face(f)->set_boundary_indicator(3);
for (unsigned int
j=0;j<GeometryInfo<3>::lines_per_face;++j)
if(cell->face(f)->line(j)->at_boundary())
if
(std::fabs(cell->face(f)->line(j)->vertex(0).norm() -
cell->face(f)->line(j)->vertex(1).norm()) > eps)
cell->face(f)->line(j)->set_boundary_indicator(3);
}
else if (std::fabs(cell->face(f)->center()(2) -
sqrt(3.)*cell->face(f)->center()(1)) < eps ) // z = sqrt(3)y set
boundary 4
{
cell->face(f)->set_boundary_indicator(4);
for (unsigned int
j=0;j<GeometryInfo<3>::lines_per_face;++j)
if(cell->face(f)->line(j)->at_boundary())
if
(std::fabs(cell->face(f)->line(j)->vertex(0).norm() -
cell->face(f)->line(j)->vertex(1).norm()) > eps)
cell->face(f)->line(j)->set_boundary_indicator(4);
}
else if (std::fabs(cell->face(f)->center()(2) +
sqrt(3.)*cell->face(f)->center()(1)) < eps ) // z = -sqrt(3)y set
boundary 5
{
cell->face(f)->set_boundary_indicator(5);
for (unsigned int
j=0;j<GeometryInfo<3>::lines_per_face;++j)
if(cell->face(f)->line(j)->at_boundary())
if
(std::fabs(cell->face(f)->line(j)->vertex(0).norm() -
cell->face(f)->line(j)->vertex(1).norm()) > eps)
cell->face(f)->line(j)->set_boundary_indicator(5);
}
else if (radius < middle) // inner radius set boundary 0
{
cell->face(f)->set_boundary_indicator(0);
for (unsigned int
j=0;j<GeometryInfo<3>::lines_per_face;++j)
if(cell->face(f)->line(j)->at_boundary())
if
(std::fabs(cell->face(f)->line(j)->vertex(0).norm() -
cell->face(f)->line(j)->vertex(1).norm()) < eps)
cell->face(f)->line(j)->set_boundary_indicator(0);
}
else if (radius > middle) // outer radius set boundary 1
{
cell->face(f)->set_boundary_indicator(1);
for (unsigned int
j=0;j<GeometryInfo<3>::lines_per_face;++j)
if(cell->face(f)->line(j)->at_boundary())
if
(std::fabs(cell->face(f)->line(j)->vertex(0).norm() -
cell->face(f)->line(j)->vertex(1).norm()) < eps)
cell->face(f)->line(j)->set_boundary_indicator(1);
}
else
AssertThrow (false, ExcInternalError());
}
}
// Implementation for 3D only
template <>
void sixty_deg_hyper_shell (Triangulation<3> & tria,
const Point<3>& center,
const double inner_radius,
const double outer_radius,
const unsigned int n,
const bool colorize)
{
if (n == 0 || n == 2)
{
const double r0 = inner_radius;
const double r1 = outer_radius;
std::vector<Point<3> > vertices;
vertices.push_back (center+Point<3>( 0., 0., r0));
//0
vertices.push_back (center+Point<3>( 0., 0., r1));
//1
vertices.push_back (center+Point<3>( 0., 0.5*r0,
sqrt(3.)/2.0*r0)); //2
vertices.push_back (center+Point<3>( 0., 0.5*r1,
sqrt(3.)/2.0*r1)); //3
vertices.push_back (center+Point<3>( 0., -0.5*r0,
sqrt(3.)/2.0*r0)); //4
vertices.push_back (center+Point<3>( 0., -0.5*r1,
sqrt(3.)/2.0*r1)); //5
vertices.push_back (center+Point<3>( 0.5*r0, 0,
sqrt(3.)/2.0*r0)); //6
vertices.push_back (center+Point<3>( 0.5*r1, 0,
sqrt(3.)/2.0*r1)); //7
vertices.push_back (center+Point<3>( 1.0/sqrt(5.)*r0,
1.0/sqrt(5.)*r0, sqrt(3./5.)*r0)); //8
vertices.push_back (center+Point<3>( 1.0/sqrt(5.)*r1,
1.0/sqrt(5.)*r1, sqrt(3./5.)*r1)); //9
vertices.push_back (center+Point<3>( 1.0/sqrt(5.)*r0,
-1.0/sqrt(5.)*r0, sqrt(3./5.)*r0)); //10
vertices.push_back (center+Point<3>( 1.0/sqrt(5.)*r1,
-1.0/sqrt(5.)*r1, sqrt(3./5.)*r1)); //11
vertices.push_back (center+Point<3>( -0.5*r0, 0,
sqrt(3.)/2.0*r0)); //12
vertices.push_back (center+Point<3>( -0.5*r1, 0,
sqrt(3.)/2.0*r1)); //13
vertices.push_back (center+Point<3>( -1.0/sqrt(5.)*r0,
1.0/sqrt(5.)*r0, sqrt(3./5.)*r0)); //14
vertices.push_back (center+Point<3>( -1.0/sqrt(5.)*r1,
1.0/sqrt(5.)*r1, sqrt(3./5.)*r1)); //15
vertices.push_back (center+Point<3>( -1.0/sqrt(5.)*r0,
-1.0/sqrt(5.)*r0, sqrt(3./5.)*r0)); //16
vertices.push_back (center+Point<3>( -1.0/sqrt(5.)*r1,
-1.0/sqrt(5.)*r1, sqrt(3./5.)*r1)); //17
const int cell_vertices[4][8] = {
{12, 0, 14, 2, 13, 1, 15, 3},
{16, 4, 12, 0, 17, 5, 13, 1},
{0, 6, 2, 8, 1, 7, 3, 9},
{4, 10, 0, 6, 5, 11, 1, 7},
};
std::vector<CellData<3> > cells(4);
for (unsigned int i=0; i<4; ++i)
{
for (unsigned int j=0; j<8; ++j)
cells[i].vertices[j] = cell_vertices[i][j];
cells[i].material_id = 0;
}
tria.create_triangulation ( vertices, cells, SubCellData());
// no boundary information
}
else
{
AssertThrow(false, ExcNotImplemented());
}
if (colorize)
colorize_sixty_deg_hyper_shell(tria, center, inner_radius,
outer_radius);
}
template<int dim>
SixtyDegHyperShellBoundary<dim>::SixtyDegHyperShellBoundary (const
Point<dim> ¢er,
const double
inner_radius,
const double
outer_radius)
:
HyperShellBoundary<dim> (center),
inner_radius (inner_radius),
outer_radius (outer_radius)
{
if (dim > 2)
Assert ((inner_radius >= 0) &&
(outer_radius > 0) &&
(outer_radius > inner_radius),
ExcMessage ("Inner and outer radii must be specified
explicitly in 3d."));
}
template <int dim>
void run()
{
Triangulation<dim> triangulation;
FESystem<dim> fe(FE_Q<dim>(1), dim);
DoFHandler<dim> dof_handler (triangulation);
ConstraintMatrix constraints;
Vector<double> solution;
sixty_deg_hyper_shell (triangulation,
Point<dim>(),
0.5,
1.0,
2,
true);
static SixtyDegHyperShellBoundary<dim> boundary(Point<dim>(),
0.5,
1.0);
triangulation.set_boundary (0, boundary);
triangulation.set_boundary (1, boundary);
triangulation.refine_global(2);
dof_handler.distribute_dofs (fe);
solution.reinit(dof_handler.n_dofs());
solution = 0;
std::set<unsigned char> no_normal_flux_boundaries;
no_normal_flux_boundaries.insert (0);
VectorTools::compute_no_normal_flux_constraints
(dof_handler, 0,
no_normal_flux_boundaries,
constraints);
no_normal_flux_boundaries.insert (1);
VectorTools::compute_no_normal_flux_constraints
(dof_handler, 0,
no_normal_flux_boundaries,
constraints);
no_normal_flux_boundaries.insert (2);
VectorTools::compute_no_normal_flux_constraints
(dof_handler, 0,
no_normal_flux_boundaries,
constraints);
no_normal_flux_boundaries.insert (3);
VectorTools::compute_no_normal_flux_constraints
(dof_handler, 0,
no_normal_flux_boundaries,
constraints);
no_normal_flux_boundaries.insert (4);
VectorTools::compute_no_normal_flux_constraints
(dof_handler, 0,
no_normal_flux_boundaries,
constraints);
no_normal_flux_boundaries.insert (5);
VectorTools::compute_no_normal_flux_constraints
(dof_handler, 0,
no_normal_flux_boundaries,
constraints);
/*
VectorTools::interpolate_boundary_values (dof_handler,
2,
ZeroFunction<dim>(dim),
constraints);
VectorTools::interpolate_boundary_values (dof_handler,
3,
ZeroFunction<dim>(dim),
constraints);
VectorTools::interpolate_boundary_values (dof_handler,
4,
ZeroFunction<dim>(dim),
constraints);
VectorTools::interpolate_boundary_values (dof_handler,
5,
ZeroFunction<dim>(dim),
constraints);
*/
constraints.close();
DataOut<dim> data_out;
data_out.attach_dof_handler(dof_handler);
data_out.add_data_vector(solution, "solution");
data_out.build_patches();
const std::string filename = "solution.vtk";
std::ofstream output (filename.c_str());
data_out.write_vtk(output);
}
int main (int argc, char *argv[])
{
deallog.depth_console (0);
run<3>();
}
_______________________________________________
dealii mailing list http://poisson.dealii.org/mailman/listinfo/dealii