Most importantly I'd like to recommend to take a look at the [Element Mesh Generation tutorial](https://reference.wolfram.com/language/FEMDocumentation/tutorial/ElementMeshCreation.html). That tutorial explains mesh generation for numerical applications like the Finite Element Method and covers you question. If anything is unclear there let me know and it can be improved.
I'll try do give a different explanation than given in the tutorial next. Let's consider for a minute that we have a boundary element mesh like the following:
Needs["NDSolve`FEM`"]
bmesh = ToBoundaryMesh["Coordinates" -> {
{1., 0.}, {0.9125378206934781, 0.4089923297618155},{0.6654505497212123, 0.7464419373774067}, {0.32914518683708227, 0.9442793262493796}, {2.8415758474179748*^-8, 0.9999999999999996}, {-0.40899232976181543, 0.9125378206934781}, {-0.7464419373774067, 0.6654505497212122}, {-0.9442793262493796, 0.3291451868370823}, {-0.9999999999999996, 2.8415758313367482*^-8}, {-0.9125378206934783, -0.40899232976181493}, {-0.6654505497212126, -0.7464419373774064}, {-0.3291451868370832, -0.9442793262493793}, {-2.841576059504587*^-8, -0.9999999999999996}, {0.40899232976181327, -0.9125378206934791}, {0.7464419373774028, -0.6654505497212166}, {0.9442793262493757, -0.3291451868370933}},
"BoundaryElements" -> {LineElement[{{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}, {7, 8}, {8, 9}, {9, 10}, {10, 11}, {11, 12}, {12, 13}, {13, 14}, {14, 15}, {15, 16}, {16, 1}}]}];
When we pass that to `ToElementMesh` it will generate a full mesh that approximates the boundary given. `ToElementMesh` has no way of knowing what the original input to `ToBoundaryMesh` was when it is given a boundary mesh representation.
mesh = ToElementMesh[bmesh];
So how well does `ToElementMesh` approximate `bmesh`? We can not really tell because we do not know what `bmesh` is.
Now, I am telling you that `bmesh` is supposed to represent a `Disk[]`. Then and only then we can check:
Pi - Total[mesh["MeshElementMeasure"], 2]
0.0819661
And it is a poor presentation. If you do have a symbolic representation of your region it's a good idea to pass that along. That is what `ToNumericalRegion` is for. Let's look at an example. This generates a numerical region of a `Disk[]`:
nr = ToNumericalRegion[Disk[]];
We can now 'fill in' a boundary mesh like so:
bem2 = ToBoundaryMesh[nr, "MaxBoundaryCellMeasure" -> .5,
AccuracyGoal -> 1]
These options are in fact the ones I used to generate the above example boundary mesh. Note that now the `NumericalRegion` has a boundary mesh - the same as `bem2`
bem2 === nr["BoundaryMesh"]
True
When you pass the numerical region to `ToElementMesh` things are very different as now `ToElementMesh` has access to the boundary representation and the symbolic representation of the region and can thus generate a better mesh.
mesh2 = ToElementMesh[nr];
Pi - Total[mesh2["MeshElementMeasure"], 2]
3.893310501545955`*^-6
When you call
ToElementMesh[Disk[]]
then `ToElementMesh` does have access to the symbolic region. In fact internally, it generates a `NumericalRegion` just as in this post and proceeds like shown here.
You can also set a (boundary) mesh to a `NumericalRegion`:
SetNumericalRegionElementMesh[nr, bmesh]
mesh2 = ToElementMesh[nr]
Pi - Total[mesh2["MeshElementMeasure"], 2]
Hope that helps.