This file is indexed.

/usr/include/deal.II/dofs/dof_tools.h is in libdeal.ii-dev 8.1.0-6ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
// ---------------------------------------------------------------------
// $Id: dof_tools.h 31932 2013-12-08 02:15:54Z heister $
//
// Copyright (C) 1999 - 2013 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#ifndef __deal2__dof_tools_h
#define __deal2__dof_tools_h


#include <deal.II/base/config.h>
#include <deal.II/base/exceptions.h>
#include <deal.II/base/table.h>
#include <deal.II/base/index_set.h>
#include <deal.II/base/point.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/lac/sparsity_pattern.h>
#include <deal.II/dofs/function_map.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/fe/fe.h>
#include <deal.II/fe/component_mask.h>
#include <deal.II/hp/mapping_collection.h>

#include <vector>
#include <set>
#include <map>

DEAL_II_NAMESPACE_OPEN

template<int dim, class T> class Table;
class SparsityPattern;
template <typename number> class Vector;
template <int dim> class Function;
template <int dim, int spacedim> class FiniteElement;
template <int dim, int spacedim> class DoFHandler;
namespace hp
{
  template <int dim, int spacedim> class DoFHandler;
  template <int dim, int spacedim> class MappingCollection;
}
template <int dim, int spacedim> class MGDoFHandler;
class ConstraintMatrix;
template <class GridClass> class InterGridMap;
template <int dim, int spacedim> class Mapping;

namespace GridTools
{
  template <typename CellIterator> struct PeriodicFacePair;
}

//TODO: map_support_points_to_dofs should generate a multimap, rather than just a map, since several dofs may be located at the same support point

/**
 * This is a collection of functions operating on, and manipulating
 * the numbers of degrees of freedom. The documentation of the member
 * functions will provide more information, but for functions that
 * exist in multiple versions, there are sections in this global
 * documentation stating some commonalities.
 *
 * All member functions are static, so there is no need to create an
 * object of class DoFTools.
 *
 *
 * <h3>Setting up sparsity patterns</h3>
 *
 * When assembling system matrices, the entries are usually of the form
 * $a_{ij} = a(\phi_i, \phi_j)$, where $a$ is a bilinear functional, often an
 * integral. When using sparse matrices, we therefore only need to reserve space
 * for those $a_{ij}$ only, which are nonzero, which is the same as to say that
 * the basis functions $\phi_i$ and $\phi_j$ have a nonempty intersection of
 * their support. Since the support of basis functions is bound only on cells
 * on which they are located or to which they are adjacent, to
 * determine the sparsity pattern it is sufficient to loop over all
 * cells and connect all basis functions on each cell with all other
 * basis functions on that cell.  There may be finite elements for
 * which not all basis functions on a cell connect with each other,
 * but no use of this case is made since no examples where this occurs
 * are known to the author.
 *
 *
 * <h3>DoF numberings on boundaries</h3>
 *
 * When projecting the traces of functions to the boundary or parts thereof,
 * one needs to build matrices and vectors that act only on those degrees of
 * freedom that are located on the boundary, rather than on all degrees of
 * freedom. One could do that by simply building matrices in which the entries
 * for all interior DoFs are zero, but such matrices are always very rank
 * deficient and not very practical to work with.
 *
 * What is needed instead in this case is a numbering of the boundary degrees
 * of freedom, i.e. we should enumerate all the degrees of freedom that are
 * sitting on the boundary, and exclude all other (interior) degrees of
 * freedom. The map_dof_to_boundary_indices() function does exactly this: it
 * provides a vector with as many entries as there are degrees of freedom on
 * the whole domain, with each entry being the number in the numbering of the
 * boundary or DoFHandler::invalid_dof_index if the dof is not on the
 * boundary.
 *
 * With this vector, one can get, for any given degree of freedom, a unique
 * number among those DoFs that sit on the boundary; or, if your DoF was
 * interior to the domain, the result would be DoFHandler::invalid_dof_index.
 * We need this mapping, for example, to build the mass matrix on the boundary
 * (for this, see make_boundary_sparsity_pattern() function, the corresponding
 * section below, as well as the MatrixCreator class documentation).
 *
 * Actually, there are two map_dof_to_boundary_indices() functions, one
 * producing a numbering for all boundary degrees of freedom and one producing
 * a numbering for only parts of the boundary, namely those parts for which
 * the boundary indicator is listed in a set of indicators given to the
 * function. The latter case is needed if, for example, we would only want to
 * project the boundary values for the Dirichlet part of the boundary. You
 * then give the function a list of boundary indicators referring to Dirichlet
 * parts on which the projection is to be performed. The parts of the boundary
 * on which you want to project need not be contiguous; however, it is not
 * guaranteed that the indices of each of the boundary parts are continuous,
 * i.e. the indices of degrees of freedom on different parts may be
 * intermixed.
 *
 * Degrees of freedom on the boundary but not on one of the specified
 * boundary parts are given the index DoFHandler::invalid_dof_index, as if
 * they were in the interior. If no boundary indicator was given or if
 * no face of a cell has a boundary indicator contained in the given
 * list, the vector of new indices consists solely of
 * DoFHandler::invalid_dof_index.
 *
 * (As a side note, for corner cases: The question what a degree of freedom on
 * the boundary is, is not so easy.  It should really be a degree of freedom
 * of which the respective basis function has nonzero values on the
 * boundary. At least for Lagrange elements this definition is equal to the
 * statement that the off-point, or what deal.II calls support_point, of the
 * shape function, i.e. the point where the function assumes its nominal value
 * (for Lagrange elements this is the point where it has the function value
 * 1), is located on the boundary. We do not check this directly, the
 * criterion is rather defined through the information the finite element
 * class gives: the FiniteElement class defines the numbers of basis functions
 * per vertex, per line, and so on and the basis functions are numbered after
 * this information; a basis function is to be considered to be on the face of
 * a cell (and thus on the boundary if the cell is at the boundary) according
 * to it belonging to a vertex, line, etc but not to the interior of the
 * cell. The finite element uses the same cell-wise numbering so that we can
 * say that if a degree of freedom was numbered as one of the dofs on lines,
 * we assume that it is located on the line. Where the off-point actually is,
 * is a secret of the finite element (well, you can ask it, but we don't do it
 * here) and not relevant in this context.)
 *
 *
 * <h3>Setting up sparsity patterns for boundary matrices</h3>
 *
 * In some cases, one wants to only work with DoFs that sit on the
 * boundary. One application is, for example, if rather than interpolating
 * non-homogenous boundary values, one would like to project them. For this,
 * we need two things: a way to identify nodes that are located on (parts of)
 * the boundary, and a way to build matrices out of only degrees of freedom
 * that are on the boundary (i.e. much smaller matrices, in which we do not
 * even build the large zero block that stems from the fact that most degrees
 * of freedom have no support on the boundary of the domain). The first of
 * these tasks is done by the map_dof_to_boundary_indices() function of this
 * class (described above).
 *
 * The second part requires us first to build a sparsity pattern for the
 * couplings between boundary nodes, and then to actually build the components
 * of this matrix. While actually computing the entries of these small
 * boundary matrices is discussed in the MatrixCreator class, the creation of
 * the sparsity pattern is done by the create_boundary_sparsity_pattern()
 * function. For its work, it needs to have a numbering of all those degrees
 * of freedom that are on those parts of the boundary that we are interested
 * in. You can get this from the map_dof_to_boundary_indices() function. It
 * then builds the sparsity pattern corresponding to integrals like
 * $\int_\Gamma \varphi_{b2d(i)} \varphi_{b2d(j)} dx$, where $i$ and $j$ are
 * indices into the matrix, and $b2d(i)$ is the global DoF number of a degree
 * of freedom sitting on a boundary (i.e., $b2d$ is the inverse of the mapping
 * returned by map_dof_to_boundary_indices() function).
 *
 *
 * @ingroup dofs
 * @author Wolfgang Bangerth, Guido Kanschat and others
 */
namespace DoFTools
{
  /**
   * The flags used in tables by certain <tt>make_*_pattern</tt>
   * functions to describe whether two components of the solution
   * couple in the bilinear forms corresponding to cell or face
   * terms. An example of using these flags is shown in the
   * introduction of step-46.
   *
   * In the descriptions of the individual elements below, remember
   * that these flags are used as elements of tables of size
   * FiniteElement::n_components times FiniteElement::n_components
   * where each element indicates whether two components do or do not
   * couple.
   */
  enum Coupling
  {
    /**
     * Two components do not couple.
     */
    none,
    /**
     * Two components do couple.
     */
    always,
    /**
     * Two components couple only if their shape functions are both
     * nonzero on a given face. This flag is only used when computing
     * integrals over faces of cells.
     */
    nonzero
  };

  /**
   * @name Auxiliary functions
   * @{
   */
  /**
   * Maximal number of degrees of freedom on a cell.
   *
   * @relates DoFHandler
   */
  template <int dim, int spacedim>
  unsigned int
  max_dofs_per_cell (const DoFHandler<dim,spacedim> &dh);

  /**
   * Maximal number of degrees of freedom on a cell.
   *
   * @relates hp::DoFHandler
   */
  template <int dim, int spacedim>
  unsigned int
  max_dofs_per_cell (const hp::DoFHandler<dim,spacedim> &dh);


  /**
   * Maximal number of degrees of freedom on a face.
   *
   * This function exists for both non-hp and hp DoFHandlers, to allow
   * for a uniform interface to query this property.
   *
   * @relates DoFHandler
   */
  template <int dim, int spacedim>
  unsigned int
  max_dofs_per_face (const DoFHandler<dim,spacedim> &dh);

  /**
   * Maximal number of degrees of freedom on a face.
   *
   * This function exists for both non-hp and hp DoFHandlers, to allow
   * for a uniform interface to query this property.
   *
   * @relates hp::DoFHandler
   */
  template <int dim, int spacedim>
  unsigned int
  max_dofs_per_face (const hp::DoFHandler<dim,spacedim> &dh);

  /**
   * Maximal number of degrees of freedom on a vertex.
   *
   * This function exists for both non-hp and hp DoFHandlers, to allow
   * for a uniform interface to query this property.
   *
   * @relates DoFHandler
   */
  template <int dim, int spacedim>
  unsigned int
  max_dofs_per_vertex (const DoFHandler<dim,spacedim> &dh);

  /**
   * Maximal number of degrees of freedom on a vertex.
   *
   * This function exists for both non-hp and hp DoFHandlers, to allow
   * for a uniform interface to query this property.
   *
   * @relates hp::DoFHandler
   */
  template <int dim, int spacedim>
  unsigned int
  max_dofs_per_vertex (const hp::DoFHandler<dim,spacedim> &dh);

  /**
   * Number of vector components in the finite element object used by
   * this DoFHandler.
   *
   * This function exists for both non-hp and hp DoFHandlers, to allow
   * for a uniform interface to query this property.
   *
   * @relates DoFHandler
   */
  template <int dim, int spacedim>
  unsigned int
  n_components (const DoFHandler<dim,spacedim> &dh);

  /**
   * Number of vector components in the finite element object used by
   * this DoFHandler.
   *
   * This function exists for both non-hp and hp DoFHandlers, to allow
   * for a uniform interface to query this property.
   *
   * @relates hp::DoFHandler
   */
  template <int dim, int spacedim>
  unsigned int
  n_components (const hp::DoFHandler<dim,spacedim> &dh);

  /**
   * Find out whether the FiniteElement used by this DoFHandler is
   * primitive or not.
   *
   * This function exists for both non-hp and hp DoFHandlers, to allow
   * for a uniform interface to query this property.
   *
   * @relates DoFHandler
   */
  template <int dim, int spacedim>
  bool
  fe_is_primitive (const DoFHandler<dim,spacedim> &dh);

  /**
   * Find out whether the FiniteElement used by this DoFHandler is
   * primitive or not.
   *
   * This function exists for both non-hp and hp DoFHandlers, to allow
   * for a uniform interface to query this property.
   *
   * @relates hp::DoFHandler
   */
  template <int dim, int spacedim>
  bool
  fe_is_primitive (const hp::DoFHandler<dim,spacedim> &dh);

  /**
   * @}
   */

  /**
   * @name Sparsity Pattern Generation
   * @{
   */

  /**
   * Locate non-zero entries of the system matrix.
   *
   * This function computes the possible positions of non-zero entries
   * in the global system matrix. We assume that a certain finite
   * element basis function is non-zero on a cell only if its degree
   * of freedom is associated with the interior, a face, an edge or a
   * vertex of this cell. As a result, the matrix entry between two
   * basis functions can be non-zero only if they correspond to
   * degrees of freedom of at least one common cell. Therefore, @p
   * make_sparsity_pattern just loops over all cells and enters all
   * couplings local to that cell. As the generation of the sparsity
   * pattern is irrespective of the equation which is solved later on,
   * the resulting sparsity pattern is symmetric.
   *
   * Remember using SparsityPattern::compress() after generating the
   * pattern.
   *
   * The actual type of the sparsity pattern may be SparsityPattern,
   * CompressedSparsityPattern, BlockSparsityPattern,
   * BlockCompressedSparsityPattern,
   * BlockCompressedSetSparsityPattern,
   * BlockCompressedSimpleSparsityPattern, or any other class that
   * satisfies similar requirements. It is assumed that the size of
   * the sparsity pattern matches the number of degrees of freedom and
   * that enough unused nonzero entries are left to fill the sparsity
   * pattern. The nonzero entries generated by this function are
   * overlaid to possible previous content of the object, that is
   * previously added entries are not deleted.
   *
   * Since this process is purely local, the sparsity pattern does not
   * provide for entries introduced by the elimination of hanging
   * nodes. They have to be taken care of by a call to
   * ConstraintMatrix::condense() afterwards.
   *
   * Alternatively, the constraints on degrees of freedom can already
   * be taken into account at the time of creating the sparsity
   * pattern. For this, pass the ConstraintMatrix object as the third
   * argument to the current function. No call to
   * ConstraintMatrix::condense() is then necessary. This process is
   * explained in step-27.
   *
   * In case the constraints are already taken care of in this
   * function, it is possible to neglect off-diagonal entries in the
   * sparsity pattern. When using
   * ConstraintMatrix::distribute_local_to_global during assembling,
   * no entries will ever be written into these matrix position, so
   * that one can save some computing time in matrix-vector products
   * by not even creating these elements. In that case, the variable
   * <tt>keep_constrained_dofs</tt> needs to be set to <tt>false</tt>.
   *
   * If the @p subdomain_id parameter is given, the sparsity pattern
   * is built only on cells that have a subdomain_id equal to the
   * given argument. This is useful in parallel contexts where the
   * matrix and sparsity pattern (for example a
   * TrilinosWrappers::SparsityPattern) may be distributed and not
   * every MPI process needs to build the entire sparsity pattern; in
   * that case, it is sufficient if every process only builds that
   * part of the sparsity pattern that corresponds to the subdomain_id
   * for which it is responsible. This feature is used in step-32.
   *
   * @ingroup constraints
   */
  template <class DH, class SparsityPattern>
  void
  make_sparsity_pattern (const DH               &dof,
                         SparsityPattern        &sparsity_pattern,
                         const ConstraintMatrix &constraints = ConstraintMatrix(),
                         const bool              keep_constrained_dofs = true,
                         const types::subdomain_id subdomain_id = numbers::invalid_subdomain_id);

  /**
   * Locate non-zero entries for vector valued finite elements.  This
   * function does mostly the same as the previous
   * make_sparsity_pattern(), but it is specialized for vector finite
   * elements and allows to specify which variables couple in which
   * equation. For example, if wanted to solve the Stokes equations,
   *
   * @f{align*}
   * -\Delta \mathbf u + \nabla p &= 0,\\
   * \text{div}\ u                    &= 0
   * @f}
   *
   * in two space dimensions, using stable Q2/Q1 mixed elements (using
   * the FESystem class), then you don't want all degrees of freedom
   * to couple in each equation. You rather may want to give the
   * following pattern of couplings:
   *
   * @f[
   * \left[
   * \begin{array}{ccc}
   *   1 & 0 & 1 \\
   *   0 & 1 & 1 \\
   *   1 & 1 & 0
   * \end{array}
   * \right]
   * @f]
   *
   * where "1" indicates that two variables (i.e. components of the
   * FESystem) couple in the respective equation, and a "0" means no
   * coupling, in which case it is not necessary to allocate space in
   * the matrix structure. Obviously, the mask refers to components of
   * the composed FESystem, rather than to the degrees of freedom
   * contained in there.
   *
   * This function is designed to accept a coupling pattern, like the
   * one shown above, through the @p couplings parameter, which
   * contains values of type #Coupling. It builds the matrix structure
   * just like the previous function, but does not create matrix
   * elements if not specified by the coupling pattern. If the
   * couplings are symmetric, then so will be the resulting sparsity
   * pattern.
   *
   * The actual type of the sparsity pattern may be SparsityPattern,
   * CompressedSparsityPattern, BlockSparsityPattern,
   * BlockCompressedSparsityPattern,
   * BlockCompressedSetSparsityPattern, or any other class that
   * satisfies similar requirements.
   *
   * There is a complication if some or all of the shape functions of
   * the finite element in use are non-zero in more than one component
   * (in deal.II speak: they are non-primitive). In this case, the
   * coupling element correspoding to the first non-zero component is
   * taken and additional ones for this component are ignored.
   *
   * @todo Not implemented for hp::DoFHandler.
   *
   * As mentioned before, the creation of the sparsity pattern is a
   * purely local process and the sparsity pattern does not provide
   * for entries introduced by the elimination of hanging nodes. They
   * have to be taken care of by a call to
   * ConstraintMatrix::condense() afterwards.
   *
   * Alternatively, the constraints on degrees of freedom can already
   * be taken into account at the time of creating the sparsity
   * pattern. For this, pass the ConstraintMatrix object as the third
   * argument to the current function. No call to
   * ConstraintMatrix::condense() is then necessary. This process is
   * explained in @ref step_27 "step-27".
   *
   * In case the constraints are already taken care of in this
   * function, it is possible to neglect off-diagonal entries in the
   * sparsity pattern. When using
   * ConstraintMatrix::distribute_local_to_global during assembling,
   * no entries will ever be written into these matrix position, so
   * that one can save some computing time in matrix-vector products
   * by not even creating these elements. In that case, the variable
   * <tt>keep_constrained_dofs</tt> needs to be set to <tt>false</tt>.
   *
   * If the @p subdomain_id parameter is given, the sparsity pattern
   * is built only on cells that have a subdomain_id equal to the
   * given argument. This is useful in parallel contexts where the
   * matrix and sparsity pattern (for example a
   * TrilinosWrappers::SparsityPattern) may be distributed and not
   * every MPI process needs to build the entire sparsity pattern; in
   * that case, it is sufficient if every process only builds that
   * part of the sparsity pattern that corresponds to the subdomain_id
   * for which it is responsible. This feature is used in step-32.
   *
   * @ingroup constraints
   */
  template <class DH, class SparsityPattern>
  void
  make_sparsity_pattern (const DH                 &dof,
                         const Table<2, Coupling> &coupling,
                         SparsityPattern          &sparsity_pattern,
                         const ConstraintMatrix   &constraints = ConstraintMatrix(),
                         const bool                keep_constrained_dofs = true,
                         const types::subdomain_id subdomain_id = numbers::invalid_subdomain_id);

  /**
   * @deprecated This is the old form of the previous function. It
   * generates a table of DoFTools::Coupling values (where a
   * <code>true</code> value in the mask is translated into a
   * Coupling::always value in the table) and calls the function
   * above.
   */
  template <class DH, class SparsityPattern>
  void
  make_sparsity_pattern (const DH                              &dof,
                         const std::vector<std::vector<bool> > &mask,
                         SparsityPattern                       &sparsity_pattern) DEAL_II_DEPRECATED;

  /**
   * Construct a sparsity pattern that allows coupling degrees of
   * freedom on two different but related meshes.
   *
   * The idea is that if the two given DoFHandler objects correspond
   * to two different meshes (and potentially to different finite
   * elements used on these cells), but that if the two triangulations
   * they are based on are derived from the same coarse mesh through
   * hierarchical refinement, then one may set up a problem where one
   * would like to test shape functions from one mesh against the
   * shape functions from another mesh. In particular, this means that
   * shape functions from a cell on the first mesh are tested against
   * those on the second cell that are located on the corresponding
   * cell; this correspondence is something that the IntergridMap
   * class can determine.
   *
   * This function then constructs a sparsity pattern for which the
   * degrees of freedom that represent the rows come from the first
   * given DoFHandler, whereas the ones that correspond to columns
   * come from the second DoFHandler.
   */
  template <class DH, class SparsityPattern>
  void
  make_sparsity_pattern (const DH        &dof_row,
                         const DH        &dof_col,
                         SparsityPattern &sparsity);

  /**
   * Create the sparsity pattern for boundary matrices. See the
   * general documentation of this class for more information.
   *
   * The actual type of the sparsity pattern may be SparsityPattern,
   * CompressedSparsityPattern, BlockSparsityPattern,
   * BlockCompressedSparsityPattern,
   * BlockCompressedSetSparsityPattern, or any other class that
   * satisfies similar requirements. It is assumed that the size of
   * the sparsity pattern is already correct.
   */
  template <class DH, class SparsityPattern>
  void
  make_boundary_sparsity_pattern (const DH                        &dof,
                                  const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
                                  SparsityPattern                 &sparsity_pattern);

  /**
   * Write the sparsity structure of the matrix composed of the basis
   * functions on the boundary into the matrix structure. In contrast
   * to the previous function, only those parts of the boundary are
   * considered of which the boundary indicator is listed in the set
   * of numbers passed to this function.
   *
   * In fact, rather than a @p set of boundary indicators, a @p map
   * needs to be passed, since most of the functions handling with
   * boundary indicators take a mapping of boundary indicators and the
   * respective boundary functions. The boundary function, however, is
   * ignored in this function.  If you have no functions at hand, but
   * only the boundary indicators, set the function pointers to null
   * pointers.
   *
   * For the type of the sparsity pattern, the same holds as said
   * above.
   */
  template <class DH, class SparsityPattern>
  void
  make_boundary_sparsity_pattern (const DH &dof,
                                  const typename FunctionMap<DH::space_dimension>::type &boundary_indicators,
                                  const std::vector<types::global_dof_index> &dof_to_boundary_mapping,
                                  SparsityPattern    &sparsity);

  /**
   * Generate sparsity pattern for fluxes, i.e. formulations of the
   * discrete problem with discontinuous elements which couple across
   * faces of cells.  This is a replacement of the function @p
   * make_sparsity_pattern for discontinuous methods. Since the fluxes
   * include couplings between neighboring elements, the normal
   * couplings and these extra matrix entries are considered.
   */
  template<class DH, class SparsityPattern>
  void
  make_flux_sparsity_pattern (const DH        &dof_handler,
                              SparsityPattern &sparsity_pattern);

  /**
   * This function does the same as the other with the same name, but
   * it gets a ConstraintMatrix additionally.  This is for the case
   * where you have fluxes but constraints as well.
   *
   * @ingroup constraints
   */
  template<class DH, class SparsityPattern>
  void
  make_flux_sparsity_pattern (const DH        &dof_handler,
                              SparsityPattern &sparsity_pattern,
                              const ConstraintMatrix   &constraints,
                              const bool                keep_constrained_dofs = true,
                              const types::subdomain_id  subdomain_id = numbers::invalid_unsigned_int);

  /**
   * This function does the same as the other with the same name, but
   * it gets two additional coefficient matrices. A matrix entry will
   * only be generated for two basis functions, if there is a non-zero
   * entry linking their associated components in the coefficient
   * matrix.
   *
   * There is one matrix for couplings in a cell and one for the
   * couplings occuring in fluxes.
   *
   * @todo Not implemented for hp::DoFHandler.
   */
  template <class DH, class SparsityPattern>
  void
  make_flux_sparsity_pattern (const DH                &dof,
                              SparsityPattern         &sparsity,
                              const Table<2,Coupling> &int_mask,
                              const Table<2,Coupling> &flux_mask);

  //@}
  /**
   * @name Hanging Nodes
   * @{
   */

  /**
   * Compute the constraints resulting from the presence of hanging
   * nodes. Hanging nodes are best explained using a small picture:
   *
   * @image html hanging_nodes.png
   *
   * In order to make a finite element function globally continuous,
   * we have to make sure that the dark red nodes have values that are
   * compatible with the adjacent yellow nodes, so that the function
   * has no jump when coming from the small cells to the large one at
   * the top right. We therefore have to add conditions that constrain
   * those "hanging nodes".
   *
   * The object into which these are inserted is later used to
   * condense the global system matrix and right hand side, and to
   * extend the solution vectors from the true degrees of freedom also
   * to the constraint nodes. This function is explained in detail in
   * the @ref step_6 "step-6" tutorial program and is used in almost
   * all following programs as well.
   *
   * This function does not clear the constraint matrix object before
   * use, in order to allow adding constraints from different sources
   * to the same object. You therefore need to make sure it contains
   * only constraints you still want; otherwise call the
   * ConstraintMatrix::clear() function.  Likewise, this function does
   * not close the object since you may want to enter other
   * constraints later on yourself.
   *
   * In the hp-case, i.e. when the argument is of type hp::DoFHandler,
   * we consider constraints due to different finite elements used on
   * two sides of a face between cells as hanging nodes as well. In
   * other words, for hp finite elements, this function computes all
   * constraints due to differing mesh sizes (h) or polynomial degrees
   * (p) between adjacent cells.
   *
   * The template argument (and by consequence the type of the first
   * argument to this function) can be either ::DoFHandler or
   * hp::DoFHandler.
   *
   * @ingroup constraints
   */
  template <class DH>
  void
  make_hanging_node_constraints (const DH         &dof_handler,
                                 ConstraintMatrix &constraints);
  //@}


  /**
   * @name Periodic Boundary Conditions
   * @{
   */

  /**
   * Insert the (algebraic) constraints due to periodic boundary
   * conditions into a ConstraintMatrix @p constraint_matrix.
   *
   * Given a pair of not necessarily active boundary faces @p face_1 and
   * @p face_2, this functions constrains all DoFs associated with the boundary
   * described by @p face_1 to the respective DoFs of the boundary described
   * by @p face_2. More precisely:
   *
   * If @p face_1 and @p face_2 are both active faces it adds the DoFs
   * of @p face_1 to the list of constrained DoFs in @p constraint_matrix
   * and adds entries to constrain them to the corresponding values of the
   * DoFs on @p face_2. This happens on a purely algebraic level, meaning,
   * the global DoF with (local face) index <tt>i</tt> on @p face_1 gets
   * constraint to the DoF with (local face) index <tt>i</tt> on @p face_2
   * (possibly corrected for orientation, see below).
   *
   * Otherwise, if @p face_1 and @p face_2 are not active faces, this
   * function loops recursively over the children of @p face_1 and @p face_2.
   * If only one of the two faces is active, then we recursively iterate
   * over the children of the non-active ones and make sure that the
   * solution function on the refined side equals that on the non-refined
   * face in much the same way as we enforce hanging node constraints
   * at places where differently refined cells come together. (However,
   * unlike hanging nodes, we do not enforce the requirement that there
   * be only a difference of one refinement level between the two sides
   * of the domain you would like to be periodic).
   *
   * This routine only constrains DoFs that are not already constrained.
   * If this routine encounters a DoF that already is constrained (for
   * instance by Dirichlet boundary conditions), the old setting of the
   * constraint (dofs the entry is constrained to, inhomogeneities) is
   * kept and nothing happens.
   *
   * The flags in the @p component_mask (see @ref GlossComponentMask)
   * denote which components of the finite element space shall be
   * constrained with periodic boundary conditions. If it is left as
   * specified by the default value all components are constrained. If it
   * is different from the default value, it is assumed that the number
   * of entries equals the number of components the finite element. This
   * can be used to enforce periodicity in only one variable in a system
   * of equations.
   *
   * @p face_orientation, @p face_flip and @p face_rotation describe an
   * orientation that should be applied to @p face_1 prior to matching and
   * constraining DoFs. This has nothing to do with the actual orientation of
   * the given faces in their respective cells (which for boundary faces is
   * always the default) but instead how you want to see periodicity to be
   * enforced. For example, by using these flags, you can enforce a condition
   * of the kind $u(0,y)=u(1,1-y)$ (i.e., a Moebius band) or in 3d
   * a twisted torus. More precisely, these flags match local face DoF indices
   * in the following manner:
   *
   * In 2d: <tt>face_orientation</tt> must always be <tt>true</tt>,
   * <tt>face_rotation</tt> is always <tt>false</tt>, and face_flip has the
   * meaning of <tt>line_flip</tt>; this implies e.g. for <tt>Q1</tt>:
   *
   * @code
   *
   * face_orientation = true, face_flip = false, face_rotation = false:
   *
   *     face1:           face2:
   *
   *     1                1
   *     |        <-->    |
   *     0                0
   *
   *     Resulting constraints: 0 <-> 0, 1 <-> 1
   *
   *     (Numbers denote local face DoF indices.)
   *
   *
   * face_orientation = true, face_flip = true, face_rotation = false:
   *
   *     face1:           face2:
   *
   *     0                1
   *     |        <-->    |
   *     1                0
   *
   *     Resulting constraints: 1 <-> 0, 0 <-> 1
   * @endcode
   *
   * And similarly for the case of Q1 in 3d:
   *
   * @code
   *
   * face_orientation = true, face_flip = false, face_rotation = false:
   *
   *     face1:           face2:
   *
   *     2 - 3            2 - 3
   *     |   |    <-->    |   |
   *     0 - 1            0 - 1
   *
   *     Resulting constraints: 0 <-> 0, 1 <-> 1, 2 <-> 2, 3 <-> 3
   *
   *     (Numbers denote local face DoF indices.)
   *
   *
   * face_orientation = false, face_flip = false, face_rotation = false:
   *
   *     face1:           face2:
   *
   *     1 - 3            2 - 3
   *     |   |    <-->    |   |
   *     0 - 2            0 - 1
   *
   *     Resulting constraints: 0 <-> 0, 2 <-> 1, 1 <-> 2, 3 <-> 3
   *
   *
   * face_orientation = true, face_flip = true, face_rotation = false:
   *
   *     face1:           face2:
   *
   *     1 - 0            2 - 3
   *     |   |    <-->    |   |
   *     3 - 2            0 - 1
   *
   *     Resulting constraints: 3 <-> 0, 2 <-> 1, 1 <-> 2, 0 <-> 3
   *
   *
   * face_orientation = true, face_flip = false, face_rotation = true
   *
   *     face1:           face2:
   *
   *     0 - 2            2 - 3
   *     |   |    <-->    |   |
   *     1 - 3            0 - 1
   *
   *     Resulting constraints: 1 <-> 0, 3 <-> 1, 0 <-> 2, 2 <-> 3
   *
   * and any combination of that...
   * @endcode
   *
   * More information on the topic can be found in the
   * @ref GlossFaceOrientation "glossary" article.
   *
   * @note For DoFHandler objects that are built on a
   * parallel::distributed::Triangulation object
   * parallel::distributed::Triangulation::add_periodicity has to be called
   * before.
   *
   * @author Matthias Maier, 2012
   */
  template<typename FaceIterator>
  void
  make_periodicity_constraints
  (const FaceIterator                          &face_1,
   const typename identity<FaceIterator>::type &face_2,
   dealii::ConstraintMatrix                    &constraint_matrix,
   const ComponentMask                         &component_mask = ComponentMask(),
   const bool                                  face_orientation = true,
   const bool                                  face_flip = false,
   const bool                                  face_rotation = false);



  /**
   * Insert the (algebraic) constraints due to periodic boundary
   * conditions into a ConstraintMatrix @p constraint_matrix.
   *
   * This function serves as a high level interface for the
   * make_periodicity_constraints function that takes face_iterator
   * arguments.
   *
   * Define a 'first' boundary as all boundary faces having boundary_id
   * @p b_id1 and a 'second' boundary consisting of all faces belonging
   * to @p b_id2.
   *
   * This function tries to match all faces belonging to the first
   * boundary with faces belonging to the second boundary with the help
   * of @p orthogonal_equality.
   *
   * If this matching is successful it constrains all DoFs associated
   * with the 'first' boundary to the respective DoFs of the 'second'
   * boundary respecting the relative orientation of the two faces.
   *
   * This routine only constrains DoFs that are not already constrained.
   * If this routine encounters a DoF that already is constrained (for
   * instance by Dirichlet boundary conditions), the old setting of the
   * constraint (dofs the entry is constrained to, inhomogeneities) is
   * kept and nothing happens.
   *
   * The flags in the last parameter, @p component_mask (see @ref
   * GlossComponentMask) denote which components of the finite element space
   * shall be constrained with periodic boundary conditions. If it is left
   * as specified by the default value all components are constrained. If
   * it is different from the default value, it is assumed that the number
   * of entries equals the number of components in the boundary functions
   * and the finite element, and those components in the given boundary
   * function will be used for which the respective flag was set in the
   * component mask.
   *
   * @note For DoFHandler objects that are built on a
   * parallel::distributed::Triangulation object
   * parallel::distributed::Triangulation::add_periodicity has to be called
   * before.
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   *
   * @author Matthias Maier, 2012
   */
  template<typename DH>
  void
  make_periodicity_constraints
  (const DH                 &dof_handler,
   const types::boundary_id b_id1,
   const types::boundary_id b_id2,
   const int                direction,
   dealii::ConstraintMatrix &constraint_matrix,
   const ComponentMask      &component_mask = ComponentMask());


  /**
   * Same as above but with an optional argument @p offset.
   *
   * The @p offset is a vector tangential to the faces that is added to
   * the location of vertices of the 'first' boundary when attempting to
   * match them to the corresponding vertices of the 'second' boundary via
   * @p orthogonal_equality. This can be used to implement conditions such
   * as $u(0,y)=u(1,y+1)$.
   *
   * @note For DoFHandler objects that are built on a
   * parallel::distributed::Triangulation object
   * parallel::distributed::Triangulation::add_periodicity has to be called
   * before.
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   *
   * @author Daniel Arndt, 2013, Matthias Maier, 2012
   */
  template<typename DH>
  void
  make_periodicity_constraints
  (const DH                              &dof_handler,
   const types::boundary_id              b_id1,
   const types::boundary_id              b_id2,
   const int                             direction,
   dealii::Tensor<1,DH::space_dimension> &offset,
   dealii::ConstraintMatrix              &constraint_matrix,
   const ComponentMask                   &component_mask = ComponentMask());


  /**
   * This compatibility version of make_periodicity_constraints only works
   * on grids with cells in @ref GlossFaceOrientation "standard orientation".
   *
   * Instead of defining a 'first' and 'second' boundary with the help of
   * two boundary_indicators this function defines a 'left' boundary as all
   * faces with local face index <code>2*dimension</code> and boundary
   * indicator @p b_id and, similarly, a 'right' boundary consisting of all
   * face with local face index <code>2*dimension+1</code> and boundary
   * indicator @p b_id.
   *
   * @note This version of make_periodicity_constraints  will not work on
   * meshes with cells not in @ref GlossFaceOrientation
   * "standard orientation".
   *
   * @note For DoFHandler objects that are built on a
   * parallel::distributed::Triangulation object
   * parallel::distributed::Triangulation::add_periodicity has to be called
   * before.
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   */
  template<typename DH>
  void
  make_periodicity_constraints
  (const DH                 &dof_handler,
   const types::boundary_id b_id,
   const int                direction,
   dealii::ConstraintMatrix &constraint_matrix,
   const ComponentMask      &component_mask = ComponentMask());


  /**
   * Same as above but with an optional argument @p offset.
   *
   * The @p offset is a vector tangential to the faces that is added to
   * the location of vertices of the 'first' boundary when attempting to
   * match them to the corresponding vertices of the 'second' boundary via
   * @p orthogonal_equality. This can be used to implement conditions such
   * as $u(0,y)=u(1,y+1)$.
   *
   * @note This version of make_periodicity_constraints  will not work on
   * meshes with cells not in @ref GlossFaceOrientation
   * "standard orientation".
   *
   * @note For DoFHandler objects that are built on a
   * parallel::distributed::Triangulation object
   * parallel::distributed::Triangulation::add_periodicity has to be called
   * before.
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   */
  template<typename DH>
  void
  make_periodicity_constraints
  (const DH                              &dof_handler,
   const types::boundary_id              b_id,
   const int                             direction,
   dealii::Tensor<1,DH::space_dimension> &offset,
   dealii::ConstraintMatrix              &constraint_matrix,
   const ComponentMask                   &component_mask = ComponentMask());

  /**
   * Same as above but the periodicity information is given by
   * @p periodic_faces. This std::vector can be created by
   * GridTools::collect_periodic_faces.
   *
   * @note For DoFHandler objects that are built on a
   * parallel::distributed::Triangulation object
   * parallel::distributed::Triangulation::add_periodicity has to be called
   * before.
   */
  template<typename DH>
  void
  make_periodicity_constraints
  (const std::vector<GridTools::PeriodicFacePair<typename DH::cell_iterator> >
   &periodic_faces,
   dealii::ConstraintMatrix &constraint_matrix,
   const ComponentMask      &component_mask = ComponentMask());


  //@}


  /**
   * Take a vector of values which live on cells (e.g. an error per
   * cell) and distribute it to the dofs in such a way that a finite
   * element field results, which can then be further processed,
   * e.g. for output. You should note that the resulting field will
   * not be continuous at hanging nodes. This can, however, easily be
   * arranged by calling the appropriate @p distribute function of a
   * ConstraintMatrix object created for this DoFHandler object, after
   * the vector has been fully assembled.
   *
   * It is assumed that the number of elements in @p cell_data equals
   * the number of active cells and that the number of elements in @p
   * dof_data equals <tt>dof_handler.n_dofs()</tt>.
   *
   * Note that the input vector may be a vector of any data type as
   * long as it is convertible to @p double.  The output vector, being
   * a data vector on a DoF handler, always consists of elements of
   * type @p double.
   *
   * In case the finite element used by this DoFHandler consists of
   * more than one component, you need to specify which component in
   * the output vector should be used to store the finite element
   * field in; the default is zero (no other value is allowed if the
   * finite element consists only of one component). All other
   * components of the vector remain untouched, i.e. their contents
   * are not changed.
   *
   * This function cannot be used if the finite element in use has
   * shape functions that are non-zero in more than one vector
   * component (in deal.II speak: they are non-primitive).
   */
  template <class DH, typename Number>
  void
  distribute_cell_to_dof_vector (const DH              &dof_handler,
                                 const Vector<Number>  &cell_data,
                                 Vector<double>        &dof_data,
                                 const unsigned int     component = 0);

  /**
   * Extract the indices of the degrees of freedom belonging to
   * certain vector components of a vector-valued finite element. The
   * @p component_mask defines which components or blocks of an
   * FESystem are to be extracted from the DoFHandler @p dof. The
   * entries in the output array @p selected_dofs corresponding to
   * degrees of freedom belonging to these components are then flagged
   * @p true, while all others are set to @p false.
   *
   * The size of @p component_mask must be compatible with the number
   * of components in the FiniteElement used by @p dof. The size of @p
   * selected_dofs must equal DoFHandler::n_dofs(). Previous contents
   * of this array are overwritten.
   *
   * If the finite element under consideration is not primitive, i.e.,
   * some or all of its shape functions are non-zero in more than one
   * vector component (which holds, for example, for FE_Nedelec or
   * FE_RaviartThomas elements), then shape functions cannot be
   * associated with a single vector component. In this case, if
   * <em>one</em> shape vector component of this element is flagged in
   * @p component_mask (see @ref GlossComponentMask), then this is
   * equivalent to selecting <em>all</em> vector components
   * corresponding to this non-primitive base element.
   *
   * @note If the @p blocks argument is true,
   */
  template <int dim, int spacedim>
  void
  extract_dofs (const DoFHandler<dim,spacedim>   &dof_handler,
                const ComponentMask &component_mask,
                std::vector<bool>       &selected_dofs);

  /**
   * The same function as above, but for a hp::DoFHandler.
   */
  template <int dim, int spacedim>
  void
  extract_dofs (const hp::DoFHandler<dim,spacedim>   &dof_handler,
                const ComponentMask     &component_mask,
                std::vector<bool>       &selected_dofs);

  /**
   * This function is the equivalent to the DoFTools::extract_dofs() functions above
   * except that the selection of which degrees of freedom to extract is not done
   * based on components (see @ref GlossComponent) but instead based on whether they
   * are part of a particular block (see @ref GlossBlock). Consequently, the second
   * argument is not a ComponentMask but a BlockMask object.
   *
   * @param dof_handler The DoFHandler object from which to extract degrees of freedom
   * @param block_mask The block mask that describes which blocks to consider (see
   *       @ref GlossBlockMask)
   * @param selected_dofs A vector of length DoFHandler::n_dofs() in which those
   *       entries are true that correspond to the selected blocks.
   */
  template <int dim, int spacedim>
  void
  extract_dofs (const DoFHandler<dim,spacedim>   &dof_handler,
                const BlockMask &block_mask,
                std::vector<bool>       &selected_dofs);

  /**
   * The same function as above, but for a hp::DoFHandler.
   */
  template <int dim, int spacedim>
  void
  extract_dofs (const hp::DoFHandler<dim,spacedim>   &dof_handler,
                const BlockMask        &block_mask,
                std::vector<bool>       &selected_dofs);

  /**
   * Do the same thing as the corresponding extract_dofs() function
   * for one level of a multi-grid DoF numbering.
   */
  template <class DH>
  void
  extract_level_dofs (const unsigned int       level,
                      const DH &dof,
                      const ComponentMask     &component_mask,
                      std::vector<bool>       &selected_dofs);

  /**
   * Do the same thing as the corresponding extract_dofs() function
   * for one level of a multi-grid DoF numbering.
   */
  template <class DH>
  void
  extract_level_dofs (const unsigned int       level,
                      const DH &dof,
                      const BlockMask     &component_mask,
                      std::vector<bool>       &selected_dofs);

  /**
   * Extract all degrees of freedom which are at the boundary and
   * belong to specified components of the solution. The function
   * returns its results in the last non-default-valued parameter
   * which contains @p true if a degree of freedom is at the boundary
   * and belongs to one of the selected components, and @p false
   * otherwise. The function is used in step-15.
   *
   * By specifying the @p boundary_indicator variable, you can select
   * which boundary indicators the faces have to have on which the
   * degrees of freedom are located that shall be extracted. If it is
   * an empty list, then all boundary indicators are accepted.
   *
   * The size of @p component_mask (see @ref GlossComponentMask) shall
   * equal the number of components in the finite element used by @p
   * dof. The size of @p selected_dofs shall equal
   * <tt>dof_handler.n_dofs()</tt>. Previous contents of this array or
   * overwritten.
   *
   * Using the usual convention, if a shape function is non-zero in
   * more than one component (i.e. it is non-primitive), then the
   * element in the component mask is used that corresponds to the
   * first non-zero components. Elements in the mask corresponding to
   * later components are ignored.
   *
   * @note This function will not work for DoFHandler objects that are
   * built on a parallel::distributed::Triangulation object. The
   * reasons is that the output argument @p selected_dofs has to have
   * a length equal to <i>all</i> global degrees of freedom.
   * Consequently, this does not scale to very large problems. If you
   * need the functionality of this function for parallel
   * triangulations, then you need to use the other
   * DoFTools::extract_boundary_dofs function.
   *
   * @param dof_handler The object that describes which degrees of freedom
   *          live on which cell
   * @param component_mask A mask denoting the vector components of the
   *          finite element that should be considered (see also
   *          @ref GlossComponentMask).
   * @param selected_dofs The IndexSet object that is returned and that
   *          will contain the indices of degrees of freedom that are
   *          located on the boundary (and correspond to the selected
   *          vector components and boundary indicators, depending on
   *          the values of the @p component_mask and @p boundary_indicators
   *          arguments).
   * @param boundary_indicators If empty, this function extracts the
   *          indices of the degrees of freedom for all parts of the boundary.
   *          If it is a non-empty list, then the function only considers
   *          boundary faces with the boundary indicators listed in this
   *          argument.
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   */
  template <class DH>
  void
  extract_boundary_dofs (const DH                   &dof_handler,
                         const ComponentMask        &component_mask,
                         std::vector<bool>          &selected_dofs,
                         const std::set<types::boundary_id> &boundary_indicators = std::set<types::boundary_id>());

  /**
   * This function does the same as the previous one but it
   * returns its result as an IndexSet rather than a std::vector@<bool@>.
   * Thus, it can also be called for DoFHandler objects that are
   * defined on parallel::distributed::Triangulation objects.
   *
   * @note If the DoFHandler object is indeed defined on a
   * parallel::distributed::Triangulation, then the @p selected_dofs
   * index set will contain only those degrees of freedom on the
   * boundary that belong to the locally relevant set (see
   * @ref GlossLocallyRelevantDof "locally relevant DoFs").
   *
   * @param dof_handler The object that describes which degrees of freedom
   *          live on which cell
   * @param component_mask A mask denoting the vector components of the
   *          finite element that should be considered (see also
   *          @ref GlossComponentMask).
   * @param selected_dofs The IndexSet object that is returned and that
   *          will contain the indices of degrees of freedom that are
   *          located on the boundary (and correspond to the selected
   *          vector components and boundary indicators, depending on
   *          the values of the @p component_mask and @p boundary_indicators
   *          arguments).
   * @param boundary_indicators If empty, this function extracts the
   *          indices of the degrees of freedom for all parts of the boundary.
   *          If it is a non-empty list, then the function only considers
   *          boundary faces with the boundary indicators listed in this
   *          argument.
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   */
  template <class DH>
  void
  extract_boundary_dofs (const DH                   &dof_handler,
                         const ComponentMask        &component_mask,
                         IndexSet                   &selected_dofs,
                         const std::set<types::boundary_id> &boundary_indicators = std::set<types::boundary_id>());

  /**
   * This function is similar to the extract_boundary_dofs() function
   * but it extracts those degrees of freedom whose shape functions
   * are nonzero on at least part of the selected boundary. For
   * continuous elements, this is exactly the set of shape functions
   * whose degrees of freedom are defined on boundary faces. On the
   * other hand, if the finite element in used is a discontinuous
   * element, all degrees of freedom are defined in the inside of
   * cells and consequently none would be boundary degrees of
   * freedom. Several of those would have shape functions that are
   * nonzero on the boundary, however. This function therefore
   * extracts all those for which the
   * FiniteElement::has_support_on_face function says that it is
   * nonzero on any face on one of the selected boundary parts.
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   */
  template <class DH>
  void
  extract_dofs_with_support_on_boundary (const DH               &dof_handler,
                                         const ComponentMask    &component_mask,
                                         std::vector<bool>      &selected_dofs,
                                         const std::set<types::boundary_id> &boundary_indicators = std::set<types::boundary_id>());

  /**
   * @name Hanging Nodes
   * @{
   */

  /**
   * Select all dofs that will be constrained by interface
   * constraints, i.e. all hanging nodes.
   *
   * The size of @p selected_dofs shall equal
   * <tt>dof_handler.n_dofs()</tt>. Previous contents of this array or
   * overwritten.
   */
  template <int dim, int spacedim>
  void
  extract_hanging_node_dofs (const DoFHandler<dim,spacedim> &dof_handler,
                             std::vector<bool>              &selected_dofs);
  //@}

  /**
   * @name Parallelization and domain decomposition
   * @{
   */
  /**
   * Flag all those degrees of freedom which are on cells with the
   * given subdomain id. Note that DoFs on faces can belong to cells
   * with differing subdomain ids, so the sets of flagged degrees of
   * freedom are not mutually exclusive for different subdomain ids.
   *
   * If you want to get a unique association of degree of freedom with
   * subdomains, use the @p get_subdomain_association function.
   */
  template <class DH>
  void
  extract_subdomain_dofs (const DH           &dof_handler,
                          const types::subdomain_id subdomain_id,
                          std::vector<bool>  &selected_dofs);


  /**
   * Extract the set of global DoF indices that are owned by the
   * current processor. For regular DoFHandler objects, this set is
   * the complete set with all DoF indices. In either case, it equals
   * what DoFHandler::locally_owned_dofs() returns.
   */
  template <class DH>
  void
  extract_locally_owned_dofs (const DH &dof_handler,
                              IndexSet &dof_set);


  /**
   * Extract the set of global DoF indices that are active on the
   * current DoFHandler. For regular DoFHandlers, these are all DoF
   * indices, but for DoFHandler objects built on
   * parallel::distributed::Triangulation this set is a superset of
   * DoFHandler::locally_owned_dofs() and contains all DoF indices
   * that live on all locally owned cells (including on the interface
   * to ghost cells). However, it does not contain the DoF indices
   * that are exclusively defined on ghost or artificial cells (see
   * @ref GlossArtificialCell "the glossary").
   *
   * The degrees of freedom identified by this function equal those
   * obtained from the dof_indices_with_subdomain_association()
   * function when called with the locally owned subdomain id.
   */
  template <class DH>
  void
  extract_locally_active_dofs (const DH &dof_handler,
                               IndexSet &dof_set);

  /**
   * Extract the set of global DoF indices that are active on the
   * current DoFHandler. For regular DoFHandlers, these are all DoF
   * indices, but for DoFHandler objects built on
   * parallel::distributed::Triangulation this set is the union of
   * DoFHandler::locally_owned_dofs() and the DoF indices on all ghost
   * cells. In essence, it is the DoF indices on all cells that are
   * not artificial (see @ref GlossArtificialCell "the glossary").
   */
  template <class DH>
  void
  extract_locally_relevant_dofs (const DH &dof_handler,
                                 IndexSet &dof_set);

  /**
   * For each DoF, return in the output array to which subdomain (as
   * given by the <tt>cell->subdomain_id()</tt> function) it
   * belongs. The output array is supposed to have the right size
   * already when calling this function.
   *
   * Note that degrees of freedom associated with faces, edges, and
   * vertices may be associated with multiple subdomains if they are
   * sitting on partition boundaries. In these cases, we put them into
   * one of the associated partitions in an undefined way. This may
   * sometimes lead to different numbers of degrees of freedom in
   * partitions, even if the number of cells is perfectly
   * equidistributed. While this is regrettable, it is not a problem
   * in practice since the number of degrees of freedom on partition
   * boundaries is asymptotically vanishing as we refine the mesh as
   * long as the number of partitions is kept constant.
   *
   * This function returns the association of each DoF with one
   * subdomain. If you are looking for the association of each @em
   * cell with a subdomain, either query the
   * <tt>cell->subdomain_id()</tt> function, or use the
   * <tt>GridTools::get_subdomain_association</tt> function.
   *
   * Note that this function is of questionable use for DoFHandler
   * objects built on parallel::distributed::Triangulation since in
   * that case ownership of individual degrees of freedom by MPI
   * processes is controlled by the DoF handler object, not based on
   * some geometric algorithm in conjunction with subdomain id. In
   * particular, the degrees of freedom identified by the functions in
   * this namespace as associated with a subdomain are not the same
   * the DoFHandler class identifies as those it owns.
   */
  template <class DH>
  void
  get_subdomain_association (const DH                  &dof_handler,
                             std::vector<types::subdomain_id> &subdomain);

  /**
   * Count how many degrees of freedom are uniquely associated with
   * the given @p subdomain index.
   *
   * Note that there may be rare cases where cells with the given @p
   * subdomain index exist, but none of its degrees of freedom are
   * actually associated with it. In that case, the returned value
   * will be zero.
   *
   * This function will generate an exception if there are no cells
   * with the given @p subdomain index.
   *
   * This function returns the number of DoFs associated with one
   * subdomain. If you are looking for the association of @em cells
   * with this subdomain, use the
   * <tt>GridTools::count_cells_with_subdomain_association</tt>
   * function.
   *
   * Note that this function is of questionable use for DoFHandler
   * objects built on parallel::distributed::Triangulation since in
   * that case ownership of individual degrees of freedom by MPI
   * processes is controlled by the DoF handler object, not based on
   * some geometric algorithm in conjunction with subdomain id. In
   * particular, the degrees of freedom identified by the functions in
   * this namespace as associated with a subdomain are not the same
   * the DoFHandler class identifies as those it owns.
   */
  template <class DH>
  unsigned int
  count_dofs_with_subdomain_association (const DH           &dof_handler,
                                         const types::subdomain_id subdomain);

  /**
   * Count how many degrees of freedom are uniquely associated with
   * the given @p subdomain index.
   *
   * This function does what the previous one does except that it
   * splits the result among the vector components of the finite
   * element in use by the DoFHandler object. The last argument (which
   * must have a length equal to the number of vector components) will
   * therefore store how many degrees of freedom of each vector
   * component are associated with the given subdomain.
   *
   * Note that this function is of questionable use for DoFHandler
   * objects built on parallel::distributed::Triangulation since in
   * that case ownership of individual degrees of freedom by MPI
   * processes is controlled by the DoF handler object, not based on
   * some geometric algorithm in conjunction with subdomain id. In
   * particular, the degrees of freedom identified by the functions in
   * this namespace as associated with a subdomain are not the same
   * the DoFHandler class identifies as those it owns.
   */
  template <class DH>
  void
  count_dofs_with_subdomain_association (const DH           &dof_handler,
                                         const types::subdomain_id subdomain,
                                         std::vector<unsigned int> &n_dofs_on_subdomain);

  /**
   * Return a set of indices that denotes the degrees of freedom that
   * live on the given subdomain, i.e. that are on cells owned by the
   * current processor. Note that this includes the ones that this
   * subdomain "owns" (i.e. the ones for which
   * get_subdomain_association() returns a value equal to the
   * subdomain given here and that are selected by the
   * extract_locally_owned() function) but also all of those that sit
   * on the boundary between the given subdomain and other
   * subdomain. In essence, degrees of freedom that sit on boundaries
   * between subdomain will be in the index sets returned by this
   * function for more than one subdomain.
   *
   * Note that this function is of questionable use for DoFHandler
   * objects built on parallel::distributed::Triangulation since in
   * that case ownership of individual degrees of freedom by MPI
   * processes is controlled by the DoF handler object, not based on
   * some geometric algorithm in conjunction with subdomain id. In
   * particular, the degrees of freedom identified by the functions in
   * this namespace as associated with a subdomain are not the same
   * the DoFHandler class identifies as those it owns.
   */
  template <class DH>
  IndexSet
  dof_indices_with_subdomain_association (const DH           &dof_handler,
                                          const types::subdomain_id subdomain);
  // @}
  /**
   * @name Dof indices for patches
   *
   * Create structures containing a large set of degrees of freedom
   * for small patches of cells. The resulting objects can be used in
   * RelaxationBlockSOR and related classes to implement Schwarz
   * preconditioners and smoothers, where the subdomains consist of
   * small numbers of cells only.
   */
  //@{
  /**
   * Create an incidence matrix that for every cell on a given level
   * of a multilevel DoFHandler flags which degrees of freedom are
   * associated with the corresponding cell. This data structure is
   * matrix with as many rows as there are cells on a given level, as
   * many rows as there are degrees of freedom on this level, and
   * entries that are either true or false. This data structure is
   * conveniently represented by a SparsityPattern object.
   *
   * @note The ordering of rows (cells) follows the ordering of the
   * standard cell iterators.
   */
  template <class DH, class Sparsity>
  void make_cell_patches(Sparsity &block_list,
                         const DH &dof_handler,
                         const unsigned int level,
                         const std::vector<bool> &selected_dofs = std::vector<bool>(),
                         types::global_dof_index offset = 0);

  /**
   * Create an incidence matrix that for every vertex on a given level
   * of a multilevel DoFHandler flags which degrees of freedom are
   * associated with the adjacent cells. This data structure is matrix
   * with as many rows as there are vertices on a given level, as many
   * rows as there are degrees of freedom on this level, and entries
   * that are either true or false. This data structure is
   * conveniently represented by a SparsityPattern object.  The
   * sparsity pattern may be empty when entering this function and
   * will be reinitialized to the correct size.
   *
   * The function has some boolean arguments (listed below)
   * controlling details of the generated patches. The default
   * settings are those for Arnold-Falk-Winther type smoothers for
   * divergence and curl conforming finite elements with essential
   * boundary conditions. Other applications are possible, in
   * particular changing <tt>boundary_patches</tt> for non-essential
   * boundary conditions.
   *
   * @arg <tt>block_list</tt>: the SparsityPattern into which the
   * patches will be stored.
   *
   * @arg <tt>dof_handler</tt>: The multilevel dof handler providing
   * the topology operated on.
   *
   * @arg <tt>interior_dofs_only</tt>: for each patch of cells around
   * a vertex, collect only the interior degrees of freedom of the
   * patch and disregard those on the boundary of the patch. This is
   * for instance the setting for smoothers of Arnold-Falk-Winther
   * type.
   *
   * @arg <tt>boundary_patches</tt>: include patches around vertices
   * at the boundary of the domain. If not, only patches around
   * interior vertices will be generated.
   *
   * @arg <tt>level_boundary_patches</tt>: same for refinement edges
   * towards coarser cells.
   *
   * @arg <tt>single_cell_patches</tt>: if not true, patches
   * containing a single cell are eliminated.
   */
  template <class DH>
  void make_vertex_patches(SparsityPattern &block_list,
                           const DH &dof_handler,
                           const unsigned int level,
                           const bool interior_dofs_only,
                           const bool boundary_patches = false,
                           const bool level_boundary_patches = false,
                           const bool single_cell_patches = false);

  /**
   * Create an incidence matrix that for every cell on a given level
   * of a multilevel DoFHandler flags which degrees of freedom are
   * associated with children of this cell. This data structure is
   * conveniently represented by a SparsityPattern object.

   * Create a sparsity pattern which in each row lists the degrees of
   * freedom associated to the cells which are the children of the
   * same cell. The sparsity pattern may be empty when entering this
   * function and will be reinitialized to the correct size.
   *
   * The function has some boolean arguments (listed below)
   * controlling details of the generated patches. The default
   * settings are those for Arnold-Falk-Winther type smoothers for
   * divergence and curl conforming finite elements with essential
   * boundary conditions. Other applications are possible, in
   * particular changing <tt>boundary_dofs</tt> for non-essential
   * boundary conditions.
   *
   * Since the patches are defined through refinement, th
   *
   * @arg <tt>block_list</tt>: the SparsityPattern into which the
   * patches will be stored.
   *
   * @arg <tt>dof_handler</tt>: The multilevel dof handler providing
   * the topology operated on.
   *
   * @arg <tt>interior_dofs_only</tt>: for each patch of cells around
   * a vertex, collect only the interior degrees of freedom of the
   * patch and disregard those on the boundary of the patch. This is
   * for instance the setting for smoothers of Arnold-Falk-Winther
   * type.
   *
   * @arg <tt>boundary_dofs</tt>: include degrees of freedom, which
   * would have excluded by <tt>interior_dofs_only</tt>, but are lying
   * on the boundary of the domain, and thus need smoothing. This
   * parameter has no effect if <tt>interior_dofs_only</tt> is false.
   */
  template <class DH>
  void make_child_patches(SparsityPattern &block_list,
                          const DH &dof_handler,
                          const unsigned int level,
                          const bool interior_dofs_only,
                          const bool boundary_dofs = false);

  /**
   * Create a block list with only a single patch, which in turn
   * contains all degrees of freedom on the given level.
   *
   * This function is mostly a closure on level 0 for functions like
   * make_child_patches() and make_vertex_patches(), which may produce
   * an empty patch list.
   *
   * @arg <tt>block_list</tt>: the SparsityPattern into which the
   * patches will be stored.
   *
   * @arg <tt>dof_handler</tt>: The multilevel dof handler providing
   * the topology operated on.
   *
   * @arg <tt>level</tt> The grid level used for building the list.
   *
   * @arg <tt>interior_dofs_only</tt>: if true, exclude degrees of
   * freedom on the boundary of the domain.
   */
  template <class DH>
  void make_single_patch(SparsityPattern &block_list,
                         const DH &dof_handler,
                         const unsigned int level,
                         const bool interior_dofs_only = false);

  //@}
  /**
   * Extract a vector that represents the constant modes of the
   * DoFHandler for the components chosen by <tt>component_mask</tt>
   * (see @ref GlossComponentMask).  The constant modes on a
   * discretization are the null space of a Laplace operator on the
   * selected components with Neumann boundary conditions applied. The
   * null space is a necessary ingredient for obtaining a good AMG
   * preconditioner when using the class
   * TrilinosWrappers::PreconditionAMG.  Since the ML AMG package only
   * works on algebraic properties of the respective matrix, it has no
   * chance to detect whether the matrix comes from a scalar or a
   * vector valued problem. However, a near null space supplies
   * exactly the needed information about these components.  The null
   * space will consist of as many vectors as there are true arguments
   * in <tt>component_mask</tt> (see @ref GlossComponentMask), each of
   * which will be one in one vector component and zero in all
   * others. We store this object in a vector of vectors, where the
   * outer vector is of the size of the number of selected components,
   * and each inner vector has as many components as there are
   * (locally owned) degrees of freedom in the selected
   * components. Note that any matrix associated with this null space
   * must have been constructed using the same <tt>component_mask</tt>
   * argument, since the numbering of DoFs is done relative to the
   * selected dofs, not to all dofs.
   *
   * The main reason for this program is the use of the null space
   * with the AMG preconditioner.
   */
  template <class DH>
  void
  extract_constant_modes (const DH                        &dof_handler,
                          const ComponentMask             &component_mask,
                          std::vector<std::vector<bool> > &constant_modes);

  /**
   * For each active cell of a DoFHandler or hp::DoFHandler, extract
   * the active finite element index and fill the vector given as
   * second argument. This vector is assumed to have as many entries
   * as there are active cells.
   *
   * For non-hp DoFHandler objects given as first argument, the
   * returned vector will consist of only zeros, indicating that all
   * cells use the same finite element. For a hp::DoFHandler, the
   * values may be different, though.
   */
  template <class DH>
  void
  get_active_fe_indices (const DH                  &dof_handler,
                         std::vector<unsigned int> &active_fe_indices);

  /**
   * Count how many degrees of freedom out of the total number belong
   * to each component. If the number of components the finite element
   * has is one (i.e. you only have one scalar variable), then the
   * number in this component obviously equals the total number of
   * degrees of freedom. Otherwise, the sum of the DoFs in all the
   * components needs to equal the total number.
   *
   * However, the last statement does not hold true if the finite
   * element is not primitive, i.e. some or all of its shape functions
   * are non-zero in more than one vector component. This applies, for
   * example, to the Nedelec or Raviart-Thomas elements. In this case,
   * a degree of freedom is counted in each component in which it is
   * non-zero, so that the sum mentioned above is greater than the
   * total number of degrees of freedom.
   *
   * This behavior can be switched off by the optional parameter
   * <tt>vector_valued_once</tt>. If this is <tt>true</tt>, the number
   * of components of a nonprimitive vector valued element is
   * collected only in the first component. All other components will
   * have a count of zero.
   *
   * The additional optional argument @p target_component allows for a
   * re-sorting and grouping of components. To this end, it contains
   * for each component the component number it shall be counted
   * as. Having the same number entered several times sums up several
   * components as the same. One of the applications of this argument
   * is when you want to form block matrices and vectors, but want to
   * pack several components into the same block (for example, when
   * you have @p dim velocities and one pressure, to put all
   * velocities into one block, and the pressure into another).
   *
   * The result is returned in @p dofs_per_component. Note that the
   * size of @p dofs_per_component needs to be enough to hold all the
   * indices specified in @p target_component. If this is not the
   * case, an assertion is thrown. The indices not targeted by
   * target_components are left untouched.
   */
  template <class DH>
  void
  count_dofs_per_component (const DH      &dof_handler,
                            std::vector<types::global_dof_index> &dofs_per_component,
                            const bool vector_valued_once = false,
                            std::vector<unsigned int>  target_component
                            = std::vector<unsigned int>());

  /**
   * Count the degrees of freedom in each block. This function is
   * similar to count_dofs_per_component(), with the difference that
   * the counting is done by blocks. See @ref GlossBlock "blocks" in
   * the glossary for details. Again the vectors are assumed to have
   * the correct size before calling this function. If this is not the
   * case, an assertion is thrown.
   *
   * This function is used in the step-22, step-31, and step-32
   * tutorial programs.
   *
   * @pre The dofs_per_block variable has as many components as the
   * finite element used by the dof_handler argument has blocks, or
   * alternatively as many blocks as are enumerated in the
   * target_blocks argument if given.
   */
  template <class DH>
  void
  count_dofs_per_block (const DH &dof,
                        std::vector<types::global_dof_index> &dofs_per_block,
                        const std::vector<unsigned int>  &target_block
                        = std::vector<unsigned int>());

  /**
   * @deprecated See the previous function with the same name for a
   * description. This function exists for compatibility with older
   * versions only.
   */
  template <int dim, int spacedim>
  void
  count_dofs_per_component (const DoFHandler<dim,spacedim>     &dof_handler,
                            std::vector<types::global_dof_index> &dofs_per_component,
                            std::vector<unsigned int>  target_component) DEAL_II_DEPRECATED;

  /**
   * This function can be used when different variables shall be
   * discretized on different grids, where one grid is coarser than
   * the other. This idea might seem nonsensical at first, but has
   * reasonable applications in inverse (parameter estimation)
   * problems, where there might not be enough information to recover
   * the parameter on the same grid as the state variable;
   * furthermore, the smoothness properties of state variable and
   * parameter might not be too much related, so using different grids
   * might be an alternative to using stronger regularization of the
   * problem.
   *
   * The basic idea of this function is explained in the
   * following. Let us, for convenience, denote by ``parameter grid''
   * the coarser of the two grids, and by ``state grid'' the finer of
   * the two. We furthermore assume that the finer grid can be
   * obtained by refinement of the coarser one, i.e. the fine grid is
   * at least as much refined as the coarse grid at each point of the
   * domain. Then, each shape function on the coarse grid can be
   * represented as a linear combination of shape functions on the
   * fine grid (assuming identical ansatz spaces). Thus, if we
   * discretize as usual, using shape functions on the fine grid, we
   * can consider the restriction that the parameter variable shall in
   * fact be discretized by shape functions on the coarse grid as a
   * constraint. These constraints are linear and happen to have the
   * form managed by the ``ConstraintMatrix'' class.
   *
   * The construction of these constraints is done as follows: for
   * each of the degrees of freedom (i.e. shape functions) on the
   * coarse grid, we compute its representation on the fine grid,
   * i.e. how the linear combination of shape functions on the fine
   * grid looks like that resembles the shape function on the coarse
   * grid. From this information, we can then compute the constraints
   * which have to hold if a solution of a linear equation on the fine
   * grid shall be representable on the coarse grid. The exact
   * algorithm how these constraints can be computed is rather
   * complicated and is best understood by reading the source code,
   * which contains many comments.
   *
   * Before explaining the use of this function, we would like to
   * state that the total number of degrees of freedom used for the
   * discretization is not reduced by the use of this function,
   * i.e. even though we discretize one variable on a coarser grid,
   * the total number of degrees of freedom is that of the fine
   * grid. This seems to be counter-productive, since it does not give
   * us a benefit from using a coarser grid. The reason why it may be
   * useful to choose this approach nonetheless is three-fold: first,
   * as stated above, there might not be enough information to recover
   * a parameter on a fine grid, i.e. we chose to discretize it on the
   * coarse grid not to save DoFs, but for other reasons. Second, the
   * ``ConstraintMatrix'' includes the constraints into the linear
   * system of equations, by which constrained nodes become dummy
   * nodes; we may therefore exclude them from the linear algebra, for
   * example by sorting them to the back of the DoF numbers and simply
   * calling the solver for the upper left block of the matrix which
   * works on the non-constrained nodes only, thus actually realizing
   * the savings in numerical effort from the reduced number of actual
   * degrees of freedom. The third reason is that for some or other
   * reason we have chosen to use two different grids, it may be
   * actually quite difficult to write a function that assembles the
   * system matrix for finite element spaces on different grids; using
   * the approach of constraints as with this function allows to use
   * standard techniques when discretizing on only one grid (the finer
   * one) without having to take care of the fact that one or several
   * of the variable actually belong to different grids.
   *
   * The use of this function is as follows: it accepts as parameters
   * two DoF Handlers, the first of which refers to the coarse grid
   * and the second of which is the fine grid. On both, a finite
   * element is represented by the DoF handler objects, which will
   * usually have several components, which may belong to different
   * finite elements. The second and fourth parameter of this function
   * therefore state which variable on the coarse grid shall be used
   * to restrict the stated component on the fine grid. Of course, the
   * finite elements used for the respective components on the two
   * grids need to be the same. An example may clarify this: consider
   * the parameter estimation mentioned briefly above; there, on the
   * fine grid the whole discretization is done, thus the variables
   * are ``u'', ``q'', and the Lagrange multiplier ``lambda'', which
   * are discretized using continuous linear, piecewise constant
   * discontinuous, and continuous linear elements, respectively. Only
   * the parameter ``q'' shall be represented on the coarse grid, thus
   * the DoFHandler object on the coarse grid represents only one
   * variable, discretized using piecewise constant discontinuous
   * elements. Then, the parameter denoting the component on the
   * coarse grid would be zero (the only possible choice, since the
   * variable on the coarse grid is scalar), and one on the fine grid
   * (corresponding to the variable ``q''; zero would be ``u'', two
   * would be ``lambda''). Furthermore, an object of type IntergridMap
   * is needed; this could in principle be generated by the function
   * itself from the two DoFHandler objects, but since it is probably
   * available anyway in programs that use this function, we shall use
   * it instead of re-generating it. Finally, the computed constraints
   * are entered into a variable of type ConstraintMatrix; the
   * constraints are added, i.e. previous contents which may have, for
   * example, be obtained from hanging nodes, are not deleted, so that
   * you only need one object of this type.
   */
  template <int dim, int spacedim>
  void
  compute_intergrid_constraints (const DoFHandler<dim,spacedim>              &coarse_grid,
                                 const unsigned int                  coarse_component,
                                 const DoFHandler<dim,spacedim>              &fine_grid,
                                 const unsigned int                  fine_component,
                                 const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
                                 ConstraintMatrix                   &constraints);


  /**
   * This function generates a matrix such that when a vector of data
   * with as many elements as there are degrees of freedom of this
   * component on the coarse grid is multiplied to this matrix, we
   * obtain a vector with as many elements are there are global
   * degrees of freedom on the fine grid. All the elements of the
   * other components of the finite element fields on the fine grid
   * are not touched.
   *
   * The output of this function is a compressed format that can be
   * given to the @p reinit functions of the SparsityPattern ad
   * SparseMatrix classes.
   */
  template <int dim, int spacedim>
  void
  compute_intergrid_transfer_representation (const DoFHandler<dim,spacedim>              &coarse_grid,
                                             const unsigned int                  coarse_component,
                                             const DoFHandler<dim,spacedim>              &fine_grid,
                                             const unsigned int                  fine_component,
                                             const InterGridMap<DoFHandler<dim,spacedim> > &coarse_to_fine_grid_map,
                                             std::vector<std::map<types::global_dof_index, float> > &transfer_representation);

  /**
   * Create a mapping from degree of freedom indices to the index of
   * that degree of freedom on the boundary. After this operation,
   * <tt>mapping[dof]</tt> gives the index of the degree of freedom
   * with global number @p dof in the list of degrees of freedom on
   * the boundary.  If the degree of freedom requested is not on the
   * boundary, the value of <tt>mapping[dof]</tt> is @p
   * invalid_dof_index. This function is mainly used when setting up
   * matrices and vectors on the boundary from the trial functions,
   * which have global numbers, while the matrices and vectors use
   * numbers of the trial functions local to the boundary.
   *
   * Prior content of @p mapping is deleted.
   */
  template <class DH>
  void
  map_dof_to_boundary_indices (const DH                   &dof_handler,
                               std::vector<types::global_dof_index>  &mapping);

  /**
   * Same as the previous function, except that only those parts of
   * the boundary are considered for which the boundary indicator is
   * listed in the second argument.
   *
   * See the general doc of this class for more information.
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   */
  template <class DH>
  void
  map_dof_to_boundary_indices (const DH                      &dof_handler,
                               const std::set<types::boundary_id> &boundary_indicators,
                               std::vector<types::global_dof_index>     &mapping);

  /**
   * Return a list of support points (see this @ref GlossSupport
   * "glossary entry") for all the degrees of freedom handled by this
   * DoF handler object. This function, of course, only works if the
   * finite element object used by the DoF handler object actually
   * provides support points, i.e. no edge elements or the
   * like. Otherwise, an exception is thrown.
   *
   * @pre The given array must have a length of as many elements as
   * there are degrees of freedom.
   *
   * @note The precondition to this function that the output argument
   * needs to have size equal to the total number of degrees of
   * freedom makes this function unsuitable for the case that the
   * given DoFHandler object derives from a
   * parallel::distributed::Triangulation object.  Consequently, this
   * function will produce an error if called with such a DoFHandler.
   */
  template <int dim, int spacedim>
  void
  map_dofs_to_support_points (const Mapping<dim,spacedim>       &mapping,
                              const DoFHandler<dim,spacedim>    &dof_handler,
                              std::vector<Point<spacedim> >     &support_points);

  /**
   * Same as the previous function but for the hp case.
   */

  template <int dim, int spacedim>
  void
  map_dofs_to_support_points (const dealii::hp::MappingCollection<dim,spacedim>   &mapping,
                              const hp::DoFHandler<dim,spacedim>    &dof_handler,
                              std::vector<Point<spacedim> > &support_points);

  /**
   * This function is a version of the above map_dofs_to_support_points
   * function that doesn't simply return a vector of support points (see
   * this @ref GlossSupport "glossary entry") with one
   * entry for each global degree of freedom, but instead a map that
   * maps from the DoFs index to its location. The point of this
   * function is that it is also usable in cases where the DoFHandler
   * is based on a parallel::distributed::Triangulation object. In such cases,
   * each processor will not be able to determine the support point location
   * of all DoFs, and worse no processor may be able to hold a vector that
   * would contain the locations of all DoFs even if they were known. As
   * a consequence, this function constructs a map from those DoFs for which
   * we can know the locations (namely, those DoFs that are
   * locally relevant (see @ref GlossLocallyRelevantDof "locally relevant DoFs")
   * to their locations.
   *
   * For non-distributed triangulations, the map returned as @p support_points
   * is of course dense, i.e., every DoF is to be found in it.
   *
   * @param mapping The mapping from the reference cell to the real cell on
   *        which DoFs are defined.
   * @param dof_handler The object that describes which DoF indices live on
   *        which cell of the triangulation.
   * @param support_points A map that for every locally relevant DoF index
   *        contains the corresponding location in real space coordinates.
   *        Previous content of this object is deleted in this function.
   */
  template <int dim, int spacedim>
  void
  map_dofs_to_support_points (const Mapping<dim,spacedim>       &mapping,
                              const DoFHandler<dim,spacedim>    &dof_handler,
                              std::map<types::global_dof_index, Point<spacedim> >     &support_points);

  /**
   * Same as the previous function but for the hp case.
   */
  template <int dim, int spacedim>
  void
  map_dofs_to_support_points (const dealii::hp::MappingCollection<dim,spacedim>   &mapping,
                              const hp::DoFHandler<dim,spacedim>    &dof_handler,
                              std::map<types::global_dof_index, Point<spacedim> > &support_points);


  /**
   * This is the opposite function to the one above. It generates a
   * map where the keys are the support points of the degrees of
   * freedom, while the values are the DoF indices. For a definition
   * of support points, see this @ref GlossSupport "glossary entry".
   *
   * Since there is no natural order in the space of points (except
   * for the 1d case), you have to provide a map with an explicitly
   * specified comparator object. This function is therefore
   * templatized on the comparator object. Previous content of the map
   * object is deleted in this function.
   *
   * Just as with the function above, it is assumed that the finite
   * element in use here actually supports the notion of support
   * points of all its components.
   */
  template <class DH, class Comp>
  void
  map_support_points_to_dofs (const Mapping<DH::dimension, DH::space_dimension> &mapping,
                              const DH                                          &dof_handler,
                              std::map<Point<DH::space_dimension>, types::global_dof_index, Comp> &point_to_index_map);

  /**
   * Map a coupling table from the user friendly organization by
   * components to the organization by blocks. Specializations of this
   * function for DoFHandler and hp::DoFHandler are required due to
   * the different results of their finite element access.
   *
   * The return vector will be initialized to the correct length
   * inside this function.
   */
  template <int dim, int spacedim>
  void
  convert_couplings_to_blocks (const hp::DoFHandler<dim,spacedim> &dof_handler,
                               const Table<2, Coupling> &table_by_component,
                               std::vector<Table<2,Coupling> > &tables_by_block);

  /**
   * Make a constraint matrix for the constraints that result from
   * zero boundary values on the given boundary indicator.
   *
   * This function constrains all degrees of freedom on the given part
   * of the boundary.
   *
   * A variant of this function with different arguments is used in
   * step-36.
   *
   * @param dof The DoFHandler to work on.
   * @param boundary_indicator The indicator of that part of the boundary
   *   for which constraints should be computed. If this number equals
   *   numbers::invalid_boundary_id then all boundaries of the domain
   *   will be treated.
   * @param zero_boundary_constraints The constraint object into which the
   *   constraints will be written. The new constraints due to zero boundary
   *   values will simply be added, preserving any other constraints
   *   previously present. However, this will only work if the previous
   *   content of that object consists of constraints on degrees of freedom
   *   that are not located on the boundary treated here. If there are
   *   previously existing constraints for degrees of freedom located on the
   *   boundary, then this would constitute a conflict. See the @ref constraints
   *   module for handling the case where there are conflicting constraints
   *   on individual degrees of freedom.
   * @param component_mask An optional component mask that
   *   restricts the functionality of this function to a subset of an FESystem.
   *   For non-@ref GlossPrimitive "primitive"
   *   shape functions, any degree of freedom
   *   is affected that belongs to a
   *   shape function where at least
   *   one of its nonzero components
   *   is affected by the component mask (see @ref GlossComponentMask). If
   *   this argument is omitted, all components of the finite element with
   *   degrees of freedom at the boundary will be considered.
   *
   * @ingroup constraints
   *
   * @see @ref GlossBoundaryIndicator "Glossary entry on boundary indicators"
   */
  template <int dim, int spacedim, template <int, int> class DH>
  void
  make_zero_boundary_constraints (const DH<dim,spacedim> &dof,
                                  const types::boundary_id boundary_indicator,
                                  ConstraintMatrix       &zero_boundary_constraints,
                                  const ComponentMask    &component_mask = ComponentMask());

  /**
   * Do the same as the previous function, except do it for all
   * parts of the boundary, not just those with a particular boundary
   * indicator. This function is then equivalent to calling the previous
   * one with numbers::invalid_boundary_id as second argument.
   *
   * This function is used in step-36, for example.
   *
   * @ingroup constraints
   */
  template <int dim, int spacedim, template <int, int> class DH>
  void
  make_zero_boundary_constraints (const DH<dim,spacedim> &dof,
                                  ConstraintMatrix       &zero_boundary_constraints,
                                  const ComponentMask    &component_mask = ComponentMask());


  /**
   * Map a coupling table from the user friendly organization by
   * components to the organization by blocks. Specializations of this
   * function for DoFHandler and hp::DoFHandler are required due to
   * the different results of their finite element access.
   *
   * The return vector will be initialized to the correct length
   * inside this function.
   */
  template <int dim, int spacedim>
  void
  convert_couplings_to_blocks (const DoFHandler<dim,spacedim> &dof_handler,
                               const Table<2, Coupling> &table_by_component,
                               std::vector<Table<2,Coupling> > &tables_by_block);

  /**
   * Given a finite element and a table how the vector components of
   * it couple with each other, compute and return a table that
   * describes how the individual shape functions couple with each
   * other.
   */
  template <int dim, int spacedim>
  Table<2,Coupling>
  dof_couplings_from_component_couplings (const FiniteElement<dim,spacedim> &fe,
                                          const Table<2,Coupling> &component_couplings);

  /**
   * Same function as above for a collection of finite elements,
   * returning a collection of tables.
   *
   * The function currently treats DoFTools::Couplings::nonzero the
   * same as DoFTools::Couplings::always .
   */
  template <int dim, int spacedim>
  std::vector<Table<2,Coupling> >
  dof_couplings_from_component_couplings (const hp::FECollection<dim,spacedim> &fe,
                                          const Table<2,Coupling> &component_couplings);
  /**
   * @todo Write description
   *
   * @ingroup Exceptions
   */
  DeclException0 (ExcFiniteElementsDontMatch);
  /**
   * @todo Write description
   *
   * @ingroup Exceptions
   */
  DeclException0 (ExcGridNotCoarser);
  /**
   * @todo Write description
   *
   * Exception
   * @ingroup Exceptions
   */
  DeclException0 (ExcGridsDontMatch);
  /**
   * The ::DoFHandler or hp::DoFHandler was not initialized with a
   * finite element. Please call DoFHandler::distribute_dofs() etc. first.
   *
   * @ingroup Exceptions
   */
  DeclException0 (ExcNoFESelected);
  /**
   * @todo Write description
   *
   * @ingroup Exceptions
   */
  DeclException0 (ExcInvalidBoundaryIndicator);
}



/* ------------------------- inline functions -------------- */

#ifndef DOXYGEN

namespace DoFTools
{
  /**
   * Operator computing the maximum coupling out of two.
   *
   * @relates DoFTools
   */
  inline
  Coupling operator |= (Coupling &c1,
                        const Coupling c2)
  {
    if (c2 == always)
      c1 = always;
    else if (c1 != always && c2 == nonzero)
      return c1 = nonzero;
    return c1;
  }


  /**
   * Operator computing the maximum coupling out of two.
   *
   * @relates DoFTools
   */
  inline
  Coupling operator | (const Coupling c1,
                       const Coupling c2)
  {
    if (c1 == always || c2 == always)
      return always;
    if (c1 == nonzero || c2 == nonzero)
      return nonzero;
    return none;
  }


// ---------------------- inline and template functions --------------------

  template <int dim, int spacedim>
  inline
  unsigned int
  max_dofs_per_cell (const DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe().dofs_per_cell;
  }


  template <int dim, int spacedim>
  inline
  unsigned int
  max_dofs_per_face (const DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe().dofs_per_face;
  }


  template <int dim, int spacedim>
  inline
  unsigned int
  max_dofs_per_vertex (const DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe().dofs_per_vertex;
  }


  template <int dim, int spacedim>
  inline
  unsigned int
  n_components (const DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe().n_components();
  }



  template <int dim, int spacedim>
  inline
  bool
  fe_is_primitive (const DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe().is_primitive();
  }


  template <int dim, int spacedim>
  inline
  unsigned int
  max_dofs_per_cell (const hp::DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe().max_dofs_per_cell ();
  }


  template <int dim, int spacedim>
  inline
  unsigned int
  max_dofs_per_face (const hp::DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe().max_dofs_per_face ();
  }


  template <int dim, int spacedim>
  inline
  unsigned int
  max_dofs_per_vertex (const hp::DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe().max_dofs_per_vertex ();
  }


  template <int dim, int spacedim>
  inline
  unsigned int
  n_components (const hp::DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe()[0].n_components();
  }


  template <int dim, int spacedim>
  inline
  bool
  fe_is_primitive (const hp::DoFHandler<dim,spacedim> &dh)
  {
    return dh.get_fe()[0].is_primitive();
  }


  template <class DH, class SparsityPattern>
  inline
  void
  make_sparsity_pattern (const DH                              &dof,
                         const std::vector<std::vector<bool> > &mask,
                         SparsityPattern                       &sparsity_pattern)
  {
    const unsigned int ncomp = dof.get_fe().n_components();

    Assert (mask.size() == ncomp,
            ExcDimensionMismatch(mask.size(), ncomp));
    for (unsigned int i=0; i<mask.size(); ++i)
      Assert (mask[i].size() == ncomp,
              ExcDimensionMismatch(mask[i].size(), ncomp));
    // Create a coupling table out of the mask
    Table<2,DoFTools::Coupling> couplings(ncomp, ncomp);
    for (unsigned int i=0; i<ncomp; ++i)
      for (unsigned int j=0; j<ncomp; ++j)
        if (mask[i][j])
          couplings(i,j) = always;
        else
          couplings(i,j) = none;

    // Call the new function
    make_sparsity_pattern(dof, couplings, sparsity_pattern);
  }


  template <class DH, class Comp>
  void
  map_support_points_to_dofs (
    const Mapping<DH::dimension,DH::space_dimension>         &mapping,
    const DH                                                 &dof_handler,
    std::map<Point<DH::space_dimension>, types::global_dof_index, Comp> &point_to_index_map)
  {
    // let the checking of arguments be
    // done by the function first
    // called
    std::vector<Point<DH::space_dimension> > support_points (dof_handler.n_dofs());
    map_dofs_to_support_points (mapping, dof_handler, support_points);
    // now copy over the results of the
    // previous function into the
    // output arg
    point_to_index_map.clear ();
    for (types::global_dof_index i=0; i<dof_handler.n_dofs(); ++i)
      point_to_index_map[support_points[i]] = i;
  }
}

#endif

DEAL_II_NAMESPACE_CLOSE

#endif