precice / openfoam-adapter

OpenFOAM-preCICE adapter
https://precice.org/adapter-openfoam-overview.html
GNU General Public License v3.0
135 stars 80 forks source link

Wrong write time for functionObjectProperties in OpenFOAM.com #26

Closed MakisH closed 5 years ago

MakisH commented 6 years ago

Issue reported by @derekrisseeuw, affecting at least OpenFOAM+ v1712 and v1806, but not affecting OpenFOAM 5.x or 6.

tl;dr: Empty entries in the results output are shown as "flickering" animation in ParaView.

The problem occurs when running a coupled implicit simulation where the openfoam write interval is larger than the coupling timestep. OpenFOAM will not only write a time at the defined 'write interval', but also at: time = write interval - coupling time

The only field that is written that time is uniform/functionObjects

Which contains the attached file, with no further information.

In terms of simulation this does not pose a problem, but for postprocessing it can be inconvenient. Also, I am not sure where this functionobject is written, but the fact that the time there is not updated might also be incorrect.

I actually first noticed this problem when running the CHT tutorial. Here the coupling time is 0.01s, and the writeInterval is 0.2s. Therefore I have timefolder 0, 0.19, 0.2, 0.39, 0.4, ... etc.

Even if this seems to be version-specific, maybe there is something wrong in the adapter, as well.

MakisH commented 5 years ago

Some observations, while I am trying to fix this:

In case you cannot acccess their GitLab repositories, the key method is Foam::functionObjectList::createStateDict() in the file src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C. Compare also the method Foam::Time::run() between .org/.com. If I understand correctly, they want to keep track of any changes in the configuration of the functionObjects during the simulation, making such a file necessary. However, I still have to understand why it is written at the wrong time in our case.

Commenting out this line didn't help: https://github.com/precice/openfoam-adapter/blob/df2e48d8924bdf13d8232e148d3f345d083cc307/Adapter.C#L419

Edit: Here are the respective Release Notes of OpenFOAM v3.0+. See the section "Function objects updates".

MakisH commented 5 years ago

As Derek mentioned, the additional file is written at time = write interval - coupling time step. The time is not dependent on the solver time step. It is also written at the normal time.

Apparently, this file is only written at the last coupling time step before writing (and at the times it is expected to be written). I was looking at the files during the simulation.

Consider the heated plate tutorial, with implicit coupling, and the following time steps:

While the time directories 0 0.2 0.4 0.6 0.8 1 are expected, the directories 0 0.19 0.2 0.39 0.4 ... 0.99 1 are written.

I guess that at the coupling time step from t=0.199 to t=0.20 (or maybe t=0.20 to t=0.201), OpenFOAM enables a writeTime or similar switch. After reloading the checkpoint and the time value to t=0.19 with our hacky approach, the functionObjectProperties file is written at t=0.19. This must be the beginning of the solver's time step from t=0.190 to t=0.191.

Keeping in mind that the function object is technically triggered at the beginning of the next time step, instead of the end of the current one, I am pretty sure the problem is in this series of events. I will look at it again later. The answer lies somewhere in Foam::Time::run() or in preciceAdapter::Adapter::execute().

MakisH commented 5 years ago

Additional thoughts and observations:

https://github.com/precice/openfoam-adapter/blob/df2e48d8924bdf13d8232e148d3f345d083cc307/Adapter.C#L419

https://github.com/precice/openfoam-adapter/blob/df2e48d8924bdf13d8232e148d3f345d083cc307/Adapter.C#L702

This is of course undesired and wrong, but it supports my aforementioned theory.

MakisH commented 5 years ago

I think I found the speciality of this object, in the method Foam::functionObjectList::execute():

     // Force writing of state dictionary after function object execution
     if (time_.writeTime())
     {
         label oldPrecision = IOstream::precision_;
         IOstream::precision_ = 16;

         stateDictPtr_->writeObject
         (
             IOstream::ASCII,
             IOstream::currentVersion,
             time_.writeCompression(),
             true
         );

         IOstream::precision_ = oldPrecision;
  }

So, the series of events is the following:

  1. t = 0.20
  2. runTime.run(), which triggers the adapter's execute()
  3. Our execute() at some point reloads the time to t = 0.19, reads the coupling data, adjust the time step, and lets the solver continue
  4. After all these steps, Foam::functionObjectList::execute() sees that time_.writeTime() is true and writes the functionObjectProperties state dictionary.

Two cross-related questions:

A. Why, after we reset the time, time_.writeTime() is true? Can we force-set it to false? B. Why is functionObjectProperties written at t=0.19 (which is not write-time) and not at t=20 (which is)?

MakisH commented 5 years ago

I give up for now, as any solution for this would again be quite hacky. I think we are writing results correctly and we know the specific reason that only this object is written out of place. This only affects some versions of OpenFOAM and this file seems to be useless in most of the cases.

I suggest the following workaround for our tutorial scripts:

# Delete all [case]/[time]/[uniform]/functionObjects directories
rm -rfv */*/*/functionObjects

# Delete all empty directories
find . -type d -empty -delete

@derekrisseeuw what do you think of this workaround?

Apparently, paraFoam uses any directory with a numerical value as name to add time stamps. Or maybe the issue is that ParaView itself needs an option to only consider non-empty time sets when plotting a specific variable. I will open an issue/PR for this upstream.

derekrisseeuw commented 5 years ago

This could work, but only for runs which don't use any other function objects.

I used a similar script removeObsoleteFolders.sh in my tutorial cases which is called automatically after the simulation. This file removes all the time folders which don't include a U file, since every simulation with FSI would save the velocity field.

MakisH commented 5 years ago

This could work, but only for runs which don't use any other function objects.

Do you have any example in mind where this could break? Maybe deleting all the functionObjects directory is overkill, deleting just the functionObjectProperties would be enough. For all the tutorials we have, it is empty (and it doesn't exist for the OpenFOAM Foundation versions).

To be honest, I have not really understood what this dictionary is meant for, as I have not encountered it in practice.

I think I will replace the removeObsoleteFolders.sh script with this, as more targeted and general (works also for laplacianFoam, for example).

MakisH commented 5 years ago

I actually think your script is better for our use case. I extended it so that it also looks for T and to not delete the 0.orig directories.

I consider this closed, as soon as the respective commit gets merged into master.

precice-bot commented 3 years ago

This issue has been mentioned on preCICE Forum on Discourse. There might be relevant details there:

https://precice.discourse.group/t/openfoam-adapter-branch-for-version-8-and-solution-frequency/537/2