Logparser: Predefined Analyses#

In this section, we showcase various predefined analyses available in the log parser. We utilize project files from the following benchmarks: ogs: Constant viscosity (Hydro-Thermal) and for the staggered scheme we use a prj from ogs tests: HT StaggeredCoupling HeatTransportInStationaryFlow


import pandas as pd

import ogstools as ot
from ogstools.examples import (
    log_adaptive_timestepping,
    log_const_viscosity_thermal_convection,
    log_staggered,
)

pd.set_option("display.max_rows", 8)  # for visualization only

The preprocessing of logs remains consistent across all examples and thoroughly explained in Logparser: Advanced topics.

records = ot.logparser.parse_file(log_const_viscosity_thermal_convection)
df_records = pd.DataFrame(records)
df_log = ot.logparser.fill_ogs_context(df_records)

Analysis of iterations per time step#

For detailed explanation, refer to: Logparser: Introduction. (Section: Use predefined analyses)

ogstools.logparser.analysis_time_step

df_ts_it = ot.logparser.time_step_vs_iterations(df_log)
df_ts_it
iteration_number
time_step
0 1
1 2
2 1
3 1
... ...
23 9
24 17
25 23
26 20

27 rows × 1 columns



Analysis of computational efficiency by time step#

The resulting table represents performance metrics for different parts of the simulation, organized by time step. It utilizes ogstools.logparser.analysis_time_step. displaying metrics such as output time [s], step size [s], time step solution time [s], assembly time [s], Dirichlet time [s], and linear solver time [s].

df_ts = ot.logparser.analysis_time_step(df_log)
df_ts = df_ts.loc[0]
# Removing MPI_process (index=0) from result (all are 0) for serial log.
df_ts
output_time step_size time_step_solution_time assembly_time dirichlet_time linear_solver_time
time_step
0 0.004476 NaN NaN 0.000000 0.000000 0.000000
1 NaN 1.000000e-07 0.142436 0.048265 0.000944 0.092496
2 NaN 1.000000e-05 0.041676 0.013362 0.000503 0.027244
3 NaN 1.000000e-03 0.033367 0.019580 0.000451 0.012804
... ... ... ... ... ... ...
23 NaN 4.000000e+07 0.531541 0.177440 0.004848 0.343803
24 NaN 2.000000e+08 1.057740 0.272943 0.010794 0.763421
25 NaN 4.000000e+08 3.149970 0.666353 0.014761 2.459589
26 0.006782 3.133499e+08 2.406160 0.550383 0.012222 1.833349

27 rows × 6 columns



Selecting specific metrics (3) and plotting using pandas plot function.

df_ts[["assembly_time", "dirichlet_time", "linear_solver_time"]].plot(
    logy=True, grid=True
)
plot 101 logparser analyses
<Axes: xlabel='time_step'>

Analysis of convergence criteria - Newton iterations#

The ogstools.logparser.analysis_convergence_newton_iteration function allows for the examination of convergence criteria based on Newton iterations. The resulting table provides convergence metrics for monolithic processes. For details, refer to the documentation on <convergence_criterion > defined in in the prj file.

  • |x| is a norm of a vector of the global component (e.g. pressure, temperature, displacement).

  • |dx| is the change of a norm of the global component between 2 iteration of non linear solver.

  • |dx|/|x| is the relative change of a norm of the global component

For this example we had defined in the prj-file:

<convergence_criterion>
  <type>DeltaX</type>
  <norm_type>NORM2</norm_type>
  <abstol>1.e-3</abstol>
</convergence_criterion>

The resulting table contains |x|, |dx| and |dx|/|x| at different time steps, processes and non linear solver iterations.

ot.logparser.analysis_convergence_newton_iteration(df_log)
dx dx_x x
time_step process iteration_number
1 0 1 2.559100e+07 2.530300e-02 1.011400e+09
2 0.000000e+00 0.000000e+00 1.011400e+09
2 0 1 0.000000e+00 0.000000e+00 1.011400e+09
3 0 1 0.000000e+00 0.000000e+00 1.011400e+09
... ... ... ... ... ...
26 0 17 9.385500e-03 9.286300e-12 1.010700e+09
18 1.646800e-03 1.629400e-12 1.010700e+09
19 2.994300e-03 2.962700e-12 1.010700e+09
20 5.881000e-04 5.818800e-13 1.010700e+09

136 rows × 3 columns



Staggered#

The resulting table provides convergence criteria for staggered coupled processes, utilizing ogstools.logparser.analysis_convergence_coupling_iteration Logs are generated from running ogs benchmark: HeatTransportInStationaryFlow

records = ot.logparser.parse_file(log_staggered)
df_records = pd.DataFrame(records)
df_log = ot.logparser.fill_ogs_context(df_records)

# Only for staggered coupled processes !
ot.logparser.analysis_convergence_coupling_iteration(df_log)
dx dx_x x
time_step coupling_iteration coupling_iteration_process
1 1 0 0.35337 0.17246 2.049
1 0.00000 0.00000 1271200.000
2 0 0.00000 0.00000 2.049
1 0.00000 0.00000 1271200.000
... ... ... ... ... ...
49 1 0 0.00000 0.00000 8.293
1 0.00000 0.00000 1271200.000
50 1 0 0.00000 0.00000 8.379
1 0.00000 0.00000 1271200.000

102 rows × 3 columns



Analysis of model time and clock time#

The ogstools.logparser.model_and_clock_time function allows to examine needed iterations, clock time, and step size over model time per attempted time step. This is especially useful to analyze the runtime behaviour of a simulation which employs adaptive time stepping. The following example failed as the simulation reached the minimal allowed time step size.

records = ot.logparser.parse_file(log_adaptive_timestepping)
df_records = pd.DataFrame(records)
df_log = ot.logparser.fill_ogs_context(df_records)
df_t = ot.logparser.model_and_clock_time(df_log)
df_t[["step_size", "clock_time", "iterations"]].plot(grid=True, subplots=True)
plot 101 logparser analyses
array([<Axes: xlabel='model_time'>, <Axes: xlabel='model_time'>,
       <Axes: xlabel='model_time'>], dtype=object)

To get an overview of the convergence behavior of the nonlinear solver over the entire simulation we can plot the relative error as a heatmap.

fig = ot.logparser.plot_convergence(df_log, "dx_x")
plot 101 logparser analyses

We can also plot this data over the model time. Note, that the last timesteps are so small, that they are not visible anymore here:

fig = ot.logparser.plot_convergence(df_log, "dx_x", x_metric="model_time")
plot 101 logparser analyses

Further we can calculate the convergence order and plot it in the same manner. In order to estimate the convergence order we need to take into account multiple values and thus cannot assign each iteration a convergence order. Only for iterations i of i >= n an order is calculated and plotted. See: convergence_order_per_ts_iteration() for more info.

fig = ot.logparser.plot_convergence_order(df_log)
plot 101 logparser analyses

Total running time of the script: (0 minutes 2.107 seconds)