cfl_monitor.py 2.95 KB
Newer Older
mashun1's avatar
veros  
mashun1 committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from veros import logger
from veros.core.operators import numpy as npx
from veros.diagnostics.base import VerosDiagnostic
from veros.distributed import global_max


class CFLMonitor(VerosDiagnostic):
    """Diagnostic monitoring the maximum CFL number of the solution to detect
    instabilities.

    Writes output to stdout (no binary output).
    """

    name = "cfl_monitor"  #:
    output_frequency = None  #: Frequency (in seconds) in which output is written.

    def initialize(self, state):
        pass

    def diagnose(self, state):
        pass

    def output(self, state):
        """
        check for CFL violation
        """
        vs = state.variables
        settings = state.settings

        cfl = global_max(
            max(
                npx.max(
                    npx.abs(vs.u[2:-2, 2:-2, :, vs.tau])
                    * vs.maskU[2:-2, 2:-2, :]
                    / (vs.cost[npx.newaxis, 2:-2, npx.newaxis] * vs.dxt[2:-2, npx.newaxis, npx.newaxis])
                    * settings.dt_tracer
                ),
                npx.max(
                    npx.abs(vs.v[2:-2, 2:-2, :, vs.tau])
                    * vs.maskV[2:-2, 2:-2, :]
                    / vs.dyt[npx.newaxis, 2:-2, npx.newaxis]
                    * settings.dt_tracer
                ),
            )
        )
        wcfl = global_max(
            npx.max(
                npx.abs(vs.w[2:-2, 2:-2, :, vs.tau])
                * vs.maskW[2:-2, 2:-2, :]
                / vs.dzt[npx.newaxis, npx.newaxis, :]
                * settings.dt_tracer
            )
        )

        if npx.isnan(cfl) or npx.isnan(wcfl):
            raise RuntimeError(f"CFL number is NaN at iteration {vs.itt}")

        logger.diagnostic(f" Maximal hor. CFL number = {cfl}")
        logger.diagnostic(f" Maximal ver. CFL number = {wcfl}")

        if settings.enable_eke or settings.enable_tke or settings.enable_idemix:
            cfl = global_max(
                max(
                    npx.max(
                        npx.abs(vs.u_wgrid[2:-2, 2:-2, :])
                        * vs.maskU[2:-2, 2:-2, :]
                        / (vs.cost[npx.newaxis, 2:-2, npx.newaxis] * vs.dxt[2:-2, npx.newaxis, npx.newaxis])
                        * settings.dt_tracer
                    ),
                    npx.max(
                        npx.abs(vs.v_wgrid[2:-2, 2:-2, :])
                        * vs.maskV[2:-2, 2:-2, :]
                        / vs.dyt[npx.newaxis, 2:-2, npx.newaxis]
                        * settings.dt_tracer
                    ),
                )
            )
            wcfl = global_max(
                npx.max(
                    npx.abs(vs.w_wgrid[2:-2, 2:-2, :])
                    * vs.maskW[2:-2, 2:-2, :]
                    / vs.dzt[npx.newaxis, npx.newaxis, :]
                    * settings.dt_tracer
                )
            )
            logger.diagnostic(f" Maximal hor. CFL number on w grid = {cfl}")
            logger.diagnostic(f" Maximal ver. CFL number on w grid = {wcfl}")