-
Notifications
You must be signed in to change notification settings - Fork 708
/
grid_tools.h
4657 lines (4347 loc) · 197 KB
/
grid_tools.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// ---------------------------------------------------------------------
//
// Copyright (C) 2001 - 2022 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.md at
// the top level directory of deal.II.
//
// ---------------------------------------------------------------------
#ifndef dealii_grid_tools_h
#define dealii_grid_tools_h
#include <deal.II/base/config.h>
#include <deal.II/base/bounding_box.h>
#include <deal.II/base/geometry_info.h>
#include <deal.II/base/point.h>
#include <deal.II/base/std_cxx17/optional.h>
#include <deal.II/boost_adaptors/bounding_box.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/mapping.h>
#include <deal.II/fe/mapping_q1.h>
#include <deal.II/grid/manifold.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/hp/dof_handler.h>
#include <deal.II/lac/la_parallel_vector.h>
#include <deal.II/lac/la_vector.h>
#include <deal.II/lac/petsc_vector.h>
#include <deal.II/lac/sparsity_tools.h>
#include <deal.II/lac/trilinos_vector.h>
#include <deal.II/numerics/rtree.h>
DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/serialization/array.hpp>
#include <boost/serialization/vector.hpp>
#ifdef DEAL_II_WITH_ZLIB
# include <boost/iostreams/device/back_inserter.hpp>
# include <boost/iostreams/filter/gzip.hpp>
# include <boost/iostreams/filtering_stream.hpp>
# include <boost/iostreams/stream.hpp>
#endif
DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
#include <bitset>
#include <list>
#include <set>
DEAL_II_NAMESPACE_OPEN
// Forward declarations
#ifndef DOXYGEN
namespace parallel
{
namespace distributed
{
template <int, int>
class Triangulation;
}
} // namespace parallel
namespace hp
{
template <int, int>
class MappingCollection;
}
class SparsityPattern;
namespace GridTools
{
template <int dim, int spacedim>
class Cache;
}
#endif
namespace internal
{
template <int dim, int spacedim, class MeshType>
class ActiveCellIterator
{
public:
#ifndef _MSC_VER
using type = typename MeshType::active_cell_iterator;
#else
using type = TriaActiveIterator<dealii::CellAccessor<dim, spacedim>>;
#endif
};
#ifdef _MSC_VER
template <int dim, int spacedim>
class ActiveCellIterator<dim, spacedim, dealii::DoFHandler<dim, spacedim>>
{
public:
using type =
TriaActiveIterator<dealii::DoFCellAccessor<dim, spacedim, false>>;
};
#endif
} // namespace internal
/**
* This namespace is a collection of algorithms working on triangulations,
* such as shifting or rotating triangulations, but also finding a cell that
* contains a given point. See the descriptions of the individual functions
* for more information.
*
* @ingroup grid
*/
namespace GridTools
{
/**
* @name Information about meshes and cells
*/
/*@{*/
/**
* Return the diameter of a triangulation. The diameter is computed using
* only the vertices, i.e. if the diameter should be larger than the maximal
* distance between boundary vertices due to a higher order mapping, then
* this function will not catch this.
*/
template <int dim, int spacedim>
double
diameter(const Triangulation<dim, spacedim> &tria);
/**
* Compute the volume (i.e. the dim-dimensional measure) of the
* triangulation. We compute the measure using the integral $\sum_K \int_K 1
* \; dx$ where $K$ are the cells of the given triangulation. The integral
* is approximated via quadrature for which we need the mapping argument.
*
* If the triangulation is a dim-dimensional one embedded in a higher
* dimensional space of dimension spacedim, then the value returned is the
* dim-dimensional measure. For example, for a two-dimensional triangulation
* in three-dimensional space, the value returned is the area of the surface
* so described. (This obviously makes sense since the spacedim-dimensional
* measure of a dim-dimensional triangulation would always be zero if dim @<
* spacedim.
*
* This function also works for objects of type
* parallel::distributed::Triangulation, in which case the function is a
* collective operation.
*
* @param tria The triangulation.
* @param mapping An optional argument used to denote the mapping that
* should be used when describing whether cells are bounded by straight or
* curved faces. The default is to use a $Q_1$ mapping, which corresponds to
* straight lines bounding the cells.
* @return The dim-dimensional measure of the domain described by the
* triangulation, as discussed above.
*/
template <int dim, int spacedim>
double
volume(const Triangulation<dim, spacedim> &tria,
const Mapping<dim, spacedim> & mapping =
(ReferenceCells::get_hypercube<dim>()
#ifndef _MSC_VER
.template get_default_linear_mapping<dim, spacedim>()
#else
.ReferenceCell::get_default_linear_mapping<dim, spacedim>()
#endif
));
/**
* Return an approximation of the diameter of the smallest active cell of a
* triangulation. See step-24 for an example of use of this function.
*
* Notice that, even if you pass a non-trivial mapping, the returned value is
* computed only using information on the vertices of the triangulation,
* possibly transformed by the mapping. While this is accurate most of the
* times, it may fail to give the correct result when the triangulation
* contains very distorted cells.
*/
template <int dim, int spacedim>
double
minimal_cell_diameter(
const Triangulation<dim, spacedim> &triangulation,
const Mapping<dim, spacedim> & mapping =
(ReferenceCells::get_hypercube<dim>()
#ifndef _MSC_VER
.template get_default_linear_mapping<dim, spacedim>()
#else
.ReferenceCell::get_default_linear_mapping<dim, spacedim>()
#endif
));
/**
* Return an approximation of the diameter of the largest active cell of a
* triangulation.
*
* Notice that, even if you pass a non-trivial mapping to this function, the
* returned value is computed only using information on the vertices of the
* triangulation, possibly transformed by the mapping. While this is accurate
* most of the times, it may fail to give the correct result when the
* triangulation contains very distorted cells.
*/
template <int dim, int spacedim>
double
maximal_cell_diameter(
const Triangulation<dim, spacedim> &triangulation,
const Mapping<dim, spacedim> & mapping =
(ReferenceCells::get_hypercube<dim>()
#ifndef _MSC_VER
.template get_default_linear_mapping<dim, spacedim>()
#else
.ReferenceCell::get_default_linear_mapping<dim, spacedim>()
#endif
));
/**
* Given a list of vertices (typically obtained using
* Triangulation::get_vertices) as the first, and a list of vertex indices
* that characterize a single cell as the second argument, return the
* measure (area, volume) of this cell. If this is a real cell, then you can
* get the same result using <code>cell-@>measure()</code>, but this
* function also works for cells that do not exist except that you make it
* up by naming its vertices from the list.
*
* @deprecated Use the more general function which takes an ArrayView instead.
*/
template <int dim>
DEAL_II_DEPRECATED double
cell_measure(
const std::vector<Point<dim>> &all_vertices,
const unsigned int (&vertex_indices)[GeometryInfo<dim>::vertices_per_cell]);
/**
* Given a list of vertices (typically obtained using
* Triangulation::get_vertices()) as the first, and a list of vertex indices
* that characterize a single cell as the second argument, return the
* measure (area, volume) of this cell. If this is a real cell, then you can
* get the same result using <code>cell-@>measure()</code>, but this
* function also works for cells that do not exist except that you make it
* up by naming its vertices from the list.
*
* The size of @p vertex_indices, combined with `dim`, implicitly encodes
* the ReferenceCell type of the provided cell. For example, if `dim == 2` and
* `vertex_indices.size() == 3` then the cell is a triangle, but if
* `dim == 2` and `vertex_indices.size() == 4` then the cell is a
* quadrilateral. A std::vector is implicitly convertible to an ArrayView, so
* it can be passed directly to this function. See the ArrayView class for
* more information.
*
* @note This function is only implemented for codimension zero objects.
*/
template <int dim>
double
cell_measure(const std::vector<Point<dim>> & all_vertices,
const ArrayView<const unsigned int> &vertex_indices);
/**
* This function computes an affine approximation of the map from the unit
* coordinates to the real coordinates of the form $p_\text{real} = A
* p_\text{unit} + b $ by a least squares fit of this affine function to the
* $2^\text{dim}$ vertices representing a quadrilateral or hexahedral cell
* in `spacedim` dimensions. The result is returned as a pair with the
* matrix <i>A</i> as the first argument and the vector <i>b</i> describing
* distance of the plane to the origin.
*
* For any valid mesh cell whose geometry is not degenerate, this operation
* results in a unique affine mapping, even in cases where the actual
* transformation by a bi-/trilinear or higher order mapping might be
* singular. The result is exact in case the transformation from the unit to
* the real cell is indeed affine, such as in one dimension or for Cartesian
* and affine (parallelogram) meshes in 2D/3D.
*
* This approximation is underlying the function
* TriaAccessor::real_to_unit_cell_affine_approximation() function.
*
* For exact transformations to the unit cell, use
* Mapping::transform_real_to_unit_cell().
*/
template <int dim, int spacedim>
std::pair<DerivativeForm<1, dim, spacedim>, Tensor<1, spacedim>>
affine_cell_approximation(const ArrayView<const Point<spacedim>> &vertices);
/**
* Computes an aspect ratio measure for all locally-owned active cells and
* fills a vector with one entry per cell, given a @p triangulation and
* @p mapping. The size of the vector that is returned equals the number of
* active cells. The vector contains zero for non locally-owned cells. The
* aspect ratio of a cell is defined as the ratio of the maximum to minimum
* singular value of the Jacobian, taking the maximum over all quadrature
* points of a quadrature rule specified via @p quadrature. For example, for
* the special case of rectangular elements in 2d with dimensions $a$ and $b$
* ($a \geq b$), this function returns the usual aspect ratio definition
* $a/b$. The above definition using singular values is a generalization to
* arbitrarily deformed elements. This function is intended to be used for
* $d=2,3$ space dimensions, but it can also be used for $d=1$ returning a
* value of 1.
*
* @note Inverted elements do not throw an exception. Instead, a value of inf
* is written into the vector in case of inverted elements.
*
* @note Make sure to use enough quadrature points for a precise calculation
* of the aspect ratio in case of deformed elements.
*
* @note In parallel computations the return value will have the length
* n_active_cells but the aspect ratio is only computed for the cells that
* are locally owned and placed at index CellAccessor::active_cell_index(),
* respectively. All other values are set to 0.
*/
template <int dim>
Vector<double>
compute_aspect_ratio_of_cells(const Mapping<dim> & mapping,
const Triangulation<dim> &triangulation,
const Quadrature<dim> & quadrature);
/**
* Computes the maximum aspect ratio by taking the maximum over all cells.
*
* @note When running in parallel with a Triangulation that supports MPI,
* this is a collective call and the return value is the maximum over all
* processors.
*/
template <int dim>
double
compute_maximum_aspect_ratio(const Mapping<dim> & mapping,
const Triangulation<dim> &triangulation,
const Quadrature<dim> & quadrature);
/**
* Compute the smallest box containing the entire triangulation.
*
* If the input triangulation is a `parallel::distributed::Triangulation`,
* then each processor will compute a bounding box enclosing all locally
* owned, ghost, and artificial cells. In the case of a domain without curved
* boundaries, these bounding boxes will all agree between processors because
* the union of the areas occupied by artificial and ghost cells equals the
* union of the areas occupied by the cells that other processors own.
* However, if the domain has curved boundaries, this is no longer the case.
* The bounding box returned may be appropriate for the current processor,
* but different from the bounding boxes computed on other processors.
*/
template <int dim, int spacedim>
BoundingBox<spacedim>
compute_bounding_box(const Triangulation<dim, spacedim> &triangulation);
/**
* Return the point on the geometrical object @p object closest to the given
* point @p trial_point. For example, if @p object is a one-dimensional line
* or edge, then the returned point will be a point on the geodesic that
* connects the vertices as the manifold associated with the object sees it
* (i.e., the geometric line may be curved if it lives in a higher
* dimensional space). If the iterator points to a quadrilateral in a higher
* dimensional space, then the returned point lies within the convex hull of
* the vertices of the quad as seen by the associated manifold.
*
* @note This projection is usually not well-posed since there may be
* multiple points on the object that minimize the distance. The algorithm
* used in this function is robust (and the output is guaranteed to be on
* the given @p object) but may only provide a few correct digits if the
* object has high curvature. If your manifold supports it then the
* specialized function Manifold::project_to_manifold() may perform better.
*/
template <typename Iterator>
Point<Iterator::AccessorType::space_dimension>
project_to_object(
const Iterator & object,
const Point<Iterator::AccessorType::space_dimension> &trial_point);
/**
* Return the arrays that define the coarse mesh of a Triangulation. This
* function is the inverse of Triangulation::create_triangulation().
*
* The return value is a tuple with the vector of vertices, the vector of
* cells, and a SubCellData structure. The latter contains additional
* information about faces and lines.
*
* This function is useful in cases where one needs to deconstruct a
* Triangulation or manipulate the numbering of the vertices in some way: an
* example is GridGenerator::merge_triangulations().
*/
template <int dim, int spacedim>
std::
tuple<std::vector<Point<spacedim>>, std::vector<CellData<dim>>, SubCellData>
get_coarse_mesh_description(const Triangulation<dim, spacedim> &tria);
/*@}*/
/**
* @name Functions supporting the creation of meshes
*/
/*@{*/
/**
* Remove vertices that are not referenced by any of the cells. This
* function is called by all <tt>GridIn::read_*</tt> functions to eliminate
* vertices that are listed in the input files but are not used by the cells
* in the input file. While these vertices should not be in the input from
* the beginning, they sometimes are, most often when some cells have been
* removed by hand without wanting to update the vertex lists, as they might
* be lengthy.
*
* This function is called by all <tt>GridIn::read_*</tt> functions as the
* triangulation class requires them to be called with used vertices only.
* This is so, since the vertices are copied verbatim by that class, so we
* have to eliminate unused vertices beforehand.
*
* Not implemented for the codimension one case.
*/
template <int dim, int spacedim>
void
delete_unused_vertices(std::vector<Point<spacedim>> &vertices,
std::vector<CellData<dim>> & cells,
SubCellData & subcelldata);
/**
* Remove vertices that are duplicated, due to the input of a structured
* grid, for example. If these vertices are not removed, the faces bounded
* by these vertices become part of the boundary, even if they are in the
* interior of the mesh.
*
* This function is called by some <tt>GridIn::read_*</tt> functions. Only
* the vertices with indices in @p considered_vertices are tested for
* equality. This speeds up the algorithm, which is, for worst-case hyper
* cube geometries $O(N^{3/2})$ in 2D and $O(N^{5/3})$ in 3D: quite slow.
* However, if you wish to consider all vertices, simply pass an empty
* vector. In that case, the function fills @p considered_vertices with all
* vertices.
*
* Two vertices are considered equal if their difference in each coordinate
* direction is less than @p tol.
*/
template <int dim, int spacedim>
void
delete_duplicated_vertices(std::vector<Point<spacedim>> &all_vertices,
std::vector<CellData<dim>> & cells,
SubCellData & subcelldata,
std::vector<unsigned int> & considered_vertices,
const double tol = 1e-12);
/**
* Grids generated by grid generators may have an orientation of cells which
* is the inverse of the orientation required by deal.II.
*
* In 2d and 3d this function checks whether all cells have negative or
* positive measure/volume. In the former case, all cells are inverted. It
* does nothing in 1d.
*
* The inversion of cells might also work when only a subset of all cells
* have negative volume. However, grids consisting of a mixture of negative
* and positively oriented cells are very likely to be broken. Therefore, an
* exception is thrown, in case cells are not uniformly oriented.
*
* @note This function should be called before GridTools::consistently_order_cells().
*
* @param all_vertices The vertices of the mesh.
* @param cells The array of CellData objects that describe the mesh's topology.
*/
template <int dim, int spacedim>
void
invert_all_negative_measure_cells(
const std::vector<Point<spacedim>> &all_vertices,
std::vector<CellData<dim>> & cells);
/**
* Check the given cells and inverts any cell that is considered to have
* negative measure/volume in the orientation required by deal.II.
*
* This function is identical to invert_all_negative_measure_cells() except it
* does not throw an error if only some of the cells are inverted. Instead,
* this function returns how many cells were inverted. Additionally, it will
* always throw an exception outside of codimension 0.
*/
template <int dim, int spacedim>
std::size_t
invert_cells_with_negative_measure(
const std::vector<Point<spacedim>> &all_vertices,
std::vector<CellData<dim>> & cells);
/**
* Given a vector of CellData objects describing a mesh, reorder their
* vertices so that all lines are consistently oriented.
*
* The expectations on orientation and a discussion of this function are
* available in the @ref reordering "reordering module".
*
* @param cells The array of CellData objects that describe the mesh's topology.
*/
template <int dim>
void
consistently_order_cells(std::vector<CellData<dim>> &cells);
/*@}*/
/**
* @name Rotating, stretching and otherwise transforming meshes
*/
/*@{*/
/**
* Transform the vertices of the given triangulation by applying the
* function object provided as first argument to all its vertices.
*
* The transformation given as argument is used to transform each vertex.
* Its respective type has to offer a function-like syntax, i.e. the
* predicate is either an object of a type that has an <tt>operator()</tt>,
* or it is a pointer to a non-member function, or it is a lambda function
* object. In either case, argument and return
* value have to be of type `Point@<spacedim@>`.
*
* @note The transformations that make sense to use with this function
* should have a Jacobian with a positive determinant. For example,
* rotation, shearing, stretching, or scaling all satisfy this (though
* there is no requirement that the transformation used actually is
* linear, as all of these examples are). On the other hand, reflections
* or inversions have a negative determinant of the Jacobian. The
* current function has no way of asserting a positive determinant
* of the Jacobian, but if you happen to use such a transformation,
* the result will be a triangulation in which cells have a negative
* volume.
*
* @note If you are using a parallel::distributed::Triangulation you will
* have hanging nodes in your local Triangulation even if your "global" mesh
* has no hanging nodes. This will cause issues with wrong positioning of
* hanging nodes in ghost cells if you call the current functions: The
* vertices of all locally owned cells will be correct, but the vertices of
* some ghost cells may not. This means that computations like
* KellyErrorEstimator may give wrong answers.
*
* @note This function is in general not compatible with manifolds attached
* to the triangulation. For example, in order to refine the grid (using
* manifolds) after the grid transformation, you have to make sure that
* the original manifold is still valid for the transformed geometry. This
* does not hold in general, and it is necessary to clear manifolds from
* the triangulation (for example, using Triangulation::clear_all_manifolds())
* before the transformation, and then attach new ones after the
* transformation that are valid for the transformed geometry. There are cases
* where this is awkward, most notably if you are using a mesh generated by
* the functions in GridGenerator which generally attach suitable manifolds
* upon mesh generation; in those cases, you will have to think about how
* these manifolds were constructed, and create a manifold that is constructed
* in a similar way but applies to the transformed geometry. As a consequence,
* if you only care about manifolds for mesh refinement, it is often simpler
* to just refine the original mesh before transformation as needed, and then
* simply forget about the manifolds. Of course, manifolds are also used for
* other cases (e.g., for normal vectors, curved edges and faces, and higher
* order mappings), and if these are relevant to what you are doing, then
* there is no alternative to building appropriate manifolds for the
* transformed geometry and attaching these to the transformed geometry. In
* general, detaching manifolds from a triangulation and then doing the
* transformation would look as follows:
* @code
* ...
* triangulation.reset_all_manifolds();
* GridTools::transform(MyTransformation<dim>(), triangulation);
* ...
* @endcode
*
* This function is used in the "Possibilities for extensions" section of
* step-38. It is also used in step-49 and step-53.
*/
template <int dim, typename Transformation, int spacedim>
void
transform(const Transformation & transformation,
Triangulation<dim, spacedim> &triangulation);
/**
* Shift each vertex of the triangulation by the given shift vector. This
* function uses the transform() function above, so the requirements on the
* triangulation stated there hold for this function as well; in particular,
* this is true about the discussion about manifolds.
*/
template <int dim, int spacedim>
void
shift(const Tensor<1, spacedim> & shift_vector,
Triangulation<dim, spacedim> &triangulation);
/**
* Rotate all vertices of the given two-dimensional triangulation in
* counter-clockwise sense around the origin of the coordinate system by the
* given angle (given in radians, rather than degrees). This function uses
* the transform() function above, so the requirements on the triangulation
* stated there hold for this function as well; in particular,
* this is true about the discussion about manifolds.
*
* @note This function is only supported for dim=2.
*/
template <int dim>
void
rotate(const double angle, Triangulation<dim> &triangulation);
/**
* Rotate all vertices of the given @p triangulation in counter-clockwise
* direction around the @p axis described by a unit vector. Otherwise like the
* function above; in particular, this function calls the transform() function
* and so the discussion about manifolds there also applies here.
*
* @param[in] angle Angle in radians to rotate the Triangulation by.
* @param[in] axis A unit vector that defines the axis of rotation.
* @param[in,out] triangulation The Triangulation object to rotate.
*
* @note Implemented for spacedim=3 and dim=1, 2, and 3.
*/
template <int dim>
void
rotate(const Tensor<1, 3, double> &axis,
const double angle,
Triangulation<dim, 3> & triangulation);
/**
* Rotate all vertices of the given @p triangulation in counter-clockwise
* direction around the axis with the given index. Otherwise like the
* function above; in particular, this function calls the transform() function
* and so the discussion about manifolds there also applies here.
*
* @param[in] angle Angle in radians to rotate the Triangulation by.
* @param[in] axis Index of the coordinate axis to rotate around, keeping
* that coordinate fixed (0=x axis, 1=y axis, 2=z axis).
* @param[in,out] triangulation The Triangulation object to rotate.
*
* @note Implemented for dim=1, 2, and 3.
*
* @deprecated Use the alternative with the unit vector instead.
*/
template <int dim>
DEAL_II_DEPRECATED_EARLY void
rotate(const double angle,
const unsigned int axis,
Triangulation<dim, 3> &triangulation);
/**
* Transform the given triangulation smoothly to a different domain where,
* typically, each of the vertices at the boundary of the triangulation is
* mapped to the corresponding points in the @p new_points map.
*
* The unknown displacement field $u_d(\mathbf x)$ in direction $d$ is
* obtained from the minimization problem \f[ \min\, \int \frac{1}{2}
* c(\mathbf x)
* \mathbf \nabla u_d(\mathbf x) \cdot
* \mathbf \nabla u_d(\mathbf x)
* \,\rm d x
* \f]
* subject to prescribed constraints. The minimizer is obtained by solving the
* Laplace equation of the dim components of a displacement field that maps
* the current
* domain into one described by @p new_points . Linear finite elements with
* four Gaussian quadrature points in each direction are used. The difference
* between the vertex positions specified in @p new_points and their current
* value in @p tria therefore represents the prescribed values of this
* displacement field at the boundary of the domain, or more precisely at all
* of those locations for which @p new_points provides values (which may be
* at part of the boundary, or even in the interior of the domain). The
* function then evaluates this displacement field at each unconstrained
* vertex and uses it to place the mapped vertex where the displacement
* field locates it. Because the solution of the Laplace equation is smooth,
* this guarantees a smooth mapping from the old domain to the new one.
*
* @param[in] new_points The locations where a subset of the existing
* vertices are to be placed. Typically, this would be a map from the vertex
* indices of all nodes on the boundary to their new locations, thus
* completely specifying the geometry of the mapped domain. However, it may
* also include interior points if necessary and it does not need to include
* all boundary vertices (although you then lose control over the exact
* shape of the mapped domain).
*
* @param[in,out] tria The Triangulation object. This object is changed in-
* place, i.e., the previous locations of vertices are overwritten.
*
* @param[in] coefficient An optional coefficient for the Laplace problem.
* Larger values make cells less prone to deformation (effectively
* increasing their stiffness). The coefficient is evaluated in the
* coordinate system of the old, undeformed configuration of the
* triangulation as input, i.e., before the transformation is applied.
* Should this function be provided, sensible results can only be expected
* if all coefficients are positive.
*
* @param[in] solve_for_absolute_positions If set to <code>true</code>, the
* minimization problem is formulated with respect to the final vertex
* positions as opposed to their displacement. The two formulations are
* equivalent for
* the homogeneous problem (default value of @p coefficient), but they
* result in very different mesh motion otherwise. Since in most cases one
* will be using a non-constant coefficient in displacement formulation, the
* default value of this parameter is <code>false</code>.
*
* @note This function is not currently implemented for the 1d case.
*/
template <int dim>
void
laplace_transform(const std::map<unsigned int, Point<dim>> &new_points,
Triangulation<dim> & tria,
const Function<dim, double> *coefficient = nullptr,
const bool solve_for_absolute_positions = false);
/**
* Return a std::map with all vertices of faces located in the boundary
*
* @param[in] tria The Triangulation object.
*/
template <int dim, int spacedim>
std::map<unsigned int, Point<spacedim>>
get_all_vertices_at_boundary(const Triangulation<dim, spacedim> &tria);
/**
* Scale the entire triangulation by the given factor. To preserve the
* orientation of the triangulation, the factor must be positive.
*
* This function uses the transform() function above, so the requirements on
* the triangulation stated there hold for this function as well.
*/
template <int dim, int spacedim>
void
scale(const double scaling_factor,
Triangulation<dim, spacedim> &triangulation);
/**
* Distort the given triangulation by randomly moving around all the
* vertices of the grid. The direction of movement of each vertex is
* random, while the length of the shift vector has a value of @p factor
* times the minimal length of the active edges adjacent to this vertex.
* Note that @p factor should obviously be well below <tt>0.5</tt>.
*
* If @p keep_boundary is set to @p true (which is the default), then
* boundary vertices are not moved.
*
* @p seed is used for the initialization of the random engine. Its
* default value initializes the engine with the same state as in
* previous versions of deal.II.
*/
template <int dim, int spacedim>
void
distort_random(
const double factor,
Triangulation<dim, spacedim> &triangulation,
const bool keep_boundary = true,
const unsigned int seed = boost::random::mt19937::default_seed);
/**
* Remove hanging nodes from a grid. If the @p isotropic parameter is set
* to @p false (default) this function detects cells with hanging nodes and
* refines the neighbours in the direction that removes hanging nodes.
* If the @p isotropic parameter is set
* to @p true, the neighbours refinement is made in each directions.
* In order to remove all hanging nodes this procedure has to be repeated:
* this could require a large number of iterations.
* To avoid this a max number (@p max_iterations) of iteration is provided.
*
* Consider the following grid:
* @image html remove_hanging_nodes-hanging.png
*
* @p isotropic == @p false would return:
* @image html remove_hanging_nodes-aniso.png
*
* @p isotropic == @p true would return:
* @image html remove_hanging_nodes-isotro.png
*
* @param[in,out] tria Triangulation to refine.
*
* @param[in] isotropic If true refine cells in each directions, otherwise
* (default value) refine the cell in the direction that removes hanging node.
*
* @param[in] max_iterations At each step only closest cells to hanging nodes
* are refined. The code may require a lot of iterations to remove all
* hanging nodes. @p max_iterations is the maximum number of iteration
* allowed. If @p max_iterations == numbers::invalid_unsigned_int this
* function continues refining until there are no hanging nodes.
*
* @note In the case of parallel codes, this function should be combined
* with GridGenerator::flatten_triangulation.
*/
template <int dim, int spacedim>
void
remove_hanging_nodes(Triangulation<dim, spacedim> &tria,
const bool isotropic = false,
const unsigned int max_iterations = 100);
/**
* Refine a mesh anisotropically such that the resulting mesh is composed by
* cells with maximum ratio between dimensions less than @p max_ratio.
* This procedure requires an algorithm that may not terminate. Consequently,
* it is possible to set a maximum number of iterations through the
* @p max_iterations parameter.
*
* Starting from a cell like this:
* @image html remove_anisotropy-coarse.png
*
* This function would return:
* @image html remove_anisotropy-refined.png
*
* @param[in,out] tria Triangulation to refine.
*
* @param[in] max_ratio Maximum value allowed among the ratio between
* the dimensions of each cell.
*
* @param[in] max_iterations Maximum number of iterations allowed.
*
* @note In the case of parallel codes, this function should be combined
* with GridGenerator::flatten_triangulation and
* GridTools::remove_hanging_nodes.
*/
template <int dim, int spacedim>
void
remove_anisotropy(Triangulation<dim, spacedim> &tria,
const double max_ratio = 1.6180339887,
const unsigned int max_iterations = 5);
/**
* Analyze the boundary cells of a mesh, and if one cell is found at
* a corner position (with dim adjacent faces on the boundary), and its
* dim-dimensional angle fraction exceeds @p limit_angle_fraction,
* refine globally once, and replace the children of such cell
* with children where the corner is no longer offending the given angle
* fraction.
*
* If no boundary cells exist with two adjacent faces on the boundary, then
* the triangulation is left untouched. If instead we do have cells with dim
* adjacent faces on the boundary, then the fraction between the
* dim-dimensional
* solid angle and dim*pi/2 is checked against the parameter @p limit_angle_fraction.
* If it is higher, the grid is refined once, and the children of the
* offending cell are replaced with some cells that instead respect the limit.
* After this process the triangulation is flattened, and all Manifold objects
* are restored as they were in the original triangulation.
*
* An example is given by the following mesh, obtained by attaching a
* SphericalManifold to a mesh generated using GridGenerator::hyper_cube:
*
* @code
* const SphericalManifold<dim> m0;
* Triangulation<dim> tria;
* GridGenerator::hyper_cube(tria,-1,1);
* tria.set_all_manifold_ids_on_boundary(0);
* tria.set_manifold(0, m0);
* tria.refine_global(4);
* @endcode
*
* <p ALIGN="center">
* @image html regularize_mesh_01.png
* </p>
*
* The four cells that were originally the corners of a square will give you
* some troubles during computations, as the jacobian of the transformation
* from the reference cell to those cells will go to zero, affecting the error
* constants of the finite element estimates.
*
* Those cells have a corner with an angle that is very close to 180 degrees,
* i.e., an angle fraction very close to one.
*
* The same code, adding a call to regularize_corner_cells:
* @code
* const SphericalManifold<dim> m0;
* Triangulation<dim> tria;
* GridGenerator::hyper_cube(tria,-1,1);
* tria.set_all_manifold_ids_on_boundary(0);
* tria.set_manifold(0, m0);
* GridTools::regularize_corner_cells(tria);
* tria.refine_global(2);
* @endcode
* generates a mesh that has a much better behavior w.r.t. the jacobian of
* the Mapping:
*
* <p ALIGN="center">
* @image html regularize_mesh_02.png
* </p>
*
* This mesh is very similar to the one obtained by GridGenerator::hyper_ball.
* However, using GridTools::regularize_corner_cells one has the freedom to
* choose when to apply the regularization, i.e., one could in principle first
* refine a few times, and then call the regularize_corner_cells function:
*
* @code
* const SphericalManifold<dim> m0;
* Triangulation<dim> tria;
* GridGenerator::hyper_cube(tria,-1,1);
* tria.set_all_manifold_ids_on_boundary(0);
* tria.set_manifold(0, m0);
* tria.refine_global(2);
* GridTools::regularize_corner_cells(tria);
* tria.refine_global(1);
* @endcode
*
* This generates the following mesh:
*
* <p ALIGN="center">
* @image html regularize_mesh_03.png
* </p>
*
* The function is currently implemented only for dim = 2 and
* will throw an exception if called with dim = 3.
*
* @param[in,out] tria Triangulation to regularize.
*
* @param[in] limit_angle_fraction Maximum ratio of angle or solid
* angle that is allowed for a corner element in the mesh.
*/
template <int dim, int spacedim>
void
regularize_corner_cells(Triangulation<dim, spacedim> &tria,
const double limit_angle_fraction = .75);
/*@}*/
/**
* @name Finding cells and vertices of a triangulation
*/
/*@{*/
/**
* Given a Triangulation's @p cache and a list of @p points, call
* find_active_cell_around_point() on each element of @p points, and return
* @p cells, reference positions @p qpoints, and a mapping @p maps from local
* to global indices into @p points .
*
* @param[in] cache The triangulation's GridTools::Cache .
* @param[in] points The point's vector.
* @param[in] cell_hint (optional) A cell iterator for a cell which likely
* contains the first point of @p points.
*
* @return A tuple containing the following information:
* - @p cells : A vector of all the cells containing at least one of
* the @p points .
* - @p qpoints : A vector of vectors of points. @p qpoints[i] contains
* the reference positions of all points that fall within the cell @p cells[i] .
* - @p indices : A vector of vectors of integers, containing the mapping between
* local numbering in @p qpoints , and global index in @p points .
*
* If @p points[a] and @p points[b] are the only two points that fall in @p cells[c],
* then @p qpoints[c][0] and @p qpoints[c][1] are the reference positions of
* @p points[a] and @p points[b] in @p cells[c], and @p indices[c][0] = a,
* @p indices[c][1] = b. The function
* Mapping::transform_unit_to_real(qpoints[c][0])
* returns @p points[a].
*
* The algorithm builds an rtree of @p points to sort them spatially, before
* attempting to call find_active_cell_around_point().
*
* @note This function is not implemented for the codimension one case (<tt>spacedim != dim</tt>).
*
* @note If a point is not found inside the mesh, or is lying inside an
* artificial cell of a parallel::TriangulationBase, the point is silently
* ignored. If you want to infer for which points the search failed, use the
* function compute_point_locations_try_all() that also returns a vector of
* indices indicating the points for which the search failed.
*
* @note The actual return type of this function, i.e., the type referenced
* above as @p return_type, is
* @code
* std::tuple<
* std::vector<
* typename Triangulation<dim, spacedim>::active_cell_iterator>,
* std::vector<std::vector<Point<dim>>>,
* std::vector<std::vector<unsigned int>>>
* @endcode
* The type is abbreviated in the online documentation to improve readability
* of this page.
*
* @note This function optimizes the search by making use of
* GridTools::Cache::get_cell_bounding_boxes_rtree(), which either returns
* a cached rtree or builds and stores one. Building an rtree might hinder
* the performance if the function is called only once on few points.
*/
template <int dim, int spacedim>
#ifndef DOXYGEN
std::tuple<
std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>,
std::vector<std::vector<Point<dim>>>,
std::vector<std::vector<unsigned int>>>
#else
return_type
#endif
compute_point_locations(
const Cache<dim, spacedim> & cache,
const std::vector<Point<spacedim>> &points,
const typename Triangulation<dim, spacedim>::active_cell_iterator
&cell_hint =
typename Triangulation<dim, spacedim>::active_cell_iterator());
/**
* This function is similar to GridTools::compute_point_locations(),
* but while compute_point_locations() silently ignores all points for which
* find_active_cell_around_point() fails, this function also returns a
* vector containing the indices of the points for which
* find_active_cell_around_point() failed.
*
* @return A tuple containing four elements; the first three
* are documented in GridTools::compute_point_locations().
* The last element of the @p return_type contains the
* indices of points which are neither found inside the mesh