HowTo setting up dynamic mesh cases
From this thread in the message board: Dynamic mesh changes (recovered via web.archive.org)
Contents
1 Basics
Basically, we've got three things to go through:
- automatic mesh motion
- layer addition/removal
- sliding interface
Please note that in most cases, the sliding interface and layer addition/removal will also require mesh motion, but it needs to be set up such that it works with the mesh modifier.
1.1 Automatic mesh motion
This is used for cases when the geometry does not change. The motionSolver class uses a FEM solver in foam to determine the new point positions from the old ones. The way to get it to work is to specify motion of boundaries as boundary conditions on the motionU field, and then use the solution to update point position. Note that the motion of one boundary will influence the complete mesh, i.e. (almost) all points in the mesh will move. If the boundary motion is time- or solution-dependent, this needs to be built into the top-level solver.
A good example for this is the icoFoamAutoMotion tutorial and I don't think this will interest you much (pretty straightforward so far)
1.2 Topological changes in the mesh
1.2.1 General implementation.
The idea is that one can define 9 basic operations on a mesh which allow all possible changes that I can imagine. They are: add/modify/remove point, face or a cell. With those 9 commands I can do everything possible on a mesh. The classes that describe this live in:
OpenFOAM-1.0/src/OpenFOAM/meshes/polyMesh/morphEngine/polyTopoChange
and are all derived from topoAction. There is a class for each of the operations in the same directory - have a look and describe what kind of change can be done.
However, taking a valid initial mesh and adding a point or removing a cell is not sufficient: doing this in an arbitrary manner will simple create an invalid mesh. Therefore, a bunch of changes needs to be grouped together until they make a sensible change in the mesh, like for example, addition of a cell layer. This is described by the polyTopoChange class - it can take a group of topoActions that belong together using a steAction member function.
At this stage, I can make myself a polyTopoChange object and put a bunch of topoActions that describe my operation.
Finally, the polyMesh is capable of taking a polyTopoChange and executing the change.
The next level is to recognise that a user cannot be expected to work with topoActions: you really want to specify where and how to create a new layer of cells and not worry about topoActions. Also, we want the possibility of having several layer addition /removals and sliding interfaces working at the same time. Also, the changes need to happen DURING the simulation, so the whole mechanism needs to be a part of the mesh definition. This is how it's done: a polyMesh has got a polyMeshMorphEngine, which consists of a set of polyMeshModifiers. When morph() is called, the polyMeshMorphEngine goues through all the mesh modifiers and asks them whether they want to change the topology. If yes, each mesh modifier adds is topoActions to the same polyTopoChange and when they are all done, the mesh executes a change.
Therefore, a job of a mesh modifier is to
- decide whether it wants to change the mesh topology
- if yes, fill in a polyTopoChange with the topoActions that describe the change
- (some other actions, not currently important)
Examples of mesh modifiers are in the dynamicMesh library and they are derived form the polyMesh modifier class. Currently, there are three:
- attachDetach
- layerAdditionRemoval
- slidingInterface
Note that our job is to create and define a self-contained object that can do the job.
In order to do this, we need some additional things necessary to define the mesh modifier - they also live in the polyMesh class and are called zones. The code for zones lives in
OpenFOAM-1.0/src/OpenFOAM/meshes/polyMesh/zones
and I can make point, face or cell zones.
A zone is an arbitrary subset of mesh objects (points, faces or cells). They are grouped into zoneMesh (pointZoneMesh, faceZoneMesh etc, depending on the object). When creating, say, a pointZoneMesh, I can distribute the points of the mesh into as many groups as I like but one point can belong to a maximum of one zone.
Finally, let's think about the faces. As you know, faces in polyMesh are ordered according to the cell ordering and they point from the lower cell index into the higher (for the two cells around the face) or, for the boundary faces, they point outwards. Therefore, if I want to collect a bunch of faces into a zone and give it oriaentation (front and back, if you like), I need to collect all face indices that belong into the zone and for each face specify a bool "flip". If the face already point in the right direction, its "flip" is set to false and if its normal vector points in the wrong direction, the flip is true.
1.3 Poly mesh modifiers
1.3.1 Attach-detach boundary
Attach-detach boundary is made up of a bunch of internal mesh faces which can at required time be converted into boundary faces. Since the set of faces has got two sides (front and back), each face will need to be converted into two boundary faces. Once the mesh modifier is detached, it can again be attached, so you can operate in on-off-on-off cycles.
The definition of an attach-detact boundary consists of 3 things:
- a face zone containing the faces that should detach. When collecting faces into a zone you have to be careful to define them such that the zone has got a well-defined front and back. If this is not the case, the algorithm will not work
- a master patch name and a slave patch name. These two patches are initially empty (zero faces) when the mesh is attached and the faces get put into them once it is detached.
- a list of trigger times. When the run time reaches a trigger time, the state of attach-detach boundary will change: detach if attached and vice versa.
An example would look like this:
HrvsAttach { type attachDetach; faceZoneName membraneFaces; masterPatchName attachMasterWall; slavePatchName attachSlaveWall; triggerTimes (3 6 9 12 15 18); }
1.3.2 Layer addition-removal
A layer addition/removal mesh modifier will add a layer of cells in front of it once the thickness goes over the give threshold and remove a layer of cells if the layer thickness goes below the minimum. It is defined with the following parameters:
- an oriented face zone. The cells will be added and removed at the front side of the zone. Faces of the zone can be either internal or boundary or a mixture (does not matter.
- min layer thickness
- max layer thickness
There are also some auxiliary stuff in there which is not important or is used for the mesh modifier to record its current state. Here is an example:
right { type layerAdditionRemoval; faceZoneName rightExtrusionFaces; minLayerThickness 2e-4; maxLayerThickness 5e-4; oldLayerThickness -1; active on; }
Please note that the overall mesh motion needs to be done in such a way that the layer thickness in front of the modifier changes in time. Typically, you will need to be careful to set this up in a useful way and avoid cases where the motion is too fast (negative cell volumes and similar).
1.3.3 Sliding interface
Finally, a sliding interface. The idea of a sliding interface is that I've got two pieces of detached mesh that I want to connect (call it left and right). I will first need to pick out a set of BOUNDARY faces on each side which will merge. Also, when I look at two patches that partially overlap, some part of them will become internal faces and some parts will remain uncovered. We want to keep the uncovered faces on the left and right in separate boundary patches.
In order for the setup to work, I will therefore need:
- one face zone (at the beginning made up of boundary faces) for the left and right side.
- one boundary patch for each of the sides. Typically at the beginning of the story (when the patches are disconnected) all patch faces will also belong to a zone
- scratch space: one empty zone for cut faces and one point zone for cut points.
This mesh modifier does not need a triggering criterion - it will find out whther the mesh has changed based on the relative mesh motion. Also, setting up mesh motion needs to be done carefully, as the two pieces of the mesh should move independently from each other before the mesh attached.
An example of a sliding interface is given below:
mixerSlider { type slidingInterface; masterFaceZoneName outsideSliderZone; slaveFaceZoneName insideSliderZone; cutPointZoneName cutPointZone; cutFaceZoneName cutFaceZone; masterPatchName outsideSlider; slavePatchName insideSlider; typeOfMatch integral; coupleDecouple off; projection visible; attached off; active on; }
(this may change a bit between the versions).
2 Examples
TODO: See the original thread