WaveBEM: Unsteady Nonlinear Potential Flow Solver for Ship-Wave Interaction.
computational_domain.cc
Go to the documentation of this file.
1 //---------------------------- step-34.cc ---------------------------
2 // $Id: step-34.cc 18734 2009-04-25 13:36:48Z heltai $
3 // Version: $Name$
4 //
5 // Copyright (C) 2009, 2010, 2011 by the deal.II authors
6 //
7 // This file is subject to QPL and may not be distributed
8 // without copyright and license information. Please refer
9 // to the file deal.II/doc/license.html for the text and
10 // further information on this license.
11 //
12 // Authors: Luca Heltai, Cataldo Manigrasso, Andrea Mola
13 //
14 //---------------------------- step-34.cc ---------------------------
15 
16 #define TOLL 0.001
17 #define MAXELEMENTSPERBLOCK 1
18 
19 #include "../include/computational_domain.h"
22 
23 // @sect4{ComputationalDomain::ComputationalDomain and
24 // ComputationalDomain::read_parameters}
25 // The constructor initializes the
26 // variuous object in much the same
27 // way as done in the finite element
28 // programs such as step-4 or
29 // step-6. The only new ingredient
30 // here is the ParsedFunction object,
31 // which needs, at construction time,
32 // the specification of the number of
33 // components.
34 //
35 // For the exact solution the number
36 // of vector components is one, and
37 // no action is required since one is
38 // the default value for a
39 // ParsedFunction object. The wind,
40 // however, requires dim components
41 // to be specified. Notice that when
42 // declaring entries in a parameter
43 // file for the expression of the
44 // Functions::ParsedFunction, we need
45 // to specify the number of
46 // components explicitly, since the
47 // function
48 // Functions::ParsedFunction::declare_parameters
49 // is static, and has no knowledge of
50 // the number of components.
51 template <int dim>
52 ComputationalDomain<dim>::ComputationalDomain(const unsigned int fe_degree,
53  const unsigned int mapping_degree)
54  :
55  mapping_degree(mapping_degree),
56  tria(coarse_tria),
57  fe(fe_degree),
58  dh(tria),
59  vector_fe(FE_Q<dim-1,dim>(fe_degree), dim),
60  vector_dh(tria),
61  mapping(NULL)
62 {}
63 
64 template <int dim>
66 {
67  if (blocks.size() > 0)
68  {
69  for (unsigned int ii = 0; ii < num_blocks; ii++)
70  delete blocks[ii];
71  }
72  if (mapping != NULL)
73  {
74  delete mapping;
75  mapping = NULL;
76  }
77 }
78 
79 
80 
81 template <int dim>
83 {
84  prm.enter_subsection("Quadrature rules");
85  {
86  prm.declare_entry("Quadrature type", "gauss",
87  Patterns::Selection(QuadratureSelector<(dim-1)>::get_quadrature_names()));
88  prm.declare_entry("Quadrature order", "4", Patterns::Integer());
89  prm.declare_entry("Singular quadrature order", "5", Patterns::Integer());
90  }
91  prm.leave_subsection();
92 
93 
94 
95  prm.enter_subsection("Boundary Conditions ID Numbers");
96  {
97  prm.declare_entry("Free Surface 1 ID", "1", Patterns::Integer());
98  prm.declare_entry("Free Surface 2 ID", "0", Patterns::Integer());
99  prm.declare_entry("Free Surface 3 ID", "0", Patterns::Integer());
100  prm.declare_entry("Wall Surface 1 ID", "0", Patterns::Integer());
101  prm.declare_entry("Wall Surface 2 ID", "0", Patterns::Integer());
102  prm.declare_entry("Wall Surface 3 ID", "0", Patterns::Integer());
103  prm.declare_entry("Inflow Surface 1 ID", "0", Patterns::Integer());
104  prm.declare_entry("Inflow Surface 2 ID", "0", Patterns::Integer());
105  prm.declare_entry("Inflow Surface 3 ID", "0", Patterns::Integer());
106  prm.declare_entry("Pressure Surface ID", "0", Patterns::Integer());
107  prm.declare_entry("Free Surface Edge On Boat ID", "0", Patterns::Integer());
108  }
109  prm.leave_subsection();
110 
111  prm.enter_subsection("Octree Params");
112  {
113  prm.declare_entry("Number of Octree Levels", "1", Patterns::Integer());
114  }
115  prm.leave_subsection();// to be moved
116 
117 }
118 
119 template <int dim>
121 {
122 
123  prm.enter_subsection("Quadrature rules");
124  {
125  quadrature =
126  std_cxx1x::shared_ptr<Quadrature<dim-1> >
127  (new QuadratureSelector<dim-1> (prm.get("Quadrature type"),
128  prm.get_integer("Quadrature order")));
129  singular_quadrature_order = prm.get_integer("Singular quadrature order");
130  }
131  prm.leave_subsection();
132 
133  prm.enter_subsection("Boundary Conditions ID Numbers");
134  {
135  free_sur_ID1 = prm.get_integer("Free Surface 1 ID");
136  free_sur_ID2 = prm.get_integer("Free Surface 2 ID");
137  free_sur_ID3 = prm.get_integer("Free Surface 3 ID");
138  wall_sur_ID1 = prm.get_integer("Wall Surface 1 ID");
139  wall_sur_ID2 = prm.get_integer("Wall Surface 2 ID");
140  wall_sur_ID3 = prm.get_integer("Wall Surface 3 ID");
141  inflow_sur_ID1 = prm.get_integer("Inflow Surface 1 ID");
142  inflow_sur_ID2 = prm.get_integer("Inflow Surface 2 ID");
143  inflow_sur_ID3 = prm.get_integer("Inflow Surface 3 ID");
144  pressure_sur_ID = prm.get_integer("Pressure Surface ID");
145  free_sur_edge_on_boat_ID = prm.get_integer("Free Surface Edge On Boat ID");
146  }
147  prm.leave_subsection();
148 
149  prm.enter_subsection("Octree Params");
150  {
151  num_octree_levels = prm.get_integer("Number of Octree Levels");
152  }
153  prm.leave_subsection();
154 
155 }
156 
157 
158 // @sect4{ComputationalDomain::read_domain}
159 
160 // A boundary element method
161 // triangulation is basically the
162 // same as a (dim-1) dimensional
163 // triangulation, with the difference
164 // that the vertices belong to a
165 // (dim) dimensional space.
166 //
167 // Some of the mesh formats supported
168 // in deal.II use by default three
169 // dimensional points to describe
170 // meshes. These are the formats
171 // which are compatible with the
172 // boundary element method
173 // capabilities of deal.II. In
174 // particular we can use either UCD
175 // or GMSH formats. In both cases, we
176 // have to be particularly careful
177 // with the orientation of the mesh,
178 // because, unlike in the standard
179 // finite element case, no reordering
180 // or compatibility check is
181 // performed here. All meshes are
182 // considered as oriented, because
183 // they are embedded in a higher
184 // dimensional space. (See the
185 // documentation of the GridIn and of
186 // the Triangulation for further
187 // details on orientation of cells in
188 // a triangulation.) In our case, the
189 // normals to the mesh are external
190 // to both the circle in 2d or the
191 // sphere in 3d.
192 //
193 // The other detail that is required
194 // for appropriate refinement of the
195 // boundary element mesh, is an
196 // accurate description of the
197 // manifold that the mesh is
198 // approximating. We already saw this
199 // several times for the boundary of
200 // standard finite element meshes
201 // (for example in step-5 and
202 // step-6), and here the principle
203 // and usage is the same, except that
204 // the HyperBallBoundary class takes
205 // an additional template parameter
206 // that specifies the embedding space
207 // dimension. The function object
208 // still has to be static to live at
209 // least as long as the triangulation
210 // object to which it is attached.
211 
212 template <int dim>
214 {
216  coarse_tria.set_mesh_smoothing (Triangulation<dim-1,dim>::do_not_produce_unrefined_islands );
218  coarse_tria.set_mesh_smoothing (Triangulation<dim-1,dim>::eliminate_refined_boundary_islands );
219 
220  tria.restore();
221 
222 }
223 
224 
225 // @sect4{ComputationalDomain::refine_and_resize}
226 
227 // This function globally refines the
228 // mesh, distributes degrees of
229 // freedom, and resizes matrices and
230 // vectors.
231 
232 template <int dim>
234 {}
235 
236 template <int dim>
238 {
239  min_diameter = 10000;
240  typename Triangulation<dim-1,dim>::active_cell_iterator
241  cell = tria.begin_active(), endc = tria.end();
242 
243  for ( ; cell != endc; ++cell)
244  {
245  min_diameter = std::min(min_diameter,cell->diameter());
246  }
247  std::cout << "Min diameter: << " << min_diameter << std::endl;
248 }
249 
250 
251 template <int dim>
253 {
254  return false;
255 }
256 
257 template <int dim>
259 {
260  std::cout<<"Generating double nodes set..."<<std::endl;
261 
262  // The following is the function
263  // which creates a set containing
264  // the double nodes.
265 
266 
267  std::vector<bool> boundary_dofs(vector_dh.n_dofs(),false);
268  std::vector< bool > comp_sel(dim,true);
269  DoFTools::extract_boundary_dofs(vector_dh,comp_sel,boundary_dofs);
270 
271  double tol = 1e-8;
272  double_nodes_set.clear();
273  double_nodes_set.resize(dh.n_dofs());
274  vector_double_nodes_set.clear();
275  vector_double_nodes_set.resize(vector_dh.n_dofs());
276 
277  update_support_points();
278 
279  for (unsigned int i=0; i<dh.n_dofs(); ++i)
280  {
281  double_nodes_set[i].insert(i);
282  for (unsigned int k=0; k<dim; ++k)
283  vector_double_nodes_set[dim*i+k].insert(dim*i+k);
284  if (boundary_dofs[dim*i] == true)
285  {
286  for (unsigned int j=0; j<dh.n_dofs(); ++j)
287  {
288  //std::cout<<"i "<<i<<" ("<<support_points[i]<<") j "<<j<<" ("<<support_points[j]<<") distance "<<support_points[i].distance(support_points[j])<<std::endl;
289  if (support_points[i].distance(support_points[j]) < tol)
290  {
291  //std::cout<<"i "<<i<<" ("<<support_points[i]<<") j "<<j<<" ("<<support_points[j]<<") distance "<<support_points[i].distance(support_points[j])<<std::endl;
292  double_nodes_set[i].insert(j);
293  //std::cout<<"i "<<i<<" double "<<j<<" "<<tol<<std::endl;
294  for (unsigned int k=0; k<dim; ++k)
295  {
296  vector_double_nodes_set[dim*i+k].insert(dim*j+k);
297  //std::cout<<"dim*i+k "<<dim*i+k<<" ("<<vector_support_points[dim*i+k]<<") dim*j+k "<<dim*j+k<<" ("<<vector_support_points[dim*j+k]<<") distance "<<vector_support_points[dim*i+k].distance(vector_support_points[dim*j+k])<<std::endl;
298  }
299  }
300  }
301  }
302 
303  }
304 
305 
306  std::cout<<"...done"<<std::endl;
307 }
308 
309 
310 
311 template <int dim>
313 {
314 
315  std::cout<<"Generating octree blocking... "<<std::endl;
316 
317  // @sect5{BEMProblem::generate_double_nodes_set}
318 
319  // The following is the function
320  // which creates the octree blocking
321  // for the fast multipole algorithm
322 
323 
324  std::vector<Point<dim> > support_points(dh.n_dofs());
325  DoFTools::map_dofs_to_support_points<dim-1, dim>( *mapping,
326  dh, support_points);
327 
328  FEValues<dim-1,dim> fe_v(*mapping,fe, *quadrature,
329  update_values |
330  update_cell_normal_vectors |
331  update_quadrature_points |
332  update_JxW_values);
333 
334  double max_coor_value = 0;
335 
336  for (unsigned int i=0; i < dh.n_dofs(); i++)
337  {
338  //for printout
339  //std::cout<<"Node "<<i<< "["<<support_points[i]<<"] "<<std::endl;
340  for (unsigned int j=0; j < dim; j++)
341  {
342  max_coor_value = std::max(max_coor_value,std::abs(support_points[i](j)));
343  }
344  }
345 
346  if (blocks.size() > 0)
347  {
348  for (unsigned int ii = 0; ii < num_blocks; ii++)
349  delete blocks[ii];
350  }
351 
352  unsigned int maxNumBlocks = num_octree_levels*tria.n_active_cells()*fe_v.n_quadrature_points;
353 //unsigned int maxNumBlocks = 0;
354 //for (unsigned int ii = 0; ii < num_octree_levels + 1; ii++)
355 // {
356 // maxNumBlocks += int(pow(8.,double(ii)));
357 // }
358 
359  blocks.clear();
360  blocks.reserve(maxNumBlocks);
361  blocks.resize(maxNumBlocks);
362 
363  unsigned int blocksCount = 0;
364  startLevel.resize(num_octree_levels+1);
365  endLevel.resize(num_octree_levels+1);
366 
367 //for (unsigned int j=0; j < num_octree_levels + 1; j++)
368 // parentList[j].clear();
369  parentList.clear();
370  parentList.resize(num_octree_levels+1);
371  parentList[0].push_back(0);
372 
373 
374  childlessList.clear();
375  unsigned int numChildless = 0;
376  numParent.resize(num_octree_levels+1);
377 
378 //qui di seguito vengono reinizializzate strutture utili al multipolo
379 
380 // mappa che associa ad ogni dof un vettore con i blocchi cui essa appartiene per ogni livello
381  dof_to_block.clear();
382 
383 // mappa che associa ad ogni quad point un vettore con i blocchi cui essa appartiene per ogni livello
384  quad_point_to_block.clear();
385 
386 // vettore di vettori contenente per ogni livello, gli ids dei blocchi
387 // contenenti almeno un dof
388  dofs_filled_blocks.clear();
389 
390 // vettore di vettori contenente per ogni livello, gli ids dei blocchi
391 // contenenti almeno un quad point
392  quad_points_filled_blocks.clear();
393 
394  quadPoints.clear();
395  quadNormals.clear();
396  quadShapeFunValues.clear();
397  quadJxW.clear();
398 
399  dofs_filled_blocks.resize(num_octree_levels+1);
400 
401  quad_points_filled_blocks.resize(num_octree_levels+1);
402 
403 
404 
405  for (unsigned int ii = 0; ii < num_octree_levels + 1 ; ii++)
406  {
407  numParent[ii] = 0;
408  }
409 
410 
411 
412  Point<dim> pMin;
413  for (int i=0; i<dim; i++)
414  pMin(i) = -1.1*max_coor_value;
415 
416  // delta e' il lato del kazzo di kubo...
417  double delta = 2.2*max_coor_value;
418 
419  OctreeBlock<dim> *block = new OctreeBlock<dim>(0, 0, pMin, delta);
420 
421  std::vector<unsigned int> local_dof_indices(fe.dofs_per_cell);
422  cell_it
423  cell = dh.begin_active(),
424  endc = dh.end();
425  for (cell = dh.begin_active(); cell != endc; ++cell)
426  {
427  fe_v.reinit(cell);
428  const unsigned int n_q_points = fe_v.n_quadrature_points;
429  quadPoints[cell] = fe_v.get_quadrature_points();
430  quadNormals[cell] = fe_v.get_normal_vectors();
431  quadJxW[cell].resize(n_q_points);
432  quadShapeFunValues[cell].resize(n_q_points);
433  for (unsigned int q=0; q<n_q_points; ++q)
434  {
435  quadJxW[cell][q] = fe_v.JxW(q);
436  for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
437  quadShapeFunValues[cell][q].push_back(fe_v.shape_value(j,q));
438  }
439 
440  quad_point_to_block[cell].resize(n_q_points);
441  for (unsigned int j=0; j<n_q_points; ++j)
442  {
443  block->AddQuadPoint(cell,j);
444  quad_point_to_block[cell][j].push_back(0);
445  }
446 
447  cell->get_dof_indices(local_dof_indices);
448  for (unsigned int j=0; j<fe.dofs_per_cell; ++j)
449  {
450  dof_to_elems[local_dof_indices[j]].push_back(cell);
451  }
452  }
453 
454  for (unsigned int ii = 0; ii < dh.n_dofs(); ii++)
455  {
456  block->AddNode(ii);
457  dof_to_block[ii].push_back(0);
458  }
459 
460 
461 // just for output
462  /*for (cell = dh.begin_active(); cell != endc; ++cell)
463  {
464  std::set<cell_it> surr_elems = elem_to_surr_elems[cell];
465  std::cout<<std::endl<<"cell "<<cell<<" surrounded by: ";
466  for (typename std::set<cell_it>::iterator pos = surr_elems.begin(); pos !=surr_elems.end(); pos++)
467  std::cout<<" "<<*pos;
468  }*/
469 
470  blocks[0] = block;
471  numParent[0] = 1;
472 
473 //std::cout<<"blocks[0].GetBlockChildrenNum() "<<blocks[0].GetBlockChildrenNum()<<std::endl;
474 
475  /*std::cout<<std::endl;
476  std::cout<<blocks[0].GetPMin()<<std::endl;
477  std::cout<<pMin<<std::endl;
478  std::cout<<block.GetDelta()<<std::endl;
479  std::cout<<block.GetBlockNodeList()[0]<<std::endl;
480  std::cout<<block.GetBlockElementsList()[1]<<std::endl;
481  std::cout<<delta<<std::endl;
482  std::cout<<std::endl;//*/
483 
484  unsigned int quadPointsInChildless = 0;
485  unsigned int nodesInChildless = 0;
486 
487  for (unsigned int level = 1; level < num_octree_levels + 1; level++)
488 
489  {
490  unsigned int quadPointsCheck = quadPointsInChildless;
491  unsigned int nodesCheck = nodesInChildless;
492  delta /= 2.;
493 
494  for (unsigned int kk = 0; kk < numParent[level-1]; kk++)
495 
496  {
497  unsigned int jj = parentList[level-1][kk];
498  //std::cout<<" level "<<level<<" block "<<jj<<std::endl;
499  OctreeBlock<dim> *parent = blocks[jj];
500  //std::cout<<"parent.GetBlockChildrenNum() "<<parent.GetBlockChildrenNum()<<std::endl;
501  //std::cout<<" Pmin "<<parent.GetPMin()(0)<<", "<<parent.GetPMin()(1)<<", "<<parent.GetPMin()(2)<<" "<<std::endl;
502  //std::cout<<" delta "<<parent.GetDelta()<<" "<<std::endl;
503 
504  pMin = parent->GetPMin();
505  unsigned int num_children_per_block = int(pow((double)2,(double)dim));
506  std::vector<OctreeBlock<dim> *> children(num_children_per_block);
507 
508  if (dim == 3)
509  {
510  children[0] = new OctreeBlock<dim>(level, jj, pMin , delta);
511  children[1] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(delta ,0., 0.), delta);
512  children[2] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(delta,delta, 0.), delta);
513  children[3] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(0. ,delta, 0.), delta);
514  children[4] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(0. , 0.,delta), delta);
515  children[5] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(delta, 0.,delta), delta);
516  children[6] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(delta,delta,delta), delta);
517  children[7] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>( 0.,delta,delta), delta);
518  }
519 
520  if (dim == 2)
521  {
522  children[0] = new OctreeBlock<dim>(level, jj, pMin , delta);
523  children[1] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(delta ,0.), delta);
524  children[2] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(delta,delta), delta);
525  children[3] = new OctreeBlock<dim>(level, jj, pMin+Point<dim>(0. ,delta), delta);
526 
527  }
528 
529  std::map <cell_it, std::vector <unsigned int> > blockQuadPointsList =
530  parent->GetBlockQuadPointsList();
531 
532  std::vector <unsigned int> blockNodeList = parent->GetBlockNodeList();
533 
534  if (dim == 3)
535  {
536  for (unsigned int i = 0; i < blockNodeList.size(); i++)
537  {
538  Point <dim> node = support_points[blockNodeList[i]];
539  // assegnamento nodi del blocco padre ai blocchi figli
540 
541  if (node(2) <= parent->GetPMin()(2)+delta)
542  {
543  if (node(1) <= parent->GetPMin()(1)+delta)
544  {
545  if (node(0) <= parent->GetPMin()(0)+delta)
546  {
547  //std::cout<<" Sono in 1 "<<std::endl;
548  children[0]->AddNode(blockNodeList[i]);
549  }
550  else
551  {
552  //std::cout<<" Sono in 2 "<<std::endl;
553  children[1]->AddNode(blockNodeList[i]);
554  }
555  }
556  else
557  {
558  if (node(0) <= parent->GetPMin()(0)+delta)
559  {
560  //std::cout<<" Sono in 4 "<<std::endl;
561  children[3]->AddNode(blockNodeList[i]);
562  }
563  else
564  {
565  //std::cout<<" Sono in 3 "<<std::endl;
566  children[2]->AddNode(blockNodeList[i]);
567  }
568  }
569  }
570  else
571  {
572  if (node(1) <= parent->GetPMin()(1)+delta)
573  {
574  if (node(0) <= parent->GetPMin()(0)+delta)
575  {
576  //std::cout<<" Sono in 5 "<<std::endl;
577  children[4]->AddNode(blockNodeList[i]);
578  }
579  else
580  {
581  //std::cout<<" Sono in 6 "<<std::endl;
582  children[5]->AddNode(blockNodeList[i]);
583  }
584  }
585  else
586  {
587  if (node(0) <= parent->GetPMin()(0)+delta)
588  {
589  //std::cout<<" Sono in 8 "<<std::endl;
590  children[7]->AddNode(blockNodeList[i]);
591  }
592  else
593  {
594  //std::cout<<" Sono in 7 "<<std::endl;
595  children[6]->AddNode(blockNodeList[i]);
596  }
597  }
598  } //fine assegnazione nodi del padre ai blocchi figli
599 
600  } //fine loop nodi del blocco
601 
602  typename std::map <cell_it, std::vector<unsigned int> >::iterator it;
603  for (it = blockQuadPointsList.begin(); it != blockQuadPointsList.end(); it++)
604  {
605  for (unsigned int pp = 0; pp < (*it).second.size(); pp++)
606  {
607  Point<dim> quadPoint = quadPoints[(*it).first][(*it).second[pp]];
608  // assegnamento punti quadratura del blocco padre ai blocchi figli
609  if (quadPoint(2) <= parent->GetPMin()(2)+delta)
610  {
611  if (quadPoint(1) <= parent->GetPMin()(1)+delta)
612  {
613  if (quadPoint(0) <= parent->GetPMin()(0)+delta)
614  {
615  //std::cout<<" Sono in 1 "<<std::endl;
616  children[0]->AddQuadPoint((*it).first,(*it).second[pp]);
617  }
618  else
619  {
620  //std::cout<<" Sono in 2 "<<std::endl;
621  children[1]->AddQuadPoint((*it).first,(*it).second[pp]);
622  }
623  }
624  else
625  {
626  if (quadPoint(0) <= parent->GetPMin()(0)+delta)
627  {
628  //std::cout<<" Sono in 4 "<<std::endl;
629  children[3]->AddQuadPoint((*it).first,(*it).second[pp]);
630  }
631  else
632  {
633  //std::cout<<" Sono in 3 "<<std::endl;
634  children[2]->AddQuadPoint((*it).first,(*it).second[pp]);
635  }
636  }
637  }
638  else
639  {
640  if (quadPoint(1) <= parent->GetPMin()(1)+delta)
641  {
642  if (quadPoint(0) <= parent->GetPMin()(0)+delta)
643  {
644  //std::cout<<" Sono in 5 "<<std::endl;
645  children[4]->AddQuadPoint((*it).first,(*it).second[pp]);
646  }
647  else
648  {
649  //std::cout<<" Sono in 6 "<<std::endl;
650  children[5]->AddQuadPoint((*it).first,(*it).second[pp]);
651  }
652  }
653  else
654  {
655  if (quadPoint(0) <= parent->GetPMin()(0)+delta)
656  {
657  //std::cout<<" Sono in 8 "<<std::endl;
658  children[7]->AddQuadPoint((*it).first,(*it).second[pp]);
659  }
660  else
661  {
662  //std::cout<<" Sono in 7 "<<std::endl;
663  children[6]->AddQuadPoint((*it).first,(*it).second[pp]);
664  }
665  }
666  } //fine assegnazione punti quadratura del padre ai blocchi figli
667  }
668  } //fine loop punti quadratura del blocco
669 
670  for (unsigned int j=0; j < num_children_per_block; j++ )
671  {
672  if (children[j]->GetBlockNodeList().size() +
673  children[j]->GetBlockQuadPointsList().size()> 0)
674  {
675  blocksCount += 1;
676  blocks[blocksCount] = new OctreeBlock<dim>();
677  blocks[blocksCount]->CopyContent(children[j]);
678  delete children[j];
679 
680  parent->AddChild(blocksCount);
681  std::map <cell_it, std::vector<unsigned int> >
682  blockQuadPointsList = blocks[blocksCount]->GetBlockQuadPointsList();
683  typename std::map <cell_it, std::vector<unsigned int> >::iterator it;
684  for (it = blockQuadPointsList.begin(); it != blockQuadPointsList.end(); it++)
685  {
686  cell_it cell = (*it).first;
687  for (unsigned int kk = 0; kk < (*it).second.size(); kk++)
688  {
689  quad_point_to_block[(*it).first][(*it).second[kk]].push_back(blocksCount);
690  }
691  }
692  std::vector<unsigned int> blockNodesList = blocks[jj]->GetBlockNodeList();
693  for (unsigned int k = 0; k < blockNodesList.size(); k++)
694  dof_to_block[blockNodesList[k]].push_back(jj);
695 
696  }
697  else
698  {
699  delete children[j];
700  }
701 
702  } // fine loop sui blocchi figlio appena creati
703 
704  } //fine ramo dim = 3 dell'if
705  else
706  {
707  for (unsigned int i = 0; i < blockNodeList.size(); i++)
708  {
709 
710  // assegnamento nodi del blocco padre ai blocchi figli
711  Point <dim> node = support_points[blockNodeList[i]];
712 
713  if (node(1) <= parent->GetPMin()(1)+delta)
714  {
715  if (node(0) <= parent->GetPMin()(0)+delta)
716  {
717  //std::cout<<" Sono in 1 "<<std::endl;
718  children[0]->AddNode(blockNodeList[i]);
719  }
720  else
721  {
722  //std::cout<<" Sono in 2 "<<std::endl;
723  children[1]->AddNode(blockNodeList[i]);
724  }
725  }
726  else
727  {
728  if (node(0) <= parent->GetPMin()(0)+delta)
729  {
730  //std::cout<<" Sono in 4 "<<std::endl;
731  children[3]->AddNode(blockNodeList[i]);
732  }
733  else
734  {
735  //std::cout<<" Sono in 3 "<<std::endl;
736  children[2]->AddNode(blockNodeList[i]);
737  }
738  }//fine assegnazione blocchi del padre ai blocchi figli
739 
740  } //fine loop nodi del blocco
741 
742  typename std::map <cell_it, std::vector<unsigned int> >::iterator it;
743  for (it = blockQuadPointsList.begin(); it != blockQuadPointsList.end(); it++)
744  {
745  for (unsigned int pp = 0; pp < (*it).second.size(); pp++)
746  {
747  // assegnamento quad points del blocco padre ai blocchi figli
748  Point<dim> quadPoint = quadPoints[(*it).first][(*it).second[pp]];
749  if (quadPoint(1) <= parent->GetPMin()(1)+delta)
750  {
751  if (quadPoint(0) <= parent->GetPMin()(0)+delta)
752  {
753  //std::cout<<" Sono in 1 "<<std::endl;
754  children[0]->AddQuadPoint((*it).first,(*it).second[pp]);
755  }
756  else
757  {
758  //std::cout<<" Sono in 2 "<<std::endl;
759  children[1]->AddQuadPoint((*it).first,(*it).second[pp]);
760  }
761  }
762  else
763  {
764  if (quadPoint(0) <= parent->GetPMin()(0)+delta)
765  {
766  //std::cout<<" Sono in 4 "<<std::endl;
767  children[3]->AddQuadPoint((*it).first,(*it).second[pp]);
768  }
769  else
770  {
771  //std::cout<<" Sono in 3 "<<std::endl;
772  children[2]->AddQuadPoint((*it).first,(*it).second[pp]);
773  }
774  }//fine assegnazione blocchi del padre ai blocchi figli
775 
776  }
777  }
778 
779  for (unsigned int j=0; j < num_children_per_block; j++ )
780  {
781  if (children[j]->GetBlockNodeList().size() +
782  children[j]->GetBlockQuadPointsList().size()> 0)
783  {
784  blocksCount += 1;
785  blocks[blocksCount] = new OctreeBlock<dim>();
786  blocks[blocksCount]->CopyContent(children[j]);
787  delete children[j];
788 
789  parent->AddChild(blocksCount);
790  std::map <cell_it, std::vector<unsigned int> >
791  blockQuadPointsList = blocks[blocksCount]->GetBlockQuadPointsList();
792  typename std::map <cell_it, std::vector<unsigned int> >::iterator it;
793  for (it = blockQuadPointsList.begin(); it != blockQuadPointsList.end(); it++)
794  {
795  cell_it cell = (*it).first;
796  for (unsigned int kk = 0; kk < (*it).second.size(); kk++)
797  {
798  quad_point_to_block[(*it).first][(*it).second[kk]].push_back(blocksCount);
799  }
800  }
801  std::vector<unsigned int> blockNodesList = blocks[jj]->GetBlockNodeList();
802  for (unsigned int k = 0; k < blockNodesList.size(); k++)
803  dof_to_block[blockNodesList[k]].push_back(jj);
804 
805  }
806  else
807  {
808  delete children[j];
809  }
810 
811  } // fine loop sui blocchi figlio appena creati
812 
813 
814  } // fine ramo dim == 2 dell'if
815 
816  } //fine loop blocchi livello precedente
817 
818 
819  //double elemCheck = numChildless;
820 
821  startLevel[level] = endLevel[level-1] + 1;
822  endLevel[level] = blocksCount;
823 
824  // here we loop over the blocks of the newly created level and
825  // we decide if each block is to be split again in the next level:
826  // if it contains more
827  // than a node or quad point, it will be placed in the parent list.
828  // Instead, if it only contains a node or quad point, it goes in the
829  // childless list, and not be refined any more. It is important to
830  // account for the presence of double nodes: if not, blocks will be
831  // always refined
832  for (unsigned int jj = startLevel[level]; jj < endLevel[level]+1; jj++)
833  {
834 
835  // here we get the number of nodes in the block
836  std::vector<unsigned int> nodesId = blocks[jj]->GetBlockNodeList();
837  int blockNumNodes = (int) nodesId.size();
838 
839  // now we compute the number of the nodes that are double of others
840  int numDoubleNodes = 0;
841  for (unsigned int kk = 0; kk < nodesId.size(); kk++)
842  {
843  int a = (int) double_nodes_set[nodesId[kk]].size();
844  numDoubleNodes += a - 1;
845  }
846 
847  // here we compute the number of quad points in the block
848  int blockNumQuadPoints = 0;
849  std::map <cell_it, std::vector<unsigned int> >
850  blockQuadPointsList = blocks[jj]->GetBlockQuadPointsList();
851  typename std::map <cell_it, std::vector<unsigned int> >::iterator it;
852  for (it = blockQuadPointsList.begin(); it != blockQuadPointsList.end(); it++)
853  blockNumQuadPoints += (int) (*it).second.size();
854  //std::cout<<"Level "<<level<<" Block "<<jj<<" nodes "<<blockNumNodes<<" + quadPoints "<<blockNumQuadPoints<<std::endl;
855 
856  quadPointsCheck += blockNumQuadPoints;
857  nodesCheck += blockNumNodes;
858  // here we decide if a block is to be placed in the parent
859  // or childless list
860  //if (blockNumNodes + blockNumQuadPoints - numDoubleNodes < 2)
861  if (blockNumNodes - numDoubleNodes < 2)
862  {
863  numChildless += 1;
864  childlessList.push_back(jj);
865  quadPointsInChildless += blockNumQuadPoints;
866  nodesInChildless += blockNumNodes;
867 
868 
869  // if a block is childless, we must assign now the nodes and quad points
870  // that belong to it for all the next levels
871 
872  for (unsigned int kk = 0; kk < nodesId.size(); kk++)
873  for (unsigned int j = level+1; j < num_octree_levels+1; j++)
874  dof_to_block[nodesId[kk]].push_back(jj);
875 
876  for (it = blockQuadPointsList.begin(); it != blockQuadPointsList.end(); it++)
877  for (unsigned int i = 0; i < (*it).second.size(); i++)
878  for (unsigned int j = level+1; j < num_octree_levels+1; j++)
879  quad_point_to_block[(*it).first][(*it).second[i]].push_back(jj);
880 
881  }
882  else
883  {
884  numParent[level] += 1;
885  parentList[level].push_back(jj);
886  }
887 
888  // let's update the list of node filled block
889  if (blockNumNodes > 0)
890  dofs_filled_blocks[level].push_back(jj);
891 
892  // let's update the list of quad point filled block
893  if (blockNumQuadPoints > 0)
894  quad_points_filled_blocks[level].push_back(jj);
895  //elemCheck += blockNumNodes + blockNumQuadPoints;
896  }
897 
898 
899  std::cout<<" Total nodes at level "<<level<<" of "<<num_octree_levels<<" are "<<nodesCheck<<std::endl;
900  std::cout<<" Total quad points at level "<<level<<" of "<<num_octree_levels<<" are "<<quadPointsCheck<<std::endl;
901  std::cout<<" Blocks at level "<<level<<" of "<<num_octree_levels<<" are "<<endLevel[level]-endLevel[level-1]<<std::endl;
902  std::cout<<" Total blocks at level "<<level<<" of "<<num_octree_levels<<" are "<<endLevel[level] + 1<<std::endl;
903  std::cout<<std::endl;
904 
905  } //fine loop livelli
906 
907  childlessList.resize(childlessList.size()+parentList[num_octree_levels].size());
908 
909  for (unsigned int jj = 0; jj < parentList[num_octree_levels].size(); jj++)
910  {
911  childlessList[numChildless + jj] = parentList[num_octree_levels][jj];
912  }
913 
914 
915 
916 
917  num_blocks = blocksCount+1;
918 
919 
920  std::cout<<"...done generating octree blocking"<<std::endl;
921 
922  std::cout<<"Computing proximity lists for blocks"<<std::endl;
923 
924 //just for output
925  /*for (cell = dh.begin_active(); cell != endc; ++cell)
926  {
927  unsigned int levelCheck = elem_to_blocks[cell].size();
928  std::cout<<std::endl<<"Elem "<<cell<<" is in the "<<levelCheck<<" blocks: ";
929  for (unsigned int zz = 0; zz < levelCheck; zz++)
930  std::cout<<elem_to_blocks[cell][zz]<<" ";
931  }*/
932 
933  /*for (cell_it cell = dh.begin_active(); cell != endc; ++cell)
934  for (unsigned int j=0; j < quadPoints[cell].size(); j++)
935  std::cout<<"Cell "<<cell<<" QP "<<j<<" of "<<quadPoints[cell].size()<<": "<<quadPoints[cell][j]<<std::endl;//*/
936 
937  /*for (cell_it cell = dh.begin_active(); cell != endc; ++cell)
938  for (unsigned int j=0; j < quad_point_to_block[cell].size(); j++)
939  {
940  std::cout<<"Cell "<<cell<<" QP "<<j<<" of "<<quad_point_to_block[cell].size()<<": ";
941  for (unsigned int i=0; i < quad_point_to_block[cell][j].size(); i++)
942  std::cout<<quad_point_to_block[cell][j][i]<<" ";
943  std::cout<<std::endl;
944  } //*/
945 
946 
947  /*for (unsigned int i=0; i < dh.n_dofs(); i++)
948  {
949  std::cout<<"Node "<<i<<" doubles: ";
950  std::set <unsigned int> doubleNodes = double_nodes_set[i];
951  for (std::set<unsigned int>::iterator pos = doubleNodes.begin(); pos != doubleNodes.end(); pos++)
952  {
953  std::cout<<*pos<<"( ";
954  for (unsigned int j=0; j < dof_to_elems[*pos].size(); j++)
955  std::cout<<" "<<dof_to_elems[*pos][j];
956  std::cout<<") ";
957  }
958  std::cout<<std::endl;
959  } //*/
960 
961 
962 
963 // ricerca blocchi nearest neighbors
964 
965  for (unsigned int ii = startLevel[1]; ii < endLevel[1] + 1; ii++)
966  {
967  for (unsigned int jj = startLevel[1]; jj < endLevel[1] + 1; jj++)
968  {
969  blocks[ii]->AddNearNeigh(0,jj);
970  }
971  }
972 
973 
974  for (unsigned int level = 2; level < num_octree_levels + 1; level++)
975 
976  {
977  for (unsigned int kk = startLevel[level]; kk < endLevel[level]+1; kk++)
978 
979  {
980  OctreeBlock<dim> *block1 = blocks[kk];
981  block1->AddNearNeigh(0,kk); // a block is NearNeigh of itself
982 
983  double delta1 = block1->GetDelta();
984  Point<dim> PMin1 = block1->GetPMin();
985  Point<dim> Center1;
986  for (unsigned int iii = 0; iii < dim; iii++)
987  Center1(iii) = delta1/2.;
988  Point<dim> PMax1 = 2.*Center1;
989  PMax1 += PMin1;
990  Center1 += PMin1;
991  unsigned int parentId = block1->GetParentId();
992  std::set <unsigned int> parentNNeighs = blocks[parentId]->GetNearNeighs(0);
993 
994  // the nearest neighbors are searched among the father's nearest neighbors children
995  for (std::set <unsigned int>::iterator pos = parentNNeighs.begin(); pos != parentNNeighs.end(); pos++)
996 
997  {
998  if (blocks[*pos]->GetBlockChildrenNum() == 0) // if a parent's near neigh is childless, he can be a near neigh: let's check
999  {
1000  unsigned int block2Id = *pos;
1001  OctreeBlock<dim> *block2 = blocks[block2Id];
1002  double delta2 = block2->GetDelta();
1003  Point<dim> PMin2 = block2->GetPMin();
1004  Point<dim> Center2;
1005  for (unsigned int iii = 0; iii < dim; iii++)
1006  Center2(iii) = delta2/2.;
1007  Point<dim> PMax2 = 2.*Center2;
1008  PMax2 += PMin2;
1009  Center2 += PMin2;
1010 
1011  if (dim == 3)
1012  {
1013  if ((fabs(PMin1(0) - PMax2(0)) <= TOLL) || (fabs(PMax1(0) - PMin2(0)) <= TOLL))
1014  {
1015  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1016  {
1017  if ((PMin1(2)-TOLL <= PMax2(2)) && (PMax1(2)+TOLL >= PMin2(2)))
1018  {
1019  block1->AddNearNeigh(0,block2Id);
1020  //std::cout<<" *"<<block2Id;
1021  }
1022  }
1023  }
1024 
1025  if ((fabs(PMin1(1) - PMax2(1)) <= TOLL) || (fabs(PMax1(1) - PMin2(1)) <= TOLL))
1026  {
1027  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1028  {
1029  if ((PMin1(2)-TOLL <= PMax2(2)) && (PMax1(2)+TOLL >= PMin2(2)))
1030  {
1031  block1->AddNearNeigh(0,block2Id);
1032  //std::cout<<" *"<<block2Id;
1033  }
1034  }
1035  }
1036 
1037  if ((fabs(PMin1(2) - PMax2(2)) <= TOLL) || (fabs(PMax1(2) - PMin2(2)) <= TOLL))
1038  {
1039  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1040  {
1041  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1042  {
1043  block1->AddNearNeigh(0,block2Id);
1044  //std::cout<<" *"<<block2Id;
1045  }
1046  }
1047  }
1048  } //fine caso dim ==3
1049 
1050  else if (dim == 2)
1051  {
1052  if ((fabs(PMin1(0) - PMax2(0)) <= TOLL) || (fabs(PMax1(0) - PMin2(0)) <= TOLL))
1053  {
1054  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1055  {
1056  block1->AddNearNeigh(0,block2Id);
1057  //std::cout<<block2Id<<" ";
1058  }
1059  }
1060 
1061  if ((fabs(PMin1(1) - PMax2(1)) <= TOLL) || (fabs(PMax1(1) - PMin2(1)) <= TOLL))
1062  {
1063  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1064  {
1065  block1->AddNearNeigh(0,block2Id);
1066  //std::cout<<block2Id<<" ";
1067  }
1068  }
1069 
1070  } // fine caso dim == 2
1071 
1072  }
1073 
1074  for (unsigned int ii = 0; ii < blocks[*pos]->GetBlockChildrenNum(); ii++)
1075  {
1076  unsigned int block2Id = blocks[*pos]->GetChildId(ii);
1077  OctreeBlock<dim> *block2 = blocks[block2Id];
1078  double delta2 = block2->GetDelta();
1079  Point<dim> PMin2 = block2->GetPMin();
1080  Point<dim> Center2;
1081  for (unsigned int iii = 0; iii < dim; iii++)
1082  Center2(iii) = delta2/2.;
1083  Point<dim> PMax2 = 2.*Center2;
1084  PMax2 += PMin2;
1085  Center2 += PMin2;
1086 
1087  if (dim == 3)
1088  {
1089  if ((fabs(PMin1(0) - PMax2(0)) <= TOLL) || (fabs(PMax1(0) - PMin2(0)) <= TOLL))
1090  {
1091  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1092  {
1093  if ((PMin1(2)-TOLL <= PMax2(2)) && (PMax1(2)+TOLL >= PMin2(2)))
1094  {
1095  block1->AddNearNeigh(0,block2Id);
1096  //std::cout<<" "<<block2Id;
1097  }
1098  }
1099  }
1100 
1101  if ((fabs(PMin1(1) - PMax2(1)) <= TOLL) || (fabs(PMax1(1) - PMin2(1)) <= TOLL))
1102  {
1103  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1104  {
1105  if ((PMin1(2)-TOLL <= PMax2(2)) && (PMax1(2)+TOLL >= PMin2(2)))
1106  {
1107  block1->AddNearNeigh(0,block2Id);
1108  //std::cout<<" "<<block2Id;
1109  }
1110  }
1111  }
1112 
1113  if ((fabs(PMin1(2) - PMax2(2)) <= TOLL) || (fabs(PMax1(2) - PMin2(2)) <= TOLL))
1114  {
1115  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1116  {
1117  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1118  {
1119  block1->AddNearNeigh(0,block2Id);
1120  //std::cout<<" "<<block2Id;
1121  }
1122  }
1123  }
1124  } //fine caso dim ==3
1125 
1126  else if (dim == 2)
1127  {
1128  if ((fabs(PMin1(0) - PMax2(0)) <= TOLL) || (fabs(PMax1(0) - PMin2(0)) <= TOLL))
1129  {
1130  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1131  {
1132  block1->AddNearNeigh(0,block2Id);
1133  //std::cout<<block2Id<<" ";
1134  }
1135  }
1136 
1137  if ((fabs(PMin1(1) - PMax2(1)) <= TOLL) || (fabs(PMax1(1) - PMin2(1)) <= TOLL))
1138  {
1139  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1140  {
1141  block1->AddNearNeigh(0,block2Id);
1142  //std::cout<<block2Id<<" ";
1143  }
1144  }
1145 
1146  } // fine caso dim == 2
1147 
1148  } // fine loop sui figli di un nearest neighbor del padre
1149 
1150 
1151  } // fine loop sui nearest neighbors del padre
1152 
1153 
1154 
1155  if ((block1->GetBlockChildrenNum() == 0)) // if the block is childless we must compute now its nearneigh at all residual levels
1156  {
1157  block1->SetNearNeighSize(num_octree_levels-level+1);
1158  block1->SetIntListSize(num_octree_levels-level+1); // intList is a vector of sets with the same number of members of nearNeigh
1159  block1->SetNonIntListSize(num_octree_levels-level+1); // nonIntList is a vector of sets with the same number of members of nearNeigh
1160 
1161  for (unsigned int subLevel = 1; subLevel < num_octree_levels - level + 1; subLevel++)
1162 
1163  {
1164 
1165  std::set <unsigned int> upperLevelNNeighs = block1->GetNearNeighs(subLevel-1);
1166  for (std::set <unsigned int>::iterator pos = upperLevelNNeighs.begin(); pos != upperLevelNNeighs.end(); pos++)
1167 
1168  {
1169  if (blocks[*pos]->GetBlockChildrenNum() == 0) // if nearneigh is childless, it will stay a near neigh
1170  block1->AddNearNeigh(subLevel,*pos);
1171 
1172  for (unsigned int ii = 0; ii < blocks[*pos]->GetBlockChildrenNum(); ii++)
1173  {
1174  unsigned int block2Id = blocks[*pos]->GetChildId(ii);
1175  OctreeBlock<dim> *block2 = blocks[block2Id];
1176  double delta2 = block2->GetDelta();
1177  Point<dim> PMin2 = block2->GetPMin();
1178  Point<dim> Center2;
1179  for (unsigned int iii = 0; iii < dim; iii++)
1180  Center2(iii) = delta2/2.;
1181  Point<dim> PMax2 = 2.*Center2;
1182  PMax2 += PMin2;
1183  Center2 += PMin2;
1184 
1185  if (dim == 3)
1186  {
1187  if ((fabs(PMin1(0) - PMax2(0)) <= TOLL) || (fabs(PMax1(0) - PMin2(0)) <= TOLL))
1188  {
1189  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1190  {
1191  if ((PMin1(2)-TOLL <= PMax2(2)) && (PMax1(2)+TOLL >= PMin2(2)))
1192  {
1193  block1->AddNearNeigh(subLevel,block2Id);
1194  //std::cout<<block2Id<<" ";
1195  }
1196  }
1197  }
1198 
1199  if ((fabs(PMin1(1) - PMax2(1)) <= TOLL) || (fabs(PMax1(1) - PMin2(1)) <= TOLL))
1200  {
1201  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1202  {
1203  if ((PMin1(2)-TOLL <= PMax2(2)) && (PMax1(2)+TOLL >= PMin2(2)))
1204  {
1205  block1->AddNearNeigh(subLevel,block2Id);
1206  //std::cout<<block2Id<<" ";
1207  }
1208  }
1209  }
1210 
1211  if ((fabs(PMin1(2) - PMax2(2)) <= TOLL) || (fabs(PMax1(2) - PMin2(2)) <= TOLL))
1212  {
1213  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1214  {
1215  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1216  {
1217  block1->AddNearNeigh(subLevel,block2Id);
1218  //std::cout<<block2Id<<" ";
1219  }
1220  }
1221  }
1222  } //fine caso dim ==3
1223 
1224  else if (dim == 2)
1225  {
1226  if ((fabs(PMin1(0) - PMax2(0)) <= TOLL) || (fabs(PMax1(0) - PMin2(0)) <= TOLL))
1227  {
1228  if ((PMin1(1)-TOLL <= PMax2(1)) && (PMax1(1)+TOLL >= PMin2(1)))
1229  {
1230  block1->AddNearNeigh(subLevel,block2Id);
1231  //std::cout<<block2Id<<" ";
1232  }
1233  }
1234 
1235  if ((fabs(PMin1(1) - PMax2(1)) <= TOLL) || (fabs(PMax1(1) - PMin2(1)) <= TOLL))
1236  {
1237  if ((PMin1(0)-TOLL <= PMax2(0)) && (PMax1(0)+TOLL >= PMin2(0)))
1238  {
1239  block1->AddNearNeigh(subLevel,block2Id);
1240  //std::cout<<block2Id<<" ";
1241  }
1242  }
1243 
1244  } // fine caso dim == 2
1245 
1246  } // fine loop sui figli di ciascun nearest neighbor del blocco childless
1247 
1248 
1249  } // fine loop sui nearest neighbors del blocco childless
1250 
1251 
1252  } // fine loop sui subLevels (da quello del blocco childless all'ultimo)
1253 
1254 
1255  } // fine if (il blocco e' childless?)
1256 
1257 
1258 
1259  } // fine loop sui blocchi di un livello
1260 
1261  } // fine loop sui livelli
1262 
1263 //for printout
1264 
1265  /*std::cout<<std::endl;
1266  std::cout<<"-------------------------------- "<<std::endl;
1267  std::cout<<"-------------------------------- "<<std::endl;
1268  std::cout<<std::endl;
1269 
1270  //for printout
1271  for (cell=dh.begin_active();cell!=endc; cell++)
1272  {
1273  std::cout<<std::endl;
1274  std::cout<<"-------------------------------- "<<std::endl;
1275  std::cout<<"Cell "<<cell<<" elementPlot(";
1276  cell->get_dof_indices(local_dof_indices);
1277  for (unsigned int j = 0; j<local_dof_indices.size(); j++)
1278  std::cout<<"["<<support_points[local_dof_indices[j]]<<"],";
1279  std::cout<<"'r')";
1280  }
1281 
1282  std::cout<<std::endl;
1283  std::cout<<"-------------------------------- "<<std::endl;
1284  std::cout<<"-------------------------------- "<<std::endl;
1285  std::cout<<std::endl;
1286  std::cout<<std::endl;//*/
1287 
1288 
1289 // search for interaction list blocks (NearNeigh + NearNeighOfNearNeigh)
1290 // and for non interaction list blocks (nonIntList for a block B is composed by blocks that are children
1291 // of blocks being in intList of B's parent, but are not in intList of B)
1292 
1293  for (unsigned int ii = startLevel[1]; ii < endLevel[1] + 1; ii++) // at level 1, add all blocks to intList
1294  {
1295  for (unsigned int jj = startLevel[1]; jj < endLevel[1] + 1; jj++)
1296  {
1297  blocks[ii]->AddBlockToIntList(0,jj);
1298  }
1299  }
1300 
1301 
1302  for (unsigned int level = 2; level < num_octree_levels + 1; level++) // loop over levels
1303 
1304  {
1305  for (unsigned int jj = startLevel[level]; jj < endLevel[level] + 1; jj++) // loop over blocks of each level
1306  {
1307  OctreeBlock<dim> *block1 = blocks[jj];
1308  //std::cout<<"??Out "<<jj<<" "<<block1.GetNearNeighSize()<<std::endl;
1309  for (unsigned int subLevel = 0; subLevel < block1->NumNearNeighLevels(); subLevel++)
1310  {
1311  std::set <unsigned int> NNList = block1->GetNearNeighs(subLevel);
1312 
1313  for (std::set <unsigned int>::iterator pos1 = NNList.begin(); pos1 != NNList.end(); pos1++) //loop over blocks in NN list and get their NNs
1314  {
1315  block1->AddBlockToIntList(subLevel,*pos1);
1316  }
1317  //std::cout<<std::endl<<"Sublevel "<<subLevel<<" elem("<<block1.GetBlockElementsList()[0]<<") NearNeighs: ";
1318  std::vector <unsigned int> nodeIds = block1->GetBlockNodeList();
1319  //std::cout<<std::endl<<"Level "<<level<<" Block1: "<<kk<<" NumElements: "<<block1.GetBlockElementsNum()<<" "<<elemIds.size()<<std::endl;
1320  //std::cout<<"Nearest Neighbors Found:"<<std::endl;
1321  for (unsigned int pp = 0; pp < nodeIds.size(); pp++)
1322  {
1323  //std::cout<<"Node "<<nodeIds[pp]<<std::endl;
1324  std::set <unsigned int> doubleNodes = double_nodes_set[nodeIds[pp]];
1325  for (std::set<unsigned int>::iterator pos = doubleNodes.begin();
1326  pos != doubleNodes.end(); pos++)
1327  {
1328  //std::cout<<"Node Double"<<*pos<<std::endl;
1329  //std::vector<cell_it > surrCellIds = dof_to_elems[*pos];
1330  for (unsigned int k=0; k < dof_to_elems[*pos].size(); k++)
1331  {
1332  cell_it cell = dof_to_elems[*pos][k];
1333  //std::cout<<cell<<std::endl;
1334  for (unsigned int j=0; j < quadPoints[cell].size(); j++)
1335  {
1336  block1->AddBlockToIntList(subLevel,quad_point_to_block[cell][j][level+subLevel]);
1337  }
1338  }
1339  }
1340  }
1341  }
1342  for (unsigned int subLevel = 0; subLevel < block1->GetNearNeighSize(); subLevel++) // for each block, loop over all sublevels in his NN list (to account for childless blocks)
1343  {
1344  // now use intList to compute nonIntList
1345  std::set <unsigned int> intList = block1->GetIntList(subLevel);
1346  std::set <unsigned int> parentIntList; // intList at the previous level
1347  if (subLevel == 0) // if a block is childless we get its intList at the previous level, otherwise we get its parent's intList
1348  parentIntList = blocks[block1->GetParentId()]->GetIntList(0);
1349  else
1350  parentIntList = block1->GetIntList(subLevel-1);
1351 
1352  for (std::set <unsigned int>::iterator pos1 = parentIntList.begin(); pos1 != parentIntList.end(); pos1++) // loop over blocks in parentIntList
1353  {
1354  OctreeBlock<dim> *block2 = blocks[*pos1];
1355  if (block2->GetBlockChildrenNum() == 0) // if blocks in parentIntList are childless, don't look for their children, but see if they are in nonIntList
1356  {
1357  if (intList.count(*pos1) == 0) // if these blocks are not in intList
1358  block1->AddBlockToNonIntList(subLevel,*pos1); // then they go in nonIntList
1359  }
1360  else // if blocks in parentIntList are not childless, do the same test on all their children
1361  {
1362  for (unsigned int kk = 0; kk < block2->GetBlockChildrenNum(); kk++) // loop over children of blocks in parentIntList
1363  {
1364  //std::cout<<"Sublevel "<<subLevel<<" Block1 "<<jj<<" Block2 "<<*pos1<<" child(kk) "<<block2.GetChildId(kk)<<std::endl;
1365  if (intList.count(block2->GetChildId(kk)) == 0) // if these blocks are not in intList
1366  block1->AddBlockToNonIntList(subLevel,block2->GetChildId(kk)); // then they go in nonIntList
1367  } // end loop over children of blocks in parentIntList
1368  }
1369  } // loop over blocks in parentIntList
1370 
1371  } // end loop over subLevels of each block's intList
1372 
1373 // for printout
1374 
1375  /*
1376  std::cout<<std::endl;
1377  std::cout<<"-------------------------------- "<<std::endl;
1378  std::cout<<"Block "<<jj<<": Parent "<<block1->GetParentId();
1379  std::cout<<" cubePlot(["<<block1->GetPMin()<<"],"<<block1->GetDelta()<<",'m')"<<std::endl;
1380  std::cout<<"Quad points of block "<<jj<<": "<<std::endl;
1381  std::map <cell_it,std::vector<unsigned int> > quadPointsList = block1->GetBlockQuadPointsList();
1382  typename std::map <cell_it, std::vector<unsigned int> >::iterator it;
1383  for (it = quadPointsList.begin(); it != quadPointsList.end(); it++)
1384  {
1385  std::cout<<(*it).first<<"( ";
1386  for (unsigned int zz = 0; zz < (*it).second.size(); zz++)
1387  std::cout<<(*it).second[zz]<<" ";
1388  std::cout<<") ";
1389  }
1390  std::cout<<std::endl;
1391 
1392  std::cout<<"Nodes of block "<<jj<<" :"<<std::endl;
1393  std::vector <unsigned int> nodeList = block1->GetBlockNodeList();
1394  for (unsigned int zz = 0; zz < block1->GetBlockNodesNum(); zz++)
1395  {
1396  std::cout<<nodeList.at(zz)<<" ";
1397  }
1398  std::cout<<std::endl;
1399 
1400  for (unsigned int subLevel = 0; subLevel < block1->GetNearNeighSize(); subLevel++)
1401  {
1402  std::set <unsigned int> NNList = block1->GetNearNeighs(subLevel);
1403  std::cout<<"NearNeigh for block "<<jj<<" at level "<<level+subLevel<<":"<<std::endl;
1404  for (std::set <unsigned int>::iterator pos1 = NNList.begin(); pos1 != NNList.end(); pos1++)
1405  {
1406  std::cout<<*pos1<<" ";
1407  }
1408  std::cout<<std::endl;
1409 
1410  std::set <unsigned int> intList = block1->GetIntList(subLevel);
1411  std::cout<<"IntList for block "<<jj<<" at level "<<level+subLevel<<":"<<std::endl;
1412  for (std::set <unsigned int>::iterator pos1 = intList.begin(); pos1 != intList.end(); pos1++)
1413  {
1414  std::cout<<*pos1<<" ";
1415  }
1416  std::cout<<std::endl;
1417 
1418  std::set <unsigned int> nonIntList = block1->GetNonIntList(subLevel);
1419  std::cout<<"NonIntList for block "<<jj<<" at level "<<level+subLevel<<":"<<std::endl;
1420  for (std::set <unsigned int>::iterator pos1 = nonIntList.begin(); pos1 != nonIntList.end(); pos1++)
1421  {
1422  std::cout<<*pos1<<" ";
1423  }
1424  std::cout<<std::endl;
1425  }
1426  //*/
1427 
1428 
1429 
1430  } // end loop over blocks of a level
1431 
1432  } // end loop over levels
1433 
1434 //if (blocks.size() > 0)
1435 // {
1436 // for (unsigned int ii = 0; ii < num_blocks; ii++)
1437 // delete blocks[ii];
1438 // }
1439 
1440  integralCheck.clear();
1441  for (unsigned int i = 0; i < dh.n_dofs(); i++)
1442  {
1443  for (cell_it cell = dh.begin_active(); cell != endc; ++cell)
1444  {
1445  //std::cout<<i<<" "<<cell<<" "<<integralCheck[i][cell]<<std::endl;
1446  integralCheck[i][cell] = 0;
1447  }
1448  }
1449 
1450 
1451 
1452  std::cout<<"Done computing proximity lists for blocks"<<std::endl;
1453 } //end method for octree blocking generation
1454 
1455 
1456 
1457 template <int dim>
1459 
1460 {
1461  std::cout<<"Smoothing inflow surface"<<std::endl;
1462 
1463  std::cout<<"done smoothing inflow surface"<<std::endl;
1464 }
1465 
1466 
1467 template <int dim>
1469 {
1470  std::ifstream ifile(fname.c_str());
1471  tria.clear();
1472 
1473  tria.read_flags(ifile);
1474 
1475 
1476 
1477  tria.restore();
1478  ifile.close();
1479 
1480  dh.distribute_dofs(fe);
1481  vector_dh.distribute_dofs(vector_fe);
1482  //DoFRenumbering::Cuthill_McKee(dh);
1483  //DoFRenumbering::Cuthill_McKee(vector_dh);
1484 
1485  map_points.reinit(vector_dh.n_dofs());
1486 
1487  if (mapping == NULL)
1488  mapping = new MappingQEulerian<dim-1, Vector<double>, dim>
1489  (mapping_degree, map_points, vector_dh);
1490 
1491  generate_double_nodes_set();
1492  compute_min_diameter();
1493  std::cout<<"Total number of dofs after restore: "<<dh.n_dofs()<<std::endl;
1494 }
1495 
1496 template <int dim>
1497 void ComputationalDomain<dim>::dump_tria(std::string fname) const
1498 {
1499  std::ofstream ofile(fname.c_str());
1500  tria.write_flags(ofile);
1501  ofile.close();
1502 }
1503 
1504 
1505 
1506 template <int dim>
1508 {
1509  ref_points.resize(vector_dh.n_dofs());
1511  vector_dh, ref_points);
1512 
1513  vector_support_points.resize(vector_dh.n_dofs());
1514  DoFTools::map_dofs_to_support_points<dim-1, dim>( *mapping, vector_dh, vector_support_points);
1515 
1516  support_points.resize(dh.n_dofs());
1517  DoFTools::map_dofs_to_support_points<dim-1, dim>( *mapping, dh, support_points);
1518 }
1519 
1520 
1521 
1522 
1523 
1524 template <int dim>
1526 {
1527  typedef typename DoFHandler<dim-1,dim>::active_cell_iterator cell_it;
1528 
1529  SparsityPattern normals_sparsity_pattern;
1530  normals_sparsity_pattern.reinit(vector_dh.n_dofs(),
1531  vector_dh.n_dofs(),
1532  vector_dh.max_couplings_between_dofs());
1533  ConstraintMatrix vector_constraints;
1534  vector_constraints.clear();
1535  DoFTools::make_hanging_node_constraints (vector_dh,vector_constraints);
1536  vector_constraints.close();
1537  DoFTools::make_sparsity_pattern (vector_dh, normals_sparsity_pattern, vector_constraints);
1538  normals_sparsity_pattern.compress();
1539  Vector<double> vector_normals_solution(vector_dh.n_dofs());
1540 
1541  SparseMatrix<double> vector_normals_matrix;
1542  Vector<double> vector_normals_rhs;
1543 
1544  vector_normals_matrix.reinit (normals_sparsity_pattern);
1545  vector_normals_rhs.reinit(vector_dh.n_dofs());
1546  vector_normals_solution.reinit(vector_dh.n_dofs());
1547 
1548 
1549  FEValues<dim-1,dim> vector_fe_v(*mapping, vector_fe, *quadrature,
1550  update_values | update_cell_normal_vectors |
1551  update_JxW_values);
1552 
1553  const unsigned int vector_n_q_points = vector_fe_v.n_quadrature_points;
1554  const unsigned int vector_dofs_per_cell = vector_fe.dofs_per_cell;
1555  std::vector<unsigned int> vector_local_dof_indices (vector_dofs_per_cell);
1556 
1557  FullMatrix<double> local_normals_matrix (vector_dofs_per_cell, vector_dofs_per_cell);
1558  Vector<double> local_normals_rhs (vector_dofs_per_cell);
1559 
1560  cell_it
1561  vector_cell = vector_dh.begin_active(),
1562  vector_endc = vector_dh.end();
1563 
1564  for (; vector_cell!=vector_endc; ++vector_cell)
1565  {
1566  vector_fe_v.reinit (vector_cell);
1567  local_normals_matrix = 0;
1568  local_normals_rhs = 0;
1569  const std::vector<Point<dim> > &vector_node_normals = vector_fe_v.get_normal_vectors();
1570  unsigned int comp_i, comp_j;
1571 
1572  for (unsigned int q=0; q<vector_n_q_points; ++q)
1573  for (unsigned int i=0; i<vector_dofs_per_cell; ++i)
1574  {
1575  comp_i = vector_fe.system_to_component_index(i).first;
1576  for (unsigned int j=0; j<vector_dofs_per_cell; ++j)
1577  {
1578  comp_j = vector_fe.system_to_component_index(j).first;
1579  if (comp_i == comp_j)
1580  {
1581  local_normals_matrix(i,j) += vector_fe_v.shape_value(i,q)*
1582  vector_fe_v.shape_value(j,q)*
1583  vector_fe_v.JxW(q);
1584  }
1585  }
1586  local_normals_rhs(i) += (vector_fe_v.shape_value(i, q)) *
1587  vector_node_normals[q](comp_i) * vector_fe_v.JxW(q);
1588  }
1589 
1590  vector_cell->get_dof_indices (vector_local_dof_indices);
1591 
1592  vector_constraints.distribute_local_to_global
1593  (local_normals_matrix,
1594  local_normals_rhs,
1595  vector_local_dof_indices,
1596  vector_normals_matrix,
1597  vector_normals_rhs);
1598  }
1599 
1600 
1601 
1602  SparseDirectUMFPACK normals_inverse;
1603  normals_inverse.initialize(vector_normals_matrix);
1604  normals_inverse.vmult(vector_normals_solution, vector_normals_rhs);
1605  vector_constraints.distribute(vector_normals_solution);
1606 
1607  nodes_normals.resize(dh.n_dofs());
1608 
1609  for (unsigned int i=0; i<vector_dh.n_dofs()/dim; ++i)
1610  {
1611  for (unsigned int d=0; d<dim; d++)
1612  nodes_normals[i](d) = vector_normals_solution(3*i+d);
1613  nodes_normals[i]/= nodes_normals[i].distance(Point<dim>(0.0,0.0,0.0));
1614  //cout<<i<<" Gradient: "<<node_normals[i]<<endl;
1615  for (unsigned int d=0; d<dim; d++)
1616  vector_normals_solution(3*i+d) = nodes_normals[i](d);
1617  }
1618 
1619 
1620 }
1621 
1622 
1623 
1624 template class ComputationalDomain<3>;
DoFHandler< dim-1, dim >::active_cell_iterator cell_it
void AddQuadPoint(cell_it elemPointer, unsigned int quadPointId)
Definition: octree_block.cc:91
unsigned int GetNearNeighSize() const
unsigned int GetParentId() const
std::map< cell_it, std::vector< unsigned int > > GetBlockQuadPointsList() const
void map_dofs_to_support_points(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof_handler, std::vector< Point< spacedim > > &support_points)
void dump_tria(std::string fname) const
void distribute(VectorType &vec) const
unsigned int NumNearNeighLevels() const
#define TOLL
std::string get(const std::string &entry_string) const
std::set< unsigned int > GetNearNeighs(unsigned int sublevel) const
std::set< unsigned int > GetIntList(unsigned int sublevel) const
virtual void declare_parameters(ParameterHandler &prm)
void SetNonIntListSize(unsigned int sublevels)
unsigned int GetChildId(unsigned int idInList) const
void enter_subsection(const std::string &subsection)
void AddChild(unsigned int childId)
void make_hanging_node_constraints(const DoFHandlerType &dof_handler, ConstraintMatrix &constraints)
void distribute_local_to_global(const InVector &local_vector, const std::vector< size_type > &local_dof_indices, OutVector &global_vector) const
std::vector< unsigned int > GetBlockNodeList() const
Definition: octree_block.cc:98
virtual void parse_parameters(ParameterHandler &prm)
void AddBlockToIntList(unsigned int sublevel, const unsigned int intListBlockId)
ComputationalDomain(const unsigned int fe_degree=1, const unsigned int mapping_degree=1)
void extract_boundary_dofs(const DoFHandlerType &dof_handler, const ComponentMask &component_mask, std::vector< bool > &selected_dofs, const std::set< types::boundary_id > &boundary_ids=std::set< types::boundary_id >())
void SetNearNeighSize(unsigned int sublevels)
void AddNode(unsigned int nodeId)
Definition: octree_block.cc:84
void leave_subsection()
virtual void refine_and_resize()
void reinit(const size_type m, const size_type n, const unsigned int max_per_row)
Point< dim > GetPMin() const
void make_sparsity_pattern(const DoFHandlerType &dof_handler, SparsityPatternType &sparsity_pattern, const ConstraintMatrix &constraints=ConstraintMatrix(), const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
void initialize(const SparsityPattern &sparsity_pattern)
void AddBlockToNonIntList(unsigned int sublevel, const unsigned int intListBlockId)
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
unsigned int GetBlockChildrenNum() const
void SetIntListSize(unsigned int sublevels)
void AddNearNeigh(unsigned int sublevel, const unsigned int nnBlockId)
void restore_tria(std::string fname)
double GetDelta() const
void CopyContent(const OctreeBlock *other)
Definition: octree_block.cc:65
long int get_integer(const std::string &entry_string) const
void vmult(Vector< double > &dst, const Vector< double > &src) const