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>     &center,
                                       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> &center,
                                        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> &center, 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

Reply via email to