Understanding the (mis)behavior of IMVJ

I am currently running a parameter study for test case where I compare different accelerators paired with different filters, filter sensitivities and accelerator specific settings. At the moment I am especially interested in comparing IMVJ and ILS.

My general understanding of the generalized Broyden acceleration (IMVJ) from Klaudius’ thesis (e.g. page 99 in [1]) was basically that:

  1. its performance depends weakly on the filter choice (ILS depends more strongly on filter)
  2. Independent of the IMVJ specific settings (restart type, SVD) truncation limit it performs on the same level as the ILS method with optimal settings
  3. The SVD truncates data at certain points which helps keeping only relevant information in the approximated Jacobian.

General settings

  • I run the simulations in parallel. Usually (4+12 threads).
  • I have used preCICE 2.0.2 for (mainly due to https://github.com/precice/precice/pull/852)
  • The solvers are written in FeniCS. Therefore I use the Python bindings.

Results

I can confirm the expected behavior for my serial-implicit simulations. However, for the parallel-implicit simulations my results go a bit crazy as the IMVJ simulations tend to diverge. See this table that shows the preCICE iteration counts, for example:

The result of ILS is basically what I would expect. It gets better with more memory/reused information. IMVJ gives completely odd results up to divergence (100 iterations needed). nan indicates that the simulation was killed due to exceeding run time. The maximum number of iterations per time window allowed was 100.

I have added two example configurations for a case where the ILS method converges, but IMVJ diverges.

ils-qr2_1e-2-restart_8-config.xml (4.1 KB)
imvj-qr2_1e-2-config.xml (4.2 KB)

The main difference I see (besides the different accelerator) is that the value of time-windows-reused is differing a lot. The value of max-used-iterations is huge such that I could have ILS with “infinite” memory similar to what Klaudius did. I assumed that the IMVJ method would just delete some data at some point due to the SVD. Are some of my assumptions wrong or am I doing something stupid? For a “fair” comparison with ILS(infinity), which should correspond to my ILS(100), what would be a good value to set time-windows-reused to for the IMVJ accelerator?

Thanks in advance!

[1] https://elib.uni-stuttgart.de/handle/11682/10413

This assumption is wrong. The SVD just handles how the past Jacobian is encoded. And there past information is neglected at some point. The Jacobian update, on the other hand, uses all columns that you provide.

By design, IMVJ should work best with 0 time-windows-reused. If a value larger than 0 still has a positive effect on the performance of IMVJ (happens sometimes, but rarely) this contradicts the motivation behind the method: to capture past information implicitly and not explicitly.

Right now, you use all available columns for the IMVJ update. This could indeed lead to the results you observe.

Thanks for the quick reply. I will setup up new simluations and report how that worked. I will see if I can propose some change to the documentation at https://github.com/precice/precice/wiki/Generalized-Broyden-Acceleration-(IMVJ). The documentation uses time-windows-reused set to zero, but says that it is problem dependent at the same time.

I have rerun the simulations after setting time-window-size to 0. However, my results got even worse. The results for the serial-implicit runs did change to the worse slightly. Some results for the parallel-implicit are given in the table below. Now, almost all parallel-implicit runs fail:

Example config: imvj-qr2_1e-2-time-window-size_0-config.xml (4.2 KB)

Have you ever observed such behavior? Does it mean I do something severely wrong or does it mean that something is wrong in the code?!

Edit: I have talked to Klaudius. The cause of the problem might be my preconditioner since I use residual-sum without freezing the scaling. I run some other tests and will report back.

Actually, we are thinking about removing these documentation pages all together. Meaning pages, where we explain features. In theory, those should be better covered in the corresponding papers + the xml reference (which still needs some more work). Would you disagree for IMVJ?

The truncation threshold for the SVD might be too low and throwing away potentially useful information. I think the default is `truncation-threshold=“0.0001”. The initial relaxation seems quite low as well, but probably not the cause here.

I was able to fix a bit my configuration with Klaudius’ and your help.

Now I finally I get results that are closer to what I expected. The main difference is that I see a stronger dependence on the filter than Klaudius did and I seem some dependence on the initial relaxation parameter for my test case.

@uekerman I would support putting the information about the parameters and maybe some suggestion on how to choose them into the XML reference. I agree that it should be enough to have the whole theory part in papers/dissertations.

@KyleDavisSA: I have added results for the case 1e-4 for the threshold. That is the number in the paranthesis after IMVJ. In general I would say that I use reasonably small values in the range of 1e-1 down to 1e-4.

Edit:
I just realized that I forgot to mention what the actual solution was.

Short summary:

  1. time-windows-reused value should be set to zero
  2. The preconditioner should vary. In my case it is important to use a preconditioner. I used residual-sum as it chooses reasonable weights, but for IMVJ it is crucial to freeze the weighting. Otherwise the singular value decomposition is not meaningful anymore.

My acceleration block now looks something like that:

<acceleration:IQN-IMVJ>
  <data name="DisplacementTop" mesh="FractureMeshTop"/> 
  <data name="DisplacementBottom" mesh="FractureMeshBottom"/> 
  <data name="Pressure" mesh="HDFlowMeshTop"/> 
  <data name="Pressure" mesh="HDFlowMeshBottom"/> 
           
  <initial-relaxation value="0.001"/>
  <max-used-iterations value="10000"/>
  <time-windows-reused value="0"/>

  <preconditioner type="residual-sum" freeze-after="1"  />
  <filter type="QR2" limit="0.01"/>

  <imvj-restart-mode type="RS-SVD" truncation-threshold="0.01" chunk-size="8" />
</acceleration:IQN-IMVJ>

Great! :tada:
Results look interesting.