Commit 0a54147c authored by Dennis Gläser's avatar Dennis Gläser
Browse files

[example2] add section on constraints on confined entities

parent 71f0f1dc
......@@ -31,11 +31,16 @@ auto constraintsOnBoundary = constraintsOnSelf;
```
to create a new constraints object. We create this copy here to improve readability
of the code when evaluating the constraints.
Within the loop in which the entities are created,
these constraints are enforced:
of the code when evaluating the constraints. Within the loop in which the entities
are created, all constraints are enforced by writing:
```cpp
if (!constraintsOnSelf.evaluate(entitySet, quad))
{ status.increaseRejectedCounter(); continue; }
if (!constraintsOnOther.evaluate(otherEntitySet, quad))
{ status.increaseRejectedCounter(); continue; }
// we want to enforce constraints also w.r.t. to the cylinder boundary
if (!constraintsOnBoundary.evaluate(domain.topFace(), quad))
{ status.increaseRejectedCounter(); continue; }
......@@ -45,9 +50,16 @@ if (!constraintsOnBoundary.evaluate(OCCUtilities::getShape(domain.lateralFace())
{ status.increaseRejectedCounter(); continue; }
```
As you can see, the `Cylinder` class provides functions for obtaining the representations
of the top, bottom and lateral boundaries. The top and bottom boundaries are represented
by instances of the `Disk` class, while the lateral surface is described by the class
In the first two if clauses, the constraints against other entities are checked, while
subsequently, the constraints against the boundary faces of the domain cylinder are evaluated.
As you can see, the constraints against the other entities are evaluated on the basis of the
raw entities. This can potentially fail to detect small length scales that appear after confining
the entities to the domain. A possibilty to address this and make the algorithm more robust (but
less efficient) is discussed at the end of this page.
As you can see in the above code snippet, the `Cylinder` class provides functions for obtaining th
representations of the top, bottom and lateral boundaries. The top and bottom boundaries are
represented by instances of the `Disk` class, while the lateral surface is described by the class
`CylinderSurface`. Please also note that for the lateral surface, we enforce the constraints
using its representation in OpenCascade, which we obtain by calling `OCCUtilities::getShape`.
We could also write `if (!constraintsOnBoundary.evaluate(domain.lateralFace(), quad)) {...}`,
......@@ -58,7 +70,7 @@ intersect with the edge of the cylindrical surface. The figure below illustrates
of a fracture quadrilateral with both the internal and the OpenCascade representations of cylindrical
surfaces.
<!--- Intersection with cylinder, nternal vs OCC representation --->
<!--- Intersection with cylinder, internal vs OCC representation --->
<p align="center">
<img src="../../doc/img/example2_isection.png" alt="frackit example 2 - cylindrical surface intersection" width="800"/>
</p>
......@@ -127,6 +139,79 @@ writer.write("network", // filename of the .geo files (will add extension .geo a
As you can see, one can specify different mesh sizes to be used on the fracture
entities and in the rest of the domain.
# Enforcing constraints on confined entities
As mentioned above, enforcing the constraints between the raw entities, small length
scales appearing after confining the entities to the domain are not detected. An
illustration of such a situation is depicted in the following figure:
<!--- Intersection of two quadrilateraly inside a cylinder, unconfined vs confined --->
<p align="center">
<img src="../../doc/img/example2_constraints.png" alt="frackit example 2 - unconfined vs confined intersections" width="800"/>
</p>
In such a case, the constraint on the minimum allowed length of intersection segments
might be fulfilled when checked on the raw entities, but might not be fulfilled on the
final geometry after confinement of all entities to the domain.
In order to overcome this, one can also evaluate the constraints on the confined entities,
thus, using the final geometry of an entity after its confinement. This could be achieved
by adjusting the part of the code of this example where the constraints are evaluated in the following way:
```cpp
auto quad = sampleIntoSet1 ? quadSampler1() : quadSampler2();
auto& entitySet = sampleIntoSet1 ? entitySet1 : entitySet2;
const auto& otherEntitySet = sampleIntoSet1 ? entitySet2 : entitySet1;
// get the face(s) that describe(s) the part of the entity that is contained in the domain
using namespace OCCUtilities;
const auto containedShape = cut(getShape(quad), getShape(domain), /*epsilon*/1e-6);
const auto containedFaces = getFaces(containedShape);
// check constraints for all faces making up the contained part
if (std::any_of(containedFaces.begin(),
containedFaces.end(),
[&] (const auto& face)
{ return !constraintsOnSelf.evaluate(entitySet, face); }))
{ status.increaseRejectedCounter(); continue; }
if (std::any_of(containedFaces.begin(),
containedFaces.end(),
[&] (const auto& face)
{ return !constraintsOnSelf.evaluate(otherEntitySet, face); }))
{ status.increaseRejectedCounter(); continue; }
```
If one is certain that the geometry of the confined entity leads to (at most) a
single face, this can be simplified to:
```cpp
auto quad = sampleIntoSet1 ? quadSampler1() : quadSampler2();
auto& entitySet = sampleIntoSet1 ? entitySet1 : entitySet2;
const auto& otherEntitySet = sampleIntoSet1 ? entitySet2 : entitySet1;
// get the face(s) that describe(s) the part of the entity that is contained in the domain
using namespace OCCUtilities;
const auto containedShape = cut(getShape(quad), getShape(domain), /*epsilon*/1e-6);
const auto containedFaces = getFaces(containedShape);
if (containedFaces.size() == 1)
{
if (!constraintsOnSelf.evaluate(entitySet, containedFaces[0]))
{ status.increaseRejectedCounter(); continue; }
if (!constraintsOnSelf.evaluate(otherEntitySet, containedFaces[0]))
{ status.increaseRejectedCounter(); continue; }
}
else
continue;
```
Note that the variable `containedFaces` is of type `std::vector<TopoDS_Face>`,
where `TopoDS_Face` is the _OpenCascade_ type used to represent general two-dimensional
faces. In both of the above code snippets we have assumed `entitySet` and `otherEntitySet`
to also be of type `std::vector<TopoDS_Face>`, and to be composed of the previously
accepted faces.
[go to example 3][2]
[0]: https://git.iws.uni-stuttgart.de/DennisGlaeser/frackit/tree/master/appl/example1
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment