I have been looking around for a while now, but have not come up with a way of doing the following:

I want to define a patch field on a mesh which looks something like this:

Code:

boundaryField
{
<patchName>
{
type <patchType>;
value <value>;

secondaryType <patchType>;
secondaryValue <value>;
}
}

During evaluation of the boundary conditions, I want to evaluate both the boundary condition types, and then decide how to combine the two results into a final result for the given patch.

As far as I could understand, the boundary fields are inherited from the class "GeometricField", and are actually setup in the file "GeometricBoundaryField.C".

In this file, a given field type (Say for example, volScalarField) is setup by iterating through all the patches in the boundary mesh, and creating a "PatchField" of the specified type (say, for example "fixedValue") as found in the boundary definition dictionary of that patch.

However, I have not been able to find any method of defining a GeometricField on any one specific patch, by giving the patch id, and a dictionary.

Basically, I want to create an internal patch field for the patch "patchName" which is of type "secondaryType" sometime during the creation of the main patch field "type".

Another option would be to create something like a placeholder patch.... which has the same starting face and number of faces as the original patch, and create a patch field of type "secondaryType" on this placeholder patch. But that somehow does not feel like the right way to do it....

Could someone help me out on this front?

For people familiar with my quest..... this is for trying to implement GGI with proper treatment of uncovered faces :-)!

Philippose

marupio

January 13, 2012 11:42

I've read through your post a few times, and I'm not sure I fully understand what you are trying to achieve. You're talking about objects I'm fairly familiar with, so I think I'd be able to help once I understood.

You mention the GeometricBoundaryField.C, where I presume the constructor is implemented for the boundary patch fields. If you want to change the behaviour of the GeometricBoundaryField, you either have to change OpenFOAM's core library, or create a derived GeometricField... but the derived one would be a nightmare to implement fully.

You talk about two patches fields on the same surface. Do the patch fields have to each be a fully realized fvPatchField, with which we can perform updateCoeffs? Or can it be one fvPatchField making the necessary calculations for two. Or, are there actually two fvPatchFields coinciding in space that need to exchange information?

I'm not too familiar with GGI... are the meshes separate objects, or is it a "supermesh" object?

philippose

January 13, 2012 16:29

Hello David,

A Good Evening to you :-)!

Sorry for the confusion.... I too, was not sure how to ask the question without having to go too deep into the details of the idea in my head :-)! It has nothing to do with hiding anything... its just that I thought an overly long post may not result in any answers from anyone.

So here goes.... I shall try to explain things, and if people like Sandeep (deepsterblue) and Arjun are reading this post, they might be able to put in some more information.

OpenFOAM-1.6-ext (and now also OpenFOAM-2.1.0) has a feature known as GGI (Generalised Grid Interface) (AMI in OF-2.1.0). GGI is a form of interpolation, which lets you connect topologically disconnected mesh parts of a complete domain without having to modify the mesh. In a way, it is very similar to the sliding interface, except that the interface is not physically connected together by modifying the mesh.

The advantage of GGI is that you can solve problems which involve boundary motion where different parts of the mesh are sliding relative to each other without having to wade through all the problems of mesh quality, mesh deformations, attach-detach of mesh regions, sliding interfaces, etc...etc....

----------------

Now.... the OpenFOAM-1.6-ext implementation of GGI arose primarily from the need to improve the simulation performance and ease of case preparation for rotating turbine simulations. The specific advantages of GGI in this field are:

1. You can easily handle the large scale rotation of the rotor with respect to the stator without having to resort to sliding interfaces (not going through the mesh modification step improves speed, and makes it a lot more robust)

2. You can create the various parts of a turbine system using different meshing methods, mesh densities, etc..etc..., and later connect them all together using GGI patches without having to worry about mesh conformity across the interfaces.

3. Case setup is a lot easier

etc...etc....

-----------------

Ok... now, my interest in GGI lies in the fact that I work in the field of Hydraulics, and am involved in the research and design of hydraulic valves. Specifically, hydraulic spool valves..... Spool valves are inherently sliding interfaces, which open and close orifices, slots, windows, etc... to vary the flow through or the pressure of a system.

For the design of hydraulic spool valves.... specifically, flow force optimisation, geometry definition, system analyses, etc... we need to run simulations which involve having to either perform a full stroke of the spool (transient incompressible simulations), or more often, move the spool based on the solution to account for flow forces (I had written a solver for this way back in 2007 or 2008 which used the sliding interface....).

Hence, as you can see, the GGI would be a perfect system for my case, because I have large scale linearly sliding interfaces which open and close flow passages. Using a GGI setup, I can mesh the housing of the valve, and the spool side of the valve separately. I can then move the spool part of the mesh using pure rigid body motion, and let the GGI handle the interface without having to perform and topological changes on the mesh at the interface.

--------------

Now for the problem...... :-) .... As I mentioned earlier, the GGI implementation in OpenFOAM-1.6-ext came out of a need in the field of turbines. One subtle feature of these kind of simulations are, that the actual rotating interfaces have either no, or almost no situations, where parts of the interface on either side become uncovered.

When a part of a GGI patch becomes uncovered, it is no more an internal face, but a normal wall patch which also needs to be treated that way during the boundary condition evaluation.

The current implementation of GGI internally treats all uncovered faces as slip boundaries. This is ok when the percentage of uncovered faces in the interface is negligible, but this does not work when the number of uncovered faces which should be treated as walls are more dominant than the covered faces (depending on the spool stroke).

---------------

How does the GGI implementation in OpenFOAM work? (This is my interpretation :-)! I hope someone corrects my mistakes....)

The GGI in OpenFOAM starts with the boundary file which requires a special mention of the following form for GGI cases:

Note: For a full example, check {tutorials}/incompressible/icoDyMFoam/mixerGgi

The implementation at the code level is spread among multiple files:

1. An implementation of the GGI Interpolation system in {src}/OpenFOAM/interpolations/GGIInterpolation

2. An implementation of the GGI Patch type in {src}/OpenFOAM/meshes/polyMesh/polyPatches/constraint/ggi

3. Finite Volume implementation of the GGI Patch in {src}/finiteVolume/fvMesh/fvPatches/constraint/ggi

4. Finite Volume implementation of the GGI fvPatchFields in {src}/finiteVolume/fields/fvPatchFields/constraint/ggi

There are some more files in lduAddressing, and GAMG, but I think we can leave these out because I think they are implemented in quite a generic manner.

For a quick overview of how all this works.....

* Each GGI pair consists of a master and a shadow patch..... The interpolation weights across the interface for each face of the master patch are calculated based on which faces lie on the shadow side of that face, and how much area of each of those shadow faces are covered by the master face.

* The weights are always calculated relative to the master.

* For conservation, the sum of all the weights for a given face add up to 1.0

* When the time comes to interpolate the fields, the value of the internal field on one side is transferred to the other side after multiplying with the weights.

* For all faces which are uncovered, the following symmetry condition is directly forced within the implementation of the GGI system itself, as shown:

the "bridge" function simply writes the bridgefield (which is basically the slip condition calculated for the entire patch) onto those faces of the patch which have been found to be uncovered.

--------------------

As can be seen, as of now, this treatment of the uncovered faces as slip boundaries is hard-coded into the GGI implementation.

Now.... the idea I (actually, its not purely mine, these are ideas that have been floating around between Sandeep, Arjun, Martin Beaudoin and me for a while now) have for trying to treat the uncovered faces is the following:

Have a new specification in the boundary file probably as shown below:

1. During the evaluation of the ggiFvPatchField, create a temporary fvPatchField (or would it have to be a GeometricField) which uses the same patch as the GGI patch, but of the patchField type mentioned in the "uncoveredType" specification and with value as specified in the "uncoveredValue"..... Then, evaluate the GGI boundary patch as it were a normal patch of the specified patchField type, and then, substitute the values got from this evaluation, and use this as the "bridgeField" (shown in the slip condition code snippet above)

This should cause all those faces which are uncovered to have the values obtained from the evaluation of the patch as a normal boundary patch, and all the covered faces to be treated as internal faces.

2. The second approach is, to create a placeholder patch which references the same boundary patch as the GGI patch, but create it with the patchFieldType specified in the "uncoveredType".

This patch should then.... not be evaluated automatically as part of the boundary mesh, but evaluated specifically through the GGI setup, and the results should be used as the "bridgeField" again, as in approach (1.)

In addition, for the turbulence models, the GGI patch will have to give a positive for the "isWall()" function, in order to take the wall-functions into account.

-------------------

This would more or less sum up the reason for my earlier post.... I was thinking of trying to implement approach (1.), but could not find a way of creating a fvPatchField (or GeometricField since the mesh geometry needs to be referenced too) or a specified type from within the ggiFvPatchField implementation.

:-) :-)! I apologise for the length of the post.... that was the reason why I did not try to explain the reasons for my vague question in the first post.

Do you think it would be better to shift this post to another thread with a more representative name, so that it can be found again in the future, or found by people who would be interested in helping out??

Thanks a lot for the reply :-)!

(Note: Though I am working for a company, all this stuff I keep trying out has nothing to do with the company, because I do it at home and whenever I find the time and need to improve something..... and ofcourse, anything implemented with this regard will be directly available in the public domain, because the core competence of the company is hydraulics, and CFD is used purely as a tool.... not as a software library to be sold.... It just happens that I like looking under the hood, and trying to implement things rather than just sit back and accept that it does not work :-)!)

Wishing you a great weekend ahead :-)!

Philippose

marupio

January 13, 2012 19:14

A few thoughts:

First, in the dictionaries, you are creating new keywords "uncoveredType", "uncoveredValue", and so forth. It would probably be wiser to go with a sub-dictionary... that way it is immediately suitable to the existing fvPatchFields:

Then you can load uncovered with .subDict instead of .lookup, and you have the dictionary argument for the dictionary constructor.

Now, my next bit of insight is that it is technically challenging to give an fvPatchField another fvPatchField from another mesh as a member variable. So, in your options above, I'd lean towards #2 - a floating independent placeholder patch. Why do I say this? Because I was trying to explain how you could do number 1, wrote a bit of a novel, and then decided it was too ugly. See the novel below as reference (you may skip it).

---- BEGIN MEANDERING NOVEL ----

You seem keen to have a temporary fvPatchField as a member of an fvPatchField. This is perfectly fine. I wouldn't create a full-blown GeometricField if you don't have to. The question of the mesh reference is a tricky one, though.

There are no existing fvPatchField constructors you can use that will give you access to the mesh. You could, conceivably look it up through the objectRegistry, but that would give you a const reference only, not sure if that is suitable. You can't be guaranteed that the other mesh will exist when you need to build the fvPatchField, so if you go this route, you cannot have a secondary fvPatchField as a member, but you can have a *pointer* to one (preferably autoPtr). In this case, you must check the validity of the pointer when you use it, if it doesn't exist, try creating it by looking up the mesh in the objectRegistry and constructing, and if this fails, you need a "limp mode" for you patchField - return zero, kind of thing... just so it doesn't all come tumbling down when updateCoeffs is used before the other mesh exists.

Alternately, you could have a special ggiFvPatchField.setSecondaryMesh() function, but to access this, you need to use dynamicCast from the top level. Using this route, you don't need a "limp mode", but rather it should totally fail if the autoPtr isn't set when it needs to be.

On the other hand, you could create a special fvPatchField constructor that takes a secondary mesh as a parameter. This requires changes to OpenFOAM's core. To get this working, you need to implement it all the way through the runTimeSelection in fvPatchField - don't be afraid, fvPatchField already has several constructors, so adding another will be a lot of copy and pasting. Once you've done that, you need to give it a default (failure) implementation, like the "notImplemented" idiom... otherwise you'd have to implement it in all the existing boundary conditions. Then, write this custom constructor for your ggi fvPatchField. Mind you, that's kind of ugly, as you'd have a single one-of constructor hanging around specifically for your custom implementation.

---- END OF RAMBLES ----

If you are working with Martin, then changes to OpenFOAM's core shouldn't be anything to fear.

Thank you for your detailed posting on the status of AMI (GGI) for uncovered faces. I am facing a similar problem (a small nozzle connecting to a big cylinder) where the uncovered faces are desired to be wall. Have you solved this problem using the method your proposed? If so, will you share how you eventually did it? If there is any test case, it would be best.